1
2 #include <string.h>
3 #include <stdio.h>
4 #include <assert.h>
5
6 typedef unsigned int UInt;
7 typedef signed int Int;
8 typedef unsigned char UChar;
9 typedef unsigned long long int ULong;
10 typedef UChar Bool;
11 #define False ((Bool)0)
12 #define True ((Bool)1)
13
14 //typedef unsigned char V128[16];
15 typedef
16 union {
17 UChar uChar[16];
18 UInt uInt[4];
19 }
20 V128;
21
fromhex(char x)22 static UChar fromhex(char x) {
23 if (x >= '0' && x <= '9') { return(x - '0'); }
24 else if (x >= 'A' && x <= 'F') { return(x - 'A' + 10); }
25 else if (x >= 'a' && x <= 'f') { return(x - 'a' + 10); }
26 else assert(0);
27 }
28
expand(V128 * dst,char * summary)29 static void expand ( V128* dst, char* summary )
30 {
31 Int i;
32 assert( strlen(summary) == 32 );
33 for (i = 0; i < 16; i++) {
34 UChar xx = 0;
35 UChar x = summary[31-2*i];
36 UChar yy = 0;
37 UChar y = summary[31-2*i-1];
38 xx = fromhex (x);
39 yy = fromhex (y);
40
41 assert(xx < 16);
42 assert(yy < 16);
43 xx = (yy << 4) | xx;
44 assert(xx < 256);
45 dst->uChar[i] = xx;
46 }
47 }
48
tohex(int nib)49 static int tohex (int nib)
50 {
51 if (nib < 10)
52 return '0' + nib;
53 else
54 return 'a' + nib - 10;
55 }
unexpand(V128 * dst,char * summary)56 static void unexpand ( V128* dst, char* summary )
57 {
58 Int i;
59 for (i = 0; i < 16; i++) {
60 *summary++ = tohex((dst->uChar[i] >> 4) & 0xf);
61 *summary++ = tohex(dst->uChar[i] & 0xf);
62 }
63 *summary = 0;
64 }
65
AESDEC(char * s_argL,char * s_argR,char * s_exp)66 static void AESDEC(char *s_argL, char *s_argR, char *s_exp)
67 {
68 /*
69 ; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key).
70 ; The result is delivered in xmm1.
71 */
72 V128 argL, argR;
73 V128 res;
74 char s_res[33];
75 V128 exp;
76 expand(&argL, s_argL);
77 expand(&argR, s_argR);
78 __asm__ __volatile__(
79 "subq $1024, %%rsp" "\n\t"
80 "movdqu %1, %%xmm1" "\n\t"
81 "movdqu %2, %%xmm2" "\n\t"
82 "aesdec %%xmm2, %%xmm1" "\n\t"
83 "movdqu %%xmm1, %0" "\n\t"
84 "addq $1024, %%rsp" "\n\t"
85 : /*out*/ "=m"(res)
86 : "m"/*in*/(argL), "m"/*in*/(argR)
87 : /*trash*/ "xmm1", "xmm2"
88 );
89
90 if (strlen(s_exp) > 0) {
91 expand(&exp, s_exp);
92 assert (0 == memcmp(&res, &exp, 16));
93 }
94 unexpand (&res, s_res);
95 printf ("aesdec %s %s result %s\n", s_argL, s_argR, s_res);
96 }
97
AESDECLAST(char * s_argL,char * s_argR,char * s_exp)98 static void AESDECLAST(char *s_argL, char *s_argR, char *s_exp)
99 {
100 /*
101 ; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key).
102 ; The result is delivered in xmm1.
103 */
104 V128 argL, argR;
105 V128 res;
106 char s_res[33];
107 V128 exp;
108 expand(&argL, s_argL);
109 expand(&argR, s_argR);
110 __asm__ __volatile__(
111 "subq $1024, %%rsp" "\n\t"
112 "movdqu %1, %%xmm1" "\n\t"
113 "movdqu %2, %%xmm2" "\n\t"
114 "aesdeclast %%xmm2, %%xmm1" "\n\t"
115 "movdqu %%xmm1, %0" "\n\t"
116 "addq $1024, %%rsp" "\n\t"
117 : /*out*/ "=m"(res)
118 : "m"/*in*/(argL), "m"/*in*/(argR)
119 : /*trash*/ "xmm1", "xmm2"
120 );
121
122 if (strlen(s_exp) > 0) {
123 expand(&exp, s_exp);
124 assert (0 == memcmp(&res, &exp, 16));
125 }
126 unexpand (&res, s_res);
127 printf ("aesdeclast %s %s result %s\n", s_argL, s_argR, s_res);
128 }
129
AESENC(char * s_argL,char * s_argR,char * s_exp)130 static void AESENC(char *s_argL, char *s_argR, char *s_exp)
131 {
132 /*
133 ; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key).
134 ; The result is delivered in xmm1.
135 */
136 V128 argL, argR;
137 V128 res;
138 char s_res[33];
139 V128 exp;
140 expand(&argL, s_argL);
141 expand(&argR, s_argR);
142 __asm__ __volatile__(
143 "subq $1024, %%rsp" "\n\t"
144 "movdqu %1, %%xmm1" "\n\t"
145 "movdqu %2, %%xmm2" "\n\t"
146 "aesenc %%xmm2, %%xmm1" "\n\t"
147 "movdqu %%xmm1, %0" "\n\t"
148 "addq $1024, %%rsp" "\n\t"
149 : /*out*/ "=m"(res)
150 : "m"/*in*/(argL), "m"/*in*/(argR)
151 : /*trash*/ "xmm1", "xmm2"
152 );
153
154 if (strlen(s_exp) > 0) {
155 expand(&exp, s_exp);
156 assert (0 == memcmp(&res, &exp, 16));
157 }
158 unexpand (&res, s_res);
159 printf ("aesenc %s %s result %s\n", s_argL, s_argR, s_res);
160 }
161
AESENCLAST(char * s_argL,char * s_argR,char * s_exp)162 static void AESENCLAST(char *s_argL, char *s_argR, char *s_exp)
163 {
164 /*
165 ; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key)
166 ; The result delivered in xmm1
167 */
168 V128 argL, argR;
169 V128 res;
170 char s_res[33];
171 V128 exp;
172 expand(&argL, s_argL);
173 expand(&argR, s_argR);
174 __asm__ __volatile__(
175 "subq $1024, %%rsp" "\n\t"
176 "movdqu %1, %%xmm1" "\n\t"
177 "movdqu %2, %%xmm2" "\n\t"
178 "aesenclast %%xmm2, %%xmm1" "\n\t"
179 "movdqu %%xmm1, %0" "\n\t"
180 "addq $1024, %%rsp" "\n\t"
181 : /*out*/ "=m"(res)
182 : "m"/*in*/(argL), "m"/*in*/(argR)
183 : /*trash*/ "xmm1", "xmm2"
184 );
185
186 if (strlen(s_exp) > 0) {
187 expand(&exp, s_exp);
188 assert (0 == memcmp(&res, &exp, 16));
189 }
190 unexpand (&res, s_res);
191 printf ("aesenclast %s %s result %s\n", s_argL, s_argR, s_res);
192 }
193
AESIMC(char * s_argR,char * s_exp)194 static void AESIMC(char *s_argR, char *s_exp)
195 {
196 /* We test another way to pass input and get results */
197 /* ; argR hold one 128-bit inputs (argR = Round key)
198 ; result delivered in xmm5 */
199
200 V128 argR;
201 V128 res;
202 char s_res[33];
203 V128 exp;
204 expand(&argR, s_argR);
205
206 __asm__ __volatile__(
207 "subq $1024, %%rsp" "\n\t"
208 "aesimc %1, %%xmm5" "\n\t"
209 "movdqu %%xmm5, %0" "\n\t"
210 "addq $1024, %%rsp" "\n\t"
211 : /*out*/ "=m"(res)
212 : "m"/*in*/(argR)
213 : /*trash*/ "xmm5"
214 );
215
216 if (strlen(s_exp) > 0) {
217 expand(&exp, s_exp);
218 assert (0 == memcmp(&res, &exp, 16));
219 }
220 unexpand (&res, s_res);
221 printf ("aesimc %s result %s\n", s_argR, s_res);
222 }
223
AESKEYGENASSIST(int imm,char * s_argL,char * s_exp)224 static void AESKEYGENASSIST(int imm, char* s_argL, char* s_exp)
225 {
226 /*
227 ; xmm2 holds a 128-bit input; imm8 holds the RCON value
228 ; result delivered in xmm1
229 */
230
231 V128 argL;
232 V128 res;
233 char s_res[33];
234 V128 exp;
235 expand(&argL, s_argL);
236 if (imm == 1)
237 __asm__ __volatile__(
238 "subq $1024, %%rsp" "\n\t"
239 "movdqu %1, %%xmm2" "\n\t"
240 "aeskeygenassist $1,%%xmm2, %%xmm1" "\n\t"
241 "movdqu %%xmm1, %0" "\n\t"
242 "addq $1024, %%rsp" "\n\t"
243 : /*out*/ "=m"(res)
244 : "m"/*in*/(argL)
245 : /*trash*/ "xmm1", "xmm2"
246 );
247 else if (imm == 2)
248 __asm__ __volatile__(
249 "subq $1024, %%rsp" "\n\t"
250 "movdqu %1, %%xmm2" "\n\t"
251 "aeskeygenassist $2,%%xmm2, %%xmm1" "\n\t"
252 "movdqu %%xmm1, %0" "\n\t"
253 "addq $1024, %%rsp" "\n\t"
254 : /*out*/ "=m"(res)
255 : "m"/*in*/(argL)
256 : /*trash*/ "xmm1", "xmm2"
257 );
258 else if (imm == 8)
259 __asm__ __volatile__(
260 "subq $1024, %%rsp" "\n\t"
261 "movdqu %1, %%xmm2" "\n\t"
262 "aeskeygenassist $8,%%xmm2, %%xmm1" "\n\t"
263 "movdqu %%xmm1, %0" "\n\t"
264 "addq $1024, %%rsp" "\n\t"
265 : /*out*/ "=m"(res)
266 : "m"/*in*/(argL)
267 : /*trash*/ "xmm1", "xmm2"
268 );
269 else assert (0);
270
271 if (strlen(s_exp) > 0) {
272 expand(&exp, s_exp);
273 assert (0 == memcmp(&res, &exp, 16));
274 }
275 unexpand (&res, s_res);
276 printf ("aeskeygenassist %d %s result %s\n", imm, s_argL, s_res);
277 }
278
279 typedef struct Aes_Args {
280 char* argL;
281 char* argR;
282 int imm; // only for aeskeygenassist
283 } Aes_Args;
284
285 /* Just a bunch of various data to compare a native run
286 with a run under Valgrind. */
287 static const Aes_Args aes_args[] = {
288 {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
289 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
290 8},
291 {"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
292 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
293 8},
294 {"3243f6a8885a308d313198a2e0370734",
295 "2b7e151628aed2a6abf7158809cf4f3c",
296 2},
297 {"193de3bea0f4e22b9ac68d2ae9f84808",
298 "d42711aee0bf98f1b8b45de51e415230",
299 2},
300 {"d4bf5d30e0b452aeb84111f11e2798e5",
301 "046681e5e0cb199a48f8d37a2806264c",
302 1},
303 {"a0fafe1788542cb123a339392a6c7605",
304 "a49c7ff2689f352b6b5bea43026a5049",
305 1},
306 {"49ded28945db96f17f39871a7702533b",
307 "49db873b453953897f02d2f177de961a",
308 8},
309 {"584dcaf11b4b5aacdbe7caa81b6bb0e5",
310 "f2c295f27a96b9435935807a7359f67f",
311 8},
312 {"aa8f5f0361dde3ef82d24ad26832469a",
313 "ac73cf7befc111df13b5d6b545235ab8",
314 2},
315 {"acc1d6b8efb55a7b1323cfdf457311b5",
316 "75ec0993200b633353c0cf7cbb25d0dc",
317 2},
318 {"e9317db5cb322c723d2e895faf090794",
319 "d014f9a8c9ee2589e13f0cc8b6630ca6",
320 1},
321 {NULL,
322 NULL,
323 0}
324 };
325
main(void)326 int main ( void )
327 {
328 int i;
329
330 /* test the various instructions, using the examples provided
331 in "White Paper Intel Advanced Encryption Standard AES
332 instruction set" January 2010 (26/1/2010)
333 Rev. 3.0
334 by Shay Gueron */
335 AESKEYGENASSIST(1,
336 "3c4fcf098815f7aba6d2ae2816157e2b",
337 "01eb848beb848a013424b5e524b5e434");
338 AESENC("7b5b54657374566563746f725d53475d",
339 "48692853686179295b477565726f6e5d",
340 "a8311c2f9fdba3c58b104b58ded7e595");
341 AESENCLAST("7b5b54657374566563746f725d53475d",
342 "48692853686179295b477565726f6e5d",
343 "c7fb881e938c5964177ec42553fdc611");
344 AESDEC("7b5b54657374566563746f725d53475d",
345 "48692853686179295b477565726f6e5d",
346 "138ac342faea2787b58eb95eb730392a");
347 AESDECLAST("7b5b54657374566563746f725d53475d",
348 "48692853686179295b477565726f6e5d",
349 "c5a391ef6b317f95d410637b72a593d0");
350 /* ??? the AESIMC example given in the Intel White paper
351 seems wrong.
352 The below fails both under Valgrind and natively.
353 AESIMC("48692853686179295b477565726f6e5d",
354 "627a6f6644b109c82b18330a81c3b3e5");
355 So we use the example given for the InvMixColums
356 transformation. */
357 AESIMC("8dcab9dc035006bc8f57161e00cafd8d",
358 "d635a667928b5eaeeec9cc3bc55f5777");
359
360
361 /* and now a bunch of other calls. The below are verified
362 using the aes.stdout.exp (produced by a native run). */
363
364 for (i = 0; aes_args[i].argL != NULL; i++) {
365 AESKEYGENASSIST(aes_args[i].imm, aes_args[i].argL, "");
366 AESENC(aes_args[i].argL, aes_args[i].argR, "");
367 AESENCLAST(aes_args[i].argL, aes_args[i].argR, "");
368 AESDEC(aes_args[i].argL, aes_args[i].argR, "");
369 AESDECLAST(aes_args[i].argL, aes_args[i].argR, "");
370 AESIMC(aes_args[i].argL, "");
371 }
372 return 0;
373 }
374