xref: /openbmc/u-boot/lib/aes.c (revision 522de019)
1 /*
2  * Copyright (c) 2011 The Chromium OS Authors.
3  * (C) Copyright 2011 NVIDIA Corporation www.nvidia.com
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 /*
25  * advanced encryption standard
26  * author: karl malbrain, malbrain@yahoo.com
27  *
28  * This work, including the source code, documentation
29  * and related data, is placed into the public domain.
30  *
31  * The orginal author is Karl Malbrain.
32  *
33  * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
34  * OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
35  * MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
36  * ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
37  * RESULTING FROM THE USE, MODIFICATION, OR
38  * REDISTRIBUTION OF THIS SOFTWARE.
39 */
40 
41 #include <common.h>
42 #include "aes.h"
43 
44 /* forward s-box */
45 static const u8 sbox[256] = {
46 	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
47 	0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
48 	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
49 	0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
50 	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
51 	0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
52 	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
53 	0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
54 	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
55 	0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
56 	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
57 	0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
58 	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
59 	0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
60 	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
61 	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
62 	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
63 	0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
64 	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
65 	0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
66 	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
67 	0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
68 	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
69 	0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
70 	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
71 	0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
72 	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
73 	0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
74 	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
75 	0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
76 	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
77 	0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
78 };
79 
80 /* inverse s-box */
81 static const u8 inv_sbox[256] = {
82 	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
83 	0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
84 	0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
85 	0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
86 	0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
87 	0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
88 	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
89 	0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
90 	0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
91 	0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
92 	0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
93 	0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
94 	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
95 	0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
96 	0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
97 	0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
98 	0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
99 	0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
100 	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
101 	0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
102 	0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
103 	0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
104 	0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
105 	0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
106 	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
107 	0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
108 	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
109 	0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
110 	0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
111 	0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
112 	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
113 	0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
114 };
115 
116 /* combined Xtimes2[Sbox[]] */
117 static const u8 x2_sbox[256] = {
118 	0xc6, 0xf8, 0xee, 0xf6, 0xff, 0xd6, 0xde, 0x91,
119 	0x60, 0x02, 0xce, 0x56, 0xe7, 0xb5, 0x4d, 0xec,
120 	0x8f, 0x1f, 0x89, 0xfa, 0xef, 0xb2, 0x8e, 0xfb,
121 	0x41, 0xb3, 0x5f, 0x45, 0x23, 0x53, 0xe4, 0x9b,
122 	0x75, 0xe1, 0x3d, 0x4c, 0x6c, 0x7e, 0xf5, 0x83,
123 	0x68, 0x51, 0xd1, 0xf9, 0xe2, 0xab, 0x62, 0x2a,
124 	0x08, 0x95, 0x46, 0x9d, 0x30, 0x37, 0x0a, 0x2f,
125 	0x0e, 0x24, 0x1b, 0xdf, 0xcd, 0x4e, 0x7f, 0xea,
126 	0x12, 0x1d, 0x58, 0x34, 0x36, 0xdc, 0xb4, 0x5b,
127 	0xa4, 0x76, 0xb7, 0x7d, 0x52, 0xdd, 0x5e, 0x13,
128 	0xa6, 0xb9, 0x00, 0xc1, 0x40, 0xe3, 0x79, 0xb6,
129 	0xd4, 0x8d, 0x67, 0x72, 0x94, 0x98, 0xb0, 0x85,
130 	0xbb, 0xc5, 0x4f, 0xed, 0x86, 0x9a, 0x66, 0x11,
131 	0x8a, 0xe9, 0x04, 0xfe, 0xa0, 0x78, 0x25, 0x4b,
132 	0xa2, 0x5d, 0x80, 0x05, 0x3f, 0x21, 0x70, 0xf1,
133 	0x63, 0x77, 0xaf, 0x42, 0x20, 0xe5, 0xfd, 0xbf,
134 	0x81, 0x18, 0x26, 0xc3, 0xbe, 0x35, 0x88, 0x2e,
135 	0x93, 0x55, 0xfc, 0x7a, 0xc8, 0xba, 0x32, 0xe6,
136 	0xc0, 0x19, 0x9e, 0xa3, 0x44, 0x54, 0x3b, 0x0b,
137 	0x8c, 0xc7, 0x6b, 0x28, 0xa7, 0xbc, 0x16, 0xad,
138 	0xdb, 0x64, 0x74, 0x14, 0x92, 0x0c, 0x48, 0xb8,
139 	0x9f, 0xbd, 0x43, 0xc4, 0x39, 0x31, 0xd3, 0xf2,
140 	0xd5, 0x8b, 0x6e, 0xda, 0x01, 0xb1, 0x9c, 0x49,
141 	0xd8, 0xac, 0xf3, 0xcf, 0xca, 0xf4, 0x47, 0x10,
142 	0x6f, 0xf0, 0x4a, 0x5c, 0x38, 0x57, 0x73, 0x97,
143 	0xcb, 0xa1, 0xe8, 0x3e, 0x96, 0x61, 0x0d, 0x0f,
144 	0xe0, 0x7c, 0x71, 0xcc, 0x90, 0x06, 0xf7, 0x1c,
145 	0xc2, 0x6a, 0xae, 0x69, 0x17, 0x99, 0x3a, 0x27,
146 	0xd9, 0xeb, 0x2b, 0x22, 0xd2, 0xa9, 0x07, 0x33,
147 	0x2d, 0x3c, 0x15, 0xc9, 0x87, 0xaa, 0x50, 0xa5,
148 	0x03, 0x59, 0x09, 0x1a, 0x65, 0xd7, 0x84, 0xd0,
149 	0x82, 0x29, 0x5a, 0x1e, 0x7b, 0xa8, 0x6d, 0x2c
150 };
151 
152 /* combined Xtimes3[Sbox[]] */
153 static const u8 x3_sbox[256] = {
154 	0xa5, 0x84, 0x99, 0x8d, 0x0d, 0xbd, 0xb1, 0x54,
155 	0x50, 0x03, 0xa9, 0x7d, 0x19, 0x62, 0xe6, 0x9a,
156 	0x45, 0x9d, 0x40, 0x87, 0x15, 0xeb, 0xc9, 0x0b,
157 	0xec, 0x67, 0xfd, 0xea, 0xbf, 0xf7, 0x96, 0x5b,
158 	0xc2, 0x1c, 0xae, 0x6a, 0x5a, 0x41, 0x02, 0x4f,
159 	0x5c, 0xf4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3f,
160 	0x0c, 0x52, 0x65, 0x5e, 0x28, 0xa1, 0x0f, 0xb5,
161 	0x09, 0x36, 0x9b, 0x3d, 0x26, 0x69, 0xcd, 0x9f,
162 	0x1b, 0x9e, 0x74, 0x2e, 0x2d, 0xb2, 0xee, 0xfb,
163 	0xf6, 0x4d, 0x61, 0xce, 0x7b, 0x3e, 0x71, 0x97,
164 	0xf5, 0x68, 0x00, 0x2c, 0x60, 0x1f, 0xc8, 0xed,
165 	0xbe, 0x46, 0xd9, 0x4b, 0xde, 0xd4, 0xe8, 0x4a,
166 	0x6b, 0x2a, 0xe5, 0x16, 0xc5, 0xd7, 0x55, 0x94,
167 	0xcf, 0x10, 0x06, 0x81, 0xf0, 0x44, 0xba, 0xe3,
168 	0xf3, 0xfe, 0xc0, 0x8a, 0xad, 0xbc, 0x48, 0x04,
169 	0xdf, 0xc1, 0x75, 0x63, 0x30, 0x1a, 0x0e, 0x6d,
170 	0x4c, 0x14, 0x35, 0x2f, 0xe1, 0xa2, 0xcc, 0x39,
171 	0x57, 0xf2, 0x82, 0x47, 0xac, 0xe7, 0x2b, 0x95,
172 	0xa0, 0x98, 0xd1, 0x7f, 0x66, 0x7e, 0xab, 0x83,
173 	0xca, 0x29, 0xd3, 0x3c, 0x79, 0xe2, 0x1d, 0x76,
174 	0x3b, 0x56, 0x4e, 0x1e, 0xdb, 0x0a, 0x6c, 0xe4,
175 	0x5d, 0x6e, 0xef, 0xa6, 0xa8, 0xa4, 0x37, 0x8b,
176 	0x32, 0x43, 0x59, 0xb7, 0x8c, 0x64, 0xd2, 0xe0,
177 	0xb4, 0xfa, 0x07, 0x25, 0xaf, 0x8e, 0xe9, 0x18,
178 	0xd5, 0x88, 0x6f, 0x72, 0x24, 0xf1, 0xc7, 0x51,
179 	0x23, 0x7c, 0x9c, 0x21, 0xdd, 0xdc, 0x86, 0x85,
180 	0x90, 0x42, 0xc4, 0xaa, 0xd8, 0x05, 0x01, 0x12,
181 	0xa3, 0x5f, 0xf9, 0xd0, 0x91, 0x58, 0x27, 0xb9,
182 	0x38, 0x13, 0xb3, 0x33, 0xbb, 0x70, 0x89, 0xa7,
183 	0xb6, 0x22, 0x92, 0x20, 0x49, 0xff, 0x78, 0x7a,
184 	0x8f, 0xf8, 0x80, 0x17, 0xda, 0x31, 0xc6, 0xb8,
185 	0xc3, 0xb0, 0x77, 0x11, 0xcb, 0xfc, 0xd6, 0x3a
186 };
187 
188 /*
189  * modular multiplication tables based on:
190  *
191  * Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x)
192  * Xtime3[x] = x^Xtime2[x];
193  */
194 static const u8 x_time_9[256] = {
195 	0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
196 	0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
197 	0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf,
198 	0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
199 	0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
200 	0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
201 	0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94,
202 	0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
203 	0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49,
204 	0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
205 	0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9,
206 	0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
207 	0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72,
208 	0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
209 	0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2,
210 	0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
211 	0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3,
212 	0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
213 	0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43,
214 	0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
215 	0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8,
216 	0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
217 	0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78,
218 	0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
219 	0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5,
220 	0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
221 	0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35,
222 	0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
223 	0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e,
224 	0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
225 	0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e,
226 	0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
227 };
228 
229 static const u8 x_time_b[256] = {
230 	0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31,
231 	0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
232 	0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81,
233 	0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
234 	0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a,
235 	0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
236 	0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa,
237 	0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
238 	0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7,
239 	0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
240 	0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77,
241 	0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
242 	0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc,
243 	0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
244 	0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c,
245 	0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
246 	0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6,
247 	0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
248 	0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76,
249 	0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
250 	0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd,
251 	0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
252 	0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d,
253 	0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
254 	0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30,
255 	0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
256 	0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80,
257 	0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
258 	0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b,
259 	0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
260 	0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb,
261 	0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
262 };
263 
264 static const u8 x_time_d[256] = {
265 	0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23,
266 	0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
267 	0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3,
268 	0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
269 	0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98,
270 	0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
271 	0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48,
272 	0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
273 	0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e,
274 	0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
275 	0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e,
276 	0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
277 	0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5,
278 	0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
279 	0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25,
280 	0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
281 	0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9,
282 	0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
283 	0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29,
284 	0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
285 	0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42,
286 	0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
287 	0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92,
288 	0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
289 	0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94,
290 	0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
291 	0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44,
292 	0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
293 	0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f,
294 	0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
295 	0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff,
296 	0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
297 };
298 
299 static const u8 x_time_e[256] = {
300 	0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a,
301 	0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
302 	0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca,
303 	0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
304 	0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1,
305 	0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
306 	0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11,
307 	0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
308 	0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87,
309 	0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
310 	0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67,
311 	0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
312 	0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c,
313 	0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
314 	0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc,
315 	0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
316 	0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b,
317 	0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
318 	0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b,
319 	0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
320 	0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0,
321 	0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
322 	0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50,
323 	0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
324 	0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6,
325 	0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
326 	0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26,
327 	0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
328 	0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d,
329 	0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
330 	0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd,
331 	0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
332 };
333 
334 /*
335  * Exchanges columns in each of 4 rows
336  * row0 - unchanged, row1- shifted left 1,
337  * row2 - shifted left 2 and row3 - shifted left 3
338  */
339 static void shift_rows(u8 *state)
340 {
341 	u8 tmp;
342 
343 	/* just substitute row 0 */
344 	state[0] = sbox[state[0]];
345 	state[4] = sbox[state[4]];
346 	state[8] = sbox[state[8]];
347 	state[12] = sbox[state[12]];
348 
349 	/* rotate row 1 */
350 	tmp = sbox[state[1]];
351 	state[1] = sbox[state[5]];
352 	state[5] = sbox[state[9]];
353 	state[9] = sbox[state[13]];
354 	state[13] = tmp;
355 
356 	/* rotate row 2 */
357 	tmp = sbox[state[2]];
358 	state[2] = sbox[state[10]];
359 	state[10] = tmp;
360 	tmp = sbox[state[6]];
361 	state[6] = sbox[state[14]];
362 	state[14] = tmp;
363 
364 	/* rotate row 3 */
365 	tmp = sbox[state[15]];
366 	state[15] = sbox[state[11]];
367 	state[11] = sbox[state[7]];
368 	state[7] = sbox[state[3]];
369 	state[3] = tmp;
370 }
371 
372 /*
373  * restores columns in each of 4 rows
374  * row0 - unchanged, row1- shifted right 1,
375  * row2 - shifted right 2 and row3 - shifted right 3
376  */
377 static void inv_shift_rows(u8 *state)
378 {
379 	u8 tmp;
380 
381 	/* restore row 0 */
382 	state[0] = inv_sbox[state[0]];
383 	state[4] = inv_sbox[state[4]];
384 	state[8] = inv_sbox[state[8]];
385 	state[12] = inv_sbox[state[12]];
386 
387 	/* restore row 1 */
388 	tmp = inv_sbox[state[13]];
389 	state[13] = inv_sbox[state[9]];
390 	state[9] = inv_sbox[state[5]];
391 	state[5] = inv_sbox[state[1]];
392 	state[1] = tmp;
393 
394 	/* restore row 2 */
395 	tmp = inv_sbox[state[2]];
396 	state[2] = inv_sbox[state[10]];
397 	state[10] = tmp;
398 	tmp = inv_sbox[state[6]];
399 	state[6] = inv_sbox[state[14]];
400 	state[14] = tmp;
401 
402 	/* restore row 3 */
403 	tmp = inv_sbox[state[3]];
404 	state[3] = inv_sbox[state[7]];
405 	state[7] = inv_sbox[state[11]];
406 	state[11] = inv_sbox[state[15]];
407 	state[15] = tmp;
408 }
409 
410 /* recombine and mix each row in a column */
411 static void mix_sub_columns(u8 *state)
412 {
413 	u8 tmp[4 * AES_STATECOLS];
414 
415 	/* mixing column 0 */
416 	tmp[0] = x2_sbox[state[0]] ^ x3_sbox[state[5]] ^
417 		 sbox[state[10]] ^ sbox[state[15]];
418 	tmp[1] = sbox[state[0]] ^ x2_sbox[state[5]] ^
419 		 x3_sbox[state[10]] ^ sbox[state[15]];
420 	tmp[2] = sbox[state[0]] ^ sbox[state[5]] ^
421 		 x2_sbox[state[10]] ^ x3_sbox[state[15]];
422 	tmp[3] = x3_sbox[state[0]] ^ sbox[state[5]] ^
423 		 sbox[state[10]] ^ x2_sbox[state[15]];
424 
425 	/* mixing column 1 */
426 	tmp[4] = x2_sbox[state[4]] ^ x3_sbox[state[9]] ^
427 		 sbox[state[14]] ^ sbox[state[3]];
428 	tmp[5] = sbox[state[4]] ^ x2_sbox[state[9]] ^
429 		 x3_sbox[state[14]] ^ sbox[state[3]];
430 	tmp[6] = sbox[state[4]] ^ sbox[state[9]] ^
431 		 x2_sbox[state[14]] ^ x3_sbox[state[3]];
432 	tmp[7] = x3_sbox[state[4]] ^ sbox[state[9]] ^
433 		 sbox[state[14]] ^ x2_sbox[state[3]];
434 
435 	/* mixing column 2 */
436 	tmp[8] = x2_sbox[state[8]] ^ x3_sbox[state[13]] ^
437 		 sbox[state[2]] ^ sbox[state[7]];
438 	tmp[9] = sbox[state[8]] ^ x2_sbox[state[13]] ^
439 		 x3_sbox[state[2]] ^ sbox[state[7]];
440 	tmp[10] = sbox[state[8]] ^ sbox[state[13]] ^
441 		  x2_sbox[state[2]] ^ x3_sbox[state[7]];
442 	tmp[11] = x3_sbox[state[8]] ^ sbox[state[13]] ^
443 		  sbox[state[2]] ^ x2_sbox[state[7]];
444 
445 	/* mixing column 3 */
446 	tmp[12] = x2_sbox[state[12]] ^ x3_sbox[state[1]] ^
447 		  sbox[state[6]] ^ sbox[state[11]];
448 	tmp[13] = sbox[state[12]] ^ x2_sbox[state[1]] ^
449 		  x3_sbox[state[6]] ^ sbox[state[11]];
450 	tmp[14] = sbox[state[12]] ^ sbox[state[1]] ^
451 		  x2_sbox[state[6]] ^ x3_sbox[state[11]];
452 	tmp[15] = x3_sbox[state[12]] ^ sbox[state[1]] ^
453 		  sbox[state[6]] ^ x2_sbox[state[11]];
454 
455 	memcpy(state, tmp, sizeof(tmp));
456 }
457 
458 /* restore and un-mix each row in a column */
459 static void inv_mix_sub_columns(u8 *state)
460 {
461 	u8 tmp[4 * AES_STATECOLS];
462 	int  i;
463 
464 	/* restore column 0 */
465 	tmp[0] = x_time_e[state[0]] ^ x_time_b[state[1]] ^
466 		 x_time_d[state[2]] ^ x_time_9[state[3]];
467 	tmp[5] = x_time_9[state[0]] ^ x_time_e[state[1]] ^
468 		 x_time_b[state[2]] ^ x_time_d[state[3]];
469 	tmp[10] = x_time_d[state[0]] ^ x_time_9[state[1]] ^
470 		  x_time_e[state[2]] ^ x_time_b[state[3]];
471 	tmp[15] = x_time_b[state[0]] ^ x_time_d[state[1]] ^
472 		  x_time_9[state[2]] ^ x_time_e[state[3]];
473 
474 	/* restore column 1 */
475 	tmp[4] = x_time_e[state[4]] ^ x_time_b[state[5]] ^
476 		 x_time_d[state[6]] ^ x_time_9[state[7]];
477 	tmp[9] = x_time_9[state[4]] ^ x_time_e[state[5]] ^
478 		 x_time_b[state[6]] ^ x_time_d[state[7]];
479 	tmp[14] = x_time_d[state[4]] ^ x_time_9[state[5]] ^
480 		  x_time_e[state[6]] ^ x_time_b[state[7]];
481 	tmp[3] = x_time_b[state[4]] ^ x_time_d[state[5]] ^
482 		 x_time_9[state[6]] ^ x_time_e[state[7]];
483 
484 	/* restore column 2 */
485 	tmp[8] = x_time_e[state[8]] ^ x_time_b[state[9]] ^
486 		 x_time_d[state[10]] ^ x_time_9[state[11]];
487 	tmp[13] = x_time_9[state[8]] ^ x_time_e[state[9]] ^
488 		  x_time_b[state[10]] ^ x_time_d[state[11]];
489 	tmp[2] = x_time_d[state[8]] ^ x_time_9[state[9]] ^
490 		 x_time_e[state[10]] ^ x_time_b[state[11]];
491 	tmp[7] = x_time_b[state[8]] ^ x_time_d[state[9]] ^
492 		 x_time_9[state[10]] ^ x_time_e[state[11]];
493 
494 	/* restore column 3 */
495 	tmp[12] = x_time_e[state[12]] ^ x_time_b[state[13]] ^
496 		  x_time_d[state[14]] ^ x_time_9[state[15]];
497 	tmp[1] = x_time_9[state[12]] ^ x_time_e[state[13]] ^
498 		 x_time_b[state[14]] ^ x_time_d[state[15]];
499 	tmp[6] = x_time_d[state[12]] ^ x_time_9[state[13]] ^
500 		 x_time_e[state[14]] ^ x_time_b[state[15]];
501 	tmp[11] = x_time_b[state[12]] ^ x_time_d[state[13]] ^
502 		  x_time_9[state[14]] ^ x_time_e[state[15]];
503 
504 	for (i = 0; i < 4 * AES_STATECOLS; i++)
505 		state[i] = inv_sbox[tmp[i]];
506 }
507 
508 /*
509  * encrypt/decrypt columns of the key
510  * n.b. you can replace this with byte-wise xor if you wish.
511  */
512 static void add_round_key(u32 *state, u32 *key)
513 {
514 	int idx;
515 
516 	for (idx = 0; idx < 4; idx++)
517 		state[idx] ^= key[idx];
518 }
519 
520 static u8 rcon[11] = {
521 	0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
522 };
523 
524 /* produce AES_STATECOLS bytes for each round */
525 void aes_expand_key(u8 *key, u8 *expkey)
526 {
527 	u8 tmp0, tmp1, tmp2, tmp3, tmp4;
528 	u32 idx;
529 
530 	memcpy(expkey, key, AES_KEYCOLS * 4);
531 
532 	for (idx = AES_KEYCOLS; idx < AES_STATECOLS * (AES_ROUNDS + 1); idx++) {
533 		tmp0 = expkey[4*idx - 4];
534 		tmp1 = expkey[4*idx - 3];
535 		tmp2 = expkey[4*idx - 2];
536 		tmp3 = expkey[4*idx - 1];
537 		if (!(idx % AES_KEYCOLS)) {
538 			tmp4 = tmp3;
539 			tmp3 = sbox[tmp0];
540 			tmp0 = sbox[tmp1] ^ rcon[idx / AES_KEYCOLS];
541 			tmp1 = sbox[tmp2];
542 			tmp2 = sbox[tmp4];
543 		} else if ((AES_KEYCOLS > 6) && (idx % AES_KEYCOLS == 4)) {
544 			tmp0 = sbox[tmp0];
545 			tmp1 = sbox[tmp1];
546 			tmp2 = sbox[tmp2];
547 			tmp3 = sbox[tmp3];
548 		}
549 
550 		expkey[4*idx+0] = expkey[4*idx - 4*AES_KEYCOLS + 0] ^ tmp0;
551 		expkey[4*idx+1] = expkey[4*idx - 4*AES_KEYCOLS + 1] ^ tmp1;
552 		expkey[4*idx+2] = expkey[4*idx - 4*AES_KEYCOLS + 2] ^ tmp2;
553 		expkey[4*idx+3] = expkey[4*idx - 4*AES_KEYCOLS + 3] ^ tmp3;
554 	}
555 }
556 
557 /* encrypt one 128 bit block */
558 void aes_encrypt(u8 *in, u8 *expkey, u8 *out)
559 {
560 	u8 state[AES_STATECOLS * 4];
561 	u32 round;
562 
563 	memcpy(state, in, AES_STATECOLS * 4);
564 	add_round_key((u32 *)state, (u32 *)expkey);
565 
566 	for (round = 1; round < AES_ROUNDS + 1; round++) {
567 		if (round < AES_ROUNDS)
568 			mix_sub_columns(state);
569 		else
570 			shift_rows(state);
571 
572 		add_round_key((u32 *)state,
573 			      (u32 *)expkey + round * AES_STATECOLS);
574 	}
575 
576 	memcpy(out, state, sizeof(state));
577 }
578 
579 void aes_decrypt(u8 *in, u8 *expkey, u8 *out)
580 {
581 	u8 state[AES_STATECOLS * 4];
582 	int round;
583 
584 	memcpy(state, in, sizeof(state));
585 
586 	add_round_key((u32 *)state,
587 		      (u32 *)expkey + AES_ROUNDS * AES_STATECOLS);
588 	inv_shift_rows(state);
589 
590 	for (round = AES_ROUNDS; round--; ) {
591 		add_round_key((u32 *)state,
592 			      (u32 *)expkey + round * AES_STATECOLS);
593 		if (round)
594 			inv_mix_sub_columns(state);
595 	}
596 
597 	memcpy(out, state, sizeof(state));
598 }
599