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