DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support
@ 2026-08-31 10:23 Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 01/10] crypto: add RSA-specific capability parameters Sucharitha Sarananaga
                   ` (10 more replies)
  0 siblings, 11 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

The asymmetric crypto capability structure currently reports only a
generic modulus length and primary hash algorithm for RSA, with no
way for a PMD to advertise which padding schemes (NONE, PKCS#1 v1.5,
OAEP, PSS) or MGF1 hash algorithms it supports. Applications have no
standard way to discover this, and the OpenSSL PMD itself only
implements NONE and PKCS#1 v1.5 padding.

This series first extends the capability API with a dedicated
rte_crypto_rsa_capa (modulus length, pad_types, mgf1_hash_algos, and
an explicit-PSS-salt flag), then updates the capability reporting in
the virtio, octeontx, cnxk, qat, and openssl PMDs to use it.

On top of that, it adds actual RSA-OAEP and RSA-PSS support to the
OpenSSL PMD:
 - RSA-OAEP encrypt/decrypt, with configurable OAEP hash, MGF1 hash,
   and an optional label, defaulting MGF1 to the OAEP hash when
   unset.
 - RSA-PSS sign/verify, with configurable hash, MGF1 hash, and salt
   length (rte_crypto_rsa_padding::pss_saltlen), using a dedicated
   EVP_PKEY_verify()-based verification path since PSS does not
   support verify-recover. The PSS salt itself is always generated
   internally by the PMD; an application-supplied salt
   (rte_crypto_rsa_op_param::pss_salt, gated by the new
   pss_explicit_salt capability bit) is introduced by this series
   for future PMD support but is not yet implemented here, so it is
   rejected with RTE_CRYPTO_OP_STATUS_INVALID_ARGS.

Test coverage for both OAEP (encrypt/decrypt, default and custom
MGF1, with and without a label) and PSS (digest-length, maximum, and
zero-length salt) is added to the cryptodev asymmetric test suite.

Sucharitha Sarananaga (10):
  crypto: add RSA-specific capability parameters
  crypto/virtio: advertise RSA padding and hash capabilities
  crypto/octeontx: advertise RSA PKCS#1 v1.5 padding support
  crypto/cnxk: advertise RSA PKCS#1 v1.5 padding support
  crypto/qat: advertise RSA padding capabilities
  crypto/openssl: advertise RSA padding and hash capabilities
  crypto/openssl: add RSA-OAEP support for OpenSSL PMD
  app/test: add RSA OAEP asymmetric test cases
  crypto/openssl: add RSA-PSS support for RSA operations
  app/test: add RSA-PSS sign and verify test cases

 app/test/test_cryptodev_asym.c                | 663 ++++++++++++++++++
 app/test/test_cryptodev_rsa_test_vectors.h    | 317 +++++++++
 .../crypto/cnxk/cnxk_cryptodev_capabilities.c |   8 +-
 .../octeontx/otx_cryptodev_capabilities.c     |   8 +-
 drivers/crypto/openssl/openssl_pmd_private.h  |  11 +
 drivers/crypto/openssl/rte_openssl_pmd.c      | 367 ++++++++--
 drivers/crypto/openssl/rte_openssl_pmd_ops.c  | 147 +++-
 drivers/crypto/qat/asym/qat_asym.h            |  20 +
 drivers/crypto/qat/dev/qat_asym_pmd_gen1.c    |   5 +-
 drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c  |   5 +-
 .../virtio/virtio_crypto_capabilities.h       |  19 +-
 lib/cryptodev/rte_crypto_asym.h               |  18 +
 lib/cryptodev/rte_cryptodev.h                 |  50 +-
 13 files changed, 1567 insertions(+), 71 deletions(-)

-- 
2.54.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 01/10] crypto: add RSA-specific capability parameters
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
@ 2026-08-31 10:23 ` Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 02/10] crypto/virtio: advertise RSA padding and hash capabilities Sucharitha Sarananaga
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

The existing asymmetric capability structure reports generic
modulus length and hash algorithm support, but it cannot
describe RSA-specific parameters required by OAEP and PSS.

RSA operations may support different padding schemes and MGF1
hash algorithms independent of the primary hash algorithm.
Applications currently have no standard way to discover these
capabilities from a PMD.

Add rsa_capa to report RSA modulus length, supported padding
schemes, and MGF1 hash algorithms. Keep hash_algos for reporting
primary digest support.

Also clarify that the generic modlen field applies to other
modulus-based transforms such as MODEXP, MODINV, DH, and DSA.

RSA-PSS signing also normally generates its salt internally, so
the same message never produces the same signature twice, making
it impossible to validate against fixed test vectors (e.g.
ACVP/CAVP SigGen).

Add pss_explicit_salt to rsa_capa so a PMD can
advertise support for an application-supplied PSS salt, and add
the corresponding pss_salt field to rte_crypto_rsa_op_param to
carry those bytes per sign operation. Leaving pss_salt unset keeps
today's internally-generated-salt behavior unchanged

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 lib/cryptodev/rte_crypto_asym.h | 18 ++++++++++++
 lib/cryptodev/rte_cryptodev.h   | 50 +++++++++++++++++++++++++++++++--
 2 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/lib/cryptodev/rte_crypto_asym.h b/lib/cryptodev/rte_crypto_asym.h
index b1546d2b7c..808c5f323e 100644
--- a/lib/cryptodev/rte_crypto_asym.h
+++ b/lib/cryptodev/rte_crypto_asym.h
@@ -494,6 +494,24 @@ struct rte_crypto_rsa_op_param {
 	 * This could be validated and overwritten by the PMD
 	 * with the signature length.
 	 */
+
+	rte_crypto_param pss_salt;
+	/**<
+	 * Explicit RSA-PSS salt bytes, used only for
+	 * RTE_CRYPTO_ASYM_OP_SIGN with RTE_CRYPTO_RSA_PADDING_PSS.
+	 * Only valid if the PMD advertises
+	 * rte_crypto_rsa_capa::pss_explicit_salt == true.
+	 *
+	 * - pss_salt.data == NULL (default): PMD generates the salt
+	 *   internally.
+	 * - pss_salt.data != NULL: PMD uses these exact bytes as the
+	 *   salt. pss_salt.length must equal the session's
+	 *   pss_saltlen, otherwise the op completes with status
+	 *   RTE_CRYPTO_OP_STATUS_INVALID_ARGS.
+	 *
+	 * Ignored for RTE_CRYPTO_ASYM_OP_VERIFY (salt is recovered from
+	 * the signature itself) and for non-PSS padding.
+	 */
 };
 
 /**
diff --git a/lib/cryptodev/rte_cryptodev.h b/lib/cryptodev/rte_cryptodev.h
index 37a6a5e49b..bdbd11ace5 100644
--- a/lib/cryptodev/rte_cryptodev.h
+++ b/lib/cryptodev/rte_cryptodev.h
@@ -157,6 +157,48 @@ struct rte_cryptodev_symmetric_capability {
 	};
 };
 
+/**
+ * RSA transform capability parameters.
+ *
+ * Used when rte_cryptodev_asymmetric_xform_capability::xform_type is
+ * RTE_CRYPTO_ASYM_XFORM_RSA. Advertises supported modulus lengths,
+ * MGF1 hash algorithms, and padding schemes.
+ *
+ * Primary hash algorithms for RSA operations (e.g. OAEP, PSS) are
+ * reported separately via hash_algos in
+ * rte_cryptodev_asymmetric_xform_capability.
+ */
+struct rte_crypto_rsa_capa {
+	struct rte_crypto_param_range modlen;
+	/**< Supported RSA modulus length range, in bytes.
+	 * A min, max, or increment value of 0 means no limit is
+	 * imposed for that field and the PMD default applies.
+	 */
+
+	bool pss_explicit_salt;
+	/**< Support for application-supplied RSA-PSS salt
+	 * (rte_crypto_rsa_op_param::pss_salt).
+	 * false (default): PMD always generates the salt internally.
+	 * true: PMD accepts an application-supplied salt.
+	 */
+
+	uint8_t pad_types;
+	/**< Bitmask of supported RSA padding schemes.
+	 * Each bit corresponds to enum rte_crypto_rsa_padding_type.
+	 * A value of 0 means padding capability is not reported and the PMD
+	 * default may apply.
+	 */
+
+	uint64_t mgf1_hash_algos;
+	/**< Bitmask of hash algorithms supported for MGF1 mask generation.
+	 * Each bit corresponds to enum rte_crypto_auth_algorithm.
+	 * Used for RSA-OAEP and RSA-PSS when MGF1 may use a digest
+	 * different from the primary hash.
+	 * A value of 0 means MGF1 capability is not reported and the PMD
+	 * default may apply.
+	 */
+};
+
 /**
  * Asymmetric Xform Crypto Capability
  */
@@ -179,8 +221,9 @@ struct rte_cryptodev_asymmetric_xform_capability {
 	__extension__
 	union {
 		struct rte_crypto_param_range modlen;
-		/**< Range of modulus length supported by modulus based xform.
-		 * Value 0 mean implementation default
+		/**< Range of modulus length supported by modulus based xform
+		 * such as MODEXP, MODINV, DH, and DSA.
+		 * Value 0 means implementation default.
 		 */
 
 		uint8_t internal_rng;
@@ -197,6 +240,9 @@ struct rte_cryptodev_asymmetric_xform_capability {
 
 		uint32_t mldsa_capa[RTE_CRYPTO_ML_DSA_OP_END];
 		/**< Bitmask of supported ML-DSA parameter sets. */
+
+		struct rte_crypto_rsa_capa rsa_capa;
+		/**< RSA modulus length, MGF1 hash, and padding capabilities. */
 	};
 
 	uint64_t hash_algos;
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 02/10] crypto/virtio: advertise RSA padding and hash capabilities
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 01/10] crypto: add RSA-specific capability parameters Sucharitha Sarananaga
@ 2026-08-31 10:23 ` Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 03/10] crypto/octeontx: advertise RSA PKCS#1 v1.5 padding support Sucharitha Sarananaga
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Update the virtio cryptodev RSA asymmetric capability to use
rsa_capa and report supported padding schemes and primary hash
algorithms.

Advertise RTE_CRYPTO_RSA_PADDING_NONE and
RTE_CRYPTO_RSA_PADDING_PKCS1_5 via pad_types, and MD5, SHA-1,
SHA-224, SHA-256, and SHA-512 via hash_algos to match PKCS#1
v1.5 hash support in the PMD.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 .../virtio/virtio_crypto_capabilities.h       | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/virtio/virtio_crypto_capabilities.h b/drivers/crypto/virtio/virtio_crypto_capabilities.h
index 1b26ff6720..7d5eea1f9d 100644
--- a/drivers/crypto/virtio/virtio_crypto_capabilities.h
+++ b/drivers/crypto/virtio/virtio_crypto_capabilities.h
@@ -58,11 +58,20 @@
 					(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |  \
 					(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) | \
 					(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)), \
-			{.modlen = {					\
-				.min = 1,				\
-				.max = 1024,				\
-				.increment = 1				\
-			}, }						\
+			.rsa_capa = {					\
+				.modlen = {					\
+					.min = 1,				\
+					.max = 1024,				\
+					.increment = 1				\
+				},						\
+				.pad_types = ((1 << RTE_CRYPTO_RSA_PADDING_NONE) | \
+					(1 << RTE_CRYPTO_RSA_PADDING_PKCS1_5)), \
+			},						\
+			.hash_algos = (RTE_BIT64(RTE_CRYPTO_AUTH_MD5) |	\
+				RTE_BIT64(RTE_CRYPTO_AUTH_SHA1) |		\
+				RTE_BIT64(RTE_CRYPTO_AUTH_SHA224) |		\
+				RTE_BIT64(RTE_CRYPTO_AUTH_SHA256) |		\
+				RTE_BIT64(RTE_CRYPTO_AUTH_SHA512)),		\
 		}							\
 		 }, }							\
 	}
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 03/10] crypto/octeontx: advertise RSA PKCS#1 v1.5 padding support
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 01/10] crypto: add RSA-specific capability parameters Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 02/10] crypto/virtio: advertise RSA padding and hash capabilities Sucharitha Sarananaga
@ 2026-08-31 10:23 ` Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 04/10] crypto/cnxk: " Sucharitha Sarananaga
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Update the OcteonTX cryptodev RSA asymmetric capability to use
rsa_capa and report supported padding schemes.

Advertise RTE_CRYPTO_RSA_PADDING_NONE and
RTE_CRYPTO_RSA_PADDING_PKCS1_5 via pad_types to match RSA
padding support in the PMD.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/octeontx/otx_cryptodev_capabilities.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/octeontx/otx_cryptodev_capabilities.c b/drivers/crypto/octeontx/otx_cryptodev_capabilities.c
index 80a9fe2123..8a70f81e1f 100644
--- a/drivers/crypto/octeontx/otx_cryptodev_capabilities.c
+++ b/drivers/crypto/octeontx/otx_cryptodev_capabilities.c
@@ -608,11 +608,15 @@ static const struct rte_cryptodev_capabilities otx_asym_capabilities[] = {
 					(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |
 					(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) |
 					(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)),
-				{.modlen = {
+				.rsa_capa = {
+				.modlen = {
 					.min = 17,
 					.max = 1024,
 					.increment = 1
-				}, }
+				},
+				.pad_types = ((1 << RTE_CRYPTO_RSA_PADDING_NONE) |
+					(1 << RTE_CRYPTO_RSA_PADDING_PKCS1_5)),
+				},
 			}
 		}, }
 	},
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 04/10] crypto/cnxk: advertise RSA PKCS#1 v1.5 padding support
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                   ` (2 preceding siblings ...)
  2026-08-31 10:23 ` [PATCH 03/10] crypto/octeontx: advertise RSA PKCS#1 v1.5 padding support Sucharitha Sarananaga
@ 2026-08-31 10:23 ` Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 05/10] crypto/qat: advertise RSA padding capabilities Sucharitha Sarananaga
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Update the CNXK cryptodev RSA asymmetric capability to use
rsa_capa and report supported padding schemes.

Advertise RTE_CRYPTO_RSA_PADDING_NONE and
RTE_CRYPTO_RSA_PADDING_PKCS1_5 via pad_types to match RSA
padding support in the PMD.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c b/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
index 736d588bde..577f080ba7 100644
--- a/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
+++ b/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
@@ -60,11 +60,15 @@ static const struct rte_cryptodev_capabilities caps_mul[] = {
 					(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |
 					(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) |
 					(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)),
-				{.modlen = {
+				.rsa_capa = {
+				.modlen = {
 					.min = 17,
 					.max = 1024,
 					.increment = 1
-				}, }
+				},
+				.pad_types = ((1 << RTE_CRYPTO_RSA_PADDING_NONE) |
+					(1 << RTE_CRYPTO_RSA_PADDING_PKCS1_5)),
+				},
 			}
 		}, }
 	},
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 05/10] crypto/qat: advertise RSA padding capabilities
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                   ` (3 preceding siblings ...)
  2026-08-31 10:23 ` [PATCH 04/10] crypto/cnxk: " Sucharitha Sarananaga
@ 2026-08-31 10:23 ` Sucharitha Sarananaga
  2026-08-31 12:11   ` Radu Nicolau
  2026-08-31 10:23 ` [PATCH 06/10] crypto/openssl: advertise RSA padding and hash capabilities Sucharitha Sarananaga
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Add QAT_ASYM_RSA_CAP macro to report RSA asymmetric capabilities
using rsa_capa, including modulus length and padding schemes.

Update Gen1 and Gen4 QAT asymmetric PMDs to advertise
RTE_CRYPTO_RSA_PADDING_NONE via pad_types, matching the padding
mode supported by the QAT RSA implementation.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/qat/asym/qat_asym.h           | 20 ++++++++++++++++++++
 drivers/crypto/qat/dev/qat_asym_pmd_gen1.c   |  5 +++--
 drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c |  5 +++--
 3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/qat/asym/qat_asym.h b/drivers/crypto/qat/asym/qat_asym.h
index 0ecbc47548..cf40d445df 100644
--- a/drivers/crypto/qat/asym/qat_asym.h
+++ b/drivers/crypto/qat/asym/qat_asym.h
@@ -56,6 +56,26 @@ typedef uint64_t large_int_ptr;
 		}							\
 	}
 
