xref: /openbmc/linux/arch/arm64/crypto/aes-glue.c (revision c0eb7591)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
249788fe2SArd Biesheuvel /*
349788fe2SArd Biesheuvel  * linux/arch/arm64/crypto/aes-glue.c - wrapper code for ARMv8 AES
449788fe2SArd Biesheuvel  *
54860620dSArd Biesheuvel  * Copyright (C) 2013 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
649788fe2SArd Biesheuvel  */
749788fe2SArd Biesheuvel 
849788fe2SArd Biesheuvel #include <asm/neon.h>
949788fe2SArd Biesheuvel #include <asm/hwcap.h>
10e2115069SArd Biesheuvel #include <asm/simd.h>
1149788fe2SArd Biesheuvel #include <crypto/aes.h>
12ff6f4115SArd Biesheuvel #include <crypto/ctr.h>
13a24d22b2SEric Biggers #include <crypto/sha2.h>
144860620dSArd Biesheuvel #include <crypto/internal/hash.h>
15d0ed0db1SHerbert Xu #include <crypto/internal/simd.h>
16d0ed0db1SHerbert Xu #include <crypto/internal/skcipher.h>
17dd597fb3SArd Biesheuvel #include <crypto/scatterwalk.h>
1849788fe2SArd Biesheuvel #include <linux/module.h>
1949788fe2SArd Biesheuvel #include <linux/cpufeature.h>
2049abc0d2SStephan Mueller #include <crypto/xts.h>
2149788fe2SArd Biesheuvel 
2212ac3efeSArd Biesheuvel #include "aes-ce-setkey.h"
2312ac3efeSArd Biesheuvel 
2449788fe2SArd Biesheuvel #ifdef USE_V8_CRYPTO_EXTENSIONS
2549788fe2SArd Biesheuvel #define MODE			"ce"
2649788fe2SArd Biesheuvel #define PRIO			300
2712ac3efeSArd Biesheuvel #define aes_expandkey		ce_aes_expandkey
2849788fe2SArd Biesheuvel #define aes_ecb_encrypt		ce_aes_ecb_encrypt
2949788fe2SArd Biesheuvel #define aes_ecb_decrypt		ce_aes_ecb_decrypt
3049788fe2SArd Biesheuvel #define aes_cbc_encrypt		ce_aes_cbc_encrypt
3149788fe2SArd Biesheuvel #define aes_cbc_decrypt		ce_aes_cbc_decrypt
32dd597fb3SArd Biesheuvel #define aes_cbc_cts_encrypt	ce_aes_cbc_cts_encrypt
33dd597fb3SArd Biesheuvel #define aes_cbc_cts_decrypt	ce_aes_cbc_cts_decrypt
34735177caSArd Biesheuvel #define aes_essiv_cbc_encrypt	ce_aes_essiv_cbc_encrypt
35735177caSArd Biesheuvel #define aes_essiv_cbc_decrypt	ce_aes_essiv_cbc_decrypt
3649788fe2SArd Biesheuvel #define aes_ctr_encrypt		ce_aes_ctr_encrypt
3723a251ccSNathan Huckleberry #define aes_xctr_encrypt	ce_aes_xctr_encrypt
3849788fe2SArd Biesheuvel #define aes_xts_encrypt		ce_aes_xts_encrypt
3949788fe2SArd Biesheuvel #define aes_xts_decrypt		ce_aes_xts_decrypt
404860620dSArd Biesheuvel #define aes_mac_update		ce_aes_mac_update
4123a251ccSNathan Huckleberry MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS/XCTR using ARMv8 Crypto Extensions");
4249788fe2SArd Biesheuvel #else
4349788fe2SArd Biesheuvel #define MODE			"neon"
4449788fe2SArd Biesheuvel #define PRIO			200
4549788fe2SArd Biesheuvel #define aes_ecb_encrypt		neon_aes_ecb_encrypt
4649788fe2SArd Biesheuvel #define aes_ecb_decrypt		neon_aes_ecb_decrypt
4749788fe2SArd Biesheuvel #define aes_cbc_encrypt		neon_aes_cbc_encrypt
4849788fe2SArd Biesheuvel #define aes_cbc_decrypt		neon_aes_cbc_decrypt
49dd597fb3SArd Biesheuvel #define aes_cbc_cts_encrypt	neon_aes_cbc_cts_encrypt
50dd597fb3SArd Biesheuvel #define aes_cbc_cts_decrypt	neon_aes_cbc_cts_decrypt
51735177caSArd Biesheuvel #define aes_essiv_cbc_encrypt	neon_aes_essiv_cbc_encrypt
52735177caSArd Biesheuvel #define aes_essiv_cbc_decrypt	neon_aes_essiv_cbc_decrypt
5349788fe2SArd Biesheuvel #define aes_ctr_encrypt		neon_aes_ctr_encrypt
5423a251ccSNathan Huckleberry #define aes_xctr_encrypt	neon_aes_xctr_encrypt
5549788fe2SArd Biesheuvel #define aes_xts_encrypt		neon_aes_xts_encrypt
5649788fe2SArd Biesheuvel #define aes_xts_decrypt		neon_aes_xts_decrypt
574860620dSArd Biesheuvel #define aes_mac_update		neon_aes_mac_update
5823a251ccSNathan Huckleberry MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS/XCTR using ARMv8 NEON");
5969b6f2e8SArd Biesheuvel #endif
6015deb433SArd Biesheuvel #if defined(USE_V8_CRYPTO_EXTENSIONS) || !IS_ENABLED(CONFIG_CRYPTO_AES_ARM64_BS)
615d26a105SKees Cook MODULE_ALIAS_CRYPTO("ecb(aes)");
625d26a105SKees Cook MODULE_ALIAS_CRYPTO("cbc(aes)");
635d26a105SKees Cook MODULE_ALIAS_CRYPTO("ctr(aes)");
645d26a105SKees Cook MODULE_ALIAS_CRYPTO("xts(aes)");
6523a251ccSNathan Huckleberry MODULE_ALIAS_CRYPTO("xctr(aes)");
6669b6f2e8SArd Biesheuvel #endif
6769b6f2e8SArd Biesheuvel MODULE_ALIAS_CRYPTO("cts(cbc(aes))");
6869b6f2e8SArd Biesheuvel MODULE_ALIAS_CRYPTO("essiv(cbc(aes),sha256)");
694860620dSArd Biesheuvel MODULE_ALIAS_CRYPTO("cmac(aes)");
704860620dSArd Biesheuvel MODULE_ALIAS_CRYPTO("xcbc(aes)");
714860620dSArd Biesheuvel MODULE_ALIAS_CRYPTO("cbcmac(aes)");
7249788fe2SArd Biesheuvel 
7349788fe2SArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
7449788fe2SArd Biesheuvel MODULE_LICENSE("GPL v2");
7549788fe2SArd Biesheuvel 
7649788fe2SArd Biesheuvel /* defined in aes-modes.S */
77557ecb45SArd Biesheuvel asmlinkage void aes_ecb_encrypt(u8 out[], u8 const in[], u32 const rk[],
7868338174SArd Biesheuvel 				int rounds, int blocks);
79557ecb45SArd Biesheuvel asmlinkage void aes_ecb_decrypt(u8 out[], u8 const in[], u32 const rk[],
8068338174SArd Biesheuvel 				int rounds, int blocks);
8149788fe2SArd Biesheuvel 
82557ecb45SArd Biesheuvel asmlinkage void aes_cbc_encrypt(u8 out[], u8 const in[], u32 const rk[],
8368338174SArd Biesheuvel 				int rounds, int blocks, u8 iv[]);
84557ecb45SArd Biesheuvel asmlinkage void aes_cbc_decrypt(u8 out[], u8 const in[], u32 const rk[],
8568338174SArd Biesheuvel 				int rounds, int blocks, u8 iv[]);
8649788fe2SArd Biesheuvel 
87dd597fb3SArd Biesheuvel asmlinkage void aes_cbc_cts_encrypt(u8 out[], u8 const in[], u32 const rk[],
88dd597fb3SArd Biesheuvel 				int rounds, int bytes, u8 const iv[]);
89dd597fb3SArd Biesheuvel asmlinkage void aes_cbc_cts_decrypt(u8 out[], u8 const in[], u32 const rk[],
90dd597fb3SArd Biesheuvel 				int rounds, int bytes, u8 const iv[]);
91dd597fb3SArd Biesheuvel 
92557ecb45SArd Biesheuvel asmlinkage void aes_ctr_encrypt(u8 out[], u8 const in[], u32 const rk[],
938daa399eSArd Biesheuvel 				int rounds, int bytes, u8 ctr[]);
9449788fe2SArd Biesheuvel 
9523a251ccSNathan Huckleberry asmlinkage void aes_xctr_encrypt(u8 out[], u8 const in[], u32 const rk[],
9623a251ccSNathan Huckleberry 				 int rounds, int bytes, u8 ctr[], int byte_ctr);
9723a251ccSNathan Huckleberry 
98557ecb45SArd Biesheuvel asmlinkage void aes_xts_encrypt(u8 out[], u8 const in[], u32 const rk1[],
997cceca8bSArd Biesheuvel 				int rounds, int bytes, u32 const rk2[], u8 iv[],
10049788fe2SArd Biesheuvel 				int first);
101557ecb45SArd Biesheuvel asmlinkage void aes_xts_decrypt(u8 out[], u8 const in[], u32 const rk1[],
1027cceca8bSArd Biesheuvel 				int rounds, int bytes, u32 const rk2[], u8 iv[],
10349788fe2SArd Biesheuvel 				int first);
10449788fe2SArd Biesheuvel 
105735177caSArd Biesheuvel asmlinkage void aes_essiv_cbc_encrypt(u8 out[], u8 const in[], u32 const rk1[],
106735177caSArd Biesheuvel 				      int rounds, int blocks, u8 iv[],
107735177caSArd Biesheuvel 				      u32 const rk2[]);
108735177caSArd Biesheuvel asmlinkage void aes_essiv_cbc_decrypt(u8 out[], u8 const in[], u32 const rk1[],
109735177caSArd Biesheuvel 				      int rounds, int blocks, u8 iv[],
110735177caSArd Biesheuvel 				      u32 const rk2[]);
111735177caSArd Biesheuvel 
112f0070f4aSArd Biesheuvel asmlinkage int aes_mac_update(u8 const in[], u32 const rk[], int rounds,
1134860620dSArd Biesheuvel 			      int blocks, u8 dg[], int enc_before,
1144860620dSArd Biesheuvel 			      int enc_after);
1154860620dSArd Biesheuvel 
11649788fe2SArd Biesheuvel struct crypto_aes_xts_ctx {
11749788fe2SArd Biesheuvel 	struct crypto_aes_ctx key1;
11849788fe2SArd Biesheuvel 	struct crypto_aes_ctx __aligned(8) key2;
11949788fe2SArd Biesheuvel };
12049788fe2SArd Biesheuvel 
121735177caSArd Biesheuvel struct crypto_aes_essiv_cbc_ctx {
122735177caSArd Biesheuvel 	struct crypto_aes_ctx key1;
123735177caSArd Biesheuvel 	struct crypto_aes_ctx __aligned(8) key2;
124735177caSArd Biesheuvel 	struct crypto_shash *hash;
125735177caSArd Biesheuvel };
126735177caSArd Biesheuvel 
1274860620dSArd Biesheuvel struct mac_tfm_ctx {
1284860620dSArd Biesheuvel 	struct crypto_aes_ctx key;
1294860620dSArd Biesheuvel 	u8 __aligned(8) consts[];
1304860620dSArd Biesheuvel };
1314860620dSArd Biesheuvel 
1324860620dSArd Biesheuvel struct mac_desc_ctx {
1334860620dSArd Biesheuvel 	unsigned int len;
1344860620dSArd Biesheuvel 	u8 dg[AES_BLOCK_SIZE];
1354860620dSArd Biesheuvel };
1364860620dSArd Biesheuvel 
skcipher_aes_setkey(struct crypto_skcipher * tfm,const u8 * in_key,unsigned int key_len)137d0ed0db1SHerbert Xu static int skcipher_aes_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
13849788fe2SArd Biesheuvel 			       unsigned int key_len)
13949788fe2SArd Biesheuvel {
140c1844729SArd Biesheuvel 	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
141c1844729SArd Biesheuvel 
142674f368aSEric Biggers 	return aes_expandkey(ctx, in_key, key_len);
143d0ed0db1SHerbert Xu }
144d0ed0db1SHerbert Xu 
xts_set_key(struct crypto_skcipher * tfm,const u8 * in_key,unsigned int key_len)14569b6f2e8SArd Biesheuvel static int __maybe_unused xts_set_key(struct crypto_skcipher *tfm,
14669b6f2e8SArd Biesheuvel 				      const u8 *in_key, unsigned int key_len)
147d0ed0db1SHerbert Xu {
148d0ed0db1SHerbert Xu 	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
14949788fe2SArd Biesheuvel 	int ret;
15049788fe2SArd Biesheuvel 
151d0ed0db1SHerbert Xu 	ret = xts_verify_key(tfm, in_key, key_len);
15228856a9eSStephan Mueller 	if (ret)
15328856a9eSStephan Mueller 		return ret;
15428856a9eSStephan Mueller 
15512ac3efeSArd Biesheuvel 	ret = aes_expandkey(&ctx->key1, in_key, key_len / 2);
15649788fe2SArd Biesheuvel 	if (!ret)
15712ac3efeSArd Biesheuvel 		ret = aes_expandkey(&ctx->key2, &in_key[key_len / 2],
15849788fe2SArd Biesheuvel 				    key_len / 2);
159674f368aSEric Biggers 	return ret;
16049788fe2SArd Biesheuvel }
16149788fe2SArd Biesheuvel 
essiv_cbc_set_key(struct crypto_skcipher * tfm,const u8 * in_key,unsigned int key_len)16269b6f2e8SArd Biesheuvel static int __maybe_unused essiv_cbc_set_key(struct crypto_skcipher *tfm,
16369b6f2e8SArd Biesheuvel 					    const u8 *in_key,
164735177caSArd Biesheuvel 					    unsigned int key_len)
165735177caSArd Biesheuvel {
166735177caSArd Biesheuvel 	struct crypto_aes_essiv_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
167735177caSArd Biesheuvel 	u8 digest[SHA256_DIGEST_SIZE];
168735177caSArd Biesheuvel 	int ret;
169735177caSArd Biesheuvel 
170735177caSArd Biesheuvel 	ret = aes_expandkey(&ctx->key1, in_key, key_len);
171735177caSArd Biesheuvel 	if (ret)
172674f368aSEric Biggers 		return ret;
173735177caSArd Biesheuvel 
174a221b33bSEric Biggers 	crypto_shash_tfm_digest(ctx->hash, in_key, key_len, digest);
175735177caSArd Biesheuvel 
176674f368aSEric Biggers 	return aes_expandkey(&ctx->key2, digest, sizeof(digest));
177735177caSArd Biesheuvel }
178735177caSArd Biesheuvel 
ecb_encrypt(struct skcipher_request * req)17969b6f2e8SArd Biesheuvel static int __maybe_unused ecb_encrypt(struct skcipher_request *req)
18049788fe2SArd Biesheuvel {
181d0ed0db1SHerbert Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
182d0ed0db1SHerbert Xu 	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
18368338174SArd Biesheuvel 	int err, rounds = 6 + ctx->key_length / 4;
184d0ed0db1SHerbert Xu 	struct skcipher_walk walk;
18549788fe2SArd Biesheuvel 	unsigned int blocks;
18649788fe2SArd Biesheuvel 
18768338174SArd Biesheuvel 	err = skcipher_walk_virt(&walk, req, false);
18849788fe2SArd Biesheuvel 
18968338174SArd Biesheuvel 	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
19049788fe2SArd Biesheuvel 		kernel_neon_begin();
19149788fe2SArd Biesheuvel 		aes_ecb_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
192557ecb45SArd Biesheuvel 				ctx->key_enc, rounds, blocks);
19368338174SArd Biesheuvel 		kernel_neon_end();
194d0ed0db1SHerbert Xu 		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
19549788fe2SArd Biesheuvel 	}
19649788fe2SArd Biesheuvel 	return err;
19749788fe2SArd Biesheuvel }
19849788fe2SArd Biesheuvel 
ecb_decrypt(struct skcipher_request * req)19969b6f2e8SArd Biesheuvel static int __maybe_unused ecb_decrypt(struct skcipher_request *req)
20049788fe2SArd Biesheuvel {
201d0ed0db1SHerbert Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
202d0ed0db1SHerbert Xu 	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
20368338174SArd Biesheuvel 	int err, rounds = 6 + ctx->key_length / 4;
204d0ed0db1SHerbert Xu 	struct skcipher_walk walk;
20549788fe2SArd Biesheuvel 	unsigned int blocks;
20649788fe2SArd Biesheuvel 
20768338174SArd Biesheuvel 	err = skcipher_walk_virt(&walk, req, false);
20849788fe2SArd Biesheuvel 
20968338174SArd Biesheuvel 	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
21049788fe2SArd Biesheuvel 		kernel_neon_begin();
21149788fe2SArd Biesheuvel 		aes_ecb_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
212557ecb45SArd Biesheuvel 				ctx->key_dec, rounds, blocks);
21368338174SArd Biesheuvel 		kernel_neon_end();
214d0ed0db1SHerbert Xu 		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
21549788fe2SArd Biesheuvel 	}
21649788fe2SArd Biesheuvel 	return err;
21749788fe2SArd Biesheuvel }
21849788fe2SArd Biesheuvel 
cbc_encrypt_walk(struct skcipher_request * req,struct skcipher_walk * walk)21965d0042bSArd Biesheuvel static int cbc_encrypt_walk(struct skcipher_request *req,
22065d0042bSArd Biesheuvel 			    struct skcipher_walk *walk)
22149788fe2SArd Biesheuvel {
222d0ed0db1SHerbert Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
223d0ed0db1SHerbert Xu 	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
22465d0042bSArd Biesheuvel 	int err = 0, rounds = 6 + ctx->key_length / 4;
22549788fe2SArd Biesheuvel 	unsigned int blocks;
22649788fe2SArd Biesheuvel 
22765d0042bSArd Biesheuvel 	while ((blocks = (walk->nbytes / AES_BLOCK_SIZE))) {
22849788fe2SArd Biesheuvel 		kernel_neon_begin();
22965d0042bSArd Biesheuvel 		aes_cbc_encrypt(walk->dst.virt.addr, walk->src.virt.addr,
23065d0042bSArd Biesheuvel 				ctx->key_enc, rounds, blocks, walk->iv);
23168338174SArd Biesheuvel 		kernel_neon_end();
23265d0042bSArd Biesheuvel 		err = skcipher_walk_done(walk, walk->nbytes % AES_BLOCK_SIZE);
23365d0042bSArd Biesheuvel 	}
23465d0042bSArd Biesheuvel 	return err;
23565d0042bSArd Biesheuvel }
23665d0042bSArd Biesheuvel 
cbc_encrypt(struct skcipher_request * req)23769b6f2e8SArd Biesheuvel static int __maybe_unused cbc_encrypt(struct skcipher_request *req)
23865d0042bSArd Biesheuvel {
23965d0042bSArd Biesheuvel 	struct skcipher_walk walk;
24065d0042bSArd Biesheuvel 	int err;
24165d0042bSArd Biesheuvel 
24265d0042bSArd Biesheuvel 	err = skcipher_walk_virt(&walk, req, false);
24365d0042bSArd Biesheuvel 	if (err)
24465d0042bSArd Biesheuvel 		return err;
24565d0042bSArd Biesheuvel 	return cbc_encrypt_walk(req, &walk);
24665d0042bSArd Biesheuvel }
24765d0042bSArd Biesheuvel 
cbc_decrypt_walk(struct skcipher_request * req,struct skcipher_walk * walk)24865d0042bSArd Biesheuvel static int cbc_decrypt_walk(struct skcipher_request *req,
24965d0042bSArd Biesheuvel 			    struct skcipher_walk *walk)
25065d0042bSArd Biesheuvel {
25165d0042bSArd Biesheuvel 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
25265d0042bSArd Biesheuvel 	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
25365d0042bSArd Biesheuvel 	int err = 0, rounds = 6 + ctx->key_length / 4;
25465d0042bSArd Biesheuvel 	unsigned int blocks;
25565d0042bSArd Biesheuvel 
25665d0042bSArd Biesheuvel 	while ((blocks = (walk->nbytes / AES_BLOCK_SIZE))) {
25765d0042bSArd Biesheuvel 		kernel_neon_begin();
25865d0042bSArd Biesheuvel 		aes_cbc_decrypt(walk->dst.virt.addr, walk->src.virt.addr,
25965d0042bSArd Biesheuvel 				ctx->key_dec, rounds, blocks, walk->iv);
26065d0042bSArd Biesheuvel 		kernel_neon_end();
26165d0042bSArd Biesheuvel 		err = skcipher_walk_done(walk, walk->nbytes % AES_BLOCK_SIZE);
26249788fe2SArd Biesheuvel 	}
26349788fe2SArd Biesheuvel 	return err;
26449788fe2SArd Biesheuvel }
26549788fe2SArd Biesheuvel 
cbc_decrypt(struct skcipher_request * req)26669b6f2e8SArd Biesheuvel static int __maybe_unused cbc_decrypt(struct skcipher_request *req)
26749788fe2SArd Biesheuvel {
268d0ed0db1SHerbert Xu 	struct skcipher_walk walk;
26965d0042bSArd Biesheuvel 	int err;
27049788fe2SArd Biesheuvel 
27168338174SArd Biesheuvel 	err = skcipher_walk_virt(&walk, req, false);
27265d0042bSArd Biesheuvel 	if (err)
27349788fe2SArd Biesheuvel 		return err;
27465d0042bSArd Biesheuvel 	return cbc_decrypt_walk(req, &walk);
27549788fe2SArd Biesheuvel }
27649788fe2SArd Biesheuvel 
cts_cbc_encrypt(struct skcipher_request * req)277dd597fb3SArd Biesheuvel static int cts_cbc_encrypt(struct skcipher_request *req)
278dd597fb3SArd Biesheuvel {
279dd597fb3SArd Biesheuvel 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
280dd597fb3SArd Biesheuvel 	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
281dd597fb3SArd Biesheuvel 	int err, rounds = 6 + ctx->key_length / 4;
282dd597fb3SArd Biesheuvel 	int cbc_blocks = DIV_ROUND_UP(req->cryptlen, AES_BLOCK_SIZE) - 2;
283dd597fb3SArd Biesheuvel 	struct scatterlist *src = req->src, *dst = req->dst;
2847c9d65c4SArd Biesheuvel 	struct scatterlist sg_src[2], sg_dst[2];
2857c9d65c4SArd Biesheuvel 	struct skcipher_request subreq;
286dd597fb3SArd Biesheuvel 	struct skcipher_walk walk;
287dd597fb3SArd Biesheuvel 
2887c9d65c4SArd Biesheuvel 	skcipher_request_set_tfm(&subreq, tfm);
2897c9d65c4SArd Biesheuvel 	skcipher_request_set_callback(&subreq, skcipher_request_flags(req),
2907c9d65c4SArd Biesheuvel 				      NULL, NULL);
291dd597fb3SArd Biesheuvel 
2927ff9036aSEric Biggers 	if (req->cryptlen <= AES_BLOCK_SIZE) {
2937ff9036aSEric Biggers 		if (req->cryptlen < AES_BLOCK_SIZE)
2947ff9036aSEric Biggers 			return -EINVAL;
295dd597fb3SArd Biesheuvel 		cbc_blocks = 1;
2967ff9036aSEric Biggers 	}
297dd597fb3SArd Biesheuvel 
298dd597fb3SArd Biesheuvel 	if (cbc_blocks > 0) {
2997c9d65c4SArd Biesheuvel 		skcipher_request_set_crypt(&subreq, req->src, req->dst,
300dd597fb3SArd Biesheuvel 					   cbc_blocks * AES_BLOCK_SIZE,
301dd597fb3SArd Biesheuvel 					   req->iv);
302dd597fb3SArd Biesheuvel 
3037c9d65c4SArd Biesheuvel 		err = skcipher_walk_virt(&walk, &subreq, false) ?:
3047c9d65c4SArd Biesheuvel 		      cbc_encrypt_walk(&subreq, &walk);
305dd597fb3SArd Biesheuvel 		if (err)
306dd597fb3SArd Biesheuvel 			return err;
307dd597fb3SArd Biesheuvel 
308dd597fb3SArd Biesheuvel 		if (req->cryptlen == AES_BLOCK_SIZE)
309dd597fb3SArd Biesheuvel 			return 0;
310dd597fb3SArd Biesheuvel 
3117c9d65c4SArd Biesheuvel 		dst = src = scatterwalk_ffwd(sg_src, req->src, subreq.cryptlen);
312dd597fb3SArd Biesheuvel 		if (req->dst != req->src)
3137c9d65c4SArd Biesheuvel 			dst = scatterwalk_ffwd(sg_dst, req->dst,
3147c9d65c4SArd Biesheuvel 					       subreq.cryptlen);
315dd597fb3SArd Biesheuvel 	}
316dd597fb3SArd Biesheuvel 
317dd597fb3SArd Biesheuvel 	/* handle ciphertext stealing */
3187c9d65c4SArd Biesheuvel 	skcipher_request_set_crypt(&subreq, src, dst,
319dd597fb3SArd Biesheuvel 				   req->cryptlen - cbc_blocks * AES_BLOCK_SIZE,
320dd597fb3SArd Biesheuvel 				   req->iv);
321dd597fb3SArd Biesheuvel 
3227c9d65c4SArd Biesheuvel 	err = skcipher_walk_virt(&walk, &subreq, false);
323dd597fb3SArd Biesheuvel 	if (err)
324dd597fb3SArd Biesheuvel 		return err;
325dd597fb3SArd Biesheuvel 
326dd597fb3SArd Biesheuvel 	kernel_neon_begin();
327dd597fb3SArd Biesheuvel 	aes_cbc_cts_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
328dd597fb3SArd Biesheuvel 			    ctx->key_enc, rounds, walk.nbytes, walk.iv);
329dd597fb3SArd Biesheuvel 	kernel_neon_end();
330dd597fb3SArd Biesheuvel 
331dd597fb3SArd Biesheuvel 	return skcipher_walk_done(&walk, 0);
332dd597fb3SArd Biesheuvel }
333dd597fb3SArd Biesheuvel 
cts_cbc_decrypt(struct skcipher_request * req)334dd597fb3SArd Biesheuvel static int cts_cbc_decrypt(struct skcipher_request *req)
335dd597fb3SArd Biesheuvel {
336dd597fb3SArd Biesheuvel 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
337dd597fb3SArd Biesheuvel 	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
338dd597fb3SArd Biesheuvel 	int err, rounds = 6 + ctx->key_length / 4;
339dd597fb3SArd Biesheuvel 	int cbc_blocks = DIV_ROUND_UP(req->cryptlen, AES_BLOCK_SIZE) - 2;
340dd597fb3SArd Biesheuvel 	struct scatterlist *src = req->src, *dst = req->dst;
3417c9d65c4SArd Biesheuvel 	struct scatterlist sg_src[2], sg_dst[2];
3427c9d65c4SArd Biesheuvel 	struct skcipher_request subreq;
343dd597fb3SArd Biesheuvel 	struct skcipher_walk walk;
344dd597fb3SArd Biesheuvel 
3457c9d65c4SArd Biesheuvel 	skcipher_request_set_tfm(&subreq, tfm);
3467c9d65c4SArd Biesheuvel 	skcipher_request_set_callback(&subreq, skcipher_request_flags(req),
3477c9d65c4SArd Biesheuvel 				      NULL, NULL);
348dd597fb3SArd Biesheuvel 
3497ff9036aSEric Biggers 	if (req->cryptlen <= AES_BLOCK_SIZE) {
3507ff9036aSEric Biggers 		if (req->cryptlen < AES_BLOCK_SIZE)
3517ff9036aSEric Biggers 			return -EINVAL;
352dd597fb3SArd Biesheuvel 		cbc_blocks = 1;
3537ff9036aSEric Biggers 	}
354dd597fb3SArd Biesheuvel 
355dd597fb3SArd Biesheuvel 	if (cbc_blocks > 0) {
3567c9d65c4SArd Biesheuvel 		skcipher_request_set_crypt(&subreq, req->src, req->dst,
357dd597fb3SArd Biesheuvel 					   cbc_blocks * AES_BLOCK_SIZE,
358dd597fb3SArd Biesheuvel 					   req->iv);
359dd597fb3SArd Biesheuvel 
3607c9d65c4SArd Biesheuvel 		err = skcipher_walk_virt(&walk, &subreq, false) ?:
3617c9d65c4SArd Biesheuvel 		      cbc_decrypt_walk(&subreq, &walk);
362dd597fb3SArd Biesheuvel 		if (err)
363dd597fb3SArd Biesheuvel 			return err;
364dd597fb3SArd Biesheuvel 
365dd597fb3SArd Biesheuvel 		if (req->cryptlen == AES_BLOCK_SIZE)
366dd597fb3SArd Biesheuvel 			return 0;
367dd597fb3SArd Biesheuvel 
3687c9d65c4SArd Biesheuvel 		dst = src = scatterwalk_ffwd(sg_src, req->src, subreq.cryptlen);
369dd597fb3SArd Biesheuvel 		if (req->dst != req->src)
3707c9d65c4SArd Biesheuvel 			dst = scatterwalk_ffwd(sg_dst, req->dst,
3717c9d65c4SArd Biesheuvel 					       subreq.cryptlen);
372dd597fb3SArd Biesheuvel 	}
373dd597fb3SArd Biesheuvel 
374dd597fb3SArd Biesheuvel 	/* handle ciphertext stealing */
3757c9d65c4SArd Biesheuvel 	skcipher_request_set_crypt(&subreq, src, dst,
376dd597fb3SArd Biesheuvel 				   req->cryptlen - cbc_blocks * AES_BLOCK_SIZE,
377dd597fb3SArd Biesheuvel 				   req->iv);
378dd597fb3SArd Biesheuvel 
3797c9d65c4SArd Biesheuvel 	err = skcipher_walk_virt(&walk, &subreq, false);
380dd597fb3SArd Biesheuvel 	if (err)
381dd597fb3SArd Biesheuvel 		return err;
382dd597fb3SArd Biesheuvel 
383dd597fb3SArd Biesheuvel 	kernel_neon_begin();
384dd597fb3SArd Biesheuvel 	aes_cbc_cts_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
385dd597fb3SArd Biesheuvel 			    ctx->key_dec, rounds, walk.nbytes, walk.iv);
386dd597fb3SArd Biesheuvel 	kernel_neon_end();
387dd597fb3SArd Biesheuvel 
388dd597fb3SArd Biesheuvel 	return skcipher_walk_done(&walk, 0);
389dd597fb3SArd Biesheuvel }
390dd597fb3SArd Biesheuvel 
essiv_cbc_init_tfm(struct crypto_skcipher * tfm)39169b6f2e8SArd Biesheuvel static int __maybe_unused essiv_cbc_init_tfm(struct crypto_skcipher *tfm)
392735177caSArd Biesheuvel {
393735177caSArd Biesheuvel 	struct crypto_aes_essiv_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
394735177caSArd Biesheuvel 
395735177caSArd Biesheuvel 	ctx->hash = crypto_alloc_shash("sha256", 0, 0);
396735177caSArd Biesheuvel 
3977b865ec1Szhong jiang 	return PTR_ERR_OR_ZERO(ctx->hash);
398735177caSArd Biesheuvel }
399735177caSArd Biesheuvel 
essiv_cbc_exit_tfm(struct crypto_skcipher * tfm)40069b6f2e8SArd Biesheuvel static void __maybe_unused essiv_cbc_exit_tfm(struct crypto_skcipher *tfm)
401735177caSArd Biesheuvel {
402735177caSArd Biesheuvel 	struct crypto_aes_essiv_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
403735177caSArd Biesheuvel 
404735177caSArd Biesheuvel 	crypto_free_shash(ctx->hash);
405735177caSArd Biesheuvel }
406735177caSArd Biesheuvel 
essiv_cbc_encrypt(struct skcipher_request * req)40769b6f2e8SArd Biesheuvel static int __maybe_unused essiv_cbc_encrypt(struct skcipher_request *req)
408735177caSArd Biesheuvel {
409735177caSArd Biesheuvel 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
410735177caSArd Biesheuvel 	struct crypto_aes_essiv_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
411735177caSArd Biesheuvel 	int err, rounds = 6 + ctx->key1.key_length / 4;
412735177caSArd Biesheuvel 	struct skcipher_walk walk;
413735177caSArd Biesheuvel 	unsigned int blocks;
414735177caSArd Biesheuvel 
415735177caSArd Biesheuvel 	err = skcipher_walk_virt(&walk, req, false);
416735177caSArd Biesheuvel 
417735177caSArd Biesheuvel 	blocks = walk.nbytes / AES_BLOCK_SIZE;
418735177caSArd Biesheuvel 	if (blocks) {
419735177caSArd Biesheuvel 		kernel_neon_begin();
420735177caSArd Biesheuvel 		aes_essiv_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
421735177caSArd Biesheuvel 				      ctx->key1.key_enc, rounds, blocks,
422735177caSArd Biesheuvel 				      req->iv, ctx->key2.key_enc);
423735177caSArd Biesheuvel 		kernel_neon_end();
424735177caSArd Biesheuvel 		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
425735177caSArd Biesheuvel 	}
426735177caSArd Biesheuvel 	return err ?: cbc_encrypt_walk(req, &walk);
427735177caSArd Biesheuvel }
428735177caSArd Biesheuvel 
essiv_cbc_decrypt(struct skcipher_request * req)42969b6f2e8SArd Biesheuvel static int __maybe_unused essiv_cbc_decrypt(struct skcipher_request *req)
430735177caSArd Biesheuvel {
431735177caSArd Biesheuvel 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
432735177caSArd Biesheuvel 	struct crypto_aes_essiv_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
433735177caSArd Biesheuvel 	int err, rounds = 6 + ctx->key1.key_length / 4;
434735177caSArd Biesheuvel 	struct skcipher_walk walk;
435735177caSArd Biesheuvel 	unsigned int blocks;
436735177caSArd Biesheuvel 
437735177caSArd Biesheuvel 	err = skcipher_walk_virt(&walk, req, false);
438735177caSArd Biesheuvel 
439735177caSArd Biesheuvel 	blocks = walk.nbytes / AES_BLOCK_SIZE;
440735177caSArd Biesheuvel 	if (blocks) {
441735177caSArd Biesheuvel 		kernel_neon_begin();
442735177caSArd Biesheuvel 		aes_essiv_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
443735177caSArd Biesheuvel 				      ctx->key1.key_dec, rounds, blocks,
444735177caSArd Biesheuvel 				      req->iv, ctx->key2.key_enc);
445735177caSArd Biesheuvel 		kernel_neon_end();
446735177caSArd Biesheuvel 		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
447735177caSArd Biesheuvel 	}
448735177caSArd Biesheuvel 	return err ?: cbc_decrypt_walk(req, &walk);
449735177caSArd Biesheuvel }
450735177caSArd Biesheuvel 
xctr_encrypt(struct skcipher_request * req)45123a251ccSNathan Huckleberry static int __maybe_unused xctr_encrypt(struct skcipher_request *req)
45223a251ccSNathan Huckleberry {
45323a251ccSNathan Huckleberry 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
45423a251ccSNathan Huckleberry 	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
45523a251ccSNathan Huckleberry 	int err, rounds = 6 + ctx->key_length / 4;
45623a251ccSNathan Huckleberry 	struct skcipher_walk walk;
45723a251ccSNathan Huckleberry 	unsigned int byte_ctr = 0;
45823a251ccSNathan Huckleberry 
45923a251ccSNathan Huckleberry 	err = skcipher_walk_virt(&walk, req, false);
46023a251ccSNathan Huckleberry 
46123a251ccSNathan Huckleberry 	while (walk.nbytes > 0) {
46223a251ccSNathan Huckleberry 		const u8 *src = walk.src.virt.addr;
46323a251ccSNathan Huckleberry 		unsigned int nbytes = walk.nbytes;
46423a251ccSNathan Huckleberry 		u8 *dst = walk.dst.virt.addr;
46523a251ccSNathan Huckleberry 		u8 buf[AES_BLOCK_SIZE];
46623a251ccSNathan Huckleberry 
467*c0eb7591SNathan Huckleberry 		/*
468*c0eb7591SNathan Huckleberry 		 * If given less than 16 bytes, we must copy the partial block
469*c0eb7591SNathan Huckleberry 		 * into a temporary buffer of 16 bytes to avoid out of bounds
470*c0eb7591SNathan Huckleberry 		 * reads and writes.  Furthermore, this code is somewhat unusual
471*c0eb7591SNathan Huckleberry 		 * in that it expects the end of the data to be at the end of
472*c0eb7591SNathan Huckleberry 		 * the temporary buffer, rather than the start of the data at
473*c0eb7591SNathan Huckleberry 		 * the start of the temporary buffer.
474*c0eb7591SNathan Huckleberry 		 */
47523a251ccSNathan Huckleberry 		if (unlikely(nbytes < AES_BLOCK_SIZE))
47623a251ccSNathan Huckleberry 			src = dst = memcpy(buf + sizeof(buf) - nbytes,
47723a251ccSNathan Huckleberry 					   src, nbytes);
47823a251ccSNathan Huckleberry 		else if (nbytes < walk.total)
47923a251ccSNathan Huckleberry 			nbytes &= ~(AES_BLOCK_SIZE - 1);
48023a251ccSNathan Huckleberry 
48123a251ccSNathan Huckleberry 		kernel_neon_begin();
48223a251ccSNathan Huckleberry 		aes_xctr_encrypt(dst, src, ctx->key_enc, rounds, nbytes,
48323a251ccSNathan Huckleberry 						 walk.iv, byte_ctr);
48423a251ccSNathan Huckleberry 		kernel_neon_end();
48523a251ccSNathan Huckleberry 
48623a251ccSNathan Huckleberry 		if (unlikely(nbytes < AES_BLOCK_SIZE))
48723a251ccSNathan Huckleberry 			memcpy(walk.dst.virt.addr,
48823a251ccSNathan Huckleberry 			       buf + sizeof(buf) - nbytes, nbytes);
48923a251ccSNathan Huckleberry 		byte_ctr += nbytes;
49023a251ccSNathan Huckleberry 
49123a251ccSNathan Huckleberry 		err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
49223a251ccSNathan Huckleberry 	}
49323a251ccSNathan Huckleberry 
49423a251ccSNathan Huckleberry 	return err;
49523a251ccSNathan Huckleberry }
49623a251ccSNathan Huckleberry 
ctr_encrypt(struct skcipher_request * req)497676e5081SArd Biesheuvel static int __maybe_unused ctr_encrypt(struct skcipher_request *req)
49849788fe2SArd Biesheuvel {
499d0ed0db1SHerbert Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
500d0ed0db1SHerbert Xu 	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
50168338174SArd Biesheuvel 	int err, rounds = 6 + ctx->key_length / 4;
502d0ed0db1SHerbert Xu 	struct skcipher_walk walk;
50349788fe2SArd Biesheuvel 
50468338174SArd Biesheuvel 	err = skcipher_walk_virt(&walk, req, false);
50549788fe2SArd Biesheuvel 
5065318d3dbSArd Biesheuvel 	while (walk.nbytes > 0) {
5075318d3dbSArd Biesheuvel 		const u8 *src = walk.src.virt.addr;
508d0ed0db1SHerbert Xu 		unsigned int nbytes = walk.nbytes;
5095318d3dbSArd Biesheuvel 		u8 *dst = walk.dst.virt.addr;
5105318d3dbSArd Biesheuvel 		u8 buf[AES_BLOCK_SIZE];
51149788fe2SArd Biesheuvel 
512*c0eb7591SNathan Huckleberry 		/*
513*c0eb7591SNathan Huckleberry 		 * If given less than 16 bytes, we must copy the partial block
514*c0eb7591SNathan Huckleberry 		 * into a temporary buffer of 16 bytes to avoid out of bounds
515*c0eb7591SNathan Huckleberry 		 * reads and writes.  Furthermore, this code is somewhat unusual
516*c0eb7591SNathan Huckleberry 		 * in that it expects the end of the data to be at the end of
517*c0eb7591SNathan Huckleberry 		 * the temporary buffer, rather than the start of the data at
518*c0eb7591SNathan Huckleberry 		 * the start of the temporary buffer.
519*c0eb7591SNathan Huckleberry 		 */
5205318d3dbSArd Biesheuvel 		if (unlikely(nbytes < AES_BLOCK_SIZE))
5218daa399eSArd Biesheuvel 			src = dst = memcpy(buf + sizeof(buf) - nbytes,
5228daa399eSArd Biesheuvel 					   src, nbytes);
5235318d3dbSArd Biesheuvel 		else if (nbytes < walk.total)
5245318d3dbSArd Biesheuvel 			nbytes &= ~(AES_BLOCK_SIZE - 1);
52549788fe2SArd Biesheuvel 
52668338174SArd Biesheuvel 		kernel_neon_begin();
5275318d3dbSArd Biesheuvel 		aes_ctr_encrypt(dst, src, ctx->key_enc, rounds, nbytes,
5288daa399eSArd Biesheuvel 				walk.iv);
52968338174SArd Biesheuvel 		kernel_neon_end();
5305318d3dbSArd Biesheuvel 
5318daa399eSArd Biesheuvel 		if (unlikely(nbytes < AES_BLOCK_SIZE))
5328daa399eSArd Biesheuvel 			memcpy(walk.dst.virt.addr,
5338daa399eSArd Biesheuvel 			       buf + sizeof(buf) - nbytes, nbytes);
5345318d3dbSArd Biesheuvel 
5355318d3dbSArd Biesheuvel 		err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
53649788fe2SArd Biesheuvel 	}
53749788fe2SArd Biesheuvel 
53849788fe2SArd Biesheuvel 	return err;
53949788fe2SArd Biesheuvel }
54049788fe2SArd Biesheuvel 
xts_encrypt(struct skcipher_request * req)54169b6f2e8SArd Biesheuvel static int __maybe_unused xts_encrypt(struct skcipher_request *req)
54249788fe2SArd Biesheuvel {
543d0ed0db1SHerbert Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
544d0ed0db1SHerbert Xu 	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
54549788fe2SArd Biesheuvel 	int err, first, rounds = 6 + ctx->key1.key_length / 4;
5467cceca8bSArd Biesheuvel 	int tail = req->cryptlen % AES_BLOCK_SIZE;
5477cceca8bSArd Biesheuvel 	struct scatterlist sg_src[2], sg_dst[2];
5487cceca8bSArd Biesheuvel 	struct skcipher_request subreq;
5497cceca8bSArd Biesheuvel 	struct scatterlist *src, *dst;
550d0ed0db1SHerbert Xu 	struct skcipher_walk walk;
5517cceca8bSArd Biesheuvel 
5527cceca8bSArd Biesheuvel 	if (req->cryptlen < AES_BLOCK_SIZE)
5537cceca8bSArd Biesheuvel 		return -EINVAL;
55449788fe2SArd Biesheuvel 
55568338174SArd Biesheuvel 	err = skcipher_walk_virt(&walk, req, false);
55649788fe2SArd Biesheuvel 
5577cceca8bSArd Biesheuvel 	if (unlikely(tail > 0 && walk.nbytes < walk.total)) {
5587cceca8bSArd Biesheuvel 		int xts_blocks = DIV_ROUND_UP(req->cryptlen,
5597cceca8bSArd Biesheuvel 					      AES_BLOCK_SIZE) - 2;
5607cceca8bSArd Biesheuvel 
5617cceca8bSArd Biesheuvel 		skcipher_walk_abort(&walk);
5627cceca8bSArd Biesheuvel 
5637cceca8bSArd Biesheuvel 		skcipher_request_set_tfm(&subreq, tfm);
5647cceca8bSArd Biesheuvel 		skcipher_request_set_callback(&subreq,
5657cceca8bSArd Biesheuvel 					      skcipher_request_flags(req),
5667cceca8bSArd Biesheuvel 					      NULL, NULL);
5677cceca8bSArd Biesheuvel 		skcipher_request_set_crypt(&subreq, req->src, req->dst,
5687cceca8bSArd Biesheuvel 					   xts_blocks * AES_BLOCK_SIZE,
5697cceca8bSArd Biesheuvel 					   req->iv);
5707cceca8bSArd Biesheuvel 		req = &subreq;
5717cceca8bSArd Biesheuvel 		err = skcipher_walk_virt(&walk, req, false);
5727cceca8bSArd Biesheuvel 	} else {
5737cceca8bSArd Biesheuvel 		tail = 0;
57449788fe2SArd Biesheuvel 	}
57549788fe2SArd Biesheuvel 
5767cceca8bSArd Biesheuvel 	for (first = 1; walk.nbytes >= AES_BLOCK_SIZE; first = 0) {
5777cceca8bSArd Biesheuvel 		int nbytes = walk.nbytes;
5787cceca8bSArd Biesheuvel 
5797cceca8bSArd Biesheuvel 		if (walk.nbytes < walk.total)
5807cceca8bSArd Biesheuvel 			nbytes &= ~(AES_BLOCK_SIZE - 1);
5817cceca8bSArd Biesheuvel 
5827cceca8bSArd Biesheuvel 		kernel_neon_begin();
5837cceca8bSArd Biesheuvel 		aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
5847cceca8bSArd Biesheuvel 				ctx->key1.key_enc, rounds, nbytes,
5857cceca8bSArd Biesheuvel 				ctx->key2.key_enc, walk.iv, first);
5867cceca8bSArd Biesheuvel 		kernel_neon_end();
5877cceca8bSArd Biesheuvel 		err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
5887cceca8bSArd Biesheuvel 	}
5897cceca8bSArd Biesheuvel 
5907cceca8bSArd Biesheuvel 	if (err || likely(!tail))
59149788fe2SArd Biesheuvel 		return err;
5927cceca8bSArd Biesheuvel 
5937cceca8bSArd Biesheuvel 	dst = src = scatterwalk_ffwd(sg_src, req->src, req->cryptlen);
5947cceca8bSArd Biesheuvel 	if (req->dst != req->src)
5957cceca8bSArd Biesheuvel 		dst = scatterwalk_ffwd(sg_dst, req->dst, req->cryptlen);
5967cceca8bSArd Biesheuvel 
5977cceca8bSArd Biesheuvel 	skcipher_request_set_crypt(req, src, dst, AES_BLOCK_SIZE + tail,
5987cceca8bSArd Biesheuvel 				   req->iv);
5997cceca8bSArd Biesheuvel 
6007cceca8bSArd Biesheuvel 	err = skcipher_walk_virt(&walk, &subreq, false);
6017cceca8bSArd Biesheuvel 	if (err)
6027cceca8bSArd Biesheuvel 		return err;
6037cceca8bSArd Biesheuvel 
6047cceca8bSArd Biesheuvel 	kernel_neon_begin();
6057cceca8bSArd Biesheuvel 	aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
6067cceca8bSArd Biesheuvel 			ctx->key1.key_enc, rounds, walk.nbytes,
6077cceca8bSArd Biesheuvel 			ctx->key2.key_enc, walk.iv, first);
6087cceca8bSArd Biesheuvel 	kernel_neon_end();
6097cceca8bSArd Biesheuvel 
6107cceca8bSArd Biesheuvel 	return skcipher_walk_done(&walk, 0);
61149788fe2SArd Biesheuvel }
61249788fe2SArd Biesheuvel 
xts_decrypt(struct skcipher_request * req)61369b6f2e8SArd Biesheuvel static int __maybe_unused xts_decrypt(struct skcipher_request *req)
61449788fe2SArd Biesheuvel {
615d0ed0db1SHerbert Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
616d0ed0db1SHerbert Xu 	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
61749788fe2SArd Biesheuvel 	int err, first, rounds = 6 + ctx->key1.key_length / 4;
6187cceca8bSArd Biesheuvel 	int tail = req->cryptlen % AES_BLOCK_SIZE;
6197cceca8bSArd Biesheuvel 	struct scatterlist sg_src[2], sg_dst[2];
6207cceca8bSArd Biesheuvel 	struct skcipher_request subreq;
6217cceca8bSArd Biesheuvel 	struct scatterlist *src, *dst;
622d0ed0db1SHerbert Xu 	struct skcipher_walk walk;
6237cceca8bSArd Biesheuvel 
6247cceca8bSArd Biesheuvel 	if (req->cryptlen < AES_BLOCK_SIZE)
6257cceca8bSArd Biesheuvel 		return -EINVAL;
62649788fe2SArd Biesheuvel 
62768338174SArd Biesheuvel 	err = skcipher_walk_virt(&walk, req, false);
62849788fe2SArd Biesheuvel 
6297cceca8bSArd Biesheuvel 	if (unlikely(tail > 0 && walk.nbytes < walk.total)) {
6307cceca8bSArd Biesheuvel 		int xts_blocks = DIV_ROUND_UP(req->cryptlen,
6317cceca8bSArd Biesheuvel 					      AES_BLOCK_SIZE) - 2;
6327cceca8bSArd Biesheuvel 
6337cceca8bSArd Biesheuvel 		skcipher_walk_abort(&walk);
6347cceca8bSArd Biesheuvel 
6357cceca8bSArd Biesheuvel 		skcipher_request_set_tfm(&subreq, tfm);
6367cceca8bSArd Biesheuvel 		skcipher_request_set_callback(&subreq,
6377cceca8bSArd Biesheuvel 					      skcipher_request_flags(req),
6387cceca8bSArd Biesheuvel 					      NULL, NULL);
6397cceca8bSArd Biesheuvel 		skcipher_request_set_crypt(&subreq, req->src, req->dst,
6407cceca8bSArd Biesheuvel 					   xts_blocks * AES_BLOCK_SIZE,
6417cceca8bSArd Biesheuvel 					   req->iv);
6427cceca8bSArd Biesheuvel 		req = &subreq;
6437cceca8bSArd Biesheuvel 		err = skcipher_walk_virt(&walk, req, false);
6447cceca8bSArd Biesheuvel 	} else {
6457cceca8bSArd Biesheuvel 		tail = 0;
64649788fe2SArd Biesheuvel 	}
64749788fe2SArd Biesheuvel 
6487cceca8bSArd Biesheuvel 	for (first = 1; walk.nbytes >= AES_BLOCK_SIZE; first = 0) {
6497cceca8bSArd Biesheuvel 		int nbytes = walk.nbytes;
6507cceca8bSArd Biesheuvel 
6517cceca8bSArd Biesheuvel 		if (walk.nbytes < walk.total)
6527cceca8bSArd Biesheuvel 			nbytes &= ~(AES_BLOCK_SIZE - 1);
6537cceca8bSArd Biesheuvel 
6547cceca8bSArd Biesheuvel 		kernel_neon_begin();
6557cceca8bSArd Biesheuvel 		aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
6567cceca8bSArd Biesheuvel 				ctx->key1.key_dec, rounds, nbytes,
6577cceca8bSArd Biesheuvel 				ctx->key2.key_enc, walk.iv, first);
6587cceca8bSArd Biesheuvel 		kernel_neon_end();
6597cceca8bSArd Biesheuvel 		err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
6607cceca8bSArd Biesheuvel 	}
6617cceca8bSArd Biesheuvel 
6627cceca8bSArd Biesheuvel 	if (err || likely(!tail))
66349788fe2SArd Biesheuvel 		return err;
6647cceca8bSArd Biesheuvel 
6657cceca8bSArd Biesheuvel 	dst = src = scatterwalk_ffwd(sg_src, req->src, req->cryptlen);
6667cceca8bSArd Biesheuvel 	if (req->dst != req->src)
6677cceca8bSArd Biesheuvel 		dst = scatterwalk_ffwd(sg_dst, req->dst, req->cryptlen);
6687cceca8bSArd Biesheuvel 
6697cceca8bSArd Biesheuvel 	skcipher_request_set_crypt(req, src, dst, AES_BLOCK_SIZE + tail,
6707cceca8bSArd Biesheuvel 				   req->iv);
6717cceca8bSArd Biesheuvel 
6727cceca8bSArd Biesheuvel 	err = skcipher_walk_virt(&walk, &subreq, false);
6737cceca8bSArd Biesheuvel 	if (err)
6747cceca8bSArd Biesheuvel 		return err;
6757cceca8bSArd Biesheuvel 
6767cceca8bSArd Biesheuvel 
6777cceca8bSArd Biesheuvel 	kernel_neon_begin();
6787cceca8bSArd Biesheuvel 	aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
6797cceca8bSArd Biesheuvel 			ctx->key1.key_dec, rounds, walk.nbytes,
6807cceca8bSArd Biesheuvel 			ctx->key2.key_enc, walk.iv, first);
6817cceca8bSArd Biesheuvel 	kernel_neon_end();
6827cceca8bSArd Biesheuvel 
6837cceca8bSArd Biesheuvel 	return skcipher_walk_done(&walk, 0);
68449788fe2SArd Biesheuvel }
68549788fe2SArd Biesheuvel 
686d0ed0db1SHerbert Xu static struct skcipher_alg aes_algs[] = { {
68715deb433SArd Biesheuvel #if defined(USE_V8_CRYPTO_EXTENSIONS) || !IS_ENABLED(CONFIG_CRYPTO_AES_ARM64_BS)
688d0ed0db1SHerbert Xu 	.base = {
689676e5081SArd Biesheuvel 		.cra_name		= "ecb(aes)",
690676e5081SArd Biesheuvel 		.cra_driver_name	= "ecb-aes-" MODE,
691d0ed0db1SHerbert Xu 		.cra_priority		= PRIO,
69249788fe2SArd Biesheuvel 		.cra_blocksize		= AES_BLOCK_SIZE,
69349788fe2SArd Biesheuvel 		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
69449788fe2SArd Biesheuvel 		.cra_module		= THIS_MODULE,
695d0ed0db1SHerbert Xu 	},
69649788fe2SArd Biesheuvel 	.min_keysize	= AES_MIN_KEY_SIZE,
69749788fe2SArd Biesheuvel 	.max_keysize	= AES_MAX_KEY_SIZE,
698d0ed0db1SHerbert Xu 	.setkey		= skcipher_aes_setkey,
69949788fe2SArd Biesheuvel 	.encrypt	= ecb_encrypt,
70049788fe2SArd Biesheuvel 	.decrypt	= ecb_decrypt,
70149788fe2SArd Biesheuvel }, {
702d0ed0db1SHerbert Xu 	.base = {
703676e5081SArd Biesheuvel 		.cra_name		= "cbc(aes)",
704676e5081SArd Biesheuvel 		.cra_driver_name	= "cbc-aes-" MODE,
705d0ed0db1SHerbert Xu 		.cra_priority		= PRIO,
70649788fe2SArd Biesheuvel 		.cra_blocksize		= AES_BLOCK_SIZE,
70749788fe2SArd Biesheuvel 		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
70849788fe2SArd Biesheuvel 		.cra_module		= THIS_MODULE,
709d0ed0db1SHerbert Xu 	},
71049788fe2SArd Biesheuvel 	.min_keysize	= AES_MIN_KEY_SIZE,
71149788fe2SArd Biesheuvel 	.max_keysize	= AES_MAX_KEY_SIZE,
71249788fe2SArd Biesheuvel 	.ivsize		= AES_BLOCK_SIZE,
713d0ed0db1SHerbert Xu 	.setkey		= skcipher_aes_setkey,
71449788fe2SArd Biesheuvel 	.encrypt	= cbc_encrypt,
71549788fe2SArd Biesheuvel 	.decrypt	= cbc_decrypt,
71649788fe2SArd Biesheuvel }, {
717d0ed0db1SHerbert Xu 	.base = {
718676e5081SArd Biesheuvel 		.cra_name		= "ctr(aes)",
719676e5081SArd Biesheuvel 		.cra_driver_name	= "ctr-aes-" MODE,
720d0ed0db1SHerbert Xu 		.cra_priority		= PRIO,
72149788fe2SArd Biesheuvel 		.cra_blocksize		= 1,
72249788fe2SArd Biesheuvel 		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
72349788fe2SArd Biesheuvel 		.cra_module		= THIS_MODULE,
724d0ed0db1SHerbert Xu 	},
72549788fe2SArd Biesheuvel 	.min_keysize	= AES_MIN_KEY_SIZE,
72649788fe2SArd Biesheuvel 	.max_keysize	= AES_MAX_KEY_SIZE,
72749788fe2SArd Biesheuvel 	.ivsize		= AES_BLOCK_SIZE,
728d0ed0db1SHerbert Xu 	.chunksize	= AES_BLOCK_SIZE,
729d0ed0db1SHerbert Xu 	.setkey		= skcipher_aes_setkey,
73049788fe2SArd Biesheuvel 	.encrypt	= ctr_encrypt,
73149788fe2SArd Biesheuvel 	.decrypt	= ctr_encrypt,
73249788fe2SArd Biesheuvel }, {
733d0ed0db1SHerbert Xu 	.base = {
73423a251ccSNathan Huckleberry 		.cra_name		= "xctr(aes)",
73523a251ccSNathan Huckleberry 		.cra_driver_name	= "xctr-aes-" MODE,
73623a251ccSNathan Huckleberry 		.cra_priority		= PRIO,
73723a251ccSNathan Huckleberry 		.cra_blocksize		= 1,
73823a251ccSNathan Huckleberry 		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
73923a251ccSNathan Huckleberry 		.cra_module		= THIS_MODULE,
74023a251ccSNathan Huckleberry 	},
74123a251ccSNathan Huckleberry 	.min_keysize	= AES_MIN_KEY_SIZE,
74223a251ccSNathan Huckleberry 	.max_keysize	= AES_MAX_KEY_SIZE,
74323a251ccSNathan Huckleberry 	.ivsize		= AES_BLOCK_SIZE,
74423a251ccSNathan Huckleberry 	.chunksize	= AES_BLOCK_SIZE,
74523a251ccSNathan Huckleberry 	.setkey		= skcipher_aes_setkey,
74623a251ccSNathan Huckleberry 	.encrypt	= xctr_encrypt,
74723a251ccSNathan Huckleberry 	.decrypt	= xctr_encrypt,
74823a251ccSNathan Huckleberry }, {
74923a251ccSNathan Huckleberry 	.base = {
750676e5081SArd Biesheuvel 		.cra_name		= "xts(aes)",
751676e5081SArd Biesheuvel 		.cra_driver_name	= "xts-aes-" MODE,
752d0ed0db1SHerbert Xu 		.cra_priority		= PRIO,
75349788fe2SArd Biesheuvel 		.cra_blocksize		= AES_BLOCK_SIZE,
75449788fe2SArd Biesheuvel 		.cra_ctxsize		= sizeof(struct crypto_aes_xts_ctx),
75549788fe2SArd Biesheuvel 		.cra_module		= THIS_MODULE,
756d0ed0db1SHerbert Xu 	},
75749788fe2SArd Biesheuvel 	.min_keysize	= 2 * AES_MIN_KEY_SIZE,
75849788fe2SArd Biesheuvel 	.max_keysize	= 2 * AES_MAX_KEY_SIZE,
75949788fe2SArd Biesheuvel 	.ivsize		= AES_BLOCK_SIZE,
7607cceca8bSArd Biesheuvel 	.walksize	= 2 * AES_BLOCK_SIZE,
76149788fe2SArd Biesheuvel 	.setkey		= xts_set_key,
76249788fe2SArd Biesheuvel 	.encrypt	= xts_encrypt,
76349788fe2SArd Biesheuvel 	.decrypt	= xts_decrypt,
76469b6f2e8SArd Biesheuvel }, {
76569b6f2e8SArd Biesheuvel #endif
76669b6f2e8SArd Biesheuvel 	.base = {
767676e5081SArd Biesheuvel 		.cra_name		= "cts(cbc(aes))",
768676e5081SArd Biesheuvel 		.cra_driver_name	= "cts-cbc-aes-" MODE,
76969b6f2e8SArd Biesheuvel 		.cra_priority		= PRIO,
77069b6f2e8SArd Biesheuvel 		.cra_blocksize		= AES_BLOCK_SIZE,
77169b6f2e8SArd Biesheuvel 		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
77269b6f2e8SArd Biesheuvel 		.cra_module		= THIS_MODULE,
77369b6f2e8SArd Biesheuvel 	},
77469b6f2e8SArd Biesheuvel 	.min_keysize	= AES_MIN_KEY_SIZE,
77569b6f2e8SArd Biesheuvel 	.max_keysize	= AES_MAX_KEY_SIZE,
77669b6f2e8SArd Biesheuvel 	.ivsize		= AES_BLOCK_SIZE,
77769b6f2e8SArd Biesheuvel 	.walksize	= 2 * AES_BLOCK_SIZE,
77869b6f2e8SArd Biesheuvel 	.setkey		= skcipher_aes_setkey,
77969b6f2e8SArd Biesheuvel 	.encrypt	= cts_cbc_encrypt,
78069b6f2e8SArd Biesheuvel 	.decrypt	= cts_cbc_decrypt,
78169b6f2e8SArd Biesheuvel }, {
78269b6f2e8SArd Biesheuvel 	.base = {
783676e5081SArd Biesheuvel 		.cra_name		= "essiv(cbc(aes),sha256)",
784676e5081SArd Biesheuvel 		.cra_driver_name	= "essiv-cbc-aes-sha256-" MODE,
78569b6f2e8SArd Biesheuvel 		.cra_priority		= PRIO + 1,
78669b6f2e8SArd Biesheuvel 		.cra_blocksize		= AES_BLOCK_SIZE,
78769b6f2e8SArd Biesheuvel 		.cra_ctxsize		= sizeof(struct crypto_aes_essiv_cbc_ctx),
78869b6f2e8SArd Biesheuvel 		.cra_module		= THIS_MODULE,
78969b6f2e8SArd Biesheuvel 	},
79069b6f2e8SArd Biesheuvel 	.min_keysize	= AES_MIN_KEY_SIZE,
79169b6f2e8SArd Biesheuvel 	.max_keysize	= AES_MAX_KEY_SIZE,
79269b6f2e8SArd Biesheuvel 	.ivsize		= AES_BLOCK_SIZE,
79369b6f2e8SArd Biesheuvel 	.setkey		= essiv_cbc_set_key,
79469b6f2e8SArd Biesheuvel 	.encrypt	= essiv_cbc_encrypt,
79569b6f2e8SArd Biesheuvel 	.decrypt	= essiv_cbc_decrypt,
79669b6f2e8SArd Biesheuvel 	.init		= essiv_cbc_init_tfm,
79769b6f2e8SArd Biesheuvel 	.exit		= essiv_cbc_exit_tfm,
79849788fe2SArd Biesheuvel } };
79949788fe2SArd Biesheuvel 
cbcmac_setkey(struct crypto_shash * tfm,const u8 * in_key,unsigned int key_len)8004860620dSArd Biesheuvel static int cbcmac_setkey(struct crypto_shash *tfm, const u8 *in_key,
8014860620dSArd Biesheuvel 			 unsigned int key_len)
8024860620dSArd Biesheuvel {
8034860620dSArd Biesheuvel 	struct mac_tfm_ctx *ctx = crypto_shash_ctx(tfm);
8044860620dSArd Biesheuvel 
805674f368aSEric Biggers 	return aes_expandkey(&ctx->key, in_key, key_len);
8064860620dSArd Biesheuvel }
8074860620dSArd Biesheuvel 
cmac_gf128_mul_by_x(be128 * y,const be128 * x)8084860620dSArd Biesheuvel static void cmac_gf128_mul_by_x(be128 *y, const be128 *x)
8094860620dSArd Biesheuvel {
8104860620dSArd Biesheuvel 	u64 a = be64_to_cpu(x->a);
8114860620dSArd Biesheuvel 	u64 b = be64_to_cpu(x->b);
8124860620dSArd Biesheuvel 
8134860620dSArd Biesheuvel 	y->a = cpu_to_be64((a << 1) | (b >> 63));
8144860620dSArd Biesheuvel 	y->b = cpu_to_be64((b << 1) ^ ((a >> 63) ? 0x87 : 0));
8154860620dSArd Biesheuvel }
8164860620dSArd Biesheuvel 
cmac_setkey(struct crypto_shash * tfm,const u8 * in_key,unsigned int key_len)8174860620dSArd Biesheuvel static int cmac_setkey(struct crypto_shash *tfm, const u8 *in_key,
8184860620dSArd Biesheuvel 		       unsigned int key_len)
8194860620dSArd Biesheuvel {
8204860620dSArd Biesheuvel 	struct mac_tfm_ctx *ctx = crypto_shash_ctx(tfm);
8214860620dSArd Biesheuvel 	be128 *consts = (be128 *)ctx->consts;
8224860620dSArd Biesheuvel 	int rounds = 6 + key_len / 4;
8234860620dSArd Biesheuvel 	int err;
8244860620dSArd Biesheuvel 
8254860620dSArd Biesheuvel 	err = cbcmac_setkey(tfm, in_key, key_len);
8264860620dSArd Biesheuvel 	if (err)
8274860620dSArd Biesheuvel 		return err;
8284860620dSArd Biesheuvel 
8294860620dSArd Biesheuvel 	/* encrypt the zero vector */
8304860620dSArd Biesheuvel 	kernel_neon_begin();
831557ecb45SArd Biesheuvel 	aes_ecb_encrypt(ctx->consts, (u8[AES_BLOCK_SIZE]){}, ctx->key.key_enc,
832557ecb45SArd Biesheuvel 			rounds, 1);
8334860620dSArd Biesheuvel 	kernel_neon_end();
8344860620dSArd Biesheuvel 
8354860620dSArd Biesheuvel 	cmac_gf128_mul_by_x(consts, consts);
8364860620dSArd Biesheuvel 	cmac_gf128_mul_by_x(consts + 1, consts);
8374860620dSArd Biesheuvel 
8384860620dSArd Biesheuvel 	return 0;
8394860620dSArd Biesheuvel }
8404860620dSArd Biesheuvel 
xcbc_setkey(struct crypto_shash * tfm,const u8 * in_key,unsigned int key_len)8414860620dSArd Biesheuvel static int xcbc_setkey(struct crypto_shash *tfm, const u8 *in_key,
8424860620dSArd Biesheuvel 		       unsigned int key_len)
8434860620dSArd Biesheuvel {
8444860620dSArd Biesheuvel 	static u8 const ks[3][AES_BLOCK_SIZE] = {
8454860620dSArd Biesheuvel 		{ [0 ... AES_BLOCK_SIZE - 1] = 0x1 },
8464860620dSArd Biesheuvel 		{ [0 ... AES_BLOCK_SIZE - 1] = 0x2 },
8474860620dSArd Biesheuvel 		{ [0 ... AES_BLOCK_SIZE - 1] = 0x3 },
8484860620dSArd Biesheuvel 	};
8494860620dSArd Biesheuvel 
8504860620dSArd Biesheuvel 	struct mac_tfm_ctx *ctx = crypto_shash_ctx(tfm);
8514860620dSArd Biesheuvel 	int rounds = 6 + key_len / 4;
8524860620dSArd Biesheuvel 	u8 key[AES_BLOCK_SIZE];
8534860620dSArd Biesheuvel 	int err;
8544860620dSArd Biesheuvel 
8554860620dSArd Biesheuvel 	err = cbcmac_setkey(tfm, in_key, key_len);
8564860620dSArd Biesheuvel 	if (err)
8574860620dSArd Biesheuvel 		return err;
8584860620dSArd Biesheuvel 
8594860620dSArd Biesheuvel 	kernel_neon_begin();
860557ecb45SArd Biesheuvel 	aes_ecb_encrypt(key, ks[0], ctx->key.key_enc, rounds, 1);
861557ecb45SArd Biesheuvel 	aes_ecb_encrypt(ctx->consts, ks[1], ctx->key.key_enc, rounds, 2);
8624860620dSArd Biesheuvel 	kernel_neon_end();
8634860620dSArd Biesheuvel 
8644860620dSArd Biesheuvel 	return cbcmac_setkey(tfm, key, sizeof(key));
8654860620dSArd Biesheuvel }
8664860620dSArd Biesheuvel 
mac_init(struct shash_desc * desc)8674860620dSArd Biesheuvel static int mac_init(struct shash_desc *desc)
8684860620dSArd Biesheuvel {
8694860620dSArd Biesheuvel 	struct mac_desc_ctx *ctx = shash_desc_ctx(desc);
8704860620dSArd Biesheuvel 
8714860620dSArd Biesheuvel 	memset(ctx->dg, 0, AES_BLOCK_SIZE);
8724860620dSArd Biesheuvel 	ctx->len = 0;
8734860620dSArd Biesheuvel 
8744860620dSArd Biesheuvel 	return 0;
8754860620dSArd Biesheuvel }
8764860620dSArd Biesheuvel 
mac_do_update(struct crypto_aes_ctx * ctx,u8 const in[],int blocks,u8 dg[],int enc_before,int enc_after)877e2115069SArd Biesheuvel static void mac_do_update(struct crypto_aes_ctx *ctx, u8 const in[], int blocks,
878e2115069SArd Biesheuvel 			  u8 dg[], int enc_before, int enc_after)
879e2115069SArd Biesheuvel {
880e2115069SArd Biesheuvel 	int rounds = 6 + ctx->key_length / 4;
881e2115069SArd Biesheuvel 
882e52b7023SEric Biggers 	if (crypto_simd_usable()) {
883f0070f4aSArd Biesheuvel 		int rem;
884f0070f4aSArd Biesheuvel 
885f0070f4aSArd Biesheuvel 		do {
886e2115069SArd Biesheuvel 			kernel_neon_begin();
887f0070f4aSArd Biesheuvel 			rem = aes_mac_update(in, ctx->key_enc, rounds, blocks,
888f0070f4aSArd Biesheuvel 					     dg, enc_before, enc_after);
889e2115069SArd Biesheuvel 			kernel_neon_end();
890f0070f4aSArd Biesheuvel 			in += (blocks - rem) * AES_BLOCK_SIZE;
891f0070f4aSArd Biesheuvel 			blocks = rem;
892f0070f4aSArd Biesheuvel 			enc_before = 0;
893f0070f4aSArd Biesheuvel 		} while (blocks);
894e2115069SArd Biesheuvel 	} else {
895e2115069SArd Biesheuvel 		if (enc_before)
896c1844729SArd Biesheuvel 			aes_encrypt(ctx, dg, dg);
897e2115069SArd Biesheuvel 
898e2115069SArd Biesheuvel 		while (blocks--) {
899e2115069SArd Biesheuvel 			crypto_xor(dg, in, AES_BLOCK_SIZE);
900e2115069SArd Biesheuvel 			in += AES_BLOCK_SIZE;
901e2115069SArd Biesheuvel 
902e2115069SArd Biesheuvel 			if (blocks || enc_after)
903c1844729SArd Biesheuvel 				aes_encrypt(ctx, dg, dg);
904e2115069SArd Biesheuvel 		}
905e2115069SArd Biesheuvel 	}
906e2115069SArd Biesheuvel }
907e2115069SArd Biesheuvel 
mac_update(struct shash_desc * desc,const u8 * p,unsigned int len)9084860620dSArd Biesheuvel static int mac_update(struct shash_desc *desc, const u8 *p, unsigned int len)
9094860620dSArd Biesheuvel {
9104860620dSArd Biesheuvel 	struct mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
9114860620dSArd Biesheuvel 	struct mac_desc_ctx *ctx = shash_desc_ctx(desc);
9124860620dSArd Biesheuvel 
9134860620dSArd Biesheuvel 	while (len > 0) {
9144860620dSArd Biesheuvel 		unsigned int l;
9154860620dSArd Biesheuvel 
9164860620dSArd Biesheuvel 		if ((ctx->len % AES_BLOCK_SIZE) == 0 &&
9174860620dSArd Biesheuvel 		    (ctx->len + len) > AES_BLOCK_SIZE) {
9184860620dSArd Biesheuvel 
9194860620dSArd Biesheuvel 			int blocks = len / AES_BLOCK_SIZE;
9204860620dSArd Biesheuvel 
9214860620dSArd Biesheuvel 			len %= AES_BLOCK_SIZE;
9224860620dSArd Biesheuvel 
923e2115069SArd Biesheuvel 			mac_do_update(&tctx->key, p, blocks, ctx->dg,
924e2115069SArd Biesheuvel 				      (ctx->len != 0), (len != 0));
9254860620dSArd Biesheuvel 
9264860620dSArd Biesheuvel 			p += blocks * AES_BLOCK_SIZE;
9274860620dSArd Biesheuvel 
9284860620dSArd Biesheuvel 			if (!len) {
9294860620dSArd Biesheuvel 				ctx->len = AES_BLOCK_SIZE;
9304860620dSArd Biesheuvel 				break;
9314860620dSArd Biesheuvel 			}
9324860620dSArd Biesheuvel 			ctx->len = 0;
9334860620dSArd Biesheuvel 		}
9344860620dSArd Biesheuvel 
9354860620dSArd Biesheuvel 		l = min(len, AES_BLOCK_SIZE - ctx->len);
9364860620dSArd Biesheuvel 
9374860620dSArd Biesheuvel 		if (l <= AES_BLOCK_SIZE) {
9384860620dSArd Biesheuvel 			crypto_xor(ctx->dg + ctx->len, p, l);
9394860620dSArd Biesheuvel 			ctx->len += l;
9404860620dSArd Biesheuvel 			len -= l;
9414860620dSArd Biesheuvel 			p += l;
9424860620dSArd Biesheuvel 		}
9434860620dSArd Biesheuvel 	}
9444860620dSArd Biesheuvel 
9454860620dSArd Biesheuvel 	return 0;
9464860620dSArd Biesheuvel }
9474860620dSArd Biesheuvel 
cbcmac_final(struct shash_desc * desc,u8 * out)9484860620dSArd Biesheuvel static int cbcmac_final(struct shash_desc *desc, u8 *out)
9494860620dSArd Biesheuvel {
9504860620dSArd Biesheuvel 	struct mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
9514860620dSArd Biesheuvel 	struct mac_desc_ctx *ctx = shash_desc_ctx(desc);
9524860620dSArd Biesheuvel 
953f6e9af87SEric Biggers 	mac_do_update(&tctx->key, NULL, 0, ctx->dg, (ctx->len != 0), 0);
9544860620dSArd Biesheuvel 
9554860620dSArd Biesheuvel 	memcpy(out, ctx->dg, AES_BLOCK_SIZE);
9564860620dSArd Biesheuvel 
9574860620dSArd Biesheuvel 	return 0;
9584860620dSArd Biesheuvel }
9594860620dSArd Biesheuvel 
cmac_final(struct shash_desc * desc,u8 * out)9604860620dSArd Biesheuvel static int cmac_final(struct shash_desc *desc, u8 *out)
9614860620dSArd Biesheuvel {
9624860620dSArd Biesheuvel 	struct mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
9634860620dSArd Biesheuvel 	struct mac_desc_ctx *ctx = shash_desc_ctx(desc);
9644860620dSArd Biesheuvel 	u8 *consts = tctx->consts;
9654860620dSArd Biesheuvel 
9664860620dSArd Biesheuvel 	if (ctx->len != AES_BLOCK_SIZE) {
9674860620dSArd Biesheuvel 		ctx->dg[ctx->len] ^= 0x80;
9684860620dSArd Biesheuvel 		consts += AES_BLOCK_SIZE;
9694860620dSArd Biesheuvel 	}
9704860620dSArd Biesheuvel 
971e2115069SArd Biesheuvel 	mac_do_update(&tctx->key, consts, 1, ctx->dg, 0, 1);
9724860620dSArd Biesheuvel 
9734860620dSArd Biesheuvel 	memcpy(out, ctx->dg, AES_BLOCK_SIZE);
9744860620dSArd Biesheuvel 
9754860620dSArd Biesheuvel 	return 0;
9764860620dSArd Biesheuvel }
9774860620dSArd Biesheuvel 
9784860620dSArd Biesheuvel static struct shash_alg mac_algs[] = { {
9794860620dSArd Biesheuvel 	.base.cra_name		= "cmac(aes)",
9804860620dSArd Biesheuvel 	.base.cra_driver_name	= "cmac-aes-" MODE,
9814860620dSArd Biesheuvel 	.base.cra_priority	= PRIO,
9824860620dSArd Biesheuvel 	.base.cra_blocksize	= AES_BLOCK_SIZE,
9834860620dSArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct mac_tfm_ctx) +
9844860620dSArd Biesheuvel 				  2 * AES_BLOCK_SIZE,
9854860620dSArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
9864860620dSArd Biesheuvel 
9874860620dSArd Biesheuvel 	.digestsize		= AES_BLOCK_SIZE,
9884860620dSArd Biesheuvel 	.init			= mac_init,
9894860620dSArd Biesheuvel 	.update			= mac_update,
9904860620dSArd Biesheuvel 	.final			= cmac_final,
9914860620dSArd Biesheuvel 	.setkey			= cmac_setkey,
9924860620dSArd Biesheuvel 	.descsize		= sizeof(struct mac_desc_ctx),
9934860620dSArd Biesheuvel }, {
9944860620dSArd Biesheuvel 	.base.cra_name		= "xcbc(aes)",
9954860620dSArd Biesheuvel 	.base.cra_driver_name	= "xcbc-aes-" MODE,
9964860620dSArd Biesheuvel 	.base.cra_priority	= PRIO,
9974860620dSArd Biesheuvel 	.base.cra_blocksize	= AES_BLOCK_SIZE,
9984860620dSArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct mac_tfm_ctx) +
9994860620dSArd Biesheuvel 				  2 * AES_BLOCK_SIZE,
10004860620dSArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
10014860620dSArd Biesheuvel 
10024860620dSArd Biesheuvel 	.digestsize		= AES_BLOCK_SIZE,
10034860620dSArd Biesheuvel 	.init			= mac_init,
10044860620dSArd Biesheuvel 	.update			= mac_update,
10054860620dSArd Biesheuvel 	.final			= cmac_final,
10064860620dSArd Biesheuvel 	.setkey			= xcbc_setkey,
10074860620dSArd Biesheuvel 	.descsize		= sizeof(struct mac_desc_ctx),
10084860620dSArd Biesheuvel }, {
10094860620dSArd Biesheuvel 	.base.cra_name		= "cbcmac(aes)",
10104860620dSArd Biesheuvel 	.base.cra_driver_name	= "cbcmac-aes-" MODE,
10114860620dSArd Biesheuvel 	.base.cra_priority	= PRIO,
10124860620dSArd Biesheuvel 	.base.cra_blocksize	= 1,
10134860620dSArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct mac_tfm_ctx),
10144860620dSArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
10154860620dSArd Biesheuvel 
10164860620dSArd Biesheuvel 	.digestsize		= AES_BLOCK_SIZE,
10174860620dSArd Biesheuvel 	.init			= mac_init,
10184860620dSArd Biesheuvel 	.update			= mac_update,
10194860620dSArd Biesheuvel 	.final			= cbcmac_final,
10204860620dSArd Biesheuvel 	.setkey			= cbcmac_setkey,
10214860620dSArd Biesheuvel 	.descsize		= sizeof(struct mac_desc_ctx),
10224860620dSArd Biesheuvel } };
10234860620dSArd Biesheuvel 
aes_exit(void)1024d0ed0db1SHerbert Xu static void aes_exit(void)
1025d0ed0db1SHerbert Xu {
10264860620dSArd Biesheuvel 	crypto_unregister_shashes(mac_algs, ARRAY_SIZE(mac_algs));
1027d0ed0db1SHerbert Xu 	crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
1028d0ed0db1SHerbert Xu }
1029d0ed0db1SHerbert Xu 
aes_init(void)103049788fe2SArd Biesheuvel static int __init aes_init(void)
103149788fe2SArd Biesheuvel {
1032d0ed0db1SHerbert Xu 	int err;
1033d0ed0db1SHerbert Xu 
1034d0ed0db1SHerbert Xu 	err = crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
1035d0ed0db1SHerbert Xu 	if (err)
1036d0ed0db1SHerbert Xu 		return err;
1037d0ed0db1SHerbert Xu 
10384860620dSArd Biesheuvel 	err = crypto_register_shashes(mac_algs, ARRAY_SIZE(mac_algs));
10394860620dSArd Biesheuvel 	if (err)
10404860620dSArd Biesheuvel 		goto unregister_ciphers;
10414860620dSArd Biesheuvel 
1042d0ed0db1SHerbert Xu 	return 0;
1043d0ed0db1SHerbert Xu 
10444860620dSArd Biesheuvel unregister_ciphers:
10454860620dSArd Biesheuvel 	crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
1046d0ed0db1SHerbert Xu 	return err;
104749788fe2SArd Biesheuvel }
104849788fe2SArd Biesheuvel 
104949788fe2SArd Biesheuvel #ifdef USE_V8_CRYPTO_EXTENSIONS
105049788fe2SArd Biesheuvel module_cpu_feature_match(AES, aes_init);
105149788fe2SArd Biesheuvel #else
105249788fe2SArd Biesheuvel module_init(aes_init);
10534edd7d01SArd Biesheuvel EXPORT_SYMBOL(neon_aes_ecb_encrypt);
10544edd7d01SArd Biesheuvel EXPORT_SYMBOL(neon_aes_cbc_encrypt);
1055fc074e13SArd Biesheuvel EXPORT_SYMBOL(neon_aes_ctr_encrypt);
105667cfa5d3SArd Biesheuvel EXPORT_SYMBOL(neon_aes_xts_encrypt);
105767cfa5d3SArd Biesheuvel EXPORT_SYMBOL(neon_aes_xts_decrypt);
105849788fe2SArd Biesheuvel #endif
105949788fe2SArd Biesheuvel module_exit(aes_exit);
1060