This optimized <../aesbench/> AES implementation conforms to FIPS-. aes.h #ifndef _AES_H
#define _AES_H #ifndef uint8
#define uint8 unsigned char
#endif #ifndef uint32
#define uint32 unsigned long int
#endif typedef struct
{
uint32 erk[]; /* encryption round keys */
uint32 drk[]; /* decryption round keys */
int nr; /* number of rounds */
}
aes_context; int aes_set_key( aes_context *ctx, uint8 *key, int nbits );
void aes_encrypt( aes_context *ctx, uint8 input[], uint8 output[] );
void aes_decrypt( aes_context *ctx, uint8 input[], uint8 output[] ); #endif /* aes.h */ aes.c /*
* FIPS-197 compliant AES implementation
*
* Copyright (C) 2001-2004 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ #include "aes.h" /* uncomment the following line to run the test suite */ /* #define TEST */ /* uncomment the following line to use pre-computed tables */
/* otherwise the tables will be generated at the first run */ /* #define FIXED_TABLES */ #ifndef FIXED_TABLES /* forward S-box & tables */ uint32 FSb[];
uint32 FT0[];
uint32 FT1[];
uint32 FT2[];
uint32 FT3[]; /* reverse S-box & tables */ uint32 RSb[];
uint32 RT0[];
uint32 RT1[];
uint32 RT2[];
uint32 RT3[]; /* round constants */ uint32 RCON[]; /* tables generation flag */ int do_init = ; /* tables generation routine */ #define ROTR8(x) ( ( ( x << 24 ) & 0xFFFFFFFF ) | \
( ( x & 0xFFFFFFFF ) >> ) ) #define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
#define MUL(x,y) ( ( x && y ) ? pow[(log[x] + log[y]) % 255] : 0 ) void aes_gen_tables( void )
{
int i;
uint8 x, y;
uint8 pow[];
uint8 log[]; /* compute pow and log tables over GF(2^8) */ for( i = , x = ; i < ; i++, x ^= XTIME( x ) )
{
pow[i] = x;
log[x] = i;
} /* calculate the round constants */ for( i = , x = ; i < ; i++, x = XTIME( x ) )
{
RCON[i] = (uint32) x << ;
} /* generate the forward and reverse S-boxes */ FSb[0x00] = 0x63;
RSb[0x63] = 0x00; for( i = ; i < ; i++ )
{
x = pow[ - log[i]]; y = x; y = ( y << ) | ( y >> );
x ^= y; y = ( y << ) | ( y >> );
x ^= y; y = ( y << ) | ( y >> );
x ^= y; y = ( y << ) | ( y >> );
x ^= y ^ 0x63; FSb[i] = x;
RSb[x] = i;
} /* generate the forward and reverse tables */ for( i = ; i < ; i++ )
{
x = (unsigned char) FSb[i]; y = XTIME( x ); FT0[i] = (uint32) ( x ^ y ) ^
( (uint32) x << ) ^
( (uint32) x << ) ^
( (uint32) y << ); FT0[i] &= 0xFFFFFFFF; FT1[i] = ROTR8( FT0[i] );
FT2[i] = ROTR8( FT1[i] );
FT3[i] = ROTR8( FT2[i] ); y = (unsigned char) RSb[i]; RT0[i] = ( (uint32) MUL( 0x0B, y ) ) ^
( (uint32) MUL( 0x0D, y ) << ) ^
( (uint32) MUL( 0x09, y ) << ) ^
( (uint32) MUL( 0x0E, y ) << ); RT0[i] &= 0xFFFFFFFF; RT1[i] = ROTR8( RT0[i] );
RT2[i] = ROTR8( RT1[i] );
RT3[i] = ROTR8( RT2[i] );
}
} #else /* forward S-box */ static const uint32 FSb[] =
{
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
}; /* forward tables */ #define FT \
\
V(C6,,,A5), V(F8,7C,7C,), V(EE,,,), V(F6,7B,7B,8D), \
V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(,C5,C5,), \
V(,,,), V(,,,), V(CE,,,A9), V(,2B,2B,7D), \
V(E7,FE,FE,), V(B5,D7,D7,), V(4D,AB,AB,E6), V(EC,,,9A), \
V(8F,CA,CA,), V(1F,,,9D), V(,C9,C9,), V(FA,7D,7D,), \
V(EF,FA,FA,), V(B2,,,EB), V(8E,,,C9), V(FB,F0,F0,0B), \
V(,AD,AD,EC), V(B3,D4,D4,), V(5F,A2,A2,FD), V(,AF,AF,EA), \
V(,9C,9C,BF), V(,A4,A4,F7), V(E4,,,), V(9B,C0,C0,5B), \
V(,B7,B7,C2), V(E1,FD,FD,1C), V(3D,,,AE), V(4C,,,6A), \
V(6C,,,5A), V(7E,3F,3F,), V(F5,F7,F7,), V(,CC,CC,4F), \
V(,,,5C), V(,A5,A5,F4), V(D1,E5,E5,), V(F9,F1,F1,), \
V(E2,,,), V(AB,D8,D8,), V(,,,), V(2A,,,3F), \
V(,,,0C), V(,C7,C7,), V(,,,), V(9D,C3,C3,5E), \
V(,,,), V(,,,A1), V(0A,,,0F), V(2F,9A,9A,B5), \
V(0E,,,), V(,,,), V(1B,,,9B), V(DF,E2,E2,3D), \
V(CD,EB,EB,), V(4E,,,), V(7F,B2,B2,CD), V(EA,,,9F), \
V(,,,1B), V(1D,,,9E), V(,2C,2C,), V(,1A,1A,2E), \
V(,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \
V(A4,,,F6), V(,3B,3B,4D), V(B7,D6,D6,), V(7D,B3,B3,CE), \
V(,,,7B), V(DD,E3,E3,3E), V(5E,2F,2F,), V(,,,), \
V(A6,,,F5), V(B9,D1,D1,), V(,,,), V(C1,ED,ED,2C), \
V(,,,), V(E3,FC,FC,1F), V(,B1,B1,C8), V(B6,5B,5B,ED), \
V(D4,6A,6A,BE), V(8D,CB,CB,), V(,BE,BE,D9), V(,,,4B), \
V(,4A,4A,DE), V(,4C,4C,D4), V(B0,,,E8), V(,CF,CF,4A), \
V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,), \
V(,,,C5), V(9A,4D,4D,D7), V(,,,), V(,,,), \
V(8A,,,CF), V(E9,F9,F9,), V(,,,), V(FE,7F,7F,), \
V(A0,,,F0), V(,3C,3C,), V(,9F,9F,BA), V(4B,A8,A8,E3), \
V(A2,,,F3), V(5D,A3,A3,FE), V(,,,C0), V(,8F,8F,8A), \
V(3F,,,AD), V(,9D,9D,BC), V(,,,), V(F1,F5,F5,), \
V(,BC,BC,DF), V(,B6,B6,C1), V(AF,DA,DA,), V(,,,), \
V(,,,), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \
V(,CD,CD,4C), V(,0C,0C,), V(,,,), V(C3,EC,EC,2F), \
V(BE,5F,5F,E1), V(,,,A2), V(,,,CC), V(2E,,,), \
V(,C4,C4,), V(,A7,A7,F2), V(FC,7E,7E,), V(7A,3D,3D,), \
V(C8,,,AC), V(BA,5D,5D,E7), V(,,,2B), V(E6,,,), \
V(C0,,,A0), V(,,,), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \
V(,,,), V(,2A,2A,7E), V(3B,,,AB), V(0B,,,), \
V(8C,,,CA), V(C7,EE,EE,), V(6B,B8,B8,D3), V(,,,3C), \
V(A7,DE,DE,), V(BC,5E,5E,E2), V(,0B,0B,1D), V(AD,DB,DB,), \
V(DB,E0,E0,3B), V(,,,), V(,3A,3A,4E), V(,0A,0A,1E), \
V(,,,DB), V(0C,,,0A), V(,,,6C), V(B8,5C,5C,E4), \
V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(,AC,AC,EF), V(C4,,,A6), \
V(,,,A8), V(,,,A4), V(D3,E4,E4,), V(F2,,,8B), \
V(D5,E7,E7,), V(8B,C8,C8,), V(6E,,,), V(DA,6D,6D,B7), \
V(,8D,8D,8C), V(B1,D5,D5,), V(9C,4E,4E,D2), V(,A9,A9,E0), \
V(D8,6C,6C,B4), V(AC,,,FA), V(F3,F4,F4,), V(CF,EA,EA,), \
V(CA,,,AF), V(F4,7A,7A,8E), V(,AE,AE,E9), V(,,,), \
V(6F,BA,BA,D5), V(F0,,,), V(4A,,,6F), V(5C,2E,2E,), \
V(,1C,1C,), V(,A6,A6,F1), V(,B4,B4,C7), V(,C6,C6,), \
V(CB,E8,E8,), V(A1,DD,DD,7C), V(E8,,,9C), V(3E,1F,1F,), \
V(,4B,4B,DD), V(,BD,BD,DC), V(0D,8B,8B,), V(0F,8A,8A,), \
V(E0,,,), V(7C,3E,3E,), V(,B5,B5,C4), V(CC,,,AA), \
V(,,,D8), V(,,,), V(F7,F6,F6,), V(1C,0E,0E,), \
V(C2,,,A3), V(6A,,,5F), V(AE,,,F9), V(,B9,B9,D0), \
V(,,,), V(,C1,C1,), V(3A,1D,1D,), V(,9E,9E,B9), \
V(D9,E1,E1,), V(EB,F8,F8,), V(2B,,,B3), V(,,,), \
V(D2,,,BB), V(A9,D9,D9,), V(,8E,8E,), V(,,,A7), \
V(2D,9B,9B,B6), V(3C,1E,1E,), V(,,,), V(C9,E9,E9,), \
V(,CE,CE,), V(AA,,,FF), V(,,,), V(A5,DF,DF,7A), \
V(,8C,8C,8F), V(,A1,A1,F8), V(,,,), V(1A,0D,0D,), \
V(,BF,BF,DA), V(D7,E6,E6,), V(,,,C6), V(D0,,,B8), \
V(,,,C3), V(,,,B0), V(5A,2D,2D,), V(1E,0F,0F,), \
V(7B,B0,B0,CB), V(A8,,,FC), V(6D,BB,BB,D6), V(2C,,,3A) #define V(a,b,c,d) 0x##a##b##c##d
static const uint32 FT0[] = { FT };
#undef V #define V(a,b,c,d) 0x##d##a##b##c
static const uint32 FT1[] = { FT };
#undef V #define V(a,b,c,d) 0x##c##d##a##b
static const uint32 FT2[] = { FT };
#undef V #define V(a,b,c,d) 0x##b##c##d##a
static const uint32 FT3[] = { FT };
#undef V #undef FT /* reverse S-box */ static const uint32 RSb[] =
{
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
}; /* reverse tables */ #define RT \
\
V(,F4,A7,), V(7E,,,), V(1A,,A4,C3), V(3A,,5E,), \
V(3B,AB,6B,CB), V(1F,9D,,F1), V(AC,FA,,AB), V(4B,E3,,), \
V(,,FA,), V(AD,,6D,F6), V(,CC,,), V(F5,,4C,), \
V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(,,,), V(B5,,A3,8F), \
V(DE,B1,5A,), V(,BA,1B,), V(,EA,0E,), V(5D,FE,C0,E1), \
V(C3,2F,,), V(,4C,F0,), V(8D,,,A3), V(6B,D3,F9,C6), \
V(,8F,5F,E7), V(,,9C,), V(BF,6D,7A,EB), V(,,,DA), \
V(D4,BE,,2D), V(,,,D3), V(,E0,,), V(8E,C9,C8,), \
V(,C2,,6A), V(F4,8E,,), V(,,3E,6B), V(,B9,,DD), \
V(BE,E1,4F,B6), V(F0,,AD,), V(C9,,AC,), V(7D,CE,3A,B4), \
V(,DF,4A,), V(E5,1A,,), V(,,,), V(,,7F,), \
V(B1,,,E0), V(BB,6B,AE,), V(FE,,A0,1C), V(F9,,2B,), \
V(,,,), V(8F,,FD,), V(,DE,6C,), V(,7B,F8,B7), \
V(AB,,D3,), V(,4B,,E2), V(E3,1F,8F,), V(,,AB,2A), \
V(B2,EB,,), V(2F,B5,C2,), V(,C5,7B,9A), V(D3,,,A5), \
V(,,,F2), V(,BF,A5,B2), V(,,6A,BA), V(ED,,,5C), \
V(8A,CF,1C,2B), V(A7,,B4,), V(F3,,F2,F0), V(4E,,E2,A1), \
V(,DA,F4,CD), V(,,BE,D5), V(D1,,,1F), V(C4,A6,FE,8A), \
V(,2E,,9D), V(A2,F3,,A0), V(,8A,E1,), V(A4,F6,EB,), \
V(0B,,EC,), V(,,EF,AA), V(5E,,9F,), V(BD,6E,,), \
V(3E,,8A,F9), V(,DD,,3D), V(DD,3E,,AE), V(4D,E6,BD,), \
V(,,8D,B5), V(,C4,5D,), V(,,D4,6F), V(,,,FF), \
V(,,FB,), V(D6,BD,E9,), V(,,,CC), V(,D9,9E,), \
V(B0,E8,,BD), V(,,8B,), V(E7,,5B,), V(,C8,EE,DB), \
V(A1,7C,0A,), V(7C,,0F,E9), V(F8,,1E,C9), V(,,,), \
V(,,,), V(,2B,ED,), V(1E,,,AC), V(6C,5A,,4E), \
V(FD,0E,FF,FB), V(0F,,,), V(3D,AE,D5,1E), V(,2D,,), \
V(0A,0F,D9,), V(,5C,A6,), V(9B,5B,,D1), V(,,2E,3A), \
V(0C,0A,,B1), V(,,E7,0F), V(B4,EE,,D2), V(1B,9B,,9E), \
V(,C0,C5,4F), V(,DC,,A2), V(5A,,4B,), V(1C,,1A,), \
V(E2,,BA,0A), V(C0,A0,2A,E5), V(3C,,E0,), V(,1B,,1D), \
V(0E,,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(,1E,A9,C8), \
V(,F1,,), V(AF,,,4C), V(EE,,DD,BB), V(A3,7F,,FD), \
V(F7,,,9F), V(5C,,F5,BC), V(,,3B,C5), V(5B,FB,7E,), \
V(8B,,,), V(CB,,C6,DC), V(B6,ED,FC,), V(B8,E4,F1,), \
V(D7,,DC,CA), V(,,,), V(,,,), V(,C6,,), \
V(,4A,,7D), V(D2,BB,3D,F8), V(AE,F9,,), V(C7,,A1,6D), \
V(1D,9E,2F,4B), V(DC,B2,,F3), V(0D,,,EC), V(,C1,E3,D0), \
V(2B,B3,,6C), V(A9,,B9,), V(,,,FA), V(,E9,,), \
V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(,7D,2C,D8), V(,,,EF), \
V(,,4E,C7), V(D9,,D1,C1), V(8C,CA,A2,FE), V(,D4,0B,), \
V(A6,F5,,CF), V(A5,7A,DE,), V(DA,B7,8E,), V(3F,AD,BF,A4), \
V(2C,3A,9D,E4), V(,,,0D), V(6A,5F,CC,9B), V(,7E,,), \
V(F6,8D,,C2), V(,D8,B8,E8), V(2E,,F7,5E), V(,C3,AF,F5), \
V(9F,5D,,BE), V(,D0,,7C), V(6F,D5,2D,A9), V(CF,,,B3), \
V(C8,AC,,3B), V(,,7D,A7), V(E8,9C,,6E), V(DB,3B,BB,7B), \
V(CD,,,), V(6E,,,F4), V(EC,9A,B7,), V(,4F,9A,A8), \
V(E6,,6E,), V(AA,FF,E6,7E), V(,BC,CF,), V(EF,,E8,E6), \
V(BA,E7,9B,D9), V(4A,6F,,CE), V(EA,9F,,D4), V(,B0,7C,D6), \
V(,A4,B2,AF), V(2A,3F,,), V(C6,A5,,), V(,A2,,C0), \
V(,4E,BC,), V(FC,,CA,A6), V(E0,,D0,B0), V(,A7,D8,), \
V(F1,,,4A), V(,EC,DA,F7), V(7F,CD,,0E), V(,,F6,2F), \
V(,4D,D6,8D), V(,EF,B0,4D), V(CC,AA,4D,), V(E4,,,DF), \
V(9E,D1,B5,E3), V(4C,6A,,1B), V(C1,2C,1F,B8), V(,,,7F), \
V(9D,5E,EA,), V(,8C,,5D), V(FA,,,), V(FB,0B,,2E), \
V(B3,,1D,5A), V(,DB,D2,), V(E9,,,), V(6D,D6,,), \
V(9A,D7,,8C), V(,A1,0C,7A), V(,F8,,8E), V(EB,,3C,), \
V(CE,A9,,EE), V(B7,,C9,), V(E1,1C,E5,ED), V(7A,,B1,3C), \
V(9C,D2,DF,), V(,F2,,3F), V(,,CE,), V(,C7,,BF), \
V(,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,), V(,,DB,), \
V(CA,AF,F3,), V(B9,,C4,3E), V(,,,2C), V(C2,A3,,5F), \
V(,1D,C3,), V(BC,E2,,0C), V(,3C,,8B), V(FF,0D,,), \
V(,A8,,), V(,0C,B3,DE), V(D8,B4,E4,9C), V(,,C1,), \
V(7B,CB,,), V(D5,,B6,), V(,6C,5C,), V(D0,B8,,) #define V(a,b,c,d) 0x##a##b##c##d
static const uint32 RT0[] = { RT };
#undef V #define V(a,b,c,d) 0x##d##a##b##c
static const uint32 RT1[] = { RT };
#undef V #define V(a,b,c,d) 0x##c##d##a##b
static const uint32 RT2[] = { RT };
#undef V #define V(a,b,c,d) 0x##b##c##d##a
static const uint32 RT3[] = { RT };
#undef V #undef RT /* round constants */ static const uint32 RCON[] =
{
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000,
0x1B000000, 0x36000000
}; int do_init = ; void aes_gen_tables( void )
{
} #endif /* platform-independant 32-bit integer manipulation macros */ #define GET_UINT32(n,b,i) \
{ \
(n) = ( (uint32) (b)[(i) ] << ) \
| ( (uint32) (b)[(i) + ] << ) \
| ( (uint32) (b)[(i) + ] << ) \
| ( (uint32) (b)[(i) + ] ); \
} #define PUT_UINT32(n,b,i) \
{ \
(b)[(i) ] = (uint8) ( (n) >> ); \
(b)[(i) + ] = (uint8) ( (n) >> ); \
(b)[(i) + ] = (uint8) ( (n) >> ); \
(b)[(i) + ] = (uint8) ( (n) ); \
} /* decryption key schedule tables */ int KT_init = ; uint32 KT0[];
uint32 KT1[];
uint32 KT2[];
uint32 KT3[]; /* AES key scheduling routine */ int aes_set_key( aes_context *ctx, uint8 *key, int nbits )
{
int i;
uint32 *RK, *SK; if( do_init )
{
aes_gen_tables(); do_init = ;
} switch( nbits )
{
case : ctx->nr = ; break;
case : ctx->nr = ; break;
case : ctx->nr = ; break;
default : return( );
} RK = ctx->erk; for( i = ; i < (nbits >> ); i++ )
{
GET_UINT32( RK[i], key, i * );
} /* setup encryption round keys */ switch( nbits )
{
case : for( i = ; i < ; i++, RK += )
{
RK[] = RK[] ^ RCON[i] ^
( FSb[ (uint8) ( RK[] >> ) ] << ) ^
( FSb[ (uint8) ( RK[] >> ) ] << ) ^
( FSb[ (uint8) ( RK[] ) ] << ) ^
( FSb[ (uint8) ( RK[] >> ) ] ); RK[] = RK[] ^ RK[];
RK[] = RK[] ^ RK[];
RK[] = RK[] ^ RK[];
}
break; case : for( i = ; i < ; i++, RK += )
{
RK[] = RK[] ^ RCON[i] ^
( FSb[ (uint8) ( RK[] >> ) ] << ) ^
( FSb[ (uint8) ( RK[] >> ) ] << ) ^
( FSb[ (uint8) ( RK[] ) ] << ) ^
( FSb[ (uint8) ( RK[] >> ) ] ); RK[] = RK[] ^ RK[];
RK[] = RK[] ^ RK[];
RK[] = RK[] ^ RK[];
RK[] = RK[] ^ RK[];
RK[] = RK[] ^ RK[];
}
break; case : for( i = ; i < ; i++, RK += )
{
RK[] = RK[] ^ RCON[i] ^
( FSb[ (uint8) ( RK[] >> ) ] << ) ^
( FSb[ (uint8) ( RK[] >> ) ] << ) ^
( FSb[ (uint8) ( RK[] ) ] << ) ^
( FSb[ (uint8) ( RK[] >> ) ] ); RK[] = RK[] ^ RK[];
RK[] = RK[] ^ RK[];
RK[] = RK[] ^ RK[]; RK[] = RK[] ^
( FSb[ (uint8) ( RK[] >> ) ] << ) ^
( FSb[ (uint8) ( RK[] >> ) ] << ) ^
( FSb[ (uint8) ( RK[] >> ) ] << ) ^
( FSb[ (uint8) ( RK[] ) ] ); RK[] = RK[] ^ RK[];
RK[] = RK[] ^ RK[];
RK[] = RK[] ^ RK[];
}
break;
} /* setup decryption round keys */ if( KT_init )
{
for( i = ; i < ; i++ )
{
KT0[i] = RT0[ FSb[i] ];
KT1[i] = RT1[ FSb[i] ];
KT2[i] = RT2[ FSb[i] ];
KT3[i] = RT3[ FSb[i] ];
} KT_init = ;
} SK = ctx->drk; *SK++ = *RK++;
*SK++ = *RK++;
*SK++ = *RK++;
*SK++ = *RK++; for( i = ; i < ctx->nr; i++ )
{
RK -= ; *SK++ = KT0[ (uint8) ( *RK >> ) ] ^
KT1[ (uint8) ( *RK >> ) ] ^
KT2[ (uint8) ( *RK >> ) ] ^
KT3[ (uint8) ( *RK ) ]; RK++; *SK++ = KT0[ (uint8) ( *RK >> ) ] ^
KT1[ (uint8) ( *RK >> ) ] ^
KT2[ (uint8) ( *RK >> ) ] ^
KT3[ (uint8) ( *RK ) ]; RK++; *SK++ = KT0[ (uint8) ( *RK >> ) ] ^
KT1[ (uint8) ( *RK >> ) ] ^
KT2[ (uint8) ( *RK >> ) ] ^
KT3[ (uint8) ( *RK ) ]; RK++; *SK++ = KT0[ (uint8) ( *RK >> ) ] ^
KT1[ (uint8) ( *RK >> ) ] ^
KT2[ (uint8) ( *RK >> ) ] ^
KT3[ (uint8) ( *RK ) ]; RK++;
} RK -= ; *SK++ = *RK++;
*SK++ = *RK++;
*SK++ = *RK++;
*SK++ = *RK++; return( );
} /* AES 128-bit block encryption routine */ void aes_encrypt( aes_context *ctx, uint8 input[], uint8 output[] )
{
uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; RK = ctx->erk; GET_UINT32( X0, input, ); X0 ^= RK[];
GET_UINT32( X1, input, ); X1 ^= RK[];
GET_UINT32( X2, input, ); X2 ^= RK[];
GET_UINT32( X3, input, ); X3 ^= RK[]; #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
{ \
RK += ; \
\
X0 = RK[] ^ FT0[ (uint8) ( Y0 >> ) ] ^ \
FT1[ (uint8) ( Y1 >> ) ] ^ \
FT2[ (uint8) ( Y2 >> ) ] ^ \
FT3[ (uint8) ( Y3 ) ]; \
\
X1 = RK[] ^ FT0[ (uint8) ( Y1 >> ) ] ^ \
FT1[ (uint8) ( Y2 >> ) ] ^ \
FT2[ (uint8) ( Y3 >> ) ] ^ \
FT3[ (uint8) ( Y0 ) ]; \
\
X2 = RK[] ^ FT0[ (uint8) ( Y2 >> ) ] ^ \
FT1[ (uint8) ( Y3 >> ) ] ^ \
FT2[ (uint8) ( Y0 >> ) ] ^ \
FT3[ (uint8) ( Y1 ) ]; \
\
X3 = RK[] ^ FT0[ (uint8) ( Y3 >> ) ] ^ \
FT1[ (uint8) ( Y0 >> ) ] ^ \
FT2[ (uint8) ( Y1 >> ) ] ^ \
FT3[ (uint8) ( Y2 ) ]; \
} AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ if( ctx->nr > )
{
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */
} if( ctx->nr > )
{
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */
} /* last round */ RK += ; X0 = RK[] ^ ( FSb[ (uint8) ( Y0 >> ) ] << ) ^
( FSb[ (uint8) ( Y1 >> ) ] << ) ^
( FSb[ (uint8) ( Y2 >> ) ] << ) ^
( FSb[ (uint8) ( Y3 ) ] ); X1 = RK[] ^ ( FSb[ (uint8) ( Y1 >> ) ] << ) ^
( FSb[ (uint8) ( Y2 >> ) ] << ) ^
( FSb[ (uint8) ( Y3 >> ) ] << ) ^
( FSb[ (uint8) ( Y0 ) ] ); X2 = RK[] ^ ( FSb[ (uint8) ( Y2 >> ) ] << ) ^
( FSb[ (uint8) ( Y3 >> ) ] << ) ^
( FSb[ (uint8) ( Y0 >> ) ] << ) ^
( FSb[ (uint8) ( Y1 ) ] ); X3 = RK[] ^ ( FSb[ (uint8) ( Y3 >> ) ] << ) ^
( FSb[ (uint8) ( Y0 >> ) ] << ) ^
( FSb[ (uint8) ( Y1 >> ) ] << ) ^
( FSb[ (uint8) ( Y2 ) ] ); PUT_UINT32( X0, output, );
PUT_UINT32( X1, output, );
PUT_UINT32( X2, output, );
PUT_UINT32( X3, output, );
} /* AES 128-bit block decryption routine */ void aes_decrypt( aes_context *ctx, uint8 input[], uint8 output[] )
{
uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; RK = ctx->drk; GET_UINT32( X0, input, ); X0 ^= RK[];
GET_UINT32( X1, input, ); X1 ^= RK[];
GET_UINT32( X2, input, ); X2 ^= RK[];
GET_UINT32( X3, input, ); X3 ^= RK[]; #define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
{ \
RK += ; \
\
X0 = RK[] ^ RT0[ (uint8) ( Y0 >> ) ] ^ \
RT1[ (uint8) ( Y3 >> ) ] ^ \
RT2[ (uint8) ( Y2 >> ) ] ^ \
RT3[ (uint8) ( Y1 ) ]; \
\
X1 = RK[] ^ RT0[ (uint8) ( Y1 >> ) ] ^ \
RT1[ (uint8) ( Y0 >> ) ] ^ \
RT2[ (uint8) ( Y3 >> ) ] ^ \
RT3[ (uint8) ( Y2 ) ]; \
\
X2 = RK[] ^ RT0[ (uint8) ( Y2 >> ) ] ^ \
RT1[ (uint8) ( Y1 >> ) ] ^ \
RT2[ (uint8) ( Y0 >> ) ] ^ \
RT3[ (uint8) ( Y3 ) ]; \
\
X3 = RK[] ^ RT0[ (uint8) ( Y3 >> ) ] ^ \
RT1[ (uint8) ( Y2 >> ) ] ^ \
RT2[ (uint8) ( Y1 >> ) ] ^ \
RT3[ (uint8) ( Y0 ) ]; \
} AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ if( ctx->nr > )
{
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */
} if( ctx->nr > )
{
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */
} /* last round */ RK += ; X0 = RK[] ^ ( RSb[ (uint8) ( Y0 >> ) ] << ) ^
( RSb[ (uint8) ( Y3 >> ) ] << ) ^
( RSb[ (uint8) ( Y2 >> ) ] << ) ^
( RSb[ (uint8) ( Y1 ) ] ); X1 = RK[] ^ ( RSb[ (uint8) ( Y1 >> ) ] << ) ^
( RSb[ (uint8) ( Y0 >> ) ] << ) ^
( RSb[ (uint8) ( Y3 >> ) ] << ) ^
( RSb[ (uint8) ( Y2 ) ] ); X2 = RK[] ^ ( RSb[ (uint8) ( Y2 >> ) ] << ) ^
( RSb[ (uint8) ( Y1 >> ) ] << ) ^
( RSb[ (uint8) ( Y0 >> ) ] << ) ^
( RSb[ (uint8) ( Y3 ) ] ); X3 = RK[] ^ ( RSb[ (uint8) ( Y3 >> ) ] << ) ^
( RSb[ (uint8) ( Y2 >> ) ] << ) ^
( RSb[ (uint8) ( Y1 >> ) ] << ) ^
( RSb[ (uint8) ( Y0 ) ] ); PUT_UINT32( X0, output, );
PUT_UINT32( X1, output, );
PUT_UINT32( X2, output, );
PUT_UINT32( X3, output, );
} #ifdef TEST #include <string.h>
#include <stdio.h> /*
* Rijndael Monte Carlo Test: ECB mode
* source: NIST - rijndael-vals.zip
*/ static unsigned char AES_enc_test[][] =
{
{ 0xA0, 0x43, 0x77, 0xAB, 0xE2, 0x59, 0xB0, 0xD0,
0xB5, 0xBA, 0x2D, 0x40, 0xA5, 0x01, 0x97, 0x1B },
{ 0x4E, 0x46, 0xF8, 0xC5, 0x09, 0x2B, 0x29, 0xE2,
0x9A, 0x97, 0x1A, 0x0C, 0xD1, 0xF6, 0x10, 0xFB },
{ 0x1F, 0x67, 0x63, 0xDF, 0x80, 0x7A, 0x7E, 0x70,
0x96, 0x0D, 0x4C, 0xD3, 0x11, 0x8E, 0x60, 0x1A }
}; static unsigned char AES_dec_test[][] =
{
{ 0xF5, 0xBF, 0x8B, 0x37, 0x13, 0x6F, 0x2E, 0x1F,
0x6B, 0xEC, 0x6F, 0x57, 0x20, 0x21, 0xE3, 0xBA },
{ 0xF1, 0xA8, 0x1B, 0x68, 0xF6, 0xE5, 0xA6, 0x27,
0x1A, 0x8C, 0xB2, 0x4E, 0x7D, 0x94, 0x91, 0xEF },
{ 0x4D, 0xE0, 0xC6, 0xDF, 0x7C, 0xB1, 0x69, 0x72,
0x84, 0x60, 0x4D, 0x60, 0x27, 0x1B, 0xC5, 0x9A }
}; int main( void )
{
int m, n, i, j;
aes_context ctx;
unsigned char buf[];
unsigned char key[]; for( m = ; m < ; m++ )
{
printf( "\n Rijndael Monte Carlo Test (ECB mode) - " ); if( m == ) printf( "encryption\n\n" );
if( m == ) printf( "decryption\n\n" ); for( n = ; n < ; n++ )
{
printf( " Test %d, key size = %3d bits: ",
n + , + n * ); fflush( stdout ); memset( buf, , );
memset( key, , + n * ); for( i = ; i < ; i++ )
{
aes_set_key( &ctx, key, + n * ); for( j = ; j < ; j++ )
{
if( m == ) aes_encrypt( &ctx, buf, buf );
if( m == ) aes_decrypt( &ctx, buf, buf );
} if( n > )
{
for( j = ; j < (n << ); j++ )
{
key[j] ^= buf[j + - (n << )];
}
} if( m == ) aes_encrypt( &ctx, buf, buf );
if( m == ) aes_decrypt( &ctx, buf, buf ); for( j = ; j < ; j++ )
{
key[j + (n << )] ^= buf[j];
}
} if( ( m == && memcmp( buf, AES_enc_test[n], ) ) ||
( m == && memcmp( buf, AES_dec_test[n], ) ) )
{
printf( "failed!\n" );
return( );
} printf( "passed.\n" );
}
} printf( "\n" ); return( );
} #endif