+#define QAT_ASYM_RSA_CAP(o, l, r, i, p)					\
+	{								\
+		.op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC,			\
+		{.asym = {						\
+			.xform_capa = {					\
+				.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA, \
+				.op_types = o,				\
+				.rsa_capa = {				\
+				.modlen = {				\
+				.min = l,				\
+				.max = r,				\
+				.increment = i				\
+				},					\
+				.pad_types = p,				\
+				},					\
+			}						\
+		},							\
+		}							\
+	}
+
 struct __rte_aligned(8) qat_asym_op_cookie {
 	uint64_t error;
 	uint32_t alg_bytesize; /* Bytesize of algorithm */
diff --git a/drivers/crypto/qat/dev/qat_asym_pmd_gen1.c b/drivers/crypto/qat/dev/qat_asym_pmd_gen1.c
index c96608dd37..5b93cf374b 100644
--- a/drivers/crypto/qat/dev/qat_asym_pmd_gen1.c
+++ b/drivers/crypto/qat/dev/qat_asym_pmd_gen1.c
@@ -32,12 +32,13 @@ static struct rte_cryptodev_capabilities qat_asym_crypto_caps_gen1[] = {
 		0, 1, 512, 1),
 	QAT_ASYM_CAP(MODINV,
 		0, 1, 512, 1),
-	QAT_ASYM_CAP(RSA,
+	QAT_ASYM_RSA_CAP(
 			((1 << RTE_CRYPTO_ASYM_OP_SIGN) |
 			(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |
 			(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) |
 			(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)),
-			64, 512, 64),
+			64, 512, 64,
+			(1 << RTE_CRYPTO_RSA_PADDING_NONE)),
 	QAT_ASYM_CAP(ECDH,
 			((1 << RTE_CRYPTO_ASYM_KE_PUB_KEY_GENERATE) |
 			(1 << RTE_CRYPTO_ASYM_KE_SHARED_SECRET_COMPUTE) |
diff --git a/drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c b/drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c
index 41cad29142..106c512a06 100644
--- a/drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c
+++ b/drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c
@@ -121,12 +121,13 @@ static struct rte_cryptodev_capabilities qat_asym_crypto_caps_gen4[] = {
 		0, 1, 512, 1),
 	QAT_ASYM_CAP(MODINV,
 		0, 1, 512, 1),
-	QAT_ASYM_CAP(RSA,
+	QAT_ASYM_RSA_CAP(
 			((1 << RTE_CRYPTO_ASYM_OP_SIGN) |
 			(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |
 			(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) |
 			(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)),
-			64, 512, 64),
+			64, 512, 64,
+			(1 << RTE_CRYPTO_RSA_PADDING_NONE)),
 	{	/* SM2 */
 		.op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
 		{.asym = {
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 06/10] crypto/openssl: advertise RSA padding and hash capabilities
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                   ` (4 preceding siblings ...)
  2026-08-31 10:23 ` [PATCH 05/10] crypto/qat: advertise RSA padding capabilities Sucharitha Sarananaga
@ 2026-08-31 10:23 ` Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 07/10] crypto/openssl: add RSA-OAEP support for OpenSSL PMD Sucharitha Sarananaga
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Extend the OpenSSL PMD RSA asymmetric capability to use rsa_capa
and report supported padding schemes, primary hash algorithms,
and MGF1 hash algorithms.

For OpenSSL 3.0 and later, advertise OAEP padding along with
SHA-1, SHA-2, and SHA-3 digests for both primary hash and MGF1.
For older OpenSSL versions, advertise only NONE and PKCS#1 v1.5
padding modes supported by the PMD.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/openssl/rte_openssl_pmd_ops.c | 32 ++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
index d927cc5228..33134573e5 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
@@ -731,14 +731,42 @@ static const struct rte_cryptodev_capabilities openssl_pmd_capabilities[] = {
 					(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |
 					(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) |
 					(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)),
-				{
+				.rsa_capa = {
 				.modlen = {
 				/* min length is based on openssl rsa keygen */
 				.min = 30,
 				/* value 0 symbolizes no limit on max length */
 				.max = 0,
 				.increment = 1
-				}, }
+				},
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+				.pad_types = ((1 << RTE_CRYPTO_RSA_PADDING_NONE) |
+					(1 << RTE_CRYPTO_RSA_PADDING_PKCS1_5) |
+					(1 << RTE_CRYPTO_RSA_PADDING_OAEP)),
+				.mgf1_hash_algos = (RTE_BIT64(RTE_CRYPTO_AUTH_SHA1) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA224) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA256) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA384) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA512) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_224) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_256) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_384) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_512)),
+				},
+				.hash_algos = (RTE_BIT64(RTE_CRYPTO_AUTH_SHA1) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA224) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA256) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA384) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA512) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_224) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_256) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_384) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_512)),
+#else
+				.pad_types = ((1 << RTE_CRYPTO_RSA_PADDING_NONE) |
+					(1 << RTE_CRYPTO_RSA_PADDING_PKCS1_5)),
+				},
+#endif
 			}
 		},
 		}
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 07/10] crypto/openssl: add RSA-OAEP support for OpenSSL PMD
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                   ` (5 preceding siblings ...)
  2026-08-31 10:23 ` [PATCH 06/10] crypto/openssl: advertise RSA padding and hash capabilities Sucharitha Sarananaga
@ 2026-08-31 10:23 ` Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 08/10] app/test: add RSA OAEP asymmetric test cases Sucharitha Sarananaga
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Add support for RSA OAEP padding in the OpenSSL PMD OpenSSL 3.x
implementation.

Store OAEP configuration parameters in the RSA asymmetric session,
including the OAEP hash, MGF1 hash, and optional label. Configure
these parameters on the EVP_PKEY context during RSA encrypt and
decrypt operations, and default the MGF1 hash to the OAEP hash when
not specified by the application.

Validate OAEP-specific usage, restrict it to encrypt/decrypt
operations, and add proper cleanup of allocated label resources on
error and session teardown paths.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/openssl/openssl_pmd_private.h |  5 ++
 drivers/crypto/openssl/rte_openssl_pmd.c     | 53 ++++++++++++
 drivers/crypto/openssl/rte_openssl_pmd_ops.c | 90 ++++++++++++++++++++
 3 files changed, 148 insertions(+)

diff --git a/drivers/crypto/openssl/openssl_pmd_private.h b/drivers/crypto/openssl/openssl_pmd_private.h
index ab40012d61..8704e1915a 100644
--- a/drivers/crypto/openssl/openssl_pmd_private.h
+++ b/drivers/crypto/openssl/openssl_pmd_private.h
@@ -181,6 +181,11 @@ struct __rte_cache_aligned openssl_asym_session {
 			RSA *rsa;
 			uint32_t pad;
 			EVP_PKEY_CTX * ctx;
+			const EVP_MD *oaep_md;
+			const EVP_MD *mgf1_md;
+
+			uint8_t *label;
+			uint32_t label_len;
 		} r;
 		struct exp {
 			BIGNUM *exp;
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 2319c7cfa9..4fbbb73bfa 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -2292,6 +2292,41 @@ process_openssl_modexp_op(struct rte_crypto_op *cop,
 	return 0;
 }
 
+/**
+ * Configure RSA-OAEP parameters on an initialized EVP_PKEY_CTX.
+ * Must be called after EVP_PKEY_encrypt_init() or EVP_PKEY_decrypt_init().
+ *
+ * @return 0 on success, -1 on failure.
+ */
+static int
+openssl_rsa_set_oaep_params(EVP_PKEY_CTX *ctx,
+		const struct openssl_asym_session *sess)
+{
+	if (sess->u.r.pad != RTE_CRYPTO_RSA_PADDING_OAEP)
+		return 0;
+
+	if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, sess->u.r.oaep_md) <= 0)
+		return -1;
+
+	if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sess->u.r.mgf1_md) <= 0)
+		return -1;
+
+	if (sess->u.r.label_len > 0) {
+		void *label = OPENSSL_memdup(sess->u.r.label, sess->u.r.label_len);
+
+		if (label == NULL)
+			return -1;
+
+		if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label, sess->u.r.label_len) <= 0) {
+			OPENSSL_free(label);
+			return -1;
+		}
+	}
+	/* Empty label is default; set0_rsa_oaep_label(NULL,0) fails on OpenSSL 3. */
+
+	return 0;
+}
+
 /* process rsa operations */
 static int
 process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
@@ -2308,6 +2343,15 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 	if (!rsa_ctx)
 		return ret;
 
+	/* OAEP is only valid for encrypt/decrypt */
+	if (sess->u.r.pad == RTE_CRYPTO_RSA_PADDING_OAEP &&
+			op->rsa.op_type != RTE_CRYPTO_ASYM_OP_ENCRYPT &&
+			op->rsa.op_type != RTE_CRYPTO_ASYM_OP_DECRYPT) {
+		OPENSSL_LOG(ERR, "OAEP supports encrypt/decrypt only");
+		cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+		return ret;
+	}
+
 	switch (pad) {
 	case RTE_CRYPTO_RSA_PADDING_PKCS1_5:
 		pad = RSA_PKCS1_PADDING;
@@ -2315,6 +2359,9 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 	case RTE_CRYPTO_RSA_PADDING_NONE:
 		pad = RSA_NO_PADDING;
 		break;
+	case RTE_CRYPTO_RSA_PADDING_OAEP:
+		pad = RSA_PKCS1_OAEP_PADDING;
+		break;
 	default:
 		cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 		OPENSSL_LOG(ERR,
@@ -2330,6 +2377,9 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 		if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, pad) <= 0)
 			goto err_rsa;
 
+		if (openssl_rsa_set_oaep_params(rsa_ctx, sess) < 0)
+			goto err_rsa;
+
 		if (EVP_PKEY_encrypt(rsa_ctx, NULL, &outlen,
 				op->rsa.message.data,
 				op->rsa.message.length) <= 0)
@@ -2355,6 +2405,9 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 		if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, pad) <= 0)
 			goto err_rsa;
 
+		if (openssl_rsa_set_oaep_params(rsa_ctx, sess) < 0)
+			goto err_rsa;
+
 		if (EVP_PKEY_decrypt(rsa_ctx, NULL, &outlen,
 				op->rsa.cipher.data,
 				op->rsa.cipher.length) <= 0)
diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
index 33134573e5..2504cfb9f5 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
@@ -2,6 +2,7 @@
  * Copyright(c) 2016-2017 Intel Corporation
  */
 
+#include <limits.h>
 #include <string.h>
 
 #include <rte_common.h>
@@ -1214,6 +1215,33 @@ openssl_pmd_sym_session_configure(struct rte_cryptodev *dev,
 	return 0;
 }
 
+static const EVP_MD *
+openssl_get_md(enum rte_crypto_auth_algorithm alg)
+{
+	switch (alg) {
+	case RTE_CRYPTO_AUTH_SHA1:
+		return EVP_sha1();
+	case RTE_CRYPTO_AUTH_SHA224:
+		return EVP_sha224();
+	case RTE_CRYPTO_AUTH_SHA256:
+		return EVP_sha256();
+	case RTE_CRYPTO_AUTH_SHA384:
+		return EVP_sha384();
+	case RTE_CRYPTO_AUTH_SHA512:
+		return EVP_sha512();
+	case RTE_CRYPTO_AUTH_SHA3_224:
+		return EVP_sha3_224();
+	case RTE_CRYPTO_AUTH_SHA3_256:
+		return EVP_sha3_256();
+	case RTE_CRYPTO_AUTH_SHA3_384:
+		return EVP_sha3_384();
+	case RTE_CRYPTO_AUTH_SHA3_512:
+		return EVP_sha3_512();
+	default:
+		return NULL;
+	}
+}
+
 static int openssl_set_asym_session_parameters(
 		struct openssl_asym_session *asym_session,
 		struct rte_crypto_asym_xform *xform)
