[PATCH 00/16] uadk_engine synchronizes some patches
From: parm64 <parm64@huawei.com> Weili Qian (9): uadk_provider: set the default provider when initializing the uadk provider uadk_engine: release asynchronous resources before destroying algorithm resources uadk_provider: release asynchronous resources before destroying algorithm resources uadk_provider/sm2: move sm2 key generation into a separate file uadk_provider/sm2: modify the return value of keygen uadk_provider/sm2: remove unnecessary code uadk_engine/ecc: remove unnecessary code uadk_engine: fix compilation warnings uadk_provider/sm2: split uadk_prov_sm2.c into 2 files Zhushuai Yin (3): uadk_provider: reduce lock scope during prov init to improve perf uadk_engine: reduce lock scope during prov init to improve perf uadk_provider: delete asynchronous redundancy declaration lizhi (4): uadk_provider: adapt uadk_provider with tls 1.3 uadk_provider: adapt rsa key management with pss padding mode uadk_provider: adapt rsa pss key management with algorithm enable configuration. uadk_engine/ecc: fix memory leak in the ecx algorithm src/Makefile.am | 4 +- src/uadk_aead.c | 1 + src/uadk_async.h | 1 - src/uadk_cipher.c | 1 + src/uadk_cipher_adapter.c | 2 +- src/uadk_dh.c | 1 + src/uadk_digest.c | 1 + src/uadk_ec.c | 34 +- src/uadk_ecx.c | 1 + src/uadk_engine_init.c | 8 +- src/uadk_pkey.c | 1 + src/uadk_prov.h | 19 +- src/uadk_prov_aead.c | 18 +- src/uadk_prov_capabilities.c | 224 +++ src/uadk_prov_cipher.c | 70 +- src/uadk_prov_dh.c | 66 +- src/uadk_prov_digest.c | 18 +- src/uadk_prov_ec_kmgmt.c | 19 + src/uadk_prov_ecdh_exch.c | 33 +- src/uadk_prov_ecx.c | 125 +- src/uadk_prov_hmac.c | 24 +- src/uadk_prov_init.c | 96 +- src/uadk_prov_pkey.c | 14 +- src/uadk_prov_pkey.h | 21 +- src/uadk_prov_rsa.c | 14 +- src/uadk_prov_rsa_enc.c | 34 +- src/uadk_prov_rsa_kmgmt.c | 101 ++ src/uadk_prov_rsa_sign.c | 34 +- src/uadk_prov_sm2.c | 3320 ---------------------------------- src/uadk_prov_sm2_enc.c | 860 +++++++++ src/uadk_prov_sm2_kmgmt.c | 505 ++++++ src/uadk_prov_sm2_sign.c | 1342 ++++++++++++++ src/uadk_rsa.c | 1 + 33 files changed, 3398 insertions(+), 3615 deletions(-) create mode 100644 src/uadk_prov_capabilities.c delete mode 100644 src/uadk_prov_sm2.c create mode 100644 src/uadk_prov_sm2_enc.c create mode 100644 src/uadk_prov_sm2_kmgmt.c create mode 100644 src/uadk_prov_sm2_sign.c -- 2.43.0
From: Weili Qian <qianweili@huawei.com> 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 <qianweili@huawei.com> --- 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 ac0de58..62a26fe 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 5bbab62..a89e555 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 d3d4763..bd5cbd9 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 898e367..3ee7e5e 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 878ac96..ebdfec4 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_KEYEXCH_free((EVP_KEYEXCH *)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_KEYEXCH_free((EVP_KEYEXCH *)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 0e050e1..406a0e3 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 7891011..7a77c5c 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 d4f8106..c6545c4 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 f71eed3..a3cf065 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 5009a0b..a297601 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 03c4e1e..83378f1 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 @@ free_ec_key: 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)); -- 2.43.0
From: Weili Qian <qianweili@huawei.com> 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 <qianweili@huawei.com> --- 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 48498c3..d7d71c8 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); -- 2.43.0
From: Weili Qian <qianweili@huawei.com> 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 <qianweili@huawei.com> --- 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 406a0e3..92ecc68 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; -- 2.43.0
From: Zhushuai Yin <yinzhushuai@huawei.com> 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 <yinzhushuai@huawei.com> --- 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 4533540..cef0503 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 0bb4aae..d442d3d 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 a89e555..2d96a1d 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 d9c5ae3..1a5cc81 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 e1a8b10..0c53d12 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 9597e7f..994ea07 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 a0bb26e..f77f718 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; } -- 2.43.0
From: Zhushuai Yin <yinzhushuai@huawei.com> 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 <yinzhushuai@huawei.com> --- 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 6920c04..db5faf7 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 9029ece..4067fb6 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 cae7d0a..e49250b 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 88e7fc8..c8372b4 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 fb45ccc..c5f711b 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 160ab8c..318f8ed 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); -- 2.43.0
From: Weili Qian <qianweili@huawei.com> 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 <qianweili@huawei.com> --- 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 447431c..6b035cc 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 83378f1..cfaa440 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 0000000..7bd7c20 --- /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 <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/bn.h> +#include <openssl/engine.h> +#include <uadk/wd_ecc.h> +#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; +} -- 2.43.0
From: Weili Qian <qianweili@huawei.com> 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 <qianweili@huawei.com> --- 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 7bd7c20..cf62677 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"); -- 2.43.0
From: Weili Qian <qianweili@huawei.com> The implementation in uadk_prov_sm2_check_priv_key() is meaningless, remove it. Signed-off-by: Weili Qian <qianweili@huawei.com> --- 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 cf62677..2f6e234 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 @@ uninit_iot: wd_ecc_del_out(sess, req.dst); free_sess: wd_ecc_free_sess(sess); -error: return UADK_P_FAIL; } -- 2.43.0
From: Weili Qian <qianweili@huawei.com> The implementation in eckey_create_key() is meaningless, remove it. Signed-off-by: Weili Qian <qianweili@huawei.com> --- src/uadk_ec.c | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/src/uadk_ec.c b/src/uadk_ec.c index eac59b5..fb83db6 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; -- 2.43.0
From: Zhushuai Yin <yinzhushuai@huawei.com> 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 <yinzhushuai@huawei.com> --- src/uadk_async.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/uadk_async.h b/src/uadk_async.h index 4aebf05..e35d286 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 -- 2.43.0
From: lizhi <lizhi206@huawei.com> Add support for OSSL_FUNC_PROVIDER_GET_CAPABILITIES to enable TLS 1.3 compatibility. Signed-off-by: lizhi <lizhi206@huawei.com> --- 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 6b035cc..7c1e1c5 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 62a26fe..60031cb 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -17,6 +17,7 @@ */ #ifndef UADK_PROV_H #define UADK_PROV_H +#include <openssl/bio.h> #include <openssl/core_dispatch.h> #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 0000000..18d2903 --- /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 <assert.h> +#include <string.h> +#include <openssl/core_dispatch.h> +#include <openssl/core_names.h> +/* For TLS1_VERSION etc */ +#include <openssl/prov_ssl.h> +#include <openssl/params.h> +#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 ebdfec4..243b977 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 92ecc68..03a3485 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -19,7 +19,6 @@ #include <stdio.h> #include <string.h> -#include <openssl/bio.h> #include <openssl/core_dispatch.h> #include <openssl/core_names.h> #include <openssl/crypto.h> @@ -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 } }; -- 2.43.0
From: lizhi <lizhi206@huawei.com> Add support for RSA key management with pss padding mode. Test with: openssl3 genpkey -provider uadk_provider -algorithm RSA-PSS Signed-off-by: lizhi <lizhi206@huawei.com> --- 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 60031cb..f162854 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 03a3485..b5d94e0 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 a3cf065..1286ae5 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 } +}; -- 2.43.0
From: lizhi <lizhi206@huawei.com> 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 <lizhi206@huawei.com> --- 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 b5d94e0..38d7426 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")) || -- 2.43.0
From: lizhi <lizhi206@huawei.com> Memory alloced in ecx derive function should be released before returning keysize to OpenSSL. Signed-off-by: lizhi <lizhi206@huawei.com> --- src/uadk_ecx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/uadk_ecx.c b/src/uadk_ecx.c index c9cc6c0..3e79a54 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; } -- 2.43.0
From: Weili Qian <qianweili@huawei.com> 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 <qianweili@huawei.com> --- 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 f2559ab..20e936f 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 fb83db6..0fbbf46 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 f162854..c802c71 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; -- 2.43.0
From: Weili Qian <qianweili@huawei.com> 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 <qianweili@huawei.com> --- 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 7c1e1c5..d30d599 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 7a77c5c..e82df34 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 cfaa440..0000000 --- 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 <openssl/err.h> -#include <openssl/evp.h> -#include <openssl/err.h> -#include <openssl/bn.h> -#include <openssl/engine.h> -#include <uadk/wd_ecc.h> -#include <uadk/wd_sched.h> -#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 0000000..e987202 --- /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 <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/err.h> +#include <openssl/bn.h> +#include <openssl/engine.h> +#include <uadk/wd_ecc.h> +#include <uadk/wd_sched.h> +#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 2f6e234..22871e6 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 0000000..27627c1 --- /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 <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/err.h> +#include <openssl/bn.h> +#include <openssl/engine.h> +#include <uadk/wd_ecc.h> +#include <uadk/wd_sched.h> +#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; +} -- 2.43.0
participants (1)
-
ZongYu Wu