1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
286464859SArd Biesheuvel /*
386464859SArd Biesheuvel * aes-ce-glue.c - wrapper code for ARMv8 AES
486464859SArd Biesheuvel *
586464859SArd Biesheuvel * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
686464859SArd Biesheuvel */
786464859SArd Biesheuvel
886464859SArd Biesheuvel #include <asm/hwcap.h>
986464859SArd Biesheuvel #include <asm/neon.h>
105eedf315SArd Biesheuvel #include <asm/simd.h>
11fafb1dcaSArd Biesheuvel #include <asm/unaligned.h>
1286464859SArd Biesheuvel #include <crypto/aes.h>
135eedf315SArd Biesheuvel #include <crypto/ctr.h>
14da40e7a4SHerbert Xu #include <crypto/internal/simd.h>
15da40e7a4SHerbert Xu #include <crypto/internal/skcipher.h>
16c61b1607SArd Biesheuvel #include <crypto/scatterwalk.h>
174d8061a5SArd Biesheuvel #include <linux/cpufeature.h>
1886464859SArd Biesheuvel #include <linux/module.h>
1949abc0d2SStephan Mueller #include <crypto/xts.h>
2086464859SArd Biesheuvel
2186464859SArd Biesheuvel MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions");
2286464859SArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
2386464859SArd Biesheuvel MODULE_LICENSE("GPL v2");
2486464859SArd Biesheuvel
2586464859SArd Biesheuvel /* defined in aes-ce-core.S */
2686464859SArd Biesheuvel asmlinkage u32 ce_aes_sub(u32 input);
2786464859SArd Biesheuvel asmlinkage void ce_aes_invert(void *dst, void *src);
2886464859SArd Biesheuvel
29fcb0e30dSArd Biesheuvel asmlinkage void ce_aes_ecb_encrypt(u8 out[], u8 const in[], u32 const rk[],
3086464859SArd Biesheuvel int rounds, int blocks);
31fcb0e30dSArd Biesheuvel asmlinkage void ce_aes_ecb_decrypt(u8 out[], u8 const in[], u32 const rk[],
3286464859SArd Biesheuvel int rounds, int blocks);
3386464859SArd Biesheuvel
34fcb0e30dSArd Biesheuvel asmlinkage void ce_aes_cbc_encrypt(u8 out[], u8 const in[], u32 const rk[],
3586464859SArd Biesheuvel int rounds, int blocks, u8 iv[]);
36fcb0e30dSArd Biesheuvel asmlinkage void ce_aes_cbc_decrypt(u8 out[], u8 const in[], u32 const rk[],
3786464859SArd Biesheuvel int rounds, int blocks, u8 iv[]);
38143d2647SArd Biesheuvel asmlinkage void ce_aes_cbc_cts_encrypt(u8 out[], u8 const in[], u32 const rk[],
39143d2647SArd Biesheuvel int rounds, int bytes, u8 const iv[]);
40143d2647SArd Biesheuvel asmlinkage void ce_aes_cbc_cts_decrypt(u8 out[], u8 const in[], u32 const rk[],
41143d2647SArd Biesheuvel int rounds, int bytes, u8 const iv[]);
4286464859SArd Biesheuvel
43fcb0e30dSArd Biesheuvel asmlinkage void ce_aes_ctr_encrypt(u8 out[], u8 const in[], u32 const rk[],
4486464859SArd Biesheuvel int rounds, int blocks, u8 ctr[]);
4586464859SArd Biesheuvel
46fcb0e30dSArd Biesheuvel asmlinkage void ce_aes_xts_encrypt(u8 out[], u8 const in[], u32 const rk1[],
47c61b1607SArd Biesheuvel int rounds, int bytes, u8 iv[],
48fcb0e30dSArd Biesheuvel u32 const rk2[], int first);
49fcb0e30dSArd Biesheuvel asmlinkage void ce_aes_xts_decrypt(u8 out[], u8 const in[], u32 const rk1[],
50c61b1607SArd Biesheuvel int rounds, int bytes, u8 iv[],
51fcb0e30dSArd Biesheuvel u32 const rk2[], int first);
5286464859SArd Biesheuvel
5386464859SArd Biesheuvel struct aes_block {
5486464859SArd Biesheuvel u8 b[AES_BLOCK_SIZE];
5586464859SArd Biesheuvel };
5686464859SArd Biesheuvel
num_rounds(struct crypto_aes_ctx * ctx)5786464859SArd Biesheuvel static int num_rounds(struct crypto_aes_ctx *ctx)
5886464859SArd Biesheuvel {
5986464859SArd Biesheuvel /*
6086464859SArd Biesheuvel * # of rounds specified by AES:
6186464859SArd Biesheuvel * 128 bit key 10 rounds
6286464859SArd Biesheuvel * 192 bit key 12 rounds
6386464859SArd Biesheuvel * 256 bit key 14 rounds
6486464859SArd Biesheuvel * => n byte key => 6 + (n/4) rounds
6586464859SArd Biesheuvel */
6686464859SArd Biesheuvel return 6 + ctx->key_length / 4;
6786464859SArd Biesheuvel }
6886464859SArd Biesheuvel
ce_aes_expandkey(struct crypto_aes_ctx * ctx,const u8 * in_key,unsigned int key_len)6986464859SArd Biesheuvel static int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
7086464859SArd Biesheuvel unsigned int key_len)
7186464859SArd Biesheuvel {
7286464859SArd Biesheuvel /*
7386464859SArd Biesheuvel * The AES key schedule round constants
7486464859SArd Biesheuvel */
7586464859SArd Biesheuvel static u8 const rcon[] = {
7686464859SArd Biesheuvel 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
7786464859SArd Biesheuvel };
7886464859SArd Biesheuvel
7986464859SArd Biesheuvel u32 kwords = key_len / sizeof(u32);
8086464859SArd Biesheuvel struct aes_block *key_enc, *key_dec;
8186464859SArd Biesheuvel int i, j;
8286464859SArd Biesheuvel
8386464859SArd Biesheuvel if (key_len != AES_KEYSIZE_128 &&
8486464859SArd Biesheuvel key_len != AES_KEYSIZE_192 &&
8586464859SArd Biesheuvel key_len != AES_KEYSIZE_256)
8686464859SArd Biesheuvel return -EINVAL;
8786464859SArd Biesheuvel
8886464859SArd Biesheuvel ctx->key_length = key_len;
89fafb1dcaSArd Biesheuvel for (i = 0; i < kwords; i++)
90fafb1dcaSArd Biesheuvel ctx->key_enc[i] = get_unaligned_le32(in_key + i * sizeof(u32));
9186464859SArd Biesheuvel
9286464859SArd Biesheuvel kernel_neon_begin();
9386464859SArd Biesheuvel for (i = 0; i < sizeof(rcon); i++) {
9486464859SArd Biesheuvel u32 *rki = ctx->key_enc + (i * kwords);
9586464859SArd Biesheuvel u32 *rko = rki + kwords;
9686464859SArd Biesheuvel
9786464859SArd Biesheuvel rko[0] = ror32(ce_aes_sub(rki[kwords - 1]), 8);
9886464859SArd Biesheuvel rko[0] = rko[0] ^ rki[0] ^ rcon[i];
9986464859SArd Biesheuvel rko[1] = rko[0] ^ rki[1];
10086464859SArd Biesheuvel rko[2] = rko[1] ^ rki[2];
10186464859SArd Biesheuvel rko[3] = rko[2] ^ rki[3];
10286464859SArd Biesheuvel
10386464859SArd Biesheuvel if (key_len == AES_KEYSIZE_192) {
10486464859SArd Biesheuvel if (i >= 7)
10586464859SArd Biesheuvel break;
10686464859SArd Biesheuvel rko[4] = rko[3] ^ rki[4];
10786464859SArd Biesheuvel rko[5] = rko[4] ^ rki[5];
10886464859SArd Biesheuvel } else if (key_len == AES_KEYSIZE_256) {
10986464859SArd Biesheuvel if (i >= 6)
11086464859SArd Biesheuvel break;
11186464859SArd Biesheuvel rko[4] = ce_aes_sub(rko[3]) ^ rki[4];
11286464859SArd Biesheuvel rko[5] = rko[4] ^ rki[5];
11386464859SArd Biesheuvel rko[6] = rko[5] ^ rki[6];
11486464859SArd Biesheuvel rko[7] = rko[6] ^ rki[7];
11586464859SArd Biesheuvel }
11686464859SArd Biesheuvel }
11786464859SArd Biesheuvel
11886464859SArd Biesheuvel /*
11986464859SArd Biesheuvel * Generate the decryption keys for the Equivalent Inverse Cipher.
12086464859SArd Biesheuvel * This involves reversing the order of the round keys, and applying
12186464859SArd Biesheuvel * the Inverse Mix Columns transformation on all but the first and
12286464859SArd Biesheuvel * the last one.
12386464859SArd Biesheuvel */
12486464859SArd Biesheuvel key_enc = (struct aes_block *)ctx->key_enc;
12586464859SArd Biesheuvel key_dec = (struct aes_block *)ctx->key_dec;
12686464859SArd Biesheuvel j = num_rounds(ctx);
12786464859SArd Biesheuvel
12886464859SArd Biesheuvel key_dec[0] = key_enc[j];
12986464859SArd Biesheuvel for (i = 1, j--; j > 0; i++, j--)
13086464859SArd Biesheuvel ce_aes_invert(key_dec + i, key_enc + j);
13186464859SArd Biesheuvel key_dec[i] = key_enc[0];
13286464859SArd Biesheuvel
13386464859SArd Biesheuvel kernel_neon_end();
13486464859SArd Biesheuvel return 0;
13586464859SArd Biesheuvel }
13686464859SArd Biesheuvel
ce_aes_setkey(struct crypto_skcipher * tfm,const u8 * in_key,unsigned int key_len)137da40e7a4SHerbert Xu static int ce_aes_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
13886464859SArd Biesheuvel unsigned int key_len)
13986464859SArd Biesheuvel {
140da40e7a4SHerbert Xu struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
14186464859SArd Biesheuvel
142674f368aSEric Biggers return ce_aes_expandkey(ctx, in_key, key_len);
14386464859SArd Biesheuvel }
14486464859SArd Biesheuvel
14586464859SArd Biesheuvel struct crypto_aes_xts_ctx {
14686464859SArd Biesheuvel struct crypto_aes_ctx key1;
14786464859SArd Biesheuvel struct crypto_aes_ctx __aligned(8) key2;
14886464859SArd Biesheuvel };
14986464859SArd Biesheuvel
xts_set_key(struct crypto_skcipher * tfm,const u8 * in_key,unsigned int key_len)150da40e7a4SHerbert Xu static int xts_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
15186464859SArd Biesheuvel unsigned int key_len)
15286464859SArd Biesheuvel {
153da40e7a4SHerbert Xu struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
15486464859SArd Biesheuvel int ret;
15586464859SArd Biesheuvel
156da40e7a4SHerbert Xu ret = xts_verify_key(tfm, in_key, key_len);
15728856a9eSStephan Mueller if (ret)
15828856a9eSStephan Mueller return ret;
15928856a9eSStephan Mueller
16086464859SArd Biesheuvel ret = ce_aes_expandkey(&ctx->key1, in_key, key_len / 2);
16186464859SArd Biesheuvel if (!ret)
16286464859SArd Biesheuvel ret = ce_aes_expandkey(&ctx->key2, &in_key[key_len / 2],
16386464859SArd Biesheuvel key_len / 2);
164674f368aSEric Biggers return ret;
16586464859SArd Biesheuvel }
16686464859SArd Biesheuvel
ecb_encrypt(struct skcipher_request * req)167da40e7a4SHerbert Xu static int ecb_encrypt(struct skcipher_request *req)
16886464859SArd Biesheuvel {
169da40e7a4SHerbert Xu struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
170da40e7a4SHerbert Xu struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
171da40e7a4SHerbert Xu struct skcipher_walk walk;
17286464859SArd Biesheuvel unsigned int blocks;
17386464859SArd Biesheuvel int err;
17486464859SArd Biesheuvel
17546a22776SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
17686464859SArd Biesheuvel
17786464859SArd Biesheuvel while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
17846a22776SArd Biesheuvel kernel_neon_begin();
17986464859SArd Biesheuvel ce_aes_ecb_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
180fcb0e30dSArd Biesheuvel ctx->key_enc, num_rounds(ctx), blocks);
18146a22776SArd Biesheuvel kernel_neon_end();
182da40e7a4SHerbert Xu err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
18386464859SArd Biesheuvel }
18486464859SArd Biesheuvel return err;
18586464859SArd Biesheuvel }
18686464859SArd Biesheuvel
ecb_decrypt(struct skcipher_request * req)187da40e7a4SHerbert Xu static int ecb_decrypt(struct skcipher_request *req)
18886464859SArd Biesheuvel {
189da40e7a4SHerbert Xu struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
190da40e7a4SHerbert Xu struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
191da40e7a4SHerbert Xu struct skcipher_walk walk;
19286464859SArd Biesheuvel unsigned int blocks;
19386464859SArd Biesheuvel int err;
19486464859SArd Biesheuvel
19546a22776SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
19686464859SArd Biesheuvel
19786464859SArd Biesheuvel while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
19846a22776SArd Biesheuvel kernel_neon_begin();
19986464859SArd Biesheuvel ce_aes_ecb_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
200fcb0e30dSArd Biesheuvel ctx->key_dec, num_rounds(ctx), blocks);
20146a22776SArd Biesheuvel kernel_neon_end();
202da40e7a4SHerbert Xu err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
20386464859SArd Biesheuvel }
20486464859SArd Biesheuvel return err;
20586464859SArd Biesheuvel }
20686464859SArd Biesheuvel
cbc_encrypt_walk(struct skcipher_request * req,struct skcipher_walk * walk)207143d2647SArd Biesheuvel static int cbc_encrypt_walk(struct skcipher_request *req,
208143d2647SArd Biesheuvel struct skcipher_walk *walk)
20986464859SArd Biesheuvel {
210da40e7a4SHerbert Xu struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
211da40e7a4SHerbert Xu struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
21286464859SArd Biesheuvel unsigned int blocks;
213143d2647SArd Biesheuvel int err = 0;
214143d2647SArd Biesheuvel
215143d2647SArd Biesheuvel while ((blocks = (walk->nbytes / AES_BLOCK_SIZE))) {
216143d2647SArd Biesheuvel kernel_neon_begin();
217143d2647SArd Biesheuvel ce_aes_cbc_encrypt(walk->dst.virt.addr, walk->src.virt.addr,
218143d2647SArd Biesheuvel ctx->key_enc, num_rounds(ctx), blocks,
219143d2647SArd Biesheuvel walk->iv);
220143d2647SArd Biesheuvel kernel_neon_end();
221143d2647SArd Biesheuvel err = skcipher_walk_done(walk, walk->nbytes % AES_BLOCK_SIZE);
222143d2647SArd Biesheuvel }
223143d2647SArd Biesheuvel return err;
224143d2647SArd Biesheuvel }
225143d2647SArd Biesheuvel
cbc_encrypt(struct skcipher_request * req)226143d2647SArd Biesheuvel static int cbc_encrypt(struct skcipher_request *req)
227143d2647SArd Biesheuvel {
228143d2647SArd Biesheuvel struct skcipher_walk walk;
22986464859SArd Biesheuvel int err;
23086464859SArd Biesheuvel
23146a22776SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
232143d2647SArd Biesheuvel if (err)
233143d2647SArd Biesheuvel return err;
234143d2647SArd Biesheuvel return cbc_encrypt_walk(req, &walk);
235143d2647SArd Biesheuvel }
23686464859SArd Biesheuvel
cbc_decrypt_walk(struct skcipher_request * req,struct skcipher_walk * walk)237143d2647SArd Biesheuvel static int cbc_decrypt_walk(struct skcipher_request *req,
238143d2647SArd Biesheuvel struct skcipher_walk *walk)
239143d2647SArd Biesheuvel {
240143d2647SArd Biesheuvel struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
241143d2647SArd Biesheuvel struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
242143d2647SArd Biesheuvel unsigned int blocks;
243143d2647SArd Biesheuvel int err = 0;
244143d2647SArd Biesheuvel
245143d2647SArd Biesheuvel while ((blocks = (walk->nbytes / AES_BLOCK_SIZE))) {
24646a22776SArd Biesheuvel kernel_neon_begin();
247143d2647SArd Biesheuvel ce_aes_cbc_decrypt(walk->dst.virt.addr, walk->src.virt.addr,
248143d2647SArd Biesheuvel ctx->key_dec, num_rounds(ctx), blocks,
249143d2647SArd Biesheuvel walk->iv);
25046a22776SArd Biesheuvel kernel_neon_end();
251143d2647SArd Biesheuvel err = skcipher_walk_done(walk, walk->nbytes % AES_BLOCK_SIZE);
25286464859SArd Biesheuvel }
25386464859SArd Biesheuvel return err;
25486464859SArd Biesheuvel }
25586464859SArd Biesheuvel
cbc_decrypt(struct skcipher_request * req)256da40e7a4SHerbert Xu static int cbc_decrypt(struct skcipher_request *req)
25786464859SArd Biesheuvel {
258da40e7a4SHerbert Xu struct skcipher_walk walk;
25986464859SArd Biesheuvel int err;
26086464859SArd Biesheuvel
26146a22776SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
262143d2647SArd Biesheuvel if (err)
263143d2647SArd Biesheuvel return err;
264143d2647SArd Biesheuvel return cbc_decrypt_walk(req, &walk);
265143d2647SArd Biesheuvel }
26686464859SArd Biesheuvel
cts_cbc_encrypt(struct skcipher_request * req)267143d2647SArd Biesheuvel static int cts_cbc_encrypt(struct skcipher_request *req)
268143d2647SArd Biesheuvel {
269143d2647SArd Biesheuvel struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
270143d2647SArd Biesheuvel struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
271143d2647SArd Biesheuvel int cbc_blocks = DIV_ROUND_UP(req->cryptlen, AES_BLOCK_SIZE) - 2;
272143d2647SArd Biesheuvel struct scatterlist *src = req->src, *dst = req->dst;
273143d2647SArd Biesheuvel struct scatterlist sg_src[2], sg_dst[2];
274143d2647SArd Biesheuvel struct skcipher_request subreq;
275143d2647SArd Biesheuvel struct skcipher_walk walk;
276143d2647SArd Biesheuvel int err;
277143d2647SArd Biesheuvel
278143d2647SArd Biesheuvel skcipher_request_set_tfm(&subreq, tfm);
279143d2647SArd Biesheuvel skcipher_request_set_callback(&subreq, skcipher_request_flags(req),
280143d2647SArd Biesheuvel NULL, NULL);
281143d2647SArd Biesheuvel
282143d2647SArd Biesheuvel if (req->cryptlen <= AES_BLOCK_SIZE) {
283143d2647SArd Biesheuvel if (req->cryptlen < AES_BLOCK_SIZE)
284143d2647SArd Biesheuvel return -EINVAL;
285143d2647SArd Biesheuvel cbc_blocks = 1;
286143d2647SArd Biesheuvel }
287143d2647SArd Biesheuvel
288143d2647SArd Biesheuvel if (cbc_blocks > 0) {
289143d2647SArd Biesheuvel skcipher_request_set_crypt(&subreq, req->src, req->dst,
290143d2647SArd Biesheuvel cbc_blocks * AES_BLOCK_SIZE,
291143d2647SArd Biesheuvel req->iv);
292143d2647SArd Biesheuvel
293143d2647SArd Biesheuvel err = skcipher_walk_virt(&walk, &subreq, false) ?:
294143d2647SArd Biesheuvel cbc_encrypt_walk(&subreq, &walk);
295143d2647SArd Biesheuvel if (err)
296143d2647SArd Biesheuvel return err;
297143d2647SArd Biesheuvel
298143d2647SArd Biesheuvel if (req->cryptlen == AES_BLOCK_SIZE)
299143d2647SArd Biesheuvel return 0;
300143d2647SArd Biesheuvel
301143d2647SArd Biesheuvel dst = src = scatterwalk_ffwd(sg_src, req->src, subreq.cryptlen);
302143d2647SArd Biesheuvel if (req->dst != req->src)
303143d2647SArd Biesheuvel dst = scatterwalk_ffwd(sg_dst, req->dst,
304143d2647SArd Biesheuvel subreq.cryptlen);
305143d2647SArd Biesheuvel }
306143d2647SArd Biesheuvel
307143d2647SArd Biesheuvel /* handle ciphertext stealing */
308143d2647SArd Biesheuvel skcipher_request_set_crypt(&subreq, src, dst,
309143d2647SArd Biesheuvel req->cryptlen - cbc_blocks * AES_BLOCK_SIZE,
310143d2647SArd Biesheuvel req->iv);
311143d2647SArd Biesheuvel
312143d2647SArd Biesheuvel err = skcipher_walk_virt(&walk, &subreq, false);
313143d2647SArd Biesheuvel if (err)
314143d2647SArd Biesheuvel return err;
315143d2647SArd Biesheuvel
31646a22776SArd Biesheuvel kernel_neon_begin();
317143d2647SArd Biesheuvel ce_aes_cbc_cts_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
318143d2647SArd Biesheuvel ctx->key_enc, num_rounds(ctx), walk.nbytes,
31986464859SArd Biesheuvel walk.iv);
32046a22776SArd Biesheuvel kernel_neon_end();
321143d2647SArd Biesheuvel
322143d2647SArd Biesheuvel return skcipher_walk_done(&walk, 0);
32386464859SArd Biesheuvel }
324143d2647SArd Biesheuvel
cts_cbc_decrypt(struct skcipher_request * req)325143d2647SArd Biesheuvel static int cts_cbc_decrypt(struct skcipher_request *req)
326143d2647SArd Biesheuvel {
327143d2647SArd Biesheuvel struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
328143d2647SArd Biesheuvel struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
329143d2647SArd Biesheuvel int cbc_blocks = DIV_ROUND_UP(req->cryptlen, AES_BLOCK_SIZE) - 2;
330143d2647SArd Biesheuvel struct scatterlist *src = req->src, *dst = req->dst;
331143d2647SArd Biesheuvel struct scatterlist sg_src[2], sg_dst[2];
332143d2647SArd Biesheuvel struct skcipher_request subreq;
333143d2647SArd Biesheuvel struct skcipher_walk walk;
334143d2647SArd Biesheuvel int err;
335143d2647SArd Biesheuvel
336143d2647SArd Biesheuvel skcipher_request_set_tfm(&subreq, tfm);
337143d2647SArd Biesheuvel skcipher_request_set_callback(&subreq, skcipher_request_flags(req),
338143d2647SArd Biesheuvel NULL, NULL);
339143d2647SArd Biesheuvel
340143d2647SArd Biesheuvel if (req->cryptlen <= AES_BLOCK_SIZE) {
341143d2647SArd Biesheuvel if (req->cryptlen < AES_BLOCK_SIZE)
342143d2647SArd Biesheuvel return -EINVAL;
343143d2647SArd Biesheuvel cbc_blocks = 1;
344143d2647SArd Biesheuvel }
345143d2647SArd Biesheuvel
346143d2647SArd Biesheuvel if (cbc_blocks > 0) {
347143d2647SArd Biesheuvel skcipher_request_set_crypt(&subreq, req->src, req->dst,
348143d2647SArd Biesheuvel cbc_blocks * AES_BLOCK_SIZE,
349143d2647SArd Biesheuvel req->iv);
350143d2647SArd Biesheuvel
351143d2647SArd Biesheuvel err = skcipher_walk_virt(&walk, &subreq, false) ?:
352143d2647SArd Biesheuvel cbc_decrypt_walk(&subreq, &walk);
353143d2647SArd Biesheuvel if (err)
35486464859SArd Biesheuvel return err;
355143d2647SArd Biesheuvel
356143d2647SArd Biesheuvel if (req->cryptlen == AES_BLOCK_SIZE)
357143d2647SArd Biesheuvel return 0;
358143d2647SArd Biesheuvel
359143d2647SArd Biesheuvel dst = src = scatterwalk_ffwd(sg_src, req->src, subreq.cryptlen);
360143d2647SArd Biesheuvel if (req->dst != req->src)
361143d2647SArd Biesheuvel dst = scatterwalk_ffwd(sg_dst, req->dst,
362143d2647SArd Biesheuvel subreq.cryptlen);
363143d2647SArd Biesheuvel }
364143d2647SArd Biesheuvel
365143d2647SArd Biesheuvel /* handle ciphertext stealing */
366143d2647SArd Biesheuvel skcipher_request_set_crypt(&subreq, src, dst,
367143d2647SArd Biesheuvel req->cryptlen - cbc_blocks * AES_BLOCK_SIZE,
368143d2647SArd Biesheuvel req->iv);
369143d2647SArd Biesheuvel
370143d2647SArd Biesheuvel err = skcipher_walk_virt(&walk, &subreq, false);
371143d2647SArd Biesheuvel if (err)
372143d2647SArd Biesheuvel return err;
373143d2647SArd Biesheuvel
374143d2647SArd Biesheuvel kernel_neon_begin();
375143d2647SArd Biesheuvel ce_aes_cbc_cts_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
376143d2647SArd Biesheuvel ctx->key_dec, num_rounds(ctx), walk.nbytes,
377143d2647SArd Biesheuvel walk.iv);
378143d2647SArd Biesheuvel kernel_neon_end();
379143d2647SArd Biesheuvel
380143d2647SArd Biesheuvel return skcipher_walk_done(&walk, 0);
38186464859SArd Biesheuvel }
38286464859SArd Biesheuvel
ctr_encrypt(struct skcipher_request * req)383da40e7a4SHerbert Xu static int ctr_encrypt(struct skcipher_request *req)
38486464859SArd Biesheuvel {
385da40e7a4SHerbert Xu struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
386da40e7a4SHerbert Xu struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
387da40e7a4SHerbert Xu struct skcipher_walk walk;
38886464859SArd Biesheuvel int err, blocks;
38986464859SArd Biesheuvel
39046a22776SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
39186464859SArd Biesheuvel
39286464859SArd Biesheuvel while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
39346a22776SArd Biesheuvel kernel_neon_begin();
39486464859SArd Biesheuvel ce_aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
395fcb0e30dSArd Biesheuvel ctx->key_enc, num_rounds(ctx), blocks,
39686464859SArd Biesheuvel walk.iv);
39746a22776SArd Biesheuvel kernel_neon_end();
398da40e7a4SHerbert Xu err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
39986464859SArd Biesheuvel }
400da40e7a4SHerbert Xu if (walk.nbytes) {
40186464859SArd Biesheuvel u8 __aligned(8) tail[AES_BLOCK_SIZE];
402da40e7a4SHerbert Xu unsigned int nbytes = walk.nbytes;
403da40e7a4SHerbert Xu u8 *tdst = walk.dst.virt.addr;
404da40e7a4SHerbert Xu u8 *tsrc = walk.src.virt.addr;
40586464859SArd Biesheuvel
40686464859SArd Biesheuvel /*
4071465fb13SArd Biesheuvel * Tell aes_ctr_encrypt() to process a tail block.
40886464859SArd Biesheuvel */
4091465fb13SArd Biesheuvel blocks = -1;
41086464859SArd Biesheuvel
41146a22776SArd Biesheuvel kernel_neon_begin();
412fcb0e30dSArd Biesheuvel ce_aes_ctr_encrypt(tail, NULL, ctx->key_enc, num_rounds(ctx),
413fcb0e30dSArd Biesheuvel blocks, walk.iv);
41446a22776SArd Biesheuvel kernel_neon_end();
41545fe93dfSArd Biesheuvel crypto_xor_cpy(tdst, tsrc, tail, nbytes);
416da40e7a4SHerbert Xu err = skcipher_walk_done(&walk, 0);
41786464859SArd Biesheuvel }
41886464859SArd Biesheuvel return err;
41986464859SArd Biesheuvel }
42086464859SArd Biesheuvel
ctr_encrypt_one(struct crypto_skcipher * tfm,const u8 * src,u8 * dst)4215eedf315SArd Biesheuvel static void ctr_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst)
4225eedf315SArd Biesheuvel {
4235eedf315SArd Biesheuvel struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
4245eedf315SArd Biesheuvel unsigned long flags;
4255eedf315SArd Biesheuvel
4265eedf315SArd Biesheuvel /*
4275eedf315SArd Biesheuvel * Temporarily disable interrupts to avoid races where
4285eedf315SArd Biesheuvel * cachelines are evicted when the CPU is interrupted
4295eedf315SArd Biesheuvel * to do something else.
4305eedf315SArd Biesheuvel */
4315eedf315SArd Biesheuvel local_irq_save(flags);
4325eedf315SArd Biesheuvel aes_encrypt(ctx, dst, src);
4335eedf315SArd Biesheuvel local_irq_restore(flags);
4345eedf315SArd Biesheuvel }
4355eedf315SArd Biesheuvel
ctr_encrypt_sync(struct skcipher_request * req)4365eedf315SArd Biesheuvel static int ctr_encrypt_sync(struct skcipher_request *req)
4375eedf315SArd Biesheuvel {
4385eedf315SArd Biesheuvel if (!crypto_simd_usable())
4395eedf315SArd Biesheuvel return crypto_ctr_encrypt_walk(req, ctr_encrypt_one);
4405eedf315SArd Biesheuvel
4415eedf315SArd Biesheuvel return ctr_encrypt(req);
4425eedf315SArd Biesheuvel }
4435eedf315SArd Biesheuvel
xts_encrypt(struct skcipher_request * req)444da40e7a4SHerbert Xu static int xts_encrypt(struct skcipher_request *req)
44586464859SArd Biesheuvel {
446da40e7a4SHerbert Xu struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
447da40e7a4SHerbert Xu struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
44886464859SArd Biesheuvel int err, first, rounds = num_rounds(&ctx->key1);
449c61b1607SArd Biesheuvel int tail = req->cryptlen % AES_BLOCK_SIZE;
450c61b1607SArd Biesheuvel struct scatterlist sg_src[2], sg_dst[2];
451c61b1607SArd Biesheuvel struct skcipher_request subreq;
452c61b1607SArd Biesheuvel struct scatterlist *src, *dst;
453da40e7a4SHerbert Xu struct skcipher_walk walk;
454c61b1607SArd Biesheuvel
455c61b1607SArd Biesheuvel if (req->cryptlen < AES_BLOCK_SIZE)
456c61b1607SArd Biesheuvel return -EINVAL;
45786464859SArd Biesheuvel
45846a22776SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
45986464859SArd Biesheuvel
460c61b1607SArd Biesheuvel if (unlikely(tail > 0 && walk.nbytes < walk.total)) {
461c61b1607SArd Biesheuvel int xts_blocks = DIV_ROUND_UP(req->cryptlen,
462c61b1607SArd Biesheuvel AES_BLOCK_SIZE) - 2;
463c61b1607SArd Biesheuvel
464c61b1607SArd Biesheuvel skcipher_walk_abort(&walk);
465c61b1607SArd Biesheuvel
466c61b1607SArd Biesheuvel skcipher_request_set_tfm(&subreq, tfm);
467c61b1607SArd Biesheuvel skcipher_request_set_callback(&subreq,
468c61b1607SArd Biesheuvel skcipher_request_flags(req),
469c61b1607SArd Biesheuvel NULL, NULL);
470c61b1607SArd Biesheuvel skcipher_request_set_crypt(&subreq, req->src, req->dst,
471c61b1607SArd Biesheuvel xts_blocks * AES_BLOCK_SIZE,
472c61b1607SArd Biesheuvel req->iv);
473c61b1607SArd Biesheuvel req = &subreq;
474c61b1607SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
475c61b1607SArd Biesheuvel } else {
476c61b1607SArd Biesheuvel tail = 0;
477c61b1607SArd Biesheuvel }
478c61b1607SArd Biesheuvel
479c61b1607SArd Biesheuvel for (first = 1; walk.nbytes >= AES_BLOCK_SIZE; first = 0) {
480c61b1607SArd Biesheuvel int nbytes = walk.nbytes;
481c61b1607SArd Biesheuvel
482c61b1607SArd Biesheuvel if (walk.nbytes < walk.total)
483c61b1607SArd Biesheuvel nbytes &= ~(AES_BLOCK_SIZE - 1);
484c61b1607SArd Biesheuvel
48546a22776SArd Biesheuvel kernel_neon_begin();
48686464859SArd Biesheuvel ce_aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
487c61b1607SArd Biesheuvel ctx->key1.key_enc, rounds, nbytes, walk.iv,
488fcb0e30dSArd Biesheuvel ctx->key2.key_enc, first);
48946a22776SArd Biesheuvel kernel_neon_end();
490c61b1607SArd Biesheuvel err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
49186464859SArd Biesheuvel }
492c61b1607SArd Biesheuvel
493c61b1607SArd Biesheuvel if (err || likely(!tail))
49486464859SArd Biesheuvel return err;
495c61b1607SArd Biesheuvel
496c61b1607SArd Biesheuvel dst = src = scatterwalk_ffwd(sg_src, req->src, req->cryptlen);
497c61b1607SArd Biesheuvel if (req->dst != req->src)
498c61b1607SArd Biesheuvel dst = scatterwalk_ffwd(sg_dst, req->dst, req->cryptlen);
499c61b1607SArd Biesheuvel
500c61b1607SArd Biesheuvel skcipher_request_set_crypt(req, src, dst, AES_BLOCK_SIZE + tail,
501c61b1607SArd Biesheuvel req->iv);
502c61b1607SArd Biesheuvel
503c61b1607SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
504c61b1607SArd Biesheuvel if (err)
505c61b1607SArd Biesheuvel return err;
506c61b1607SArd Biesheuvel
507c61b1607SArd Biesheuvel kernel_neon_begin();
508c61b1607SArd Biesheuvel ce_aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
509c61b1607SArd Biesheuvel ctx->key1.key_enc, rounds, walk.nbytes, walk.iv,
510c61b1607SArd Biesheuvel ctx->key2.key_enc, first);
511c61b1607SArd Biesheuvel kernel_neon_end();
512c61b1607SArd Biesheuvel
513c61b1607SArd Biesheuvel return skcipher_walk_done(&walk, 0);
51486464859SArd Biesheuvel }
51586464859SArd Biesheuvel
xts_decrypt(struct skcipher_request * req)516da40e7a4SHerbert Xu static int xts_decrypt(struct skcipher_request *req)
51786464859SArd Biesheuvel {
518da40e7a4SHerbert Xu struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
519da40e7a4SHerbert Xu struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
52086464859SArd Biesheuvel int err, first, rounds = num_rounds(&ctx->key1);
521c61b1607SArd Biesheuvel int tail = req->cryptlen % AES_BLOCK_SIZE;
522c61b1607SArd Biesheuvel struct scatterlist sg_src[2], sg_dst[2];
523c61b1607SArd Biesheuvel struct skcipher_request subreq;
524c61b1607SArd Biesheuvel struct scatterlist *src, *dst;
525da40e7a4SHerbert Xu struct skcipher_walk walk;
526c61b1607SArd Biesheuvel
527c61b1607SArd Biesheuvel if (req->cryptlen < AES_BLOCK_SIZE)
528c61b1607SArd Biesheuvel return -EINVAL;
52986464859SArd Biesheuvel
53046a22776SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
53186464859SArd Biesheuvel
532c61b1607SArd Biesheuvel if (unlikely(tail > 0 && walk.nbytes < walk.total)) {
533c61b1607SArd Biesheuvel int xts_blocks = DIV_ROUND_UP(req->cryptlen,
534c61b1607SArd Biesheuvel AES_BLOCK_SIZE) - 2;
535c61b1607SArd Biesheuvel
536c61b1607SArd Biesheuvel skcipher_walk_abort(&walk);
537c61b1607SArd Biesheuvel
538c61b1607SArd Biesheuvel skcipher_request_set_tfm(&subreq, tfm);
539c61b1607SArd Biesheuvel skcipher_request_set_callback(&subreq,
540c61b1607SArd Biesheuvel skcipher_request_flags(req),
541c61b1607SArd Biesheuvel NULL, NULL);
542c61b1607SArd Biesheuvel skcipher_request_set_crypt(&subreq, req->src, req->dst,
543c61b1607SArd Biesheuvel xts_blocks * AES_BLOCK_SIZE,
544c61b1607SArd Biesheuvel req->iv);
545c61b1607SArd Biesheuvel req = &subreq;
546c61b1607SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
547c61b1607SArd Biesheuvel } else {
548c61b1607SArd Biesheuvel tail = 0;
549c61b1607SArd Biesheuvel }
550c61b1607SArd Biesheuvel
551c61b1607SArd Biesheuvel for (first = 1; walk.nbytes >= AES_BLOCK_SIZE; first = 0) {
552c61b1607SArd Biesheuvel int nbytes = walk.nbytes;
553c61b1607SArd Biesheuvel
554c61b1607SArd Biesheuvel if (walk.nbytes < walk.total)
555c61b1607SArd Biesheuvel nbytes &= ~(AES_BLOCK_SIZE - 1);
556c61b1607SArd Biesheuvel
55746a22776SArd Biesheuvel kernel_neon_begin();
55886464859SArd Biesheuvel ce_aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
559c61b1607SArd Biesheuvel ctx->key1.key_dec, rounds, nbytes, walk.iv,
560fcb0e30dSArd Biesheuvel ctx->key2.key_enc, first);
56146a22776SArd Biesheuvel kernel_neon_end();
562c61b1607SArd Biesheuvel err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
56386464859SArd Biesheuvel }
564c61b1607SArd Biesheuvel
565c61b1607SArd Biesheuvel if (err || likely(!tail))
56686464859SArd Biesheuvel return err;
567c61b1607SArd Biesheuvel
568c61b1607SArd Biesheuvel dst = src = scatterwalk_ffwd(sg_src, req->src, req->cryptlen);
569c61b1607SArd Biesheuvel if (req->dst != req->src)
570c61b1607SArd Biesheuvel dst = scatterwalk_ffwd(sg_dst, req->dst, req->cryptlen);
571c61b1607SArd Biesheuvel
572c61b1607SArd Biesheuvel skcipher_request_set_crypt(req, src, dst, AES_BLOCK_SIZE + tail,
573c61b1607SArd Biesheuvel req->iv);
574c61b1607SArd Biesheuvel
575c61b1607SArd Biesheuvel err = skcipher_walk_virt(&walk, req, false);
576c61b1607SArd Biesheuvel if (err)
577c61b1607SArd Biesheuvel return err;
578c61b1607SArd Biesheuvel
579c61b1607SArd Biesheuvel kernel_neon_begin();
580c61b1607SArd Biesheuvel ce_aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
581c61b1607SArd Biesheuvel ctx->key1.key_dec, rounds, walk.nbytes, walk.iv,
582c61b1607SArd Biesheuvel ctx->key2.key_enc, first);
583c61b1607SArd Biesheuvel kernel_neon_end();
584c61b1607SArd Biesheuvel
585c61b1607SArd Biesheuvel return skcipher_walk_done(&walk, 0);
58686464859SArd Biesheuvel }
58786464859SArd Biesheuvel
588da40e7a4SHerbert Xu static struct skcipher_alg aes_algs[] = { {
58920bb4ef0SArd Biesheuvel .base.cra_name = "__ecb(aes)",
59020bb4ef0SArd Biesheuvel .base.cra_driver_name = "__ecb-aes-ce",
59120bb4ef0SArd Biesheuvel .base.cra_priority = 300,
59220bb4ef0SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_INTERNAL,
59320bb4ef0SArd Biesheuvel .base.cra_blocksize = AES_BLOCK_SIZE,
59420bb4ef0SArd Biesheuvel .base.cra_ctxsize = sizeof(struct crypto_aes_ctx),
59520bb4ef0SArd Biesheuvel .base.cra_module = THIS_MODULE,
59620bb4ef0SArd Biesheuvel
59786464859SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE,
59886464859SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE,
59986464859SArd Biesheuvel .setkey = ce_aes_setkey,
60086464859SArd Biesheuvel .encrypt = ecb_encrypt,
60186464859SArd Biesheuvel .decrypt = ecb_decrypt,
60286464859SArd Biesheuvel }, {
60320bb4ef0SArd Biesheuvel .base.cra_name = "__cbc(aes)",
60420bb4ef0SArd Biesheuvel .base.cra_driver_name = "__cbc-aes-ce",
60520bb4ef0SArd Biesheuvel .base.cra_priority = 300,
60620bb4ef0SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_INTERNAL,
60720bb4ef0SArd Biesheuvel .base.cra_blocksize = AES_BLOCK_SIZE,
60820bb4ef0SArd Biesheuvel .base.cra_ctxsize = sizeof(struct crypto_aes_ctx),
60920bb4ef0SArd Biesheuvel .base.cra_module = THIS_MODULE,
61020bb4ef0SArd Biesheuvel
61186464859SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE,
61286464859SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE,
61386464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE,
61486464859SArd Biesheuvel .setkey = ce_aes_setkey,
61586464859SArd Biesheuvel .encrypt = cbc_encrypt,
61686464859SArd Biesheuvel .decrypt = cbc_decrypt,
61786464859SArd Biesheuvel }, {
618143d2647SArd Biesheuvel .base.cra_name = "__cts(cbc(aes))",
619143d2647SArd Biesheuvel .base.cra_driver_name = "__cts-cbc-aes-ce",
620143d2647SArd Biesheuvel .base.cra_priority = 300,
621143d2647SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_INTERNAL,
622143d2647SArd Biesheuvel .base.cra_blocksize = AES_BLOCK_SIZE,
623143d2647SArd Biesheuvel .base.cra_ctxsize = sizeof(struct crypto_aes_ctx),
624143d2647SArd Biesheuvel .base.cra_module = THIS_MODULE,
625143d2647SArd Biesheuvel
626143d2647SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE,
627143d2647SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE,
628143d2647SArd Biesheuvel .ivsize = AES_BLOCK_SIZE,
629143d2647SArd Biesheuvel .walksize = 2 * AES_BLOCK_SIZE,
630143d2647SArd Biesheuvel .setkey = ce_aes_setkey,
631143d2647SArd Biesheuvel .encrypt = cts_cbc_encrypt,
632143d2647SArd Biesheuvel .decrypt = cts_cbc_decrypt,
633143d2647SArd Biesheuvel }, {
63420bb4ef0SArd Biesheuvel .base.cra_name = "__ctr(aes)",
63520bb4ef0SArd Biesheuvel .base.cra_driver_name = "__ctr-aes-ce",
63620bb4ef0SArd Biesheuvel .base.cra_priority = 300,
63720bb4ef0SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_INTERNAL,
63820bb4ef0SArd Biesheuvel .base.cra_blocksize = 1,
63920bb4ef0SArd Biesheuvel .base.cra_ctxsize = sizeof(struct crypto_aes_ctx),
64020bb4ef0SArd Biesheuvel .base.cra_module = THIS_MODULE,
64120bb4ef0SArd Biesheuvel
64286464859SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE,
64386464859SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE,
64486464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE,
645da40e7a4SHerbert Xu .chunksize = AES_BLOCK_SIZE,
64686464859SArd Biesheuvel .setkey = ce_aes_setkey,
64786464859SArd Biesheuvel .encrypt = ctr_encrypt,
64886464859SArd Biesheuvel .decrypt = ctr_encrypt,
64986464859SArd Biesheuvel }, {
6505eedf315SArd Biesheuvel .base.cra_name = "ctr(aes)",
6515eedf315SArd Biesheuvel .base.cra_driver_name = "ctr-aes-ce-sync",
6525eedf315SArd Biesheuvel .base.cra_priority = 300 - 1,
6535eedf315SArd Biesheuvel .base.cra_blocksize = 1,
6545eedf315SArd Biesheuvel .base.cra_ctxsize = sizeof(struct crypto_aes_ctx),
6555eedf315SArd Biesheuvel .base.cra_module = THIS_MODULE,
6565eedf315SArd Biesheuvel
6575eedf315SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE,
6585eedf315SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE,
6595eedf315SArd Biesheuvel .ivsize = AES_BLOCK_SIZE,
6605eedf315SArd Biesheuvel .chunksize = AES_BLOCK_SIZE,
6615eedf315SArd Biesheuvel .setkey = ce_aes_setkey,
6625eedf315SArd Biesheuvel .encrypt = ctr_encrypt_sync,
6635eedf315SArd Biesheuvel .decrypt = ctr_encrypt_sync,
6645eedf315SArd Biesheuvel }, {
66520bb4ef0SArd Biesheuvel .base.cra_name = "__xts(aes)",
66620bb4ef0SArd Biesheuvel .base.cra_driver_name = "__xts-aes-ce",
66720bb4ef0SArd Biesheuvel .base.cra_priority = 300,
66820bb4ef0SArd Biesheuvel .base.cra_flags = CRYPTO_ALG_INTERNAL,
66920bb4ef0SArd Biesheuvel .base.cra_blocksize = AES_BLOCK_SIZE,
67020bb4ef0SArd Biesheuvel .base.cra_ctxsize = sizeof(struct crypto_aes_xts_ctx),
67120bb4ef0SArd Biesheuvel .base.cra_module = THIS_MODULE,
67220bb4ef0SArd Biesheuvel
67386464859SArd Biesheuvel .min_keysize = 2 * AES_MIN_KEY_SIZE,
67486464859SArd Biesheuvel .max_keysize = 2 * AES_MAX_KEY_SIZE,
67586464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE,
676c61b1607SArd Biesheuvel .walksize = 2 * AES_BLOCK_SIZE,
67786464859SArd Biesheuvel .setkey = xts_set_key,
67886464859SArd Biesheuvel .encrypt = xts_encrypt,
67986464859SArd Biesheuvel .decrypt = xts_decrypt,
68086464859SArd Biesheuvel } };
68186464859SArd Biesheuvel
682efad2b61SHerbert Xu static struct simd_skcipher_alg *aes_simd_algs[ARRAY_SIZE(aes_algs)];
683da40e7a4SHerbert Xu
aes_exit(void)684da40e7a4SHerbert Xu static void aes_exit(void)
685da40e7a4SHerbert Xu {
686da40e7a4SHerbert Xu int i;
687da40e7a4SHerbert Xu
688da40e7a4SHerbert Xu for (i = 0; i < ARRAY_SIZE(aes_simd_algs) && aes_simd_algs[i]; i++)
689da40e7a4SHerbert Xu simd_skcipher_free(aes_simd_algs[i]);
690da40e7a4SHerbert Xu
691da40e7a4SHerbert Xu crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
692da40e7a4SHerbert Xu }
693da40e7a4SHerbert Xu
aes_init(void)69486464859SArd Biesheuvel static int __init aes_init(void)
69586464859SArd Biesheuvel {
696da40e7a4SHerbert Xu struct simd_skcipher_alg *simd;
697da40e7a4SHerbert Xu const char *basename;
698da40e7a4SHerbert Xu const char *algname;
699da40e7a4SHerbert Xu const char *drvname;
700da40e7a4SHerbert Xu int err;
701da40e7a4SHerbert Xu int i;
702da40e7a4SHerbert Xu
703da40e7a4SHerbert Xu err = crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
704da40e7a4SHerbert Xu if (err)
705da40e7a4SHerbert Xu return err;
706da40e7a4SHerbert Xu
707da40e7a4SHerbert Xu for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
7085eedf315SArd Biesheuvel if (!(aes_algs[i].base.cra_flags & CRYPTO_ALG_INTERNAL))
7095eedf315SArd Biesheuvel continue;
7105eedf315SArd Biesheuvel
711da40e7a4SHerbert Xu algname = aes_algs[i].base.cra_name + 2;
712da40e7a4SHerbert Xu drvname = aes_algs[i].base.cra_driver_name + 2;
713da40e7a4SHerbert Xu basename = aes_algs[i].base.cra_driver_name;
714*b60d2bc6SHerbert Xu simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
715da40e7a4SHerbert Xu err = PTR_ERR(simd);
716da40e7a4SHerbert Xu if (IS_ERR(simd))
717da40e7a4SHerbert Xu goto unregister_simds;
718da40e7a4SHerbert Xu
719da40e7a4SHerbert Xu aes_simd_algs[i] = simd;
72086464859SArd Biesheuvel }
72186464859SArd Biesheuvel
722da40e7a4SHerbert Xu return 0;
723da40e7a4SHerbert Xu
724da40e7a4SHerbert Xu unregister_simds:
725da40e7a4SHerbert Xu aes_exit();
726da40e7a4SHerbert Xu return err;
72786464859SArd Biesheuvel }
72886464859SArd Biesheuvel
7294d8061a5SArd Biesheuvel module_cpu_feature_match(AES, aes_init);
73086464859SArd Biesheuvel module_exit(aes_exit);
731