libwd/0041-uadk-v1-digest-support-new-AES-mode-algs.patch
2023-10-31 16:59:15 +08:00

459 lines
14 KiB
Diff

From d0499781ec60e553adef8a3275bcf321abd25d77 Mon Sep 17 00:00:00 2001
From: Weili Qian <qianweili@huawei.com>
Date: Thu, 26 Oct 2023 16:17:53 +0800
Subject: [PATCH 41/42] uadk/v1/digest: support new AES mode algs
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 */
--
2.25.1