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