blob: 6992f1c901e1bab2289c2f263f8a72b966624fcf [file] [log] [blame]
Denys Vlasenkob7e9ae62017-01-18 17:20:27 +01001/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
Denys Vlasenko6e99f1c2017-04-01 20:11:59 +02006
7/* This AES implementation is derived from tiny-AES128-C code,
8 * which was put by its author into public domain:
9 *
10 * tiny-AES128-C/unlicense.txt, Dec 8, 2014
11 * """
12 * This is free and unencumbered software released into the public domain.
13 *
14 * Anyone is free to copy, modify, publish, use, compile, sell, or
15 * distribute this software, either in source code form or as a compiled
16 * binary, for any purpose, commercial or non-commercial, and by any
17 * means.
18 *
19 * In jurisdictions that recognize copyright laws, the author or authors
20 * of this software dedicate any and all copyright interest in the
21 * software to the public domain. We make this dedication for the benefit
22 * of the public at large and to the detriment of our heirs and
23 * successors. We intend this dedication to be an overt act of
24 * relinquishment in perpetuity of all present and future rights to this
25 * software under copyright law.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
30 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 * """
35 */
36/* Note that only original tiny-AES128-C code is public domain.
37 * The derived code in this file has been expanded to also implement aes192
38 * and aes256 and use more efficient word-sized operations in many places,
39 * and put under GPLv2 license.
40 */
Denys Vlasenkob7e9ae62017-01-18 17:20:27 +010041#include "tls.h"
42
Denys Vlasenko6e99f1c2017-04-01 20:11:59 +020043/* TODO: grep for this and move to libbb */
44#define get_unaligned_be32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_BE32(v); })
45
46
47// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
48// The numbers below can be computed dynamically trading ROM for RAM -
49// This can be useful in (embedded) bootloader applications, where ROM is often limited.
50static const uint8_t sbox[] = {
51 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
52 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
53 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
54 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
55 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
56 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
57 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
58 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
59 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
60 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
61 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
62 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
63 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
64 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
65 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
66 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
67 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
68 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
69 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
70 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
71 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
72 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
73 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
74 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
75 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
76 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
77 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
78 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
79 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
80 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
81 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
82 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
83};
84
85static const uint8_t rsbox[] = {
86 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
87 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
88 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
89 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
90 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
91 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
92 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
93 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
94 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
95 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
96 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
97 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
98 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
99 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
100 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
101 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
102 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
103 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
104 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
105 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
106 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
107 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
108 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
109 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
110 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
111 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
112 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
113 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
114 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
115 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
116 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
117 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
118};
119
120// SubWord() is a function that takes a four-byte input word and
121// applies the S-box to each of the four bytes to produce an output word.
122static uint32_t Subword(uint32_t x)
123{
124 return (sbox[(x >> 24) ] << 24)
125 | (sbox[(x >> 16) & 255] << 16)
126 | (sbox[(x >> 8 ) & 255] << 8 )
127 | (sbox[(x ) & 255] );
128}
129
130// This function produces Nb(Nr+1) round keys.
131// The round keys are used in each round to decrypt the states.
132static int KeyExpansion(uint32_t *RoundKey, const void *key, unsigned key_len)
133{
134 // The round constant word array, Rcon[i], contains the values given by
135 // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8).
136 // Note that i starts at 2, not 0.
137 static const uint8_t Rcon[] = {
138 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
139 //..... 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6,...
140 // but aes256 only uses values up to 0x36
141 };
142 int rounds, words_key, words_RoundKey;
143 int i, j, k;
144
145 // key_len 16: aes128, rounds 10, words_key 4, words_RoundKey 44
146 // key_len 24: aes192, rounds 12, words_key 6, words_RoundKey 52
147 // key_len 32: aes256, rounds 14, words_key 8, words_RoundKey 60
148 words_key = key_len / 4;
149 rounds = 6 + (key_len / 4);
150 words_RoundKey = 28 + key_len;
151
152 // The first round key is the key itself.
153 for (i = 0; i < words_key; i++)
154 RoundKey[i] = get_unaligned_be32((uint32_t*)key + i);
155 // i == words_key now
156
157 // All other round keys are found from the previous round keys.
158 j = k = 0;
159 for (; i < words_RoundKey; i++) {
160 uint32_t tempa;
161
162 tempa = RoundKey[i - 1];
163 if (j == 0) {
164 // RotWord(): rotates the 4 bytes in a word to the left once.
165 tempa = (tempa << 8) | (tempa >> 24);
166 tempa = Subword(tempa);
167 tempa ^= (uint32_t)Rcon[k] << 24;
168 } else if (words_key > 6 && j == 4) {
169 tempa = Subword(tempa);
170 }
171 RoundKey[i] = RoundKey[i - words_key] ^ tempa;
172 j++;
173 if (j == words_key) {
174 j = 0;
175 k++;
176 }
177 }
178 return rounds;
179}
180
181// This function adds the round key to state.
182// The round key is added to the state by an XOR function.
183static void AddRoundKey(unsigned astate[16], const uint32_t *RoundKeys)
184{
185 int i;
186
187 for (i = 0; i < 16; i += 4) {
188 uint32_t n = *RoundKeys++;
189 astate[i + 0] ^= (n >> 24);
190 astate[i + 1] ^= (n >> 16) & 255;
191 astate[i + 2] ^= (n >> 8) & 255;
192 astate[i + 3] ^= n & 255;
193 }
194}
195
196// The SubBytes Function Substitutes the values in the
197// state matrix with values in an S-box.
198static void SubBytes(unsigned astate[16])
199{
200 int i;
201
202 for (i = 0; i < 16; i++)
203 astate[i] = sbox[astate[i]];
204}
205
206// Our code actually stores "columns" (in aes encryption terminology)
207// of state in rows: first 4 elements are "row 0, col 0", "row 1, col 0".
208// "row 2, col 0", "row 3, col 0". The fifth element is "row 0, col 1",
209// and so on.
210#define ASTATE(col,row) astate[(col)*4 + (row)]
211
212// The ShiftRows() function shifts the rows in the state to the left.
213// Each row is shifted with different offset.
214// Offset = Row number. So the first row is not shifted.
215static void ShiftRows(unsigned astate[16])
216{
217 unsigned v;
218
219 // Rotate first row 1 columns to left
220 v = ASTATE(0,1);
221 ASTATE(0,1) = ASTATE(1,1);
222 ASTATE(1,1) = ASTATE(2,1);
223 ASTATE(2,1) = ASTATE(3,1);
224 ASTATE(3,1) = v;
225
226 // Rotate second row 2 columns to left
227 v = ASTATE(0,2); ASTATE(0,2) = ASTATE(2,2); ASTATE(2,2) = v;
228 v = ASTATE(1,2); ASTATE(1,2) = ASTATE(3,2); ASTATE(3,2) = v;
229
230 // Rotate third row 3 columns to left
231 v = ASTATE(3,3);
232 ASTATE(3,3) = ASTATE(2,3);
233 ASTATE(2,3) = ASTATE(1,3);
234 ASTATE(1,3) = ASTATE(0,3);
235 ASTATE(0,3) = v;
236}
237
238// MixColumns function mixes the columns of the state matrix
239static void MixColumns(unsigned astate[16])
240{
241 int i;
242
243 for (i = 0; i < 16; i += 4) {
244 unsigned a, b, c, d;
245 unsigned x, y, z, t;
246
247 a = astate[i + 0];
248 b = astate[i + 1];
249 c = astate[i + 2];
250 d = astate[i + 3];
251 x = (a << 1) ^ b ^ (b << 1) ^ c ^ d;
252 y = a ^ (b << 1) ^ c ^ (c << 1) ^ d;
253 z = a ^ b ^ (c << 1) ^ d ^ (d << 1);
254 t = a ^ (a << 1) ^ b ^ c ^ (d << 1);
255 astate[i + 0] = x ^ ((-(int)(x >> 8)) & 0x11b);
256 astate[i + 1] = y ^ ((-(int)(y >> 8)) & 0x11b);
257 astate[i + 2] = z ^ ((-(int)(z >> 8)) & 0x11b);
258 astate[i + 3] = t ^ ((-(int)(t >> 8)) & 0x11b);
259 }
260}
261
262// The SubBytes Function Substitutes the values in the
263// state matrix with values in an S-box.
264static void InvSubBytes(unsigned astate[16])
265{
266 int i;
267
268 for (i = 0; i < 16; i++)
269 astate[i] = rsbox[astate[i]];
270}
271
272static void InvShiftRows(unsigned astate[16])
273{
274 unsigned v;
275
276 // Rotate first row 1 columns to right
277 v = ASTATE(3,1);
278 ASTATE(3,1) = ASTATE(2,1);
279 ASTATE(2,1) = ASTATE(1,1);
280 ASTATE(1,1) = ASTATE(0,1);
281 ASTATE(0,1) = v;
282
283 // Rotate second row 2 columns to right
284 v = ASTATE(0,2); ASTATE(0,2) = ASTATE(2,2); ASTATE(2,2) = v;
285 v = ASTATE(1,2); ASTATE(1,2) = ASTATE(3,2); ASTATE(3,2) = v;
286
287 // Rotate third row 3 columns to right
288 v = ASTATE(0,3);
289 ASTATE(0,3) = ASTATE(1,3);
290 ASTATE(1,3) = ASTATE(2,3);
291 ASTATE(2,3) = ASTATE(3,3);
292 ASTATE(3,3) = v;
293}
294
295static ALWAYS_INLINE unsigned Multiply(unsigned x)
296{
297 unsigned y;
298
299 y = x >> 8;
300 return (x ^ y ^ (y << 1) ^ (y << 3) ^ (y << 4)) & 255;
301}
302
303// MixColumns function mixes the columns of the state matrix.
304// The method used to multiply may be difficult to understand for the inexperienced.
305// Please use the references to gain more information.
306static void InvMixColumns(unsigned astate[16])
307{
308 int i;
309
310 for (i = 0; i < 16; i += 4) {
311 unsigned a, b, c, d;
312 unsigned x, y, z, t;
313
314 a = astate[i + 0];
315 b = astate[i + 1];
316 c = astate[i + 2];
317 d = astate[i + 3];
318 x = (a << 1) ^ (a << 2) ^ (a << 3) ^ b ^ (b << 1) ^ (b << 3)
319 /***/ ^ c ^ (c << 2) ^ (c << 3) ^ d ^ (d << 3);
320 y = a ^ (a << 3) ^ (b << 1) ^ (b << 2) ^ (b << 3)
321 /***/ ^ c ^ (c << 1) ^ (c << 3) ^ d ^ (d << 2) ^ (d << 3);
322 z = a ^ (a << 2) ^ (a << 3) ^ b ^ (b << 3)
323 /***/ ^ (c << 1) ^ (c << 2) ^ (c << 3) ^ d ^ (d << 1) ^ (d << 3);
324 t = a ^ (a << 1) ^ (a << 3) ^ b ^ (b << 2) ^ (b << 3)
325 /***/ ^ c ^ (c << 3) ^ (d << 1) ^ (d << 2) ^ (d << 3);
326 astate[i + 0] = Multiply(x);
327 astate[i + 1] = Multiply(y);
328 astate[i + 2] = Multiply(z);
329 astate[i + 3] = Multiply(t);
330 }
331}
332
333static void aes_encrypt_1(unsigned astate[16], unsigned rounds, const uint32_t *RoundKey)
334{
335 for (;;) {
336 AddRoundKey(astate, RoundKey);
337 RoundKey += 4;
338 SubBytes(astate);
339 ShiftRows(astate);
340 if (--rounds == 0)
341 break;
342 MixColumns(astate);
343 }
344 AddRoundKey(astate, RoundKey);
345}
346
347#if 0 // UNUSED
348static void aes_encrypt_one_block(unsigned rounds, const uint32_t *RoundKey, const void *data, void *dst)
349{
350 unsigned astate[16];
351 unsigned i;
352
353 const uint8_t *pt = data;
354 uint8_t *ct = dst;
355
356 for (i = 0; i < 16; i++)
357 astate[i] = pt[i];
358 aes_encrypt_1(astate, rounds, RoundKey);
359 for (i = 0; i < 16; i++)
360 ct[i] = astate[i];
361}
362#endif
Denys Vlasenkoc31b54f2017-02-04 16:23:49 +0100363
364void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst)
365{
Denys Vlasenko6e99f1c2017-04-01 20:11:59 +0200366 uint32_t RoundKey[60];
367 uint8_t iv2[16];
368 unsigned rounds;
369
370 const uint8_t *pt = data;
371 uint8_t *ct = dst;
372
373 memcpy(iv2, iv, 16);
374 rounds = KeyExpansion(RoundKey, key, klen);
375 while (len > 0) {
376 {
377 /* almost aes_encrypt_one_block(rounds, RoundKey, pt, ct);
378 * but xor'ing of IV with plaintext[] is combined
379 * with plaintext[] -> astate[]
380 */
381 int i;
382 unsigned astate[16];
383 for (i = 0; i < 16; i++)
384 astate[i] = pt[i] ^ iv2[i];
385 aes_encrypt_1(astate, rounds, RoundKey);
386 for (i = 0; i < 16; i++)
387 iv2[i] = ct[i] = astate[i];
388 }
389 ct += 16;
390 pt += 16;
391 len -= 16;
392 }
Denys Vlasenkoc31b54f2017-02-04 16:23:49 +0100393}
394
Denys Vlasenko6e99f1c2017-04-01 20:11:59 +0200395static void aes_decrypt_1(unsigned astate[16], unsigned rounds, const uint32_t *RoundKey)
396{
397 RoundKey += rounds * 4;
398 AddRoundKey(astate, RoundKey);
399 for (;;) {
400 InvShiftRows(astate);
401 InvSubBytes(astate);
402 RoundKey -= 4;
403 AddRoundKey(astate, RoundKey);
404 if (--rounds == 0)
405 break;
406 InvMixColumns(astate);
407 }
408}
409
410#if 0 //UNUSED
411static void aes_decrypt_one_block(unsigned rounds, const uint32_t *RoundKey, const void *data, void *dst)
412{
413 unsigned astate[16];
414 unsigned i;
415
416 const uint8_t *ct = data;
417 uint8_t *pt = dst;
418
419 for (i = 0; i < 16; i++)
420 astate[i] = ct[i];
421 aes_decrypt_1(astate, rounds, RoundKey);
422 for (i = 0; i < 16; i++)
423 pt[i] = astate[i];
424}
425#endif
426
Denys Vlasenkoc31b54f2017-02-04 16:23:49 +0100427void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst)
428{
Denys Vlasenko6e99f1c2017-04-01 20:11:59 +0200429 uint32_t RoundKey[60];
430 uint8_t iv2[16];
431 uint8_t iv3[16];
432 unsigned rounds;
433 uint8_t *ivbuf;
434 uint8_t *ivnext;
Denys Vlasenkoc31b54f2017-02-04 16:23:49 +0100435
Denys Vlasenko6e99f1c2017-04-01 20:11:59 +0200436 const uint8_t *ct = data;
437 uint8_t *pt = dst;
Denys Vlasenkob7e9ae62017-01-18 17:20:27 +0100438
Denys Vlasenko6e99f1c2017-04-01 20:11:59 +0200439 rounds = KeyExpansion(RoundKey, key, klen);
440 ivbuf = memcpy(iv2, iv, 16);
441 while (len) {
442 ivnext = (ivbuf==iv2) ? iv3 : iv2;
443 {
444 /* almost aes_decrypt_one_block(rounds, RoundKey, ct, pt)
445 * but xor'ing of ivbuf is combined with astate[] -> plaintext[]
446 */
447 int i;
448 unsigned astate[16];
449 for (i = 0; i < 16; i++)
450 ivnext[i] = astate[i] = ct[i];
451 aes_decrypt_1(astate, rounds, RoundKey);
452 for (i = 0; i < 16; i++)
453 pt[i] = astate[i] ^ ivbuf[i];
Denys Vlasenkob7e9ae62017-01-18 17:20:27 +0100454 }
Denys Vlasenko6e99f1c2017-04-01 20:11:59 +0200455 ivbuf = ivnext;
456 ct += 16;
457 pt += 16;
458 len -= 16;
Denys Vlasenkob7e9ae62017-01-18 17:20:27 +0100459 }
Denys Vlasenkob7e9ae62017-01-18 17:20:27 +0100460}