Home | History | Annotate | Download | only in amd64
      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 
     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 
     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 
     49 static int tohex (int nib)
     50 {
     51    if (nib < 10)
     52       return '0' + nib;
     53    else
     54       return 'a' + nib - 10;
     55 }
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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