• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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