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;