@@ -1235,6 +1263,7 @@ static int openssl_set_asym_session_parameters(
 		BIGNUM *d = NULL;
 		BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL;
 		BIGNUM *iqmp = NULL, *dmq1 = NULL;
+		uint32_t label_len = 0;
 
 		/* copy xfrm data into rsa struct */
 		n = BN_bin2bn((const unsigned char *)xform->rsa.n.data,
@@ -1246,6 +1275,57 @@ static int openssl_set_asym_session_parameters(
 			goto err_rsa;
 
 		asym_session->u.r.pad = xform->rsa.padding.type;
+		if (xform->rsa.padding.type == RTE_CRYPTO_RSA_PADDING_OAEP) {
+			asym_session->u.r.oaep_md = openssl_get_md(xform->rsa.padding.hash);
+
+			if (asym_session->u.r.oaep_md == NULL) {
+				OPENSSL_LOG(ERR,
+					"Unsupported OAEP hash algorithm %u",
+					xform->rsa.padding.hash);
+				goto err_rsa;
+			}
+
+			enum rte_crypto_auth_algorithm mgf1 = xform->rsa.padding.mgf1hash;
+
+			if (mgf1 == 0)
+				mgf1 = xform->rsa.padding.hash;
+
+			asym_session->u.r.mgf1_md = openssl_get_md(mgf1);
+			if (asym_session->u.r.mgf1_md == NULL) {
+				OPENSSL_LOG(ERR,
+					"Unsupported OAEP MGF1 hash algorithm %u", mgf1);
+				goto err_rsa;
+			}
+
+			if (xform->rsa.padding.oaep_label.length > (size_t)INT_MAX) {
+				OPENSSL_LOG(ERR,
+					"OAEP label length %zu is too large",
+					xform->rsa.padding.oaep_label.length);
+				goto err_rsa;
+			}
+
+			label_len = (uint32_t)xform->rsa.padding.oaep_label.length;
+			if (label_len > 0) {
+				if (xform->rsa.padding.oaep_label.data == NULL) {
+					OPENSSL_LOG(ERR,
+						"OAEP label length is non-zero but data is NULL");
+					goto err_rsa;
+				}
+
+				asym_session->u.r.label = OPENSSL_zalloc(label_len);
+				if (asym_session->u.r.label == NULL)
+					goto err_rsa;
+
+				rte_memcpy(asym_session->u.r.label,
+					xform->rsa.padding.oaep_label.data,
+					label_len);
+				asym_session->u.r.label_len = label_len;
+			} else {
+				asym_session->u.r.label_len = 0;
+				asym_session->u.r.label = NULL;
+			}
+		}
+
 		OSSL_PARAM_BLD * param_bld = OSSL_PARAM_BLD_new();
 		if (!param_bld) {
 			OPENSSL_LOG(ERR, "failed to allocate resources");
@@ -1348,6 +1428,11 @@ static int openssl_set_asym_session_parameters(
 		ret = 0;
 
 err_rsa:
+		if (ret != 0 && asym_session->u.r.label) {
+			OPENSSL_free(asym_session->u.r.label);
+			asym_session->u.r.label = NULL;
+			asym_session->u.r.label_len = 0;
+		}
 		BN_clear_free(n);
 		BN_clear_free(e);
 		BN_clear_free(d);
@@ -1823,6 +1908,11 @@ static void openssl_reset_asym_session(struct openssl_asym_session *sess)
 	switch (sess->xfrm_type) {
 	case RTE_CRYPTO_ASYM_XFORM_RSA:
 		EVP_PKEY_CTX_free(sess->u.r.ctx);
+		if (sess->u.r.label_len > 0) {
+			OPENSSL_free(sess->u.r.label);
+			sess->u.r.label = NULL;
+			sess->u.r.label_len = 0;
+		}
 		break;
 	case RTE_CRYPTO_ASYM_XFORM_MODEX:
 		if (sess->u.e.ctx) {
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 08/10] app/test: add RSA OAEP asymmetric test cases
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                   ` (6 preceding siblings ...)
  2026-08-31 10:23 ` [PATCH 07/10] crypto/openssl: add RSA-OAEP support for OpenSSL PMD Sucharitha Sarananaga
@ 2026-08-31 10:23 ` Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 09/10] crypto/openssl: add RSA-PSS support for RSA operations Sucharitha Sarananaga
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Add RSA OAEP encrypt/decrypt tests to the asymmetric cryptodev test
suite.

Introduce OAEP test vectors with default and custom OAEP parameters,
including support for custom MGF1 hashes and OAEP labels. The tests
cover both exponent and CRT private key types and execute end-to-end
encrypt/decrypt validation.

Add capability checks to skip the tests on devices that do not support
OAEP padding or the required RSA private key operations. Also extend
capability reporting to display RSA padding and hash capabilities.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 app/test/test_cryptodev_asym.c             | 356 +++++++++++++++++++++
 app/test/test_cryptodev_rsa_test_vectors.h | 154 +++++++++
 2 files changed, 510 insertions(+)

diff --git a/app/test/test_cryptodev_asym.c b/app/test/test_cryptodev_asym.c
index 7b8afe5f92..ceae029a4a 100644
--- a/app/test/test_cryptodev_asym.c
+++ b/app/test/test_cryptodev_asym.c
@@ -273,6 +273,339 @@ queue_ops_rsa_enc_dec(void *sess)
 	return status;
 }
 
+/*
+ * Check that the device supports RSA-OAEP padding, along with the
+ * specific hash and MGF1 hash used by padding. If mgf1hash is left
+ * unconfigured (0), the PMD falls back to using hash for MGF1, which
+ * is already covered by the hash_algos check above, so mgf1_hash_algos
+ * only needs checking when mgf1hash is explicitly set.
+ */
+static int
+rsa_oaep_supported(uint8_t dev_id, const struct rte_crypto_rsa_padding *padding)
+{
+	struct rte_cryptodev_asym_capability_idx idx = {
+		.type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	};
+	const struct rte_cryptodev_asymmetric_xform_capability *capa;
+
+	capa = rte_cryptodev_asym_capability_get(dev_id, &idx);
+	if (capa == NULL) {
+		RTE_LOG(INFO, USER1, "RSA capability not reported by device\n");
+		return 0;
+	}
+
+	if (capa->rsa_capa.pad_types != 0 &&
+			(capa->rsa_capa.pad_types & (1 << RTE_CRYPTO_RSA_PADDING_OAEP)) == 0) {
+		RTE_LOG(INFO, USER1,
+			"RSA OAEP padding not supported by device. Supported pad_types=%#x\n",
+			capa->rsa_capa.pad_types);
+		return 0;
+	}
+
+	if (!rte_cryptodev_asym_xform_capability_check_hash(capa, padding->hash)) {
+		RTE_LOG(INFO, USER1,
+			"RSA OAEP hash %u not supported by device capabilities "
+			"(supported hash_algos=%#"PRIx64")\n",
+			padding->hash, capa->hash_algos);
+		return 0;
+	}
+
+	if (padding->mgf1hash != 0 &&
+			(capa->rsa_capa.mgf1_hash_algos & RTE_BIT64(padding->mgf1hash)) == 0) {
+		RTE_LOG(INFO, USER1,
+			"RSA OAEP MGF1 hash %u not supported by device capabilities "
+			"(supported mgf1_hash_algos=%#"PRIx64")\n",
+			padding->mgf1hash, capa->rsa_capa.mgf1_hash_algos);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int
+test_rsa_oaep_enc_dec(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id, &rsa_oaep_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_oaep_xform, sizeof(rsa_oaep_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for OAEP enc_dec\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_oaep_enc_dec_crt(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id, &rsa_oaep_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"quintuple key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &rsa_oaep_xform,
+			sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"OAEP enc_dec_crt\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_oaep_labeled_enc_dec(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id, &rsa_oaep_labeled_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_oaep_labeled_xform, sizeof(rsa_oaep_labeled_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"OAEP labeled enc_dec\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_oaep_labeled_enc_dec_crt(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id, &rsa_oaep_labeled_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"quintuple key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &rsa_oaep_labeled_xform,
+			sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"OAEP labeled enc_dec_crt\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_oaep_labeled_default_mgf1_enc_dec(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id,
+			&rsa_oaep_labeled_default_mgf1_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_oaep_labeled_default_mgf1_xform,
+			sizeof(rsa_oaep_labeled_default_mgf1_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"OAEP labeled default MGF1 enc_dec\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_oaep_labeled_default_mgf1_enc_dec_crt(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id,
+			&rsa_oaep_labeled_default_mgf1_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"quintuple key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	ret = rte_cryptodev_asym_session_create(dev_id,
+			&rsa_oaep_labeled_default_mgf1_xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"OAEP labeled default MGF1 enc_dec_crt\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
 static int
 test_rsa_sign_verify(void)
 {
@@ -677,6 +1010,18 @@ static inline void print_asym_capa(
 	}
 	switch (capa->xform_type) {
 	case RTE_CRYPTO_ASYM_XFORM_RSA:
+		printf(" modlen: min %d max %d increment %d",
+				capa->rsa_capa.modlen.min,
+				capa->rsa_capa.modlen.max,
+				capa->rsa_capa.modlen.increment);
+		if (capa->rsa_capa.pad_types != 0)
+			printf(" pad_types: %#x", capa->rsa_capa.pad_types);
+		if (capa->rsa_capa.mgf1_hash_algos != 0)
+			printf(" mgf1_hash_algos: %#" PRIx64,
+				capa->rsa_capa.mgf1_hash_algos);
+		if (capa->hash_algos != 0)
+			printf(" hash_algos: %#" PRIx64, capa->hash_algos);
+		break;
 	case RTE_CRYPTO_ASYM_XFORM_MODINV:
 	case RTE_CRYPTO_ASYM_XFORM_MODEX:
 	case RTE_CRYPTO_ASYM_XFORM_DH:
@@ -5349,6 +5694,17 @@ static struct unit_test_suite cryptodev_asym_rsa_testsuite = {
 				test_rsa_enc_dec_crt),
 		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
 				test_rsa_sign_verify_crt),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym, test_rsa_oaep_enc_dec),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_oaep_enc_dec_crt),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_oaep_labeled_enc_dec),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_oaep_labeled_enc_dec_crt),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_oaep_labeled_default_mgf1_enc_dec),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_oaep_labeled_default_mgf1_enc_dec_crt),
 		/* RSA EXP */
 		TEST_CASE_NAMED_WITH_DATA(
 			"RSA Encryption (n=128, pt=20, e=3) EXP, Padding: NONE",
diff --git a/app/test/test_cryptodev_rsa_test_vectors.h b/app/test/test_cryptodev_rsa_test_vectors.h
index 9652b0d43a..6835453b6d 100644
--- a/app/test/test_cryptodev_rsa_test_vectors.h
+++ b/app/test/test_cryptodev_rsa_test_vectors.h
@@ -236,6 +236,12 @@ rsa_test_data_2 rsa_vector_128_20_3_none = {
 	.padding = RTE_CRYPTO_RSA_PADDING_NONE,
 };
 
+uint8_t rsa_oaep_label[] = {
+	0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f, 0x60, 0x71,
+	0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7, 0xe8, 0xf9,
+	0x01, 0x12, 0x23, 0x34
+};
+
 struct rsa_test_data rsaplaintext = {
 	.data = {
 		0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae,
@@ -384,4 +390,152 @@ struct rte_crypto_asym_xform rsa_xform = {
 	}
 };
 
+/** rsa OAEP xform (SHA-256, QT private key type by default) */
+struct rte_crypto_asym_xform rsa_oaep_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_OAEP,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
+/** rsa OAEP xform with MGF1-SHA1 and label */
+struct rte_crypto_asym_xform rsa_oaep_labeled_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_OAEP,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.padding.mgf1hash = RTE_CRYPTO_AUTH_SHA1,
+		.padding.oaep_label = {
+			.data = rsa_oaep_label,
+			.length = sizeof(rsa_oaep_label)
+		},
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
+/**
+ * rsa OAEP xform with label but no explicit MGF1 hash.
+ * mgf1hash is left unset (0) so the PMD falls back to using the
+ * primary hash (SHA-256) for MGF1
+ */
+struct rte_crypto_asym_xform rsa_oaep_labeled_default_mgf1_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_OAEP,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.padding.oaep_label = {
+			.data = rsa_oaep_label,
+			.length = sizeof(rsa_oaep_label)
+		},
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
 #endif /* TEST_CRYPTODEV_RSA_TEST_VECTORS_H__ */
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 09/10] crypto/openssl: add RSA-PSS support for RSA operations
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                   ` (7 preceding siblings ...)
  2026-08-31 10:23 ` [PATCH 08/10] app/test: add RSA OAEP asymmetric test cases Sucharitha Sarananaga
@ 2026-08-31 10:23 ` Sucharitha Sarananaga
  2026-08-31 10:23 ` [PATCH 10/10] app/test: add RSA-PSS sign and verify test cases Sucharitha Sarananaga
  2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
  10 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Add RSA-PSS padding support to the OpenSSL crypto PMD.

Store PSS-specific parameters (hash, MGF1 hash, and salt length)
in the RSA session, advertise PSS capability, and configure the
OpenSSL EVP context accordingly for sign and verify operations.

Introduce a dedicated RSA-PSS verification path using
EVP_PKEY_verify(), while retaining verify-recover for supported
deterministic padding schemes. Reject unsupported RSA-PSS usage
for non-sign/verify operations.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/openssl/openssl_pmd_private.h |   6 +
 drivers/crypto/openssl/rte_openssl_pmd.c     | 314 +++++++++++++++----
 drivers/crypto/openssl/rte_openssl_pmd_ops.c |  27 +-
 3 files changed, 292 insertions(+), 55 deletions(-)

diff --git a/drivers/crypto/openssl/openssl_pmd_private.h b/drivers/crypto/openssl/openssl_pmd_private.h
index 8704e1915a..8a6db6066f 100644
--- a/drivers/crypto/openssl/openssl_pmd_private.h
+++ b/drivers/crypto/openssl/openssl_pmd_private.h
@@ -5,6 +5,8 @@
 #ifndef _OPENSSL_PMD_PRIVATE_H_
 #define _OPENSSL_PMD_PRIVATE_H_
 
+#include <rte_common.h>
+
 #include <openssl/evp.h>
 #include <openssl/cmac.h>
 #include <openssl/hmac.h>
@@ -186,6 +188,10 @@ struct __rte_cache_aligned openssl_asym_session {
 
 			uint8_t *label;
 			uint32_t label_len;
+
+			const EVP_MD *pss_md;
+			const EVP_MD *pss_mgf1_md;
+			int pss_saltlen;
 		} r;
 		struct exp {
 			BIGNUM *exp;
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 4fbbb73bfa..1b33470c8f 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -2327,6 +2327,216 @@ openssl_rsa_set_oaep_params(EVP_PKEY_CTX *ctx,
 	return 0;
 }
 
+/**
+ * Configure RSA-PSS padding parameters, including the signature digest,
+ * on an initialized EVP_PKEY_CTX. Must be called after
+ * EVP_PKEY_CTX_set_rsa_padding().
+ *
+ * @return 0 on success, -1 on failure.
+ */
+static int
+openssl_rsa_set_pss_params(EVP_PKEY_CTX *ctx,
+		const struct openssl_asym_session *sess)
+{
+	/*
+	 * Tells OpenSSL which hash algorithm was used to create the
+	 * input message digest (rte_crypto_rsa_padding::hash), so it
+	 * knows the expected digest length and can embed the correct
+	 * algorithm identifier while PSS-encoding it. This does not
+	 * cause the digest to be (re-)computed here: EVP_PKEY_sign()/
+	 * EVP_PKEY_verify() operate on the digest bytes as-is.
+	 */
+	if (EVP_PKEY_CTX_set_signature_md(ctx, sess->u.r.pss_md) <= 0)
+		return -1;
+
+	if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sess->u.r.pss_mgf1_md) <= 0)
+		return -1;
+
+	/* pss_saltlen is a literal byte count (0 is valid: no salt) */
+	if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sess->u.r.pss_saltlen) <= 0)
+		return -1;
+
+	return 0;
+}
+
+/**
+ * Sign a message using RSA-PSS. Per rte_crypto_rsa_op_param::message and
+ * rte_crypto_rsa_padding::hash, the input is a digest already hashed by
+ * the caller with the configured algorithm, not the raw message, so
+ * EVP_PKEY_sign() is used directly on it (no internal re-hashing). This
+ * matches the pattern used for PKCS#1 v1.5/unpadded RSA signing in
+ * process_openssl_rsa_op_evp().
+ *
+ * The OpenSSL PMD does not advertise rte_crypto_rsa_capa::pss_explicit_salt,
+ * so an application-supplied rte_crypto_rsa_op_param::pss_salt is rejected
+ * by the caller before this function is invoked; the salt is always
+ * generated internally by OpenSSL's RNG via EVP_PKEY_sign().
+ *
+ * @return 0 on success, -1 on failure.
+ */
+static int
+openssl_rsa_pss_sign(uint32_t pad, const struct openssl_asym_session *sess,
+		struct rte_crypto_asym_op *op)
+{
+	EVP_PKEY_CTX *ctx = sess->u.r.ctx;
+	size_t outlen = 0;
+
+	if (EVP_PKEY_sign_init(ctx) <= 0)
+		return -1;
+
+	if (EVP_PKEY_CTX_set_rsa_padding(ctx, pad) <= 0)
+		return -1;
+
+	if (openssl_rsa_set_pss_params(ctx, sess) < 0)
+		return -1;
+
+	if (EVP_PKEY_sign(ctx, NULL, &outlen,
+			op->rsa.message.data, op->rsa.message.length) <= 0)
+		return -1;
+
+	if (outlen == 0 || outlen > op->rsa.sign.length)
+		return -1;
+
+	outlen = op->rsa.sign.length;
+	if (EVP_PKEY_sign(ctx, op->rsa.sign.data, &outlen,
+			op->rsa.message.data, op->rsa.message.length) <= 0)
+		return -1;
+
+	op->rsa.sign.length = outlen;
+	return 0;
+}
+
+/**
+ * Verify an RSA-PSS signature against a pre-computed message digest.
+ * Per rte_crypto_rsa_op_param::message and rte_crypto_rsa_padding::hash,
+ * the input is already a digest, so EVP_PKEY_verify() is used directly
+ * on it (no internal re-hashing). PSS does not support verify-recover,
+ * so this also gives a direct pass/fail result.
+ *
+ * A signature mismatch (including one caused by OpenSSL rejecting a
+ * malformed signature outright, e.g. wrong size) is a normal outcome,
+ * not a processing error, so it must not fail the enqueue operation.
+ *
+ * @return 0 if the signature is valid, 1 if invalid/mismatched,
+ *         -1 on a setup/processing failure unrelated to the signature.
+ */
+static int
+openssl_rsa_pss_verify(uint32_t pad, const struct openssl_asym_session *sess,
+		struct rte_crypto_asym_op *op)
+{
+	EVP_PKEY_CTX *ctx = sess->u.r.ctx;
+	int ret;
+
+	if (EVP_PKEY_verify_init(ctx) <= 0)
+		return -1;
+
+	if (EVP_PKEY_CTX_set_rsa_padding(ctx, pad) <= 0)
+		return -1;
+
+	if (openssl_rsa_set_pss_params(ctx, sess) < 0)
+		return -1;
+
+	/*
+	 * EVP_PKEY_verify() returns 1 for a valid signature, 0 for an
+	 * invalid one, and a negative value only for setup/library errors
+	 * (see EVP_PKEY_verify(3)); a malformed signature is reported via
+	 * a 0 return here too, not a negative one.
+	 */
+	ret = EVP_PKEY_verify(ctx,
+			op->rsa.sign.data, op->rsa.sign.length,
+			op->rsa.message.data, op->rsa.message.length);
+	if (ret < 0)
+		return -1;
+
+	if (ret == 0) {
+		OPENSSL_LOG(DEBUG, "RSA-PSS signature verification failed");
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * Verify an RSA signature using verify-recover, for deterministic
+ * padding schemes (PKCS#1 v1.5, no padding). Not applicable to PSS,
+ * since OpenSSL does not support recover-mode verification for PSS
+ * (RSA-PSS is a probabilistic scheme and cannot be undone to recover
+ * the original digest).
+ *
+ * A signature mismatch is a normal outcome, not a processing error, so
+ * it must not fail the enqueue operation. Note that EVP_PKEY_verify_recover()
+ * itself can return <= 0 for a mismatch too, e.g. when the signature does not
+ * decode to a validly padded value (OpenSSL then reports it as a hard
+ * "data too large for modulus"/padding error rather than a soft 0 return),
+ * so that case is treated the same as a successful-but-mismatching recover.
+ *
+ * @return 0 if the signature is valid, 1 if invalid/mismatched,
+ *         -1 on a setup/processing failure unrelated to the signature.
+ */
+static int
+openssl_rsa_verify_recover(EVP_PKEY_CTX *ctx, uint32_t pad,
+		struct rte_crypto_asym_op *op)
+{
+	uint8_t *tmp;
+	size_t outlen = 0;
+	int ret;
+
+	if (EVP_PKEY_verify_recover_init(ctx) <= 0)
+		return -1;
+
+	if (EVP_PKEY_CTX_set_rsa_padding(ctx, pad) <= 0)
+		return -1;
+
+	if (EVP_PKEY_verify_recover(ctx, NULL, &outlen,
+			op->rsa.sign.data,
+			op->rsa.sign.length) <= 0) {
+		OPENSSL_LOG(ERR, "RSA sign Verification failed");
+		return 1;
+	}
+
+	if ((outlen <= 0) || (outlen != op->rsa.sign.length)) {
+		OPENSSL_LOG(ERR, "RSA sign Verification failed");
+		return 1;
+	}
+
+	tmp = OPENSSL_malloc(outlen);
+	if (tmp == NULL) {
+		OPENSSL_LOG(ERR, "Memory allocation failed");
+		return -1;
+	}
+
+	ret = EVP_PKEY_verify_recover(ctx, tmp, &outlen,
+			op->rsa.sign.data,
+			op->rsa.sign.length);
+	if (ret <= 0) {
+		/*
+		 * A malformed/corrupted signature can make the underlying
+		 * RSA op itself fail (e.g. invalid padding), rather than
+		 * just returning a recovered value that fails to compare.
+		 * Both cases mean verification failed, not that processing
+		 * broke, so still let the op complete successfully.
+		 */
+		OPENSSL_free(tmp);
+		OPENSSL_LOG(ERR, "RSA sign Verification failed");
+		return 1;
+	}
+
+	OPENSSL_LOG(DEBUG,
+			"Length of public_decrypt %zu "
+			"length of message %zd",
+			outlen, op->rsa.message.length);
+	if (outlen != op->rsa.message.length ||
+			CRYPTO_memcmp(tmp, op->rsa.message.data,
+				op->rsa.message.length) != 0) {
+		OPENSSL_free(tmp);
+		OPENSSL_LOG(ERR, "RSA sign Verification failed");
+		return 1;
+	}
+	OPENSSL_free(tmp);
+
+	return 0;
+}
+
 /* process rsa operations */
 static int
 process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
@@ -2334,7 +2544,6 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 {
 	struct rte_crypto_asym_op *op = cop->asym;
 	uint32_t pad = sess->u.r.pad;
-	uint8_t *tmp;
 	size_t outlen = 0;
 	int ret = -1;
 
@@ -2352,6 +2561,15 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 		return ret;
 	}
 
+	/* PSS is only valid for sign/verify */
+	if (sess->u.r.pad == RTE_CRYPTO_RSA_PADDING_PSS &&
+		op->rsa.op_type != RTE_CRYPTO_ASYM_OP_SIGN &&
+		op->rsa.op_type != RTE_CRYPTO_ASYM_OP_VERIFY) {
+		OPENSSL_LOG(ERR, "PSS supports sign/verify only");
+		cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+		return ret;
+	}
+
 	switch (pad) {
 	case RTE_CRYPTO_RSA_PADDING_PKCS1_5:
 		pad = RSA_PKCS1_PADDING;
@@ -2362,6 +2580,9 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 	case RTE_CRYPTO_RSA_PADDING_OAEP:
 		pad = RSA_PKCS1_OAEP_PADDING;
 		break;
+	case RTE_CRYPTO_RSA_PADDING_PSS:
+		pad = RSA_PKCS1_PSS_PADDING;
+		break;
 	default:
 		cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 		OPENSSL_LOG(ERR,
@@ -2426,70 +2647,55 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 		break;
 
 	case RTE_CRYPTO_ASYM_OP_SIGN:
-		if (EVP_PKEY_sign_init(rsa_ctx) <= 0)
-			goto err_rsa;
+		if (sess->u.r.pad == RTE_CRYPTO_RSA_PADDING_PSS) {
+			if (op->rsa.pss_salt.data != NULL) {
+				OPENSSL_LOG(ERR, "Explicit RSA-PSS salt is not supported");
+				cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+				return ret;
+			}
+			if (openssl_rsa_pss_sign(pad, sess, op) < 0)
+				goto err_rsa;
+		} else {
+			if (EVP_PKEY_sign_init(rsa_ctx) <= 0)
+				goto err_rsa;
 
-		if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, pad) <= 0)
-			goto err_rsa;
+			if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, pad) <= 0)
+				goto err_rsa;
 
-		if (EVP_PKEY_sign(rsa_ctx, NULL, &outlen,
-				op->rsa.message.data,
-				op->rsa.message.length) <= 0)
-			goto err_rsa;
+			if (EVP_PKEY_sign(rsa_ctx, NULL, &outlen,
+					op->rsa.message.data,
+					op->rsa.message.length) <= 0)
+				goto err_rsa;
 
-		if (outlen <= 0)
-			goto err_rsa;
+			if (outlen <= 0)
+				goto err_rsa;
 
-		if (EVP_PKEY_sign(rsa_ctx, op->rsa.sign.data, &outlen,
-				op->rsa.message.data,
-				op->rsa.message.length) <= 0)
-			goto err_rsa;
-		op->rsa.sign.length = outlen;
+			if (EVP_PKEY_sign(rsa_ctx, op->rsa.sign.data, &outlen,
+					op->rsa.message.data,
+					op->rsa.message.length) <= 0)
+				goto err_rsa;
+			op->rsa.sign.length = outlen;
+		}
 		break;
 
 	case RTE_CRYPTO_ASYM_OP_VERIFY:
-		if (EVP_PKEY_verify_recover_init(rsa_ctx) <= 0)
-			goto err_rsa;
-
-		if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, pad) <= 0)
-			goto err_rsa;
+		if (sess->u.r.pad == RTE_CRYPTO_RSA_PADDING_PSS)
+			ret = openssl_rsa_pss_verify(pad, sess, op);
+		else
+			ret = openssl_rsa_verify_recover(rsa_ctx, pad, op);
 
-		if (EVP_PKEY_verify_recover(rsa_ctx, NULL, &outlen,
-				op->rsa.sign.data,
-				op->rsa.sign.length) <= 0)
+		if (ret < 0)
 			goto err_rsa;
 
-		if ((outlen <= 0) || (outlen != op->rsa.sign.length))
-			goto err_rsa;
-
-		tmp = OPENSSL_malloc(outlen);
-		if (tmp == NULL) {
-			OPENSSL_LOG(ERR, "Memory allocation failed");
-			goto err_rsa;
-		}
-
-		ret = EVP_PKEY_verify_recover(rsa_ctx, tmp, &outlen,
-				op->rsa.sign.data,
-				op->rsa.sign.length);
-		if (ret <= 0) {
-			/* OpenSSL RSA verification returns one on
-			 * successful verification, otherwise 0. Hence,
-			 * this enqueue operation should succeed even if
-			 * invalid signature has been requested in verify.
-			 */
-			OPENSSL_free(tmp);
-			goto err_rsa;
-		}
-
-		OPENSSL_LOG(DEBUG,
-				"Length of public_decrypt %zu "
-				"length of message %zd",
-				outlen, op->rsa.message.length);
-		if (CRYPTO_memcmp(tmp, op->rsa.message.data,
-				op->rsa.message.length)) {
-			OPENSSL_LOG(ERR, "RSA sign Verification failed");
+		/*
+		 * ret == 1 means the signature did not verify; that is a
+		 * normal outcome, so the op still completes (with an error
+		 * status) instead of failing the enqueue itself.
+		 */
+		if (ret > 0) {
+			cop->status = RTE_CRYPTO_OP_STATUS_ERROR;
+			return 0;
 		}
-		OPENSSL_free(tmp);
 		break;
 
 	default:
diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
index 2504cfb9f5..efc11339be 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
@@ -741,9 +741,11 @@ static const struct rte_cryptodev_capabilities openssl_pmd_capabilities[] = {
 				.increment = 1
 				},
 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+				/* pss_explicit_salt not supported, defaults to false */
 				.pad_types = ((1 << RTE_CRYPTO_RSA_PADDING_NONE) |
 					(1 << RTE_CRYPTO_RSA_PADDING_PKCS1_5) |
-					(1 << RTE_CRYPTO_RSA_PADDING_OAEP)),
+					(1 << RTE_CRYPTO_RSA_PADDING_OAEP) |
+					(1 << RTE_CRYPTO_RSA_PADDING_PSS)),
 				.mgf1_hash_algos = (RTE_BIT64(RTE_CRYPTO_AUTH_SHA1) |
 					RTE_BIT64(RTE_CRYPTO_AUTH_SHA224) |
 					RTE_BIT64(RTE_CRYPTO_AUTH_SHA256) |
@@ -1324,6 +1326,29 @@ static int openssl_set_asym_session_parameters(
 				asym_session->u.r.label_len = 0;
 				asym_session->u.r.label = NULL;
 			}
+		} else if (xform->rsa.padding.type == RTE_CRYPTO_RSA_PADDING_PSS) {
+			asym_session->u.r.pss_md = openssl_get_md(xform->rsa.padding.hash);
+
+			if (asym_session->u.r.pss_md == NULL) {
+				OPENSSL_LOG(ERR,
+					"Unsupported PSS hash algorithm %u",
+					xform->rsa.padding.hash);
+				goto err_rsa;
+			}
+
+			enum rte_crypto_auth_algorithm mgf1 = xform->rsa.padding.mgf1hash;
+
+			if (mgf1 == 0)
+				mgf1 = xform->rsa.padding.hash;
+
+			asym_session->u.r.pss_mgf1_md = openssl_get_md(mgf1);
+			if (asym_session->u.r.pss_mgf1_md == NULL) {
+				OPENSSL_LOG(ERR,
+					"Unsupported PSS MGF1 hash algorithm %u", mgf1);
+				goto err_rsa;
+			}
+
+			asym_session->u.r.pss_saltlen = xform->rsa.padding.pss_saltlen;
 		}
 
 		OSSL_PARAM_BLD * param_bld = OSSL_PARAM_BLD_new();
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 10/10] app/test: add RSA-PSS sign and verify test cases
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                   ` (8 preceding siblings ...)
  2026-08-31 10:23 ` [PATCH 09/10] crypto/openssl: add RSA-PSS support for RSA operations Sucharitha Sarananaga
@ 2026-08-31 10:23 ` Sucharitha Sarananaga
  2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
  10 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-08-31 10:23 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Add OpenSSL asymmetric tests for RSA-PSS sign and verify
operations using SHA-256 with different salt length settings.

Introduce test vectors covering digest-length salt, maximum
supported salt length, and zero-length salt. Update the
OpenSSL asym test suite to validate RSA-PSS functionality
when supported by the device capabilities.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 app/test/test_cryptodev_asym.c             | 307 +++++++++++++++++++++
 app/test/test_cryptodev_rsa_test_vectors.h | 163 +++++++++++
 2 files changed, 470 insertions(+)

diff --git a/app/test/test_cryptodev_asym.c b/app/test/test_cryptodev_asym.c
index ceae029a4a..718b06aefa 100644
--- a/app/test/test_cryptodev_asym.c
+++ b/app/test/test_cryptodev_asym.c
@@ -606,6 +606,307 @@ test_rsa_oaep_labeled_default_mgf1_enc_dec_crt(void)
 	return status;
 }
 
+/*
+ * Check that the device supports RSA-PSS padding, the hash used for
+ * the signature digest, and, if explicitly set, the MGF1 hash (this
+ * PMD defaults MGF1 to the same hash as the digest when unset).
+ */
+static int
+rsa_pss_supported(uint8_t dev_id, const struct rte_crypto_rsa_padding *padding)
+{
+	struct rte_cryptodev_asym_capability_idx idx = {
+		.type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	};
+	const struct rte_cryptodev_asymmetric_xform_capability *capa;
+
+	capa = rte_cryptodev_asym_capability_get(dev_id, &idx);
+	if (capa == NULL) {
+		RTE_LOG(INFO, USER1, "RSA capability not reported by device\n");
+		return 0;
+	}
+
+	if (capa->rsa_capa.pad_types != 0 &&
+			(capa->rsa_capa.pad_types & (1 << RTE_CRYPTO_RSA_PADDING_PSS)) == 0) {
+		RTE_LOG(INFO, USER1,
+			"RSA PSS padding not supported by device. Supported pad_types=%#x\n",
+			capa->rsa_capa.pad_types);
+		return 0;
+	}
+
+	if (!rte_cryptodev_asym_xform_capability_check_hash(capa, padding->hash)) {
+		RTE_LOG(INFO, USER1,
+			"RSA PSS hash %u not supported by device capabilities "
+			"(supported hash_algos=%#"PRIx64")\n",
+			padding->hash, capa->hash_algos);
+		return 0;
+	}
+
+	if (padding->mgf1hash != 0 &&
+			(capa->rsa_capa.mgf1_hash_algos & RTE_BIT64(padding->mgf1hash)) == 0) {
+		RTE_LOG(INFO, USER1,
+			"RSA PSS MGF1 hash %u not supported by device capabilities "
+			"(supported mgf1_hash_algos=%#"PRIx64")\n",
+			padding->mgf1hash, capa->rsa_capa.mgf1_hash_algos);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Sign then verify the freshly-generated signature. Unlike
+ * queue_ops_rsa_sign_verify(), this does not include a
+ * corrupted-signature negative test: RSA-PSS verification does not
+ * support verify-recover, and mismatches are reported via op->status.
+ */
+static int
+queue_ops_rsa_pss_sign_verify(void *sess)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *op_mpool = ts_params->op_mpool;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_op *op, *result_op;
+	struct rte_crypto_asym_op *asym_op;
+	uint8_t output_buf[TEST_DATA_SIZE];
+	int status;
+
+	/* Set up crypto op data structure */
+	op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+	if (!op) {
+		RTE_LOG(ERR, USER1, "Failed to allocate asymmetric crypto "
+			"operation struct\n");
+		return TEST_FAILED;
+	}
+
+	asym_op = op->asym;
+
+	/* Compute sign on the test vector */
+	asym_op->rsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+
+	/*
+	 * RTE_CRYPTO_RSA_PADDING_PSS expects message to already be a
+	 * digest hashed with the algorithm configured in the session's
+	 * padding.hash (SHA-256 here), not the raw plaintext.
+	 */
+	asym_op->rsa.message.data = rsa_pss_digest_sha256.data;
+	asym_op->rsa.message.length = rsa_pss_digest_sha256.len;
+	asym_op->rsa.sign.length = RTE_DIM(rsa_n);
+	asym_op->rsa.sign.data = output_buf;
+
+	debug_hexdump(stdout, "digest", asym_op->rsa.message.data,
+		      asym_op->rsa.message.length);
+
+	/* Attach asymmetric crypto session to crypto operations */
+	rte_crypto_op_attach_asym_session(op, sess);
+
+	RTE_LOG(DEBUG, USER1, "Process ASYM operation\n");
+
+	/* Process crypto operation */
+	if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+		RTE_LOG(ERR, USER1, "Error sending packet for sign\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+		rte_pause();
+
+	if (result_op == NULL) {
+		RTE_LOG(ERR, USER1, "Failed to process sign op\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	if (result_op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		RTE_LOG(ERR, USER1, "Failed to process PSS sign op\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	debug_hexdump(stdout, "signed message", asym_op->rsa.sign.data,
+		      asym_op->rsa.sign.length);
+	asym_op = result_op->asym;
+
+	/* Verify sign */
+	asym_op->rsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+
+	/* Process crypto operation */
+	if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+		RTE_LOG(ERR, USER1, "Error sending packet for verify\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+		rte_pause();
+
+	if (result_op == NULL) {
+		RTE_LOG(ERR, USER1, "Failed to process verify op\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	if (result_op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		RTE_LOG(ERR, USER1, "Failed to process PSS sign-verify op\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = TEST_SUCCESS;
+error_exit:
+
+	rte_crypto_op_free(op);
+
+	return status;
+}
+
+static int
+test_rsa_pss_sign_verify_digest_saltlen(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_pss_supported(dev_id, &rsa_pss_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA PSS not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support sign op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_pss_xform, sizeof(rsa_pss_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"PSS sign_verify (saltlen = digest length)\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_pss_sign_verify(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_pss_sign_verify_max_saltlen(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_pss_supported(dev_id, &rsa_pss_max_salt_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA PSS not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support sign op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_pss_max_salt_xform, sizeof(rsa_pss_max_salt_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"PSS sign_verify (max saltlen)\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_pss_sign_verify(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_pss_sign_verify_zero_saltlen(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_pss_supported(dev_id, &rsa_pss_zero_salt_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA PSS not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support sign op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_pss_zero_salt_xform, sizeof(rsa_pss_zero_salt_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"PSS sign_verify (zero saltlen)\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_pss_sign_verify(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
 static int
 test_rsa_sign_verify(void)
 {
@@ -5705,6 +6006,12 @@ static struct unit_test_suite cryptodev_asym_rsa_testsuite = {
 				test_rsa_oaep_labeled_default_mgf1_enc_dec),
 		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
 				test_rsa_oaep_labeled_default_mgf1_enc_dec_crt),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_pss_sign_verify_digest_saltlen),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_pss_sign_verify_max_saltlen),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_pss_sign_verify_zero_saltlen),
 		/* RSA EXP */
 		TEST_CASE_NAMED_WITH_DATA(
 			"RSA Encryption (n=128, pt=20, e=3) EXP, Padding: NONE",
diff --git a/app/test/test_cryptodev_rsa_test_vectors.h b/app/test/test_cryptodev_rsa_test_vectors.h
index 6835453b6d..f35a83c016 100644
--- a/app/test/test_cryptodev_rsa_test_vectors.h
+++ b/app/test/test_cryptodev_rsa_test_vectors.h
@@ -251,6 +251,23 @@ struct rsa_test_data rsaplaintext = {
 	.len = 20
 };
 
+/*
+ * SHA-256 digest of rsaplaintext.data. RTE_CRYPTO_RSA_PADDING_PSS
+ * expects rte_crypto_rsa_op_param::message to already be a digest
+ * hashed with the algorithm configured in rte_crypto_rsa_padding::hash
+ * (SHA-256 for the PSS xforms below), not the raw message, so PSS
+ * sign/verify tests use this instead of rsaplaintext directly.
+ */
+struct rsa_test_data rsa_pss_digest_sha256 = {
+	.data = {
+		0x45, 0x24, 0x54, 0x32, 0x9d, 0x91, 0xda, 0x1b,
+		0xb8, 0x76, 0x0d, 0x9b, 0xdd, 0xea, 0xe5, 0x21,
+		0x30, 0x91, 0x72, 0xb0, 0x9c, 0x23, 0x12, 0x3f,
+		0xb3, 0x43, 0x09, 0x5d, 0xa3, 0x10, 0x78, 0x7c
+	},
+	.len = 32
+};
+
 uint8_t rsa_n[] = {
 	0xb3, 0xa1, 0xaf, 0xb7, 0x13, 0x08, 0x00,
 	0x0a, 0x35, 0xdc, 0x2b, 0x20, 0x8d, 0xa1, 0xb5,
@@ -538,4 +555,150 @@ struct rte_crypto_asym_xform rsa_oaep_labeled_default_mgf1_xform = {
 	}
 };
 
+/*
+ * RSA-PSS xforms below all use the same 1024-bit test key (rsa_n, 128
+ * bytes) and SHA-256 (hLen = 32 bytes). For this key/hash combination:
+ *   emBits = modBits - 1 = 1023, emLen = ceil(emBits / 8) = 128
+ *   maxSaltLen = emLen - hLen - 2 = 128 - 32 - 2 = 94
+ * (see RFC 8017 EMSA-PSS-ENCODE, section 9.1.1)
+ */
+
+/** rsa PSS xform (SHA-256, salt length = digest length, QT private key type by default) */
+struct rte_crypto_asym_xform rsa_pss_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_PSS,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.padding.pss_saltlen = 32,
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
+/** rsa PSS xform with the maximum permissible salt length (94 bytes) */
+struct rte_crypto_asym_xform rsa_pss_max_salt_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_PSS,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.padding.pss_saltlen = 94,
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
+/** rsa PSS xform with zero-length salt (deterministic PSS, no randomization) */
+struct rte_crypto_asym_xform rsa_pss_zero_salt_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_PSS,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.padding.pss_saltlen = 0, /* no salt bytes */
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
 #endif /* TEST_CRYPTODEV_RSA_TEST_VECTORS_H__ */
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH 05/10] crypto/qat: advertise RSA padding capabilities
  2026-08-31 10:23 ` [PATCH 05/10] crypto/qat: advertise RSA padding capabilities Sucharitha Sarananaga
@ 2026-08-31 12:11   ` Radu Nicolau
  0 siblings, 0 replies; 21+ messages in thread
From: Radu Nicolau @ 2026-08-31 12:11 UTC (permalink / raw)
  To: Sucharitha Sarananaga, dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, gmuthukrishn


On 31-Aug-26 11:23 AM, Sucharitha Sarananaga wrote:
> Add QAT_ASYM_RSA_CAP macro to report RSA asymmetric capabilities
> using rsa_capa, including modulus length and padding schemes.
>
> Update Gen1 and Gen4 QAT asymmetric PMDs to advertise
> RTE_CRYPTO_RSA_PADDING_NONE via pad_types, matching the padding
> mode supported by the QAT RSA implementation.
>
> Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
> ---
>   drivers/crypto/qat/asym/qat_asym.h           | 20 ++++++++++++++++++++
>   drivers/crypto/qat/dev/qat_asym_pmd_gen1.c   |  5 +++--
>   drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c |  5 +++--
>   3 files changed, 26 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/crypto/qat/asym/qat_asym.h b/drivers/crypto/qat/asym/qat_asym.h
> index 0ecbc47548..cf40d445df 100644
> --- a/drivers/crypto/qat/asym/qat_asym.h
> +++ b/drivers/crypto/qat/asym/qat_asym.h
> @@ -56,6 +56,26 @@ typedef uint64_t large_int_ptr;
>   		}							\
>   	}
>   
> +#define QAT_ASYM_RSA_CAP(o, l, r, i, p)					\
> +	{								\
> +		.op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC,			\
> +		{.asym = {						\
> +			.xform_capa = {					\
> +				.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA, \
> +				.op_types = o,				\
> +				.rsa_capa = {				\
> +				.modlen = {				\
> +				.min = l,				\
> +				.max = r,				\
> +				.increment = i				\
> +				},					\
> +				.pad_types = p,				\
> +				},					\
> +			}						\
> +		},							\
> +		}							\
> +	}
> +
>   struct __rte_aligned(8) qat_asym_op_cookie {
>   	uint64_t error;
>   	uint32_t alg_bytesize; /* Bytesize of algorithm */
> diff --git a/drivers/crypto/qat/dev/qat_asym_pmd_gen1.c b/drivers/crypto/qat/dev/qat_asym_pmd_gen1.c
> index c96608dd37..5b93cf374b 100644
> --- a/drivers/crypto/qat/dev/qat_asym_pmd_gen1.c
> +++ b/drivers/crypto/qat/dev/qat_asym_pmd_gen1.c
> @@ -32,12 +32,13 @@ static struct rte_cryptodev_capabilities qat_asym_crypto_caps_gen1[] = {
>   		0, 1, 512, 1),
>   	QAT_ASYM_CAP(MODINV,
>   		0, 1, 512, 1),
> -	QAT_ASYM_CAP(RSA,
> +	QAT_ASYM_RSA_CAP(
>   			((1 << RTE_CRYPTO_ASYM_OP_SIGN) |
>   			(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |
>   			(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) |
>   			(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)),
> -			64, 512, 64),
> +			64, 512, 64,
> +			(1 << RTE_CRYPTO_RSA_PADDING_NONE)),
>   	QAT_ASYM_CAP(ECDH,
>   			((1 << RTE_CRYPTO_ASYM_KE_PUB_KEY_GENERATE) |
>   			(1 << RTE_CRYPTO_ASYM_KE_SHARED_SECRET_COMPUTE) |
> diff --git a/drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c b/drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c
> index 41cad29142..106c512a06 100644
> --- a/drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c
> +++ b/drivers/crypto/qat/dev/qat_crypto_pmd_gen4.c
> @@ -121,12 +121,13 @@ static struct rte_cryptodev_capabilities qat_asym_crypto_caps_gen4[] = {
>   		0, 1, 512, 1),
>   	QAT_ASYM_CAP(MODINV,
>   		0, 1, 512, 1),
> -	QAT_ASYM_CAP(RSA,
> +	QAT_ASYM_RSA_CAP(
>   			((1 << RTE_CRYPTO_ASYM_OP_SIGN) |
>   			(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |
>   			(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) |
>   			(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)),
> -			64, 512, 64),
> +			64, 512, 64,
> +			(1 << RTE_CRYPTO_RSA_PADDING_NONE)),
>   	{	/* SM2 */
>   		.op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
>   		{.asym = {.pad_types

These changes are not needed, pad_types field will still be zero.



^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support
  2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                   ` (9 preceding siblings ...)
  2026-08-31 10:23 ` [PATCH 10/10] app/test: add RSA-PSS sign and verify test cases Sucharitha Sarananaga
@ 2026-09-03  8:26 ` Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 1/8] crypto: add RSA-specific capability parameters Sucharitha Sarananaga
                     ` (7 more replies)
  10 siblings, 8 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-09-03  8:26 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

The asymmetric crypto capability structure currently reports only a
generic modulus length and primary hash algorithm for RSA, with no
way for a PMD to advertise which padding schemes (NONE, PKCS#1 v1.5,
OAEP, PSS) or MGF1 hash algorithms it supports. Applications have no
standard way to discover this, and the OpenSSL PMD itself only
implements NONE and PKCS#1 v1.5 padding.

This series first extends the capability API with a dedicated
rte_crypto_rsa_capa (modulus length, pad_types, mgf1_hash_algos, and
an explicit-PSS-salt flag), then updates the capability reporting in
the octeontx, cnxk, and openssl PMDs to use it.

On top of that, it adds actual RSA-OAEP and RSA-PSS support to the
OpenSSL PMD:
 - RSA-OAEP encrypt/decrypt, with configurable OAEP hash, MGF1 hash,
   and an optional label, defaulting MGF1 to the OAEP hash when
   unset.
 - RSA-PSS sign/verify, with configurable hash, MGF1 hash, and salt
   length (rte_crypto_rsa_padding::pss_saltlen), using a dedicated
   EVP_PKEY_verify()-based verification path since PSS does not
   support verify-recover. The PSS salt itself is always generated
   internally by the PMD; an application-supplied salt
   (rte_crypto_rsa_op_param::pss_salt, gated by the new
   pss_explicit_salt capability bit) is introduced by this series
   for future PMD support but is not yet implemented here, so it is
   rejected with RTE_CRYPTO_OP_STATUS_INVALID_ARGS.

Test coverage for both OAEP (encrypt/decrypt, default and custom
MGF1, with and without a label) and PSS (digest-length, maximum, and
zero-length salt) is added to the cryptodev asymmetric test suite.

v2:
 - Dropped the virtio and qat capability-advertisement patches from
   this series; they will be sent separately.
 - Documented the new rsa_capa/pss_salt fields in release_26_11.rst
   (this series' target release) instead of the already-released
   26.07 notes.

Sucharitha Sarananaga (8):
  crypto: add RSA-specific capability parameters
  crypto/octeontx: advertise RSA PKCS#1 v1.5 padding support
  crypto/cnxk: advertise RSA PKCS#1 v1.5 padding support
  crypto/openssl: advertise RSA padding and hash capabilities
  crypto/openssl: add RSA-OAEP support for OpenSSL PMD
  app/test: add RSA OAEP asymmetric test cases
  crypto/openssl: add RSA-PSS support for RSA operations
  app/test: add RSA-PSS sign and verify test cases

 app/test/test_cryptodev_asym.c                | 663 ++++++++++++++++++
 app/test/test_cryptodev_rsa_test_vectors.h    | 317 +++++++++
 doc/guides/rel_notes/release_26_11.rst        |  16 +
 .../crypto/cnxk/cnxk_cryptodev_capabilities.c |   8 +-
 .../octeontx/otx_cryptodev_capabilities.c     |   8 +-
 drivers/crypto/openssl/openssl_pmd_private.h  |  11 +
 drivers/crypto/openssl/rte_openssl_pmd.c      | 367 ++++++++--
 drivers/crypto/openssl/rte_openssl_pmd_ops.c  | 141 +++-
 lib/cryptodev/rte_crypto_asym.h               |  18 +
 lib/cryptodev/rte_cryptodev.h                 |  50 +-
 10 files changed, 1537 insertions(+), 62 deletions(-)

-- 
2.54.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 1/8] crypto: add RSA-specific capability parameters
  2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
@ 2026-09-03  8:26   ` Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 2/8] crypto/octeontx: advertise RSA PKCS#1 v1.5 padding support Sucharitha Sarananaga
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-09-03  8:26 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

The existing asymmetric capability structure reports generic
modulus length and hash algorithm support, but it cannot
describe RSA-specific parameters required by OAEP and PSS.

RSA operations may support different padding schemes and MGF1
hash algorithms independent of the primary hash algorithm.
Applications currently have no standard way to discover these
capabilities from a PMD.

Add rsa_capa to report RSA modulus length, supported padding
schemes, and MGF1 hash algorithms. Keep hash_algos for reporting
primary digest support.

Also clarify that the generic modlen field applies to other
modulus-based transforms such as MODEXP, MODINV, DH, and DSA.

RSA-PSS signing also normally generates its salt internally, so
the same message never produces the same signature twice, making
it impossible to validate against fixed test vectors (e.g.
ACVP/CAVP SigGen).

Add pss_explicit_salt to rsa_capa so a PMD can
advertise support for an application-supplied PSS salt, and add
the corresponding pss_salt field to rte_crypto_rsa_op_param to
carry those bytes per sign operation. Leaving pss_salt unset keeps
today's internally-generated-salt behavior unchanged.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 doc/guides/rel_notes/release_26_11.rst | 16 +++++++++
 lib/cryptodev/rte_crypto_asym.h        | 18 ++++++++++
 lib/cryptodev/rte_cryptodev.h          | 50 ++++++++++++++++++++++++--
 3 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 938617ca75..48f7722686 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -24,6 +24,15 @@ DPDK Release 26.11
 New Features
 ------------
 
+* **Added RSA-specific capability parameters in cryptodev.**
+
+  Added ``rte_crypto_rsa_capa`` to report RSA modulus length, supported
+  padding schemes, and MGF1 hash algorithms. Also added
+  ``pss_explicit_salt`` so a PMD can advertise support for an
+  application-supplied RSA-PSS salt, along with the corresponding
+  ``pss_salt`` field in ``rte_crypto_rsa_op_param`` to carry it per
+  sign operation.
+
 .. This section should contain new features added in this release.
    Sample format:
 
@@ -88,6 +97,13 @@ API Changes
 ABI Changes
 -----------
 
+* cryptodev: The struct ``rte_cryptodev_asymmetric_xform_capability`` is
+  updated to include ``rsa_capa``, a new ``rte_crypto_rsa_capa`` field for
+  reporting RSA modulus length, padding schemes, and MGF1 hash algorithms.
+
+* cryptodev: The struct ``rte_crypto_rsa_op_param`` is updated to include
+  ``pss_salt``, allowing an application to supply an explicit RSA-PSS salt.
+
 .. This section should contain ABI changes. Sample format:
 
    * sample: Add a short 1-2 sentence description of the ABI change
diff --git a/lib/cryptodev/rte_crypto_asym.h b/lib/cryptodev/rte_crypto_asym.h
index b1546d2b7c..808c5f323e 100644
--- a/lib/cryptodev/rte_crypto_asym.h
+++ b/lib/cryptodev/rte_crypto_asym.h
@@ -494,6 +494,24 @@ struct rte_crypto_rsa_op_param {
 	 * This could be validated and overwritten by the PMD
 	 * with the signature length.
 	 */
+
+	rte_crypto_param pss_salt;
+	/**<
+	 * Explicit RSA-PSS salt bytes, used only for
+	 * RTE_CRYPTO_ASYM_OP_SIGN with RTE_CRYPTO_RSA_PADDING_PSS.
+	 * Only valid if the PMD advertises
+	 * rte_crypto_rsa_capa::pss_explicit_salt == true.
+	 *
+	 * - pss_salt.data == NULL (default): PMD generates the salt
+	 *   internally.
+	 * - pss_salt.data != NULL: PMD uses these exact bytes as the
+	 *   salt. pss_salt.length must equal the session's
+	 *   pss_saltlen, otherwise the op completes with status
+	 *   RTE_CRYPTO_OP_STATUS_INVALID_ARGS.
+	 *
+	 * Ignored for RTE_CRYPTO_ASYM_OP_VERIFY (salt is recovered from
+	 * the signature itself) and for non-PSS padding.
+	 */
 };
 
 /**
diff --git a/lib/cryptodev/rte_cryptodev.h b/lib/cryptodev/rte_cryptodev.h
index 37a6a5e49b..bdbd11ace5 100644
--- a/lib/cryptodev/rte_cryptodev.h
+++ b/lib/cryptodev/rte_cryptodev.h
@@ -157,6 +157,48 @@ struct rte_cryptodev_symmetric_capability {
 	};
 };
 
+/**
+ * RSA transform capability parameters.
+ *
+ * Used when rte_cryptodev_asymmetric_xform_capability::xform_type is
+ * RTE_CRYPTO_ASYM_XFORM_RSA. Advertises supported modulus lengths,
+ * MGF1 hash algorithms, and padding schemes.
+ *
+ * Primary hash algorithms for RSA operations (e.g. OAEP, PSS) are
+ * reported separately via hash_algos in
+ * rte_cryptodev_asymmetric_xform_capability.
+ */
+struct rte_crypto_rsa_capa {
+	struct rte_crypto_param_range modlen;
+	/**< Supported RSA modulus length range, in bytes.
+	 * A min, max, or increment value of 0 means no limit is
+	 * imposed for that field and the PMD default applies.
+	 */
+
+	bool pss_explicit_salt;
+	/**< Support for application-supplied RSA-PSS salt
+	 * (rte_crypto_rsa_op_param::pss_salt).
+	 * false (default): PMD always generates the salt internally.
+	 * true: PMD accepts an application-supplied salt.
+	 */
+
+	uint8_t pad_types;
+	/**< Bitmask of supported RSA padding schemes.
+	 * Each bit corresponds to enum rte_crypto_rsa_padding_type.
+	 * A value of 0 means padding capability is not reported and the PMD
+	 * default may apply.
+	 */
+
+	uint64_t mgf1_hash_algos;
+	/**< Bitmask of hash algorithms supported for MGF1 mask generation.
+	 * Each bit corresponds to enum rte_crypto_auth_algorithm.
+	 * Used for RSA-OAEP and RSA-PSS when MGF1 may use a digest
+	 * different from the primary hash.
+	 * A value of 0 means MGF1 capability is not reported and the PMD
+	 * default may apply.
+	 */
+};
+
 /**
  * Asymmetric Xform Crypto Capability
  */
@@ -179,8 +221,9 @@ struct rte_cryptodev_asymmetric_xform_capability {
 	__extension__
 	union {
 		struct rte_crypto_param_range modlen;
-		/**< Range of modulus length supported by modulus based xform.
-		 * Value 0 mean implementation default
+		/**< Range of modulus length supported by modulus based xform
+		 * such as MODEXP, MODINV, DH, and DSA.
+		 * Value 0 means implementation default.
 		 */
 
 		uint8_t internal_rng;
@@ -197,6 +240,9 @@ struct rte_cryptodev_asymmetric_xform_capability {
 
 		uint32_t mldsa_capa[RTE_CRYPTO_ML_DSA_OP_END];
 		/**< Bitmask of supported ML-DSA parameter sets. */
+
+		struct rte_crypto_rsa_capa rsa_capa;
+		/**< RSA modulus length, MGF1 hash, and padding capabilities. */
 	};
 
 	uint64_t hash_algos;
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 2/8] crypto/octeontx: advertise RSA PKCS#1 v1.5 padding support
  2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 1/8] crypto: add RSA-specific capability parameters Sucharitha Sarananaga
@ 2026-09-03  8:26   ` Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 3/8] crypto/cnxk: " Sucharitha Sarananaga
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-09-03  8:26 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Update the OcteonTX cryptodev RSA asymmetric capability to use
rsa_capa and report supported padding schemes.

Advertise RTE_CRYPTO_RSA_PADDING_NONE and
RTE_CRYPTO_RSA_PADDING_PKCS1_5 via pad_types to match RSA
padding support in the PMD.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/octeontx/otx_cryptodev_capabilities.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/octeontx/otx_cryptodev_capabilities.c b/drivers/crypto/octeontx/otx_cryptodev_capabilities.c
index 80a9fe2123..8a70f81e1f 100644
--- a/drivers/crypto/octeontx/otx_cryptodev_capabilities.c
+++ b/drivers/crypto/octeontx/otx_cryptodev_capabilities.c
@@ -608,11 +608,15 @@ static const struct rte_cryptodev_capabilities otx_asym_capabilities[] = {
 					(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |
 					(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) |
 					(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)),
-				{.modlen = {
+				.rsa_capa = {
+				.modlen = {
 					.min = 17,
 					.max = 1024,
 					.increment = 1
-				}, }
+				},
+				.pad_types = ((1 << RTE_CRYPTO_RSA_PADDING_NONE) |
+					(1 << RTE_CRYPTO_RSA_PADDING_PKCS1_5)),
+				},
 			}
 		}, }
 	},
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 3/8] crypto/cnxk: advertise RSA PKCS#1 v1.5 padding support
  2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 1/8] crypto: add RSA-specific capability parameters Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 2/8] crypto/octeontx: advertise RSA PKCS#1 v1.5 padding support Sucharitha Sarananaga
@ 2026-09-03  8:26   ` Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 4/8] crypto/openssl: advertise RSA padding and hash capabilities Sucharitha Sarananaga
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-09-03  8:26 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Update the CNXK cryptodev RSA asymmetric capability to use
rsa_capa and report supported padding schemes.

Advertise RTE_CRYPTO_RSA_PADDING_NONE and
RTE_CRYPTO_RSA_PADDING_PKCS1_5 via pad_types to match RSA
padding support in the PMD.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c b/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
index 736d588bde..577f080ba7 100644
--- a/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
+++ b/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
@@ -60,11 +60,15 @@ static const struct rte_cryptodev_capabilities caps_mul[] = {
 					(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |
 					(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) |
 					(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)),
-				{.modlen = {
+				.rsa_capa = {
+				.modlen = {
 					.min = 17,
 					.max = 1024,
 					.increment = 1
-				}, }
+				},
+				.pad_types = ((1 << RTE_CRYPTO_RSA_PADDING_NONE) |
+					(1 << RTE_CRYPTO_RSA_PADDING_PKCS1_5)),
+				},
 			}
 		}, }
 	},
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 4/8] crypto/openssl: advertise RSA padding and hash capabilities
  2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                     ` (2 preceding siblings ...)
  2026-09-03  8:26   ` [PATCH v2 3/8] crypto/cnxk: " Sucharitha Sarananaga
@ 2026-09-03  8:26   ` Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 5/8] crypto/openssl: add RSA-OAEP support for OpenSSL PMD Sucharitha Sarananaga
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-09-03  8:26 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Extend the OpenSSL PMD RSA asymmetric capability to use rsa_capa
and report supported padding schemes, primary hash algorithms,
and MGF1 hash algorithms.

For OpenSSL 3.0 and later, advertise OAEP padding along with
SHA-1, SHA-2, and SHA-3 digests for both primary hash and MGF1.
For older OpenSSL versions, advertise only NONE and PKCS#1 v1.5
padding modes supported by the PMD.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/openssl/rte_openssl_pmd_ops.c | 26 ++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
index d927cc5228..60d33f3474 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
@@ -731,14 +731,36 @@ static const struct rte_cryptodev_capabilities openssl_pmd_capabilities[] = {
 					(1 << RTE_CRYPTO_ASYM_OP_VERIFY) |
 					(1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) |
 					(1 << RTE_CRYPTO_ASYM_OP_DECRYPT)),
-				{
+				.rsa_capa = {
 				.modlen = {
 				/* min length is based on openssl rsa keygen */
 				.min = 30,
 				/* value 0 symbolizes no limit on max length */
 				.max = 0,
 				.increment = 1
-				}, }
+				},
+				.pad_types = ((1 << RTE_CRYPTO_RSA_PADDING_NONE) |
+					(1 << RTE_CRYPTO_RSA_PADDING_PKCS1_5) |
+					(1 << RTE_CRYPTO_RSA_PADDING_OAEP)),
+				.mgf1_hash_algos = (RTE_BIT64(RTE_CRYPTO_AUTH_SHA1) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA224) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA256) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA384) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA512) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_224) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_256) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_384) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_512)),
+				},
+				.hash_algos = (RTE_BIT64(RTE_CRYPTO_AUTH_SHA1) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA224) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA256) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA384) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA512) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_224) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_256) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_384) |
+					RTE_BIT64(RTE_CRYPTO_AUTH_SHA3_512)),
 			}
 		},
 		}
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 5/8] crypto/openssl: add RSA-OAEP support for OpenSSL PMD
  2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                     ` (3 preceding siblings ...)
  2026-09-03  8:26   ` [PATCH v2 4/8] crypto/openssl: advertise RSA padding and hash capabilities Sucharitha Sarananaga
