Add new mode for cipher and digest
Weili Qian (4): uadk/cipher: support sm4-xts GB standard. uadk/v1/cipher: support sm4-xts GB standard uadk/v1/digest: support new AES mode algs uadk/v1: fix long hash state issue
drv/hisi_sec.c | 8 ++- include/wd_cipher.h | 3 + v1/drv/hisi_sec_udrv.c | 146 ++++++++++++++++++++++++++++++----------- v1/wd_cipher.c | 3 +- v1/wd_cipher.h | 5 ++ v1/wd_digest.c | 69 +++++++++++++++++-- v1/wd_digest.h | 24 +++++-- v1/wd_util.c | 2 +- wd_alg.c | 3 + wd_cipher.c | 9 +-- 10 files changed, 216 insertions(+), 56 deletions(-)
Support sm4-xts GB standard.
Signed-off-by: Weili Qian qianweili@huawei.com --- drv/hisi_sec.c | 8 +++++++- include/wd_cipher.h | 3 +++ wd_alg.c | 3 +++ wd_cipher.c | 9 +++++---- 4 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index 507f48b..03e7037 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -45,6 +45,8 @@ #define SEC_CALG_OFFSET_V3 4 #define SEC_AKEY_OFFSET_V3 9 #define SEC_MAC_OFFSET_V3 4 +#define SEC_SM4_XTS_STD_V3 25 +#define SEC_SM4_XTS_GB_V3 0x1 #define SEC_AUTH_ALG_OFFSET_V3 15 #define SEC_SVA_PREFETCH_OFFSET 27 #define SEC_ENABLE_SVA_PREFETCH 0x1 @@ -927,7 +929,7 @@ static int cipher_len_check(struct wd_cipher_msg *msg) msg->mode == WD_CIPHER_CTR) return 0;
- if (msg->mode == WD_CIPHER_XTS) { + if (msg->mode == WD_CIPHER_XTS || msg->mode == WD_CIPHER_XTS_GB) { if (msg->in_bytes < AES_BLOCK_SIZE) { WD_ERR("input cipher length is too small, size = %u\n", msg->in_bytes); @@ -1217,6 +1219,10 @@ static int fill_cipher_bd3_mode(struct wd_cipher_msg *msg, case WD_CIPHER_XTS: c_mode = C_MODE_XTS; break; + case WD_CIPHER_XTS_GB: + c_mode = C_MODE_XTS; + sqe->auth_mac_key |= (__u32)(SEC_SM4_XTS_GB_V3 << SEC_SM4_XTS_STD_V3); + break; case WD_CIPHER_CFB: c_mode = C_MODE_CFB; break; diff --git a/include/wd_cipher.h b/include/wd_cipher.h index 8f043fd..7e63402 100644 --- a/include/wd_cipher.h +++ b/include/wd_cipher.h @@ -50,6 +50,8 @@ enum wd_cipher_alg {
/** * wd_cipher_mode - Algorithm mode of cipher + * WD_CIPHER_XTS for xts specified by IEEE Std 1619-2007. + * WD_CIPHER_XTS_GB for xts specified by GB/T 17964-2021. */ enum wd_cipher_mode { WD_CIPHER_ECB, @@ -63,6 +65,7 @@ enum wd_cipher_mode { WD_CIPHER_CBC_CS3, WD_CIPHER_CCM, WD_CIPHER_GCM, + WD_CIPHER_XTS_GB, WD_CIPHER_MODE_TYPE_MAX, };
diff --git a/wd_alg.c b/wd_alg.c index be38e52..8d88316 100644 --- a/wd_alg.c +++ b/wd_alg.c @@ -213,6 +213,9 @@ bool wd_drv_alg_support(const char *alg_name, struct wd_alg_list *head = &alg_list_head; struct wd_alg_list *pnext = head->next;
+ if (!alg_name) + return false; + while (pnext) { if (!strcmp(alg_name, pnext->alg_name) && !strcmp(drv->drv_name, pnext->drv_name)) { diff --git a/wd_cipher.c b/wd_cipher.c index 2eaa77b..58d34f7 100644 --- a/wd_cipher.c +++ b/wd_cipher.c @@ -46,7 +46,8 @@ static const unsigned char des_weak_keys[DES_WEAK_KEY_NUM][DES_KEY_SIZE] = {
static char *wd_cipher_alg_name[WD_CIPHER_ALG_TYPE_MAX][WD_CIPHER_MODE_TYPE_MAX] = { {"ecb(sm4)", "cbc(sm4)", "ctr(sm4)", "xts(sm4)", "ofb(sm4)", - "cfb(sm4)", "cbc-cs1(sm4)", "cbc-cs2(sm4)", "cbc-cs3(sm4)"}, + "cfb(sm4)", "cbc-cs1(sm4)", "cbc-cs2(sm4)", "cbc-cs3(sm4)", + "", "", "xts(sm4)"}, {"ecb(aes)", "cbc(aes)", "ctr(aes)", "xts(aes)", "ofb(aes)", "cfb(aes)", "cbc-cs1(aes)", "cbc-cs2(aes)", "cbc-cs3(aes)"}, {"ecb(des)", "cbc(des)",}, @@ -145,7 +146,7 @@ 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) { + if (sess->mode == WD_CIPHER_XTS || sess->mode == WD_CIPHER_XTS_GB) { if (length & XTS_MODE_KEY_LEN_MASK) { WD_ERR("invalid: unsupported XTS key length, length = %u!\n", length); return -WD_EINVAL; @@ -250,13 +251,13 @@ handle_t wd_cipher_alloc_sess(struct wd_cipher_sess_setup *setup) }
sess->alg_name = wd_cipher_alg_name[setup->alg][setup->mode]; - sess->alg = setup->alg; - sess->mode = setup->mode; ret = wd_drv_alg_support(sess->alg_name, wd_cipher_setting.driver); if (!ret) { WD_ERR("failed to support this algorithm: %s!\n", sess->alg_name); goto err_sess; } + sess->alg = setup->alg; + sess->mode = setup->mode;
/* Some simple scheduler don't need scheduling parameters */ sess->sched_key = (void *)wd_cipher_setting.sched.sched_init(
Support sm4-xts GB standard.
Signed-off-by: Weili Qian qianweili@huawei.com --- v1/drv/hisi_sec_udrv.c | 11 ++++++++--- v1/wd_cipher.c | 3 ++- v1/wd_cipher.h | 5 +++++ 3 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/v1/drv/hisi_sec_udrv.c b/v1/drv/hisi_sec_udrv.c index 1249cb6..9866c10 100644 --- a/v1/drv/hisi_sec_udrv.c +++ b/v1/drv/hisi_sec_udrv.c @@ -37,6 +37,7 @@
#define SEC_HW_TASK_DONE 1 #define SEC_HW_ICV_ERR 0x2 +#define SEC_SM4_XTS_GB_V3 0x1 #define SQE_BYTES_NUMS 128 #define CTR_MODE_LEN_SHIFT 4 #define WORD_BYTES 4 @@ -699,7 +700,7 @@ static int cipher_param_check(struct wcrypto_cipher_msg *msg) msg->mode == WCRYPTO_CIPHER_CTR) return WD_SUCCESS;
- if (msg->mode == WCRYPTO_CIPHER_XTS) { + if (msg->mode == WCRYPTO_CIPHER_XTS || msg->mode == WCRYPTO_CIPHER_XTS_GB) { if (unlikely(msg->in_bytes < CBC_AES_BLOCK_SIZE)) { WD_ERR("input cipher length is too small!\n"); return -WD_EINVAL; @@ -893,6 +894,10 @@ static int fill_cipher_bd3_mode(struct wcrypto_cipher_msg *msg, case WCRYPTO_CIPHER_XTS: sqe->c_mode = C_MODE_XTS; break; + case WCRYPTO_CIPHER_XTS_GB: + sqe->c_mode = C_MODE_XTS; + sqe->ctr_counter_mode = SEC_SM4_XTS_GB_V3; + break; case WCRYPTO_CIPHER_CFB: sqe->c_mode = C_MODE_CFB; break; @@ -910,8 +915,7 @@ static int fill_cipher_bd3_mode(struct wcrypto_cipher_msg *msg, break; default: WD_ERR("Invalid cipher alg type!\n"); - ret = -WD_EINVAL; - break; + return -WD_EINVAL; }
return ret; @@ -967,6 +971,7 @@ static int sm4_mode_check(int mode) case WCRYPTO_CIPHER_CFB: case WCRYPTO_CIPHER_CTR: case WCRYPTO_CIPHER_XTS: + case WCRYPTO_CIPHER_XTS_GB: case WCRYPTO_CIPHER_CCM: case WCRYPTO_CIPHER_GCM: return WD_SUCCESS; diff --git a/v1/wd_cipher.c b/v1/wd_cipher.c index 624adb0..3e6fb3d 100644 --- a/v1/wd_cipher.c +++ b/v1/wd_cipher.c @@ -92,6 +92,7 @@ static __u32 get_iv_block_size(int alg, int mode) iv_block_size = CBC_3DES_BLOCK_SIZE; break; case WCRYPTO_CIPHER_XTS: + case WCRYPTO_CIPHER_XTS_GB: case WCRYPTO_CIPHER_CFB: case WCRYPTO_CIPHER_CTR: break; @@ -273,7 +274,7 @@ static int cipher_key_len_check(struct wcrypto_cipher_ctx_setup *setup, __u16 key_len = length; int ret = WD_SUCCESS;
- if (setup->mode == WCRYPTO_CIPHER_XTS) { + if (setup->mode == WCRYPTO_CIPHER_XTS || setup->mode == WCRYPTO_CIPHER_XTS_GB) { if (length & XTS_MODE_KEY_LEN_MASK) { WD_ERR("invalid: unsupported XTS key length, length = %u!\n", length); return -WD_EINVAL; diff --git a/v1/wd_cipher.h b/v1/wd_cipher.h index dafd8a4..29f3ebe 100644 --- a/v1/wd_cipher.h +++ b/v1/wd_cipher.h @@ -38,6 +38,10 @@ enum wcrypto_cipher_alg { WCRYPTO_CIPHER_3DES, };
+/** + * WCRYPTO_CIPHER_XTS for xts specified by IEEE Std 1619-2007. + * WCRYPTO_CIPHER_XTS_GB for xts specified by GB/T 17964-2021. + */ enum wcrypto_cipher_mode { WCRYPTO_CIPHER_ECB, WCRYPTO_CIPHER_CBC, @@ -50,6 +54,7 @@ enum wcrypto_cipher_mode { WCRYPTO_CIPHER_CBC_CS1, WCRYPTO_CIPHER_CBC_CS2, WCRYPTO_CIPHER_CBC_CS3, + WCRYPTO_CIPHER_XTS_GB, WCRYPTO_CIPHER_MODE_MAX, };
Supports some new auth algs: AES-CMAC,AES-GMAC,AES_XCBC_MAC_96,AES-CBC_PRF_128.
Signed-off-by: Weili Qian qianweili@huawei.com --- v1/drv/hisi_sec_udrv.c | 135 ++++++++++++++++++++++++++++++----------- v1/wd_digest.c | 69 +++++++++++++++++++-- v1/wd_digest.h | 24 ++++++-- 3 files changed, 182 insertions(+), 46 deletions(-)
diff --git a/v1/drv/hisi_sec_udrv.c b/v1/drv/hisi_sec_udrv.c index 9866c10..02a63c2 100644 --- a/v1/drv/hisi_sec_udrv.c +++ b/v1/drv/hisi_sec_udrv.c @@ -54,6 +54,7 @@ #define CBC_AES_BLOCK_SIZE 16 #define AEAD_IV_MAX_BYTES 64 #define MAX_CCM_AAD_LEN 65279 +#define SEC_GMAC_IV_LEN 16
static int g_digest_a_alg[WCRYPTO_MAX_DIGEST_TYPE] = { A_ALG_SM3, A_ALG_MD5, A_ALG_SHA1, A_ALG_SHA256, A_ALG_SHA224, @@ -62,7 +63,9 @@ static int g_digest_a_alg[WCRYPTO_MAX_DIGEST_TYPE] = { static int g_hmac_a_alg[WCRYPTO_MAX_DIGEST_TYPE] = { A_ALG_HMAC_SM3, A_ALG_HMAC_MD5, A_ALG_HMAC_SHA1, A_ALG_HMAC_SHA256, A_ALG_HMAC_SHA224, A_ALG_HMAC_SHA384, - A_ALG_HMAC_SHA512, A_ALG_HMAC_SHA512_224, A_ALG_HMAC_SHA512_256 + A_ALG_HMAC_SHA512, A_ALG_HMAC_SHA512_224, A_ALG_HMAC_SHA512_256, + A_ALG_AES_XCBC_MAC_96, A_ALG_AES_XCBC_PRF_128, A_ALG_AES_CMAC, + A_ALG_AES_GMAC };
static void parse_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, @@ -1128,13 +1131,19 @@ int qm_fill_cipher_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i) return ret; }
-static int digest_param_check(struct wcrypto_digest_msg *msg) +static int digest_param_check(struct wcrypto_digest_msg *msg, __u8 bd_type) { if (unlikely(msg->alg >= WCRYPTO_MAX_DIGEST_TYPE)) { WD_ERR("invalid digest type!\n"); return -WD_EINVAL; }
+ if (msg->alg >= WCRYPTO_AES_XCBC_MAC_96 && + (bd_type == BD_TYPE1 || bd_type == BD_TYPE2)) { + WD_ERR("invalid: BD tpye does not support the alg %d!\n", msg->alg); + return -WD_EINVAL; + } + if (unlikely(msg->in_bytes > MAX_CIPHER_LENGTH)) { WD_ERR("invalid digest in_bytes!\n"); return -WD_EINVAL; @@ -1153,12 +1162,12 @@ static int fill_digest_bd2_alg(struct wcrypto_digest_msg *msg, { int ret;
- ret = digest_param_check(msg); + ret = digest_param_check(msg, BD_TYPE2); if (unlikely(ret)) return ret;
if(unlikely(msg->in_bytes == 0)) { - if ((msg->has_next && !msg->iv_bytes) || (msg->has_next && msg->iv_bytes)) { + if (msg->has_next) { /* Long hash first and middle BD */ WD_ERR("invalid: digest bd2 not supports 0 packet in first bd and middle bd!\n"); return -WD_EINVAL; @@ -1223,7 +1232,7 @@ static int fill_digest_bd1_alg(struct wcrypto_digest_msg *msg, { int ret;
- ret = digest_param_check(msg); + ret = digest_param_check(msg, BD_TYPE1); if (unlikely(ret)) return ret;
@@ -1513,12 +1522,29 @@ int qm_fill_digest_sqe(void *message, struct qm_queue_info *info, __u16 i) return WD_SUCCESS; }
-static void qm_fill_digest_long_bd3(struct wcrypto_digest_msg *msg, +static int qm_fill_digest_long_bd3(struct wcrypto_digest_msg *msg, struct hisi_sec_bd3_sqe *sqe) { struct wcrypto_digest_tag *digest_tag = (void *)(uintptr_t)msg->usr_data; __u64 total_bits = 0;
+ if (msg->alg == WCRYPTO_AES_XCBC_MAC_96 || + msg->alg == WCRYPTO_AES_XCBC_PRF_128 || + msg->alg == WCRYPTO_AES_CMAC || + msg->alg == WCRYPTO_AES_GMAC) { + if (msg->has_next) { + WD_ERR("aes alg %d not supports long hash mode!\n", msg->alg); + return -WD_EINVAL; + } + return WD_SUCCESS; + } + + if (unlikely(msg->has_next && !msg->in_bytes)) { + /* Long hash first and middle BD */ + WD_ERR("invalid: digest bd3 not supports 0 packet in first bd and middle bd!\n"); + return -WD_EINVAL; + } + /* iv_bytes is multiplexed as a flag bit to determine whether it is LOGN BD FIRST */ if (msg->has_next && msg->iv_bytes == 0) { /* LONG BD FIRST */ @@ -1548,26 +1574,13 @@ static void qm_fill_digest_long_bd3(struct wcrypto_digest_msg *msg, /* SHORT BD */ msg->iv_bytes = 0; } + + return WD_SUCCESS; }
static int fill_digest_bd3_alg(struct wcrypto_digest_msg *msg, struct hisi_sec_bd3_sqe *sqe) { - int ret; - - ret = digest_param_check(msg); - if (unlikely(ret)) - return ret; - - if (unlikely(msg->in_bytes == 0)) { - if ((msg->has_next && !msg->iv_bytes) || (msg->has_next && msg->iv_bytes)) { - /* Long hash first and middle BD */ - WD_ERR("invalid: digest bd3 not supports 0 packet in first bd and middle bd!\n"); - return -WD_EINVAL; - } - } - - sqe->mac_len = msg->out_bytes / WORD_BYTES; if (msg->mode == WCRYPTO_DIGEST_NORMAL) sqe->a_alg = g_digest_a_alg[msg->alg]; else if (msg->mode == WCRYPTO_DIGEST_HMAC) @@ -1591,8 +1604,7 @@ static int set_hmac_mode_v3(struct wcrypto_digest_msg *msg,
if (unlikely(msg->key_bytes & WORD_ALIGNMENT_MASK)) { WD_ERR("Invalid digest key_bytes!\n"); - ret = -WD_EINVAL; - return ret; + return -WD_EINVAL; } sqe->a_key_len = msg->key_bytes / WORD_BYTES; ret = map_addr(q, msg->key, msg->key_bytes, @@ -1604,21 +1616,68 @@ static int set_hmac_mode_v3(struct wcrypto_digest_msg *msg, return ret; }
- return 0; + if (msg->alg != WCRYPTO_AES_GMAC) + return WD_SUCCESS; + + sqe->ai_gen = AI_GEN_IVIN_ADDR; + ret = map_addr(q, msg->iv, SEC_GMAC_IV_LEN, &sqe->auth_key_iv.a_ivin_addr_l, + &sqe->auth_key_iv.a_ivin_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Get digest bd3 hmac iv dma address fail!\n"); + unmap_addr(q, msg->key, msg->key_bytes, sqe->auth_key_iv.a_key_addr_l, + sqe->auth_key_iv.a_key_addr_h, msg->data_fmt); + return ret; + } + + return WD_SUCCESS; +} + +static int digest_param_check_v3(struct wcrypto_digest_msg *msg) +{ + int ret; + + ret = digest_param_check(msg, BD_TYPE3); + if (unlikely(ret)) + return ret; + + if (unlikely(!msg->in_bytes && + (msg->alg == WCRYPTO_AES_XCBC_MAC_96 || + msg->alg == WCRYPTO_AES_XCBC_PRF_128 || + msg->alg == WCRYPTO_AES_CMAC))) { + WD_ERR("invalid: digest mode %d not supports 0 packet!\n", msg->alg); + return -WD_EINVAL; + } + + if (unlikely((msg->alg == WCRYPTO_AES_XCBC_MAC_96 && + msg->out_bytes != WCRYPTO_AES_XCBC_MAC_96_LEN) || + (msg->alg == WCRYPTO_AES_XCBC_PRF_128 && + msg->out_bytes != WCRYPTO_AES_XCBC_PRF_128_LEN))) { + WD_ERR("invalid digest out_bytes %u, msg->alg = %d!\n", + msg->out_bytes, msg->alg); + return -WD_EINVAL; + } + + return WD_SUCCESS; }
static int fill_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, struct wcrypto_digest_msg *msg, struct wcrypto_digest_tag *tag) { - int ret = -WD_ENOMEM; uintptr_t phy; + int ret; + + ret = digest_param_check_v3(msg); + if (unlikely(ret)) + return ret;
sqe->type = BD_TYPE3; - sqe->scene = SCENE_STREAM; + if (msg->alg == WCRYPTO_AES_GMAC) + sqe->scene = SCENE_IPSEC; + else + sqe->scene = SCENE_STREAM;
sqe->auth = AUTH_MAC_CALCULATE; sqe->a_len = msg->in_bytes; - phy = (uintptr_t)drv_iova_map(q, msg->in, msg->in_bytes); if (unlikely(!phy)) { WD_ERR("Get message in dma address fail!\n"); @@ -1634,17 +1693,21 @@ static int fill_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, WD_ERR("Get digest bd3 message out dma address fail!\n"); goto map_out_error; } - - ret = set_hmac_mode_v3(msg, sqe, q); - if (ret) - goto map_key_error; + sqe->mac_len = msg->out_bytes / WORD_BYTES;
ret = fill_digest_bd3_alg(msg, sqe); if (ret != WD_SUCCESS) { WD_ERR("fill_digest_bd3_alg fail!\n"); goto map_alg_error; } - qm_fill_digest_long_bd3(msg, sqe); + + ret = qm_fill_digest_long_bd3(msg, sqe); + if (ret) + goto map_alg_error; + + ret = set_hmac_mode_v3(msg, sqe, q); + if (ret) + goto map_alg_error;
if (tag) sqe->tag_l = tag->wcrypto_tag.ctx_id; @@ -1652,9 +1715,6 @@ static int fill_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, return ret;
map_alg_error: - unmap_addr(q, msg->key, msg->key_bytes, sqe->auth_key_iv.a_key_addr_l, - sqe->auth_key_iv.a_key_addr_h, msg->data_fmt); -map_key_error: unmap_addr(q, msg->out, msg->out_bytes, sqe->mac_addr_l, sqe->mac_addr_h, msg->data_fmt); map_out_error: @@ -2585,6 +2645,11 @@ static void parse_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, unmap_addr(q, digest_msg->key, digest_msg->key_bytes, sqe->auth_key_iv.a_key_addr_l, sqe->auth_key_iv.a_key_addr_h, digest_msg->data_fmt); + + if (digest_msg->alg == WCRYPTO_AES_GMAC) + unmap_addr(q, digest_msg->iv, SEC_GMAC_IV_LEN, + sqe->auth_key_iv.a_ivin_addr_l, + sqe->auth_key_iv.a_ivin_addr_h, digest_msg->data_fmt); }
int qm_parse_digest_bd3_sqe(void *msg, const struct qm_queue_info *info, diff --git a/v1/wd_digest.c b/v1/wd_digest.c index be43c73..f6c8b84 100644 --- a/v1/wd_digest.c +++ b/v1/wd_digest.c @@ -30,6 +30,7 @@ #define MAX_DIGEST_RETRY_CNT 20000000 #define SEC_SHA1_ALIGN_SZ 64 #define SEC_SHA512_ALIGN_SZ 128 +#define SEC_GMAC_IV_LEN 16
struct wcrypto_digest_cookie { struct wcrypto_digest_tag tag; @@ -51,7 +52,9 @@ static __u32 g_digest_mac_len[WCRYPTO_MAX_DIGEST_TYPE] = { WCRYPTO_DIGEST_SM3_LEN, WCRYPTO_DIGEST_MD5_LEN, WCRYPTO_DIGEST_SHA1_LEN, WCRYPTO_DIGEST_SHA256_LEN, WCRYPTO_DIGEST_SHA224_LEN, WCRYPTO_DIGEST_SHA384_LEN, WCRYPTO_DIGEST_SHA512_LEN, - WCRYPTO_DIGEST_SHA512_224_LEN, WCRYPTO_DIGEST_SHA512_256_LEN + WCRYPTO_DIGEST_SHA512_224_LEN, WCRYPTO_DIGEST_SHA512_256_LEN, + WCRYPTO_AES_XCBC_MAC_96_LEN, WCRYPTO_AES_XCBC_PRF_128_LEN, + WCRYPTO_AES_CMAC_LEN, WCRYPTO_AES_GMAC_LEN };
static __u32 g_digest_mac_full_len[WCRYPTO_MAX_DIGEST_TYPE] = { @@ -103,6 +106,17 @@ static int create_ctx_para_check(struct wd_queue *q, return -WD_EINVAL; }
+ if (setup->alg >= WCRYPTO_MAX_DIGEST_TYPE) { + WD_ERR("invalid: the alg %d does not support!\n", setup->alg); + return -WD_EINVAL; + } + + if (setup->mode == WCRYPTO_DIGEST_NORMAL && + setup->alg >= WCRYPTO_AES_XCBC_MAC_96) { + WD_ERR("invalid: the alg %d does not support normal mode!\n", setup->alg); + return -WD_EINVAL; + } + return WD_SUCCESS; }
@@ -246,26 +260,65 @@ static void digest_requests_init(struct wcrypto_digest_msg **req, req[i]->in_bytes = op[i]->in_bytes; req[i]->out = op[i]->out; req[i]->out_bytes = op[i]->out_bytes; + req[i]->iv = op[i]->iv; c->io_bytes += op[i]->in_bytes; } }
+static int digest_hmac_key_check(enum wcrypto_digest_alg alg, __u16 key_len) +{ + switch (alg) { + case WCRYPTO_SM3 ... WCRYPTO_SHA224: + if (key_len > (MAX_HMAC_KEY_SIZE >> 1)) { + WD_ERR("failed to check alg %u key bytes, key_len = %u\n", alg, key_len); + return -WD_EINVAL; + } + break; + case WCRYPTO_SHA384 ... WCRYPTO_SHA512_256: + break; + case WCRYPTO_AES_XCBC_MAC_96: + case WCRYPTO_AES_XCBC_PRF_128: + case WCRYPTO_AES_CMAC: + if (key_len != AES_KEYSIZE_128) { + WD_ERR("failed to check alg %u key bytes, key_len = %u\n", alg, key_len); + return -WD_EINVAL; + } + break; + case WCRYPTO_AES_GMAC: + if (key_len != AES_KEYSIZE_128 && + key_len != AES_KEYSIZE_192 && + key_len != AES_KEYSIZE_256) { + WD_ERR("failed to check alg %u key bytes, key_len = %u\n", alg, key_len); + return -WD_EINVAL; + } + break; + default: + WD_ERR("failed to check digest key bytes, invalid alg type = %d\n", alg); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + int wcrypto_set_digest_key(void *ctx, __u8 *key, __u16 key_len) { struct wcrypto_digest_ctx *ctxt = ctx; + int ret;
if (!ctx || !key) { WD_ERR("%s(): input param err!\n", __func__); return -WD_EINVAL; }
- if ((ctxt->setup.alg <= WCRYPTO_SHA224 && key_len > - MAX_HMAC_KEY_SIZE >> 1) || key_len == 0 || - key_len > MAX_HMAC_KEY_SIZE) { - WD_ERR("%s: input key length err!\n", __func__); + if (key_len == 0 || key_len > MAX_HMAC_KEY_SIZE) { + WD_ERR("%s: input key length err, key_len = %u!\n", __func__, key_len); return -WD_EINVAL; }
+ ret = digest_hmac_key_check(ctxt->setup.alg, key_len); + if (ret) + return ret; + ctxt->key_bytes = key_len;
if (ctxt->setup.data_fmt == WD_SGL_BUF) @@ -361,6 +414,12 @@ static int param_check(struct wcrypto_digest_ctx *d_ctx, WD_ERR("failed to check digest mac length!\n"); return -WD_EINVAL; } + if (d_ctx->setup.alg == WCRYPTO_AES_GMAC && + d_opdata[i]->iv_bytes != SEC_GMAC_IV_LEN) { + WD_ERR("failed to check digest aes_gmac iv length, iv_bytes = %u\n", + d_opdata[i]->iv_bytes); + return -WD_EINVAL; + } }
if (unlikely(tag && !tag[i])) { diff --git a/v1/wd_digest.h b/v1/wd_digest.h index 8f7ac2e..9667a66 100644 --- a/v1/wd_digest.h +++ b/v1/wd_digest.h @@ -36,6 +36,10 @@ enum wcrypto_digest_alg { WCRYPTO_SHA512, WCRYPTO_SHA512_224, WCRYPTO_SHA512_256, + WCRYPTO_AES_XCBC_MAC_96, + WCRYPTO_AES_XCBC_PRF_128, + WCRYPTO_AES_CMAC, + WCRYPTO_AES_GMAC, WCRYPTO_MAX_DIGEST_TYPE, };
@@ -43,12 +47,16 @@ enum wd_digest_mac_len { WCRYPTO_DIGEST_SM3_LEN = 32, WCRYPTO_DIGEST_MD5_LEN = 16, WCRYPTO_DIGEST_SHA1_LEN = 20, - WCRYPTO_DIGEST_SHA256_LEN = 32, - WCRYPTO_DIGEST_SHA224_LEN = 28, - WCRYPTO_DIGEST_SHA384_LEN = 48, - WCRYPTO_DIGEST_SHA512_LEN = 64, - WCRYPTO_DIGEST_SHA512_224_LEN = 28, - WCRYPTO_DIGEST_SHA512_256_LEN = 32 + WCRYPTO_DIGEST_SHA256_LEN = 32, + WCRYPTO_DIGEST_SHA224_LEN = 28, + WCRYPTO_DIGEST_SHA384_LEN = 48, + WCRYPTO_DIGEST_SHA512_LEN = 64, + WCRYPTO_DIGEST_SHA512_224_LEN = 28, + WCRYPTO_DIGEST_SHA512_256_LEN = 32, + WCRYPTO_AES_XCBC_MAC_96_LEN = 12, + WCRYPTO_AES_XCBC_PRF_128_LEN = 16, + WCRYPTO_AES_CMAC_LEN = 16, + WCRYPTO_AES_GMAC_LEN = 16, };
enum wcrypto_digest_mac_full_len { @@ -93,6 +101,8 @@ struct wcrypto_digest_ctx_setup { * @priv:reserved data field segment * @status:I/O operation return status * @has_next: is there next data block + * @iv: initialization verctor data address + * @iv_bytes:initialization verctor data size */ struct wcrypto_digest_op_data { void *in; @@ -102,6 +112,8 @@ struct wcrypto_digest_op_data { void *priv; int status; bool has_next; + void *iv; + __u32 iv_bytes; };
/* Digest message format of Warpdrive */
'iv_bytes' in msg is used as the packet status in the long hash service. If initial value is not 0, the long hash calculation may be abnormal. Therefore, initialize the cookie to 0.
Signed-off-by: Weili Qian qianweili@huawei.com --- v1/wd_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/v1/wd_util.c b/v1/wd_util.c index 6b8f944..a1d08b4 100644 --- a/v1/wd_util.c +++ b/v1/wd_util.c @@ -87,7 +87,7 @@ int wd_init_cookie_pool(struct wd_cookie_pool *pool, { __u64 total_size = cookies_size * cookies_num;
- pool->cookies = malloc(total_size + cookies_num); + pool->cookies = calloc(1, total_size + cookies_num); if (!pool->cookies) return -WD_ENOMEM;