📄 aes.c
字号:
// I retain copyright in this code but I encourage its free use provided
// that I don't carry any responsibility for the results. I am especially
// happy to see it used in free and open source software. If you do use
// it I would appreciate an acknowledgement of its origin in the code or
// the product that results and I would also appreciate knowing a liitle
// about the use to which it is being put.
//
// Dr B. R. Gladman <brg@gladman.uk.net> 23rd January 2001.
// This is an implementation of the AES encryption algorithm (Rijndael)
// designed by Joan Daemen and Vincent Rijmen. This version is designed
// to provide both fixed and dynamic block and key lengths and can also
// run with either big or little endian internal byte order (see aes.h).
// It inputs block and key lengths in bytes with the legal values being
// 16, 24 and 32.
// CONFIGURATION OPTIONS (see also aes.h)
// 1. define COMPACT for a compact but slow version of the cipher (the
// other options below do not apply to the compact version)
// 2. define UNROLL for loop unrolling in encrypt and decrypt
// 3. define FIXED_TABLES for static tables built within the executable
// image - otherwise tables are built dynamically on first use
// 4. define FOUR_TABLES for high speed but increased memory use (uses four
// tables in place of one to reduce inner loop instruction counts)
// 5. define LAST_ROUND_TABLES for ultimate speed but still more memory use
// (this uses tables for the last round)
// 6. define SMALL_PTABLE for slower field multiply but smaller table
//#define COMPACT
#define UNROLL
#define FIXED_TABLES
#define FOUR_TABLES
#define LAST_ROUND_TABLES
//#define SMALL_PTABLE
// End of configuration options
#include "aes.h"
#if !defined(AES_DLL) || !defined(TEST)
// the finite field modular polynomial and elements
#define ff_poly 0x011b
#define ff_hi 0x80
#define ff_02 0x02
#define ff_03 0x03
#define ff_09 0x09
#define ff_0b 0x0b
#define ff_0d 0x0d
#define ff_0e 0x0e
// finite field multiply of a and b
#if defined(SMALL_PTABLE)
#define FFmul(a, b) (a && b ? \
FFpow[(u = FFlog[a], v = FFlog[b] + u, v + (v < u ? 1 : 0))] : 0)
#else
#define FFmul(a, b) (a && b ? FFpow[FFlog[a] + FFlog[b]] : 0)
#endif
// multiply four bytes in GF(2^8) by 'x' {02} in parallel
#define m1 0x80808080
#define m2 0x7f7f7f7f
#define m3 0x1b1b1b1b
#define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m3)
// perform column mix operation on four bytes in parallel
#define mix_col(x) (f2 = FFmulX(x), f2 ^ rot3(x ^ f2) ^ rot2(x) ^ rot1(x))
// perform inverse column mix operation on four bytes in parallel
#define inv_mix_col(x) (f9 = (x),f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, f2 ^ f4 ^ f8 ^ rot3(f2 ^ f9) ^ rot2(f4 ^ f9) ^ rot1(f9))
#if defined(FIXED_TABLES) || defined(COMPACT)
#include "aes_tab.h"
#else
#if defined(SMALL_PTABLE)
static byte FFpow[256]; // powers of generator (0x03) in GF(2^8)
#else
static byte FFpow[512];
#endif
static byte FFlog[256]; // log: map element to power of generator
static byte s_box[256]; // the S box
static byte inv_s_box[256]; // the inverse S box
static word rcon_tab[30]; // table of round constants (can be reduced
// to a length of 10 for 128-bit blocks)
#if defined(FOUR_TABLES)
static word ft_tab[4][256];
static word it_tab[4][256];
#else
static word ft_tab[256];
static word it_tab[256];
#endif
#if defined(LAST_ROUND_TABLES)
#if defined(FOUR_TABLES)
static word fl_tab[4][256];
static word il_tab[4][256];
#else
static word fl_tab[256];
static word il_tab[256];
#endif
#endif
static void gen_tabs(void)
{
word i, w;
byte b;
#if defined(SMALL_PTABLE)
byte u, v;
#endif
// log and power tables for GF(2^8) finite field with
// 0x011b as modular polynomial - the simplest primitive
// root is 0x03, used here to generate the tables
i = 0; w = 1;
do
{
FFpow[i] = (byte)w;
#if !defined(SMALL_PTABLE)
FFpow[i + 255] = (byte)w;
#endif
FFlog[w] = (byte)i++;
w ^= (w << 1) ^ (w & ff_hi ? ff_poly : 0);
}
while ( w != 1 );
FFpow[255] = 1;
for ( i = 0, w = 1; i < 28; ++i )
{
rcon_tab[i] = bytes2word(w, 0, 0, 0);
w = (w << 1) ^ (w & ff_hi ? ff_poly : 0);
}
for ( i = w = 0; i < 256; ++i )
{
w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
w ^= 0x63 ^ (w >> 8);
s_box[i] = (byte)w;
inv_s_box[(byte)w] = (byte)i;
w = FFpow[255 - FFlog[i + 1]];
}
for ( i = 0; i < 256; ++i )
{
b = s_box[i];
#if defined(LAST_ROUND_TABLES)
w = bytes2word(b, 0, 0, 0);
#if defined(FOUR_TABLES)
fl_tab[0][i] = w;
fl_tab[1][i] = rot1(w);
fl_tab[2][i] = rot2(w);
fl_tab[3][i] = rot3(w);
#else
fl_tab[i] = w;
#endif
#endif
w = bytes2word(FFmul(ff_02, b), b, b, FFmul(ff_03, b));
#if defined(FOUR_TABLES)
ft_tab[0][i] = w;
ft_tab[1][i] = rot1(w);
ft_tab[2][i] = rot2(w);
ft_tab[3][i] = rot3(w);
#else
ft_tab[i] = w;
#endif
b = inv_s_box[i];
#if defined(LAST_ROUND_TABLES)
w = bytes2word(b, 0, 0, 0);
#if defined(FOUR_TABLES)
il_tab[0][i] = w;
il_tab[1][i] = rot1(w);
il_tab[2][i] = rot2(w);
il_tab[3][i] = rot3(w);
#else
il_tab[i] = w;
#endif
#endif
w = bytes2word(FFmul(ff_0e, b), FFmul(ff_09, b),
FFmul(ff_0d, b), FFmul(ff_0b, b));
#if defined(FOUR_TABLES)
it_tab[0][i] = w;
it_tab[1][i] = rot1(w);
it_tab[2][i] = rot2(w);
it_tab[3][i] = rot3(w);
#else
it_tab[i] = w;
#endif
}
}
#endif // !FIXED_TABLES && !COMPACT
#if defined(COMPACT) || !defined(LAST_ROUND_TABLES)
#define ls_box(x) bytes2word( \
s_box[byte0(x)], s_box[byte1(x)], \
s_box[byte2(x)], s_box[byte3(x)])
#elif defined(FOUR_TABLES)
#define ls_box(x) ( fl_tab[0][byte0(x)] ^ fl_tab[1][byte1(x)] ^ fl_tab[2][byte2(x)] ^ fl_tab[3][byte3(x)] )
#else
#define ls_box(x) \
( fl_tab[byte0(x)] \
^ rot1(fl_tab[byte1(x)]) \
^ rot2(fl_tab[byte2(x)]) \
^ rot3(fl_tab[byte3(x)]) )
#endif
// Subroutne to set the block size (if variable) in bytes, legal
// values being 16, 24 and 32.
#if defined(BLOCK_SIZE_R)
#define n_col (Ncol)
#define fr_sh(n,r) (((n) + Shr##r) % n_col)
#define ir_sh(n,r) (((n) + n_col - Shr##r) % n_col)
#else
#define n_col (f_dat(cx,Ncol))
#define sh(x) (f_dat(cx,Shr)[x])
#define fr_sh(n,r) (f_dat(cx,shf##r)[n])
#define ir_sh(n,r) (f_dat(cx,shr##r)[n])
#if defined(AES_IN_CPP)
rval aes::set_blk(const word n_bytes)
#else
cf_dec set_blk(const word n_bytes, aes *cx)
#endif
{
word i, j;
if ( n_bytes != 16 && n_bytes != 24 && n_bytes != 32 )
return(n_bytes ? aes_bad : (rval)n_col);
#if !defined(FIXED_TABLES)
if ( !(f_dat(cx,mode) & 0x08) )
{
gen_tabs(); mode = 0x08;
}
#endif
f_dat(cx,mode) |= 0x04;
n_col = n_bytes >> 2;
for ( i = 0; i < 8; ++i )
{
j = 1;
f_dat(cx,shf1)[i] = (byte)((i + j) % n_col);
f_dat(cx,shr1)[i] = (byte)((n_col + i - j) % n_col);
j = (n_col == 8 ? 3 : 2);
f_dat(cx,shf2)[i] = (byte)((i + j) % n_col);
f_dat(cx,shr2)[i] = (byte)((n_col + i - j) % n_col);
++j;
f_dat(cx,shf3)[i] = (byte)((i + j) % n_col);
f_dat(cx,shr3)[i] = (byte)((n_col + i - j) % n_col);
}
return aes_good;
}
#endif
// Initialise the key schedule from the user supplied key. The key
// length is now specified in bytes - 16, 24 or 32 as appropriate.
// This corresponds to bit lengths of 128, 192 and 256 bits, and
// to Nk values of 4, 6 and 8 respectively.
#define mx(t,f) *t++ = inv_mix_col(*f++);
#if !defined(BLOCK_SIZE_R)
#define cpy(t,f) \
switch(n_col) \
{ case 8: *t++ = *f++; *t++ = *f++; \
case 6: *t++ = *f++; *t++ = *f++; \
case 4: *t++ = *f++; *t++ = *f++; \
*t++ = *f++; *t++ = *f++; \
}
#define mix(t,f) \
switch(n_col) \
{ case 8: mx(t,f); mx(t,f); \
case 6: mx(t,f); mx(t,f); \
case 4: mx(t,f); mx(t,f); \
mx(t,f); mx(t,f); \
}
#elif BLOCK_SIZE_R == 16
#define cpy(t,f) *t++ = *f++; *t++ = *f++; *t++ = *f++; *t++ = *f++
#define mix(t,f) { mx(t,f); mx(t,f); mx(t,f); mx(t,f); }
#elif BLOCK_SIZE_R == 24
#define cpy(t,f) *t++ = *f++; *t++ = *f++; *t++ = *f++; *t++ = *f++; \
*t++ = *f++; *t++ = *f++
#define mix(t,f) { mx(t,f); mx(t,f); mx(t,f); mx(t,f); \
mx(t,f); mx(t,f); }
#elif BLOCK_SIZE_R == 32
#define cpy(t,f) *t++ = *f++; *t++ = *f++; *t++ = *f++; *t++ = *f++; \
*t++ = *f++; *t++ = *f++; *t++ = *f++; *t++ = *f++
#define mix(t,f) { mx(t,f); mx(t,f); mx(t,f); mx(t,f); \
mx(t,f); mx(t,f); mx(t,f); mx(t,f); }
#endif
#if defined(AES_IN_CPP)
rval aes::set_key(const byte in_key[], const word n_bytes, const enum aes_key f)
#else
cf_dec set_key(const byte in_key[], const word n_bytes, const enum aes_key f, aes *cx)
#endif
{
word t, *k1, *kt, *rcp;
if ( n_bytes != 16 && n_bytes != 24 && n_bytes != 32 ) return aes_bad;
#if !defined(FIXED_TABLES)
if ( !(f_dat(cx,mode) & 0x08) )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -