mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-18 03:23:53 -04:00
crypto: hisilicon/sec2 - fix for aead invalid authsize
When the digest alg is HMAC-SHAx or another, the authsize may be less
than 4 bytes and mac_len of the BD is set to zero, the hardware considers
it a BD configuration error and reports a ras error, so the sec driver
needs to switch to software calculation in this case, this patch add a
check for it and remove unnecessary check that has been done by crypto.
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>
This commit is contained in:
@@ -1119,10 +1119,7 @@ static int sec_aead_setauthsize(struct crypto_aead *aead, unsigned int authsize)
|
||||
struct sec_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
|
||||
|
||||
if (unlikely(a_ctx->fallback_aead_tfm))
|
||||
return crypto_aead_setauthsize(a_ctx->fallback_aead_tfm, authsize);
|
||||
|
||||
return 0;
|
||||
return crypto_aead_setauthsize(a_ctx->fallback_aead_tfm, authsize);
|
||||
}
|
||||
|
||||
static int sec_aead_fallback_setkey(struct sec_auth_ctx *a_ctx,
|
||||
@@ -1159,13 +1156,7 @@ static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
|
||||
}
|
||||
memcpy(c_ctx->c_key, key, keylen);
|
||||
|
||||
if (unlikely(a_ctx->fallback_aead_tfm)) {
|
||||
ret = sec_aead_fallback_setkey(a_ctx, tfm, key, keylen);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return sec_aead_fallback_setkey(a_ctx, tfm, key, keylen);
|
||||
}
|
||||
|
||||
ret = crypto_authenc_extractkeys(&keys, key, keylen);
|
||||
@@ -1190,6 +1181,12 @@ static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
|
||||
goto bad_key;
|
||||
}
|
||||
|
||||
ret = sec_aead_fallback_setkey(a_ctx, tfm, key, keylen);
|
||||
if (ret) {
|
||||
dev_err(dev, "set sec fallback key err!\n");
|
||||
goto bad_key;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bad_key:
|
||||
@@ -1917,8 +1914,10 @@ static void sec_aead_exit(struct crypto_aead *tfm)
|
||||
|
||||
static int sec_aead_ctx_init(struct crypto_aead *tfm, const char *hash_name)
|
||||
{
|
||||
struct aead_alg *alg = crypto_aead_alg(tfm);
|
||||
struct sec_ctx *ctx = crypto_aead_ctx(tfm);
|
||||
struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
|
||||
struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
|
||||
const char *aead_name = alg->base.cra_name;
|
||||
int ret;
|
||||
|
||||
ret = sec_aead_init(tfm);
|
||||
@@ -1927,11 +1926,20 @@ static int sec_aead_ctx_init(struct crypto_aead *tfm, const char *hash_name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
auth_ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
|
||||
if (IS_ERR(auth_ctx->hash_tfm)) {
|
||||
a_ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
|
||||
if (IS_ERR(a_ctx->hash_tfm)) {
|
||||
dev_err(ctx->dev, "aead alloc shash error!\n");
|
||||
sec_aead_exit(tfm);
|
||||
return PTR_ERR(auth_ctx->hash_tfm);
|
||||
return PTR_ERR(a_ctx->hash_tfm);
|
||||
}
|
||||
|
||||
a_ctx->fallback_aead_tfm = crypto_alloc_aead(aead_name, 0,
|
||||
CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(a_ctx->fallback_aead_tfm)) {
|
||||
dev_err(ctx->dev, "aead driver alloc fallback tfm error!\n");
|
||||
crypto_free_shash(ctx->a_ctx.hash_tfm);
|
||||
sec_aead_exit(tfm);
|
||||
return PTR_ERR(a_ctx->fallback_aead_tfm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1941,6 +1949,7 @@ static void sec_aead_ctx_exit(struct crypto_aead *tfm)
|
||||
{
|
||||
struct sec_ctx *ctx = crypto_aead_ctx(tfm);
|
||||
|
||||
crypto_free_aead(ctx->a_ctx.fallback_aead_tfm);
|
||||
crypto_free_shash(ctx->a_ctx.hash_tfm);
|
||||
sec_aead_exit(tfm);
|
||||
}
|
||||
@@ -1967,7 +1976,6 @@ static int sec_aead_xcm_ctx_init(struct crypto_aead *tfm)
|
||||
sec_aead_exit(tfm);
|
||||
return PTR_ERR(a_ctx->fallback_aead_tfm);
|
||||
}
|
||||
a_ctx->fallback = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2226,15 +2234,15 @@ static int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req *sreq)
|
||||
struct device *dev = ctx->dev;
|
||||
int ret;
|
||||
|
||||
if (unlikely(req->cryptlen + req->assoclen > MAX_INPUT_DATA_LEN ||
|
||||
req->assoclen > SEC_MAX_AAD_LEN)) {
|
||||
dev_err(dev, "aead input spec error!\n");
|
||||
/* Hardware does not handle cases where authsize is less than 4 bytes */
|
||||
if (unlikely(sz < MIN_MAC_LEN)) {
|
||||
sreq->aead_req.fallback = true;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (unlikely((c_mode == SEC_CMODE_GCM && sz < DES_BLOCK_SIZE) ||
|
||||
(c_mode == SEC_CMODE_CCM && (sz < MIN_MAC_LEN || sz & MAC_LEN_MASK)))) {
|
||||
dev_err(dev, "aead input mac length error!\n");
|
||||
if (unlikely(req->cryptlen + req->assoclen > MAX_INPUT_DATA_LEN ||
|
||||
req->assoclen > SEC_MAX_AAD_LEN)) {
|
||||
dev_err(dev, "aead input spec error!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -2280,7 +2288,7 @@ static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
|
||||
if (ctx->sec->qm.ver == QM_HW_V2) {
|
||||
if (unlikely(!req->cryptlen || (!sreq->c_req.encrypt &&
|
||||
req->cryptlen <= authsize))) {
|
||||
ctx->a_ctx.fallback = true;
|
||||
sreq->aead_req.fallback = true;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -2308,16 +2316,9 @@ static int sec_aead_soft_crypto(struct sec_ctx *ctx,
|
||||
bool encrypt)
|
||||
{
|
||||
struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
|
||||
struct device *dev = ctx->dev;
|
||||
struct aead_request *subreq;
|
||||
int ret;
|
||||
|
||||
/* Kunpeng920 aead mode not support input 0 size */
|
||||
if (!a_ctx->fallback_aead_tfm) {
|
||||
dev_err(dev, "aead fallback tfm is NULL!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
subreq = aead_request_alloc(a_ctx->fallback_aead_tfm, GFP_KERNEL);
|
||||
if (!subreq)
|
||||
return -ENOMEM;
|
||||
@@ -2349,10 +2350,11 @@ static int sec_aead_crypto(struct aead_request *a_req, bool encrypt)
|
||||
req->aead_req.aead_req = a_req;
|
||||
req->c_req.encrypt = encrypt;
|
||||
req->ctx = ctx;
|
||||
req->aead_req.fallback = false;
|
||||
|
||||
ret = sec_aead_param_check(ctx, req);
|
||||
if (unlikely(ret)) {
|
||||
if (ctx->a_ctx.fallback)
|
||||
if (req->aead_req.fallback)
|
||||
return sec_aead_soft_crypto(ctx, a_req, encrypt);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user