From 49894a710e811b03fe311bbb27eddb99bede1733 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Wed, 13 Sep 2023 17:46:29 +0800 Subject: [PATCH 44/48] uadk: add uadk_prov_rsa for openssl 3.0 Test: openssl speed -provider uadk_provider rsa1024 openssl speed -provider uadk_provider rsa2048 openssl speed -provider uadk_provider rsa4096 openssl speed -provider uadk_provider -async_jobs 1 rsa1024 openssl speed -provider uadk_provider -async_jobs 1 rsa2048 openssl speed -provider uadk_provider -async_jobs 1 rsa4096 openssl genrsa -out prikey.pem -provider uadk_provider 1024 openssl rsa -in prikey.pem -pubout -out pubkey.pem \ -provider uadk_provider -provider default echo "Content to be encrypted" > plain.txt openssl pkeyutl -encrypt -in plain.txt -inkey pubkey.pem -pubin -out enc.txt \ -pkeyopt rsa_padding_mode:pkcs1 -provider uadk_provider -provider default openssl pkeyutl -decrypt -in enc.txt -inkey prikey.pem -out dec.txt \ -pkeyopt rsa_padding_mode:pkcs1 -provider uadk_provider -provider default Notes: "-provider default" is required when -store-loaders is required $ openssl list -provider default -store-loaders Provided STORE LOADERs: file @ default $ openssl rsa -in prikey.pem -pubout -out pubkey.pem -provider uadk_provider -provider default writing RSA key $ openssl rsa -in prikey.pem -pubout -out pubkey.pem -provider uadk_provider Could not open file or uri for loading private key from prikey.pem 206096A7FFFF0000:error:16000069:STORE routines:ossl_store_get0_loader_int:unregistered scheme:crypto/store/store_register.c:237:scheme=file 206096A7FFFF0000:error:1608010C:STORE routines:inner_loader_fetch:unsupported:crypto/store/store_meth.c:383:No store loader found. For standard store loaders you need at least one of the default or base providers available. Did you forget to load them? Info: Global default library context, Scheme (file : 0), Properties () Signed-off-by: Zhangfei Gao --- src/Makefile.am | 3 +- src/uadk_prov.h | 17 + src/uadk_prov_init.c | 29 +- src/uadk_prov_rsa.c | 2953 ++++++++++++++++++++++++++++++++++++++++++ test/sanity_test.sh | 21 + 5 files changed, 3017 insertions(+), 6 deletions(-) create mode 100644 src/uadk_prov_rsa.c diff --git a/src/Makefile.am b/src/Makefile.am index af16d85..6fdee47 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,7 +51,8 @@ uadk_engine_la_SOURCES+=v1/alg/ciphers/sec_ciphers.c \ 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_digest.c uadk_prov_cipher.c \ + uadk_prov_rsa.c uadk_provider_la_LDFLAGS=-module -version-number $(VERSION) uadk_provider_la_LIBADD=$(WD_LIBS) -lpthread diff --git a/src/uadk_prov.h b/src/uadk_prov.h index 35f1789..f8a3cd7 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -18,6 +18,18 @@ #ifndef UADK_PROV_H #define UADK_PROV_H +struct p_uadk_ctx { + const OSSL_CORE_HANDLE *handle; + OSSL_LIB_CTX *libctx; +}; + +static inline OSSL_LIB_CTX *prov_libctx_of(struct p_uadk_ctx *ctx) +{ + if (ctx == NULL) + return NULL; + return ctx->libctx; +} + extern const OSSL_DISPATCH uadk_md5_functions[]; extern const OSSL_DISPATCH uadk_sm3_functions[]; extern const OSSL_DISPATCH uadk_sha1_functions[]; @@ -39,6 +51,11 @@ extern const OSSL_DISPATCH uadk_sm4_ecb_functions[]; extern const OSSL_DISPATCH uadk_des_ede3_cbc_functions[]; extern const OSSL_DISPATCH uadk_des_ede3_ecb_functions[]; +extern const OSSL_DISPATCH uadk_rsa_signature_functions[]; +extern const OSSL_DISPATCH uadk_rsa_keymgmt_functions[]; +extern const OSSL_DISPATCH uadk_rsa_asym_cipher_functions[]; + void uadk_prov_destroy_digest(void); void uadk_prov_destroy_cipher(void); +void uadk_prov_destroy_rsa(void); #endif diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 965092d..b28ce69 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -28,11 +28,6 @@ #include "uadk_async.h" #include "uadk_prov.h" -struct p_uadk_ctx { - const OSSL_CORE_HANDLE *handle; - OSSL_LIB_CTX *libctx; -}; - const char *engine_uadk_id = "uadk_provider"; static const char UADK_DEFAULT_PROPERTIES[] = "provider=uadk_provider"; static OSSL_PROVIDER *prov; @@ -83,6 +78,23 @@ const OSSL_ALGORITHM uadk_prov_ciphers[] = { { NULL, NULL, NULL } }; +static const OSSL_ALGORITHM uadk_prov_signature[] = { + {"RSA", UADK_DEFAULT_PROPERTIES, + uadk_rsa_signature_functions, "uadk_provider rsa_signature" }, + {NULL, NULL, NULL} +}; + +static const OSSL_ALGORITHM uadk_prov_keymgmt[] = { + {"RSA", UADK_DEFAULT_PROPERTIES, + uadk_rsa_keymgmt_functions, "uadk RSA Keymgmt implementation."}, + {NULL, NULL, NULL} +}; + +static const OSSL_ALGORITHM uadk_prov_asym_cipher[] = { + { "RSA", UADK_DEFAULT_PROPERTIES, uadk_rsa_asym_cipher_functions }, + { NULL, NULL, NULL } +}; + static const OSSL_ALGORITHM *p_prov_query(void *provctx, int operation_id, int *no_cache) { @@ -103,6 +115,12 @@ static const OSSL_ALGORITHM *p_prov_query(void *provctx, int operation_id, return uadk_prov_digests; case OSSL_OP_CIPHER: return uadk_prov_ciphers; + case OSSL_OP_SIGNATURE: + return uadk_prov_signature; + case OSSL_OP_KEYMGMT: + return uadk_prov_keymgmt; + case OSSL_OP_ASYM_CIPHER: + return uadk_prov_asym_cipher; } return NULL; } @@ -113,6 +131,7 @@ static void p_teardown(void *provctx) uadk_prov_destroy_digest(); uadk_prov_destroy_cipher(); + uadk_prov_destroy_rsa(); OPENSSL_free(ctx); OSSL_PROVIDER_unload(prov); async_poll_task_free(); diff --git a/src/uadk_prov_rsa.c b/src/uadk_prov_rsa.c new file mode 100644 index 0000000..a342e92 --- /dev/null +++ b/src/uadk_prov_rsa.c @@ -0,0 +1,2953 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "uadk_async.h" +#include "uadk.h" +#include "uadk_prov.h" + +#define UN_SET 0 +#define IS_SET 1 +#define BIT_BYTES_SHIFT 3 +#define RSA_MIN_MODULUS_BITS 512 +#define RSA_MAX_PRIME_NUM 2 +#define RSA1024BITS 1024 +#define RSA2048BITS 2048 +#define RSA3072BITS 3072 +#define RSA4096BITS 4096 +#define OPENSSLRSA7680BITS 7680 +#define OPENSSLRSA15360BITS 15360 +#define CTX_ASYNC 1 +#define CTX_SYNC 0 +#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 SOFT 2 +#define UNUSED(x) ((void)(x)) +#define UADK_E_SUCCESS 1 +#define UADK_E_FAIL 0 +#define UADK_DO_SOFT (-0xE0) +#define UADK_E_POLL_SUCCESS 0 +#define UADK_E_POLL_FAIL (-1) +#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 + +struct bignum_st { + BN_ULONG *d; + int top; + int dmax; + int neg; + int flags; +}; + +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_pubkey_param { + const BIGNUM *e; + const BIGNUM *n; +}; + +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; +}; + +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_sched { + int sched_type; + struct wd_sched wd_sched; +}; + +struct rsa_prov { + int pid; +}; +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; //CRYPTO_REF_COUNT 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 rsa_st RSA; + +typedef int CRYPTO_REF_COUNT; + +struct evp_signature_st { + int name_id; + char *type_name; + const char *description; + OSSL_PROVIDER *prov; + CRYPTO_REF_COUNT refcnt; + CRYPTO_RWLOCK *lock; + + OSSL_FUNC_signature_newctx_fn *newctx; + OSSL_FUNC_signature_sign_init_fn *sign_init; + OSSL_FUNC_signature_sign_fn *sign; + OSSL_FUNC_signature_verify_init_fn *verify_init; + OSSL_FUNC_signature_verify_fn *verify; + OSSL_FUNC_signature_verify_recover_init_fn *verify_recover_init; + OSSL_FUNC_signature_verify_recover_fn *verify_recover; + OSSL_FUNC_signature_digest_sign_init_fn *digest_sign_init; + OSSL_FUNC_signature_digest_sign_update_fn *digest_sign_update; + OSSL_FUNC_signature_digest_sign_final_fn *digest_sign_final; + OSSL_FUNC_signature_digest_sign_fn *digest_sign; + OSSL_FUNC_signature_digest_verify_init_fn *digest_verify_init; + OSSL_FUNC_signature_digest_verify_update_fn *digest_verify_update; + OSSL_FUNC_signature_digest_verify_final_fn *digest_verify_final; + OSSL_FUNC_signature_digest_verify_fn *digest_verify; + OSSL_FUNC_signature_freectx_fn *freectx; + OSSL_FUNC_signature_dupctx_fn *dupctx; + OSSL_FUNC_signature_get_ctx_params_fn *get_ctx_params; + OSSL_FUNC_signature_gettable_ctx_params_fn *gettable_ctx_params; + OSSL_FUNC_signature_set_ctx_params_fn *set_ctx_params; + OSSL_FUNC_signature_settable_ctx_params_fn *settable_ctx_params; + OSSL_FUNC_signature_get_ctx_md_params_fn *get_ctx_md_params; + OSSL_FUNC_signature_gettable_ctx_md_params_fn *gettable_ctx_md_params; + OSSL_FUNC_signature_set_ctx_md_params_fn *set_ctx_md_params; + OSSL_FUNC_signature_settable_ctx_md_params_fn *settable_ctx_md_params; +} /* EVP_SIGNATURE */; + +struct evp_asym_cipher_st { + int name_id; + char *type_name; + const char *description; + OSSL_PROVIDER *prov; + CRYPTO_REF_COUNT refcnt; + CRYPTO_RWLOCK *lock; + + OSSL_FUNC_asym_cipher_newctx_fn *newctx; + OSSL_FUNC_asym_cipher_encrypt_init_fn *encrypt_init; + OSSL_FUNC_asym_cipher_encrypt_fn *encrypt; + OSSL_FUNC_asym_cipher_decrypt_init_fn *decrypt_init; + OSSL_FUNC_asym_cipher_decrypt_fn *decrypt; + OSSL_FUNC_asym_cipher_freectx_fn *freectx; + OSSL_FUNC_asym_cipher_dupctx_fn *dupctx; + OSSL_FUNC_asym_cipher_get_ctx_params_fn *get_ctx_params; + OSSL_FUNC_asym_cipher_gettable_ctx_params_fn *gettable_ctx_params; + OSSL_FUNC_asym_cipher_set_ctx_params_fn *set_ctx_params; + OSSL_FUNC_asym_cipher_settable_ctx_params_fn *settable_ctx_params; +} /* EVP_ASYM_CIPHER */; + +typedef struct{ + int id; /* libcrypto internal */ + int name_id; + char *type_name; + const char *description; + OSSL_PROVIDER *prov; + + int refcnt; + void *lock; + + /* Constructor(s), destructor, information */ + OSSL_FUNC_keymgmt_new_fn *new; + OSSL_FUNC_keymgmt_free_fn *free; + OSSL_FUNC_keymgmt_get_params_fn *get_params; + OSSL_FUNC_keymgmt_gettable_params_fn *gettable_params; + OSSL_FUNC_keymgmt_set_params_fn *set_params; + OSSL_FUNC_keymgmt_settable_params_fn *settable_params; + + /* Generation, a complex constructor */ + OSSL_FUNC_keymgmt_gen_init_fn *gen_init; + OSSL_FUNC_keymgmt_gen_set_template_fn *gen_set_template; + OSSL_FUNC_keymgmt_gen_set_params_fn *gen_set_params; + OSSL_FUNC_keymgmt_gen_settable_params_fn *gen_settable_params; + OSSL_FUNC_keymgmt_gen_fn *gen; + OSSL_FUNC_keymgmt_gen_cleanup_fn *gen_cleanup; + OSSL_FUNC_keymgmt_load_fn *load; + + /* Key object checking */ + OSSL_FUNC_keymgmt_query_operation_name_fn *query_operation_name; + OSSL_FUNC_keymgmt_has_fn *has; + OSSL_FUNC_keymgmt_validate_fn *validate; + OSSL_FUNC_keymgmt_match_fn *match; + + /* Import and export routines */ + OSSL_FUNC_keymgmt_import_fn *import; + OSSL_FUNC_keymgmt_import_types_fn *import_types; + OSSL_FUNC_keymgmt_export_fn *export; + OSSL_FUNC_keymgmt_export_types_fn *export_types; + OSSL_FUNC_keymgmt_dup_fn *dup; +} UADK_RSA_KEYMGMT; + +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 void uadk_rsa_clear_flags(RSA *r, int flags) +{ + r->flags &= ~flags; +} + +static 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) } */ + return r->version; +} + +static void uadk_rsa_get0_factors(const RSA *r, const BIGNUM **p, + const BIGNUM **q) +{ + if (p != NULL) + *p = r->p; + if (q != NULL) + *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 0; + + 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 1; +} + +static void uadk_rsa_get0_crt_params(const RSA *r, const BIGNUM **dmp1, + const BIGNUM **dmq1, const BIGNUM **iqmp) +{ + if (dmp1 != NULL) + *dmp1 = r->dmp1; + if (dmq1 != NULL) + *dmq1 = r->dmq1; + if (iqmp != NULL) + *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 0; + + 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 1; +} + +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 0; + + 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 1; +} + +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 1; + + ctx->tbuf = OPENSSL_malloc(uadk_rsa_size(ctx->rsa)); + if (ctx->tbuf == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + + return 1; +} + +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 (flen > bits) + return SOFT; + + if (bits < RSA_MIN_MODULUS_BITS) + return UADK_E_FAIL; + + switch (bits) { + case RSA1024BITS: + case RSA2048BITS: + case RSA3072BITS: + case RSA4096BITS: + return UADK_E_SUCCESS; + case OPENSSLRSA7680BITS: + case OPENSSLRSA15360BITS: + case RSA_MIN_MODULUS_BITS: + return SOFT; + default: + return 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) +{ + static int retries; + 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 < 0x9 || bitst > 0xF) { + /* + * 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 -1; + + ret = BN_GENCB_call(cb, GENCB_NEXT, *n); + (*n)++; + if (!ret) + return -1; + + if (retries == PRIME_RETRY_COUNT) { + *num = -1; + *bitse = 0; + retries = 0; + return BN_CONTINUE; + } + retries++; + return BN_REDO; + } + + ret = BN_GENCB_call(cb, GENCB_RETRY, *num); + if (!ret) + return BN_ERR; + 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 j; + + for (j = 0; j < num; j++) { + prev_prime = NULL; + if (j == 0) + prev_prime = rsa_p; + else + prev_prime = rsa_q; + /* + * BN_cmp(a,b) returns -1 if a < b; + * returns 0 if a == b; + * returns 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 -1; + 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); + (*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(q, rsa_q); + BN_copy(p, rsa_p); +} + +static int check_rsa_is_crt(RSA *rsa) +{ + const BIGNUM *p = NULL; + const BIGNUM *q = NULL; + const BIGNUM *dmp1 = NULL; + const BIGNUM *dmq1 = NULL; + const BIGNUM *iqmp = NULL; + int version; + + if (uadk_rsa_test_flags(rsa, RSA_FLAG_EXT_PKEY)) + return IS_SET; + + version = uadk_rsa_get_version(rsa); + if (version == RSA_ASN1_VERSION_MULTI) + return IS_SET; + + uadk_rsa_get0_factors(rsa, &p, &q); + uadk_rsa_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); + if ((p != NULL) && (q != NULL) && (dmp1 != NULL) && + (dmq1 != NULL) && (iqmp != NULL)) + return IS_SET; + + 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 end; + + param->r2 = BN_CTX_get(ctx); + if (!param->r2) + goto end; + + param->rsa_p = BN_CTX_get(ctx); + if (!param->rsa_p) + goto end; + + param->rsa_q = BN_CTX_get(ctx); + if (!param->rsa_q) + goto end; + + return UADK_E_SUCCESS; + +end: + fprintf(stderr, "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) +{ + struct rsa_prime_param *param = NULL; + int bitsr[RSA_MAX_PRIME_NUM] = {0}; + int flag, quo, rmd, i; + BN_CTX *ctx; + int bitse = 0; + int ret = 0; + /* n: modulo n, a part of public key */ + int n = 0; + + ctx = BN_CTX_new(); + if (!ctx) + return ret; + + BN_CTX_start(ctx); + param = OPENSSL_zalloc(sizeof(struct rsa_prime_param)); + if (!param) + goto free_ctx; + + ret = get_rsa_prime_param(param, ctx); + if (ret != UADK_E_SUCCESS) + goto free_param; + + /* Divide bits into 'primes' pieces evenly */ + quo = bits / RSA_MAX_PRIME_NUM; + rmd = bits % RSA_MAX_PRIME_NUM; + for (i = 0; i < RSA_MAX_PRIME_NUM; i++) + bitsr[i] = (i < rmd) ? quo + 1 : quo; + + /* 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, + ctx, cb); + if (ret == -1) + goto free_param; + bitse += bitsr[i]; + ret = check_rsa_prime_sufficient(&i, bitsr, &bitse, &n, + param, ctx, 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(ctx); + BN_CTX_free(ctx); + 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) { + fprintf(stderr, "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) + fprintf(stderr, "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) + fprintf(stderr, "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 len, + int padding) +{ + int ret; + + switch (padding) { + case RSA_PKCS1_PADDING: + ret = RSA_padding_check_PKCS1_type_2(to, num, buf, len, num); + if (!ret) + fprintf(stderr, "RSA_PKCS1_PADDING err\n"); + break; + case RSA_PKCS1_OAEP_PADDING: + ret = RSA_padding_check_PKCS1_OAEP(to, num, buf, len, num, + NULL, 0); + if (!ret) + fprintf(stderr, "RSA_PKCS1_OAEP_PADDING err\n"); + break; + default: + ret = UADK_E_FAIL; + } + + if (ret == CHECK_PADDING_FAIL) + ret = UADK_E_FAIL; + + return ret; +} + +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) + fprintf(stderr, "RSA_PKCS1_PADDING err\n"); + break; + case RSA_X931_PADDING: + ret = RSA_padding_add_X931(to_buf, tlen, from, flen); + if (!ret) + fprintf(stderr, "RSA_X931_PADDING err\n"); + break; + default: + ret = UADK_E_FAIL; + } + if (ret <= 0) + ret = UADK_E_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) + fprintf(stderr, "RSA_PKCS1_PADDING err\n"); + break; + case RSA_X931_PADDING: + ret = RSA_padding_check_X931(to, num, buf, len, num); + if (!ret) + fprintf(stderr, "RSA_X931_PADDING err\n"); + break; + default: + ret = UADK_E_FAIL; + } + + if (ret == CHECK_PADDING_FAIL) + ret = UADK_E_FAIL; + + return ret; +} + +static int check_rsa_input_para(const int flen, const unsigned char *from, + unsigned char *to, RSA *rsa) +{ + if (!rsa || !from || !to || flen <= 0) { + fprintf(stderr, "input param invalid\n"); + return UADK_E_FAIL; + } + + return rsa_check_bit_useful(uadk_rsa_bits(rsa), flen); +} + +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_E_FAIL; + if (BN_cmp(ret_bn, to_bn) > 0) + *res = to_bn; + else + *res = ret_bn; + } else { + *res = ret_bn; + } + + return UADK_E_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_E_FAIL; + } + + return UADK_E_SUCCESS; +} + +static int uadk_rsa_env_poll(void *ctx) +{ + __u64 rx_cnt = 0; + __u32 recv = 0; + /* Poll one packet currently */ + int expt = 1; + int ret; + + do { + ret = wd_rsa_poll(expt, &recv); + if (ret < 0 || recv == expt) + return ret; + rx_cnt++; + } while (rx_cnt < ENGINE_RECV_MAX_CNT); + + fprintf(stderr, "failed to poll msg: timeout!\n"); + + return -ETIMEDOUT; +} + +static int uadk_prov_rsa_init(void) +{ + int ret; + + pthread_mutex_lock(&rsa_mutex); + if (g_rsa_prov.pid != getpid()) { + ret = wd_rsa_init2("rsa", 0, 0); + if (unlikely(ret)) + return ret; + g_rsa_prov.pid = getpid(); + async_register_poll_fn(ASYNC_TASK_RSA, uadk_rsa_env_poll); + } + pthread_mutex_unlock(&rsa_mutex); + + return UADK_E_INIT_SUCCESS; +} + +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; + + memset(rsa_sess, 0, sizeof(struct uadk_rsa_sess)); + rsa_sess->alg = rsa; + rsa_sess->is_prikey_ready = UN_SET; + rsa_sess->is_pubkey_ready = UN_SET; + + return rsa_sess; +} + +static void rsa_free_eng_session(struct uadk_rsa_sess *rsa_sess) +{ + if (!rsa_sess) + return; + + rsa_sess->alg = NULL; + rsa_sess->is_prikey_ready = UN_SET; + rsa_sess->is_pubkey_ready = UN_SET; + + wd_rsa_free_sess(rsa_sess->sess); + OPENSSL_free(rsa_sess); +} + +static struct uadk_rsa_sess *rsa_get_eng_session(RSA *rsa, unsigned int bits, + int is_crt) +{ + unsigned int key_size = bits >> BIT_BYTES_SHIFT; + struct sched_params params = {0}; + struct uadk_rsa_sess *rsa_sess; + + rsa_sess = rsa_new_eng_session(rsa); + if (!rsa_sess) + return NULL; + + rsa_sess->key_size = key_size; + rsa_sess->setup.key_bits = key_size << BIT_BYTES_SHIFT; + + /* Use the default numa parameters */ + params.numa_id = -1; + rsa_sess->setup.sched_param = ¶ms; + rsa_sess->setup.is_crt = is_crt; + + rsa_sess->sess = wd_rsa_alloc_sess(&rsa_sess->setup); + if (!rsa_sess->sess) { + rsa_free_eng_session(rsa_sess); + return NULL; + } + + 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_e = NULL; + struct wd_dtb *wd_n = 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_e || !wd_n) + return UADK_E_FAIL; + + wd_e->dsize = BN_bn2bin(pubkey_param->e, + (unsigned char *)wd_e->data); + wd_n->dsize = BN_bn2bin(pubkey_param->n, + (unsigned char *)wd_n->data); + rsa_sess->is_pubkey_ready = IS_SET; + 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->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_dq = NULL; + struct wd_dtb *wd_dp = NULL; + struct wd_dtb *wd_q = NULL; + struct wd_dtb *wd_p = NULL; + struct wd_dtb *wd_d = NULL; + struct wd_dtb *wd_n = 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_dq->dsize = BN_bn2bin(pri->dmq1, + (unsigned char *)wd_dq->data); + wd_dp->dsize = BN_bn2bin(pri->dmp1, + (unsigned char *)wd_dp->data); + wd_q->dsize = BN_bn2bin(pri->q, + (unsigned char *)wd_q->data); + wd_p->dsize = BN_bn2bin(pri->p, + (unsigned char *)wd_p->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_d->dsize = BN_bn2bin(pri->d, + (unsigned char *)wd_d->data); + wd_n->dsize = BN_bn2bin(pri->n, + (unsigned char *)wd_n->data); + } else { + return UADK_E_FAIL; + } + rsa_sess->is_prikey_ready = IS_SET; + rsa_sess->req.src_bytes = rsa_sess->key_size; + rsa_sess->req.op_type = WD_RSA_SIGN; + 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, BN_CTX **bn_ctx_in) +{ + 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, *n, *d; + unsigned int key_bits, key_size; + BN_CTX *bn_ctx = *bn_ctx_in; + + 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); + + dmp1 = BN_CTX_get(bn_ctx); + if (!dmp1) + return UADK_E_FAIL; + + dmq1 = BN_CTX_get(bn_ctx); + if (!dmq1) + return UADK_E_FAIL; + + iqmp = BN_CTX_get(bn_ctx); + if (!iqmp) + return UADK_E_FAIL; + + n = BN_CTX_get(bn_ctx); + if (!n) + return UADK_E_FAIL; + + d = BN_CTX_get(bn_ctx); + if (!d) + return UADK_E_FAIL; + + BN_bin2bn((unsigned char *)wd_d.data, key_size, d); + BN_bin2bn((unsigned char *)wd_n.data, key_size, n); + 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))) + return UADK_E_FAIL; + + return UADK_E_SUCCESS; +} + +static void uadk_e_rsa_cb(void *req_t) +{ + struct wd_rsa_req *req_new = (struct wd_rsa_req *)req_t; + struct uadk_e_cb_info *cb_param; + struct wd_rsa_req *req_origin; + struct async_op *op; + + if (!req_new) + return; + + cb_param = req_new->cb_param; + if (!cb_param) + return; + + req_origin = cb_param->priv; + if (!req_origin) + return; + + req_origin->status = req_new->status; + + op = cb_param->op; + if (op && op->job && !op->done) { + op->done = 1; + async_free_poll_task(op->idx, 1); + async_wake_job(op->job); + } +} + +static int rsa_do_crypto(struct uadk_rsa_sess *rsa_sess) +{ + struct uadk_e_cb_info cb_param; + struct async_op op; + int idx, ret; + + ret = async_setup_async_event_notification(&op); + if (!ret) { + fprintf(stderr, "failed to setup async event notification.\n"); + return UADK_E_FAIL; + } + + if (!op.job) { + ret = wd_do_rsa_sync(rsa_sess->sess, &(rsa_sess->req)); + if (ret) + goto err; + return UADK_E_SUCCESS; + } + cb_param.op = &op; + cb_param.priv = &(rsa_sess->req); + rsa_sess->req.cb = uadk_e_rsa_cb; + rsa_sess->req.cb_param = &cb_param; + rsa_sess->req.status = -1; + + ret = async_get_free_task(&idx); + if (ret == 0) + goto err; + + op.idx = idx; + do { + ret = wd_do_rsa_async(rsa_sess->sess, &(rsa_sess->req)); + if (ret < 0 && ret != -EBUSY) { + async_free_poll_task(op.idx, 0); + goto err; + } + } while (ret == -EBUSY); + + ret = async_pause_job(rsa_sess, &op, ASYNC_TASK_RSA, idx); + if (!ret) + goto err; + + if (rsa_sess->req.status) + return UADK_E_FAIL; + + return UADK_E_SUCCESS; + +err: + (void)async_clear_async_event_notification(); + return UADK_E_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) +{ + 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_q || !keygen_param->wd_p) + return UADK_E_FAIL; + + keygen_param->wd_q->dsize = BN_bn2bin(bn_param->q, + (unsigned char *)keygen_param->wd_q->data); + keygen_param->wd_p->dsize = BN_bn2bin(bn_param->p, + (unsigned char *)keygen_param->wd_p->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; +} + +static void rsa_free_keygen_data(struct uadk_rsa_sess *rsa_sess) +{ + if (!rsa_sess) + return; + + wd_rsa_del_kg_in(rsa_sess->sess, rsa_sess->req.src); + wd_rsa_del_kg_out(rsa_sess->sess, rsa_sess->req.dst); +} + +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, BN_CTX **bn_ctx_in) +{ + BN_CTX *bn_ctx; + + *keygen_param = OPENSSL_malloc(sizeof(struct rsa_keygen_param)); + if (!(*keygen_param)) + goto err; + + *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; + + bn_ctx = BN_CTX_new(); + if (!bn_ctx) + goto free_key_pair; + + BN_CTX_start(bn_ctx); + *bn_ctx_in = bn_ctx; + + (*keygen_bn_param)->e = BN_CTX_get(bn_ctx); + if (!(*keygen_bn_param)->e) + goto free_bn_ctx; + + (*keygen_bn_param)->p = BN_CTX_get(bn_ctx); + if (!(*keygen_bn_param)->p) + goto free_bn_ctx; + + (*keygen_bn_param)->q = BN_CTX_get(bn_ctx); + if (!(*keygen_bn_param)->q) + goto free_bn_ctx; + + return UADK_E_SUCCESS; + +free_bn_ctx: + BN_CTX_end(bn_ctx); + BN_CTX_free(bn_ctx); +free_key_pair: + OPENSSL_free(*key_pair); +free_keygen_bn_param: + OPENSSL_free(*keygen_bn_param); +free_keygen_param: + OPENSSL_free(*keygen_param); +err: + return -ENOMEM; +} + +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, BN_CTX **bn_ctx, + 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 ctx we alloced before. But in normal situation, + * the BN ctx 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_CTX_end(*bn_ctx); + BN_CTX_free(*bn_ctx); + } + + OPENSSL_free(*keygen_bn_param); + OPENSSL_free(*keygen_param); + OPENSSL_free(*key_pair); +} + +static int rsa_pkey_param_alloc(struct rsa_pubkey_param **pub, + struct rsa_prikey_param **pri) +{ + if (pub) { + *pub = OPENSSL_malloc(sizeof(struct rsa_pubkey_param)); + if (!(*pub)) + return -ENOMEM; + } + + if (pri) { + *pri = OPENSSL_malloc(sizeof(struct rsa_prikey_param)); + if (!(*pri)) { + if (pub) + OPENSSL_free(*pub); + return -ENOMEM; + } + } + + return UADK_E_SUCCESS; +} + +static void rsa_pkey_param_free(struct rsa_pubkey_param **pub, + struct rsa_prikey_param **pri) +{ + if (pub) + OPENSSL_free(*pub); + if (pri) + OPENSSL_free(*pri); +} + +static 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->n) || !(pub->e)) + return UADK_E_FAIL; + + *num_bytes = BN_num_bytes(pub->n); + if (!(*num_bytes)) + return UADK_E_FAIL; + + *from_buf = OPENSSL_malloc(*num_bytes); + if (!(*from_buf)) + return -ENOMEM; + + return UADK_E_SUCCESS; +} + +static void rsa_free_pub_bn_ctx(unsigned char **from_buf) +{ + OPENSSL_free(*from_buf); +} + +static 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; + + uadk_rsa_get0_factors(rsa, &pri->p, &pri->q); + if (!(pri->p) || !(pri->q)) + return UADK_E_FAIL; + + uadk_rsa_get0_crt_params(rsa, &pri->dmp1, &pri->dmq1, &pri->iqmp); + if (!(pri->dmp1) || !(pri->dmq1) || !(pri->iqmp)) + return UADK_E_FAIL; + + *num_bytes = BN_num_bytes(pri->n); + if (!(*num_bytes)) + return UADK_E_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 uadk_rsa_sess *rsa_sess = NULL; + struct rsa_keypair *key_pair = NULL; + BN_CTX *bn_ctx = NULL; + int is_crt = 1; + int ret; + + ret = rsa_check_bit_useful(bits, 0); + if (!ret || ret == SOFT) + return UADK_DO_SOFT; + + ret = rsa_keygen_param_alloc(&keygen_param, &bn_param, &key_pair, &bn_ctx); + if (ret == -ENOMEM) + return UADK_DO_SOFT; + + 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_DO_SOFT; + goto free_sess; + } + + if (!BN_copy(bn_param->e, e)) { + ret = UADK_DO_SOFT; + goto free_sess; + } + + ret = rsa_fill_keygen_data(rsa_sess, key_pair, keygen_param, bn_param); + if (!ret) { + ret = UADK_DO_SOFT; + 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, &bn_ctx); + if (!ret) + ret = UADK_DO_SOFT; + +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, &bn_ctx, ret); + 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 = NULL; + unsigned char *from_buf = NULL; + int num_bytes, is_crt, ret; + BIGNUM *enc_bn = NULL; + + ret = check_rsa_input_para(flen, from, to, rsa); + if (!ret || ret == SOFT) + return UADK_DO_SOFT; + + ret = rsa_pkey_param_alloc(&pub_enc, NULL); + if (ret == -ENOMEM) + return UADK_DO_SOFT; + + 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 || flen > num_bytes) { + ret = UADK_DO_SOFT; + goto free_sess; + } + + ret = add_rsa_pubenc_padding(flen, from, from_buf, num_bytes, padding); + if (!ret) { + ret = UADK_DO_SOFT; + goto free_buf; + } + + ret = rsa_fill_pubkey(pub_enc, rsa_sess, from_buf, to); + if (!ret) { + ret = UADK_DO_SOFT; + goto free_buf; + } + + ret = rsa_do_crypto(rsa_sess); + if (!ret || rsa_sess->req.status) { + ret = UADK_DO_SOFT; + goto free_buf; + } + + enc_bn = BN_bin2bn((const unsigned char *)rsa_sess->req.dst, + rsa_sess->req.dst_bytes, NULL); + if (!enc_bn) { + ret = UADK_DO_SOFT; + goto free_buf; + } + + ret = BN_bn2binpad(enc_bn, to, num_bytes); + if (ret == -1) + ret = UADK_DO_SOFT; + + BN_free(enc_bn); + +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, len, ret; + BIGNUM *dec_bn = NULL; + + ret = check_rsa_input_para(flen, from, to, rsa); + if (!ret || ret == SOFT) + return UADK_DO_SOFT; + + ret = rsa_pkey_param_alloc(NULL, &pri); + if (ret == -ENOMEM) + return UADK_DO_SOFT; + + 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 || flen > num_bytes) { + ret = UADK_DO_SOFT; + goto free_sess; + } + + ret = rsa_fill_prikey(rsa, rsa_sess, pri, from_buf, to); + if (!ret) { + ret = UADK_DO_SOFT; + 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; + } + + dec_bn = BN_bin2bn((const unsigned char *)rsa_sess->req.dst, + rsa_sess->req.dst_bytes, NULL); + if (!dec_bn) { + ret = UADK_DO_SOFT; + goto free_buf; + } + + len = BN_bn2binpad(dec_bn, from_buf, num_bytes); + if (!len) { + ret = UADK_DO_SOFT; + goto free_dec_bn; + } + + ret = check_rsa_pridec_padding(to, num_bytes, from_buf, len, padding); + if (!ret) + ret = UADK_DO_SOFT; + +free_dec_bn: + BN_free(dec_bn); +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_prov_rsa_private_sign(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + struct uadk_rsa_sess *rsa_sess = NULL; + struct rsa_prikey_param *pri = NULL; + unsigned char *from_buf = NULL; + BIGNUM *sign_bn = NULL; + BIGNUM *to_bn = NULL; + BIGNUM *res = NULL; + int num_bytes, ret; + + ret = check_rsa_input_para(flen, from, to, rsa); + if (!ret || ret == SOFT) + return UADK_DO_SOFT; + + ret = rsa_pkey_param_alloc(NULL, &pri); + if (ret == -ENOMEM) + return UADK_DO_SOFT; + + 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 || flen > num_bytes) { + ret = UADK_DO_SOFT; + goto free_sess; + } + + ret = add_rsa_prienc_padding(flen, from, from_buf, num_bytes, padding); + if (!ret) { + ret = UADK_DO_SOFT; + goto free_buf; + } + + ret = rsa_fill_prikey(rsa, rsa_sess, pri, from_buf, to); + if (!ret) { + ret = UADK_DO_SOFT; + goto free_buf; + } + + ret = rsa_do_crypto(rsa_sess); + if (!ret || rsa_sess->req.status) { + ret = UADK_DO_SOFT; + goto free_buf; + } + + sign_bn = BN_bin2bn((const unsigned char *)rsa_sess->req.dst, + rsa_sess->req.dst_bytes, NULL); + if (!sign_bn) { + ret = UADK_DO_SOFT; + goto free_buf; + } + + to_bn = BN_bin2bn(from_buf, num_bytes, NULL); + if (!to_bn) { + ret = UADK_DO_SOFT; + goto free_sign_bn; + } + + ret = rsa_get_sign_res(padding, to_bn, pri->n, sign_bn, &res); + if (!ret) { + ret = UADK_DO_SOFT; + 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); +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_prov_rsa_public_verify(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + struct uadk_rsa_sess *rsa_sess = NULL; + struct rsa_pubkey_param *pub = NULL; + int num_bytes, is_crt, len, ret; + unsigned char *from_buf = NULL; + BIGNUM *verify_bn = NULL; + + ret = check_rsa_input_para(flen, from, to, rsa); + if (!ret) + return UADK_E_FAIL; + else if (ret == SOFT) + return UADK_DO_SOFT; + + ret = rsa_pkey_param_alloc(&pub, NULL); + if (ret == -ENOMEM) + return UADK_DO_SOFT; + + 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_DO_SOFT; + goto free_sess; + } + + ret = rsa_fill_pubkey(pub, rsa_sess, from_buf, to); + if (!ret) { + ret = UADK_DO_SOFT; + 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; + } + + verify_bn = BN_bin2bn((const unsigned char *)rsa_sess->req.dst, + rsa_sess->req.dst_bytes, NULL); + if (!verify_bn) { + ret = UADK_DO_SOFT; + goto free_buf; + } + + ret = rsa_get_verify_res(padding, pub->n, verify_bn); + if (!ret) { + ret = UADK_DO_SOFT; + goto free_verify_bn; + } + + len = BN_bn2binpad(verify_bn, from_buf, num_bytes); + if (!len) { + ret = UADK_DO_SOFT; + goto free_verify_bn; + } + + ret = check_rsa_pubdec_padding(to, num_bytes, from_buf, len, padding); + if (!ret) + ret = UADK_DO_SOFT; + +free_verify_bn: + BN_free(verify_bn); +free_buf: + 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 EVP_SIGNATURE get_default_rsa_signature(void) +{ + static EVP_SIGNATURE s_signature; + static int initilazed; + + if (!initilazed) { + EVP_SIGNATURE *signature = + (EVP_SIGNATURE *)EVP_SIGNATURE_fetch(NULL, "RSA", "provider=default"); + if (signature) { + s_signature = *signature; + EVP_SIGNATURE_free((EVP_SIGNATURE *)signature); + initilazed = 1; + } else { + fprintf(stderr, "EVP_SIGNATURE_fetch from default provider failed"); + } + } + return s_signature; +} + +static EVP_ASYM_CIPHER get_default_asym_cipher(void) +{ + static EVP_ASYM_CIPHER s_asym_cipher; + static int initilazed; + + if (!initilazed) { + EVP_ASYM_CIPHER *asym_cipher = + (EVP_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 { + fprintf(stderr, "EVP_ASYM_CIPHER_fetch from default provider failed"); + } + } + return s_asym_cipher; +} + +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: + ERR_raise(ERR_LIB_RSA, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + + if (uadk_prov_rsa_init()) + priv->soft = 1; + + return 1; +} + +static int uadk_rsa_init(void *vprsactx, void *vrsa, + const OSSL_PARAM params[], int operation) +{ + PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; + + if (priv == NULL || vrsa == NULL) + return 0; + + priv->rsa = vrsa; + priv->operation = operation; + + /* Maximum for sign, auto for verify */ + priv->saltlen = RSA_PSS_SALTLEN_AUTO; + priv->min_saltlen = -1; + + 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: + ERR_raise(ERR_LIB_RSA, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + + if (uadk_prov_rsa_init()) + priv->soft = 1; + + return 1; +} + +static int uadk_rsa_verify_recover_init(void *vprsactx, void *vrsa, + const OSSL_PARAM params[]) +{ + return 1; +} + +static int uadk_rsa_verify_recover(void *vprsactx, unsigned char *rout, + size_t *routlen, size_t routsize, + const unsigned char *sig, size_t siglen) +{ + return 1; +} + +static int uadk_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_verify(void *vprsactx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen) +{ + typedef int (*fun_ptr)(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) + goto soft; + + /* todo call public_verify */ + if (priv->md != NULL) { + /* todo */ + } else { + if (!setup_tbuf(priv)) + return 0; + rslen = uadk_prov_rsa_public_verify(siglen, sig, priv->tbuf, + priv->rsa, priv->pad_mode); + if (rslen == UADK_DO_SOFT) + goto soft; + } + + if ((rslen != tbslen) || memcmp(tbs, priv->tbuf, rslen)) + return 0; + + return 1; + +soft: + fprintf(stderr, "switch to execute openssl software calculation.\n"); + fun_ptr fun = get_default_rsa_signature().verify; + + if (!fun) + return 0; + + return fun(vprsactx, sig, siglen, tbs, tbslen); +} + +static int uadk_rsa_sign(void *vprsactx, unsigned char *sig, + size_t *siglen, size_t sigsize, + const unsigned char *tbs, size_t tbslen) +{ + typedef int (*fun_ptr)(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) + goto soft; + + if (sig == NULL) { + *siglen = rsasize; + return 1; + } + + if (sigsize < rsasize) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE, + "is %zu, should be at least %zu", sigsize, rsasize); + return 0; + } + + ret = uadk_prov_rsa_private_sign(tbslen, tbs, sig, priv->rsa, priv->pad_mode); + if (ret == UADK_DO_SOFT) + goto soft; + + if (ret < 0) + return ret; + + *siglen = ret; + + return 1; +soft: + fprintf(stderr, "switch to execute openssl software calculation.\n"); + fun_ptr fun = get_default_rsa_signature().sign; + + if (!fun) + return 0; + return fun(vprsactx, sig, siglen, sigsize, tbs, tbslen); +} + +static int uadk_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_rsa_signature_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); + fprintf(stderr, "%s failed.\n", __func__); + return NULL; +} + +static void uadk_rsa_signature_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_rsa_asym_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_rsa_asym_freectx(void *vprsactx) +{ + PROV_RSA_ASYM_CTX *priv = (PROV_RSA_ASYM_CTX *)vprsactx; + + if (priv == NULL) + return; + + OPENSSL_free(priv); +} + +static int uadk_rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) +{ + PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; + + if (priv == NULL) + return 0; + if (params == NULL) + return 1; + + /* todo */ + + return 1; +} + +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_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_digest_sign_init(void *vprsactx, const char *mdname, + void *vrsa, const OSSL_PARAM params[]) +{ + typedef int (*fun_ptr)(void *vprsactx, const char *mdname, + void *vrsa, const OSSL_PARAM params[]); + + fun_ptr fun = get_default_rsa_signature().digest_sign_init; + + if (!fun) + return 0; + + return fun(vprsactx, mdname, vrsa, params); +} + +static int uadk_rsa_digest_signverify_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_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]; + unsigned int dlen = 0; + + if (priv == NULL) + return 0; + priv->flag_allow_md = 1; + + if (priv->mdctx == NULL) + return 0; + /* + * 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 0; + } + + return uadk_rsa_sign(vprsactx, sig, siglen, sigsize, + digest, (size_t)dlen); +} + +static int uadk_rsa_digest_verify_init(void *vprsactx, const char *mdname, + void *vrsa, const OSSL_PARAM params[]) +{ + typedef int (*fun_ptr)(void *vprsactx, const char *mdname, + void *vrsa, const OSSL_PARAM params[]); + fun_ptr fun = get_default_rsa_signature().digest_verify_init; + + if (!fun) + return 0; + + return fun(vprsactx, mdname, vrsa, params); +} + + +static int uadk_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 digest[EVP_MAX_MD_SIZE]; + unsigned int dlen = 0; + + if (priv == NULL) + return 0; + priv->flag_allow_md = 1; + if (priv->mdctx == NULL) + return 0; + + /* + * 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 0; + + return uadk_rsa_verify(vprsactx, sig, siglen, + digest, (size_t)dlen); +} + + +static void *uadk_rsa_dupctx(void *vprsactx) +{ + typedef void* (*fun_ptr)(void *vprsactx); + fun_ptr fun = get_default_rsa_signature().dupctx; + + if (!fun) + return NULL; + + return fun(vprsactx); +} + +static int uadk_rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) +{ + typedef int (*fun_ptr)(void *vprsactx, OSSL_PARAM *params); + fun_ptr fun = get_default_rsa_signature().get_ctx_params; + + if (!fun) + return 0; + return fun(vprsactx, params); +} + +static const OSSL_PARAM *uadk_rsa_gettable_ctx_md_params(void *vprsactx) +{ + typedef const OSSL_PARAM * (*fun_ptr)(void *vprsactx); + fun_ptr fun = get_default_rsa_signature().gettable_ctx_md_params; + + if (!fun) + return NULL; + return fun(vprsactx); +} + + +static int uadk_rsa_set_ctx_md_params(void *vprsactx, const OSSL_PARAM params[]) +{ + typedef int (*fun_ptr)(void *vprsactx, const OSSL_PARAM params[]); + fun_ptr fun = get_default_rsa_signature().set_ctx_md_params; + + if (!fun) + return 0; + return fun(vprsactx, params); +} + +static const OSSL_PARAM *uadk_rsa_settable_ctx_md_params(void *vprsactx) +{ + typedef const OSSL_PARAM * (*fun_ptr)(void *vprsactx); + fun_ptr fun = get_default_rsa_signature().settable_ctx_md_params; + + if (!fun) + return NULL; + return fun(vprsactx); +} + +static const OSSL_PARAM *uadk_rsa_gettable_ctx_params(ossl_unused void *vprsactx, + ossl_unused void *provctx) +{ + typedef const OSSL_PARAM * (*fun_ptr)(ossl_unused void *vprsactx, + ossl_unused void *provctx); + fun_ptr fun = get_default_rsa_signature().gettable_ctx_params; + + if (!fun) + return NULL; + + return fun(vprsactx, provctx); +} + +static int uadk_rsa_get_ctx_md_params(void *vprsactx, OSSL_PARAM *params) +{ + typedef int (*fun_ptr)(void *vprsactx, OSSL_PARAM *params); + fun_ptr fun = get_default_rsa_signature().get_ctx_md_params; + + if (!fun) + return 0; + + return fun(vprsactx, params); +} + +static int uadk_rsa_asym_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_rsa_asym_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_asym_encrypt(void *vprsactx, unsigned char *out, + size_t *outlen, size_t outsize, + const unsigned char *in, size_t inlen) +{ + typedef int (*fun_ptr)(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; + int ret; + + if (priv->soft) + goto soft; + + if (out == NULL) { + size_t len = uadk_rsa_size(priv->rsa); + + if (len == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); + return 0; + } + *outlen = len; + return 1; + } + + ret = uadk_prov_rsa_public_encrypt(inlen, in, out, priv->rsa, priv->pad_mode); + if (ret == UADK_DO_SOFT) + goto soft; + if (ret < 0) + return ret; + + *outlen = ret; + + return 1; +soft: + fprintf(stderr, "switch to execute openssl software calculation.\n"); + fun_ptr fun = get_default_asym_cipher().encrypt; + + if (!fun) + return 0; + + return fun(vprsactx, out, outlen, outsize, in, inlen); +} + +static int uadk_rsa_asym_decrypt(void *vprsactx, unsigned char *out, + size_t *outlen, size_t outsize, + const unsigned char *in, size_t inlen) +{ + typedef int (*fun_ptr)(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) + goto soft; + + if (out == NULL) { + if (len == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); + return 0; + } + *outlen = len; + return 1; + } + + if (outsize < len) { + ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH); + return 0; + } + + ret = uadk_prov_rsa_private_decrypt(inlen, in, out, priv->rsa, priv->pad_mode); + if (ret == UADK_DO_SOFT) + goto soft; + if (ret < 0) + return ret; + + *outlen = ret; + + return 1; +soft: + fprintf(stderr, "switch to execute openssl software calculation.\n"); + fun_ptr fun = get_default_asym_cipher().decrypt; + + if (!fun) + return 0; + + return fun(vprsactx, out, outlen, outsize, in, inlen); +} + +static int uadk_rsa_asym_get_ctx_params(void *vprsactx, OSSL_PARAM *params) +{ + typedef int (*fun_ptr)(void *vprsactx, OSSL_PARAM *params); + fun_ptr fun = get_default_asym_cipher().get_ctx_params; + + if (!fun) + return 0; + return fun(vprsactx, params); +} + +static const OSSL_PARAM *uadk_rsa_asym_gettable_ctx_params(void *vprsactx, + void *provctx) +{ + typedef const OSSL_PARAM * (*fun_ptr)(void *vprsactx, void *provctx); + fun_ptr fun = get_default_asym_cipher().gettable_ctx_params; + + if (!fun) + return 0; + return fun(vprsactx, provctx); +} + +static int uadk_rsa_asym_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) +{ + typedef int (*fun_ptr)(void *vprsactx, const OSSL_PARAM *params); + fun_ptr fun = get_default_asym_cipher().set_ctx_params; + + if (!fun) + return 0; + return fun(vprsactx, params); +} + +static const OSSL_PARAM *uadk_rsa_asym_settable_ctx_params(void *vprsactx, + void *provctx) +{ + typedef const OSSL_PARAM * (*fun_ptr)(void *vprsactx, void *provctx); + fun_ptr fun = get_default_asym_cipher().settable_ctx_params; + + if (!fun) + return 0; + return fun(vprsactx, provctx); +} + +static UADK_RSA_KEYMGMT get_default_keymgmt(void) +{ + static UADK_RSA_KEYMGMT s_keymgmt; + static int initialized; + + if (!initialized) { + UADK_RSA_KEYMGMT *keymgmt = + (UADK_RSA_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "RSA", "provider=default"); + if (keymgmt) { + s_keymgmt = *keymgmt; + EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); + initialized = 1; + } else { + fprintf(stderr, "EVP_KEYMGMT_fetch from default provider failed"); + } + } + return s_keymgmt; +} + +static void *uadk_keymgmt_rsa_newdata(void *provctx) +{ + typedef void* (*fun_ptr)(void *); + fun_ptr fun = get_default_keymgmt().new; + + if (!fun) + return NULL; + return fun(provctx); +} + +static void uadk_keymgmt_rsa_freedata(void *keydata) +{ + typedef void (*fun_ptr)(void *); + fun_ptr fun = get_default_keymgmt().free; + + if (!fun) + return; + fun(keydata); +} + +static int uadk_keymgmt_rsa_has(const void *keydata, int selection) +{ + typedef int (*fun_ptr)(const void *, int); + fun_ptr fun = get_default_keymgmt().has; + + if (!fun) + return 0; + + return fun(keydata, selection); +} + +static int uadk_keymgmt_rsa_import(void *keydata, int selection, const OSSL_PARAM params[]) +{ + typedef int (*fun_ptr)(void *, int, const OSSL_PARAM*); + fun_ptr fun = get_default_keymgmt().import; + + if (!fun) + return 0; + return fun(keydata, selection, params); +} + +static const OSSL_PARAM *uadk_keymgmt_rsa_import_types(int selection) +{ + typedef const OSSL_PARAM* (*fun_ptr)(int); + fun_ptr fun = get_default_keymgmt().import_types; + + if (!fun) + return NULL; + return fun(selection); +} + +static void *uadk_keymgmt_rsa_gen_init(void *provctx, int selection, + const OSSL_PARAM params[]) +{ + typedef void * (*fun_ptr)(void *, int, const OSSL_PARAM *); + fun_ptr fun = get_default_keymgmt().gen_init; + + if (!fun) + return NULL; + return fun(provctx, selection, params); +} + +static int uadk_keymgmt_rsa_gen_set_params(void *genctx, const OSSL_PARAM params[]) +{ + typedef int (*fun_ptr)(void *, const OSSL_PARAM *); + fun_ptr fun = get_default_keymgmt().gen_set_params; + + if (!fun) + return 0; + return fun(genctx, params); +} + +static const OSSL_PARAM *uadk_keymgmt_rsa_gen_settable_params(ossl_unused void *genctx, + ossl_unused void *provctx) +{ + typedef const OSSL_PARAM * (*fun_ptr)(void *, void *); + fun_ptr fun = get_default_keymgmt().gen_settable_params; + + if (!fun) + return NULL; + return fun(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) { + ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->references = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + + ret->libctx = libctx; + + return ret; +} + +static void *uadk_keymgmt_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) +{ + typedef void * (*fun_ptr)(void *, OSSL_CALLBACK *, void *); + struct rsa_gen_ctx *gctx = genctx; + RSA *rsa = NULL; + BN_GENCB *gencb = NULL; + int ret; + + if (gctx == NULL) + return NULL; + + ret = uadk_prov_rsa_init(); + if (ret) + 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) { + BN_GENCB_free(gencb); + uadk_keymgmt_rsa_freedata(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: + fprintf(stderr, "switch to execute openssl software calculation.\n"); + fun_ptr fun = get_default_keymgmt().gen; + + if (!fun) + return NULL; + return fun(genctx, osslcb, cbarg); +} + +static void uadk_keymgmt_rsa_gen_cleanup(void *genctx) +{ + typedef void (*fun_ptr)(void *); + fun_ptr fun = get_default_keymgmt().gen_cleanup; + + if (!fun) + return; + fun(genctx); +} + +static void *uadk_keymgmt_rsa_load(const void *reference, size_t reference_sz) +{ + typedef void * (*fun_ptr)(const void *, size_t); + fun_ptr fun = get_default_keymgmt().load; + + if (!fun) + return NULL; + return fun(reference, reference_sz); +} + +static int uadk_keymgmt_rsa_get_params(void *key, OSSL_PARAM params[]) +{ + typedef int (*fun_ptr)(void *, OSSL_PARAM *); + fun_ptr fun = get_default_keymgmt().get_params; + + if (!fun) + return 0; + return fun(key, params); +} + +static const OSSL_PARAM *uadk_keymgmt_rsa_gettable_params(void *provctx) +{ + typedef const OSSL_PARAM * (*fun_ptr)(void *); + fun_ptr fun = get_default_keymgmt().gettable_params; + + if (!fun) + return NULL; + return fun(provctx); +} + +static int uadk_keymgmt_rsa_match(const void *keydata1, const void *keydata2, int selection) +{ + typedef int (*fun_ptr)(const void *, const void *, int); + fun_ptr fun = get_default_keymgmt().match; + + if (!fun) + return 0; + return fun(keydata1, keydata2, selection); +} + +static int uadk_keymgmt_rsa_validate(const void *keydata, int selection, int checktype) +{ + typedef int (*fun_ptr)(const void *, int, int); + fun_ptr fun = get_default_keymgmt().validate; + + if (!fun) + return 0; + return fun(keydata, selection, checktype); +} + +static int uadk_keymgmt_rsa_export(void *keydata, int selection, + OSSL_CALLBACK *param_callback, void *cbarg) +{ + typedef int (*fun_ptr)(void *, int, OSSL_CALLBACK *, void *); + fun_ptr fun = get_default_keymgmt().export; + + if (!fun) + return 0; + return fun(keydata, selection, param_callback, cbarg); +} + +static const OSSL_PARAM *uadk_keymgmt_rsa_export_types(int selection) +{ + typedef const OSSL_PARAM * (*fun_ptr)(int); + fun_ptr fun = get_default_keymgmt().export_types; + + if (!fun) + return NULL; + return fun(selection); +} + +static void *uadk_keymgmt_rsa_dup(const void *keydata_from, int selection) +{ + typedef void * (*fun_ptr)(const void *, int); + fun_ptr fun = get_default_keymgmt().dup; + + if (!fun) + return NULL; + return fun(keydata_from, selection); +} + +const OSSL_DISPATCH uadk_rsa_keymgmt_functions[] = { + { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))uadk_keymgmt_rsa_newdata }, + { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))uadk_keymgmt_rsa_freedata }, + { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))uadk_keymgmt_rsa_has }, + { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))uadk_keymgmt_rsa_import }, + { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, + (void (*)(void))uadk_keymgmt_rsa_import_types }, + { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))uadk_keymgmt_rsa_gen_init }, + { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, + (void (*)(void))uadk_keymgmt_rsa_gen_set_params }, + { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, + (void (*)(void))uadk_keymgmt_rsa_gen_settable_params }, + { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))uadk_keymgmt_rsa_gen }, + { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))uadk_keymgmt_rsa_gen_cleanup }, + { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))uadk_keymgmt_rsa_load }, + { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))uadk_keymgmt_rsa_get_params }, + { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, + (void (*) (void))uadk_keymgmt_rsa_gettable_params }, + { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))uadk_keymgmt_rsa_match }, + { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))uadk_keymgmt_rsa_validate }, + { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))uadk_keymgmt_rsa_export }, + { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))uadk_keymgmt_rsa_export_types }, + { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))uadk_keymgmt_rsa_dup }, + {0, NULL} +}; + +const OSSL_DISPATCH uadk_rsa_signature_functions[] = { + {OSSL_FUNC_SIGNATURE_NEWCTX, + (void (*)(void))uadk_rsa_signature_newctx}, + {OSSL_FUNC_SIGNATURE_SIGN_INIT, + (void (*)(void))uadk_rsa_sign_init}, + {OSSL_FUNC_SIGNATURE_SIGN, + (void (*)(void))uadk_rsa_sign}, + {OSSL_FUNC_SIGNATURE_VERIFY_INIT, + (void (*)(void))uadk_rsa_verify_init }, + {OSSL_FUNC_SIGNATURE_VERIFY, + (void (*)(void))uadk_rsa_verify }, + {OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, + (void (*)(void))uadk_rsa_verify_recover_init }, + {OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, + (void (*)(void))uadk_rsa_verify_recover }, + {OSSL_FUNC_SIGNATURE_FREECTX, + (void (*)(void))uadk_rsa_signature_freectx}, + {OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, + (void (*)(void))uadk_rsa_set_ctx_params}, + {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, + (void (*)(void))uadk_rsa_settable_ctx_params}, + {OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, + (void (*)(void))uadk_rsa_digest_sign_init }, + {OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, + (void (*)(void))uadk_rsa_digest_signverify_update }, + {OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, + (void (*)(void))uadk_rsa_digest_sign_final }, + {OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, + (void (*)(void))uadk_rsa_digest_verify_init }, + {OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, + (void (*)(void))uadk_rsa_digest_signverify_update }, + {OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, + (void (*)(void))uadk_rsa_digest_verify_final }, + {OSSL_FUNC_SIGNATURE_DUPCTX, + (void (*)(void))uadk_rsa_dupctx }, + {OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, + (void (*)(void))uadk_rsa_get_ctx_params }, + {OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, + (void (*)(void))uadk_rsa_gettable_ctx_params }, + {OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, + (void (*)(void))uadk_rsa_get_ctx_md_params }, + {OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, + (void (*)(void))uadk_rsa_gettable_ctx_md_params }, + {OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, + (void (*)(void))uadk_rsa_set_ctx_md_params }, + {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, + (void (*)(void))uadk_rsa_settable_ctx_md_params }, + {0, NULL} +}; + +const OSSL_DISPATCH uadk_rsa_asym_cipher_functions[] = { + { OSSL_FUNC_ASYM_CIPHER_NEWCTX, + (void (*)(void))uadk_rsa_asym_newctx }, + { OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT, + (void (*)(void))uadk_rsa_asym_encrypt_init }, + { OSSL_FUNC_ASYM_CIPHER_ENCRYPT, + (void (*)(void))uadk_rsa_asym_encrypt }, + { OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT, + (void (*)(void))uadk_rsa_asym_decrypt_init }, + { OSSL_FUNC_ASYM_CIPHER_DECRYPT, + (void (*)(void))uadk_rsa_asym_decrypt }, + { OSSL_FUNC_ASYM_CIPHER_FREECTX, + (void (*)(void))uadk_rsa_asym_freectx }, + { OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS, + (void (*)(void))uadk_rsa_asym_get_ctx_params }, + { OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS, + (void (*)(void))uadk_rsa_asym_gettable_ctx_params }, + { OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS, + (void (*)(void))uadk_rsa_asym_set_ctx_params }, + { OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS, + (void (*)(void))uadk_rsa_asym_settable_ctx_params }, + { 0, NULL } +}; + +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); +} diff --git a/test/sanity_test.sh b/test/sanity_test.sh index 1e9983b..6a37014 100755 --- a/test/sanity_test.sh +++ b/test/sanity_test.sh @@ -17,6 +17,7 @@ if ((major_version >= 3)); then engine_id="$TEST_SCRIPT_DIR/../src/.libs/uadk_provider.so" digest_algs=$(openssl list -provider $engine_id -digest-algorithms) cipher_algs=$(openssl list -provider $engine_id -cipher-algorithms) + signature_algs=$(openssl list -provider $engine_id -signature-algorithms) fi if [[ $digest_algs =~ "uadk_provider" ]]; then @@ -67,6 +68,26 @@ if [[ $cipher_algs =~ "uadk_provider" ]]; then openssl speed -provider $engine_id -async_jobs 1 -evp des-ede3-ecb fi +if [[ $signature_algs =~ "uadk_provider" ]]; then + echo "uadk_provider testing rsa" + openssl speed -provider $engine_id rsa1024 + openssl speed -provider $engine_id rsa2048 + openssl speed -provider $engine_id rsa4096 + openssl speed -provider $engine_id -async_jobs 1 rsa1024 + openssl speed -provider $engine_id -async_jobs 1 rsa2048 + openssl speed -provider $engine_id -async_jobs 1 rsa4096 + + openssl genrsa -out prikey.pem -provider $engine_id 1024 + openssl rsa -in prikey.pem -pubout -out pubkey.pem -provider $engine_id -provider default + echo "Content to be encrypted" > plain.txt + + openssl pkeyutl -encrypt -in plain.txt -inkey pubkey.pem -pubin -out enc.txt \ + -pkeyopt rsa_padding_mode:pkcs1 -provider uadk_provider -provider default + + openssl pkeyutl -decrypt -in enc.txt -inkey prikey.pem -out dec.txt \ + -pkeyopt rsa_padding_mode:pkcs1 -provider $engine_id -provider default +fi + if [[ $version =~ "1.1.1" ]]; then echo "openssl 1.1.1" engine_id="$TEST_SCRIPT_DIR/../src/.libs/uadk_engine.so" -- 2.25.1