diff --git a/configure.ac b/configure.ac index 0fc14edf..7f52738d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,19 +1,39 @@ -AC_PREREQ([2.69]) -AC_INIT([uadk_engine], [1.2]) +AC_PREREQ([2.71]) +AC_INIT([uadk_engine],[1.2]) AM_INIT_AUTOMAKE([1.10 no-define]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) AC_PROG_CC -AC_PROG_LIBTOOL -AM_PROG_LIBTOOL +LT_INIT +LT_INIT AC_ARG_ENABLE(kae, AS_HELP_STRING([--enable-kae],[Enable kae support])) AC_SUBST(enable_kae) AM_CONDITIONAL([WD_KAE], [test "$enable_kae" = "yes"]) +AC_ARG_ENABLE(rsa, + AS_HELP_STRING([--enable-rsa],[enable rsa support])) +AC_SUBST(enable_rsa) +AM_CONDITIONAL([DISABLE_RSA],[test "$enable_rsa" = "no"]) + +AC_ARG_ENABLE(dh, + AS_HELP_STRING([--enable-dh],[enable dh support])) +AC_SUBST(enable_dh) +AM_CONDITIONAL([DISABLE_DH],[test "$enable_dh"="no"]) + +AC_ARG_ENABLE(x448, + AS_HELP_STRING([--enable-x448],[enable x448 support])) +AC_SUBST(enable_x448) +AM_CONDITIONAL([DISABLE_X448],[test "$enable_x448" = "no"]) + +AC_ARG_ENABLE(x25519, + AS_HELP_STRING([--enable-x25519],[enable x25519 support])) +AC_SUBST(enable_x25519) +AM_CONDITIONAL([DISABLE_X25519],[test "$enable_x25519" = "no"]) + PKG_CHECK_MODULES(WD, libwd libwd_crypto, [with_wd=yes], [with_wd=no]) AM_CONDITIONAL(HAVE_WD, [test "$with_wd" != "no"]) diff --git a/src/Makefile.am b/src/Makefile.am index 9d5102ad..1ce362df 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,8 @@ VERSION = 1:2 ACLOCAL_AMFLAGS = -I m4 +uadk_engine_la_CFLAGS=$(WD_CFLAGS) $(libcrypto_CFLAGS) + if HAVE_CRYPTO lib_LTLIBRARIES=uadk_engine.la endif #HAVE_CRYPTO @@ -10,12 +12,32 @@ lib_LTLIBRARIES=uadk_provider.la endif #HAVE_CRYPTO3 uadk_engine_la_SOURCES=uadk_utils.c uadk_engine_init.c uadk_cipher.c \ - uadk_digest.c uadk_async.c uadk_rsa.c uadk_sm2.c \ - uadk_pkey.c uadk_dh.c uadk_ec.c uadk_ecx.c + uadk_digest.c uadk_async.c uadk_sm2.c \ + uadk_pkey.c uadk_ec.c +if DISABLE_RSA + uadk_engine_la_CFLAGS+=-DDISABLE_RSA +else + uadk_engine_la_SOURCES+=uadk_rsa.c +endif + +if DISABLE_DH + uadk_engine_la_CFLAGS+=-DDISABLE_DH +else + uadk_engine_la_SOURCES+=uadk_dh.c +endif + +if DISABLE_X448 + uadk_engine_la_CFLAGS+=-DDISABLE_X448 +endif + +if DISABLE_X25519 + uadk_engine_la_CFLAGS+=-DDISABLE_X25519 +endif + uadk_engine_la_LIBADD=-ldl $(WD_LIBS) -lpthread uadk_engine_la_LDFLAGS=-module -version-number $(VERSION) -uadk_engine_la_CFLAGS=$(WD_CFLAGS) $(libcrypto_CFLAGS) + uadk_engine_la_CFLAGS+=-DCRYPTO AUTOMAKE_OPTIONS = subdir-objects @@ -26,16 +48,9 @@ uadk_engine_la_SOURCES+=v1/alg/ciphers/sec_ciphers.c \ v1/alg/ciphers/sec_ciphers_soft.c \ v1/alg/ciphers/sec_ciphers_utils.c \ v1/alg/ciphers/sec_ciphers_wd.c \ - v1/alg/dh/hpre_dh.c \ - v1/alg/dh/hpre_dh_soft.c \ - v1/alg/dh/hpre_dh_wd.c \ v1/alg/digests/sec_digests.c \ v1/alg/digests/sec_digests_soft.c \ v1/alg/digests/sec_digests_wd.c \ - v1/alg/pkey/hpre_rsa.c \ - v1/alg/pkey/hpre_rsa_soft.c \ - v1/alg/pkey/hpre_rsa_utils.c \ - v1/alg/pkey/hpre_wd.c \ v1/wdmngr/wd_alg_queue.c \ v1/wdmngr/wd_queue_memory.c \ v1/utils/engine_check.c \ @@ -48,6 +63,18 @@ uadk_engine_la_SOURCES+=v1/alg/ciphers/sec_ciphers.c \ v1/async/async_event.c \ v1/async/async_poll.c \ v1/async/async_task_queue.c +if !DISABLE_DH + uadk_engine_la_SOURCES+=v1/alg/dh/hpre_dh.c \ + v1/alg/dh/hpre_dh_soft.c \ + v1/alg/dh/hpre_dh_wd.c +endif +if !DISABLE_RSA + uadk_engine_la_SOURCES+=v1/alg/pkey/hpre_rsa.c \ + v1/alg/pkey/hpre_rsa_soft.c \ + v1/alg/pkey/hpre_rsa_utils.c \ + v1/alg/pkey/hpre_wd.c +endif + endif #WD_KAE uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \ diff --git a/src/Makefile.am.orig b/src/Makefile.am.orig new file mode 100644 index 00000000..9d5102ad --- /dev/null +++ b/src/Makefile.am.orig @@ -0,0 +1,60 @@ +VERSION = 1:2 +ACLOCAL_AMFLAGS = -I m4 + +if HAVE_CRYPTO +lib_LTLIBRARIES=uadk_engine.la +endif #HAVE_CRYPTO + +if HAVE_CRYPTO3 +lib_LTLIBRARIES=uadk_provider.la +endif #HAVE_CRYPTO3 + +uadk_engine_la_SOURCES=uadk_utils.c uadk_engine_init.c uadk_cipher.c \ + uadk_digest.c uadk_async.c uadk_rsa.c uadk_sm2.c \ + uadk_pkey.c uadk_dh.c uadk_ec.c uadk_ecx.c + +uadk_engine_la_LIBADD=-ldl $(WD_LIBS) -lpthread +uadk_engine_la_LDFLAGS=-module -version-number $(VERSION) +uadk_engine_la_CFLAGS=$(WD_CFLAGS) $(libcrypto_CFLAGS) +uadk_engine_la_CFLAGS+=-DCRYPTO + +AUTOMAKE_OPTIONS = subdir-objects + +if WD_KAE +uadk_engine_la_CFLAGS += -DKAE +uadk_engine_la_SOURCES+=v1/alg/ciphers/sec_ciphers.c \ + v1/alg/ciphers/sec_ciphers_soft.c \ + v1/alg/ciphers/sec_ciphers_utils.c \ + v1/alg/ciphers/sec_ciphers_wd.c \ + v1/alg/dh/hpre_dh.c \ + v1/alg/dh/hpre_dh_soft.c \ + v1/alg/dh/hpre_dh_wd.c \ + v1/alg/digests/sec_digests.c \ + v1/alg/digests/sec_digests_soft.c \ + v1/alg/digests/sec_digests_wd.c \ + v1/alg/pkey/hpre_rsa.c \ + v1/alg/pkey/hpre_rsa_soft.c \ + v1/alg/pkey/hpre_rsa_utils.c \ + v1/alg/pkey/hpre_wd.c \ + v1/wdmngr/wd_alg_queue.c \ + v1/wdmngr/wd_queue_memory.c \ + v1/utils/engine_check.c \ + v1/utils/engine_config.c \ + v1/utils/engine_fork.c \ + v1/utils/engine_log.c \ + v1/utils/engine_opensslerr.c \ + v1/utils/engine_utils.c \ + v1/async/async_callback.c \ + v1/async/async_event.c \ + v1/async/async_poll.c \ + v1/async/async_task_queue.c +endif #WD_KAE + +uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \ + uadk_prov_digest.c uadk_prov_cipher.c \ + uadk_prov_rsa.c + +uadk_provider_la_LDFLAGS=-module -version-number $(VERSION) +uadk_provider_la_LIBADD=$(WD_LIBS) -lpthread +uadk_provider_la_CFLAGS=$(WD_CFLAGS) $(libcrypto_CFLAGS) +uadk_provider_la_CFLAGS+=-DOPENSSL_SUPPRESS_DEPRECATED diff --git a/src/uadk_engine_init.c b/src/uadk_engine_init.c index e2aa3925..d4e7ebd9 100644 --- a/src/uadk_engine_init.c +++ b/src/uadk_engine_init.c @@ -202,10 +202,16 @@ static int uadk_destroy(ENGINE *e) sec_ciphers_free_ciphers(); if (uadk_digest_nosva) sec_digests_free_methods(); + +#ifndef DISABLE_RSA if (uadk_rsa_nosva) hpre_destroy(); +#endif + +#ifndef DISABLE_DH if (uadk_dh_nosva) hpre_dh_destroy(); +#endif kae_debug_close_log(); #endif @@ -213,12 +219,19 @@ static int uadk_destroy(ENGINE *e) uadk_e_destroy_cipher(); if (uadk_digest) uadk_e_destroy_digest(); + +#ifndef DISABLE_RSA if (uadk_rsa) uadk_e_destroy_rsa(); +#endif + if (uadk_ecc) uadk_e_destroy_ecc(); + +#ifndef DISABLE_DH if (uadk_dh) uadk_e_destroy_dh(); +#endif async_poll_task_free(); @@ -252,10 +265,17 @@ static int uadk_init(ENGINE *e) uadk_e_digest_lock_init(); if (uadk_cipher) uadk_e_cipher_lock_init(); + +#ifndef DISABLE_RSA if (uadk_rsa) uadk_e_rsa_lock_init(); +#endif + +#ifndef DISABLE_DH if (uadk_dh) uadk_e_dh_lock_init(); +#endif + if (uadk_ecc) uadk_e_ecc_lock_init(); @@ -302,6 +322,7 @@ static void bind_fn_kae_alg(ENGINE *e) uadk_digest_nosva = 1; } +#ifndef DISABLE_RSA dev_num = wd_get_nosva_dev_num("rsa"); if (dev_num > 0) { hpre_module_init(); @@ -310,7 +331,9 @@ static void bind_fn_kae_alg(ENGINE *e) else uadk_rsa_nosva = 1; } +#endif +#ifndef DISABLE_DH dev_num = wd_get_nosva_dev_num("dh"); if (dev_num > 0) { hpre_module_dh_init(); @@ -319,7 +342,9 @@ static void bind_fn_kae_alg(ENGINE *e) else uadk_dh_nosva = 1; } +#endif } + #endif static void bind_fn_uadk_alg(ENGINE *e) @@ -344,6 +369,7 @@ static void bind_fn_uadk_alg(ENGINE *e) free(dev); } +#ifndef DISABLE_RSA dev = wd_get_accel_dev("rsa"); if (dev) { if (!uadk_e_bind_rsa(e)) @@ -352,7 +378,9 @@ static void bind_fn_uadk_alg(ENGINE *e) uadk_rsa = 1; free(dev); } +#endif +#ifndef DISABLE_DH dev = wd_get_accel_dev("dh"); if (dev) { if (!uadk_e_bind_dh(e)) @@ -361,6 +389,7 @@ static void bind_fn_uadk_alg(ENGINE *e) uadk_dh = 1; free(dev); } +#endif /* find an ecc device, no difference for sm2/ecdsa/ecdh/x25519/x448 */ dev = wd_get_accel_dev("ecdsa"); diff --git a/src/uadk_engine_init.c.orig b/src/uadk_engine_init.c.orig new file mode 100644 index 00000000..e2aa3925 --- /dev/null +++ b/src/uadk_engine_init.c.orig @@ -0,0 +1,423 @@ +/* + * Copyright 2020-2022 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2022 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. + * + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "uadk.h" +#include "uadk_async.h" +#ifdef KAE +#include "v1/uadk_v1.h" +#endif + +#define UADK_CMD_ENABLE_CIPHER_ENV ENGINE_CMD_BASE +#define UADK_CMD_ENABLE_DIGEST_ENV (ENGINE_CMD_BASE + 1) +#define UADK_CMD_ENABLE_RSA_ENV (ENGINE_CMD_BASE + 2) +#define UADK_CMD_ENABLE_DH_ENV (ENGINE_CMD_BASE + 3) +#define UADK_CMD_ENABLE_ECC_ENV (ENGINE_CMD_BASE + 4) + +/* Constants used when creating the ENGINE */ +const char *engine_uadk_id = "uadk_engine"; +static const char *engine_uadk_name = "uadk hardware engine support"; + +static int uadk_cipher; +static int uadk_digest; +static int uadk_rsa; +static int uadk_dh; +static int uadk_ecc; +static int uadk_inited; +static pthread_mutex_t uadk_engine_mutex = PTHREAD_MUTEX_INITIALIZER; + +#ifdef KAE +static int uadk_cipher_nosva; +static int uadk_digest_nosva; +static int uadk_rsa_nosva; +static int uadk_dh_nosva; +#endif + +static const ENGINE_CMD_DEFN g_uadk_cmd_defns[] = { + { + UADK_CMD_ENABLE_CIPHER_ENV, + "UADK_CMD_ENABLE_CIPHER_ENV", + "Enable or Disable cipher engine environment variable.", + ENGINE_CMD_FLAG_NUMERIC + }, + { + UADK_CMD_ENABLE_DIGEST_ENV, + "UADK_CMD_ENABLE_DIGEST_ENV", + "Enable or Disable digest engine environment variable.", + ENGINE_CMD_FLAG_NUMERIC + }, + { + UADK_CMD_ENABLE_RSA_ENV, + "UADK_CMD_ENABLE_RSA_ENV", + "Enable or Disable rsa engine environment variable.", + ENGINE_CMD_FLAG_NUMERIC + }, + { + UADK_CMD_ENABLE_DH_ENV, + "UADK_CMD_ENABLE_DH_ENV", + "Enable or Disable dh engine environment variable.", + ENGINE_CMD_FLAG_NUMERIC + }, + { + UADK_CMD_ENABLE_ECC_ENV, + "UADK_CMD_ENABLE_ECC_ENV", + "Enable or Disable ecc engine environment variable.", + ENGINE_CMD_FLAG_NUMERIC + }, + { + 0, NULL, NULL, 0 + } +}; + +static void __attribute__((constructor)) uadk_constructor(void) +{ +} + +static void __attribute__((destructor)) uadk_destructor(void) +{ +} + +struct uadk_alg_env_enabled { + const char *alg_name; + __u8 env_enabled; +}; + +static struct uadk_alg_env_enabled uadk_env_enabled[] = { + { "cipher", 0 }, + { "digest", 0 }, + { "rsa", 0 }, + { "dh", 0 }, + { "ecc", 0 } +}; + +int uadk_e_is_env_enabled(const char *alg_name) +{ + int len = ARRAY_SIZE(uadk_env_enabled); + int i = 0; + + while (i < len) { + if (!strcmp(uadk_env_enabled[i].alg_name, alg_name)) + return uadk_env_enabled[i].env_enabled; + i++; + } + + return 0; +} + +static void uadk_e_set_env_enabled(const char *alg_name, __u8 value) +{ + int len = ARRAY_SIZE(uadk_env_enabled); + int i = 0; + + while (i < len) { + if (!strcmp(uadk_env_enabled[i].alg_name, alg_name)) { + uadk_env_enabled[i].env_enabled = value; + return; + } + + i++; + } +} + +int uadk_e_set_env(const char *var_name, int numa_id) +{ + char env_string[ENV_STRING_LEN] = {0}; + const char *var_s; + int ret; + + var_s = secure_getenv(var_name); + if (!var_s || !strlen(var_s)) { + /* uadk will request ctxs from device on specified numa node */ + ret = snprintf(env_string, ENV_STRING_LEN, "%s%d%s%d", + "sync:2@", numa_id, + ",async:2@", numa_id); + if (ret < 0) + return ret; + + ret = setenv(var_name, env_string, 1); + if (ret < 0) + return ret; + } + return 0; +} + +static int uadk_engine_ctrl(ENGINE *e, int cmd, long i, + void *p, void (*f) (void)) +{ + (void)p; + (void)f; + + if (!e) { + fprintf(stderr, "Null Engine\n"); + return 0; + } + + switch (cmd) { + case UADK_CMD_ENABLE_CIPHER_ENV: + uadk_e_set_env_enabled("cipher", i); + break; + case UADK_CMD_ENABLE_DIGEST_ENV: + uadk_e_set_env_enabled("digest", i); + break; + case UADK_CMD_ENABLE_RSA_ENV: + uadk_e_set_env_enabled("rsa", i); + break; + case UADK_CMD_ENABLE_DH_ENV: + uadk_e_set_env_enabled("dh", i); + break; + case UADK_CMD_ENABLE_ECC_ENV: + uadk_e_set_env_enabled("ecc", i); + break; + default: + return 0; + } + + return 1; +} + +static int uadk_destroy(ENGINE *e) +{ +#ifdef KAE + if (uadk_cipher_nosva) + sec_ciphers_free_ciphers(); + if (uadk_digest_nosva) + sec_digests_free_methods(); + if (uadk_rsa_nosva) + hpre_destroy(); + if (uadk_dh_nosva) + hpre_dh_destroy(); + kae_debug_close_log(); +#endif + + if (uadk_cipher) + uadk_e_destroy_cipher(); + if (uadk_digest) + uadk_e_destroy_digest(); + if (uadk_rsa) + uadk_e_destroy_rsa(); + if (uadk_ecc) + uadk_e_destroy_ecc(); + if (uadk_dh) + uadk_e_destroy_dh(); + + async_poll_task_free(); + + pthread_mutex_lock(&uadk_engine_mutex); + uadk_inited = 0; + pthread_mutex_unlock(&uadk_engine_mutex); + + return 1; +} + +static int uadk_init(ENGINE *e) +{ + int ret; + + pthread_mutex_lock(&uadk_engine_mutex); + if (uadk_inited) { + pthread_mutex_unlock(&uadk_engine_mutex); + return 1; + } + + if (uadk_cipher || uadk_digest || uadk_rsa || uadk_dh || uadk_ecc) { + ret = async_module_init(); + if (!ret) { + pthread_mutex_unlock(&uadk_engine_mutex); + fprintf(stderr, "failed to init async module!\n"); + return 0; + } + } + + if (uadk_digest) + uadk_e_digest_lock_init(); + if (uadk_cipher) + uadk_e_cipher_lock_init(); + if (uadk_rsa) + uadk_e_rsa_lock_init(); + if (uadk_dh) + uadk_e_dh_lock_init(); + if (uadk_ecc) + uadk_e_ecc_lock_init(); + + uadk_inited = 1; + pthread_mutex_unlock(&uadk_engine_mutex); + + return 1; +} + +static int uadk_finish(ENGINE *e) +{ + return 1; +} + +static void engine_init_child_at_fork_handler(void) +{ + int ret; + + ret = async_module_init(); + if (!ret) + fprintf(stderr, "failed to init child async module!\n"); +} + +#ifdef KAE +static void bind_fn_kae_alg(ENGINE *e) +{ + int dev_num; + + dev_num = wd_get_nosva_dev_num("cipher"); + if (dev_num > 0) { + cipher_module_init(); + if (!ENGINE_set_ciphers(e, sec_engine_ciphers)) + fprintf(stderr, "uadk bind cipher failed\n"); + else + uadk_cipher_nosva = 1; + } + + dev_num = wd_get_nosva_dev_num("digest"); + if (dev_num > 0) { + digest_module_init(); + if (!ENGINE_set_digests(e, sec_engine_digests)) + fprintf(stderr, "uadk bind digest failed\n"); + else + uadk_digest_nosva = 1; + } + + dev_num = wd_get_nosva_dev_num("rsa"); + if (dev_num > 0) { + hpre_module_init(); + if (!ENGINE_set_RSA(e, hpre_get_rsa_methods())) + fprintf(stderr, "uadk bind rsa failed\n"); + else + uadk_rsa_nosva = 1; + } + + dev_num = wd_get_nosva_dev_num("dh"); + if (dev_num > 0) { + hpre_module_dh_init(); + if (!ENGINE_set_DH(e, hpre_get_dh_methods())) + fprintf(stderr, "uadk bind dh failed\n"); + else + uadk_dh_nosva = 1; + } +} +#endif + +static void bind_fn_uadk_alg(ENGINE *e) +{ + struct uacce_dev *dev; + + dev = wd_get_accel_dev("cipher"); + if (dev) { + if (!uadk_e_bind_cipher(e)) + fprintf(stderr, "uadk bind cipher failed\n"); + else + uadk_cipher = 1; + free(dev); + } + + dev = wd_get_accel_dev("digest"); + if (dev) { + if (!uadk_e_bind_digest(e)) + fprintf(stderr, "uadk bind digest failed\n"); + else + uadk_digest = 1; + free(dev); + } + + dev = wd_get_accel_dev("rsa"); + if (dev) { + if (!uadk_e_bind_rsa(e)) + fprintf(stderr, "uadk bind rsa failed\n"); + else + uadk_rsa = 1; + free(dev); + } + + dev = wd_get_accel_dev("dh"); + if (dev) { + if (!uadk_e_bind_dh(e)) + fprintf(stderr, "uadk bind dh failed\n"); + else + uadk_dh = 1; + free(dev); + } + + /* find an ecc device, no difference for sm2/ecdsa/ecdh/x25519/x448 */ + dev = wd_get_accel_dev("ecdsa"); + if (dev) { + if (!uadk_e_bind_ecc(e)) + fprintf(stderr, "uadk bind ecc failed\n"); + else + uadk_ecc = 1; + free(dev); + } +} + +/* + * Connect uadk_engine to OpenSSL engine library. + */ +static int bind_fn(ENGINE *e, const char *id) +{ + int ret; + + if (!ENGINE_set_id(e, engine_uadk_id) || + !ENGINE_set_destroy_function(e, uadk_destroy) || + !ENGINE_set_init_function(e, uadk_init) || + !ENGINE_set_finish_function(e, uadk_finish) || + !ENGINE_set_name(e, engine_uadk_name)) { + fprintf(stderr, "bind failed\n"); + return 0; + } + +#ifdef KAE + kae_debug_init_log(); + bind_fn_kae_alg(e); + + if (uadk_cipher_nosva || uadk_digest_nosva || uadk_rsa_nosva || + uadk_dh_nosva) { + async_module_init_v1(); + pthread_atfork(NULL, NULL, engine_init_child_at_fork_handler_v1); + } +#endif + bind_fn_uadk_alg(e); + + if (uadk_cipher || uadk_digest || uadk_rsa || uadk_dh || uadk_ecc) + pthread_atfork(NULL, NULL, engine_init_child_at_fork_handler); + + ret = ENGINE_set_ctrl_function(e, uadk_engine_ctrl); + if (ret != 1) { + fprintf(stderr, "failed to set ctrl function\n"); + return 0; + } + + ret = ENGINE_set_cmd_defns(e, g_uadk_cmd_defns); + if (ret != 1) { + fprintf(stderr, "failed to set defns\n"); + return 0; + } + + return 1; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) diff --git a/src/uadk_pkey.c b/src/uadk_pkey.c index 60e32380..75fa37c9 100644 --- a/src/uadk_pkey.c +++ b/src/uadk_pkey.c @@ -31,13 +31,41 @@ static int g_ecc_support_state[ECC_TYPE]; +#if defined(DISABLE_X448) && defined(DISABLE_X25519) + static int pkey_nids[] = { EVP_PKEY_EC, - EVP_PKEY_SM2, - EVP_PKEY_X25519, - EVP_PKEY_X448 + EVP_PKEY_SM2 }; +#else + + #if defined(DISABLE_X448) + + static int pkey_nids[] = { + EVP_PKEY_EC, + EVP_PKEY_SM2, + EVP_PKEY_X25519 + }; + #elif defined(DISABLE_X25519) + + static int pkey_nids[] = { + EVP_PKEY_EC, + EVP_PKEY_SM2, + EVP_PKEY_X448 + }; + + #else + + static int pkey_nids[] = { + EVP_PKEY_EC, + EVP_PKEY_SM2, + EVP_PKEY_X25519, + EVP_PKEY_X448 + }; + + #endif +#endif struct ecc_sched { int sched_type; struct wd_sched wd_sched; @@ -601,6 +629,8 @@ static int get_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, } *pmeth = pkey_meth.ec; break; + +#ifndef DISABLE_X448 case EVP_PKEY_X448: ret = uadk_x448_create_pmeth(&pkey_meth); if (!ret) { @@ -609,6 +639,9 @@ static int get_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, } *pmeth = pkey_meth.x448; break; +#endif + +#ifndef DISABLE_X25519 case EVP_PKEY_X25519: ret = uadk_x25519_create_pmeth(&pkey_meth); if (!ret) { @@ -617,6 +650,7 @@ static int get_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, } *pmeth = pkey_meth.x25519; break; +#endif default: fprintf(stderr, "not find nid %d\n", nid); return 0; diff --git a/src/uadk_pkey.c.orig b/src/uadk_pkey.c.orig new file mode 100644 index 00000000..60e32380 --- /dev/null +++ b/src/uadk_pkey.c.orig @@ -0,0 +1,673 @@ +/* + * Copyright 2020-2022 Huawei Technologies Co.,Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include "uadk_async.h" +#include "uadk.h" +#include "uadk_pkey.h" + +#define ECC_MAX_DEV_NUM 16 +#define CTX_ASYNC 1 +#define CTX_SYNC 0 +#define CTX_NUM 2 +#define GET_RAND_MAX_CNT 100 +#define SUPPORT 1 + +static int g_ecc_support_state[ECC_TYPE]; + +static int pkey_nids[] = { + EVP_PKEY_EC, + EVP_PKEY_SM2, + EVP_PKEY_X25519, + EVP_PKEY_X448 +}; + +struct ecc_sched { + int sched_type; + struct wd_sched wd_sched; +}; + +struct ecc_res_config { + struct ecc_sched sched; +}; + +/* ECC global hardware resource is saved here */ +struct ecc_res { + struct wd_ctx_config *ctx_res; + int pid; + int numa_id; + pthread_spinlock_t lock; +} ecc_res; + +static struct uadk_pkey_meth pkey_meth; + +static handle_t ecc_sched_init(handle_t h_sched_ctx, void *sched_param) +{ + return (handle_t)0; +} + +static __u32 ecc_pick_next_ctx(handle_t sched_ctx, + void *sched_key, const int sched_mode) +{ + if (sched_mode) + return CTX_ASYNC; + else + return CTX_SYNC; +} + +static int ecc_poll_policy(handle_t h_sched_ctx, __u32 expect, __u32 *count) +{ + return 0; +} + +void uadk_e_ecc_cb(void *req_t) +{ + struct wd_ecc_req *req_new = (struct wd_ecc_req *)req_t; + struct uadk_e_cb_info *cb_param; + struct wd_ecc_req *req_origin; + struct async_op *op; + + if (!req_new) + return; + + cb_param = req_new->cb_param; + if (!cb_param) + return; + + req_origin = cb_param->priv; + if (!req_origin) + return; + + req_origin->status = req_new->status; + + op = cb_param->op; + if (op && op->job && !op->done) { + op->done = 1; + op->ret = 0; + async_free_poll_task(op->idx, 1); + async_wake_job(op->job); + } +} + +static int uadk_ecc_poll(void *ctx) +{ + unsigned int recv = 0; + __u64 rx_cnt = 0; + int expt = 1; + int ret; + + do { + ret = wd_ecc_poll_ctx(CTX_ASYNC, expt, &recv); + if (!ret && recv == expt) + return 0; + else if (ret == -EAGAIN) + rx_cnt++; + else + return -1; + } while (rx_cnt < ENGINE_RECV_MAX_CNT); + + fprintf(stderr, "failed to recv msg: timeout!\n"); + + return -ETIMEDOUT; +} + +/* Make resource configure static */ +static struct ecc_res_config ecc_res_config = { + .sched = { + .sched_type = -1, + .wd_sched = { + .name = "ECC RR", + .sched_init = ecc_sched_init, + .pick_next_ctx = ecc_pick_next_ctx, + .poll_policy = ecc_poll_policy, + .h_sched_ctx = 0, + }, + }, +}; + +int uadk_e_ecc_get_numa_id(void) +{ + return ecc_res.numa_id; +} + +int uadk_e_ecc_get_support_state(int alg_tag) +{ + return g_ecc_support_state[alg_tag]; +} + +static void uadk_e_ecc_set_support_state(int alg_tag, int value) +{ + g_ecc_support_state[alg_tag] = value; +} + +static int uadk_e_ecc_env_poll(void *ctx) +{ + __u64 rx_cnt = 0; + __u32 recv = 0; + /* Poll one packet currently */ + int expt = 1; + int ret; + + do { + ret = wd_ecc_poll(expt, &recv); + if (ret < 0 || recv == expt) + return ret; + rx_cnt++; + } while (rx_cnt < ENGINE_RECV_MAX_CNT); + + fprintf(stderr, "failed to poll msg: timeout!\n"); + + return -ETIMEDOUT; +} + +static int uadk_e_wd_ecc_env_init(struct uacce_dev *dev) +{ + int ret; + + ret = uadk_e_set_env("WD_ECC_CTX_NUM", dev->numa_id); + if (ret) + return ret; + + ret = wd_ecc_env_init(NULL); + if (ret) + return ret; + + async_register_poll_fn(ASYNC_TASK_ECC, uadk_e_ecc_env_poll); + + return 0; +} + +static int uadk_e_wd_ecc_general_init(struct uacce_dev *dev, + struct wd_sched *sched) +{ + struct wd_ctx_config *ctx_cfg; + __u32 i; + int ret; + + ctx_cfg = calloc(1, sizeof(struct wd_ctx_config)); + if (!ctx_cfg) + return -ENOMEM; + + ecc_res.ctx_res = ctx_cfg; + ctx_cfg->ctx_num = CTX_NUM; + ctx_cfg->ctxs = calloc(CTX_NUM, sizeof(struct wd_ctx)); + if (!ctx_cfg->ctxs) { + ret = -ENOMEM; + goto free_cfg; + } + + for (i = 0; i < CTX_NUM; i++) { + ctx_cfg->ctxs[i].ctx = wd_request_ctx(dev); + if (!ctx_cfg->ctxs[i].ctx) { + ret = -EINVAL; + goto free_ctx; + } + ctx_cfg->ctxs[i].ctx_mode = (i == 0) ? CTX_SYNC : CTX_ASYNC; + } + + ret = wd_ecc_init(ctx_cfg, sched); + if (ret) + goto free_ctx; + + async_register_poll_fn(ASYNC_TASK_ECC, uadk_ecc_poll); + + return 0; + +free_ctx: + for (i = 0; i < CTX_NUM; i++) { + if (ctx_cfg->ctxs[i].ctx) + wd_release_ctx(ctx_cfg->ctxs[i].ctx); + } + free(ctx_cfg->ctxs); +free_cfg: + free(ctx_cfg); + ecc_res.ctx_res = NULL; + + return ret; +} + +static int uadk_wd_ecc_init(struct ecc_res_config *config, struct uacce_dev *dev) +{ + struct wd_sched *sched = &config->sched.wd_sched; + int ret; + + ret = uadk_e_is_env_enabled("ecc"); + if (ret) + ret = uadk_e_wd_ecc_env_init(dev); + else + ret = uadk_e_wd_ecc_general_init(dev, sched); + + return ret; +} + +static void uadk_wd_ecc_uninit(void) +{ + struct wd_ctx_config *ctx_cfg = ecc_res.ctx_res; + __u32 i; + int ret; + + if (ecc_res.pid != getpid()) + return; + + ret = uadk_e_is_env_enabled("ecc"); + if (ret == ENV_ENABLED) { + wd_ecc_env_uninit(); + } else { + wd_ecc_uninit(); + for (i = 0; i < ctx_cfg->ctx_num; i++) + wd_release_ctx(ctx_cfg->ctxs[i].ctx); + free(ctx_cfg->ctxs); + free(ctx_cfg); + ecc_res.ctx_res = NULL; + } + ecc_res.pid = 0; + ecc_res.numa_id = 0; +} + +int uadk_ecc_crypto(handle_t sess, struct wd_ecc_req *req, void *usr) +{ + struct uadk_e_cb_info cb_param; + struct async_op op; + int idx, ret; + + ret = async_setup_async_event_notification(&op); + if (!ret) { + fprintf(stderr, "failed to setup async event notification.\n"); + return 0; + } + + if (op.job != NULL) { + cb_param.op = &op; + cb_param.priv = req; + req->cb_param = &cb_param; + req->cb = uadk_e_ecc_cb; + req->status = -1; + ret = async_get_free_task(&idx); + if (!ret) + goto err; + + op.idx = idx; + + do { + ret = wd_do_ecc_async(sess, req); + if (ret < 0 && ret != -EBUSY) { + async_free_poll_task(op.idx, 0); + goto err; + } + } while (ret == -EBUSY); + + ret = async_pause_job((void *)usr, &op, ASYNC_TASK_ECC, idx); + if (!ret) + goto err; + if (req->status) + return 0; + } else { + ret = wd_do_ecc_sync(sess, req); + if (ret < 0) + return 0; + } + return 1; +err: + (void)async_clear_async_event_notification(); + return 0; +} + +bool uadk_is_all_zero(const unsigned char *data, size_t dlen) +{ + size_t i; + + for (i = 0; i < dlen; i++) { + if (data[i]) + return false; + } + + return true; +} + +int uadk_ecc_set_public_key(handle_t sess, const EC_KEY *eckey) +{ + unsigned char *point_bin = NULL; + struct wd_ecc_point pubkey; + struct wd_ecc_key *ecc_key; + const EC_POINT *point; + const EC_GROUP *group; + int ret, len; + + point = EC_KEY_get0_public_key(eckey); + if (!point) { + fprintf(stderr, "pubkey not set!\n"); + return -EINVAL; + } + + group = EC_KEY_get0_group(eckey); + len = EC_POINT_point2buf(group, point, UADK_OCTET_STRING, + &point_bin, NULL); + if (!len) { + fprintf(stderr, "EC_POINT_point2buf error.\n"); + return -EINVAL; + } + + len /= UADK_ECC_PUBKEY_PARAM_NUM; + pubkey.x.data = (char *)point_bin + 1; + pubkey.x.dsize = len; + pubkey.y.data = pubkey.x.data + len; + pubkey.y.dsize = len; + ecc_key = wd_ecc_get_key(sess); + ret = wd_ecc_set_pubkey(ecc_key, &pubkey); + if (ret) { + fprintf(stderr, "failed to set ecc pubkey\n"); + ret = UADK_DO_SOFT; + } + + OPENSSL_free(point_bin); + + return ret; +} + +int uadk_ecc_set_private_key(handle_t sess, const EC_KEY *eckey) +{ + unsigned char bin[UADK_ECC_MAX_KEY_BYTES]; + struct wd_ecc_key *ecc_key; + const EC_GROUP *group; + struct wd_dtb prikey; + const BIGNUM *d; + size_t degree; + int buflen; + int ret; + + d = EC_KEY_get0_private_key(eckey); + if (!d) { + fprintf(stderr, "private key not set\n"); + return -EINVAL; + } + + group = EC_KEY_get0_group(eckey); + if (!group) { + fprintf(stderr, "failed to get ecc group\n"); + return -EINVAL; + } + + degree = EC_GROUP_get_degree(group); + buflen = BITS_TO_BYTES(degree); + ecc_key = wd_ecc_get_key(sess); + prikey.data = (void *)bin; + prikey.dsize = BN_bn2binpad(d, bin, buflen); + + ret = wd_ecc_set_prikey(ecc_key, &prikey); + if (ret) { + fprintf(stderr, "failed to set ecc prikey, ret = %d\n", ret); + ret = UADK_DO_SOFT; + } + + return ret; +} + +int uadk_ecc_get_rand(char *out, size_t out_len, void *usr) +{ + int count = GET_RAND_MAX_CNT; + BIGNUM *k; + int ret; + + if (!out) { + fprintf(stderr, "out is NULL\n"); + return -1; + } + + k = BN_new(); + if (!k) + return -ENOMEM; + + do { + ret = BN_priv_rand_range(k, usr); + if (!ret) { + fprintf(stderr, "failed to BN_priv_rand_range\n"); + ret = -EINVAL; + goto err; + } + + ret = BN_bn2binpad(k, (void *)out, (int)out_len); + if (ret < 0) { + ret = -EINVAL; + fprintf(stderr, "failed to BN_bn2binpad\n"); + goto err; + } + } while (--count >= 0 && BN_is_zero(k)); + + ret = 0; + if (count < 0) + ret = -1; +err: + BN_free(k); + + return ret; +} + +bool uadk_prime_field(const EC_GROUP *group) +{ + int type = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); + + return type == NID_X9_62_prime_field; +} + +int uadk_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx) +{ +# if OPENSSL_VERSION_NUMBER > 0x10101000L + if (!EC_GROUP_get_curve(group, p, a, b, ctx)) + return -1; +# else + if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) + return -1; +# endif + return 0; +} + +int uadk_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx) +{ +# if OPENSSL_VERSION_NUMBER > 0x10101000L + if (!EC_POINT_get_affine_coordinates(group, p, x, y, ctx)) + return -1; +# else + if (!EC_POINT_get_affine_coordinates_GFp(group, p, x, y, ctx)) + return -1; +# endif + return 0; +} + +void uadk_ecc_fill_req(struct wd_ecc_req *req, unsigned int op, + void *in, void *out) +{ + req->op_type = op; + req->src = in; + req->dst = out; +} + +bool uadk_support_algorithm(const char *alg) +{ + struct uacce_dev_list *list = wd_get_accel_list(alg); + + if (list) { + wd_free_list_accels(list); + return true; + } + + return false; +} + +int uadk_init_ecc(void) +{ + struct uacce_dev *dev; + int ret; + + if (ecc_res.pid != getpid()) { + pthread_spin_lock(&ecc_res.lock); + if (ecc_res.pid == getpid()) { + pthread_spin_unlock(&ecc_res.lock); + return 0; + } + + /* Find an ecc device, no difference for sm2/ecdsa/ecdh/x25519/x448 */ + dev = wd_get_accel_dev("ecdsa"); + if (!dev) { + pthread_spin_unlock(&ecc_res.lock); + fprintf(stderr, "failed to get device for ecc\n"); + return -ENOMEM; + } + + ret = uadk_wd_ecc_init(&ecc_res_config, dev); + if (ret) { + fprintf(stderr, "failed to init ec(%d).\n", ret); + goto err_unlock; + } + + ecc_res.numa_id = dev->numa_id; + ecc_res.pid = getpid(); + pthread_spin_unlock(&ecc_res.lock); + free(dev); + } + + return 0; + +err_unlock: + pthread_spin_unlock(&ecc_res.lock); + free(dev); + return ret; +} + +static void uadk_uninit_ecc(void) +{ + uadk_wd_ecc_uninit(); +} + +const EVP_PKEY_METHOD *get_openssl_pkey_meth(int nid) +{ + size_t count = EVP_PKEY_meth_get_count(); + const EVP_PKEY_METHOD *pmeth; + int pkey_id = -1; + size_t i; + + for (i = 0; i < count; i++) { + pmeth = EVP_PKEY_meth_get0(i); + EVP_PKEY_meth_get0_info(&pkey_id, NULL, pmeth); + if (nid == pkey_id) + return pmeth; + } + + fprintf(stderr, "not find openssl method %d\n", nid); + return NULL; +} + +static int get_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, + const int **nids, int nid) +{ + int ret; + + if (!pmeth) { + *nids = pkey_nids; + return ARRAY_SIZE(pkey_nids); + } + + switch (nid) { + case EVP_PKEY_SM2: + ret = uadk_sm2_create_pmeth(&pkey_meth); + if (!ret) { + fprintf(stderr, "failed to register sm2 pmeth.\n"); + return 0; + } + *pmeth = pkey_meth.sm2; + break; + case EVP_PKEY_EC: + ret = uadk_ec_create_pmeth(&pkey_meth); + if (!ret) { + fprintf(stderr, "failed to register ec pmeth.\n"); + return 0; + } + *pmeth = pkey_meth.ec; + break; + case EVP_PKEY_X448: + ret = uadk_x448_create_pmeth(&pkey_meth); + if (!ret) { + fprintf(stderr, "failed to register x448 pmeth.\n"); + return 0; + } + *pmeth = pkey_meth.x448; + break; + case EVP_PKEY_X25519: + ret = uadk_x25519_create_pmeth(&pkey_meth); + if (!ret) { + fprintf(stderr, "failed to register x25519 pmeth.\n"); + return 0; + } + *pmeth = pkey_meth.x25519; + break; + default: + fprintf(stderr, "not find nid %d\n", nid); + return 0; + } + + return 1; +} + +static int uadk_ecc_bind_pmeth(ENGINE *e) +{ + return ENGINE_set_pkey_meths(e, get_pkey_meths); +} + +void uadk_e_ecc_lock_init(void) +{ + pthread_spin_init(&ecc_res.lock, PTHREAD_PROCESS_PRIVATE); +} + +int uadk_e_bind_ecc(ENGINE *e) +{ + static const char * const ecc_alg[] = {"sm2", "ecdsa", "ecdh", "x25519", "x448"}; + __u32 i, size; + int ret; + bool sp; + + /* Enumerate ecc algs to check whether it is supported and set tags */ + size = ARRAY_SIZE(ecc_alg); + for (i = 0; i < size; i++) { + sp = uadk_support_algorithm(*(ecc_alg + i)); + if (sp) + uadk_e_ecc_set_support_state(i, SUPPORT); + } + + ret = uadk_ecc_bind_pmeth(e); + if (!ret) { + fprintf(stderr, "failed to bind ecc pmeth\n"); + return ret; + } + + ret = uadk_bind_ec(e); + if (!ret) { + fprintf(stderr, "failed to bind ec\n"); + return ret; + } + + return ret; +} + +void uadk_e_destroy_ecc(void) +{ + pthread_spin_destroy(&ecc_res.lock); + uadk_ec_delete_meth(); + uadk_uninit_ecc(); +} diff --git a/src/uadk_pkey.h b/src/uadk_pkey.h index 31684744..05d5dd1a 100644 --- a/src/uadk_pkey.h +++ b/src/uadk_pkey.h @@ -77,10 +77,17 @@ int uadk_sm2_create_pmeth(struct uadk_pkey_meth *pkey_meth); void uadk_sm2_delete_pmeth(struct uadk_pkey_meth *pkey_meth); int uadk_ec_create_pmeth(struct uadk_pkey_meth *pkey_meth); void uadk_ec_delete_meth(void); + +#ifndef DISABLE_X448 int uadk_x448_create_pmeth(struct uadk_pkey_meth *pkey_meth); void uadk_x448_delete_pmeth(struct uadk_pkey_meth *pkey_meth); +#endif + +#ifndef DISABLE_X25519 int uadk_x25519_create_pmeth(struct uadk_pkey_meth *pkey_meth); void uadk_x25519_delete_pmeth(struct uadk_pkey_meth *pkey_meth); +#endif + int uadk_bind_ec(ENGINE *e); int uadk_e_ecc_get_numa_id(void); int uadk_e_ecc_get_support_state(int alg_tag); diff --git a/src/v1/utils/engine_check.c b/src/v1/utils/engine_check.c index 949eeb8f..faa17474 100644 --- a/src/v1/utils/engine_check.c +++ b/src/v1/utils/engine_check.c @@ -27,7 +27,11 @@ #include "../alg/ciphers/sec_ciphers_wd.h" #include "../alg/digests/sec_digests_wd.h" #include "../alg/pkey/hpre_wd.h" + +#ifndef DISABLE_DH #include "../alg/dh/hpre_dh_wd.h" +#endif + #include "engine_check.h" #include "engine_utils.h" #include "engine_log.h" @@ -81,8 +85,15 @@ static void *kae_checking_q_loop_fn(void *args) kae_queue_pool_check_and_release(wd_ciphers_get_qnode_pool(), wd_ciphers_free_engine_ctx); kae_queue_pool_check_and_release(wd_digests_get_qnode_pool(), wd_digests_free_engine_ctx); + +#ifndef DISABLE_RSA kae_queue_pool_check_and_release(wd_hpre_get_qnode_pool(), NULL); +#endif + +#ifndef DISABLE_DH kae_queue_pool_check_and_release(wd_hpre_dh_get_qnode_pool(), NULL); +#endif + } US_INFO("check thread exit normally."); @@ -96,8 +107,15 @@ static void kae_checking_q_thread_destroy(void) (void)wd_digests_uninit_qnode_pool(); (void)wd_ciphers_uninit_qnode_pool(); + +#ifndef DISABLE_DH (void)wd_hpre_dh_uninit_qnode_pool(); +#endif + +#ifndef DISABLE_RSA (void)wd_hpre_uninit_qnode_pool(); +#endif + } static void kae_check_thread_init(void) diff --git a/src/v1/utils/engine_fork.c b/src/v1/utils/engine_fork.c index 14f4e6e6..c881b014 100644 --- a/src/v1/utils/engine_fork.c +++ b/src/v1/utils/engine_fork.c @@ -41,13 +41,25 @@ void engine_init_child_at_fork_handler_v1(void) g_sec_digests_qnode_pool->pool_use_num = 0; if (g_sec_ciphers_qnode_pool) g_sec_ciphers_qnode_pool->pool_use_num = 0; + +#ifndef DISABLE_RSA if (g_hpre_rsa_qnode_pool) g_hpre_rsa_qnode_pool->pool_use_num = 0; +#endif + +#ifndef DISABLE_DH if (g_hpre_dh_qnode_pool) g_hpre_dh_qnode_pool->pool_use_num = 0; +#endif +#ifndef DISABLE_RSA (void)hpre_module_init(); +#endif + +#ifndef DISABLE_DH (void)hpre_module_dh_init(); +#endif + (void)cipher_module_init(); (void)digest_module_init();