@ 2026-09-03  8:26   ` Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 6/8] app/test: add RSA OAEP asymmetric test cases Sucharitha Sarananaga
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-09-03  8:26 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Add support for RSA OAEP padding in the OpenSSL PMD OpenSSL 3.x
implementation.

Store OAEP configuration parameters in the RSA asymmetric session,
including the OAEP hash, MGF1 hash, and optional label. Configure
these parameters on the EVP_PKEY context during RSA encrypt and
decrypt operations, and default the MGF1 hash to the OAEP hash when
not specified by the application.

Validate OAEP-specific usage, restrict it to encrypt/decrypt
operations, and add proper cleanup of allocated label resources on
error and session teardown paths.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/openssl/openssl_pmd_private.h |  5 ++
 drivers/crypto/openssl/rte_openssl_pmd.c     | 53 ++++++++++++
 drivers/crypto/openssl/rte_openssl_pmd_ops.c | 90 ++++++++++++++++++++
 3 files changed, 148 insertions(+)

diff --git a/drivers/crypto/openssl/openssl_pmd_private.h b/drivers/crypto/openssl/openssl_pmd_private.h
index ab40012d61..8704e1915a 100644
--- a/drivers/crypto/openssl/openssl_pmd_private.h
+++ b/drivers/crypto/openssl/openssl_pmd_private.h
@@ -181,6 +181,11 @@ struct __rte_cache_aligned openssl_asym_session {
 			RSA *rsa;
 			uint32_t pad;
 			EVP_PKEY_CTX * ctx;
+			const EVP_MD *oaep_md;
+			const EVP_MD *mgf1_md;
+
+			uint8_t *label;
+			uint32_t label_len;
 		} r;
 		struct exp {
 			BIGNUM *exp;
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 2319c7cfa9..4fbbb73bfa 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -2292,6 +2292,41 @@ process_openssl_modexp_op(struct rte_crypto_op *cop,
 	return 0;
 }
 
+/**
+ * Configure RSA-OAEP parameters on an initialized EVP_PKEY_CTX.
+ * Must be called after EVP_PKEY_encrypt_init() or EVP_PKEY_decrypt_init().
+ *
+ * @return 0 on success, -1 on failure.
+ */
+static int
+openssl_rsa_set_oaep_params(EVP_PKEY_CTX *ctx,
+		const struct openssl_asym_session *sess)
+{
+	if (sess->u.r.pad != RTE_CRYPTO_RSA_PADDING_OAEP)
+		return 0;
+
+	if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, sess->u.r.oaep_md) <= 0)
+		return -1;
+
+	if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sess->u.r.mgf1_md) <= 0)
+		return -1;
+
+	if (sess->u.r.label_len > 0) {
+		void *label = OPENSSL_memdup(sess->u.r.label, sess->u.r.label_len);
+
+		if (label == NULL)
+			return -1;
+
+		if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label, sess->u.r.label_len) <= 0) {
+			OPENSSL_free(label);
+			return -1;
+		}
+	}
+	/* Empty label is default; set0_rsa_oaep_label(NULL,0) fails on OpenSSL 3. */
+
+	return 0;
+}
+
 /* process rsa operations */
 static int
 process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
@@ -2308,6 +2343,15 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 	if (!rsa_ctx)
 		return ret;
 
+	/* OAEP is only valid for encrypt/decrypt */
+	if (sess->u.r.pad == RTE_CRYPTO_RSA_PADDING_OAEP &&
+			op->rsa.op_type != RTE_CRYPTO_ASYM_OP_ENCRYPT &&
+			op->rsa.op_type != RTE_CRYPTO_ASYM_OP_DECRYPT) {
+		OPENSSL_LOG(ERR, "OAEP supports encrypt/decrypt only");
+		cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+		return ret;
+	}
+
 	switch (pad) {
 	case RTE_CRYPTO_RSA_PADDING_PKCS1_5:
 		pad = RSA_PKCS1_PADDING;
@@ -2315,6 +2359,9 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 	case RTE_CRYPTO_RSA_PADDING_NONE:
 		pad = RSA_NO_PADDING;
 		break;
+	case RTE_CRYPTO_RSA_PADDING_OAEP:
+		pad = RSA_PKCS1_OAEP_PADDING;
+		break;
 	default:
 		cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 		OPENSSL_LOG(ERR,
@@ -2330,6 +2377,9 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 		if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, pad) <= 0)
 			goto err_rsa;
 
+		if (openssl_rsa_set_oaep_params(rsa_ctx, sess) < 0)
+			goto err_rsa;
+
 		if (EVP_PKEY_encrypt(rsa_ctx, NULL, &outlen,
 				op->rsa.message.data,
 				op->rsa.message.length) <= 0)
@@ -2355,6 +2405,9 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 		if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, pad) <= 0)
 			goto err_rsa;
 
+		if (openssl_rsa_set_oaep_params(rsa_ctx, sess) < 0)
+			goto err_rsa;
+
 		if (EVP_PKEY_decrypt(rsa_ctx, NULL, &outlen,
 				op->rsa.cipher.data,
 				op->rsa.cipher.length) <= 0)
diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
index 60d33f3474..902b46918d 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
@@ -2,6 +2,7 @@
  * Copyright(c) 2016-2017 Intel Corporation
  */
 
+#include <limits.h>
 #include <string.h>
 
 #include <rte_common.h>
@@ -1208,6 +1209,33 @@ openssl_pmd_sym_session_configure(struct rte_cryptodev *dev,
 	return 0;
 }
 
+static const EVP_MD *
+openssl_get_md(enum rte_crypto_auth_algorithm alg)
+{
+	switch (alg) {
+	case RTE_CRYPTO_AUTH_SHA1:
+		return EVP_sha1();
+	case RTE_CRYPTO_AUTH_SHA224:
+		return EVP_sha224();
+	case RTE_CRYPTO_AUTH_SHA256:
+		return EVP_sha256();
+	case RTE_CRYPTO_AUTH_SHA384:
+		return EVP_sha384();
+	case RTE_CRYPTO_AUTH_SHA512:
+		return EVP_sha512();
+	case RTE_CRYPTO_AUTH_SHA3_224:
+		return EVP_sha3_224();
+	case RTE_CRYPTO_AUTH_SHA3_256:
+		return EVP_sha3_256();
+	case RTE_CRYPTO_AUTH_SHA3_384:
+		return EVP_sha3_384();
+	case RTE_CRYPTO_AUTH_SHA3_512:
+		return EVP_sha3_512();
+	default:
+		return NULL;
+	}
+}
+
 static int openssl_set_asym_session_parameters(
 		struct openssl_asym_session *asym_session,
 		struct rte_crypto_asym_xform *xform)
@@ -1229,6 +1257,7 @@ static int openssl_set_asym_session_parameters(
 		BIGNUM *d = NULL;
 		BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL;
 		BIGNUM *iqmp = NULL, *dmq1 = NULL;
+		uint32_t label_len = 0;
 
 		/* copy xfrm data into rsa struct */
 		n = BN_bin2bn((const unsigned char *)xform->rsa.n.data,
@@ -1240,6 +1269,57 @@ static int openssl_set_asym_session_parameters(
 			goto err_rsa;
 
 		asym_session->u.r.pad = xform->rsa.padding.type;
+		if (xform->rsa.padding.type == RTE_CRYPTO_RSA_PADDING_OAEP) {
+			asym_session->u.r.oaep_md = openssl_get_md(xform->rsa.padding.hash);
+
+			if (asym_session->u.r.oaep_md == NULL) {
+				OPENSSL_LOG(ERR,
+					"Unsupported OAEP hash algorithm %u",
+					xform->rsa.padding.hash);
+				goto err_rsa;
+			}
+
+			enum rte_crypto_auth_algorithm mgf1 = xform->rsa.padding.mgf1hash;
+
+			if (mgf1 == 0)
+				mgf1 = xform->rsa.padding.hash;
+
+			asym_session->u.r.mgf1_md = openssl_get_md(mgf1);
+			if (asym_session->u.r.mgf1_md == NULL) {
+				OPENSSL_LOG(ERR,
+					"Unsupported OAEP MGF1 hash algorithm %u", mgf1);
+				goto err_rsa;
+			}
+
+			if (xform->rsa.padding.oaep_label.length > (size_t)INT_MAX) {
+				OPENSSL_LOG(ERR,
+					"OAEP label length %zu is too large",
+					xform->rsa.padding.oaep_label.length);
+				goto err_rsa;
+			}
+
+			label_len = (uint32_t)xform->rsa.padding.oaep_label.length;
+			if (label_len > 0) {
+				if (xform->rsa.padding.oaep_label.data == NULL) {
+					OPENSSL_LOG(ERR,
+						"OAEP label length is non-zero but data is NULL");
+					goto err_rsa;
+				}
+
+				asym_session->u.r.label = OPENSSL_zalloc(label_len);
+				if (asym_session->u.r.label == NULL)
+					goto err_rsa;
+
+				rte_memcpy(asym_session->u.r.label,
+					xform->rsa.padding.oaep_label.data,
+					label_len);
+				asym_session->u.r.label_len = label_len;
+			} else {
+				asym_session->u.r.label_len = 0;
+				asym_session->u.r.label = NULL;
+			}
+		}
+
 		OSSL_PARAM_BLD * param_bld = OSSL_PARAM_BLD_new();
 		if (!param_bld) {
 			OPENSSL_LOG(ERR, "failed to allocate resources");
@@ -1342,6 +1422,11 @@ static int openssl_set_asym_session_parameters(
 		ret = 0;
 
 err_rsa:
+		if (ret != 0 && asym_session->u.r.label) {
+			OPENSSL_free(asym_session->u.r.label);
+			asym_session->u.r.label = NULL;
+			asym_session->u.r.label_len = 0;
+		}
 		BN_clear_free(n);
 		BN_clear_free(e);
 		BN_clear_free(d);
@@ -1817,6 +1902,11 @@ static void openssl_reset_asym_session(struct openssl_asym_session *sess)
 	switch (sess->xfrm_type) {
 	case RTE_CRYPTO_ASYM_XFORM_RSA:
 		EVP_PKEY_CTX_free(sess->u.r.ctx);
+		if (sess->u.r.label_len > 0) {
+			OPENSSL_free(sess->u.r.label);
+			sess->u.r.label = NULL;
+			sess->u.r.label_len = 0;
+		}
 		break;
 	case RTE_CRYPTO_ASYM_XFORM_MODEX:
 		if (sess->u.e.ctx) {
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 6/8] app/test: add RSA OAEP asymmetric test cases
  2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                     ` (4 preceding siblings ...)
  2026-09-03  8:26   ` [PATCH v2 5/8] crypto/openssl: add RSA-OAEP support for OpenSSL PMD Sucharitha Sarananaga
@ 2026-09-03  8:26   ` Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 7/8] crypto/openssl: add RSA-PSS support for RSA operations Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 8/8] app/test: add RSA-PSS sign and verify test cases Sucharitha Sarananaga
  7 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-09-03  8:26 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Add RSA OAEP encrypt/decrypt tests to the asymmetric cryptodev test
