1 /* ykaes.c --- Implementation of AES-128.
2 *
3 * Copyright (c) 2006, 2007, 2008, 2009 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 unsigned char RC[] =
37 { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 };
38
39 static const unsigned char 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 unsigned char 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 /* Called by: yubikey_aes_decrypt x7 */
110 static /*inline*/ unsigned char
xtime(unsigned char b)111 xtime (unsigned char b)
112 {
113 return (b & 0x80) ? ((b << 1) ^ 0x1b) : (b << 1);
114 }
115
116 /* Called by: authn_user, zx_yubikey_authn */
117 void
yubikey_aes_decrypt(unsigned char * state,const unsigned char * key)118 yubikey_aes_decrypt (unsigned char * state, const unsigned char * key)
119 {
120 unsigned char i, j, round_key[0x10];
121 unsigned char a02x, a13x;
122 unsigned char a02xx, a13xx;
123 unsigned char k1, k2;
124
125 memcpy (round_key, key, sizeof (round_key));
126 for (i = 0; i < NUMBER_OF_ROUNDS; i++)
127 {
128 round_key[0] ^= RC[i];
129
130 round_key[0] ^= rijndael_sbox[round_key[13]];
131 round_key[1] ^= rijndael_sbox[round_key[14]];
132 round_key[2] ^= rijndael_sbox[round_key[15]];
133 round_key[3] ^= rijndael_sbox[round_key[12]];
134
135 for (j = 4; j < 16; j++)
136 round_key[j] ^= round_key[j - 4];
137 }
138 for (i = 0; i < 0x10; i++)
139 state[i] ^= round_key[i];
140
141 for (i = 1; i <= NUMBER_OF_ROUNDS; i++)
142 {
143 // inv_byte_sub_shift_row();
144
145 /* First row: 0 shift, 0 4 8 12 */
146 state[0] = rijndael_inv_sbox[state[0]];
147 state[4] = rijndael_inv_sbox[state[4]];
148 state[8] = rijndael_inv_sbox[state[8]];
149 state[12] = rijndael_inv_sbox[state[12]];
150
151 /* Second row: -1 shift, 1 5 9 13 */
152 j = state[13];
153 state[13] = rijndael_inv_sbox[state[9]];
154 state[9] = rijndael_inv_sbox[state[5]];
155 state[5] = rijndael_inv_sbox[state[1]];
156 state[1] = rijndael_inv_sbox[j];
157
158 /* Third row: -2 shift, 2 6 10 14 */
159 j = state[2];
160 state[2] = rijndael_inv_sbox[state[10]];
161 state[10] = rijndael_inv_sbox[j];
162 j = state[6];
163 state[6] = rijndael_inv_sbox[state[14]];
164 state[14] = rijndael_inv_sbox[j];
165
166 /* Fourth row: -3 shift, 3 7 11 15 */
167 j = state[3];
168 state[3] = rijndael_inv_sbox[state[7]];
169 state[7] = rijndael_inv_sbox[state[11]];
170 state[11] = rijndael_inv_sbox[state[15]];
171 state[15] = rijndael_inv_sbox[j];
172
173 // get_inv_round_key(i);
174
175 for (j = 15; j > 3; j--)
176 round_key[j] ^= round_key[j - 4];
177
178 round_key[0] ^=
179 (RC[NUMBER_OF_ROUNDS - i] ^ rijndael_sbox[round_key[13]]);
180
181 round_key[1] ^= rijndael_sbox[round_key[14]];
182 round_key[2] ^= rijndael_sbox[round_key[15]];
183 round_key[3] ^= rijndael_sbox[round_key[12]];
184
185 for (j = 0; j < 16; j++)
186 state[j] ^= round_key[j];
187 if (i != NUMBER_OF_ROUNDS)
188 {
189
190 //inv_mix_column();
191
192 for (j = 0; j < 16; j += 4)
193 {
194 k1 = state[j] ^ state[j + 2];
195 a02x = xtime (k1);
196 k2 = state[j + 1] ^ state[j + 3];
197 a13x = xtime (k2);
198
199 k1 ^= (k2 ^ xtime (state[j + 1] ^ state[j + 2]));
200 k2 = k1;
201
202 a02xx = xtime (a02x);
203 a13xx = xtime (a13x);
204
205 k1 ^= (xtime (a02xx ^ a13xx) ^ a02xx);
206 k2 ^= (xtime (a02xx ^ a13xx) ^ a13xx);
207
208 state[j] ^= (k1 ^ a02x);
209 state[j + 1] ^= k2;
210 state[j + 2] ^= (k1 ^ a13x);
211 state[j + 3] ^= (k2 ^ a02x ^ a13x);
212 }
213 }
214
215 }
216 }
217