From: Shangbin Liu liushangbin@hisilicon.com
This patchset fixes some issues of the uadk.
The first patch adds init wait timeout judgment to prevent deadlocks when making loopback calls from the same thread.
The second and third patches add a key length validity check before calculating the actual key length of the algorithm in xts mode. Because if the key length is odd, it will result in incorrect calculation results.
Shangbin Liu (3): uadk: add init wait timeout uadk: fix key length check error in xts mode uadk/v1: fix key length check error in xts mode
include/wd_util.h | 7 ++++--- v1/wd_cipher.c | 29 ++++++++++++++++------------- wd_aead.c | 16 +++++++--------- wd_cipher.c | 47 ++++++++++++++++++++++++++--------------------- wd_comp.c | 15 +++++++-------- wd_dh.c | 16 +++++++--------- wd_digest.c | 16 +++++++--------- wd_ecc.c | 15 +++++++-------- wd_rsa.c | 16 +++++++--------- wd_util.c | 18 +++++++++++------- 10 files changed, 99 insertions(+), 96 deletions(-)
From: Shangbin Liu liushangbin@hisilicon.com
Add init wait timeout judgment to prevent deadlocks when making loopback calls from the same thread.
Signed-off-by: Shangbin Liu liushangbin@hisilicon.com --- include/wd_util.h | 7 ++++--- wd_aead.c | 16 +++++++--------- wd_cipher.c | 15 +++++++-------- wd_comp.c | 15 +++++++-------- wd_dh.c | 16 +++++++--------- wd_digest.c | 16 +++++++--------- wd_ecc.c | 15 +++++++-------- wd_rsa.c | 16 +++++++--------- wd_util.c | 18 +++++++++++------- 9 files changed, 64 insertions(+), 70 deletions(-)
diff --git a/include/wd_util.h b/include/wd_util.h index 144ba59..a2d3ec3 100644 --- a/include/wd_util.h +++ b/include/wd_util.h @@ -384,10 +384,11 @@ int wd_init_param_check(struct wd_ctx_config *config, struct wd_sched *sched); * if need initialization. * @status: algorithm initialization status. * - * Return true if need initialization and false if initialized, otherwise will wait - * last initialization result. + * Return 0 if need initialization. + * Return -WD_EEXIST if the algorithm has been initialized. + * Return -WD_ETIMEDOUT if wait timeout. */ -bool wd_alg_try_init(enum wd_status *status); +int wd_alg_try_init(enum wd_status *status);
/** * wd_alg_set_init() - Set the algorithm status as WD_INIT. diff --git a/wd_aead.c b/wd_aead.c index 7c3f160..33a319c 100644 --- a/wd_aead.c +++ b/wd_aead.c @@ -453,14 +453,13 @@ out_clear_ctx_config:
int wd_aead_init(struct wd_ctx_config *config, struct wd_sched *sched) { - bool flag; int ret;
pthread_atfork(NULL, NULL, wd_aead_clear_status);
- flag = wd_alg_try_init(&wd_aead_setting.status); - if (!flag) - return -WD_EEXIST; + ret = wd_alg_try_init(&wd_aead_setting.status); + if (ret) + return ret;
ret = wd_init_param_check(config, sched); if (ret) @@ -525,14 +524,13 @@ int wd_aead_init2_(char *alg, __u32 sched_type, int task_type, { struct wd_ctx_nums aead_ctx_num[WD_DIGEST_CIPHER_DECRYPTION + 1] = {0}; struct wd_ctx_params aead_ctx_params = {0}; - int ret = -WD_EINVAL; - bool flag; + int state, ret = -WD_EINVAL;
pthread_atfork(NULL, NULL, wd_aead_clear_status);
- flag = wd_alg_try_init(&wd_aead_setting.status); - if (!flag) - return -WD_EEXIST; + state = wd_alg_try_init(&wd_aead_setting.status); + if (state) + return state;
if (!alg || sched_type >= SCHED_POLICY_BUTT || task_type < 0 || task_type >= TASK_MAX_TYPE) { diff --git a/wd_cipher.c b/wd_cipher.c index adb6496..52d3b79 100644 --- a/wd_cipher.c +++ b/wd_cipher.c @@ -354,14 +354,13 @@ static int wd_cipher_common_uninit(void)
int wd_cipher_init(struct wd_ctx_config *config, struct wd_sched *sched) { - bool flag; int ret;
pthread_atfork(NULL, NULL, wd_cipher_clear_status);
- flag = wd_alg_try_init(&wd_cipher_setting.status); - if (!flag) - return -WD_EEXIST; + ret = wd_alg_try_init(&wd_cipher_setting.status); + if (ret) + return ret;
ret = wd_init_param_check(config, sched); if (ret) @@ -402,14 +401,14 @@ int wd_cipher_init2_(char *alg, __u32 sched_type, int task_type, struct wd_ctx_p { struct wd_ctx_nums cipher_ctx_num[WD_CIPHER_DECRYPTION + 1] = {0}; struct wd_ctx_params cipher_ctx_params = {0}; - int ret = -WD_EINVAL; + int state, ret = -WD_EINVAL; bool flag;
pthread_atfork(NULL, NULL, wd_cipher_clear_status);
- flag = wd_alg_try_init(&wd_cipher_setting.status); - if (!flag) - return -WD_EEXIST; + state = wd_alg_try_init(&wd_cipher_setting.status); + if (state) + return state;
if (!alg || sched_type >= SCHED_POLICY_BUTT || task_type < 0 || task_type >= TASK_MAX_TYPE) { diff --git a/wd_comp.c b/wd_comp.c index 93c3031..f532d9e 100644 --- a/wd_comp.c +++ b/wd_comp.c @@ -175,14 +175,13 @@ static int wd_comp_uninit_nolock(void)
int wd_comp_init(struct wd_ctx_config *config, struct wd_sched *sched) { - bool flag; int ret;
pthread_atfork(NULL, NULL, wd_comp_clear_status);
- flag = wd_alg_try_init(&wd_comp_setting.status); - if (!flag) - return -WD_EEXIST; + ret = wd_alg_try_init(&wd_comp_setting.status); + if (ret) + return ret;
ret = wd_init_param_check(config, sched); if (ret) @@ -223,14 +222,14 @@ int wd_comp_init2_(char *alg, __u32 sched_type, int task_type, struct wd_ctx_par { struct wd_ctx_nums comp_ctx_num[WD_DIR_MAX] = {0}; struct wd_ctx_params comp_ctx_params; - int ret = -WD_EINVAL; + int state, ret = -WD_EINVAL; bool flag;
pthread_atfork(NULL, NULL, wd_comp_clear_status);
- flag = wd_alg_try_init(&wd_comp_setting.status); - if (!flag) - return -WD_EEXIST; + state = wd_alg_try_init(&wd_comp_setting.status); + if (state) + return state;
if (!alg || sched_type >= SCHED_POLICY_BUTT || task_type < 0 || task_type >= TASK_MAX_TYPE) { diff --git a/wd_dh.c b/wd_dh.c index 50a1532..b33aca3 100644 --- a/wd_dh.c +++ b/wd_dh.c @@ -141,14 +141,13 @@ static int wd_dh_common_uninit(void)
int wd_dh_init(struct wd_ctx_config *config, struct wd_sched *sched) { - bool flag; int ret;
pthread_atfork(NULL, NULL, wd_dh_clear_status);
- flag = wd_alg_try_init(&wd_dh_setting.status); - if (!flag) - return -WD_EEXIST; + ret = wd_alg_try_init(&wd_dh_setting.status); + if (ret) + return ret;
ret = wd_init_param_check(config, sched); if (ret) @@ -189,14 +188,13 @@ int wd_dh_init2_(char *alg, __u32 sched_type, int task_type, struct wd_ctx_param { struct wd_ctx_nums dh_ctx_num[WD_DH_PHASE2] = {0}; struct wd_ctx_params dh_ctx_params = {0}; - int ret = -WD_EINVAL; - bool flag; + int state, ret = -WD_EINVAL;
pthread_atfork(NULL, NULL, wd_dh_clear_status);
- flag = wd_alg_try_init(&wd_dh_setting.status); - if (!flag) - return -WD_EEXIST; + state = wd_alg_try_init(&wd_dh_setting.status); + if (state) + return state;
if (!alg || sched_type >= SCHED_POLICY_BUTT || task_type < 0 || task_type >= TASK_MAX_TYPE) { diff --git a/wd_digest.c b/wd_digest.c index c5dbeca..c58f8ff 100644 --- a/wd_digest.c +++ b/wd_digest.c @@ -267,14 +267,13 @@ out_clear_ctx_config:
int wd_digest_init(struct wd_ctx_config *config, struct wd_sched *sched) { - bool flag; int ret;
pthread_atfork(NULL, NULL, wd_digest_clear_status);
- flag = wd_alg_try_init(&wd_digest_setting.status); - if (!flag) - return -WD_EEXIST; + ret = wd_alg_try_init(&wd_digest_setting.status); + if (ret) + return ret;
ret = wd_init_param_check(config, sched); if (ret) @@ -335,14 +334,13 @@ int wd_digest_init2_(char *alg, __u32 sched_type, int task_type, { struct wd_ctx_params digest_ctx_params = {0}; struct wd_ctx_nums digest_ctx_num = {0}; - int ret = -WD_EINVAL; - bool flag; + int state, ret = -WD_EINVAL;
pthread_atfork(NULL, NULL, wd_digest_clear_status);
- flag = wd_alg_try_init(&wd_digest_setting.status); - if (!flag) - return -WD_EEXIST; + state = wd_alg_try_init(&wd_digest_setting.status); + if (state) + return state;
if (!alg || sched_type >= SCHED_POLICY_BUTT || task_type < 0 || task_type >= TASK_MAX_TYPE) { diff --git a/wd_ecc.c b/wd_ecc.c index 9f83fea..16bbfc5 100644 --- a/wd_ecc.c +++ b/wd_ecc.c @@ -207,14 +207,13 @@ static int wd_ecc_common_uninit(void)
int wd_ecc_init(struct wd_ctx_config *config, struct wd_sched *sched) { - bool flag; int ret;
pthread_atfork(NULL, NULL, wd_ecc_clear_status);
- flag = wd_alg_try_init(&wd_ecc_setting.status); - if (!flag) - return -WD_EEXIST; + ret = wd_alg_try_init(&wd_ecc_setting.status); + if (ret) + return ret;
ret = wd_init_param_check(config, sched); if (ret) @@ -255,14 +254,14 @@ int wd_ecc_init2_(char *alg, __u32 sched_type, int task_type, struct wd_ctx_para { struct wd_ctx_nums ecc_ctx_num[WD_EC_OP_MAX] = {0}; struct wd_ctx_params ecc_ctx_params = {0}; - int ret = -WD_EINVAL; + int state, ret = -WD_EINVAL; bool flag;
pthread_atfork(NULL, NULL, wd_ecc_clear_status);
- flag = wd_alg_try_init(&wd_ecc_setting.status); - if (!flag) - return -WD_EEXIST; + state = wd_alg_try_init(&wd_ecc_setting.status); + if (state) + return state;
if (!alg || sched_type >= SCHED_POLICY_BUTT || task_type < 0 || task_type >= TASK_MAX_TYPE) { diff --git a/wd_rsa.c b/wd_rsa.c index 19a590f..8520eb0 100644 --- a/wd_rsa.c +++ b/wd_rsa.c @@ -182,14 +182,13 @@ static int wd_rsa_common_uninit(void)
int wd_rsa_init(struct wd_ctx_config *config, struct wd_sched *sched) { - bool flag; int ret;
pthread_atfork(NULL, NULL, wd_rsa_clear_status);
- flag = wd_alg_try_init(&wd_rsa_setting.status); - if (!flag) - return -WD_EEXIST; + ret = wd_alg_try_init(&wd_rsa_setting.status); + if (ret) + return ret;
ret = wd_init_param_check(config, sched); if (ret) @@ -230,14 +229,13 @@ int wd_rsa_init2_(char *alg, __u32 sched_type, int task_type, struct wd_ctx_para { struct wd_ctx_nums rsa_ctx_num[WD_RSA_GENKEY] = {0}; struct wd_ctx_params rsa_ctx_params = {0}; - int ret = -WD_EINVAL; - bool flag; + int state, ret = -WD_EINVAL;
pthread_atfork(NULL, NULL, wd_rsa_clear_status);
- flag = wd_alg_try_init(&wd_rsa_setting.status); - if (!flag) - return -WD_EEXIST; + state = wd_alg_try_init(&wd_rsa_setting.status); + if (state) + return state;
if (!alg || sched_type >= SCHED_POLICY_BUTT || task_type < 0 || task_type >= TASK_MAX_TYPE) { diff --git a/wd_util.c b/wd_util.c index ef67f1f..cab25e8 100644 --- a/wd_util.c +++ b/wd_util.c @@ -25,6 +25,8 @@
#define WD_INIT_SLEEP_UTIME 1000 #define WD_INIT_RETRY_TIMES 10000 +#define US2S(us) ((us) >> 20) +#define WD_INIT_RETRY_TIMEOUT 3
#define DEF_DRV_LIB_FILE "libwd.so"
@@ -2298,10 +2300,10 @@ void wd_alg_drv_unbind(struct wd_alg_driver *drv) wd_release_drv(drv); }
-bool wd_alg_try_init(enum wd_status *status) +int wd_alg_try_init(enum wd_status *status) { enum wd_status expected; - int count = 0; + __u32 count = 0; bool ret;
do { @@ -2310,15 +2312,17 @@ bool wd_alg_try_init(enum wd_status *status) __ATOMIC_RELAXED, __ATOMIC_RELAXED); if (expected == WD_INIT) { WD_ERR("The algorithm has been initialized!\n"); - return false; + return -WD_EEXIST; } usleep(WD_INIT_SLEEP_UTIME); - if (!(++count % WD_INIT_RETRY_TIMES)) - WD_ERR("The algorithm initizalite has been waiting for %ds!\n", - WD_INIT_SLEEP_UTIME * count / 1000000); + + if (US2S(WD_INIT_SLEEP_UTIME * ++count) >= WD_INIT_RETRY_TIMEOUT) { + WD_ERR("The algorithm initialize wait timeout!\n"); + return -WD_ETIMEDOUT; + } } while (!ret);
- return true; + return 0; }
static __u32 wd_get_ctx_numbers(struct wd_ctx_params ctx_params, int end)
From: Shangbin Liu liushangbin@hisilicon.com
The input key in the xts mode is a combination of key1 and key2, so the key length is even. When calculating the algorithm key length, it is necessary to check whether the input key is even.
Signed-off-by: Shangbin Liu liushangbin@hisilicon.com --- wd_cipher.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-)
diff --git a/wd_cipher.c b/wd_cipher.c index 52d3b79..38345d8 100644 --- a/wd_cipher.c +++ b/wd_cipher.c @@ -11,7 +11,8 @@ #include "include/drv/wd_cipher_drv.h" #include "wd_cipher.h"
-#define XTS_MODE_KEY_DIVISOR 2 +#define XTS_MODE_KEY_SHIFT 1 +#define XTS_MODE_KEY_LEN_MASK 0x1 #define SM4_KEY_SIZE 16 #define DES_KEY_SIZE 8 #define DES3_2KEY_SIZE (2 * DES_KEY_SIZE) @@ -142,27 +143,36 @@ static int aes_key_len_check(__u32 length)
static int cipher_key_len_check(struct wd_cipher_sess *sess, __u32 length) { + __u32 key_len = length; int ret = 0;
- if (sess->mode == WD_CIPHER_XTS && length == AES_KEYSIZE_192) { - WD_ERR("unsupported XTS key length, length = %u\n", length); - return -WD_EINVAL; + if (sess->mode == WD_CIPHER_XTS) { + if (length & XTS_MODE_KEY_LEN_MASK) { + WD_ERR("invalid: unsupported XTS key length, length = %u!\n", length); + return -WD_EINVAL; + } + key_len = length >> XTS_MODE_KEY_SHIFT; + + if (key_len == AES_KEYSIZE_192) { + WD_ERR("invalid: unsupported XTS key length, length = %u!\n", length); + return -WD_EINVAL; + } }
switch (sess->alg) { case WD_CIPHER_SM4: - if (length != SM4_KEY_SIZE) + if (key_len != SM4_KEY_SIZE) ret = -WD_EINVAL; break; case WD_CIPHER_AES: - ret = aes_key_len_check(length); + ret = aes_key_len_check(key_len); break; case WD_CIPHER_DES: - if (length != DES_KEY_SIZE) + if (key_len != DES_KEY_SIZE) ret = -WD_EINVAL; break; case WD_CIPHER_3DES: - if (length != DES3_2KEY_SIZE && length != DES3_3KEY_SIZE) + if (key_len != DES3_2KEY_SIZE && key_len != DES3_3KEY_SIZE) ret = -WD_EINVAL; break; default: @@ -194,7 +204,6 @@ static bool wd_cipher_alg_check(const char *alg_name) int wd_cipher_set_key(handle_t h_sess, const __u8 *key, __u32 key_len) { struct wd_cipher_sess *sess = (struct wd_cipher_sess *)h_sess; - __u32 length = key_len; int ret;
if (!key || !sess) { @@ -202,10 +211,7 @@ int wd_cipher_set_key(handle_t h_sess, const __u8 *key, __u32 key_len) return -WD_EINVAL; }
- if (sess->mode == WD_CIPHER_XTS) - length = key_len / XTS_MODE_KEY_DIVISOR; - - ret = cipher_key_len_check(sess, length); + ret = cipher_key_len_check(sess, key_len); if (ret) { WD_ERR("cipher set key input key length err!\n"); return -WD_EINVAL;
From: Shangbin Liu liushangbin@hisilicon.com
The input key in the xts mode is a combination of key1 and key2, so the key length is even. When calculating the algorithm key length, it is necessary to check whether the input key is even.
Signed-off-by: Shangbin Liu liushangbin@hisilicon.com --- v1/wd_cipher.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/v1/wd_cipher.c b/v1/wd_cipher.c index 3d7d140..b5e3498 100644 --- a/v1/wd_cipher.c +++ b/v1/wd_cipher.c @@ -29,6 +29,7 @@ #define MAX_CIPHER_KEY_SIZE 64 #define MAX_CIPHER_RETRY_CNT 20000000
+#define XTS_MODE_KEY_LEN_MASK 0x1 #define DES_KEY_SIZE 8 #define SM4_KEY_SIZE 16 #define SEC_3DES_2KEY_SIZE (2 * DES_KEY_SIZE) @@ -259,30 +260,36 @@ static int aes_key_len_check(__u16 length) static int cipher_key_len_check(struct wcrypto_cipher_ctx_setup *setup, __u16 length) { + __u16 key_len = length; int ret = WD_SUCCESS;
if (setup->mode == WCRYPTO_CIPHER_XTS) { - if (length != AES_KEYSIZE_128 && length != AES_KEYSIZE_256) { - WD_ERR("unsupported XTS key length, length = %u.\n", - length); + if (length & XTS_MODE_KEY_LEN_MASK) { + WD_ERR("invalid: unsupported XTS key length, length = %u!\n", length); + return -WD_EINVAL; + } + key_len = length >> XTS_MODE_KEY_SHIFT; + + if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_256) { + WD_ERR("invalid: unsupported XTS key length, length = %u!\n", length); return -WD_EINVAL; } }
switch (setup->alg) { case WCRYPTO_CIPHER_SM4: - if (length != SM4_KEY_SIZE) + if (key_len != SM4_KEY_SIZE) ret = -WD_EINVAL; break; case WCRYPTO_CIPHER_AES: - ret = aes_key_len_check(length); + ret = aes_key_len_check(key_len); break; case WCRYPTO_CIPHER_DES: - if (length != DES_KEY_SIZE) + if (key_len != DES_KEY_SIZE) ret = -WD_EINVAL; break; case WCRYPTO_CIPHER_3DES: - if ((length != SEC_3DES_2KEY_SIZE) && (length != SEC_3DES_3KEY_SIZE)) + if ((key_len != SEC_3DES_2KEY_SIZE) && (key_len != SEC_3DES_3KEY_SIZE)) ret = -WD_EINVAL; break; default: @@ -296,7 +303,6 @@ static int cipher_key_len_check(struct wcrypto_cipher_ctx_setup *setup, int wcrypto_set_cipher_key(void *ctx, __u8 *key, __u16 key_len) { struct wcrypto_cipher_ctx *ctxt = ctx; - __u16 length = key_len; int ret;
if (!ctx || !key) { @@ -304,17 +310,14 @@ int wcrypto_set_cipher_key(void *ctx, __u8 *key, __u16 key_len) return -WD_EINVAL; }
- if (ctxt->setup.mode == WCRYPTO_CIPHER_XTS) - length = key_len >> XTS_MODE_KEY_SHIFT; - - ret = cipher_key_len_check(&ctxt->setup, length); + ret = cipher_key_len_check(&ctxt->setup, key_len); if (ret != WD_SUCCESS) { WD_ERR("%s: input key length err!\n", __func__); return ret; }
if (ctxt->setup.alg == WCRYPTO_CIPHER_DES && - is_des_weak_key((__u64 *)key, length)) { + is_des_weak_key((__u64 *)key, key_len)) { WD_ERR("%s: des weak key!\n", __func__); return -WD_EINVAL; }