From 590607ec21cb2ec6e386fddcd34db64c32c52d26 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 01/16] uadk_provider: set the default provider when initializing the uadk provider Set the default provider when initializing the uadk provider to avoid data races that may occur when setting the default provider during business operations. Signed-off-by: Weili Qian --- src/uadk_prov.h | 12 +++++ src/uadk_prov_dh.c | 51 +++++++++++++------- src/uadk_prov_ec_kmgmt.c | 19 ++++++++ src/uadk_prov_ecdh_exch.c | 33 ++++++------- src/uadk_prov_ecx.c | 97 ++++++++++++++++++++++++--------------- src/uadk_prov_init.c | 81 +++++++++++++++++++++----------- src/uadk_prov_pkey.h | 19 -------- src/uadk_prov_rsa_enc.c | 34 ++++++-------- src/uadk_prov_rsa_kmgmt.c | 20 ++++++++ src/uadk_prov_rsa_sign.c | 34 ++++++-------- src/uadk_prov_sm2.c | 88 +++++++++++++++++++---------------- 11 files changed, 293 insertions(+), 195 deletions(-) diff --git a/src/uadk_prov.h b/src/uadk_prov.h index ac0de58d..62a26fea 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -219,6 +219,18 @@ int uadk_prov_cipher_version(void); int uadk_prov_digest_version(void); int uadk_get_sw_offload_state(void); void uadk_set_sw_offload_state(int enable); +void set_default_dh_keymgmt(void); +void set_default_dh_keyexch(void); +void set_default_ec_keymgmt(void); +void set_default_ecdh_keyexch(void); +void set_default_ecx_keymgmt(void); +void set_default_ecx_keyexch(void); +void set_default_rsa_keymgmt(void); +void set_default_rsa_signature(void); +void set_default_rsa_asym_cipher(void); +void set_default_sm2_asym_cipher(void); +void set_default_sm2_signature(void); +void set_default_sm2_keymgmt(void); /* offload small packets to sw */ extern int enable_sw_offload; diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c index 5bbab628..a89e5550 100644 --- a/src/uadk_prov_dh.c +++ b/src/uadk_prov_dh.c @@ -60,29 +60,46 @@ UADK_PKEY_KEYMGMT_DESCR(dh, DH); UADK_PKEY_KEYEXCH_DESCR(dh, DH); static pthread_mutex_t dh_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t dh_default_mutex = PTHREAD_MUTEX_INITIALIZER; -static UADK_PKEY_KEYEXCH get_default_dh_keyexch(void) + +static UADK_PKEY_KEYEXCH s_keyexch; +static UADK_PKEY_KEYMGMT s_keymgmt; + +static UADK_PKEY_KEYMGMT get_default_dh_keymgmt(void) { - static UADK_PKEY_KEYEXCH s_keyexch; - static int initialized; - - pthread_mutex_lock(&dh_default_mutex); - if (!initialized) { - UADK_PKEY_KEYEXCH *keyexch = - (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "dh", "provider=default"); - if (keyexch) { - s_keyexch = *keyexch; - EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); - initialized = 1; - } else { - UADK_ERR("failed to EVP_KEYEXCH_fetch default dh provider\n"); - } + return s_keymgmt; +} + +void set_default_dh_keymgmt(void) +{ + UADK_PKEY_KEYMGMT *keymgmt; + + keymgmt = (UADK_PKEY_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "DH", "provider=default"); + if (keymgmt) { + s_keymgmt = *keymgmt; + EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); + } else { + UADK_INFO("failed to EVP_KEYMGMT_fetch dh default provider\n"); } - pthread_mutex_unlock(&dh_default_mutex); +} +static UADK_PKEY_KEYEXCH get_default_dh_keyexch(void) +{ return s_keyexch; } +void set_default_dh_keyexch(void) +{ + UADK_PKEY_KEYEXCH *keyexch; + + keyexch = (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "DH", "provider=default"); + if (keyexch) { + s_keyexch = *keyexch; + EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); + } else { + UADK_INFO("failed to EVP_KEYEXCH_fetch dh default provider\n"); + } +} + struct dh_st { /* * This first argument is used to pick up errors when a DH is passed diff --git a/src/uadk_prov_ec_kmgmt.c b/src/uadk_prov_ec_kmgmt.c index d3d47636..bd5cbd91 100644 --- a/src/uadk_prov_ec_kmgmt.c +++ b/src/uadk_prov_ec_kmgmt.c @@ -37,6 +37,25 @@ static const OSSL_ITEM check_group_type_nameid_map[] = { }; UADK_PKEY_KEYMGMT_DESCR(ec, EC); +static UADK_PKEY_KEYMGMT s_keymgmt; + +static UADK_PKEY_KEYMGMT get_default_ec_keymgmt(void) +{ + return s_keymgmt; +} + +void set_default_ec_keymgmt(void) +{ + UADK_PKEY_KEYMGMT *keymgmt; + + keymgmt = (UADK_PKEY_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "EC", "provider=default"); + if (keymgmt) { + s_keymgmt = *keymgmt; + EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); + } else { + UADK_INFO("failed to EVP_KEYMGMT_fetch EC default provider\n"); + } +} static int ec_param_check(struct ec_gen_ctx *gctx, EC_KEY *ec) { diff --git a/src/uadk_prov_ecdh_exch.c b/src/uadk_prov_ecdh_exch.c index 898e3672..3ee7e5ec 100644 --- a/src/uadk_prov_ecdh_exch.c +++ b/src/uadk_prov_ecdh_exch.c @@ -73,29 +73,26 @@ struct ecdh_sess_ctx { }; UADK_PKEY_KEYEXCH_DESCR(ecdh, ECDH); -static pthread_mutex_t ecdh_mutex = PTHREAD_MUTEX_INITIALIZER; +static UADK_PKEY_KEYEXCH s_keyexch; + static UADK_PKEY_KEYEXCH get_default_ecdh_keyexch(void) { - static UADK_PKEY_KEYEXCH s_keyexch; - static int initialized; - - pthread_mutex_lock(&ecdh_mutex); - if (!initialized) { - UADK_PKEY_KEYEXCH *keyexch = - (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "ecdh", "provider=default"); - if (keyexch) { - s_keyexch = *keyexch; - EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); - initialized = 1; - } else { - UADK_ERR("failed to EVP_KEYEXCH_fetch default X448 provider\n"); - } - } - pthread_mutex_unlock(&ecdh_mutex); - return s_keyexch; } +void set_default_ecdh_keyexch(void) +{ + UADK_PKEY_KEYEXCH *keyexch; + + keyexch = (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "ecdh", "provider=default"); + if (keyexch) { + s_keyexch = *keyexch; + EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); + } else { + UADK_INFO("failed to EVP_KEYEXCH_fetch default ecdh provider\n"); + } +} + static size_t ecdh_get_ec_size(const EC_GROUP *group) { size_t degree; diff --git a/src/uadk_prov_ecx.c b/src/uadk_prov_ecx.c index 878ac961..89b1a243 100644 --- a/src/uadk_prov_ecx.c +++ b/src/uadk_prov_ecx.c @@ -51,55 +51,78 @@ static inline int UADK_CRYPTO_DOWN_REF(int *val, int *ret, __atomic_thread_fence(__ATOMIC_ACQUIRE); return 1; } -static pthread_mutex_t x25519_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t x448_mutex = PTHREAD_MUTEX_INITIALIZER; + +static UADK_PKEY_KEYEXCH s_x448_keyexch; +static UADK_PKEY_KEYEXCH s_x25519_keyexch; + +static UADK_PKEY_KEYMGMT s_x448_keymgmt; +static UADK_PKEY_KEYMGMT s_x25519_keymgmt; UADK_PKEY_KEYMGMT_DESCR(x448, X448); UADK_PKEY_KEYEXCH_DESCR(x448, X448); +UADK_PKEY_KEYMGMT_DESCR(x25519, X25519); +UADK_PKEY_KEYEXCH_DESCR(x25519, X25519); + +static UADK_PKEY_KEYEXCH get_default_x25519_keyexch(void) +{ + return s_x25519_keyexch; +} + static UADK_PKEY_KEYEXCH get_default_x448_keyexch(void) { - static UADK_PKEY_KEYEXCH s_keyexch; - static int initilazed; - - pthread_mutex_lock(&x448_mutex); - if (!initilazed) { - UADK_PKEY_KEYEXCH *keyexch = - (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "X448", "provider=default"); - if (keyexch) { - s_keyexch = *keyexch; - EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); - initilazed = 1; - } else { - UADK_ERR("failed to EVP_KEYEXCH_fetch default X448 provider\n"); - } + return s_x448_keyexch; +} + +void set_default_ecx_keyexch(void) +{ + UADK_PKEY_KEYEXCH *keyexch; + + keyexch = (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "X448", "provider=default"); + if (keyexch) { + s_x448_keyexch = *keyexch; + EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); + } else { + UADK_INFO("failed to EVP_KEYEXCH_fetch default X448 provider\n"); } - pthread_mutex_unlock(&x448_mutex); - return s_keyexch; + keyexch = (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "X25519", "provider=default"); + if (keyexch) { + s_x25519_keyexch = *keyexch; + EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); + } else { + UADK_INFO("failed to EVP_KEYEXCH_fetch default X25519 provider\n"); + } } -UADK_PKEY_KEYMGMT_DESCR(x25519, X25519); -UADK_PKEY_KEYEXCH_DESCR(x25519, X25519); -static UADK_PKEY_KEYEXCH get_default_x25519_keyexch(void) +static UADK_PKEY_KEYMGMT get_default_x25519_keymgmt(void) { - static UADK_PKEY_KEYEXCH s_keyexch; - static int initialized; - - pthread_mutex_lock(&x25519_mutex); - if (!initialized) { - UADK_PKEY_KEYEXCH *keyexch = - (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "X25519", "provider=default"); - if (keyexch) { - s_keyexch = *keyexch; - EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); - initialized = 1; - } else { - UADK_ERR("failed to EVP_KEYEXCH_fetch default X25519 provider\n"); - } + return s_x25519_keymgmt; +} + +static UADK_PKEY_KEYMGMT get_default_x448_keymgmt(void) +{ + return s_x448_keymgmt; +} + +void set_default_ecx_keymgmt(void) +{ + UADK_PKEY_KEYMGMT *keymgmt; + + keymgmt = (UADK_PKEY_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "X448", "provider=default"); + if (keymgmt) { + s_x448_keymgmt = *keymgmt; + EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); + } else { + UADK_INFO("failed to EVP_KEYMGMT_fetch X448 default provider\n"); } - pthread_mutex_unlock(&x25519_mutex); - return s_keyexch; + keymgmt = (UADK_PKEY_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "X25519", "provider=default"); + if (keymgmt) { + s_x25519_keymgmt = *keymgmt; + EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); + } else { + UADK_INFO("failed to EVP_KEYMGMT_fetch X25519 default provider\n"); + } } typedef enum { diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 0e050e15..406a0e3e 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -666,34 +666,53 @@ static OSSL_ALGORITHM *uadk_generate_keyexch_array_v3(void) return keyexch_array_v3; } +static void uadk_set_default_alg(void) +{ + set_default_dh_keymgmt(); + set_default_dh_keyexch(); + set_default_ec_keymgmt(); + set_default_ecdh_keyexch(); + set_default_ecx_keymgmt(); + set_default_ecx_keyexch(); + set_default_rsa_keymgmt(); + set_default_rsa_asym_cipher(); + set_default_rsa_signature(); + set_default_sm2_asym_cipher(); + set_default_sm2_keymgmt(); + set_default_sm2_signature(); +} + +static int uadk_set_default_prov(OSSL_LIB_CTX *libctx) +{ + if (default_prov) + return UADK_P_SUCCESS; + + default_prov = OSSL_PROVIDER_load(libctx, "default"); + if (!default_prov) { + printf("failed to load default provider\n"); + return UADK_P_FAIL; + } + /* + * uadk_provider takes the highest priority + * and overwrite the openssl.cnf property. + */ + EVP_set_default_properties(libctx, "?provider=uadk_provider"); + /* + * In asynchronous scenarios, if random numbers are obtained using + * uadk provider cipher, deadlocks may occur. Therefore, random numbers are + * obtained using default provider cipher. + */ + (void)RAND_set_DRBG_type(libctx, NULL, "provider=default", NULL, NULL); + uadk_set_default_alg(); + + return UADK_P_SUCCESS; +} + static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, int *no_cache) { - OSSL_LIB_CTX *libctx; - static int prov_init; int ver; - if (__atomic_compare_exchange_n(&prov_init, &(int){0}, 1, false, __ATOMIC_SEQ_CST, - __ATOMIC_SEQ_CST)) { - libctx = prov_libctx_of(provctx); - default_prov = OSSL_PROVIDER_load(libctx, "default"); - if (!default_prov) { - UADK_ERR("failed to load default provider\n"); - return NULL; - } - /* - * uadk_provider takes the highest priority - * and overwrite the openssl.cnf property. - */ - EVP_set_default_properties(libctx, "?provider=uadk_provider"); - /* - * In asynchronous scenarios, if random numbers are obtained using - * uadk provider cipher, deadlocks may occur. Therefore, random numbers are - * obtained using default provider cipher. - */ - (void)RAND_set_DRBG_type(libctx, NULL, "provider=default", NULL, NULL); - } - if (no_cache) *no_cache = 0; @@ -995,10 +1014,12 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, ctx->libctx = (OSSL_LIB_CTX *)c_get_libctx(handle); ret = uadk_prov_ctx_set_core_bio_method(ctx); - if (!ret) { - OPENSSL_free(ctx); - return UADK_P_FAIL; - } + if (!ret) + goto free_ctx; + + ret = uadk_set_default_prov(ctx->libctx); + if (!ret) + goto free_corebiometh; ret = async_module_init(); if (!ret) @@ -1009,4 +1030,10 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, *out = uadk_dispatch_table; return UADK_P_SUCCESS; + +free_corebiometh: + BIO_meth_free(ctx->corebiometh); +free_ctx: + OPENSSL_free(ctx); + return UADK_P_FAIL; } diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index 78910116..7a77c5c0 100644 --- a/src/uadk_prov_pkey.h +++ b/src/uadk_prov_pkey.h @@ -187,25 +187,6 @@ static OSSL_FUNC_keymgmt_export_fn uadk_keymgmt_##nm##_export; \ static OSSL_FUNC_keymgmt_export_types_fn uadk_keymgmt_##nm##_export_types; \ static OSSL_FUNC_keymgmt_dup_fn uadk_keymgmt_##nm##_dup; \ static OSSL_FUNC_keymgmt_query_operation_name_fn uadk_keymgmt_##nm##_query_operation_name; \ -static UADK_PKEY_KEYMGMT get_default_##nm##_keymgmt(void) \ -{ \ - static UADK_PKEY_KEYMGMT s_keymgmt; \ - static int initilazed; \ - \ - if (!initilazed) { \ - UADK_PKEY_KEYMGMT *keymgmt = \ - (UADK_PKEY_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, #alg, "provider=default"); \ - \ - if (keymgmt) { \ - s_keymgmt = *keymgmt; \ - EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); \ - initilazed = 1; \ - } else { \ - fprintf(stderr, "failed to EVP_KEYMGMT_fetch default provider\n"); \ - } \ - } \ - return s_keymgmt; \ -} \ const OSSL_DISPATCH uadk_##nm##_keymgmt_functions[] = { \ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))uadk_keymgmt_##nm##_new }, \ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))uadk_keymgmt_##nm##_free }, \ diff --git a/src/uadk_prov_rsa_enc.c b/src/uadk_prov_rsa_enc.c index d4f81069..c6545c40 100644 --- a/src/uadk_prov_rsa_enc.c +++ b/src/uadk_prov_rsa_enc.c @@ -48,31 +48,27 @@ struct PROV_RSA_ASYM_CTX { unsigned int soft : 1; }; -static pthread_mutex_t asym_mutex = PTHREAD_MUTEX_INITIALIZER; +static UADK_PKEY_ASYM_CIPHER s_asym_cipher; 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; } +void set_default_rsa_asym_cipher(void) +{ + UADK_PKEY_ASYM_CIPHER *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); + } else { + UADK_INFO("failed to EVP_ASYM_CIPHER_fetch rsa default provider\n"); + } +} + /** * 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 diff --git a/src/uadk_prov_rsa_kmgmt.c b/src/uadk_prov_rsa_kmgmt.c index f71eed37..a3cf065b 100644 --- a/src/uadk_prov_rsa_kmgmt.c +++ b/src/uadk_prov_rsa_kmgmt.c @@ -74,6 +74,26 @@ struct rsa_gen_ctx { void *cbarg; }; +static UADK_PKEY_KEYMGMT s_keymgmt; + +static UADK_PKEY_KEYMGMT get_default_rsa_keymgmt(void) +{ + return s_keymgmt; +} + +void set_default_rsa_keymgmt(void) +{ + UADK_PKEY_KEYMGMT *keymgmt; + + keymgmt = (UADK_PKEY_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "RSA", "provider=default"); + if (keymgmt) { + s_keymgmt = *keymgmt; + EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); + } else { + UADK_INFO("failed to EVP_KEYMGMT_fetch rsa default provider\n"); + } +} + static void uadk_rsa_clear_flags(RSA *r, int flags) { r->flags &= ~flags; diff --git a/src/uadk_prov_rsa_sign.c b/src/uadk_prov_rsa_sign.c index 5009a0b6..a297601c 100644 --- a/src/uadk_prov_rsa_sign.c +++ b/src/uadk_prov_rsa_sign.c @@ -68,33 +68,29 @@ struct PROV_RSA_SIG_CTX { unsigned int soft : 1; }; -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 s_signature; + 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; } +void set_default_rsa_signature(void) +{ + UADK_PKEY_SIGNATURE *signature; + + signature = (UADK_PKEY_SIGNATURE *)EVP_SIGNATURE_fetch(NULL, "RSA", "provider=default"); + if (signature) { + s_signature = *signature; + EVP_SIGNATURE_free((EVP_SIGNATURE *)signature); + } else { + UADK_INFO("failed to EVP_SIGNATURE_fetch rsa default provider\n"); + } +} + static size_t uadk_rsa_get_md_size(struct PROV_RSA_SIG_CTX *prsactx) { if (prsactx->md != NULL) diff --git a/src/uadk_prov_sm2.c b/src/uadk_prov_sm2.c index 03c4e1e1..83378f14 100644 --- a/src/uadk_prov_sm2.c +++ b/src/uadk_prov_sm2.c @@ -36,9 +36,6 @@ #define SM2_DEFAULT_USERID "1234567812345678" #define SM2_DEFAULT_USERID_LEN 16 -static pthread_mutex_t sign_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t asym_mutex = PTHREAD_MUTEX_INITIALIZER; - UADK_PKEY_KEYMGMT_DESCR(sm2, SM2); UADK_PKEY_SIGNATURE_DESCR(sm2, SM2); UADK_PKEY_ASYM_CIPHER_DESCR(sm2, SM2); @@ -221,6 +218,28 @@ ASN1_SEQUENCE(SM2_Ciphertext) = { IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext) +static UADK_PKEY_KEYMGMT s_keymgmt; +static UADK_PKEY_ASYM_CIPHER s_asym_cipher; +static UADK_PKEY_SIGNATURE s_signature; + +static UADK_PKEY_KEYMGMT get_default_sm2_keymgmt(void) +{ + return s_keymgmt; +} + +void set_default_sm2_keymgmt(void) +{ + UADK_PKEY_KEYMGMT *keymgmt; + + keymgmt = (UADK_PKEY_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "SM2", "provider=default"); + if (keymgmt) { + s_keymgmt = *keymgmt; + EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); + } else { + UADK_INFO("failed to EVP_KEYMGMT_fetch sm2 default provider\n"); + } +} + static const char *uadk_keymgmt_sm2_query_operation_name(int operation_id) { if (!get_default_sm2_keymgmt().query_operation_name) { @@ -711,26 +730,22 @@ static void *uadk_keymgmt_sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba static UADK_PKEY_SIGNATURE get_default_sm2_signature(void) { - static UADK_PKEY_SIGNATURE s_signature; - static int initilazed; - - pthread_mutex_lock(&sign_mutex); - if (!initilazed) { - UADK_PKEY_SIGNATURE *signature = - (UADK_PKEY_SIGNATURE *)EVP_SIGNATURE_fetch(NULL, "SM2", "provider=default"); - if (signature) { - s_signature = *signature; - EVP_SIGNATURE_free((EVP_SIGNATURE *)signature); - initilazed = 1; - } else { - UADK_ERR("failed to EVP_SIGNATURE_fetch default SM2 provider\n"); - } - } - pthread_mutex_unlock(&sign_mutex); - return s_signature; } +void set_default_sm2_signature(void) +{ + UADK_PKEY_SIGNATURE *signature; + + signature = (UADK_PKEY_SIGNATURE *)EVP_SIGNATURE_fetch(NULL, "SM2", "provider=default"); + if (signature) { + s_signature = *signature; + EVP_SIGNATURE_free((EVP_SIGNATURE *)signature); + } else { + UADK_INFO("failed to EVP_SIGNATURE_fetch sm2 default provider\n"); + } +} + static void *uadk_signature_sm2_newctx(void *provctx, const char *propq) { PROV_SM2_SIGN_CTX *psm2ctx = OPENSSL_zalloc(sizeof(PROV_SM2_SIGN_CTX)); @@ -2371,28 +2386,23 @@ static int uadk_signature_sm2_verify_recover(void *vpsm2ctx, unsigned char *rout static UADK_PKEY_ASYM_CIPHER get_default_sm2_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, "SM2", - "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 SM2 provider\n"); - } - } - pthread_mutex_unlock(&asym_mutex); - return s_asym_cipher; } +void set_default_sm2_asym_cipher(void) +{ + UADK_PKEY_ASYM_CIPHER *asym_cipher; + + asym_cipher = (UADK_PKEY_ASYM_CIPHER *)EVP_ASYM_CIPHER_fetch(NULL, + "SM2", "provider=default"); + if (asym_cipher) { + s_asym_cipher = *asym_cipher; + EVP_ASYM_CIPHER_free((EVP_ASYM_CIPHER *)asym_cipher); + } else { + UADK_INFO("failed to EVP_ASYM_CIPHER_fetch sm2 default provider\n"); + } +} + static void *uadk_asym_cipher_sm2_newctx(void *provctx) { PROV_SM2_ASYM_CTX *psm2ctx = OPENSSL_zalloc(sizeof(PROV_SM2_ASYM_CTX)); From 09f8c499dca1707d078a66071a3381dab3454731 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 02/16] uadk_engine: release asynchronous resources before destroying algorithm resources To avoid accessing resources after algorithm resources have been released, first stop the poll thread and release asynchronous resources, and finally destroy the algorithm resources. Signed-off-by: Weili Qian --- src/uadk_engine_init.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/uadk_engine_init.c b/src/uadk_engine_init.c index 48498c36..d7d71c86 100644 --- a/src/uadk_engine_init.c +++ b/src/uadk_engine_init.c @@ -223,6 +223,10 @@ static int uadk_destroy(ENGINE *e) kae_debug_close_log(); #endif + pthread_mutex_lock(&uadk_engine_mutex); + if (uadk_cipher || uadk_digest || uadk_rsa || uadk_dh || uadk_ecc) + async_module_uninit(); + if (uadk_cipher) uadk_e_destroy_ciphers(); if (uadk_digest) @@ -234,10 +238,6 @@ static int uadk_destroy(ENGINE *e) if (uadk_dh) uadk_e_destroy_dh(); - if (uadk_cipher || uadk_digest || uadk_rsa || uadk_dh || uadk_ecc) - async_module_uninit(); - - pthread_mutex_lock(&uadk_engine_mutex); uadk_inited = 0; pthread_mutex_unlock(&uadk_engine_mutex); From e5da12bc7531b0228b9723da10c286c097a2818e Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 03/16] uadk_provider: release asynchronous resources before destroying algorithm resources To avoid accessing resources after algorithm resources have been released, first stop the poll thread and release asynchronous resources, and finally destroy the algorithm resources. Signed-off-by: Weili Qian --- src/uadk_prov_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 406a0e3e..92ecc686 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -779,6 +779,7 @@ static void uadk_teardown(void *provctx) OPENSSL_free(ctx); } + async_module_uninit(); uadk_prov_destroy_digest(); uadk_prov_destroy_hmac(); uadk_prov_destroy_cipher(); @@ -786,7 +787,6 @@ static void uadk_teardown(void *provctx) uadk_prov_destroy_rsa(); uadk_prov_ecc_uninit(); uadk_prov_dh_uninit(); - async_module_uninit(); if (default_prov) { OSSL_PROVIDER_unload(default_prov); default_prov = NULL; From 41a47a9fa3f0345592b4fe0b2d2cdb4cee5012f4 Mon Sep 17 00:00:00 2001 From: Zhushuai Yin Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 04/16] uadk_provider: reduce lock scope during prov init toimprove perf To improve performance, the lock scope is narrowed, and the mb() operation is added to ensure the visibility and ordering of shared data, thereby avoiding data races. Signed-off-by: Zhushuai Yin --- src/uadk_prov_aead.c | 18 ++++++----- src/uadk_prov_cipher.c | 70 +++++++++++++++++++++--------------------- src/uadk_prov_dh.c | 15 ++++++--- src/uadk_prov_digest.c | 18 ++++++----- src/uadk_prov_hmac.c | 24 +++++++-------- src/uadk_prov_pkey.c | 14 ++++++--- src/uadk_prov_rsa.c | 14 ++++++--- 7 files changed, 98 insertions(+), 75 deletions(-) diff --git a/src/uadk_prov_aead.c b/src/uadk_prov_aead.c index 4533540d..cef05035 100644 --- a/src/uadk_prov_aead.c +++ b/src/uadk_prov_aead.c @@ -293,18 +293,15 @@ static int uadk_prov_aead_dev_init(struct aead_priv_ctx *priv) struct wd_ctx_params cparams = {0}; int ret = UADK_AEAD_SUCCESS; - pthread_atfork(NULL, NULL, uadk_aead_mutex_infork); - pthread_mutex_lock(&aead_mutex); if (aprov.pid == getpid()) - goto mutex_unlock; + return ret; cparams.op_type_num = UADK_AEAD_OP_NUM; cparams.ctx_set_num = &ctx_set_num; cparams.bmp = numa_allocate_nodemask(); if (!cparams.bmp) { - ret = UADK_AEAD_FAIL; UADK_ERR("failed to create nodemask!\n"); - goto mutex_unlock; + return UADK_AEAD_FAIL; } numa_bitmask_setall(cparams.bmp); @@ -312,6 +309,11 @@ static int uadk_prov_aead_dev_init(struct aead_priv_ctx *priv) ctx_set_num.sync_ctx_num = UADK_AEAD_DEF_CTXS; ctx_set_num.async_ctx_num = UADK_AEAD_DEF_CTXS; + pthread_atfork(NULL, NULL, uadk_aead_mutex_infork); + pthread_mutex_lock(&aead_mutex); + if (aprov.pid == getpid()) + goto free_nodemask; + ret = wd_aead_init2_(priv->alg_name, TASK_MIX, SCHED_POLICY_RR, &cparams); if (unlikely(ret)) { ret = UADK_AEAD_FAIL; @@ -319,13 +321,13 @@ static int uadk_prov_aead_dev_init(struct aead_priv_ctx *priv) goto free_nodemask; } - aprov.pid = getpid(); async_register_poll_fn(ASYNC_TASK_AEAD, uadk_aead_poll); + mb(); + aprov.pid = getpid(); free_nodemask: - numa_free_nodemask(cparams.bmp); -mutex_unlock: pthread_mutex_unlock(&aead_mutex); + numa_free_nodemask(cparams.bmp); return ret; } diff --git a/src/uadk_prov_cipher.c b/src/uadk_prov_cipher.c index 0bb4aaec..d442d3d7 100644 --- a/src/uadk_prov_cipher.c +++ b/src/uadk_prov_cipher.c @@ -528,54 +528,54 @@ static void uadk_cipher_mutex_infork(void) static int uadk_prov_cipher_dev_init(struct cipher_priv_ctx *priv) { - int ret; + struct wd_ctx_params cparams = {0}; + struct wd_ctx_nums *ctx_set_num; + int ret = UADK_P_SUCCESS; - pthread_atfork(NULL, NULL, uadk_cipher_mutex_infork); - pthread_mutex_lock(&cipher_mutex); - if (prov.pid != getpid()) { - struct wd_ctx_nums *ctx_set_num; - struct wd_ctx_params cparams = {0}; - - ctx_set_num = calloc(UADK_CIPHER_OP_NUM, sizeof(*ctx_set_num)); - if (!ctx_set_num) { - UADK_ERR("failed to alloc ctx_set_size!\n"); - ret = UADK_P_FAIL; - goto init_err; - } + if (prov.pid == getpid()) + return ret; - cparams.op_type_num = UADK_CIPHER_OP_NUM; - cparams.ctx_set_num = ctx_set_num; - cparams.bmp = numa_allocate_nodemask(); - if (!cparams.bmp) { - UADK_ERR("failed to create nodemask!\n"); - free(ctx_set_num); - ret = UADK_P_FAIL; - goto init_err; - } + ctx_set_num = calloc(UADK_CIPHER_OP_NUM, sizeof(*ctx_set_num)); + if (!ctx_set_num) { + UADK_ERR("failed to alloc ctx_set_size!\n"); + return UADK_P_FAIL; + } - numa_bitmask_setall(cparams.bmp); + cparams.op_type_num = UADK_CIPHER_OP_NUM; + cparams.ctx_set_num = ctx_set_num; + cparams.bmp = numa_allocate_nodemask(); + if (!cparams.bmp) { + UADK_ERR("failed to create nodemask!\n"); + free(ctx_set_num); + return UADK_P_FAIL; + } - ctx_set_num->sync_ctx_num = UADK_CIPHER_DEF_CTXS; - ctx_set_num->async_ctx_num = UADK_CIPHER_DEF_CTXS; + numa_bitmask_setall(cparams.bmp); - ret = wd_cipher_init2_(priv->alg_name, TASK_MIX, SCHED_POLICY_RR, &cparams); - numa_free_nodemask(cparams.bmp); - free(ctx_set_num); + ctx_set_num->sync_ctx_num = UADK_CIPHER_DEF_CTXS; + ctx_set_num->async_ctx_num = UADK_CIPHER_DEF_CTXS; - if (unlikely(ret)) { - UADK_ERR("failed to init cipher!\n"); - ret = UADK_P_FAIL; - goto init_err; - } + pthread_atfork(NULL, NULL, uadk_cipher_mutex_infork); + pthread_mutex_lock(&cipher_mutex); + if (prov.pid == getpid()) + goto init_err; - prov.pid = getpid(); - async_register_poll_fn(ASYNC_TASK_CIPHER, uadk_cipher_poll); + ret = wd_cipher_init2_(priv->alg_name, TASK_MIX, SCHED_POLICY_RR, &cparams); + if (unlikely(ret)) { + UADK_ERR("failed to init cipher!\n"); + ret = UADK_P_FAIL; + goto init_err; } + async_register_poll_fn(ASYNC_TASK_CIPHER, uadk_cipher_poll); + mb(); + prov.pid = getpid(); ret = UADK_P_SUCCESS; init_err: pthread_mutex_unlock(&cipher_mutex); + numa_free_nodemask(cparams.bmp); + free(ctx_set_num); return ret; } diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c index a89e5550..2d96a1dd 100644 --- a/src/uadk_prov_dh.c +++ b/src/uadk_prov_dh.c @@ -658,18 +658,25 @@ static int uadk_prov_dh_init(void) char alg_name[] = "dh"; int ret; - pthread_atfork(NULL, NULL, uadk_prov_dh_mutex_infork); - pthread_mutex_lock(&dh_mutex); if (g_dh_prov.pid != getpid()) { + pthread_atfork(NULL, NULL, uadk_prov_dh_mutex_infork); + pthread_mutex_lock(&dh_mutex); + if (g_dh_prov.pid == getpid()) { + pthread_mutex_unlock(&dh_mutex); + return UADK_P_INIT_SUCCESS; + } + ret = wd_dh_init2(alg_name, SCHED_POLICY_RR, TASK_HW); if (unlikely(ret)) { pthread_mutex_unlock(&dh_mutex); return ret; } - g_dh_prov.pid = getpid(); + async_register_poll_fn(ASYNC_TASK_DH, uadk_prov_dh_poll); + mb(); + g_dh_prov.pid = getpid(); + pthread_mutex_unlock(&dh_mutex); } - pthread_mutex_unlock(&dh_mutex); return UADK_P_INIT_SUCCESS; } diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c index d9c5ae3f..1a5cc81b 100644 --- a/src/uadk_prov_digest.c +++ b/src/uadk_prov_digest.c @@ -345,18 +345,15 @@ static int uadk_prov_digest_dev_init(struct digest_priv_ctx *priv) struct wd_ctx_nums ctx_set_num; int ret = UADK_DIGEST_SUCCESS; - pthread_atfork(NULL, NULL, uadk_digest_mutex_infork); - pthread_mutex_lock(&digest_mutex); if (dprov.pid == getpid()) - goto mutex_unlock; + return ret; cparams.op_type_num = UADK_DIGEST_OP_NUM; cparams.ctx_set_num = &ctx_set_num; cparams.bmp = numa_allocate_nodemask(); if (!cparams.bmp) { - ret = UADK_DIGEST_FAIL; UADK_ERR("failed to create nodemask!\n"); - goto mutex_unlock; + return UADK_DIGEST_FAIL; } numa_bitmask_setall(cparams.bmp); @@ -364,6 +361,11 @@ static int uadk_prov_digest_dev_init(struct digest_priv_ctx *priv) ctx_set_num.sync_ctx_num = UADK_DIGEST_DEF_CTXS; ctx_set_num.async_ctx_num = UADK_DIGEST_DEF_CTXS; + pthread_atfork(NULL, NULL, uadk_digest_mutex_infork); + pthread_mutex_lock(&digest_mutex); + if (dprov.pid == getpid()) + goto free_nodemask; + ret = wd_digest_init2_(priv->alg_name, TASK_MIX, SCHED_POLICY_RR, &cparams); if (unlikely(ret && ret != -WD_EEXIST)) { UADK_ERR("uadk failed to initialize digest dev, ret = %d\n", ret); @@ -371,13 +373,13 @@ static int uadk_prov_digest_dev_init(struct digest_priv_ctx *priv) } ret = UADK_DIGEST_SUCCESS; - dprov.pid = getpid(); async_register_poll_fn(ASYNC_TASK_DIGEST, uadk_digest_poll); + mb(); + dprov.pid = getpid(); free_nodemask: - numa_free_nodemask(cparams.bmp); -mutex_unlock: pthread_mutex_unlock(&digest_mutex); + numa_free_nodemask(cparams.bmp); return ret; } diff --git a/src/uadk_prov_hmac.c b/src/uadk_prov_hmac.c index e1a8b104..0c53d121 100644 --- a/src/uadk_prov_hmac.c +++ b/src/uadk_prov_hmac.c @@ -412,24 +412,19 @@ static int uadk_prov_hmac_dev_init(struct hmac_priv_ctx *priv) int ret = UADK_P_SUCCESS; const char *alg_name; - pthread_atfork(NULL, NULL, uadk_hmac_mutex_infork); - pthread_mutex_lock(&hmac_mutex); if (hprov.pid == getpid()) - goto mutex_unlock; + return ret; alg_name = get_uadk_alg_name(priv->alg_id); - if (!alg_name) { - ret = UADK_P_FAIL; - goto mutex_unlock; - } + if (!alg_name) + return UADK_P_FAIL; cparams.op_type_num = UADK_DIGEST_OP_NUM; cparams.ctx_set_num = &ctx_set_num; cparams.bmp = numa_allocate_nodemask(); if (!cparams.bmp) { - ret = UADK_P_FAIL; UADK_ERR("failed to create nodemask!\n"); - goto mutex_unlock; + return UADK_P_FAIL; } numa_bitmask_setall(cparams.bmp); @@ -437,6 +432,11 @@ static int uadk_prov_hmac_dev_init(struct hmac_priv_ctx *priv) ctx_set_num.sync_ctx_num = UADK_DIGEST_DEF_CTXS; ctx_set_num.async_ctx_num = UADK_DIGEST_DEF_CTXS; + pthread_atfork(NULL, NULL, uadk_hmac_mutex_infork); + pthread_mutex_lock(&hmac_mutex); + if (hprov.pid == getpid()) + goto free_nodemask; + ret = wd_digest_init2_((char *)alg_name, TASK_MIX, SCHED_POLICY_RR, &cparams); if (unlikely(ret && ret != -WD_EEXIST)) { UADK_ERR("uadk failed to initialize hmac, ret = %d\n", ret); @@ -444,13 +444,13 @@ static int uadk_prov_hmac_dev_init(struct hmac_priv_ctx *priv) } ret = UADK_P_SUCCESS; - hprov.pid = getpid(); async_register_poll_fn(ASYNC_TASK_HMAC, uadk_hmac_poll); + mb(); + hprov.pid = getpid(); free_nodemask: - numa_free_nodemask(cparams.bmp); -mutex_unlock: pthread_mutex_unlock(&hmac_mutex); + numa_free_nodemask(cparams.bmp); return ret; } diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c index 9597e7f6..994ea076 100644 --- a/src/uadk_prov_pkey.c +++ b/src/uadk_prov_pkey.c @@ -815,18 +815,24 @@ int uadk_prov_ecc_init(const char *alg_name) { int ret; - pthread_atfork(NULL, NULL, uadk_prov_ecc_mutex_infork); - pthread_mutex_lock(&ecc_mutex); if (g_ecc_prov.pid != getpid()) { + pthread_atfork(NULL, NULL, uadk_prov_ecc_mutex_infork); + pthread_mutex_lock(&ecc_mutex); + if (g_ecc_prov.pid == getpid()) { + pthread_mutex_unlock(&ecc_mutex); + return UADK_P_SUCCESS; + } + ret = wd_ecc_init2((char *)alg_name, SCHED_POLICY_RR, TASK_HW); if (unlikely(ret)) { pthread_mutex_unlock(&ecc_mutex); return UADK_P_FAIL; } - g_ecc_prov.pid = getpid(); async_register_poll_fn(ASYNC_TASK_ECC, uadk_prov_ecc_poll); + mb(); + g_ecc_prov.pid = getpid(); + pthread_mutex_unlock(&ecc_mutex); } - pthread_mutex_unlock(&ecc_mutex); return UADK_P_SUCCESS; } diff --git a/src/uadk_prov_rsa.c b/src/uadk_prov_rsa.c index a0bb26e6..f77f718d 100644 --- a/src/uadk_prov_rsa.c +++ b/src/uadk_prov_rsa.c @@ -213,18 +213,24 @@ int uadk_prov_rsa_init(void) char alg_name[] = "rsa"; int ret; - pthread_atfork(NULL, NULL, uadk_rsa_mutex_infork); - pthread_mutex_lock(&rsa_mutex); if (g_rsa_prov.pid != getpid()) { + pthread_atfork(NULL, NULL, uadk_rsa_mutex_infork); + pthread_mutex_lock(&rsa_mutex); + if (g_rsa_prov.pid == getpid()) { + pthread_mutex_unlock(&rsa_mutex); + return UADK_P_INIT_SUCCESS; + } + ret = wd_rsa_init2(alg_name, SCHED_POLICY_RR, TASK_MIX); if (unlikely(ret)) { pthread_mutex_unlock(&rsa_mutex); return ret; } - g_rsa_prov.pid = getpid(); async_register_poll_fn(ASYNC_TASK_RSA, uadk_rsa_env_poll); + mb(); + g_rsa_prov.pid = getpid(); + pthread_mutex_unlock(&rsa_mutex); } - pthread_mutex_unlock(&rsa_mutex); return UADK_P_INIT_SUCCESS; } From 22bbf101f7d47577160fd2f175d6e7a12063eca9 Mon Sep 17 00:00:00 2001 From: Zhushuai Yin Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 05/16] uadk_engine: reduce lock scope during prov init to improve perf To improve performance, the lock scope is narrowed, and the mb() operation is added to ensure the visibility and ordering of shared data, thereby avoiding data races. Signed-off-by: Zhushuai Yin --- src/uadk_aead.c | 1 + src/uadk_cipher.c | 1 + src/uadk_dh.c | 1 + src/uadk_digest.c | 1 + src/uadk_pkey.c | 1 + src/uadk_rsa.c | 1 + 6 files changed, 6 insertions(+) diff --git a/src/uadk_aead.c b/src/uadk_aead.c index 6920c040..db5faf70 100644 --- a/src/uadk_aead.c +++ b/src/uadk_aead.c @@ -263,6 +263,7 @@ static int uadk_e_init_aead_cipher(void) return UADK_E_FAIL; } + mb(); g_aead_engine.pid = getpid(); pthread_spin_unlock(&g_aead_engine.lock); free(dev); diff --git a/src/uadk_cipher.c b/src/uadk_cipher.c index 9029ece7..4067fb67 100644 --- a/src/uadk_cipher.c +++ b/src/uadk_cipher.c @@ -448,6 +448,7 @@ static int uadk_e_init_cipher(void) if (ret) goto err_unlock; + mb(); g_cipher_engine.pid = getpid(); pthread_spin_unlock(&g_cipher_engine.lock); free(dev); diff --git a/src/uadk_dh.c b/src/uadk_dh.c index cae7d0a5..e49250b2 100644 --- a/src/uadk_dh.c +++ b/src/uadk_dh.c @@ -400,6 +400,7 @@ static int uadk_e_dh_init(void) } g_dh_res.numa_id = dev->numa_id; + mb(); g_dh_res.status = UADK_INIT_SUCCESS; pthread_spin_unlock(&g_dh_res.lock); free(dev); diff --git a/src/uadk_digest.c b/src/uadk_digest.c index 88e7fc86..c8372b4b 100644 --- a/src/uadk_digest.c +++ b/src/uadk_digest.c @@ -523,6 +523,7 @@ static int uadk_e_init_digest(void) if (ret) goto err_unlock; + mb(); g_digest_engine.pid = getpid(); pthread_spin_unlock(&g_digest_engine.lock); free(dev); diff --git a/src/uadk_pkey.c b/src/uadk_pkey.c index fb45ccc6..c5f711b8 100644 --- a/src/uadk_pkey.c +++ b/src/uadk_pkey.c @@ -599,6 +599,7 @@ int uadk_init_ecc(void) } ecc_res.numa_id = dev->numa_id; + mb(); ecc_res.status = UADK_INIT_SUCCESS; pthread_spin_unlock(&ecc_res.lock); free(dev); diff --git a/src/uadk_rsa.c b/src/uadk_rsa.c index 160ab8c0..318f8ed1 100644 --- a/src/uadk_rsa.c +++ b/src/uadk_rsa.c @@ -849,6 +849,7 @@ static int uadk_e_rsa_init(void) } g_rsa_res.numa_id = dev->numa_id; + mb(); g_rsa_res.status = UADK_INIT_SUCCESS; pthread_spin_unlock(&g_rsa_res.lock); free(dev); From 412865604e4d826dae0b14d0874b3e5db581c17f Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 06/16] uadk_provider/sm2: move sm2 key generation into a separate file The uadk_prov_sm2.c file is too large, so separate the key generation code from it into a separate file. No functional changes. Signed-off-by: Weili Qian --- src/Makefile.am | 2 +- src/uadk_prov_sm2.c | 508 ----------------------------------- src/uadk_prov_sm2_kmgmt.c | 538 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 539 insertions(+), 509 deletions(-) create mode 100644 src/uadk_prov_sm2_kmgmt.c diff --git a/src/Makefile.am b/src/Makefile.am index 447431ce..6b035cc2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,7 +67,7 @@ uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.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 \ + uadk_prov_pkey.c uadk_prov_sm2.c uadk_prov_sm2_kmgmt.c \ uadk_prov_ffc.c uadk_prov_aead.c \ uadk_prov_ec_kmgmt.c uadk_prov_ecdh_exch.c \ uadk_prov_ecx.c uadk_prov_ecdsa.c \ diff --git a/src/uadk_prov_sm2.c b/src/uadk_prov_sm2.c index 83378f14..cfaa4409 100644 --- a/src/uadk_prov_sm2.c +++ b/src/uadk_prov_sm2.c @@ -36,7 +36,6 @@ #define SM2_DEFAULT_USERID "1234567812345678" #define SM2_DEFAULT_USERID_LEN 16 -UADK_PKEY_KEYMGMT_DESCR(sm2, SM2); UADK_PKEY_SIGNATURE_DESCR(sm2, SM2); UADK_PKEY_ASYM_CIPHER_DESCR(sm2, SM2); @@ -218,516 +217,9 @@ ASN1_SEQUENCE(SM2_Ciphertext) = { IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext) -static UADK_PKEY_KEYMGMT s_keymgmt; static UADK_PKEY_ASYM_CIPHER s_asym_cipher; static UADK_PKEY_SIGNATURE s_signature; -static UADK_PKEY_KEYMGMT get_default_sm2_keymgmt(void) -{ - return s_keymgmt; -} - -void set_default_sm2_keymgmt(void) -{ - UADK_PKEY_KEYMGMT *keymgmt; - - keymgmt = (UADK_PKEY_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "SM2", "provider=default"); - if (keymgmt) { - s_keymgmt = *keymgmt; - EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); - } else { - UADK_INFO("failed to EVP_KEYMGMT_fetch sm2 default provider\n"); - } -} - -static const char *uadk_keymgmt_sm2_query_operation_name(int operation_id) -{ - if (!get_default_sm2_keymgmt().query_operation_name) { - UADK_ERR("failed to get keymgmt query_operation_name function\n"); - return NULL; - } - - return get_default_sm2_keymgmt().query_operation_name(operation_id); -} - -/** - * Create an uadk provider side sm2 key object. - * - * @param provctx The provider context. - * @return Return created key object if success, return NULL if failed. - */ -static void *uadk_keymgmt_sm2_new(void *provctx) -{ - if (!get_default_sm2_keymgmt().new_fun) { - UADK_ERR("failed to get keymgmt new function\n"); - return NULL; - } - - return get_default_sm2_keymgmt().new_fun(provctx); -} - -/** - * Release an uadk provider side sm2 key object - * - * @param keydata Key object related data. - */ -static void uadk_keymgmt_sm2_free(void *keydata) -{ - if (!get_default_sm2_keymgmt().free) { - UADK_ERR("failed to get keymgmt free function\n"); - return; - } - - get_default_sm2_keymgmt().free(keydata); -} - -static int uadk_keymgmt_sm2_get_params(void *key, OSSL_PARAM params[]) -{ - if (!get_default_sm2_keymgmt().get_params) { - UADK_ERR("failed to get keymgmt get_params function\n"); - return UADK_P_FAIL; - } - - return get_default_sm2_keymgmt().get_params(key, params); -} - -static const OSSL_PARAM *uadk_keymgmt_sm2_gettable_params(void *provctx) -{ - if (!get_default_sm2_keymgmt().gettable_params) { - UADK_ERR("failed to get keymgmt gettable_params function\n"); - return NULL; - } - - return get_default_sm2_keymgmt().gettable_params(provctx); -} - -static int uadk_keymgmt_sm2_set_params(void *key, const OSSL_PARAM params[]) -{ - if (!get_default_sm2_keymgmt().set_params) { - UADK_ERR("failed to get keymgmt set_params function\n"); - return UADK_P_FAIL; - } - - return get_default_sm2_keymgmt().set_params(key, params); -} - -static int uadk_keymgmt_sm2_gen_set_template(void *genctx, void *templates) -{ - if (!get_default_sm2_keymgmt().gen_set_template) { - UADK_ERR("failed to get keymgmt gen_set_template function\n"); - return UADK_P_FAIL; - } - - return get_default_sm2_keymgmt().gen_set_template(genctx, templates); -} - -static void uadk_keymgmt_sm2_gen_cleanup(void *genctx) -{ - if (!get_default_sm2_keymgmt().gen_cleanup) { - UADK_ERR("failed to get keymgmt gen_cleanup function\n"); - return; - } - - get_default_sm2_keymgmt().gen_cleanup(genctx); -} - -static void *uadk_keymgmt_sm2_load(const void *reference, size_t reference_sz) -{ - if (!get_default_sm2_keymgmt().load) { - UADK_ERR("failed to get keymgmt load function\n"); - return NULL; - } - - return get_default_sm2_keymgmt().load(reference, reference_sz); -} - -static int uadk_keymgmt_sm2_validate(const void *keydata, int selection, int checktype) -{ - if (!get_default_sm2_keymgmt().validate) { - UADK_ERR("failed to get keymgmt validate function\n"); - return UADK_P_FAIL; - } - - return get_default_sm2_keymgmt().validate(keydata, selection, checktype); -} - -static int uadk_keymgmt_sm2_match(const void *keydata1, const void *keydata2, int selection) -{ - if (!get_default_sm2_keymgmt().match) { - UADK_ERR("failed to get keymgmt validate function\n"); - return UADK_P_FAIL; - } - - return get_default_sm2_keymgmt().match(keydata1, keydata2, selection); -} - -/** - * Check if a sm2 key object has specific options, such as public key, - * private key, domain params etc. - * - * @param keydata The key object to check. - * @param selection Check options, like public key, private key, domain params etc. - * @return Return 1 if success, return 0 if failed. - */ -static int uadk_keymgmt_sm2_has(const void *keydata, int selection) -{ - if (!get_default_sm2_keymgmt().has) { - UADK_ERR("failed to get keymgmt has function\n"); - return UADK_P_FAIL; - } - - return get_default_sm2_keymgmt().has(keydata, selection); -} - -/** - * Import a sm2 key object with key related params. - * - * @param keydata The key object to import. - * @param selection The key params to import. - * @param params OSSL params. - * @return Return 1 if success, return 0 if failed. - */ -static int uadk_keymgmt_sm2_import(void *keydata, int selection, const OSSL_PARAM params[]) -{ - if (!get_default_sm2_keymgmt().import) { - UADK_ERR("failed to get keymgmt import function\n"); - return UADK_P_FAIL; - } - - return get_default_sm2_keymgmt().import(keydata, selection, params); -} - -/** - * Returns an array of argument types based on the type selected. - * - * @param selection Type of the selected key. - * @return Return param type array. - */ -static const OSSL_PARAM *uadk_keymgmt_sm2_import_types(int selection) -{ - if (!get_default_sm2_keymgmt().import_types) { - UADK_ERR("failed to get keymgmt import_types function\n"); - return NULL; - } - - return get_default_sm2_keymgmt().import_types(selection); -} - -static int uadk_keymgmt_sm2_export(void *keydata, int selection, - OSSL_CALLBACK *param_callback, void *cbarg) -{ - if (!get_default_sm2_keymgmt().export_fun) { - UADK_ERR("failed to get keymgmt export function\n"); - return UADK_P_FAIL; - } - - return get_default_sm2_keymgmt().export_fun(keydata, selection, param_callback, cbarg); -} - -static const OSSL_PARAM *uadk_keymgmt_sm2_export_types(int selection) -{ - if (!get_default_sm2_keymgmt().export_types) { - UADK_ERR("failed to get keymgmt export_types function\n"); - return NULL; - } - - return get_default_sm2_keymgmt().export_types(selection); -} - -static void *uadk_keymgmt_sm2_dup(const void *keydata_from, int selection) -{ - if (!get_default_sm2_keymgmt().dup) { - UADK_ERR("failed to get keymgmt dup function\n"); - return NULL; - } - - return get_default_sm2_keymgmt().dup(keydata_from, selection); -} - -/** - * Init sm2 key generation context. - * - * @param provctx The provider context. - * @param selection The selected params related to the key. - * @param params OSSL params. - * @return Return inited key generation context if success, return NULL if failed. - */ -static void *uadk_keymgmt_sm2_gen_init(void *provctx, int selection, - const OSSL_PARAM params[]) -{ - if (!get_default_sm2_keymgmt().gen_init) { - UADK_ERR("failed to get keymgmt gen_init function\n"); - return NULL; - } - - return get_default_sm2_keymgmt().gen_init(provctx, selection, params); -} - -/** - * Set sm2 key params - * - * @param genctx The pkey generation context. - * @param params OSSL params array. - * @return Return 1 if success, return 0 if failed. - */ -static int uadk_keymgmt_sm2_gen_set_params(void *genctx, const OSSL_PARAM params[]) -{ - if (!get_default_sm2_keymgmt().gen_set_params) { - UADK_ERR("failed to get keymgmt gen_set_params function\n"); - return UADK_P_FAIL; - } - - return get_default_sm2_keymgmt().gen_set_params(genctx, params); -} - -static const OSSL_PARAM *uadk_keymgmt_sm2_settable_params(ossl_unused void *provctx) -{ - if (!get_default_sm2_keymgmt().settable_params) { - UADK_ERR("failed to get keymgmt settable_params function\n"); - return NULL; - } - - return get_default_sm2_keymgmt().settable_params(provctx); -} - -/** - * Get the settable params list. - * - * @param genctx key generation context. - * @param provctx provider context. - * @return Return params list if success, return NULL if failed. - */ -static const OSSL_PARAM *uadk_keymgmt_sm2_gen_settable_params(ossl_unused void *genctx, - ossl_unused void *provctx) -{ - if (!get_default_sm2_keymgmt().gen_settable_params) { - UADK_ERR("failed to get keymgmt gen_settable_params function\n"); - return NULL; - } - - return get_default_sm2_keymgmt().gen_settable_params(genctx, provctx); -} - -static int uadk_prov_sm2_keygen_init_iot(handle_t sess, struct wd_ecc_req *req) -{ - struct wd_ecc_out *ecc_out = wd_sm2_new_kg_out(sess); - - if (ecc_out == NULL) { - UADK_ERR("failed to new sign out\n"); - return UADK_P_FAIL; - } - - uadk_prov_ecc_fill_req(req, WD_SM2_KG, NULL, ecc_out); - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_set_key_to_ec_key(EC_KEY *ec, struct wd_ecc_req *req) -{ - unsigned char key_buff[ECC_POINT_SIZE(SM2_KEY_BYTES) + 1] = {0}; - struct wd_ecc_point *pubkey = NULL; - struct wd_dtb *privkey = NULL; - int x_offset, y_offset, ret; - const EC_GROUP *group; - EC_POINT *point, *ptr; - BIGNUM *bn_key; - - wd_sm2_get_kg_out_params(req->dst, &privkey, &pubkey); - if (privkey == NULL || pubkey == NULL) { - UADK_ERR("failed to get privkey or pubkey\n"); - return UADK_P_FAIL; - } - - if (pubkey->x.dsize > SM2_KEY_BYTES || pubkey->y.dsize > SM2_KEY_BYTES) { - UADK_ERR("invalid pubkey size: %u, %u\n", pubkey->x.dsize, pubkey->y.dsize); - return UADK_P_FAIL; - } - - bn_key = BN_bin2bn((unsigned char *)privkey->data, privkey->dsize, NULL); - ret = EC_KEY_set_private_key(ec, bn_key); - BN_free(bn_key); - if (ret == 0) { - UADK_ERR("failed to EC KEY set private key\n"); - return UADK_P_FAIL; - } - - group = EC_KEY_get0_group(ec); - point = EC_POINT_new(group); - if (point == NULL) { - UADK_ERR("failed to EC POINT new\n"); - return UADK_P_FAIL; - } - - key_buff[0] = UADK_OCTET_STRING; - /* The component of sm2 pubkey need a SM2_KEY_BYTES align */ - x_offset = 1 + SM2_KEY_BYTES - pubkey->x.dsize; - y_offset = 1 + ECC_POINT_SIZE(SM2_KEY_BYTES) - pubkey->y.dsize; - memcpy(key_buff + x_offset, pubkey->x.data, pubkey->x.dsize); - memcpy(key_buff + y_offset, pubkey->y.data, pubkey->y.dsize); - bn_key = BN_bin2bn(key_buff, ECC_POINT_SIZE(SM2_KEY_BYTES) + 1, NULL); - ptr = EC_POINT_bn2point(group, bn_key, point, NULL); - BN_free(bn_key); - if (ptr == NULL) { - UADK_ERR("failed to EC_POINT_bn2point\n"); - EC_POINT_free(point); - return UADK_P_FAIL; - } - - ret = EC_KEY_set_public_key(ec, point); - EC_POINT_free(point); - if (ret == 0) { - UADK_ERR("failed to EC_KEY_set_public_key\n"); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_check_priv_key(EC_KEY *eckey) -{ - BIGNUM *priv_key; - int ret; - - priv_key = (BIGNUM *)EC_KEY_get0_private_key(eckey); - if (priv_key) - return UADK_P_SUCCESS; - - priv_key = BN_new(); - if (priv_key == NULL) { - UADK_ERR("failed to BN_new priv_key\n"); - return UADK_P_FAIL; - } - - ret = EC_KEY_set_private_key(eckey, priv_key); - if (ret == 0) - UADK_ERR("failed to set private key\n"); - - BN_free(priv_key); - - return ret; -} - -static int uadk_prov_sm2_keygen(EC_KEY *eckey) -{ - struct wd_ecc_req req = {0}; - handle_t sess; - int ret; - - ret = uadk_prov_sm2_check_priv_key(eckey); - if (ret == UADK_P_FAIL) - goto error; - - sess = uadk_prov_ecc_alloc_sess(eckey, "sm2"); - if (sess == (handle_t)0) - goto error; - - ret = uadk_prov_sm2_keygen_init_iot(sess, &req); - if (ret == UADK_P_FAIL) - goto free_sess; - - ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); - if (ret == UADK_P_FAIL) - goto uninit_iot; - - ret = uadk_prov_sm2_set_key_to_ec_key(eckey, &req); - if (ret == UADK_P_FAIL) - goto uninit_iot; - - wd_ecc_del_out(sess, req.dst); - wd_ecc_free_sess(sess); - - return UADK_P_SUCCESS; - -uninit_iot: - wd_ecc_del_out(sess, req.dst); -free_sess: - wd_ecc_free_sess(sess); -error: - return UADK_P_FAIL; -} - -static void *uadk_keymgmt_sm2_gen_sw(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) -{ - if (!uadk_get_sw_offload_state()) - return NULL; - - if (!get_default_sm2_keymgmt().gen) { - UADK_ERR("failed to get keymgmt gen function\n"); - return NULL; - } - - UADK_INFO("switch to software sm2 keygen.\n"); - return get_default_sm2_keymgmt().gen(genctx, osslcb, cbarg); -} - -/** - * @brief Generate SM2 key pair. - * - * @param genctx Key generation context. - * @param osslcb Callback function. - * @param cbarg The param of callback function. - * - * @return Return generated key pair if success, return NULL if failed. - */ -static void *uadk_keymgmt_sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) -{ - struct ec_gen_ctx *gctx = genctx; - EC_KEY *ec; - int ret; - - if (gctx == NULL) { - UADK_ERR("invalid: the generation context is NULL\n"); - return NULL; - } - - ec = EC_KEY_new_ex(gctx->libctx, NULL); - if (ec == NULL) { - UADK_ERR("failed to EC_KEY_new_ex\n"); - return NULL; - } - - ret = uadk_prov_ecc_genctx_check(genctx, ec); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to check genctx\n"); - goto free_ec_key; - } - - ret = uadk_prov_keymgmt_get_support_state(KEYMGMT_SM2); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to get hardware sm2 keygen support\n"); - goto do_soft; - } - - /* SM2 hardware init */ - ret = uadk_prov_ecc_init("sm2"); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to init sm2\n"); - goto do_soft; - } - - /* Do sm2 keygen with hardware */ - if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) { - UADK_ERR("invalid keymgmt keypair selection\n"); - goto free_ec_key; - } - - ret = uadk_prov_sm2_keygen(ec); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to generate sm2 key\n"); - goto do_soft; - } - - return ec; - -do_soft: - EC_KEY_free(ec); - return uadk_keymgmt_sm2_gen_sw(genctx, osslcb, cbarg); -free_ec_key: - /* Something went wrong, throw the key away */ - EC_KEY_free(ec); - return NULL; -} - static UADK_PKEY_SIGNATURE get_default_sm2_signature(void) { return s_signature; diff --git a/src/uadk_prov_sm2_kmgmt.c b/src/uadk_prov_sm2_kmgmt.c new file mode 100644 index 00000000..7bd7c206 --- /dev/null +++ b/src/uadk_prov_sm2_kmgmt.c @@ -0,0 +1,538 @@ +// 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 +#include +#include +#include +#include +#include "uadk_prov.h" +#include "uadk_prov_pkey.h" +#include "uadk_utils.h" + +#define SM2_KEY_BYTES 32 + +UADK_PKEY_KEYMGMT_DESCR(sm2, SM2); +static UADK_PKEY_KEYMGMT s_keymgmt; + +static UADK_PKEY_KEYMGMT get_default_sm2_keymgmt(void) +{ + return s_keymgmt; +} + +void set_default_sm2_keymgmt(void) +{ + UADK_PKEY_KEYMGMT *keymgmt; + + keymgmt = (UADK_PKEY_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "SM2", "provider=default"); + if (keymgmt) { + s_keymgmt = *keymgmt; + EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); + } else { + UADK_INFO("failed to EVP_KEYMGMT_fetch sm2 default provider\n"); + } +} + +static const char *uadk_keymgmt_sm2_query_operation_name(int operation_id) +{ + if (!get_default_sm2_keymgmt().query_operation_name) { + UADK_ERR("failed to get keymgmt query_operation_name function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().query_operation_name(operation_id); +} + +/** + * Create an uadk provider side sm2 key object. + * + * @param provctx The provider context. + * @return Return created key object if success, return NULL if failed. + */ +static void *uadk_keymgmt_sm2_new(void *provctx) +{ + if (!get_default_sm2_keymgmt().new_fun) { + UADK_ERR("failed to get keymgmt new function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().new_fun(provctx); +} + +/** + * Release an uadk provider side sm2 key object + * + * @param keydata Key object related data. + */ +static void uadk_keymgmt_sm2_free(void *keydata) +{ + if (!get_default_sm2_keymgmt().free) { + UADK_ERR("failed to get keymgmt free function\n"); + return; + } + + get_default_sm2_keymgmt().free(keydata); +} + +static int uadk_keymgmt_sm2_get_params(void *key, OSSL_PARAM params[]) +{ + if (!get_default_sm2_keymgmt().get_params) { + UADK_ERR("failed to get keymgmt get_params function\n"); + return UADK_P_FAIL; + } + + return get_default_sm2_keymgmt().get_params(key, params); +} + +static const OSSL_PARAM *uadk_keymgmt_sm2_gettable_params(void *provctx) +{ + if (!get_default_sm2_keymgmt().gettable_params) { + UADK_ERR("failed to get keymgmt gettable_params function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().gettable_params(provctx); +} + +static int uadk_keymgmt_sm2_set_params(void *key, const OSSL_PARAM params[]) +{ + if (!get_default_sm2_keymgmt().set_params) { + UADK_ERR("failed to get keymgmt set_params function\n"); + return UADK_P_FAIL; + } + + return get_default_sm2_keymgmt().set_params(key, params); +} + +static int uadk_keymgmt_sm2_gen_set_template(void *genctx, void *templates) +{ + if (!get_default_sm2_keymgmt().gen_set_template) { + UADK_ERR("failed to get keymgmt gen_set_template function\n"); + return UADK_P_FAIL; + } + + return get_default_sm2_keymgmt().gen_set_template(genctx, templates); +} + +static void uadk_keymgmt_sm2_gen_cleanup(void *genctx) +{ + if (!get_default_sm2_keymgmt().gen_cleanup) { + UADK_ERR("failed to get keymgmt gen_cleanup function\n"); + return; + } + + get_default_sm2_keymgmt().gen_cleanup(genctx); +} + +static void *uadk_keymgmt_sm2_load(const void *reference, size_t reference_sz) +{ + if (!get_default_sm2_keymgmt().load) { + UADK_ERR("failed to get keymgmt load function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().load(reference, reference_sz); +} + +static int uadk_keymgmt_sm2_validate(const void *keydata, int selection, int checktype) +{ + if (!get_default_sm2_keymgmt().validate) { + UADK_ERR("failed to get keymgmt validate function\n"); + return UADK_P_FAIL; + } + + return get_default_sm2_keymgmt().validate(keydata, selection, checktype); +} + +static int uadk_keymgmt_sm2_match(const void *keydata1, const void *keydata2, int selection) +{ + if (!get_default_sm2_keymgmt().match) { + UADK_ERR("failed to get keymgmt validate function\n"); + return UADK_P_FAIL; + } + + return get_default_sm2_keymgmt().match(keydata1, keydata2, selection); +} + +/** + * Check if a sm2 key object has specific options, such as public key, + * private key, domain params etc. + * + * @param keydata The key object to check. + * @param selection Check options, like public key, private key, domain params etc. + * @return Return 1 if success, return 0 if failed. + */ +static int uadk_keymgmt_sm2_has(const void *keydata, int selection) +{ + if (!get_default_sm2_keymgmt().has) { + UADK_ERR("failed to get keymgmt has function\n"); + return UADK_P_FAIL; + } + + return get_default_sm2_keymgmt().has(keydata, selection); +} + +/** + * Import a sm2 key object with key related params. + * + * @param keydata The key object to import. + * @param selection The key params to import. + * @param params OSSL params. + * @return Return 1 if success, return 0 if failed. + */ +static int uadk_keymgmt_sm2_import(void *keydata, int selection, const OSSL_PARAM params[]) +{ + if (!get_default_sm2_keymgmt().import) { + UADK_ERR("failed to get keymgmt import function\n"); + return UADK_P_FAIL; + } + + return get_default_sm2_keymgmt().import(keydata, selection, params); +} + +/** + * Returns an array of argument types based on the type selected. + * + * @param selection Type of the selected key. + * @return Return param type array. + */ +static const OSSL_PARAM *uadk_keymgmt_sm2_import_types(int selection) +{ + if (!get_default_sm2_keymgmt().import_types) { + UADK_ERR("failed to get keymgmt import_types function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().import_types(selection); +} + +static int uadk_keymgmt_sm2_export(void *keydata, int selection, + OSSL_CALLBACK *param_callback, void *cbarg) +{ + if (!get_default_sm2_keymgmt().export_fun) { + UADK_ERR("failed to get keymgmt export function\n"); + return UADK_P_FAIL; + } + + return get_default_sm2_keymgmt().export_fun(keydata, selection, param_callback, cbarg); +} + +static const OSSL_PARAM *uadk_keymgmt_sm2_export_types(int selection) +{ + if (!get_default_sm2_keymgmt().export_types) { + UADK_ERR("failed to get keymgmt export_types function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().export_types(selection); +} + +static void *uadk_keymgmt_sm2_dup(const void *keydata_from, int selection) +{ + if (!get_default_sm2_keymgmt().dup) { + UADK_ERR("failed to get keymgmt dup function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().dup(keydata_from, selection); +} + +/** + * Init sm2 key generation context. + * + * @param provctx The provider context. + * @param selection The selected params related to the key. + * @param params OSSL params. + * @return Return inited key generation context if success, return NULL if failed. + */ +static void *uadk_keymgmt_sm2_gen_init(void *provctx, int selection, + const OSSL_PARAM params[]) +{ + if (!get_default_sm2_keymgmt().gen_init) { + UADK_ERR("failed to get keymgmt gen_init function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().gen_init(provctx, selection, params); +} + +/** + * Set sm2 key params + * + * @param genctx The pkey generation context. + * @param params OSSL params array. + * @return Return 1 if success, return 0 if failed. + */ +static int uadk_keymgmt_sm2_gen_set_params(void *genctx, const OSSL_PARAM params[]) +{ + if (!get_default_sm2_keymgmt().gen_set_params) { + UADK_ERR("failed to get keymgmt gen_set_params function\n"); + return UADK_P_FAIL; + } + + return get_default_sm2_keymgmt().gen_set_params(genctx, params); +} + +static const OSSL_PARAM *uadk_keymgmt_sm2_settable_params(ossl_unused void *provctx) +{ + if (!get_default_sm2_keymgmt().settable_params) { + UADK_ERR("failed to get keymgmt settable_params function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().settable_params(provctx); +} + +/** + * Get the settable params list. + * + * @param genctx key generation context. + * @param provctx provider context. + * @return Return params list if success, return NULL if failed. + */ +static const OSSL_PARAM *uadk_keymgmt_sm2_gen_settable_params(ossl_unused void *genctx, + ossl_unused void *provctx) +{ + if (!get_default_sm2_keymgmt().gen_settable_params) { + UADK_ERR("failed to get keymgmt gen_settable_params function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().gen_settable_params(genctx, provctx); +} + +static int uadk_prov_sm2_set_key_to_ec_key(EC_KEY *ec, struct wd_ecc_req *req) +{ + unsigned char key_buff[ECC_POINT_SIZE(SM2_KEY_BYTES) + 1] = {0}; + struct wd_ecc_point *pubkey = NULL; + struct wd_dtb *privkey = NULL; + int x_offset, y_offset, ret; + const EC_GROUP *group; + EC_POINT *point, *ptr; + BIGNUM *bn_key; + + wd_sm2_get_kg_out_params(req->dst, &privkey, &pubkey); + if (privkey == NULL || pubkey == NULL) { + UADK_ERR("failed to get privkey or pubkey\n"); + return UADK_P_FAIL; + } + + if (pubkey->x.dsize > SM2_KEY_BYTES || pubkey->y.dsize > SM2_KEY_BYTES) { + UADK_ERR("invalid pubkey size: %u, %u\n", pubkey->x.dsize, pubkey->y.dsize); + return UADK_P_FAIL; + } + + bn_key = BN_bin2bn((unsigned char *)privkey->data, privkey->dsize, NULL); + ret = EC_KEY_set_private_key(ec, bn_key); + BN_free(bn_key); + if (ret == 0) { + UADK_ERR("failed to EC KEY set private key\n"); + return UADK_P_FAIL; + } + + group = EC_KEY_get0_group(ec); + point = EC_POINT_new(group); + if (point == NULL) { + UADK_ERR("failed to EC POINT new\n"); + return UADK_P_FAIL; + } + + key_buff[0] = UADK_OCTET_STRING; + /* The component of sm2 pubkey need a SM2_KEY_BYTES align */ + x_offset = 1 + SM2_KEY_BYTES - pubkey->x.dsize; + y_offset = 1 + ECC_POINT_SIZE(SM2_KEY_BYTES) - pubkey->y.dsize; + memcpy(key_buff + x_offset, pubkey->x.data, pubkey->x.dsize); + memcpy(key_buff + y_offset, pubkey->y.data, pubkey->y.dsize); + bn_key = BN_bin2bn(key_buff, ECC_POINT_SIZE(SM2_KEY_BYTES) + 1, NULL); + ptr = EC_POINT_bn2point(group, bn_key, point, NULL); + BN_free(bn_key); + if (ptr == NULL) { + UADK_ERR("failed to EC_POINT_bn2point\n"); + EC_POINT_free(point); + return UADK_P_FAIL; + } + + ret = EC_KEY_set_public_key(ec, point); + EC_POINT_free(point); + if (ret == 0) { + UADK_ERR("failed to EC_KEY_set_public_key\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static int uadk_prov_sm2_keygen_init_iot(handle_t sess, struct wd_ecc_req *req) +{ + struct wd_ecc_out *ecc_out = wd_sm2_new_kg_out(sess); + + if (ecc_out == NULL) { + UADK_ERR("failed to new sign out\n"); + return UADK_P_FAIL; + } + + uadk_prov_ecc_fill_req(req, WD_SM2_KG, NULL, ecc_out); + + return UADK_P_SUCCESS; +} + +static int uadk_prov_sm2_check_priv_key(EC_KEY *eckey) +{ + BIGNUM *priv_key; + int ret; + + priv_key = (BIGNUM *)EC_KEY_get0_private_key(eckey); + if (priv_key) + return UADK_P_SUCCESS; + + priv_key = BN_new(); + if (!priv_key) { + UADK_ERR("failed to BN_new priv_key\n"); + return UADK_P_FAIL; + } + + ret = EC_KEY_set_private_key(eckey, priv_key); + if (ret == 0) + UADK_ERR("failed to set private key\n"); + + BN_free(priv_key); + + return ret; +} + +static int uadk_prov_sm2_keygen(EC_KEY *eckey) +{ + struct wd_ecc_req req = {0}; + handle_t sess; + int ret; + + ret = uadk_prov_sm2_check_priv_key(eckey); + if (ret == UADK_P_FAIL) + goto error; + + sess = uadk_prov_ecc_alloc_sess(eckey, "sm2"); + if (sess == (handle_t)0) + goto error; + + ret = uadk_prov_sm2_keygen_init_iot(sess, &req); + if (ret == UADK_P_FAIL) + goto free_sess; + + ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); + if (ret == UADK_P_FAIL) + goto uninit_iot; + + ret = uadk_prov_sm2_set_key_to_ec_key(eckey, &req); + if (ret == UADK_P_FAIL) + goto uninit_iot; + + wd_ecc_del_out(sess, req.dst); + wd_ecc_free_sess(sess); + + return UADK_P_SUCCESS; + +uninit_iot: + wd_ecc_del_out(sess, req.dst); +free_sess: + wd_ecc_free_sess(sess); +error: + return UADK_P_FAIL; +} + +static void *uadk_keymgmt_sm2_gen_sw(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) +{ + if (!uadk_get_sw_offload_state()) + return NULL; + + if (!get_default_sm2_keymgmt().gen) { + UADK_ERR("failed to get keymgmt gen function\n"); + return NULL; + } + + UADK_INFO("switch to software sm2 keygen.\n"); + return get_default_sm2_keymgmt().gen(genctx, osslcb, cbarg); +} + +/** + * @brief Generate SM2 key pair. + * + * @param genctx Key generation context. + * @param osslcb Callback function. + * @param cbarg The param of callback function. + * + * @return Return generated key pair if success, return NULL if failed. + */ +static void *uadk_keymgmt_sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) +{ + struct ec_gen_ctx *gctx = genctx; + EC_KEY *ec; + int ret; + + if (gctx == NULL) { + UADK_ERR("invalid: the generation context is NULL\n"); + return NULL; + } + + ec = EC_KEY_new_ex(gctx->libctx, NULL); + if (ec == NULL) { + UADK_ERR("failed to EC_KEY_new_ex\n"); + return NULL; + } + + ret = uadk_prov_ecc_genctx_check(genctx, ec); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to check genctx\n"); + goto free_ec_key; + } + + ret = uadk_prov_keymgmt_get_support_state(KEYMGMT_SM2); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to get hardware sm2 keygen support\n"); + goto do_soft; + } + + /* SM2 hardware init */ + ret = uadk_prov_ecc_init("sm2"); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to init sm2\n"); + goto do_soft; + } + + /* Do sm2 keygen with hardware */ + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) { + UADK_ERR("invalid keymgmt keypair selection\n"); + goto free_ec_key; + } + + ret = uadk_prov_sm2_keygen(ec); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to generate sm2 key\n"); + goto do_soft; + } + + return ec; + +do_soft: + EC_KEY_free(ec); + return uadk_keymgmt_sm2_gen_sw(genctx, osslcb, cbarg); +free_ec_key: + /* Something went wrong, throw the key away */ + EC_KEY_free(ec); + return NULL; +} From 5077b23b36639acd0f419d0e616718292673770b Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 07/16] uadk_provider/sm2: modify the return value of keygen If the user has not set to retrieve the public and private keys, return ec key directly instead of a null pointer to avoid failure when using ec key. Signed-off-by: Weili Qian --- src/uadk_prov_sm2_kmgmt.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/uadk_prov_sm2_kmgmt.c b/src/uadk_prov_sm2_kmgmt.c index 7bd7c206..cf62677b 100644 --- a/src/uadk_prov_sm2_kmgmt.c +++ b/src/uadk_prov_sm2_kmgmt.c @@ -501,6 +501,10 @@ static void *uadk_keymgmt_sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba goto free_ec_key; } + /* If there is no need to generate the private and public keys, return directly. */ + if (!gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) + return ec; + ret = uadk_prov_keymgmt_get_support_state(KEYMGMT_SM2); if (ret == UADK_P_FAIL) { UADK_ERR("failed to get hardware sm2 keygen support\n"); @@ -514,12 +518,6 @@ static void *uadk_keymgmt_sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba goto do_soft; } - /* Do sm2 keygen with hardware */ - if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) { - UADK_ERR("invalid keymgmt keypair selection\n"); - goto free_ec_key; - } - ret = uadk_prov_sm2_keygen(ec); if (ret == UADK_P_FAIL) { UADK_ERR("failed to generate sm2 key\n"); From 19b4210034e8dece8da996e7e8b2ac3d43a17bc1 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 08/16] uadk_provider/sm2: remove unnecessary code The implementation in uadk_prov_sm2_check_priv_key() is meaningless, remove it. Signed-off-by: Weili Qian --- src/uadk_prov_sm2_kmgmt.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/src/uadk_prov_sm2_kmgmt.c b/src/uadk_prov_sm2_kmgmt.c index cf62677b..2f6e2340 100644 --- a/src/uadk_prov_sm2_kmgmt.c +++ b/src/uadk_prov_sm2_kmgmt.c @@ -392,43 +392,15 @@ static int uadk_prov_sm2_keygen_init_iot(handle_t sess, struct wd_ecc_req *req) return UADK_P_SUCCESS; } -static int uadk_prov_sm2_check_priv_key(EC_KEY *eckey) -{ - BIGNUM *priv_key; - int ret; - - priv_key = (BIGNUM *)EC_KEY_get0_private_key(eckey); - if (priv_key) - return UADK_P_SUCCESS; - - priv_key = BN_new(); - if (!priv_key) { - UADK_ERR("failed to BN_new priv_key\n"); - return UADK_P_FAIL; - } - - ret = EC_KEY_set_private_key(eckey, priv_key); - if (ret == 0) - UADK_ERR("failed to set private key\n"); - - BN_free(priv_key); - - return ret; -} - static int uadk_prov_sm2_keygen(EC_KEY *eckey) { struct wd_ecc_req req = {0}; handle_t sess; int ret; - ret = uadk_prov_sm2_check_priv_key(eckey); - if (ret == UADK_P_FAIL) - goto error; - sess = uadk_prov_ecc_alloc_sess(eckey, "sm2"); if (sess == (handle_t)0) - goto error; + return UADK_P_FAIL; ret = uadk_prov_sm2_keygen_init_iot(sess, &req); if (ret == UADK_P_FAIL) @@ -451,7 +423,6 @@ static int uadk_prov_sm2_keygen(EC_KEY *eckey) wd_ecc_del_out(sess, req.dst); free_sess: wd_ecc_free_sess(sess); -error: return UADK_P_FAIL; } From 13eeb238d19aa2037b75219e0786d2e3723e3cfd Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 09/16] uadk_engine/ecc: remove unnecessary code The implementation in eckey_create_key() is meaningless, remove it. Signed-off-by: Weili Qian --- src/uadk_ec.c | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/src/uadk_ec.c b/src/uadk_ec.c index eac59b5d..fb83db67 100644 --- a/src/uadk_ec.c +++ b/src/uadk_ec.c @@ -880,39 +880,11 @@ static int sm2_keygen_init_iot(handle_t sess, struct wd_ecc_req *req) return 0; } -static int eckey_create_key(EC_KEY *eckey) -{ - BIGNUM *priv_key; - int ret; - - priv_key = (BIGNUM *)EC_KEY_get0_private_key(eckey); - if (priv_key) - return 1; - - priv_key = BN_new(); - if (!priv_key) { - fprintf(stderr, "failed to BN_new priv_key\n"); - return 0; - } - - ret = EC_KEY_set_private_key(eckey, priv_key); - if (!ret) - fprintf(stderr, "failed to set private key\n"); - - BN_free(priv_key); - - return ret; -} - static int ecdh_set_private_key(EC_KEY *eckey, BIGNUM *order) { BIGNUM *priv_key; int ret; - priv_key = (BIGNUM *)EC_KEY_get0_private_key(eckey); - if (priv_key) - return 1; - priv_key = BN_new(); if (!priv_key) { fprintf(stderr, "failed to BN_new priv_key\n"); @@ -987,10 +959,6 @@ static int sm2_generate_key(EC_KEY *eckey) if (ret) goto soft_log; - ret = eckey_create_key(eckey); - if (!ret) - goto soft_log; - ret = uadk_e_ecc_get_support_state(SM2_SUPPORT); if (!ret) goto soft_log; From 3a48b9ee18a3b02aa0caa4b9060bf851dba7d13c Mon Sep 17 00:00:00 2001 From: Zhushuai Yin Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 10/16] uadk_provider: delete asynchronous redundancy declaration The `async_poll_task_free()` function has been renamed, but its declaration was not removed. The redundant declaration needs to be deleted. Signed-off-by: Zhushuai Yin --- src/uadk_async.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/uadk_async.h b/src/uadk_async.h index 4aebf055..e35d2864 100644 --- a/src/uadk_async.h +++ b/src/uadk_async.h @@ -87,6 +87,5 @@ void async_module_uninit(void); int async_wake_job(ASYNC_JOB *job); void async_free_poll_task(int id, bool is_cb); int async_get_free_task(int *id); -void async_poll_task_free(void); ASYNC_JOB *async_get_async_job(void); #endif From 59c3b348f256b8147bd4d5db95b376110848c6a2 Mon Sep 17 00:00:00 2001 From: lizhi Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 11/16] uadk_provider: adapt uadk provider with tls 1.3 Add support for OSSL_FUNC_PROVIDER_GET_CAPABILITIES to enable TLS 1.3 compatibility. Signed-off-by: lizhi --- src/Makefile.am | 1 + src/uadk_prov.h | 3 + src/uadk_prov_capabilities.c | 224 +++++++++++++++++++++++++++++++++++ src/uadk_prov_ecx.c | 28 ++--- src/uadk_prov_init.c | 2 +- 5 files changed, 238 insertions(+), 20 deletions(-) create mode 100644 src/uadk_prov_capabilities.c diff --git a/src/Makefile.am b/src/Makefile.am index 6b035cc2..7c1e1c50 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,6 +61,7 @@ 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_capabilities.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 \ diff --git a/src/uadk_prov.h b/src/uadk_prov.h index 62a26fea..60031cb1 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -17,6 +17,7 @@ */ #ifndef UADK_PROV_H #define UADK_PROV_H +#include #include #define FUNC_MAX_NUM 32 @@ -45,6 +46,8 @@ #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" +OSSL_FUNC_provider_get_capabilities_fn uadk_get_capabilities; + enum HW_SYMM_ENC_DEV { HW_SYMM_ENC_INVALID = 0x0, HW_SYMM_ENC_V2 = 0x2, diff --git a/src/uadk_prov_capabilities.c b/src/uadk_prov_capabilities.c new file mode 100644 index 00000000..18d29036 --- /dev/null +++ b/src/uadk_prov_capabilities.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#include +#include +#include +#include +/* For TLS1_VERSION etc */ +#include +#include +#include "uadk_prov.h" + +# define OSSL_TLS_GROUP_ID_sect163k1 0x0001 +# define OSSL_TLS_GROUP_ID_sect163r1 0x0002 +# define OSSL_TLS_GROUP_ID_sect163r2 0x0003 +# define OSSL_TLS_GROUP_ID_sect193r1 0x0004 +# define OSSL_TLS_GROUP_ID_sect193r2 0x0005 +# define OSSL_TLS_GROUP_ID_sect233k1 0x0006 +# define OSSL_TLS_GROUP_ID_sect233r1 0x0007 +# define OSSL_TLS_GROUP_ID_sect239k1 0x0008 +# define OSSL_TLS_GROUP_ID_sect283k1 0x0009 +# define OSSL_TLS_GROUP_ID_sect283r1 0x000A +# define OSSL_TLS_GROUP_ID_sect409k1 0x000B +# define OSSL_TLS_GROUP_ID_sect409r1 0x000C +# define OSSL_TLS_GROUP_ID_sect571k1 0x000D +# define OSSL_TLS_GROUP_ID_sect571r1 0x000E +# define OSSL_TLS_GROUP_ID_secp160k1 0x000F +# define OSSL_TLS_GROUP_ID_secp160r1 0x0010 +# define OSSL_TLS_GROUP_ID_secp160r2 0x0011 +# define OSSL_TLS_GROUP_ID_secp192k1 0x0012 +# define OSSL_TLS_GROUP_ID_secp192r1 0x0013 +# define OSSL_TLS_GROUP_ID_secp224k1 0x0014 +# define OSSL_TLS_GROUP_ID_secp224r1 0x0015 +# define OSSL_TLS_GROUP_ID_secp256k1 0x0016 +# define OSSL_TLS_GROUP_ID_secp256r1 0x0017 +# define OSSL_TLS_GROUP_ID_secp384r1 0x0018 +# define OSSL_TLS_GROUP_ID_secp521r1 0x0019 +# define OSSL_TLS_GROUP_ID_brainpoolP256r1 0x001A +# define OSSL_TLS_GROUP_ID_brainpoolP384r1 0x001B +# define OSSL_TLS_GROUP_ID_brainpoolP512r1 0x001C +# define OSSL_TLS_GROUP_ID_x25519 0x001D +# define OSSL_TLS_GROUP_ID_x448 0x001E +# define OSSL_TLS_GROUP_ID_ffdhe2048 0x0100 +# define OSSL_TLS_GROUP_ID_ffdhe3072 0x0101 +# define OSSL_TLS_GROUP_ID_ffdhe4096 0x0102 +# define OSSL_TLS_GROUP_ID_ffdhe6144 0x0103 +# define OSSL_TLS_GROUP_ID_ffdhe8192 0x0104 +# define OSSL_TLS_GROUP_ID_sm2 0x0029 + +# if !defined(NTLS1_1_VERSION) +/* NTLS version. + * OpenSSL3 doesn't support yet, define to pass the compile. + */ +# define NTLS1_1_VERSION 0x0101 +# endif + +#define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0])) + +struct tls_group_constants_st { + /* Group ID */ + unsigned int group_id; + /* Bits of security */ + unsigned int secbits; + /* Minimum TLS version, -1 unsupported */ + int mintls; + /* Maximum TLS version (or 0 for undefined) */ + int maxtls; + /* Minimum DTLS version, -1 unsupported */ + int mindtls; + /* Maximum DTLS version (or 0 for undefined) */ + int maxdtls; +}; + +static const struct tls_group_constants_st group_list[36] = { + { OSSL_TLS_GROUP_ID_sect163k1, 80, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect163r1, 80, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect163r2, 80, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect193r1, 80, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect193r2, 80, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect233k1, 112, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect233r1, 112, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect239k1, 112, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect283k1, 128, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect283r1, 128, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect409k1, 192, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect409r1, 192, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect571k1, 256, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_sect571r1, 256, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_secp160k1, 80, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_secp160r1, 80, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_secp160r2, 80, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_secp192k1, 80, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_secp192r1, 80, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_secp224k1, 112, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_secp224r1, 112, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_secp256k1, 128, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_secp256r1, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0 }, + { OSSL_TLS_GROUP_ID_secp384r1, 192, TLS1_VERSION, 0, DTLS1_VERSION, 0 }, + { OSSL_TLS_GROUP_ID_secp521r1, 256, TLS1_VERSION, 0, DTLS1_VERSION, 0 }, + { OSSL_TLS_GROUP_ID_brainpoolP256r1, 128, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_brainpoolP384r1, 192, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_brainpoolP512r1, 256, TLS1_VERSION, TLS1_2_VERSION, + DTLS1_VERSION, DTLS1_2_VERSION }, + { OSSL_TLS_GROUP_ID_x25519, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0 }, + { OSSL_TLS_GROUP_ID_x448, 224, TLS1_VERSION, 0, DTLS1_VERSION, 0 }, + /* Security bit values as given by BN_security_bits() */ + { OSSL_TLS_GROUP_ID_ffdhe2048, 112, TLS1_3_VERSION, 0, -1, -1 }, + { OSSL_TLS_GROUP_ID_ffdhe3072, 128, TLS1_3_VERSION, 0, -1, -1 }, + { OSSL_TLS_GROUP_ID_ffdhe4096, 128, TLS1_3_VERSION, 0, -1, -1 }, + { OSSL_TLS_GROUP_ID_ffdhe6144, 128, TLS1_3_VERSION, 0, -1, -1 }, + { OSSL_TLS_GROUP_ID_ffdhe8192, 192, TLS1_3_VERSION, 0, -1, -1 }, + { OSSL_TLS_GROUP_ID_sm2, 128, NTLS1_1_VERSION, 0, -1, -1 }, +}; + +#define TLS_GROUP_ENTRY_COMMON(tlsname, realname, algorithm, idx) \ + OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, \ + tlsname, sizeof(tlsname)), \ + OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, \ + realname, sizeof(realname)), \ + OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, \ + algorithm, sizeof(algorithm)), \ + OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, \ + (unsigned int *)&group_list[idx].group_id) + +#define TLS_GROUP_ENTRY_TLS(idx) \ + OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS, \ + (unsigned int *)&group_list[idx].secbits), \ + OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, \ + (unsigned int *)&group_list[idx].mintls), \ + OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, \ + (unsigned int *)&group_list[idx].maxtls) + +#define TLS_GROUP_ENTRY_DTLS(idx) \ + OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, \ + (unsigned int *)&group_list[idx].mindtls), \ + OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, \ + (unsigned int *)&group_list[idx].maxdtls) + +#define TLS_GROUP_ENTRY(tlsname, realname, algorithm, idx) \ +{ \ + TLS_GROUP_ENTRY_COMMON(tlsname, realname, algorithm, idx), \ + TLS_GROUP_ENTRY_TLS(idx), \ + TLS_GROUP_ENTRY_DTLS(idx), \ + OSSL_PARAM_END \ +} + +static const OSSL_PARAM param_group_list[][10] = { + TLS_GROUP_ENTRY("secp256r1", "prime256v1", "EC", 22), + /* Alias of above */ + TLS_GROUP_ENTRY("P-256", "prime256v1", "EC", 22), + TLS_GROUP_ENTRY("secp384r1", "secp384r1", "EC", 23), + /* Alias of above */ + TLS_GROUP_ENTRY("P-384", "secp384r1", "EC", 23), + TLS_GROUP_ENTRY("secp521r1", "secp521r1", "EC", 24), + /* Alias of above */ + TLS_GROUP_ENTRY("P-521", "secp521r1", "EC", 24), + + TLS_GROUP_ENTRY("x25519", "X25519", "X25519", 28), + TLS_GROUP_ENTRY("x448", "X448", "X448", 29), + + /* Security bit values for FFDHE groups are as per RFC 7919 */ + TLS_GROUP_ENTRY("ffdhe2048", "ffdhe2048", "DH", 30), + TLS_GROUP_ENTRY("ffdhe3072", "ffdhe3072", "DH", 31), + TLS_GROUP_ENTRY("ffdhe4096", "ffdhe4096", "DH", 32), + /* + * Note: uadk_provider doesn't support DH with 6144/8192-bit width, + * but can fallback to software computation if needed. + */ + TLS_GROUP_ENTRY("ffdhe6144", "ffdhe6144", "DH", 33), + TLS_GROUP_ENTRY("ffdhe8192", "ffdhe8192", "DH", 34), + + TLS_GROUP_ENTRY("curveSM2", "SM2", "SM2", 35), +}; + +static int tls_group_capability(OSSL_CALLBACK *cb, void *arg) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(param_group_list); i++) + if (!cb(param_group_list[i], arg)) + return UADK_P_FAIL; + + return UADK_P_SUCCESS; +} + +int uadk_get_capabilities(void *provctx, const char *capability, + OSSL_CALLBACK *cb, void *arg) +{ + if (strcasecmp(capability, "TLS-GROUP") == 0) + return tls_group_capability(cb, arg); + + /* We don't support this capability */ + return UADK_P_FAIL; +} diff --git a/src/uadk_prov_ecx.c b/src/uadk_prov_ecx.c index 89b1a243..73538363 100644 --- a/src/uadk_prov_ecx.c +++ b/src/uadk_prov_ecx.c @@ -299,18 +299,12 @@ static const OSSL_PARAM *uadk_keymgmt_x448_gen_settable_params(ossl_unused void static int uadk_keymgmt_x448_gen_set_template(void *genctx, void *templ) { - if (get_default_x448_keymgmt().gen_set_template == NULL) - return UADK_P_FAIL; - - return get_default_x448_keymgmt().gen_set_template(genctx, templ); + return UADK_P_SUCCESS; } static const char *uadk_keymgmt_x448_query_operation_name(int operation_id) { - if (get_default_x448_keymgmt().query_operation_name == NULL) - return NULL; - - return get_default_x448_keymgmt().query_operation_name(operation_id); + return "X448"; } static int ossl_param_build_set_octet_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, @@ -780,7 +774,7 @@ static int uadk_prov_ecx_keygen(PROV_ECX_KEYMGMT_CTX *gctx, ECX_KEY **ecx_key) return UADK_P_FAIL; *ecx_key = uadk_prov_ecx_create_prikey(gctx); - if (*ecx_key == NULL) + if (*ecx_key == NULL || !(gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR)) return UADK_P_FAIL; ret = uadk_prov_ecx_keygen_init_iot(gctx->sess, &req); @@ -895,7 +889,8 @@ static void *uadk_keymgmt_x448_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_par } ret = uadk_prov_ecx_keygen(gctx, &ecx_key); - if (ret != UADK_P_SUCCESS) { + /* Blank key and UADK_P_FAIL in parameter generation is expected, not an error */ + if (ret != UADK_P_SUCCESS && (gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR)) { UADK_ERR("failed to generate x448 key\n"); uadk_prov_ecx_free_sess(gctx->sess); goto exe_soft; @@ -1466,18 +1461,12 @@ static const OSSL_PARAM *uadk_keymgmt_x25519_gen_settable_params(ossl_unused voi static int uadk_keymgmt_x25519_gen_set_template(void *genctx, void *templ) { - if (get_default_x25519_keymgmt().gen_set_template == NULL) - return UADK_P_FAIL; - - return get_default_x25519_keymgmt().gen_set_template(genctx, templ); + return UADK_P_SUCCESS; } static const char *uadk_keymgmt_x25519_query_operation_name(int operation_id) { - if (get_default_x25519_keymgmt().query_operation_name == NULL) - return NULL; - - return get_default_x25519_keymgmt().query_operation_name(operation_id); + return "X25519"; } static int uadk_keymgmt_x25519_get_params(void *key, OSSL_PARAM params[]) @@ -1544,7 +1533,8 @@ static void *uadk_keymgmt_x25519_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_p } ret = uadk_prov_ecx_keygen(gctx, &ecx_key); - if (ret != UADK_P_SUCCESS) { + /* Blank key and UADK_P_FAIL in parameter generation is expected, not an error */ + if (ret != UADK_P_SUCCESS && (gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR)) { UADK_ERR("failed to generate x25519 key\n"); uadk_prov_ecx_free_sess(gctx->sess); goto exe_soft; diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 92ecc686..03a34853 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -843,6 +842,7 @@ static const OSSL_DISPATCH uadk_dispatch_table[] = { { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))uadk_teardown }, { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))uadk_get_params }, { OSSL_FUNC_PROVIDER_UNQUERY_OPERATION, (void (*)(void))uadk_unquery }, + { OSSL_FUNC_PROVIDER_GET_CAPABILITIES, (void (*)(void))uadk_get_capabilities}, { 0, NULL } }; From 0862aaf6f4e57d20a70738aad72f8f51217569dd Mon Sep 17 00:00:00 2001 From: lizhi Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 12/16] uadk_provider: adapt rsa key management with pss padding mode Add support for RSA key management with pss padding mode. Test with: openssl3 genpkey -provider uadk_provider -algorithm RSA-PSS Signed-off-by: lizhi --- src/uadk_prov.h | 2 + src/uadk_prov_init.c | 8 +++- src/uadk_prov_rsa_kmgmt.c | 81 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/uadk_prov.h b/src/uadk_prov.h index 60031cb1..f1628541 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -190,6 +190,7 @@ extern const OSSL_DISPATCH uadk_des_ede3_ecb_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_rsa_signature_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_rsa_keymgmt_functions[FUNC_MAX_NUM]; +extern const OSSL_DISPATCH uadk_rsapss_keymgmt_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_rsa_asym_cipher_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_dh_keymgmt_functions[FUNC_MAX_NUM]; @@ -229,6 +230,7 @@ void set_default_ecdh_keyexch(void); void set_default_ecx_keymgmt(void); void set_default_ecx_keyexch(void); void set_default_rsa_keymgmt(void); +void set_default_rsapss_keymgmt(void); void set_default_rsa_signature(void); void set_default_rsa_asym_cipher(void); void set_default_sm2_asym_cipher(void); diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 03a34853..b5d94e0f 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -288,6 +288,8 @@ static const OSSL_ALGORITHM uadk_prov_signature_v3[] = { static const OSSL_ALGORITHM uadk_prov_keymgmt_v2[] = { { "RSA", UADK_DEFAULT_PROPERTIES, uadk_rsa_keymgmt_functions, "uadk RSA Keymgmt implementation." }, + { "RSA-PSS", UADK_DEFAULT_PROPERTIES, + uadk_rsapss_keymgmt_functions, "uadk RSA-PSS Keymgmt implementation." }, { "DH", UADK_DEFAULT_PROPERTIES, uadk_dh_keymgmt_functions }, { NULL, NULL, NULL, NULL } }; @@ -295,7 +297,10 @@ static const OSSL_ALGORITHM uadk_prov_keymgmt_v2[] = { static const OSSL_ALGORITHM uadk_prov_keymgmt_v3[] = { { "RSA", UADK_DEFAULT_PROPERTIES, uadk_rsa_keymgmt_functions, "uadk RSA Keymgmt implementation." }, - { "DH", UADK_DEFAULT_PROPERTIES, uadk_dh_keymgmt_functions }, + { "RSA-PSS", UADK_DEFAULT_PROPERTIES, + uadk_rsapss_keymgmt_functions, "uadk RSA-PSS Keymgmt implementation." }, + { "DH", UADK_DEFAULT_PROPERTIES, + uadk_dh_keymgmt_functions, "uadk dh Keymgmt implementation." }, { "SM2", UADK_DEFAULT_PROPERTIES, uadk_sm2_keymgmt_functions, "uadk SM2 Keymgmt implementation." }, { "EC", UADK_DEFAULT_PROPERTIES, @@ -674,6 +679,7 @@ static void uadk_set_default_alg(void) set_default_ecx_keymgmt(); set_default_ecx_keyexch(); set_default_rsa_keymgmt(); + set_default_rsapss_keymgmt(); set_default_rsa_asym_cipher(); set_default_rsa_signature(); set_default_sm2_asym_cipher(); diff --git a/src/uadk_prov_rsa_kmgmt.c b/src/uadk_prov_rsa_kmgmt.c index a3cf065b..1286ae52 100644 --- a/src/uadk_prov_rsa_kmgmt.c +++ b/src/uadk_prov_rsa_kmgmt.c @@ -75,12 +75,18 @@ struct rsa_gen_ctx { }; static UADK_PKEY_KEYMGMT s_keymgmt; +static UADK_PKEY_KEYMGMT rsapss_keymgmt; static UADK_PKEY_KEYMGMT get_default_rsa_keymgmt(void) { return s_keymgmt; } +static UADK_PKEY_KEYMGMT get_default_rsapss_keymgmt(void) +{ + return rsapss_keymgmt; +} + void set_default_rsa_keymgmt(void) { UADK_PKEY_KEYMGMT *keymgmt; @@ -94,6 +100,19 @@ void set_default_rsa_keymgmt(void) } } +void set_default_rsapss_keymgmt(void) +{ + UADK_PKEY_KEYMGMT *keymgmt; + + keymgmt = (UADK_PKEY_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "RSA-PSS", "provider=default"); + if (keymgmt) { + rsapss_keymgmt = *keymgmt; + EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); + } else { + UADK_INFO("failed to EVP_KEYMGMT_fetch rsa-pss default provider\n"); + } +} + static void uadk_rsa_clear_flags(RSA *r, int flags) { r->flags &= ~flags; @@ -993,3 +1012,65 @@ static void *uadk_keymgmt_rsa_dup(const void *keydata_from, int selection) return get_default_rsa_keymgmt().dup(keydata_from, selection); } + +static void *uadk_keymgmt_rsapss_new(void *provctx) +{ + if (!get_default_rsapss_keymgmt().new_fun) + return NULL; + + return get_default_rsapss_keymgmt().new_fun(provctx); +} + +static void *uadk_keymgmt_rsapss_gen_init(void *provctx, int selection, + const OSSL_PARAM params[]) +{ + if (!get_default_rsapss_keymgmt().gen_init) + return NULL; + + return get_default_rsapss_keymgmt().gen_init(provctx, selection, params); +} + +static const OSSL_PARAM *uadk_keymgmt_rsapss_gen_settable_params(ossl_unused void *genctx, + ossl_unused void *provctx) +{ + if (!get_default_rsapss_keymgmt().gen_settable_params) + return NULL; + + return get_default_rsapss_keymgmt().gen_settable_params(genctx, provctx); +} + +static void *uadk_keymgmt_rsapss_load(const void *reference, size_t reference_sz) +{ + if (!get_default_rsapss_keymgmt().load) + return NULL; + + return get_default_rsapss_keymgmt().load(reference, reference_sz); +} + +const OSSL_DISPATCH uadk_rsapss_keymgmt_functions[] = { + { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))uadk_keymgmt_rsapss_new }, + { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))uadk_keymgmt_rsa_free }, + { 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_GEN_INIT, (void (*)(void))uadk_keymgmt_rsapss_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_rsapss_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_rsapss_load }, + { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))uadk_keymgmt_rsa_has }, + { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))uadk_keymgmt_rsa_validate }, + { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))uadk_keymgmt_rsa_match }, + { 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_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 }, + { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, + (void (*)(void))uadk_keymgmt_rsa_query_operation_name }, + { 0, NULL } +}; From 6704e3ae49d8eb099e11fc9fc34f94910e9695c6 Mon Sep 17 00:00:00 2001 From: lizhi Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 13/16] uadk_provider: adapt rsa pss key management with algorithm enable configuration Adapt rsa pss key management with algorithm enable configuration. Since RSA and RSA-PSS share a similar implementation, the RSA enable flag also controls the enablement or disablement of the RSA-PSS algorithm. Signed-off-by: lizhi --- src/uadk_prov_init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index b5d94e0f..38d7426b 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -536,6 +536,8 @@ static OSSL_ALGORITHM *uadk_generate_keymgmt_array_v2(void) name = uadk_prov_keymgmt_v2[i].algorithm_names; if (name == NULL || (uadk_prov_alg_en.rsa_en && !strcmp(name, "RSA")) || + /* RSA and RSA-PSS can utilize the same enable flag */ + (uadk_prov_alg_en.rsa_en && !strcmp(name, "RSA-PSS")) || (uadk_prov_alg_en.dh_en && !strcmp(name, "DH"))) memcpy(&keymgmt_array_v2[index++], &uadk_prov_keymgmt_v2[i], sizeof(OSSL_ALGORITHM)); @@ -561,6 +563,7 @@ static OSSL_ALGORITHM *uadk_generate_keymgmt_array_v3(void) name = uadk_prov_keymgmt_v3[i].algorithm_names; if (name == NULL || (uadk_prov_alg_en.rsa_en && !strcmp(name, "RSA")) || + (uadk_prov_alg_en.rsa_en && !strcmp(name, "RSA-PSS")) || (uadk_prov_alg_en.dh_en && !strcmp(name, "DH")) || (uadk_prov_alg_en.sm2_en && !strcmp(name, "SM2")) || (uadk_prov_alg_en.ecdh_en && !strcmp(name, "EC")) || From 3dbaf4e9b7054537d19bea9c7622d86056691b34 Mon Sep 17 00:00:00 2001 From: lizhi Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 14/16] uadk_engine/ecc: fix memory leak in the ecx algorithm Memory alloced in ecx derive function should be released before returning keysize to OpenSSL. Signed-off-by: lizhi --- src/uadk_ecx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/uadk_ecx.c b/src/uadk_ecx.c index c9cc6c06..3e79a546 100644 --- a/src/uadk_ecx.c +++ b/src/uadk_ecx.c @@ -806,6 +806,7 @@ static int ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) if (!key || !(*keylen)) { *keylen = (size_t)derive_ctx->key_size; + ecx_uninit(ctx); return UADK_E_SUCCESS; } From 33258faa9f3d773530e7b4d2869068e28945f3a0 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 15/16] uadk_engine: fix compilation warnings 1. uadk_digest.c:953:1: warning: label 'clear' defined but not used [-Wunused-label]. 2. uadk_cipher_adapter.c:142:5: warning: no previous prototype for 'uadk_e_ciphers' [-Wmissing-prototypes]. 3. uadk_aead.c:335:6: warning: unused variable 'ret' [-Wunused-variable]. 4.uadk_ec.c:499:31: warning: passing argument 2 of 'ecc_alloc_sess' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]. Signed-off-by: Weili Qian --- src/uadk_cipher_adapter.c | 2 +- src/uadk_ec.c | 2 +- src/uadk_prov.h | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/uadk_cipher_adapter.c b/src/uadk_cipher_adapter.c index f2559abe..20e936fb 100644 --- a/src/uadk_cipher_adapter.c +++ b/src/uadk_cipher_adapter.c @@ -139,7 +139,7 @@ static void uadk_e_create_ciphers(int index) } } -int uadk_e_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid) +static int uadk_e_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid) { __u32 i; diff --git a/src/uadk_ec.c b/src/uadk_ec.c index fb83db67..0fbbf463 100644 --- a/src/uadk_ec.c +++ b/src/uadk_ec.c @@ -191,7 +191,7 @@ static int get_smallest_hw_keybits(int bits) return ECC128BITS; } -static handle_t ecc_alloc_sess(const EC_KEY *eckey, char *alg) +static handle_t ecc_alloc_sess(const EC_KEY *eckey, const char *alg) { char buff[UADK_ECC_MAX_KEY_BYTES * UADK_ECC_CV_PARAM_NUM]; struct sched_params sch_p = {0}; diff --git a/src/uadk_prov.h b/src/uadk_prov.h index f1628541..c802c719 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -54,8 +54,6 @@ enum HW_SYMM_ENC_DEV { HW_SYMM_ENC_V3 = 0x3 }; -typedef int CRYPTO_REF_COUNT; - struct ossl_provider_st { /* Flag bits */ unsigned int flag_initialized:1; From 35ff73c9fbc447821445635eeda6482b48145d03 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Thu, 26 Feb 2026 16:45:43 +0800 Subject: [PATCH 16/16] uadk_provider/sm2: split uadk_prov_sm2.c into 2 files Split uadk_prov_sm2.c into 2 files based on the signing/verification and encryption/decryption functionalities to avoid the file being too large. Signed-off-by: Weili Qian --- src/Makefile.am | 3 +- src/uadk_prov_pkey.h | 2 + src/uadk_prov_sm2.c | 2822 ------------------------------------- src/uadk_prov_sm2_enc.c | 860 +++++++++++ src/uadk_prov_sm2_kmgmt.c | 2 - src/uadk_prov_sm2_sign.c | 1342 ++++++++++++++++++ 6 files changed, 2206 insertions(+), 2825 deletions(-) delete mode 100644 src/uadk_prov_sm2.c create mode 100644 src/uadk_prov_sm2_enc.c create mode 100644 src/uadk_prov_sm2_sign.c diff --git a/src/Makefile.am b/src/Makefile.am index 7c1e1c50..d30d599d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -68,7 +68,8 @@ uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.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 uadk_prov_sm2_kmgmt.c \ + uadk_prov_pkey.c uadk_prov_sm2_sign.c \ + uadk_prov_sm2_kmgmt.c uadk_prov_sm2_enc.c \ uadk_prov_ffc.c uadk_prov_aead.c \ uadk_prov_ec_kmgmt.c uadk_prov_ecdh_exch.c \ uadk_prov_ecx.c uadk_prov_ecdsa.c \ diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index 7a77c5c0..e82df345 100644 --- a/src/uadk_prov_pkey.h +++ b/src/uadk_prov_pkey.h @@ -61,6 +61,8 @@ #define GET_MS_BYTE(n) ((n) >> 8) #define GET_LS_BYTE(n) ((n) & 0xFF) +#define SM2_KEY_BYTES 32 + enum HW_ASYM_ENC_DEV { HW_ASYM_ENC_INVALID = 0x0, HW_ASYM_ENC_V2 = 0x2, diff --git a/src/uadk_prov_sm2.c b/src/uadk_prov_sm2.c deleted file mode 100644 index cfaa4409..00000000 --- a/src/uadk_prov_sm2.c +++ /dev/null @@ -1,2822 +0,0 @@ -// 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 -#include -#include -#include -#include -#include -#include -#include "uadk_async.h" -#include "uadk_prov.h" -#include "uadk_prov_der_writer.h" -#include "uadk_prov_packet.h" -#include "uadk_prov_pkey.h" -#include "uadk_utils.h" - -#define SM2_KEY_BYTES 32 -#define SM2_GET_SIGNLEN 1 -#define SM3_DIGEST_LENGTH 32 -#define SM2_DEFAULT_USERID "1234567812345678" -#define SM2_DEFAULT_USERID_LEN 16 - -UADK_PKEY_SIGNATURE_DESCR(sm2, SM2); -UADK_PKEY_ASYM_CIPHER_DESCR(sm2, SM2); - -static const OSSL_PARAM sm2_asym_cipher_known_settable_ctx_params[] = { - OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PROPERTIES, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_ENGINE, NULL, 0), - OSSL_PARAM_END -}; - -static const OSSL_PARAM sm2_asym_cipher_known_gettable_ctx_params[] = { - OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_END -}; - -static const OSSL_PARAM sm2_sig_known_settable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), - OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DIST_ID, NULL, 0), - OSSL_PARAM_END -}; - -static const OSSL_PARAM sm2_sig_known_gettable_ctx_params[] = { - OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0), - OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), - OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_END -}; - -enum { - CTX_INIT_FAIL = -1, - CTX_UNINIT, - CTX_INIT_SUCC -}; - -/* Structure for sm2 key related data */ -typedef struct { - BIGNUM *order; - /* Key and paramgen group */ - EC_GROUP *gen_group; - const BIGNUM *prikey; - const EC_POINT *pubkey; -} SM2_PKEY_DATA; - -/* Structure for sm2 digest method related data */ -typedef struct { - /* The nid of digest method */ - int md_nid; - /* Legacy: update status of digest method, changed (1), unchanged (0) */ - int md_update_status; - /* - * References to the underlying digest implementation. - * |md| caches the digest, always. - * |alloc_md| only holds a reference to an explicitly fetched digest. - */ - EVP_MD_CTX *mdctx; - EVP_MD *md; - EVP_MD *alloc_md; - size_t mdsize; -} SM2_MD_DATA; - -/* Structure for SM2 private context in uadk_provider, related to UADK */ -typedef struct { - int init_status; - /* The session related to UADK */ - handle_t sess; - SM2_PKEY_DATA *sm2_pd; - SM2_MD_DATA *sm2_md; -} SM2_PROV_CTX; - -/* - * Provider sm2 signature algorithm context structure. - * Upper application will use, such as, EVP_PKEY_CTX *ctx, - * this structure will be called like: ctx->op.sig.algctx, - * the 'algctx' can be defined by our uadk_provider, which is - * the structure below. - */ -typedef struct { - OSSL_LIB_CTX *libctx; - char *propq; - /* Use EC_KEY refer to keymgmt */ - EC_KEY *key; - - /* - * Flag to termine if the 'z' digest needs to be computed and fed to the - * hash function. - * This flag should be set on initialization and the compuation should - * be performed only once, on first update. - */ - unsigned int flag_compute_z_digest : 1; - - /* Will used by openssl, but not used by UADK, so put it outside SM2_PROV_CTX */ - char mdname[OSSL_MAX_NAME_SIZE]; - - /* The Algorithm Identifier of the combined signature algorithm */ - unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE]; - unsigned char *aid; - size_t aid_len; - - /* main digest */ - EVP_MD *md; - EVP_MD_CTX *mdctx; - size_t mdsize; - - /* - * SM2 ID used for calculating the Z value, - * distinguishing Identifier, ISO/IEC 15946-3 - */ - unsigned char *id; - size_t id_len; - /* Indicates if the 'id' field is set (1) or not (0) */ - int id_set; - - SM2_PROV_CTX *sm2_pctx; -} PROV_SM2_SIGN_CTX; - -/* - * To stay same structure with openssl sm2 cipher context, - * add openssl PROV_DIGEST type to uadk provider. - * It will not be used in uadk provider, so set it all zero. - */ -struct PROV_DIGEST { - const EVP_MD *md; - EVP_MD *alloc_md; - - ENGINE *engine; - - /* The resv is additional field, not in openssl structure. - * Add it to prevent possible field changes of openssl in future. - */ - char resv[OSSL_MAX_NAME_SIZE]; -}; - -typedef struct { - OSSL_LIB_CTX *libctx; - /* Use EC_KEY refer to keymgmt */ - EC_KEY *key; - /* The md will used by openssl, but not used by uadk provider */ - struct PROV_DIGEST md; - - SM2_PROV_CTX *sm2_pctx; -} PROV_SM2_ASYM_CTX; - -struct sm2_param { - /* - * p: BIGNUM with the prime number (GFp) or the polynomial - * defining the underlying field (GF2m) - */ - BIGNUM *p; - /* a: BIGNUM for parameter a of the equation */ - BIGNUM *a; - /* b: BIGNUM for parameter b of the equation */ - BIGNUM *b; - /* xG: BIGNUM for the x-coordinate value of G point */ - BIGNUM *xG; - /* yG: BIGNUM for the y-coordinate value of G point */ - BIGNUM *yG; - /* xA: BIGNUM for the x-coordinate value of PA point */ - BIGNUM *xA; - /* yA: BIGNUM for the y-coordinate value of PA point */ - BIGNUM *yA; -}; - -typedef struct sm2_ciphertext { - BIGNUM *C1x; - BIGNUM *C1y; - ASN1_OCTET_STRING *C3; - ASN1_OCTET_STRING *C2; -} SM2_Ciphertext; - -DECLARE_ASN1_FUNCTIONS(SM2_Ciphertext) - -ASN1_SEQUENCE(SM2_Ciphertext) = { - ASN1_SIMPLE(SM2_Ciphertext, C1x, BIGNUM), - ASN1_SIMPLE(SM2_Ciphertext, C1y, BIGNUM), - ASN1_SIMPLE(SM2_Ciphertext, C3, ASN1_OCTET_STRING), - ASN1_SIMPLE(SM2_Ciphertext, C2, ASN1_OCTET_STRING), -} ASN1_SEQUENCE_END(SM2_Ciphertext) - -IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext) - -static UADK_PKEY_ASYM_CIPHER s_asym_cipher; -static UADK_PKEY_SIGNATURE s_signature; - -static UADK_PKEY_SIGNATURE get_default_sm2_signature(void) -{ - return s_signature; -} - -void set_default_sm2_signature(void) -{ - UADK_PKEY_SIGNATURE *signature; - - signature = (UADK_PKEY_SIGNATURE *)EVP_SIGNATURE_fetch(NULL, "SM2", "provider=default"); - if (signature) { - s_signature = *signature; - EVP_SIGNATURE_free((EVP_SIGNATURE *)signature); - } else { - UADK_INFO("failed to EVP_SIGNATURE_fetch sm2 default provider\n"); - } -} - -static void *uadk_signature_sm2_newctx(void *provctx, const char *propq) -{ - PROV_SM2_SIGN_CTX *psm2ctx = OPENSSL_zalloc(sizeof(PROV_SM2_SIGN_CTX)); - SM2_PROV_CTX *smctx; - - if (psm2ctx == NULL) { - UADK_ERR("failed to alloc sm2 signature ctx\n"); - return NULL; - } - /* The libctx maybe NULL, if libctx is NULL, will use default ctx. */ - psm2ctx->libctx = prov_libctx_of(provctx); - - smctx = OPENSSL_zalloc(sizeof(SM2_PROV_CTX)); - if (smctx == NULL) { - UADK_ERR("failed to alloc sm2 prov ctx\n"); - goto free_ctx; - } - - smctx->sm2_pd = OPENSSL_zalloc(sizeof(SM2_PKEY_DATA)); - if (smctx->sm2_pd == NULL) { - UADK_ERR("failed to alloc sm2 pkey data\n"); - goto free_smctx; - } - - smctx->sm2_md = OPENSSL_zalloc(sizeof(SM2_MD_DATA)); - if (smctx->sm2_md == NULL) { - UADK_ERR("failed to alloc sm2 md data\n"); - goto free_pd; - } - - /* - * Use SM3 for digest method in default, other digest algs - * can be set with set_ctx_params API. - */ - smctx->sm2_md->mdsize = SM3_DIGEST_LENGTH; - psm2ctx->mdsize = SM3_DIGEST_LENGTH; - smctx->sm2_md->md_nid = NID_sm3; - strcpy(psm2ctx->mdname, OSSL_DIGEST_NAME_SM3); - smctx->sm2_md->mdctx = EVP_MD_CTX_new(); - if (smctx->sm2_md->mdctx == NULL) { - UADK_ERR("failed to alloc sm2 mdctx\n"); - goto free_md; - } - - psm2ctx->sm2_pctx = smctx; - - if (propq) { - psm2ctx->propq = OPENSSL_strdup(propq); - if (psm2ctx->propq == NULL) { - UADK_ERR("failed to dup propq\n"); - goto free_mdctx; - } - } - - return psm2ctx; - -free_mdctx: - EVP_MD_CTX_free(smctx->sm2_md->mdctx); -free_md: - OPENSSL_free(smctx->sm2_md); -free_pd: - OPENSSL_free(smctx->sm2_pd); -free_smctx: - OPENSSL_free(smctx); -free_ctx: - OPENSSL_free(psm2ctx); - return NULL; -} - -static void uadk_signature_sm2_freectx(void *vpsm2ctx) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - - if (psm2ctx == NULL) - return; - - smctx = psm2ctx->sm2_pctx; - if (smctx) { - if (smctx->sess) - wd_ecc_free_sess(smctx->sess); - - if (smctx->sm2_md) { - EVP_MD_free(smctx->sm2_md->md); - EVP_MD_CTX_free(smctx->sm2_md->mdctx); - OPENSSL_free(smctx->sm2_md); - } - - if (smctx->sm2_pd) { - if (smctx->sm2_pd->order) - BN_free(smctx->sm2_pd->order); - OPENSSL_free(smctx->sm2_pd); - } - - OPENSSL_free(smctx); - } - - if (psm2ctx->propq) - OPENSSL_free(psm2ctx->propq); - if (psm2ctx->key) - EC_KEY_free(psm2ctx->key); - if (psm2ctx->id) - OPENSSL_free(psm2ctx->id); - - OPENSSL_free(psm2ctx); -} - -static int uadk_prov_sm2_check_md_params(SM2_PROV_CTX *smctx) -{ - if (smctx->sm2_md == NULL) { - UADK_ERR("invalid: sm2_md is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_md->md == NULL) { - UADK_ERR("invalid: md is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_md->mdctx == NULL) { - UADK_ERR("invalid: mdctx is NULL\n"); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_sig_set_mdname(PROV_SM2_SIGN_CTX *psm2ctx, const char *mdname) -{ - SM2_PROV_CTX *smctx; - - /* If mdname is NULL, no need to set, just return */ - if (mdname == NULL) - return UADK_P_SUCCESS; - - /* 'psm2ctx' has already been checked when call this function, no need to check again */ - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_md == NULL) { - UADK_ERR("invalid: smctx->sm2_md is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_md->md == NULL) { - smctx->sm2_md->md = EVP_MD_fetch(psm2ctx->libctx, - psm2ctx->mdname, psm2ctx->propq); - if (smctx->sm2_md->md == NULL) { - UADK_ERR("failed to fetch digest method\n"); - return UADK_P_FAIL; - } - } - - if (strlen(mdname) >= sizeof(psm2ctx->mdname) || - !EVP_MD_is_a(smctx->sm2_md->md, mdname)) { - UADK_ERR("failed to check mdname, digest=%s\n", mdname); - return UADK_P_FAIL; - } - - OPENSSL_strlcpy(psm2ctx->mdname, mdname, sizeof(psm2ctx->mdname)); - - return UADK_P_SUCCESS; -} - -static int uadk_prov_compute_hash(const char *in, size_t in_len, - char *out, size_t out_len, void *usr) -{ - const EVP_MD *digest = (const EVP_MD *)usr; - int ret = WD_SUCCESS; - EVP_MD_CTX *hash; - - hash = EVP_MD_CTX_new(); - if (hash == NULL) - return -WD_EINVAL; - - if (EVP_DigestInit(hash, digest) == 0 || - EVP_DigestUpdate(hash, in, in_len) == 0 || - EVP_DigestFinal(hash, (void *)out, NULL) == 0) { - UADK_ERR("compute hash failed\n"); - ret = -WD_EINVAL; - } - - EVP_MD_CTX_free(hash); - - return ret; -} - -static int uadk_prov_get_hash_type(int nid_hash) -{ - switch (nid_hash) { - case NID_sha1: - return WD_HASH_SHA1; - case NID_sha224: - return WD_HASH_SHA224; - case NID_sha256: - return WD_HASH_SHA256; - case NID_sha384: - return WD_HASH_SHA384; - case NID_sha512: - return WD_HASH_SHA512; - case NID_md4: - return WD_HASH_MD4; - case NID_md5: - return WD_HASH_MD5; - case NID_sm3: - return WD_HASH_SM3; - default: - return -WD_EINVAL; - } -} - -static int uadk_prov_sm2_update_sess(SM2_PROV_CTX *smctx) -{ - const unsigned char sm2_order[] = { - 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x72, 0x03, 0xdf, 0x6b, 0x21, 0xc6, 0x05, 0x2b, - 0x53, 0xbb, 0xf4, 0x09, 0x39, 0xd5, 0x41, 0x23 - }; - struct wd_ecc_sess_setup setup = {0}; - struct sched_params params = {0}; - handle_t sess; - int type; - - if (smctx->sm2_pd == NULL) { - UADK_ERR("invalid: sm2 pd is NULL\n"); - return UADK_P_FAIL; - } - - /* order is free in freectx */ - if (smctx->sm2_pd->order == NULL) { - smctx->sm2_pd->order = BN_bin2bn((void *)sm2_order, sizeof(sm2_order), NULL); - if (smctx->sm2_pd->order == NULL) { - UADK_ERR("failed to BN_bin2bn order\n"); - return UADK_P_FAIL; - } - } - setup.rand.usr = (void *)smctx->sm2_pd->order; - - if (smctx->sm2_md->md) { - /* Set hash method */ - setup.hash.cb = uadk_prov_compute_hash; - setup.hash.usr = (void *)smctx->sm2_md->md; - type = uadk_prov_get_hash_type(smctx->sm2_md->md_nid); - if (type < 0) { - UADK_ERR("uadk not support hash nid %d\n", smctx->sm2_md->md_nid); - return UADK_P_FAIL; - } - setup.hash.type = type; - } - setup.alg = "sm2"; - - /* Use the default numa parameters */ - params.numa_id = -1; - setup.sched_param = ¶ms; - setup.rand.cb = uadk_prov_ecc_get_rand; - sess = wd_ecc_alloc_sess(&setup); - if (sess == (handle_t)0) { - UADK_ERR("failed to alloc sess\n"); - smctx->init_status = CTX_INIT_FAIL; - return UADK_P_FAIL; - } - - /* Free old session before setting new session */ - if (smctx->sess) - wd_ecc_free_sess(smctx->sess); - smctx->sess = sess; - - smctx->sm2_pd->prikey = NULL; - smctx->sm2_pd->pubkey = NULL; - - return UADK_P_SUCCESS; -} - -static int uadk_signature_sm2_sign_init_sw(void *vpsm2ctx, void *ec, - const OSSL_PARAM params[]) -{ - if (uadk_get_sw_offload_state() && get_default_sm2_signature().sign_init) { - UADK_INFO("switch to software sm2 sign_init.\n"); - return get_default_sm2_signature().sign_init(vpsm2ctx, ec, params); - } - - return UADK_P_FAIL; -} - -static int uadk_signature_sm2_sign_init(void *vpsm2ctx, void *ec, - const OSSL_PARAM params[]) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - int ret; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: vpsm2ctx is NULL\n"); - return UADK_P_FAIL; - } - - if (ec == NULL && psm2ctx->key == NULL) { - UADK_ERR("invalid: sm2 key is NULL\n"); - return UADK_P_FAIL; - } - - if (ec) { - if (!EC_KEY_up_ref(ec)) { - UADK_ERR("failed to EC_KEY_up_ref\n"); - return UADK_P_FAIL; - } - EC_KEY_free(psm2ctx->key); - psm2ctx->key = (EC_KEY *)ec; - } - - if (psm2ctx->sm2_pctx == NULL) { - UADK_ERR("failed to get smctx\n"); - return UADK_P_FAIL; - } - - /* openssl dgst tool will call sign_init twice, avoid repeated initialization */ - if (psm2ctx->sm2_pctx->init_status == CTX_INIT_SUCC) - return UADK_P_SUCCESS; - - ret = uadk_signature_sm2_set_ctx_params((void *)psm2ctx, params); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to set sm2 sig ctx params\n"); - goto do_soft; - } - - ret = uadk_prov_signature_get_support_state(SIGNATURE_SM2); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to get hardware sm2 signature support\n"); - goto do_soft; - } - - /* Init with UADK */ - ret = uadk_prov_ecc_init("sm2"); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to init sm2\n"); - goto do_soft; - } - - psm2ctx->sm2_pctx->init_status = CTX_INIT_SUCC; - - return UADK_P_SUCCESS; - -do_soft: - return uadk_signature_sm2_sign_init_sw(vpsm2ctx, ec, params); -} - -static int uadk_signature_sm2_verify_init(void *vpsm2ctx, void *ec, - const OSSL_PARAM params[]) -{ - return uadk_signature_sm2_sign_init(vpsm2ctx, ec, params); -} - -static int uadk_prov_sm2_check_tbs_params(PROV_SM2_SIGN_CTX *psm2ctx, - const unsigned char *tbs, size_t tbslen) -{ - SM2_PROV_CTX *smctx = psm2ctx->sm2_pctx; - - if (smctx == NULL) { - UADK_ERR("invalid: ctx is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->init_status != CTX_INIT_SUCC) { - UADK_ERR("sm2 ctx init did not init\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_md == NULL) { - UADK_ERR("invalid: sm2_md is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_md->mdsize != 0 && tbslen != smctx->sm2_md->mdsize) { - UADK_ERR("invalid: tbslen(%zu) != mdsize(%zu)\n", - tbslen, smctx->sm2_md->mdsize); - return UADK_P_FAIL; - } - - if (tbslen > SM2_KEY_BYTES) { - UADK_ERR("invalid: tbslen(%zu) > SM2_KEY_BYTES(32)\n", tbslen); - return UADK_P_FAIL; - } - - if (uadk_prov_is_all_zero(tbs, tbslen)) { - UADK_ERR("invalid: tbs all zero\n"); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_sign_init_iot(handle_t sess, struct wd_ecc_req *req, - unsigned char *digest, size_t digest_len) -{ - struct wd_ecc_out *ecc_out; - struct wd_ecc_in *ecc_in; - struct wd_dtb e = {0}; - - ecc_out = wd_sm2_new_sign_out(sess); - if (ecc_out == NULL) { - UADK_ERR("failed to new sign out\n"); - return UADK_P_FAIL; - } - - e.data = (void *)digest; - e.dsize = digest_len; - ecc_in = wd_sm2_new_sign_in(sess, &e, NULL, NULL, 1); - if (ecc_in == NULL) { - UADK_ERR("failed to new sign in\n"); - wd_ecc_del_out(sess, ecc_out); - return UADK_P_FAIL; - } - - uadk_prov_ecc_fill_req(req, WD_SM2_SIGN, ecc_in, ecc_out); - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_update_private_key(SM2_PROV_CTX *smctx, EC_KEY *eckey) -{ - const BIGNUM *d; - int ret; - - d = EC_KEY_get0_private_key(eckey); - if (d == NULL) { - UADK_ERR("failed to set private key\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_pd == NULL) { - UADK_ERR("invalid: sm2_pd is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_pd->prikey && !BN_cmp(d, smctx->sm2_pd->prikey)) { - UADK_ERR("invalid: private key mismatch\n"); - return UADK_P_FAIL; - } - - ret = uadk_prov_ecc_set_private_key(smctx->sess, eckey); - if (ret == UADK_P_FAIL) - return ret; - - smctx->sm2_pd->prikey = d; - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_sign_bin_to_ber(struct wd_dtb *r, struct wd_dtb *s, - unsigned char *sig, size_t *siglen) -{ - BIGNUM *bn_r, *bn_s; - ECDSA_SIG *e_sig; - int sltmp, ret; - - e_sig = ECDSA_SIG_new(); - if (e_sig == NULL) { - UADK_ERR("failed to ECDSA_SIG_new\n"); - return UADK_P_FAIL; - } - - bn_r = BN_bin2bn((void *)r->data, r->dsize, NULL); - if (bn_r == NULL) { - UADK_ERR("failed to BN_bin2bn r\n"); - goto free_sig; - } - - bn_s = BN_bin2bn((void *)s->data, s->dsize, NULL); - if (bn_s == NULL) { - UADK_ERR("failed to BN_bin2bn s\n"); - goto free_r; - } - - ret = ECDSA_SIG_set0(e_sig, bn_r, bn_s); - if (ret == 0) { - UADK_ERR("failed to ECDSA_SIG_set0\n"); - goto free_s; - } - - sltmp = i2d_ECDSA_SIG(e_sig, &sig); - if (sltmp < 0) { - UADK_ERR("failed to i2d_ECDSA_SIG\n"); - /* bs and br set to e_sig, use unified interface to prevent double release. */ - goto free_sig; - } - *siglen = (size_t)sltmp; - ECDSA_SIG_free(e_sig); - - return UADK_P_SUCCESS; - -free_s: - BN_free(bn_s); -free_r: - BN_free(bn_r); -free_sig: - ECDSA_SIG_free(e_sig); - - return UADK_P_FAIL; -} - -static int uadk_prov_sm2_sign_ber_to_bin(unsigned char *sig, size_t sig_len, - struct wd_dtb *r, struct wd_dtb *s) -{ - const unsigned char *p = sig; - unsigned char *der = NULL; - BIGNUM *bn_r, *bn_s; - ECDSA_SIG *e_sig; - int len1, len2; - - e_sig = ECDSA_SIG_new(); - if (e_sig == NULL) { - UADK_ERR("failed to ECDSA_SIG_new\n"); - return UADK_P_FAIL; - } - - if (d2i_ECDSA_SIG(&e_sig, &p, sig_len) == NULL) { - UADK_ERR("d2i_ECDSA_SIG error\n"); - goto free_sig; - } - - /* Ensure signature uses DER and doesn't have trailing garbage */ - len1 = i2d_ECDSA_SIG(e_sig, &der); - if (len1 != sig_len || memcmp(sig, der, len1) != 0) { - UADK_ERR("sig data error, der_len(%d), sig_len(%zu)\n", - len1, sig_len); - goto free_der; - } - - bn_r = (void *)ECDSA_SIG_get0_r((const ECDSA_SIG *)e_sig); - if (bn_r == NULL) { - UADK_ERR("failed to get r\n"); - goto free_der; - } - - bn_s = (void *)ECDSA_SIG_get0_s((const ECDSA_SIG *)e_sig); - if (bn_s == NULL) { - UADK_ERR("failed to get s\n"); - goto free_der; - } - - len1 = BN_num_bytes(bn_r); - len2 = BN_num_bytes(bn_s); - if (len1 > UADK_ECC_MAX_KEY_BYTES || len2 > UADK_ECC_MAX_KEY_BYTES) { - UADK_ERR("r or s bytes = (%d, %d) error\n", len1, len2); - goto free_der; - } - r->dsize = BN_bn2bin(bn_r, (void *)r->data); - s->dsize = BN_bn2bin(bn_s, (void *)s->data); - - OPENSSL_free(der); - ECDSA_SIG_free(e_sig); - - return UADK_P_SUCCESS; - -free_der: - OPENSSL_free(der); -free_sig: - ECDSA_SIG_free(e_sig); - - return UADK_P_FAIL; -} - -static int uadk_prov_sm2_sign(PROV_SM2_SIGN_CTX *psm2ctx, - unsigned char *sig, size_t *siglen, - const unsigned char *tbs, size_t tbslen) -{ - SM2_PROV_CTX *smctx = psm2ctx->sm2_pctx; - struct wd_ecc_req req = {0}; - struct wd_dtb *r = NULL; - struct wd_dtb *s = NULL; - int ret; - - /* sess is free in uadk_signature_sm2_freectx() */ - if (smctx->sess == (handle_t)0) { - ret = uadk_prov_sm2_update_sess(smctx); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to alloc sess in sign\n"); - return ret; - } - } - - ret = uadk_prov_sm2_sign_init_iot(smctx->sess, &req, (void *)tbs, tbslen); - if (ret == UADK_P_FAIL) - return ret; - - ret = uadk_prov_sm2_update_private_key(smctx, psm2ctx->key); - if (ret == UADK_P_FAIL) - goto uninit_iot; - - ret = uadk_prov_ecc_crypto(smctx->sess, &req, smctx); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to uadk_ecc_crypto, ret = %d\n", ret); - goto uninit_iot; - } - - wd_sm2_get_sign_out_params(req.dst, &r, &s); - if (r == NULL || s == NULL) { - UADK_ERR("failed to get sign result\n"); - ret = UADK_P_FAIL; - goto uninit_iot; - } - - ret = uadk_prov_sm2_sign_bin_to_ber(r, s, sig, siglen); - -uninit_iot: - wd_ecc_del_in(smctx->sess, req.src); - wd_ecc_del_out(smctx->sess, req.dst); - - return ret; -} - -static int uadk_signature_sm2_sign_sw(void *vpsm2ctx, unsigned char *sig, size_t *siglen, - size_t sigsize, const unsigned char *tbs, size_t tbslen) -{ - if (uadk_get_sw_offload_state() && get_default_sm2_signature().sign) { - UADK_INFO("switch to soft sm2 sign\n"); - return get_default_sm2_signature().sign(vpsm2ctx, sig, siglen, sigsize, - tbs, tbslen); - } - - return UADK_P_FAIL; -} - -static int uadk_signature_sm2_sign(void *vpsm2ctx, unsigned char *sig, size_t *siglen, - size_t sigsize, const unsigned char *tbs, size_t tbslen) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - int ret, ecsize; - size_t sltmp; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: psm2ctx is NULL\n"); - return UADK_P_FAIL; - } - - if (psm2ctx->key == NULL) { - UADK_ERR("invalid: sm2 ec is NULL\n"); - return UADK_P_FAIL; - } - - ecsize = ECDSA_size(psm2ctx->key); - if (ecsize <= 0) { - UADK_ERR("ecsize error %d\n", ecsize); - return UADK_P_FAIL; - } - - /* - * If 'sig' is NULL, users can use sm2_decrypt API to obtain the valid 'siglen' first, - * then users use the value of 'signlen' to alloc the memory of 'sig' and call the - * sm2_decrypt API a second time to do the decryption task. - */ - if (sig == NULL) { - *siglen = (size_t)ecsize; - return SM2_GET_SIGNLEN; - } - - if (sigsize < (size_t)ecsize) { - UADK_ERR("sigsize(%zu) < ecsize(%d)\n", sigsize, ecsize); - return UADK_P_FAIL; - } - - ret = uadk_prov_sm2_check_tbs_params(psm2ctx, tbs, tbslen); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to check sm2 signature params\n"); - goto do_soft; - } - - ret = uadk_prov_sm2_sign(psm2ctx, sig, &sltmp, tbs, tbslen); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to do sm2 sign\n"); - goto do_soft; - } - - *siglen = sltmp; - - return UADK_P_SUCCESS; - -do_soft: - return uadk_signature_sm2_sign_sw(vpsm2ctx, sig, siglen, sigsize, tbs, tbslen); -} - -static int uadk_prov_sm2_verify_init_iot(handle_t sess, struct wd_ecc_req *req, - struct wd_dtb *e, struct wd_dtb *r, - struct wd_dtb *s) -{ - struct wd_ecc_in *ecc_in; - - ecc_in = wd_sm2_new_verf_in(sess, e, r, s, NULL, 1); - if (ecc_in == NULL) { - UADK_ERR("failed to new verf in\n"); - return UADK_E_FAIL; - } - - uadk_prov_ecc_fill_req(req, WD_SM2_VERIFY, ecc_in, NULL); - - return UADK_E_SUCCESS; -} - -static int uadk_prov_sm2_update_public_key(SM2_PROV_CTX *smctx, EC_KEY *eckey) -{ - SM2_PKEY_DATA *spd = smctx->sm2_pd; - const EC_GROUP *group; - const EC_POINT *point; - int ret; - - point = EC_KEY_get0_public_key(eckey); - if (point == NULL) { - UADK_ERR("pubkey not set!\n"); - return UADK_E_FAIL; - } - - if (spd == NULL) { - UADK_ERR("invalid: sm2_pd is NULL\n"); - return UADK_P_FAIL; - } - - if (spd->pubkey) { - group = EC_KEY_get0_group(eckey); - if (group == NULL) { - UADK_ERR("failed to get group\n"); - return UADK_E_FAIL; - } - - ret = EC_POINT_cmp(group, (void *)spd->pubkey, point, NULL); - if (ret == UADK_E_FAIL) { - UADK_ERR("failed to do EC_POINT_cmp\n"); - return ret; - } - } - - ret = uadk_prov_ecc_set_public_key(smctx->sess, eckey); - if (ret == UADK_E_FAIL) - return ret; - - spd->pubkey = point; - - return UADK_E_SUCCESS; -} - -static int uadk_prov_sm2_verify(PROV_SM2_SIGN_CTX *psm2ctx, - const unsigned char *sig, size_t siglen, - const unsigned char *tbs, size_t tbslen) -{ - unsigned char buf_r[UADK_ECC_MAX_KEY_BYTES] = {0}; - unsigned char buf_s[UADK_ECC_MAX_KEY_BYTES] = {0}; - SM2_PROV_CTX *smctx = psm2ctx->sm2_pctx; - struct wd_ecc_req req = {0}; - EC_KEY *ec = psm2ctx->key; - struct wd_dtb e = {0}; - struct wd_dtb r = {0}; - struct wd_dtb s = {0}; - int ret; - - /* sess is free in uadk_signature_sm2_freectx() */ - if (smctx->sess == (handle_t)0) { - ret = uadk_prov_sm2_update_sess(smctx); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to alloc sess in verify\n"); - return ret; - } - } - - r.data = (void *)buf_r; - s.data = (void *)buf_s; - r.bsize = UADK_ECC_MAX_KEY_BYTES; - s.bsize = UADK_ECC_MAX_KEY_BYTES; - ret = uadk_prov_sm2_sign_ber_to_bin((void *)sig, siglen, &r, &s); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to uadk_prov_sm2_sign_ber_to_bin\n"); - return ret; - } - - e.data = (void *)tbs; - e.dsize = tbslen; - ret = uadk_prov_sm2_verify_init_iot(smctx->sess, &req, &e, &r, &s); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to uadk_prov_sm2_verify_init_iot\n"); - return ret; - } - - ret = uadk_prov_sm2_update_public_key(smctx, ec); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to uadk_prov_sm2_update_public_key\n"); - goto uninit_iot; - } - - ret = uadk_prov_ecc_crypto(smctx->sess, &req, smctx); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to uadk_ecc_crypto, ret = %d\n", ret); - goto uninit_iot; - } - - wd_ecc_del_in(smctx->sess, req.src); - - return UADK_P_SUCCESS; - -uninit_iot: - wd_ecc_del_in(smctx->sess, req.src); - - return UADK_P_FAIL; -} - -static int uadk_signature_sm2_verify_sw(void *vpsm2ctx, const unsigned char *sig, size_t siglen, - const unsigned char *tbs, size_t tbslen) -{ - if (uadk_get_sw_offload_state() && get_default_sm2_signature().verify) { - UADK_INFO("switch to soft sm2 verify\n"); - return get_default_sm2_signature().verify(vpsm2ctx, sig, siglen, tbs, tbslen); - } - - return UADK_P_FAIL; -} - -static int uadk_signature_sm2_verify(void *vpsm2ctx, const unsigned char *sig, size_t siglen, - const unsigned char *tbs, size_t tbslen) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - int ret; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: psm2ctx is NULL\n"); - return UADK_P_FAIL; - } - - ret = uadk_prov_sm2_check_tbs_params(psm2ctx, tbs, tbslen); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to check sm2 verify params\n"); - goto do_soft; - } - - ret = uadk_prov_sm2_verify(psm2ctx, sig, siglen, tbs, tbslen); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to do sm2 verify\n"); - goto do_soft; - } - - return UADK_P_SUCCESS; - -do_soft: - return uadk_signature_sm2_verify_sw(vpsm2ctx, sig, siglen, tbs, tbslen); -} - -static int uadk_signature_sm2_digest_sign_init(void *vpsm2ctx, const char *mdname, - void *ec, const OSSL_PARAM params[]) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - int md_nid; - WPACKET pkt; - - if (!uadk_signature_sm2_sign_init(vpsm2ctx, ec, params) || - !uadk_prov_sm2_sig_set_mdname(psm2ctx, mdname)) - return UADK_P_FAIL; - - smctx = psm2ctx->sm2_pctx; - - if (smctx->sm2_md->mdctx == NULL) { - smctx->sm2_md->mdctx = EVP_MD_CTX_new(); - if (unlikely(smctx->sm2_md->mdctx == NULL)) { - UADK_ERR("failed to EVP_MD_CTX_new\n"); - return UADK_P_FAIL; - } - } - - /* - * We do not care about DER writing errors. - * All it really means is that for some reason, there's no - * AlgorithmIdentifier to be had, but the operation itself is - * still valid, just as long as it's not used to construct - * anything that needs an AlgorithmIdentifier. - */ - md_nid = EVP_MD_get_type(smctx->sm2_md->md); - smctx->sm2_md->md_nid = md_nid; - psm2ctx->aid_len = 0; - if (WPACKET_init_der(&pkt, psm2ctx->aid_buf, sizeof(psm2ctx->aid_buf)) && - ossl_DER_w_algorithmIdentifier_SM2_with_MD(&pkt, -1, psm2ctx->key, md_nid) && - WPACKET_finish(&pkt)) { - WPACKET_get_total_written(&pkt, &psm2ctx->aid_len); - psm2ctx->aid = WPACKET_get_curr(&pkt); - } - WPACKET_cleanup(&pkt); - - if (!EVP_DigestInit_ex2(smctx->sm2_md->mdctx, smctx->sm2_md->md, params)) { - UADK_ERR("failed to do digest init\n"); - EVP_MD_CTX_free(smctx->sm2_md->mdctx); - return UADK_P_FAIL; - } - - psm2ctx->flag_compute_z_digest = 1; - - return UADK_P_SUCCESS; -} - -static int uadk_prov_check_equation_param(struct sm2_param *param, EVP_MD_CTX *hash, - uint8_t *buf, int p_bytes) -{ - if (BN_bn2binpad(param->a, buf, p_bytes) < 0 || - !EVP_DigestUpdate(hash, buf, p_bytes) || - BN_bn2binpad(param->b, buf, p_bytes) < 0 || - !EVP_DigestUpdate(hash, buf, p_bytes)) { - UADK_ERR("failed to check equation param\n"); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static int uadk_prov_check_base_point_group_param(struct sm2_param *param, BN_CTX *ctx, - const EC_KEY *key) -{ - const EC_GROUP *group = EC_KEY_get0_group(key); - - if (!EC_POINT_get_affine_coordinates(group, - EC_GROUP_get0_generator(group), - param->xG, param->yG, ctx)) { - UADK_ERR("failed to check base point group param\n"); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static int uadk_prov_check_base_point_param(struct sm2_param *param, EVP_MD_CTX *hash, - uint8_t *buf, int p_bytes) -{ - if (BN_bn2binpad(param->xG, buf, p_bytes) < 0 || - !EVP_DigestUpdate(hash, buf, p_bytes) || - BN_bn2binpad(param->yG, buf, p_bytes) < 0 || - !EVP_DigestUpdate(hash, buf, p_bytes)) { - UADK_ERR("failed to check base point param\n"); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static int uadk_prov_check_pkey_point_group_param(struct sm2_param *param, BN_CTX *ctx, - const EC_KEY *key) -{ - const EC_GROUP *group = EC_KEY_get0_group(key); - - if (!EC_POINT_get_affine_coordinates(group, - EC_KEY_get0_public_key(key), - param->xA, param->yA, ctx)) { - UADK_ERR("failed to check pkey point group param\n"); - return UADK_P_FAIL; - } - return UADK_P_SUCCESS; -} - -static int uadk_prov_check_pkey_point_param(struct sm2_param *param, EVP_MD_CTX *hash, - uint8_t *buf, int p_bytes, uint8_t *out) -{ - if (BN_bn2binpad(param->xA, buf, p_bytes) < 0 || - !EVP_DigestUpdate(hash, buf, p_bytes) || - BN_bn2binpad(param->yA, buf, p_bytes) < 0 || - !EVP_DigestUpdate(hash, buf, p_bytes) || - !EVP_DigestFinal(hash, out, NULL)) { - UADK_ERR("failed to check pkey point param\n"); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static int uadk_prov_get_sm2_param(struct sm2_param *params, BN_CTX *ctx) -{ - params->p = BN_CTX_get(ctx); - if (params->p == NULL) - goto end; - - params->a = BN_CTX_get(ctx); - if (params->a == NULL) - goto end; - - params->b = BN_CTX_get(ctx); - if (params->b == NULL) - goto end; - - params->xG = BN_CTX_get(ctx); - if (params->xG == NULL) - goto end; - - params->yG = BN_CTX_get(ctx); - if (params->yG == NULL) - goto end; - - params->xA = BN_CTX_get(ctx); - if (params->xA == NULL) - goto end; - - params->yA = BN_CTX_get(ctx); - if (params->yA == NULL) - goto end; - - return UADK_P_SUCCESS; - -end: - UADK_ERR("failed to get bn ctx for sm2 params\n"); - return UADK_P_FAIL; -} - -static int uadk_prov_check_digest_evp_lib(const EVP_MD *digest, EVP_MD_CTX *hash, - const size_t id_len, const uint8_t *id) -{ - uint8_t e_byte; - uint16_t entl; - - if (!EVP_DigestInit(hash, digest)) { - UADK_ERR("error evp lib\n"); - return UADK_P_FAIL; - } - - /* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */ - if (id_len >= (UINT16_MAX >> TRANS_BITS_BYTES_SHIFT)) { - UADK_ERR("invalid: id too large\n"); - return UADK_P_FAIL; - } - - entl = (uint16_t)(id_len << TRANS_BITS_BYTES_SHIFT); - - /* Update the most significant (first) byte of 'entl' */ - e_byte = GET_MS_BYTE(entl); - if (!EVP_DigestUpdate(hash, &e_byte, 1)) { - UADK_ERR("failed to do EVP_DigestUpdate for e_byte's first byte\n"); - return UADK_P_FAIL; - } - - /* Update the least significant (second) byte of 'entl' */ - e_byte = GET_LS_BYTE(entl); - if (!EVP_DigestUpdate(hash, &e_byte, 1)) { - UADK_ERR("failed to do EVP_DigestUpdate for e_byte's second byte\n"); - return UADK_P_FAIL; - } - - if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) { - UADK_ERR("failed to do EVP_DigestUpdate for id\n"); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_compute_z_digest(uint8_t *out, const EVP_MD *digest, - const uint8_t *id, const size_t id_len, - const EC_KEY *key) -{ - const EC_GROUP *group = EC_KEY_get0_group(key); - struct sm2_param *params; - int ret = UADK_P_FAIL; - EVP_MD_CTX *hash; - uint8_t *buf; - BN_CTX *ctx; - int p_bytes; - - hash = EVP_MD_CTX_new(); - if (hash == NULL) - return ret; - - ctx = BN_CTX_new_ex(key->libctx); - if (ctx == NULL) - goto free_hash; - - params = OPENSSL_zalloc(sizeof(struct sm2_param)); - if (params == NULL) { - UADK_ERR("failed to malloc sm2 param\n"); - goto free_ctx; - } - - if (uadk_prov_get_sm2_param(params, ctx) == UADK_P_FAIL) - goto free_params; - - if (uadk_prov_check_digest_evp_lib(digest, hash, id_len, id) == UADK_P_FAIL) - goto free_params; - - if (EC_GROUP_get_curve(group, params->p, params->a, params->b, ctx) == 0) { - UADK_ERR("failed to EC_GROUP_get_curve\n"); - goto free_params; - } - - p_bytes = BN_num_bytes(params->p); - buf = OPENSSL_zalloc(p_bytes); - if (buf == NULL) { - UADK_ERR("failed to alloc buffer\n"); - goto free_params; - } - - if (!uadk_prov_check_equation_param(params, hash, buf, p_bytes) || - !uadk_prov_check_base_point_group_param(params, ctx, key) || - !uadk_prov_check_base_point_param(params, hash, buf, p_bytes) || - !uadk_prov_check_pkey_point_group_param(params, ctx, key) || - !uadk_prov_check_pkey_point_param(params, hash, buf, p_bytes, out)) - goto free_buf; - - ret = UADK_P_SUCCESS; - -free_buf: - OPENSSL_free(buf); -free_params: - OPENSSL_free(params); -free_ctx: - BN_CTX_free(ctx); -free_hash: - EVP_MD_CTX_free(hash); - return ret; -} - -static int sm2_sig_compute_z_digest(PROV_SM2_SIGN_CTX *psm2ctx) -{ - SM2_PROV_CTX *smctx = psm2ctx->sm2_pctx; - uint8_t *z; - int ret; - - if (psm2ctx->flag_compute_z_digest) { - /* Only do this once */ - psm2ctx->flag_compute_z_digest = 0; - - z = OPENSSL_zalloc(smctx->sm2_md->mdsize); - if (z == NULL) { - UADK_ERR("failed to alloc z\n"); - return UADK_P_FAIL; - } - - /* if id is not set, use default id */ - if (psm2ctx->id == NULL) { - /* psm2ctx id will be freed in uadk_signature_sm2_freectx, not here */ - psm2ctx->id = OPENSSL_memdup(SM2_DEFAULT_USERID, SM2_DEFAULT_USERID_LEN); - if (psm2ctx->id == NULL) { - UADK_ERR("failed to memdup psm2ctx id\n"); - goto free_z; - } - psm2ctx->id_len = SM2_DEFAULT_USERID_LEN; - } - - /* get hashed prefix 'z' of tbs message */ - ret = uadk_prov_sm2_compute_z_digest(z, smctx->sm2_md->md, psm2ctx->id, - psm2ctx->id_len, psm2ctx->key); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to uadk_prov_sm2_compute_z_digest\n"); - goto free_z; - } - - ret = EVP_DigestUpdate(smctx->sm2_md->mdctx, z, smctx->sm2_md->mdsize); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to EVP_DigestUpdate\n"); - goto free_z; - } - OPENSSL_free(z); - } - - return UADK_P_SUCCESS; - -free_z: - OPENSSL_free(z); - return UADK_P_FAIL; -} - -static int uadk_signature_sm2_digest_sign_update(void *vpsm2ctx, const unsigned char *data, - size_t datalen) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - int ret; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: psm2ctx is NULL in digest sign update\n"); - return UADK_P_FAIL; - } - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL in compute z digest\n"); - return UADK_P_FAIL; - } - - ret = uadk_prov_sm2_check_md_params(smctx); - if (ret == UADK_P_FAIL) - return ret; - - ret = sm2_sig_compute_z_digest(psm2ctx); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to compute z digest\n"); - return ret; - } - - ret = EVP_DigestUpdate(smctx->sm2_md->mdctx, data, datalen); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to EVP_DigestUpdate\n"); - return ret; - } - - return UADK_P_SUCCESS; -} - -static int uadk_signature_sm2_digest_sign_final(void *vpsm2ctx, - unsigned char *sig, size_t *siglen, - size_t sigsize) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - unsigned char digest[EVP_MAX_MD_SIZE]; - unsigned int dlen = 0; - SM2_PROV_CTX *smctx; - int ret; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: psm2ctx is NULL\n"); - return UADK_P_FAIL; - } - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL\n"); - return UADK_P_FAIL; - } - - ret = uadk_prov_sm2_check_md_params(smctx); - if (ret == UADK_P_FAIL) - return ret; - - /* - * If sig is NULL then we're just finding out the sig size. Other fields - * are ignored. Defer to sm2sig_sign. - */ - if (sig != NULL) { - ret = sm2_sig_compute_z_digest(psm2ctx); - if (ret == UADK_P_FAIL) - return ret; - - ret = EVP_DigestFinal_ex(smctx->sm2_md->mdctx, digest, &dlen); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to do EVP_DigestFinal_ex\n"); - return ret; - } - } - - return uadk_signature_sm2_sign(vpsm2ctx, sig, siglen, sigsize, digest, (size_t)dlen); -} - -static int uadk_signature_sm2_digest_verify_init(void *vpsm2ctx, const char *mdname, - void *ec, const OSSL_PARAM params[]) -{ - return uadk_signature_sm2_digest_sign_init(vpsm2ctx, mdname, ec, params); -} - -static int uadk_signature_sm2_digest_verify_update(void *vpsm2ctx, const unsigned char *data, - size_t datalen) -{ - return uadk_signature_sm2_digest_sign_update(vpsm2ctx, data, datalen); -} - -static int uadk_signature_sm2_digest_verify_final(void *vpsm2ctx, const unsigned char *sig, - size_t siglen) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - unsigned char digest[EVP_MAX_MD_SIZE]; - unsigned int dlen = 0; - SM2_PROV_CTX *smctx; - int ret, size; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: psm2ctx is NULL\n"); - return UADK_P_FAIL; - } - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL\n"); - return UADK_P_FAIL; - } - - ret = uadk_prov_sm2_check_md_params(smctx); - if (ret == UADK_P_FAIL) - return ret; - - size = EVP_MD_get_size(smctx->sm2_md->md); - if (size > EVP_MAX_MD_SIZE) { - UADK_ERR("invalid: md size(%d) > %d\n", size, EVP_MAX_MD_SIZE); - return UADK_P_FAIL; - } - - ret = sm2_sig_compute_z_digest(psm2ctx); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to do sm2_sig_compute_z_digest\n"); - return ret; - } - - ret = EVP_DigestFinal_ex(smctx->sm2_md->mdctx, digest, &dlen); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to do EVP_DigestFinal_ex, dlen = %u\n", dlen); - return ret; - } - - return uadk_signature_sm2_verify(vpsm2ctx, sig, siglen, digest, (size_t)dlen); -} - -static SM2_PROV_CTX *sm2_copy_src_smctx(SM2_PROV_CTX *src_smctx) -{ - SM2_PROV_CTX *dst_smctx; - int ret; - - if (src_smctx == NULL || src_smctx->sm2_md == NULL || src_smctx->sm2_pd == NULL) { - UADK_ERR("invalid: src_smctx is NULL to dupctx\n"); - return NULL; - } - - dst_smctx = OPENSSL_zalloc(sizeof(SM2_PROV_CTX)); - if (dst_smctx == NULL) { - UADK_ERR("failed to alloc dst_smctx\n"); - return NULL; - } - dst_smctx->init_status = src_smctx->init_status; - - dst_smctx->sm2_md = OPENSSL_zalloc(sizeof(SM2_MD_DATA)); - if (dst_smctx->sm2_md == NULL) { - UADK_ERR("failed to alloc dst_smctx->sm2_md\n"); - goto free_dst_smctx; - } - - if (src_smctx->sm2_md->md != NULL && !EVP_MD_up_ref(src_smctx->sm2_md->md)) { - UADK_ERR("failed to check srcctx md reference\n"); - goto free_sm2_md; - } - dst_smctx->sm2_md->md = src_smctx->sm2_md->md; - dst_smctx->sm2_md->mdsize = src_smctx->sm2_md->mdsize; - dst_smctx->sm2_md->md_nid = src_smctx->sm2_md->md_nid; - - if (src_smctx->sm2_md->mdctx != NULL) { - dst_smctx->sm2_md->mdctx = EVP_MD_CTX_new(); - if (dst_smctx->sm2_md->mdctx == NULL || - EVP_MD_CTX_copy_ex(dst_smctx->sm2_md->mdctx, src_smctx->sm2_md->mdctx) == 0) { - UADK_ERR("failed to new dst mdctx or copy src mdctx\n"); - goto free_mdctx; - } - } - - dst_smctx->sm2_pd = OPENSSL_zalloc(sizeof(SM2_PKEY_DATA)); - if (dst_smctx->sm2_pd == NULL) { - UADK_ERR("failed to alloc sm2_pd\n"); - goto free_mdctx; - } - - if (src_smctx->sess) { - ret = uadk_prov_sm2_update_sess(dst_smctx); - if (!ret) - goto free_sm2_pd; - } - - return dst_smctx; - -free_sm2_pd: - OPENSSL_free(dst_smctx->sm2_pd); -free_mdctx: - if (dst_smctx->sm2_md->mdctx != NULL) - EVP_MD_CTX_free(dst_smctx->sm2_md->mdctx); - EVP_MD_free(dst_smctx->sm2_md->md); -free_sm2_md: - OPENSSL_free(dst_smctx->sm2_md); -free_dst_smctx: - OPENSSL_free(dst_smctx); - return NULL; -} - -static void *uadk_signature_sm2_dupctx(void *vpsm2ctx) -{ - PROV_SM2_SIGN_CTX *srcctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - PROV_SM2_SIGN_CTX *dstctx; - - if (srcctx == NULL) { - UADK_ERR("invalid: src ctx is NULL to dupctx!\n"); - return NULL; - } - - dstctx = OPENSSL_zalloc(sizeof(PROV_SM2_SIGN_CTX)); - if (dstctx == NULL) { - UADK_ERR("failed to alloc dst ctx\n"); - return NULL; - } - *dstctx = *srcctx; - dstctx->key = NULL; - dstctx->id = NULL; - dstctx->sm2_pctx = NULL; - dstctx->propq = NULL; - - if (srcctx->key != NULL && !EC_KEY_up_ref(srcctx->key)) { - UADK_ERR("failed to check srcctx key reference\n"); - goto free_ctx; - } - dstctx->key = srcctx->key; - - if (srcctx->propq) { - dstctx->propq = OPENSSL_strdup(srcctx->propq); - if (dstctx->propq == NULL) - goto free_ctx; - } - - dstctx->sm2_pctx = sm2_copy_src_smctx(srcctx->sm2_pctx); - if (dstctx->sm2_pctx == NULL) - goto free_ctx; - - if (srcctx->id != NULL) { - dstctx->id = OPENSSL_malloc(srcctx->id_len); - if (dstctx->id == NULL) { - UADK_ERR("failed to alloc id\n"); - goto free_ctx; - } - memcpy(dstctx->id, srcctx->id, srcctx->id_len); - } - - return dstctx; - -free_ctx: - uadk_signature_sm2_freectx(dstctx); - return NULL; -} - -static int uadk_prov_sm2_locate_id_digest(PROV_SM2_SIGN_CTX *psm2ctx, const OSSL_PARAM params[]) -{ - size_t tmp_idlen = 0; - const OSSL_PARAM *p; - void *tmp_id = NULL; - char *mdname = NULL; - size_t mdsize; - - p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DIST_ID); - if (p) { - /*If the 'z' digest has already been computed, the ID is set too late */ - if (psm2ctx->flag_compute_z_digest == 0) { - UADK_ERR("invalid: should set ID param before z digest\n"); - return UADK_P_FAIL; - } - - if (p->data_size != 0 && - !OSSL_PARAM_get_octet_string(p, &tmp_id, 0, &tmp_idlen)) { - UADK_ERR("failed to OSSL_PARAM_get_octet_string\n"); - return UADK_P_FAIL; - } - if (psm2ctx->id != NULL) - OPENSSL_free(psm2ctx->id); - psm2ctx->id = tmp_id; - psm2ctx->id_len = tmp_idlen; - } - - /* - * The following code checks that the size is the same as the SM3 digest - * size returning an error otherwise. - * If there is ever any different digest algorithm allowed with SM2 - * this needs to be adjusted accordingly. - */ - p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); - if (p != NULL && (!OSSL_PARAM_get_size_t(p, &mdsize) || - mdsize != psm2ctx->sm2_pctx->sm2_md->mdsize)) { - UADK_ERR("failed to locate digest size\n"); - return UADK_P_FAIL; - } - - p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST); - if (p) { - if (!OSSL_PARAM_get_utf8_string(p, &mdname, 0)) { - UADK_ERR("failed to OSSL_PARAM_get_utf8_string\n"); - return UADK_P_FAIL; - } - - if (!uadk_prov_sm2_sig_set_mdname(psm2ctx, mdname)) { - OPENSSL_free(mdname); - UADK_ERR("failed to OSSL_PARAM_get_utf8_string\n"); - return UADK_P_FAIL; - } - - if (mdname != NULL) - OPENSSL_free(mdname); - } - - return UADK_P_SUCCESS; -} - -static int uadk_signature_sm2_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM params[]) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - - /* - * 'set_ctx_param' function can be called independently, - * so check 'psm2ctx' again here. - */ - if (psm2ctx == NULL) { - UADK_ERR("invalid: sm2 ctx is NULL\n"); - return UADK_P_FAIL; - } - - /* If params is NULL, no need to set ctx params, just return */ - if (params == NULL) - return UADK_P_SUCCESS; - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL\n"); - return UADK_P_FAIL; - } - - return uadk_prov_sm2_locate_id_digest(psm2ctx, params); -} - -static int uadk_signature_sm2_get_ctx_params(void *vpsm2ctx, OSSL_PARAM *params) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - OSSL_PARAM *p; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: psm2ctx is NULL\n"); - return UADK_P_FAIL; - } - - p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID); - if (p != NULL && !OSSL_PARAM_set_octet_string(p, psm2ctx->aid, psm2ctx->aid_len)) { - UADK_ERR("failed to locate algorithm id\n"); - return UADK_P_FAIL; - } - - p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); - if (p != NULL && !OSSL_PARAM_set_size_t(p, psm2ctx->sm2_pctx->sm2_md->mdsize)) { - UADK_ERR("failed to locate digest size\n"); - return UADK_P_FAIL; - } - - p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST); - if (p != NULL && !OSSL_PARAM_set_utf8_string(p, psm2ctx->sm2_pctx->sm2_md->md == NULL - ? psm2ctx->mdname : EVP_MD_get0_name(psm2ctx->sm2_pctx->sm2_md->md))) { - UADK_ERR("failed to locate digest\n"); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static const OSSL_PARAM *uadk_signature_sm2_settable_ctx_params(ossl_unused void *vpsm2ctx, - ossl_unused void *provctx) -{ - return sm2_sig_known_settable_ctx_params; -} - -static const OSSL_PARAM *uadk_signature_sm2_gettable_ctx_params(ossl_unused void *vpsm2ctx, - ossl_unused void *provctx) -{ - return sm2_sig_known_gettable_ctx_params; -} - -static int uadk_signature_sm2_set_ctx_md_params(void *vpsm2ctx, const OSSL_PARAM params[]) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_md->mdctx == NULL) { - UADK_ERR("invalid: mdctx is NULL\n"); - return UADK_P_FAIL; - } - - return EVP_MD_CTX_set_params(smctx->sm2_md->mdctx, params); -} - -static int uadk_signature_sm2_get_ctx_md_params(void *vpsm2ctx, OSSL_PARAM *params) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_md->mdctx == NULL) { - UADK_ERR("invalid: mdctx is NULL\n"); - return UADK_P_FAIL; - } - - return EVP_MD_CTX_get_params(smctx->sm2_md->mdctx, params); -} - -static const OSSL_PARAM *uadk_signature_sm2_settable_ctx_md_params(void *vpsm2ctx) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_md->md == NULL) { - UADK_ERR("invalid: md is NULL\n"); - return UADK_P_FAIL; - } - - return EVP_MD_settable_ctx_params(smctx->sm2_md->md); -} - -static const OSSL_PARAM *uadk_signature_sm2_gettable_ctx_md_params(void *vpsm2ctx) -{ - PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->sm2_md->md == NULL) { - UADK_ERR("invalid: md is NULL\n"); - return UADK_P_FAIL; - } - - return EVP_MD_gettable_ctx_params(smctx->sm2_md->md); -} - -static int uadk_signature_sm2_verify_recover_init(void *vpsm2ctx, void *vsm2, - const OSSL_PARAM params[]) -{ - return UADK_P_SUCCESS; -} - -static int uadk_signature_sm2_verify_recover(void *vpsm2ctx, unsigned char *rout, - size_t *routlen, size_t routsize, - const unsigned char *sig, size_t siglen) -{ - return UADK_P_SUCCESS; -} - -static UADK_PKEY_ASYM_CIPHER get_default_sm2_asym_cipher(void) -{ - return s_asym_cipher; -} - -void set_default_sm2_asym_cipher(void) -{ - UADK_PKEY_ASYM_CIPHER *asym_cipher; - - asym_cipher = (UADK_PKEY_ASYM_CIPHER *)EVP_ASYM_CIPHER_fetch(NULL, - "SM2", "provider=default"); - if (asym_cipher) { - s_asym_cipher = *asym_cipher; - EVP_ASYM_CIPHER_free((EVP_ASYM_CIPHER *)asym_cipher); - } else { - UADK_INFO("failed to EVP_ASYM_CIPHER_fetch sm2 default provider\n"); - } -} - -static void *uadk_asym_cipher_sm2_newctx(void *provctx) -{ - PROV_SM2_ASYM_CTX *psm2ctx = OPENSSL_zalloc(sizeof(PROV_SM2_ASYM_CTX)); - SM2_PROV_CTX *smctx; - - if (psm2ctx == NULL) { - UADK_ERR("failed to alloc PROV_SM2_ASYM_CTX\n"); - return NULL; - } - - psm2ctx->libctx = prov_libctx_of(provctx); - - smctx = OPENSSL_zalloc(sizeof(SM2_PROV_CTX)); - if (smctx == NULL) { - UADK_ERR("failed to alloc sm2 prov ctx\n"); - goto free_psm2ctx; - } - - smctx->sm2_md = OPENSSL_zalloc(sizeof(SM2_MD_DATA)); - if (smctx->sm2_md == NULL) { - UADK_ERR("failed to alloc sm2 md data\n"); - goto free_smctx; - } - /* Use SM3 in default, other digest can be set with set_ctx_params API. */ - smctx->sm2_md->mdsize = SM3_DIGEST_LENGTH; - - smctx->sm2_pd = OPENSSL_zalloc(sizeof(SM2_PKEY_DATA)); - if (smctx->sm2_pd == NULL) { - UADK_ERR("failed to alloc sm2 pkey data\n"); - goto free_sm2_md; - } - - psm2ctx->sm2_pctx = smctx; - - return psm2ctx; - -free_sm2_md: - OPENSSL_free(smctx->sm2_md); -free_smctx: - OPENSSL_free(smctx); -free_psm2ctx: - OPENSSL_free(psm2ctx); - - return NULL; -} - -static void ossl_prov_digest_reset(struct PROV_DIGEST *pd) -{ - EVP_MD_free(pd->alloc_md); - -#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE) - ENGINE_finish(pd->engine); -#endif -} - -static void uadk_asym_cipher_sm2_freectx(void *vpsm2ctx) -{ - PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - - if (psm2ctx == NULL) - return; - - smctx = psm2ctx->sm2_pctx; - if (smctx) { - if (smctx->sm2_md) { - EVP_MD_free(smctx->sm2_md->md); - OPENSSL_free(smctx->sm2_md); - } - - if (smctx->sm2_pd) { - if (smctx->sm2_pd->order) - BN_free(smctx->sm2_pd->order); - OPENSSL_free(smctx->sm2_pd); - } - - if (smctx->sess) - wd_ecc_free_sess(smctx->sess); - OPENSSL_free(smctx); - } - - if (psm2ctx->key) - EC_KEY_free(psm2ctx->key); - - ossl_prov_digest_reset(&psm2ctx->md); - OPENSSL_free(psm2ctx); -} - -static void uadk_prov_sm2_set_default_md(PROV_SM2_ASYM_CTX *psm2ctx) -{ - SM2_PROV_CTX *smctx = psm2ctx->sm2_pctx; - SM2_MD_DATA *smd = smctx->sm2_md; - - /* Set SM3 as default digest method */ - if (smd->alloc_md) - EVP_MD_free(smd->alloc_md); - smd->md = smd->alloc_md = EVP_MD_fetch(psm2ctx->libctx, "SM3", NULL); - smd->md_nid = NID_sm3; -} - -static int uadk_asym_cipher_sm2_encrypt_init_sw(void *vpsm2ctx, void *vkey, - const OSSL_PARAM params[]) -{ - if (uadk_get_sw_offload_state() && get_default_sm2_asym_cipher().encrypt_init) { - UADK_INFO("switch to software sm2 encrypt init\n"); - return get_default_sm2_asym_cipher().encrypt_init(vpsm2ctx, vkey, params); - } - - return UADK_P_FAIL; -} - -static int uadk_asym_cipher_sm2_encrypt_init(void *vpsm2ctx, void *vkey, - const OSSL_PARAM params[]) -{ - PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - int ret; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: psm2ctx is NULL\n"); - return UADK_P_FAIL; - } - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL\n"); - return UADK_P_FAIL; - } - - if (vkey == NULL || !EC_KEY_up_ref(vkey)) { - UADK_ERR("invalid: vkey is NULL\n"); - return UADK_P_FAIL; - } - EC_KEY_free(psm2ctx->key); - psm2ctx->key = vkey; - - /* Set default digest method as SM3 */ - uadk_prov_sm2_set_default_md(psm2ctx); - - ret = uadk_asym_cipher_sm2_set_ctx_params(psm2ctx, params); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to set_ctx_params\n"); - goto do_soft; - } - - ret = uadk_prov_asym_cipher_get_support_state(SIGNATURE_SM2); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to get hardware sm2 signature support\n"); - goto do_soft; - } - - /* Init with UADK */ - ret = uadk_prov_ecc_init("sm2"); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to init sm2\n"); - goto do_soft; - } - - smctx->init_status = CTX_INIT_SUCC; - - ret = uadk_prov_sm2_update_sess(smctx); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to update sess\n"); - goto do_soft; - } - - return UADK_P_SUCCESS; - -do_soft: - return uadk_asym_cipher_sm2_encrypt_init_sw(vpsm2ctx, vkey, params); -} - -static int uadk_prov_sm2_encrypt_check(PROV_SM2_ASYM_CTX *psm2ctx, - unsigned char *out, size_t *outlen, - const unsigned char *in, size_t inlen) -{ - SM2_PROV_CTX *smctx = psm2ctx->sm2_pctx; - const EVP_MD *md; - int c3_size; - - if (smctx == NULL || smctx->sess == (handle_t)0) { - UADK_ERR("smctx or sess NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->init_status != CTX_INIT_SUCC) { - UADK_ERR("sm2 ctx init failed\n"); - return UADK_P_FAIL; - } - - /* - * As we have already set md method in init, if not set, will use default digest. - * The md is unlikey to be NULL here, so if the md is still NULL when encrypt start, - * just return fail. - */ - md = smctx->sm2_md->md; - if (md == NULL) { - UADK_ERR("failed to get md method\n"); - return UADK_P_FAIL; - } - - c3_size = EVP_MD_size(md); - if (c3_size <= 0) { - UADK_ERR("c3 size error\n"); - return UADK_P_FAIL; - } - - if (inlen > UINT_MAX) { - UADK_ERR("invalid: inlen is out of range\n"); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_encrypt_init_iot(handle_t sess, struct wd_ecc_req *req, - unsigned char *in, size_t inlen) -{ - struct wd_ecc_out *ecc_out; - struct wd_ecc_in *ecc_in; - struct wd_dtb e = {0}; - - ecc_out = wd_sm2_new_enc_out(sess, inlen); - if (ecc_out == NULL) { - UADK_ERR("failed to new enc out\n"); - return UADK_P_FAIL; - } - - e.data = (void *)in; - e.dsize = inlen; - ecc_in = wd_sm2_new_enc_in(sess, NULL, &e); - if (ecc_in == NULL) { - UADK_ERR("failed to new enc in\n"); - wd_ecc_del_out(sess, ecc_out); - return UADK_P_FAIL; - } - - uadk_prov_ecc_fill_req(req, WD_SM2_ENCRYPT, ecc_in, ecc_out); - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_asym_bin_to_ber(struct wd_ecc_point *c1, - struct wd_dtb *c2, struct wd_dtb *c3, - unsigned char *ber, size_t *ber_len) -{ - struct sm2_ciphertext ctext; - int ctext_leni, ret; - BIGNUM *x1, *y1; - - x1 = BN_bin2bn((void *)c1->x.data, c1->x.dsize, NULL); - if (x1 == NULL) { - UADK_ERR("failed to BN_bin2bn x1\n"); - return UADK_P_FAIL; - } - - y1 = BN_bin2bn((void *)c1->y.data, c1->y.dsize, NULL); - if (y1 == NULL) { - UADK_ERR("failed to BN_bin2bn y1\n"); - ret = UADK_P_FAIL; - goto free_x1; - } - - ctext.C1x = x1; - ctext.C1y = y1; - ctext.C3 = ASN1_OCTET_STRING_new(); - if (ctext.C3 == NULL) { - ret = UADK_P_FAIL; - goto free_y1; - } - - ret = ASN1_OCTET_STRING_set(ctext.C3, (void *)c3->data, c3->dsize); - if (ret == 0) - goto free_c3; - - ctext.C2 = ASN1_OCTET_STRING_new(); - if (ctext.C2 == NULL) { - ret = UADK_P_FAIL; - goto free_c3; - } - - ret = ASN1_OCTET_STRING_set(ctext.C2, (void *)c2->data, c2->dsize); - if (ret == 0) - goto free_c2; - - ctext_leni = i2d_SM2_Ciphertext(&ctext, &ber); - /* Ensure cast to size_t is safe */ - if (ctext_leni < 0) { - ret = UADK_P_FAIL; - goto free_c2; - } - *ber_len = (size_t)ctext_leni; - ret = UADK_P_SUCCESS; - -free_c2: - ASN1_OCTET_STRING_free(ctext.C2); -free_c3: - ASN1_OCTET_STRING_free(ctext.C3); -free_y1: - BN_free(y1); -free_x1: - BN_free(x1); - - return ret; -} - -static int uadk_prov_sm2_encrypt_sw(PROV_SM2_ASYM_CTX *vpsm2ctx, - unsigned char *out, size_t *outlen, - const unsigned char *in, size_t inlen) -{ - if (uadk_get_sw_offload_state() && get_default_sm2_asym_cipher().encrypt) { - UADK_INFO("switch to software sm2 encrypt\n"); - return get_default_sm2_asym_cipher().encrypt(vpsm2ctx, out, outlen, 0, in, inlen); - } - - return UADK_P_FAIL; -} - -static int uadk_prov_sm2_encrypt(PROV_SM2_ASYM_CTX *vpsm2ctx, - unsigned char *out, size_t *outlen, - const unsigned char *in, size_t inlen) -{ - SM2_PROV_CTX *smctx = vpsm2ctx->sm2_pctx; - struct wd_ecc_point *c1 = NULL; - struct wd_ecc_req req = {0}; - struct wd_dtb *c2 = NULL; - struct wd_dtb *c3 = NULL; - const EVP_MD *md; - int md_size, ret; - - ret = uadk_prov_sm2_encrypt_init_iot(smctx->sess, &req, (void *)in, inlen); - if (ret == UADK_P_FAIL) - goto do_soft; - - ret = uadk_prov_sm2_update_public_key(smctx, vpsm2ctx->key); - if (ret == UADK_P_FAIL) - goto uninit_iot; - - ret = uadk_prov_ecc_crypto(smctx->sess, &req, smctx); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to uadk_ecc_crypto, ret = %d\n", ret); - goto uninit_iot; - } - - wd_sm2_get_enc_out_params(req.dst, &c1, &c2, &c3); - if (c1 == NULL || c2 == NULL || c3 == NULL) { - ret = UADK_P_FAIL; - goto uninit_iot; - } - - ret = uadk_prov_sm2_asym_bin_to_ber(c1, c2, c3, out, outlen); - if (ret == UADK_P_FAIL) - goto uninit_iot; - - md = (smctx->sm2_md->md == NULL) ? EVP_sm3() : smctx->sm2_md->md; - md_size = EVP_MD_size(md); - if (c3->dsize != md_size) { - UADK_ERR("invalid: c3 dsize(%u) != hash_size(%d)\n", c3->dsize, md_size); - ret = UADK_P_FAIL; - goto uninit_iot; - } - - wd_ecc_del_in(smctx->sess, req.src); - wd_ecc_del_out(smctx->sess, req.dst); - - return UADK_P_SUCCESS; - -uninit_iot: - wd_ecc_del_in(smctx->sess, req.src); - wd_ecc_del_out(smctx->sess, req.dst); -do_soft: - return uadk_prov_sm2_encrypt_sw(vpsm2ctx, out, outlen, in, inlen); -} - -static size_t uadk_prov_ec_field_size(const EC_GROUP *group) -{ - BIGNUM *p = BN_new(); - BIGNUM *a = BN_new(); - BIGNUM *b = BN_new(); - size_t field_size = 0; - size_t p_bits; - - if (p == NULL || a == NULL || b == NULL) { - UADK_ERR("failed to new bignumber\n"); - goto done; - } - - if (!EC_GROUP_get_curve(group, p, a, b, NULL)) { - UADK_ERR("failed to get curve from group\n"); - goto done; - } - - p_bits = BN_num_bits(p); - field_size = BITS_TO_BYTES(p_bits); - -done: - BN_free(p); - BN_free(a); - BN_free(b); - - return field_size; -} - -static int uadk_prov_sm2_ciphertext_size(const EC_KEY *key, - const EVP_MD *digest, size_t msg_len, - size_t *ct_size) -{ - const size_t field_size = uadk_prov_ec_field_size(EC_KEY_get0_group(key)); - const int md_size = EVP_MD_size(digest); - size_t sz; - - if (field_size == 0) - return UADK_P_FAIL; - - if (md_size < 0) { - UADK_ERR("invalid md_size: %d\n", md_size); - return UADK_P_FAIL; - } - - /* - * Integer and string are simple type; set constructed = 0, means - * primitive and definite length encoding. - */ - sz = ECC_POINT_SIZE(ASN1_object_size(0, field_size + 1, V_ASN1_INTEGER)) + - ASN1_object_size(0, md_size, V_ASN1_OCTET_STRING) + - ASN1_object_size(0, msg_len, V_ASN1_OCTET_STRING); - *ct_size = ASN1_object_size(1, sz, V_ASN1_SEQUENCE); - - return UADK_P_SUCCESS; -} - -static int uadk_asym_cipher_sm2_encrypt(void *vpsm2ctx, unsigned char *out, size_t *outlen, - size_t outsize, const unsigned char *in, - size_t inlen) -{ - PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - SM2_MD_DATA *smd; - const EVP_MD *md; - int ret; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: psm2ctx is NULL\n"); - return UADK_P_FAIL; - } - - ret = uadk_prov_sm2_encrypt_check(psm2ctx, out, outlen, in, inlen); - if (ret == UADK_P_FAIL) - return uadk_prov_sm2_encrypt_sw(vpsm2ctx, out, outlen, in, inlen); - - /* If out is NULL, compute outlen size and return */ - if (out == NULL) { - smctx = psm2ctx->sm2_pctx; - smd = smctx->sm2_md; - md = (const EVP_MD *)smd->md; - if (!uadk_prov_sm2_ciphertext_size(psm2ctx->key, md, inlen, outlen)) - return UADK_P_FAIL; - else - return UADK_P_SUCCESS; - } - - return uadk_prov_sm2_encrypt(psm2ctx, out, outlen, in, inlen); -} - -static int uadk_asym_cipher_sm2_decrypt_init(void *vpsm2ctx, void *vkey, - const OSSL_PARAM params[]) -{ - return uadk_asym_cipher_sm2_encrypt_init(vpsm2ctx, vkey, params); -} - -static int uadk_prov_sm2_decrypt_check(SM2_PROV_CTX *smctx, - unsigned char *out, size_t *outlen, - const unsigned char *in, size_t inlen) -{ - const EVP_MD *md; - int hash_size; - - if (smctx == NULL || smctx->sess == (handle_t)0) { - UADK_ERR("smctx or sess NULL\n"); - return UADK_P_FAIL; - } - - if (smctx->init_status != CTX_INIT_SUCC) { - UADK_ERR("sm2 ctx init failed\n"); - return UADK_P_FAIL; - } - - /* - * As we have already set md method in init, if not set, will use default digest. - * The md is unlikey to be NULL here, so if the md is still NULL when encrypt start, - * just return fail. - */ - md = smctx->sm2_md->md; - if (md == NULL) { - UADK_ERR("failed to get md method\n"); - return UADK_P_FAIL; - } - - hash_size = EVP_MD_size(md); - if (hash_size <= 0) { - UADK_ERR("hash size = %d error\n", hash_size); - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_asym_ber_to_bin(const EVP_MD *md, struct sm2_ciphertext *ctext, - struct wd_ecc_point *c1, struct wd_dtb *c2, - struct wd_dtb *c3) -{ - int c1x_len, c1y_len, md_size; - - if (md == NULL) { - UADK_ERR("invalid: md is NULL\n"); - return UADK_P_FAIL; - } - - c1x_len = BN_num_bytes(ctext->C1x); - c1y_len = BN_num_bytes(ctext->C1y); - c1->x.data = malloc(c1x_len + c1y_len + ctext->C2->length + ctext->C3->length); - if (c1->x.data == NULL) - return UADK_P_FAIL; - - c1->y.data = c1->x.data + c1x_len; - c3->data = c1->y.data + c1y_len; - c2->data = c3->data + ctext->C3->length; - memcpy(c2->data, ctext->C2->data, ctext->C2->length); - memcpy(c3->data, ctext->C3->data, ctext->C3->length); - c2->dsize = ctext->C2->length; - c3->dsize = ctext->C3->length; - md_size = EVP_MD_size(md); - if (c3->dsize != md_size) { - UADK_ERR("invalid: c3 dsize(%u) != hash_size(%d)\n", c3->dsize, md_size); - free(c1->x.data); - return UADK_P_FAIL; - } - - c1->x.dsize = BN_bn2bin(ctext->C1x, (void *)c1->x.data); - c1->y.dsize = BN_bn2bin(ctext->C1y, (void *)c1->y.data); - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_decrypt_init_iot(handle_t sess, struct wd_ecc_req *req, - struct wd_ecc_point *c1, - struct wd_dtb *c2, struct wd_dtb *c3) -{ - struct wd_ecc_out *ecc_out; - struct wd_ecc_in *ecc_in; - - ecc_out = wd_sm2_new_dec_out(sess, c2->dsize); - if (ecc_out == NULL) { - UADK_ERR("failed to new dec out\n"); - return UADK_P_FAIL; - } - - ecc_in = wd_sm2_new_dec_in(sess, c1, c2, c3); - if (ecc_in == NULL) { - UADK_ERR("failed to new dec in\n"); - wd_ecc_del_out(sess, ecc_out); - return UADK_P_FAIL; - } - - uadk_prov_ecc_fill_req(req, WD_SM2_DECRYPT, ecc_in, ecc_out); - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_get_plaintext(struct wd_ecc_req *req, - unsigned char *out, size_t *outlen) -{ - struct wd_dtb *ptext = NULL; - - wd_sm2_get_dec_out_params(req->dst, &ptext); - if (ptext == NULL) { - UADK_ERR("failed to get ptext\n"); - return UADK_P_FAIL; - } - - if (*outlen < ptext->dsize) { - UADK_ERR("outlen(%zu) < (%u)\n", *outlen, ptext->dsize); - return UADK_P_FAIL; - } - - memcpy(out, ptext->data, ptext->dsize); - *outlen = ptext->dsize; - - return UADK_P_SUCCESS; -} - -static int uadk_prov_sm2_decrypt_sw(PROV_SM2_ASYM_CTX *ctx, - unsigned char *out, size_t *outlen, - const unsigned char *in, size_t inlen) -{ - if (uadk_get_sw_offload_state() && get_default_sm2_asym_cipher().decrypt) { - UADK_INFO("switch to software sm2 decrypt\n"); - return get_default_sm2_asym_cipher().decrypt(ctx, out, outlen, 0, in, inlen); - } - - return UADK_P_FAIL; -} - -static int uadk_prov_sm2_decrypt(PROV_SM2_ASYM_CTX *ctx, - unsigned char *out, size_t *outlen, - const unsigned char *in, size_t inlen) -{ - const unsigned char *original_in = in; - SM2_PROV_CTX *smctx = ctx->sm2_pctx; - struct sm2_ciphertext *ctext; - struct wd_ecc_req req = {0}; - struct wd_ecc_point c1; - struct wd_dtb c2, c3; - const EVP_MD *md; - int ret; - - ret = uadk_prov_sm2_decrypt_check(smctx, out, outlen, in, inlen); - if (ret == UADK_P_FAIL) - goto do_soft; - - ctext = d2i_SM2_Ciphertext(NULL, &in, inlen); - if (ctext == NULL) - goto do_soft; - - md = (smctx->sm2_md->md == NULL) ? EVP_sm3() : smctx->sm2_md->md; - ret = uadk_prov_sm2_asym_ber_to_bin(md, ctext, &c1, &c2, &c3); - if (ret == UADK_P_FAIL) - goto free_ctext; - - ret = uadk_prov_sm2_decrypt_init_iot(smctx->sess, &req, &c1, &c2, &c3); - if (ret == UADK_P_FAIL) - goto free_c1; - - ret = uadk_prov_sm2_update_private_key(smctx, ctx->key); - if (ret == UADK_P_FAIL) - goto uninit_iot; - - ret = uadk_prov_ecc_crypto(smctx->sess, &req, smctx); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to uadk_ecc_crypto, ret = %d\n", ret); - goto uninit_iot; - } - - ret = uadk_prov_sm2_get_plaintext(&req, out, outlen); - if (ret == UADK_P_FAIL) - goto uninit_iot; - - wd_ecc_del_in(smctx->sess, req.src); - wd_ecc_del_out(smctx->sess, req.dst); - free(c1.x.data); - SM2_Ciphertext_free(ctext); - - return UADK_P_SUCCESS; - -uninit_iot: - wd_ecc_del_in(smctx->sess, req.src); - wd_ecc_del_out(smctx->sess, req.dst); -free_c1: - free(c1.x.data); -free_ctext: - SM2_Ciphertext_free(ctext); -do_soft: - return uadk_prov_sm2_decrypt_sw(ctx, out, outlen, original_in, inlen); -} - -static int uadk_prov_sm2_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size) -{ - struct sm2_ciphertext *sm2_ctext; - - sm2_ctext = d2i_SM2_Ciphertext(NULL, &ct, ct_size); - if (sm2_ctext == NULL) { - UADK_ERR("invalid sm2 encoding\n"); - return UADK_P_FAIL; - } - - *pt_size = sm2_ctext->C2->length; - SM2_Ciphertext_free(sm2_ctext); - - return UADK_P_SUCCESS; -} - -static int uadk_asym_cipher_sm2_decrypt(void *vpsm2ctx, unsigned char *out, size_t *outlen, - size_t outsize, const unsigned char *in, - size_t inlen) -{ - PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - int ret; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: psm2ctx is NULL\n"); - return UADK_P_FAIL; - } - - smctx = psm2ctx->sm2_pctx; - ret = uadk_prov_sm2_decrypt_check(smctx, out, outlen, in, inlen); - if (ret == UADK_P_FAIL) - return uadk_prov_sm2_decrypt_sw(vpsm2ctx, out, outlen, in, inlen); - - if (out == NULL) { - if (!uadk_prov_sm2_plaintext_size(in, inlen, outlen)) - return UADK_P_FAIL; - else - return UADK_P_SUCCESS; - } - - return uadk_prov_sm2_decrypt(psm2ctx, out, outlen, in, inlen); -} - -static int ossl_prov_digest_copy(struct PROV_DIGEST *dst, const struct PROV_DIGEST *src) -{ - if (src->alloc_md != NULL && !EVP_MD_up_ref(src->alloc_md)) - return UADK_P_FAIL; - -#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE) - if (src->engine != NULL && !ENGINE_init(src->engine)) { - EVP_MD_free(src->alloc_md); - return UADK_P_FAIL; - } -#endif - dst->engine = src->engine; - dst->md = src->md; - dst->alloc_md = src->alloc_md; - - return UADK_P_SUCCESS; -} - -static void *uadk_asym_cipher_sm2_dupctx(void *vpsm2ctx) -{ - PROV_SM2_ASYM_CTX *srcctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; - PROV_SM2_ASYM_CTX *dstctx; - int ret; - - if (srcctx == NULL) { - UADK_ERR("src ctx is NULL\n"); - return NULL; - } - - dstctx = OPENSSL_zalloc(sizeof(PROV_SM2_ASYM_CTX)); - if (dstctx == NULL) { - UADK_ERR("failed to alloc dst ctx\n"); - return NULL; - } - *dstctx = *srcctx; - dstctx->key = NULL; - dstctx->sm2_pctx = NULL; - memset(&dstctx->md, 0, sizeof(dstctx->md)); - - ret = ossl_prov_digest_copy(&dstctx->md, &srcctx->md); - if (!ret) - goto free_ctx; - - if (srcctx->key != NULL && !EC_KEY_up_ref(srcctx->key)) { - UADK_ERR("failed to check dstctx key reference\n"); - goto free_ctx; - } - dstctx->key = srcctx->key; - - dstctx->sm2_pctx = sm2_copy_src_smctx(srcctx->sm2_pctx); - if (dstctx->sm2_pctx == NULL) - goto free_ctx; - - return dstctx; - -free_ctx: - uadk_asym_cipher_sm2_freectx(dstctx); - return NULL; -} - -static int uadk_asym_cipher_sm2_get_ctx_params(void *vpsm2ctx, OSSL_PARAM *params) -{ - PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - SM2_MD_DATA *smd; - OSSL_PARAM *p; - EVP_MD *md; - - if (psm2ctx == NULL) { - UADK_ERR("failed to get psm2ctx\n"); - return UADK_P_FAIL; - } - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("failed to get smctx\n"); - return UADK_P_FAIL; - } - - smd = smctx->sm2_md; - if (smd == NULL) { - UADK_ERR("failed to get sm2 md\n"); - return UADK_P_FAIL; - } - - if (params == NULL) { - UADK_ERR("params is NULL\n"); - return UADK_P_FAIL; - } - - p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_DIGEST); - if (p != NULL) { - md = smd->md; - if (!OSSL_PARAM_set_utf8_string(p, md == NULL ? "" : EVP_MD_get0_name(md))) { - UADK_ERR("failed to set utf8 string\n"); - return UADK_P_FAIL; - } - smd->md_nid = EVP_MD_type(md); - } else { - return UADK_P_FAIL; - } - - return UADK_P_SUCCESS; -} - -static EVP_MD *uadk_prov_load_digest_from_params(SM2_MD_DATA *smd, const OSSL_PARAM params[], - OSSL_LIB_CTX *ctx) -{ - const char *propquery = NULL; - const OSSL_PARAM *p; - - /* Load common param properties, p can be NULL */ - p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_PROPERTIES); - if (p) { - if (p->data_type != OSSL_PARAM_UTF8_STRING) { - UADK_ERR("data_type != OSSL_PARAM_UTF8_STRING\n"); - return NULL; - } - propquery = p->data; - } - - /* Load digest related params */ - p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST); - if (p) { - if (p->data_type != OSSL_PARAM_UTF8_STRING) { - UADK_ERR("data_type != OSSL_PARAM_UTF8_STRING\n"); - return NULL; - } - } else { - /* If digest related params is NULL, no need to set digest */ - return NULL; - } - - /* Fetch digest */ - EVP_MD_free(smd->alloc_md); - smd->md = smd->alloc_md = EVP_MD_fetch(ctx, p->data, propquery); - if (smd->md == NULL) { - UADK_ERR("failed to fetch MD method\n"); - return NULL; - } - - return smd->md; -} - -static int uadk_asym_cipher_sm2_set_ctx_params_sw(void *vpsm2ctx, const OSSL_PARAM params[]) -{ - if (uadk_get_sw_offload_state() && get_default_sm2_asym_cipher().set_ctx_params) { - UADK_INFO("switch to software sm2 set ctx params\n"); - return get_default_sm2_asym_cipher().set_ctx_params(vpsm2ctx, params); - } - - return UADK_P_FAIL; -} - -static int uadk_asym_cipher_sm2_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM params[]) -{ - PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; - SM2_PROV_CTX *smctx; - SM2_MD_DATA *smd; - int ret; - - if (psm2ctx == NULL) { - UADK_ERR("invalid: sm2 ctx is NULL\n"); - return UADK_P_FAIL; - } - - /* No need to set */ - if (params == NULL) - return UADK_P_SUCCESS; - - smctx = psm2ctx->sm2_pctx; - if (smctx == NULL) { - UADK_ERR("invalid: smctx is NULL\n"); - return UADK_P_FAIL; - } - - /* Set digest method */ - smd = smctx->sm2_md; - if (smd == NULL) { - UADK_ERR("invalid: sm2 md is NULL\n"); - return UADK_P_FAIL; - } - - smd->md = uadk_prov_load_digest_from_params(smctx->sm2_md, params, psm2ctx->libctx); - if (smd->md == NULL) { - UADK_ERR("failed to set digest with set_ctx_params\n"); - return UADK_P_FAIL; - } - smd->md_nid = EVP_MD_type(smd->md); - - /* If not init, do not need to update session, just set the data before */ - if (smctx->init_status == CTX_INIT_SUCC) { - ret = uadk_prov_sm2_update_sess(smctx); - if (ret == UADK_P_FAIL) { - UADK_ERR("failed to update sess\n"); - goto do_soft; - } - } - - return UADK_P_SUCCESS; - -do_soft: - return uadk_asym_cipher_sm2_set_ctx_params_sw(vpsm2ctx, params); -} - -static const OSSL_PARAM *uadk_asym_cipher_sm2_gettable_ctx_params(ossl_unused void *vpsm2ctx, - ossl_unused void *provctx) -{ - return sm2_asym_cipher_known_gettable_ctx_params; -} - -static const OSSL_PARAM *uadk_asym_cipher_sm2_settable_ctx_params(ossl_unused void *vpsm2ctx, - ossl_unused void *provctx) -{ - return sm2_asym_cipher_known_settable_ctx_params; -} diff --git a/src/uadk_prov_sm2_enc.c b/src/uadk_prov_sm2_enc.c new file mode 100644 index 00000000..e9872026 --- /dev/null +++ b/src/uadk_prov_sm2_enc.c @@ -0,0 +1,860 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include "uadk_async.h" +#include "uadk_prov.h" +#include "uadk_prov_pkey.h" +#include "uadk_utils.h" + +typedef struct { + /* + * References to the underlying digest implementation. |md| caches + * the digest, always. |alloc_md| only holds a reference to an explicitly + * fetched digest. + */ + const EVP_MD *md; + /* fetched digest */ + EVP_MD *alloc_md; + + /* Conditions for legacy EVP_MD uses, digest engine */ + ENGINE *engine; +} PROV_DIGEST; + +typedef struct { + OSSL_LIB_CTX *libctx; + /* Use EC_KEY refer to keymgmt */ + EC_KEY *key; + /* The md will used by openssl, but not used by uadk provider */ + PROV_DIGEST md; +} PROV_SM2_ASYM_CTX; + +typedef struct sm2_ciphertext { + BIGNUM *C1x; + BIGNUM *C1y; + ASN1_OCTET_STRING *C3; + ASN1_OCTET_STRING *C2; +} SM2_Ciphertext; + +static const OSSL_PARAM sm2_asym_cipher_known_gettable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM sm2_asym_cipher_known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_ENGINE, NULL, 0), + OSSL_PARAM_END +}; + +DECLARE_ASN1_FUNCTIONS(SM2_Ciphertext) + +ASN1_SEQUENCE(SM2_Ciphertext) = { + ASN1_SIMPLE(SM2_Ciphertext, C1x, BIGNUM), + ASN1_SIMPLE(SM2_Ciphertext, C1y, BIGNUM), + ASN1_SIMPLE(SM2_Ciphertext, C3, ASN1_OCTET_STRING), + ASN1_SIMPLE(SM2_Ciphertext, C2, ASN1_OCTET_STRING), +} ASN1_SEQUENCE_END(SM2_Ciphertext) + +IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext) +UADK_PKEY_ASYM_CIPHER_DESCR(sm2, SM2); + +static UADK_PKEY_ASYM_CIPHER s_asym_cipher; + +static UADK_PKEY_ASYM_CIPHER get_default_sm2_asym_cipher(void) +{ + return s_asym_cipher; +} + +void set_default_sm2_asym_cipher(void) +{ + UADK_PKEY_ASYM_CIPHER *asym_cipher; + + asym_cipher = (UADK_PKEY_ASYM_CIPHER *)EVP_ASYM_CIPHER_fetch(NULL, + "SM2", "provider=default"); + if (asym_cipher) { + s_asym_cipher = *asym_cipher; + EVP_ASYM_CIPHER_free((EVP_ASYM_CIPHER *)asym_cipher); + } else { + UADK_INFO("failed to EVP_ASYM_CIPHER_fetch sm2 default provider\n"); + } +} + +static void *uadk_asym_cipher_sm2_newctx(void *provctx) +{ + PROV_SM2_ASYM_CTX *psm2ctx; + + psm2ctx = OPENSSL_zalloc(sizeof(PROV_SM2_ASYM_CTX)); + if (!psm2ctx) { + UADK_ERR("failed to alloc PROV_SM2_ASYM_CTX\n"); + return NULL; + } + + psm2ctx->libctx = prov_libctx_of(provctx); + + return psm2ctx; +} + +static void sm2_prov_digest_reset(PROV_DIGEST *pd) +{ + EVP_MD_free(pd->alloc_md); +} + +static void uadk_asym_cipher_sm2_freectx(void *vpsm2ctx) +{ + PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; + + if (!psm2ctx) + return; + + EC_KEY_free(psm2ctx->key); + sm2_prov_digest_reset(&psm2ctx->md); + OPENSSL_free(psm2ctx); +} + +static int sm2_prov_load_common(const OSSL_PARAM params[], const char **propquery, ENGINE **engine) +{ + const OSSL_PARAM *p; + + *propquery = NULL; + p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_PROPERTIES); + if (p) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return UADK_P_FAIL; + *propquery = p->data; + } + + *engine = NULL; + + return UADK_P_SUCCESS; +} + +static const EVP_MD *sm2_prov_digest_fetch(PROV_DIGEST *pd, OSSL_LIB_CTX *libctx, + const char *mdname, const char *propquery) +{ + EVP_MD_free(pd->alloc_md); + pd->md = pd->alloc_md = EVP_MD_fetch(libctx, mdname, propquery); + + return pd->md; +} + +static int sm2_load_digest_from_params(PROV_DIGEST *pd, const OSSL_PARAM params[], + OSSL_LIB_CTX *ctx) +{ + const char *propquery; + const OSSL_PARAM *p; + + if (!sm2_prov_load_common(params, &propquery, &pd->engine)) + return UADK_P_FAIL; + + p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST); + if (!p) + return UADK_P_SUCCESS; + + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return UADK_P_FAIL; + + pd->md = sm2_prov_digest_fetch(pd, ctx, p->data, propquery); + if (!pd->md) + return UADK_P_FAIL; + + return UADK_P_SUCCESS; +} + +static int uadk_asym_cipher_sm2_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM params[]) +{ + PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; + int ret; + + if (!psm2ctx) { + UADK_ERR("invalid: sm2 ctx is NULL\n"); + return UADK_P_FAIL; + } + + /* No need to set */ + if (!params) + return UADK_P_SUCCESS; + + ret = sm2_load_digest_from_params(&psm2ctx->md, params, psm2ctx->libctx); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to set digest with set_ctx_params\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static int uadk_asym_cipher_sm2_encrypt_init(void *vpsm2ctx, void *vkey, + const OSSL_PARAM params[]) +{ + PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; + + if (!psm2ctx || !vkey) { + UADK_ERR("invalid: psm2ctx or vkey is NULL\n"); + return UADK_P_FAIL; + } + + if (!EC_KEY_up_ref(vkey)) { + UADK_ERR("failed to EC_KEY_up_ref vkey\n"); + return UADK_P_FAIL; + } + EC_KEY_free(psm2ctx->key); + psm2ctx->key = vkey; + + return uadk_asym_cipher_sm2_set_ctx_params(psm2ctx, params); +} + +static int uadk_asym_cipher_sm2_decrypt_init(void *vpsm2ctx, void *vkey, + const OSSL_PARAM params[]) +{ + return uadk_asym_cipher_sm2_encrypt_init(vpsm2ctx, vkey, params); +} + +static const EVP_MD *sm2_prov_digest_md(const PROV_DIGEST *pd) +{ + return pd->md; +} + +static const EVP_MD *sm2_prov_get_md(PROV_SM2_ASYM_CTX *psm2ctx) +{ + const EVP_MD *md = sm2_prov_digest_md(&psm2ctx->md); + + if (!md) + md = sm2_prov_digest_fetch(&psm2ctx->md, psm2ctx->libctx, "SM3", NULL); + + return md; +} + +static size_t sm2_prov_ec_field_size(const EC_GROUP *group) +{ + size_t field_size = 0; + size_t p_bits; + BIGNUM *p; + + p = BN_new(); + if (!p) { + UADK_ERR("failed to new bignumber\n"); + return field_size; + } + + if (!EC_GROUP_get_curve(group, p, NULL, NULL, NULL)) { + UADK_ERR("failed to get curve p from group\n"); + goto out; + } + + p_bits = BN_num_bits(p); + field_size = BITS_TO_BYTES(p_bits); + +out: + BN_free(p); + return field_size; +} + +static int sm2_prov_compute_hash(const char *in, size_t in_len, + char *out, size_t out_len, void *usr) +{ + const EVP_MD *digest = (const EVP_MD *)usr; + int ret = WD_SUCCESS; + EVP_MD_CTX *hash; + + hash = EVP_MD_CTX_new(); + if (!hash) + return -WD_EINVAL; + + if (EVP_DigestInit(hash, digest) == 0 || + EVP_DigestUpdate(hash, in, in_len) == 0 || + EVP_DigestFinal(hash, (void *)out, NULL) == 0) { + UADK_ERR("compute hash failed\n"); + ret = -WD_EINVAL; + } + + EVP_MD_CTX_free(hash); + + return ret; +} + +static int sm2_prov_get_hash_type(int nid_hash) +{ + switch (nid_hash) { + case NID_sha1: + return WD_HASH_SHA1; + case NID_sha224: + return WD_HASH_SHA224; + case NID_sha256: + return WD_HASH_SHA256; + case NID_sha384: + return WD_HASH_SHA384; + case NID_sha512: + return WD_HASH_SHA512; + case NID_md4: + return WD_HASH_MD4; + case NID_md5: + return WD_HASH_MD5; + case NID_sm3: + return WD_HASH_SM3; + default: + return -WD_EINVAL; + } +} + +static int sm2_prov_alloc_sess(PROV_SM2_ASYM_CTX *vpsm2ctx, handle_t *sess) +{ + const EC_GROUP *group = EC_KEY_get0_group(vpsm2ctx->key); + const EVP_MD *md = sm2_prov_digest_md(&vpsm2ctx->md); + const BIGNUM *order = EC_GROUP_get0_order(group); + struct wd_ecc_sess_setup setup = {0}; + struct sched_params params = {0}; + int md_nid = EVP_MD_get_type(md); + int type; + + type = sm2_prov_get_hash_type(md_nid); + if (type < 0) { + UADK_ERR("uadk not support hash nid %d\n", md_nid); + return UADK_DO_SOFT; + } + setup.hash.type = type; + setup.hash.cb = sm2_prov_compute_hash; + setup.hash.usr = (void *)md; + + setup.rand.cb = uadk_prov_ecc_get_rand; + setup.rand.usr = (void *)order; + setup.alg = "sm2"; + + /* Use the default numa parameters */ + params.numa_id = -1; + setup.sched_param = ¶ms; + *sess = wd_ecc_alloc_sess(&setup); + if (*sess == (handle_t)0) { + UADK_ERR("failed to alloc sess\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static void sm2_prov_free_sess(handle_t sess) +{ + wd_ecc_free_sess(sess); +} + +static int sm2_prov_encrypt_init_iot(handle_t sess, struct wd_ecc_req *req, + void *in, size_t inlen) +{ + struct wd_ecc_out *ecc_out; + struct wd_ecc_in *ecc_in; + struct wd_dtb e = {0}; + + ecc_out = wd_sm2_new_enc_out(sess, inlen); + if (!ecc_out) { + UADK_ERR("failed to new enc out\n"); + return UADK_P_FAIL; + } + + e.data = in; + e.dsize = inlen; + e.bsize = inlen; + ecc_in = wd_sm2_new_enc_in(sess, NULL, &e); + if (!ecc_in) { + UADK_ERR("failed to new enc in\n"); + wd_ecc_del_out(sess, ecc_out); + return UADK_P_FAIL; + } + + uadk_prov_ecc_fill_req(req, WD_SM2_ENCRYPT, ecc_in, ecc_out); + + return UADK_P_SUCCESS; +} + +static void sm2_prov_uninit_iot(handle_t sess, struct wd_ecc_req *req) +{ + wd_ecc_del_in(sess, req->src); + wd_ecc_del_out(sess, req->dst); +} + +static int sm2_prov_asym_bin_to_ber(struct wd_ecc_point *c1, + struct wd_dtb *c2, struct wd_dtb *c3, + unsigned char *ber, size_t *ber_len) +{ + struct sm2_ciphertext ctext; + int ret = UADK_P_FAIL; + BIGNUM *x1, *y1; + int ctext_leni; + + x1 = BN_bin2bn((const unsigned char *)c1->x.data, c1->x.dsize, NULL); + if (!x1) { + UADK_ERR("failed to BN_bin2bn x1\n"); + return UADK_P_FAIL; + } + + y1 = BN_bin2bn((const unsigned char *)c1->y.data, c1->y.dsize, NULL); + if (!y1) { + UADK_ERR("failed to BN_bin2bn y1\n"); + goto free_x1; + } + + ctext.C1x = x1; + ctext.C1y = y1; + ctext.C3 = ASN1_OCTET_STRING_new(); + if (!ctext.C3) + goto free_y1; + + ret = ASN1_OCTET_STRING_set(ctext.C3, (const unsigned char *)c3->data, c3->dsize); + if (ret == UADK_P_FAIL) + goto free_c3; + + ctext.C2 = ASN1_OCTET_STRING_new(); + if (!ctext.C2) { + ret = UADK_P_FAIL; + goto free_c3; + } + + ret = ASN1_OCTET_STRING_set(ctext.C2, (const unsigned char *)c2->data, c2->dsize); + if (ret == UADK_P_FAIL) + goto free_c2; + + ctext_leni = i2d_SM2_Ciphertext(&ctext, &ber); + /* Ensure cast to size_t is safe */ + if (ctext_leni < 0) { + ret = UADK_P_FAIL; + goto free_c2; + } + *ber_len = (size_t)ctext_leni; + ret = UADK_P_SUCCESS; + +free_c2: + ASN1_OCTET_STRING_free(ctext.C2); +free_c3: + ASN1_OCTET_STRING_free(ctext.C3); +free_y1: + BN_free(y1); +free_x1: + BN_free(x1); + + return ret; +} + +static int sm2_prov_encrypt_sw(PROV_SM2_ASYM_CTX *vpsm2ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + if (uadk_get_sw_offload_state() && get_default_sm2_asym_cipher().encrypt) { + UADK_INFO("switch to software sm2 encrypt\n"); + return get_default_sm2_asym_cipher().encrypt(vpsm2ctx, out, outlen, 0, in, inlen); + } + + return UADK_P_FAIL; +} + +static int sm2_prov_encrypt(PROV_SM2_ASYM_CTX *vpsm2ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + struct wd_ecc_point *c1 = NULL; + struct wd_ecc_req req = {0}; + struct wd_dtb *c2 = NULL; + struct wd_dtb *c3 = NULL; + handle_t sess; + int ret; + + if (inlen > UINT_MAX) { + ret = UADK_DO_SOFT; + goto do_soft; + } + + ret = uadk_prov_ecc_init("sm2"); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to init sm2\n"); + ret = UADK_DO_SOFT; + goto do_soft; + } + + ret = sm2_prov_alloc_sess(vpsm2ctx, &sess); + if (ret != UADK_P_SUCCESS) { + UADK_ERR("failed to alloc sess in encrypt\n"); + goto do_soft; + } + + ret = sm2_prov_encrypt_init_iot(sess, &req, (void *)in, inlen); + if (ret == UADK_P_FAIL) + goto free_sess; + + ret = uadk_prov_ecc_set_public_key(sess, vpsm2ctx->key); + if (ret == UADK_P_FAIL) + goto uninit_iot; + + ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to do sm2 encrypt\n"); + ret = UADK_DO_SOFT; + goto uninit_iot; + } + + wd_sm2_get_enc_out_params(req.dst, &c1, &c2, &c3); + if (!c1 || !c2 || !c3) { + ret = UADK_P_FAIL; + goto uninit_iot; + } + + ret = sm2_prov_asym_bin_to_ber(c1, c2, c3, out, outlen); + +uninit_iot: + sm2_prov_uninit_iot(sess, &req); +free_sess: + sm2_prov_free_sess(sess); +do_soft: + if (ret == UADK_DO_SOFT) + return sm2_prov_encrypt_sw(vpsm2ctx, out, outlen, in, inlen); + return ret; +} + +static int sm2_prov_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, + size_t msg_len, size_t *ct_size) +{ + const size_t field_size = sm2_prov_ec_field_size(EC_KEY_get0_group(key)); + const int md_size = EVP_MD_get_size(digest); + size_t sz; + + if (!field_size || md_size < 0) { + UADK_ERR("invalid field_size or md_size: %d\n", md_size); + return UADK_P_FAIL; + } + + /* + * Integer and string are simple type; set constructed = 0, means + * primitive and definite length encoding. + */ + sz = ECC_POINT_SIZE(ASN1_object_size(0, field_size + 1, V_ASN1_INTEGER)) + + ASN1_object_size(0, md_size, V_ASN1_OCTET_STRING) + + ASN1_object_size(0, msg_len, V_ASN1_OCTET_STRING); + *ct_size = ASN1_object_size(1, sz, V_ASN1_SEQUENCE); + + return UADK_P_SUCCESS; +} + +static int uadk_asym_cipher_sm2_encrypt(void *vpsm2ctx, unsigned char *out, size_t *outlen, + size_t outsize, const unsigned char *in, size_t inlen) +{ + PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; + const EVP_MD *md; + + if (!psm2ctx) { + UADK_ERR("invalid: psm2ctx is NULL\n"); + return UADK_P_FAIL; + } + + md = sm2_prov_get_md(psm2ctx); + if (!md) { + UADK_ERR("failed to get md method\n"); + return UADK_P_FAIL; + } + + /* If out is NULL, compute outlen size and return */ + if (!out) + return sm2_prov_ciphertext_size(psm2ctx->key, md, inlen, outlen); + + return sm2_prov_encrypt(psm2ctx, out, outlen, in, inlen); +} + +static int sm2_prov_get_plaintext(struct wd_ecc_req *req, + unsigned char *out, size_t *outlen) +{ + struct wd_dtb *ptext = NULL; + + wd_sm2_get_dec_out_params(req->dst, &ptext); + if (!ptext) { + UADK_ERR("failed to get ptext\n"); + return UADK_P_FAIL; + } + + if (*outlen < ptext->dsize) { + UADK_ERR("outlen(%zu) < (%u)\n", *outlen, ptext->dsize); + return UADK_P_FAIL; + } + + memcpy(out, ptext->data, ptext->dsize); + *outlen = ptext->dsize; + + return UADK_P_SUCCESS; +} + +static int sm2_prov_decrypt_init_iot(handle_t sess, struct wd_ecc_req *req, + int md_size, const unsigned char *in, size_t inlen) +{ + char buf_x[SM2_KEY_BYTES] = {0}; + char buf_y[SM2_KEY_BYTES] = {0}; + struct sm2_ciphertext **a = NULL; + struct sm2_ciphertext *ctext; + struct wd_ecc_out *ecc_out; + struct wd_ecc_in *ecc_in; + struct wd_ecc_point c1; + struct wd_dtb c2, c3; + int ret = UADK_P_FAIL; + int c1x_len, c1y_len; + + ctext = d2i_SM2_Ciphertext(a, &in, inlen); + if (!ctext) + return UADK_P_FAIL; + + if (ctext->C3->length != md_size) { + UADK_ERR("invalid: c3 dsize(%d) != md_size(%d)\n", ctext->C3->length, md_size); + goto free_ctext; + } + + c1x_len = BN_num_bytes(ctext->C1x); + c1y_len = BN_num_bytes(ctext->C1y); + if (c1x_len > SM2_KEY_BYTES || c1y_len > SM2_KEY_BYTES) { + UADK_ERR("invalid: x size %d or y size %d is error\n", c1x_len, c1y_len); + goto free_ctext; + } + + c1.x.dsize = BN_bn2bin(ctext->C1x, (void *)buf_x); + c1.y.dsize = BN_bn2bin(ctext->C1y, (void *)buf_y); + c1.x.bsize = SM2_KEY_BYTES; + c1.y.bsize = SM2_KEY_BYTES; + c1.x.data = buf_x; + c1.y.data = buf_y; + + c2.data = (char *)ctext->C2->data; + c2.dsize = ctext->C2->length; + c2.bsize = ctext->C2->length; + + c3.data = (char *)ctext->C3->data; + c3.dsize = ctext->C3->length; + c3.bsize = ctext->C3->length; + + ecc_out = wd_sm2_new_dec_out(sess, c2.dsize); + if (!ecc_out) { + UADK_ERR("failed to new dec out\n"); + goto free_ctext; + } + + ecc_in = wd_sm2_new_dec_in(sess, &c1, &c2, &c3); + if (!ecc_in) { + UADK_ERR("failed to new dec in\n"); + wd_ecc_del_out(sess, ecc_out); + goto free_ctext; + } + + uadk_prov_ecc_fill_req(req, WD_SM2_DECRYPT, ecc_in, ecc_out); + ret = UADK_P_SUCCESS; + +free_ctext: + SM2_Ciphertext_free(ctext); + return ret; +} + +static int sm2_prov_decrypt_sw(PROV_SM2_ASYM_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + if (uadk_get_sw_offload_state() && get_default_sm2_asym_cipher().decrypt) { + UADK_INFO("switch to software sm2 decrypt\n"); + return get_default_sm2_asym_cipher().decrypt(ctx, out, outlen, 0, in, inlen); + } + + return UADK_P_FAIL; +} + +static int sm2_prov_decrypt(PROV_SM2_ASYM_CTX *psm2ctx, unsigned char *out, + size_t *outlen, const unsigned char *in, size_t inlen) +{ + const EVP_MD *md = sm2_prov_digest_md(&psm2ctx->md); + int md_size = EVP_MD_get_size(md); + struct wd_ecc_req req = {0}; + handle_t sess; + int ret; + + if (inlen > UINT_MAX) { + ret = UADK_DO_SOFT; + goto do_soft; + } + + ret = uadk_prov_ecc_init("sm2"); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to init sm2\n"); + ret = UADK_DO_SOFT; + goto do_soft; + } + + ret = sm2_prov_alloc_sess(psm2ctx, &sess); + if (ret != UADK_P_SUCCESS) { + UADK_ERR("failed to alloc sess in encrypt\n"); + goto do_soft; + } + + ret = sm2_prov_decrypt_init_iot(sess, &req, md_size, in, inlen); + if (ret == UADK_P_FAIL) + goto free_sess; + + ret = uadk_prov_ecc_set_private_key(sess, psm2ctx->key); + if (ret == UADK_P_FAIL) + goto uninit_iot; + + ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to do sm2 decrypt\n"); + ret = UADK_DO_SOFT; + goto uninit_iot; + } + + ret = sm2_prov_get_plaintext(&req, out, outlen); + +uninit_iot: + sm2_prov_uninit_iot(sess, &req); +free_sess: + sm2_prov_free_sess(sess); +do_soft: + if (ret == UADK_DO_SOFT) + return sm2_prov_decrypt_sw(psm2ctx, out, outlen, in, inlen); + + return ret; +} + +static int sm2_prov_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size) +{ + struct sm2_ciphertext *sm2_ctext; + + sm2_ctext = d2i_SM2_Ciphertext(NULL, &ct, ct_size); + if (!sm2_ctext) { + UADK_ERR("invalid sm2 encoding\n"); + return UADK_P_FAIL; + } + + *pt_size = sm2_ctext->C2->length; + SM2_Ciphertext_free(sm2_ctext); + + return UADK_P_SUCCESS; +} + +static int uadk_asym_cipher_sm2_decrypt(void *vpsm2ctx, unsigned char *out, size_t *outlen, + size_t outsize, const unsigned char *in, size_t inlen) +{ + PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; + const EVP_MD *md; + + if (!psm2ctx) { + UADK_ERR("invalid: psm2ctx is NULL\n"); + return UADK_P_FAIL; + } + + md = sm2_prov_get_md(psm2ctx); + if (!md) { + UADK_ERR("invalid: md is NULL\n"); + return UADK_P_FAIL; + } + + if (!out) + return sm2_prov_plaintext_size(in, inlen, outlen); + + return sm2_prov_decrypt(psm2ctx, out, outlen, in, inlen); +} + +static int sm2_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src) +{ + if (src->alloc_md && !EVP_MD_up_ref(src->alloc_md)) + return UADK_P_FAIL; + + dst->engine = src->engine; + dst->md = src->md; + dst->alloc_md = src->alloc_md; + + return UADK_P_SUCCESS; +} + +static void *uadk_asym_cipher_sm2_dupctx(void *vpsm2ctx) +{ + PROV_SM2_ASYM_CTX *srcctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; + PROV_SM2_ASYM_CTX *dstctx; + int ret; + + if (!srcctx) { + UADK_ERR("src ctx is NULL\n"); + return NULL; + } + + dstctx = OPENSSL_zalloc(sizeof(PROV_SM2_ASYM_CTX)); + if (!dstctx) { + UADK_ERR("failed to alloc dst ctx\n"); + return NULL; + } + memcpy(dstctx, srcctx, sizeof(*dstctx)); + memset(&dstctx->md, 0, sizeof(dstctx->md)); + + if (srcctx->key && !EC_KEY_up_ref(srcctx->key)) { + OPENSSL_free(dstctx); + return NULL; + } + dstctx->key = srcctx->key; + + ret = sm2_prov_digest_copy(&dstctx->md, &srcctx->md); + if (ret == UADK_P_FAIL) { + uadk_asym_cipher_sm2_freectx(dstctx); + return NULL; + } + + return dstctx; +} + +static int uadk_asym_cipher_sm2_get_ctx_params(void *vpsm2ctx, OSSL_PARAM *params) +{ + PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; + const char *mdname; + const EVP_MD *md; + OSSL_PARAM *p; + + if (!psm2ctx) { + UADK_ERR("failed to get psm2ctx\n"); + return UADK_P_FAIL; + } + + if (!params) { + UADK_ERR("params is NULL\n"); + return UADK_P_FAIL; + } + + p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_DIGEST); + if (p) { + md = sm2_prov_digest_md(&psm2ctx->md); + mdname = md ? EVP_MD_get0_name(md) : ""; + if (!OSSL_PARAM_set_utf8_string(p, mdname)) { + UADK_ERR("failed to set utf8 string\n"); + return UADK_P_FAIL; + } + } + + return UADK_P_SUCCESS; +} + +static const OSSL_PARAM *uadk_asym_cipher_sm2_gettable_ctx_params(ossl_unused void *vpsm2ctx, + ossl_unused void *provctx) +{ + return sm2_asym_cipher_known_gettable_ctx_params; +} + +static const OSSL_PARAM *uadk_asym_cipher_sm2_settable_ctx_params(ossl_unused void *vpsm2ctx, + ossl_unused void *provctx) +{ + return sm2_asym_cipher_known_settable_ctx_params; +} diff --git a/src/uadk_prov_sm2_kmgmt.c b/src/uadk_prov_sm2_kmgmt.c index 2f6e2340..22871e61 100644 --- a/src/uadk_prov_sm2_kmgmt.c +++ b/src/uadk_prov_sm2_kmgmt.c @@ -26,8 +26,6 @@ #include "uadk_prov_pkey.h" #include "uadk_utils.h" -#define SM2_KEY_BYTES 32 - UADK_PKEY_KEYMGMT_DESCR(sm2, SM2); static UADK_PKEY_KEYMGMT s_keymgmt; diff --git a/src/uadk_prov_sm2_sign.c b/src/uadk_prov_sm2_sign.c new file mode 100644 index 00000000..27627c13 --- /dev/null +++ b/src/uadk_prov_sm2_sign.c @@ -0,0 +1,1342 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include "uadk_async.h" +#include "uadk_prov.h" +#include "uadk_prov_der_writer.h" +#include "uadk_prov_pkey.h" +#include "uadk_utils.h" + +#define SM2_GET_SIGNLEN 1 +#define SM2_DEFAULT_USERID "1234567812345678" +#define SM2_DEFAULT_USERID_LEN 16 +#define SM3_DIGEST_LENGTH 32 + +UADK_PKEY_SIGNATURE_DESCR(sm2, SM2); + +/* + * Provider sm2 signature algorithm context structure. + * Upper application will use, such as, EVP_PKEY_CTX *ctx, + * this structure will be called like: ctx->op.sig.algctx, + * the 'algctx' can be defined by our uadk_provider, which is + * the structure below. + */ +typedef struct { + OSSL_LIB_CTX *libctx; + char *propq; + /* Use EC_KEY refer to keymgmt */ + EC_KEY *key; + + /* + * Flag to termine if the 'z' digest needs to be computed and fed to the + * hash function. + * This flag should be set on initialization and the compuation should + * be performed only once, on first update. + */ + unsigned int flag_compute_z_digest : 1; + + char mdname[OSSL_MAX_NAME_SIZE]; + + /* The Algorithm Identifier of the combined signature algorithm */ + unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE]; + unsigned char *aid; + size_t aid_len; + + /* main digest */ + EVP_MD *md; + EVP_MD_CTX *mdctx; + size_t mdsize; + + /* + * SM2 ID used for calculating the Z value, + * distinguishing Identifier, ISO/IEC 15946-3 + */ + unsigned char *id; + size_t id_len; +} PROV_SM2_SIGN_CTX; + +struct sm2_param { + /* + * p: BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + */ + BIGNUM *p; + /* a: BIGNUM for parameter a of the equation */ + BIGNUM *a; + /* b: BIGNUM for parameter b of the equation */ + BIGNUM *b; + /* xG: BIGNUM for the x-coordinate value of G point */ + BIGNUM *xG; + /* yG: BIGNUM for the y-coordinate value of G point */ + BIGNUM *yG; + /* xA: BIGNUM for the x-coordinate value of PA point */ + BIGNUM *xA; + /* yA: BIGNUM for the y-coordinate value of PA point */ + BIGNUM *yA; +}; + +static const OSSL_PARAM sm2_sig_known_settable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DIST_ID, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM sm2_sig_known_gettable_ctx_params[] = { + OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0), + OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_END +}; + +static UADK_PKEY_SIGNATURE s_signature; + +static UADK_PKEY_SIGNATURE get_default_sm2_signature(void) +{ + return s_signature; +} + +void set_default_sm2_signature(void) +{ + UADK_PKEY_SIGNATURE *signature; + + signature = (UADK_PKEY_SIGNATURE *)EVP_SIGNATURE_fetch(NULL, "SM2", "provider=default"); + if (signature) { + s_signature = *signature; + EVP_SIGNATURE_free((EVP_SIGNATURE *)signature); + } else { + UADK_INFO("failed to EVP_SIGNATURE_fetch sm2 default provider\n"); + } +} + +static void *uadk_signature_sm2_newctx(void *provctx, const char *propq) +{ + PROV_SM2_SIGN_CTX *psm2ctx; + + psm2ctx = OPENSSL_zalloc(sizeof(PROV_SM2_SIGN_CTX)); + if (!psm2ctx) { + UADK_ERR("failed to alloc sm2 signature ctx\n"); + return NULL; + } + + if (propq) { + psm2ctx->propq = OPENSSL_strdup(propq); + if (!psm2ctx->propq) { + UADK_ERR("failed to dup propq\n"); + OPENSSL_free(psm2ctx); + return NULL; + } + } + + /* + * Use SM3 for digest method in default, other digest algs + * can be set with set_ctx_params API. + */ + psm2ctx->mdsize = SM3_DIGEST_LENGTH; + strcpy(psm2ctx->mdname, OSSL_DIGEST_NAME_SM3); + + /* The libctx maybe NULL, if libctx is NULL, will use default ctx. */ + psm2ctx->libctx = prov_libctx_of(provctx); + + return psm2ctx; +} + +static void uadk_signature_sm2_freectx(void *vpsm2ctx) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + + if (!psm2ctx) + return; + + EVP_MD_CTX_free(psm2ctx->mdctx); + EVP_MD_free(psm2ctx->md); + OPENSSL_free(psm2ctx->propq); + EC_KEY_free(psm2ctx->key); + OPENSSL_free(psm2ctx->id); + OPENSSL_free(psm2ctx); +} + +static int sm2_sig_set_mdname(PROV_SM2_SIGN_CTX *psm2ctx, const char *mdname) +{ + if (!psm2ctx->md) { + psm2ctx->md = EVP_MD_fetch(psm2ctx->libctx, + psm2ctx->mdname, psm2ctx->propq); + if (!psm2ctx->md) { + UADK_ERR("failed to fetch digest method\n"); + return UADK_P_FAIL; + } + } + + /* If mdname is NULL, no need to set, just return */ + if (!mdname) + return UADK_P_SUCCESS; + + /* psm2ctx->md is free in freectx */ + if (strlen(mdname) >= sizeof(psm2ctx->mdname) || + !EVP_MD_is_a(psm2ctx->md, mdname)) { + UADK_ERR("failed to check mdname, digest=%s\n", mdname); + return UADK_P_FAIL; + } + + OPENSSL_strlcpy(psm2ctx->mdname, mdname, sizeof(psm2ctx->mdname)); + + return UADK_P_SUCCESS; +} + +static handle_t sm2_alloc_sess(const EC_KEY *key) +{ + const EC_GROUP *group = EC_KEY_get0_group(key); + const BIGNUM *order = EC_GROUP_get0_order(group); + struct wd_ecc_sess_setup setup = {0}; + struct sched_params params = {0}; + handle_t sess; + + setup.alg = "sm2"; + setup.rand.cb = uadk_prov_ecc_get_rand; + setup.rand.usr = (void *)order; + if (!setup.rand.usr) { + UADK_ERR("failed to BN_bin2bn order\n"); + return (handle_t)0; + } + + /* Use the default numa parameters */ + params.numa_id = -1; + setup.sched_param = ¶ms; + sess = wd_ecc_alloc_sess(&setup); + if (sess == (handle_t)0) + UADK_ERR("failed to alloc sess\n"); + + return sess; +} + +static void sm2_free_sess(handle_t sess) +{ + wd_ecc_free_sess(sess); +} + +static int sm2_locate_id_digest(PROV_SM2_SIGN_CTX *psm2ctx, const OSSL_PARAM params[]) +{ + size_t tmp_idlen = 0; + const OSSL_PARAM *p; + void *tmp_id = NULL; + char *mdname = NULL; + size_t mdsize; + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DIST_ID); + if (p) { + if (!psm2ctx->flag_compute_z_digest) { + UADK_ERR("invalid: should set ID param before z digest\n"); + return UADK_P_FAIL; + } + + if (p->data_size && + !OSSL_PARAM_get_octet_string(p, &tmp_id, 0, &tmp_idlen)) { + UADK_ERR("failed to get sm2 sign id and len\n"); + return UADK_P_FAIL; + } + + OPENSSL_free(psm2ctx->id); + psm2ctx->id = tmp_id; + psm2ctx->id_len = tmp_idlen; + } + + /* + * The following code checks that the size is the same as the SM3 digest + * size returning an error otherwise. + * If there is ever any different digest algorithm allowed with SM2 + * this needs to be adjusted accordingly. + */ + p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); + if (p && (!OSSL_PARAM_get_size_t(p, &mdsize) || mdsize != psm2ctx->mdsize)) { + UADK_ERR("failed to locate digest size\n"); + return UADK_P_FAIL; + } + + p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST); + if (p) { + if (!OSSL_PARAM_get_utf8_string(p, &mdname, 0)) { + UADK_ERR("failed to get sm2 sign mdname\n"); + return UADK_P_FAIL; + } + + if (!sm2_sig_set_mdname(psm2ctx, mdname)) { + OPENSSL_free(mdname); + UADK_ERR("failed to set sm2 mdname\n"); + return UADK_P_FAIL; + } + + OPENSSL_free(mdname); + } + + return UADK_P_SUCCESS; +} + +static int uadk_signature_sm2_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM params[]) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + + /* + * 'set_ctx_param' function can be called independently, + * so check 'psm2ctx' again here. + */ + if (!psm2ctx) { + UADK_ERR("invalid: sm2 ctx is NULL for set_ctx_params\n"); + return UADK_P_FAIL; + } + + /* If params is NULL, no need to set ctx params, just return */ + if (!params) + return UADK_P_SUCCESS; + + return sm2_locate_id_digest(psm2ctx, params); +} + +static int sm2_signverify_init(void *vpsm2ctx, void *ec, const OSSL_PARAM params[]) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + + if (!psm2ctx) { + UADK_ERR("invalid: vpsm2ctx is NULL\n"); + return UADK_P_FAIL; + } + + if (!ec && !psm2ctx->key) { + UADK_ERR("invalid: sm2 key is NULL\n"); + return UADK_P_FAIL; + } + + if (ec) { + if (!EC_KEY_up_ref(ec)) { + UADK_ERR("failed to EC_KEY_up_ref\n"); + return UADK_P_FAIL; + } + EC_KEY_free(psm2ctx->key); + psm2ctx->key = (EC_KEY *)ec; + } + + return uadk_signature_sm2_set_ctx_params(vpsm2ctx, params); +} + +static int uadk_signature_sm2_sign_init(void *vpsm2ctx, void *ec, + const OSSL_PARAM params[]) +{ + return sm2_signverify_init(vpsm2ctx, ec, params); +} + +static int uadk_signature_sm2_verify_init(void *vpsm2ctx, void *ec, + const OSSL_PARAM params[]) +{ + return sm2_signverify_init(vpsm2ctx, ec, params); +} + +static int sm2_check_tbs_params(PROV_SM2_SIGN_CTX *psm2ctx, + const unsigned char *tbs, size_t tbslen) +{ + if (psm2ctx->mdsize && tbslen != psm2ctx->mdsize) { + UADK_ERR("invalid: tbslen(%zu) != mdsize(%zu)\n", + tbslen, psm2ctx->mdsize); + return UADK_P_FAIL; + } + + if (uadk_prov_is_all_zero(tbs, tbslen)) { + UADK_ERR("invalid: tbs all zero\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static int sm2_sign_init_iot(handle_t sess, struct wd_ecc_req *req, + void *digest, size_t digest_len) +{ + struct wd_ecc_out *ecc_out; + struct wd_ecc_in *ecc_in; + struct wd_dtb e = {0}; + + ecc_out = wd_sm2_new_sign_out(sess); + if (!ecc_out) { + UADK_ERR("failed to new sign out\n"); + return UADK_P_FAIL; + } + + e.data = digest; + e.dsize = digest_len; + e.bsize = digest_len; + ecc_in = wd_sm2_new_sign_in(sess, &e, NULL, NULL, 1); + if (!ecc_in) { + UADK_ERR("failed to new sign in\n"); + wd_ecc_del_out(sess, ecc_out); + return UADK_P_FAIL; + } + + uadk_prov_ecc_fill_req(req, WD_SM2_SIGN, ecc_in, ecc_out); + + return UADK_P_SUCCESS; +} + +static void sm2_sign_uninit_iot(handle_t sess, struct wd_ecc_req *req) +{ + wd_ecc_del_in(sess, req->src); + wd_ecc_del_out(sess, req->dst); +} + +static int sm2_sign_bin_to_ber(struct wd_ecc_req *req, + unsigned char *sig, size_t *siglen) +{ + struct wd_dtb *r = NULL; + struct wd_dtb *s = NULL; + BIGNUM *bn_r, *bn_s; + ECDSA_SIG *e_sig; + int sltmp, ret; + + wd_sm2_get_sign_out_params(req->dst, &r, &s); + if (!r || !s) { + UADK_ERR("failed to get sign result\n"); + return UADK_P_FAIL; + } + + e_sig = ECDSA_SIG_new(); + if (!e_sig) { + UADK_ERR("failed to ECDSA_SIG_new\n"); + return UADK_P_FAIL; + } + + bn_r = BN_bin2bn((const unsigned char *)r->data, r->dsize, NULL); + if (!bn_r) { + UADK_ERR("failed to BN_bin2bn r\n"); + goto free_sig; + } + + bn_s = BN_bin2bn((const unsigned char *)s->data, s->dsize, NULL); + if (!bn_s) { + UADK_ERR("failed to BN_bin2bn s\n"); + goto free_r; + } + + ret = ECDSA_SIG_set0(e_sig, bn_r, bn_s); + if (ret == 0) { + UADK_ERR("failed to ECDSA_SIG_set0\n"); + goto free_s; + } + + sltmp = i2d_ECDSA_SIG(e_sig, &sig); + if (sltmp < 0) { + UADK_ERR("failed to i2d_ECDSA_SIG\n"); + /* bs and br set to e_sig, use unified interface to prevent double release. */ + goto free_sig; + } + *siglen = (size_t)sltmp; + ECDSA_SIG_free(e_sig); + + return UADK_P_SUCCESS; + +free_s: + BN_free(bn_s); +free_r: + BN_free(bn_r); +free_sig: + ECDSA_SIG_free(e_sig); + + return UADK_P_FAIL; +} + +static int sm2_sign_ber_to_bin(unsigned char *sig, size_t sig_len, + struct wd_dtb *r, struct wd_dtb *s) +{ + const unsigned char *p = sig; + unsigned char *der = NULL; + const BIGNUM *bn_r, *bn_s; + ECDSA_SIG *e_sig; + int len1, len2; + + e_sig = ECDSA_SIG_new(); + if (e_sig == NULL) { + UADK_ERR("failed to ECDSA_SIG_new\n"); + return UADK_P_FAIL; + } + + if (d2i_ECDSA_SIG(&e_sig, &p, sig_len) == NULL) { + UADK_ERR("d2i_ECDSA_SIG error\n"); + goto free_sig; + } + + /* Ensure signature uses DER and doesn't have trailing garbage */ + len1 = i2d_ECDSA_SIG(e_sig, &der); + if (len1 != sig_len || memcmp(sig, der, len1) != 0) { + UADK_ERR("sig data error, der_len(%d), sig_len(%zu)\n", + len1, sig_len); + goto free_der; + } + + ECDSA_SIG_get0(e_sig, &bn_r, &bn_s); + if (!bn_r || !bn_s) { + UADK_ERR("failed to get r or s\n"); + goto free_der; + } + + len1 = BN_num_bytes(bn_r); + len2 = BN_num_bytes(bn_s); + if (len1 > UADK_ECC_MAX_KEY_BYTES || len2 > UADK_ECC_MAX_KEY_BYTES) { + UADK_ERR("r or s bytes = (%d, %d) error\n", len1, len2); + goto free_der; + } + r->dsize = BN_bn2bin(bn_r, (unsigned char *)r->data); + s->dsize = BN_bn2bin(bn_s, (unsigned char *)s->data); + + OPENSSL_free(der); + ECDSA_SIG_free(e_sig); + + return UADK_P_SUCCESS; + +free_der: + OPENSSL_free(der); +free_sig: + ECDSA_SIG_free(e_sig); + + return UADK_P_FAIL; +} + +static int sm2_sign_hw(PROV_SM2_SIGN_CTX *psm2ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + struct wd_ecc_req req = {0}; + handle_t sess; + int ret; + + /* Init with UADK */ + ret = uadk_prov_ecc_init("sm2"); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to init sm2\n"); + return UADK_DO_SOFT; + } + + sess = sm2_alloc_sess(psm2ctx->key); + if (sess == (handle_t)0) { + UADK_ERR("failed to alloc sess in sign\n"); + return UADK_P_FAIL; + } + + ret = sm2_sign_init_iot(sess, &req, (void *)tbs, tbslen); + if (ret == UADK_P_FAIL) + goto free_sess; + + ret = uadk_prov_ecc_set_private_key(sess, psm2ctx->key); + if (ret == UADK_P_FAIL) + goto uninit_iot; + + ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to do sm2 sign\n"); + ret = UADK_DO_SOFT; + goto uninit_iot; + } + + ret = sm2_sign_bin_to_ber(&req, sig, siglen); + +uninit_iot: + sm2_sign_uninit_iot(sess, &req); +free_sess: + sm2_free_sess(sess); + return ret; +} + +static int sm2_sign_sw(void *vpsm2ctx, unsigned char *sig, size_t *siglen, + size_t sigsize, const unsigned char *tbs, size_t tbslen) +{ + if (uadk_get_sw_offload_state() && get_default_sm2_signature().sign) { + UADK_INFO("switch to soft sm2 sign\n"); + return get_default_sm2_signature().sign(vpsm2ctx, sig, siglen, sigsize, + tbs, tbslen); + } + + return UADK_P_FAIL; +} + +static int uadk_signature_sm2_sign(void *vpsm2ctx, unsigned char *sig, size_t *siglen, + size_t sigsize, const unsigned char *tbs, size_t tbslen) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + size_t sltmp = 0; + int ret, ecsize; + + if (!psm2ctx || !psm2ctx->key) { + UADK_ERR("invalid: psm2ctx or key is NULL\n"); + return UADK_P_FAIL; + } + + ecsize = ECDSA_size(psm2ctx->key); + if (ecsize <= 0) { + UADK_ERR("ecsize error %d\n", ecsize); + return UADK_P_FAIL; + } + + if (!sig) { + *siglen = (size_t)ecsize; + return SM2_GET_SIGNLEN; + } + + if (sigsize < (size_t)ecsize) { + UADK_ERR("sigsize(%zu) < ecsize(%d)\n", sigsize, ecsize); + return UADK_P_FAIL; + } + + ret = sm2_check_tbs_params(psm2ctx, tbs, tbslen); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to check sm2 signature params\n"); + return UADK_P_FAIL; + } + + ret = sm2_sign_hw(psm2ctx, sig, &sltmp, tbs, tbslen); + if (ret != UADK_P_SUCCESS) { + UADK_ERR("failed to do sm2 sign\n"); + goto do_soft; + } + + *siglen = sltmp; + + return UADK_P_SUCCESS; + +do_soft: + if (ret == UADK_DO_SOFT) + return sm2_sign_sw(vpsm2ctx, sig, siglen, sigsize, tbs, tbslen); + + return UADK_P_FAIL; +} + +static int sm2_verify_init_iot(handle_t sess, struct wd_ecc_req *req, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + unsigned char buf_r[UADK_ECC_MAX_KEY_BYTES] = {0}; + unsigned char buf_s[UADK_ECC_MAX_KEY_BYTES] = {0}; + struct wd_ecc_in *ecc_in; + struct wd_dtb e = {0}; + struct wd_dtb r = {0}; + struct wd_dtb s = {0}; + int ret; + + r.data = (void *)buf_r; + s.data = (void *)buf_s; + r.bsize = UADK_ECC_MAX_KEY_BYTES; + s.bsize = UADK_ECC_MAX_KEY_BYTES; + ret = sm2_sign_ber_to_bin((void *)sig, siglen, &r, &s); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to sm2_sign_ber_to_bin\n"); + return ret; + } + + e.data = (void *)tbs; + e.dsize = tbslen; + e.bsize = tbslen; + ecc_in = wd_sm2_new_verf_in(sess, &e, &r, &s, NULL, 1); + if (!ecc_in) { + UADK_ERR("failed to new verf in\n"); + return UADK_P_FAIL; + } + + uadk_prov_ecc_fill_req(req, WD_SM2_VERIFY, ecc_in, NULL); + + return UADK_P_SUCCESS; +} + +static void sm2_verify_uninit_iot(handle_t sess, struct wd_ecc_req *req) +{ + wd_ecc_del_in(sess, req->src); +} + +static int sm2_verify_hw(PROV_SM2_SIGN_CTX *psm2ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + struct wd_ecc_req req = {0}; + handle_t sess; + int ret; + + /* Init with UADK */ + ret = uadk_prov_ecc_init("sm2"); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to init sm2\n"); + return UADK_DO_SOFT; + } + + sess = sm2_alloc_sess(psm2ctx->key); + if (sess == (handle_t)0) { + UADK_ERR("failed to alloc sess in verify\n"); + return UADK_P_FAIL; + } + + ret = sm2_verify_init_iot(sess, &req, sig, siglen, tbs, tbslen); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to sm2_verify_init_iot\n"); + goto free_sess; + } + + ret = uadk_prov_ecc_set_public_key(sess, psm2ctx->key); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to uadk_prov_ecc_set_public_key\n"); + goto uninit_iot; + } + + ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); + if (req.status == WD_VERIFY_ERR) { + ret = UADK_P_FAIL; + } else if (ret == UADK_P_FAIL) { + ret = UADK_DO_SOFT; + UADK_ERR("failed to do sm2 verify\n"); + } + +uninit_iot: + sm2_verify_uninit_iot(sess, &req); +free_sess: + sm2_free_sess(sess); + + return ret; +} + +static int sm2_verify_sw(void *vpsm2ctx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + if (uadk_get_sw_offload_state() && get_default_sm2_signature().verify) { + UADK_INFO("switch to soft sm2 verify\n"); + return get_default_sm2_signature().verify(vpsm2ctx, sig, siglen, tbs, tbslen); + } + + return UADK_P_FAIL; +} + +static int uadk_signature_sm2_verify(void *vpsm2ctx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + int ret; + + if (!psm2ctx) { + UADK_ERR("invalid: psm2ctx is NULL\n"); + return UADK_P_FAIL; + } + + ret = sm2_check_tbs_params(psm2ctx, tbs, tbslen); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to check sm2 verify params\n"); + return UADK_P_FAIL; + } + + ret = sm2_verify_hw(psm2ctx, sig, siglen, tbs, tbslen); + if (ret == UADK_DO_SOFT) + return sm2_verify_sw(vpsm2ctx, sig, siglen, tbs, tbslen); + + return ret; +} + +static int sm2_digest_signverify_init(void *vpsm2ctx, const char *mdname, + void *ec, const OSSL_PARAM params[]) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + int md_nid; + WPACKET pkt; + + if (!sm2_signverify_init(vpsm2ctx, ec, params) || + !sm2_sig_set_mdname(psm2ctx, mdname)) + return UADK_P_FAIL; + + /* psm2ctx->mdctx free in freectx */ + if (!psm2ctx->mdctx) { + psm2ctx->mdctx = EVP_MD_CTX_new(); + if (unlikely(!psm2ctx->mdctx)) { + UADK_ERR("failed to EVP_MD_CTX_new\n"); + return UADK_P_FAIL; + } + } + + /* + * We do not care about DER writing errors. + * All it really means is that for some reason, there's no + * AlgorithmIdentifier to be had, but the operation itself is + * still valid, just as long as it's not used to construct + * anything that needs an AlgorithmIdentifier. + */ + md_nid = EVP_MD_get_type(psm2ctx->md); + psm2ctx->aid_len = 0; + if (WPACKET_init_der(&pkt, psm2ctx->aid_buf, sizeof(psm2ctx->aid_buf)) && + ossl_DER_w_algorithmIdentifier_SM2_with_MD(&pkt, -1, psm2ctx->key, md_nid) && + WPACKET_finish(&pkt)) { + WPACKET_get_total_written(&pkt, &psm2ctx->aid_len); + psm2ctx->aid = WPACKET_get_curr(&pkt); + } + WPACKET_cleanup(&pkt); + + if (!EVP_DigestInit_ex2(psm2ctx->mdctx, psm2ctx->md, params)) { + UADK_ERR("failed to do digest init\n"); + return UADK_P_FAIL; + } + + psm2ctx->flag_compute_z_digest = 1; + + return UADK_P_SUCCESS; +} + +static int uadk_signature_sm2_digest_sign_init(void *vpsm2ctx, const char *mdname, + void *ec, const OSSL_PARAM params[]) +{ + return sm2_digest_signverify_init(vpsm2ctx, mdname, ec, params); +} + +static int sm2_get_params(struct sm2_param *params, BN_CTX *ctx) +{ + params->p = BN_CTX_get(ctx); + if (params->p == NULL) + goto end; + + params->a = BN_CTX_get(ctx); + if (params->a == NULL) + goto end; + + params->b = BN_CTX_get(ctx); + if (params->b == NULL) + goto end; + + params->xG = BN_CTX_get(ctx); + if (params->xG == NULL) + goto end; + + params->yG = BN_CTX_get(ctx); + if (params->yG == NULL) + goto end; + + params->xA = BN_CTX_get(ctx); + if (params->xA == NULL) + goto end; + + params->yA = BN_CTX_get(ctx); + if (params->yA == NULL) + goto end; + + return UADK_P_SUCCESS; + +end: + UADK_ERR("failed to get bn ctx for sm2 params\n"); + return UADK_P_FAIL; +} + +static int sm2_check_digest_evp_lib(const EVP_MD *digest, EVP_MD_CTX *hash, + const size_t id_len, const uint8_t *id) +{ + uint8_t e_byte; + uint16_t entl; + + if (!EVP_DigestInit(hash, digest)) { + UADK_ERR("error evp lib\n"); + return UADK_P_FAIL; + } + + /* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */ + if (id_len >= (UINT16_MAX >> TRANS_BITS_BYTES_SHIFT)) { + UADK_ERR("invalid: id too large\n"); + return UADK_P_FAIL; + } + + entl = (uint16_t)(id_len << TRANS_BITS_BYTES_SHIFT); + + /* Update the most significant (first) byte of 'entl' */ + e_byte = GET_MS_BYTE(entl); + if (!EVP_DigestUpdate(hash, &e_byte, 1)) { + UADK_ERR("failed to do EVP_DigestUpdate for e_byte's first byte\n"); + return UADK_P_FAIL; + } + + /* Update the least significant (second) byte of 'entl' */ + e_byte = GET_LS_BYTE(entl); + if (!EVP_DigestUpdate(hash, &e_byte, 1)) { + UADK_ERR("failed to do EVP_DigestUpdate for e_byte's second byte\n"); + return UADK_P_FAIL; + } + + if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) { + UADK_ERR("failed to do EVP_DigestUpdate for id\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static int sm2_check_equation_param(struct sm2_param *param, EVP_MD_CTX *hash, + uint8_t *buf, int p_bytes) +{ + if (BN_bn2binpad(param->a, buf, p_bytes) < 0 || + !EVP_DigestUpdate(hash, buf, p_bytes) || + BN_bn2binpad(param->b, buf, p_bytes) < 0 || + !EVP_DigestUpdate(hash, buf, p_bytes)) { + UADK_ERR("failed to check equation param\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static int sm2_check_base_point_group_param(struct sm2_param *param, + BN_CTX *ctx, const EC_KEY *key) +{ + const EC_GROUP *group = EC_KEY_get0_group(key); + + if (!EC_POINT_get_affine_coordinates(group, + EC_GROUP_get0_generator(group), + param->xG, param->yG, ctx)) { + UADK_ERR("failed to check base point group param\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static int sm2_check_base_point_param(struct sm2_param *param, EVP_MD_CTX *hash, + uint8_t *buf, int p_bytes) +{ + if (BN_bn2binpad(param->xG, buf, p_bytes) < 0 || + !EVP_DigestUpdate(hash, buf, p_bytes) || + BN_bn2binpad(param->yG, buf, p_bytes) < 0 || + !EVP_DigestUpdate(hash, buf, p_bytes)) { + UADK_ERR("failed to check base point param\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static int sm2_check_pkey_point_group_param(struct sm2_param *param, + BN_CTX *ctx, const EC_KEY *key) +{ + const EC_GROUP *group = EC_KEY_get0_group(key); + + if (!EC_POINT_get_affine_coordinates(group, + EC_KEY_get0_public_key(key), + param->xA, param->yA, ctx)) { + UADK_ERR("failed to check pkey point group param\n"); + return UADK_P_FAIL; + } + return UADK_P_SUCCESS; +} + +static int sm2_check_pkey_point_param(struct sm2_param *param, EVP_MD_CTX *hash, + uint8_t *buf, int p_bytes, uint8_t *out) +{ + if (BN_bn2binpad(param->xA, buf, p_bytes) < 0 || + !EVP_DigestUpdate(hash, buf, p_bytes) || + BN_bn2binpad(param->yA, buf, p_bytes) < 0 || + !EVP_DigestUpdate(hash, buf, p_bytes) || + !EVP_DigestFinal(hash, out, NULL)) { + UADK_ERR("failed to check pkey point param\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static int sm2_compute_z_digest(uint8_t *out, const EVP_MD *digest, + const uint8_t *id, const size_t id_len, + const EC_KEY *key) +{ + const EC_GROUP *group = EC_KEY_get0_group(key); + struct sm2_param *params; + int ret = UADK_P_FAIL; + EVP_MD_CTX *hash; + uint8_t *buf; + BN_CTX *ctx; + int p_bytes; + + hash = EVP_MD_CTX_new(); + if (!hash) + return UADK_P_FAIL; + + ctx = BN_CTX_new_ex(key->libctx); + if (!ctx) + goto free_hash; + + params = OPENSSL_zalloc(sizeof(struct sm2_param)); + if (!params) { + UADK_ERR("failed to malloc sm2 param\n"); + goto free_ctx; + } + + if (!sm2_get_params(params, ctx)) + goto free_params; + + if (!sm2_check_digest_evp_lib(digest, hash, id_len, id)) + goto free_params; + + if (!EC_GROUP_get_curve(group, params->p, params->a, params->b, ctx)) { + UADK_ERR("failed to EC_GROUP_get_curve\n"); + goto free_params; + } + + p_bytes = BN_num_bytes(params->p); + buf = OPENSSL_zalloc(p_bytes); + if (!buf) { + UADK_ERR("failed to alloc buffer\n"); + goto free_params; + } + + if (!sm2_check_equation_param(params, hash, buf, p_bytes) || + !sm2_check_base_point_group_param(params, ctx, key) || + !sm2_check_base_point_param(params, hash, buf, p_bytes) || + !sm2_check_pkey_point_group_param(params, ctx, key) || + !sm2_check_pkey_point_param(params, hash, buf, p_bytes, out)) + goto free_buf; + + ret = UADK_P_SUCCESS; + +free_buf: + OPENSSL_free(buf); +free_params: + OPENSSL_free(params); +free_ctx: + BN_CTX_free(ctx); +free_hash: + EVP_MD_CTX_free(hash); + return ret; +} + +static int sm2_sig_compute_z_digest(PROV_SM2_SIGN_CTX *psm2ctx) +{ + uint8_t *z; + int ret; + + if (psm2ctx->flag_compute_z_digest) { + /* Only do this once */ + psm2ctx->flag_compute_z_digest = 0; + + z = OPENSSL_zalloc(psm2ctx->mdsize); + if (!z) { + UADK_ERR("failed to alloc z\n"); + return UADK_P_FAIL; + } + + /* if id is not set, use default id */ + if (!psm2ctx->id) { + /* psm2ctx id will be freed in uadk_signature_sm2_freectx, not here */ + psm2ctx->id = OPENSSL_memdup(SM2_DEFAULT_USERID, SM2_DEFAULT_USERID_LEN); + if (!psm2ctx->id) { + UADK_ERR("failed to memdup psm2ctx id\n"); + goto free_z; + } + psm2ctx->id_len = SM2_DEFAULT_USERID_LEN; + } + + /* get hashed prefix 'z' of tbs message */ + ret = sm2_compute_z_digest(z, psm2ctx->md, psm2ctx->id, + psm2ctx->id_len, psm2ctx->key); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to sm2_compute_z_digest\n"); + goto free_z; + } + + ret = EVP_DigestUpdate(psm2ctx->mdctx, z, psm2ctx->mdsize); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to EVP_DigestUpdate\n"); + goto free_z; + } + OPENSSL_free(z); + } + + return UADK_P_SUCCESS; + +free_z: + OPENSSL_free(z); + return UADK_P_FAIL; +} + +static int sm2_digest_signverify_update(void *vpsm2ctx, const unsigned char *data, size_t datalen) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + int ret; + + if (!psm2ctx || !psm2ctx->mdctx) { + UADK_ERR("invalid: psm2ctx or mdctx is NULL in digest sign update\n"); + return UADK_P_FAIL; + } + + ret = sm2_sig_compute_z_digest(psm2ctx); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to compute z digest\n"); + return UADK_P_FAIL; + } + + ret = EVP_DigestUpdate(psm2ctx->mdctx, data, datalen); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to EVP_DigestUpdate\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static int uadk_signature_sm2_digest_sign_update(void *vpsm2ctx, + const unsigned char *data, + size_t datalen) +{ + return sm2_digest_signverify_update(vpsm2ctx, data, datalen); +} + +static int uadk_signature_sm2_digest_sign_final(void *vpsm2ctx, unsigned char *sig, + size_t *siglen, size_t sigsize) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int dlen = 0; + int ret; + + if (!psm2ctx || !psm2ctx->mdctx) { + UADK_ERR("invalid: psm2ctx or mdctx is NULL\n"); + return UADK_P_FAIL; + } + + /* + * If sig is NULL then we're just finding out the sig size. Other fields + * are ignored. Defer to sm2sig_sign. + */ + if (sig) { + ret = sm2_sig_compute_z_digest(psm2ctx); + if (ret == UADK_P_FAIL) + return ret; + + ret = EVP_DigestFinal_ex(psm2ctx->mdctx, digest, &dlen); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to do EVP_DigestFinal_ex\n"); + return ret; + } + } + + return uadk_signature_sm2_sign(vpsm2ctx, sig, siglen, sigsize, digest, (size_t)dlen); +} + +static int uadk_signature_sm2_digest_verify_init(void *vpsm2ctx, const char *mdname, + void *ec, const OSSL_PARAM params[]) +{ + return sm2_digest_signverify_init(vpsm2ctx, mdname, ec, params); +} + +static int uadk_signature_sm2_digest_verify_update(void *vpsm2ctx, const unsigned char *data, + size_t datalen) +{ + return sm2_digest_signverify_update(vpsm2ctx, data, datalen); +} + +static int uadk_signature_sm2_digest_verify_final(void *vpsm2ctx, const unsigned char *sig, + size_t siglen) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int dlen = 0; + int ret, size; + + if (!psm2ctx || !psm2ctx->mdctx || !psm2ctx->md) { + UADK_ERR("invalid: psm2ctx or mdctx is NULL\n"); + return UADK_P_FAIL; + } + + size = EVP_MD_get_size(psm2ctx->md); + if (size > EVP_MAX_MD_SIZE) { + UADK_ERR("invalid: md size(%d) > %d\n", size, EVP_MAX_MD_SIZE); + return UADK_P_FAIL; + } + + ret = sm2_sig_compute_z_digest(psm2ctx); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to do sm2_sig_compute_z_digest\n"); + return ret; + } + + ret = EVP_DigestFinal_ex(psm2ctx->mdctx, digest, &dlen); + if (ret == UADK_P_FAIL) { + UADK_ERR("failed to do EVP_DigestFinal_ex, dlen = %u\n", dlen); + return ret; + } + + return uadk_signature_sm2_verify(vpsm2ctx, sig, siglen, digest, (size_t)dlen); +} + +static const OSSL_PARAM *uadk_signature_sm2_settable_ctx_md_params(void *vpsm2ctx) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + + if (!psm2ctx || !psm2ctx->md) { + UADK_ERR("invalid: psm2ctx or md is NULL\n"); + return NULL; + } + + return EVP_MD_settable_ctx_params(psm2ctx->md); +} + +static int uadk_signature_sm2_set_ctx_md_params(void *vpsm2ctx, const OSSL_PARAM params[]) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + + if (!psm2ctx || !psm2ctx->mdctx) { + UADK_ERR("invalid: psm2ctx or mdctx is NULL\n"); + return UADK_P_FAIL; + } + + return EVP_MD_CTX_set_params(psm2ctx->mdctx, params); +} + +static const OSSL_PARAM *uadk_signature_sm2_gettable_ctx_md_params(void *vpsm2ctx) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + + if (!psm2ctx || !psm2ctx->md) { + UADK_ERR("invalid: psm2ctx or md is NULL for gettable_ctx_md_params\n"); + return NULL; + } + + return EVP_MD_gettable_ctx_params(psm2ctx->md); +} + +static int uadk_signature_sm2_get_ctx_md_params(void *vpsm2ctx, OSSL_PARAM *params) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + + if (!psm2ctx || !psm2ctx->mdctx) { + UADK_ERR("invalid: psm2ctx or mdctx is NULL for get_ctx_md_params\n"); + return UADK_P_FAIL; + } + + return EVP_MD_CTX_get_params(psm2ctx->mdctx, params); +} + +static const OSSL_PARAM *uadk_signature_sm2_settable_ctx_params(ossl_unused void *vpsm2ctx, + ossl_unused void *provctx) +{ + return sm2_sig_known_settable_ctx_params; +} + +static const OSSL_PARAM *uadk_signature_sm2_gettable_ctx_params(ossl_unused void *vpsm2ctx, + ossl_unused void *provctx) +{ + return sm2_sig_known_gettable_ctx_params; +} + +static int uadk_signature_sm2_get_ctx_params(void *vpsm2ctx, OSSL_PARAM *params) +{ + PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + OSSL_PARAM *p; + + if (!psm2ctx) { + UADK_ERR("invalid: psm2ctx is NULL for get_ctx_params\n"); + return UADK_P_FAIL; + } + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID); + if (p && !OSSL_PARAM_set_octet_string(p, psm2ctx->aid, psm2ctx->aid_len)) { + UADK_ERR("failed to locate algorithm id\n"); + return UADK_P_FAIL; + } + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); + if (p && !OSSL_PARAM_set_size_t(p, psm2ctx->mdsize)) { + UADK_ERR("failed to locate digest size\n"); + return UADK_P_FAIL; + } + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST); + if (p && !OSSL_PARAM_set_utf8_string(p, !psm2ctx->md ? + psm2ctx->mdname : + EVP_MD_get0_name(psm2ctx->md))) { + UADK_ERR("failed to locate digest\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +static void *uadk_signature_sm2_dupctx(void *vpsm2ctx) +{ + PROV_SM2_SIGN_CTX *srcctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; + PROV_SM2_SIGN_CTX *dstctx; + + if (!srcctx) { + UADK_ERR("invalid: src ctx is NULL to dupctx!\n"); + return NULL; + } + + dstctx = OPENSSL_zalloc(sizeof(PROV_SM2_SIGN_CTX)); + if (!dstctx) { + UADK_ERR("failed to alloc dst ctx\n"); + return NULL; + } + memcpy(dstctx, srcctx, sizeof(*dstctx)); + dstctx->key = NULL; + dstctx->propq = NULL; + dstctx->md = NULL; + dstctx->mdctx = NULL; + dstctx->id = NULL; + + if (srcctx->key && !EC_KEY_up_ref(srcctx->key)) { + UADK_ERR("failed to check srcctx key reference\n"); + goto free_ctx; + } + dstctx->key = srcctx->key; + + if (srcctx->propq) { + dstctx->propq = OPENSSL_strdup(srcctx->propq); + if (!dstctx->propq) + goto free_ctx; + } + + if (srcctx->md && !EVP_MD_up_ref(srcctx->md)) + goto free_ctx; + dstctx->md = srcctx->md; + + if (srcctx->mdctx) { + dstctx->mdctx = EVP_MD_CTX_new(); + if (!dstctx->mdctx || + !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx)) + goto free_ctx; + } + + if (srcctx->id) { + dstctx->id = OPENSSL_memdup(srcctx->id, srcctx->id_len); + if (!dstctx->id) + goto free_ctx; + } + + return dstctx; + +free_ctx: + uadk_signature_sm2_freectx(dstctx); + return NULL; +} + +static int uadk_signature_sm2_verify_recover_init(void *vpsm2ctx, void *vsm2, + const OSSL_PARAM params[]) +{ + return UADK_P_SUCCESS; +} + +static int uadk_signature_sm2_verify_recover(void *vpsm2ctx, unsigned char *rout, + size_t *routlen, size_t routsize, + const unsigned char *sig, size_t siglen) +{ + return UADK_P_SUCCESS; +}