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 <[email protected]> --- 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

