From 1cf7d8b09dc6e1d69cfc2d15d900e16447549649 Mon Sep 17 00:00:00 2001 From: JiangShui Yang <1175135535@qq.com> Date: Thu, 18 Dec 2025 15:04:58 +0800 Subject: [PATCH] uadk_provider supports more RSA padding modes --- ...lit-RSA-algorithm-into-four-function.patch | 6002 +++++++++++++++++ ...d-some-RSA-utils-functions-to-adapt-.patch | 221 + ...apt-rsa-signature-operation-with-X93.patch | 1370 ++++ ...apt-rsa-encryption-operation-with-OA.patch | 519 ++ ...e-hardware-version-and-availability-.patch | 240 + ...ve-several-macro-definitions-to-shar.patch | 579 ++ ...the-SM2-x25519-x448-err-in-OpenSSL3..patch | 217 + ...ovider-dh-set-meth-flags-when-new-dh.patch | 225 + ...gine-delete-several-unused-functions.patch | 35 + ...fixup-a-bug-in-rsa-X931-padding-mode.patch | 33 + uadk_engine.spec | 15 +- 11 files changed, 9455 insertions(+), 1 deletion(-) create mode 100644 0023-uadk_provider-split-RSA-algorithm-into-four-function.patch create mode 100644 0024-uadk_provider-add-some-RSA-utils-functions-to-adapt-.patch create mode 100644 0025-uadk_provider-adapt-rsa-signature-operation-with-X93.patch create mode 100644 0026-uadk_provider-adapt-rsa-encryption-operation-with-OA.patch create mode 100644 0027-provider-optimize-hardware-version-and-availability-.patch create mode 100644 0028-uadk_provider-move-several-macro-definitions-to-shar.patch create mode 100644 0029-uadk_engine-fix-the-SM2-x25519-x448-err-in-OpenSSL3..patch create mode 100644 0030-uadk_provider-dh-set-meth-flags-when-new-dh.patch create mode 100644 0031-uadk_engine-delete-several-unused-functions.patch create mode 100644 0032-uadk_engine-fixup-a-bug-in-rsa-X931-padding-mode.patch diff --git a/0023-uadk_provider-split-RSA-algorithm-into-four-function.patch b/0023-uadk_provider-split-RSA-algorithm-into-four-function.patch new file mode 100644 index 0000000..5dc3974 --- /dev/null +++ b/0023-uadk_provider-split-RSA-algorithm-into-four-function.patch @@ -0,0 +1,6002 @@ +From 2da5e2283675968f4de1570232103d4b27b57041 Mon Sep 17 00:00:00 2001 +From: lizhi +Date: Tue, 16 Dec 2025 19:17:15 +0800 +Subject: [PATCH 23/32] uadk_provider: split RSA algorithm into four functional + components + +For better code organization and maintainability, original RSA algorithm +is splited into four functional components, including key generation, +encryption/decryption, signing/verification, and public interface +functions. + +Signed-off-by: lizhi +Signed-off-by: JiangShui Yang +--- + src/Makefile.am | 6 +- + src/uadk_prov_rsa.c | 2974 ++----------------------------------- + src/uadk_prov_rsa.h | 179 +++ + src/uadk_prov_rsa_enc.c | 463 ++++++ + src/uadk_prov_rsa_kmgmt.c | 975 ++++++++++++ + src/uadk_prov_rsa_sign.c | 1138 ++++++++++++++ + 6 files changed, 2918 insertions(+), 2817 deletions(-) + create mode 100644 src/uadk_prov_rsa.h + create mode 100644 src/uadk_prov_rsa_enc.c + create mode 100644 src/uadk_prov_rsa_kmgmt.c + create mode 100644 src/uadk_prov_rsa_sign.c + +diff --git a/src/Makefile.am b/src/Makefile.am +index 0e4fd16..7ce9aeb 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -62,8 +62,10 @@ endif #WD_KAE + + uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \ + uadk_prov_digest.c uadk_prov_cipher.c \ +- uadk_prov_rsa.c uadk_prov_dh.c \ +- uadk_prov_bio.c uadk_prov_der_writer.c uadk_prov_packet.c \ ++ uadk_prov_rsa.c uadk_prov_rsa_kmgmt.c \ ++ uadk_prov_rsa_enc.c uadk_prov_rsa_sign.c \ ++ uadk_prov_dh.c uadk_prov_bio.c \ ++ uadk_prov_der_writer.c uadk_prov_packet.c \ + uadk_prov_pkey.c uadk_prov_sm2.c \ + uadk_prov_ffc.c uadk_prov_aead.c \ + uadk_prov_ec_kmgmt.c uadk_prov_ecdh_exch.c \ +diff --git a/src/uadk_prov_rsa.c b/src/uadk_prov_rsa.c +index da5be2f..a0bb26e 100644 +--- a/src/uadk_prov_rsa.c ++++ b/src/uadk_prov_rsa.c +@@ -16,26 +16,10 @@ + * limitations under the License. + * + */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include "uadk_async.h" +-#include "uadk_prov.h" +-#include "uadk_prov_pkey.h" +-#include "uadk_utils.h" ++#include "uadk_prov_rsa.h" + + #define UN_SET 0 + #define IS_SET 1 +-#define RSA_MAX_PRIME_NUM 2 +-#define BIT_BYTES_SHIFT 3 + #define RSA_MIN_MODULUS_BITS 512 + #define RSA1024BITS 1024 + #define RSA2048BITS 2048 +@@ -43,310 +27,16 @@ + #define RSA4096BITS 4096 + #define OPENSSLRSA7680BITS 7680 + #define OPENSSLRSA15360BITS 15360 +-#define CTX_SYNC 0 +-#define CTX_ASYNC 1 +-#define CTX_NUM 2 +-#define BN_CONTINUE 1 +-#define BN_VALID 0 +-#define BN_ERR (-1) +-#define BN_REDO (-2) +-#define GET_ERR_FINISH 0 +-#define UNUSED(x) ((void)(x)) +-#define UADK_E_FAIL 0 +-#define UADK_E_SUCCESS 1 +-#define UADK_DO_SOFT (-0xE0) +-#define UADK_E_POLL_FAIL (-1) +-#define UADK_E_POLL_SUCCESS 0 +-#define UADK_E_INIT_SUCCESS 0 +-#define CHECK_PADDING_FAIL (-1) +-#define ENV_ENABLED 1 +-#define PRIME_RETRY_COUNT 4 +-#define GENCB_NEXT 2 +-#define GENCB_RETRY 3 +-#define PRIME_CHECK_BIT_NUM 4 +- +-UADK_PKEY_KEYMGMT_DESCR(rsa, RSA); +-UADK_PKEY_SIGNATURE_DESCR(rsa, RSA); +-UADK_PKEY_ASYM_CIPHER_DESCR(rsa, RSA); +-struct rsa_keypair { +- struct wd_rsa_pubkey *pubkey; +- struct wd_rsa_prikey *prikey; +-}; +- +-struct rsa_keygen_param { +- struct wd_dtb *wd_e; +- struct wd_dtb *wd_p; +- struct wd_dtb *wd_q; +-}; +- +-struct bignum_st { +- BN_ULONG *d; +- int top; +- int dmax; +- int neg; +- int flags; +-}; +- +-struct rsa_keygen_param_bn { +- BIGNUM *e; +- BIGNUM *p; +- BIGNUM *q; +-}; +- +-struct rsa_prikey_param { +- const BIGNUM *n; +- const BIGNUM *e; +- const BIGNUM *d; +- const BIGNUM *p; +- const BIGNUM *q; +- const BIGNUM *dmp1; +- const BIGNUM *dmq1; +- const BIGNUM *iqmp; +- int is_crt; +-}; +- +-struct rsa_prime_param { +- BIGNUM *r1; +- BIGNUM *r2; +- BIGNUM *rsa_p; +- BIGNUM *rsa_q; +- BIGNUM *prime; +- int retries; +-}; +- +-struct rsa_pubkey_param { +- const BIGNUM *e; +- const BIGNUM *n; +-}; +- +-struct rsa_sched { +- int sched_type; +- struct wd_sched wd_sched; +-}; +- +-struct uadk_rsa_sess { +- handle_t sess; +- struct wd_rsa_sess_setup setup; +- struct wd_rsa_req req; +- RSA *alg; +- int is_pubkey_ready; +- int is_prikey_ready; +- int key_size; +-}; +- +-struct rsa_prov { +- int pid; +-}; +-static struct rsa_prov g_rsa_prov; ++#define UADK_P_INIT_SUCCESS 0 + ++static struct rsa_prov g_rsa_prov; + static pthread_mutex_t rsa_mutex = PTHREAD_MUTEX_INITIALIZER; + +-typedef struct { +- OSSL_LIB_CTX *libctx; +- char *propq; +- RSA *rsa; +- int operation; +- +- /* +- * Flag to determine if the hash function can be changed (1) or not (0) +- * Because it's dangerous to change during a DigestSign or DigestVerify +- * operation, this flag is cleared by their Init function, and set again +- * by their Final function. +- */ +- unsigned int flag_allow_md : 1; +- unsigned int mgf1_md_set : 1; +- +- /* main digest */ +- EVP_MD *md; +- EVP_MD_CTX *mdctx; +- int mdnid; +- char mdname[50]; /* Purely informational */ +- +- /* RSA padding mode */ +- int pad_mode; +- /* message digest for MGF1 */ +- EVP_MD *mgf1_md; +- int mgf1_mdnid; +- char mgf1_mdname[50]; /* Purely informational */ +- /* PSS salt length */ +- int saltlen; +- /* Minimum salt length or -1 if no PSS parameter restriction */ +- int min_saltlen; +- +- /* Temp buffer */ +- unsigned char *tbuf; +- +- unsigned int soft : 1; +-} PROV_RSA_SIG_CTX; +- +-typedef struct rsa_pss_params_30_st { +- int hash_algorithm_nid; +- struct { +- int algorithm_nid; /* Currently always NID_mgf1 */ +- int hash_algorithm_nid; +- } mask_gen; +- int salt_len; +- int trailer_field; +-} RSA_PSS_PARAMS_30; +- +-struct rsa_st { +- /* +- * #legacy +- * The first field is used to pickup errors where this is passed +- * instead of an EVP_PKEY. It is always zero. +- * THIS MUST REMAIN THE FIRST FIELD. +- */ +- int dummy_zero; +- +- OSSL_LIB_CTX *libctx; +- int32_t version; +- const RSA_METHOD *meth; +- /* functional reference if 'meth' is ENGINE-provided */ +- ENGINE *engine; +- BIGNUM *n; +- BIGNUM *e; +- BIGNUM *d; +- BIGNUM *p; +- BIGNUM *q; +- BIGNUM *dmp1; +- BIGNUM *dmq1; +- BIGNUM *iqmp; +- +- /* +- * If a PSS only key this contains the parameter restrictions. +- * There are two structures for the same thing, used in different cases. +- */ +- /* This is used uniquely by OpenSSL provider implementations. */ +- RSA_PSS_PARAMS_30 pss_params; +- +- /* This is used uniquely by rsa_ameth.c and rsa_pmeth.c. */ +- RSA_PSS_PARAMS *pss; +- /* for multi-prime RSA, defined in RFC 8017 */ +- STACK_OF(RSA_PRIME_INFO) * prime_infos; +- /* Be careful using this if the RSA structure is shared */ +- CRYPTO_EX_DATA ex_data; +- +- int references; +- int flags; +- /* Used to cache montgomery values */ +- BN_MONT_CTX *_method_mod_n; +- BN_MONT_CTX *_method_mod_p; +- BN_MONT_CTX *_method_mod_q; +- BN_BLINDING *blinding; +- BN_BLINDING *mt_blinding; +- CRYPTO_RWLOCK *lock; +- +- int dirty_cnt; +-}; +- +-typedef struct { +- OSSL_LIB_CTX *libctx; +- RSA *rsa; +- int pad_mode; +- int operation; +- /* OAEP message digest */ +- EVP_MD *oaep_md; +- /* message digest for MGF1 */ +- EVP_MD *mgf1_md; +- /* OAEP label */ +- unsigned char *oaep_label; +- size_t oaep_labellen; +- /* TLS padding */ +- unsigned int client_version; +- unsigned int alt_version; +- +- unsigned int soft : 1; +-} PROV_RSA_ASYM_CTX; +- +-struct rsa_gen_ctx { +- OSSL_LIB_CTX *libctx; +- const char *propq; +- +- int rsa_type; +- +- size_t nbits; +- BIGNUM *pub_exp; +- size_t primes; +- +- /* For PSS */ +- RSA_PSS_PARAMS_30 pss_params; +- int pss_defaults_set; +- +- /* For generation callback */ +- OSSL_CALLBACK *cb; +- void *cbarg; +-}; +- +-enum { +- INVALID = 0, +- PUB_ENC, +- PUB_DEC, +- PRI_ENC, +- PRI_DEC, +- MAX_CODE, +-}; +- +-static pthread_mutex_t sig_mutex = PTHREAD_MUTEX_INITIALIZER; +-static pthread_mutex_t asym_mutex = PTHREAD_MUTEX_INITIALIZER; +- +-static UADK_PKEY_SIGNATURE get_default_rsa_signature(void) +-{ +- static UADK_PKEY_SIGNATURE s_signature; +- static int initilazed; +- pthread_mutex_lock(&sig_mutex); +- if (!initilazed) { +- UADK_PKEY_SIGNATURE *signature = +- (UADK_PKEY_SIGNATURE *)EVP_SIGNATURE_fetch(NULL, "RSA", "provider=default"); +- +- if (signature) { +- s_signature = *signature; +- EVP_SIGNATURE_free((EVP_SIGNATURE *)signature); +- initilazed = 1; +- } else { +- UADK_ERR("failed to EVP_SIGNATURE_fetch default RSA provider\n"); +- } +- } +- pthread_mutex_unlock(&sig_mutex); +- return s_signature; +-} +- +-static UADK_PKEY_ASYM_CIPHER get_default_rsa_asym_cipher(void) +-{ +- static UADK_PKEY_ASYM_CIPHER s_asym_cipher; +- static int initilazed; +- pthread_mutex_lock(&asym_mutex); +- if (!initilazed) { +- UADK_PKEY_ASYM_CIPHER *asym_cipher = +- (UADK_PKEY_ASYM_CIPHER *)EVP_ASYM_CIPHER_fetch(NULL, "RSA", +- "provider=default"); +- +- if (asym_cipher) { +- s_asym_cipher = *asym_cipher; +- EVP_ASYM_CIPHER_free((EVP_ASYM_CIPHER *)asym_cipher); +- initilazed = 1; +- } else { +- UADK_ERR("failed to EVP_ASYM_CIPHER_fetch default RSA provider\n"); +- } +- } +- pthread_mutex_unlock(&asym_mutex); +- return s_asym_cipher; +-} +- +-static void uadk_rsa_clear_flags(RSA *r, int flags) +-{ +- r->flags &= ~flags; +-} +- +-static int uadk_rsa_test_flags(const RSA *r, int flags) ++int uadk_rsa_test_flags(const RSA *r, int flags) + { + return r->flags & flags; + } + +-static void uadk_rsa_set_flags(RSA *r, int flags) +-{ +- r->flags |= flags; +-} +- + static int uadk_rsa_get_version(RSA *r) + { + /* { two-prime(0), multi(1) } */ +@@ -362,46 +52,6 @@ static void uadk_rsa_get0_factors(const RSA *r, const BIGNUM **p, + *q = r->q; + } + +-static void uadk_rsa_get0_key(const RSA *r, const BIGNUM **n, +- const BIGNUM **e, const BIGNUM **d) +-{ +- if (n != NULL) +- *n = r->n; +- if (e != NULL) +- *e = r->e; +- if (d != NULL) +- *d = r->d; +-} +- +-static int uadk_rsa_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +-{ +- /* +- * If the fields n and e in r are NULL, the corresponding input +- * parameters MUST be non-NULL for n and e. d may be +- * left NULL (in case only the public key is used). +- */ +- if ((r->n == NULL && n == NULL) +- || (r->e == NULL && e == NULL)) +- return UADK_E_FAIL; +- +- if (n != NULL) { +- BN_free(r->n); +- r->n = n; +- } +- if (e != NULL) { +- BN_free(r->e); +- r->e = e; +- } +- if (d != NULL) { +- BN_clear_free(r->d); +- r->d = d; +- BN_set_flags(r->d, BN_FLG_CONSTTIME); +- } +- r->dirty_cnt++; +- +- return UADK_E_SUCCESS; +-} +- + static void uadk_rsa_get0_crt_params(const RSA *r, const BIGNUM **dmp1, + const BIGNUM **dmq1, const BIGNUM **iqmp) + { +@@ -413,328 +63,7 @@ static void uadk_rsa_get0_crt_params(const RSA *r, const BIGNUM **dmp1, + *iqmp = r->iqmp; + } + +-static int uadk_rsa_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) +-{ +- /* +- * If the fields p and q in r are NULL, the corresponding input +- * parameters MUST be non-NULL. +- */ +- if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL)) +- return UADK_E_FAIL; +- +- if (p != NULL) { +- BN_clear_free(r->p); +- r->p = p; +- BN_set_flags(r->p, BN_FLG_CONSTTIME); +- } +- +- if (q != NULL) { +- BN_clear_free(r->q); +- r->q = q; +- BN_set_flags(r->q, BN_FLG_CONSTTIME); +- } +- +- r->dirty_cnt++; +- +- return UADK_E_SUCCESS; +-} +- +-static int uadk_rsa_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) +-{ +- /* +- * If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input +- * parameters MUST be non-NULL. +- */ +- if ((r->dmp1 == NULL && dmp1 == NULL) +- || (r->dmq1 == NULL && dmq1 == NULL) +- || (r->iqmp == NULL && iqmp == NULL)) +- return UADK_E_FAIL; +- +- if (dmp1 != NULL) { +- BN_clear_free(r->dmp1); +- r->dmp1 = dmp1; +- BN_set_flags(r->dmp1, BN_FLG_CONSTTIME); +- } +- +- if (dmq1 != NULL) { +- BN_clear_free(r->dmq1); +- r->dmq1 = dmq1; +- BN_set_flags(r->dmq1, BN_FLG_CONSTTIME); +- } +- +- if (iqmp != NULL) { +- BN_clear_free(r->iqmp); +- r->iqmp = iqmp; +- BN_set_flags(r->iqmp, BN_FLG_CONSTTIME); +- } +- +- r->dirty_cnt++; +- +- return UADK_E_SUCCESS; +-} +- +-static int uadk_rsa_bits(const RSA *r) +-{ +- return BN_num_bits(r->n); +-} +- +-static int uadk_rsa_size(const RSA *r) +-{ +- return BN_num_bytes(r->n); +-} +- +-static int setup_tbuf(PROV_RSA_SIG_CTX *ctx) +-{ +- if (ctx->tbuf != NULL) +- return UADK_E_SUCCESS; +- +- ctx->tbuf = OPENSSL_malloc(uadk_rsa_size(ctx->rsa)); +- if (ctx->tbuf == NULL) { +- UADK_ERR("failed to zalloc ctx tbuf!\n"); +- return UADK_E_FAIL; +- } +- +- return UADK_E_SUCCESS; +-} +- +-static void clean_tbuf(PROV_RSA_SIG_CTX *ctx) +-{ +- if (ctx->tbuf != NULL) +- OPENSSL_cleanse(ctx->tbuf, uadk_rsa_size(ctx->rsa)); +-} +- +-static void free_tbuf(PROV_RSA_SIG_CTX *ctx) +-{ +- clean_tbuf(ctx); +- OPENSSL_free(ctx->tbuf); +- ctx->tbuf = NULL; +-} +- +-static int rsa_check_bit_useful(const int bits, int flen) +-{ +- if (bits < RSA_MIN_MODULUS_BITS) +- return UADK_E_FAIL; +- if (flen > (bits >> BIT_BYTES_SHIFT)) +- return UADK_DO_SOFT; +- +- switch (bits) { +- case RSA1024BITS: +- case RSA2048BITS: +- case RSA3072BITS: +- case RSA4096BITS: +- return UADK_E_SUCCESS; +- case OPENSSLRSA7680BITS: +- case OPENSSLRSA15360BITS: +- case RSA_MIN_MODULUS_BITS: +- return UADK_DO_SOFT; +- default: +- return UADK_DO_SOFT; +- } +-} +- +-static int rsa_prime_mul_res(int num, struct rsa_prime_param *param, +- BN_CTX *ctx, BN_GENCB *cb) +-{ +- if (num == 1) { +- if (!BN_mul(param->r1, param->rsa_p, param->rsa_q, ctx)) +- return BN_ERR; +- } else { +- if (!BN_GENCB_call(cb, GENCB_RETRY, num)) +- return BN_ERR; +- return BN_CONTINUE; +- } +- +- return BN_VALID; +-} +- +-static int check_rsa_prime_sufficient(int *num, const int *bitsr, +- int *bitse, int * const n, +- struct rsa_prime_param *param, +- BN_CTX *ctx, BN_GENCB *cb) +-{ +- BN_ULONG bitst; +- int ret; +- +- ret = rsa_prime_mul_res(*num, param, ctx, cb); +- if (ret) +- return ret; +- +- /* +- * If |r1|, product of factors so far, is not as long as expected +- * (by checking the first 4 bits are less than 0x9 or greater than +- * 0xF). If so, re-generate the last prime. +- * +- * NOTE: This actually can't happen in two-prime case, because of +- * the way factors are generated. +- * +- * Besides, another consideration is, for multi-prime case, even the +- * length modulus is as long as expected, the modulus could start at +- * 0x8, which could be utilized to distinguish a multi-prime private +- * key by using the modulus in a certificate. This is also covered +- * by checking the length should not be less than 0x9. +- */ +- if (!BN_rshift(param->r2, param->r1, *bitse - PRIME_CHECK_BIT_NUM)) +- return BN_ERR; +- +- bitst = BN_get_word(param->r2); +- if (bitst > 0xF || bitst < 0x9) { +- /* +- * For keys with more than 4 primes, we attempt longer factor +- * to meet length requirement. +- * Otherwise, we just re-generate the prime with the same length. +- * This strategy has the following goals: +- * 1. 1024-bit factors are efficient when using 3072 and 4096-bit key +- * 2. stay the same logic with normal 2-prime key +- */ +- if (*num < RSA_MAX_PRIME_NUM) +- *bitse -= bitsr[*num]; +- else +- return BN_ERR; +- +- ret = BN_GENCB_call(cb, GENCB_NEXT, (*n)++); +- if (!ret) +- return BN_ERR; +- +- if (param->retries == PRIME_RETRY_COUNT) { +- param->retries = 0; +- *bitse = 0; +- *num = -1; +- return BN_CONTINUE; +- } +- param->retries++; +- return BN_REDO; +- } +- +- ret = BN_GENCB_call(cb, GENCB_RETRY, *num); +- if (!ret) +- return BN_ERR; +- param->retries = 0; +- +- return BN_VALID; +-} +- +-static void rsa_set_primes(int num, BIGNUM *rsa_p, BIGNUM *rsa_q, +- BIGNUM **prime) +-{ +- if (num == 0) +- *prime = rsa_p; +- else +- *prime = rsa_q; +- +- /* Set BN_FLG_CONSTTIME to prime exponent */ +- BN_set_flags(*prime, BN_FLG_CONSTTIME); +-} +- +-static int check_rsa_prime_equal(int num, BIGNUM *rsa_p, BIGNUM *rsa_q, +- BIGNUM *prime) +-{ +- BIGNUM *prev_prime; +- int k; +- +- for (k = 0; k < num; k++) { +- prev_prime = NULL; +- if (k == 0) +- prev_prime = rsa_p; +- else +- prev_prime = rsa_q; +- +- /* +- * BN_cmp(a,b) return -1 if a < b; +- * return 0 if a == b; +- * return 1 if a > b. +- */ +- if (!BN_cmp(prime, prev_prime)) +- return UADK_E_FAIL; +- } +- +- return UADK_E_SUCCESS; +-} +- +-static int check_rsa_prime_useful(int * const n, struct rsa_prime_param *param, +- BIGNUM *e_pub, BN_CTX *ctx, BN_GENCB *cb) +-{ +- unsigned long err; +- int ret; +- +- /* +- * BN_sub(r, a, b) substracts b from a and place the result in r, +- * r = a - b. +- * BN_value_one() returns a BIGNUM constant of value 1. +- * r2 = prime - 1. +- */ +- if (!BN_sub(param->r2, param->prime, BN_value_one())) +- return BN_ERR; +- ERR_set_mark(); +- BN_set_flags(param->r2, BN_FLG_CONSTTIME); +- +- /* +- * BN_mod_inverse(r, a, n, ctx) used to compute inverse modulo n. +- * Precisely, it computes the inverse of a modulo n, and places +- * the result in r, which means (a * r) % n == 1. +- * If r == NULL, error. If r != NULL, success. +- * The expected result: (r2 * r1) % e_pub == 1, +- * the inverse of r2 exist, that is r1. +- */ +- if (BN_mod_inverse(param->r1, param->r2, e_pub, ctx)) +- return UADK_E_SUCCESS; +- +- err = ERR_peek_last_error(); +- if (ERR_GET_LIB(err) == ERR_LIB_BN && +- ERR_GET_REASON(err) == BN_R_NO_INVERSE) +- ERR_pop_to_mark(); +- else +- return BN_ERR; +- +- ret = BN_GENCB_call(cb, GENCB_NEXT, (*n)++); +- if (!ret) +- return BN_ERR; +- +- return GET_ERR_FINISH; +-} +- +-static int get_rsa_prime_once(int num, const int *bitsr, int * const n, +- BIGNUM *e_pub, struct rsa_prime_param *param, +- BN_CTX *ctx, BN_GENCB *cb) +-{ +- int ret = -1; +- +- if (num >= RSA_MAX_PRIME_NUM) +- return ret; +- +- while (1) { +- /* Generate prime with bitsr[num] len. */ +- if (!BN_generate_prime_ex(param->prime, bitsr[num], +- 0, NULL, NULL, cb)) +- return BN_ERR; +- if (!check_rsa_prime_equal(num, param->rsa_p, param->rsa_q, +- param->prime)) +- continue; +- +- ret = check_rsa_prime_useful(n, param, e_pub, ctx, cb); +- if (ret == BN_ERR) +- return BN_ERR; +- else if (ret == UADK_E_SUCCESS) +- break; +- } +- +- return ret; +-} +- +-static void rsa_switch_p_q(BIGNUM *rsa_p, BIGNUM *rsa_q, BIGNUM *p, BIGNUM *q) +-{ +- BIGNUM *tmp; +- +- if (BN_cmp(rsa_p, rsa_q) < 0) { +- tmp = rsa_p; +- rsa_p = rsa_q; +- rsa_q = tmp; +- } +- +- BN_copy(p, rsa_p); +- BN_copy(q, rsa_q); +-} +- +-static int check_rsa_is_crt(RSA *rsa) ++int check_rsa_is_crt(RSA *rsa) + { + const BIGNUM *p = NULL; + const BIGNUM *q = NULL; +@@ -759,249 +88,98 @@ static int check_rsa_is_crt(RSA *rsa) + return UN_SET; + } + +-static int get_rsa_prime_param(struct rsa_prime_param *param, BN_CTX *ctx) +-{ +- param->r1 = BN_CTX_get(ctx); +- if (!param->r1) +- goto error; +- +- param->r2 = BN_CTX_get(ctx); +- if (!param->r2) +- goto error; +- +- param->rsa_q = BN_CTX_get(ctx); +- if (!param->rsa_q) +- goto error; +- +- param->rsa_p = BN_CTX_get(ctx); +- if (!param->rsa_p) +- goto error; +- +- return UADK_E_SUCCESS; +- +-error: +- UADK_ERR("failed to allocate rsa prime params\n"); +- return -ENOMEM; +-} +- +-static int rsa_primes_gen(int bits, BIGNUM *e_pub, BIGNUM *p, +- BIGNUM *q, BN_GENCB *cb) +-{ +- int bitsr[RSA_MAX_PRIME_NUM] = {0}; +- struct rsa_prime_param *param; +- int flag, quot, rmd, i; +- BN_CTX *bnctx; +- int bitse = 0; +- int ret = 0; +- /* n: modulo n, a part of public key */ +- int n = 0; +- +- bnctx = BN_CTX_new(); +- if (!bnctx) +- return ret; +- +- BN_CTX_start(bnctx); +- param = OPENSSL_zalloc(sizeof(struct rsa_prime_param)); +- if (!param) +- goto free_ctx; +- +- ret = get_rsa_prime_param(param, bnctx); +- if (ret != UADK_E_SUCCESS) +- goto free_param; +- +- /* Divide bits into 'primes' pieces evenly */ +- quot = bits / RSA_MAX_PRIME_NUM; +- rmd = bits % RSA_MAX_PRIME_NUM; +- for (i = 0; i < RSA_MAX_PRIME_NUM; i++) +- bitsr[i] = (i < rmd) ? quot + 1 : quot; +- +- /* Generate p, q and other primes (if any) */ +- for (i = 0; i < RSA_MAX_PRIME_NUM; i++) { +- /* flag: whether primes are generated correctely. */ +- flag = 1; +- /* Set flag for primes rsa_p and rsa_q separately. */ +- rsa_set_primes(i, param->rsa_p, param->rsa_q, ¶m->prime); +- while (flag == 1) { +- ret = get_rsa_prime_once(i, bitsr, &n, e_pub, param, +- bnctx, cb); +- if (ret == -1) +- goto free_param; +- bitse += bitsr[i]; +- ret = check_rsa_prime_sufficient(&i, bitsr, &bitse, &n, +- param, bnctx, cb); +- if (ret == BN_ERR) +- goto free_param; +- else if (ret == BN_REDO) +- continue; +- else +- flag = 0; +- } +- } +- rsa_switch_p_q(param->rsa_p, param->rsa_q, p, q); +- +- ret = UADK_E_SUCCESS; +- +-free_param: +- OPENSSL_free(param); +-free_ctx: +- BN_CTX_end(bnctx); +- BN_CTX_free(bnctx); +- return ret; +-} +- +-static int add_rsa_pubenc_padding(int flen, const unsigned char *from, +- unsigned char *buf, int num, int padding) +-{ +- int ret; +- +- if (!buf || !num) { +- UADK_ERR("buf or num is invalid.\n"); +- return UADK_E_FAIL; +- } +- +- switch (padding) { +- case RSA_PKCS1_PADDING: +- ret = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); +- if (!ret) +- UADK_ERR("RSA_PKCS1_PADDING err.\n"); +- break; +- case RSA_PKCS1_OAEP_PADDING: +- ret = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); +- if (!ret) +- UADK_ERR("RSA_PKCS1_OAEP_PADDING err.\n"); +- break; +- default: +- ret = UADK_E_FAIL; +- } +- +- return ret; +-} +- +-static int check_rsa_pridec_padding(unsigned char *to, int num, +- const unsigned char *buf, int flen, +- int padding) ++int rsa_fill_prikey(RSA *rsa, struct uadk_rsa_sess *rsa_sess, ++ struct rsa_prikey_param *pri, ++ unsigned char *in_buf, unsigned char *to) + { +- int ret; +- +- switch (padding) { +- case RSA_PKCS1_PADDING: +- ret = RSA_padding_check_PKCS1_type_2(to, num, buf, flen, num); +- if (ret == CHECK_PADDING_FAIL) +- UADK_ERR("RSA_PKCS1_PADDING err.\n"); +- break; +- case RSA_PKCS1_OAEP_PADDING: +- ret = RSA_padding_check_PKCS1_OAEP(to, num, buf, flen, num, +- NULL, 0); +- if (ret == CHECK_PADDING_FAIL) +- UADK_ERR("RSA_PKCS1_OAEP_PADDING err.\n"); +- break; +- default: +- ret = UADK_E_FAIL; +- } +- +- if (ret == CHECK_PADDING_FAIL) +- ret = UADK_E_FAIL; +- +- return ret; +-} ++ struct wd_rsa_prikey *prikey = NULL; ++ struct wd_dtb *wd_qinv = NULL; ++ struct wd_dtb *wd_dp = NULL; ++ struct wd_dtb *wd_dq = NULL; ++ struct wd_dtb *wd_p = NULL; ++ struct wd_dtb *wd_q = NULL; ++ struct wd_dtb *wd_n = NULL; ++ struct wd_dtb *wd_d = NULL; + +-static int add_rsa_prienc_padding(int flen, const unsigned char *from, +- unsigned char *to_buf, int tlen, +- int padding) +-{ +- int ret; ++ if (!rsa_sess->is_prikey_ready && pri->is_crt) { ++ wd_rsa_get_prikey(rsa_sess->sess, &prikey); ++ if (!prikey) ++ return UADK_P_FAIL; + +- switch (padding) { +- case RSA_PKCS1_PADDING: +- ret = RSA_padding_add_PKCS1_type_1(to_buf, tlen, from, flen); +- if (!ret) +- UADK_ERR("RSA_PKCS1_PADDING err.\n"); +- break; +- case RSA_X931_PADDING: +- ret = RSA_padding_add_X931(to_buf, tlen, from, flen); +- if (ret == -1) +- UADK_ERR("RSA_X931_PADDING err.\n"); +- break; +- default: +- ret = UADK_E_FAIL; +- } +- if (ret <= 0) +- ret = UADK_E_FAIL; ++ wd_rsa_get_crt_prikey_params(prikey, &wd_dq, &wd_dp, ++ &wd_qinv, &wd_q, &wd_p); ++ if (!wd_dq || !wd_dp || !wd_qinv || !wd_q || !wd_p) ++ return UADK_P_FAIL; + +- return ret; +-} ++ wd_dp->dsize = BN_bn2bin(pri->dmp1, ++ (unsigned char *)wd_dp->data); ++ wd_dq->dsize = BN_bn2bin(pri->dmq1, ++ (unsigned char *)wd_dq->data); ++ wd_p->dsize = BN_bn2bin(pri->p, ++ (unsigned char *)wd_p->data); ++ wd_q->dsize = BN_bn2bin(pri->q, ++ (unsigned char *)wd_q->data); ++ wd_qinv->dsize = BN_bn2bin(pri->iqmp, ++ (unsigned char *)wd_qinv->data); ++ } else if (!rsa_sess->is_prikey_ready && !pri->is_crt) { ++ wd_rsa_get_prikey(rsa_sess->sess, &prikey); ++ if (!prikey) ++ return UADK_P_FAIL; + +-static int check_rsa_pubdec_padding(unsigned char *to, int num, +- const unsigned char *buf, int len, +- int padding) +-{ +- int ret; ++ wd_rsa_get_prikey_params(prikey, &wd_d, &wd_n); ++ if (!wd_d || !wd_n) ++ return UADK_P_FAIL; + +- switch (padding) { +- case RSA_PKCS1_PADDING: +- ret = RSA_padding_check_PKCS1_type_1(to, num, buf, len, num); +- if (ret == CHECK_PADDING_FAIL) +- UADK_ERR("RSA_PKCS1_PADDING err.\n"); +- break; +- case RSA_X931_PADDING: +- ret = RSA_padding_check_X931(to, num, buf, len, num); +- if (ret == CHECK_PADDING_FAIL) +- UADK_ERR("RSA_X931_PADDING err.\n"); +- break; +- default: +- ret = UADK_E_FAIL; ++ wd_n->dsize = BN_bn2bin(pri->n, ++ (unsigned char *)wd_n->data); ++ wd_d->dsize = BN_bn2bin(pri->d, ++ (unsigned char *)wd_d->data); ++ } else { ++ return UADK_P_FAIL; + } + +- if (ret == CHECK_PADDING_FAIL) +- ret = UADK_E_FAIL; +- +- return ret; +-} ++ rsa_sess->is_prikey_ready = IS_SET; ++ rsa_sess->req.op_type = WD_RSA_SIGN; ++ rsa_sess->req.src_bytes = rsa_sess->key_size; ++ rsa_sess->req.dst_bytes = rsa_sess->key_size; ++ rsa_sess->req.src = in_buf; ++ rsa_sess->req.dst = to; + +-static BN_ULONG *bn_get_words(const BIGNUM *a) +-{ +- return a->d; ++ return UADK_P_SUCCESS; + } + +-static int check_rsa_input_para(const int flen, const unsigned char *from, +- unsigned char *to, RSA *rsa) ++int rsa_fill_pubkey(struct rsa_pubkey_param *pubkey_param, ++ struct uadk_rsa_sess *rsa_sess, ++ unsigned char *in_buf, unsigned char *to) + { +- if (!rsa || !to || !from || flen <= 0) { +- UADK_ERR("input param invalid\n"); +- return UADK_E_FAIL; +- } +- +- return rsa_check_bit_useful(uadk_rsa_bits(rsa), flen); +-} ++ struct wd_rsa_pubkey *pubkey = NULL; ++ struct wd_dtb *wd_n = NULL; ++ struct wd_dtb *wd_e = NULL; + +-static int rsa_get_sign_res(int padding, BIGNUM *to_bn, const BIGNUM *n, +- BIGNUM *ret_bn, BIGNUM **res) +-{ +- if (padding == RSA_X931_PADDING) { +- if (!BN_sub(to_bn, n, ret_bn)) +- return UADK_E_FAIL; +- if (BN_cmp(ret_bn, to_bn) > 0) +- *res = to_bn; +- else +- *res = ret_bn; +- } else { +- *res = ret_bn; +- } ++ if (!rsa_sess->is_pubkey_ready) { ++ wd_rsa_get_pubkey(rsa_sess->sess, &pubkey); ++ if (!pubkey) ++ return UADK_P_FAIL; + +- return UADK_E_SUCCESS; +-} ++ wd_rsa_get_pubkey_params(pubkey, &wd_e, &wd_n); ++ if (!wd_n || !wd_e) ++ return UADK_P_FAIL; + +-static int rsa_get_verify_res(int padding, const BIGNUM *n, BIGNUM *ret_bn) +-{ +- BIGNUM *to_bn = NULL; ++ wd_n->dsize = BN_bn2bin(pubkey_param->n, ++ (unsigned char *)wd_n->data); ++ wd_e->dsize = BN_bn2bin(pubkey_param->e, ++ (unsigned char *)wd_e->data); ++ rsa_sess->req.src_bytes = rsa_sess->key_size; ++ rsa_sess->req.dst_bytes = rsa_sess->key_size; ++ rsa_sess->req.op_type = WD_RSA_VERIFY; ++ rsa_sess->is_pubkey_ready = IS_SET; ++ rsa_sess->req.src = in_buf; ++ rsa_sess->req.dst = to; + +- if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret_bn)[0] & 0xf) +- != 0x0c)) { +- if (!BN_sub(to_bn, n, ret_bn)) +- return UADK_E_FAIL; ++ return UADK_P_SUCCESS; + } + +- return UADK_E_SUCCESS; ++ return UADK_P_FAIL; + } + + static int uadk_rsa_env_poll(void *ctx) +@@ -1030,7 +208,7 @@ static void uadk_rsa_mutex_infork(void) + pthread_mutex_unlock(&rsa_mutex); + } + +-static int uadk_prov_rsa_init(void) ++int uadk_prov_rsa_init(void) + { + char alg_name[] = "rsa"; + int ret; +@@ -1048,13 +226,23 @@ static int uadk_prov_rsa_init(void) + } + pthread_mutex_unlock(&rsa_mutex); + +- return UADK_E_INIT_SUCCESS; ++ return UADK_P_INIT_SUCCESS; + } + +-static struct uadk_rsa_sess *rsa_new_eng_session(RSA *rsa) ++void uadk_prov_destroy_rsa(void) + { +- struct uadk_rsa_sess *rsa_sess; +- ++ pthread_mutex_lock(&rsa_mutex); ++ if (g_rsa_prov.pid == getpid()) { ++ wd_rsa_uninit2(); ++ g_rsa_prov.pid = 0; ++ } ++ pthread_mutex_unlock(&rsa_mutex); ++} ++ ++static struct uadk_rsa_sess *rsa_new_eng_session(RSA *rsa) ++{ ++ struct uadk_rsa_sess *rsa_sess; ++ + rsa_sess = OPENSSL_malloc(sizeof(struct uadk_rsa_sess)); + if (!rsa_sess) + return NULL; +@@ -1067,7 +255,7 @@ static struct uadk_rsa_sess *rsa_new_eng_session(RSA *rsa) + return rsa_sess; + } + +-static void rsa_free_eng_session(struct uadk_rsa_sess *rsa_sess) ++void rsa_free_eng_session(struct uadk_rsa_sess *rsa_sess) + { + if (!rsa_sess) + return; +@@ -1080,7 +268,7 @@ static void rsa_free_eng_session(struct uadk_rsa_sess *rsa_sess) + OPENSSL_free(rsa_sess); + } + +-static struct uadk_rsa_sess *rsa_get_eng_session(RSA *rsa, unsigned int bits, ++struct uadk_rsa_sess *rsa_get_eng_session(RSA *rsa, unsigned int bits, + int is_crt) + { + unsigned int key_size = bits >> BIT_BYTES_SHIFT; +@@ -1108,163 +296,6 @@ static struct uadk_rsa_sess *rsa_get_eng_session(RSA *rsa, unsigned int bits, + return rsa_sess; + } + +-static int rsa_fill_pubkey(struct rsa_pubkey_param *pubkey_param, +- struct uadk_rsa_sess *rsa_sess, +- unsigned char *in_buf, unsigned char *to) +-{ +- struct wd_rsa_pubkey *pubkey = NULL; +- struct wd_dtb *wd_n = NULL; +- struct wd_dtb *wd_e = NULL; +- +- if (!rsa_sess->is_pubkey_ready) { +- wd_rsa_get_pubkey(rsa_sess->sess, &pubkey); +- if (!pubkey) +- return UADK_E_FAIL; +- +- wd_rsa_get_pubkey_params(pubkey, &wd_e, &wd_n); +- if (!wd_n || !wd_e) +- return UADK_E_FAIL; +- +- wd_n->dsize = BN_bn2bin(pubkey_param->n, +- (unsigned char *)wd_n->data); +- wd_e->dsize = BN_bn2bin(pubkey_param->e, +- (unsigned char *)wd_e->data); +- rsa_sess->req.src_bytes = rsa_sess->key_size; +- rsa_sess->req.dst_bytes = rsa_sess->key_size; +- rsa_sess->req.op_type = WD_RSA_VERIFY; +- rsa_sess->is_pubkey_ready = IS_SET; +- rsa_sess->req.src = in_buf; +- rsa_sess->req.dst = to; +- +- return UADK_E_SUCCESS; +- } +- +- return UADK_E_FAIL; +-} +- +-static int rsa_fill_prikey(RSA *rsa, struct uadk_rsa_sess *rsa_sess, +- struct rsa_prikey_param *pri, +- unsigned char *in_buf, unsigned char *to) +-{ +- struct wd_rsa_prikey *prikey = NULL; +- struct wd_dtb *wd_qinv = NULL; +- struct wd_dtb *wd_dp = NULL; +- struct wd_dtb *wd_dq = NULL; +- struct wd_dtb *wd_p = NULL; +- struct wd_dtb *wd_q = NULL; +- struct wd_dtb *wd_n = NULL; +- struct wd_dtb *wd_d = NULL; +- +- if (!(rsa_sess->is_prikey_ready) && (pri->is_crt)) { +- wd_rsa_get_prikey(rsa_sess->sess, &prikey); +- if (!prikey) +- return UADK_E_FAIL; +- +- wd_rsa_get_crt_prikey_params(prikey, &wd_dq, &wd_dp, +- &wd_qinv, &wd_q, &wd_p); +- if (!wd_dq || !wd_dp || !wd_qinv || !wd_q || !wd_p) +- return UADK_E_FAIL; +- +- wd_dp->dsize = BN_bn2bin(pri->dmp1, +- (unsigned char *)wd_dp->data); +- wd_dq->dsize = BN_bn2bin(pri->dmq1, +- (unsigned char *)wd_dq->data); +- wd_p->dsize = BN_bn2bin(pri->p, +- (unsigned char *)wd_p->data); +- wd_q->dsize = BN_bn2bin(pri->q, +- (unsigned char *)wd_q->data); +- wd_qinv->dsize = BN_bn2bin(pri->iqmp, +- (unsigned char *)wd_qinv->data); +- } else if (!(rsa_sess->is_prikey_ready) && !(pri->is_crt)) { +- wd_rsa_get_prikey(rsa_sess->sess, &prikey); +- if (!prikey) +- return UADK_E_FAIL; +- +- wd_rsa_get_prikey_params(prikey, &wd_d, &wd_n); +- if (!wd_d || !wd_n) +- return UADK_E_FAIL; +- +- wd_n->dsize = BN_bn2bin(pri->n, +- (unsigned char *)wd_n->data); +- wd_d->dsize = BN_bn2bin(pri->d, +- (unsigned char *)wd_d->data); +- } else { +- return UADK_E_FAIL; +- } +- +- rsa_sess->is_prikey_ready = IS_SET; +- rsa_sess->req.op_type = WD_RSA_SIGN; +- rsa_sess->req.src_bytes = rsa_sess->key_size; +- rsa_sess->req.dst_bytes = rsa_sess->key_size; +- rsa_sess->req.src = in_buf; +- rsa_sess->req.dst = to; +- +- return UADK_E_SUCCESS; +-} +- +-static int rsa_get_keygen_param(struct wd_rsa_req *req, handle_t ctx, RSA *rsa, +- struct rsa_keygen_param_bn *bn_param) +-{ +- struct wd_rsa_kg_out *out = (struct wd_rsa_kg_out *)req->dst; +- struct wd_dtb wd_d, wd_n, wd_qinv, wd_dq, wd_dp; +- BIGNUM *dmp1, *dmq1, *iqmp, *d, *n; +- unsigned int key_bits, key_size; +- +- key_bits = wd_rsa_get_key_bits(ctx); +- if (!key_bits) +- return UADK_E_FAIL; +- +- key_size = key_bits >> BIT_BYTES_SHIFT; +- wd_rsa_get_kg_out_params(out, &wd_d, &wd_n); +- wd_rsa_get_kg_out_crt_params(out, &wd_qinv, &wd_dq, &wd_dp); +- +- dmq1 = BN_secure_new(); +- if (!dmq1) +- return UADK_E_FAIL; +- +- dmp1 = BN_secure_new(); +- if (!dmp1) +- goto free_bn_dq; +- +- iqmp = BN_new(); +- if (!iqmp) +- goto free_bn_dp; +- +- n = BN_new(); +- if (!n) +- goto free_bn_qinv; +- +- d = BN_secure_new(); +- if (!d) +- goto free_bn_n; +- +- BN_bin2bn((unsigned char *)wd_n.data, key_size, n); +- BN_bin2bn((unsigned char *)wd_d.data, key_size, d); +- BN_bin2bn((unsigned char *)wd_qinv.data, wd_qinv.dsize, iqmp); +- BN_bin2bn((unsigned char *)wd_dq.data, wd_dq.dsize, dmq1); +- BN_bin2bn((unsigned char *)wd_dp.data, wd_dp.dsize, dmp1); +- +- if (!(uadk_rsa_set0_key(rsa, n, bn_param->e, d) && +- uadk_rsa_set0_factors(rsa, bn_param->p, bn_param->q) && +- uadk_rsa_set0_crt_params(rsa, dmp1, dmq1, iqmp))) +- goto free_bn_d; +- +- return UADK_E_SUCCESS; +- +-free_bn_d: +- BN_clear_free(d); +-free_bn_n: +- BN_clear_free(n); +-free_bn_qinv: +- BN_clear_free(iqmp); +-free_bn_dp: +- BN_clear_free(dmp1); +-free_bn_dq: +- BN_clear_free(dmq1); +- +- return UADK_E_FAIL; +-} +- + static void uadk_e_rsa_cb(void *req_t) + { + struct wd_rsa_req *req = (struct wd_rsa_req *)req_t; +@@ -1293,7 +324,7 @@ static void uadk_e_rsa_cb(void *req_t) + } + } + +-static int rsa_do_crypto(struct uadk_rsa_sess *rsa_sess) ++int rsa_do_crypto(struct uadk_rsa_sess *rsa_sess) + { + struct uadk_e_cb_info cb_param; + struct async_op op; +@@ -1302,14 +333,14 @@ static int rsa_do_crypto(struct uadk_rsa_sess *rsa_sess) + ret = async_setup_async_event_notification(&op); + if (!ret) { + UADK_ERR("failed to setup async event notification.\n"); +- return UADK_E_FAIL; ++ return UADK_P_FAIL; + } + + if (!op.job) { + ret = wd_do_rsa_sync(rsa_sess->sess, &(rsa_sess->req)); + if (ret) + goto err; +- return UADK_E_SUCCESS; ++ return UADK_P_SUCCESS; + } + cb_param.op = &op; + cb_param.priv = &(rsa_sess->req); +@@ -1335,139 +366,59 @@ static int rsa_do_crypto(struct uadk_rsa_sess *rsa_sess) + goto err; + + if (rsa_sess->req.status) +- return UADK_E_FAIL; ++ return UADK_P_FAIL; + +- return UADK_E_SUCCESS; ++ return UADK_P_SUCCESS; + + err: + (void)async_clear_async_event_notification(); +- return UADK_E_FAIL; ++ return UADK_P_FAIL; + } + +-static int rsa_fill_keygen_data(struct uadk_rsa_sess *rsa_sess, +- struct rsa_keypair *key_pair, +- struct rsa_keygen_param *keygen_param, +- struct rsa_keygen_param_bn *bn_param) ++int uadk_rsa_bits(const RSA *r) + { +- wd_rsa_get_pubkey(rsa_sess->sess, &key_pair->pubkey); +- if (!key_pair->pubkey) +- return UADK_E_FAIL; +- +- wd_rsa_get_pubkey_params(key_pair->pubkey, &keygen_param->wd_e, NULL); +- if (!keygen_param->wd_e) +- return UADK_E_FAIL; +- +- keygen_param->wd_e->dsize = BN_bn2bin(bn_param->e, +- (unsigned char *)keygen_param->wd_e->data); +- +- wd_rsa_get_prikey(rsa_sess->sess, &key_pair->prikey); +- if (!key_pair->prikey) +- return UADK_E_FAIL; +- +- wd_rsa_get_crt_prikey_params(key_pair->prikey, NULL, NULL, NULL, +- &keygen_param->wd_q, &keygen_param->wd_p); +- if (!keygen_param->wd_p || !keygen_param->wd_q) +- return UADK_E_FAIL; +- +- keygen_param->wd_p->dsize = BN_bn2bin(bn_param->p, +- (unsigned char *)keygen_param->wd_p->data); +- keygen_param->wd_q->dsize = BN_bn2bin(bn_param->q, +- (unsigned char *)keygen_param->wd_q->data); +- +- rsa_sess->req.src_bytes = rsa_sess->key_size; +- rsa_sess->req.dst_bytes = rsa_sess->key_size; +- rsa_sess->req.op_type = WD_RSA_GENKEY; +- rsa_sess->req.src = wd_rsa_new_kg_in(rsa_sess->sess, keygen_param->wd_e, +- keygen_param->wd_p, keygen_param->wd_q); +- if (!rsa_sess->req.src) +- return UADK_E_FAIL; +- +- rsa_sess->req.dst = wd_rsa_new_kg_out(rsa_sess->sess); +- if (!rsa_sess->req.dst) { +- wd_rsa_del_kg_in(rsa_sess->sess, rsa_sess->req.src); +- return UADK_E_FAIL; +- } +- +- return UADK_E_SUCCESS; ++ return BN_num_bits(r->n); + } + +-static void rsa_free_keygen_data(struct uadk_rsa_sess *rsa_sess) ++int uadk_rsa_size(const RSA *r) + { +- if (!rsa_sess) +- return; +- +- wd_rsa_del_kg_out(rsa_sess->sess, rsa_sess->req.dst); +- wd_rsa_del_kg_in(rsa_sess->sess, rsa_sess->req.src); ++ return BN_num_bytes(r->n); + } + +-static int rsa_keygen_param_alloc(struct rsa_keygen_param **keygen_param, +- struct rsa_keygen_param_bn **keygen_bn_param, +- struct rsa_keypair **key_pair) ++int rsa_check_bit_useful(const int bits, int flen) + { +- *keygen_param = OPENSSL_malloc(sizeof(struct rsa_keygen_param)); +- if (!(*keygen_param)) +- goto error; +- +- *keygen_bn_param = (struct rsa_keygen_param_bn *) +- OPENSSL_malloc(sizeof(struct rsa_keygen_param_bn)); +- if (!(*keygen_bn_param)) +- goto free_keygen_param; +- +- *key_pair = OPENSSL_malloc(sizeof(struct rsa_keypair)); +- if (!(*key_pair)) +- goto free_keygen_bn_param; +- +- (*keygen_bn_param)->p = BN_secure_new(); +- if (!(*keygen_bn_param)->p) +- goto free_key_pair; +- +- (*keygen_bn_param)->q = BN_secure_new(); +- if (!(*keygen_bn_param)->q) +- goto free_p; +- +- (*keygen_bn_param)->e = BN_new(); +- if (!(*keygen_bn_param)->e) +- goto free_q; +- +- return UADK_E_SUCCESS; +- +-free_q: +- BN_clear_free((*keygen_bn_param)->q); +-free_p: +- BN_clear_free((*keygen_bn_param)->p); +-free_key_pair: +- OPENSSL_free(*key_pair); +-free_keygen_bn_param: +- OPENSSL_free(*keygen_bn_param); +-free_keygen_param: +- OPENSSL_free(*keygen_param); +-error: +- return -ENOMEM; ++ if (bits < RSA_MIN_MODULUS_BITS) ++ return UADK_P_FAIL; ++ if (flen > (bits >> BIT_BYTES_SHIFT)) ++ return UADK_DO_SOFT; ++ ++ switch (bits) { ++ case RSA1024BITS: ++ case RSA2048BITS: ++ case RSA3072BITS: ++ case RSA4096BITS: ++ return UADK_P_SUCCESS; ++ case OPENSSLRSA7680BITS: ++ case OPENSSLRSA15360BITS: ++ case RSA_MIN_MODULUS_BITS: ++ return UADK_DO_SOFT; ++ default: ++ return UADK_DO_SOFT; ++ } + } + +-static void rsa_keygen_param_free(struct rsa_keygen_param **keygen_param, +- struct rsa_keygen_param_bn **keygen_bn_param, +- struct rsa_keypair **key_pair, int free_bn_ctx_tag) ++int check_rsa_input_para(const int flen, const unsigned char *from, ++ unsigned char *to, RSA *rsa) + { +- /* +- * When an abnormal situation occurs, uadk engine needs to +- * switch to software keygen function, so we need to free +- * BN we alloced before. But in normal situation, +- * the BN should be freed by OpenSSL tools or users. +- * Therefore, we use a tag to distinguish these cases. +- */ +- if (free_bn_ctx_tag == UADK_DO_SOFT) { +- BN_clear_free((*keygen_bn_param)->p); +- BN_clear_free((*keygen_bn_param)->q); +- BN_clear_free((*keygen_bn_param)->e); ++ if (!rsa || !to || !from || flen <= 0) { ++ UADK_ERR("input param invalid\n"); ++ return UADK_P_FAIL; + } + +- OPENSSL_free(*key_pair); +- OPENSSL_free(*keygen_param); +- OPENSSL_free(*keygen_bn_param); ++ return rsa_check_bit_useful(uadk_rsa_bits(rsa), flen); + } + +-static int rsa_pkey_param_alloc(struct rsa_pubkey_param **pub, ++int rsa_pkey_param_alloc(struct rsa_pubkey_param **pub, + struct rsa_prikey_param **pri) + { + if (pub) { +@@ -1485,10 +436,9 @@ static int rsa_pkey_param_alloc(struct rsa_pubkey_param **pub, + } + } + +- return UADK_E_SUCCESS; ++ return UADK_P_SUCCESS; + } +- +-static void rsa_pkey_param_free(struct rsa_pubkey_param **pub, ++void rsa_pkey_param_free(struct rsa_pubkey_param **pub, + struct rsa_prikey_param **pri) + { + if (pri) +@@ -1497,1673 +447,67 @@ static void rsa_pkey_param_free(struct rsa_pubkey_param **pub, + OPENSSL_free(*pub); + } + +-static int rsa_create_pub_bn_ctx(RSA *rsa, struct rsa_pubkey_param *pub, ++static void uadk_rsa_get0_key(const RSA *r, const BIGNUM **n, ++ const BIGNUM **e, const BIGNUM **d) ++{ ++ if (n != NULL) ++ *n = r->n; ++ if (e != NULL) ++ *e = r->e; ++ if (d != NULL) ++ *d = r->d; ++} ++ ++int rsa_create_pub_bn_ctx(RSA *rsa, struct rsa_pubkey_param *pub, + unsigned char **from_buf, int *num_bytes) + { + uadk_rsa_get0_key(rsa, &pub->n, &pub->e, NULL); + if (!(pub->e) || !(pub->n)) +- return UADK_E_FAIL; ++ return UADK_P_FAIL; + + *num_bytes = BN_num_bytes(pub->n); + if (!(*num_bytes)) +- return UADK_E_FAIL; ++ return UADK_P_FAIL; + + *from_buf = OPENSSL_malloc(*num_bytes); + if (!(*from_buf)) + return -ENOMEM; + +- return UADK_E_SUCCESS; ++ return UADK_P_SUCCESS; + } + +-static void rsa_free_pub_bn_ctx(unsigned char **from_buf) ++void rsa_free_pub_bn_ctx(unsigned char *from_buf) + { +- OPENSSL_free(*from_buf); ++ OPENSSL_free(from_buf); + } + +-static int rsa_create_pri_bn_ctx(RSA *rsa, struct rsa_prikey_param *pri, ++int rsa_create_pri_bn_ctx(RSA *rsa, struct rsa_prikey_param *pri, + unsigned char **from_buf, int *num_bytes) + { + uadk_rsa_get0_key(rsa, &pri->n, &pri->e, &pri->d); + if (!(pri->n) || !(pri->e) || !(pri->d)) +- return UADK_E_FAIL; ++ return UADK_P_FAIL; + + uadk_rsa_get0_factors(rsa, &pri->p, &pri->q); + if (!(pri->p) || !(pri->q)) +- return UADK_E_FAIL; ++ return UADK_P_FAIL; + + uadk_rsa_get0_crt_params(rsa, &pri->dmp1, &pri->dmq1, &pri->iqmp); + if (!(pri->dmp1) || !(pri->dmq1) || !(pri->iqmp)) +- return UADK_E_FAIL; ++ return UADK_P_FAIL; + + *num_bytes = BN_num_bytes(pri->n); + if (!(*num_bytes)) +- return UADK_E_FAIL; ++ return UADK_P_FAIL; + + *from_buf = OPENSSL_malloc(*num_bytes); + if (!(*from_buf)) + return -ENOMEM; + +- return UADK_E_SUCCESS; +-} +- +-static void rsa_free_pri_bn_ctx(unsigned char **from_buf) +-{ +- OPENSSL_free(*from_buf); +-} +- +-static int uadk_prov_rsa_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) +-{ +- struct rsa_keygen_param *keygen_param = NULL; +- struct rsa_keygen_param_bn *bn_param = NULL; +- struct rsa_keypair *key_pair = NULL; +- struct uadk_rsa_sess *rsa_sess; +- int is_crt = 1; +- int ret; +- +- ret = rsa_check_bit_useful(bits, 0); +- if (ret != UADK_E_SUCCESS) +- return ret; +- +- ret = rsa_keygen_param_alloc(&keygen_param, &bn_param, &key_pair); +- if (ret == -ENOMEM) +- return UADK_E_FAIL; +- +- rsa_sess = rsa_get_eng_session(rsa, bits, is_crt); +- if (!rsa_sess) { +- ret = UADK_DO_SOFT; +- goto free_keygen; +- } +- +- ret = rsa_primes_gen(bits, e, bn_param->p, bn_param->q, cb); +- if (!ret) { +- ret = UADK_E_FAIL; +- goto free_sess; +- } +- +- if (!BN_copy(bn_param->e, e)) { +- ret = UADK_E_FAIL; +- goto free_sess; +- } +- +- ret = rsa_fill_keygen_data(rsa_sess, key_pair, keygen_param, bn_param); +- if (!ret) { +- ret = UADK_E_FAIL; +- goto free_sess; +- } +- +- ret = rsa_do_crypto(rsa_sess); +- if (!ret || rsa_sess->req.status) { +- ret = UADK_DO_SOFT; +- goto free_kg_in_out; +- } +- +- ret = rsa_get_keygen_param(&rsa_sess->req, rsa_sess->sess, rsa, bn_param); +- if (!ret) +- ret = UADK_E_FAIL; +- +-free_kg_in_out: +- rsa_free_keygen_data(rsa_sess); +-free_sess: +- rsa_free_eng_session(rsa_sess); +-free_keygen: +- rsa_keygen_param_free(&keygen_param, &bn_param, &key_pair, ret); +- return ret; +-} +- +-static int crypt_trans_bn(struct uadk_rsa_sess *rsa_sess, unsigned char *buf, int num_bytes) +-{ +- BIGNUM *bn; +- int ret; +- +- bn = BN_bin2bn((const unsigned char *)rsa_sess->req.dst, +- rsa_sess->req.dst_bytes, NULL); +- if (!bn) +- return UADK_E_FAIL; +- +- ret = BN_bn2binpad(bn, buf, num_bytes); +- if (ret == BN_ERR) +- ret = UADK_E_FAIL; +- +- BN_free(bn); +- +- return ret; +-} +- +-static int uadk_prov_rsa_public_encrypt(int flen, const unsigned char *from, +- unsigned char *to, RSA *rsa, int padding) +-{ +- struct rsa_pubkey_param *pub_enc = NULL; +- struct uadk_rsa_sess *rsa_sess; +- unsigned char *from_buf = NULL; +- int num_bytes, is_crt, ret; +- +- ret = check_rsa_input_para(flen, from, to, rsa); +- if (ret != UADK_E_SUCCESS) +- return ret; +- +- ret = rsa_pkey_param_alloc(&pub_enc, NULL); +- if (ret == -ENOMEM) +- return UADK_E_FAIL; +- +- is_crt = check_rsa_is_crt(rsa); +- +- rsa_sess = rsa_get_eng_session(rsa, uadk_rsa_bits(rsa), is_crt); +- if (!rsa_sess) { +- ret = UADK_DO_SOFT; +- goto free_pkey; +- } +- +- ret = rsa_create_pub_bn_ctx(rsa, pub_enc, &from_buf, &num_bytes); +- if (ret <= 0) { +- ret = UADK_E_FAIL; +- goto free_sess; +- } +- +- ret = add_rsa_pubenc_padding(flen, from, from_buf, num_bytes, padding); +- if (!ret) { +- ret = UADK_E_FAIL; +- goto free_buf; +- } +- +- ret = rsa_fill_pubkey(pub_enc, rsa_sess, from_buf, to); +- if (!ret) { +- ret = UADK_E_FAIL; +- goto free_buf; +- } +- +- ret = rsa_do_crypto(rsa_sess); +- if (!ret || rsa_sess->req.status) { +- ret = UADK_DO_SOFT; +- goto free_buf; +- } +- +- ret = crypt_trans_bn(rsa_sess, to, num_bytes); +- +-free_buf: +- rsa_free_pub_bn_ctx(&from_buf); +-free_sess: +- rsa_free_eng_session(rsa_sess); +-free_pkey: +- rsa_pkey_param_free(&pub_enc, NULL); +- return ret; +-} +- +-static int uadk_prov_rsa_private_decrypt(int flen, const unsigned char *from, +- unsigned char *to, RSA *rsa, int padding) +-{ +- struct rsa_prikey_param *pri = NULL; +- unsigned char *from_buf = NULL; +- struct uadk_rsa_sess *rsa_sess; +- int num_bytes, ret; +- +- ret = check_rsa_input_para(flen, from, to, rsa); +- if (ret != UADK_E_SUCCESS) +- return ret; +- +- ret = rsa_pkey_param_alloc(NULL, &pri); +- if (ret == -ENOMEM) +- return UADK_E_FAIL; +- +- pri->is_crt = check_rsa_is_crt(rsa); +- +- rsa_sess = rsa_get_eng_session(rsa, uadk_rsa_bits(rsa), pri->is_crt); +- if (!rsa_sess) { +- ret = UADK_DO_SOFT; +- goto free_pkey; +- } +- +- ret = rsa_create_pri_bn_ctx(rsa, pri, &from_buf, &num_bytes); +- if (ret <= 0) { +- ret = UADK_E_FAIL; +- goto free_sess; +- } +- +- if (flen != num_bytes) { +- ret = UADK_E_FAIL; +- goto free_buf; +- } +- +- ret = rsa_fill_prikey(rsa, rsa_sess, pri, from_buf, to); +- if (!ret) { +- ret = UADK_E_FAIL; +- goto free_buf; +- } +- +- memcpy(rsa_sess->req.src, from, rsa_sess->req.src_bytes); +- +- ret = rsa_do_crypto(rsa_sess); +- if (!ret || rsa_sess->req.status) { +- ret = UADK_DO_SOFT; +- goto free_buf; +- } +- +- ret = crypt_trans_bn(rsa_sess, from_buf, num_bytes); +- if (!ret) +- goto free_buf; +- +- ret = check_rsa_pridec_padding(to, num_bytes, from_buf, flen, padding); +- if (!ret) +- ret = UADK_E_FAIL; +- +-free_buf: +- rsa_free_pri_bn_ctx(&from_buf); +-free_sess: +- rsa_free_eng_session(rsa_sess); +-free_pkey: +- rsa_pkey_param_free(NULL, &pri); +- return ret; +-} +- +-static int sign_trans_bn(struct uadk_rsa_sess *rsa_sess, unsigned char *from_buf, +- struct rsa_prikey_param *pri, int padding, +- unsigned char *to, int num_bytes) +-{ +- BIGNUM *res = NULL; +- BIGNUM *sign_bn; +- BIGNUM *to_bn; +- int ret; +- +- sign_bn = BN_bin2bn((const unsigned char *)rsa_sess->req.dst, +- rsa_sess->req.dst_bytes, NULL); +- if (!sign_bn) +- return UADK_E_FAIL; +- +- to_bn = BN_bin2bn(from_buf, num_bytes, NULL); +- if (!to_bn) { +- ret = UADK_E_FAIL; +- goto free_sign_bn; +- } +- +- ret = rsa_get_sign_res(padding, to_bn, pri->n, sign_bn, &res); +- if (!ret) +- goto free_to_bn; +- +- ret = BN_bn2binpad(res, to, num_bytes); +- +-free_to_bn: +- BN_free(to_bn); +-free_sign_bn: +- BN_free(sign_bn); +- return ret; ++ return UADK_P_SUCCESS; + } + +-static int uadk_prov_rsa_private_sign(int flen, const unsigned char *from, +- unsigned char *to, RSA *rsa, int padding) ++void rsa_free_pri_bn_ctx(unsigned char *from_buf) + { +- struct rsa_prikey_param *prik = NULL; +- struct uadk_rsa_sess *rsa_sess; +- unsigned char *from_buf = NULL; +- int ret, num_bytes; +- +- ret = check_rsa_input_para(flen, from, to, rsa); +- if (ret != UADK_E_SUCCESS) +- return ret; +- +- ret = rsa_pkey_param_alloc(NULL, &prik); +- if (ret == -ENOMEM) +- return UADK_E_FAIL; +- +- prik->is_crt = check_rsa_is_crt(rsa); +- +- rsa_sess = rsa_get_eng_session(rsa, uadk_rsa_bits(rsa), prik->is_crt); +- if (!rsa_sess) { +- ret = UADK_DO_SOFT; +- goto free_pkey; +- } +- +- ret = rsa_create_pri_bn_ctx(rsa, prik, &from_buf, &num_bytes); +- if (ret <= 0 || flen > num_bytes) { +- ret = UADK_E_FAIL; +- goto free_sess; +- } +- +- ret = add_rsa_prienc_padding(flen, from, from_buf, num_bytes, padding); +- if (!ret) { +- ret = UADK_E_FAIL; +- goto free_buf; +- } +- +- ret = rsa_fill_prikey(rsa, rsa_sess, prik, from_buf, to); +- if (!ret) { +- ret = UADK_E_FAIL; +- goto free_buf; +- } +- +- ret = rsa_do_crypto(rsa_sess); +- if (!ret || rsa_sess->req.status) { +- ret = UADK_DO_SOFT; +- goto free_buf; +- } +- +- ret = sign_trans_bn(rsa_sess, from_buf, prik, padding, to, num_bytes); +- +-free_buf: +- rsa_free_pri_bn_ctx(&from_buf); +-free_sess: +- rsa_free_eng_session(rsa_sess); +-free_pkey: +- rsa_pkey_param_free(NULL, &prik); +- return ret; +-} +- +-static int verify_trans_bn(struct uadk_rsa_sess *rsa_sess, unsigned char *from_buf, +- int num_bytes, struct rsa_pubkey_param *pub, +- int padding, int *len) +-{ +- BIGNUM *verify_bn; +- int ret; +- +- verify_bn = BN_bin2bn((const unsigned char *)rsa_sess->req.dst, +- rsa_sess->req.dst_bytes, NULL); +- if (!verify_bn) +- return UADK_E_FAIL; +- +- ret = rsa_get_verify_res(padding, pub->n, verify_bn); +- if (!ret) +- goto verify_end; +- +- *len = BN_bn2binpad(verify_bn, from_buf, num_bytes); +- if (*len == 0) +- ret = UADK_E_FAIL; +- +-verify_end: +- BN_free(verify_bn); +- return ret; +-} +- +-static int uadk_prov_rsa_public_verify(int flen, const unsigned char *from, +- unsigned char *to, RSA *rsa, int padding) +-{ +- struct rsa_pubkey_param *pub = NULL; +- int num_bytes, is_crt, len, ret; +- struct uadk_rsa_sess *rsa_sess; +- unsigned char *from_buf = NULL; +- +- ret = check_rsa_input_para(flen, from, to, rsa); +- if (ret != UADK_E_SUCCESS) +- return ret; +- +- ret = rsa_pkey_param_alloc(&pub, NULL); +- if (ret == -ENOMEM) +- return UADK_E_FAIL; +- +- is_crt = check_rsa_is_crt(rsa); +- +- rsa_sess = rsa_get_eng_session(rsa, uadk_rsa_bits(rsa), is_crt); +- if (!rsa_sess) { +- ret = UADK_DO_SOFT; +- goto free_pkey; +- } +- +- ret = rsa_create_pub_bn_ctx(rsa, pub, &from_buf, &num_bytes); +- if (ret <= 0 || flen > num_bytes) { +- ret = UADK_E_FAIL; +- goto free_sess; +- } +- +- ret = rsa_fill_pubkey(pub, rsa_sess, from_buf, to); +- if (!ret) { +- ret = UADK_E_FAIL; +- goto free_buff; +- } +- +- memcpy(rsa_sess->req.src, from, rsa_sess->req.src_bytes); +- ret = rsa_do_crypto(rsa_sess); +- if (!ret || rsa_sess->req.status) { +- ret = UADK_DO_SOFT; +- goto free_buff; +- } +- +- ret = verify_trans_bn(rsa_sess, from_buf, num_bytes, pub, padding, &len); +- if (!ret) +- goto free_buff; +- +- ret = check_rsa_pubdec_padding(to, num_bytes, from_buf, len, padding); +- +-free_buff: +- rsa_free_pub_bn_ctx(&from_buf); +-free_sess: +- rsa_free_eng_session(rsa_sess); +-free_pkey: +- rsa_pkey_param_free(&pub, NULL); +- return ret; +-} +- +-static int uadk_rsa_asym_init(void *vprsactx, void *vrsa, +- const OSSL_PARAM params[], int operation) +-{ +- PROV_RSA_ASYM_CTX *priv = (PROV_RSA_ASYM_CTX *)vprsactx; +- +- priv->rsa = vrsa; +- priv->operation = operation; +- +- switch (uadk_rsa_test_flags(priv->rsa, RSA_FLAG_TYPE_MASK)) { +- case RSA_FLAG_TYPE_RSA: +- priv->pad_mode = RSA_PKCS1_PADDING; +- break; +- case RSA_FLAG_TYPE_RSASSAPSS: +- priv->pad_mode = RSA_PKCS1_PSS_PADDING; +- break; +- default: +- UADK_ERR("rsa asym operation not supported this keytype!\n"); +- return UADK_E_FAIL; +- } +- +- if (uadk_prov_rsa_init()) +- priv->soft = 1; +- +- return UADK_E_SUCCESS; +-} +- +-static int uadk_rsa_init(void *vprsactx, void *vrsa, +- const OSSL_PARAM params[], int operation) +-{ +- PROV_RSA_SIG_CTX *ctx = (PROV_RSA_SIG_CTX *)vprsactx; +- +- if (ctx == NULL || vrsa == NULL) +- return UADK_E_FAIL; +- +- ctx->rsa = vrsa; +- ctx->operation = operation; +- +- /* Maximum for sign, auto for verify */ +- ctx->saltlen = RSA_PSS_SALTLEN_AUTO; +- ctx->min_saltlen = -1; +- +- switch (uadk_rsa_test_flags(ctx->rsa, RSA_FLAG_TYPE_MASK)) { +- case RSA_FLAG_TYPE_RSA: +- ctx->pad_mode = RSA_PKCS1_PADDING; +- break; +- case RSA_FLAG_TYPE_RSASSAPSS: +- ctx->pad_mode = RSA_PKCS1_PSS_PADDING; +- break; +- default: +- UADK_ERR("rsa init operation not supported this keytype!\n"); +- return UADK_E_FAIL; +- } +- +- if (uadk_prov_rsa_init()) +- ctx->soft = 1; +- +- return UADK_E_SUCCESS; +-} +- +-static int uadk_signature_rsa_verify_recover_init(void *vprsactx, void *vrsa, +- const OSSL_PARAM params[]) +-{ +- return UADK_E_SUCCESS; +-} +- +-static int uadk_signature_rsa_verify_recover(void *vprsactx, unsigned char *rout, +- size_t *routlen, size_t routsize, +- const unsigned char *sig, size_t siglen) +-{ +- return UADK_E_SUCCESS; +-} +- +-static int uadk_signature_rsa_verify_init(void *vprsactx, void *vrsa, +- const OSSL_PARAM params[]) +-{ +- return uadk_rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY); +-} +- +-static int uadk_rsa_sw_verify(void *vprsactx, const unsigned char *sig, +- size_t siglen, const unsigned char *tbs, +- size_t tbslen) +-{ +- if (!enable_sw_offload || !get_default_rsa_signature().verify) +- return UADK_E_FAIL; +- +- UADK_INFO("switch to openssl software calculation in verifaction.\n"); +- +- return get_default_rsa_signature().verify(vprsactx, sig, siglen, tbs, tbslen); +-} +- +-static int uadk_signature_rsa_verify(void *vprsactx, const unsigned char *sig, +- size_t siglen, const unsigned char *tbs, +- size_t tbslen) +-{ +- PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; +- size_t rslen = 0; +- +- if (priv->soft) { +- rslen = UADK_DO_SOFT; +- goto exe_soft; +- } +- +- /* todo call public_verify */ +- if (priv->md != NULL) { +- /* todo */ +- } else { +- if (!setup_tbuf(priv)) +- return UADK_E_FAIL; +- rslen = uadk_prov_rsa_public_verify(siglen, sig, priv->tbuf, +- priv->rsa, priv->pad_mode); +- if (rslen == UADK_DO_SOFT || rslen == UADK_E_FAIL) +- goto exe_soft; +- } +- +- if ((rslen != tbslen) || memcmp(tbs, priv->tbuf, rslen)) +- return UADK_E_FAIL; +- +- return UADK_E_SUCCESS; +- +-exe_soft: +- if (rslen == UADK_DO_SOFT) +- return uadk_rsa_sw_verify(vprsactx, sig, siglen, tbs, tbslen); +- return UADK_E_FAIL; +-} +- +-static int uadk_rsa_sw_sign(void *vprsactx, unsigned char *sig, +- size_t *siglen, size_t sigsize, +- const unsigned char *tbs, size_t tbslen) +-{ +- if (!enable_sw_offload || !get_default_rsa_signature().sign) +- return UADK_E_FAIL; +- +- UADK_INFO("switch to openssl software calculation in rsa signature.\n"); +- return get_default_rsa_signature().sign(vprsactx, sig, siglen, sigsize, tbs, tbslen); +-} +- +-static int uadk_signature_rsa_sign(void *vprsactx, unsigned char *sig, +- size_t *siglen, size_t sigsize, +- const unsigned char *tbs, size_t tbslen) +-{ +- PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; +- size_t rsasize = uadk_rsa_size(priv->rsa); +- int ret; +- +- if (priv->soft) { +- ret = UADK_DO_SOFT; +- goto exe_soft; +- } +- +- if (sig == NULL) { +- *siglen = rsasize; +- return UADK_E_SUCCESS; +- } +- +- if (sigsize < rsasize) { +- UADK_ERR("invalid signature size is %zu, should be at least %zu!\n", +- sigsize, rsasize); +- return UADK_E_FAIL; +- } +- +- ret = uadk_prov_rsa_private_sign(tbslen, tbs, sig, priv->rsa, priv->pad_mode); +- if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) +- goto exe_soft; +- +- if (ret < 0) +- return ret; +- +- *siglen = ret; +- +- return UADK_E_SUCCESS; +-exe_soft: +- if (ret == UADK_DO_SOFT) +- return uadk_rsa_sw_sign(vprsactx, sig, siglen, sigsize, tbs, tbslen); +- return UADK_E_FAIL; +-} +- +-static int uadk_signature_rsa_sign_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[]) +-{ +- return uadk_rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_SIGN); +-} +- +-static void *uadk_signature_rsa_newctx(void *provctx, const char *propq) +-{ +- PROV_RSA_SIG_CTX *priv = OPENSSL_zalloc(sizeof(PROV_RSA_SIG_CTX)); +- char *propq_copy = NULL; +- +- if (priv == NULL) +- goto err; +- +- if (propq != NULL) { +- propq_copy = OPENSSL_strdup(propq); +- if (propq_copy == NULL) +- goto err; +- } +- +- priv->libctx = prov_libctx_of(provctx); +- priv->flag_allow_md = 1; +- priv->propq = propq_copy; +- return priv; +- +-err: +- OPENSSL_free(priv); +- UADK_ERR("%s failed.\n", __func__); +- return NULL; +-} +- +-static void uadk_signature_rsa_freectx(void *vprsactx) +-{ +- PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; +- +- if (priv == NULL) +- return; +- +- free_tbuf(priv); +- OPENSSL_clear_free(priv, sizeof(*priv)); +-} +- +-static void *uadk_asym_cipher_rsa_newctx(void *provctx) +-{ +- PROV_RSA_ASYM_CTX *priv = NULL; +- +- priv = OPENSSL_zalloc(sizeof(*priv)); +- if (priv == NULL) +- return NULL; +- priv->libctx = prov_libctx_of(provctx); +- +- return priv; +-} +- +-static void uadk_asym_cipher_rsa_freectx(void *vprsactx) +-{ +- PROV_RSA_ASYM_CTX *priv = (PROV_RSA_ASYM_CTX *)vprsactx; +- +- if (priv == NULL) +- return; +- +- OPENSSL_free(priv); +-} +- +-static int uadk_signature_rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) +-{ +- PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; +- +- if (priv == NULL) +- return UADK_E_FAIL; +- if (params == NULL) +- return UADK_E_SUCCESS; +- +- /* todo */ +- +- return UADK_E_SUCCESS; +-} +- +-static const OSSL_PARAM settable_ctx_params[] = { +- OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), +- OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0), +- OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0), +- OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), +- OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0), +- OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), +- OSSL_PARAM_END +-}; +- +-static const OSSL_PARAM settable_ctx_params_no_digest[] = { +- OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0), +- OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), +- OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0), +- OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), +- OSSL_PARAM_END +-}; +- +-static const OSSL_PARAM *uadk_signature_rsa_settable_ctx_params(void *vprsactx, +- void *provctx) +-{ +- PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; +- +- if (priv != NULL && !priv->flag_allow_md) +- return settable_ctx_params_no_digest; +- +- return settable_ctx_params; +-} +- +-static int uadk_rsa_check_padding(const PROV_RSA_SIG_CTX *prsactx, +- const char *mdname, const char *mgf1_mdname, +- int mdnid) +-{ +- switch (prsactx->pad_mode) { +- case RSA_NO_PADDING: +- UADK_ERR("invalid rsa padding mode.\n"); +- return UADK_E_FAIL; +- case RSA_X931_PADDING: +- if (RSA_X931_hash_id(mdnid) == -1) { +- UADK_ERR("invalid rsa x931 digest.\n"); +- return UADK_E_FAIL; +- } +- break; +- case RSA_PKCS1_PSS_PADDING: +- if (prsactx->min_saltlen != -1) { +- if ((mdname != NULL && !EVP_MD_is_a(prsactx->md, mdname)) || +- (mgf1_mdname != NULL && +- !EVP_MD_is_a(prsactx->mgf1_md, mgf1_mdname))) { +- UADK_ERR("rsa digest is not allowed.\n"); +- return UADK_E_FAIL; +- } +- } +- break; +- default: +- break; +- } +- +- return UADK_E_SUCCESS; +-} +- +-static int uadk_digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t it_len) +-{ +- size_t i; +- +- if (md == NULL) +- return NID_undef; +- +- for (i = 0; i < it_len; i++) +- if (EVP_MD_is_a(md, it[i].ptr)) +- return (int)it[i].id; +- return NID_undef; +-} +- +-static int uadk_digest_get_approved_nid(const EVP_MD *md) +-{ +- static const OSSL_ITEM name_to_nid[] = { +- { NID_sha1, OSSL_DIGEST_NAME_SHA1 }, +- { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 }, +- { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 }, +- { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 }, +- { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 }, +- { NID_sha512_224, OSSL_DIGEST_NAME_SHA2_512_224 }, +- { NID_sha512_256, OSSL_DIGEST_NAME_SHA2_512_256 }, +- { NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 }, +- { NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 }, +- { NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 }, +- { NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 }, +- }; +- +- return uadk_digest_md_to_nid(md, name_to_nid, OSSL_NELEM(name_to_nid)); +-} +- +-static int uadk_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md, +- int sha1_allowed) +-{ +- return uadk_digest_get_approved_nid(md); +-} +- +-static int uadk_rsa_setup_md(PROV_RSA_SIG_CTX *ctx, const char *mdname, +- const char *mdprops) +-{ +- size_t mdname_len; +- +- if (mdprops == NULL) +- mdprops = ctx->propq; +- +- if (mdname != NULL) { +- EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); +- int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); +- int md_nid = uadk_digest_rsa_sign_get_md_nid(ctx->libctx, md, +- sha1_allowed); +- mdname_len = strlen(mdname); +- if (md == NULL || md_nid <= 0 || +- !uadk_rsa_check_padding(ctx, mdname, NULL, md_nid) || +- mdname_len >= sizeof(ctx->mdname)) { +- if (md == NULL) +- UADK_ERR("invalid rsa name %s could not be fetched.\n", mdname); +- if (md_nid <= 0) +- UADK_ERR("digest name is not allowed digest = %s.\n", mdname); +- if (mdname_len >= sizeof(ctx->mdname)) +- UADK_ERR("invalid name %s exceeds name buffer length.\n", mdname); +- if (md) +- EVP_MD_free(md); +- return 0; +- } +- +- if (!ctx->mgf1_md_set) { +- if (!EVP_MD_up_ref(md)) { +- if (md) +- EVP_MD_free(md); +- return 0; +- } +- if (ctx->mgf1_md) +- EVP_MD_free(ctx->mgf1_md); +- ctx->mgf1_md = md; +- ctx->mgf1_mdnid = md_nid; +- OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname)); +- } +- +- if (ctx->mdctx) { +- EVP_MD_CTX_free(ctx->mdctx); +- ctx->mdctx = NULL; +- } +- +- if (ctx->md) +- EVP_MD_free(ctx->md); +- +- ctx->md = md; +- ctx->mdnid = md_nid; +- OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname)); +- } +- +- return 1; +-} +- +-static int uadk_signature_rsa_digest_signverify_init(void *vprsactx, const char *mdname, +- void *vrsa, const OSSL_PARAM params[], +- int operation) +-{ +- PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; +- +- if (!uadk_rsa_init(vprsactx, vrsa, params, operation)) +- return 0; +- +- if (mdname != NULL && +- (mdname[0] == '\0' || OPENSSL_strcasecmp(priv->mdname, mdname) != 0) && +- !uadk_rsa_setup_md(priv, mdname, priv->propq)) +- return 0; +- +- priv->flag_allow_md = 0; +- +- if (priv->mdctx == NULL) { +- priv->mdctx = EVP_MD_CTX_new(); +- if (priv->mdctx == NULL) +- goto error; +- } +- +- if (!EVP_DigestInit_ex2(priv->mdctx, priv->md, params)) +- goto error; +- +- return 1; +- +-error: +- if (priv->mdctx) { +- EVP_MD_CTX_free(priv->mdctx); +- priv->mdctx = NULL; +- } +- +- return 0; +-} +- +-static int uadk_signature_rsa_digest_sign_init(void *vprsactx, const char *mdname, +- void *vrsa, const OSSL_PARAM params[]) +-{ +- return uadk_signature_rsa_digest_signverify_init(vprsactx, mdname, vrsa, +- params, EVP_PKEY_OP_SIGN); +-} +- +-static int uadk_signature_rsa_digest_sign_update(void *vprsactx, +- const unsigned char *data, +- size_t datalen) +-{ +- PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; +- +- if (priv == NULL || priv->mdctx == NULL) +- return UADK_E_FAIL; +- +- return EVP_DigestUpdate(priv->mdctx, data, datalen); +-} +- +-#define ASN1_SEQUENCE_RSA 0x30 +-#define ASN1_OCTET_STRING_ 0x04 +-#define ASN1_NULL 0x05 +-#define ASN1_OID 0x06 +- +-/* SHA OIDs are of the form: (2 16 840 1 101 3 4 2 |n|) */ +-#define ENCODE_DIGESTINFO_SHA(name, n, sz) \ +-static const unsigned char digestinfo_##name##_der[] = { \ +- ASN1_SEQUENCE_RSA, 0x11 + sz, \ +- ASN1_SEQUENCE_RSA, 0x0d, \ +- ASN1_OID, 0x09, 2 * 40 + 16, 0x86, 0x48, 1, 101, 3, 4, 2, n, \ +- ASN1_NULL, 0x00, \ +- ASN1_OCTET_STRING_, sz \ +-} +- +-/* SHA-1 (1 3 14 3 2 26) */ +-static const unsigned char digestinfo_sha1_der[] = { +- ASN1_SEQUENCE_RSA, 0x0d + SHA_DIGEST_LENGTH, +- ASN1_SEQUENCE_RSA, 0x09, +- ASN1_OID, 0x05, 1 * 40 + 3, 14, 3, 2, 26, +- ASN1_NULL, 0x00, +- ASN1_OCTET_STRING_, SHA_DIGEST_LENGTH +-}; +- +-ENCODE_DIGESTINFO_SHA(sha256, 0x01, SHA256_DIGEST_LENGTH); +-ENCODE_DIGESTINFO_SHA(sha384, 0x02, SHA384_DIGEST_LENGTH); +-ENCODE_DIGESTINFO_SHA(sha512, 0x03, SHA512_DIGEST_LENGTH); +-ENCODE_DIGESTINFO_SHA(sha224, 0x04, SHA224_DIGEST_LENGTH); +-ENCODE_DIGESTINFO_SHA(sha512_224, 0x05, SHA224_DIGEST_LENGTH); +-ENCODE_DIGESTINFO_SHA(sha512_256, 0x06, SHA256_DIGEST_LENGTH); +-ENCODE_DIGESTINFO_SHA(sha3_224, 0x07, SHA224_DIGEST_LENGTH); +-ENCODE_DIGESTINFO_SHA(sha3_256, 0x08, SHA256_DIGEST_LENGTH); +-ENCODE_DIGESTINFO_SHA(sha3_384, 0x09, SHA384_DIGEST_LENGTH); +-ENCODE_DIGESTINFO_SHA(sha3_512, 0x0a, SHA512_DIGEST_LENGTH); +- +-#define MD_CASE(name) \ +- case NID_##name: \ +- *len = sizeof(digestinfo_##name##_der); \ +- return digestinfo_##name##_der +- +- +-static const unsigned char *uadk_rsa_digestinfo_encoding(int md_nid, size_t *len) +-{ +- switch (md_nid) { +- MD_CASE(sha1); +- MD_CASE(sha224); +- MD_CASE(sha256); +- MD_CASE(sha384); +- MD_CASE(sha512); +- MD_CASE(sha512_224); +- MD_CASE(sha512_256); +- MD_CASE(sha3_224); +- MD_CASE(sha3_256); +- MD_CASE(sha3_384); +- MD_CASE(sha3_512); +- default: +- return NULL; +- } +-} +- +-/* Size of an SSL signature: MD5+SHA1 */ +-#define SSL_SIG_LENGTH 36 +- +-/* +- * Encodes a DigestInfo prefix of hash |type| and digest |m|, as +- * described in EMSA-PKCS1-v1_5-ENCODE, RFC 3447 section 9.2 step 2. This +- * encodes the DigestInfo (T and tLen) but does not add the padding. +- * +- * On success, it returns one and sets |*out| to a newly allocated buffer +- * containing the result and |*out_len| to its length. The caller must free +- * |*out| with OPENSSL_free(). Otherwise, it returns zero. +- */ +-static int encode_pkcs1(unsigned char **out, size_t *out_len, int type, +- const unsigned char *m, size_t m_len) +-{ +- size_t di_prefix_len, dig_info_len; +- const unsigned char *di_prefix; +- unsigned char *dig_info; +- +- if (type == NID_undef) { +- UADK_ERR("invalid: rsa unknown algorithm type.\n"); +- return 0; +- } +- di_prefix = uadk_rsa_digestinfo_encoding(type, &di_prefix_len); +- if (di_prefix == NULL) { +- UADK_ERR("invalid: rsa di prefix is NULL.\n"); +- return 0; +- } +- dig_info_len = di_prefix_len + m_len; +- dig_info = OPENSSL_malloc(dig_info_len); +- if (dig_info == NULL) { +- UADK_ERR("failed to malloc dig info.\n"); +- return 0; +- } +- memcpy(dig_info, di_prefix, di_prefix_len); +- memcpy(dig_info + di_prefix_len, m, m_len); +- +- *out = dig_info; +- *out_len = dig_info_len; +- return 1; +-} +- +-static int uadk_signature_rsa_digest_sign_final(void *vprsactx, unsigned char *sig, +- size_t *siglen, size_t sigsize) +-{ +- PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; +- unsigned char digest[EVP_MAX_MD_SIZE]; +- const unsigned char *encoded = NULL; +- unsigned char *tmps = NULL; +- unsigned int dlen = 0; +- size_t encoded_len = 0; +- size_t rsasize; +- int ret; +- +- if (priv == NULL) +- return UADK_E_FAIL; +- +- if (priv->mdctx == NULL) +- return UADK_E_FAIL; +- +- rsasize = uadk_rsa_size(priv->rsa); +- +- /* +- * If sig is NULL then we're just finding out the sig size. Other fields +- * are ignored. Defer to rsa_sign. +- */ +- if (sig != NULL) { +- /* +- * The digests used here are all known (see rsa_get_md_nid()), so they +- * should not exceed the internal buffer size of EVP_MAX_MD_SIZE. +- */ +- if (!EVP_DigestFinal_ex(priv->mdctx, digest, &dlen)) +- return UADK_E_FAIL; +- } else { +- *siglen = rsasize; +- return 1; +- } +- +- priv->flag_allow_md = 1; +- +- if (priv->pad_mode == RSA_PKCS1_PADDING) { +- /* Compute the encoded digest. */ +- if (priv->mdnid == NID_md5_sha1) { +- /* +- * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and +- * earlier. It has no DigestInfo wrapper but otherwise is +- * RSASSA-PKCS1-v1_5. +- */ +- if (dlen != SSL_SIG_LENGTH) { +- UADK_ERR("invalid: rsa message length.\n"); +- return 0; +- } +- encoded_len = SSL_SIG_LENGTH; +- encoded = digest; +- } else { +- if (!encode_pkcs1(&tmps, &encoded_len, priv->mdnid, digest, dlen)) +- goto err; +- encoded = tmps; +- } +- } else { +- UADK_ERR("This padding mode is not supported\n"); +- return UADK_E_FAIL; +- } +- +- ret = uadk_prov_rsa_private_sign(encoded_len, encoded, sig, priv->rsa, priv->pad_mode); +- if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) +- goto err; +- +- OPENSSL_clear_free(tmps, encoded_len); +- return ret; +-err: +- OPENSSL_clear_free(tmps, encoded_len); +- if (ret == UADK_DO_SOFT) +- return uadk_rsa_sw_sign(vprsactx, sig, siglen, sigsize, digest, dlen); +- +- return UADK_E_FAIL; +-} +- +-static int uadk_signature_rsa_digest_verify_init(void *vprsactx, const char *mdname, +- void *vrsa, const OSSL_PARAM params[]) +-{ +- return uadk_signature_rsa_digest_signverify_init(vprsactx, mdname, vrsa, +- params, EVP_PKEY_OP_VERIFY); +-} +- +-static int uadk_signature_rsa_digest_verify_update(void *vprsactx, const unsigned char *data, +- size_t datalen) +-{ +- PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; +- +- if (priv == NULL || priv->mdctx == NULL) +- return 0; +- +- return EVP_DigestUpdate(priv->mdctx, data, datalen); +-} +- +-static int uadk_signature_rsa_digest_verify_final(void *vprsactx, const unsigned char *sig, +- size_t siglen) +-{ +- PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; +- unsigned char *decrypt_buf = NULL, *encoded = NULL; +- size_t decrypt_len, encoded_len = 0; +- unsigned char digest[EVP_MAX_MD_SIZE]; +- unsigned int dlen = 0; +- int ret = UADK_E_FAIL; +- +- if (priv == NULL) +- return UADK_E_FAIL; +- priv->flag_allow_md = 1; +- if (priv->mdctx == NULL) +- return UADK_E_FAIL; +- +- /* +- * The digests used here are all known (see rsa_get_md_nid()), so they +- * should not exceed the internal buffer size of EVP_MAX_MD_SIZE. +- */ +- if (!EVP_DigestFinal_ex(priv->mdctx, digest, &dlen)) +- return UADK_E_FAIL; +- +- if (priv->pad_mode == RSA_PKCS1_PADDING) { +- if (siglen != (size_t)uadk_rsa_size(priv->rsa)) { +- UADK_ERR("invalid: rsa signature length.\n"); +- return UADK_E_FAIL; +- } +- +- /* Recover the encoded digest. */ +- decrypt_buf = OPENSSL_malloc(siglen); +- if (decrypt_buf == NULL) { +- UADK_ERR("failed to malloc decrypt buf.\n"); +- return UADK_E_FAIL; +- } +- +- ret = uadk_prov_rsa_public_verify(siglen, sig, decrypt_buf, +- priv->rsa, priv->pad_mode); +- if (ret <= 0) +- goto err; +- decrypt_len = ret; +- +- if (priv->mdnid == NID_md5_sha1) { +- /* +- * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and +- * earlier. It has no DigestInfo wrapper but otherwise is +- * RSASSA-PKCS1-v1_5. +- */ +- if (decrypt_len != SSL_SIG_LENGTH) { +- UADK_ERR("invalid: rsa decrypt length.\n"); +- ret = UADK_E_FAIL; +- goto err; +- } +- +- if (siglen != SSL_SIG_LENGTH) { +- UADK_ERR("invalid: rsa siglen.\n"); +- ret = UADK_E_FAIL; +- goto err; +- } +- +- if (memcmp(decrypt_buf, digest, SSL_SIG_LENGTH) != 0) { +- UADK_ERR("failed to memcmp decrypt buf and digest.\n"); +- ret = UADK_E_FAIL; +- goto err; +- } +- } else { +- /* Construct the encoded digest and ensure it matches. */ +- if (!encode_pkcs1(&encoded, &encoded_len, priv->mdnid, digest, dlen)) { +- ret = UADK_E_FAIL; +- goto err; +- } +- +- if (encoded_len != decrypt_len +- || memcmp(encoded, decrypt_buf, encoded_len) != 0) { +- UADK_ERR("failed to memcmp decrypt buf and encoded.\n"); +- ret = UADK_E_FAIL; +- goto err; +- } +- } +- ret = UADK_E_SUCCESS; +- } else { +- UADK_ERR("This padding mode is not supported\n"); +- return UADK_E_FAIL; +- } +- +-err: +- if (encoded) +- OPENSSL_clear_free(encoded, encoded_len); +- if (decrypt_buf) +- OPENSSL_clear_free(decrypt_buf, siglen); +- +- if (ret == UADK_DO_SOFT) +- return uadk_rsa_sw_verify(vprsactx, sig, siglen, digest, dlen); +- +- return ret; +-} +- +-static void *uadk_signature_rsa_dupctx(void *vprsactx) +-{ +- if (!get_default_rsa_signature().dupctx) +- return NULL; +- +- return get_default_rsa_signature().dupctx(vprsactx); +-} +- +-static int uadk_signature_rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) +-{ +- if (!get_default_rsa_signature().get_ctx_params) +- return UADK_E_FAIL; +- +- return get_default_rsa_signature().get_ctx_params(vprsactx, params); +-} +- +-static const OSSL_PARAM *uadk_signature_rsa_gettable_ctx_md_params(void *vprsactx) +-{ +- if (!get_default_rsa_signature().gettable_ctx_md_params) +- return NULL; +- +- return get_default_rsa_signature().gettable_ctx_md_params(vprsactx); +-} +- +-static int uadk_signature_rsa_set_ctx_md_params(void *vprsactx, const OSSL_PARAM params[]) +-{ +- if (!get_default_rsa_signature().set_ctx_md_params) +- return UADK_E_FAIL; +- +- return get_default_rsa_signature().set_ctx_md_params(vprsactx, params); +-} +- +-static const OSSL_PARAM *uadk_signature_rsa_settable_ctx_md_params(void *vprsactx) +-{ +- if (!get_default_rsa_signature().settable_ctx_md_params) +- return NULL; +- +- return get_default_rsa_signature().settable_ctx_md_params(vprsactx); +-} +- +-static const OSSL_PARAM *uadk_signature_rsa_gettable_ctx_params(ossl_unused void *vprsactx, +- ossl_unused void *provctx) +-{ +- if (!get_default_rsa_signature().gettable_ctx_params) +- return NULL; +- +- return get_default_rsa_signature().gettable_ctx_params(vprsactx, provctx); +-} +- +-static int uadk_signature_rsa_get_ctx_md_params(void *vprsactx, OSSL_PARAM *params) +-{ +- if (!get_default_rsa_signature().get_ctx_md_params) +- return UADK_E_FAIL; +- +- return get_default_rsa_signature().get_ctx_md_params(vprsactx, params); +-} +- +-static int uadk_asym_cipher_rsa_encrypt_init(void *vprsactx, void *vrsa, +- const OSSL_PARAM params[]) +-{ +- return uadk_rsa_asym_init(vprsactx, vrsa, params, EVP_PKEY_OP_ENCRYPT); +-} +- +-static int uadk_asym_cipher_rsa_decrypt_init(void *vprsactx, void *vrsa, +- const OSSL_PARAM params[]) +-{ +- return uadk_rsa_asym_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECRYPT); +-} +- +-static int uadk_rsa_sw_encrypt(void *vprsactx, unsigned char *out, +- size_t *outlen, size_t outsize, +- const unsigned char *in, size_t inlen) +-{ +- if (!enable_sw_offload || !get_default_rsa_asym_cipher().encrypt) +- return UADK_E_FAIL; +- +- UADK_INFO("switch to openssl software calculation in rsa encryption.\n"); +- +- return get_default_rsa_asym_cipher().encrypt(vprsactx, out, outlen, outsize, in, inlen); +-} +- +-static int uadk_asym_cipher_rsa_encrypt(void *vprsactx, unsigned char *out, +- size_t *outlen, size_t outsize, +- const unsigned char *in, size_t inlen) +-{ +- PROV_RSA_ASYM_CTX *priv = (PROV_RSA_ASYM_CTX *)vprsactx; +- size_t len; +- int ret; +- +- if (priv->soft) { +- ret = UADK_DO_SOFT; +- goto exe_soft; +- } +- +- if (out == NULL) { +- len = uadk_rsa_size(priv->rsa); +- if (len == 0) { +- UADK_ERR("invalid: rsa encrypt size.\n"); +- return UADK_E_FAIL; +- } +- *outlen = len; +- return UADK_E_SUCCESS; +- } +- +- ret = uadk_prov_rsa_public_encrypt(inlen, in, out, priv->rsa, priv->pad_mode); +- if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) +- goto exe_soft; +- +- *outlen = ret; +- +- return UADK_E_SUCCESS; +-exe_soft: +- if (ret == UADK_DO_SOFT) +- return uadk_rsa_sw_encrypt(vprsactx, out, outlen, outsize, in, inlen); +- return UADK_E_FAIL; +-} +- +-static int uadk_rsa_sw_decrypt(void *vprsactx, unsigned char *out, +- size_t *outlen, size_t outsize, +- const unsigned char *in, size_t inlen) +-{ +- if (!enable_sw_offload || !get_default_rsa_asym_cipher().decrypt) +- return UADK_E_FAIL; +- +- UADK_INFO("switch to openssl software calculation in rsa decryption.\n"); +- return get_default_rsa_asym_cipher().decrypt(vprsactx, out, outlen, outsize, in, inlen); +-} +- +-static int uadk_asym_cipher_rsa_decrypt(void *vprsactx, unsigned char *out, +- size_t *outlen, size_t outsize, +- const unsigned char *in, size_t inlen) +-{ +- PROV_RSA_ASYM_CTX *priv = (PROV_RSA_ASYM_CTX *)vprsactx; +- size_t len = uadk_rsa_size(priv->rsa); +- int ret; +- +- if (priv->soft) { +- ret = UADK_DO_SOFT; +- goto exe_soft; +- } +- +- if (out == NULL) { +- if (len == 0) { +- UADK_ERR("invalid: rsa decrypt size.\n"); +- return UADK_E_FAIL; +- } +- *outlen = len; +- return UADK_E_SUCCESS; +- } +- +- if (outsize < len) { +- UADK_ERR("invalid: rsa decrypt outsize is too small.\n"); +- return UADK_E_FAIL; +- } +- +- ret = uadk_prov_rsa_private_decrypt(inlen, in, out, priv->rsa, priv->pad_mode); +- if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) +- goto exe_soft; +- +- *outlen = ret; +- +- return UADK_E_SUCCESS; +-exe_soft: +- if (ret == UADK_DO_SOFT) +- return uadk_rsa_sw_decrypt(vprsactx, out, outlen, outsize, in, inlen); +- return UADK_E_FAIL; +-} +- +-static int uadk_asym_cipher_rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) +-{ +- if (!get_default_rsa_asym_cipher().get_ctx_params) +- return UADK_E_FAIL; +- +- return get_default_rsa_asym_cipher().get_ctx_params(vprsactx, params); +-} +- +-static const OSSL_PARAM *uadk_asym_cipher_rsa_gettable_ctx_params(void *vprsactx, +- void *provctx) +-{ +- if (!get_default_rsa_asym_cipher().gettable_ctx_params) +- return NULL; +- +- return get_default_rsa_asym_cipher().gettable_ctx_params(vprsactx, provctx); +-} +- +-static int uadk_asym_cipher_rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) +-{ +- if (!get_default_rsa_asym_cipher().set_ctx_params) +- return UADK_E_FAIL; +- +- return get_default_rsa_asym_cipher().set_ctx_params(vprsactx, params); +-} +- +-static const OSSL_PARAM *uadk_asym_cipher_rsa_settable_ctx_params(void *vprsactx, +- void *provctx) +-{ +- if (!get_default_rsa_asym_cipher().settable_ctx_params) +- return NULL; +- +- return get_default_rsa_asym_cipher().settable_ctx_params(vprsactx, provctx); +-} +- +-static const char *uadk_keymgmt_rsa_query_operation_name(int operation_id) +-{ +- if (!get_default_rsa_keymgmt().query_operation_name) +- return NULL; +- +- return get_default_rsa_keymgmt().query_operation_name(operation_id); +-} +- +-static void *uadk_keymgmt_rsa_new(void *provctx) +-{ +- if (!get_default_rsa_keymgmt().new_fun) +- return NULL; +- +- return get_default_rsa_keymgmt().new_fun(provctx); +-} +- +-static void uadk_keymgmt_rsa_free(void *keydata) +-{ +- if (!get_default_rsa_keymgmt().free) +- return; +- +- get_default_rsa_keymgmt().free(keydata); +-} +- +-static int uadk_keymgmt_rsa_has(const void *keydata, int selection) +-{ +- if (!get_default_rsa_keymgmt().has) +- return UADK_E_FAIL; +- +- return get_default_rsa_keymgmt().has(keydata, selection); +-} +- +-static int uadk_keymgmt_rsa_import(void *keydata, int selection, const OSSL_PARAM params[]) +-{ +- if (!get_default_rsa_keymgmt().import) +- return UADK_E_FAIL; +- +- return get_default_rsa_keymgmt().import(keydata, selection, params); +-} +- +-static const OSSL_PARAM *uadk_keymgmt_rsa_import_types(int selection) +-{ +- if (!get_default_rsa_keymgmt().import_types) +- return NULL; +- +- return get_default_rsa_keymgmt().import_types(selection); +-} +- +-static void *uadk_keymgmt_rsa_gen_init(void *provctx, int selection, +- const OSSL_PARAM params[]) +-{ +- if (!get_default_rsa_keymgmt().gen_init) +- return NULL; +- +- return get_default_rsa_keymgmt().gen_init(provctx, selection, params); +-} +- +-static int uadk_keymgmt_rsa_gen_set_params(void *genctx, const OSSL_PARAM params[]) +-{ +- if (!get_default_rsa_keymgmt().gen_set_params) +- return UADK_E_FAIL; +- +- return get_default_rsa_keymgmt().gen_set_params(genctx, params); +-} +- +-static int uadk_keymgmt_rsa_gen_set_template(void *genctx, void *templates) +-{ +- if (!get_default_rsa_keymgmt().gen_set_template) { +- UADK_ERR("failed to get keymgmt gen_set_template function\n"); +- return UADK_P_FAIL; +- } +- +- return get_default_rsa_keymgmt().gen_set_template(genctx, templates); +-} +- +-static const OSSL_PARAM *uadk_keymgmt_rsa_gen_settable_params(ossl_unused void *genctx, +- ossl_unused void *provctx) +-{ +- if (!get_default_rsa_keymgmt().gen_settable_params) +- return NULL; +- +- return get_default_rsa_keymgmt().gen_settable_params(genctx, provctx); +-} +- +-static int rsa_gencb(int p, int n, BN_GENCB *cb) +-{ +- struct rsa_gen_ctx *gctx = BN_GENCB_get_arg(cb); +- OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; +- +- params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p); +- params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n); +- return gctx->cb(params, gctx->cbarg); +-} +- +-static RSA *ossl_rsa_new_with_ctx(OSSL_LIB_CTX *libctx) +-{ +- RSA *ret = OPENSSL_zalloc(sizeof(*ret)); +- +- if (ret == NULL) { +- UADK_ERR("failed to zalloc rsa ret\n"); +- return NULL; +- } +- +- ret->references = 1; +- ret->lock = CRYPTO_THREAD_lock_new(); +- if (ret->lock == NULL) { +- UADK_ERR("failed to malloc thread lock\n"); +- OPENSSL_free(ret); +- return NULL; +- } +- +- ret->libctx = libctx; +- ret->meth = RSA_get_default_method(); +- +- return ret; +-} +- +-static void *uadk_rsa_sw_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) +-{ +- if (!enable_sw_offload || !get_default_rsa_keymgmt().gen) +- return NULL; +- +- UADK_INFO("switch to openssl software calculation in rsa key generation.\n"); +- return get_default_rsa_keymgmt().gen(genctx, osslcb, cbarg); +-} +- +-static void *uadk_keymgmt_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) +-{ +- struct rsa_gen_ctx *gctx = genctx; +- BN_GENCB *gencb; +- RSA *rsa; +- int ret; +- +- if (gctx == NULL) +- return NULL; +- +- ret = uadk_prov_rsa_init(); +- if (ret) { +- ret = UADK_DO_SOFT; +- goto exe_soft; +- } +- +- rsa = ossl_rsa_new_with_ctx(gctx->libctx); +- if (rsa == NULL) +- return NULL; +- +- gctx->cb = osslcb; +- gctx->cbarg = cbarg; +- gencb = BN_GENCB_new(); +- if (gencb != NULL) +- BN_GENCB_set(gencb, rsa_gencb, genctx); +- +- ret = uadk_prov_rsa_keygen(rsa, (int)gctx->nbits, gctx->pub_exp, gencb); +- if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) { +- BN_GENCB_free(gencb); +- uadk_keymgmt_rsa_free(rsa); +- goto exe_soft; +- } +- +- uadk_rsa_clear_flags(rsa, RSA_FLAG_TYPE_MASK); +- uadk_rsa_set_flags(rsa, gctx->rsa_type); +- BN_GENCB_free(gencb); +- +- return rsa; +- +-exe_soft: +- if (ret == UADK_DO_SOFT) +- return uadk_rsa_sw_gen(genctx, osslcb, cbarg); +- return NULL; +-} +- +-static void uadk_keymgmt_rsa_gen_cleanup(void *genctx) +-{ +- if (!get_default_rsa_keymgmt().gen_cleanup) +- return; +- +- get_default_rsa_keymgmt().gen_cleanup(genctx); +-} +- +-static void *uadk_keymgmt_rsa_load(const void *reference, size_t reference_sz) +-{ +- if (!get_default_rsa_keymgmt().load) +- return NULL; +- +- return get_default_rsa_keymgmt().load(reference, reference_sz); +-} +- +-static int uadk_keymgmt_rsa_get_params(void *key, OSSL_PARAM params[]) +-{ +- if (!get_default_rsa_keymgmt().get_params) +- return UADK_E_FAIL; +- +- return get_default_rsa_keymgmt().get_params(key, params); +-} +- +-static const OSSL_PARAM *uadk_keymgmt_rsa_gettable_params(void *provctx) +-{ +- if (!get_default_rsa_keymgmt().gettable_params) +- return NULL; +- +- return get_default_rsa_keymgmt().gettable_params(provctx); +-} +- +-static int uadk_keymgmt_rsa_set_params(void *key, const OSSL_PARAM params[]) +-{ +- if (!get_default_rsa_keymgmt().set_params) { +- UADK_ERR("failed to get keymgmt set_params function\n"); +- return UADK_P_FAIL; +- } +- +- return get_default_rsa_keymgmt().set_params(key, params); +-} +- +-static const OSSL_PARAM *uadk_keymgmt_rsa_settable_params(ossl_unused void *provctx) +-{ +- if (!get_default_rsa_keymgmt().settable_params) { +- UADK_ERR("failed to get keymgmt settable_params function\n"); +- return NULL; +- } +- +- return get_default_rsa_keymgmt().settable_params(provctx); +-} +- +-static int uadk_keymgmt_rsa_match(const void *keydata1, const void *keydata2, int selection) +-{ +- if (!get_default_rsa_keymgmt().match) +- return UADK_E_FAIL; +- +- return get_default_rsa_keymgmt().match(keydata1, keydata2, selection); +-} +- +-static int uadk_keymgmt_rsa_validate(const void *keydata, int selection, int checktype) +-{ +- if (!get_default_rsa_keymgmt().validate) +- return UADK_E_FAIL; +- +- return get_default_rsa_keymgmt().validate(keydata, selection, checktype); +-} +- +-static int uadk_keymgmt_rsa_export(void *keydata, int selection, +- OSSL_CALLBACK *param_callback, void *cbarg) +-{ +- if (!get_default_rsa_keymgmt().export_fun) +- return UADK_E_FAIL; +- +- return get_default_rsa_keymgmt().export_fun(keydata, selection, param_callback, cbarg); +-} +- +-static const OSSL_PARAM *uadk_keymgmt_rsa_export_types(int selection) +-{ +- if (!get_default_rsa_keymgmt().export_types) +- return NULL; +- +- return get_default_rsa_keymgmt().export_types(selection); +-} +- +-static void *uadk_keymgmt_rsa_dup(const void *keydata_from, int selection) +-{ +- if (!get_default_rsa_keymgmt().dup) +- return NULL; +- +- return get_default_rsa_keymgmt().dup(keydata_from, selection); +-} +- +-static void *uadk_asym_cipher_rsa_dupctx(void *vprsactx) +-{ +- if (!get_default_rsa_asym_cipher().dupctx) +- return NULL; +- return get_default_rsa_asym_cipher().dupctx(vprsactx); +-} +- +-void uadk_prov_destroy_rsa(void) +-{ +- pthread_mutex_lock(&rsa_mutex); +- if (g_rsa_prov.pid == getpid()) { +- wd_rsa_uninit2(); +- g_rsa_prov.pid = 0; +- } +- pthread_mutex_unlock(&rsa_mutex); ++ OPENSSL_free(from_buf); + } +diff --git a/src/uadk_prov_rsa.h b/src/uadk_prov_rsa.h +new file mode 100644 +index 0000000..279f64a +--- /dev/null ++++ b/src/uadk_prov_rsa.h +@@ -0,0 +1,179 @@ ++/* SPDX-License-Identifier: Apache-2.0 */ ++/* ++ * Copyright 2023-2024 Huawei Technologies Co.,Ltd. All rights reserved. ++ * Copyright 2023-2024 Linaro ltd. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ */ ++#ifndef UADK_PROV_RSA_H ++#define UADK_PROV_RSA_H ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "uadk_async.h" ++#include "uadk_prov.h" ++#include "uadk_prov_pkey.h" ++#include "uadk_utils.h" ++ ++#define BN_ERR (-1) ++#define BN_REDO (-2) ++#define CHECK_PADDING_FAIL (-1) ++#define BIT_BYTES_SHIFT 3 ++ ++struct bignum_st { ++ BN_ULONG *d; ++ int top; ++ int dmax; ++ int neg; ++ int flags; ++}; ++ ++struct rsa_prov { ++ int pid; ++}; ++ ++struct rsa_pss_params_30_st { ++ int hash_algorithm_nid; ++ struct { ++ int algorithm_nid; /* Currently always NID_mgf1 */ ++ int hash_algorithm_nid; ++ } mask_gen; ++ int salt_len; ++ int trailer_field; ++}; ++ ++struct rsa_st { ++ /* ++ * #legacy ++ * The first field is used to pickup errors where this is passed ++ * instead of an EVP_PKEY. It is always zero. ++ * THIS MUST REMAIN THE FIRST FIELD. ++ */ ++ int dummy_zero; ++ ++ OSSL_LIB_CTX *libctx; ++ int32_t version; ++ const RSA_METHOD *meth; ++ /* functional reference if 'meth' is ENGINE-provided */ ++ ENGINE *engine; ++ BIGNUM *n; ++ BIGNUM *e; ++ BIGNUM *d; ++ BIGNUM *p; ++ BIGNUM *q; ++ BIGNUM *dmp1; ++ BIGNUM *dmq1; ++ BIGNUM *iqmp; ++ ++ /* ++ * If a PSS only key this contains the parameter restrictions. ++ * There are two structures for the same thing, used in different cases. ++ */ ++ /* This is used uniquely by OpenSSL provider implementations. */ ++ struct rsa_pss_params_30_st pss_params; ++ ++ /* This is used uniquely by rsa_ameth.c and rsa_pmeth.c. */ ++ RSA_PSS_PARAMS *pss; ++ /* for multi-prime RSA, defined in RFC 8017 */ ++ STACK_OF(RSA_PRIME_INFO) * prime_infos; ++ /* Be careful using this if the RSA structure is shared */ ++ CRYPTO_EX_DATA ex_data; ++ ++ int references; ++ int flags; ++ /* Used to cache montgomery values */ ++ BN_MONT_CTX *_method_mod_n; ++ BN_MONT_CTX *_method_mod_p; ++ BN_MONT_CTX *_method_mod_q; ++ BN_BLINDING *blinding; ++ BN_BLINDING *mt_blinding; ++ CRYPTO_RWLOCK *lock; ++ ++ int dirty_cnt; ++}; ++ ++struct rsa_prikey_param { ++ const BIGNUM *n; ++ const BIGNUM *e; ++ const BIGNUM *d; ++ const BIGNUM *p; ++ const BIGNUM *q; ++ const BIGNUM *dmp1; ++ const BIGNUM *dmq1; ++ const BIGNUM *iqmp; ++ int is_crt; ++}; ++ ++struct rsa_pubkey_param { ++ const BIGNUM *e; ++ const BIGNUM *n; ++}; ++ ++struct uadk_rsa_sess { ++ handle_t sess; ++ struct wd_rsa_sess_setup setup; ++ struct wd_rsa_req req; ++ RSA *alg; ++ int is_pubkey_ready; ++ int is_prikey_ready; ++ int key_size; ++}; ++ ++enum { ++ INVALID = 0, ++ PUB_ENC, ++ PUB_DEC, ++ PRI_ENC, ++ PRI_DEC, ++ MAX_CODE, ++}; ++ ++int uadk_rsa_test_flags(const RSA *r, int flags); ++int check_rsa_is_crt(RSA *rsa); ++int rsa_fill_prikey(RSA *rsa, struct uadk_rsa_sess *rsa_sess, ++ struct rsa_prikey_param *pri, ++ unsigned char *in_buf, unsigned char *to); ++int rsa_fill_pubkey(struct rsa_pubkey_param *pubkey_param, ++ struct uadk_rsa_sess *rsa_sess, ++ unsigned char *in_buf, unsigned char *to); ++int uadk_prov_rsa_init(void); ++void rsa_free_eng_session(struct uadk_rsa_sess *rsa_sess); ++struct uadk_rsa_sess *rsa_get_eng_session(RSA *rsa, unsigned int bits, ++ int is_crt); ++int rsa_do_crypto(struct uadk_rsa_sess *rsa_sess); ++int uadk_rsa_bits(const RSA *r); ++int uadk_rsa_size(const RSA *r); ++int rsa_check_bit_useful(const int bits, int flen); ++int check_rsa_input_para(const int flen, const unsigned char *from, ++ unsigned char *to, RSA *rsa); ++int rsa_pkey_param_alloc(struct rsa_pubkey_param **pub, ++ struct rsa_prikey_param **pri); ++void rsa_pkey_param_free(struct rsa_pubkey_param **pub, ++ struct rsa_prikey_param **pri); ++int rsa_create_pub_bn_ctx(RSA *rsa, struct rsa_pubkey_param *pub, ++ unsigned char **from_buf, int *num_bytes); ++void rsa_free_pub_bn_ctx(unsigned char *from_buf); ++int rsa_create_pri_bn_ctx(RSA *rsa, struct rsa_prikey_param *pri, ++ unsigned char **from_buf, int *num_bytes); ++void rsa_free_pri_bn_ctx(unsigned char *from_buf); ++ ++#endif +diff --git a/src/uadk_prov_rsa_enc.c b/src/uadk_prov_rsa_enc.c +new file mode 100644 +index 0000000..3c4fe0e +--- /dev/null ++++ b/src/uadk_prov_rsa_enc.c +@@ -0,0 +1,463 @@ ++// SPDX-License-Identifier: Apache-2.0 ++/* ++ * Copyright 2023-2024 Huawei Technologies Co.,Ltd. All rights reserved. ++ * Copyright 2023-2024 Linaro ltd. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ */ ++#include "uadk_prov_rsa.h" ++ ++UADK_PKEY_ASYM_CIPHER_DESCR(rsa, RSA); ++ ++struct PROV_RSA_ASYM_CTX { ++ OSSL_LIB_CTX *libctx; ++ RSA *rsa; ++ int pad_mode; ++ int operation; ++ /* OAEP message digest */ ++ EVP_MD *oaep_md; ++ /* message digest for MGF1 */ ++ EVP_MD *mgf1_md; ++ /* OAEP label */ ++ unsigned char *oaep_label; ++ size_t oaep_labellen; ++ /* TLS padding */ ++ unsigned int client_version; ++ unsigned int alt_version; ++ ++ unsigned int soft : 1; ++}; ++ ++static pthread_mutex_t asym_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++static UADK_PKEY_ASYM_CIPHER get_default_rsa_asym_cipher(void) ++{ ++ static UADK_PKEY_ASYM_CIPHER s_asym_cipher; ++ static int initilazed; ++ ++ pthread_mutex_lock(&asym_mutex); ++ if (!initilazed) { ++ UADK_PKEY_ASYM_CIPHER *asym_cipher = ++ (UADK_PKEY_ASYM_CIPHER *)EVP_ASYM_CIPHER_fetch(NULL, "RSA", ++ "provider=default"); ++ ++ if (asym_cipher) { ++ s_asym_cipher = *asym_cipher; ++ EVP_ASYM_CIPHER_free((EVP_ASYM_CIPHER *)asym_cipher); ++ initilazed = 1; ++ } else { ++ UADK_ERR("failed to EVP_ASYM_CIPHER_fetch default RSA provider\n"); ++ } ++ } ++ pthread_mutex_unlock(&asym_mutex); ++ return s_asym_cipher; ++} ++ ++static int add_rsa_pubenc_padding(int flen, const unsigned char *from, ++ unsigned char *buf, int num, int padding) ++{ ++ int ret; ++ ++ switch (padding) { ++ case RSA_PKCS1_PADDING: ++ ret = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); ++ if (!ret) ++ UADK_ERR("RSA_PKCS1_PADDING err.\n"); ++ break; ++ case RSA_PKCS1_OAEP_PADDING: ++ ret = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); ++ if (!ret) ++ UADK_ERR("RSA_PKCS1_OAEP_PADDING err.\n"); ++ break; ++ default: ++ ret = UADK_P_FAIL; ++ } ++ ++ return ret; ++} ++ ++static int check_rsa_pridec_padding(unsigned char *to, int num, ++ const unsigned char *buf, int flen, ++ int padding) ++{ ++ int ret; ++ ++ switch (padding) { ++ case RSA_PKCS1_PADDING: ++ ret = RSA_padding_check_PKCS1_type_2(to, num, buf, flen, num); ++ if (ret == CHECK_PADDING_FAIL) ++ UADK_ERR("RSA_PKCS1_PADDING err.\n"); ++ break; ++ case RSA_PKCS1_OAEP_PADDING: ++ ret = RSA_padding_check_PKCS1_OAEP(to, num, buf, flen, num, ++ NULL, 0); ++ if (ret == CHECK_PADDING_FAIL) ++ UADK_ERR("RSA_PKCS1_OAEP_PADDING err.\n"); ++ break; ++ default: ++ ret = UADK_P_FAIL; ++ } ++ ++ if (ret == CHECK_PADDING_FAIL) ++ ret = UADK_P_FAIL; ++ ++ return ret; ++} ++ ++static int crypt_trans_bn(struct uadk_rsa_sess *rsa_sess, unsigned char *buf, int num_bytes) ++{ ++ BIGNUM *bn; ++ int ret; ++ ++ bn = BN_bin2bn((const unsigned char *)rsa_sess->req.dst, ++ rsa_sess->req.dst_bytes, NULL); ++ if (!bn) ++ return UADK_P_FAIL; ++ ++ ret = BN_bn2binpad(bn, buf, num_bytes); ++ if (ret == BN_ERR) ++ ret = UADK_P_FAIL; ++ ++ BN_free(bn); ++ ++ return ret; ++} ++ ++static int uadk_prov_rsa_public_encrypt(int flen, const unsigned char *from, ++ unsigned char *to, RSA *rsa, int padding) ++{ ++ struct rsa_pubkey_param *pub_enc = NULL; ++ struct uadk_rsa_sess *rsa_sess; ++ unsigned char *from_buf = NULL; ++ int num_bytes, is_crt, ret; ++ ++ ret = check_rsa_input_para(flen, from, to, rsa); ++ if (ret != UADK_P_SUCCESS) ++ return ret; ++ ++ ret = rsa_pkey_param_alloc(&pub_enc, NULL); ++ if (ret == -ENOMEM) ++ return UADK_P_FAIL; ++ ++ is_crt = check_rsa_is_crt(rsa); ++ ++ rsa_sess = rsa_get_eng_session(rsa, uadk_rsa_bits(rsa), is_crt); ++ if (!rsa_sess) { ++ ret = UADK_DO_SOFT; ++ goto free_pkey; ++ } ++ ++ ret = rsa_create_pub_bn_ctx(rsa, pub_enc, &from_buf, &num_bytes); ++ if (ret <= 0) { ++ ret = UADK_P_FAIL; ++ goto free_sess; ++ } ++ ++ ret = add_rsa_pubenc_padding(flen, from, from_buf, num_bytes, padding); ++ if (!ret) { ++ ret = UADK_P_FAIL; ++ goto free_buf; ++ } ++ ++ ret = rsa_fill_pubkey(pub_enc, rsa_sess, from_buf, to); ++ if (!ret) { ++ ret = UADK_P_FAIL; ++ goto free_buf; ++ } ++ ++ ret = rsa_do_crypto(rsa_sess); ++ if (!ret || rsa_sess->req.status) { ++ ret = UADK_DO_SOFT; ++ goto free_buf; ++ } ++ ++ ret = crypt_trans_bn(rsa_sess, to, num_bytes); ++ ++free_buf: ++ rsa_free_pub_bn_ctx(from_buf); ++free_sess: ++ rsa_free_eng_session(rsa_sess); ++free_pkey: ++ rsa_pkey_param_free(&pub_enc, NULL); ++ return ret; ++} ++ ++static int uadk_prov_rsa_private_decrypt(int flen, const unsigned char *from, ++ unsigned char *to, RSA *rsa, int padding) ++{ ++ struct rsa_prikey_param *pri = NULL; ++ unsigned char *from_buf = NULL; ++ struct uadk_rsa_sess *rsa_sess; ++ int num_bytes, ret; ++ ++ ret = check_rsa_input_para(flen, from, to, rsa); ++ if (ret != UADK_P_SUCCESS) ++ return ret; ++ ++ ret = rsa_pkey_param_alloc(NULL, &pri); ++ if (ret == -ENOMEM) ++ return UADK_P_FAIL; ++ ++ pri->is_crt = check_rsa_is_crt(rsa); ++ ++ rsa_sess = rsa_get_eng_session(rsa, uadk_rsa_bits(rsa), pri->is_crt); ++ if (!rsa_sess) { ++ ret = UADK_DO_SOFT; ++ goto free_pkey; ++ } ++ ++ ret = rsa_create_pri_bn_ctx(rsa, pri, &from_buf, &num_bytes); ++ if (ret <= 0) { ++ ret = UADK_P_FAIL; ++ goto free_sess; ++ } ++ ++ if (flen != num_bytes) { ++ ret = UADK_P_FAIL; ++ goto free_buf; ++ } ++ ++ ret = rsa_fill_prikey(rsa, rsa_sess, pri, from_buf, to); ++ if (!ret) { ++ ret = UADK_P_FAIL; ++ goto free_buf; ++ } ++ ++ memcpy(rsa_sess->req.src, from, rsa_sess->req.src_bytes); ++ ++ ret = rsa_do_crypto(rsa_sess); ++ if (!ret || rsa_sess->req.status) { ++ ret = UADK_DO_SOFT; ++ goto free_buf; ++ } ++ ++ ret = crypt_trans_bn(rsa_sess, from_buf, num_bytes); ++ if (!ret) ++ goto free_buf; ++ ++ ret = check_rsa_pridec_padding(to, num_bytes, from_buf, flen, padding); ++ if (!ret) ++ ret = UADK_P_FAIL; ++ ++free_buf: ++ rsa_free_pri_bn_ctx(from_buf); ++free_sess: ++ rsa_free_eng_session(rsa_sess); ++free_pkey: ++ rsa_pkey_param_free(NULL, &pri); ++ return ret; ++} ++ ++static int uadk_rsa_asym_init(void *vprsactx, void *vrsa, ++ const OSSL_PARAM params[], int operation) ++{ ++ struct PROV_RSA_ASYM_CTX *priv = (struct PROV_RSA_ASYM_CTX *)vprsactx; ++ ++ if (priv == NULL || vrsa == NULL) ++ return UADK_P_FAIL; ++ ++ priv->rsa = vrsa; ++ priv->operation = operation; ++ ++ switch (uadk_rsa_test_flags(priv->rsa, RSA_FLAG_TYPE_MASK)) { ++ case RSA_FLAG_TYPE_RSA: ++ priv->pad_mode = RSA_PKCS1_PADDING; ++ break; ++ case RSA_FLAG_TYPE_RSASSAPSS: ++ priv->pad_mode = RSA_PKCS1_PSS_PADDING; ++ break; ++ default: ++ UADK_ERR("rsa asym operation not supported this keytype!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ if (uadk_prov_rsa_init()) ++ priv->soft = 1; ++ ++ return UADK_P_SUCCESS; ++} ++ ++static void *uadk_asym_cipher_rsa_newctx(void *provctx) ++{ ++ struct PROV_RSA_ASYM_CTX *priv = NULL; ++ ++ priv = OPENSSL_zalloc(sizeof(*priv)); ++ if (priv == NULL) ++ return NULL; ++ priv->libctx = prov_libctx_of(provctx); ++ ++ return priv; ++} ++ ++static void uadk_asym_cipher_rsa_freectx(void *vprsactx) ++{ ++ struct PROV_RSA_ASYM_CTX *priv = (struct PROV_RSA_ASYM_CTX *)vprsactx; ++ ++ if (priv == NULL) ++ return; ++ ++ OPENSSL_free(priv); ++} ++ ++static void *uadk_asym_cipher_rsa_dupctx(void *vprsactx) ++{ ++ if (!get_default_rsa_asym_cipher().dupctx) ++ return NULL; ++ return get_default_rsa_asym_cipher().dupctx(vprsactx); ++} ++ ++static int uadk_asym_cipher_rsa_encrypt_init(void *vprsactx, void *vrsa, ++ const OSSL_PARAM params[]) ++{ ++ return uadk_rsa_asym_init(vprsactx, vrsa, params, EVP_PKEY_OP_ENCRYPT); ++} ++ ++static int uadk_asym_cipher_rsa_decrypt_init(void *vprsactx, void *vrsa, ++ const OSSL_PARAM params[]) ++{ ++ return uadk_rsa_asym_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECRYPT); ++} ++ ++static int uadk_rsa_sw_encrypt(void *vprsactx, unsigned char *out, ++ size_t *outlen, size_t outsize, ++ const unsigned char *in, size_t inlen) ++{ ++ if (!enable_sw_offload || !get_default_rsa_asym_cipher().encrypt) ++ return UADK_P_FAIL; ++ ++ UADK_INFO("switch to openssl software calculation in rsa encryption.\n"); ++ ++ return get_default_rsa_asym_cipher().encrypt(vprsactx, out, outlen, outsize, in, inlen); ++} ++ ++static int uadk_asym_cipher_rsa_encrypt(void *vprsactx, unsigned char *out, ++ size_t *outlen, size_t outsize, ++ const unsigned char *in, size_t inlen) ++{ ++ struct PROV_RSA_ASYM_CTX *priv = (struct PROV_RSA_ASYM_CTX *)vprsactx; ++ size_t len; ++ int ret; ++ ++ if (!priv || priv->soft) { ++ ret = UADK_DO_SOFT; ++ goto exe_soft; ++ } ++ ++ if (out == NULL) { ++ len = uadk_rsa_size(priv->rsa); ++ if (len == 0) { ++ UADK_ERR("invalid: rsa encrypt size.\n"); ++ return UADK_P_FAIL; ++ } ++ *outlen = len; ++ return UADK_P_SUCCESS; ++ } ++ ++ ret = uadk_prov_rsa_public_encrypt(inlen, in, out, priv->rsa, priv->pad_mode); ++ if (ret == UADK_DO_SOFT || ret == UADK_P_FAIL) ++ goto exe_soft; ++ ++ *outlen = ret; ++ ++ return UADK_P_SUCCESS; ++exe_soft: ++ if (ret == UADK_DO_SOFT) ++ return uadk_rsa_sw_encrypt(vprsactx, out, outlen, outsize, in, inlen); ++ return UADK_P_FAIL; ++} ++ ++static int uadk_rsa_sw_decrypt(void *vprsactx, unsigned char *out, ++ size_t *outlen, size_t outsize, ++ const unsigned char *in, size_t inlen) ++{ ++ if (!enable_sw_offload || !get_default_rsa_asym_cipher().decrypt) ++ return UADK_P_FAIL; ++ ++ UADK_INFO("switch to openssl software calculation in rsa decryption.\n"); ++ return get_default_rsa_asym_cipher().decrypt(vprsactx, out, outlen, outsize, in, inlen); ++} ++ ++static int uadk_asym_cipher_rsa_decrypt(void *vprsactx, unsigned char *out, ++ size_t *outlen, size_t outsize, ++ const unsigned char *in, size_t inlen) ++{ ++ struct PROV_RSA_ASYM_CTX *priv = (struct PROV_RSA_ASYM_CTX *)vprsactx; ++ size_t len = uadk_rsa_size(priv->rsa); ++ int ret; ++ ++ if (priv->soft) { ++ ret = UADK_DO_SOFT; ++ goto exe_soft; ++ } ++ ++ if (out == NULL) { ++ if (len == 0) { ++ UADK_ERR("invalid: rsa decrypt size.\n"); ++ return UADK_P_FAIL; ++ } ++ *outlen = len; ++ return UADK_P_SUCCESS; ++ } ++ ++ if (outsize < len) { ++ UADK_ERR("invalid: rsa decrypt outsize is too small.\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_rsa_private_decrypt(inlen, in, out, priv->rsa, priv->pad_mode); ++ if (ret == UADK_DO_SOFT || ret == UADK_P_FAIL) ++ goto exe_soft; ++ ++ *outlen = ret; ++ ++ return UADK_P_SUCCESS; ++exe_soft: ++ if (ret == UADK_DO_SOFT) ++ return uadk_rsa_sw_decrypt(vprsactx, out, outlen, outsize, in, inlen); ++ return UADK_P_FAIL; ++} ++ ++static int uadk_asym_cipher_rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) ++{ ++ if (!get_default_rsa_asym_cipher().get_ctx_params) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_asym_cipher().get_ctx_params(vprsactx, params); ++} ++ ++static const OSSL_PARAM *uadk_asym_cipher_rsa_gettable_ctx_params(void *vprsactx, ++ void *provctx) ++{ ++ if (!get_default_rsa_asym_cipher().gettable_ctx_params) ++ return NULL; ++ ++ return get_default_rsa_asym_cipher().gettable_ctx_params(vprsactx, provctx); ++} ++ ++static int uadk_asym_cipher_rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) ++{ ++ if (!get_default_rsa_asym_cipher().set_ctx_params) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_asym_cipher().set_ctx_params(vprsactx, params); ++} ++ ++static const OSSL_PARAM *uadk_asym_cipher_rsa_settable_ctx_params(void *vprsactx, ++ void *provctx) ++{ ++ if (!get_default_rsa_asym_cipher().settable_ctx_params) ++ return NULL; ++ ++ return get_default_rsa_asym_cipher().settable_ctx_params(vprsactx, provctx); ++} +diff --git a/src/uadk_prov_rsa_kmgmt.c b/src/uadk_prov_rsa_kmgmt.c +new file mode 100644 +index 0000000..fc03276 +--- /dev/null ++++ b/src/uadk_prov_rsa_kmgmt.c +@@ -0,0 +1,975 @@ ++// SPDX-License-Identifier: Apache-2.0 ++/* ++ * Copyright 2023-2024 Huawei Technologies Co.,Ltd. All rights reserved. ++ * Copyright 2023-2024 Linaro ltd. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ */ ++#include "uadk_prov_rsa.h" ++ ++#define PRIME_CHECK_BIT_NUM 4 ++#define RSA_MAX_PRIME_NUM 2 ++#define PRIME_RETRY_COUNT 4 ++#define GET_ERR_FINISH 0 ++#define GENCB_RETRY 3 ++#define GENCB_NEXT 2 ++#define BN_CONTINUE 1 ++#define BN_VALID 0 ++ ++UADK_PKEY_KEYMGMT_DESCR(rsa, RSA); ++ ++struct rsa_keypair { ++ struct wd_rsa_pubkey *pubkey; ++ struct wd_rsa_prikey *prikey; ++}; ++ ++struct rsa_keygen_param { ++ struct wd_dtb *wd_e; ++ struct wd_dtb *wd_p; ++ struct wd_dtb *wd_q; ++}; ++ ++struct rsa_keygen_param_bn { ++ BIGNUM *e; ++ BIGNUM *p; ++ BIGNUM *q; ++}; ++ ++struct rsa_prime_param { ++ BIGNUM *r1; ++ BIGNUM *r2; ++ BIGNUM *rsa_p; ++ BIGNUM *rsa_q; ++ BIGNUM *prime; ++ int retries; ++}; ++ ++struct rsa_gen_ctx { ++ OSSL_LIB_CTX *libctx; ++ const char *propq; ++ ++ int rsa_type; ++ ++ size_t nbits; ++ BIGNUM *pub_exp; ++ size_t primes; ++ ++ /* For PSS */ ++ struct rsa_pss_params_30_st pss_params; ++ int pss_defaults_set; ++ ++ /* For generation callback */ ++ OSSL_CALLBACK *cb; ++ void *cbarg; ++}; ++ ++static void uadk_rsa_clear_flags(RSA *r, int flags) ++{ ++ r->flags &= ~flags; ++} ++ ++static void uadk_rsa_set_flags(RSA *r, int flags) ++{ ++ r->flags |= flags; ++} ++ ++static int uadk_rsa_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) ++{ ++ /* ++ * If the fields n and e in r are NULL, the corresponding input ++ * parameters MUST be non-NULL for n and e. d may be ++ * left NULL (in case only the public key is used). ++ */ ++ if ((r->n == NULL && n == NULL) ++ || (r->e == NULL && e == NULL)) ++ return UADK_P_FAIL; ++ ++ if (n != NULL) { ++ BN_free(r->n); ++ r->n = n; ++ } ++ if (e != NULL) { ++ BN_free(r->e); ++ r->e = e; ++ } ++ if (d != NULL) { ++ BN_clear_free(r->d); ++ r->d = d; ++ BN_set_flags(r->d, BN_FLG_CONSTTIME); ++ } ++ r->dirty_cnt++; ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_rsa_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) ++{ ++ /* ++ * If the fields p and q in r are NULL, the corresponding input ++ * parameters MUST be non-NULL. ++ */ ++ if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL)) ++ return UADK_P_FAIL; ++ ++ if (p != NULL) { ++ BN_clear_free(r->p); ++ r->p = p; ++ BN_set_flags(r->p, BN_FLG_CONSTTIME); ++ } ++ ++ if (q != NULL) { ++ BN_clear_free(r->q); ++ r->q = q; ++ BN_set_flags(r->q, BN_FLG_CONSTTIME); ++ } ++ ++ r->dirty_cnt++; ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_rsa_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) ++{ ++ /* ++ * If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input ++ * parameters MUST be non-NULL. ++ */ ++ if ((r->dmp1 == NULL && dmp1 == NULL) ++ || (r->dmq1 == NULL && dmq1 == NULL) ++ || (r->iqmp == NULL && iqmp == NULL)) ++ return UADK_P_FAIL; ++ ++ if (dmp1 != NULL) { ++ BN_clear_free(r->dmp1); ++ r->dmp1 = dmp1; ++ BN_set_flags(r->dmp1, BN_FLG_CONSTTIME); ++ } ++ ++ if (dmq1 != NULL) { ++ BN_clear_free(r->dmq1); ++ r->dmq1 = dmq1; ++ BN_set_flags(r->dmq1, BN_FLG_CONSTTIME); ++ } ++ ++ if (iqmp != NULL) { ++ BN_clear_free(r->iqmp); ++ r->iqmp = iqmp; ++ BN_set_flags(r->iqmp, BN_FLG_CONSTTIME); ++ } ++ ++ r->dirty_cnt++; ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int rsa_prime_mul_res(int num, struct rsa_prime_param *param, ++ BN_CTX *ctx, BN_GENCB *cb) ++{ ++ if (num == 1) { ++ if (!BN_mul(param->r1, param->rsa_p, param->rsa_q, ctx)) ++ return BN_ERR; ++ } else { ++ if (!BN_GENCB_call(cb, GENCB_RETRY, num)) ++ return BN_ERR; ++ return BN_CONTINUE; ++ } ++ ++ return BN_VALID; ++} ++ ++static int check_rsa_prime_sufficient(int *num, const int *bitsr, ++ int *bitse, int * const n, ++ struct rsa_prime_param *param, ++ BN_CTX *ctx, BN_GENCB *cb) ++{ ++ BN_ULONG bitst; ++ int ret; ++ ++ ret = rsa_prime_mul_res(*num, param, ctx, cb); ++ if (ret) ++ return ret; ++ ++ /* ++ * If |r1|, product of factors so far, is not as long as expected ++ * (by checking the first 4 bits are less than 0x9 or greater than ++ * 0xF). If so, re-generate the last prime. ++ * ++ * NOTE: This actually can't happen in two-prime case, because of ++ * the way factors are generated. ++ * ++ * Besides, another consideration is, for multi-prime case, even the ++ * length modulus is as long as expected, the modulus could start at ++ * 0x8, which could be utilized to distinguish a multi-prime private ++ * key by using the modulus in a certificate. This is also covered ++ * by checking the length should not be less than 0x9. ++ */ ++ if (!BN_rshift(param->r2, param->r1, *bitse - PRIME_CHECK_BIT_NUM)) ++ return BN_ERR; ++ ++ bitst = BN_get_word(param->r2); ++ if (bitst > 0xF || bitst < 0x9) { ++ /* ++ * For keys with more than 4 primes, we attempt longer factor ++ * to meet length requirement. ++ * Otherwise, we just re-generate the prime with the same length. ++ * This strategy has the following goals: ++ * 1. 1024-bit factors are efficient when using 3072 and 4096-bit key ++ * 2. stay the same logic with normal 2-prime key ++ */ ++ if (*num < RSA_MAX_PRIME_NUM) ++ *bitse -= bitsr[*num]; ++ else ++ return BN_ERR; ++ ++ ret = BN_GENCB_call(cb, GENCB_NEXT, (*n)++); ++ if (!ret) ++ return BN_ERR; ++ ++ if (param->retries == PRIME_RETRY_COUNT) { ++ param->retries = 0; ++ *bitse = 0; ++ *num = -1; ++ return BN_CONTINUE; ++ } ++ param->retries++; ++ return BN_REDO; ++ } ++ ++ ret = BN_GENCB_call(cb, GENCB_RETRY, *num); ++ if (!ret) ++ return BN_ERR; ++ param->retries = 0; ++ ++ return BN_VALID; ++} ++ ++static void rsa_set_primes(int num, BIGNUM *rsa_p, BIGNUM *rsa_q, ++ BIGNUM **prime) ++{ ++ if (num == 0) ++ *prime = rsa_p; ++ else ++ *prime = rsa_q; ++ ++ /* Set BN_FLG_CONSTTIME to prime exponent */ ++ BN_set_flags(*prime, BN_FLG_CONSTTIME); ++} ++ ++static int check_rsa_prime_equal(int num, BIGNUM *rsa_p, BIGNUM *rsa_q, ++ BIGNUM *prime) ++{ ++ BIGNUM *prev_prime; ++ int k; ++ ++ for (k = 0; k < num; k++) { ++ prev_prime = NULL; ++ if (k == 0) ++ prev_prime = rsa_p; ++ else ++ prev_prime = rsa_q; ++ ++ /* ++ * BN_cmp(a,b) return -1 if a < b; ++ * return 0 if a == b; ++ * return 1 if a > b. ++ */ ++ if (!BN_cmp(prime, prev_prime)) ++ return UADK_P_FAIL; ++ } ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int check_rsa_prime_useful(int * const n, struct rsa_prime_param *param, ++ BIGNUM *e_pub, BN_CTX *ctx, BN_GENCB *cb) ++{ ++ unsigned long err; ++ int ret; ++ ++ /* ++ * BN_sub(r, a, b) substracts b from a and place the result in r, ++ * r = a - b. ++ * BN_value_one() returns a BIGNUM constant of value 1. ++ * r2 = prime - 1. ++ */ ++ if (!BN_sub(param->r2, param->prime, BN_value_one())) ++ return BN_ERR; ++ ERR_set_mark(); ++ BN_set_flags(param->r2, BN_FLG_CONSTTIME); ++ ++ /* ++ * BN_mod_inverse(r, a, n, ctx) used to compute inverse modulo n. ++ * Precisely, it computes the inverse of a modulo n, and places ++ * the result in r, which means (a * r) % n == 1. ++ * If r == NULL, error. If r != NULL, success. ++ * The expected result: (r2 * r1) % e_pub == 1, ++ * the inverse of r2 exist, that is r1. ++ */ ++ if (BN_mod_inverse(param->r1, param->r2, e_pub, ctx)) ++ return UADK_P_SUCCESS; ++ ++ err = ERR_peek_last_error(); ++ if (ERR_GET_LIB(err) == ERR_LIB_BN && ++ ERR_GET_REASON(err) == BN_R_NO_INVERSE) ++ ERR_pop_to_mark(); ++ else ++ return BN_ERR; ++ ++ ret = BN_GENCB_call(cb, GENCB_NEXT, (*n)++); ++ if (!ret) ++ return BN_ERR; ++ ++ return GET_ERR_FINISH; ++} ++ ++static int get_rsa_prime_once(int num, const int *bitsr, int * const n, ++ BIGNUM *e_pub, struct rsa_prime_param *param, ++ BN_CTX *ctx, BN_GENCB *cb) ++{ ++ int ret = -1; ++ ++ if (num >= RSA_MAX_PRIME_NUM) ++ return ret; ++ ++ while (1) { ++ /* Generate prime with bitsr[num] len. */ ++ if (!BN_generate_prime_ex(param->prime, bitsr[num], ++ 0, NULL, NULL, cb)) ++ return BN_ERR; ++ if (!check_rsa_prime_equal(num, param->rsa_p, param->rsa_q, ++ param->prime)) ++ continue; ++ ++ ret = check_rsa_prime_useful(n, param, e_pub, ctx, cb); ++ if (ret == BN_ERR) ++ return BN_ERR; ++ else if (ret == UADK_P_SUCCESS) ++ break; ++ } ++ ++ return ret; ++} ++ ++static void rsa_switch_p_q(BIGNUM *rsa_p, BIGNUM *rsa_q, BIGNUM *p, BIGNUM *q) ++{ ++ BIGNUM *tmp; ++ ++ if (BN_cmp(rsa_p, rsa_q) < 0) { ++ tmp = rsa_p; ++ rsa_p = rsa_q; ++ rsa_q = tmp; ++ } ++ ++ BN_copy(p, rsa_p); ++ BN_copy(q, rsa_q); ++} ++ ++static int get_rsa_prime_param(struct rsa_prime_param *param, BN_CTX *ctx) ++{ ++ param->r1 = BN_CTX_get(ctx); ++ if (!param->r1) ++ goto error; ++ ++ param->r2 = BN_CTX_get(ctx); ++ if (!param->r2) ++ goto error; ++ ++ param->rsa_q = BN_CTX_get(ctx); ++ if (!param->rsa_q) ++ goto error; ++ ++ param->rsa_p = BN_CTX_get(ctx); ++ if (!param->rsa_p) ++ goto error; ++ ++ return UADK_P_SUCCESS; ++ ++error: ++ UADK_ERR("failed to allocate rsa prime params\n"); ++ return -ENOMEM; ++} ++ ++static int rsa_primes_gen(int bits, BIGNUM *e_pub, BIGNUM *p, ++ BIGNUM *q, BN_GENCB *cb) ++{ ++ int bitsr[RSA_MAX_PRIME_NUM] = {0}; ++ struct rsa_prime_param *param; ++ int flag, quot, rmd, i; ++ int ret = UADK_P_FAIL; ++ BN_CTX *bnctx; ++ int bitse = 0; ++ /* n: modulo n, a part of public key */ ++ int n = 0; ++ ++ bnctx = BN_CTX_new(); ++ if (!bnctx) ++ return ret; ++ ++ BN_CTX_start(bnctx); ++ param = OPENSSL_zalloc(sizeof(struct rsa_prime_param)); ++ if (!param) ++ goto free_ctx; ++ ++ ret = get_rsa_prime_param(param, bnctx); ++ if (ret != UADK_P_SUCCESS) ++ goto free_param; ++ ++ /* Divide bits into 'primes' pieces evenly */ ++ quot = bits / RSA_MAX_PRIME_NUM; ++ rmd = bits % RSA_MAX_PRIME_NUM; ++ for (i = 0; i < RSA_MAX_PRIME_NUM; i++) ++ bitsr[i] = (i < rmd) ? quot + 1 : quot; ++ ++ /* Generate p, q and other primes (if any) */ ++ for (i = 0; i < RSA_MAX_PRIME_NUM; i++) { ++ /* flag: whether primes are generated correctely. */ ++ flag = 1; ++ /* Set flag for primes rsa_p and rsa_q separately. */ ++ rsa_set_primes(i, param->rsa_p, param->rsa_q, ¶m->prime); ++ while (flag == 1) { ++ ret = get_rsa_prime_once(i, bitsr, &n, e_pub, param, ++ bnctx, cb); ++ if (ret == -1) ++ goto free_param; ++ bitse += bitsr[i]; ++ ret = check_rsa_prime_sufficient(&i, bitsr, &bitse, &n, ++ param, bnctx, cb); ++ if (ret == BN_ERR) ++ goto free_param; ++ else if (ret == BN_REDO) ++ continue; ++ else ++ flag = 0; ++ } ++ } ++ rsa_switch_p_q(param->rsa_p, param->rsa_q, p, q); ++ ++ ret = UADK_P_SUCCESS; ++ ++free_param: ++ OPENSSL_free(param); ++free_ctx: ++ BN_CTX_end(bnctx); ++ BN_CTX_free(bnctx); ++ return ret; ++} ++ ++static int rsa_fill_keygen_data(struct uadk_rsa_sess *rsa_sess, ++ struct rsa_keypair *key_pair, ++ struct rsa_keygen_param *keygen_param, ++ struct rsa_keygen_param_bn *bn_param) ++{ ++ wd_rsa_get_pubkey(rsa_sess->sess, &key_pair->pubkey); ++ if (!key_pair->pubkey) ++ return UADK_P_FAIL; ++ ++ wd_rsa_get_pubkey_params(key_pair->pubkey, &keygen_param->wd_e, NULL); ++ if (!keygen_param->wd_e) ++ return UADK_P_FAIL; ++ ++ keygen_param->wd_e->dsize = BN_bn2bin(bn_param->e, ++ (unsigned char *)keygen_param->wd_e->data); ++ ++ wd_rsa_get_prikey(rsa_sess->sess, &key_pair->prikey); ++ if (!key_pair->prikey) ++ return UADK_P_FAIL; ++ ++ wd_rsa_get_crt_prikey_params(key_pair->prikey, NULL, NULL, NULL, ++ &keygen_param->wd_q, &keygen_param->wd_p); ++ if (!keygen_param->wd_p || !keygen_param->wd_q) ++ return UADK_P_FAIL; ++ ++ keygen_param->wd_p->dsize = BN_bn2bin(bn_param->p, ++ (unsigned char *)keygen_param->wd_p->data); ++ keygen_param->wd_q->dsize = BN_bn2bin(bn_param->q, ++ (unsigned char *)keygen_param->wd_q->data); ++ ++ rsa_sess->req.src_bytes = rsa_sess->key_size; ++ rsa_sess->req.dst_bytes = rsa_sess->key_size; ++ rsa_sess->req.op_type = WD_RSA_GENKEY; ++ rsa_sess->req.src = wd_rsa_new_kg_in(rsa_sess->sess, keygen_param->wd_e, ++ keygen_param->wd_p, keygen_param->wd_q); ++ if (!rsa_sess->req.src) ++ return UADK_P_FAIL; ++ ++ rsa_sess->req.dst = wd_rsa_new_kg_out(rsa_sess->sess); ++ if (!rsa_sess->req.dst) { ++ wd_rsa_del_kg_in(rsa_sess->sess, rsa_sess->req.src); ++ return UADK_P_FAIL; ++ } ++ ++ return UADK_P_SUCCESS; ++} ++ ++static RSA *ossl_rsa_new_with_ctx(OSSL_LIB_CTX *libctx) ++{ ++ RSA *rsa = OPENSSL_zalloc(sizeof(*rsa)); ++ ++ if (rsa == NULL) { ++ UADK_ERR("failed to zalloc rsa ret\n"); ++ return NULL; ++ } ++ ++ rsa->references = 1; ++ rsa->lock = CRYPTO_THREAD_lock_new(); ++ if (rsa->lock == NULL) { ++ UADK_ERR("failed to malloc thread lock\n"); ++ OPENSSL_free(rsa); ++ return NULL; ++ } ++ ++ rsa->libctx = libctx; ++ rsa->meth = RSA_get_default_method(); ++ ++ return rsa; ++} ++ ++static int rsa_gencb(int p, int n, BN_GENCB *cb) ++{ ++ struct rsa_gen_ctx *gctx = BN_GENCB_get_arg(cb); ++ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; ++ ++ params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p); ++ params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n); ++ return gctx->cb(params, gctx->cbarg); ++} ++ ++static int rsa_get_keygen_param(struct wd_rsa_req *req, handle_t ctx, RSA *rsa, ++ struct rsa_keygen_param_bn *bn_param) ++{ ++ struct wd_rsa_kg_out *out = (struct wd_rsa_kg_out *)req->dst; ++ struct wd_dtb wd_d, wd_n, wd_qinv, wd_dq, wd_dp; ++ BIGNUM *dmp1, *dmq1, *iqmp, *d, *n; ++ unsigned int key_bits, key_size; ++ ++ key_bits = wd_rsa_get_key_bits(ctx); ++ if (!key_bits) ++ return UADK_P_FAIL; ++ ++ key_size = key_bits >> BIT_BYTES_SHIFT; ++ wd_rsa_get_kg_out_params(out, &wd_d, &wd_n); ++ wd_rsa_get_kg_out_crt_params(out, &wd_qinv, &wd_dq, &wd_dp); ++ ++ dmq1 = BN_secure_new(); ++ if (!dmq1) ++ return UADK_P_FAIL; ++ ++ dmp1 = BN_secure_new(); ++ if (!dmp1) ++ goto free_bn_dq; ++ ++ iqmp = BN_new(); ++ if (!iqmp) ++ goto free_bn_dp; ++ ++ n = BN_new(); ++ if (!n) ++ goto free_bn_qinv; ++ ++ d = BN_secure_new(); ++ if (!d) ++ goto free_bn_n; ++ ++ BN_bin2bn((unsigned char *)wd_n.data, key_size, n); ++ BN_bin2bn((unsigned char *)wd_d.data, key_size, d); ++ BN_bin2bn((unsigned char *)wd_qinv.data, wd_qinv.dsize, iqmp); ++ BN_bin2bn((unsigned char *)wd_dq.data, wd_dq.dsize, dmq1); ++ BN_bin2bn((unsigned char *)wd_dp.data, wd_dp.dsize, dmp1); ++ ++ if (!(uadk_rsa_set0_key(rsa, n, bn_param->e, d) && ++ uadk_rsa_set0_factors(rsa, bn_param->p, bn_param->q) && ++ uadk_rsa_set0_crt_params(rsa, dmp1, dmq1, iqmp))) ++ goto free_bn_d; ++ ++ return UADK_P_SUCCESS; ++ ++free_bn_d: ++ BN_clear_free(d); ++free_bn_n: ++ BN_clear_free(n); ++free_bn_qinv: ++ BN_clear_free(iqmp); ++free_bn_dp: ++ BN_clear_free(dmp1); ++free_bn_dq: ++ BN_clear_free(dmq1); ++ ++ return UADK_P_FAIL; ++} ++ ++static void rsa_free_keygen_data(struct uadk_rsa_sess *rsa_sess) ++{ ++ if (!rsa_sess) ++ return; ++ ++ wd_rsa_del_kg_out(rsa_sess->sess, rsa_sess->req.dst); ++ wd_rsa_del_kg_in(rsa_sess->sess, rsa_sess->req.src); ++} ++ ++static void rsa_keygen_param_free(struct rsa_keygen_param **keygen_param, ++ struct rsa_keygen_param_bn **keygen_bn_param, ++ struct rsa_keypair **key_pair, int free_bn_ctx_tag) ++{ ++ /* ++ * When an abnormal situation occurs, uadk engine needs to ++ * switch to software keygen function, so we need to free ++ * BN we alloced before. But in normal situation, ++ * the BN should be freed by OpenSSL tools or users. ++ * Therefore, we use a tag to distinguish these cases. ++ */ ++ if (free_bn_ctx_tag == UADK_DO_SOFT) { ++ BN_clear_free((*keygen_bn_param)->p); ++ BN_clear_free((*keygen_bn_param)->q); ++ BN_clear_free((*keygen_bn_param)->e); ++ } ++ ++ OPENSSL_free(*key_pair); ++ OPENSSL_free(*keygen_param); ++ OPENSSL_free(*keygen_bn_param); ++} ++ ++static int rsa_keygen_param_alloc(struct rsa_keygen_param **keygen_param, ++ struct rsa_keygen_param_bn **keygen_bn_param, ++ struct rsa_keypair **key_pair) ++{ ++ *keygen_param = OPENSSL_malloc(sizeof(struct rsa_keygen_param)); ++ if (!(*keygen_param)) ++ goto error; ++ ++ *keygen_bn_param = (struct rsa_keygen_param_bn *) ++ OPENSSL_malloc(sizeof(struct rsa_keygen_param_bn)); ++ if (!(*keygen_bn_param)) ++ goto free_keygen_param; ++ ++ *key_pair = OPENSSL_malloc(sizeof(struct rsa_keypair)); ++ if (!(*key_pair)) ++ goto free_keygen_bn_param; ++ ++ (*keygen_bn_param)->p = BN_secure_new(); ++ if (!(*keygen_bn_param)->p) ++ goto free_key_pair; ++ ++ (*keygen_bn_param)->q = BN_secure_new(); ++ if (!(*keygen_bn_param)->q) ++ goto free_p; ++ ++ (*keygen_bn_param)->e = BN_new(); ++ if (!(*keygen_bn_param)->e) ++ goto free_q; ++ ++ return UADK_P_SUCCESS; ++ ++free_q: ++ BN_clear_free((*keygen_bn_param)->q); ++free_p: ++ BN_clear_free((*keygen_bn_param)->p); ++free_key_pair: ++ OPENSSL_free(*key_pair); ++free_keygen_bn_param: ++ OPENSSL_free(*keygen_bn_param); ++free_keygen_param: ++ OPENSSL_free(*keygen_param); ++error: ++ return -ENOMEM; ++} ++ ++static int uadk_prov_rsa_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) ++{ ++ struct rsa_keygen_param *keygen_param = NULL; ++ struct rsa_keygen_param_bn *bn_param = NULL; ++ struct rsa_keypair *key_pair = NULL; ++ struct uadk_rsa_sess *rsa_sess; ++ int is_crt = 1; ++ int ret; ++ ++ ret = rsa_check_bit_useful(bits, 0); ++ if (ret != UADK_P_SUCCESS) ++ return ret; ++ ++ ret = rsa_keygen_param_alloc(&keygen_param, &bn_param, &key_pair); ++ if (ret == -ENOMEM) ++ return UADK_P_FAIL; ++ ++ rsa_sess = rsa_get_eng_session(rsa, bits, is_crt); ++ if (!rsa_sess) { ++ ret = UADK_DO_SOFT; ++ goto free_keygen; ++ } ++ ++ ret = rsa_primes_gen(bits, e, bn_param->p, bn_param->q, cb); ++ if (!ret) { ++ ret = UADK_P_FAIL; ++ goto free_sess; ++ } ++ ++ if (!BN_copy(bn_param->e, e)) { ++ ret = UADK_P_FAIL; ++ goto free_sess; ++ } ++ ++ ret = rsa_fill_keygen_data(rsa_sess, key_pair, keygen_param, bn_param); ++ if (!ret) { ++ ret = UADK_P_FAIL; ++ goto free_sess; ++ } ++ ++ ret = rsa_do_crypto(rsa_sess); ++ if (!ret || rsa_sess->req.status) { ++ ret = UADK_DO_SOFT; ++ goto free_kg_in_out; ++ } ++ ++ ret = rsa_get_keygen_param(&rsa_sess->req, rsa_sess->sess, rsa, bn_param); ++ if (!ret) ++ ret = UADK_P_FAIL; ++ ++free_kg_in_out: ++ rsa_free_keygen_data(rsa_sess); ++free_sess: ++ rsa_free_eng_session(rsa_sess); ++free_keygen: ++ rsa_keygen_param_free(&keygen_param, &bn_param, &key_pair, ret); ++ return ret; ++} ++ ++static const char *uadk_keymgmt_rsa_query_operation_name(int operation_id) ++{ ++ if (!get_default_rsa_keymgmt().query_operation_name) ++ return NULL; ++ ++ return get_default_rsa_keymgmt().query_operation_name(operation_id); ++} ++ ++static void *uadk_keymgmt_rsa_new(void *provctx) ++{ ++ if (!get_default_rsa_keymgmt().new_fun) ++ return NULL; ++ ++ return get_default_rsa_keymgmt().new_fun(provctx); ++} ++ ++static void uadk_keymgmt_rsa_free(void *keydata) ++{ ++ if (!get_default_rsa_keymgmt().free) ++ return; ++ ++ get_default_rsa_keymgmt().free(keydata); ++} ++ ++static int uadk_keymgmt_rsa_has(const void *keydata, int selection) ++{ ++ if (!get_default_rsa_keymgmt().has) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_keymgmt().has(keydata, selection); ++} ++ ++static int uadk_keymgmt_rsa_import(void *keydata, int selection, const OSSL_PARAM params[]) ++{ ++ if (!get_default_rsa_keymgmt().import) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_keymgmt().import(keydata, selection, params); ++} ++ ++static const OSSL_PARAM *uadk_keymgmt_rsa_import_types(int selection) ++{ ++ if (!get_default_rsa_keymgmt().import_types) ++ return NULL; ++ ++ return get_default_rsa_keymgmt().import_types(selection); ++} ++ ++static void *uadk_keymgmt_rsa_gen_init(void *provctx, int selection, ++ const OSSL_PARAM params[]) ++{ ++ if (!get_default_rsa_keymgmt().gen_init) ++ return NULL; ++ ++ return get_default_rsa_keymgmt().gen_init(provctx, selection, params); ++} ++ ++static int uadk_keymgmt_rsa_gen_set_params(void *genctx, const OSSL_PARAM params[]) ++{ ++ if (!get_default_rsa_keymgmt().gen_set_params) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_keymgmt().gen_set_params(genctx, params); ++} ++ ++static int uadk_keymgmt_rsa_gen_set_template(void *genctx, void *templates) ++{ ++ if (!get_default_rsa_keymgmt().gen_set_template) { ++ UADK_ERR("failed to get keymgmt gen_set_template function\n"); ++ return UADK_P_FAIL; ++ } ++ ++ return get_default_rsa_keymgmt().gen_set_template(genctx, templates); ++} ++ ++static const OSSL_PARAM *uadk_keymgmt_rsa_gen_settable_params(ossl_unused void *genctx, ++ ossl_unused void *provctx) ++{ ++ if (!get_default_rsa_keymgmt().gen_settable_params) ++ return NULL; ++ ++ return get_default_rsa_keymgmt().gen_settable_params(genctx, provctx); ++} ++ ++static void *uadk_rsa_sw_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) ++{ ++ if (!enable_sw_offload || !get_default_rsa_keymgmt().gen) ++ return NULL; ++ ++ UADK_INFO("switch to openssl software calculation in rsa key generation.\n"); ++ return get_default_rsa_keymgmt().gen(genctx, osslcb, cbarg); ++} ++ ++static void *uadk_keymgmt_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) ++{ ++ struct rsa_gen_ctx *gctx = genctx; ++ BN_GENCB *gencb; ++ RSA *rsa; ++ int ret; ++ ++ if (gctx == NULL) ++ return NULL; ++ ++ ret = uadk_prov_rsa_init(); ++ if (ret) { ++ ret = UADK_DO_SOFT; ++ goto exe_soft; ++ } ++ ++ rsa = ossl_rsa_new_with_ctx(gctx->libctx); ++ if (rsa == NULL) ++ return NULL; ++ ++ gctx->cb = osslcb; ++ gctx->cbarg = cbarg; ++ gencb = BN_GENCB_new(); ++ if (gencb != NULL) ++ BN_GENCB_set(gencb, rsa_gencb, genctx); ++ ++ ret = uadk_prov_rsa_keygen(rsa, (int)gctx->nbits, gctx->pub_exp, gencb); ++ if (ret == UADK_DO_SOFT || ret == UADK_P_FAIL) { ++ BN_GENCB_free(gencb); ++ uadk_keymgmt_rsa_free(rsa); ++ goto exe_soft; ++ } ++ ++ uadk_rsa_clear_flags(rsa, RSA_FLAG_TYPE_MASK); ++ uadk_rsa_set_flags(rsa, gctx->rsa_type); ++ BN_GENCB_free(gencb); ++ ++ return rsa; ++ ++exe_soft: ++ if (ret == UADK_DO_SOFT) ++ return uadk_rsa_sw_gen(genctx, osslcb, cbarg); ++ return NULL; ++} ++ ++static void uadk_keymgmt_rsa_gen_cleanup(void *genctx) ++{ ++ if (!get_default_rsa_keymgmt().gen_cleanup) ++ return; ++ ++ get_default_rsa_keymgmt().gen_cleanup(genctx); ++} ++ ++static void *uadk_keymgmt_rsa_load(const void *reference, size_t reference_sz) ++{ ++ if (!get_default_rsa_keymgmt().load) ++ return NULL; ++ ++ return get_default_rsa_keymgmt().load(reference, reference_sz); ++} ++ ++static int uadk_keymgmt_rsa_get_params(void *key, OSSL_PARAM params[]) ++{ ++ if (!get_default_rsa_keymgmt().get_params) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_keymgmt().get_params(key, params); ++} ++ ++static const OSSL_PARAM *uadk_keymgmt_rsa_gettable_params(void *provctx) ++{ ++ if (!get_default_rsa_keymgmt().gettable_params) ++ return NULL; ++ ++ return get_default_rsa_keymgmt().gettable_params(provctx); ++} ++ ++static int uadk_keymgmt_rsa_set_params(void *key, const OSSL_PARAM params[]) ++{ ++ if (!get_default_rsa_keymgmt().set_params) { ++ UADK_ERR("failed to get keymgmt set_params function\n"); ++ return UADK_P_FAIL; ++ } ++ ++ return get_default_rsa_keymgmt().set_params(key, params); ++} ++ ++static const OSSL_PARAM *uadk_keymgmt_rsa_settable_params(ossl_unused void *provctx) ++{ ++ if (!get_default_rsa_keymgmt().settable_params) { ++ UADK_ERR("failed to get keymgmt settable_params function\n"); ++ return NULL; ++ } ++ ++ return get_default_rsa_keymgmt().settable_params(provctx); ++} ++ ++static int uadk_keymgmt_rsa_match(const void *keydata1, const void *keydata2, int selection) ++{ ++ if (!get_default_rsa_keymgmt().match) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_keymgmt().match(keydata1, keydata2, selection); ++} ++ ++static int uadk_keymgmt_rsa_validate(const void *keydata, int selection, int checktype) ++{ ++ if (!get_default_rsa_keymgmt().validate) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_keymgmt().validate(keydata, selection, checktype); ++} ++ ++static int uadk_keymgmt_rsa_export(void *keydata, int selection, ++ OSSL_CALLBACK *param_callback, void *cbarg) ++{ ++ if (!get_default_rsa_keymgmt().export_fun) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_keymgmt().export_fun(keydata, selection, param_callback, cbarg); ++} ++ ++static const OSSL_PARAM *uadk_keymgmt_rsa_export_types(int selection) ++{ ++ if (!get_default_rsa_keymgmt().export_types) ++ return NULL; ++ ++ return get_default_rsa_keymgmt().export_types(selection); ++} ++ ++static void *uadk_keymgmt_rsa_dup(const void *keydata_from, int selection) ++{ ++ if (!get_default_rsa_keymgmt().dup) ++ return NULL; ++ ++ return get_default_rsa_keymgmt().dup(keydata_from, selection); ++} +diff --git a/src/uadk_prov_rsa_sign.c b/src/uadk_prov_rsa_sign.c +new file mode 100644 +index 0000000..8e0a571 +--- /dev/null ++++ b/src/uadk_prov_rsa_sign.c +@@ -0,0 +1,1138 @@ ++// SPDX-License-Identifier: Apache-2.0 ++/* ++ * Copyright 2023-2024 Huawei Technologies Co.,Ltd. All rights reserved. ++ * Copyright 2023-2024 Linaro ltd. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ */ ++#include "uadk_prov_rsa.h" ++ ++UADK_PKEY_SIGNATURE_DESCR(rsa, RSA); ++ ++struct PROV_RSA_SIG_CTX { ++ OSSL_LIB_CTX *libctx; ++ char *propq; ++ RSA *rsa; ++ int operation; ++ ++ /* ++ * Flag to determine if the hash function can be changed (1) or not (0) ++ * Because it's dangerous to change during a DigestSign or DigestVerify ++ * operation, this flag is cleared by their Init function, and set again ++ * by their Final function. ++ */ ++ unsigned int flag_allow_md : 1; ++ unsigned int mgf1_md_set : 1; ++ ++ /* main digest */ ++ EVP_MD *md; ++ EVP_MD_CTX *mdctx; ++ int mdnid; ++ char mdname[50]; /* Purely informational */ ++ ++ /* RSA padding mode */ ++ int pad_mode; ++ /* message digest for MGF1 */ ++ EVP_MD *mgf1_md; ++ int mgf1_mdnid; ++ char mgf1_mdname[50]; /* Purely informational */ ++ /* PSS salt length */ ++ int saltlen; ++ /* Minimum salt length or -1 if no PSS parameter restriction */ ++ int min_saltlen; ++ ++ /* Temp buffer */ ++ unsigned char *tbuf; ++ ++ unsigned int soft : 1; ++}; ++ ++static pthread_mutex_t sig_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++static UADK_PKEY_SIGNATURE get_default_rsa_signature(void) ++{ ++ static UADK_PKEY_SIGNATURE s_signature; ++ static int initilazed; ++ ++ pthread_mutex_lock(&sig_mutex); ++ if (!initilazed) { ++ UADK_PKEY_SIGNATURE *signature = ++ (UADK_PKEY_SIGNATURE *)EVP_SIGNATURE_fetch(NULL, "RSA", "provider=default"); ++ ++ if (signature) { ++ s_signature = *signature; ++ EVP_SIGNATURE_free((EVP_SIGNATURE *)signature); ++ initilazed = 1; ++ } else { ++ UADK_ERR("failed to EVP_SIGNATURE_fetch default RSA provider\n"); ++ } ++ } ++ pthread_mutex_unlock(&sig_mutex); ++ return s_signature; ++} ++ ++static int setup_tbuf(struct PROV_RSA_SIG_CTX *ctx) ++{ ++ if (ctx->tbuf != NULL) ++ return UADK_P_SUCCESS; ++ ++ ctx->tbuf = OPENSSL_malloc(uadk_rsa_size(ctx->rsa)); ++ if (ctx->tbuf == NULL) { ++ UADK_ERR("failed to zalloc ctx tbuf!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ return UADK_P_SUCCESS; ++} ++ ++static void clean_tbuf(struct PROV_RSA_SIG_CTX *ctx) ++{ ++ if (ctx->tbuf != NULL) ++ OPENSSL_cleanse(ctx->tbuf, uadk_rsa_size(ctx->rsa)); ++} ++ ++static void free_tbuf(struct PROV_RSA_SIG_CTX *ctx) ++{ ++ clean_tbuf(ctx); ++ OPENSSL_free(ctx->tbuf); ++ ctx->tbuf = NULL; ++} ++ ++static int add_rsa_prienc_padding(int flen, const unsigned char *from, ++ unsigned char *to_buf, int tlen, ++ int padding) ++{ ++ int ret; ++ ++ switch (padding) { ++ case RSA_PKCS1_PADDING: ++ ret = RSA_padding_add_PKCS1_type_1(to_buf, tlen, from, flen); ++ if (!ret) ++ UADK_ERR("RSA_PKCS1_PADDING err.\n"); ++ break; ++ case RSA_X931_PADDING: ++ ret = RSA_padding_add_X931(to_buf, tlen, from, flen); ++ if (ret == -1) ++ UADK_ERR("RSA_X931_PADDING err.\n"); ++ break; ++ default: ++ ret = UADK_P_FAIL; ++ } ++ if (ret <= 0) ++ ret = UADK_P_FAIL; ++ ++ return ret; ++} ++ ++static int check_rsa_pubdec_padding(unsigned char *to, int num, ++ const unsigned char *buf, int len, ++ int padding) ++{ ++ int ret; ++ ++ switch (padding) { ++ case RSA_PKCS1_PADDING: ++ ret = RSA_padding_check_PKCS1_type_1(to, num, buf, len, num); ++ if (ret == CHECK_PADDING_FAIL) ++ UADK_ERR("RSA_PKCS1_PADDING err.\n"); ++ break; ++ case RSA_X931_PADDING: ++ ret = RSA_padding_check_X931(to, num, buf, len, num); ++ if (ret == CHECK_PADDING_FAIL) ++ UADK_ERR("RSA_X931_PADDING err.\n"); ++ break; ++ default: ++ ret = UADK_P_FAIL; ++ } ++ ++ if (ret == CHECK_PADDING_FAIL) ++ ret = UADK_P_FAIL; ++ ++ return ret; ++} ++ ++static BN_ULONG *bn_get_words(const BIGNUM *a) ++{ ++ return a->d; ++} ++ ++static int rsa_get_sign_res(int padding, BIGNUM *to_bn, const BIGNUM *n, ++ BIGNUM *ret_bn, BIGNUM **res) ++{ ++ if (padding == RSA_X931_PADDING) { ++ if (!BN_sub(to_bn, n, ret_bn)) ++ return UADK_P_FAIL; ++ if (BN_cmp(ret_bn, to_bn) > 0) ++ *res = to_bn; ++ else ++ *res = ret_bn; ++ } else { ++ *res = ret_bn; ++ } ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int rsa_get_verify_res(int padding, const BIGNUM *n, BIGNUM *ret_bn) ++{ ++ BIGNUM *to_bn = NULL; ++ ++ if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret_bn)[0] & 0xf) ++ != 0x0c)) { ++ if (!BN_sub(to_bn, n, ret_bn)) ++ return UADK_P_FAIL; ++ } ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int sign_trans_bn(struct uadk_rsa_sess *rsa_sess, unsigned char *from_buf, ++ struct rsa_prikey_param *pri, int padding, ++ unsigned char *to, int num_bytes) ++{ ++ BIGNUM *res = NULL; ++ BIGNUM *sign_bn; ++ BIGNUM *to_bn; ++ int ret; ++ ++ sign_bn = BN_bin2bn((const unsigned char *)rsa_sess->req.dst, ++ rsa_sess->req.dst_bytes, NULL); ++ if (!sign_bn) ++ return UADK_P_FAIL; ++ ++ to_bn = BN_bin2bn(from_buf, num_bytes, NULL); ++ if (!to_bn) { ++ ret = UADK_P_FAIL; ++ goto free_sign_bn; ++ } ++ ++ ret = rsa_get_sign_res(padding, to_bn, pri->n, sign_bn, &res); ++ if (!ret) ++ goto free_to_bn; ++ ++ ret = BN_bn2binpad(res, to, num_bytes); ++ ++free_to_bn: ++ BN_free(to_bn); ++free_sign_bn: ++ BN_free(sign_bn); ++ return ret; ++} ++ ++static int uadk_prov_rsa_private_sign(int flen, const unsigned char *from, ++ unsigned char *to, RSA *rsa, int padding) ++{ ++ struct rsa_prikey_param *prik = NULL; ++ struct uadk_rsa_sess *rsa_sess; ++ unsigned char *from_buf = NULL; ++ int ret, num_bytes; ++ ++ ret = check_rsa_input_para(flen, from, to, rsa); ++ if (ret != UADK_P_SUCCESS) ++ return ret; ++ ++ ret = rsa_pkey_param_alloc(NULL, &prik); ++ if (ret == -ENOMEM) ++ return UADK_P_FAIL; ++ ++ prik->is_crt = check_rsa_is_crt(rsa); ++ ++ rsa_sess = rsa_get_eng_session(rsa, uadk_rsa_bits(rsa), prik->is_crt); ++ if (!rsa_sess) { ++ ret = UADK_DO_SOFT; ++ goto free_pkey; ++ } ++ ++ ret = rsa_create_pri_bn_ctx(rsa, prik, &from_buf, &num_bytes); ++ if (ret <= 0 || flen > num_bytes) { ++ ret = UADK_P_FAIL; ++ goto free_sess; ++ } ++ ++ ret = add_rsa_prienc_padding(flen, from, from_buf, num_bytes, padding); ++ if (!ret) { ++ ret = UADK_P_FAIL; ++ goto free_buf; ++ } ++ ++ ret = rsa_fill_prikey(rsa, rsa_sess, prik, from_buf, to); ++ if (!ret) { ++ ret = UADK_P_FAIL; ++ goto free_buf; ++ } ++ ++ ret = rsa_do_crypto(rsa_sess); ++ if (!ret || rsa_sess->req.status) { ++ ret = UADK_DO_SOFT; ++ goto free_buf; ++ } ++ ++ ret = sign_trans_bn(rsa_sess, from_buf, prik, padding, to, num_bytes); ++ ++free_buf: ++ rsa_free_pri_bn_ctx(from_buf); ++free_sess: ++ rsa_free_eng_session(rsa_sess); ++free_pkey: ++ rsa_pkey_param_free(NULL, &prik); ++ return ret; ++} ++ ++static int verify_trans_bn(struct uadk_rsa_sess *rsa_sess, unsigned char *from_buf, ++ int num_bytes, struct rsa_pubkey_param *pub, ++ int padding, int *len) ++{ ++ BIGNUM *verify_bn; ++ int ret; ++ ++ verify_bn = BN_bin2bn((const unsigned char *)rsa_sess->req.dst, ++ rsa_sess->req.dst_bytes, NULL); ++ if (!verify_bn) ++ return UADK_P_FAIL; ++ ++ ret = rsa_get_verify_res(padding, pub->n, verify_bn); ++ if (!ret) ++ goto verify_end; ++ ++ *len = BN_bn2binpad(verify_bn, from_buf, num_bytes); ++ if (*len == 0) ++ ret = UADK_P_FAIL; ++ ++verify_end: ++ BN_free(verify_bn); ++ return ret; ++} ++ ++static int uadk_prov_rsa_public_verify(int flen, const unsigned char *from, ++ unsigned char *to, RSA *rsa, int padding) ++{ ++ struct rsa_pubkey_param *pub = NULL; ++ int num_bytes, is_crt, len, ret; ++ struct uadk_rsa_sess *rsa_sess; ++ unsigned char *from_buf = NULL; ++ ++ ret = check_rsa_input_para(flen, from, to, rsa); ++ if (ret != UADK_P_SUCCESS) ++ return ret; ++ ++ ret = rsa_pkey_param_alloc(&pub, NULL); ++ if (ret == -ENOMEM) ++ return UADK_P_FAIL; ++ ++ is_crt = check_rsa_is_crt(rsa); ++ ++ rsa_sess = rsa_get_eng_session(rsa, uadk_rsa_bits(rsa), is_crt); ++ if (!rsa_sess) { ++ ret = UADK_DO_SOFT; ++ goto free_pkey; ++ } ++ ++ ret = rsa_create_pub_bn_ctx(rsa, pub, &from_buf, &num_bytes); ++ if (ret <= 0 || flen > num_bytes) { ++ ret = UADK_P_FAIL; ++ goto free_sess; ++ } ++ ++ ret = rsa_fill_pubkey(pub, rsa_sess, from_buf, to); ++ if (!ret) { ++ ret = UADK_P_FAIL; ++ goto free_buff; ++ } ++ ++ memcpy(rsa_sess->req.src, from, rsa_sess->req.src_bytes); ++ ret = rsa_do_crypto(rsa_sess); ++ if (!ret || rsa_sess->req.status) { ++ ret = UADK_DO_SOFT; ++ goto free_buff; ++ } ++ ++ ret = verify_trans_bn(rsa_sess, from_buf, num_bytes, pub, padding, &len); ++ if (!ret) ++ goto free_buff; ++ ++ ret = check_rsa_pubdec_padding(to, num_bytes, from_buf, len, padding); ++ ++free_buff: ++ rsa_free_pub_bn_ctx(from_buf); ++free_sess: ++ rsa_free_eng_session(rsa_sess); ++free_pkey: ++ rsa_pkey_param_free(&pub, NULL); ++ return ret; ++} ++ ++static int uadk_rsa_init(void *vprsactx, void *vrsa, ++ const OSSL_PARAM params[], int operation) ++{ ++ struct PROV_RSA_SIG_CTX *ctx = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ ++ if (ctx == NULL || vrsa == NULL) ++ return UADK_P_FAIL; ++ ++ ctx->rsa = vrsa; ++ ctx->operation = operation; ++ ++ /* Maximum for sign, auto for verify */ ++ ctx->saltlen = RSA_PSS_SALTLEN_AUTO; ++ ctx->min_saltlen = -1; ++ ++ switch (uadk_rsa_test_flags(ctx->rsa, RSA_FLAG_TYPE_MASK)) { ++ case RSA_FLAG_TYPE_RSA: ++ ctx->pad_mode = RSA_PKCS1_PADDING; ++ break; ++ case RSA_FLAG_TYPE_RSASSAPSS: ++ ctx->pad_mode = RSA_PKCS1_PSS_PADDING; ++ break; ++ default: ++ UADK_ERR("rsa init operation not supported this keytype!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ if (uadk_prov_rsa_init()) ++ ctx->soft = 1; ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_signature_rsa_verify_recover_init(void *vprsactx, void *vrsa, ++ const OSSL_PARAM params[]) ++{ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_signature_rsa_verify_recover(void *vprsactx, unsigned char *rout, ++ size_t *routlen, size_t routsize, ++ const unsigned char *sig, size_t siglen) ++{ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_signature_rsa_verify_init(void *vprsactx, void *vrsa, ++ const OSSL_PARAM params[]) ++{ ++ return uadk_rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY); ++} ++ ++static int uadk_rsa_sw_verify(void *vprsactx, const unsigned char *sig, ++ size_t siglen, const unsigned char *tbs, ++ size_t tbslen) ++{ ++ if (!enable_sw_offload || !get_default_rsa_signature().verify) ++ return UADK_P_FAIL; ++ ++ UADK_INFO("switch to openssl software calculation in verifaction.\n"); ++ ++ return get_default_rsa_signature().verify(vprsactx, sig, siglen, tbs, tbslen); ++} ++ ++static int uadk_signature_rsa_verify(void *vprsactx, const unsigned char *sig, ++ size_t siglen, const unsigned char *tbs, ++ size_t tbslen) ++{ ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ size_t rslen = 0; ++ ++ if (priv->soft) { ++ rslen = UADK_DO_SOFT; ++ goto exe_soft; ++ } ++ ++ /* todo call public_verify */ ++ if (priv->md != NULL) { ++ /* todo */ ++ } else { ++ if (!setup_tbuf(priv)) ++ return UADK_P_FAIL; ++ rslen = uadk_prov_rsa_public_verify(siglen, sig, priv->tbuf, ++ priv->rsa, priv->pad_mode); ++ if (rslen == UADK_DO_SOFT || rslen == UADK_P_FAIL) ++ goto exe_soft; ++ } ++ ++ if ((rslen != tbslen) || memcmp(tbs, priv->tbuf, rslen)) ++ return UADK_P_FAIL; ++ ++ return UADK_P_SUCCESS; ++ ++exe_soft: ++ if (rslen == UADK_DO_SOFT) ++ return uadk_rsa_sw_verify(vprsactx, sig, siglen, tbs, tbslen); ++ return UADK_P_FAIL; ++} ++ ++static int uadk_rsa_sw_sign(void *vprsactx, unsigned char *sig, ++ size_t *siglen, size_t sigsize, ++ const unsigned char *tbs, size_t tbslen) ++{ ++ if (!enable_sw_offload || !get_default_rsa_signature().sign) ++ return UADK_P_FAIL; ++ ++ UADK_INFO("switch to openssl software calculation in rsa signature.\n"); ++ return get_default_rsa_signature().sign(vprsactx, sig, siglen, sigsize, tbs, tbslen); ++} ++ ++static int uadk_signature_rsa_sign(void *vprsactx, unsigned char *sig, ++ size_t *siglen, size_t sigsize, ++ const unsigned char *tbs, size_t tbslen) ++{ ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ size_t rsasize = uadk_rsa_size(priv->rsa); ++ int ret; ++ ++ if (priv->soft) { ++ ret = UADK_DO_SOFT; ++ goto exe_soft; ++ } ++ ++ if (sig == NULL) { ++ *siglen = rsasize; ++ return UADK_P_SUCCESS; ++ } ++ ++ if (sigsize < rsasize) { ++ UADK_ERR("invalid signature size is %zu, should be at least %zu!\n", ++ sigsize, rsasize); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_rsa_private_sign(tbslen, tbs, sig, priv->rsa, priv->pad_mode); ++ if (ret == UADK_DO_SOFT || ret == UADK_P_FAIL) ++ goto exe_soft; ++ ++ if (ret < 0) ++ return ret; ++ ++ *siglen = ret; ++ ++ return UADK_P_SUCCESS; ++exe_soft: ++ if (ret == UADK_DO_SOFT) ++ return uadk_rsa_sw_sign(vprsactx, sig, siglen, sigsize, tbs, tbslen); ++ return UADK_P_FAIL; ++} ++ ++static int uadk_signature_rsa_sign_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[]) ++{ ++ return uadk_rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_SIGN); ++} ++ ++static void *uadk_signature_rsa_newctx(void *provctx, const char *propq) ++{ ++ struct PROV_RSA_SIG_CTX *priv = OPENSSL_zalloc(sizeof(struct PROV_RSA_SIG_CTX)); ++ char *propq_copy = NULL; ++ ++ if (priv == NULL) ++ goto err; ++ ++ if (propq != NULL) { ++ propq_copy = OPENSSL_strdup(propq); ++ if (propq_copy == NULL) ++ goto err; ++ } ++ ++ priv->libctx = prov_libctx_of(provctx); ++ priv->flag_allow_md = 1; ++ priv->propq = propq_copy; ++ return priv; ++ ++err: ++ OPENSSL_free(priv); ++ UADK_ERR("%s failed.\n", __func__); ++ return NULL; ++} ++ ++static void uadk_signature_rsa_freectx(void *vprsactx) ++{ ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ ++ if (priv == NULL) ++ return; ++ ++ free_tbuf(priv); ++ OPENSSL_clear_free(priv, sizeof(*priv)); ++} ++ ++static int uadk_signature_rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) ++{ ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ ++ if (priv == NULL) ++ return UADK_P_FAIL; ++ if (params == NULL) ++ return UADK_P_SUCCESS; ++ ++ /* todo */ ++ ++ return UADK_P_SUCCESS; ++} ++ ++static const OSSL_PARAM settable_ctx_params[] = { ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0), ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0), ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0), ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), ++ OSSL_PARAM_END ++}; ++ ++static const OSSL_PARAM settable_ctx_params_no_digest[] = { ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0), ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0), ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), ++ OSSL_PARAM_END ++}; ++ ++static const OSSL_PARAM *uadk_signature_rsa_settable_ctx_params(void *vprsactx, ++ void *provctx) ++{ ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ ++ if (priv != NULL && !priv->flag_allow_md) ++ return settable_ctx_params_no_digest; ++ ++ return settable_ctx_params; ++} ++ ++static int uadk_rsa_check_padding(const struct PROV_RSA_SIG_CTX *prsactx, ++ const char *mdname, const char *mgf1_mdname, ++ int mdnid) ++{ ++ switch (prsactx->pad_mode) { ++ case RSA_NO_PADDING: ++ UADK_ERR("invalid rsa padding mode.\n"); ++ return UADK_P_FAIL; ++ case RSA_X931_PADDING: ++ if (RSA_X931_hash_id(mdnid) == -1) { ++ UADK_ERR("invalid rsa x931 digest.\n"); ++ return UADK_P_FAIL; ++ } ++ break; ++ case RSA_PKCS1_PSS_PADDING: ++ if (prsactx->min_saltlen != -1) { ++ if ((mdname != NULL && !EVP_MD_is_a(prsactx->md, mdname)) || ++ (mgf1_mdname != NULL && ++ !EVP_MD_is_a(prsactx->mgf1_md, mgf1_mdname))) { ++ UADK_ERR("rsa digest is not allowed.\n"); ++ return UADK_P_FAIL; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t it_len) ++{ ++ size_t i; ++ ++ if (md == NULL) ++ return NID_undef; ++ ++ for (i = 0; i < it_len; i++) ++ if (EVP_MD_is_a(md, it[i].ptr)) ++ return (int)it[i].id; ++ return NID_undef; ++} ++ ++static int uadk_digest_get_approved_nid(const EVP_MD *md) ++{ ++ static const OSSL_ITEM name_to_nid[] = { ++ { NID_sha1, OSSL_DIGEST_NAME_SHA1 }, ++ { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 }, ++ { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 }, ++ { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 }, ++ { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 }, ++ { NID_sha512_224, OSSL_DIGEST_NAME_SHA2_512_224 }, ++ { NID_sha512_256, OSSL_DIGEST_NAME_SHA2_512_256 }, ++ { NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 }, ++ { NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 }, ++ { NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 }, ++ { NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 }, ++ }; ++ ++ return uadk_digest_md_to_nid(md, name_to_nid, OSSL_NELEM(name_to_nid)); ++} ++ ++static int uadk_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md, ++ int sha1_allowed) ++{ ++ return uadk_digest_get_approved_nid(md); ++} ++ ++static int uadk_rsa_setup_md(struct PROV_RSA_SIG_CTX *ctx, const char *mdname, ++ const char *mdprops) ++{ ++ size_t mdname_len; ++ ++ if (mdprops == NULL) ++ mdprops = ctx->propq; ++ ++ if (mdname != NULL) { ++ EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); ++ int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); ++ int md_nid = uadk_digest_rsa_sign_get_md_nid(ctx->libctx, md, ++ sha1_allowed); ++ mdname_len = strlen(mdname); ++ if (md == NULL || md_nid <= 0 || ++ !uadk_rsa_check_padding(ctx, mdname, NULL, md_nid) || ++ mdname_len >= sizeof(ctx->mdname)) { ++ if (md == NULL) ++ UADK_ERR("invalid rsa name %s could not be fetched.\n", mdname); ++ if (md_nid <= 0) ++ UADK_ERR("digest name is not allowed digest = %s.\n", mdname); ++ if (mdname_len >= sizeof(ctx->mdname)) ++ UADK_ERR("invalid name %s exceeds name buffer length.\n", mdname); ++ if (md) ++ EVP_MD_free(md); ++ return 0; ++ } ++ ++ if (!ctx->mgf1_md_set) { ++ if (!EVP_MD_up_ref(md)) { ++ if (md) ++ EVP_MD_free(md); ++ return 0; ++ } ++ if (ctx->mgf1_md) ++ EVP_MD_free(ctx->mgf1_md); ++ ctx->mgf1_md = md; ++ ctx->mgf1_mdnid = md_nid; ++ OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname)); ++ } ++ ++ if (ctx->mdctx) { ++ EVP_MD_CTX_free(ctx->mdctx); ++ ctx->mdctx = NULL; ++ } ++ ++ if (ctx->md) ++ EVP_MD_free(ctx->md); ++ ++ ctx->md = md; ++ ctx->mdnid = md_nid; ++ OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname)); ++ } ++ ++ return 1; ++} ++ ++static int uadk_signature_rsa_digest_signverify_init(void *vprsactx, const char *mdname, ++ void *vrsa, const OSSL_PARAM params[], ++ int operation) ++{ ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ ++ if (!uadk_rsa_init(vprsactx, vrsa, params, operation)) ++ return 0; ++ ++ if (mdname != NULL && ++ (mdname[0] == '\0' || OPENSSL_strcasecmp(priv->mdname, mdname) != 0) && ++ !uadk_rsa_setup_md(priv, mdname, priv->propq)) ++ return 0; ++ ++ priv->flag_allow_md = 0; ++ ++ if (priv->mdctx == NULL) { ++ priv->mdctx = EVP_MD_CTX_new(); ++ if (priv->mdctx == NULL) ++ goto error; ++ } ++ ++ if (!EVP_DigestInit_ex2(priv->mdctx, priv->md, params)) ++ goto error; ++ ++ return 1; ++ ++error: ++ if (priv->mdctx) { ++ EVP_MD_CTX_free(priv->mdctx); ++ priv->mdctx = NULL; ++ } ++ ++ return 0; ++} ++ ++static int uadk_signature_rsa_digest_sign_init(void *vprsactx, const char *mdname, ++ void *vrsa, const OSSL_PARAM params[]) ++{ ++ return uadk_signature_rsa_digest_signverify_init(vprsactx, mdname, vrsa, ++ params, EVP_PKEY_OP_SIGN); ++} ++ ++static int uadk_signature_rsa_digest_sign_update(void *vprsactx, ++ const unsigned char *data, ++ size_t datalen) ++{ ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ ++ if (priv == NULL || priv->mdctx == NULL) ++ return UADK_P_FAIL; ++ ++ return EVP_DigestUpdate(priv->mdctx, data, datalen); ++} ++ ++#define ASN1_SEQUENCE_RSA 0x30 ++#define ASN1_OCTET_STRING_ 0x04 ++#define ASN1_NULL 0x05 ++#define ASN1_OID 0x06 ++ ++/* SHA OIDs are of the form: (2 16 840 1 101 3 4 2 |n|) */ ++#define ENCODE_DIGESTINFO_SHA(name, n, sz) \ ++static const unsigned char digestinfo_##name##_der[] = { \ ++ ASN1_SEQUENCE_RSA, 0x11 + sz, \ ++ ASN1_SEQUENCE_RSA, 0x0d, \ ++ ASN1_OID, 0x09, 2 * 40 + 16, 0x86, 0x48, 1, 101, 3, 4, 2, n, \ ++ ASN1_NULL, 0x00, \ ++ ASN1_OCTET_STRING_, sz \ ++} ++ ++/* SHA-1 (1 3 14 3 2 26) */ ++static const unsigned char digestinfo_sha1_der[] = { ++ ASN1_SEQUENCE_RSA, 0x0d + SHA_DIGEST_LENGTH, ++ ASN1_SEQUENCE_RSA, 0x09, ++ ASN1_OID, 0x05, 1 * 40 + 3, 14, 3, 2, 26, ++ ASN1_NULL, 0x00, ++ ASN1_OCTET_STRING_, SHA_DIGEST_LENGTH ++}; ++ ++ENCODE_DIGESTINFO_SHA(sha256, 0x01, SHA256_DIGEST_LENGTH); ++ENCODE_DIGESTINFO_SHA(sha384, 0x02, SHA384_DIGEST_LENGTH); ++ENCODE_DIGESTINFO_SHA(sha512, 0x03, SHA512_DIGEST_LENGTH); ++ENCODE_DIGESTINFO_SHA(sha224, 0x04, SHA224_DIGEST_LENGTH); ++ENCODE_DIGESTINFO_SHA(sha512_224, 0x05, SHA224_DIGEST_LENGTH); ++ENCODE_DIGESTINFO_SHA(sha512_256, 0x06, SHA256_DIGEST_LENGTH); ++ENCODE_DIGESTINFO_SHA(sha3_224, 0x07, SHA224_DIGEST_LENGTH); ++ENCODE_DIGESTINFO_SHA(sha3_256, 0x08, SHA256_DIGEST_LENGTH); ++ENCODE_DIGESTINFO_SHA(sha3_384, 0x09, SHA384_DIGEST_LENGTH); ++ENCODE_DIGESTINFO_SHA(sha3_512, 0x0a, SHA512_DIGEST_LENGTH); ++ ++#define MD_CASE(name) \ ++ case NID_##name: \ ++ *len = sizeof(digestinfo_##name##_der); \ ++ return digestinfo_##name##_der ++ ++ ++static const unsigned char *uadk_rsa_digestinfo_encoding(int md_nid, size_t *len) ++{ ++ switch (md_nid) { ++ MD_CASE(sha1); ++ MD_CASE(sha224); ++ MD_CASE(sha256); ++ MD_CASE(sha384); ++ MD_CASE(sha512); ++ MD_CASE(sha512_224); ++ MD_CASE(sha512_256); ++ MD_CASE(sha3_224); ++ MD_CASE(sha3_256); ++ MD_CASE(sha3_384); ++ MD_CASE(sha3_512); ++ default: ++ return NULL; ++ } ++} ++ ++/* Size of an SSL signature: MD5+SHA1 */ ++#define SSL_SIG_LENGTH 36 ++ ++/* ++ * Encodes a DigestInfo prefix of hash |type| and digest |m|, as ++ * described in EMSA-PKCS1-v1_5-ENCODE, RFC 3447 section 9.2 step 2. This ++ * encodes the DigestInfo (T and tLen) but does not add the padding. ++ * ++ * On success, it returns one and sets |*out| to a newly allocated buffer ++ * containing the result and |*out_len| to its length. The caller must free ++ * |*out| with OPENSSL_free(). Otherwise, it returns zero. ++ */ ++static int encode_pkcs1(unsigned char **out, size_t *out_len, int type, ++ const unsigned char *m, size_t m_len) ++{ ++ size_t di_prefix_len, dig_info_len; ++ const unsigned char *di_prefix; ++ unsigned char *dig_info; ++ ++ if (type == NID_undef) { ++ UADK_ERR("invalid: rsa unknown algorithm type.\n"); ++ return 0; ++ } ++ di_prefix = uadk_rsa_digestinfo_encoding(type, &di_prefix_len); ++ if (di_prefix == NULL) { ++ UADK_ERR("invalid: rsa di prefix is NULL.\n"); ++ return 0; ++ } ++ dig_info_len = di_prefix_len + m_len; ++ dig_info = OPENSSL_malloc(dig_info_len); ++ if (dig_info == NULL) { ++ UADK_ERR("failed to malloc dig info.\n"); ++ return 0; ++ } ++ memcpy(dig_info, di_prefix, di_prefix_len); ++ memcpy(dig_info + di_prefix_len, m, m_len); ++ ++ *out = dig_info; ++ *out_len = dig_info_len; ++ return 1; ++} ++ ++static int uadk_signature_rsa_digest_sign_final(void *vprsactx, unsigned char *sig, ++ size_t *siglen, size_t sigsize) ++{ ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ unsigned char digest[EVP_MAX_MD_SIZE]; ++ const unsigned char *encoded = NULL; ++ unsigned char *tmps = NULL; ++ size_t encoded_len = 0; ++ unsigned int dlen = 0; ++ int ret = UADK_P_FAIL; ++ size_t rsasize; ++ ++ if (priv == NULL) ++ return UADK_P_FAIL; ++ ++ if (priv->mdctx == NULL) ++ return UADK_P_FAIL; ++ ++ rsasize = uadk_rsa_size(priv->rsa); ++ ++ /* ++ * If sig is NULL then we're just finding out the sig size. Other fields ++ * are ignored. Defer to rsa_sign. ++ */ ++ if (sig != NULL) { ++ /* ++ * The digests used here are all known (see rsa_get_md_nid()), so they ++ * should not exceed the internal buffer size of EVP_MAX_MD_SIZE. ++ */ ++ if (!EVP_DigestFinal_ex(priv->mdctx, digest, &dlen)) ++ return UADK_P_FAIL; ++ } else { ++ *siglen = rsasize; ++ return 1; ++ } ++ ++ priv->flag_allow_md = 1; ++ ++ if (priv->pad_mode == RSA_PKCS1_PADDING) { ++ /* Compute the encoded digest. */ ++ if (priv->mdnid == NID_md5_sha1) { ++ /* ++ * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and ++ * earlier. It has no DigestInfo wrapper but otherwise is ++ * RSASSA-PKCS1-v1_5. ++ */ ++ if (dlen != SSL_SIG_LENGTH) { ++ UADK_ERR("invalid: rsa message length.\n"); ++ return 0; ++ } ++ encoded_len = SSL_SIG_LENGTH; ++ encoded = digest; ++ } else { ++ if (!encode_pkcs1(&tmps, &encoded_len, priv->mdnid, digest, dlen)) ++ goto err; ++ encoded = tmps; ++ } ++ } else { ++ UADK_ERR("This padding mode is not supported\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_rsa_private_sign(encoded_len, encoded, sig, priv->rsa, priv->pad_mode); ++ if (ret == UADK_DO_SOFT || ret == UADK_P_FAIL) ++ goto err; ++ ++ OPENSSL_clear_free(tmps, encoded_len); ++ return ret; ++err: ++ OPENSSL_clear_free(tmps, encoded_len); ++ if (ret == UADK_DO_SOFT) ++ return uadk_rsa_sw_sign(vprsactx, sig, siglen, sigsize, digest, dlen); ++ ++ return UADK_P_FAIL; ++} ++ ++static int uadk_signature_rsa_digest_verify_init(void *vprsactx, const char *mdname, ++ void *vrsa, const OSSL_PARAM params[]) ++{ ++ return uadk_signature_rsa_digest_signverify_init(vprsactx, mdname, vrsa, ++ params, EVP_PKEY_OP_VERIFY); ++} ++ ++static int uadk_signature_rsa_digest_verify_update(void *vprsactx, const unsigned char *data, ++ size_t datalen) ++{ ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ ++ if (priv == NULL || priv->mdctx == NULL) ++ return 0; ++ ++ return EVP_DigestUpdate(priv->mdctx, data, datalen); ++} ++ ++static int uadk_signature_rsa_digest_verify_final(void *vprsactx, const unsigned char *sig, ++ size_t siglen) ++{ ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ unsigned char *decrypt_buf = NULL, *encoded = NULL; ++ size_t decrypt_len, encoded_len = 0; ++ unsigned char digest[EVP_MAX_MD_SIZE]; ++ unsigned int dlen = 0; ++ int ret = UADK_P_FAIL; ++ ++ if (priv == NULL) ++ return UADK_P_FAIL; ++ priv->flag_allow_md = 1; ++ if (priv->mdctx == NULL) ++ return UADK_P_FAIL; ++ ++ /* ++ * The digests used here are all known (see rsa_get_md_nid()), so they ++ * should not exceed the internal buffer size of EVP_MAX_MD_SIZE. ++ */ ++ if (!EVP_DigestFinal_ex(priv->mdctx, digest, &dlen)) ++ return UADK_P_FAIL; ++ ++ if (priv->pad_mode == RSA_PKCS1_PADDING) { ++ if (siglen != (size_t)uadk_rsa_size(priv->rsa)) { ++ UADK_ERR("invalid: rsa signature length.\n"); ++ return UADK_P_FAIL; ++ } ++ ++ /* Recover the encoded digest. */ ++ decrypt_buf = OPENSSL_malloc(siglen); ++ if (decrypt_buf == NULL) { ++ UADK_ERR("failed to malloc decrypt buf.\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_rsa_public_verify(siglen, sig, decrypt_buf, ++ priv->rsa, priv->pad_mode); ++ if (ret <= 0) ++ goto err; ++ decrypt_len = ret; ++ ++ if (priv->mdnid == NID_md5_sha1) { ++ /* ++ * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and ++ * earlier. It has no DigestInfo wrapper but otherwise is ++ * RSASSA-PKCS1-v1_5. ++ */ ++ if (decrypt_len != SSL_SIG_LENGTH) { ++ UADK_ERR("invalid: rsa decrypt length.\n"); ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++ ++ if (siglen != SSL_SIG_LENGTH) { ++ UADK_ERR("invalid: rsa siglen.\n"); ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++ ++ if (memcmp(decrypt_buf, digest, SSL_SIG_LENGTH) != 0) { ++ UADK_ERR("failed to memcmp decrypt buf and digest.\n"); ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++ } else { ++ /* Construct the encoded digest and ensure it matches. */ ++ if (!encode_pkcs1(&encoded, &encoded_len, priv->mdnid, digest, dlen)) { ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++ ++ if (encoded_len != decrypt_len ++ || memcmp(encoded, decrypt_buf, encoded_len) != 0) { ++ UADK_ERR("failed to memcmp decrypt buf and encoded.\n"); ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++ } ++ ret = UADK_P_SUCCESS; ++ } else { ++ UADK_ERR("This padding mode is not supported\n"); ++ return UADK_P_FAIL; ++ } ++ ++err: ++ if (encoded) ++ OPENSSL_clear_free(encoded, encoded_len); ++ if (decrypt_buf) ++ OPENSSL_clear_free(decrypt_buf, siglen); ++ ++ if (ret == UADK_DO_SOFT) ++ return uadk_rsa_sw_verify(vprsactx, sig, siglen, digest, dlen); ++ ++ return ret; ++} ++ ++static void *uadk_signature_rsa_dupctx(void *vprsactx) ++{ ++ if (!get_default_rsa_signature().dupctx) ++ return NULL; ++ ++ return get_default_rsa_signature().dupctx(vprsactx); ++} ++ ++static int uadk_signature_rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) ++{ ++ if (!get_default_rsa_signature().get_ctx_params) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_signature().get_ctx_params(vprsactx, params); ++} ++ ++static const OSSL_PARAM *uadk_signature_rsa_gettable_ctx_md_params(void *vprsactx) ++{ ++ if (!get_default_rsa_signature().gettable_ctx_md_params) ++ return NULL; ++ ++ return get_default_rsa_signature().gettable_ctx_md_params(vprsactx); ++} ++ ++static int uadk_signature_rsa_set_ctx_md_params(void *vprsactx, const OSSL_PARAM params[]) ++{ ++ if (!get_default_rsa_signature().set_ctx_md_params) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_signature().set_ctx_md_params(vprsactx, params); ++} ++ ++static const OSSL_PARAM *uadk_signature_rsa_settable_ctx_md_params(void *vprsactx) ++{ ++ if (!get_default_rsa_signature().settable_ctx_md_params) ++ return NULL; ++ ++ return get_default_rsa_signature().settable_ctx_md_params(vprsactx); ++} ++ ++static const OSSL_PARAM *uadk_signature_rsa_gettable_ctx_params(ossl_unused void *vprsactx, ++ ossl_unused void *provctx) ++{ ++ if (!get_default_rsa_signature().gettable_ctx_params) ++ return NULL; ++ ++ return get_default_rsa_signature().gettable_ctx_params(vprsactx, provctx); ++} ++ ++static int uadk_signature_rsa_get_ctx_md_params(void *vprsactx, OSSL_PARAM *params) ++{ ++ if (!get_default_rsa_signature().get_ctx_md_params) ++ return UADK_P_FAIL; ++ ++ return get_default_rsa_signature().get_ctx_md_params(vprsactx, params); ++} +-- +2.25.1 + diff --git a/0024-uadk_provider-add-some-RSA-utils-functions-to-adapt-.patch b/0024-uadk_provider-add-some-RSA-utils-functions-to-adapt-.patch new file mode 100644 index 0000000..2f05047 --- /dev/null +++ b/0024-uadk_provider-add-some-RSA-utils-functions-to-adapt-.patch @@ -0,0 +1,221 @@ +From 92dfb6c3a708eb671aa9c8dfd701467bc3cf10ca Mon Sep 17 00:00:00 2001 +From: lizhi +Date: Thu, 18 Dec 2025 14:37:13 +0800 +Subject: [PATCH 24/32] uadk_provider: add some RSA utils functions to adapt + RSA with several padding modes + +Several utility functions are introduced to the RSA implementation. +These functions are designed to adapt the existing RSA implementation +to support multiple padding modes, enhancing the Extensibility +of the cryptographic operations. + +Signed-off-by: lizhi +Signed-off-by: JiangShui Yang +--- + src/Makefile.am | 1 + + src/uadk_prov_rsa_sign.c | 1 + + src/uadk_prov_rsa_utils.c | 125 ++++++++++++++++++++++++++++++++++++++ + src/uadk_prov_rsa_utils.h | 35 +++++++++++ + 4 files changed, 162 insertions(+) + create mode 100644 src/uadk_prov_rsa_utils.c + create mode 100644 src/uadk_prov_rsa_utils.h + +diff --git a/src/Makefile.am b/src/Makefile.am +index 7ce9aeb..22f1069 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -64,6 +64,7 @@ uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \ + uadk_prov_digest.c uadk_prov_cipher.c \ + uadk_prov_rsa.c uadk_prov_rsa_kmgmt.c \ + uadk_prov_rsa_enc.c uadk_prov_rsa_sign.c \ ++ uadk_prov_rsa_utils.c \ + uadk_prov_dh.c uadk_prov_bio.c \ + uadk_prov_der_writer.c uadk_prov_packet.c \ + uadk_prov_pkey.c uadk_prov_sm2.c \ +diff --git a/src/uadk_prov_rsa_sign.c b/src/uadk_prov_rsa_sign.c +index 8e0a571..98e1d59 100644 +--- a/src/uadk_prov_rsa_sign.c ++++ b/src/uadk_prov_rsa_sign.c +@@ -17,6 +17,7 @@ + * + */ + #include "uadk_prov_rsa.h" ++#include "uadk_prov_rsa_utils.h" + + UADK_PKEY_SIGNATURE_DESCR(rsa, RSA); + +diff --git a/src/uadk_prov_rsa_utils.c b/src/uadk_prov_rsa_utils.c +new file mode 100644 +index 0000000..a459077 +--- /dev/null ++++ b/src/uadk_prov_rsa_utils.c +@@ -0,0 +1,125 @@ ++// SPDX-License-Identifier: Apache-2.0 ++/* ++ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License 2.0 (the "License"). You may not use ++ * this file except in compliance with the License. You can obtain a copy ++ * in the file LICENSE in the source distribution or at ++ * https://www.openssl.org/source/license.html ++ */ ++#include "uadk_prov_rsa_utils.h" ++ ++struct rsa_pss_params_30_st *ossl_rsa_get0_pss_params_30(RSA *r) ++{ ++ return &r->pss_params; ++} ++ ++struct rsa_pss_params_30_st default_RSASSA_PSS_params = { ++ NID_sha1, /* default hashAlgorithm */ ++ { ++ NID_mgf1, /* default maskGenAlgorithm */ ++ NID_sha1 /* default MGF1 hash */ ++ }, ++ 20, /* default saltLength */ ++ 1 /* default trailerField (0xBC) */ ++}; ++ ++int ossl_rsa_pss_params_30_is_unrestricted(const struct rsa_pss_params_30_st *rsa_pss_params) ++{ ++ static struct rsa_pss_params_30_st pss_params_cmp = { 0, }; ++ ++ return !rsa_pss_params || ++ memcmp(rsa_pss_params, &pss_params_cmp, ++ sizeof(*rsa_pss_params)) == 0; ++} ++ ++int ossl_rsa_pss_params_30_maskgenhashalg(const struct rsa_pss_params_30_st *rsa_pss_params) ++{ ++ if (!rsa_pss_params) ++ return default_RSASSA_PSS_params.hash_algorithm_nid; ++ return rsa_pss_params->mask_gen.hash_algorithm_nid; ++} ++ ++int ossl_rsa_pss_params_30_saltlen(const struct rsa_pss_params_30_st *rsa_pss_params) ++{ ++ if (!rsa_pss_params) ++ return default_RSASSA_PSS_params.salt_len; ++ return rsa_pss_params->salt_len; ++} ++ ++int ossl_rsa_pss_params_30_hashalg(const struct rsa_pss_params_30_st *rsa_pss_params) ++{ ++ if (!rsa_pss_params) ++ return default_RSASSA_PSS_params.hash_algorithm_nid; ++ return rsa_pss_params->hash_algorithm_nid; ++} ++const char *nid2name(int meth, const OSSL_ITEM *items, size_t items_n) ++{ ++ size_t i; ++ ++ for (i = 0; i < items_n; i++) ++ if (meth == (int)items[i].id) ++ return items[i].ptr; ++ return NULL; ++} ++ ++static const OSSL_ITEM oaeppss_name_nid_map[] = { ++ { NID_sha1, OSSL_DIGEST_NAME_SHA1 }, ++ { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 }, ++ { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 }, ++ { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 }, ++ { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 }, ++ { NID_sha512_224, OSSL_DIGEST_NAME_SHA2_512_224 }, ++ { NID_sha512_256, OSSL_DIGEST_NAME_SHA2_512_256 }, ++}; ++ ++const char *ossl_rsa_oaeppss_nid2name(int md) ++{ ++ return nid2name(md, oaeppss_name_nid_map, OSSL_NELEM(oaeppss_name_nid_map)); ++} ++ ++/* ++ * Internal library code deals with NIDs, so we need to translate from a name. ++ * We do so using EVP_MD_is_a(), and therefore need a name to NID map. ++ */ ++static int ossl_digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t it_len) ++{ ++ size_t i; ++ ++ if (!md) ++ return NID_undef; ++ ++ for (i = 0; i < it_len; i++) ++ if (EVP_MD_is_a(md, it[i].ptr)) ++ return (int)it[i].id; ++ return NID_undef; ++} ++ ++/* ++ * Retrieve one of the FIPS approved hash algorithms by nid. ++ * See FIPS 180-4 "Secure Hash Standard" and FIPS 202 - SHA-3. ++ */ ++static int ossl_digest_get_approved_nid(const EVP_MD *md) ++{ ++ static const OSSL_ITEM name_to_nid[] = { ++ { NID_sha1, OSSL_DIGEST_NAME_SHA1 }, ++ { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 }, ++ { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 }, ++ { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 }, ++ { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 }, ++ { NID_sha512_224, OSSL_DIGEST_NAME_SHA2_512_224 }, ++ { NID_sha512_256, OSSL_DIGEST_NAME_SHA2_512_256 }, ++ { NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 }, ++ { NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 }, ++ { NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 }, ++ { NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 }, ++ }; ++ ++ return ossl_digest_md_to_nid(md, name_to_nid, OSSL_NELEM(name_to_nid)); ++} ++ ++int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md, ++ int sha1_allowed) ++{ ++ return ossl_digest_get_approved_nid(md); ++} +diff --git a/src/uadk_prov_rsa_utils.h b/src/uadk_prov_rsa_utils.h +new file mode 100644 +index 0000000..9dce2b0 +--- /dev/null ++++ b/src/uadk_prov_rsa_utils.h +@@ -0,0 +1,35 @@ ++// SPDX-License-Identifier: Apache-2.0 ++/* ++ * Copyright 2023-2024 Huawei Technologies Co.,Ltd. All rights reserved. ++ * Copyright 2023-2024 Linaro ltd. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ */ ++#ifndef UADK_PROV_PROV_RSA_UTILS_H ++#define UADK_PROV_PROV_RSA_UTILS_H ++#include "uadk_prov_rsa.h" ++ ++/* True if PSS parameters are restricted */ ++#define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1) ++ ++struct rsa_pss_params_30_st *ossl_rsa_get0_pss_params_30(RSA *r); ++int ossl_rsa_pss_params_30_is_unrestricted(const struct rsa_pss_params_30_st *rsa_pss_params); ++int ossl_rsa_pss_params_30_maskgenhashalg(const struct rsa_pss_params_30_st *rsa_pss_params); ++int ossl_rsa_pss_params_30_saltlen(const struct rsa_pss_params_30_st *rsa_pss_params); ++int ossl_rsa_pss_params_30_hashalg(const struct rsa_pss_params_30_st *rsa_pss_params); ++const char *nid2name(int meth, const OSSL_ITEM *items, size_t items_n); ++const char *ossl_rsa_oaeppss_nid2name(int md); ++int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md, int sha1_allowed); ++ ++#endif +-- +2.25.1 + diff --git a/0025-uadk_provider-adapt-rsa-signature-operation-with-X93.patch b/0025-uadk_provider-adapt-rsa-signature-operation-with-X93.patch new file mode 100644 index 0000000..60ca85b --- /dev/null +++ b/0025-uadk_provider-adapt-rsa-signature-operation-with-X93.patch @@ -0,0 +1,1370 @@ +From 97b6b7962e965549367ec9dd95574c09fa85f571 Mon Sep 17 00:00:00 2001 +From: lizhi +Date: Thu, 18 Dec 2025 14:37:18 +0800 +Subject: [PATCH 25/32] uadk_provider: adapt rsa signature operation with X931 + and PKCS1_PSS padding modes + +Add support for RSA signature padding modes with OpenSSL provider +mechanism, including RSA_X931_PADDING and RSA_PKCS1_PSS_PADDING. + +Test with: +openssl dgst -sha256 -sign privkey.pem -sigopt rsa_padding_mode:x931 +-out signature.bin message.txt +openssl dgst -sha256 -verify pubkey.pem -sigopt rsa_padding_mode:x931 +-signature signature.bin message.txt + +openssl dgst -sha256 -sign privkey.pem -sigopt rsa_padding_mode:pss +-out signature.bin message.txt +openssl dgst -sha256 -verify pubkey.pem -sigopt rsa_padding_mode:pss +-signature signature.bin message.txt + +Signed-off-by: lizhi +Signed-off-by: JiangShui Yang +--- + src/uadk_prov_rsa_sign.c | 990 ++++++++++++++++++++++++++++++--------- + 1 file changed, 764 insertions(+), 226 deletions(-) + +diff --git a/src/uadk_prov_rsa_sign.c b/src/uadk_prov_rsa_sign.c +index 98e1d59..5009a0b 100644 +--- a/src/uadk_prov_rsa_sign.c ++++ b/src/uadk_prov_rsa_sign.c +@@ -19,6 +19,15 @@ + #include "uadk_prov_rsa.h" + #include "uadk_prov_rsa_utils.h" + ++#define PRIME_CHECK_BIT_NUM 4 ++/* Size of an SSL signature: MD5+SHA1 */ ++#define SSL_SIG_LENGTH 36 ++#define MDC2_MESSAGE_LEN 16 ++#define MDC2_HEAD_LEN 2 ++#define RSA_MDC2_FIRST_BYTE 0x4 ++#define RSA_MDC2_SECOND_BYTE 0x10 ++#define RSA_PSS_SIZE_MASK 0x7 ++ + UADK_PKEY_SIGNATURE_DESCR(rsa, RSA); + + struct PROV_RSA_SIG_CTX { +@@ -61,6 +70,9 @@ struct PROV_RSA_SIG_CTX { + + static pthread_mutex_t sig_mutex = PTHREAD_MUTEX_INITIALIZER; + ++static int encode_pkcs1(unsigned char **out, size_t *out_len, int type, ++ const unsigned char *m, size_t m_len); ++ + static UADK_PKEY_SIGNATURE get_default_rsa_signature(void) + { + static UADK_PKEY_SIGNATURE s_signature; +@@ -83,13 +95,20 @@ static UADK_PKEY_SIGNATURE get_default_rsa_signature(void) + return s_signature; + } + ++static size_t uadk_rsa_get_md_size(struct PROV_RSA_SIG_CTX *prsactx) ++{ ++ if (prsactx->md != NULL) ++ return EVP_MD_get_size(prsactx->md); ++ return UADK_P_FAIL; ++} ++ + static int setup_tbuf(struct PROV_RSA_SIG_CTX *ctx) + { + if (ctx->tbuf != NULL) + return UADK_P_SUCCESS; + + ctx->tbuf = OPENSSL_malloc(uadk_rsa_size(ctx->rsa)); +- if (ctx->tbuf == NULL) { ++ if (!ctx->tbuf) { + UADK_ERR("failed to zalloc ctx tbuf!\n"); + return UADK_P_FAIL; + } +@@ -119,19 +138,21 @@ static int add_rsa_prienc_padding(int flen, const unsigned char *from, + switch (padding) { + case RSA_PKCS1_PADDING: + ret = RSA_padding_add_PKCS1_type_1(to_buf, tlen, from, flen); +- if (!ret) +- UADK_ERR("RSA_PKCS1_PADDING err.\n"); + break; + case RSA_X931_PADDING: + ret = RSA_padding_add_X931(to_buf, tlen, from, flen); +- if (ret == -1) +- UADK_ERR("RSA_X931_PADDING err.\n"); ++ break; ++ case RSA_NO_PADDING: ++ ret = RSA_padding_add_none(to_buf, tlen, from, flen); + break; + default: + ret = UADK_P_FAIL; + } +- if (ret <= 0) ++ ++ if (ret <= UADK_P_FAIL) { ++ UADK_ERR("failed to add padding type %d in rsa sign\n", padding); + ret = UADK_P_FAIL; ++ } + + return ret; + } +@@ -145,20 +166,24 @@ static int check_rsa_pubdec_padding(unsigned char *to, int num, + switch (padding) { + case RSA_PKCS1_PADDING: + ret = RSA_padding_check_PKCS1_type_1(to, num, buf, len, num); +- if (ret == CHECK_PADDING_FAIL) +- UADK_ERR("RSA_PKCS1_PADDING err.\n"); + break; + case RSA_X931_PADDING: + ret = RSA_padding_check_X931(to, num, buf, len, num); +- if (ret == CHECK_PADDING_FAIL) +- UADK_ERR("RSA_X931_PADDING err.\n"); ++ break; ++ case RSA_NO_PADDING: ++ memcpy(to, buf, len); ++ ret = len; + break; + default: + ret = UADK_P_FAIL; ++ UADK_ERR("failed to check padding type %d in rsa verify\n", padding); ++ break; + } + +- if (ret == CHECK_PADDING_FAIL) ++ if (ret < 0) { ++ UADK_ERR("failed to check padding type %d in rsa verify\n", padding); + ret = UADK_P_FAIL; ++ } + + return ret; + } +@@ -187,11 +212,9 @@ static int rsa_get_sign_res(int padding, BIGNUM *to_bn, const BIGNUM *n, + + static int rsa_get_verify_res(int padding, const BIGNUM *n, BIGNUM *ret_bn) + { +- BIGNUM *to_bn = NULL; +- + if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret_bn)[0] & 0xf) + != 0x0c)) { +- if (!BN_sub(to_bn, n, ret_bn)) ++ if (!BN_sub(ret_bn, n, ret_bn)) + return UADK_P_FAIL; + } + +@@ -373,15 +396,227 @@ free_pkey: + return ret; + } + +-static int uadk_rsa_init(void *vprsactx, void *vrsa, ++static int rsa_check_parameters(struct PROV_RSA_SIG_CTX *prsactx, int min_saltlen) ++{ ++ int max_saltlen; ++ ++ if (prsactx->pad_mode == RSA_PKCS1_PSS_PADDING) { ++ /* See if minimum salt length exceeds maximum possible */ ++ max_saltlen = RSA_size(prsactx->rsa) - EVP_MD_get_size(prsactx->md); ++ if ((RSA_bits(prsactx->rsa) & RSA_PSS_SIZE_MASK) == 1) ++ max_saltlen--; ++ if (min_saltlen < 0 || min_saltlen > max_saltlen) { ++ UADK_ERR("invalid: incorrect salt length %d\n", min_saltlen); ++ return UADK_P_FAIL; ++ } ++ prsactx->min_saltlen = min_saltlen; ++ } ++ return UADK_P_SUCCESS; ++} ++ ++static int rsa_check_padding(const struct PROV_RSA_SIG_CTX *prsactx, ++ const char *mdname, const char *mgf1_mdname, ++ int mdnid) ++{ ++ switch (prsactx->pad_mode) { ++ case RSA_NO_PADDING: ++ if (mdname != NULL || mdnid != NID_undef) { ++ UADK_ERR("invalid: digest %s or mdnid %d not allowed in NO_PADDING mode\n", ++ mdname, mdnid); ++ return UADK_P_FAIL; ++ } ++ break; ++ case RSA_X931_PADDING: ++ if (RSA_X931_hash_id(mdnid) == -1) { ++ UADK_ERR("invalid: mdnid %d not allowed in X931_PADDING mode\n", mdnid); ++ return UADK_P_FAIL; ++ } ++ break; ++ case RSA_PKCS1_PSS_PADDING: ++ if (rsa_pss_restricted(prsactx)) ++ if ((mdname != NULL && !EVP_MD_is_a(prsactx->md, mdname)) ++ || (mgf1_mdname != NULL ++ && !EVP_MD_is_a(prsactx->mgf1_md, mgf1_mdname))) { ++ UADK_ERR("invalid: incorrect digest %s in PSS mode\n", mdname); ++ return UADK_P_FAIL; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int rsa_setup_mgf1_md(struct PROV_RSA_SIG_CTX *ctx, const char *mdname, ++ const char *mdprops) ++{ ++ size_t len; ++ EVP_MD *md; ++ int mdnid; ++ ++ if (!mdprops) ++ mdprops = ctx->propq; ++ ++ md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); ++ if (!md) { ++ UADK_ERR("failed to fetch digest %s\n", mdname); ++ return UADK_P_FAIL; ++ } ++ /* The default for mgf1 is SHA1 - so allow SHA1 */ ++ mdnid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md, 1); ++ if (mdnid <= 0 || !rsa_check_padding(ctx, NULL, mdname, mdnid)) { ++ if (mdnid <= 0) ++ UADK_ERR("invalid: %s is not a supported digest\n", mdname); ++ EVP_MD_free(md); ++ return UADK_P_FAIL; ++ } ++ len = OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname)); ++ if (len >= sizeof(ctx->mgf1_mdname)) { ++ UADK_ERR("invalid: %s exceeds name buffer length\n", mdname); ++ EVP_MD_free(md); ++ return UADK_P_FAIL; ++ } ++ ++ EVP_MD_free(ctx->mgf1_md); ++ ctx->mgf1_md = md; ++ ctx->mgf1_mdnid = mdnid; ++ ctx->mgf1_md_set = 1; ++ return UADK_P_SUCCESS; ++} ++ ++static int rsa_setup_md(struct PROV_RSA_SIG_CTX *ctx, const char *mdname, ++ const char *mdprops) ++{ ++ if (!mdprops) ++ mdprops = ctx->propq; ++ ++ if (mdname != NULL) { ++ EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); ++ int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); ++ int md_nid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md, sha1_allowed); ++ size_t mdname_len = strlen(mdname); ++ bool md_ret = (!md) || (md_nid <= 0); ++ ++ if (md_ret || !rsa_check_padding(ctx, mdname, NULL, md_nid) || ++ mdname_len >= sizeof(ctx->mdname)) { ++ if (!md) ++ UADK_ERR("invalid: %s could not be fetched\n", mdname); ++ if (md_nid <= 0) ++ UADK_ERR("invalid: %s is not a supported digest\n", mdname); ++ if (mdname_len >= sizeof(ctx->mdname)) ++ UADK_ERR("invalid: %s exceeds name buffer length\n", mdname); ++ EVP_MD_free(md); ++ return UADK_P_FAIL; ++ } ++ ++ if (!ctx->flag_allow_md) { ++ if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) { ++ UADK_ERR("invalid: %s is not the same as ctx %s\n", ++ mdname, ctx->mdname); ++ EVP_MD_free(md); ++ return UADK_P_FAIL; ++ } ++ EVP_MD_free(md); ++ return UADK_P_SUCCESS; ++ } ++ ++ if (!ctx->mgf1_md_set) { ++ if (!EVP_MD_up_ref(md)) { ++ EVP_MD_free(md); ++ return UADK_P_FAIL; ++ } ++ EVP_MD_free(ctx->mgf1_md); ++ ctx->mgf1_md = md; ++ ctx->mgf1_mdnid = md_nid; ++ OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname)); ++ } ++ ++ EVP_MD_CTX_free(ctx->mdctx); ++ EVP_MD_free(ctx->md); ++ ++ ctx->mdctx = NULL; ++ ctx->md = md; ++ ctx->mdnid = md_nid; ++ OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname)); ++ } ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_signature_rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) ++{ ++ if (!get_default_rsa_signature().set_ctx_params) ++ return UADK_P_FAIL; ++ return get_default_rsa_signature().set_ctx_params(vprsactx, params); ++} ++ ++static int uadk_rsa_init_pss_mode(struct PROV_RSA_SIG_CTX *ctx, void *vrsa) ++{ ++ const struct rsa_pss_params_30_st *pss; ++ int md_nid, mgf1md_nid, min_saltlen; ++ const char *mdname, *mgf1mdname; ++ size_t len; ++ ++ pss = ossl_rsa_get0_pss_params_30(ctx->rsa); ++ if (ossl_rsa_pss_params_30_is_unrestricted(pss)) ++ return UADK_P_SUCCESS; ++ ++ md_nid = ossl_rsa_pss_params_30_hashalg(pss); ++ mgf1md_nid = ossl_rsa_pss_params_30_maskgenhashalg(pss); ++ min_saltlen = ossl_rsa_pss_params_30_saltlen(pss); ++ mdname = ossl_rsa_oaeppss_nid2name(md_nid); ++ if (!mdname) { ++ UADK_ERR("invalid: PSS restrictions lack digest\n"); ++ return UADK_P_FAIL; ++ } ++ mgf1mdname = ossl_rsa_oaeppss_nid2name(mgf1md_nid); ++ if (!mgf1mdname) { ++ UADK_ERR("invalid: PSS restrictions lack MGF1 digest\n"); ++ return UADK_P_FAIL; ++ } ++ ++ len = OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname)); ++ if (len >= sizeof(ctx->mdname)) { ++ UADK_ERR("invalid: hash algorithm name too long\n"); ++ return UADK_P_FAIL; ++ } ++ len = OPENSSL_strlcpy(ctx->mgf1_mdname, mgf1mdname, sizeof(ctx->mgf1_mdname)); ++ if (len >= sizeof(ctx->mgf1_mdname)) { ++ UADK_ERR("invalid: MGF1 hash algorithm name too long\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ctx->saltlen = min_saltlen; ++ if (!rsa_setup_mgf1_md(ctx, mgf1mdname, ctx->propq) || ++ !rsa_setup_md(ctx, mdname, ctx->propq) || ++ !rsa_check_parameters(ctx, min_saltlen)) { ++ return UADK_P_FAIL; ++ } ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_rsa_signverify_init(void *vprsactx, void *vrsa, + const OSSL_PARAM params[], int operation) + { + struct PROV_RSA_SIG_CTX *ctx = (struct PROV_RSA_SIG_CTX *)vprsactx; + +- if (ctx == NULL || vrsa == NULL) ++ if (!ctx) ++ return UADK_P_FAIL; ++ ++ if (!vrsa && !ctx->rsa) { ++ UADK_ERR("invalid: no available rsa\n"); + return UADK_P_FAIL; ++ } ++ ++ if (vrsa != NULL) { ++ if (!RSA_up_ref(vrsa)) ++ return UADK_P_FAIL; ++ RSA_free(ctx->rsa); ++ ctx->rsa = vrsa; ++ } + +- ctx->rsa = vrsa; + ctx->operation = operation; + + /* Maximum for sign, auto for verify */ +@@ -394,6 +629,8 @@ static int uadk_rsa_init(void *vprsactx, void *vrsa, + break; + case RSA_FLAG_TYPE_RSASSAPSS: + ctx->pad_mode = RSA_PKCS1_PSS_PADDING; ++ if (!uadk_rsa_init_pss_mode(ctx, vrsa)) ++ return UADK_P_FAIL; + break; + default: + UADK_ERR("rsa init operation not supported this keytype!\n"); +@@ -403,26 +640,120 @@ static int uadk_rsa_init(void *vprsactx, void *vrsa, + if (uadk_prov_rsa_init()) + ctx->soft = 1; + ++ if (!uadk_signature_rsa_set_ctx_params(ctx, params)) ++ return UADK_P_FAIL; ++ + return UADK_P_SUCCESS; + } + + static int uadk_signature_rsa_verify_recover_init(void *vprsactx, void *vrsa, + const OSSL_PARAM params[]) + { +- return UADK_P_SUCCESS; ++ return uadk_rsa_signverify_init(vprsactx, vrsa, params, ++ EVP_PKEY_OP_VERIFYRECOVER); ++} ++ ++static int uadk_rsa_sw_verify_recover(void *vprsactx, unsigned char *rout, ++ size_t *routlen, size_t routsize, ++ const unsigned char *sig, size_t siglen) ++{ ++ if (!enable_sw_offload || !get_default_rsa_signature().verify_recover) ++ return UADK_P_FAIL; ++ ++ UADK_INFO("switch to openssl software calculation in verify recover.\n"); ++ return get_default_rsa_signature().verify_recover(vprsactx, rout, routlen, ++ routsize, sig, siglen); ++} ++ ++static int uadk_signature_rsa_verify_x931_recover(struct PROV_RSA_SIG_CTX *priv, ++ unsigned char *rout, ++ size_t *routlen, size_t routsize, ++ const unsigned char *sig, size_t siglen) ++{ ++ int ret; ++ ++ if (!setup_tbuf(priv)) ++ return UADK_P_FAIL; ++ ++ /* RSA in X931 mode returns both the hash's length and algorithm identifier. */ ++ ret = uadk_prov_rsa_public_verify(siglen, sig, priv->tbuf, priv->rsa, RSA_X931_PADDING); ++ if (ret <= UADK_P_FAIL) ++ return ret; ++ ret--; ++ if (priv->tbuf[ret] != RSA_X931_hash_id(priv->mdnid)) { ++ UADK_ERR("invalid: hash id mismatch in rsa x931 verify recover\n"); ++ return UADK_P_FAIL; ++ } ++ ++ if (ret != EVP_MD_get_size(priv->md)) { ++ UADK_ERR("invalid: incorrect digest size in rsa x931 verify recover\n"); ++ return UADK_P_FAIL; ++ } ++ ++ *routlen = ret; ++ if (rout != priv->tbuf) { ++ if (routsize < (size_t)ret) { ++ UADK_ERR("invalid: incorrect buf size in rsa x931 verify recover\n"); ++ return UADK_P_FAIL; ++ } ++ memcpy(rout, priv->tbuf, ret); ++ } ++ return ret; + } + + static int uadk_signature_rsa_verify_recover(void *vprsactx, unsigned char *rout, + size_t *routlen, size_t routsize, + const unsigned char *sig, size_t siglen) + { ++ struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ int ret; ++ ++ if (!priv || priv->soft) { ++ ret = UADK_DO_SOFT; ++ goto exe_soft; ++ } ++ ++ if (!rout) { ++ *routlen = RSA_size(priv->rsa); ++ return UADK_P_SUCCESS; ++ } ++ ++ if (!priv->md) { ++ ret = uadk_prov_rsa_public_verify(siglen, sig, rout, ++ priv->rsa, priv->pad_mode); ++ goto end; ++ } ++ ++ switch (priv->pad_mode) { ++ case RSA_X931_PADDING: ++ ret = uadk_signature_rsa_verify_x931_recover(priv, rout, routlen, routsize, ++ sig, siglen); ++ break; ++ default: ++ if (!get_default_rsa_signature().verify_recover) ++ return UADK_P_FAIL; ++ return get_default_rsa_signature().verify_recover(priv, rout, routlen, ++ routsize, sig, siglen); ++ } ++ ++end: ++ if (ret == UADK_DO_SOFT) ++ goto exe_soft; ++ if (ret <= UADK_P_FAIL) { ++ UADK_ERR("failed to do rsa verify recover with padding %d\n", priv->pad_mode); ++ return UADK_P_FAIL; ++ } ++ *routlen = ret; + return UADK_P_SUCCESS; ++ ++exe_soft: ++ return uadk_rsa_sw_verify_recover(vprsactx, rout, routlen, routsize, sig, siglen); + } + + static int uadk_signature_rsa_verify_init(void *vprsactx, void *vrsa, + const OSSL_PARAM params[]) + { +- return uadk_rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY); ++ return uadk_rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY); + } + + static int uadk_rsa_sw_verify(void *vprsactx, const unsigned char *sig, +@@ -437,28 +768,182 @@ static int uadk_rsa_sw_verify(void *vprsactx, const unsigned char *sig, + return get_default_rsa_signature().verify(vprsactx, sig, siglen, tbs, tbslen); + } + ++static int uadk_rsa_pkcs1_verify(struct PROV_RSA_SIG_CTX *priv, const unsigned char *sig, ++ size_t siglen, const unsigned char *tbs, ++ size_t tbslen) ++{ ++ unsigned char *decrypt_buf, *encoded = NULL; ++ size_t decrypt_len, encoded_len = 0; ++ int ret; ++ ++ if (siglen != (size_t)uadk_rsa_size(priv->rsa)) { ++ UADK_ERR("invalid: siglen size %zu is wrong\n", siglen); ++ return UADK_P_FAIL; ++ } ++ ++ /* Recover the encoded digest. */ ++ decrypt_buf = OPENSSL_malloc(siglen); ++ if (!decrypt_buf) { ++ UADK_ERR("failed to alloc decrypt_buf\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_rsa_public_verify(siglen, sig, decrypt_buf, ++ priv->rsa, RSA_PKCS1_PADDING); ++ if (ret <= 0) ++ goto err; ++ decrypt_len = ret; ++ ++#ifndef FIPS_MODULE ++ if (priv->mdnid == NID_md5_sha1) { ++ /* ++ * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and ++ * earlier. It has no DigestInfo wrapper but otherwise is ++ * RSASSA-PKCS1-v1_5. ++ */ ++ if (decrypt_len != SSL_SIG_LENGTH || tbslen != SSL_SIG_LENGTH) { ++ UADK_ERR("invalid: decrypt_len %zu or tbslen %zu\n" ++ "not equal to siglen %d\n", ++ decrypt_len, tbslen, SSL_SIG_LENGTH); ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++ ++ if (memcmp(decrypt_buf, tbs, SSL_SIG_LENGTH) != 0) { ++ UADK_ERR("invalid: decrypt_buf is not equal to tbs\n"); ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++ } else if ((priv->mdnid == NID_mdc2 && ++ decrypt_len == (MDC2_MESSAGE_LEN + MDC2_HEAD_LEN) && ++ decrypt_buf[0] == RSA_MDC2_FIRST_BYTE && ++ decrypt_buf[1] == RSA_MDC2_SECOND_BYTE)) { ++ if (tbslen != MDC2_MESSAGE_LEN) { ++ UADK_ERR("invalid: tbslen size %zu is wrong\n", tbslen); ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++ ++ if (memcmp(tbs, decrypt_buf + MDC2_HEAD_LEN, MDC2_MESSAGE_LEN) != 0) { ++ UADK_ERR("invalid: decrypt_buf is not equal to tbs\n"); ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++ } else { ++#endif /* FIPS_MODULE */ ++ /* Construct the encoded digest and ensure it matches. */ ++ if (!encode_pkcs1(&encoded, &encoded_len, priv->mdnid, tbs, tbslen)) { ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++ ++ if (encoded_len != decrypt_len || ++ memcmp(encoded, decrypt_buf, encoded_len) != 0) { ++ UADK_ERR("invalid: encoded_len %zu is not equal to decrypt_len %zu\n" ++ "or encoded is not equal to encoded_len\n", ++ encoded_len, decrypt_len); ++ ret = UADK_P_FAIL; ++ goto err; ++ } ++#ifndef FIPS_MODULE ++ } ++#endif /* FIPS_MODULE */ ++ ret = UADK_P_SUCCESS; ++err: ++ OPENSSL_clear_free(encoded, encoded_len); ++ OPENSSL_clear_free(decrypt_buf, siglen); ++ return ret; ++} ++ ++static int uadk_rsa_pkcs1_pss_verify(struct PROV_RSA_SIG_CTX *priv, ++ const unsigned char *sig, size_t siglen, ++ const unsigned char *tbs, size_t tbslen) ++{ ++ size_t mdsize = uadk_rsa_get_md_size(priv); ++ int ret; ++ ++ if (tbslen != mdsize) { ++ UADK_ERR("RSA verify fail, tbslen %zu is not equal to mdsize %zu\n", ++ tbslen, mdsize); ++ return UADK_P_FAIL; ++ } ++ ++ if (!setup_tbuf(priv)) ++ return UADK_P_FAIL; ++ ++ ret = uadk_prov_rsa_public_verify(siglen, sig, priv->tbuf, ++ priv->rsa, RSA_NO_PADDING); ++ if (ret <= UADK_P_FAIL) ++ return ret; ++ ++ ret = RSA_verify_PKCS1_PSS_mgf1(priv->rsa, tbs, ++ priv->md, priv->mgf1_md, ++ priv->tbuf, ++ priv->saltlen); ++ if (ret <= UADK_P_FAIL) { ++ UADK_ERR("failed to do RSA_verify_PKCS1_PSS_mgf1\n"); ++ return UADK_P_FAIL; ++ } ++ ++ return UADK_P_SUCCESS; ++} ++ + static int uadk_signature_rsa_verify(void *vprsactx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen) + { + struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; + size_t rslen = 0; ++ int ret; + +- if (priv->soft) { +- rslen = UADK_DO_SOFT; ++ if (!priv || priv->soft) { ++ ret = UADK_DO_SOFT; + goto exe_soft; + } + +- /* todo call public_verify */ +- if (priv->md != NULL) { +- /* todo */ +- } else { +- if (!setup_tbuf(priv)) ++ if (!priv->md) { ++ if (!setup_tbuf(priv)) { ++ UADK_ERR("failed to setup tbuf in rsa verify\n"); ++ return UADK_P_FAIL; ++ } ++ ret = uadk_prov_rsa_public_verify(siglen, sig, priv->tbuf, ++ priv->rsa, priv->pad_mode); ++ if (ret > UADK_P_FAIL) ++ rslen = ret; ++ goto end; ++ } ++ ++ switch (priv->pad_mode) { ++ case RSA_PKCS1_PADDING: ++ ret = uadk_rsa_pkcs1_verify(priv, sig, siglen, tbs, tbslen); ++ if (ret == UADK_P_SUCCESS) ++ return ret; ++ break; ++ case RSA_X931_PADDING: ++ if (!setup_tbuf(priv)) { ++ UADK_ERR("failed to setup tbuf in rsa x931 verify\n"); + return UADK_P_FAIL; +- rslen = uadk_prov_rsa_public_verify(siglen, sig, priv->tbuf, +- priv->rsa, priv->pad_mode); +- if (rslen == UADK_DO_SOFT || rslen == UADK_P_FAIL) +- goto exe_soft; ++ } ++ /* software fallback will be done once in verify_recover, don't fallback here */ ++ ret = uadk_signature_rsa_verify_recover(priv, priv->tbuf, &rslen, 0, sig, siglen); ++ if (ret <= UADK_P_FAIL) ++ return ret; ++ break; ++ case RSA_PKCS1_PSS_PADDING: ++ ret = uadk_rsa_pkcs1_pss_verify(priv, sig, siglen, tbs, tbslen); ++ if (ret == UADK_P_SUCCESS) ++ return ret; ++ break; ++ default: ++ ret = UADK_DO_SOFT; ++ } ++ ++end: ++ if (ret == UADK_DO_SOFT) ++ goto exe_soft; ++ if (ret <= UADK_P_FAIL) { ++ UADK_ERR("failed to do rsa verify with padding %d\n", priv->pad_mode); ++ return UADK_P_FAIL; + } + + if ((rslen != tbslen) || memcmp(tbs, priv->tbuf, rslen)) +@@ -467,9 +952,7 @@ static int uadk_signature_rsa_verify(void *vprsactx, const unsigned char *sig, + return UADK_P_SUCCESS; + + exe_soft: +- if (rslen == UADK_DO_SOFT) +- return uadk_rsa_sw_verify(vprsactx, sig, siglen, tbs, tbslen); +- return UADK_P_FAIL; ++ return uadk_rsa_sw_verify(vprsactx, sig, siglen, tbs, tbslen); + } + + static int uadk_rsa_sw_sign(void *vprsactx, unsigned char *sig, +@@ -483,49 +966,232 @@ static int uadk_rsa_sw_sign(void *vprsactx, unsigned char *sig, + return get_default_rsa_signature().sign(vprsactx, sig, siglen, sigsize, tbs, tbslen); + } + ++ ++static int uadk_rsa_pks1_sign(struct PROV_RSA_SIG_CTX *priv, const unsigned char *tbs, ++ size_t tbslen, unsigned char *sig) ++{ ++ const unsigned char *encoded = NULL; ++ unsigned char *tmps = NULL; ++ size_t encoded_len = 0; ++ int ret; ++ ++ /* Compute the encoded digest. */ ++ if (priv->mdnid == NID_md5_sha1) { ++ /* ++ * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and ++ * earlier. It has no DigestInfo wrapper but otherwise is ++ * RSASSA-PKCS1-v1_5. ++ */ ++ if (tbslen != SSL_SIG_LENGTH) { ++ UADK_ERR("invalid: rsa message length %zu is error\n", tbslen); ++ return UADK_P_FAIL; ++ } ++ encoded_len = SSL_SIG_LENGTH; ++ encoded = tbs; ++ } else { ++ if (!encode_pkcs1(&tmps, &encoded_len, priv->mdnid, tbs, tbslen)) ++ return UADK_P_FAIL; ++ encoded = tmps; ++ } ++ ++ ret = uadk_prov_rsa_private_sign(encoded_len, encoded, sig, priv->rsa, priv->pad_mode); ++ OPENSSL_clear_free(tmps, encoded_len); ++ return ret; ++} ++ ++static int uadk_rsa_pks1_pss_sign(struct PROV_RSA_SIG_CTX *priv, ++ const unsigned char *tbs, ++ unsigned char *sig) ++{ ++ int md_size = uadk_rsa_get_md_size(priv); ++ int rsa_size = uadk_rsa_size(priv->rsa); ++ int ret; ++ ++ /* Check PSS restrictions */ ++ if (rsa_pss_restricted(priv)) { ++ switch (priv->saltlen) { ++ case RSA_PSS_SALTLEN_DIGEST: ++ if (priv->min_saltlen > md_size) { ++ UADK_ERR("min pss saltlen %d is too small, mdsize %d\n", ++ priv->min_saltlen, md_size); ++ return UADK_P_FAIL; ++ } ++ [[fallthrough]]; ++ default: ++ if (priv->saltlen >= 0 && priv->saltlen < priv->min_saltlen) { ++ UADK_ERR("minpss saltlen %d is too small, saltlen %d\n", ++ priv->min_saltlen, priv->saltlen); ++ return UADK_P_FAIL; ++ } ++ break; ++ } ++ } ++ ++ if (!setup_tbuf(priv)) ++ return UADK_P_FAIL; ++ ++ if (!RSA_padding_add_PKCS1_PSS_mgf1(priv->rsa, ++ priv->tbuf, tbs, ++ priv->md, priv->mgf1_md, ++ priv->saltlen)) { ++ UADK_ERR("failed to RSA_padding_add_PKCS1_PSS_mgf1\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_rsa_private_sign(rsa_size, priv->tbuf, sig, priv->rsa, RSA_NO_PADDING); ++ clean_tbuf(priv); ++ ++ return ret; ++} ++ ++static int uadk_rsa_x931_sign(struct PROV_RSA_SIG_CTX *priv, const unsigned char *tbs, ++ size_t tbslen, unsigned char *sig) ++{ ++ int rsa_size = uadk_rsa_size(priv->rsa); ++ int ret; ++ ++ if ((size_t)rsa_size < tbslen + 1) { ++ UADK_ERR("invalid: RSA key size = %d, expected minimum = %d in rsa x931 sign\n", ++ (int)rsa_size, (int)tbslen + 1); ++ return UADK_P_FAIL; ++ } ++ ++ if (!setup_tbuf(priv)) { ++ UADK_ERR("failed to setup tbuf in rsa x931 sign\n"); ++ return UADK_P_FAIL; ++ } ++ ++ memcpy(priv->tbuf, tbs, tbslen); ++ priv->tbuf[tbslen] = RSA_X931_hash_id(priv->mdnid); ++ ret = uadk_prov_rsa_private_sign(tbslen + 1, priv->tbuf, sig, ++ priv->rsa, RSA_X931_PADDING); ++ clean_tbuf(priv); ++ return ret; ++} ++ ++#ifndef FIPS_MODULE ++static int uadk_rsa_asn1_octet_string_sign(struct PROV_RSA_SIG_CTX *priv, ++ const unsigned char *tbs, size_t tbslen, ++ unsigned char *sig) ++{ ++ ASN1_OCTET_STRING tmpsig; ++ int sigsize, rsasize; ++ unsigned char *p, *s; ++ int ret; ++ ++ tmpsig.type = V_ASN1_OCTET_STRING; ++ tmpsig.length = tbslen; ++ tmpsig.data = (unsigned char *)tbs; ++ sigsize = i2d_ASN1_OCTET_STRING(&tmpsig, NULL); ++ ++ rsasize = uadk_rsa_size(priv->rsa); ++ if (sigsize > (rsasize - RSA_PKCS1_PADDING_SIZE)) { ++ UADK_ERR("signature size %d is too big for rsa key\n", sigsize); ++ return UADK_P_FAIL; ++ } ++ ++ s = OPENSSL_malloc((unsigned int)rsasize + 1); ++ if (!s) { ++ UADK_ERR("failed to malloc s\n"); ++ return UADK_P_FAIL; ++ } ++ ++ p = s; ++ i2d_ASN1_OCTET_STRING(&tmpsig, &p); ++ ret = uadk_prov_rsa_private_sign(sigsize, s, sig, priv->rsa, RSA_PKCS1_PADDING); ++ ++ OPENSSL_clear_free(s, (unsigned int)rsasize + 1); ++ return ret; ++} ++ ++static int uadk_rsa_mdc2_sign(struct PROV_RSA_SIG_CTX *priv, ++ const unsigned char *tbs, size_t tbslen, ++ unsigned char *sig) ++{ ++ if (priv->pad_mode != RSA_PKCS1_PADDING) { ++ UADK_ERR("only PKCS#1 padding supported with MDC2\n"); ++ return UADK_P_FAIL; ++ } ++ return uadk_rsa_asn1_octet_string_sign(priv, tbs, tbslen, sig); ++} ++#endif ++ + static int uadk_signature_rsa_sign(void *vprsactx, unsigned char *sig, + size_t *siglen, size_t sigsize, + const unsigned char *tbs, size_t tbslen) + { + struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; +- size_t rsasize = uadk_rsa_size(priv->rsa); ++ size_t rsasize; ++ size_t mdsize; + int ret; + +- if (priv->soft) { ++ if (!priv || priv->soft) { + ret = UADK_DO_SOFT; + goto exe_soft; + } + +- if (sig == NULL) { ++ rsasize = uadk_rsa_size(priv->rsa); ++ mdsize = uadk_rsa_get_md_size(priv); ++ ++ if (!sig) { + *siglen = rsasize; + return UADK_P_SUCCESS; + } +- + if (sigsize < rsasize) { +- UADK_ERR("invalid signature size is %zu, should be at least %zu!\n", ++ UADK_ERR("invalid: signature size is %zu, should be at least %zu!\n", + sigsize, rsasize); + return UADK_P_FAIL; + } + +- ret = uadk_prov_rsa_private_sign(tbslen, tbs, sig, priv->rsa, priv->pad_mode); +- if (ret == UADK_DO_SOFT || ret == UADK_P_FAIL) +- goto exe_soft; ++ if (!mdsize) { ++ ret = uadk_prov_rsa_private_sign(tbslen, tbs, sig, ++ priv->rsa, priv->pad_mode); ++ goto end; ++ } + +- if (ret < 0) +- return ret; ++ if (tbslen != mdsize) { ++ UADK_ERR("invalid: rsa sign tbslen %zu is not equal to mdsize %zu\n", ++ tbslen, mdsize); ++ return UADK_P_FAIL; ++ } + +- *siglen = ret; ++#ifndef FIPS_MODULE ++ if (EVP_MD_is_a(priv->md, OSSL_DIGEST_NAME_MDC2)) { ++ ret = uadk_rsa_mdc2_sign(priv, tbs, tbslen, sig); ++ goto end; ++ } ++#endif ++ switch (priv->pad_mode) { ++ case RSA_X931_PADDING: ++ ret = uadk_rsa_x931_sign(priv, tbs, tbslen, sig); ++ break; ++ case RSA_PKCS1_PADDING: ++ ret = uadk_rsa_pks1_sign(priv, tbs, tbslen, sig); ++ break; ++ case RSA_PKCS1_PSS_PADDING: ++ ret = uadk_rsa_pks1_pss_sign(priv, tbs, sig); ++ break; ++ default: ++ ret = UADK_DO_SOFT; ++ } + ++end: ++ if (ret == UADK_DO_SOFT) ++ goto exe_soft; ++ if (ret <= UADK_P_FAIL) { ++ UADK_ERR("failed to do rsa sign with padding %d\n", priv->pad_mode); ++ return UADK_P_FAIL; ++ } ++ *siglen = ret; + return UADK_P_SUCCESS; ++ + exe_soft: +- if (ret == UADK_DO_SOFT) +- return uadk_rsa_sw_sign(vprsactx, sig, siglen, sigsize, tbs, tbslen); +- return UADK_P_FAIL; ++ return uadk_rsa_sw_sign(vprsactx, sig, siglen, sigsize, tbs, tbslen); + } + + static int uadk_signature_rsa_sign_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[]) + { +- return uadk_rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_SIGN); ++ return uadk_rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_SIGN); + } + + static void *uadk_signature_rsa_newctx(void *provctx, const char *propq) +@@ -533,18 +1199,21 @@ static void *uadk_signature_rsa_newctx(void *provctx, const char *propq) + struct PROV_RSA_SIG_CTX *priv = OPENSSL_zalloc(sizeof(struct PROV_RSA_SIG_CTX)); + char *propq_copy = NULL; + +- if (priv == NULL) ++ if (!priv) + goto err; + + if (propq != NULL) { + propq_copy = OPENSSL_strdup(propq); +- if (propq_copy == NULL) ++ if (!propq_copy) + goto err; + } + + priv->libctx = prov_libctx_of(provctx); + priv->flag_allow_md = 1; + priv->propq = propq_copy; ++ /* Maximum for sign, auto for verify */ ++ priv->saltlen = RSA_PSS_SALTLEN_AUTO; ++ priv->min_saltlen = -1; + return priv; + + err: +@@ -557,25 +1226,17 @@ static void uadk_signature_rsa_freectx(void *vprsactx) + { + struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; + +- if (priv == NULL) ++ if (!priv) + return; + ++ EVP_MD_CTX_free(priv->mdctx); ++ EVP_MD_free(priv->md); ++ EVP_MD_free(priv->mgf1_md); ++ OPENSSL_free(priv->propq); + free_tbuf(priv); +- OPENSSL_clear_free(priv, sizeof(*priv)); +-} +- +-static int uadk_signature_rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) +-{ +- struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; ++ RSA_free(priv->rsa); + +- if (priv == NULL) +- return UADK_P_FAIL; +- if (params == NULL) +- return UADK_P_SUCCESS; +- +- /* todo */ +- +- return UADK_P_SUCCESS; ++ OPENSSL_clear_free(priv, sizeof(*priv)); + } + + static const OSSL_PARAM settable_ctx_params[] = { +@@ -642,7 +1303,7 @@ static int uadk_digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t i + { + size_t i; + +- if (md == NULL) ++ if (!md) + return NID_undef; + + for (i = 0; i < it_len; i++) +@@ -680,35 +1341,33 @@ static int uadk_rsa_setup_md(struct PROV_RSA_SIG_CTX *ctx, const char *mdname, + const char *mdprops) + { + size_t mdname_len; ++ int sha1_allowed; ++ int md_nid; ++ EVP_MD *md; + +- if (mdprops == NULL) ++ if (!mdprops) + mdprops = ctx->propq; + + if (mdname != NULL) { +- EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); +- int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); +- int md_nid = uadk_digest_rsa_sign_get_md_nid(ctx->libctx, md, +- sha1_allowed); ++ md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); ++ sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); ++ md_nid = uadk_digest_rsa_sign_get_md_nid(ctx->libctx, md, sha1_allowed); + mdname_len = strlen(mdname); +- if (md == NULL || md_nid <= 0 || ++ if (!md || md_nid <= 0 || + !uadk_rsa_check_padding(ctx, mdname, NULL, md_nid) || + mdname_len >= sizeof(ctx->mdname)) { +- if (md == NULL) +- UADK_ERR("invalid rsa name %s could not be fetched.\n", mdname); +- if (md_nid <= 0) +- UADK_ERR("digest name is not allowed digest = %s.\n", mdname); +- if (mdname_len >= sizeof(ctx->mdname)) +- UADK_ERR("invalid name %s exceeds name buffer length.\n", mdname); ++ UADK_ERR("invalid: mdname %s, md_nid %d or name length %zu is incorrect\n", ++ mdname, md_nid, mdname_len); + if (md) + EVP_MD_free(md); +- return 0; ++ return UADK_P_FAIL; + } + + if (!ctx->mgf1_md_set) { + if (!EVP_MD_up_ref(md)) { + if (md) + EVP_MD_free(md); +- return 0; ++ return UADK_P_FAIL; + } + if (ctx->mgf1_md) + EVP_MD_free(ctx->mgf1_md); +@@ -730,7 +1389,7 @@ static int uadk_rsa_setup_md(struct PROV_RSA_SIG_CTX *ctx, const char *mdname, + OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname)); + } + +- return 1; ++ return UADK_P_SUCCESS; + } + + static int uadk_signature_rsa_digest_signverify_init(void *vprsactx, const char *mdname, +@@ -739,26 +1398,26 @@ static int uadk_signature_rsa_digest_signverify_init(void *vprsactx, const char + { + struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; + +- if (!uadk_rsa_init(vprsactx, vrsa, params, operation)) +- return 0; ++ if (!uadk_rsa_signverify_init(vprsactx, vrsa, params, operation)) ++ return UADK_P_FAIL; + + if (mdname != NULL && + (mdname[0] == '\0' || OPENSSL_strcasecmp(priv->mdname, mdname) != 0) && + !uadk_rsa_setup_md(priv, mdname, priv->propq)) +- return 0; ++ return UADK_P_FAIL; + + priv->flag_allow_md = 0; + +- if (priv->mdctx == NULL) { ++ if (!priv->mdctx) { + priv->mdctx = EVP_MD_CTX_new(); +- if (priv->mdctx == NULL) ++ if (!priv->mdctx) + goto error; + } + + if (!EVP_DigestInit_ex2(priv->mdctx, priv->md, params)) + goto error; + +- return 1; ++ return UADK_P_SUCCESS; + + error: + if (priv->mdctx) { +@@ -766,7 +1425,7 @@ error: + priv->mdctx = NULL; + } + +- return 0; ++ return UADK_P_FAIL; + } + + static int uadk_signature_rsa_digest_sign_init(void *vprsactx, const char *mdname, +@@ -782,7 +1441,7 @@ static int uadk_signature_rsa_digest_sign_update(void *vprsactx, + { + struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; + +- if (priv == NULL || priv->mdctx == NULL) ++ if (!priv || !priv->mdctx) + return UADK_P_FAIL; + + return EVP_DigestUpdate(priv->mdctx, data, datalen); +@@ -848,9 +1507,6 @@ static const unsigned char *uadk_rsa_digestinfo_encoding(int md_nid, size_t *len + } + } + +-/* Size of an SSL signature: MD5+SHA1 */ +-#define SSL_SIG_LENGTH 36 +- + /* + * Encodes a DigestInfo prefix of hash |type| and digest |m|, as + * described in EMSA-PKCS1-v1_5-ENCODE, RFC 3447 section 9.2 step 2. This +@@ -869,25 +1525,25 @@ static int encode_pkcs1(unsigned char **out, size_t *out_len, int type, + + if (type == NID_undef) { + UADK_ERR("invalid: rsa unknown algorithm type.\n"); +- return 0; ++ return UADK_P_FAIL; + } + di_prefix = uadk_rsa_digestinfo_encoding(type, &di_prefix_len); +- if (di_prefix == NULL) { ++ if (!di_prefix) { + UADK_ERR("invalid: rsa di prefix is NULL.\n"); +- return 0; ++ return UADK_P_FAIL; + } + dig_info_len = di_prefix_len + m_len; + dig_info = OPENSSL_malloc(dig_info_len); +- if (dig_info == NULL) { ++ if (!dig_info) { + UADK_ERR("failed to malloc dig info.\n"); +- return 0; ++ return UADK_P_FAIL; + } + memcpy(dig_info, di_prefix, di_prefix_len); + memcpy(dig_info + di_prefix_len, m, m_len); + + *out = dig_info; + *out_len = dig_info_len; +- return 1; ++ return UADK_P_SUCCESS; + } + + static int uadk_signature_rsa_digest_sign_final(void *vprsactx, unsigned char *sig, +@@ -895,21 +1551,14 @@ static int uadk_signature_rsa_digest_sign_final(void *vprsactx, unsigned char *s + { + struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; + unsigned char digest[EVP_MAX_MD_SIZE]; +- const unsigned char *encoded = NULL; +- unsigned char *tmps = NULL; +- size_t encoded_len = 0; + unsigned int dlen = 0; +- int ret = UADK_P_FAIL; +- size_t rsasize; + +- if (priv == NULL) ++ if (!priv) + return UADK_P_FAIL; + +- if (priv->mdctx == NULL) ++ if (!priv->mdctx) + return UADK_P_FAIL; + +- rsasize = uadk_rsa_size(priv->rsa); +- + /* + * If sig is NULL then we're just finding out the sig size. Other fields + * are ignored. Defer to rsa_sign. +@@ -921,49 +1570,11 @@ static int uadk_signature_rsa_digest_sign_final(void *vprsactx, unsigned char *s + */ + if (!EVP_DigestFinal_ex(priv->mdctx, digest, &dlen)) + return UADK_P_FAIL; +- } else { +- *siglen = rsasize; +- return 1; + } + + priv->flag_allow_md = 1; + +- if (priv->pad_mode == RSA_PKCS1_PADDING) { +- /* Compute the encoded digest. */ +- if (priv->mdnid == NID_md5_sha1) { +- /* +- * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and +- * earlier. It has no DigestInfo wrapper but otherwise is +- * RSASSA-PKCS1-v1_5. +- */ +- if (dlen != SSL_SIG_LENGTH) { +- UADK_ERR("invalid: rsa message length.\n"); +- return 0; +- } +- encoded_len = SSL_SIG_LENGTH; +- encoded = digest; +- } else { +- if (!encode_pkcs1(&tmps, &encoded_len, priv->mdnid, digest, dlen)) +- goto err; +- encoded = tmps; +- } +- } else { +- UADK_ERR("This padding mode is not supported\n"); +- return UADK_P_FAIL; +- } +- +- ret = uadk_prov_rsa_private_sign(encoded_len, encoded, sig, priv->rsa, priv->pad_mode); +- if (ret == UADK_DO_SOFT || ret == UADK_P_FAIL) +- goto err; +- +- OPENSSL_clear_free(tmps, encoded_len); +- return ret; +-err: +- OPENSSL_clear_free(tmps, encoded_len); +- if (ret == UADK_DO_SOFT) +- return uadk_rsa_sw_sign(vprsactx, sig, siglen, sigsize, digest, dlen); +- +- return UADK_P_FAIL; ++ return uadk_signature_rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen); + } + + static int uadk_signature_rsa_digest_verify_init(void *vprsactx, const char *mdname, +@@ -978,8 +1589,8 @@ static int uadk_signature_rsa_digest_verify_update(void *vprsactx, const unsigne + { + struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; + +- if (priv == NULL || priv->mdctx == NULL) +- return 0; ++ if (!priv || !priv->mdctx) ++ return UADK_P_FAIL; + + return EVP_DigestUpdate(priv->mdctx, data, datalen); + } +@@ -988,16 +1599,13 @@ static int uadk_signature_rsa_digest_verify_final(void *vprsactx, const unsigned + size_t siglen) + { + struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; +- unsigned char *decrypt_buf = NULL, *encoded = NULL; +- size_t decrypt_len, encoded_len = 0; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int dlen = 0; +- int ret = UADK_P_FAIL; + +- if (priv == NULL) ++ if (!priv) + return UADK_P_FAIL; +- priv->flag_allow_md = 1; +- if (priv->mdctx == NULL) ++ ++ if (!priv->mdctx) + return UADK_P_FAIL; + + /* +@@ -1007,78 +1615,8 @@ static int uadk_signature_rsa_digest_verify_final(void *vprsactx, const unsigned + if (!EVP_DigestFinal_ex(priv->mdctx, digest, &dlen)) + return UADK_P_FAIL; + +- if (priv->pad_mode == RSA_PKCS1_PADDING) { +- if (siglen != (size_t)uadk_rsa_size(priv->rsa)) { +- UADK_ERR("invalid: rsa signature length.\n"); +- return UADK_P_FAIL; +- } +- +- /* Recover the encoded digest. */ +- decrypt_buf = OPENSSL_malloc(siglen); +- if (decrypt_buf == NULL) { +- UADK_ERR("failed to malloc decrypt buf.\n"); +- return UADK_P_FAIL; +- } +- +- ret = uadk_prov_rsa_public_verify(siglen, sig, decrypt_buf, +- priv->rsa, priv->pad_mode); +- if (ret <= 0) +- goto err; +- decrypt_len = ret; +- +- if (priv->mdnid == NID_md5_sha1) { +- /* +- * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and +- * earlier. It has no DigestInfo wrapper but otherwise is +- * RSASSA-PKCS1-v1_5. +- */ +- if (decrypt_len != SSL_SIG_LENGTH) { +- UADK_ERR("invalid: rsa decrypt length.\n"); +- ret = UADK_P_FAIL; +- goto err; +- } +- +- if (siglen != SSL_SIG_LENGTH) { +- UADK_ERR("invalid: rsa siglen.\n"); +- ret = UADK_P_FAIL; +- goto err; +- } +- +- if (memcmp(decrypt_buf, digest, SSL_SIG_LENGTH) != 0) { +- UADK_ERR("failed to memcmp decrypt buf and digest.\n"); +- ret = UADK_P_FAIL; +- goto err; +- } +- } else { +- /* Construct the encoded digest and ensure it matches. */ +- if (!encode_pkcs1(&encoded, &encoded_len, priv->mdnid, digest, dlen)) { +- ret = UADK_P_FAIL; +- goto err; +- } +- +- if (encoded_len != decrypt_len +- || memcmp(encoded, decrypt_buf, encoded_len) != 0) { +- UADK_ERR("failed to memcmp decrypt buf and encoded.\n"); +- ret = UADK_P_FAIL; +- goto err; +- } +- } +- ret = UADK_P_SUCCESS; +- } else { +- UADK_ERR("This padding mode is not supported\n"); +- return UADK_P_FAIL; +- } +- +-err: +- if (encoded) +- OPENSSL_clear_free(encoded, encoded_len); +- if (decrypt_buf) +- OPENSSL_clear_free(decrypt_buf, siglen); +- +- if (ret == UADK_DO_SOFT) +- return uadk_rsa_sw_verify(vprsactx, sig, siglen, digest, dlen); +- +- return ret; ++ priv->flag_allow_md = 1; ++ return uadk_signature_rsa_verify(vprsactx, sig, siglen, digest, (size_t)dlen); + } + + static void *uadk_signature_rsa_dupctx(void *vprsactx) +-- +2.25.1 + diff --git a/0026-uadk_provider-adapt-rsa-encryption-operation-with-OA.patch b/0026-uadk_provider-adapt-rsa-encryption-operation-with-OA.patch new file mode 100644 index 0000000..985b3d5 --- /dev/null +++ b/0026-uadk_provider-adapt-rsa-encryption-operation-with-OA.patch @@ -0,0 +1,519 @@ +From ae17824bb956f811af835f619a08583839d0c6e0 Mon Sep 17 00:00:00 2001 +From: lizhi +Date: Tue, 16 Dec 2025 19:17:15 +0800 +Subject: [PATCH 26/32] uadk_provider: adapt rsa encryption operation with OAEP + and PKCS1_WITH_TLS padding modes + +Add support for RSA encryption padding modes with OpenSSL provider +mechanism, including RSA_PKCS1_OAEP_PADDING and +RSA_PKCS1_WITH_TLS_PADDING. + +Test with: +openssl pkeyutl -encrypt -in test.txt -out encrypted.bin -pubin +-inkey public.pem -pkeyopt rsa_padding_mode:oaep +openssl pkeyutl -decrypt -in encrypted.bin -out decrypted.txt +-inkey private.pem -pkeyopt rsa_padding_mode:oaep + +openssl s_server -provider uadk_provider -accept 4333 -cert server.pem -www +-cipher AES256-SHA +openssl s_client -provider uadk_provider -connect localhost:4333 + +Signed-off-by: lizhi +Signed-off-by: JiangShui Yang +--- + src/uadk_prov_rsa_enc.c | 287 ++++++++++++++++++++++++++++++++++---- + src/uadk_prov_rsa_kmgmt.c | 20 +-- + 2 files changed, 268 insertions(+), 39 deletions(-) + +diff --git a/src/uadk_prov_rsa_enc.c b/src/uadk_prov_rsa_enc.c +index 3c4fe0e..d4f8106 100644 +--- a/src/uadk_prov_rsa_enc.c ++++ b/src/uadk_prov_rsa_enc.c +@@ -17,6 +17,15 @@ + * + */ + #include "uadk_prov_rsa.h" ++#include ++#include ++ ++#define RSA_PKCS1_PADDING_SIZE 11 ++#define PKCS1_TLS_ZERO_PADD 0x00 ++#define PKCS1_TLS_NONE_ZERO_PADD 0x02 ++#define CLIENT_VERSION_SHIFT 8 ++#define PKCS1_TLS_PADDING_POS 2 ++#define CLIENT_VERSION_MASK 0xFF + + UADK_PKEY_ASYM_CIPHER_DESCR(rsa, RSA); + +@@ -64,6 +73,66 @@ static UADK_PKEY_ASYM_CIPHER get_default_rsa_asym_cipher(void) + return s_asym_cipher; + } + ++/** ++ * Checks and removes PKCS#1 v1.5 padding for TLS RSA decryption. ++ * This function validates and strips PKCS#1 type 2 (v1.5) padding from an RSA-encrypted ++ * pre-master secret as used in TLS. It ensures the decrypted data conforms to the expected ++ * format, checks the client version, and provides constant-time fallback to random data ++ * if the padding or version is invalid, as required by the TLS protocol to prevent ++ * side-channel attacks. ++ */ ++static int RSA_padding_check_PKCS1_type_2_TLS(OSSL_LIB_CTX *libctx, ++ unsigned char *to, size_t tlen, ++ const unsigned char *from, size_t flen, ++ int client_version, int alt_version) ++{ ++ unsigned char rand_premaster[SSL_MAX_MASTER_KEY_LENGTH]; ++ int premaster_len = SSL_MAX_MASTER_KEY_LENGTH; ++ int plen, good; ++ unsigned char *p; ++ int i; ++ ++ if (flen < RSA_PKCS1_PADDING_SIZE || tlen < premaster_len) ++ goto err; ++ ++ p = (unsigned char *)from; ++ if (p[0] != PKCS1_TLS_ZERO_PADD || p[1] != PKCS1_TLS_NONE_ZERO_PADD) ++ goto err; ++ ++ for (i = PKCS1_TLS_PADDING_POS; i < flen; i++) { ++ if (p[i] == PKCS1_TLS_ZERO_PADD) ++ break; ++ } ++ ++ if (i == flen || i < (RSA_PKCS1_PADDING_SIZE - 1)) ++ goto err; ++ plen = flen - (i + 1); ++ if (plen != premaster_len) ++ goto err; ++ memcpy(to, p + i + 1, premaster_len); ++ ++ good = (to[0] == (client_version >> CLIENT_VERSION_SHIFT) && ++ to[1] == (client_version & CLIENT_VERSION_MASK)); ++ if (!good && alt_version > 0) ++ good = (to[0] == (alt_version >> CLIENT_VERSION_SHIFT) ++ && to[1] == ++ (alt_version & CLIENT_VERSION_MASK)); ++ if (!good) { ++ if (RAND_bytes_ex(libctx, rand_premaster, premaster_len, 0) <= 0) ++ goto err; ++ memcpy(to, rand_premaster, premaster_len); ++ } ++ ++ OPENSSL_cleanse(rand_premaster, premaster_len); ++ return premaster_len; ++err: ++ if (RAND_bytes_ex(libctx, rand_premaster, premaster_len, 0) > 0) ++ memcpy(to, rand_premaster, premaster_len); ++ OPENSSL_cleanse(rand_premaster, premaster_len); ++ ++ return CHECK_PADDING_FAIL; ++} ++ + static int add_rsa_pubenc_padding(int flen, const unsigned char *from, + unsigned char *buf, int num, int padding) + { +@@ -72,18 +141,22 @@ static int add_rsa_pubenc_padding(int flen, const unsigned char *from, + switch (padding) { + case RSA_PKCS1_PADDING: + ret = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); +- if (!ret) +- UADK_ERR("RSA_PKCS1_PADDING err.\n"); + break; + case RSA_PKCS1_OAEP_PADDING: + ret = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); +- if (!ret) +- UADK_ERR("RSA_PKCS1_OAEP_PADDING err.\n"); ++ break; ++ case RSA_NO_PADDING: ++ ret = RSA_padding_add_none(buf, num, from, flen); + break; + default: + ret = UADK_P_FAIL; + } + ++ if (ret <= UADK_P_FAIL) { ++ ret = UADK_P_FAIL; ++ UADK_ERR("failed to add rsa encrypt padding %d\n", padding); ++ } ++ + return ret; + } + +@@ -96,21 +169,23 @@ static int check_rsa_pridec_padding(unsigned char *to, int num, + switch (padding) { + case RSA_PKCS1_PADDING: + ret = RSA_padding_check_PKCS1_type_2(to, num, buf, flen, num); +- if (ret == CHECK_PADDING_FAIL) +- UADK_ERR("RSA_PKCS1_PADDING err.\n"); + break; + case RSA_PKCS1_OAEP_PADDING: + ret = RSA_padding_check_PKCS1_OAEP(to, num, buf, flen, num, + NULL, 0); +- if (ret == CHECK_PADDING_FAIL) +- UADK_ERR("RSA_PKCS1_OAEP_PADDING err.\n"); ++ break; ++ case RSA_NO_PADDING: ++ memcpy(to, buf, flen); ++ ret = flen; + break; + default: +- ret = UADK_P_FAIL; ++ ret = CHECK_PADDING_FAIL; + } + +- if (ret == CHECK_PADDING_FAIL) ++ if (ret == CHECK_PADDING_FAIL) { ++ UADK_ERR("failed to check rsa decrypt %d\n", padding); + ret = UADK_P_FAIL; ++ } + + return ret; + } +@@ -247,8 +322,6 @@ static int uadk_prov_rsa_private_decrypt(int flen, const unsigned char *from, + goto free_buf; + + ret = check_rsa_pridec_padding(to, num_bytes, from_buf, flen, padding); +- if (!ret) +- ret = UADK_P_FAIL; + + free_buf: + rsa_free_pri_bn_ctx(from_buf); +@@ -264,9 +337,13 @@ static int uadk_rsa_asym_init(void *vprsactx, void *vrsa, + { + struct PROV_RSA_ASYM_CTX *priv = (struct PROV_RSA_ASYM_CTX *)vprsactx; + +- if (priv == NULL || vrsa == NULL) ++ if (!priv || !vrsa) ++ return UADK_P_FAIL; ++ ++ if (!RSA_up_ref(vrsa)) + return UADK_P_FAIL; + ++ RSA_free(priv->rsa); + priv->rsa = vrsa; + priv->operation = operation; + +@@ -293,7 +370,7 @@ static void *uadk_asym_cipher_rsa_newctx(void *provctx) + struct PROV_RSA_ASYM_CTX *priv = NULL; + + priv = OPENSSL_zalloc(sizeof(*priv)); +- if (priv == NULL) ++ if (!priv) + return NULL; + priv->libctx = prov_libctx_of(provctx); + +@@ -304,9 +381,14 @@ static void uadk_asym_cipher_rsa_freectx(void *vprsactx) + { + struct PROV_RSA_ASYM_CTX *priv = (struct PROV_RSA_ASYM_CTX *)vprsactx; + +- if (priv == NULL) ++ if (!priv) + return; + ++ RSA_free(priv->rsa); ++ EVP_MD_free(priv->oaep_md); ++ EVP_MD_free(priv->mgf1_md); ++ OPENSSL_free(priv->oaep_label); ++ + OPENSSL_free(priv); + } + +@@ -341,6 +423,46 @@ static int uadk_rsa_sw_encrypt(void *vprsactx, unsigned char *out, + return get_default_rsa_asym_cipher().encrypt(vprsactx, out, outlen, outsize, in, inlen); + } + ++static int uadk_asym_cipher_rsa_oaep_encrypt(void *vprsactx, unsigned char *out, ++ const unsigned char *in, size_t inlen) ++{ ++ struct PROV_RSA_ASYM_CTX *priv = (struct PROV_RSA_ASYM_CTX *)vprsactx; ++ unsigned char *tbuf; ++ int rsasize, ret; ++ ++ rsasize = RSA_size(priv->rsa); ++ tbuf = OPENSSL_malloc(rsasize); ++ if (!tbuf) { ++ UADK_ERR("failed to malloc buffer in rsa oaep encrypt\n"); ++ return UADK_P_FAIL; ++ } ++ ++ if (!priv->oaep_md) { ++ priv->oaep_md = EVP_MD_fetch(priv->libctx, "SHA-1", NULL); ++ if (!priv->oaep_md) { ++ OPENSSL_free(tbuf); ++ UADK_ERR("failed to fetch SHA-1 digest method in rsa oaep encrypt\n"); ++ return UADK_P_FAIL; ++ } ++ } ++ ++ ret = RSA_padding_add_PKCS1_OAEP_mgf1(tbuf, rsasize, ++ in, inlen, ++ priv->oaep_label, ++ priv->oaep_labellen, ++ priv->oaep_md, ++ priv->mgf1_md); ++ if (!ret) { ++ OPENSSL_free(tbuf); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_rsa_public_encrypt(rsasize, tbuf, out, priv->rsa, RSA_NO_PADDING); ++ OPENSSL_free(tbuf); ++ ++ return ret; ++} ++ + static int uadk_asym_cipher_rsa_encrypt(void *vprsactx, unsigned char *out, + size_t *outlen, size_t outsize, + const unsigned char *in, size_t inlen) +@@ -354,7 +476,7 @@ static int uadk_asym_cipher_rsa_encrypt(void *vprsactx, unsigned char *out, + goto exe_soft; + } + +- if (out == NULL) { ++ if (!out) { + len = uadk_rsa_size(priv->rsa); + if (len == 0) { + UADK_ERR("invalid: rsa encrypt size.\n"); +@@ -364,12 +486,15 @@ static int uadk_asym_cipher_rsa_encrypt(void *vprsactx, unsigned char *out, + return UADK_P_SUCCESS; + } + +- ret = uadk_prov_rsa_public_encrypt(inlen, in, out, priv->rsa, priv->pad_mode); ++ if (priv->pad_mode == RSA_PKCS1_OAEP_PADDING) ++ ret = uadk_asym_cipher_rsa_oaep_encrypt(priv, out, in, inlen); ++ else ++ ret = uadk_prov_rsa_public_encrypt(inlen, in, out, priv->rsa, priv->pad_mode); ++ + if (ret == UADK_DO_SOFT || ret == UADK_P_FAIL) + goto exe_soft; + + *outlen = ret; +- + return UADK_P_SUCCESS; + exe_soft: + if (ret == UADK_DO_SOFT) +@@ -388,34 +513,138 @@ static int uadk_rsa_sw_decrypt(void *vprsactx, unsigned char *out, + return get_default_rsa_asym_cipher().decrypt(vprsactx, out, outlen, outsize, in, inlen); + } + ++static int uadk_asym_cipher_rsa_oaep_decrypt(struct PROV_RSA_ASYM_CTX *priv, ++ unsigned char *out, size_t *outlen, size_t outsize, ++ const unsigned char *in, size_t inlen) ++{ ++ size_t len = uadk_rsa_size(priv->rsa); ++ unsigned char *tbuf; ++ int ret; ++ ++ tbuf = OPENSSL_malloc(len); ++ if (!tbuf) { ++ UADK_ERR("failed to malloc buf in rsa oaep decrypt\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_rsa_private_decrypt(inlen, in, tbuf, priv->rsa, RSA_NO_PADDING); ++ if (ret != (int)len) { ++ OPENSSL_free(tbuf); ++ UADK_ERR("failed to do rsa oaep decrypt\n"); ++ return ret; ++ } ++ ++ if (!priv->oaep_md) { ++ priv->oaep_md = EVP_MD_fetch(priv->libctx, "SHA-1", NULL); ++ if (!priv->oaep_md) { ++ OPENSSL_free(tbuf); ++ UADK_ERR("faile to fetch SHA-1 digest method in rsa oaep decrypt\n"); ++ return UADK_P_FAIL; ++ } ++ } ++ ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, outsize, tbuf, ++ len, len, ++ priv->oaep_label, ++ priv->oaep_labellen, ++ priv->oaep_md, ++ priv->mgf1_md); ++ if (ret == CHECK_PADDING_FAIL) ++ ret = UADK_P_FAIL; ++ ++ OPENSSL_free(tbuf); ++ return ret; ++} ++ ++static int uadk_asym_cipher_rsa_tls_decrypt(struct PROV_RSA_ASYM_CTX *priv, ++ unsigned char *out, size_t *outlen, size_t outsize, ++ const unsigned char *in, size_t inlen) ++{ ++ size_t len = uadk_rsa_size(priv->rsa); ++ unsigned char *tbuf; ++ int ret; ++ ++ /* RSA_PKCS1_WITH_TLS_PADDING */ ++ if (priv->client_version == 0) { ++ UADK_ERR("invalid: tls client version is %u\n", priv->client_version); ++ return UADK_P_FAIL; ++ } ++ ++ tbuf = OPENSSL_malloc(len); ++ if (!tbuf) { ++ UADK_ERR("failed to malloc buf in rsa tls decrypt\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_rsa_private_decrypt(inlen, in, tbuf, priv->rsa, RSA_NO_PADDING); ++ if (ret != (int)len) { ++ OPENSSL_free(tbuf); ++ UADK_ERR("failed to do rsa tls decrypt\n"); ++ return ret; ++ } ++ ++ ret = RSA_padding_check_PKCS1_type_2_TLS(priv->libctx, out, outsize, ++ tbuf, len, priv->client_version, ++ priv->alt_version); ++ if (ret == CHECK_PADDING_FAIL) ++ ret = UADK_P_FAIL; ++ ++ OPENSSL_free(tbuf); ++ return ret; ++} ++ + static int uadk_asym_cipher_rsa_decrypt(void *vprsactx, unsigned char *out, + size_t *outlen, size_t outsize, + const unsigned char *in, size_t inlen) + { + struct PROV_RSA_ASYM_CTX *priv = (struct PROV_RSA_ASYM_CTX *)vprsactx; +- size_t len = uadk_rsa_size(priv->rsa); ++ size_t len; + int ret; + +- if (priv->soft) { ++ if (!priv || priv->soft) { + ret = UADK_DO_SOFT; + goto exe_soft; + } + +- if (out == NULL) { +- if (len == 0) { +- UADK_ERR("invalid: rsa decrypt size.\n"); ++ len = uadk_rsa_size(priv->rsa); ++ if (priv->pad_mode == RSA_PKCS1_WITH_TLS_PADDING) { ++ if (!out) { ++ *outlen = SSL_MAX_MASTER_KEY_LENGTH; ++ return UADK_P_SUCCESS; ++ } ++ if (outsize < SSL_MAX_MASTER_KEY_LENGTH) { ++ UADK_ERR("invalid: incorrect rsa decrypt outsize in padding %d\n", ++ priv->pad_mode); ++ return UADK_P_FAIL; ++ } ++ } else { ++ if (!out) { ++ if (len == 0) { ++ UADK_ERR("invalid: incorrect rsa decrypt size in padding %d\n", ++ priv->pad_mode); ++ return UADK_P_FAIL; ++ } ++ *outlen = len; ++ return UADK_P_SUCCESS; ++ } ++ ++ if (outsize < len) { ++ UADK_ERR("invalid: incorrect rsa decrypt outsize in padding %d\n", ++ priv->pad_mode); + return UADK_P_FAIL; + } +- *outlen = len; +- return UADK_P_SUCCESS; + } + +- if (outsize < len) { +- UADK_ERR("invalid: rsa decrypt outsize is too small.\n"); +- return UADK_P_FAIL; ++ switch (priv->pad_mode) { ++ case RSA_PKCS1_OAEP_PADDING: ++ ret = uadk_asym_cipher_rsa_oaep_decrypt(priv, out, outlen, outsize, in, inlen); ++ break; ++ case RSA_PKCS1_WITH_TLS_PADDING: ++ ret = uadk_asym_cipher_rsa_tls_decrypt(priv, out, outlen, outsize, in, inlen); ++ break; ++ default: ++ ret = uadk_prov_rsa_private_decrypt(inlen, in, out, priv->rsa, priv->pad_mode); + } + +- ret = uadk_prov_rsa_private_decrypt(inlen, in, out, priv->rsa, priv->pad_mode); + if (ret == UADK_DO_SOFT || ret == UADK_P_FAIL) + goto exe_soft; + +diff --git a/src/uadk_prov_rsa_kmgmt.c b/src/uadk_prov_rsa_kmgmt.c +index fc03276..f71eed3 100644 +--- a/src/uadk_prov_rsa_kmgmt.c ++++ b/src/uadk_prov_rsa_kmgmt.c +@@ -91,8 +91,8 @@ static int uadk_rsa_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) + * parameters MUST be non-NULL for n and e. d may be + * left NULL (in case only the public key is used). + */ +- if ((r->n == NULL && n == NULL) +- || (r->e == NULL && e == NULL)) ++ if ((!r->n && !n) ++ || (!r->e && !e)) + return UADK_P_FAIL; + + if (n != NULL) { +@@ -119,7 +119,7 @@ static int uadk_rsa_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) + * If the fields p and q in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ +- if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL)) ++ if ((!r->p && !p) || (!r->q && !q)) + return UADK_P_FAIL; + + if (p != NULL) { +@@ -145,9 +145,9 @@ static int uadk_rsa_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM * + * If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ +- if ((r->dmp1 == NULL && dmp1 == NULL) +- || (r->dmq1 == NULL && dmq1 == NULL) +- || (r->iqmp == NULL && iqmp == NULL)) ++ if ((!r->dmp1 && !dmp1) ++ || (!r->dmq1 && !dmq1) ++ || (!r->iqmp && !iqmp)) + return UADK_P_FAIL; + + if (dmp1 != NULL) { +@@ -516,14 +516,14 @@ static RSA *ossl_rsa_new_with_ctx(OSSL_LIB_CTX *libctx) + { + RSA *rsa = OPENSSL_zalloc(sizeof(*rsa)); + +- if (rsa == NULL) { ++ if (!rsa) { + UADK_ERR("failed to zalloc rsa ret\n"); + return NULL; + } + + rsa->references = 1; + rsa->lock = CRYPTO_THREAD_lock_new(); +- if (rsa->lock == NULL) { ++ if (!rsa->lock) { + UADK_ERR("failed to malloc thread lock\n"); + OPENSSL_free(rsa); + return NULL; +@@ -843,7 +843,7 @@ static void *uadk_keymgmt_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba + RSA *rsa; + int ret; + +- if (gctx == NULL) ++ if (!gctx) + return NULL; + + ret = uadk_prov_rsa_init(); +@@ -853,7 +853,7 @@ static void *uadk_keymgmt_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba + } + + rsa = ossl_rsa_new_with_ctx(gctx->libctx); +- if (rsa == NULL) ++ if (!rsa) + return NULL; + + gctx->cb = osslcb; +-- +2.25.1 + diff --git a/0027-provider-optimize-hardware-version-and-availability-.patch b/0027-provider-optimize-hardware-version-and-availability-.patch new file mode 100644 index 0000000..fc44373 --- /dev/null +++ b/0027-provider-optimize-hardware-version-and-availability-.patch @@ -0,0 +1,240 @@ +From 8e64cd3feae72baae69611575fed59efe6122522 Mon Sep 17 00:00:00 2001 +From: lizhi +Date: Tue, 16 Dec 2025 19:17:15 +0800 +Subject: [PATCH 27/32] provider: optimize hardware version and availability + queries using global variables + +Introduce global variables to cache hardware version, +reducing repeated device queries. + +Signed-off-by: lizhi +Signed-off-by: JiangShui Yang +--- + src/uadk_prov.h | 8 ++++++-- + src/uadk_prov_cipher.c | 14 +++++++++----- + src/uadk_prov_digest.c | 14 ++++++++++++-- + src/uadk_prov_init.c | 10 +++++----- + src/uadk_prov_pkey.c | 13 ++++++++++--- + src/uadk_prov_pkey.h | 9 ++++++--- + 6 files changed, 48 insertions(+), 20 deletions(-) + +diff --git a/src/uadk_prov.h b/src/uadk_prov.h +index 0829b19..2261d3e 100644 +--- a/src/uadk_prov.h ++++ b/src/uadk_prov.h +@@ -26,8 +26,6 @@ + #define UADK_INIT_SUCCESS 1 + #define UADK_INIT_FAIL 2 + #define UADK_DEVICE_ERROR 3 +-#define HW_SEC_V2 2 +-#define HW_SEC_V3 3 + #define POLL_ERROR (-1) + #define PROV_SEND_MAX_CNT 90000000 + #define PROV_RECV_MAX_CNT 60000000 +@@ -44,6 +42,12 @@ + #define PROV_NAMES_SHA2_512_224 "SHA2-512/224:SHA-512/224:SHA512-224:2.16.840.1.101.3.4.2.5" + #define PROV_NAMES_SHA2_512_256 "SHA2-512/256:SHA-512/256:SHA512-256:2.16.840.1.101.3.4.2.6" + ++enum HW_SYMM_ENC_DEV { ++ HW_SYMM_ENC_INVALID = 0x0, ++ HW_SYMM_ENC_V2 = 0x2, ++ HW_SYMM_ENC_V3 = 0x3 ++}; ++ + typedef int CRYPTO_REF_COUNT; + + struct ossl_provider_st { +diff --git a/src/uadk_prov_cipher.c b/src/uadk_prov_cipher.c +index e5f1acf..73359c6 100644 +--- a/src/uadk_prov_cipher.c ++++ b/src/uadk_prov_cipher.c +@@ -104,6 +104,7 @@ struct cipher_prov { + int pid; + }; + static struct cipher_prov prov; ++static enum HW_SYMM_ENC_DEV g_hw_symm_enc_dev; + static pthread_mutex_t cipher_mutex = PTHREAD_MUTEX_INITIALIZER; + + struct cipher_priv_ctx { +@@ -1342,22 +1343,25 @@ static void uadk_prov_cipher_freectx(void *ctx) + int uadk_prov_cipher_version(void) + { + struct uacce_dev *dev; +- int ver; ++ ++ if (g_hw_symm_enc_dev != HW_SYMM_ENC_INVALID) ++ return g_hw_symm_enc_dev; + + dev = uadk_get_accel_dev("cipher"); + if (!dev) { + UADK_ERR("no cipher device available!\n"); +- return 0; ++ g_hw_symm_enc_dev = HW_SYMM_ENC_INVALID; ++ return g_hw_symm_enc_dev; + } + + if (!strcmp(dev->api, "hisi_qm_v2")) +- ver = HW_SEC_V2; ++ g_hw_symm_enc_dev = HW_SYMM_ENC_V2; + else +- ver = HW_SEC_V3; ++ g_hw_symm_enc_dev = HW_SYMM_ENC_V3; + + free(dev); + +- return ver; ++ return g_hw_symm_enc_dev; + } + + #define UADK_CIPHER_DESCR(nm, blk_size, key_len, iv_len, \ +diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c +index 001c389..239c31a 100644 +--- a/src/uadk_prov_digest.c ++++ b/src/uadk_prov_digest.c +@@ -67,6 +67,11 @@ struct digest_prov { + int pid; + }; + ++enum { ++ HW_DIGEST_INVALID = 0x0, ++ HW_DIGEST_VALID = 0x1 ++} g_digest_avaiable; ++ + static struct digest_prov dprov; + static pthread_mutex_t digest_mutex = PTHREAD_MUTEX_INITIALIZER; + +@@ -1043,13 +1048,18 @@ int uadk_prov_digest_version(void) + { + struct uacce_dev *dev; + ++ if (g_digest_avaiable != HW_DIGEST_INVALID) ++ return g_digest_avaiable; ++ + dev = uadk_get_accel_dev("digest"); + if (!dev) { + UADK_ERR("no digest device available!\n"); +- return UADK_DIGEST_FAIL; ++ g_digest_avaiable = HW_DIGEST_INVALID; ++ return g_digest_avaiable; + } + + free(dev); ++ g_digest_avaiable = HW_DIGEST_VALID; + +- return UADK_DIGEST_SUCCESS; ++ return g_digest_avaiable; + } +diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c +index c057be2..0e050e1 100644 +--- a/src/uadk_prov_init.c ++++ b/src/uadk_prov_init.c +@@ -709,7 +709,7 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, + ver = uadk_prov_cipher_version(); + if (!ver && uadk_get_sw_offload_state()) + break; +- else if (ver == HW_SEC_V2) ++ else if (ver == HW_SYMM_ENC_V2) + return uadk_generate_cipher_array_v2(); + return uadk_generate_cipher_array_v3(); + case OSSL_OP_SIGNATURE: +@@ -717,7 +717,7 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, + ver = uadk_prov_pkey_version(); + if (!ver && uadk_get_sw_offload_state()) + break; +- else if (ver == HW_PKEY_V2) ++ else if (ver == HW_ASYM_ENC_V2) + return uadk_generate_signature_array_v2(); + return uadk_generate_signature_array_v3(); + case OSSL_OP_KEYMGMT: +@@ -725,7 +725,7 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, + ver = uadk_prov_pkey_version(); + if (!ver && uadk_get_sw_offload_state()) + break; +- else if (ver == HW_PKEY_V2) ++ else if (ver == HW_ASYM_ENC_V2) + return uadk_generate_keymgmt_array_v2(); + return uadk_generate_keymgmt_array_v3(); + case OSSL_OP_ASYM_CIPHER: +@@ -733,7 +733,7 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, + ver = uadk_prov_pkey_version(); + if (!ver && uadk_get_sw_offload_state()) + break; +- else if (ver == HW_PKEY_V2) ++ else if (ver == HW_ASYM_ENC_V2) + return uadk_generate_asym_cipher_array_v2(); + return uadk_generate_asym_cipher_array_v3(); + case OSSL_OP_KEYEXCH: +@@ -741,7 +741,7 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, + ver = uadk_prov_pkey_version(); + if (!ver && uadk_get_sw_offload_state()) + break; +- else if (ver == HW_PKEY_V2) ++ else if (ver == HW_ASYM_ENC_V2) + return uadk_generate_keyexch_array_v2(); + return uadk_generate_keyexch_array_v3(); + default: +diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c +index 57ae3a4..9597e7f 100644 +--- a/src/uadk_prov_pkey.c ++++ b/src/uadk_prov_pkey.c +@@ -39,6 +39,7 @@ static int p_keymgmt_support_state[KEYMGMT_TYPE]; + static int p_signature_support_state[SIGNATURE_TYPE]; + static int p_asym_cipher_support_state[ASYM_CIPHER_TYPE]; + static int p_keyexch_support_state[KEYEXCH_TYPE]; ++static enum HW_ASYM_ENC_DEV g_hw_asym_enc_dev; + + struct ecc_prov { + int pid; +@@ -947,20 +948,26 @@ int uadk_prov_pkey_version(void) + { + struct uacce_dev *dev1, *dev2; + ++ if (g_hw_asym_enc_dev != HW_ASYM_ENC_INVALID) ++ return g_hw_asym_enc_dev; ++ + dev1 = uadk_get_accel_dev("rsa"); + if (!dev1) { + UADK_ERR("no pkey device available!\n"); +- return HW_PKEY_INVALID; ++ g_hw_asym_enc_dev = HW_ASYM_ENC_INVALID; ++ return g_hw_asym_enc_dev; + } + + dev2 = uadk_get_accel_dev("sm2"); + if (!dev2) { + free(dev1); +- return HW_PKEY_V2; ++ g_hw_asym_enc_dev = HW_ASYM_ENC_V2; ++ return g_hw_asym_enc_dev; + } + + free(dev1); + free(dev2); ++ g_hw_asym_enc_dev = HW_ASYM_ENC_V3; + +- return HW_PKEY_V3; ++ return g_hw_asym_enc_dev; + } +diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h +index 507e7ec..2f44aeb 100644 +--- a/src/uadk_prov_pkey.h ++++ b/src/uadk_prov_pkey.h +@@ -63,9 +63,12 @@ + #define TRANS_BITS_BYTES_SHIFT 3 + #define GET_MS_BYTE(n) ((n) >> 8) + #define GET_LS_BYTE(n) ((n) & 0xFF) +-#define HW_PKEY_V2 2 +-#define HW_PKEY_V3 3 +-#define HW_PKEY_INVALID 0 ++ ++enum HW_ASYM_ENC_DEV { ++ HW_ASYM_ENC_INVALID = 0x0, ++ HW_ASYM_ENC_V2 = 0x2, ++ HW_ASYM_ENC_V3 = 0x3 ++}; + + enum { + KEYMGMT_SM2 = 0x0, +-- +2.25.1 + diff --git a/0028-uadk_provider-move-several-macro-definitions-to-shar.patch b/0028-uadk_provider-move-several-macro-definitions-to-shar.patch new file mode 100644 index 0000000..4dc2938 --- /dev/null +++ b/0028-uadk_provider-move-several-macro-definitions-to-shar.patch @@ -0,0 +1,579 @@ +From bf260267dc98bcabde0c89f2f28ad03708833e87 Mon Sep 17 00:00:00 2001 +From: lizhi +Date: Tue, 16 Dec 2025 19:17:15 +0800 +Subject: [PATCH 28/32] uadk_provider: move several macro definitions to shared + header file + +Unified provider success and failure return values, and moved +return value macros to uadk_prov.h for better consistency and +maintainability. + +Signed-off-by: lizhi +Signed-off-by: JiangShui Yang +--- + src/uadk_prov.h | 3 + + src/uadk_prov_aead.c | 1 - + src/uadk_prov_cipher.c | 4 -- + src/uadk_prov_dh.c | 1 - + src/uadk_prov_digest.c | 1 - + src/uadk_prov_hmac.c | 122 ++++++++++++++++++++--------------------- + src/uadk_prov_pkey.h | 3 - + 7 files changed, 62 insertions(+), 73 deletions(-) + +diff --git a/src/uadk_prov.h b/src/uadk_prov.h +index 2261d3e..ac0de58 100644 +--- a/src/uadk_prov.h ++++ b/src/uadk_prov.h +@@ -30,6 +30,9 @@ + #define PROV_SEND_MAX_CNT 90000000 + #define PROV_RECV_MAX_CNT 60000000 + #define PROV_SCH_RECV_MAX_CNT 60000 ++#define UADK_P_SUCCESS 1 ++#define UADK_P_FAIL 0 ++#define UADK_DO_SOFT (-0xE0) + + /* Copy openssl/providers/implementations/include/prov/names.h */ + #define PROV_NAMES_MD5 "MD5:SSL3-MD5:1.2.840.113549.2.5" +diff --git a/src/uadk_prov_aead.c b/src/uadk_prov_aead.c +index f2e294b..4533540 100644 +--- a/src/uadk_prov_aead.c ++++ b/src/uadk_prov_aead.c +@@ -54,7 +54,6 @@ + #define PROV_CIPHER_FLAG_CUSTOM_IV 0x0002 + #define AEAD_FLAGS (PROV_CIPHER_FLAG_AEAD | PROV_CIPHER_FLAG_CUSTOM_IV) + +-#define UADK_DO_SOFT (-0xE0) + #define UADK_DO_HW (-0xF0) + #define UADK_AEAD_DEF_CTXS 2 + #define UADK_AEAD_OP_NUM 1 +diff --git a/src/uadk_prov_cipher.c b/src/uadk_prov_cipher.c +index 73359c6..0bb4aae 100644 +--- a/src/uadk_prov_cipher.c ++++ b/src/uadk_prov_cipher.c +@@ -30,7 +30,6 @@ + #include "uadk_prov.h" + #include "uadk_utils.h" + +-#define UADK_DO_SOFT (-0xE0) + #define UADK_DO_HW (-0xF0) + #define CTX_SYNC_ENC 0 + #define CTX_SYNC_DEC 1 +@@ -42,9 +41,6 @@ + #define ALG_NAME_SIZE 128 + #define GENERIC_BLOCK_SIZE 16 + +-#define UADK_P_SUCCESS 1 +-#define UADK_P_FAIL 0 +- + /* Internal flags that can be queried */ + #define PROV_CIPHER_FLAG_AEAD 0x0001 + #define PROV_CIPHER_FLAG_CUSTOM_IV 0x0002 +diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c +index 9b9859e..9def329 100644 +--- a/src/uadk_prov_dh.c ++++ b/src/uadk_prov_dh.c +@@ -45,7 +45,6 @@ + #define CTX_ASYNC 1 + #define CTX_SYNC 0 + #define CTX_NUM 2 +-#define UADK_DO_SOFT (-0xE0) + #define UADK_P_INIT_SUCCESS 0 + #define ENV_ENABLED 1 + #define KEY_GEN_BY_PROV 1 +diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c +index 239c31a..d9c5ae3 100644 +--- a/src/uadk_prov_digest.c ++++ b/src/uadk_prov_digest.c +@@ -32,7 +32,6 @@ + #include "uadk_prov.h" + #include "uadk_utils.h" + +-#define UADK_DO_SOFT (-0xE0) + #define CTX_SYNC 0 + #define CTX_ASYNC 1 + #define CTX_NUM 2 +diff --git a/src/uadk_prov_hmac.c b/src/uadk_prov_hmac.c +index d0b6a2c..e1a8b10 100644 +--- a/src/uadk_prov_hmac.c ++++ b/src/uadk_prov_hmac.c +@@ -32,10 +32,6 @@ + #include "uadk_prov.h" + #include "uadk_utils.h" + +-#define UADK_DO_SOFT (-0xE0) +-#define UADK_HMAC_SUCCESS 1 +-#define UADK_HMAC_FAIL 0 +- + /* The max BD data length is 16M-512B */ + #define BUF_LEN 0xFFFE00 + +@@ -126,12 +122,12 @@ static struct hmac_info hmac_info_table[] = { + static int uadk_create_hmac_soft_ctx(struct hmac_priv_ctx *priv) + { + if (priv->soft_md) +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + + priv->soft_libctx = OSSL_LIB_CTX_new(); + if (!priv->soft_libctx) { + UADK_ERR("new soft libctx failed.\n"); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + switch (priv->alg_id) { +@@ -161,7 +157,7 @@ static int uadk_create_hmac_soft_ctx(struct hmac_priv_ctx *priv) + goto free_mac_md; + } + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + + free_mac_md: + EVP_MAC_free(priv->soft_md); +@@ -170,7 +166,7 @@ free_libctx: + OSSL_LIB_CTX_free(priv->soft_libctx); + priv->soft_libctx = NULL; + +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + static int uadk_hmac_soft_init(struct hmac_priv_ctx *priv) +@@ -180,7 +176,7 @@ static int uadk_hmac_soft_init(struct hmac_priv_ctx *priv) + int ret; + + if (!priv->soft_md) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + /* The underlying digest to be used */ + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, priv->alg_name, +@@ -190,7 +186,7 @@ static int uadk_hmac_soft_init(struct hmac_priv_ctx *priv) + ret = EVP_MAC_init(priv->soft_ctx, priv->key, priv->keylen, params); + if (!ret) { + UADK_ERR("do soft hmac init failed!\n"); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + priv->switch_flag = UADK_DO_SOFT; +@@ -204,7 +200,7 @@ static int uadk_hmac_soft_update(struct hmac_priv_ctx *priv, + int ret; + + if (!priv->soft_md) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + ret = EVP_MAC_update(priv->soft_ctx, data, len); + if (!ret) +@@ -219,7 +215,7 @@ static int uadk_hmac_soft_final(struct hmac_priv_ctx *priv, unsigned char *out) + int ret; + + if (!priv->soft_md) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + ret = EVP_MAC_final(priv->soft_ctx, out, &hmac_length, priv->out_len); + if (!ret) +@@ -254,12 +250,12 @@ static int uadk_hmac_soft_work(struct hmac_priv_ctx *priv, int inl, + int ret; + + if (!priv->soft_md) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + if (!priv->switch_flag) { + ret = uadk_hmac_soft_init(priv); + if (unlikely(!ret)) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + if (inl) { +@@ -364,13 +360,13 @@ static int uadk_get_hmac_info(struct hmac_priv_ctx *priv) + priv->req.out_bytes = hmac_info_table[i].out_len; + priv->switch_threshold = hmac_info_table[i].threshold; + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + } + } + + UADK_ERR("failed to get hmac info, algname = %s.\n", priv->alg_name); + +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + static const char *get_uadk_alg_name(__u32 alg_id) +@@ -413,7 +409,7 @@ static int uadk_prov_hmac_dev_init(struct hmac_priv_ctx *priv) + { + struct wd_ctx_params cparams = {0}; + struct wd_ctx_nums ctx_set_num; +- int ret = UADK_HMAC_SUCCESS; ++ int ret = UADK_P_SUCCESS; + const char *alg_name; + + pthread_atfork(NULL, NULL, uadk_hmac_mutex_infork); +@@ -423,7 +419,7 @@ static int uadk_prov_hmac_dev_init(struct hmac_priv_ctx *priv) + + alg_name = get_uadk_alg_name(priv->alg_id); + if (!alg_name) { +- ret = UADK_HMAC_FAIL; ++ ret = UADK_P_FAIL; + goto mutex_unlock; + } + +@@ -431,7 +427,7 @@ static int uadk_prov_hmac_dev_init(struct hmac_priv_ctx *priv) + cparams.ctx_set_num = &ctx_set_num; + cparams.bmp = numa_allocate_nodemask(); + if (!cparams.bmp) { +- ret = UADK_HMAC_FAIL; ++ ret = UADK_P_FAIL; + UADK_ERR("failed to create nodemask!\n"); + goto mutex_unlock; + } +@@ -446,7 +442,7 @@ static int uadk_prov_hmac_dev_init(struct hmac_priv_ctx *priv) + UADK_ERR("uadk failed to initialize hmac, ret = %d\n", ret); + goto free_nodemask; + } +- ret = UADK_HMAC_SUCCESS; ++ ret = UADK_P_SUCCESS; + + hprov.pid = getpid(); + async_register_poll_fn(ASYNC_TASK_HMAC, uadk_hmac_poll); +@@ -461,14 +457,14 @@ mutex_unlock: + static int uadk_prov_compute_key_hash(struct hmac_priv_ctx *priv, + const unsigned char *key, size_t keylen) + { +- int ret = UADK_HMAC_FAIL; ++ int ret = UADK_P_FAIL; + __u32 outlen = 0; + EVP_MD_CTX *ctx; + EVP_MD *key_md; + + key_md = EVP_MD_fetch(priv->libctx, priv->alg_name, NULL); + if (!key_md) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + ctx = EVP_MD_CTX_new(); + if (!ctx) +@@ -480,7 +476,7 @@ static int uadk_prov_compute_key_hash(struct hmac_priv_ctx *priv, + goto free_ctx; + + priv->keylen = outlen; +- ret = UADK_HMAC_SUCCESS; ++ ret = UADK_P_SUCCESS; + + free_ctx: + EVP_MD_CTX_free(ctx); +@@ -528,7 +524,7 @@ static int uadk_hmac_ctx_init(struct hmac_priv_ctx *priv) + } + } + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + + free_sess: + wd_digest_free_sess(priv->sess); +@@ -565,15 +561,15 @@ static int uadk_do_hmac_sync(struct hmac_priv_ctx *priv) + if (priv->soft_md && + priv->req.in_bytes <= priv->switch_threshold && + priv->state == SEC_DIGEST_INIT) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + ret = wd_do_digest_sync(priv->sess, &priv->req); + if (ret) { + UADK_ERR("do sec hmac sync failed.\n"); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + } + + static int uadk_do_hmac_async(struct hmac_priv_ctx *priv, struct async_op *op) +@@ -584,7 +580,7 @@ static int uadk_do_hmac_async(struct hmac_priv_ctx *priv, struct async_op *op) + + if (unlikely(priv->switch_flag == UADK_DO_SOFT)) { + UADK_ERR("soft switching is not supported in asynchronous mode.\n"); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + cb_param.op = op; +@@ -595,7 +591,7 @@ static int uadk_do_hmac_async(struct hmac_priv_ctx *priv, struct async_op *op) + + ret = async_get_free_task(&idx); + if (!ret) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + op->idx = idx; + do { +@@ -613,13 +609,13 @@ static int uadk_do_hmac_async(struct hmac_priv_ctx *priv, struct async_op *op) + + ret = async_pause_job(priv, op, ASYNC_TASK_HMAC); + if (!ret || priv->req.state) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + + free_poll_task: + async_free_poll_task(op->idx, 0); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + static int uadk_hmac_update_inner(struct hmac_priv_ctx *priv, const void *data, size_t data_len) +@@ -630,8 +626,8 @@ static int uadk_hmac_update_inner(struct hmac_priv_ctx *priv, const void *data, + int ret; + + ret = uadk_hmac_ctx_init(priv); +- if (ret != UADK_HMAC_SUCCESS) +- return UADK_HMAC_FAIL; ++ if (ret != UADK_P_SUCCESS) ++ return UADK_P_FAIL; + + uadk_digest_set_msg_state(priv, false); + uadk_fill_mac_buffer_len(priv, false); +@@ -681,7 +677,7 @@ static int uadk_hmac_update_inner(struct hmac_priv_ctx *priv, const void *data, + priv->last_update_bufflen = remain_len; + uadk_memcpy(priv->data, input_data, priv->last_update_bufflen); + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + + do_soft_hmac: + if (priv->state == SEC_DIGEST_FIRST_UPDATING) { +@@ -710,7 +706,7 @@ do_soft_hmac: + return ret; + } + +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + err_out: + hmac_soft_cleanup(priv); +@@ -721,7 +717,7 @@ static int uadk_hmac_update(struct hmac_priv_ctx *priv, const void *data, size_t + { + if (!priv->data) { + UADK_ERR("failed to do digest update, data in CTX is NULL.\n"); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + if (unlikely(priv->switch_flag == UADK_DO_SOFT)) +@@ -732,7 +728,7 @@ static int uadk_hmac_update(struct hmac_priv_ctx *priv, const void *data, size_t + if (priv->last_update_bufflen + data_len <= HMAC_BLOCK_SIZE) { + uadk_memcpy(priv->data + priv->last_update_bufflen, data, data_len); + priv->last_update_bufflen += data_len; +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + } + + return uadk_hmac_update_inner(priv, data, data_len); +@@ -748,14 +744,14 @@ static int uadk_hmac_final(struct hmac_priv_ctx *priv, unsigned char *digest) + + if (!priv->data) { + UADK_ERR("failed to do digest final, data in CTX is NULL.\n"); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + /* It dose not need to be initialized again if the software calculation is applied. */ + if (priv->switch_flag != UADK_DO_SOFT) { + ret = uadk_hmac_ctx_init(priv); + if (!ret) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + priv->req.in = priv->data; +@@ -768,7 +764,7 @@ static int uadk_hmac_final(struct hmac_priv_ctx *priv, unsigned char *digest) + ret = async_setup_async_event_notification(&op); + if (unlikely(!ret)) { + UADK_ERR("failed to setup async event notification.\n"); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + if (!op.job) { +@@ -791,7 +787,7 @@ static int uadk_hmac_final(struct hmac_priv_ctx *priv, unsigned char *digest) + if (priv->state != SEC_DIGEST_INIT) + memcpy(digest, priv->req.out, priv->req.out_bytes); + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + + do_hmac_err: + if (priv->state == SEC_DIGEST_INIT) { +@@ -799,7 +795,7 @@ do_hmac_err: + SW_SWITCH_PRINT_ENABLE(enable_sw_offload)); + ret = uadk_hmac_soft_work(priv, priv->req.in_bytes, digest); + } else { +- ret = UADK_HMAC_FAIL; ++ ret = UADK_P_FAIL; + UADK_ERR("do sec digest final failed.\n"); + } + clear: +@@ -900,7 +896,7 @@ static int uadk_prov_hmac_setkey(struct hmac_priv_ctx *priv, + memcpy(priv->key, key, keylen); + priv->keylen = padding; + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + } + + static int uadk_prov_hmac_init(void *hctx, const unsigned char *key, +@@ -911,16 +907,16 @@ static int uadk_prov_hmac_init(void *hctx, const unsigned char *key, + + if (!hctx) { + UADK_ERR("CTX is NULL.\n"); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + ret = uadk_prov_hmac_set_ctx_params(hctx, params); + if (unlikely(!ret)) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + ret = uadk_get_hmac_info(priv); + if (unlikely(!ret)) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + if (enable_sw_offload) + uadk_create_hmac_soft_ctx(hctx); +@@ -928,14 +924,14 @@ static int uadk_prov_hmac_init(void *hctx, const unsigned char *key, + if (key) { + ret = uadk_prov_hmac_setkey(priv, key, keylen); + if (!ret) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + ret = uadk_prov_hmac_dev_init(priv); + if (unlikely(ret <= 0)) + goto soft_init; + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + + soft_init: + UADK_ERR("uadk failed to initialize dev%s.\n", +@@ -947,7 +943,7 @@ static int uadk_prov_hmac_update(void *hctx, const unsigned char *data, size_t d + { + if (!hctx || !data) { + UADK_ERR("CTX or input data is NULL.\n"); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + return uadk_hmac_update((struct hmac_priv_ctx *)hctx, data, datalen); +@@ -963,11 +959,11 @@ static int uadk_prov_hmac_final(void *hctx, unsigned char *out, size_t *outl, + size_t outsize) + { + struct hmac_priv_ctx *priv = (struct hmac_priv_ctx *)hctx; +- int ret = UADK_HMAC_SUCCESS; ++ int ret = UADK_P_SUCCESS; + + if (!hctx) { + UADK_ERR("hmac CTX or output data is NULL.\n"); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + if (out && outsize > 0) { +@@ -1013,17 +1009,17 @@ static int uadk_prov_hmac_get_ctx_params(void *hctx, OSSL_PARAM params[]) + OSSL_PARAM *p = NULL; + + if (!hctx) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE); + if (p && !OSSL_PARAM_set_size_t(p, priv->out_len)) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_BLOCK_SIZE); + if (p && !OSSL_PARAM_set_size_t(p, priv->blk_size)) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + } + + static const OSSL_PARAM uadk_prov_settable_ctx_params[] = { +@@ -1056,16 +1052,16 @@ static int uadk_prov_hmac_set_ctx_params(void *hctx, const OSSL_PARAM params[]) + int ret; + + if (!params || !params->key) +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + + if (!hctx) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST); + if (p) { + if (p->data_type != OSSL_PARAM_UTF8_STRING || + strlen((char *)p->data) > ALG_NAME_SIZE - 1) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + /* + * For subsequent character string matching, no end flag is added, +@@ -1074,7 +1070,7 @@ static int uadk_prov_hmac_set_ctx_params(void *hctx, const OSSL_PARAM params[]) + ret = snprintf(priv->alg_name, ALG_NAME_SIZE, "%s", (char *)p->data); + if (ret < 0) { + UADK_ERR("Invalid alg name %s.\n", (char *)p->data); +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + + uadk_hmac_name_uppercase(priv->alg_name); +@@ -1083,13 +1079,13 @@ static int uadk_prov_hmac_set_ctx_params(void *hctx, const OSSL_PARAM params[]) + p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY); + if (p) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + + if (!uadk_prov_hmac_setkey(priv, p->data, p->data_size)) +- return UADK_HMAC_FAIL; ++ return UADK_P_FAIL; + } + +- return UADK_HMAC_SUCCESS; ++ return UADK_P_SUCCESS; + } + + static void *uadk_prov_hmac_newctx(void *hctx) +diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h +index 2f44aeb..7891011 100644 +--- a/src/uadk_prov_pkey.h ++++ b/src/uadk_prov_pkey.h +@@ -41,9 +41,6 @@ + #define UADK_ECC_MAX_KEY_BITS 521 + #define UADK_ECC_MAX_KEY_BYTES 66 + #define UADK_ECC_CV_PARAM_NUM 6 +-#define UADK_DO_SOFT (-0xE0) +-#define UADK_P_SUCCESS 1 +-#define UADK_P_FAIL 0 + #define UADK_P_INVALID (-1) + #define PROV_KEYMGMT_ALG_NUM 7 + #define ECC_POINT_SIZE(n) ((n) << 1) +-- +2.25.1 + diff --git a/0029-uadk_engine-fix-the-SM2-x25519-x448-err-in-OpenSSL3..patch b/0029-uadk_engine-fix-the-SM2-x25519-x448-err-in-OpenSSL3..patch new file mode 100644 index 0000000..77e7a75 --- /dev/null +++ b/0029-uadk_engine-fix-the-SM2-x25519-x448-err-in-OpenSSL3..patch @@ -0,0 +1,217 @@ +From f76ed738eb6ed9d55560b027d85f03710bfa442f Mon Sep 17 00:00:00 2001 +From: Zhushuai Yin +Date: Tue, 16 Dec 2025 19:17:15 +0800 +Subject: [PATCH 29/32] uadk_engine: fix the SM2 x25519 x448 err in OpenSSL3.0 + +uadk_engine will support some algorithms in the OpenSSL 3.0 scenario. +Currently, the framework has adapted to some of these algorithms. +However, when executing the SM3 algorithm, an error related to SM2 +is reported. This is because OpenSSL 3.0 has removed SM2 from +the engine scenario in methmods, causing the failure. A fix is needed. + +At the same time, the differences in the pkey_ctx structure between +the two OpenSSL versions were resolved, enabling the engine +to support the x25519 and x448 algorithms on OpenSSL 3.0. + +Signed-off-by: Zhushuai Yin +Signed-off-by: JiangShui Yang +--- + src/uadk_ecx.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++- + src/uadk_pkey.c | 2 + + 2 files changed, 151 insertions(+), 3 deletions(-) + +diff --git a/src/uadk_ecx.c b/src/uadk_ecx.c +index 20a0f77..c9cc6c0 100644 +--- a/src/uadk_ecx.c ++++ b/src/uadk_ecx.c +@@ -35,11 +35,157 @@ + #define UADK_E_SUCCESS 1 + #define UADK_E_FAIL 0 + ++#if OPENSSL_VERSION_NUMBER >= 0x30000000 ++enum ECX_KEY_TYPE { ++ ECX_KEY_TYPE_X25519, ++ ECX_KEY_TYPE_X448, ++ ECX_KEY_TYPE_ED25519, ++ ECX_KEY_TYPE_ED448 ++}; ++ ++struct ecx_key { ++ OSSL_LIB_CTX *libctx; ++ char *propq; ++ unsigned int haspubkey:1; ++ unsigned char pubkey[ECX_MAX_KEYLEN]; ++ unsigned char *privkey; ++ size_t keylen; ++ enum ECX_KEY_TYPE type; ++ int references; ++ CRYPTO_RWLOCK *lock; ++}; ++ ++struct evp_pkey_ctx_st { ++ /* Actual operation */ ++ int operation; ++ ++ /* ++ * Library context, property query, keytype and keymgmt associated with ++ * this context ++ */ ++ OSSL_LIB_CTX *libctx; ++ char *propquery; ++ const char *keytype; ++ /* If |pkey| below is set, this field is always a reference to its keymgmt */ ++ EVP_KEYMGMT *keymgmt; ++ ++ union { ++ struct { ++ void *genctx; ++ } keymgmt; ++ ++ struct { ++ EVP_KEYEXCH *exchange; ++ /* ++ * Opaque ctx returned from a providers exchange algorithm ++ * implementation OSSL_FUNC_keyexch_newctx() ++ */ ++ void *algctx; ++ } kex; ++ ++ struct { ++ EVP_SIGNATURE *signature; ++ /* ++ * Opaque ctx returned from a providers signature algorithm ++ * implementation OSSL_FUNC_signature_newctx() ++ */ ++ void *algctx; ++ } sig; ++ ++ struct { ++ EVP_ASYM_CIPHER *cipher; ++ /* ++ * Opaque ctx returned from a providers asymmetric cipher algorithm ++ * implementation OSSL_FUNC_asym_cipher_newctx() ++ */ ++ void *algctx; ++ } ciph; ++ struct { ++ EVP_KEM *kem; ++ /* ++ * Opaque ctx returned from a providers KEM algorithm ++ * implementation OSSL_FUNC_kem_newctx() ++ */ ++ void *algctx; ++ } encap; ++ } op; ++ ++ /* ++ * Cached parameters. Inits of operations that depend on these should ++ * call evp_pkey_ctx_use_delayed_data() when the operation has been set ++ * up properly. ++ */ ++ struct { ++ /* Distinguishing Identifier, ISO/IEC 15946-3, FIPS 196 */ ++ char *dist_id_name; /* The name used with EVP_PKEY_CTX_ctrl_str() */ ++ void *dist_id; /* The distinguishing ID itself */ ++ size_t dist_id_len; /* The length of the distinguishing ID */ ++ ++ /* Indicators of what has been set. Keep them together! */ ++ unsigned int dist_id_set : 1; ++ } cached_parameters; ++ ++ /* Application specific data, usually used by the callback */ ++ void *app_data; ++ /* Keygen callback */ ++ EVP_PKEY_gen_cb *pkey_gencb; ++ /* implementation specific keygen data */ ++ int *keygen_info; ++ int keygen_info_count; ++ ++ /* Legacy fields below */ ++ ++ /* EVP_PKEY identity */ ++ int legacy_keytype; ++ /* Method associated with this operation */ ++ const EVP_PKEY_METHOD *pmeth; ++ /* Engine that implements this method or NULL if builtin */ ++ ENGINE *engine; ++ /* Key: may be NULL */ ++ EVP_PKEY *pkey; ++ /* Peer key for key agreement, may be NULL */ ++ EVP_PKEY *peerkey; ++ /* Algorithm specific data */ ++ void *data; ++ /* Indicator if digest_custom needs to be called */ ++ unsigned int flag_call_digest_custom:1; ++ /* ++ * Used to support taking custody of memory in the case of a provider being ++ * used with the deprecated EVP_PKEY_CTX_set_rsa_keygen_pubexp() API. This ++ * member should NOT be used for any other purpose and should be removed ++ * when said deprecated API is excised completely. ++ */ ++ BIGNUM *rsa_pubexp; ++}; ++#else + struct ecx_key { + unsigned char pubkey[ECX_MAX_KEYLEN]; + unsigned char *privkey; + }; + ++struct evp_pkey_ctx_st { ++ /* Method associated with this operation */ ++ const EVP_PKEY_METHOD *pmeth; ++ /* Engine that implements this method or NULL if builtin */ ++ ENGINE *engine; ++ /* Key: may be NULL */ ++ EVP_PKEY *pkey; ++ /* Peer key for key agreement, may be NULL */ ++ EVP_PKEY *peerkey; ++ /* Actual operation */ ++ int operation; ++ /* Algorithm specific data */ ++ void *data; ++ /* Application specific data */ ++ void *app_data; ++ /* Keygen callback */ ++ EVP_PKEY_gen_cb *pkey_gencb; ++ /* implementation specific keygen data */ ++ int *keygen_info; ++ int keygen_info_count; ++}; ++#endif ++ + struct ecx_ctx { + handle_t sess; + __u32 key_size; +@@ -151,12 +297,12 @@ static int x448_init(EVP_PKEY_CTX *ctx) + + static int ecx_get_nid(EVP_PKEY_CTX *ctx) + { +- const EVP_PKEY_METHOD **pmeth_from_ctx; ++ const EVP_PKEY_METHOD *pmeth_from_ctx; + int nid; + +- pmeth_from_ctx = (const EVP_PKEY_METHOD **)ctx; ++ pmeth_from_ctx = (const EVP_PKEY_METHOD *)(ctx->pmeth); + +- EVP_PKEY_meth_get0_info(&nid, NULL, *pmeth_from_ctx); ++ EVP_PKEY_meth_get0_info(&nid, NULL, pmeth_from_ctx); + if (nid != EVP_PKEY_X25519 && nid != EVP_PKEY_X448) + return UADK_E_FAIL; + +diff --git a/src/uadk_pkey.c b/src/uadk_pkey.c +index 94a74d9..fb45ccc 100644 +--- a/src/uadk_pkey.c ++++ b/src/uadk_pkey.c +@@ -34,7 +34,9 @@ static int g_ecc_support_state[ECC_TYPE]; + + static int pkey_nids[] = { + EVP_PKEY_EC, ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + EVP_PKEY_SM2, ++#endif + EVP_PKEY_X25519, + EVP_PKEY_X448 + }; +-- +2.25.1 + diff --git a/0030-uadk_provider-dh-set-meth-flags-when-new-dh.patch b/0030-uadk_provider-dh-set-meth-flags-when-new-dh.patch new file mode 100644 index 0000000..ce34487 --- /dev/null +++ b/0030-uadk_provider-dh-set-meth-flags-when-new-dh.patch @@ -0,0 +1,225 @@ +From 72f5d06899c2ca538e6bf115197bf0c702a3e6d2 Mon Sep 17 00:00:00 2001 +From: Weili Qian +Date: Thu, 18 Dec 2025 14:37:40 +0800 +Subject: [PATCH 30/32] uadk_provider/dh: set meth flags when new dh + +When creating new dh, set the flags from the method +and call the initialization function. In addition, +remove unnecessary parameter checks. + +Signed-off-by: Weili Qian +Signed-off-by: JiangShui Yang +--- + src/uadk_prov_dh.c | 108 +++++++++++++++++++++++++++++---------------- + 1 file changed, 69 insertions(+), 39 deletions(-) + +diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c +index 9def329..5bbab62 100644 +--- a/src/uadk_prov_dh.c ++++ b/src/uadk_prov_dh.c +@@ -383,13 +383,8 @@ static void *uadk_keymgmt_dh_dup(const void *keydata_from, int selection) + return get_default_dh_keymgmt().dup(keydata_from, selection); + } + +-static int uadk_DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) ++static void uadk_DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) + { +- if (dh == NULL) { +- UADK_ERR("invalid: dh is NULL\n"); +- return UADK_P_FAIL; +- } +- + if (pub_key != NULL) { + BN_clear_free(dh->pub_key); + dh->pub_key = pub_key; +@@ -401,8 +396,6 @@ static int uadk_DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) + } + + dh->dirty_cnt++; +- +- return UADK_P_SUCCESS; + } + + static FFC_PARAMS *ossl_dh_get0_params(DH *dh) +@@ -937,20 +930,17 @@ err: + return UADK_P_FAIL; + } + +-static int uadk_prov_dh_set_pkey(DH *dh, BIGNUM *pubkey, BIGNUM *prikey) ++static void uadk_prov_dh_set_pkey(DH *dh, BIGNUM *pubkey, BIGNUM *prikey) + { + const BIGNUM *old_priv = uadk_DH_get0_priv_key(dh); + const BIGNUM *old_pub = uadk_DH_get0_pub_key(dh); +- int ret = UADK_P_SUCCESS; + + if (old_pub != pubkey && old_priv != prikey) +- ret = uadk_DH_set0_key(dh, pubkey, prikey); ++ uadk_DH_set0_key(dh, pubkey, prikey); + else if (old_pub != pubkey) +- ret = uadk_DH_set0_key(dh, pubkey, NULL); ++ uadk_DH_set0_key(dh, pubkey, NULL); + else if (old_priv != prikey) +- ret = uadk_DH_set0_key(dh, NULL, prikey); +- +- return ret; ++ uadk_DH_set0_key(dh, NULL, prikey); + } + + static int uadk_prov_dh_generate_key(DH *dh) +@@ -962,11 +952,6 @@ static int uadk_prov_dh_generate_key(DH *dh) + BIGNUM *pubkey = NULL; + int ret; + +- if (dh == NULL) { +- UADK_ERR("invalid: dh is NULL\n"); +- return UADK_P_FAIL; +- } +- + ret = uadk_prov_dh_init(); + if (ret) { + UADK_ERR("failed to init dh\n"); +@@ -1005,14 +990,12 @@ static int uadk_prov_dh_generate_key(DH *dh) + goto free_req; + } + +- ret = uadk_prov_dh_set_pkey(dh, pubkey, prikey); +- if (ret == UADK_P_FAIL) +- UADK_ERR("failed to set dh pkey\n"); ++ uadk_prov_dh_set_pkey(dh, pubkey, prikey); + + uadk_prov_dh_free_genkey_req(dh_sess); + uadk_prov_dh_free_session(dh_sess); + +- return ret; ++ return UADK_P_SUCCESS; + + free_req: + uadk_prov_dh_free_genkey_req(dh_sess); +@@ -1087,10 +1070,22 @@ static int ossl_dh_generate_ffc_parameters(DH *dh, int type, int pbits, int qbit + return ret; + } + ++static int dh_down_ref(int *val) ++{ ++ int i; ++ ++ i = __atomic_fetch_sub(val, 1, __ATOMIC_RELAXED) - 1; ++ if (i == 0) ++ __atomic_thread_fence(__ATOMIC_ACQUIRE); ++ ++ return i; ++} ++ + static DH *ossl_dh_new_ex(OSSL_LIB_CTX *libctx) + { +- DH *dh = OPENSSL_zalloc(sizeof(*dh)); ++ DH *dh; + ++ dh = OPENSSL_zalloc(sizeof(*dh)); + if (dh == NULL) { + UADK_ERR("failed to alloc dh\n"); + return NULL; +@@ -1100,21 +1095,63 @@ static DH *ossl_dh_new_ex(OSSL_LIB_CTX *libctx) + dh->lock = CRYPTO_THREAD_lock_new(); + if (dh->lock == NULL) { + UADK_ERR("failed to new dh thread lock\n"); +- OPENSSL_free(dh); +- return NULL; ++ goto free_dh; + } + + dh->libctx = libctx; ++ dh->meth = DH_get_default_method(); ++ dh->flags = dh->meth->flags; ++ ++#ifndef FIPS_MODULE ++ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data)) { ++ UADK_ERR("failed to new ex_data\n"); ++ goto free_lock; ++ } ++#endif /* FIPS_MODULE */ ++ ++ ossl_ffc_params_init(&dh->params); ++ ++ if ((dh->meth->init != NULL) && !dh->meth->init(dh)) { ++ UADK_ERR("failed to init dh\n"); ++ goto free_ex_data; ++ } + + return dh; ++ ++free_ex_data: ++#ifndef FIPS_MODULE ++ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data); ++free_lock: ++#endif /* FIPS_MODULE */ ++ CRYPTO_THREAD_lock_free(dh->lock); ++free_dh: ++ OPENSSL_free(dh); ++ return NULL; + } + + static void ossl_dh_free_ex(DH *dh) + { +- if (dh) { +- CRYPTO_THREAD_lock_free(dh->lock); +- OPENSSL_free(dh); +- } ++ int i; ++ ++ if (dh == NULL) ++ return; ++ ++ i = dh_down_ref(&dh->references); ++ if (i > 0) ++ return; ++ ++ if (dh->meth != NULL && dh->meth->finish != NULL) ++ dh->meth->finish(dh); ++#ifndef FIPS_MODULE ++ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data); ++#endif /* FIPS_MODULE */ ++ ++ CRYPTO_THREAD_lock_free(dh->lock); ++ ++ ossl_ffc_params_cleanup(&dh->params); ++ BN_clear_free(dh->pub_key); ++ BN_clear_free(dh->priv_key); ++ OPENSSL_free(dh); + } + + static DH *uadk_prov_dh_gen_params_with_group(PROV_DH_KEYMGMT_CTX *gctx, FFC_PARAMS **ffc) +@@ -1143,7 +1180,6 @@ static DH *uadk_prov_dh_gen_params_with_group(PROV_DH_KEYMGMT_CTX *gctx, FFC_PAR + return NULL; + } + +- dh->meth = DH_get_default_method(); + ossl_ffc_named_group_set(&dh->params, group); + dh->params.nid = ossl_ffc_named_group_get_uid(group); + dh->dirty_cnt++; +@@ -1280,12 +1316,6 @@ static DH *uadk_prov_dh_gen_params(PROV_DH_KEYMGMT_CTX *gctx, FFC_PARAMS **ffc, + + static void uadk_prov_dh_free_params(DH *dh) + { +- FFC_PARAMS *ffc; +- +- ffc = ossl_dh_get0_params(dh); +- if (ffc) +- ossl_ffc_params_cleanup(ffc); +- + /* + * Release DH object that allocated by uadk_prov_dh_gen_params_ex() or + * uadk_prov_dh_gen_params_with_group(). +@@ -1306,8 +1336,8 @@ static void *uadk_keymgmt_dh_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_param + { + PROV_DH_KEYMGMT_CTX *gctx = (PROV_DH_KEYMGMT_CTX *)genctx; + FFC_PARAMS *ffc = NULL; ++ int ret = UADK_P_FAIL; + DH *dh = NULL; +- int ret; + + if (gctx == NULL) { + UADK_ERR("invalid: keygen ctx is NULL\n"); +-- +2.25.1 + diff --git a/0031-uadk_engine-delete-several-unused-functions.patch b/0031-uadk_engine-delete-several-unused-functions.patch new file mode 100644 index 0000000..642a55e --- /dev/null +++ b/0031-uadk_engine-delete-several-unused-functions.patch @@ -0,0 +1,35 @@ +From 59427edf3da256cec3d0dc61a8cfe1226fd013aa Mon Sep 17 00:00:00 2001 +From: lizhi +Date: Tue, 16 Dec 2025 19:17:15 +0800 +Subject: [PATCH 31/32] uadk_engine: delete several unused functions + +Delete several unused functions in asymmetric encryption algorithm to +improve code clarity. + +Signed-off-by: lizhi +Signed-off-by: JiangShui Yang +--- + src/uadk_pkey.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/uadk_pkey.h b/src/uadk_pkey.h +index 05b6881..73472f2 100644 +--- a/src/uadk_pkey.h ++++ b/src/uadk_pkey.h +@@ -75,13 +75,10 @@ int uadk_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p, + int uadk_init_ecc(void); + const EVP_PKEY_METHOD *get_openssl_pkey_meth(int nid); + int uadk_sm2_create_pmeth(struct uadk_pkey_meth *pkey_meth); +-void uadk_sm2_delete_pmeth(struct uadk_pkey_meth *pkey_meth); + int uadk_ec_create_pmeth(struct uadk_pkey_meth *pkey_meth); + void uadk_ec_delete_meth(void); + int uadk_x448_create_pmeth(struct uadk_pkey_meth *pkey_meth); +-void uadk_x448_delete_pmeth(struct uadk_pkey_meth *pkey_meth); + int uadk_x25519_create_pmeth(struct uadk_pkey_meth *pkey_meth); +-void uadk_x25519_delete_pmeth(struct uadk_pkey_meth *pkey_meth); + int uadk_bind_ec(ENGINE *e); + int uadk_e_ecc_get_numa_id(void); + int uadk_e_ecc_get_support_state(int alg_tag); +-- +2.25.1 + diff --git a/0032-uadk_engine-fixup-a-bug-in-rsa-X931-padding-mode.patch b/0032-uadk_engine-fixup-a-bug-in-rsa-X931-padding-mode.patch new file mode 100644 index 0000000..195cb0b --- /dev/null +++ b/0032-uadk_engine-fixup-a-bug-in-rsa-X931-padding-mode.patch @@ -0,0 +1,33 @@ +From 963c0c6e392d35106eafe531f89f0e1532eda036 Mon Sep 17 00:00:00 2001 +From: lizhi +Date: Tue, 16 Dec 2025 19:17:15 +0800 +Subject: [PATCH 32/32] uadk_engine: fixup a bug in rsa X931 padding mode + +Fix a null pointer dereference bug in RSA X931 mode. + +Signed-off-by: lizhi +Signed-off-by: JiangShui Yang +--- + src/uadk_rsa.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/src/uadk_rsa.c b/src/uadk_rsa.c +index f99b43b..160ab8c 100644 +--- a/src/uadk_rsa.c ++++ b/src/uadk_rsa.c +@@ -656,11 +656,9 @@ static int rsa_get_sign_res(int padding, BIGNUM *to_bn, const BIGNUM *n, + + static int rsa_get_verify_res(int padding, const BIGNUM *n, BIGNUM *ret_bn) + { +- BIGNUM *to_bn = NULL; +- + if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret_bn)[0] & 0xf) + != 0x0c)) { +- if (!BN_sub(to_bn, n, ret_bn)) ++ if (!BN_sub(ret_bn, n, ret_bn)) + return UADK_E_FAIL; + } + +-- +2.25.1 + diff --git a/uadk_engine.spec b/uadk_engine.spec index 54bb7a0..87ab5cd 100644 --- a/uadk_engine.spec +++ b/uadk_engine.spec @@ -2,7 +2,7 @@ Name: uadk_engine Summary: UADK Accelerator Engine Version: 1.6.0 -Release: 3 +Release: 4 License: Apache-2.0 Source: %{name}-%{version}.tar.gz ExclusiveOS: linux @@ -36,6 +36,16 @@ Patch0019: 0019-uadk_provider-fix-the-issue-of-algorithm-prohibition.patch Patch0020: 0020-uadk_provider-fix-issues-that-may-cause-encryption-t.patch Patch0021: 0021-uadk_engine-fix-the-issue-of-incorrect-engine-use-th.patch Patch0022: 0022-uadk_provider-adding-security-compilation-dptions-to.patch +Patch0023: 0023-uadk_provider-split-RSA-algorithm-into-four-function.patch +Patch0024: 0024-uadk_provider-add-some-RSA-utils-functions-to-adapt-.patch +Patch0025: 0025-uadk_provider-adapt-rsa-signature-operation-with-X93.patch +Patch0026: 0026-uadk_provider-adapt-rsa-encryption-operation-with-OA.patch +Patch0027: 0027-provider-optimize-hardware-version-and-availability-.patch +Patch0028: 0028-uadk_provider-move-several-macro-definitions-to-shar.patch +Patch0029: 0029-uadk_engine-fix-the-SM2-x25519-x448-err-in-OpenSSL3..patch +Patch0030: 0030-uadk_provider-dh-set-meth-flags-when-new-dh.patch +Patch0031: 0031-uadk_engine-delete-several-unused-functions.patch +Patch0032: 0032-uadk_engine-fixup-a-bug-in-rsa-X931-padding-mode.patch %description This package contains the UADK Accelerator Engine. @@ -96,6 +106,9 @@ rm -rf ${RPM_BUILD_ROOT} /sbin/ldconfig %changelog +* Tue Dec 16 2025 JiangShui Yang 1.6.0-4 + - uadk_provider supports more RSA padding modes + * Tue Nov 18 2025 JiangShui Yang 1.6.0-3 - Backport uadk engine patch -- Gitee