amd64: Implement RDRAND, VCVTPH2PS and VCVTPS2PH.
[valgrind.git] / none / tests / amd64 / aes.c
bloba0c83c6b2b26239cecdbf226cb178474111031af
2 #include <string.h>
3 #include <stdio.h>
4 #include <assert.h>
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)
14 //typedef unsigned char V128[16];
15 typedef
16 union {
17 UChar uChar[16];
18 UInt uInt[4];
20 V128;
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);
29 static void expand ( V128* dst, char* summary )
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);
41 assert(xx < 16);
42 assert(yy < 16);
43 xx = (yy << 4) | xx;
44 assert(xx < 256);
45 dst->uChar[i] = xx;
49 static int tohex (int nib)
51 if (nib < 10)
52 return '0' + nib;
53 else
54 return 'a' + nib - 10;
56 static void unexpand ( V128* dst, char* summary )
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);
63 *summary = 0;
66 static void AESDEC(char *s_argL, char *s_argR, char *s_exp)
69 ; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key).
70 ; The result is delivered in xmm1.
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"
90 if (strlen(s_exp) > 0) {
91 expand(&exp, s_exp);
92 assert (0 == memcmp(&res, &exp, 16));
94 unexpand (&res, s_res);
95 printf ("aesdec %s %s result %s\n", s_argL, s_argR, s_res);
98 static void AESDECLAST(char *s_argL, char *s_argR, char *s_exp)
101 ; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key).
102 ; The result is delivered in xmm1.
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"
122 if (strlen(s_exp) > 0) {
123 expand(&exp, s_exp);
124 assert (0 == memcmp(&res, &exp, 16));
126 unexpand (&res, s_res);
127 printf ("aesdeclast %s %s result %s\n", s_argL, s_argR, s_res);
130 static void AESENC(char *s_argL, char *s_argR, char *s_exp)
133 ; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key).
134 ; The result is delivered in xmm1.
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"
154 if (strlen(s_exp) > 0) {
155 expand(&exp, s_exp);
156 assert (0 == memcmp(&res, &exp, 16));
158 unexpand (&res, s_res);
159 printf ("aesenc %s %s result %s\n", s_argL, s_argR, s_res);
162 static void AESENCLAST(char *s_argL, char *s_argR, char *s_exp)
165 ; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key)
166 ; The result delivered in xmm1
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"
186 if (strlen(s_exp) > 0) {
187 expand(&exp, s_exp);
188 assert (0 == memcmp(&res, &exp, 16));
190 unexpand (&res, s_res);
191 printf ("aesenclast %s %s result %s\n", s_argL, s_argR, s_res);
194 static void AESIMC(char *s_argR, char *s_exp)
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 */
200 V128 argR;
201 V128 res;
202 char s_res[33];
203 V128 exp;
204 expand(&argR, s_argR);
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"
216 if (strlen(s_exp) > 0) {
217 expand(&exp, s_exp);
218 assert (0 == memcmp(&res, &exp, 16));
220 unexpand (&res, s_res);
221 printf ("aesimc %s result %s\n", s_argR, s_res);
224 static void AESKEYGENASSIST(int imm, char* s_argL, char* s_exp)
227 ; xmm2 holds a 128-bit input; imm8 holds the RCON value
228 ; result delivered in xmm1
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"
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"
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"
269 else assert (0);
271 if (strlen(s_exp) > 0) {
272 expand(&exp, s_exp);
273 assert (0 == memcmp(&res, &exp, 16));
275 unexpand (&res, s_res);
276 printf ("aeskeygenassist %d %s result %s\n", imm, s_argL, s_res);
279 typedef struct Aes_Args {
280 char* argL;
281 char* argR;
282 int imm; // only for aeskeygenassist
283 } Aes_Args;
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",
291 {"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
292 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
294 {"3243f6a8885a308d313198a2e0370734",
295 "2b7e151628aed2a6abf7158809cf4f3c",
297 {"193de3bea0f4e22b9ac68d2ae9f84808",
298 "d42711aee0bf98f1b8b45de51e415230",
300 {"d4bf5d30e0b452aeb84111f11e2798e5",
301 "046681e5e0cb199a48f8d37a2806264c",
303 {"a0fafe1788542cb123a339392a6c7605",
304 "a49c7ff2689f352b6b5bea43026a5049",
306 {"49ded28945db96f17f39871a7702533b",
307 "49db873b453953897f02d2f177de961a",
309 {"584dcaf11b4b5aacdbe7caa81b6bb0e5",
310 "f2c295f27a96b9435935807a7359f67f",
312 {"aa8f5f0361dde3ef82d24ad26832469a",
313 "ac73cf7befc111df13b5d6b545235ab8",
315 {"acc1d6b8efb55a7b1323cfdf457311b5",
316 "75ec0993200b633353c0cf7cbb25d0dc",
318 {"e9317db5cb322c723d2e895faf090794",
319 "d014f9a8c9ee2589e13f0cc8b6630ca6",
321 {NULL,
322 NULL,
326 int main ( void )
328 int i;
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");
361 /* and now a bunch of other calls. The below are verified
362 using the aes.stdout.exp (produced by a native run). */
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, "");
372 return 0;