crypto: hisilicon/sec2 - fix for aead icv error

[ Upstream commit fd337f852b2677b53d0859a47b58e6e6bd189f30 ]

When the AEAD algorithm is used for encryption or decryption,
the input authentication length varies, the hardware needs to
obtain the input length to pass the integrity check verification.
Currently, the driver uses a fixed authentication length,which
causes decryption failure, so the length configuration is modified.
In addition, the step of setting the auth length is unnecessary,
so it was deleted from the setkey function.

Fixes: 2f072d75d1 ("crypto: hisilicon - Add aead support on SEC2")
Signed-off-by: Wenkai Lin <linwenkai6@hisilicon.com>
Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Wenkai Lin
2024-12-13 17:13:34 +08:00
committed by Greg Kroah-Hartman
parent fdc596efd7
commit ff1de68f69
3 changed files with 42 additions and 67 deletions

View File

@@ -90,7 +90,6 @@ struct sec_auth_ctx {
dma_addr_t a_key_dma; dma_addr_t a_key_dma;
u8 *a_key; u8 *a_key;
u8 a_key_len; u8 a_key_len;
u8 mac_len;
u8 a_alg; u8 a_alg;
bool fallback; bool fallback;
struct crypto_shash *hash_tfm; struct crypto_shash *hash_tfm;

View File

@@ -954,15 +954,14 @@ static int sec_aead_mac_init(struct sec_aead_req *req)
struct aead_request *aead_req = req->aead_req; struct aead_request *aead_req = req->aead_req;
struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req); struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
size_t authsize = crypto_aead_authsize(tfm); size_t authsize = crypto_aead_authsize(tfm);
u8 *mac_out = req->out_mac;
struct scatterlist *sgl = aead_req->src; struct scatterlist *sgl = aead_req->src;
u8 *mac_out = req->out_mac;
size_t copy_size; size_t copy_size;
off_t skip_size; off_t skip_size;
/* Copy input mac */ /* Copy input mac */
skip_size = aead_req->assoclen + aead_req->cryptlen - authsize; skip_size = aead_req->assoclen + aead_req->cryptlen - authsize;
copy_size = sg_pcopy_to_buffer(sgl, sg_nents(sgl), mac_out, copy_size = sg_pcopy_to_buffer(sgl, sg_nents(sgl), mac_out, authsize, skip_size);
authsize, skip_size);
if (unlikely(copy_size != authsize)) if (unlikely(copy_size != authsize))
return -EINVAL; return -EINVAL;
@@ -1144,7 +1143,6 @@ static int sec_aead_fallback_setkey(struct sec_auth_ctx *a_ctx,
static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key, static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
const u32 keylen, const enum sec_hash_alg a_alg, const u32 keylen, const enum sec_hash_alg a_alg,
const enum sec_calg c_alg, const enum sec_calg c_alg,
const enum sec_mac_len mac_len,
const enum sec_cmode c_mode) const enum sec_cmode c_mode)
{ {
struct sec_ctx *ctx = crypto_aead_ctx(tfm); struct sec_ctx *ctx = crypto_aead_ctx(tfm);
@@ -1156,7 +1154,6 @@ static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
ctx->a_ctx.a_alg = a_alg; ctx->a_ctx.a_alg = a_alg;
ctx->c_ctx.c_alg = c_alg; ctx->c_ctx.c_alg = c_alg;
ctx->a_ctx.mac_len = mac_len;
c_ctx->c_mode = c_mode; c_ctx->c_mode = c_mode;
if (c_mode == SEC_CMODE_CCM || c_mode == SEC_CMODE_GCM) { if (c_mode == SEC_CMODE_CCM || c_mode == SEC_CMODE_GCM) {
@@ -1192,10 +1189,9 @@ static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
goto bad_key; goto bad_key;
} }
if ((ctx->a_ctx.mac_len & SEC_SQE_LEN_RATE_MASK) || if (ctx->a_ctx.a_key_len & SEC_SQE_LEN_RATE_MASK) {
(ctx->a_ctx.a_key_len & SEC_SQE_LEN_RATE_MASK)) {
ret = -EINVAL; ret = -EINVAL;
dev_err(dev, "MAC or AUTH key length error!\n"); dev_err(dev, "AUTH key length error!\n");
goto bad_key; goto bad_key;
} }
@@ -1207,27 +1203,19 @@ bad_key:
} }
#define GEN_SEC_AEAD_SETKEY_FUNC(name, aalg, calg, maclen, cmode) \ #define GEN_SEC_AEAD_SETKEY_FUNC(name, aalg, calg, cmode) \
static int sec_setkey_##name(struct crypto_aead *tfm, const u8 *key, \ static int sec_setkey_##name(struct crypto_aead *tfm, const u8 *key, u32 keylen) \
u32 keylen) \ { \
{ \ return sec_aead_setkey(tfm, key, keylen, aalg, calg, cmode); \
return sec_aead_setkey(tfm, key, keylen, aalg, calg, maclen, cmode);\
} }
GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha1, SEC_A_HMAC_SHA1, GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha1, SEC_A_HMAC_SHA1, SEC_CALG_AES, SEC_CMODE_CBC)
SEC_CALG_AES, SEC_HMAC_SHA1_MAC, SEC_CMODE_CBC) GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha256, SEC_A_HMAC_SHA256, SEC_CALG_AES, SEC_CMODE_CBC)
GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha256, SEC_A_HMAC_SHA256, GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha512, SEC_A_HMAC_SHA512, SEC_CALG_AES, SEC_CMODE_CBC)
SEC_CALG_AES, SEC_HMAC_SHA256_MAC, SEC_CMODE_CBC) GEN_SEC_AEAD_SETKEY_FUNC(aes_ccm, 0, SEC_CALG_AES, SEC_CMODE_CCM)
GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha512, SEC_A_HMAC_SHA512, GEN_SEC_AEAD_SETKEY_FUNC(aes_gcm, 0, SEC_CALG_AES, SEC_CMODE_GCM)
SEC_CALG_AES, SEC_HMAC_SHA512_MAC, SEC_CMODE_CBC) GEN_SEC_AEAD_SETKEY_FUNC(sm4_ccm, 0, SEC_CALG_SM4, SEC_CMODE_CCM)
GEN_SEC_AEAD_SETKEY_FUNC(aes_ccm, 0, SEC_CALG_AES, GEN_SEC_AEAD_SETKEY_FUNC(sm4_gcm, 0, SEC_CALG_SM4, SEC_CMODE_GCM)
SEC_HMAC_CCM_MAC, SEC_CMODE_CCM)
GEN_SEC_AEAD_SETKEY_FUNC(aes_gcm, 0, SEC_CALG_AES,
SEC_HMAC_GCM_MAC, SEC_CMODE_GCM)
GEN_SEC_AEAD_SETKEY_FUNC(sm4_ccm, 0, SEC_CALG_SM4,
SEC_HMAC_CCM_MAC, SEC_CMODE_CCM)
GEN_SEC_AEAD_SETKEY_FUNC(sm4_gcm, 0, SEC_CALG_SM4,
SEC_HMAC_GCM_MAC, SEC_CMODE_GCM)
static int sec_aead_sgl_map(struct sec_ctx *ctx, struct sec_req *req) static int sec_aead_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
{ {
@@ -1476,9 +1464,10 @@ static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req,
static void set_aead_auth_iv(struct sec_ctx *ctx, struct sec_req *req) static void set_aead_auth_iv(struct sec_ctx *ctx, struct sec_req *req)
{ {
struct aead_request *aead_req = req->aead_req.aead_req; struct aead_request *aead_req = req->aead_req.aead_req;
struct sec_cipher_req *c_req = &req->c_req; struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
size_t authsize = crypto_aead_authsize(tfm);
struct sec_aead_req *a_req = &req->aead_req; struct sec_aead_req *a_req = &req->aead_req;
size_t authsize = ctx->a_ctx.mac_len; struct sec_cipher_req *c_req = &req->c_req;
u32 data_size = aead_req->cryptlen; u32 data_size = aead_req->cryptlen;
u8 flage = 0; u8 flage = 0;
u8 cm, cl; u8 cm, cl;
@@ -1519,10 +1508,8 @@ static void set_aead_auth_iv(struct sec_ctx *ctx, struct sec_req *req)
static void sec_aead_set_iv(struct sec_ctx *ctx, struct sec_req *req) static void sec_aead_set_iv(struct sec_ctx *ctx, struct sec_req *req)
{ {
struct aead_request *aead_req = req->aead_req.aead_req; struct aead_request *aead_req = req->aead_req.aead_req;
struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
size_t authsize = crypto_aead_authsize(tfm);
struct sec_cipher_req *c_req = &req->c_req;
struct sec_aead_req *a_req = &req->aead_req; struct sec_aead_req *a_req = &req->aead_req;
struct sec_cipher_req *c_req = &req->c_req;
memcpy(c_req->c_ivin, aead_req->iv, ctx->c_ctx.ivsize); memcpy(c_req->c_ivin, aead_req->iv, ctx->c_ctx.ivsize);
@@ -1530,15 +1517,11 @@ static void sec_aead_set_iv(struct sec_ctx *ctx, struct sec_req *req)
/* /*
* CCM 16Byte Cipher_IV: {1B_Flage,13B_IV,2B_counter}, * CCM 16Byte Cipher_IV: {1B_Flage,13B_IV,2B_counter},
* the counter must set to 0x01 * the counter must set to 0x01
* CCM 16Byte Auth_IV: {1B_AFlage,13B_IV,2B_Ptext_length}
*/ */
ctx->a_ctx.mac_len = authsize;
/* CCM 16Byte Auth_IV: {1B_AFlage,13B_IV,2B_Ptext_length} */
set_aead_auth_iv(ctx, req); set_aead_auth_iv(ctx, req);
} } else if (ctx->c_ctx.c_mode == SEC_CMODE_GCM) {
/* GCM 12Byte Cipher_IV == Auth_IV */
/* GCM 12Byte Cipher_IV == Auth_IV */
if (ctx->c_ctx.c_mode == SEC_CMODE_GCM) {
ctx->a_ctx.mac_len = authsize;
memcpy(a_req->a_ivin, c_req->c_ivin, SEC_AIV_SIZE); memcpy(a_req->a_ivin, c_req->c_ivin, SEC_AIV_SIZE);
} }
} }
@@ -1548,9 +1531,11 @@ static void sec_auth_bd_fill_xcm(struct sec_auth_ctx *ctx, int dir,
{ {
struct sec_aead_req *a_req = &req->aead_req; struct sec_aead_req *a_req = &req->aead_req;
struct aead_request *aq = a_req->aead_req; struct aead_request *aq = a_req->aead_req;
struct crypto_aead *tfm = crypto_aead_reqtfm(aq);
size_t authsize = crypto_aead_authsize(tfm);
/* C_ICV_Len is MAC size, 0x4 ~ 0x10 */ /* C_ICV_Len is MAC size, 0x4 ~ 0x10 */
sec_sqe->type2.icvw_kmode |= cpu_to_le16((u16)ctx->mac_len); sec_sqe->type2.icvw_kmode |= cpu_to_le16((u16)authsize);
/* mode set to CCM/GCM, don't set {A_Alg, AKey_Len, MAC_Len} */ /* mode set to CCM/GCM, don't set {A_Alg, AKey_Len, MAC_Len} */
sec_sqe->type2.a_key_addr = sec_sqe->type2.c_key_addr; sec_sqe->type2.a_key_addr = sec_sqe->type2.c_key_addr;
@@ -1574,9 +1559,11 @@ static void sec_auth_bd_fill_xcm_v3(struct sec_auth_ctx *ctx, int dir,
{ {
struct sec_aead_req *a_req = &req->aead_req; struct sec_aead_req *a_req = &req->aead_req;
struct aead_request *aq = a_req->aead_req; struct aead_request *aq = a_req->aead_req;
struct crypto_aead *tfm = crypto_aead_reqtfm(aq);
size_t authsize = crypto_aead_authsize(tfm);
/* C_ICV_Len is MAC size, 0x4 ~ 0x10 */ /* C_ICV_Len is MAC size, 0x4 ~ 0x10 */
sqe3->c_icv_key |= cpu_to_le16((u16)ctx->mac_len << SEC_MAC_OFFSET_V3); sqe3->c_icv_key |= cpu_to_le16((u16)authsize << SEC_MAC_OFFSET_V3);
/* mode set to CCM/GCM, don't set {A_Alg, AKey_Len, MAC_Len} */ /* mode set to CCM/GCM, don't set {A_Alg, AKey_Len, MAC_Len} */
sqe3->a_key_addr = sqe3->c_key_addr; sqe3->a_key_addr = sqe3->c_key_addr;
@@ -1600,11 +1587,12 @@ static void sec_auth_bd_fill_ex(struct sec_auth_ctx *ctx, int dir,
struct sec_aead_req *a_req = &req->aead_req; struct sec_aead_req *a_req = &req->aead_req;
struct sec_cipher_req *c_req = &req->c_req; struct sec_cipher_req *c_req = &req->c_req;
struct aead_request *aq = a_req->aead_req; struct aead_request *aq = a_req->aead_req;
struct crypto_aead *tfm = crypto_aead_reqtfm(aq);
size_t authsize = crypto_aead_authsize(tfm);
sec_sqe->type2.a_key_addr = cpu_to_le64(ctx->a_key_dma); sec_sqe->type2.a_key_addr = cpu_to_le64(ctx->a_key_dma);
sec_sqe->type2.mac_key_alg = sec_sqe->type2.mac_key_alg = cpu_to_le32(authsize / SEC_SQE_LEN_RATE);
cpu_to_le32(ctx->mac_len / SEC_SQE_LEN_RATE);
sec_sqe->type2.mac_key_alg |= sec_sqe->type2.mac_key_alg |=
cpu_to_le32((u32)((ctx->a_key_len) / cpu_to_le32((u32)((ctx->a_key_len) /
@@ -1654,11 +1642,13 @@ static void sec_auth_bd_fill_ex_v3(struct sec_auth_ctx *ctx, int dir,
struct sec_aead_req *a_req = &req->aead_req; struct sec_aead_req *a_req = &req->aead_req;
struct sec_cipher_req *c_req = &req->c_req; struct sec_cipher_req *c_req = &req->c_req;
struct aead_request *aq = a_req->aead_req; struct aead_request *aq = a_req->aead_req;
struct crypto_aead *tfm = crypto_aead_reqtfm(aq);
size_t authsize = crypto_aead_authsize(tfm);
sqe3->a_key_addr = cpu_to_le64(ctx->a_key_dma); sqe3->a_key_addr = cpu_to_le64(ctx->a_key_dma);
sqe3->auth_mac_key |= sqe3->auth_mac_key |=
cpu_to_le32((u32)(ctx->mac_len / cpu_to_le32((u32)(authsize /
SEC_SQE_LEN_RATE) << SEC_MAC_OFFSET_V3); SEC_SQE_LEN_RATE) << SEC_MAC_OFFSET_V3);
sqe3->auth_mac_key |= sqe3->auth_mac_key |=
@@ -1709,9 +1699,9 @@ static void sec_aead_callback(struct sec_ctx *c, struct sec_req *req, int err)
{ {
struct aead_request *a_req = req->aead_req.aead_req; struct aead_request *a_req = req->aead_req.aead_req;
struct crypto_aead *tfm = crypto_aead_reqtfm(a_req); struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
size_t authsize = crypto_aead_authsize(tfm);
struct sec_aead_req *aead_req = &req->aead_req; struct sec_aead_req *aead_req = &req->aead_req;
struct sec_cipher_req *c_req = &req->c_req; struct sec_cipher_req *c_req = &req->c_req;
size_t authsize = crypto_aead_authsize(tfm);
struct sec_qp_ctx *qp_ctx = req->qp_ctx; struct sec_qp_ctx *qp_ctx = req->qp_ctx;
struct aead_request *backlog_aead_req; struct aead_request *backlog_aead_req;
struct sec_req *backlog_req; struct sec_req *backlog_req;
@@ -1724,10 +1714,8 @@ static void sec_aead_callback(struct sec_ctx *c, struct sec_req *req, int err)
if (!err && c_req->encrypt) { if (!err && c_req->encrypt) {
struct scatterlist *sgl = a_req->dst; struct scatterlist *sgl = a_req->dst;
sz = sg_pcopy_from_buffer(sgl, sg_nents(sgl), sz = sg_pcopy_from_buffer(sgl, sg_nents(sgl), aead_req->out_mac,
aead_req->out_mac, authsize, a_req->cryptlen + a_req->assoclen);
authsize, a_req->cryptlen +
a_req->assoclen);
if (unlikely(sz != authsize)) { if (unlikely(sz != authsize)) {
dev_err(c->dev, "copy out mac err!\n"); dev_err(c->dev, "copy out mac err!\n");
err = -EINVAL; err = -EINVAL;
@@ -2267,7 +2255,7 @@ static int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req *sreq)
{ {
struct aead_request *req = sreq->aead_req.aead_req; struct aead_request *req = sreq->aead_req.aead_req;
struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct crypto_aead *tfm = crypto_aead_reqtfm(req);
size_t authsize = crypto_aead_authsize(tfm); size_t sz = crypto_aead_authsize(tfm);
u8 c_mode = ctx->c_ctx.c_mode; u8 c_mode = ctx->c_ctx.c_mode;
struct device *dev = ctx->dev; struct device *dev = ctx->dev;
int ret; int ret;
@@ -2278,9 +2266,8 @@ static int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req *sreq)
return -EINVAL; return -EINVAL;
} }
if (unlikely((c_mode == SEC_CMODE_GCM && authsize < DES_BLOCK_SIZE) || if (unlikely((c_mode == SEC_CMODE_GCM && sz < DES_BLOCK_SIZE) ||
(c_mode == SEC_CMODE_CCM && (authsize < MIN_MAC_LEN || (c_mode == SEC_CMODE_CCM && (sz < MIN_MAC_LEN || sz & MAC_LEN_MASK)))) {
authsize & MAC_LEN_MASK)))) {
dev_err(dev, "aead input mac length error!\n"); dev_err(dev, "aead input mac length error!\n");
return -EINVAL; return -EINVAL;
} }
@@ -2300,7 +2287,7 @@ static int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req *sreq)
if (sreq->c_req.encrypt) if (sreq->c_req.encrypt)
sreq->c_req.c_len = req->cryptlen; sreq->c_req.c_len = req->cryptlen;
else else
sreq->c_req.c_len = req->cryptlen - authsize; sreq->c_req.c_len = req->cryptlen - sz;
if (c_mode == SEC_CMODE_CBC) { if (c_mode == SEC_CMODE_CBC) {
if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) { if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) {
dev_err(dev, "aead crypto length error!\n"); dev_err(dev, "aead crypto length error!\n");
@@ -2326,7 +2313,7 @@ static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
if (ctx->sec->qm.ver == QM_HW_V2) { if (ctx->sec->qm.ver == QM_HW_V2) {
if (unlikely(!req->cryptlen || (!sreq->c_req.encrypt && if (unlikely(!req->cryptlen || (!sreq->c_req.encrypt &&
req->cryptlen <= authsize))) { req->cryptlen <= authsize))) {
ctx->a_ctx.fallback = true; ctx->a_ctx.fallback = true;
return -EINVAL; return -EINVAL;
} }

View File

@@ -23,17 +23,6 @@ enum sec_hash_alg {
SEC_A_HMAC_SHA512 = 0x15, SEC_A_HMAC_SHA512 = 0x15,
}; };
enum sec_mac_len {
SEC_HMAC_CCM_MAC = 16,
SEC_HMAC_GCM_MAC = 16,
SEC_SM3_MAC = 32,
SEC_HMAC_SM3_MAC = 32,
SEC_HMAC_MD5_MAC = 16,
SEC_HMAC_SHA1_MAC = 20,
SEC_HMAC_SHA256_MAC = 32,
SEC_HMAC_SHA512_MAC = 64,
};
enum sec_cmode { enum sec_cmode {
SEC_CMODE_ECB = 0x0, SEC_CMODE_ECB = 0x0,
SEC_CMODE_CBC = 0x1, SEC_CMODE_CBC = 0x1,