suite.

Introduce OAEP test vectors with default and custom OAEP parameters,
including support for custom MGF1 hashes and OAEP labels. The tests
cover both exponent and CRT private key types and execute end-to-end
encrypt/decrypt validation.

Add capability checks to skip the tests on devices that do not support
OAEP padding or the required RSA private key operations. Also extend
capability reporting to display RSA padding and hash capabilities.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 app/test/test_cryptodev_asym.c             | 356 +++++++++++++++++++++
 app/test/test_cryptodev_rsa_test_vectors.h | 154 +++++++++
 2 files changed, 510 insertions(+)

diff --git a/app/test/test_cryptodev_asym.c b/app/test/test_cryptodev_asym.c
index 7b8afe5f92..ceae029a4a 100644
--- a/app/test/test_cryptodev_asym.c
+++ b/app/test/test_cryptodev_asym.c
@@ -273,6 +273,339 @@ queue_ops_rsa_enc_dec(void *sess)
 	return status;
 }
 
+/*
+ * Check that the device supports RSA-OAEP padding, along with the
+ * specific hash and MGF1 hash used by padding. If mgf1hash is left
+ * unconfigured (0), the PMD falls back to using hash for MGF1, which
+ * is already covered by the hash_algos check above, so mgf1_hash_algos
+ * only needs checking when mgf1hash is explicitly set.
+ */
+static int
+rsa_oaep_supported(uint8_t dev_id, const struct rte_crypto_rsa_padding *padding)
+{
+	struct rte_cryptodev_asym_capability_idx idx = {
+		.type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	};
+	const struct rte_cryptodev_asymmetric_xform_capability *capa;
+
+	capa = rte_cryptodev_asym_capability_get(dev_id, &idx);
+	if (capa == NULL) {
+		RTE_LOG(INFO, USER1, "RSA capability not reported by device\n");
+		return 0;
+	}
+
+	if (capa->rsa_capa.pad_types != 0 &&
+			(capa->rsa_capa.pad_types & (1 << RTE_CRYPTO_RSA_PADDING_OAEP)) == 0) {
+		RTE_LOG(INFO, USER1,
+			"RSA OAEP padding not supported by device. Supported pad_types=%#x\n",
+			capa->rsa_capa.pad_types);
+		return 0;
+	}
+
+	if (!rte_cryptodev_asym_xform_capability_check_hash(capa, padding->hash)) {
+		RTE_LOG(INFO, USER1,
+			"RSA OAEP hash %u not supported by device capabilities "
+			"(supported hash_algos=%#"PRIx64")\n",
+			padding->hash, capa->hash_algos);
+		return 0;
+	}
+
+	if (padding->mgf1hash != 0 &&
+			(capa->rsa_capa.mgf1_hash_algos & RTE_BIT64(padding->mgf1hash)) == 0) {
+		RTE_LOG(INFO, USER1,
+			"RSA OAEP MGF1 hash %u not supported by device capabilities "
+			"(supported mgf1_hash_algos=%#"PRIx64")\n",
+			padding->mgf1hash, capa->rsa_capa.mgf1_hash_algos);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int
+test_rsa_oaep_enc_dec(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id, &rsa_oaep_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_oaep_xform, sizeof(rsa_oaep_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for OAEP enc_dec\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_oaep_enc_dec_crt(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id, &rsa_oaep_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"quintuple key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &rsa_oaep_xform,
+			sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"OAEP enc_dec_crt\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_oaep_labeled_enc_dec(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id, &rsa_oaep_labeled_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_oaep_labeled_xform, sizeof(rsa_oaep_labeled_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"OAEP labeled enc_dec\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_oaep_labeled_enc_dec_crt(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id, &rsa_oaep_labeled_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"quintuple key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &rsa_oaep_labeled_xform,
+			sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"OAEP labeled enc_dec_crt\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_oaep_labeled_default_mgf1_enc_dec(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id,
+			&rsa_oaep_labeled_default_mgf1_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_oaep_labeled_default_mgf1_xform,
+			sizeof(rsa_oaep_labeled_default_mgf1_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"OAEP labeled default MGF1 enc_dec\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_oaep_labeled_default_mgf1_enc_dec_crt(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_oaep_supported(dev_id,
+			&rsa_oaep_labeled_default_mgf1_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA OAEP not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+			"quintuple key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	ret = rte_cryptodev_asym_session_create(dev_id,
+			&rsa_oaep_labeled_default_mgf1_xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"OAEP labeled default MGF1 enc_dec_crt\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
 static int
 test_rsa_sign_verify(void)
 {
@@ -677,6 +1010,18 @@ static inline void print_asym_capa(
 	}
 	switch (capa->xform_type) {
 	case RTE_CRYPTO_ASYM_XFORM_RSA:
+		printf(" modlen: min %d max %d increment %d",
+				capa->rsa_capa.modlen.min,
+				capa->rsa_capa.modlen.max,
+				capa->rsa_capa.modlen.increment);
+		if (capa->rsa_capa.pad_types != 0)
+			printf(" pad_types: %#x", capa->rsa_capa.pad_types);
+		if (capa->rsa_capa.mgf1_hash_algos != 0)
+			printf(" mgf1_hash_algos: %#" PRIx64,
+				capa->rsa_capa.mgf1_hash_algos);
+		if (capa->hash_algos != 0)
+			printf(" hash_algos: %#" PRIx64, capa->hash_algos);
+		break;
 	case RTE_CRYPTO_ASYM_XFORM_MODINV:
 	case RTE_CRYPTO_ASYM_XFORM_MODEX:
 	case RTE_CRYPTO_ASYM_XFORM_DH:
@@ -5349,6 +5694,17 @@ static struct unit_test_suite cryptodev_asym_rsa_testsuite = {
 				test_rsa_enc_dec_crt),
 		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
 				test_rsa_sign_verify_crt),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym, test_rsa_oaep_enc_dec),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_oaep_enc_dec_crt),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_oaep_labeled_enc_dec),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_oaep_labeled_enc_dec_crt),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_oaep_labeled_default_mgf1_enc_dec),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_oaep_labeled_default_mgf1_enc_dec_crt),
 		/* RSA EXP */
 		TEST_CASE_NAMED_WITH_DATA(
 			"RSA Encryption (n=128, pt=20, e=3) EXP, Padding: NONE",
diff --git a/app/test/test_cryptodev_rsa_test_vectors.h b/app/test/test_cryptodev_rsa_test_vectors.h
index 9652b0d43a..6835453b6d 100644
--- a/app/test/test_cryptodev_rsa_test_vectors.h
+++ b/app/test/test_cryptodev_rsa_test_vectors.h
@@ -236,6 +236,12 @@ rsa_test_data_2 rsa_vector_128_20_3_none = {
 	.padding = RTE_CRYPTO_RSA_PADDING_NONE,
 };
 
+uint8_t rsa_oaep_label[] = {
+	0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f, 0x60, 0x71,
+	0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7, 0xe8, 0xf9,
+	0x01, 0x12, 0x23, 0x34
+};
+
 struct rsa_test_data rsaplaintext = {
 	.data = {
 		0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae,
@@ -384,4 +390,152 @@ struct rte_crypto_asym_xform rsa_xform = {
 	}
 };
 
+/** rsa OAEP xform (SHA-256, QT private key type by default) */
+struct rte_crypto_asym_xform rsa_oaep_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_OAEP,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
+/** rsa OAEP xform with MGF1-SHA1 and label */
+struct rte_crypto_asym_xform rsa_oaep_labeled_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_OAEP,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.padding.mgf1hash = RTE_CRYPTO_AUTH_SHA1,
+		.padding.oaep_label = {
+			.data = rsa_oaep_label,
+			.length = sizeof(rsa_oaep_label)
+		},
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
+/**
+ * rsa OAEP xform with label but no explicit MGF1 hash.
+ * mgf1hash is left unset (0) so the PMD falls back to using the
+ * primary hash (SHA-256) for MGF1
+ */
+struct rte_crypto_asym_xform rsa_oaep_labeled_default_mgf1_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_OAEP,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.padding.oaep_label = {
+			.data = rsa_oaep_label,
+			.length = sizeof(rsa_oaep_label)
+		},
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
 #endif /* TEST_CRYPTODEV_RSA_TEST_VECTORS_H__ */
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 7/8] crypto/openssl: add RSA-PSS support for RSA operations
  2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                     ` (5 preceding siblings ...)
  2026-09-03  8:26   ` [PATCH v2 6/8] app/test: add RSA OAEP asymmetric test cases Sucharitha Sarananaga
@ 2026-09-03  8:26   ` Sucharitha Sarananaga
  2026-09-03  8:26   ` [PATCH v2 8/8] app/test: add RSA-PSS sign and verify test cases Sucharitha Sarananaga
  7 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-09-03  8:26 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Add RSA-PSS padding support to the OpenSSL crypto PMD.

Store PSS-specific parameters (hash, MGF1 hash, and salt length)
in the RSA session, advertise PSS capability, and configure the
OpenSSL EVP context accordingly for sign and verify operations.

Introduce a dedicated RSA-PSS verification path using
EVP_PKEY_verify(), while retaining verify-recover for supported
deterministic padding schemes. Reject unsupported RSA-PSS usage
for non-sign/verify operations.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 drivers/crypto/openssl/openssl_pmd_private.h |   6 +
 drivers/crypto/openssl/rte_openssl_pmd.c     | 314 +++++++++++++++----
 drivers/crypto/openssl/rte_openssl_pmd_ops.c |  27 +-
 3 files changed, 292 insertions(+), 55 deletions(-)

diff --git a/drivers/crypto/openssl/openssl_pmd_private.h b/drivers/crypto/openssl/openssl_pmd_private.h
index 8704e1915a..8a6db6066f 100644
--- a/drivers/crypto/openssl/openssl_pmd_private.h
+++ b/drivers/crypto/openssl/openssl_pmd_private.h
@@ -5,6 +5,8 @@
 #ifndef _OPENSSL_PMD_PRIVATE_H_
 #define _OPENSSL_PMD_PRIVATE_H_
 
+#include <rte_common.h>
+
 #include <openssl/evp.h>
 #include <openssl/cmac.h>
 #include <openssl/hmac.h>
@@ -186,6 +188,10 @@ struct __rte_cache_aligned openssl_asym_session {
 
 			uint8_t *label;
 			uint32_t label_len;
+
+			const EVP_MD *pss_md;
+			const EVP_MD *pss_mgf1_md;
+			int pss_saltlen;
 		} r;
 		struct exp {
 			BIGNUM *exp;
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 4fbbb73bfa..1b33470c8f 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -2327,6 +2327,216 @@ openssl_rsa_set_oaep_params(EVP_PKEY_CTX *ctx,
 	return 0;
 }
 
+/**
+ * Configure RSA-PSS padding parameters, including the signature digest,
+ * on an initialized EVP_PKEY_CTX. Must be called after
+ * EVP_PKEY_CTX_set_rsa_padding().
+ *
+ * @return 0 on success, -1 on failure.
+ */
+static int
+openssl_rsa_set_pss_params(EVP_PKEY_CTX *ctx,
+		const struct openssl_asym_session *sess)
+{
+	/*
+	 * Tells OpenSSL which hash algorithm was used to create the
+	 * input message digest (rte_crypto_rsa_padding::hash), so it
+	 * knows the expected digest length and can embed the correct
+	 * algorithm identifier while PSS-encoding it. This does not
+	 * cause the digest to be (re-)computed here: EVP_PKEY_sign()/
+	 * EVP_PKEY_verify() operate on the digest bytes as-is.
+	 */
+	if (EVP_PKEY_CTX_set_signature_md(ctx, sess->u.r.pss_md) <= 0)
+		return -1;
+
+	if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sess->u.r.pss_mgf1_md) <= 0)
+		return -1;
+
+	/* pss_saltlen is a literal byte count (0 is valid: no salt) */
+	if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sess->u.r.pss_saltlen) <= 0)
+		return -1;
+
+	return 0;
+}
+
+/**
+ * Sign a message using RSA-PSS. Per rte_crypto_rsa_op_param::message and
+ * rte_crypto_rsa_padding::hash, the input is a digest already hashed by
+ * the caller with the configured algorithm, not the raw message, so
+ * EVP_PKEY_sign() is used directly on it (no internal re-hashing). This
+ * matches the pattern used for PKCS#1 v1.5/unpadded RSA signing in
+ * process_openssl_rsa_op_evp().
+ *
+ * The OpenSSL PMD does not advertise rte_crypto_rsa_capa::pss_explicit_salt,
+ * so an application-supplied rte_crypto_rsa_op_param::pss_salt is rejected
+ * by the caller before this function is invoked; the salt is always
+ * generated internally by OpenSSL's RNG via EVP_PKEY_sign().
+ *
+ * @return 0 on success, -1 on failure.
+ */
+static int
+openssl_rsa_pss_sign(uint32_t pad, const struct openssl_asym_session *sess,
+		struct rte_crypto_asym_op *op)
+{
+	EVP_PKEY_CTX *ctx = sess->u.r.ctx;
+	size_t outlen = 0;
+
+	if (EVP_PKEY_sign_init(ctx) <= 0)
+		return -1;
+
+	if (EVP_PKEY_CTX_set_rsa_padding(ctx, pad) <= 0)
+		return -1;
+
+	if (openssl_rsa_set_pss_params(ctx, sess) < 0)
+		return -1;
+
+	if (EVP_PKEY_sign(ctx, NULL, &outlen,
+			op->rsa.message.data, op->rsa.message.length) <= 0)
+		return -1;
+
+	if (outlen == 0 || outlen > op->rsa.sign.length)
+		return -1;
+
+	outlen = op->rsa.sign.length;
+	if (EVP_PKEY_sign(ctx, op->rsa.sign.data, &outlen,
+			op->rsa.message.data, op->rsa.message.length) <= 0)
+		return -1;
+
+	op->rsa.sign.length = outlen;
+	return 0;
+}
+
+/**
+ * Verify an RSA-PSS signature against a pre-computed message digest.
+ * Per rte_crypto_rsa_op_param::message and rte_crypto_rsa_padding::hash,
+ * the input is already a digest, so EVP_PKEY_verify() is used directly
+ * on it (no internal re-hashing). PSS does not support verify-recover,
+ * so this also gives a direct pass/fail result.
+ *
+ * A signature mismatch (including one caused by OpenSSL rejecting a
+ * malformed signature outright, e.g. wrong size) is a normal outcome,
+ * not a processing error, so it must not fail the enqueue operation.
+ *
+ * @return 0 if the signature is valid, 1 if invalid/mismatched,
+ *         -1 on a setup/processing failure unrelated to the signature.
+ */
+static int
+openssl_rsa_pss_verify(uint32_t pad, const struct openssl_asym_session *sess,
+		struct rte_crypto_asym_op *op)
+{
+	EVP_PKEY_CTX *ctx = sess->u.r.ctx;
+	int ret;
+
+	if (EVP_PKEY_verify_init(ctx) <= 0)
+		return -1;
+
+	if (EVP_PKEY_CTX_set_rsa_padding(ctx, pad) <= 0)
+		return -1;
+
+	if (openssl_rsa_set_pss_params(ctx, sess) < 0)
+		return -1;
+
+	/*
+	 * EVP_PKEY_verify() returns 1 for a valid signature, 0 for an
+	 * invalid one, and a negative value only for setup/library errors
+	 * (see EVP_PKEY_verify(3)); a malformed signature is reported via
+	 * a 0 return here too, not a negative one.
+	 */
+	ret = EVP_PKEY_verify(ctx,
+			op->rsa.sign.data, op->rsa.sign.length,
+			op->rsa.message.data, op->rsa.message.length);
+	if (ret < 0)
+		return -1;
+
+	if (ret == 0) {
+		OPENSSL_LOG(DEBUG, "RSA-PSS signature verification failed");
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * Verify an RSA signature using verify-recover, for deterministic
+ * padding schemes (PKCS#1 v1.5, no padding). Not applicable to PSS,
+ * since OpenSSL does not support recover-mode verification for PSS
+ * (RSA-PSS is a probabilistic scheme and cannot be undone to recover
+ * the original digest).
+ *
+ * A signature mismatch is a normal outcome, not a processing error, so
+ * it must not fail the enqueue operation. Note that EVP_PKEY_verify_recover()
+ * itself can return <= 0 for a mismatch too, e.g. when the signature does not
+ * decode to a validly padded value (OpenSSL then reports it as a hard
+ * "data too large for modulus"/padding error rather than a soft 0 return),
+ * so that case is treated the same as a successful-but-mismatching recover.
+ *
+ * @return 0 if the signature is valid, 1 if invalid/mismatched,
+ *         -1 on a setup/processing failure unrelated to the signature.
+ */
+static int
+openssl_rsa_verify_recover(EVP_PKEY_CTX *ctx, uint32_t pad,
+		struct rte_crypto_asym_op *op)
+{
+	uint8_t *tmp;
+	size_t outlen = 0;
+	int ret;
+
+	if (EVP_PKEY_verify_recover_init(ctx) <= 0)
+		return -1;
+
+	if (EVP_PKEY_CTX_set_rsa_padding(ctx, pad) <= 0)
+		return -1;
+
+	if (EVP_PKEY_verify_recover(ctx, NULL, &outlen,
+			op->rsa.sign.data,
+			op->rsa.sign.length) <= 0) {
+		OPENSSL_LOG(ERR, "RSA sign Verification failed");
+		return 1;
+	}
+
+	if ((outlen <= 0) || (outlen != op->rsa.sign.length)) {
+		OPENSSL_LOG(ERR, "RSA sign Verification failed");
+		return 1;
+	}
+
+	tmp = OPENSSL_malloc(outlen);
+	if (tmp == NULL) {
+		OPENSSL_LOG(ERR, "Memory allocation failed");
+		return -1;
+	}
+
+	ret = EVP_PKEY_verify_recover(ctx, tmp, &outlen,
+			op->rsa.sign.data,
+			op->rsa.sign.length);
+	if (ret <= 0) {
+		/*
+		 * A malformed/corrupted signature can make the underlying
+		 * RSA op itself fail (e.g. invalid padding), rather than
+		 * just returning a recovered value that fails to compare.
+		 * Both cases mean verification failed, not that processing
+		 * broke, so still let the op complete successfully.
+		 */
+		OPENSSL_free(tmp);
+		OPENSSL_LOG(ERR, "RSA sign Verification failed");
+		return 1;
+	}
+
+	OPENSSL_LOG(DEBUG,
+			"Length of public_decrypt %zu "
+			"length of message %zd",
+			outlen, op->rsa.message.length);
+	if (outlen != op->rsa.message.length ||
+			CRYPTO_memcmp(tmp, op->rsa.message.data,
+				op->rsa.message.length) != 0) {
+		OPENSSL_free(tmp);
+		OPENSSL_LOG(ERR, "RSA sign Verification failed");
+		return 1;
+	}
+	OPENSSL_free(tmp);
+
+	return 0;
+}
+
 /* process rsa operations */
 static int
 process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
@@ -2334,7 +2544,6 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 {
 	struct rte_crypto_asym_op *op = cop->asym;
 	uint32_t pad = sess->u.r.pad;
-	uint8_t *tmp;
 	size_t outlen = 0;
 	int ret = -1;
 
@@ -2352,6 +2561,15 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 		return ret;
 	}
 
+	/* PSS is only valid for sign/verify */
+	if (sess->u.r.pad == RTE_CRYPTO_RSA_PADDING_PSS &&
+		op->rsa.op_type != RTE_CRYPTO_ASYM_OP_SIGN &&
+		op->rsa.op_type != RTE_CRYPTO_ASYM_OP_VERIFY) {
+		OPENSSL_LOG(ERR, "PSS supports sign/verify only");
+		cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+		return ret;
+	}
+
 	switch (pad) {
 	case RTE_CRYPTO_RSA_PADDING_PKCS1_5:
 		pad = RSA_PKCS1_PADDING;
@@ -2362,6 +2580,9 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 	case RTE_CRYPTO_RSA_PADDING_OAEP:
 		pad = RSA_PKCS1_OAEP_PADDING;
 		break;
+	case RTE_CRYPTO_RSA_PADDING_PSS:
+		pad = RSA_PKCS1_PSS_PADDING;
+		break;
 	default:
 		cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 		OPENSSL_LOG(ERR,
@@ -2426,70 +2647,55 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop,
 		break;
 
 	case RTE_CRYPTO_ASYM_OP_SIGN:
-		if (EVP_PKEY_sign_init(rsa_ctx) <= 0)
-			goto err_rsa;
+		if (sess->u.r.pad == RTE_CRYPTO_RSA_PADDING_PSS) {
+			if (op->rsa.pss_salt.data != NULL) {
+				OPENSSL_LOG(ERR, "Explicit RSA-PSS salt is not supported");
+				cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+				return ret;
+			}
+			if (openssl_rsa_pss_sign(pad, sess, op) < 0)
+				goto err_rsa;
+		} else {
+			if (EVP_PKEY_sign_init(rsa_ctx) <= 0)
+				goto err_rsa;
 
-		if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, pad) <= 0)
-			goto err_rsa;
+			if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, pad) <= 0)
+				goto err_rsa;
 
-		if (EVP_PKEY_sign(rsa_ctx, NULL, &outlen,
-				op->rsa.message.data,
-				op->rsa.message.length) <= 0)
-			goto err_rsa;
+			if (EVP_PKEY_sign(rsa_ctx, NULL, &outlen,
+					op->rsa.message.data,
+					op->rsa.message.length) <= 0)
+				goto err_rsa;
 
-		if (outlen <= 0)
-			goto err_rsa;
+			if (outlen <= 0)
+				goto err_rsa;
 
-		if (EVP_PKEY_sign(rsa_ctx, op->rsa.sign.data, &outlen,
-				op->rsa.message.data,
-				op->rsa.message.length) <= 0)
-			goto err_rsa;
-		op->rsa.sign.length = outlen;
+			if (EVP_PKEY_sign(rsa_ctx, op->rsa.sign.data, &outlen,
+					op->rsa.message.data,
+					op->rsa.message.length) <= 0)
+				goto err_rsa;
+			op->rsa.sign.length = outlen;
+		}
 		break;
 
 	case RTE_CRYPTO_ASYM_OP_VERIFY:
-		if (EVP_PKEY_verify_recover_init(rsa_ctx) <= 0)
-			goto err_rsa;
-
-		if (EVP_PKEY_CTX_set_rsa_padding(rsa_ctx, pad) <= 0)
-			goto err_rsa;
+		if (sess->u.r.pad == RTE_CRYPTO_RSA_PADDING_PSS)
+			ret = openssl_rsa_pss_verify(pad, sess, op);
+		else
+			ret = openssl_rsa_verify_recover(rsa_ctx, pad, op);
 
-		if (EVP_PKEY_verify_recover(rsa_ctx, NULL, &outlen,
-				op->rsa.sign.data,
-				op->rsa.sign.length) <= 0)
+		if (ret < 0)
 			goto err_rsa;
 
-		if ((outlen <= 0) || (outlen != op->rsa.sign.length))
-			goto err_rsa;
-
-		tmp = OPENSSL_malloc(outlen);
-		if (tmp == NULL) {
-			OPENSSL_LOG(ERR, "Memory allocation failed");
-			goto err_rsa;
-		}
-
-		ret = EVP_PKEY_verify_recover(rsa_ctx, tmp, &outlen,
-				op->rsa.sign.data,
-				op->rsa.sign.length);
-		if (ret <= 0) {
-			/* OpenSSL RSA verification returns one on
-			 * successful verification, otherwise 0. Hence,
-			 * this enqueue operation should succeed even if
-			 * invalid signature has been requested in verify.
-			 */
-			OPENSSL_free(tmp);
-			goto err_rsa;
-		}
-
-		OPENSSL_LOG(DEBUG,
-				"Length of public_decrypt %zu "
-				"length of message %zd",
-				outlen, op->rsa.message.length);
-		if (CRYPTO_memcmp(tmp, op->rsa.message.data,
-				op->rsa.message.length)) {
-			OPENSSL_LOG(ERR, "RSA sign Verification failed");
+		/*
+		 * ret == 1 means the signature did not verify; that is a
+		 * normal outcome, so the op still completes (with an error
+		 * status) instead of failing the enqueue itself.
+		 */
+		if (ret > 0) {
+			cop->status = RTE_CRYPTO_OP_STATUS_ERROR;
+			return 0;
 		}
-		OPENSSL_free(tmp);
 		break;
 
 	default:
diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
index 902b46918d..b4c78a2a02 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
@@ -740,9 +740,11 @@ static const struct rte_cryptodev_capabilities openssl_pmd_capabilities[] = {
 				.max = 0,
 				.increment = 1
 				},
+				/* pss_explicit_salt not supported, defaults to false */
 				.pad_types = ((1 << RTE_CRYPTO_RSA_PADDING_NONE) |
 					(1 << RTE_CRYPTO_RSA_PADDING_PKCS1_5) |
-					(1 << RTE_CRYPTO_RSA_PADDING_OAEP)),
+					(1 << RTE_CRYPTO_RSA_PADDING_OAEP) |
+					(1 << RTE_CRYPTO_RSA_PADDING_PSS)),
 				.mgf1_hash_algos = (RTE_BIT64(RTE_CRYPTO_AUTH_SHA1) |
 					RTE_BIT64(RTE_CRYPTO_AUTH_SHA224) |
 					RTE_BIT64(RTE_CRYPTO_AUTH_SHA256) |
@@ -1318,6 +1320,29 @@ static int openssl_set_asym_session_parameters(
 				asym_session->u.r.label_len = 0;
 				asym_session->u.r.label = NULL;
 			}
+		} else if (xform->rsa.padding.type == RTE_CRYPTO_RSA_PADDING_PSS) {
+			asym_session->u.r.pss_md = openssl_get_md(xform->rsa.padding.hash);
+
+			if (asym_session->u.r.pss_md == NULL) {
+				OPENSSL_LOG(ERR,
+					"Unsupported PSS hash algorithm %u",
+					xform->rsa.padding.hash);
+				goto err_rsa;
+			}
+
+			enum rte_crypto_auth_algorithm mgf1 = xform->rsa.padding.mgf1hash;
+
+			if (mgf1 == 0)
+				mgf1 = xform->rsa.padding.hash;
+
+			asym_session->u.r.pss_mgf1_md = openssl_get_md(mgf1);
+			if (asym_session->u.r.pss_mgf1_md == NULL) {
+				OPENSSL_LOG(ERR,
+					"Unsupported PSS MGF1 hash algorithm %u", mgf1);
+				goto err_rsa;
+			}
+
+			asym_session->u.r.pss_saltlen = xform->rsa.padding.pss_saltlen;
 		}
 
 		OSSL_PARAM_BLD * param_bld = OSSL_PARAM_BLD_new();
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 8/8] app/test: add RSA-PSS sign and verify test cases
  2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
                     ` (6 preceding siblings ...)
  2026-09-03  8:26   ` [PATCH v2 7/8] crypto/openssl: add RSA-PSS support for RSA operations Sucharitha Sarananaga
