Skip to content

Commit 4ade590

Browse files
ryan-wannercristibirsan
authored andcommitted
crypto: atmel-aes: Add fallback for unsupported ESP header length
Adding a software fallback for hmac(x)-cbc(aes) in cases where the ESP header length is not a multiple of 4 words. The only ESP header length that is not a multiple of 4 words is 6 words in this case, so this is the only case tested. As not all SoCs are affected by this limitation the HW version is used to discriminate the SoCs. In this case HW versions 600 and 700 are affected by this limitation. To keep the hardware acceleration the check is put in place to use the fallback for the highlighted case. Signed-off-by: Ryan Wanner <Ryan.Wanner@microchip.com>
1 parent 112cbfe commit 4ade590

1 file changed

Lines changed: 59 additions & 2 deletions

File tree

drivers/crypto/atmel-aes.c

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,24 @@
8484

8585
#define ATMEL_AES_DMA_THRESHOLD 256
8686

87-
87+
/**
88+
* struct atmel_aes_caps: at91 aes capabilities
89+
* @has_dualbuff: dual buffer support
90+
* @has_cfb64: cfb64 support
91+
* @has_gcm: gcm support
92+
* @has_xts: xts suppport
93+
* @has_authenc: authentication support
94+
* @max_burst_size: max DMA bust size
95+
* @has_6words_limitation: some versions of IP have a 6 word headder limitation
96+
*/
8897
struct atmel_aes_caps {
8998
bool has_dualbuff;
9099
bool has_cfb64;
91100
bool has_gcm;
92101
bool has_xts;
93102
bool has_authenc;
94103
u32 max_burst_size;
104+
bool has_6words_limitation;
95105
};
96106

97107
struct atmel_aes_dev;
@@ -150,6 +160,8 @@ struct atmel_aes_xts_ctx {
150160
struct atmel_aes_authenc_ctx {
151161
struct atmel_aes_base_ctx base;
152162
struct atmel_sha_authenc_ctx *auth;
163+
164+
struct crypto_aead *fallback;
153165
};
154166
#endif
155167

@@ -2120,6 +2132,12 @@ static int atmel_aes_authenc_setkey(struct crypto_aead *tfm, const u8 *key,
21202132
memcpy(ctx->base.key, keys.enckey, keys.enckeylen);
21212133

21222134
memzero_explicit(&keys, sizeof(keys));
2135+
2136+
if (ctx->base.dd->caps.has_6words_limitation) {
2137+
crypto_aead_clear_flags(ctx->fallback, CRYPTO_TFM_REQ_MASK);
2138+
crypto_aead_set_flags(ctx->fallback, crypto_aead_get_flags(tfm) & CRYPTO_TFM_REQ_MASK);
2139+
crypto_aead_setkey(ctx->fallback, key, keylen);
2140+
}
21232141
return 0;
21242142

21252143
badkey:
@@ -2132,15 +2150,27 @@ static int atmel_aes_authenc_init_tfm(struct crypto_aead *tfm,
21322150
{
21332151
struct atmel_aes_authenc_ctx *ctx = crypto_aead_ctx(tfm);
21342152
unsigned int auth_reqsize = atmel_sha_authenc_get_reqsize();
2153+
struct aead_alg *alg = crypto_aead_alg(tfm);
21352154
struct atmel_aes_dev *dd;
21362155

21372156
dd = atmel_aes_dev_alloc(&ctx->base);
21382157
if (!dd)
21392158
return -ENODEV;
21402159

2160+
if (dd->caps.has_6words_limitation) {
2161+
ctx->fallback = crypto_alloc_aead(alg->base.cra_name, 0,
2162+
CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_ASYNC);
2163+
if (IS_ERR(ctx->fallback)) {
2164+
dev_err(dd->dev, "fallback driver fail %s\n", alg->base.cra_name);
2165+
return PTR_ERR(ctx->fallback);
2166+
}
2167+
}
21412168
ctx->auth = atmel_sha_authenc_spawn(auth_mode);
2142-
if (IS_ERR(ctx->auth))
2169+
if (IS_ERR(ctx->auth)) {
2170+
if (dd->caps.has_6words_limitation)
2171+
crypto_free_aead(ctx->fallback);
21432172
return PTR_ERR(ctx->auth);
2173+
}
21442174

21452175
crypto_aead_set_reqsize(tfm, (sizeof(struct atmel_aes_authenc_reqctx) +
21462176
auth_reqsize));
@@ -2180,6 +2210,8 @@ static void atmel_aes_authenc_exit_tfm(struct crypto_aead *tfm)
21802210
struct atmel_aes_authenc_ctx *ctx = crypto_aead_ctx(tfm);
21812211

21822212
atmel_sha_authenc_free(ctx->auth);
2213+
if (ctx->base.dd->caps.has_6words_limitation)
2214+
crypto_free_aead(ctx->fallback);
21832215
}
21842216

21852217
static int atmel_aes_authenc_crypt(struct aead_request *req,
@@ -2188,8 +2220,10 @@ static int atmel_aes_authenc_crypt(struct aead_request *req,
21882220
struct atmel_aes_authenc_reqctx *rctx = aead_request_ctx(req);
21892221
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
21902222
struct atmel_aes_base_ctx *ctx = crypto_aead_ctx(tfm);
2223+
struct atmel_aes_authenc_ctx *actx = crypto_aead_ctx(tfm);
21912224
u32 authsize = crypto_aead_authsize(tfm);
21922225
bool enc = (mode & AES_FLAGS_ENCRYPT);
2226+
bool limitation = ctx->dd->caps.has_6words_limitation;
21932227

21942228
/* Compute text length. */
21952229
if (!enc && req->cryptlen < authsize)
@@ -2203,6 +2237,26 @@ static int atmel_aes_authenc_crypt(struct aead_request *req,
22032237
*/
22042238
if (!rctx->textlen && !req->assoclen)
22052239
return -EINVAL;
2240+
/*
2241+
*Check if data size triggers the HW limitation and
2242+
* run fallback functions
2243+
*/
2244+
if ((req->assoclen != 16) && limitation) {
2245+
struct aead_request *subreq = aead_request_ctx(req);
2246+
int ret;
2247+
2248+
aead_request_set_tfm(subreq, actx->fallback);
2249+
aead_request_set_callback(subreq, req->base.flags,
2250+
req->base.complete, req->base.data);
2251+
aead_request_set_crypt(subreq, req->src, req->dst,
2252+
req->cryptlen, req->iv);
2253+
aead_request_set_ad(subreq, req->assoclen);
2254+
2255+
if (enc)
2256+
return crypto_aead_encrypt(subreq);
2257+
else
2258+
return crypto_aead_decrypt(subreq);
2259+
}
22062260

22072261
rctx->base.mode = mode;
22082262
ctx->block_size = AES_BLOCK_SIZE;
@@ -2500,10 +2554,13 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
25002554
dd->caps.has_xts = 0;
25012555
dd->caps.has_authenc = 0;
25022556
dd->caps.max_burst_size = 1;
2557+
dd->caps.has_6words_limitation = 0;
25032558

25042559
/* keep only major version number */
25052560
switch (dd->hw_version & 0xff0) {
25062561
case 0x700:
2562+
case 0x600:
2563+
dd->caps.has_6words_limitation = 1;
25072564
case 0x500:
25082565
dd->caps.has_dualbuff = 1;
25092566
dd->caps.has_cfb64 = 1;

0 commit comments

Comments
 (0)