[PATCH 00/11] uadk_provider: adapt rsa with several padding modes
From: parm64 <parm64@huawei.com> Add support for multiple RSA padding modes with OpenSSL provider mechanism. 1. RSA_X931_PADDING and RSA_PKCS1_PSS_PADDING for signing and verification. 2. RSA_PKCS1_OAEP_PADDING and RSA_PKCS1_WITH_TLS_PADDING for encryption and decryption. Weili Qian (1): uadk_provider/dh: set meth flags when new dh Zhushuai Yin (2): uadk_engine: fix the SM2 x25519 x448 err in OpenSSL3.0 uadk_provider: prov added compilation options lizhi (8): uadk_provider: split RSA algorithm into four functional components uadk_provider: add some RSA utils functions to adapt RSA with several padding modes uadk_provider: adapt rsa signature operation with X931 and PKCS1_PSS padding modes uadk_provider: adapt rsa encryption operation with OAEP and PKCS1_WITH_TLS padding modes provider: optimize hardware version and availability queries using global variables uadk_provider: move several macro definitions to shared header file uadk_engine: delete several unused functions uadk_engine: fixup a bug in rsa X931 padding mode src/Makefile.am | 9 +- src/uadk_ecx.c | 152 +- src/uadk_pkey.c | 2 + src/uadk_pkey.h | 3 - src/uadk_prov.h | 11 +- src/uadk_prov_aead.c | 1 - src/uadk_prov_cipher.c | 18 +- src/uadk_prov_dh.c | 107 +- src/uadk_prov_digest.c | 15 +- src/uadk_prov_hmac.c | 122 +- src/uadk_prov_init.c | 10 +- src/uadk_prov_pkey.c | 13 +- src/uadk_prov_pkey.h | 12 +- src/uadk_prov_rsa.c | 2974 ++----------------------------------- src/uadk_prov_rsa.h | 179 +++ src/uadk_prov_rsa_enc.c | 692 +++++++++ src/uadk_prov_rsa_kmgmt.c | 975 ++++++++++++ src/uadk_prov_rsa_sign.c | 1676 +++++++++++++++++++++ src/uadk_prov_rsa_utils.c | 138 ++ src/uadk_rsa.c | 4 +- 20 files changed, 4156 insertions(+), 2957 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 create mode 100644 src/uadk_prov_rsa_utils.c -- 2.43.0
From: lizhi <lizhi206@huawei.com> 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 <lizhi206@huawei.com> --- 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 <openssl/bn.h> -#include <openssl/core.h> -#include <openssl/core_names.h> -#include <openssl/crypto.h> -#include <openssl/err.h> -#include <openssl/proverr.h> -#include <openssl/rsa.h> -#include <openssl/sha.h> -#include <openssl/types.h> -#include <uadk/wd_rsa.h> -#include <uadk/wd_sched.h> -#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 <openssl/bn.h> +#include <openssl/core.h> +#include <openssl/core_names.h> +#include <openssl/crypto.h> +#include <openssl/err.h> +#include <openssl/proverr.h> +#include <openssl/rsa.h> +#include <openssl/sha.h> +#include <openssl/types.h> +#include <uadk/wd_rsa.h> +#include <uadk/wd_sched.h> +#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.43.0
From: lizhi <lizhi206@huawei.com> 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 <lizhi206@huawei.com> --- src/Makefile.am | 1 + src/uadk_prov_rsa_utils.c | 138 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 src/uadk_prov_rsa_utils.c 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_utils.c b/src/uadk_prov_rsa_utils.c new file mode 100644 index 0000000..240851a --- /dev/null +++ b/src/uadk_prov_rsa_utils.c @@ -0,0 +1,138 @@ +// 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" + +/* True if PSS parameters are restricted */ +#define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1) + +static struct rsa_pss_params_30_st *ossl_rsa_get0_pss_params_30(RSA *r) +{ + return &r->pss_params; +} + +static 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) */ +}; + +static 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; +} + +static 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; +} + +static 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; +} + +static 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; +} + +static 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 }, +}; + +static 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)); +} + +static 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); +} -- 2.43.0
From: lizhi <lizhi206@huawei.com> 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 <lizhi206@huawei.com> --- src/uadk_prov_rsa_sign.c | 992 ++++++++++++++++++++++++++++++--------- 1 file changed, 765 insertions(+), 227 deletions(-) diff --git a/src/uadk_prov_rsa_sign.c b/src/uadk_prov_rsa_sign.c index 8e0a571..b65bae0 100644 --- a/src/uadk_prov_rsa_sign.c +++ b/src/uadk_prov_rsa_sign.c @@ -16,7 +16,16 @@ * limitations under the License. * */ -#include "uadk_prov_rsa.h" +#include "uadk_prov_rsa_utils.c" + +#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); @@ -60,6 +69,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; @@ -82,13 +94,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; } @@ -118,19 +137,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; } @@ -144,20 +165,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; } @@ -186,11 +211,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; } @@ -372,15 +395,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 */ @@ -393,6 +628,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"); @@ -402,26 +639,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, @@ -436,28 +767,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)) @@ -466,9 +951,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, @@ -482,49 +965,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) @@ -532,18 +1198,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: @@ -556,25 +1225,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[] = { @@ -641,7 +1302,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++) @@ -679,35 +1340,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); @@ -729,7 +1388,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, @@ -738,26 +1397,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) { @@ -765,7 +1424,7 @@ error: priv->mdctx = NULL; } - return 0; + return UADK_P_FAIL; } static int uadk_signature_rsa_digest_sign_init(void *vprsactx, const char *mdname, @@ -781,7 +1440,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); @@ -847,9 +1506,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 @@ -868,25 +1524,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, @@ -894,21 +1550,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. @@ -920,49 +1569,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, @@ -977,8 +1588,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); } @@ -987,16 +1598,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; /* @@ -1006,78 +1614,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.43.0
From: lizhi <lizhi206@huawei.com> 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 <lizhi206@huawei.com> --- 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 <openssl/prov_ssl.h> +#include <openssl/rand.h> + +#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.43.0
From: lizhi <lizhi206@huawei.com> Introduce global variables to cache hardware version, reducing repeated device queries. Signed-off-by: lizhi <lizhi206@huawei.com> --- 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.43.0
From: lizhi <lizhi206@huawei.com> 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 <lizhi206@huawei.com> --- 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.43.0
From: Zhushuai Yin <yinzhushuai@huawei.com> 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 <yinzhushuai@huawei.com> --- 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.43.0
From: Weili Qian <qianweili@huawei.com> 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 <qianweili@huawei.com> --- src/uadk_prov_dh.c | 106 +++++++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 38 deletions(-) diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c index 9def329..3c78ee2 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(). -- 2.43.0
From: Zhushuai Yin <yinzhushuai@huawei.com> add some general optimization compilation options, security enhancement options, linker security options, etc. Signed-off-by: Zhushuai Yin <yinzhushuai@huawei.com> --- src/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 22f1069..5a2539c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,3 +77,5 @@ uadk_provider_la_LDFLAGS=-module -version-number $(VERSION) uadk_provider_la_LIBADD=$(WD_LIBS) -lpthread uadk_provider_la_CFLAGS=$(WD_CFLAGS) $(libcrypto_CFLAGS) uadk_provider_la_CFLAGS+=-DOPENSSL_SUPPRESS_DEPRECATED +uadk_provider_la_CFLAGS+=-fPIC -fPIE -pie -fstack-protector-strong -D_FORTIFY_SOURCE=2 \ + -O2 -ftrapv -Wl,-z,relro,-z,now -Wl,-s -- 2.43.0
From: lizhi <lizhi206@huawei.com> Delete several unused functions in asymmetric encryption algorithm to improve code clarity. Signed-off-by: lizhi <lizhi206@huawei.com> --- 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.43.0
From: lizhi <lizhi206@huawei.com> Fix a null pointer dereference bug in RSA X931 mode. Signed-off-by: lizhi <lizhi206@huawei.com> --- 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.43.0
participants (1)
-
ZongYu Wu