xref: /openbmc/linux/lib/crypto/aes.c (revision 976e3645923bdd2fe7893aae33fd7a21098bfb28)
1e59c1c98SArd Biesheuvel // SPDX-License-Identifier: GPL-2.0
2e59c1c98SArd Biesheuvel /*
3e59c1c98SArd Biesheuvel  * Copyright (C) 2017-2019 Linaro Ltd <ard.biesheuvel@linaro.org>
4e59c1c98SArd Biesheuvel  */
5e59c1c98SArd Biesheuvel 
6e59c1c98SArd Biesheuvel #include <crypto/aes.h>
7e59c1c98SArd Biesheuvel #include <linux/crypto.h>
8e59c1c98SArd Biesheuvel #include <linux/module.h>
9e59c1c98SArd Biesheuvel #include <asm/unaligned.h>
10e59c1c98SArd Biesheuvel 
11e59c1c98SArd Biesheuvel /*
12e59c1c98SArd Biesheuvel  * Emit the sbox as volatile const to prevent the compiler from doing
13e59c1c98SArd Biesheuvel  * constant folding on sbox references involving fixed indexes.
14e59c1c98SArd Biesheuvel  */
15e59c1c98SArd Biesheuvel static volatile const u8 __cacheline_aligned aes_sbox[] = {
16e59c1c98SArd Biesheuvel 	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
17e59c1c98SArd Biesheuvel 	0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
18e59c1c98SArd Biesheuvel 	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
19e59c1c98SArd Biesheuvel 	0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
20e59c1c98SArd Biesheuvel 	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
21e59c1c98SArd Biesheuvel 	0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
22e59c1c98SArd Biesheuvel 	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
23e59c1c98SArd Biesheuvel 	0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
24e59c1c98SArd Biesheuvel 	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
25e59c1c98SArd Biesheuvel 	0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
26e59c1c98SArd Biesheuvel 	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
27e59c1c98SArd Biesheuvel 	0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
28e59c1c98SArd Biesheuvel 	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
29e59c1c98SArd Biesheuvel 	0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
30e59c1c98SArd Biesheuvel 	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
31e59c1c98SArd Biesheuvel 	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
32e59c1c98SArd Biesheuvel 	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
33e59c1c98SArd Biesheuvel 	0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
34e59c1c98SArd Biesheuvel 	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
35e59c1c98SArd Biesheuvel 	0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
36e59c1c98SArd Biesheuvel 	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
37e59c1c98SArd Biesheuvel 	0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
38e59c1c98SArd Biesheuvel 	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
39e59c1c98SArd Biesheuvel 	0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
40e59c1c98SArd Biesheuvel 	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
41e59c1c98SArd Biesheuvel 	0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
42e59c1c98SArd Biesheuvel 	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
43e59c1c98SArd Biesheuvel 	0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
44e59c1c98SArd Biesheuvel 	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
45e59c1c98SArd Biesheuvel 	0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
46e59c1c98SArd Biesheuvel 	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
47e59c1c98SArd Biesheuvel 	0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
48e59c1c98SArd Biesheuvel };
49e59c1c98SArd Biesheuvel 
50e59c1c98SArd Biesheuvel static volatile const u8 __cacheline_aligned aes_inv_sbox[] = {
51e59c1c98SArd Biesheuvel 	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
52e59c1c98SArd Biesheuvel 	0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
53e59c1c98SArd Biesheuvel 	0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
54e59c1c98SArd Biesheuvel 	0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
55e59c1c98SArd Biesheuvel 	0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
56e59c1c98SArd Biesheuvel 	0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
57e59c1c98SArd Biesheuvel 	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
58e59c1c98SArd Biesheuvel 	0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
59e59c1c98SArd Biesheuvel 	0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
60e59c1c98SArd Biesheuvel 	0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
61e59c1c98SArd Biesheuvel 	0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
62e59c1c98SArd Biesheuvel 	0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
63e59c1c98SArd Biesheuvel 	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
64e59c1c98SArd Biesheuvel 	0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
65e59c1c98SArd Biesheuvel 	0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
66e59c1c98SArd Biesheuvel 	0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
67e59c1c98SArd Biesheuvel 	0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
68e59c1c98SArd Biesheuvel 	0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
69e59c1c98SArd Biesheuvel 	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
70e59c1c98SArd Biesheuvel 	0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
71e59c1c98SArd Biesheuvel 	0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
72e59c1c98SArd Biesheuvel 	0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
73e59c1c98SArd Biesheuvel 	0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
74e59c1c98SArd Biesheuvel 	0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
75e59c1c98SArd Biesheuvel 	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
76e59c1c98SArd Biesheuvel 	0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
77e59c1c98SArd Biesheuvel 	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
78e59c1c98SArd Biesheuvel 	0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
79e59c1c98SArd Biesheuvel 	0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
80e59c1c98SArd Biesheuvel 	0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
81e59c1c98SArd Biesheuvel 	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
82e59c1c98SArd Biesheuvel 	0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
83e59c1c98SArd Biesheuvel };
84e59c1c98SArd Biesheuvel 
859467a315SArd Biesheuvel extern const u8 crypto_aes_sbox[256] __alias(aes_sbox);
869467a315SArd Biesheuvel extern const u8 crypto_aes_inv_sbox[256] __alias(aes_inv_sbox);
879467a315SArd Biesheuvel 
889467a315SArd Biesheuvel EXPORT_SYMBOL(crypto_aes_sbox);
899467a315SArd Biesheuvel EXPORT_SYMBOL(crypto_aes_inv_sbox);
909467a315SArd Biesheuvel 
mul_by_x(u32 w)91e59c1c98SArd Biesheuvel static u32 mul_by_x(u32 w)
92e59c1c98SArd Biesheuvel {
93e59c1c98SArd Biesheuvel 	u32 x = w & 0x7f7f7f7f;
94e59c1c98SArd Biesheuvel 	u32 y = w & 0x80808080;
95e59c1c98SArd Biesheuvel 
96e59c1c98SArd Biesheuvel 	/* multiply by polynomial 'x' (0b10) in GF(2^8) */
97e59c1c98SArd Biesheuvel 	return (x << 1) ^ (y >> 7) * 0x1b;
98e59c1c98SArd Biesheuvel }
99e59c1c98SArd Biesheuvel 
mul_by_x2(u32 w)100e59c1c98SArd Biesheuvel static u32 mul_by_x2(u32 w)
101e59c1c98SArd Biesheuvel {
102e59c1c98SArd Biesheuvel 	u32 x = w & 0x3f3f3f3f;
103e59c1c98SArd Biesheuvel 	u32 y = w & 0x80808080;
104e59c1c98SArd Biesheuvel 	u32 z = w & 0x40404040;
105e59c1c98SArd Biesheuvel 
106e59c1c98SArd Biesheuvel 	/* multiply by polynomial 'x^2' (0b100) in GF(2^8) */
107e59c1c98SArd Biesheuvel 	return (x << 2) ^ (y >> 7) * 0x36 ^ (z >> 6) * 0x1b;
108e59c1c98SArd Biesheuvel }
109e59c1c98SArd Biesheuvel 
mix_columns(u32 x)110e59c1c98SArd Biesheuvel static u32 mix_columns(u32 x)
111e59c1c98SArd Biesheuvel {
112e59c1c98SArd Biesheuvel 	/*
113e59c1c98SArd Biesheuvel 	 * Perform the following matrix multiplication in GF(2^8)
114e59c1c98SArd Biesheuvel 	 *
115e59c1c98SArd Biesheuvel 	 * | 0x2 0x3 0x1 0x1 |   | x[0] |
116e59c1c98SArd Biesheuvel 	 * | 0x1 0x2 0x3 0x1 |   | x[1] |
117e59c1c98SArd Biesheuvel 	 * | 0x1 0x1 0x2 0x3 | x | x[2] |
118e59c1c98SArd Biesheuvel 	 * | 0x3 0x1 0x1 0x2 |   | x[3] |
119e59c1c98SArd Biesheuvel 	 */
120e59c1c98SArd Biesheuvel 	u32 y = mul_by_x(x) ^ ror32(x, 16);
121e59c1c98SArd Biesheuvel 
122e59c1c98SArd Biesheuvel 	return y ^ ror32(x ^ y, 8);
123e59c1c98SArd Biesheuvel }
124e59c1c98SArd Biesheuvel 
inv_mix_columns(u32 x)125e59c1c98SArd Biesheuvel static u32 inv_mix_columns(u32 x)
126e59c1c98SArd Biesheuvel {
127e59c1c98SArd Biesheuvel 	/*
128e59c1c98SArd Biesheuvel 	 * Perform the following matrix multiplication in GF(2^8)
129e59c1c98SArd Biesheuvel 	 *
130e59c1c98SArd Biesheuvel 	 * | 0xe 0xb 0xd 0x9 |   | x[0] |
131e59c1c98SArd Biesheuvel 	 * | 0x9 0xe 0xb 0xd |   | x[1] |
132e59c1c98SArd Biesheuvel 	 * | 0xd 0x9 0xe 0xb | x | x[2] |
133e59c1c98SArd Biesheuvel 	 * | 0xb 0xd 0x9 0xe |   | x[3] |
134e59c1c98SArd Biesheuvel 	 *
135e59c1c98SArd Biesheuvel 	 * which can conveniently be reduced to
136e59c1c98SArd Biesheuvel 	 *
137e59c1c98SArd Biesheuvel 	 * | 0x2 0x3 0x1 0x1 |   | 0x5 0x0 0x4 0x0 |   | x[0] |
138e59c1c98SArd Biesheuvel 	 * | 0x1 0x2 0x3 0x1 |   | 0x0 0x5 0x0 0x4 |   | x[1] |
139e59c1c98SArd Biesheuvel 	 * | 0x1 0x1 0x2 0x3 | x | 0x4 0x0 0x5 0x0 | x | x[2] |
140e59c1c98SArd Biesheuvel 	 * | 0x3 0x1 0x1 0x2 |   | 0x0 0x4 0x0 0x5 |   | x[3] |
141e59c1c98SArd Biesheuvel 	 */
142e59c1c98SArd Biesheuvel 	u32 y = mul_by_x2(x);
143e59c1c98SArd Biesheuvel 
144e59c1c98SArd Biesheuvel 	return mix_columns(x ^ y ^ ror32(y, 16));
145e59c1c98SArd Biesheuvel }
146e59c1c98SArd Biesheuvel 
subshift(u32 in[],int pos)147e59c1c98SArd Biesheuvel static __always_inline u32 subshift(u32 in[], int pos)
148e59c1c98SArd Biesheuvel {
149e59c1c98SArd Biesheuvel 	return (aes_sbox[in[pos] & 0xff]) ^
150e59c1c98SArd Biesheuvel 	       (aes_sbox[(in[(pos + 1) % 4] >>  8) & 0xff] <<  8) ^
151e59c1c98SArd Biesheuvel 	       (aes_sbox[(in[(pos + 2) % 4] >> 16) & 0xff] << 16) ^
152e59c1c98SArd Biesheuvel 	       (aes_sbox[(in[(pos + 3) % 4] >> 24) & 0xff] << 24);
153e59c1c98SArd Biesheuvel }
154e59c1c98SArd Biesheuvel 
inv_subshift(u32 in[],int pos)155e59c1c98SArd Biesheuvel static __always_inline u32 inv_subshift(u32 in[], int pos)
156e59c1c98SArd Biesheuvel {
157e59c1c98SArd Biesheuvel 	return (aes_inv_sbox[in[pos] & 0xff]) ^
158e59c1c98SArd Biesheuvel 	       (aes_inv_sbox[(in[(pos + 3) % 4] >>  8) & 0xff] <<  8) ^
159e59c1c98SArd Biesheuvel 	       (aes_inv_sbox[(in[(pos + 2) % 4] >> 16) & 0xff] << 16) ^
160e59c1c98SArd Biesheuvel 	       (aes_inv_sbox[(in[(pos + 1) % 4] >> 24) & 0xff] << 24);
161e59c1c98SArd Biesheuvel }
162e59c1c98SArd Biesheuvel 
subw(u32 in)163e59c1c98SArd Biesheuvel static u32 subw(u32 in)
164e59c1c98SArd Biesheuvel {
165e59c1c98SArd Biesheuvel 	return (aes_sbox[in & 0xff]) ^
166e59c1c98SArd Biesheuvel 	       (aes_sbox[(in >>  8) & 0xff] <<  8) ^
167e59c1c98SArd Biesheuvel 	       (aes_sbox[(in >> 16) & 0xff] << 16) ^
168e59c1c98SArd Biesheuvel 	       (aes_sbox[(in >> 24) & 0xff] << 24);
169e59c1c98SArd Biesheuvel }
170e59c1c98SArd Biesheuvel 
171e59c1c98SArd Biesheuvel /**
172e59c1c98SArd Biesheuvel  * aes_expandkey - Expands the AES key as described in FIPS-197
173e59c1c98SArd Biesheuvel  * @ctx:	The location where the computed key will be stored.
174e59c1c98SArd Biesheuvel  * @in_key:	The supplied key.
175e59c1c98SArd Biesheuvel  * @key_len:	The length of the supplied key.
176e59c1c98SArd Biesheuvel  *
177e59c1c98SArd Biesheuvel  * Returns 0 on success. The function fails only if an invalid key size (or
178e59c1c98SArd Biesheuvel  * pointer) is supplied.
179e59c1c98SArd Biesheuvel  * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes
180e59c1c98SArd Biesheuvel  * key schedule plus a 16 bytes key which is used before the first round).
181e59c1c98SArd Biesheuvel  * The decryption key is prepared for the "Equivalent Inverse Cipher" as
182e59c1c98SArd Biesheuvel  * described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is
183e59c1c98SArd Biesheuvel  * for the initial combination, the second slot for the first round and so on.
184e59c1c98SArd Biesheuvel  */
aes_expandkey(struct crypto_aes_ctx * ctx,const u8 * in_key,unsigned int key_len)185e59c1c98SArd Biesheuvel int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
186e59c1c98SArd Biesheuvel 		  unsigned int key_len)
187e59c1c98SArd Biesheuvel {
188e59c1c98SArd Biesheuvel 	u32 kwords = key_len / sizeof(u32);
189e59c1c98SArd Biesheuvel 	u32 rc, i, j;
190*bc67d04eSIuliana Prodan 	int err;
191e59c1c98SArd Biesheuvel 
192*bc67d04eSIuliana Prodan 	err = aes_check_keylen(key_len);
193*bc67d04eSIuliana Prodan 	if (err)
194*bc67d04eSIuliana Prodan 		return err;
195e59c1c98SArd Biesheuvel 
196e59c1c98SArd Biesheuvel 	ctx->key_length = key_len;
197e59c1c98SArd Biesheuvel 
198e59c1c98SArd Biesheuvel 	for (i = 0; i < kwords; i++)
199e59c1c98SArd Biesheuvel 		ctx->key_enc[i] = get_unaligned_le32(in_key + i * sizeof(u32));
200e59c1c98SArd Biesheuvel 
201e59c1c98SArd Biesheuvel 	for (i = 0, rc = 1; i < 10; i++, rc = mul_by_x(rc)) {
202e59c1c98SArd Biesheuvel 		u32 *rki = ctx->key_enc + (i * kwords);
203e59c1c98SArd Biesheuvel 		u32 *rko = rki + kwords;
204e59c1c98SArd Biesheuvel 
205e59c1c98SArd Biesheuvel 		rko[0] = ror32(subw(rki[kwords - 1]), 8) ^ rc ^ rki[0];
206e59c1c98SArd Biesheuvel 		rko[1] = rko[0] ^ rki[1];
207e59c1c98SArd Biesheuvel 		rko[2] = rko[1] ^ rki[2];
208e59c1c98SArd Biesheuvel 		rko[3] = rko[2] ^ rki[3];
209e59c1c98SArd Biesheuvel 
210e59c1c98SArd Biesheuvel 		if (key_len == AES_KEYSIZE_192) {
211e59c1c98SArd Biesheuvel 			if (i >= 7)
212e59c1c98SArd Biesheuvel 				break;
213e59c1c98SArd Biesheuvel 			rko[4] = rko[3] ^ rki[4];
214e59c1c98SArd Biesheuvel 			rko[5] = rko[4] ^ rki[5];
215e59c1c98SArd Biesheuvel 		} else if (key_len == AES_KEYSIZE_256) {
216e59c1c98SArd Biesheuvel 			if (i >= 6)
217e59c1c98SArd Biesheuvel 				break;
218e59c1c98SArd Biesheuvel 			rko[4] = subw(rko[3]) ^ rki[4];
219e59c1c98SArd Biesheuvel 			rko[5] = rko[4] ^ rki[5];
220e59c1c98SArd Biesheuvel 			rko[6] = rko[5] ^ rki[6];
221e59c1c98SArd Biesheuvel 			rko[7] = rko[6] ^ rki[7];
222e59c1c98SArd Biesheuvel 		}
223e59c1c98SArd Biesheuvel 	}
224e59c1c98SArd Biesheuvel 
225e59c1c98SArd Biesheuvel 	/*
226e59c1c98SArd Biesheuvel 	 * Generate the decryption keys for the Equivalent Inverse Cipher.
227e59c1c98SArd Biesheuvel 	 * This involves reversing the order of the round keys, and applying
228e59c1c98SArd Biesheuvel 	 * the Inverse Mix Columns transformation to all but the first and
229e59c1c98SArd Biesheuvel 	 * the last one.
230e59c1c98SArd Biesheuvel 	 */
231e59c1c98SArd Biesheuvel 	ctx->key_dec[0] = ctx->key_enc[key_len + 24];
232e59c1c98SArd Biesheuvel 	ctx->key_dec[1] = ctx->key_enc[key_len + 25];
233e59c1c98SArd Biesheuvel 	ctx->key_dec[2] = ctx->key_enc[key_len + 26];
234e59c1c98SArd Biesheuvel 	ctx->key_dec[3] = ctx->key_enc[key_len + 27];
235e59c1c98SArd Biesheuvel 
236e59c1c98SArd Biesheuvel 	for (i = 4, j = key_len + 20; j > 0; i += 4, j -= 4) {
237e59c1c98SArd Biesheuvel 		ctx->key_dec[i]     = inv_mix_columns(ctx->key_enc[j]);
238e59c1c98SArd Biesheuvel 		ctx->key_dec[i + 1] = inv_mix_columns(ctx->key_enc[j + 1]);
239e59c1c98SArd Biesheuvel 		ctx->key_dec[i + 2] = inv_mix_columns(ctx->key_enc[j + 2]);
240e59c1c98SArd Biesheuvel 		ctx->key_dec[i + 3] = inv_mix_columns(ctx->key_enc[j + 3]);
241e59c1c98SArd Biesheuvel 	}
242e59c1c98SArd Biesheuvel 
243e59c1c98SArd Biesheuvel 	ctx->key_dec[i]     = ctx->key_enc[0];
244e59c1c98SArd Biesheuvel 	ctx->key_dec[i + 1] = ctx->key_enc[1];
245e59c1c98SArd Biesheuvel 	ctx->key_dec[i + 2] = ctx->key_enc[2];
246e59c1c98SArd Biesheuvel 	ctx->key_dec[i + 3] = ctx->key_enc[3];
247e59c1c98SArd Biesheuvel 
248e59c1c98SArd Biesheuvel 	return 0;
249e59c1c98SArd Biesheuvel }
250e59c1c98SArd Biesheuvel EXPORT_SYMBOL(aes_expandkey);
251e59c1c98SArd Biesheuvel 
252e59c1c98SArd Biesheuvel /**
253e59c1c98SArd Biesheuvel  * aes_encrypt - Encrypt a single AES block
254e59c1c98SArd Biesheuvel  * @ctx:	Context struct containing the key schedule
255e59c1c98SArd Biesheuvel  * @out:	Buffer to store the ciphertext
256e59c1c98SArd Biesheuvel  * @in:		Buffer containing the plaintext
257e59c1c98SArd Biesheuvel  */
aes_encrypt(const struct crypto_aes_ctx * ctx,u8 * out,const u8 * in)258e59c1c98SArd Biesheuvel void aes_encrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in)
259e59c1c98SArd Biesheuvel {
260e59c1c98SArd Biesheuvel 	const u32 *rkp = ctx->key_enc + 4;
261e59c1c98SArd Biesheuvel 	int rounds = 6 + ctx->key_length / 4;
262e59c1c98SArd Biesheuvel 	u32 st0[4], st1[4];
263e59c1c98SArd Biesheuvel 	int round;
264e59c1c98SArd Biesheuvel 
265e59c1c98SArd Biesheuvel 	st0[0] = ctx->key_enc[0] ^ get_unaligned_le32(in);
266e59c1c98SArd Biesheuvel 	st0[1] = ctx->key_enc[1] ^ get_unaligned_le32(in + 4);
267e59c1c98SArd Biesheuvel 	st0[2] = ctx->key_enc[2] ^ get_unaligned_le32(in + 8);
268e59c1c98SArd Biesheuvel 	st0[3] = ctx->key_enc[3] ^ get_unaligned_le32(in + 12);
269e59c1c98SArd Biesheuvel 
270e59c1c98SArd Biesheuvel 	/*
271e59c1c98SArd Biesheuvel 	 * Force the compiler to emit data independent Sbox references,
272e59c1c98SArd Biesheuvel 	 * by xoring the input with Sbox values that are known to add up
273e59c1c98SArd Biesheuvel 	 * to zero. This pulls the entire Sbox into the D-cache before any
274e59c1c98SArd Biesheuvel 	 * data dependent lookups are done.
275e59c1c98SArd Biesheuvel 	 */
276e59c1c98SArd Biesheuvel 	st0[0] ^= aes_sbox[ 0] ^ aes_sbox[ 64] ^ aes_sbox[134] ^ aes_sbox[195];
277e59c1c98SArd Biesheuvel 	st0[1] ^= aes_sbox[16] ^ aes_sbox[ 82] ^ aes_sbox[158] ^ aes_sbox[221];
278e59c1c98SArd Biesheuvel 	st0[2] ^= aes_sbox[32] ^ aes_sbox[ 96] ^ aes_sbox[160] ^ aes_sbox[234];
279e59c1c98SArd Biesheuvel 	st0[3] ^= aes_sbox[48] ^ aes_sbox[112] ^ aes_sbox[186] ^ aes_sbox[241];
280e59c1c98SArd Biesheuvel 
281e59c1c98SArd Biesheuvel 	for (round = 0;; round += 2, rkp += 8) {
282e59c1c98SArd Biesheuvel 		st1[0] = mix_columns(subshift(st0, 0)) ^ rkp[0];
283e59c1c98SArd Biesheuvel 		st1[1] = mix_columns(subshift(st0, 1)) ^ rkp[1];
284e59c1c98SArd Biesheuvel 		st1[2] = mix_columns(subshift(st0, 2)) ^ rkp[2];
285e59c1c98SArd Biesheuvel 		st1[3] = mix_columns(subshift(st0, 3)) ^ rkp[3];
286e59c1c98SArd Biesheuvel 
287e59c1c98SArd Biesheuvel 		if (round == rounds - 2)
288e59c1c98SArd Biesheuvel 			break;
289e59c1c98SArd Biesheuvel 
290e59c1c98SArd Biesheuvel 		st0[0] = mix_columns(subshift(st1, 0)) ^ rkp[4];
291e59c1c98SArd Biesheuvel 		st0[1] = mix_columns(subshift(st1, 1)) ^ rkp[5];
292e59c1c98SArd Biesheuvel 		st0[2] = mix_columns(subshift(st1, 2)) ^ rkp[6];
293e59c1c98SArd Biesheuvel 		st0[3] = mix_columns(subshift(st1, 3)) ^ rkp[7];
294e59c1c98SArd Biesheuvel 	}
295e59c1c98SArd Biesheuvel 
296e59c1c98SArd Biesheuvel 	put_unaligned_le32(subshift(st1, 0) ^ rkp[4], out);
297e59c1c98SArd Biesheuvel 	put_unaligned_le32(subshift(st1, 1) ^ rkp[5], out + 4);
298e59c1c98SArd Biesheuvel 	put_unaligned_le32(subshift(st1, 2) ^ rkp[6], out + 8);
299e59c1c98SArd Biesheuvel 	put_unaligned_le32(subshift(st1, 3) ^ rkp[7], out + 12);
300e59c1c98SArd Biesheuvel }
301e59c1c98SArd Biesheuvel EXPORT_SYMBOL(aes_encrypt);
302e59c1c98SArd Biesheuvel 
303e59c1c98SArd Biesheuvel /**
304e59c1c98SArd Biesheuvel  * aes_decrypt - Decrypt a single AES block
305e59c1c98SArd Biesheuvel  * @ctx:	Context struct containing the key schedule
306e59c1c98SArd Biesheuvel  * @out:	Buffer to store the plaintext
307e59c1c98SArd Biesheuvel  * @in:		Buffer containing the ciphertext
308e59c1c98SArd Biesheuvel  */
aes_decrypt(const struct crypto_aes_ctx * ctx,u8 * out,const u8 * in)309e59c1c98SArd Biesheuvel void aes_decrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in)
310e59c1c98SArd Biesheuvel {
311e59c1c98SArd Biesheuvel 	const u32 *rkp = ctx->key_dec + 4;
312e59c1c98SArd Biesheuvel 	int rounds = 6 + ctx->key_length / 4;
313e59c1c98SArd Biesheuvel 	u32 st0[4], st1[4];
314e59c1c98SArd Biesheuvel 	int round;
315e59c1c98SArd Biesheuvel 
316e59c1c98SArd Biesheuvel 	st0[0] = ctx->key_dec[0] ^ get_unaligned_le32(in);
317e59c1c98SArd Biesheuvel 	st0[1] = ctx->key_dec[1] ^ get_unaligned_le32(in + 4);
318e59c1c98SArd Biesheuvel 	st0[2] = ctx->key_dec[2] ^ get_unaligned_le32(in + 8);
319e59c1c98SArd Biesheuvel 	st0[3] = ctx->key_dec[3] ^ get_unaligned_le32(in + 12);
320e59c1c98SArd Biesheuvel 
321e59c1c98SArd Biesheuvel 	/*
322e59c1c98SArd Biesheuvel 	 * Force the compiler to emit data independent Sbox references,
323e59c1c98SArd Biesheuvel 	 * by xoring the input with Sbox values that are known to add up
324e59c1c98SArd Biesheuvel 	 * to zero. This pulls the entire Sbox into the D-cache before any
325e59c1c98SArd Biesheuvel 	 * data dependent lookups are done.
326e59c1c98SArd Biesheuvel 	 */
327e59c1c98SArd Biesheuvel 	st0[0] ^= aes_inv_sbox[ 0] ^ aes_inv_sbox[ 64] ^ aes_inv_sbox[129] ^ aes_inv_sbox[200];
328e59c1c98SArd Biesheuvel 	st0[1] ^= aes_inv_sbox[16] ^ aes_inv_sbox[ 83] ^ aes_inv_sbox[150] ^ aes_inv_sbox[212];
329e59c1c98SArd Biesheuvel 	st0[2] ^= aes_inv_sbox[32] ^ aes_inv_sbox[ 96] ^ aes_inv_sbox[160] ^ aes_inv_sbox[236];
330e59c1c98SArd Biesheuvel 	st0[3] ^= aes_inv_sbox[48] ^ aes_inv_sbox[112] ^ aes_inv_sbox[187] ^ aes_inv_sbox[247];
331e59c1c98SArd Biesheuvel 
332e59c1c98SArd Biesheuvel 	for (round = 0;; round += 2, rkp += 8) {
333e59c1c98SArd Biesheuvel 		st1[0] = inv_mix_columns(inv_subshift(st0, 0)) ^ rkp[0];
334e59c1c98SArd Biesheuvel 		st1[1] = inv_mix_columns(inv_subshift(st0, 1)) ^ rkp[1];
335e59c1c98SArd Biesheuvel 		st1[2] = inv_mix_columns(inv_subshift(st0, 2)) ^ rkp[2];
336e59c1c98SArd Biesheuvel 		st1[3] = inv_mix_columns(inv_subshift(st0, 3)) ^ rkp[3];
337e59c1c98SArd Biesheuvel 
338e59c1c98SArd Biesheuvel 		if (round == rounds - 2)
339e59c1c98SArd Biesheuvel 			break;
340e59c1c98SArd Biesheuvel 
341e59c1c98SArd Biesheuvel 		st0[0] = inv_mix_columns(inv_subshift(st1, 0)) ^ rkp[4];
342e59c1c98SArd Biesheuvel 		st0[1] = inv_mix_columns(inv_subshift(st1, 1)) ^ rkp[5];
343e59c1c98SArd Biesheuvel 		st0[2] = inv_mix_columns(inv_subshift(st1, 2)) ^ rkp[6];
344e59c1c98SArd Biesheuvel 		st0[3] = inv_mix_columns(inv_subshift(st1, 3)) ^ rkp[7];
345e59c1c98SArd Biesheuvel 	}
346e59c1c98SArd Biesheuvel 
347e59c1c98SArd Biesheuvel 	put_unaligned_le32(inv_subshift(st1, 0) ^ rkp[4], out);
348e59c1c98SArd Biesheuvel 	put_unaligned_le32(inv_subshift(st1, 1) ^ rkp[5], out + 4);
349e59c1c98SArd Biesheuvel 	put_unaligned_le32(inv_subshift(st1, 2) ^ rkp[6], out + 8);
350e59c1c98SArd Biesheuvel 	put_unaligned_le32(inv_subshift(st1, 3) ^ rkp[7], out + 12);
351e59c1c98SArd Biesheuvel }
352e59c1c98SArd Biesheuvel EXPORT_SYMBOL(aes_decrypt);
353e59c1c98SArd Biesheuvel 
354e59c1c98SArd Biesheuvel MODULE_DESCRIPTION("Generic AES library");
355e59c1c98SArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
356e59c1c98SArd Biesheuvel MODULE_LICENSE("GPL v2");
357