@ 2026-09-03  8:26   ` Sucharitha Sarananaga
  7 siblings, 0 replies; 21+ messages in thread
From: Sucharitha Sarananaga @ 2026-09-03  8:26 UTC (permalink / raw)
  To: dev
  Cc: gakhil, fanzhang.oss, adwivedi, anoobj, ktejasree, kai.ji,
	jianjay.zhou, radu.nicolau, gmuthukrishn, Sucharitha Sarananaga

Add OpenSSL asymmetric tests for RSA-PSS sign and verify
operations using SHA-256 with different salt length settings.

Introduce test vectors covering digest-length salt, maximum
supported salt length, and zero-length salt. Update the
OpenSSL asym test suite to validate RSA-PSS functionality
when supported by the device capabilities.

Signed-off-by: Sucharitha Sarananaga <ssarananaga@marvell.com>
---
 app/test/test_cryptodev_asym.c             | 307 +++++++++++++++++++++
 app/test/test_cryptodev_rsa_test_vectors.h | 163 +++++++++++
 2 files changed, 470 insertions(+)

diff --git a/app/test/test_cryptodev_asym.c b/app/test/test_cryptodev_asym.c
index ceae029a4a..718b06aefa 100644
--- a/app/test/test_cryptodev_asym.c
+++ b/app/test/test_cryptodev_asym.c
@@ -606,6 +606,307 @@ test_rsa_oaep_labeled_default_mgf1_enc_dec_crt(void)
 	return status;
 }
 
+/*
+ * Check that the device supports RSA-PSS padding, the hash used for
+ * the signature digest, and, if explicitly set, the MGF1 hash (this
+ * PMD defaults MGF1 to the same hash as the digest when unset).
+ */
+static int
+rsa_pss_supported(uint8_t dev_id, const struct rte_crypto_rsa_padding *padding)
+{
+	struct rte_cryptodev_asym_capability_idx idx = {
+		.type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	};
+	const struct rte_cryptodev_asymmetric_xform_capability *capa;
+
+	capa = rte_cryptodev_asym_capability_get(dev_id, &idx);
+	if (capa == NULL) {
+		RTE_LOG(INFO, USER1, "RSA capability not reported by device\n");
+		return 0;
+	}
+
+	if (capa->rsa_capa.pad_types != 0 &&
+			(capa->rsa_capa.pad_types & (1 << RTE_CRYPTO_RSA_PADDING_PSS)) == 0) {
+		RTE_LOG(INFO, USER1,
+			"RSA PSS padding not supported by device. Supported pad_types=%#x\n",
+			capa->rsa_capa.pad_types);
+		return 0;
+	}
+
+	if (!rte_cryptodev_asym_xform_capability_check_hash(capa, padding->hash)) {
+		RTE_LOG(INFO, USER1,
+			"RSA PSS hash %u not supported by device capabilities "
+			"(supported hash_algos=%#"PRIx64")\n",
+			padding->hash, capa->hash_algos);
+		return 0;
+	}
+
+	if (padding->mgf1hash != 0 &&
+			(capa->rsa_capa.mgf1_hash_algos & RTE_BIT64(padding->mgf1hash)) == 0) {
+		RTE_LOG(INFO, USER1,
+			"RSA PSS MGF1 hash %u not supported by device capabilities "
+			"(supported mgf1_hash_algos=%#"PRIx64")\n",
+			padding->mgf1hash, capa->rsa_capa.mgf1_hash_algos);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Sign then verify the freshly-generated signature. Unlike
+ * queue_ops_rsa_sign_verify(), this does not include a
+ * corrupted-signature negative test: RSA-PSS verification does not
+ * support verify-recover, and mismatches are reported via op->status.
+ */
+static int
+queue_ops_rsa_pss_sign_verify(void *sess)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *op_mpool = ts_params->op_mpool;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_op *op, *result_op;
+	struct rte_crypto_asym_op *asym_op;
+	uint8_t output_buf[TEST_DATA_SIZE];
+	int status;
+
+	/* Set up crypto op data structure */
+	op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+	if (!op) {
+		RTE_LOG(ERR, USER1, "Failed to allocate asymmetric crypto "
+			"operation struct\n");
+		return TEST_FAILED;
+	}
+
+	asym_op = op->asym;
+
+	/* Compute sign on the test vector */
+	asym_op->rsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+
+	/*
+	 * RTE_CRYPTO_RSA_PADDING_PSS expects message to already be a
+	 * digest hashed with the algorithm configured in the session's
+	 * padding.hash (SHA-256 here), not the raw plaintext.
+	 */
+	asym_op->rsa.message.data = rsa_pss_digest_sha256.data;
+	asym_op->rsa.message.length = rsa_pss_digest_sha256.len;
+	asym_op->rsa.sign.length = RTE_DIM(rsa_n);
+	asym_op->rsa.sign.data = output_buf;
+
+	debug_hexdump(stdout, "digest", asym_op->rsa.message.data,
+		      asym_op->rsa.message.length);
+
+	/* Attach asymmetric crypto session to crypto operations */
+	rte_crypto_op_attach_asym_session(op, sess);
+
+	RTE_LOG(DEBUG, USER1, "Process ASYM operation\n");
+
+	/* Process crypto operation */
+	if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+		RTE_LOG(ERR, USER1, "Error sending packet for sign\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+		rte_pause();
+
+	if (result_op == NULL) {
+		RTE_LOG(ERR, USER1, "Failed to process sign op\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	if (result_op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		RTE_LOG(ERR, USER1, "Failed to process PSS sign op\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	debug_hexdump(stdout, "signed message", asym_op->rsa.sign.data,
+		      asym_op->rsa.sign.length);
+	asym_op = result_op->asym;
+
+	/* Verify sign */
+	asym_op->rsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+
+	/* Process crypto operation */
+	if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+		RTE_LOG(ERR, USER1, "Error sending packet for verify\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+		rte_pause();
+
+	if (result_op == NULL) {
+		RTE_LOG(ERR, USER1, "Failed to process verify op\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	if (result_op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		RTE_LOG(ERR, USER1, "Failed to process PSS sign-verify op\n");
+		status = TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = TEST_SUCCESS;
+error_exit:
+
+	rte_crypto_op_free(op);
+
+	return status;
+}
+
+static int
+test_rsa_pss_sign_verify_digest_saltlen(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_pss_supported(dev_id, &rsa_pss_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA PSS not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support sign op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_pss_xform, sizeof(rsa_pss_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"PSS sign_verify (saltlen = digest length)\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_pss_sign_verify(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_pss_sign_verify_max_saltlen(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_pss_supported(dev_id, &rsa_pss_max_salt_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA PSS not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support sign op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_pss_max_salt_xform, sizeof(rsa_pss_max_salt_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"PSS sign_verify (max saltlen)\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_pss_sign_verify(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
+static int
+test_rsa_pss_sign_verify_zero_saltlen(void)
+{
+	struct crypto_testsuite_params_asym *ts_params = &testsuite_params;
+	struct rte_mempool *sess_mpool = ts_params->session_mpool;
+	struct rte_cryptodev_asym_capability_idx idx;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	struct rte_crypto_asym_xform xform;
+	void *sess = NULL;
+	struct rte_cryptodev_info dev_info;
+	int ret, status = TEST_SUCCESS;
+
+	idx.type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	if (rte_cryptodev_asym_capability_get(dev_id, &idx) == NULL)
+		return -ENOTSUP;
+
+	if (!rsa_pss_supported(dev_id, &rsa_pss_zero_salt_xform.rsa.padding)) {
+		RTE_LOG(INFO, USER1, "RSA PSS not supported. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	rte_cryptodev_info_get(dev_id, &dev_info);
+	if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+		RTE_LOG(INFO, USER1, "Device doesn't support sign op with "
+			"exponent key type. Test skipped\n");
+		return TEST_SKIPPED;
+	}
+
+	memcpy(&xform, &rsa_pss_zero_salt_xform, sizeof(rsa_pss_zero_salt_xform));
+	xform.rsa.key_type = RTE_RSA_KEY_TYPE_EXP;
+
+	ret = rte_cryptodev_asym_session_create(dev_id, &xform, sess_mpool, &sess);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Session creation failed for "
+			"PSS sign_verify (zero saltlen)\n");
+		status = (ret == -ENOTSUP) ? TEST_SKIPPED : TEST_FAILED;
+		goto error_exit;
+	}
+
+	status = queue_ops_rsa_pss_sign_verify(sess);
+
+error_exit:
+	rte_cryptodev_asym_session_free(dev_id, sess);
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return status;
+}
+
 static int
 test_rsa_sign_verify(void)
 {
@@ -5705,6 +6006,12 @@ static struct unit_test_suite cryptodev_asym_rsa_testsuite = {
 				test_rsa_oaep_labeled_default_mgf1_enc_dec),
 		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
 				test_rsa_oaep_labeled_default_mgf1_enc_dec_crt),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_pss_sign_verify_digest_saltlen),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_pss_sign_verify_max_saltlen),
+		TEST_CASE_ST(ut_setup_asym, ut_teardown_asym,
+				test_rsa_pss_sign_verify_zero_saltlen),
 		/* RSA EXP */
 		TEST_CASE_NAMED_WITH_DATA(
 			"RSA Encryption (n=128, pt=20, e=3) EXP, Padding: NONE",
diff --git a/app/test/test_cryptodev_rsa_test_vectors.h b/app/test/test_cryptodev_rsa_test_vectors.h
index 6835453b6d..f35a83c016 100644
--- a/app/test/test_cryptodev_rsa_test_vectors.h
+++ b/app/test/test_cryptodev_rsa_test_vectors.h
@@ -251,6 +251,23 @@ struct rsa_test_data rsaplaintext = {
 	.len = 20
 };
 
+/*
+ * SHA-256 digest of rsaplaintext.data. RTE_CRYPTO_RSA_PADDING_PSS
+ * expects rte_crypto_rsa_op_param::message to already be a digest
+ * hashed with the algorithm configured in rte_crypto_rsa_padding::hash
+ * (SHA-256 for the PSS xforms below), not the raw message, so PSS
+ * sign/verify tests use this instead of rsaplaintext directly.
+ */
+struct rsa_test_data rsa_pss_digest_sha256 = {
+	.data = {
+		0x45, 0x24, 0x54, 0x32, 0x9d, 0x91, 0xda, 0x1b,
+		0xb8, 0x76, 0x0d, 0x9b, 0xdd, 0xea, 0xe5, 0x21,
+		0x30, 0x91, 0x72, 0xb0, 0x9c, 0x23, 0x12, 0x3f,
+		0xb3, 0x43, 0x09, 0x5d, 0xa3, 0x10, 0x78, 0x7c
+	},
+	.len = 32
+};
+
 uint8_t rsa_n[] = {
 	0xb3, 0xa1, 0xaf, 0xb7, 0x13, 0x08, 0x00,
 	0x0a, 0x35, 0xdc, 0x2b, 0x20, 0x8d, 0xa1, 0xb5,
@@ -538,4 +555,150 @@ struct rte_crypto_asym_xform rsa_oaep_labeled_default_mgf1_xform = {
 	}
 };
 
+/*
+ * RSA-PSS xforms below all use the same 1024-bit test key (rsa_n, 128
+ * bytes) and SHA-256 (hLen = 32 bytes). For this key/hash combination:
+ *   emBits = modBits - 1 = 1023, emLen = ceil(emBits / 8) = 128
+ *   maxSaltLen = emLen - hLen - 2 = 128 - 32 - 2 = 94
+ * (see RFC 8017 EMSA-PSS-ENCODE, section 9.1.1)
+ */
+
+/** rsa PSS xform (SHA-256, salt length = digest length, QT private key type by default) */
+struct rte_crypto_asym_xform rsa_pss_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_PSS,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.padding.pss_saltlen = 32,
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
+/** rsa PSS xform with the maximum permissible salt length (94 bytes) */
+struct rte_crypto_asym_xform rsa_pss_max_salt_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_PSS,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.padding.pss_saltlen = 94,
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
+/** rsa PSS xform with zero-length salt (deterministic PSS, no randomization) */
+struct rte_crypto_asym_xform rsa_pss_zero_salt_xform = {
+	.next = NULL,
+	.xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+	.rsa = {
+		.padding.type = RTE_CRYPTO_RSA_PADDING_PSS,
+		.padding.hash = RTE_CRYPTO_AUTH_SHA256,
+		.padding.pss_saltlen = 0, /* no salt bytes */
+		.n = {
+			.data = rsa_n,
+			.length = sizeof(rsa_n)
+		},
+		.e = {
+			.data = rsa_e,
+			.length = sizeof(rsa_e)
+		},
+		.qt = {
+			.p = {
+				.data = rsa_p,
+				.length = sizeof(rsa_p)
+			},
+			.q = {
+				.data = rsa_q,
+				.length = sizeof(rsa_q)
+			},
+			.dP = {
+				.data = rsa_dP,
+				.length = sizeof(rsa_dP)
+			},
+			.dQ = {
+				.data = rsa_dQ,
+				.length = sizeof(rsa_dQ)
+			},
+			.qInv = {
+				.data = rsa_qInv,
+				.length = sizeof(rsa_qInv)
+			},
+		},
+		.d = {
+			.data = rsa_d,
+			.length = sizeof(rsa_d)
+		},
+		.key_type = RTE_RSA_KEY_TYPE_QT
+	}
+};
+
 #endif /* TEST_CRYPTODEV_RSA_TEST_VECTORS_H__ */
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2026-09-03  8:28 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 10:23 [PATCH 00/10] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
2026-08-31 10:23 ` [PATCH 01/10] crypto: add RSA-specific capability parameters Sucharitha Sarananaga
2026-08-31 10:23 ` [PATCH 02/10] crypto/virtio: advertise RSA padding and hash capabilities Sucharitha Sarananaga
2026-08-31 10:23 ` [PATCH 03/10] crypto/octeontx: advertise RSA PKCS#1 v1.5 padding support Sucharitha Sarananaga
2026-08-31 10:23 ` [PATCH 04/10] crypto/cnxk: " Sucharitha Sarananaga
2026-08-31 10:23 ` [PATCH 05/10] crypto/qat: advertise RSA padding capabilities Sucharitha Sarananaga
2026-08-31 12:11   ` Radu Nicolau
2026-08-31 10:23 ` [PATCH 06/10] crypto/openssl: advertise RSA padding and hash capabilities Sucharitha Sarananaga
2026-08-31 10:23 ` [PATCH 07/10] crypto/openssl: add RSA-OAEP support for OpenSSL PMD Sucharitha Sarananaga
2026-08-31 10:23 ` [PATCH 08/10] app/test: add RSA OAEP asymmetric test cases Sucharitha Sarananaga
2026-08-31 10:23 ` [PATCH 09/10] crypto/openssl: add RSA-PSS support for RSA operations Sucharitha Sarananaga
2026-08-31 10:23 ` [PATCH 10/10] app/test: add RSA-PSS sign and verify test cases Sucharitha Sarananaga
2026-09-03  8:26 ` [PATCH v2 0/8] cryptodev: add RSA-OAEP and RSA-PSS padding support Sucharitha Sarananaga
2026-09-03  8:26   ` [PATCH v2 1/8] crypto: add RSA-specific capability parameters Sucharitha Sarananaga
2026-09-03  8:26   ` [PATCH v2 2/8] crypto/octeontx: advertise RSA PKCS#1 v1.5 padding support Sucharitha Sarananaga
2026-09-03  8:26   ` [PATCH v2 3/8] crypto/cnxk: " Sucharitha Sarananaga
2026-09-03  8:26   ` [PATCH v2 4/8] crypto/openssl: advertise RSA padding and hash capabilities Sucharitha Sarananaga
2026-09-03  8:26   ` [PATCH v2 5/8] crypto/openssl: add RSA-OAEP support for OpenSSL PMD Sucharitha Sarananaga
2026-09-03  8:26   ` [PATCH v2 6/8] app/test: add RSA OAEP asymmetric test cases Sucharitha Sarananaga
2026-09-03  8:26   ` [PATCH v2 7/8] crypto/openssl: add RSA-PSS support for RSA operations Sucharitha Sarananaga
2026-09-03  8:26   ` [PATCH v2 8/8] app/test: add RSA-PSS sign and verify test cases Sucharitha Sarananaga

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox