supports new auth algs and cipher algs.
Signed-off-by: Kai Ye yekai13@huawei.com --- test/hisi_sec_test/test_hisi_sec.c | 185 +++++++++++++++++++++++++++-- test/hisi_sec_test/test_hisi_sec.h | 140 ++++++++++++++++++++++ 2 files changed, 317 insertions(+), 8 deletions(-) mode change 100644 => 100755 test/hisi_sec_test/test_hisi_sec.c
diff --git a/test/hisi_sec_test/test_hisi_sec.c b/test/hisi_sec_test/test_hisi_sec.c old mode 100644 new mode 100755 index 6f27cd1..9aa4e56 --- a/test/hisi_sec_test/test_hisi_sec.c +++ b/test/hisi_sec_test/test_hisi_sec.c @@ -30,7 +30,7 @@ #define SCHED_SINGLE "sched_single" #define SCHED_NULL_CTX_SIZE 4 #define TEST_WORD_LEN 4096 -#define MAX_ALGO_PER_TYPE 13 +#define MAX_ALGO_PER_TYPE 16 #define MIN_SVA_BD_NUM 1
#define SGL_ALIGNED_BYTES 64 @@ -59,7 +59,26 @@ static struct hash_testvec g_long_hash_tv;
char *skcipher_names[MAX_ALGO_PER_TYPE] = {"ecb(aes)", "cbc(aes)", "xts(aes)", "ofb(aes)", "cfb(aes)", "ecb(des3_ede)", - "cbc(des3_ede)", "cbc(sm4)", "xts(sm4)", "ofb(sm4)", "cfb(sm4)", "ecb(sm4)", NULL,}; + "cbc(des3_ede)", "cbc(sm4)", "xts(sm4)", "ofb(sm4)", "cfb(sm4)", "ecb(sm4)", + "cbc_cs1(aes)", "cbc_cs2(aes)", "cbc_cs3(aes)", NULL,}; + +enum digest_type { + LOCAL_SM3, + LOCAL_MD5, + LOCAL_SHA1, + LOCAL_SHA256, + LOCAL_SHA224, + LOCAL_SHA384, + LOCAL_SHA512, + LOCAL_SHA512_224, + LOCAL_SHA512_256, + LOCAL_AES_CMAC, + LOCAL_AES_GMAC_128, + LOCAL_AES_GMAC_192, + LOCAL_AES_GMAC_256, + LOCAL_AES_XCBC_MAC_96, +}; + struct sva_bd { char *src; char *dst; @@ -452,6 +471,66 @@ int get_cipher_resource(struct cipher_testvec **alg_tv, int* alg, int* mode) } tv = &sm4_ecb_tv_template_128[0]; break; + case 12: + alg_type = WD_CIPHER_AES; + switch (g_keylen) { + case AES_KEYSIZE_128: + mode_type = WD_CIPHER_CBC_CS1; + tv = &aes_cbc_cs1_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + mode_type = WD_CIPHER_CBC_CS1; + tv = &aes_cbc_cs1_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + mode_type = WD_CIPHER_CBC_CS1; + tv = &aes_cbc_cs1_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 13: + alg_type = WD_CIPHER_AES; + switch (g_keylen) { + case AES_KEYSIZE_128: + mode_type = WD_CIPHER_CBC_CS2; + tv = &aes_cbc_cs1_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + mode_type = WD_CIPHER_CBC_CS2; + tv = &aes_cbc_cs1_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + mode_type = WD_CIPHER_CBC_CS2; + tv = &aes_cbc_cs1_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 14: + alg_type = WD_CIPHER_AES; + switch (g_keylen) { + case AES_KEYSIZE_128: + mode_type = WD_CIPHER_CBC_CS3; + tv = &aes_cbc_cs1_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + mode_type = WD_CIPHER_CBC_CS3; + tv = &aes_cbc_cs1_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + mode_type = WD_CIPHER_CBC_CS3; + tv = &aes_cbc_cs1_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; case 16: alg_type = WD_CIPHER_AES; mode_type = WD_CIPHER_CBC; @@ -622,8 +701,12 @@ static int test_sec_cipher_sync_once(void) }
SEC_TST_PRT("req src--------->:\n"); - copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, - (void *)tv->ptext, (size_t)tv->len); + if (g_direction == 0) + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, + (void *)tv->ptext, (size_t)tv->len); + else + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, + (void *)tv->ctext, (size_t)tv->len); dump_mem(g_data_fmt, req.src, req.in_bytes);
req.out_bytes = tv->len; @@ -755,8 +838,12 @@ static int test_sec_cipher_async_once(void) }
SEC_TST_PRT("req src--------->:\n"); - copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, - (void *)tv->ptext, (size_t)tv->len); + if (g_direction == 0) + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, + (void *)tv->ptext, (size_t)tv->len); + else + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, + (void *)tv->ctext, (size_t)tv->len); dump_mem(g_data_fmt, req.src, req.in_bytes);
req.out_bytes = tv->len; @@ -767,7 +854,6 @@ static int test_sec_cipher_async_once(void) goto out_dst; }
- req.iv = malloc(IV_SIZE); if (!req.iv) { ret = -ENOMEM; @@ -1510,6 +1596,73 @@ int get_digest_resource(struct hash_testvec **alg_tv, int* alg, int* mode) tv->dsize = 32; alg_type = WD_DIGEST_SHA512_256; break; + case 9: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-cmac"); + tv = &aes_cmac_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_AES_CMAC; + break; + case 10: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-gmac-128"); + tv = &aes_gmac_128_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_AES_GMAC; + break; + case 11: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-gmac-192"); + tv = &aes_gmac_192_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_AES_GMAC; + break; + case 12: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-gmac-256"); + tv = &aes_gmac_256_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_AES_GMAC; + break; + case 13: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-xcbc-mac-96"); + tv = &aes_xcbc_mac_96_tv_template[0]; + break; + } + tv->dsize = 12; + alg_type = WD_DIGEST_AES_XCBC_MAC_96; + break; + case 14: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-xcbc-prf-128"); + tv = &aes_xcbc_mac_96_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_AES_XCBC_PRF_128; + break; + default: SEC_TST_PRT("keylenth error, default test alg: %s\n", "normal(sm3)"); return -EINVAL; @@ -1599,6 +1752,18 @@ static int sec_digest_sync_once(void) SEC_TST_PRT("sess set key failed!\n"); goto out_key; } + + if (g_testalg == LOCAL_AES_GMAC_128 || + g_testalg == LOCAL_AES_GMAC_192 || + g_testalg == LOCAL_AES_GMAC_256) { + req.iv = malloc(sizeof(char) * 16); + if (!req.iv) { + SEC_TST_PRT("failed to alloc iv memory!\n"); + goto out_key; + } + memcpy(req.iv, tv->iv, 16); + req.iv_bytes = 16; + } }
gettimeofday(&start_tval, NULL); @@ -1625,6 +1790,7 @@ out_dst: free_buf(g_data_fmt, req.in); out_src: digest_uninit_config(); + free(req.iv);
return ret; } @@ -3858,11 +4024,14 @@ static void print_help(void) SEC_TST_PRT(" 0 : AES-ECB; 1 : AES-CBC; 2 : AES-XTS; 3 : AES-OFB\n"); SEC_TST_PRT(" 4 : AES-CFB; 5 : 3DES-ECB; 6 : 3DES-CBC; 7 : SM4-CBC\n"); SEC_TST_PRT(" 8 : SM4-XTS; 9 : SM4-OFB; 10 : SM4-CFB; 11 : SM4-ECB\n"); + SEC_TST_PRT(" 12 : AES-CBC_CS1; 13 : AES-CBC_CS2; 14 : AES-CBC_CS3\n"); SEC_TST_PRT(" [--digest ]:\n"); SEC_TST_PRT(" specify symmetric hash algorithm\n"); SEC_TST_PRT(" 0 : SM3; 1 : MD5; 2 : SHA1; 3 : SHA256\n"); SEC_TST_PRT(" 4 : SHA224; 5 : SHA384; 6 : SHA512; 7 : SHA512_224\n"); - SEC_TST_PRT(" 8 : SHA512_256\n"); + SEC_TST_PRT(" 8 : SHA512_256; 9 : AES_CMAC; 10 : AES_GMAC_128\n"); + SEC_TST_PRT(" 11 : AES_GMAC_192; 12 : AES_GMAC_256; 13 : AES_XCBC_MAC_96\n"); + SEC_TST_PRT(" 14 : AES_XCBC_PRF_128\n"); SEC_TST_PRT(" [--aead ]:\n"); SEC_TST_PRT(" specify symmetric aead algorithm\n"); SEC_TST_PRT(" 0 : AES-CCM; 1 : AES-GCM; 2 : Hmac(sha256),cbc(aes)\n"); diff --git a/test/hisi_sec_test/test_hisi_sec.h b/test/hisi_sec_test/test_hisi_sec.h index defd3c4..8e21681 100644 --- a/test/hisi_sec_test/test_hisi_sec.h +++ b/test/hisi_sec_test/test_hisi_sec.h @@ -43,6 +43,7 @@ struct cipher_testvec { struct hash_testvec { char *key; char *plaintext; + char *iv; const char *digest; unsigned int psize; unsigned short ksize; @@ -298,6 +299,93 @@ struct hash_testvec hmac_sha512_256_tv_template[] = { }, };
+struct hash_testvec aes_cmac_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ksize = 16, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + } +}; + +struct hash_testvec aes_gmac_128_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ksize = 16, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + } +}; + +struct hash_testvec aes_gmac_192_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .ksize = 24, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + } +}; + +struct hash_testvec aes_gmac_256_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .ksize = 32, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + } +}; + +struct hash_testvec aes_xcbc_mac_96_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ksize = 16, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + } +}; + +struct hash_testvec aes_xcbc_prf_128_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ksize = 16, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + } +}; + struct hash_testvec long_hash_tv_template[] = { { /* @@ -878,6 +966,58 @@ struct cipher_testvec aes_cbc_tv_template_128[] = { } };
+struct cipher_testvec aes_cbc_cs1_tv_template_128[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .klen = 16, + .iv = "\x33\x33\x33\x33\x33\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .ctext = "\x4d\xe5\xc3\xd2\x9e\xe1\x29\x73" + "\x8b\x10\x7b\xde\x5e\x6c\xdb\x36" + "\x95\x35\x5e\x0c\x42\xc8\x33\x7a" + "\x17\x36\xa4\x34\xfd\xb1\x12\xbf", + .len = 32, + } +}; + +struct cipher_testvec aes_cbc_cs1_tv_template_192[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 24, + .iv = "\x33\x33\x33\x33\x33\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .len = 32, + } +}; + +struct cipher_testvec aes_cbc_cs1_tv_template_256[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .len = 32, + } +}; + struct cipher_testvec aes_cbc_perf_128[] = { { .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
1. supports some new auth algs and ciphers. auth algs: AES-CMAC,AES-GMAC,AES_XCBC_MAC_96,AES-CBC_PRF_128
cipher algs: AES_CBC_CS1,AES_CBC_CS2,AES_CBC_CS3
2. modify some function name.
Signed-off-by: Kai Ye yekai13@huawei.com --- drv/hisi_sec.c | 237 ++++++++++++++++++++++++----- include/wd_cipher.h | 6 +- include/wd_digest.h | 16 +- test/hisi_sec_test/test_hisi_sec.c | 3 + wd_aead.c | 11 +- wd_cipher.c | 3 + wd_digest.c | 73 +++++++-- 7 files changed, 290 insertions(+), 59 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index 858dbb6..eaffbea 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -41,6 +41,7 @@
#define SEC_DE_OFFSET_V3 9 #define SEC_SCENE_OFFSET_V3 5 +#define SEC_CWIDTH_OFFSET_V3 10 #define SEC_CKEY_OFFSET_V3 13 #define SEC_CALG_OFFSET_V3 4 #define SEC_AKEY_OFFSET_V3 9 @@ -171,6 +172,12 @@ enum sec_bd_type { BD_TYPE3 = 0x3, };
+enum sec_c_width { + C_WIDTH_CS1 = 0x1, + C_WIDTH_CS2 = 0x2, + C_WIDTH_CS3 = 0x3, +}; + struct hisi_sec_ctx { struct wd_ctx_config_internal config; }; @@ -480,7 +487,9 @@ static int g_digest_a_alg[WD_DIGEST_TYPE_MAX] = { static int g_hmac_a_alg[WD_DIGEST_TYPE_MAX] = { 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 };
int hisi_sec_init(struct wd_ctx_config_internal *config, void *priv); @@ -554,6 +563,9 @@ static void update_iv(struct wd_cipher_msg *msg) { switch (msg->mode) { case WD_CIPHER_CBC: + case WD_CIPHER_CBC_CS1: + case WD_CIPHER_CBC_CS2: + case WD_CIPHER_CBC_CS3: if (msg->op_type == WD_CIPHER_ENCRYPTION && msg->out_bytes >= msg->iv_bytes) memcpy(msg->iv, msg->out + msg->out_bytes - @@ -765,8 +777,32 @@ static void parse_cipher_bd2(struct hisi_qp *qp, struct hisi_sec_sqe *sqe, dump_sec_msg(temp_msg, "cipher"); }
+static int aes_sm4_len_check(struct wd_cipher_msg *msg) +{ + if ((msg->mode == WD_CIPHER_CBC_CS1 || + msg->mode == WD_CIPHER_CBC_CS2 || + msg->mode == WD_CIPHER_CBC_CS3) && + msg->alg == WD_CIPHER_AES && + msg->in_bytes <= AES_BLOCK_SIZE) { + WD_ERR("failed to check input bytes of AES_CBC_CS_X, size = %u\n", + msg->in_bytes); + return -WD_EINVAL; + } + + if ((msg->mode == WD_CIPHER_CBC || msg->mode == WD_CIPHER_ECB) && + msg->in_bytes & (AES_BLOCK_SIZE - 1)) { + WD_ERR("failed to check input bytes of AES or SM4, size = %u\n", + msg->in_bytes); + return -WD_EINVAL; + } + + return 0; +} + static int cipher_len_check(struct wd_cipher_msg *msg) { + int ret; + if (msg->in_bytes > MAX_INPUT_DATA_LEN || !msg->in_bytes) { WD_ERR("input cipher length is error, size = %u\n", @@ -795,13 +831,12 @@ static int cipher_len_check(struct wd_cipher_msg *msg) return -WD_EINVAL; } return 0; - } else if (msg->alg == WD_CIPHER_AES || msg->alg == WD_CIPHER_SM4) { - if (msg->in_bytes & (AES_BLOCK_SIZE - 1)) { - WD_ERR("failed to check input bytes of AES or SM4, size = %u\n", - msg->in_bytes); - return -WD_EINVAL; - } - return 0; + } + + if (msg->alg == WD_CIPHER_AES || msg->alg == WD_CIPHER_SM4) { + ret = aes_sm4_len_check(msg); + if (ret) + return ret; }
return 0; @@ -1083,6 +1118,18 @@ static int fill_cipher_bd3_mode(struct wd_cipher_msg *msg, case WD_CIPHER_CFB: c_mode = C_MODE_CFB; break; + case WD_CIPHER_CBC_CS1: + c_mode = C_MODE_CBC_CS; + sqe->c_icv_key |= C_WIDTH_CS1 << SEC_CWIDTH_OFFSET_V3; + break; + case WD_CIPHER_CBC_CS2: + c_mode = C_MODE_CBC_CS; + sqe->c_icv_key |= C_WIDTH_CS2 << SEC_CWIDTH_OFFSET_V3; + break; + case WD_CIPHER_CBC_CS3: + c_mode = C_MODE_CBC_CS; + sqe->c_icv_key |= C_WIDTH_CS3 << SEC_CWIDTH_OFFSET_V3; + break; default: WD_ERR("failed to check cipher mode type, mode = %u\n", msg->mode); @@ -1285,28 +1332,41 @@ static int fill_digest_bd2_alg(struct wd_digest_msg *msg, return WD_SUCCESS; }
-static void qm_fill_digest_long_bd(struct wd_digest_msg *msg, +static int fill_digest_long_hash(struct wd_digest_msg *msg, struct hisi_sec_sqe *sqe) { __u64 total_bits;
+ if (msg->data_fmt == WD_SGL_BUF && msg->has_next) { + WD_ERR("invalid: sgl mode not supports long hash!\n"); + return -WD_EINVAL; + } + if (msg->has_next && !msg->iv_bytes) { - /* LONG BD FIRST */ + /* Long hash first */ sqe->ai_apd_cs = AI_GEN_INNER; sqe->ai_apd_cs |= AUTHPAD_NOPAD << AUTHPAD_OFFSET; - } else if (msg->has_next && (msg->iv_bytes != 0)) { - /* LONG BD MIDDLE */ + } + + if (msg->has_next && msg->iv_bytes) { + /* Long hash middle */ sqe->ai_apd_cs = AI_GEN_IVIN_ADDR; sqe->ai_apd_cs |= AUTHPAD_NOPAD << AUTHPAD_OFFSET; sqe->type2.a_ivin_addr = sqe->type2.mac_addr; - } else if (!msg->has_next && (msg->iv_bytes != 0)) { - /* LONG BD END */ + } + + if (!msg->has_next && msg->iv_bytes) { + /* Long hash end */ sqe->ai_apd_cs = AI_GEN_IVIN_ADDR; sqe->ai_apd_cs |= AUTHPAD_PAD << AUTHPAD_OFFSET; sqe->type2.a_ivin_addr = sqe->type2.mac_addr; + + /* The max total_bits length is LONG_MAX */ total_bits = msg->long_data_len * BYTE_BITS; sqe->type2.long_a_data_len = total_bits; } + + return 0; }
static void parse_digest_bd2(struct hisi_qp *qp, struct hisi_sec_sqe *sqe, @@ -1346,7 +1406,7 @@ static void parse_digest_bd2(struct hisi_qp *qp, struct hisi_sec_sqe *sqe, dump_sec_msg(temp_msg, "digest"); }
-static int digest_long_bd_check(struct wd_digest_msg *msg) +static int digest_long_bd_align_check(struct wd_digest_msg *msg) { __u32 alg_align_sz;
@@ -1359,6 +1419,18 @@ static int digest_long_bd_check(struct wd_digest_msg *msg) return 0; }
+static int aes_auth_len_check(struct wd_digest_msg *msg) +{ + if ((msg->alg == WD_DIGEST_AES_XCBC_MAC_96 || + msg->alg == WD_DIGEST_AES_XCBC_PRF_128 || + msg->alg == WD_DIGEST_AES_CMAC) && !msg->in_bytes) { + WD_ERR("digest mode: %u not supports 0 size!\n", msg->alg); + return -WD_EINVAL; + } + + return 0; +} + static int digest_len_check(struct wd_digest_msg *msg, enum sec_bd_type type) { int ret; @@ -1369,6 +1441,12 @@ static int digest_len_check(struct wd_digest_msg *msg, enum sec_bd_type type) return -WD_EINVAL; }
+ if (type == BD_TYPE3) { + ret = aes_auth_len_check(msg); + if (ret) + return ret; + } + if (unlikely(msg->in_bytes > MAX_INPUT_DATA_LEN)) { WD_ERR("digest input length is too long, size = %u\n", msg->in_bytes); @@ -1382,7 +1460,7 @@ static int digest_len_check(struct wd_digest_msg *msg, enum sec_bd_type type) }
if (msg->has_next) { - ret = digest_long_bd_check(msg); + ret = digest_long_bd_align_check(msg); if (ret) { WD_ERR("input data isn't aligned, size = %u\n", msg->in_bytes); @@ -1437,7 +1515,9 @@ int hisi_sec_digest_send(handle_t ctx, void *digest_msg) if (ret) goto put_sgl;
- qm_fill_digest_long_bd(msg, &sqe); + ret = fill_digest_long_hash(msg, &sqe); + if (ret) + goto put_sgl;
hisi_set_msg_id(h_qp, &msg->tag); sqe.type2.tag = (__u16)msg->tag; @@ -1493,9 +1573,35 @@ static struct wd_digest_driver hisi_digest_driver = {
WD_DIGEST_SET_DRIVER(hisi_digest_driver);
+static int hmac_key_len_check(struct wd_digest_msg *msg) +{ + switch (msg->alg) { + case WD_DIGEST_AES_XCBC_MAC_96: + case WD_DIGEST_AES_XCBC_PRF_128: + case WD_DIGEST_AES_CMAC: + if (msg->key_bytes != AES_KEYSIZE_128) { + WD_ERR("failed to check digest key bytes, size = %u\n", + msg->key_bytes); + return -WD_EINVAL; + } + break; + default: + if (msg->key_bytes & WORD_ALIGNMENT_MASK) { + WD_ERR("failed to check digest key bytes, size = %u\n", + msg->key_bytes); + return -WD_EINVAL; + } + break; + } + + return 0; +} + static int fill_digest_bd3_alg(struct wd_digest_msg *msg, struct hisi_sec_sqe3 *sqe) { + int ret; + if (msg->alg >= WD_DIGEST_TYPE_MAX) { WD_ERR("failed to check digest type, alg = %u\n", msg->alg); return -WD_EINVAL; @@ -1507,16 +1613,20 @@ static int fill_digest_bd3_alg(struct wd_digest_msg *msg, sqe->auth_mac_key |= (__u32)g_digest_a_alg[msg->alg] << SEC_AUTH_ALG_OFFSET_V3; } else if (msg->mode == WD_DIGEST_HMAC) { - if (msg->key_bytes & WORD_ALIGNMENT_MASK) { - WD_ERR("failed to check digest key bytes, size = %u\n", - msg->key_bytes); - return -WD_EINVAL; - } + ret = hmac_key_len_check(msg); + if (ret) + return ret; + sqe->auth_mac_key |= (__u32)(msg->key_bytes / WORD_BYTES) << SEC_AKEY_OFFSET_V3; sqe->a_key_addr = (__u64)(uintptr_t)msg->key; sqe->auth_mac_key |= (__u32)g_hmac_a_alg[msg->alg] << SEC_AUTH_ALG_OFFSET_V3; + + if (msg->alg == WD_DIGEST_AES_GMAC) { + sqe->auth_mac_key |= AI_GEN_IVIN_ADDR << SEC_AI_GEN_OFFSET_V3; + sqe->auth_ivin.a_ivin_addr = (__u64)(uintptr_t)msg->iv; + } } else { WD_ERR("failed to check digest mode, mode = %u\n", msg->mode); return -WD_EINVAL; @@ -1525,28 +1635,78 @@ static int fill_digest_bd3_alg(struct wd_digest_msg *msg, return WD_SUCCESS; }
-static void qm_fill_digest_long_bd3(struct wd_digest_msg *msg, +static int aes_auth_long_hash_check(struct wd_digest_msg *msg) +{ + if ((msg->alg == WD_DIGEST_AES_XCBC_MAC_96 || + msg->alg == WD_DIGEST_AES_XCBC_PRF_128 || + msg->alg == WD_DIGEST_AES_CMAC || + msg->alg == WD_DIGEST_AES_GMAC) && msg->has_next) { + WD_ERR("aes auth algs not supports long hash mode!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static int fill_digest_long_hash3(struct wd_digest_msg *msg, struct hisi_sec_sqe3 *sqe) { __u64 total_bits; + int ret; + + if (msg->data_fmt == WD_SGL_BUF && msg->has_next) { + WD_ERR("invalid: sgl mode not supports long hash!\n"); + return -WD_EINVAL; + } + + ret = aes_auth_long_hash_check(msg); + if (ret) + return ret;
if (msg->has_next && !msg->iv_bytes) { - /* LONG BD FIRST */ + /* Long hash first */ sqe->auth_mac_key |= AI_GEN_INNER << SEC_AI_GEN_OFFSET_V3; sqe->stream_scene.stream_auth_pad = AUTHPAD_NOPAD; - } else if (msg->has_next && (msg->iv_bytes != 0)) { - /* LONG BD MIDDLE */ + } + + if (msg->has_next && msg->iv_bytes) { + /* Long hash middle */ sqe->auth_mac_key |= AI_GEN_IVIN_ADDR << SEC_AI_GEN_OFFSET_V3; sqe->stream_scene.stream_auth_pad = AUTHPAD_NOPAD; sqe->auth_ivin.a_ivin_addr = sqe->mac_addr; - } else if (!msg->has_next && (msg->iv_bytes != 0)) { - /* LONG BD END */ + } + + if (!msg->has_next && msg->iv_bytes) { + /* Long hash end */ sqe->auth_mac_key |= AI_GEN_IVIN_ADDR << SEC_AI_GEN_OFFSET_V3; sqe->stream_scene.stream_auth_pad = AUTHPAD_PAD; sqe->auth_ivin.a_ivin_addr = sqe->mac_addr; + + /* The max total_bits length is LONG_MAX */ total_bits = msg->long_data_len * BYTE_BITS; sqe->stream_scene.long_a_data_len = total_bits; } + + return 0; +} + +static void fill_digest_v3_scene(struct hisi_sec_sqe3 *sqe, + struct wd_digest_msg *msg) +{ + __u16 scene, de; + + /* config BD type */ + sqe->bd_param = BD_TYPE3; + + /* config scene */ + if (msg->alg == WD_DIGEST_AES_GMAC) + scene = SEC_IPSEC_SCENE << SEC_SCENE_OFFSET_V3; + else + scene = SEC_STREAM_SCENE << SEC_SCENE_OFFSET_V3; + + de = DATA_DST_ADDR_DISABLE << SEC_DE_OFFSET_V3; + + sqe->bd_param |= (__u16)(de | scene); }
int hisi_sec_digest_send_v3(handle_t ctx, void *digest_msg) @@ -1555,8 +1715,6 @@ int hisi_sec_digest_send_v3(handle_t ctx, void *digest_msg) struct wd_digest_msg *msg = digest_msg; struct hisi_sec_sqe3 sqe; __u16 count = 0; - __u16 scene; - __u16 de; int ret;
if (!msg) { @@ -1569,13 +1727,9 @@ int hisi_sec_digest_send_v3(handle_t ctx, void *digest_msg) return ret;
memset(&sqe, 0, sizeof(struct hisi_sec_sqe3)); - /* config BD type */ - sqe.bd_param = BD_TYPE3; - sqe.auth_mac_key = AUTH_HMAC_CALCULATE; + fill_digest_v3_scene(&sqe, msg);
- /* config scene */ - scene = SEC_STREAM_SCENE << SEC_SCENE_OFFSET_V3; - de = DATA_DST_ADDR_DISABLE << SEC_DE_OFFSET_V3; + sqe.auth_mac_key = AUTH_HMAC_CALCULATE;
if (msg->data_fmt == WD_SGL_BUF) { ret = hisi_sec_fill_sgl_v3(h_qp, &msg->in, &msg->out, &sqe, @@ -1584,7 +1738,6 @@ int hisi_sec_digest_send_v3(handle_t ctx, void *digest_msg) return ret; }
- sqe.bd_param |= (__u16)(de | scene); sqe.a_len_key = (__u32)msg->in_bytes; sqe.data_src_addr = (__u64)(uintptr_t)msg->in; sqe.mac_addr = (__u64)(uintptr_t)msg->out; @@ -1593,7 +1746,9 @@ int hisi_sec_digest_send_v3(handle_t ctx, void *digest_msg) if (ret) goto put_sgl;
- qm_fill_digest_long_bd3(msg, &sqe); + ret = fill_digest_long_hash3(msg, &sqe); + if (ret) + goto put_sgl;
hisi_set_msg_id(h_qp, &msg->tag); sqe.tag = (__u64)(uintptr_t)msg->tag; @@ -1698,7 +1853,7 @@ static int aead_get_aes_key_len(struct wd_aead_msg *msg, __u8 *key_len) return 0; }
-static int aead_bd_msg_check(struct wd_aead_msg *msg) +static int aead_akey_len_check(struct wd_aead_msg *msg) { if (unlikely(msg->akey_bytes & WORD_ALIGNMENT_MASK)) { WD_ERR("failed to check aead auth key bytes, size = %u\n", @@ -1734,7 +1889,7 @@ static int fill_aead_bd2_alg(struct wd_aead_msg *msg,
sqe->type2.mac_key_alg = msg->auth_bytes / WORD_BYTES;
- ret = aead_bd_msg_check(msg); + ret = aead_akey_len_check(msg); if (ret) return ret;
@@ -2074,7 +2229,7 @@ static int fill_aead_bd3_alg(struct wd_aead_msg *msg, if (msg->cmode == WD_CIPHER_CCM || msg->cmode == WD_CIPHER_GCM) return ret;
- ret = aead_bd_msg_check(msg); + ret = aead_akey_len_check(msg); if (ret) return ret;
diff --git a/include/wd_cipher.h b/include/wd_cipher.h index 127cd45..dfd6e60 100644 --- a/include/wd_cipher.h +++ b/include/wd_cipher.h @@ -15,9 +15,6 @@ extern "C" { #endif
-#define AES_KEYSIZE_128 16 -#define AES_KEYSIZE_192 24 -#define AES_KEYSIZE_256 32 #define AES_BLOCK_SIZE 16 #define GCM_BLOCK_SIZE 12 #define DES3_BLOCK_SIZE 8 @@ -62,6 +59,9 @@ enum wd_cipher_mode { WD_CIPHER_XTS, WD_CIPHER_OFB, WD_CIPHER_CFB, + WD_CIPHER_CBC_CS1, + WD_CIPHER_CBC_CS2, + WD_CIPHER_CBC_CS3, WD_CIPHER_CCM, WD_CIPHER_GCM, WD_CIPHER_MODE_TYPE_MAX, diff --git a/include/wd_digest.h b/include/wd_digest.h index e1a33cd..bf085ea 100644 --- a/include/wd_digest.h +++ b/include/wd_digest.h @@ -31,6 +31,10 @@ enum wd_digest_type { WD_DIGEST_SHA512, WD_DIGEST_SHA512_224, WD_DIGEST_SHA512_256, + WD_DIGEST_AES_XCBC_MAC_96, + WD_DIGEST_AES_XCBC_PRF_128, + WD_DIGEST_AES_CMAC, + WD_DIGEST_AES_GMAC, WD_DIGEST_TYPE_MAX, };
@@ -43,7 +47,11 @@ enum wd_digest_mac_len { WD_DIGEST_SHA384_LEN = 48, WD_DIGEST_SHA512_LEN = 64, WD_DIGEST_SHA512_224_LEN = 28, - WD_DIGEST_SHA512_256_LEN = 32 + WD_DIGEST_SHA512_256_LEN = 32, + WD_DIGEST_AES_XCBC_MAC_96_LEN = 12, + WD_DIGEST_AES_XCBC_PRF_128_LEN = 16, + WD_DIGEST_AES_CMAC_LEN = 16, + WD_DIGEST_AES_GMAC_LEN = 16, };
/** @@ -78,6 +86,8 @@ typedef void *wd_digest_cb_t(void *cb_param); * @in_bytes: input data size * @out_bytes: output data size * @out_buf_bytes: actual output buffer size + * @iv: input iv data addrss for AES_GMAC + * @iv_bytes: input iv data size * @has_next: is there next data block * @cb: callback function for async mode * @cb_param: pointer of callback parameter @@ -96,9 +106,11 @@ struct wd_digest_req { __u32 in_bytes; __u32 out_bytes; __u32 out_buf_bytes; + __u8 *iv; + __u32 iv_bytes; __u16 state; __u16 has_next; - __u8 data_fmt; + __u8 data_fmt; wd_digest_cb_t *cb; void *cb_param; }; diff --git a/test/hisi_sec_test/test_hisi_sec.c b/test/hisi_sec_test/test_hisi_sec.c index 9aa4e56..be30d35 100755 --- a/test/hisi_sec_test/test_hisi_sec.c +++ b/test/hisi_sec_test/test_hisi_sec.c @@ -32,6 +32,9 @@ #define TEST_WORD_LEN 4096 #define MAX_ALGO_PER_TYPE 16 #define MIN_SVA_BD_NUM 1 +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32
#define SGL_ALIGNED_BYTES 64
diff --git a/wd_aead.c b/wd_aead.c index a1bdb12..d6c2380 100644 --- a/wd_aead.c +++ b/wd_aead.c @@ -15,6 +15,9 @@ #define DES_KEY_SIZE 8 #define DES3_2KEY_SIZE (2 * DES_KEY_SIZE) #define DES3_3KEY_SIZE (3 * DES_KEY_SIZE) +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32
#define WD_AEAD_CCM_GCM_MIN 4U #define WD_AEAD_CCM_GCM_MAX 16 @@ -81,7 +84,7 @@ void wd_aead_set_driver(struct wd_aead_driver *drv) wd_aead_setting.driver = drv; }
-static int aes_key_len_check(__u16 length) +static int aes_key_len_check(__u32 length) { switch (length) { case AES_KEYSIZE_128: @@ -333,7 +336,7 @@ static int aead_mac_param_check(struct wd_aead_sess *sess, return ret; }
-static int aead_param_check(struct wd_aead_sess *sess, +static int wd_aead_param_check(struct wd_aead_sess *sess, struct wd_aead_req *req) { __u32 len; @@ -516,7 +519,7 @@ int wd_do_aead_sync(handle_t h_sess, struct wd_aead_req *req) __u32 idx; int ret;
- ret = aead_param_check(sess, req); + ret = wd_aead_param_check(sess, req); if (unlikely(ret)) return -WD_EINVAL;
@@ -548,7 +551,7 @@ int wd_do_aead_async(handle_t h_sess, struct wd_aead_req *req) int msg_id, ret; __u32 idx;
- ret = aead_param_check(sess, req); + ret = wd_aead_param_check(sess, req); if (unlikely(ret)) return -WD_EINVAL;
diff --git a/wd_cipher.c b/wd_cipher.c index 884c933..8ce975a 100644 --- a/wd_cipher.c +++ b/wd_cipher.c @@ -16,6 +16,9 @@ #define DES_KEY_SIZE 8 #define DES3_2KEY_SIZE (2 * DES_KEY_SIZE) #define DES3_3KEY_SIZE (3 * DES_KEY_SIZE) +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32
#define WD_POOL_MAX_ENTRIES 1024 #define DES_WEAK_KEY_NUM 16 diff --git a/wd_digest.c b/wd_digest.c index 3e64168..a55b1ed 100644 --- a/wd_digest.c +++ b/wd_digest.c @@ -14,6 +14,10 @@ #define SM4_KEY_SIZE 16 #define DES_KEY_SIZE 8 #define DES3_3KEY_SIZE (3 * DES_KEY_SIZE) +#define GMAC_IV_LEN 16 +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32
#define WD_POOL_MAX_ENTRIES 1024 #define DES_WEAK_KEY_NUM 4 @@ -22,7 +26,9 @@ static int g_digest_mac_len[WD_DIGEST_TYPE_MAX] = { WD_DIGEST_SM3_LEN, WD_DIGEST_MD5_LEN, WD_DIGEST_SHA1_LEN, WD_DIGEST_SHA256_LEN, WD_DIGEST_SHA224_LEN, WD_DIGEST_SHA384_LEN, WD_DIGEST_SHA512_LEN, - WD_DIGEST_SHA512_224_LEN, WD_DIGEST_SHA512_256_LEN + WD_DIGEST_SHA512_224_LEN, WD_DIGEST_SHA512_256_LEN, + WD_DIGEST_AES_XCBC_MAC_96_LEN, WD_DIGEST_AES_XCBC_PRF_128_LEN, + WD_DIGEST_AES_CMAC_LEN, WD_DIGEST_AES_GMAC_LEN };
struct wd_digest_setting { @@ -82,9 +88,22 @@ void wd_digest_set_driver(struct wd_digest_driver *drv) wd_digest_setting.driver = drv; }
+static int aes_key_len_check(__u32 length) +{ + switch (length) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_192: + case AES_KEYSIZE_256: + return 0; + default: + return -WD_EINVAL; + } +} + int wd_digest_set_key(handle_t h_sess, const __u8 *key, __u32 key_len) { struct wd_digest_sess *sess = (struct wd_digest_sess *)h_sess; + int ret;
if (!key || !sess) { WD_ERR("failed to check key param!\n"); @@ -99,6 +118,15 @@ int wd_digest_set_key(handle_t h_sess, const __u8 *key, __u32 key_len) return -WD_EINVAL; }
+ if (sess->alg == WD_DIGEST_AES_GMAC) { + ret = aes_key_len_check(key_len); + if (ret) { + WD_ERR("failed to check aes-gmac key length, size = %u\n", + key_len); + return ret; + } + } + sess->key_bytes = key_len; memcpy(sess->key, key, key_len);
@@ -227,7 +255,27 @@ void wd_digest_uninit(void) wd_clear_ctx_config(&wd_digest_setting.config); }
-static int digest_param_check(struct wd_digest_sess *sess, +static int wd_hmac_length_check(struct wd_digest_sess *sess, + struct wd_digest_req *req) +{ + switch (sess->alg) { + case WD_DIGEST_AES_XCBC_MAC_96: + case WD_DIGEST_AES_XCBC_PRF_128: + case WD_DIGEST_AES_CMAC: + if (!req->in_bytes) { + WD_ERR("failed to check 0 packet length, alg = %d\n", + sess->alg); + return -WD_EINVAL; + } + break; + default: + break; + } + + return 0; +} + +static int wd_digest_param_check(struct wd_digest_sess *sess, struct wd_digest_req *req) { int ret; @@ -250,6 +298,13 @@ static int digest_param_check(struct wd_digest_sess *sess, return -WD_EINVAL; }
+ if (unlikely(sess->alg == WD_DIGEST_AES_GMAC && + req->iv_bytes != GMAC_IV_LEN)) { + WD_ERR("failed to check digest aes_gmac iv length, iv_bytes = %u\n", + req->iv_bytes); + return -WD_EINVAL; + } + if (req->data_fmt == WD_SGL_BUF) { ret = wd_check_datalist(req->list_in, req->in_bytes); if (unlikely(ret)) { @@ -259,7 +314,7 @@ static int digest_param_check(struct wd_digest_sess *sess, } }
- return 0; + return wd_hmac_length_check(sess, req); }
static void fill_request_msg(struct wd_digest_msg *msg, @@ -273,6 +328,7 @@ static void fill_request_msg(struct wd_digest_msg *msg, msg->mode = sess->mode; msg->key = sess->key; msg->key_bytes = sess->key_bytes; + msg->iv = req->iv; msg->in = req->in; msg->in_bytes = req->in_bytes; msg->out = req->out; @@ -281,6 +337,7 @@ static void fill_request_msg(struct wd_digest_msg *msg, msg->has_next = req->has_next; sess->long_data_len += req->in_bytes; msg->long_data_len = sess->long_data_len; + /* To store the stream BD state, iv_bytes also means BD state */ msg->iv_bytes = sess->bd_state; if (req->has_next == 0) { @@ -305,11 +362,9 @@ static int send_recv_sync(struct wd_ctx_internal *ctx, struct wd_digest_sess *ds goto out;
/* - * 'out_bytes' can be expressed BD state, non-zero is final BD or - * middle BD as stream mode. + * non-zero is final BD or middle BD as stream mode. */ - if (msg->has_next) - dsess->bd_state = msg->out_bytes; + dsess->bd_state = msg->has_next;
out: pthread_spin_unlock(&ctx->lock); @@ -325,7 +380,7 @@ int wd_do_digest_sync(handle_t h_sess, struct wd_digest_req *req) __u32 idx; int ret;
- ret = digest_param_check(dsess, req); + ret = wd_digest_param_check(dsess, req); if (unlikely(ret)) return -WD_EINVAL;
@@ -357,7 +412,7 @@ int wd_do_digest_async(handle_t h_sess, struct wd_digest_req *req) int msg_id, ret; __u32 idx;
- ret = digest_param_check(dsess, req); + ret = wd_digest_param_check(dsess, req); if (unlikely(ret)) return -WD_EINVAL;
Due to async mode and sgl buffer not supports long hash currently. So add format checking for digest.
Signed-off-by: Kai Ye yekai13@huawei.com --- drv/hisi_sec.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index eaffbea..1728529 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -1332,16 +1332,33 @@ static int fill_digest_bd2_alg(struct wd_digest_msg *msg, return WD_SUCCESS; }
-static int fill_digest_long_hash(struct wd_digest_msg *msg, - struct hisi_sec_sqe *sqe) +static int long_hash_param_check(handle_t h_qp, struct wd_digest_msg *msg) { - __u64 total_bits; + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + + if (qp->q_info.qp_mode == CTX_MODE_ASYNC && msg->has_next) { + WD_ERR("invalid: async mode not supports long hash!\n"); + return -WD_EINVAL; + }
if (msg->data_fmt == WD_SGL_BUF && msg->has_next) { WD_ERR("invalid: sgl mode not supports long hash!\n"); return -WD_EINVAL; }
+ return 0; +} + +static int fill_digest_long_hash(handle_t h_qp, struct wd_digest_msg *msg, + struct hisi_sec_sqe *sqe) +{ + __u64 total_bits; + int ret; + + ret = long_hash_param_check(h_qp, msg); + if (ret) + return ret; + if (msg->has_next && !msg->iv_bytes) { /* Long hash first */ sqe->ai_apd_cs = AI_GEN_INNER; @@ -1515,7 +1532,7 @@ int hisi_sec_digest_send(handle_t ctx, void *digest_msg) if (ret) goto put_sgl;
- ret = fill_digest_long_hash(msg, &sqe); + ret = fill_digest_long_hash(h_qp, msg, &sqe); if (ret) goto put_sgl;
@@ -1648,16 +1665,15 @@ static int aes_auth_long_hash_check(struct wd_digest_msg *msg) return 0; }
-static int fill_digest_long_hash3(struct wd_digest_msg *msg, +static int fill_digest_long_hash3(handle_t h_qp, struct wd_digest_msg *msg, struct hisi_sec_sqe3 *sqe) { __u64 total_bits; int ret;
- if (msg->data_fmt == WD_SGL_BUF && msg->has_next) { - WD_ERR("invalid: sgl mode not supports long hash!\n"); - return -WD_EINVAL; - } + ret = long_hash_param_check(h_qp, msg); + if (ret) + return ret;
ret = aes_auth_long_hash_check(msg); if (ret) @@ -1746,7 +1762,7 @@ int hisi_sec_digest_send_v3(handle_t ctx, void *digest_msg) if (ret) goto put_sgl;
- ret = fill_digest_long_hash3(msg, &sqe); + ret = fill_digest_long_hash3(h_qp, msg, &sqe); if (ret) goto put_sgl;
Updata the stream mode for digest test.
Signed-off-by: Kai Ye yekai13@huawei.com --- test/hisi_sec_test/test_hisi_sec.c | 41 +++++++++++++++++------------- 1 file changed, 24 insertions(+), 17 deletions(-)
diff --git a/test/hisi_sec_test/test_hisi_sec.c b/test/hisi_sec_test/test_hisi_sec.c index be30d35..0a49597 100755 --- a/test/hisi_sec_test/test_hisi_sec.c +++ b/test/hisi_sec_test/test_hisi_sec.c @@ -49,6 +49,7 @@ static unsigned int g_pktlen; static unsigned int g_block; static unsigned int g_blknum; static unsigned int g_direction; +static unsigned int g_stream; static unsigned int g_alg_op_type; static unsigned int g_ivlen; static unsigned int g_syncmode; @@ -132,6 +133,7 @@ struct test_sec_option { __u32 ctxnum; __u32 block; __u32 blknum; + __u32 stream_mode; __u32 sgl_num; __u32 use_env; }; @@ -158,7 +160,7 @@ static void *create_buf(int sgl, size_t sz, size_t unit_sz) int i, tail_sz, sgl_num; void *buf;
- buf = calloc(1, sz); + buf = calloc(sz, sizeof(char)); if (!buf) { SEC_TST_PRT("Fail to allocate buffer %ld size!\n", sz); return NULL; @@ -169,7 +171,7 @@ static void *create_buf(int sgl, size_t sz, size_t unit_sz) sgl_num = sz / unit_sz; /* the number with unit_sz bytes */
/* the additional slot is for tail_sz */ - head = calloc(1, sizeof(struct wd_datalist) * (sgl_num + 1)); + head = calloc(sgl_num + 1, sizeof(struct wd_datalist)); if (!head) { SEC_TST_PRT("Fail to allocate memory for SGL head!\n"); goto out; @@ -672,12 +674,11 @@ static int test_sec_cipher_sync_once(void) float speed, time_used; int pid = getpid(); int cnt = g_times; + size_t unit_sz, len; int ret; - size_t unit_sz;
/* config setup */ ret = init_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); - if (ret) { SEC_TST_PRT("Fail to init sigle ctx config!\n"); return ret; @@ -1932,7 +1933,6 @@ static int sec_digest_sync_stream_mode(void) goto out; }
- while (cnt) { do { if (data_len > 256) { // soft block size @@ -4058,15 +4058,19 @@ static void print_help(void) SEC_TST_PRT(" the number of memory blocks in the pre-allocated BD message memory pool\n"); SEC_TST_PRT(" [--ctxnum]:\n"); SEC_TST_PRT(" the number of QP queues used by the entire test task\n"); + SEC_TST_PRT(" [--stream]:\n"); + SEC_TST_PRT(" set the steam mode for digest\n"); SEC_TST_PRT(" [--help] = usage\n"); SEC_TST_PRT("Example\n"); SEC_TST_PRT(" ./test_hisi_sec --cipher 0 --sync --optype 0\n"); SEC_TST_PRT("--pktlen 16 --keylen 16 --times 1 --multi 1\n"); - SEC_TST_PRT(" ./test_hisi_sec --digest 0 --sync --optype 3\n"); - SEC_TST_PRT("--pktlen 16 --keylen 16 --times 1 --multi 2\n"); + SEC_TST_PRT(" ./test_hisi_sec --digest 0 --sync --optype 0\n"); + SEC_TST_PRT("--pktlen 16 --keylen 16 --times 1 --multi 2 --stream\n"); + SEC_TST_PRT(" ./test_hisi_sec --digest 1 --sync --optype 0\n"); + SEC_TST_PRT("--pktlen 16 --keylen 16 --times 1 --multi 2 --stream\n"); SEC_TST_PRT(" ./test_hisi_sec --perf --sync --pktlen 1024 --block 1024\n"); SEC_TST_PRT("--blknum 100000 --times 10000 --multi 1 --ctxnum 1\n"); - SEC_TST_PRT("UPDATE:2020-11-06\n"); + SEC_TST_PRT("UPDATE:2022-06-29\n"); }
static void test_sec_cmd_parse(int argc, char *argv[], struct test_sec_option *option) @@ -4089,9 +4093,10 @@ static void test_sec_cmd_parse(int argc, char *argv[], struct test_sec_option *o {"ctxnum", required_argument, 0, 12}, {"block", required_argument, 0, 13}, {"blknum", required_argument, 0, 14}, - {"help", no_argument, 0, 15}, + {"stream", no_argument, 0, 15}, {"sglnum", required_argument, 0, 16}, {"use_env", no_argument, 0, 17}, + {"help", no_argument, 0, 18}, {0, 0, 0, 0} };
@@ -4147,14 +4152,17 @@ static void test_sec_cmd_parse(int argc, char *argv[], struct test_sec_option *o option->blknum = strtol(optarg, NULL, 0); break; case 15: - print_help(); - exit(-1); + option->stream_mode = 1; + break; case 16: option->sgl_num = strtol(optarg, NULL, 0); break; case 17: option->use_env = 1; break; + case 18: + print_help(); + exit(-1); default: SEC_TST_PRT("bad input parameter, exit\n"); print_help(); @@ -4203,18 +4211,17 @@ static int test_sec_option_convert(struct test_sec_option *option) g_ctxnum = option->ctxnum ? option->ctxnum : 1; g_data_fmt = option->sgl_num ? WD_SGL_BUF : WD_FLAT_BUF; g_sgl_num = option->sgl_num; + g_stream = option->stream_mode;
SEC_TST_PRT("set global times is %lld\n", g_times);
g_thread_num = option->xmulti ? option->xmulti : 1; g_direction = option->optype; if (option->algclass == DIGEST_CLASS) { - //0 is normal mode, 1 is HMAC mode, 3 is long hash mode. + //0 is normal mode, 1 is HMAC mode g_alg_op_type = g_direction; - if (g_direction == 3) { - g_alg_op_type = 0; + if (g_stream) g_ivlen = 1; - } }
return 0; @@ -4273,11 +4280,11 @@ static int test_sec_run(__u32 sync_mode, __u32 alg_class) if (g_thread_num > 1 && g_direction != 3) { SEC_TST_PRT("currently digest test is synchronize psize:%u, multi -%d threads!\n", g_pktlen, g_thread_num); ret = sec_digest_sync_multi(); - } else if (g_thread_num > 1 && g_direction == 3) { + } else if (g_thread_num > 1 && g_stream) { ret = sec_digest_sync_stream_mode_multi(); (void)sec_digest_sync_stream_cmp(); SEC_TST_PRT("currently digest long hash mode, psize:%u, multi thread!\n", g_pktlen); - } else if (g_thread_num == 1 && g_direction == 3) { + } else if (g_thread_num == 1 && g_stream) { if (g_ivlen == 1) { ret = sec_digest_sync_stream_mode(); (void)sec_digest_sync_stream_cmp();
1. User need to input full mac buffer in first and middile hash. 2. sha384 alignment mask is 128Byte, here is fix it.
Signed-off-by: Kai Ye yekai13@huawei.com --- drv/hisi_sec.c | 56 ++++++++++++++++++++++++++++++++++++++++++--- include/wd_digest.h | 13 +++++++++++ wd_digest.c | 47 ++++++++++++++++++++++++++++++++----- 3 files changed, 107 insertions(+), 9 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index 1728529..5b676e9 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -116,6 +116,19 @@ enum A_ALG { A_ALG_HMAC_SM3 = 0x26 };
+/* The long hash mode requires full-length mac output */ +enum SEC_MAX_MAC_LEN { + SEC_HMAC_SM3_MAC_LEN = 0x8, + SEC_HMAC_MD5_MAC_LEN = 0x4, + SEC_HMAC_SHA1_MAC_LEN = 0x5, + SEC_HMAC_SHA256_MAC_LEN = 0x8, + SEC_HMAC_SHA224_MAC_LEN = 0x7, + SEC_HMAC_SHA384_MAC_LEN = 0xc, + SEC_HMAC_SHA512_MAC_LEN = 0x10, + SEC_HMAC_SHA512_224_MAC_LEN = 0x7, + SEC_HMAC_SHA512_256_MAC_LEN = 0x8 +}; + enum C_MODE { C_MODE_ECB = 0x0, C_MODE_CBC = 0x1, @@ -484,6 +497,7 @@ static int g_digest_a_alg[WD_DIGEST_TYPE_MAX] = { A_ALG_SM3, A_ALG_MD5, A_ALG_SHA1, A_ALG_SHA256, A_ALG_SHA224, A_ALG_SHA384, A_ALG_SHA512, A_ALG_SHA512_224, A_ALG_SHA512_256 }; + static int g_hmac_a_alg[WD_DIGEST_TYPE_MAX] = { A_ALG_HMAC_SM3, A_ALG_HMAC_MD5, A_ALG_HMAC_SHA1, A_ALG_HMAC_SHA256, A_ALG_HMAC_SHA224, A_ALG_HMAC_SHA384, @@ -492,6 +506,12 @@ static int g_hmac_a_alg[WD_DIGEST_TYPE_MAX] = { A_ALG_AES_GMAC };
+static __u32 g_sec_hmac_full_len[WD_DIGEST_TYPE_MAX] = { + SEC_HMAC_SM3_MAC_LEN, SEC_HMAC_MD5_MAC_LEN, SEC_HMAC_SHA1_MAC_LEN, + SEC_HMAC_SHA256_MAC_LEN, SEC_HMAC_SHA224_MAC_LEN, SEC_HMAC_SHA384_MAC_LEN, + SEC_HMAC_SHA512_MAC_LEN, SEC_HMAC_SHA512_224_MAC_LEN, SEC_HMAC_SHA512_256_MAC_LEN +}; + int hisi_sec_init(struct wd_ctx_config_internal *config, void *priv); void hisi_sec_exit(void *priv);
@@ -1308,7 +1328,21 @@ static int fill_digest_bd2_alg(struct wd_digest_msg *msg, return -WD_EINVAL; }
- sqe->type2.mac_key_alg = msg->out_bytes / WORD_BYTES; + /* + * Long hash mode must config full output length, 0 mac len indicates + * the output full length. + */ + if (!msg->has_next) + sqe->type2.mac_key_alg = msg->out_bytes / WORD_BYTES; + + /* SM3 can't config 0 in normal mode */ + if (msg->has_next && msg->mode == WD_DIGEST_NORMAL && + msg->alg == WD_DIGEST_SM3) + sqe->type2.mac_key_alg = g_sec_hmac_full_len[msg->alg]; + + if (msg->has_next && msg->mode == WD_DIGEST_HMAC) + sqe->type2.mac_key_alg = g_sec_hmac_full_len[msg->alg]; + if (msg->mode == WD_DIGEST_NORMAL) sqe->type2.mac_key_alg |= (__u32)g_digest_a_alg[msg->alg] << AUTH_ALG_OFFSET; @@ -1427,7 +1461,7 @@ static int digest_long_bd_align_check(struct wd_digest_msg *msg) { __u32 alg_align_sz;
- alg_align_sz = msg->alg >= WD_DIGEST_SHA512 ? + alg_align_sz = msg->alg >= WD_DIGEST_SHA384 ? SHA512_ALIGN_SZ - 1 : SHA1_ALIGN_SZ - 1;
if (msg->in_bytes & alg_align_sz) @@ -1624,8 +1658,24 @@ static int fill_digest_bd3_alg(struct wd_digest_msg *msg, return -WD_EINVAL; }
- sqe->auth_mac_key |= (msg->out_bytes / WORD_BYTES) << + /* + * Long hash mode must config full output length, 0 mac len indicates + * the output full length. + */ + if (!msg->has_next) + sqe->auth_mac_key |= (msg->out_bytes / WORD_BYTES) << + SEC_MAC_OFFSET_V3; + + /* SM3 can't config 0 in normal mode */ + if (msg->has_next && msg->mode == WD_DIGEST_NORMAL && + msg->alg == WD_DIGEST_SM3) + sqe->auth_mac_key |= g_sec_hmac_full_len[msg->alg] << + SEC_MAC_OFFSET_V3; + + if (msg->has_next && msg->mode == WD_DIGEST_HMAC) + sqe->auth_mac_key |= g_sec_hmac_full_len[msg->alg] << SEC_MAC_OFFSET_V3; + if (msg->mode == WD_DIGEST_NORMAL) { sqe->auth_mac_key |= (__u32)g_digest_a_alg[msg->alg] << SEC_AUTH_ALG_OFFSET_V3; diff --git a/include/wd_digest.h b/include/wd_digest.h index bf085ea..6a7a913 100644 --- a/include/wd_digest.h +++ b/include/wd_digest.h @@ -54,6 +54,19 @@ enum wd_digest_mac_len { WD_DIGEST_AES_GMAC_LEN = 16, };
+/* User need to input full mac len in first and middle hash */ +enum wd_digest_mac_full_len { + WD_DIGEST_SM3_FULL_LEN = 32, + WD_DIGEST_MD5_FULL_LEN = 16, + WD_DIGEST_SHA1_FULL_LEN = 20, + WD_DIGEST_SHA256_FULL_LEN = 32, + WD_DIGEST_SHA224_FULL_LEN = 32, + WD_DIGEST_SHA384_FULL_LEN = 64, + WD_DIGEST_SHA512_FULL_LEN = 64, + WD_DIGEST_SHA512_224_FULL_LEN = 64, + WD_DIGEST_SHA512_256_FULL_LEN = 64, +}; + /** * wd_digest_mode - Mode of digest * Mode should be offered by struct wd_digest_arg diff --git a/wd_digest.c b/wd_digest.c index a55b1ed..f56be0c 100644 --- a/wd_digest.c +++ b/wd_digest.c @@ -31,6 +31,13 @@ static int g_digest_mac_len[WD_DIGEST_TYPE_MAX] = { WD_DIGEST_AES_CMAC_LEN, WD_DIGEST_AES_GMAC_LEN };
+static int g_digest_mac_full_len[WD_DIGEST_TYPE_MAX] = { + WD_DIGEST_SM3_FULL_LEN, WD_DIGEST_MD5_LEN, WD_DIGEST_SHA1_FULL_LEN, + WD_DIGEST_SHA256_FULL_LEN, WD_DIGEST_SHA224_FULL_LEN, + WD_DIGEST_SHA384_FULL_LEN, WD_DIGEST_SHA512_FULL_LEN, + WD_DIGEST_SHA512_224_FULL_LEN, WD_DIGEST_SHA512_256_FULL_LEN +}; + struct wd_digest_setting { struct wd_ctx_config_internal config; struct wd_sched sched; @@ -255,7 +262,7 @@ void wd_digest_uninit(void) wd_clear_ctx_config(&wd_digest_setting.config); }
-static int wd_hmac_length_check(struct wd_digest_sess *sess, +static int wd_aes_hmac_length_check(struct wd_digest_sess *sess, struct wd_digest_req *req) { switch (sess->alg) { @@ -275,6 +282,32 @@ static int wd_hmac_length_check(struct wd_digest_sess *sess, return 0; }
+static int wd_mac_length_check(struct wd_digest_sess *sess, + struct wd_digest_req *req) +{ + if (unlikely(req->out_bytes == 0)) { + WD_ERR("invalid: digest alg:%d mac length is 0.\n", sess->alg); + return -WD_EINVAL; + } + + if (unlikely(!req->has_next && + req->out_bytes > g_digest_mac_len[sess->alg])) { + WD_ERR("invalid: digest mac length, alg = %d, out_bytes = %u\n", + sess->alg, req->out_bytes); + return -WD_EINVAL; + } + + /* User need to input full mac buffer in first and middle hash */ + if (unlikely(req->has_next && + req->out_bytes != g_digest_mac_full_len[sess->alg])) { + WD_ERR("invalid: digest mac full length is error, alg = %d, out_bytes = %u\n", + sess->alg, req->out_bytes); + return -WD_EINVAL; + } + + return 0; +} + static int wd_digest_param_check(struct wd_digest_sess *sess, struct wd_digest_req *req) { @@ -291,13 +324,15 @@ static int wd_digest_param_check(struct wd_digest_sess *sess, return -WD_EINVAL; }
- if (unlikely(sess->alg >= WD_DIGEST_TYPE_MAX || req->out_bytes == 0 || - req->out_bytes > g_digest_mac_len[sess->alg])) { - WD_ERR("failed to check digest type or mac length, alg = %d, out_bytes = %u\n", - sess->alg, req->out_bytes); + if (unlikely(sess->alg >= WD_DIGEST_TYPE_MAX)) { + WD_ERR("invalid: check digest type, alg = %d\n", sess->alg); return -WD_EINVAL; }
+ ret = wd_mac_length_check(sess, req); + if (ret) + return ret; + if (unlikely(sess->alg == WD_DIGEST_AES_GMAC && req->iv_bytes != GMAC_IV_LEN)) { WD_ERR("failed to check digest aes_gmac iv length, iv_bytes = %u\n", @@ -314,7 +349,7 @@ static int wd_digest_param_check(struct wd_digest_sess *sess, } }
- return wd_hmac_length_check(sess, req); + return wd_aes_hmac_length_check(sess, req); }
static void fill_request_msg(struct wd_digest_msg *msg,
Hardware v2 digest needs to check the zero byte packet in the frist and middle bd.
Signed-off-by: Kai Ye yekai13@huawei.com --- drv/hisi_sec.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index 5b676e9..9ceb9b4 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -1482,14 +1482,36 @@ static int aes_auth_len_check(struct wd_digest_msg *msg) return 0; }
+static int digest_bd2_zero_packet_check(struct wd_digest_msg *msg) +{ + /* Long hash first and middle bd */ + if (msg->has_next && !msg->in_bytes) { + WD_ERR("hardware v2 not supports 0 size in long hash!\n"); + return -WD_EINVAL; + } + + /* Block mode hash bd */ + if (!msg->has_next && !msg->iv_bytes && !msg->in_bytes) { + WD_ERR("hardware v2 not supports 0 size in block hash!\n"); + return -WD_EINVAL; + } + + return 0; +} + static int digest_len_check(struct wd_digest_msg *msg, enum sec_bd_type type) { int ret;
- /* End BD not need to check the input zero bytes */ - if (unlikely(type == BD_TYPE2 && !msg->has_next && !msg->in_bytes)) { - WD_ERR("kunpeng 920, digest mode not support 0 size!\n"); - return -WD_EINVAL; + /* + * Hardware v2 needs to check the zero byte packet in the block + * and long hash mode. Frist and Middle bd not supports 0 size, + * final bd not need to check it. Hardware v3 has fixed it. + */ + if (type == BD_TYPE2) { + ret = digest_bd2_zero_packet_check(msg); + if (ret) + return ret; }
if (type == BD_TYPE3) { @@ -1566,6 +1588,13 @@ int hisi_sec_digest_send(handle_t ctx, void *digest_msg) if (ret) goto put_sgl;
+ /* + * [has_next , iv_bytes] + * [ 1 , 0 ] = long hash(frist bd) + * [ 1 , 1 ] = long hash(middle bd) + * [ 0 , 1 ] = long hash(end bd) + * [ 0 , 0 ] = block hash(single bd) + */ ret = fill_digest_long_hash(h_qp, msg, &sqe); if (ret) goto put_sgl; @@ -1812,6 +1841,13 @@ int hisi_sec_digest_send_v3(handle_t ctx, void *digest_msg) if (ret) goto put_sgl;
+ /* + * [has_next , iv_bytes] + * [ 1 , 0 ] = long hash(frist bd) + * [ 1 , 1 ] = long hash(middle bd) + * [ 0 , 1 ] = long hash(end bd) + * [ 0 , 0 ] = block hash(single bd) + */ ret = fill_digest_long_hash3(h_qp, msg, &sqe); if (ret) goto put_sgl;