mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 08:26:14 +00:00
374 lines
11 KiB
C
374 lines
11 KiB
C
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
|
|
typedef unsigned int UInt;
|
|
typedef signed int Int;
|
|
typedef unsigned char UChar;
|
|
typedef unsigned long long int ULong;
|
|
typedef UChar Bool;
|
|
#define False ((Bool)0)
|
|
#define True ((Bool)1)
|
|
|
|
//typedef unsigned char V128[16];
|
|
typedef
|
|
union {
|
|
UChar uChar[16];
|
|
UInt uInt[4];
|
|
}
|
|
V128;
|
|
|
|
static UChar fromhex(char x) {
|
|
if (x >= '0' && x <= '9') { return(x - '0'); }
|
|
else if (x >= 'A' && x <= 'F') { return(x - 'A' + 10); }
|
|
else if (x >= 'a' && x <= 'f') { return(x - 'a' + 10); }
|
|
else assert(0);
|
|
}
|
|
|
|
static void expand ( V128* dst, char* summary )
|
|
{
|
|
Int i;
|
|
assert( strlen(summary) == 32 );
|
|
for (i = 0; i < 16; i++) {
|
|
UChar xx = 0;
|
|
UChar x = summary[31-2*i];
|
|
UChar yy = 0;
|
|
UChar y = summary[31-2*i-1];
|
|
xx = fromhex (x);
|
|
yy = fromhex (y);
|
|
|
|
assert(xx < 16);
|
|
assert(yy < 16);
|
|
xx = (yy << 4) | xx;
|
|
assert(xx < 256);
|
|
dst->uChar[i] = xx;
|
|
}
|
|
}
|
|
|
|
static int tohex (int nib)
|
|
{
|
|
if (nib < 10)
|
|
return '0' + nib;
|
|
else
|
|
return 'a' + nib - 10;
|
|
}
|
|
static void unexpand ( V128* dst, char* summary )
|
|
{
|
|
Int i;
|
|
for (i = 0; i < 16; i++) {
|
|
*summary++ = tohex((dst->uChar[i] >> 4) & 0xf);
|
|
*summary++ = tohex(dst->uChar[i] & 0xf);
|
|
}
|
|
*summary = 0;
|
|
}
|
|
|
|
static void AESDEC(char *s_argL, char *s_argR, char *s_exp)
|
|
{
|
|
/*
|
|
; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key).
|
|
; The result is delivered in xmm1.
|
|
*/
|
|
V128 argL, argR;
|
|
V128 res;
|
|
char s_res[33];
|
|
V128 exp;
|
|
expand(&argL, s_argL);
|
|
expand(&argR, s_argR);
|
|
__asm__ __volatile__(
|
|
"subq $1024, %%rsp" "\n\t"
|
|
"movdqu %1, %%xmm1" "\n\t"
|
|
"movdqu %2, %%xmm2" "\n\t"
|
|
"aesdec %%xmm2, %%xmm1" "\n\t"
|
|
"movdqu %%xmm1, %0" "\n\t"
|
|
"addq $1024, %%rsp" "\n\t"
|
|
: /*out*/ "=m"(res)
|
|
: "m"/*in*/(argL), "m"/*in*/(argR)
|
|
: /*trash*/ "xmm1", "xmm2"
|
|
);
|
|
|
|
if (strlen(s_exp) > 0) {
|
|
expand(&exp, s_exp);
|
|
assert (0 == memcmp(&res, &exp, 16));
|
|
}
|
|
unexpand (&res, s_res);
|
|
printf ("aesdec %s %s result %s\n", s_argL, s_argR, s_res);
|
|
}
|
|
|
|
static void AESDECLAST(char *s_argL, char *s_argR, char *s_exp)
|
|
{
|
|
/*
|
|
; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key).
|
|
; The result is delivered in xmm1.
|
|
*/
|
|
V128 argL, argR;
|
|
V128 res;
|
|
char s_res[33];
|
|
V128 exp;
|
|
expand(&argL, s_argL);
|
|
expand(&argR, s_argR);
|
|
__asm__ __volatile__(
|
|
"subq $1024, %%rsp" "\n\t"
|
|
"movdqu %1, %%xmm1" "\n\t"
|
|
"movdqu %2, %%xmm2" "\n\t"
|
|
"aesdeclast %%xmm2, %%xmm1" "\n\t"
|
|
"movdqu %%xmm1, %0" "\n\t"
|
|
"addq $1024, %%rsp" "\n\t"
|
|
: /*out*/ "=m"(res)
|
|
: "m"/*in*/(argL), "m"/*in*/(argR)
|
|
: /*trash*/ "xmm1", "xmm2"
|
|
);
|
|
|
|
if (strlen(s_exp) > 0) {
|
|
expand(&exp, s_exp);
|
|
assert (0 == memcmp(&res, &exp, 16));
|
|
}
|
|
unexpand (&res, s_res);
|
|
printf ("aesdeclast %s %s result %s\n", s_argL, s_argR, s_res);
|
|
}
|
|
|
|
static void AESENC(char *s_argL, char *s_argR, char *s_exp)
|
|
{
|
|
/*
|
|
; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key).
|
|
; The result is delivered in xmm1.
|
|
*/
|
|
V128 argL, argR;
|
|
V128 res;
|
|
char s_res[33];
|
|
V128 exp;
|
|
expand(&argL, s_argL);
|
|
expand(&argR, s_argR);
|
|
__asm__ __volatile__(
|
|
"subq $1024, %%rsp" "\n\t"
|
|
"movdqu %1, %%xmm1" "\n\t"
|
|
"movdqu %2, %%xmm2" "\n\t"
|
|
"aesenc %%xmm2, %%xmm1" "\n\t"
|
|
"movdqu %%xmm1, %0" "\n\t"
|
|
"addq $1024, %%rsp" "\n\t"
|
|
: /*out*/ "=m"(res)
|
|
: "m"/*in*/(argL), "m"/*in*/(argR)
|
|
: /*trash*/ "xmm1", "xmm2"
|
|
);
|
|
|
|
if (strlen(s_exp) > 0) {
|
|
expand(&exp, s_exp);
|
|
assert (0 == memcmp(&res, &exp, 16));
|
|
}
|
|
unexpand (&res, s_res);
|
|
printf ("aesenc %s %s result %s\n", s_argL, s_argR, s_res);
|
|
}
|
|
|
|
static void AESENCLAST(char *s_argL, char *s_argR, char *s_exp)
|
|
{
|
|
/*
|
|
; xmm1 and xmm2 hold two 128-bit inputs (xmm1 = State; xmm2 = Round key)
|
|
; The result delivered in xmm1
|
|
*/
|
|
V128 argL, argR;
|
|
V128 res;
|
|
char s_res[33];
|
|
V128 exp;
|
|
expand(&argL, s_argL);
|
|
expand(&argR, s_argR);
|
|
__asm__ __volatile__(
|
|
"subq $1024, %%rsp" "\n\t"
|
|
"movdqu %1, %%xmm1" "\n\t"
|
|
"movdqu %2, %%xmm2" "\n\t"
|
|
"aesenclast %%xmm2, %%xmm1" "\n\t"
|
|
"movdqu %%xmm1, %0" "\n\t"
|
|
"addq $1024, %%rsp" "\n\t"
|
|
: /*out*/ "=m"(res)
|
|
: "m"/*in*/(argL), "m"/*in*/(argR)
|
|
: /*trash*/ "xmm1", "xmm2"
|
|
);
|
|
|
|
if (strlen(s_exp) > 0) {
|
|
expand(&exp, s_exp);
|
|
assert (0 == memcmp(&res, &exp, 16));
|
|
}
|
|
unexpand (&res, s_res);
|
|
printf ("aesenclast %s %s result %s\n", s_argL, s_argR, s_res);
|
|
}
|
|
|
|
static void AESIMC(char *s_argR, char *s_exp)
|
|
{
|
|
/* We test another way to pass input and get results */
|
|
/* ; argR hold one 128-bit inputs (argR = Round key)
|
|
; result delivered in xmm5 */
|
|
|
|
V128 argR;
|
|
V128 res;
|
|
char s_res[33];
|
|
V128 exp;
|
|
expand(&argR, s_argR);
|
|
|
|
__asm__ __volatile__(
|
|
"subq $1024, %%rsp" "\n\t"
|
|
"aesimc %1, %%xmm5" "\n\t"
|
|
"movdqu %%xmm5, %0" "\n\t"
|
|
"addq $1024, %%rsp" "\n\t"
|
|
: /*out*/ "=m"(res)
|
|
: "m"/*in*/(argR)
|
|
: /*trash*/ "xmm5"
|
|
);
|
|
|
|
if (strlen(s_exp) > 0) {
|
|
expand(&exp, s_exp);
|
|
assert (0 == memcmp(&res, &exp, 16));
|
|
}
|
|
unexpand (&res, s_res);
|
|
printf ("aesimc %s result %s\n", s_argR, s_res);
|
|
}
|
|
|
|
static void AESKEYGENASSIST(int imm, char* s_argL, char* s_exp)
|
|
{
|
|
/*
|
|
; xmm2 holds a 128-bit input; imm8 holds the RCON value
|
|
; result delivered in xmm1
|
|
*/
|
|
|
|
V128 argL;
|
|
V128 res;
|
|
char s_res[33];
|
|
V128 exp;
|
|
expand(&argL, s_argL);
|
|
if (imm == 1)
|
|
__asm__ __volatile__(
|
|
"subq $1024, %%rsp" "\n\t"
|
|
"movdqu %1, %%xmm2" "\n\t"
|
|
"aeskeygenassist $1,%%xmm2, %%xmm1" "\n\t"
|
|
"movdqu %%xmm1, %0" "\n\t"
|
|
"addq $1024, %%rsp" "\n\t"
|
|
: /*out*/ "=m"(res)
|
|
: "m"/*in*/(argL)
|
|
: /*trash*/ "xmm1", "xmm2"
|
|
);
|
|
else if (imm == 2)
|
|
__asm__ __volatile__(
|
|
"subq $1024, %%rsp" "\n\t"
|
|
"movdqu %1, %%xmm2" "\n\t"
|
|
"aeskeygenassist $2,%%xmm2, %%xmm1" "\n\t"
|
|
"movdqu %%xmm1, %0" "\n\t"
|
|
"addq $1024, %%rsp" "\n\t"
|
|
: /*out*/ "=m"(res)
|
|
: "m"/*in*/(argL)
|
|
: /*trash*/ "xmm1", "xmm2"
|
|
);
|
|
else if (imm == 8)
|
|
__asm__ __volatile__(
|
|
"subq $1024, %%rsp" "\n\t"
|
|
"movdqu %1, %%xmm2" "\n\t"
|
|
"aeskeygenassist $8,%%xmm2, %%xmm1" "\n\t"
|
|
"movdqu %%xmm1, %0" "\n\t"
|
|
"addq $1024, %%rsp" "\n\t"
|
|
: /*out*/ "=m"(res)
|
|
: "m"/*in*/(argL)
|
|
: /*trash*/ "xmm1", "xmm2"
|
|
);
|
|
else assert (0);
|
|
|
|
if (strlen(s_exp) > 0) {
|
|
expand(&exp, s_exp);
|
|
assert (0 == memcmp(&res, &exp, 16));
|
|
}
|
|
unexpand (&res, s_res);
|
|
printf ("aeskeygenassist %d %s result %s\n", imm, s_argL, s_res);
|
|
}
|
|
|
|
typedef struct Aes_Args {
|
|
char* argL;
|
|
char* argR;
|
|
int imm; // only for aeskeygenassist
|
|
} Aes_Args;
|
|
|
|
/* Just a bunch of various data to compare a native run
|
|
with a run under Valgrind. */
|
|
static const Aes_Args aes_args[] = {
|
|
{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
8},
|
|
{"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
8},
|
|
{"3243f6a8885a308d313198a2e0370734",
|
|
"2b7e151628aed2a6abf7158809cf4f3c",
|
|
2},
|
|
{"193de3bea0f4e22b9ac68d2ae9f84808",
|
|
"d42711aee0bf98f1b8b45de51e415230",
|
|
2},
|
|
{"d4bf5d30e0b452aeb84111f11e2798e5",
|
|
"046681e5e0cb199a48f8d37a2806264c",
|
|
1},
|
|
{"a0fafe1788542cb123a339392a6c7605",
|
|
"a49c7ff2689f352b6b5bea43026a5049",
|
|
1},
|
|
{"49ded28945db96f17f39871a7702533b",
|
|
"49db873b453953897f02d2f177de961a",
|
|
8},
|
|
{"584dcaf11b4b5aacdbe7caa81b6bb0e5",
|
|
"f2c295f27a96b9435935807a7359f67f",
|
|
8},
|
|
{"aa8f5f0361dde3ef82d24ad26832469a",
|
|
"ac73cf7befc111df13b5d6b545235ab8",
|
|
2},
|
|
{"acc1d6b8efb55a7b1323cfdf457311b5",
|
|
"75ec0993200b633353c0cf7cbb25d0dc",
|
|
2},
|
|
{"e9317db5cb322c723d2e895faf090794",
|
|
"d014f9a8c9ee2589e13f0cc8b6630ca6",
|
|
1},
|
|
{NULL,
|
|
NULL,
|
|
0}
|
|
};
|
|
|
|
int main ( void )
|
|
{
|
|
int i;
|
|
|
|
/* test the various instructions, using the examples provided
|
|
in "White Paper Intel Advanced Encryption Standard AES
|
|
instruction set" January 2010 (26/1/2010)
|
|
Rev. 3.0
|
|
by Shay Gueron */
|
|
AESKEYGENASSIST(1,
|
|
"3c4fcf098815f7aba6d2ae2816157e2b",
|
|
"01eb848beb848a013424b5e524b5e434");
|
|
AESENC("7b5b54657374566563746f725d53475d",
|
|
"48692853686179295b477565726f6e5d",
|
|
"a8311c2f9fdba3c58b104b58ded7e595");
|
|
AESENCLAST("7b5b54657374566563746f725d53475d",
|
|
"48692853686179295b477565726f6e5d",
|
|
"c7fb881e938c5964177ec42553fdc611");
|
|
AESDEC("7b5b54657374566563746f725d53475d",
|
|
"48692853686179295b477565726f6e5d",
|
|
"138ac342faea2787b58eb95eb730392a");
|
|
AESDECLAST("7b5b54657374566563746f725d53475d",
|
|
"48692853686179295b477565726f6e5d",
|
|
"c5a391ef6b317f95d410637b72a593d0");
|
|
/* ??? the AESIMC example given in the Intel White paper
|
|
seems wrong.
|
|
The below fails both under Valgrind and natively.
|
|
AESIMC("48692853686179295b477565726f6e5d",
|
|
"627a6f6644b109c82b18330a81c3b3e5");
|
|
So we use the example given for the InvMixColums
|
|
transformation. */
|
|
AESIMC("8dcab9dc035006bc8f57161e00cafd8d",
|
|
"d635a667928b5eaeeec9cc3bc55f5777");
|
|
|
|
|
|
/* and now a bunch of other calls. The below are verified
|
|
using the aes.stdout.exp (produced by a native run). */
|
|
|
|
for (i = 0; aes_args[i].argL != NULL; i++) {
|
|
AESKEYGENASSIST(aes_args[i].imm, aes_args[i].argL, "");
|
|
AESENC(aes_args[i].argL, aes_args[i].argR, "");
|
|
AESENCLAST(aes_args[i].argL, aes_args[i].argR, "");
|
|
AESDEC(aes_args[i].argL, aes_args[i].argR, "");
|
|
AESDECLAST(aes_args[i].argL, aes_args[i].argR, "");
|
|
AESIMC(aes_args[i].argL, "");
|
|
}
|
|
return 0;
|
|
}
|