From: Sucharitha Sarananaga <ssarananaga@marvell.com>
To: <dev@dpdk.org>
Cc: <gakhil@marvell.com>, <fanzhang.oss@gmail.com>,
<adwivedi@marvell.com>, <anoobj@marvell.com>,
<ktejasree@marvell.com>, <kai.ji@intel.com>,
<jianjay.zhou@huawei.com>, <radu.nicolau@intel.com>,
<gmuthukrishn@marvell.com>,
Sucharitha Sarananaga <ssarananaga@marvell.com>
Subject: [PATCH v2 7/8] crypto/openssl: add RSA-PSS support for RSA operations
Date: Thu, 3 Sep 2026 08:26:47 +0000 [thread overview]
Message-ID: <20260903082648.3610676-8-ssarananaga@marvell.com> (raw)
In-Reply-To: <20260903082648.3610676-1-ssarananaga@marvell.com>
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
next prev parent reply other threads:[~2026-09-03 8:28 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Sucharitha Sarananaga [this message]
2026-09-03 8:26 ` [PATCH v2 8/8] app/test: add RSA-PSS sign and verify " Sucharitha Sarananaga
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260903082648.3610676-8-ssarananaga@marvell.com \
--to=ssarananaga@marvell.com \
--cc=adwivedi@marvell.com \
--cc=anoobj@marvell.com \
--cc=dev@dpdk.org \
--cc=fanzhang.oss@gmail.com \
--cc=gakhil@marvell.com \
--cc=gmuthukrishn@marvell.com \
--cc=jianjay.zhou@huawei.com \
--cc=kai.ji@intel.com \
--cc=ktejasree@marvell.com \
--cc=radu.nicolau@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox