aes-ce-glue.c 12.8 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2 3 4 5 6 7 8 9
/*
 * aes-ce-glue.c - wrapper code for ARMv8 AES
 *
 * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
 */

#include <asm/hwcap.h>
#include <asm/neon.h>
10
#include <asm/simd.h>
11
#include <asm/unaligned.h>
12
#include <crypto/aes.h>
13
#include <crypto/ctr.h>
H
Herbert Xu 已提交
14 15
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h>
16
#include <linux/cpufeature.h>
17
#include <linux/module.h>
18
#include <crypto/xts.h>
19 20 21 22 23 24 25 26 27

MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2");

/* defined in aes-ce-core.S */
asmlinkage u32 ce_aes_sub(u32 input);
asmlinkage void ce_aes_invert(void *dst, void *src);

28
asmlinkage void ce_aes_ecb_encrypt(u8 out[], u8 const in[], u32 const rk[],
29
				   int rounds, int blocks);
30
asmlinkage void ce_aes_ecb_decrypt(u8 out[], u8 const in[], u32 const rk[],
31 32
				   int rounds, int blocks);

33
asmlinkage void ce_aes_cbc_encrypt(u8 out[], u8 const in[], u32 const rk[],
34
				   int rounds, int blocks, u8 iv[]);
35
asmlinkage void ce_aes_cbc_decrypt(u8 out[], u8 const in[], u32 const rk[],
36 37
				   int rounds, int blocks, u8 iv[]);

38
asmlinkage void ce_aes_ctr_encrypt(u8 out[], u8 const in[], u32 const rk[],
39 40
				   int rounds, int blocks, u8 ctr[]);

41
asmlinkage void ce_aes_xts_encrypt(u8 out[], u8 const in[], u32 const rk1[],
42
				   int rounds, int blocks, u8 iv[],
43 44
				   u32 const rk2[], int first);
asmlinkage void ce_aes_xts_decrypt(u8 out[], u8 const in[], u32 const rk1[],
45
				   int rounds, int blocks, u8 iv[],
46
				   u32 const rk2[], int first);
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

struct aes_block {
	u8 b[AES_BLOCK_SIZE];
};

static int num_rounds(struct crypto_aes_ctx *ctx)
{
	/*
	 * # of rounds specified by AES:
	 * 128 bit key		10 rounds
	 * 192 bit key		12 rounds
	 * 256 bit key		14 rounds
	 * => n byte key	=> 6 + (n/4) rounds
	 */
	return 6 + ctx->key_length / 4;
}

static int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
			    unsigned int key_len)
{
	/*
	 * The AES key schedule round constants
	 */
	static u8 const rcon[] = {
		0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
	};

	u32 kwords = key_len / sizeof(u32);
	struct aes_block *key_enc, *key_dec;
	int i, j;

	if (key_len != AES_KEYSIZE_128 &&
	    key_len != AES_KEYSIZE_192 &&
	    key_len != AES_KEYSIZE_256)
		return -EINVAL;

	ctx->key_length = key_len;
84 85
	for (i = 0; i < kwords; i++)
		ctx->key_enc[i] = get_unaligned_le32(in_key + i * sizeof(u32));
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131

	kernel_neon_begin();
	for (i = 0; i < sizeof(rcon); i++) {
		u32 *rki = ctx->key_enc + (i * kwords);
		u32 *rko = rki + kwords;

		rko[0] = ror32(ce_aes_sub(rki[kwords - 1]), 8);
		rko[0] = rko[0] ^ rki[0] ^ rcon[i];
		rko[1] = rko[0] ^ rki[1];
		rko[2] = rko[1] ^ rki[2];
		rko[3] = rko[2] ^ rki[3];

		if (key_len == AES_KEYSIZE_192) {
			if (i >= 7)
				break;
			rko[4] = rko[3] ^ rki[4];
			rko[5] = rko[4] ^ rki[5];
		} else if (key_len == AES_KEYSIZE_256) {
			if (i >= 6)
				break;
			rko[4] = ce_aes_sub(rko[3]) ^ rki[4];
			rko[5] = rko[4] ^ rki[5];
			rko[6] = rko[5] ^ rki[6];
			rko[7] = rko[6] ^ rki[7];
		}
	}

	/*
	 * Generate the decryption keys for the Equivalent Inverse Cipher.
	 * This involves reversing the order of the round keys, and applying
	 * the Inverse Mix Columns transformation on all but the first and
	 * the last one.
	 */
	key_enc = (struct aes_block *)ctx->key_enc;
	key_dec = (struct aes_block *)ctx->key_dec;
	j = num_rounds(ctx);

	key_dec[0] = key_enc[j];
	for (i = 1, j--; j > 0; i++, j--)
		ce_aes_invert(key_dec + i, key_enc + j);
	key_dec[i] = key_enc[0];

	kernel_neon_end();
	return 0;
}

H
Herbert Xu 已提交
132
static int ce_aes_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
133 134
			 unsigned int key_len)
{
H
Herbert Xu 已提交
135
	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
136 137 138 139 140 141
	int ret;

	ret = ce_aes_expandkey(ctx, in_key, key_len);
	if (!ret)
		return 0;

H
Herbert Xu 已提交
142
	crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
143 144 145 146 147 148 149 150
	return -EINVAL;
}

struct crypto_aes_xts_ctx {
	struct crypto_aes_ctx key1;
	struct crypto_aes_ctx __aligned(8) key2;
};

H
Herbert Xu 已提交
151
static int xts_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
152 153
		       unsigned int key_len)
{
H
Herbert Xu 已提交
154
	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
155 156
	int ret;

H
Herbert Xu 已提交
157
	ret = xts_verify_key(tfm, in_key, key_len);
158 159 160
	if (ret)
		return ret;

161 162 163 164 165 166 167
	ret = ce_aes_expandkey(&ctx->key1, in_key, key_len / 2);
	if (!ret)
		ret = ce_aes_expandkey(&ctx->key2, &in_key[key_len / 2],
				       key_len / 2);
	if (!ret)
		return 0;

H
Herbert Xu 已提交
168
	crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
169 170 171
	return -EINVAL;
}

H
Herbert Xu 已提交
172
static int ecb_encrypt(struct skcipher_request *req)
173
{
H
Herbert Xu 已提交
174 175 176
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
	struct skcipher_walk walk;
177 178 179
	unsigned int blocks;
	int err;

H
Herbert Xu 已提交
180
	err = skcipher_walk_virt(&walk, req, true);
181 182 183 184

	kernel_neon_begin();
	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
		ce_aes_ecb_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
185
				   ctx->key_enc, num_rounds(ctx), blocks);
H
Herbert Xu 已提交
186
		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
187 188 189 190 191
	}
	kernel_neon_end();
	return err;
}

H
Herbert Xu 已提交
192
static int ecb_decrypt(struct skcipher_request *req)
193
{
H
Herbert Xu 已提交
194 195 196
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
	struct skcipher_walk walk;
197 198 199
	unsigned int blocks;
	int err;

H
Herbert Xu 已提交
200
	err = skcipher_walk_virt(&walk, req, true);
201 202 203 204

	kernel_neon_begin();
	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
		ce_aes_ecb_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
205
				   ctx->key_dec, num_rounds(ctx), blocks);
H
Herbert Xu 已提交
206
		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
207 208 209 210 211
	}
	kernel_neon_end();
	return err;
}

H
Herbert Xu 已提交
212
static int cbc_encrypt(struct skcipher_request *req)
213
{
H
Herbert Xu 已提交
214 215 216
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
	struct skcipher_walk walk;
217 218 219
	unsigned int blocks;
	int err;

H
Herbert Xu 已提交
220
	err = skcipher_walk_virt(&walk, req, true);
221 222 223 224

	kernel_neon_begin();
	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
		ce_aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
225
				   ctx->key_enc, num_rounds(ctx), blocks,
226
				   walk.iv);
H
Herbert Xu 已提交
227
		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
228 229 230 231 232
	}
	kernel_neon_end();
	return err;
}

H
Herbert Xu 已提交
233
static int cbc_decrypt(struct skcipher_request *req)
234
{
H
Herbert Xu 已提交
235 236 237
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
	struct skcipher_walk walk;
238 239 240
	unsigned int blocks;
	int err;

H
Herbert Xu 已提交
241
	err = skcipher_walk_virt(&walk, req, true);
242 243 244 245

	kernel_neon_begin();
	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
		ce_aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
246
				   ctx->key_dec, num_rounds(ctx), blocks,
247
				   walk.iv);
H
Herbert Xu 已提交
248
		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
249 250 251 252 253
	}
	kernel_neon_end();
	return err;
}

H
Herbert Xu 已提交
254
static int ctr_encrypt(struct skcipher_request *req)
255
{
H
Herbert Xu 已提交
256 257 258
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
	struct skcipher_walk walk;
259 260
	int err, blocks;

H
Herbert Xu 已提交
261
	err = skcipher_walk_virt(&walk, req, true);
262 263 264 265

	kernel_neon_begin();
	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
		ce_aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
266
				   ctx->key_enc, num_rounds(ctx), blocks,
267
				   walk.iv);
H
Herbert Xu 已提交
268
		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
269
	}
H
Herbert Xu 已提交
270
	if (walk.nbytes) {
271
		u8 __aligned(8) tail[AES_BLOCK_SIZE];
H
Herbert Xu 已提交
272 273 274
		unsigned int nbytes = walk.nbytes;
		u8 *tdst = walk.dst.virt.addr;
		u8 *tsrc = walk.src.virt.addr;
275 276

		/*
277
		 * Tell aes_ctr_encrypt() to process a tail block.
278
		 */
279
		blocks = -1;
280

281 282
		ce_aes_ctr_encrypt(tail, NULL, ctx->key_enc, num_rounds(ctx),
				   blocks, walk.iv);
283
		crypto_xor_cpy(tdst, tsrc, tail, nbytes);
H
Herbert Xu 已提交
284
		err = skcipher_walk_done(&walk, 0);
285 286 287 288 289 290
	}
	kernel_neon_end();

	return err;
}

291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
static void ctr_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst)
{
	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
	unsigned long flags;

	/*
	 * Temporarily disable interrupts to avoid races where
	 * cachelines are evicted when the CPU is interrupted
	 * to do something else.
	 */
	local_irq_save(flags);
	aes_encrypt(ctx, dst, src);
	local_irq_restore(flags);
}

static int ctr_encrypt_sync(struct skcipher_request *req)
{
	if (!crypto_simd_usable())
		return crypto_ctr_encrypt_walk(req, ctr_encrypt_one);

	return ctr_encrypt(req);
}

H
Herbert Xu 已提交
314
static int xts_encrypt(struct skcipher_request *req)
315
{
H
Herbert Xu 已提交
316 317
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
318
	int err, first, rounds = num_rounds(&ctx->key1);
H
Herbert Xu 已提交
319
	struct skcipher_walk walk;
320 321
	unsigned int blocks;

H
Herbert Xu 已提交
322
	err = skcipher_walk_virt(&walk, req, true);
323 324 325 326

	kernel_neon_begin();
	for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
		ce_aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
327 328
				   ctx->key1.key_enc, rounds, blocks, walk.iv,
				   ctx->key2.key_enc, first);
H
Herbert Xu 已提交
329
		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
330 331 332 333 334 335
	}
	kernel_neon_end();

	return err;
}

H
Herbert Xu 已提交
336
static int xts_decrypt(struct skcipher_request *req)
337
{
H
Herbert Xu 已提交
338 339
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
340
	int err, first, rounds = num_rounds(&ctx->key1);
H
Herbert Xu 已提交
341
	struct skcipher_walk walk;
342 343
	unsigned int blocks;

H
Herbert Xu 已提交
344
	err = skcipher_walk_virt(&walk, req, true);
345 346 347 348

	kernel_neon_begin();
	for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
		ce_aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
349 350
				   ctx->key1.key_dec, rounds, blocks, walk.iv,
				   ctx->key2.key_enc, first);
H
Herbert Xu 已提交
351
		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
352 353 354 355 356 357
	}
	kernel_neon_end();

	return err;
}

H
Herbert Xu 已提交
358
static struct skcipher_alg aes_algs[] = { {
359 360 361 362 363 364 365 366 367 368 369 370 371
	.base.cra_name		= "__ecb(aes)",
	.base.cra_driver_name	= "__ecb-aes-ce",
	.base.cra_priority	= 300,
	.base.cra_flags		= CRYPTO_ALG_INTERNAL,
	.base.cra_blocksize	= AES_BLOCK_SIZE,
	.base.cra_ctxsize	= sizeof(struct crypto_aes_ctx),
	.base.cra_module	= THIS_MODULE,

	.min_keysize		= AES_MIN_KEY_SIZE,
	.max_keysize		= AES_MAX_KEY_SIZE,
	.setkey			= ce_aes_setkey,
	.encrypt		= ecb_encrypt,
	.decrypt		= ecb_decrypt,
372
}, {
373 374 375 376 377 378 379 380 381 382 383 384 385 386
	.base.cra_name		= "__cbc(aes)",
	.base.cra_driver_name	= "__cbc-aes-ce",
	.base.cra_priority	= 300,
	.base.cra_flags		= CRYPTO_ALG_INTERNAL,
	.base.cra_blocksize	= AES_BLOCK_SIZE,
	.base.cra_ctxsize	= sizeof(struct crypto_aes_ctx),
	.base.cra_module	= THIS_MODULE,

	.min_keysize		= AES_MIN_KEY_SIZE,
	.max_keysize		= AES_MAX_KEY_SIZE,
	.ivsize			= AES_BLOCK_SIZE,
	.setkey			= ce_aes_setkey,
	.encrypt		= cbc_encrypt,
	.decrypt		= cbc_decrypt,
387
}, {
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
	.base.cra_name		= "__ctr(aes)",
	.base.cra_driver_name	= "__ctr-aes-ce",
	.base.cra_priority	= 300,
	.base.cra_flags		= CRYPTO_ALG_INTERNAL,
	.base.cra_blocksize	= 1,
	.base.cra_ctxsize	= sizeof(struct crypto_aes_ctx),
	.base.cra_module	= THIS_MODULE,

	.min_keysize		= AES_MIN_KEY_SIZE,
	.max_keysize		= AES_MAX_KEY_SIZE,
	.ivsize			= AES_BLOCK_SIZE,
	.chunksize		= AES_BLOCK_SIZE,
	.setkey			= ce_aes_setkey,
	.encrypt		= ctr_encrypt,
	.decrypt		= ctr_encrypt,
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
}, {
	.base.cra_name		= "ctr(aes)",
	.base.cra_driver_name	= "ctr-aes-ce-sync",
	.base.cra_priority	= 300 - 1,
	.base.cra_blocksize	= 1,
	.base.cra_ctxsize	= sizeof(struct crypto_aes_ctx),
	.base.cra_module	= THIS_MODULE,

	.min_keysize		= AES_MIN_KEY_SIZE,
	.max_keysize		= AES_MAX_KEY_SIZE,
	.ivsize			= AES_BLOCK_SIZE,
	.chunksize		= AES_BLOCK_SIZE,
	.setkey			= ce_aes_setkey,
	.encrypt		= ctr_encrypt_sync,
	.decrypt		= ctr_encrypt_sync,
418
}, {
419 420 421 422 423 424 425 426 427 428 429 430 431 432
	.base.cra_name		= "__xts(aes)",
	.base.cra_driver_name	= "__xts-aes-ce",
	.base.cra_priority	= 300,
	.base.cra_flags		= CRYPTO_ALG_INTERNAL,
	.base.cra_blocksize	= AES_BLOCK_SIZE,
	.base.cra_ctxsize	= sizeof(struct crypto_aes_xts_ctx),
	.base.cra_module	= THIS_MODULE,

	.min_keysize		= 2 * AES_MIN_KEY_SIZE,
	.max_keysize		= 2 * AES_MAX_KEY_SIZE,
	.ivsize			= AES_BLOCK_SIZE,
	.setkey			= xts_set_key,
	.encrypt		= xts_encrypt,
	.decrypt		= xts_decrypt,
433 434
} };

435
static struct simd_skcipher_alg *aes_simd_algs[ARRAY_SIZE(aes_algs)];
H
Herbert Xu 已提交
436 437 438 439 440 441 442 443 444 445 446

static void aes_exit(void)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(aes_simd_algs) && aes_simd_algs[i]; i++)
		simd_skcipher_free(aes_simd_algs[i]);

	crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
}

447 448
static int __init aes_init(void)
{
H
Herbert Xu 已提交
449 450 451 452 453 454 455 456 457 458 459 460
	struct simd_skcipher_alg *simd;
	const char *basename;
	const char *algname;
	const char *drvname;
	int err;
	int i;

	err = crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
	if (err)
		return err;

	for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
461 462 463
		if (!(aes_algs[i].base.cra_flags & CRYPTO_ALG_INTERNAL))
			continue;

H
Herbert Xu 已提交
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
		algname = aes_algs[i].base.cra_name + 2;
		drvname = aes_algs[i].base.cra_driver_name + 2;
		basename = aes_algs[i].base.cra_driver_name;
		simd = simd_skcipher_create_compat(algname, drvname, basename);
		err = PTR_ERR(simd);
		if (IS_ERR(simd))
			goto unregister_simds;

		aes_simd_algs[i] = simd;
	}

	return 0;

unregister_simds:
	aes_exit();
	return err;
480 481
}

482
module_cpu_feature_match(AES, aes_init);
483
module_exit(aes_exit);