1 /* ykaes.c --- Implementation of AES-128.
2 *
3 * Copyright (c) 2006-2013 Yubico AB
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32 #include "yubikey.h"
33
34 #define NUMBER_OF_ROUNDS 10
35
36 static const uint8_t RC[] =
37 { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 };
38
39 static const uint8_t rijndael_sbox[] = {
40 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
41 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
42 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
43 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
44 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
45 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
46 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
47 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
48 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
49 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
50 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
51 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
52 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
53 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
54 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
55 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
56 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
57 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
58 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
59 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
60 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
61 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
62 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
63 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
64 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
65 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
66 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
67 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
68 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
69 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
70 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
71 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
72 };
73
74 static const uint8_t rijndael_inv_sbox[] = {
75 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
76 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
77 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
78 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
79 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
80 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
81 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
82 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
83 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
84 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
85 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
86 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
87 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
88 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
89 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
90 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
91 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
92 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
93 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
94 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
95 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
96 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
97 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
98 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
99 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
100 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
101 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
102 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
103 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
104 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
105 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
106 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
107 };
108
109 static inline uint8_t
xtime(uint8_t b)110 xtime (uint8_t b)
111 {
112 return (b & 0x80) ? ((b << 1) ^ 0x1b) : (b << 1);
113 }
114
115 void
yubikey_aes_decrypt(uint8_t * state,const uint8_t * key)116 yubikey_aes_decrypt (uint8_t * state, const uint8_t * key)
117 {
118 uint8_t i, j, round_key[0x10];
119 uint8_t a02x, a13x;
120 uint8_t a02xx, a13xx;
121 uint8_t k1, k2;
122
123 memcpy (round_key, key, sizeof (round_key));
124 for (i = 0; i < NUMBER_OF_ROUNDS; i++)
125 {
126 round_key[0] ^= RC[i];
127
128 round_key[0] ^= rijndael_sbox[round_key[13]];
129 round_key[1] ^= rijndael_sbox[round_key[14]];
130 round_key[2] ^= rijndael_sbox[round_key[15]];
131 round_key[3] ^= rijndael_sbox[round_key[12]];
132
133 for (j = 4; j < 16; j++)
134 round_key[j] ^= round_key[j - 4];
135 }
136 for (i = 0; i < 0x10; i++)
137 state[i] ^= round_key[i];
138
139 for (i = 1; i <= NUMBER_OF_ROUNDS; i++)
140 {
141 /* First row: 0 shift, 0 4 8 12 */
142 state[0] = rijndael_inv_sbox[state[0]];
143 state[4] = rijndael_inv_sbox[state[4]];
144 state[8] = rijndael_inv_sbox[state[8]];
145 state[12] = rijndael_inv_sbox[state[12]];
146
147 /* Second row: -1 shift, 1 5 9 13 */
148 j = state[13];
149 state[13] = rijndael_inv_sbox[state[9]];
150 state[9] = rijndael_inv_sbox[state[5]];
151 state[5] = rijndael_inv_sbox[state[1]];
152 state[1] = rijndael_inv_sbox[j];
153
154 /* Third row: -2 shift, 2 6 10 14 */
155 j = state[2];
156 state[2] = rijndael_inv_sbox[state[10]];
157 state[10] = rijndael_inv_sbox[j];
158 j = state[6];
159 state[6] = rijndael_inv_sbox[state[14]];
160 state[14] = rijndael_inv_sbox[j];
161
162 /* Fourth row: -3 shift, 3 7 11 15 */
163 j = state[3];
164 state[3] = rijndael_inv_sbox[state[7]];
165 state[7] = rijndael_inv_sbox[state[11]];
166 state[11] = rijndael_inv_sbox[state[15]];
167 state[15] = rijndael_inv_sbox[j];
168
169 for (j = 15; j > 3; j--)
170 round_key[j] ^= round_key[j - 4];
171
172 round_key[0] ^=
173 (RC[NUMBER_OF_ROUNDS - i] ^ rijndael_sbox[round_key[13]]);
174
175 round_key[1] ^= rijndael_sbox[round_key[14]];
176 round_key[2] ^= rijndael_sbox[round_key[15]];
177 round_key[3] ^= rijndael_sbox[round_key[12]];
178
179 for (j = 0; j < 16; j++)
180 state[j] ^= round_key[j];
181 if (i != NUMBER_OF_ROUNDS)
182 {
183 for (j = 0; j < 16; j += 4)
184 {
185 k1 = state[j] ^ state[j + 2];
186 a02x = xtime (k1);
187 k2 = state[j + 1] ^ state[j + 3];
188 a13x = xtime (k2);
189
190 k1 ^= (k2 ^ xtime (state[j + 1] ^ state[j + 2]));
191 k2 = k1;
192
193 a02xx = xtime (a02x);
194 a13xx = xtime (a13x);
195
196 k1 ^= (xtime (a02xx ^ a13xx) ^ a02xx);
197 k2 ^= (xtime (a02xx ^ a13xx) ^ a13xx);
198
199 state[j] ^= (k1 ^ a02x);
200 state[j + 1] ^= k2;
201 state[j + 2] ^= (k1 ^ a13x);
202 state[j + 3] ^= (k2 ^ a02x ^ a13x);
203 }
204 }
205
206 }
207 }
208
209
210 /*******************************************************************
211 function aesEncrypt encrypts a single AES-128 block
212
213 void aesEncrypt(unsigned char *state, const unsigned char *key)
214
215 Where:
216 "state" is state buffer, i.e. plaintext in, ciphertext out
217 "key" is pointer to AES key
218
219 *************************************************************************/
220
221 void
yubikey_aes_encrypt(uint8_t * state,const uint8_t * key)222 yubikey_aes_encrypt (uint8_t * state, const uint8_t * key)
223 {
224 unsigned char i, j, k, tmp, round_key[0x10];
225
226 memcpy (round_key, key, sizeof (round_key));
227
228 for (i = 0; i < 16; i++)
229 state[i] ^= key[i];
230
231 for (i = 0; i < NUMBER_OF_ROUNDS; i++)
232 {
233 /* First row: 0 shift, 0 4 8 12 */
234 state[0] = rijndael_sbox[state[0]];
235 state[4] = rijndael_sbox[state[4]];
236 state[8] = rijndael_sbox[state[8]];
237 state[12] = rijndael_sbox[state[12]];
238
239 /* Second row: 1 shift, 1 5 9 13 */
240 tmp = state[1];
241 state[1] = rijndael_sbox[state[5]];
242 state[5] = rijndael_sbox[state[9]];
243 state[9] = rijndael_sbox[state[13]];
244 state[13] = rijndael_sbox[tmp];
245
246 /* Third row: 2 shift, 2 6 10 14 */
247 tmp = state[2];
248 state[2] = rijndael_sbox[state[10]];
249 state[10] = rijndael_sbox[tmp];
250 tmp = state[6];
251 state[6] = rijndael_sbox[state[14]];
252 state[14] = rijndael_sbox[tmp];
253
254 /* Fourth row: 3 shift, 3 7 11 15 */
255 tmp = state[15];
256 state[15] = rijndael_sbox[state[11]];
257 state[11] = rijndael_sbox[state[7]];
258 state[7] = rijndael_sbox[state[3]];
259 state[3] = rijndael_sbox[tmp];
260
261 if (i != (NUMBER_OF_ROUNDS - 1))
262 {
263 for (k = 0; k < 16; k += 4)
264 {
265
266 j = state[k] ^ state[k + 1];
267 tmp = j ^ state[k + 2] ^ state[k + 3];
268
269 j = xtime (j);
270
271 state[k] ^= (j ^ tmp);
272
273 j = state[k + 1] ^ state[k + 2];
274 j = xtime (j);
275
276 state[k + 1] ^= (j ^ tmp);
277
278 j = state[k + 2] ^ state[k + 3];
279 j = xtime (j);
280
281 state[k + 2] ^= (j ^ tmp);
282 state[k + 3] = state[k] ^ state[k + 1] ^ state[k + 2] ^ tmp;
283 }
284 }
285
286 round_key[0] ^= RC[i];
287
288 round_key[0] ^= rijndael_sbox[round_key[13]];
289 round_key[1] ^= rijndael_sbox[round_key[14]];
290 round_key[2] ^= rijndael_sbox[round_key[15]];
291 round_key[3] ^= rijndael_sbox[round_key[12]];
292
293 for (k = 4; k < 16; k++)
294 round_key[k] ^= round_key[k - 4];
295
296 for (j = 0; j < 16; j++)
297 state[j] ^= round_key[j];
298 }
299 }
300