After adding the aead module of the init2 interface, combine the driver module dynamic load in the initialization process, transform HiSilicon aead driver, and implemented using the dynamic loading function connection between driver and algorithm layer.
Signed-off-by: Hao Fang fanghao11@huawei.com --- drv/hisi_sec.c | 47 ++++++--- include/drv/wd_aead_drv.h | 26 ----- wd_aead.c | 207 +++++++++++++++++++++++++------------- 3 files changed, 169 insertions(+), 111 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index 719b37e..6301d28 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -581,6 +581,15 @@ static struct wd_alg_driver digest_alg_driver[] = { GEN_SEC_ALG_DRIVER("aes-gmac"), };
+static struct wd_alg_driver aead_alg_driver[] = { + GEN_SEC_ALG_DRIVER("ccm(aes)"), + GEN_SEC_ALG_DRIVER("gcm(aes)"), + GEN_SEC_ALG_DRIVER("authenc(hmac(sha256),cbc(aes))"), + GEN_SEC_ALG_DRIVER("ccm(sm4)"), + GEN_SEC_ALG_DRIVER("gcm(sm4)"), + GEN_SEC_ALG_DRIVER("authenc(hmac(sha256),cbc(sm4))"), +}; + static void dump_sec_msg(void *msg, const char *alg) { struct wd_cipher_msg *cmsg; @@ -2349,16 +2358,6 @@ int hisi_sec_aead_recv(handle_t ctx, void *aead_msg) return 0; }
-static struct wd_aead_driver hisi_aead_driver = { - .drv_name = "hisi_sec2", - .alg_name = "aead", - .drv_ctx_size = sizeof(struct hisi_sec_ctx), - .init = hisi_sec_init, - .exit = hisi_sec_exit, -}; - -WD_AEAD_SET_DRIVER(hisi_aead_driver); - static int fill_aead_bd3_alg(struct wd_aead_msg *msg, struct hisi_sec_sqe3 *sqe) { @@ -2636,9 +2635,11 @@ static void hisi_sec_driver_adapter(struct hisi_qp *qp) digest_alg_driver[i].send = hisi_sec_digest_send; digest_alg_driver[i].recv = hisi_sec_digest_recv; } - - hisi_aead_driver.aead_send = hisi_sec_aead_send; - hisi_aead_driver.aead_recv = hisi_sec_aead_recv; + alg_num = ARRAY_SIZE(aead_alg_driver); + for (i = 0; i < alg_num; i++) { + aead_alg_driver[i].send = hisi_sec_aead_send; + aead_alg_driver[i].recv = hisi_sec_aead_recv; + } } else { WD_INFO("hisi sec init HIP09!\n"); alg_num = ARRAY_SIZE(cipher_alg_driver); @@ -2652,9 +2653,11 @@ static void hisi_sec_driver_adapter(struct hisi_qp *qp) digest_alg_driver[i].send = hisi_sec_digest_send_v3; digest_alg_driver[i].recv = hisi_sec_digest_recv_v3; } - - hisi_aead_driver.aead_send = hisi_sec_aead_send_v3; - hisi_aead_driver.aead_recv = hisi_sec_aead_recv_v3; + alg_num = ARRAY_SIZE(aead_alg_driver); + for (i = 0; i < alg_num; i++) { + aead_alg_driver[i].send = hisi_sec_aead_send_v3; + aead_alg_driver[i].recv = hisi_sec_aead_recv_v3; + } } }
@@ -2741,6 +2744,14 @@ static void __attribute__((constructor)) hisi_sec2_probe(void) WD_ERR("Error: register SEC %s failed!\n", digest_alg_driver[i].alg_name); } + + alg_num = ARRAY_SIZE(aead_alg_driver); + for (i = 0; i < alg_num; i++) { + ret = wd_alg_driver_register(&aead_alg_driver[i]); + if (ret) + WD_ERR("Error: register SEC %s failed!\n", + aead_alg_driver[i].alg_name); + } }
static void __attribute__((destructor)) hisi_sec2_remove(void) @@ -2755,5 +2766,9 @@ static void __attribute__((destructor)) hisi_sec2_remove(void) alg_num = ARRAY_SIZE(digest_alg_driver); for (i = 0; i < alg_num; i++) wd_alg_driver_unregister(&digest_alg_driver[i]); + + alg_num = ARRAY_SIZE(aead_alg_driver); + for (i = 0; i < alg_num; i++) + wd_alg_driver_unregister(&aead_alg_driver[i]); }
diff --git a/include/drv/wd_aead_drv.h b/include/drv/wd_aead_drv.h index 8446238..d2ecb22 100644 --- a/include/drv/wd_aead_drv.h +++ b/include/drv/wd_aead_drv.h @@ -63,34 +63,8 @@ struct wd_aead_msg { __u8 *mac; };
-struct wd_aead_driver { - const char *drv_name; - const char *alg_name; - __u32 drv_ctx_size; - int (*init)(void *conf, void *priv); - void (*exit)(void *priv); - int (*aead_send)(handle_t ctx, void *aead_msg); - int (*aead_recv)(handle_t ctx, void *aead_msg); -}; - -void wd_aead_set_driver(struct wd_aead_driver *drv); -struct wd_aead_driver *wd_aead_get_driver(void); struct wd_aead_msg *wd_aead_get_msg(__u32 idx, __u32 tag);
-#ifdef WD_STATIC_DRV -#define WD_AEAD_SET_DRIVER(drv) \ -struct wd_aead_driver *wd_aead_get_driver(void) \ -{ \ - return &drv; \ -} -#else -#define WD_AEAD_SET_DRIVER(drv) \ -static void __attribute__((constructor)) set_aead_driver(void) \ -{ \ - wd_aead_set_driver(&(drv)); \ -} -#endif - #ifdef __cplusplus } #endif diff --git a/wd_aead.c b/wd_aead.c index 8b63daa..5c13ba1 100644 --- a/wd_aead.c +++ b/wd_aead.c @@ -29,15 +29,23 @@ static int g_aead_mac_len[WD_DIGEST_TYPE_MAX] = { WD_DIGEST_SHA512_224_LEN, WD_DIGEST_SHA512_256_LEN };
+/* Fixme, need correct match */ +static char* wd_aead_alg_name[WD_CIPHER_ALG_TYPE_MAX][WD_CIPHER_MODE_TYPE_MAX] = { + {"", "authenc(hmac(sha256),cbc(sm4))", "", "", "", "", "", "", "", + "ccm(sm4)", "gcm(sm4)"}, + {"", "authenc(hmac(sha256),cbc(aes))", "", "", "", "", "", "", "", + "ccm(aes)", "gcm(aes)"} +}; + struct wd_aead_setting { enum wd_status status; struct wd_ctx_config_internal config; struct wd_sched sched; - struct wd_aead_driver *driver; + struct wd_alg_driver *driver; struct wd_async_msg_pool pool; - void *sched_ctx; void *priv; void *dlhandle; + void *dlh_list; } wd_aead_setting;
struct wd_aead_sess { @@ -58,41 +66,49 @@ struct wd_aead_sess { struct wd_env_config wd_aead_env_config; static struct wd_init_attrs wd_aead_init_attrs;
-static struct wd_ctx_nums wd_aead_ctx_num[] = { - {1, 1}, {} -}; - -static struct wd_ctx_params wd_aead_ctx_params = { - .op_type_num = 1, - .ctx_set_num = wd_aead_ctx_num, - .bmp = NULL, -}; - -#ifdef WD_STATIC_DRV -static void wd_aead_set_static_drv(void) +static void wd_aead_close_driver(void) { - wd_aead_setting.driver = wd_aead_get_driver(); - if (!wd_aead_setting.driver) - WD_ERR("failed to get driver!\n"); + if (wd_aead_setting.dlhandle) { + wd_release_drv(wd_aead_setting.driver); + dlclose(wd_aead_setting.dlhandle); + wd_aead_setting.dlhandle = NULL; + } } -#else -static void __attribute__((constructor)) wd_aead_open_driver(void) + +static int wd_aead_open_driver(void) { - wd_aead_setting.dlhandle = dlopen("libhisi_sec.so", RTLD_NOW); - if (!wd_aead_setting.dlhandle) + struct wd_alg_driver *driver = NULL; + const char *alg_name = "cbc(aes)"; + char lib_path[PATH_STR_SIZE]; + int ret; + + /* + * Compatible with the normal acquisition of device + * drivers in the init interface + */ + if (wd_aead_setting.dlh_list) + return 0; + + ret = wd_get_lib_file_path("libhisi_sec.so", lib_path, false); + if (ret) + return ret; + + wd_aead_setting.dlhandle = dlopen(lib_path, RTLD_NOW); + if (!wd_aead_setting.dlhandle) { WD_ERR("failed to open libhisi_sec.so, %s\n", dlerror()); -} + return -WD_EINVAL; + }
-static void __attribute__((destructor)) wd_aead_close_driver(void) -{ - if (wd_aead_setting.dlhandle) - dlclose(wd_aead_setting.dlhandle); -} -#endif + driver = wd_request_drv(alg_name, false); + if (!driver) { + wd_aead_close_driver(); + WD_ERR("failed to get %s driver support\n", alg_name); + return -WD_EINVAL; + }
-void wd_aead_set_driver(struct wd_aead_driver *drv) -{ - wd_aead_setting.driver = drv; + wd_aead_setting.driver = driver; + + return 0; }
static int aes_key_len_check(__u32 length) @@ -272,12 +288,19 @@ int wd_aead_get_maxauthsize(handle_t h_sess) handle_t wd_aead_alloc_sess(struct wd_aead_sess_setup *setup) { struct wd_aead_sess *sess = NULL; + bool ret;
if (unlikely(!setup)) { WD_ERR("failed to check session input parameter!\n"); return (handle_t)0; }
+ if (setup->calg >= WD_CIPHER_ALG_TYPE_MAX || + setup->cmode >= WD_CIPHER_MODE_TYPE_MAX) { + WD_ERR("failed to check algorithm setup!\n"); + return (handle_t)0; + } + sess = malloc(sizeof(struct wd_aead_sess)); if (!sess) { WD_ERR("failed to alloc session memory!\n"); @@ -285,20 +308,32 @@ handle_t wd_aead_alloc_sess(struct wd_aead_sess_setup *setup) } memset(sess, 0, sizeof(struct wd_aead_sess));
+ sess->alg_name = wd_aead_alg_name[setup->calg][setup->cmode]; sess->calg = setup->calg; sess->cmode = setup->cmode; sess->dalg = setup->dalg; sess->dmode = setup->dmode; + ret = wd_drv_alg_support(sess->alg_name, wd_aead_setting.driver); + if (!ret) { + WD_ERR("failed to support this algorithm: %s!\n", sess->alg_name); + goto err_sess; + } + /* Some simple scheduler don't need scheduling parameters */ sess->sched_key = (void *)wd_aead_setting.sched.sched_init( wd_aead_setting.sched.h_sched_ctx, setup->sched_param); if (WD_IS_ERR(sess->sched_key)) { WD_ERR("failed to init session schedule key!\n"); - free(sess); - return (handle_t)0; + goto err_sess; }
return (handle_t)sess; +err_sess: + if (sess->sched_key) + free(sess->sched_key); + free(sess); + return (handle_t)0; + }
void wd_aead_free_sess(handle_t h_sess) @@ -407,7 +442,6 @@ static void wd_aead_clear_status(void)
static int wd_aead_init_nolock(struct wd_ctx_config *config, struct wd_sched *sched) { - void *priv; int ret;
ret = wd_set_epoll_en("WD_AEAD_EPOLL_EN", @@ -423,11 +457,6 @@ static int wd_aead_init_nolock(struct wd_ctx_config *config, struct wd_sched *sc if (ret < 0) goto out_clear_ctx_config;
- /* set driver */ -#ifdef WD_STATIC_DRV - wd_aead_set_static_drv(); -#endif - /* init async request pool */ ret = wd_init_async_request_pool(&wd_aead_setting.pool, config->ctx_num, WD_POOL_MAX_ENTRIES, @@ -435,25 +464,14 @@ static int wd_aead_init_nolock(struct wd_ctx_config *config, struct wd_sched *sc if (ret < 0) goto out_clear_sched;
- /* init ctx related resources in specific driver */ - priv = calloc(1, wd_aead_setting.driver->drv_ctx_size); - if (!priv) { - ret = -WD_ENOMEM; + ret = wd_alg_init_driver(&wd_aead_setting.config, + wd_aead_setting.driver, + &wd_aead_setting.priv); + if (ret) goto out_clear_pool; - } - wd_aead_setting.priv = priv; - - ret = wd_aead_setting.driver->init(&wd_aead_setting.config, priv); - if (ret < 0) { - WD_ERR("failed to init aead dirver!\n"); - goto out_free_priv; - }
return 0;
-out_free_priv: - free(priv); - wd_aead_setting.priv = NULL; out_clear_pool: wd_uninit_async_request_pool(&wd_aead_setting.pool); out_clear_sched: @@ -479,14 +497,20 @@ int wd_aead_init(struct wd_ctx_config *config, struct wd_sched *sched) if (ret) goto out_clear_init;
- ret = wd_aead_init_nolock(config, sched); + ret = wd_aead_open_driver(); if (ret) goto out_clear_init;
+ ret = wd_aead_init_nolock(config, sched); + if (ret) + goto out_close_driver; + wd_alg_set_init(&wd_aead_setting.status);
return 0;
+out_close_driver: + wd_aead_close_driver(); out_clear_init: wd_alg_clear_init(&wd_aead_setting.status); return ret; @@ -499,18 +523,16 @@ static void wd_aead_uninit_nolock(void) if (!priv) return;
- wd_aead_setting.driver->exit(priv); - wd_aead_setting.priv = NULL; - free(priv); - wd_uninit_async_request_pool(&wd_aead_setting.pool); wd_clear_sched(&wd_aead_setting.sched); - wd_clear_ctx_config(&wd_aead_setting.config); + wd_alg_uninit_driver(&wd_aead_setting.config, + wd_aead_setting.driver, &priv); }
void wd_aead_uninit(void) { wd_aead_uninit_nolock(); + wd_aead_close_driver(); wd_alg_clear_init(&wd_aead_setting.status); }
@@ -518,8 +540,10 @@ void wd_aead_uninit(void) int wd_aead_init2_(char *alg, __u32 sched_type, int task_type, struct wd_ctx_params *ctx_params) { + struct wd_ctx_nums aead_ctx_num[WD_DIGEST_CIPHER_DECRYPTION + 1] = {0}; + struct wd_ctx_params aead_ctx_params = {0}; + int ret = 0; bool flag; - int ret;
pthread_atfork(NULL, NULL, wd_aead_clear_status);
@@ -534,21 +558,65 @@ int wd_aead_init2_(char *alg, __u32 sched_type, int task_type, goto out_uninit; }
+ /* + * Driver lib file path could set by env param. + * than open them by wd_dlopen_drv() + * use NULL means dynamic query path + */ + wd_aead_setting.dlh_list = wd_dlopen_drv(NULL); + if (!wd_aead_setting.dlh_list) { + WD_ERR("fail to open driver lib files.\n"); + goto out_uninit; + } + +res_retry: + memset(&wd_aead_setting.config, 0, sizeof(struct wd_ctx_config_internal)); + + /* Get alg driver and dev name */ + wd_aead_setting.driver = wd_alg_drv_bind(task_type, alg); + if (!wd_aead_setting.driver) { + WD_ERR("fail to bind a valid driver.\n"); + ret = -WD_EINVAL; + goto out_dlopen; + } + + ret = wd_ctx_param_init(&aead_ctx_params, ctx_params, + aead_ctx_num, wd_aead_setting.driver, + WD_DIGEST_CIPHER_DECRYPTION + 1); + if (ret) { + if (ret == -WD_EAGAIN) { + wd_disable_drv(wd_aead_setting.driver); + wd_alg_drv_unbind(wd_aead_setting.driver); + goto res_retry; + } + goto out_driver; + } + wd_aead_init_attrs.alg = alg; wd_aead_init_attrs.sched_type = sched_type; - wd_aead_init_attrs.ctx_params = ctx_params ? ctx_params : &wd_aead_ctx_params; + wd_aead_init_attrs.driver = wd_aead_setting.driver; + wd_aead_init_attrs.ctx_params = &aead_ctx_params; wd_aead_init_attrs.alg_init = wd_aead_init_nolock; wd_aead_init_attrs.alg_poll_ctx = wd_aead_poll_ctx; ret = wd_alg_attrs_init(&wd_aead_init_attrs); if (ret) { + if (ret == -WD_ENODEV) { + wd_disable_drv(wd_aead_setting.driver); + wd_alg_drv_unbind(wd_aead_setting.driver); + goto res_retry; + } WD_ERR("fail to init alg attrs.\n"); - goto out_uninit; + goto out_driver; }
wd_alg_set_init(&wd_aead_setting.status);
return 0;
+out_driver: + wd_alg_drv_unbind(wd_aead_setting.driver); +out_dlopen: + wd_dlclose_drv(wd_aead_setting.dlh_list); out_uninit: wd_alg_clear_init(&wd_aead_setting.status); return ret; @@ -557,9 +625,10 @@ out_uninit: void wd_aead_uninit2(void) { wd_aead_uninit_nolock(); - wd_alg_attrs_uninit(&wd_aead_init_attrs); - + wd_alg_drv_unbind(wd_aead_setting.driver); + wd_dlclose_drv(wd_aead_setting.dlh_list); + wd_aead_setting.dlh_list = NULL; wd_alg_clear_init(&wd_aead_setting.status); }
@@ -596,8 +665,8 @@ static int send_recv_sync(struct wd_ctx_internal *ctx, struct wd_msg_handle msg_handle; int ret;
- msg_handle.send = wd_aead_setting.driver->aead_send; - msg_handle.recv = wd_aead_setting.driver->aead_recv; + msg_handle.send = wd_aead_setting.driver->send; + msg_handle.recv = wd_aead_setting.driver->recv;
pthread_spin_lock(&ctx->lock); ret = wd_handle_msg_sync(&msg_handle, ctx->ctx, msg, NULL, @@ -676,7 +745,7 @@ int wd_do_aead_async(handle_t h_sess, struct wd_aead_req *req) fill_request_msg(msg, req, sess); msg->tag = msg_id;
- ret = wd_aead_setting.driver->aead_send(ctx->ctx, msg); + ret = wd_aead_setting.driver->send(ctx->ctx, msg); if (unlikely(ret < 0)) { if (ret != -WD_EBUSY) WD_ERR("failed to send BD, hw is err!\n"); @@ -724,7 +793,7 @@ int wd_aead_poll_ctx(__u32 idx, __u32 expt, __u32 *count) ctx = config->ctxs + idx;
do { - ret = wd_aead_setting.driver->aead_recv(ctx->ctx, &resp_msg); + ret = wd_aead_setting.driver->recv(ctx->ctx, &resp_msg); if (ret == -WD_EAGAIN) { return ret; } else if (ret < 0) {