📄 aesvec.c
字号:
// Copyright in this code is held by Dr B. R. Gladman but free direct or
// derivative use is permitted subject to acknowledgement of its origin.
// Dr B. R. Gladman <brg@gladman.uk.net> 1st June 2001.
//
// This is an implementation of the AES encryption algorithm (Rijndael)
// designed by Joan Daemen and Vincent Rijmen. This version is based on
// the reference implementation and is not efficient. It can run with
// either big or little endian internal byte order. This version has
// been modified to output the values in the round state array during
// its operation in order to provide development test vectors.
// IMPORTANT NOTE: undefine AES_DLL in aes.h
#include <stdio.h>
#include <memory.h>
#include "aes.h"
#include "aestst.h"
typedef byte wa_ptr[4];
typedef const byte cwa_ptr[4];
const byte m_poly = 0x1b;
int mod = 0; // true (1) if decryption order is modified
byte inv_tab[] = // Table of finite field inverses
{
0x00, 0x01, 0x8d, 0xf6, 0xcb, 0x52, 0x7b, 0xd1,
0xe8, 0x4f, 0x29, 0xc0, 0xb0, 0xe1, 0xe5, 0xc7,
0x74, 0xb4, 0xaa, 0x4b, 0x99, 0x2b, 0x60, 0x5f,
0x58, 0x3f, 0xfd, 0xcc, 0xff, 0x40, 0xee, 0xb2,
0x3a, 0x6e, 0x5a, 0xf1, 0x55, 0x4d, 0xa8, 0xc9,
0xc1, 0x0a, 0x98, 0x15, 0x30, 0x44, 0xa2, 0xc2,
0x2c, 0x45, 0x92, 0x6c, 0xf3, 0x39, 0x66, 0x42,
0xf2, 0x35, 0x20, 0x6f, 0x77, 0xbb, 0x59, 0x19,
0x1d, 0xfe, 0x37, 0x67, 0x2d, 0x31, 0xf5, 0x69,
0xa7, 0x64, 0xab, 0x13, 0x54, 0x25, 0xe9, 0x09,
0xed, 0x5c, 0x05, 0xca, 0x4c, 0x24, 0x87, 0xbf,
0x18, 0x3e, 0x22, 0xf0, 0x51, 0xec, 0x61, 0x17,
0x16, 0x5e, 0xaf, 0xd3, 0x49, 0xa6, 0x36, 0x43,
0xf4, 0x47, 0x91, 0xdf, 0x33, 0x93, 0x21, 0x3b,
0x79, 0xb7, 0x97, 0x85, 0x10, 0xb5, 0xba, 0x3c,
0xb6, 0x70, 0xd0, 0x06, 0xa1, 0xfa, 0x81, 0x82,
0x83, 0x7e, 0x7f, 0x80, 0x96, 0x73, 0xbe, 0x56,
0x9b, 0x9e, 0x95, 0xd9, 0xf7, 0x02, 0xb9, 0xa4,
0xde, 0x6a, 0x32, 0x6d, 0xd8, 0x8a, 0x84, 0x72,
0x2a, 0x14, 0x9f, 0x88, 0xf9, 0xdc, 0x89, 0x9a,
0xfb, 0x7c, 0x2e, 0xc3, 0x8f, 0xb8, 0x65, 0x48,
0x26, 0xc8, 0x12, 0x4a, 0xce, 0xe7, 0xd2, 0x62,
0x0c, 0xe0, 0x1f, 0xef, 0x11, 0x75, 0x78, 0x71,
0xa5, 0x8e, 0x76, 0x3d, 0xbd, 0xbc, 0x86, 0x57,
0x0b, 0x28, 0x2f, 0xa3, 0xda, 0xd4, 0xe4, 0x0f,
0xa9, 0x27, 0x53, 0x04, 0x1b, 0xfc, 0xac, 0xe6,
0x7a, 0x07, 0xae, 0x63, 0xc5, 0xdb, 0xe2, 0xea,
0x94, 0x8b, 0xc4, 0xd5, 0x9d, 0xf8, 0x90, 0x6b,
0xb1, 0x0d, 0xd6, 0xeb, 0xc6, 0x0e, 0xcf, 0xad,
0x08, 0x4e, 0xd7, 0xe3, 0x5d, 0x50, 0x1e, 0xb3,
0x5b, 0x23, 0x38, 0x34, 0x68, 0x46, 0x03, 0x8c,
0xdd, 0x9c, 0x7d, 0xa0, 0xcd, 0x1a, 0x41, 0x1c
};
// finite field multiply by 0x02 (x)
byte FFmulX(const byte a)
{
return (a << 1) ^ (a & 0x80 ? m_poly : 0);
}
byte fwd_affine(byte x)
{ word w = x;
w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
return 0x63 ^ (byte)(w ^ (w >> 8));
}
byte inv_affine(byte x)
{ word w = x;
w = (w << 1) ^ (w << 3) ^ (w << 6);
return 0x05 ^ (byte)(w ^ (w >> 8));
}
// the SubWord transformation performed on the bytes in a column
word SubWord(const word x)
{
return bytes2word(
fwd_affine(inv_tab[bval(x,0)]),
fwd_affine(inv_tab[bval(x,1)]),
fwd_affine(inv_tab[bval(x,2)]),
fwd_affine(inv_tab[bval(x,3)]) );
}
// the RotWord transformation performed on the bytes in a column
word RotWord(const word x)
{
return upr(x,3);
}
// the SubBytes transformation performed on all bytes in the state
void SubBytes(byte state[][4], word Ncol)
{ word col;
for(col = 0; col < Ncol; ++col)
{
state[col][0] = fwd_affine(inv_tab[state[col][0]]);
state[col][1] = fwd_affine(inv_tab[state[col][1]]);
state[col][2] = fwd_affine(inv_tab[state[col][2]]);
state[col][3] = fwd_affine(inv_tab[state[col][3]]);
}
}
// the inverse SubBytes transformation performed on all bytes in the state
void InvSubBytes(byte state[][4], word Ncol)
{ word col;
for(col = 0; col < Ncol; ++col)
{
state[col][0] = inv_tab[inv_affine(state[col][0])];
state[col][1] = inv_tab[inv_affine(state[col][1])];
state[col][2] = inv_tab[inv_affine(state[col][2])];
state[col][3] = inv_tab[inv_affine(state[col][3])];
}
}
// the ShiftRows transformation performed on rows 1, 2 and 3 of the state
void ShiftRows(byte state[][4], const word Ncol, const word Shr[])
{ word col, t[Mcol];
for(col = 0; col < Ncol; ++col)
t[col] = bytes2word(0, state[col][1], state[col][2], state[col][3]);
for(col = 0; col < Ncol; ++col)
{
state[col][1] = bval(t[(col + Shr[1]) % Ncol], 1);
state[col][2] = bval(t[(col + Shr[2]) % Ncol], 2);
state[col][3] = bval(t[(col + Shr[3]) % Ncol], 3);
}
}
// the inverse ShiftRows transformation performed on rows 1, 2 and 3 of state
void InvShiftRows(byte state[][4], const word Ncol, const word Shr[])
{ word col, t[Mcol];
for(col = 0; col < Ncol; ++col)
t[col] = bytes2word(0, state[col][1], state[col][2], state[col][3]);
for(col = 0; col < Ncol; ++col)
{
state[(col + Shr[1]) % Ncol][1] = bval(t[col], 1);
state[(col + Shr[2]) % Ncol][2] = bval(t[col], 2);
state[(col + Shr[3]) % Ncol][3] = bval(t[col], 3);
}
}
// the MixColumns transformation performed on all columns of the state
void MixColumns(byte state[][4], word Ncol)
{ word col;
byte t, u;
for(col = 0; col < Ncol; ++col)
{ t = state[col][0];
u = state[col][0] ^ state[col][1] ^ state[col][2] ^ state[col][3];
state[col][0] ^= u ^ FFmulX(t ^ state[col][1]);
state[col][1] ^= u ^ FFmulX(state[col][1] ^ state[col][2]);
state[col][2] ^= u ^ FFmulX(state[col][2] ^ state[col][3]);
state[col][3] ^= u ^ FFmulX(state[col][3] ^ t);
}
}
// the inverse MixColumns transformation performed on all columns of the state
void InvMixColumns(byte state[][4], word Ncol)
{ word col;
byte t, u, v;
for(col = 0; col < Ncol; ++col)
{ t = state[col][0];
u = state[col][0] ^ state[col][1] ^ state[col][2] ^ state[col][3];
u ^= FFmulX(FFmulX(FFmulX(u)));
v = u ^ FFmulX(FFmulX(state[col][1] ^ state[col][3]));
u ^= FFmulX(FFmulX(state[col][0] ^ state[col][2]));
state[col][0] ^= u ^ FFmulX(t ^ state[col][1]);
state[col][1] ^= v ^ FFmulX(state[col][1] ^ state[col][2]);
state[col][2] ^= u ^ FFmulX(state[col][2] ^ state[col][3]);
state[col][3] ^= v ^ FFmulX(state[col][3] ^ t);
}
}
// XorRoundKey - add the round key to the state
void XorRoundKey(byte state[][4], const word rk[], const word Ncol)
{ word col, t;
for(col = 0; col < Ncol; ++col)
{ t = rk[col];
state[col][0] ^= bval(t,0);
state[col][1] ^= bval(t,1);
state[col][2] ^= bval(t,2);
state[col][3] ^= bval(t,3);
}
}
// input the state from the input byte array
void GetState(byte state[][4], const byte in[], const word Ncol)
{ word col, i;
for(col = 0, i = 0; col < Ncol; ++col)
{
state[col][0] = in[i++];
state[col][1] = in[i++];
state[col][2] = in[i++];
state[col][3] = in[i++];
}
}
// output the state to the output byte array
void PutState(const byte state[][4], byte out[], const word Ncol)
{ word col, i;
for(col = 0, i = 0; col < Ncol; ++col)
{
out[i++] = state[col][0];
out[i++] = state[col][1];
out[i++] = state[col][2];
out[i++] = state[col][3];
}
}
#if(0)
// code to test the generation of the key schedule from the top downwards
static word t_key[128];
void reverse(const word Ncol, const word Nrnd, const word Nkey, const byte e_key[])
{ word i;
i = Ncol * (Nrnd + 1);
while(i-- > Ncol * (Nrnd + 1) - Nkey)
{
t_key[i] = e_key[i];
}
i = Ncol * (Nrnd + 1);
while(i-- > Nkey)
{
word t = t_key[i - 1];
if(i % Nkey == 0)
{
t = SubWord(RotWord(t)) ^ bytes2word(rc_tab[i / Nkey - 1], 0, 0, 0);
}
else if(Nkey == 8 && i % Nkey == 4)
t = SubWord(t);
t_key[i - Nkey] = t_key[i] ^ t;
}
}
#endif
// Subroutne to set the block size (if variable)
#if defined(BLOCK_SIZE)
#define nc (Ncol)
#else
#define nc (cx->Ncol)
#endif
#if !defined(BLOCK_SIZE)
cf_dec c_name(set_blk)(const word n_bytes, c_name(aes) *cx)
{
if((n_bytes & 3) || n_bytes < 16 || n_bytes > 32)
{
return (n_bytes ? cx->mode &= ~0x07, aes_bad : (aes_ret)(nc << 2));
}
cx->mode = cx->mode & ~0x07 | 0x04;
nc = n_bytes >> 2;
return aes_good;
}
#endif
// Key Expansion - expand the key to form the key schedule from the
// user supplied key, where Nk is the key length in bits divided by
// 32 with a value of 4, 6 or 8
cf_dec c_name(set_key)(const byte key[], const word n_bytes, const enum aes_key f, c_name(aes) *cx)
{ word i;
byte rc;
const byte *p;
if((n_bytes & 3) || n_bytes < 16 || n_bytes > 32 || !(f & 1) && !(f & 2))
{
return (n_bytes ? cx->mode &= ~0x03, aes_bad : (aes_ret)(cx->Nkey << 2));
}
cx->mode = cx->mode & ~0x03 | (byte)f & 0x03;
cx->Nkey = n_bytes >> 2;
cx->Nrnd = Nr(cx->Nkey, nc);
i = 0; p = key;
while (i < cx->Nkey)
{
cx->e_key[i] = bytes2word(p[0], p[1], p[2], p[3]);
i = i + 1; p += Nrow;
}
i = cx->Nkey; rc = 1;
while(i < nc * (cx->Nrnd + 1))
{
word t = cx->e_key[i - 1];
if(i % cx->Nkey == 0)
{
t = SubWord(RotWord(t)) ^ bytes2word(rc, 0, 0, 0); rc = FFmulX(rc);
}
else if(cx->Nkey > 6 && i % cx->Nkey == 4)
t = SubWord(t);
cx->e_key[i] = cx->e_key[i - cx->Nkey] ^ t;
i = i + 1;
}
if(cx->mode != enc)
{
for(i = 0; i < (cx->Nrnd + 1) * nc; ++i)
cx->d_key[i] = cx->e_key[i];
// typedef byte wa_ptr[4];
for(i = 1; i < cx->Nrnd; ++i)
InvMixColumns((wa_ptr*)(cx->d_key + i * nc), nc);
}
// reverse(nc, Nrnd, Nkey, e_key);
return aes_good;
}
#if(1)
FILE *outf = 0L;
static char *hxx = "0123456789abcdef";
void block_out(const word round, const char* xt, const byte b[][4], const word Ncol)
{ word row, col;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -