Skip to content

Commit df9f807

Browse files
committed
crypto: atmel-aes: Add fallback to XTS software implementation
XTS is supported just for input lengths with data units of 128-bit blocks. Add a fallback to software implementation when the last block is shorter than 128 bits. Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
1 parent a890388 commit df9f807

1 file changed

Lines changed: 51 additions & 4 deletions

File tree

drivers/crypto/atmel-aes.c

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ struct atmel_aes_xts_ctx {
143143
struct atmel_aes_base_ctx base;
144144

145145
u32 key2[AES_KEYSIZE_256 / sizeof(u32)];
146+
struct crypto_skcipher *fallback_tfm;
146147
};
147148

148149
#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
@@ -155,6 +156,7 @@ struct atmel_aes_authenc_ctx {
155156
struct atmel_aes_reqctx {
156157
unsigned long mode;
157158
u8 lastc[AES_BLOCK_SIZE];
159+
struct skcipher_request fallback_req;
158160
};
159161

160162
#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
@@ -1083,6 +1085,22 @@ static int atmel_aes_ctr_start(struct atmel_aes_dev *dd)
10831085
return atmel_aes_ctr_transfer(dd);
10841086
}
10851087

1088+
static int atmel_aes_xts_fallback(struct skcipher_request *req, bool enc)
1089+
{
1090+
struct atmel_aes_reqctx *rctx = skcipher_request_ctx(req);
1091+
struct atmel_aes_xts_ctx *ctx = crypto_skcipher_ctx(
1092+
crypto_skcipher_reqtfm(req));
1093+
1094+
skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
1095+
skcipher_request_set_callback(&rctx->fallback_req, req->base.flags,
1096+
req->base.complete, req->base.data);
1097+
skcipher_request_set_crypt(&rctx->fallback_req, req->src, req->dst,
1098+
req->cryptlen, req->iv);
1099+
1100+
return enc ? crypto_skcipher_encrypt(&rctx->fallback_req) :
1101+
crypto_skcipher_decrypt(&rctx->fallback_req);
1102+
}
1103+
10861104
static int atmel_aes_crypt(struct skcipher_request *req, unsigned long mode)
10871105
{
10881106
struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
@@ -1091,8 +1109,14 @@ static int atmel_aes_crypt(struct skcipher_request *req, unsigned long mode)
10911109
struct atmel_aes_dev *dd;
10921110
u32 opmode = mode & AES_FLAGS_OPMODE_MASK;
10931111

1094-
if (opmode == AES_FLAGS_XTS && req->cryptlen < XTS_BLOCK_SIZE)
1095-
return -EINVAL;
1112+
if (opmode == AES_FLAGS_XTS) {
1113+
if (req->cryptlen < XTS_BLOCK_SIZE)
1114+
return -EINVAL;
1115+
1116+
if (!IS_ALIGNED(req->cryptlen, XTS_BLOCK_SIZE))
1117+
return atmel_aes_xts_fallback(req,
1118+
mode & AES_FLAGS_ENCRYPT);
1119+
}
10961120

10971121
/*
10981122
* ECB, CBC, CFB, OFB or CTR mode require the plaintext and ciphertext
@@ -1864,6 +1888,13 @@ static int atmel_aes_xts_setkey(struct crypto_skcipher *tfm, const u8 *key,
18641888
if (err)
18651889
return err;
18661890

1891+
crypto_skcipher_clear_flags(ctx->fallback_tfm, CRYPTO_TFM_REQ_MASK);
1892+
crypto_skcipher_set_flags(ctx->fallback_tfm, tfm->base.crt_flags &
1893+
CRYPTO_TFM_REQ_MASK);
1894+
err = crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen);
1895+
if (err)
1896+
return err;
1897+
18671898
memcpy(ctx->base.key, key, keylen/2);
18681899
memcpy(ctx->key2, key + keylen/2, keylen/2);
18691900
ctx->base.keylen = keylen/2;
@@ -1884,18 +1915,33 @@ static int atmel_aes_xts_decrypt(struct skcipher_request *req)
18841915
static int atmel_aes_xts_init_tfm(struct crypto_skcipher *tfm)
18851916
{
18861917
struct atmel_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
1918+
const char *tfm_name = crypto_tfm_alg_name(&tfm->base);
18871919

1888-
crypto_skcipher_set_reqsize(tfm, sizeof(struct atmel_aes_reqctx));
1920+
ctx->fallback_tfm = crypto_alloc_skcipher(tfm_name, 0,
1921+
CRYPTO_ALG_NEED_FALLBACK);
1922+
if (IS_ERR(ctx->fallback_tfm))
1923+
return PTR_ERR(ctx->fallback_tfm);
1924+
1925+
crypto_skcipher_set_reqsize(tfm, sizeof(struct atmel_aes_reqctx) +
1926+
crypto_skcipher_reqsize(ctx->fallback_tfm));
18891927
ctx->base.start = atmel_aes_xts_start;
18901928

18911929
return 0;
18921930
}
18931931

1932+
static void atmel_aes_xts_exit_tfm(struct crypto_skcipher *tfm)
1933+
{
1934+
struct atmel_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
1935+
1936+
crypto_free_skcipher(ctx->fallback_tfm);
1937+
}
1938+
18941939
static struct skcipher_alg aes_xts_alg = {
18951940
.base.cra_name = "xts(aes)",
18961941
.base.cra_driver_name = "atmel-xts-aes",
18971942
.base.cra_blocksize = AES_BLOCK_SIZE,
18981943
.base.cra_ctxsize = sizeof(struct atmel_aes_xts_ctx),
1944+
.base.cra_flags = CRYPTO_ALG_NEED_FALLBACK,
18991945

19001946
.min_keysize = 2 * AES_MIN_KEY_SIZE,
19011947
.max_keysize = 2 * AES_MAX_KEY_SIZE,
@@ -1904,6 +1950,7 @@ static struct skcipher_alg aes_xts_alg = {
19041950
.encrypt = atmel_aes_xts_encrypt,
19051951
.decrypt = atmel_aes_xts_decrypt,
19061952
.init = atmel_aes_xts_init_tfm,
1953+
.exit = atmel_aes_xts_exit_tfm,
19071954
};
19081955

19091956
#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
@@ -2373,7 +2420,7 @@ static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
23732420

23742421
static void atmel_aes_crypto_alg_init(struct crypto_alg *alg)
23752422
{
2376-
alg->cra_flags = CRYPTO_ALG_ASYNC;
2423+
alg->cra_flags |= CRYPTO_ALG_ASYNC;
23772424
alg->cra_alignmask = 0xf;
23782425
alg->cra_priority = ATMEL_AES_PRIORITY;
23792426
alg->cra_module = THIS_MODULE;

0 commit comments

Comments
 (0)