rijndael-alg-ref.c [plain text]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rijndael-alg-ref.h"
#include <cspdebugging.h>
#define SC ((BC - 4) >> 1)
#include "boxes-ref.h"
static const word8 shifts[3][4][2] = {
{ { 0, 0 },
{ 1, 3 },
{ 2, 2 },
{ 3, 1 }
},
{ { 0, 0 },
{ 1, 5 },
{ 2, 4 },
{ 3, 3 }
},
{ { 0, 0 },
{ 1, 7 },
{ 3, 5 },
{ 4, 4 }
}
};
#if !GLADMAN_AES_128_ENABLE
static const word8 shifts128[4][2] = {
{ 0, 0 },
{ 8, 24 },
{ 16, 16 },
{ 24, 8 }
};
#endif
#if !AES_MUL_BY_LOOKUP
static inline word8 mod255(word32 b)
{
if(b >= 255) {
b -= 255;
}
return b;
}
word8 mul(word8 a, word8 b) {
if (a && b) return Alogtable[mod255(Logtable[a] + Logtable[b])];
else return 0;
}
#endif
static
void KeyAddition(word8 a[4][MAXBC], word8 rk[4][MAXBC], word8 BC) {
int i, j;
for(i = 0; i < 4; i++)
for(j = 0; j < BC; j++) a[i][j] ^= rk[i][j];
}
static
void ShiftRow(word8 a[4][MAXBC], word8 d, word8 BC) {
word8 tmp[MAXBC];
int i, j;
for(i = 1; i < 4; i++) {
for(j = 0; j < BC; j++) tmp[j] = a[i][(j + shifts[SC][i][d]) % BC];
for(j = 0; j < BC; j++) a[i][j] = tmp[j];
}
}
static
void Substitution(word8 a[4][MAXBC], const word8 box[256], word8 BC) {
int i, j;
for(i = 0; i < 4; i++)
for(j = 0; j < BC; j++) a[i][j] = box[a[i][j]] ;
}
static
void MixColumn(word8 a[4][MAXBC], word8 BC) {
word8 b[4][MAXBC];
int i, j;
for(j = 0; j < BC; j++) {
for(i = 0; i < 4; i++) {
#if AES_MUL_BY_LOOKUP
b[i][j] = mulBy0x02[a[i][j]]
^ mulBy0x03[a[(i + 1) % 4][j]]
^ a[(i + 2) % 4][j]
^ a[(i + 3) % 4][j];
#else
b[i][j] = mul(2,a[i][j])
^ mul(3,a[(i + 1) % 4][j])
^ a[(i + 2) % 4][j]
^ a[(i + 3) % 4][j];
#endif
}
}
for(i = 0; i < 4; i++) {
for(j = 0; j < BC; j++) a[i][j] = b[i][j];
}
}
static
void InvMixColumn(word8 a[4][MAXBC], word8 BC) {
word8 b[4][MAXBC];
int i, j;
for(j = 0; j < BC; j++) {
for(i = 0; i < 4; i++) {
#if AES_MUL_BY_LOOKUP
b[i][j] = mulBy0x0e[a[i][j]]
^ mulBy0x0b[a[(i + 1) % 4][j]]
^ mulBy0x0d[a[(i + 2) % 4][j]]
^ mulBy0x09[a[(i + 3) % 4][j]];
#else
b[i][j] = mul(0xe,a[i][j])
^ mul(0xb,a[(i + 1) % 4][j])
^ mul(0xd,a[(i + 2) % 4][j])
^ mul(0x9,a[(i + 3) % 4][j]);
#endif
}
}
for(i = 0; i < 4; i++) {
for(j = 0; j < BC; j++) a[i][j] = b[i][j];
}
}
int rijndaelKeySched (
word8 k[4][MAXKC],
int keyBits,
int blockBits,
word8 W[MAXROUNDS+1][4][MAXBC]) {
int KC, BC, ROUNDS;
int i, j, t, rconpointer = 0;
word8 tk[4][MAXKC];
switch (keyBits) {
case 128: KC = 4; break;
case 192: KC = 6; break;
case 256: KC = 8; break;
default : return (-1);
}
switch (blockBits) {
case 128: BC = 4; break;
case 192: BC = 6; break;
case 256: BC = 8; break;
default : return (-2);
}
switch (keyBits >= blockBits ? keyBits : blockBits) {
case 128: ROUNDS = 10; break;
case 192: ROUNDS = 12; break;
case 256: ROUNDS = 14; break;
default : return (-3);
}
for(j = 0; j < KC; j++)
for(i = 0; i < 4; i++)
tk[i][j] = k[i][j];
t = 0;
for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++)
for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j];
while (t < (ROUNDS+1)*BC) {
for(i = 0; i < 4; i++)
tk[i][0] ^= S[tk[(i+1)%4][KC-1]];
tk[0][0] ^= rcon[rconpointer++];
if (KC != 8)
for(j = 1; j < KC; j++)
for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1];
else {
for(j = 1; j < KC/2; j++)
for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1];
for(i = 0; i < 4; i++) tk[i][KC/2] ^= S[tk[i][KC/2 - 1]];
for(j = KC/2 + 1; j < KC; j++)
for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1];
}
for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++)
for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j];
}
return 0;
}
int rijndaelEncrypt (
word8 a[4][MAXBC],
int keyBits,
int blockBits,
word8 rk[MAXROUNDS+1][4][MAXBC])
{
int r, BC, ROUNDS;
switch (blockBits) {
case 128: BC = 4; break;
case 192: BC = 6; break;
case 256: BC = 8; break;
default : return (-2);
}
switch (keyBits >= blockBits ? keyBits : blockBits) {
case 128: ROUNDS = 10; break;
case 192: ROUNDS = 12; break;
case 256: ROUNDS = 14; break;
default : return (-3);
}
KeyAddition(a,rk[0],BC);
for(r = 1; r < ROUNDS; r++) {
Substitution(a,S,BC);
ShiftRow(a,0,BC);
MixColumn(a,BC);
KeyAddition(a,rk[r],BC);
}
Substitution(a,S,BC);
ShiftRow(a,0,BC);
KeyAddition(a,rk[ROUNDS],BC);
return 0;
}
int rijndaelDecrypt (
word8 a[4][MAXBC],
int keyBits,
int blockBits,
word8 rk[MAXROUNDS+1][4][MAXBC])
{
int r, BC, ROUNDS;
switch (blockBits) {
case 128: BC = 4; break;
case 192: BC = 6; break;
case 256: BC = 8; break;
default : return (-2);
}
switch (keyBits >= blockBits ? keyBits : blockBits) {
case 128: ROUNDS = 10; break;
case 192: ROUNDS = 12; break;
case 256: ROUNDS = 14; break;
default : return (-3);
}
KeyAddition(a,rk[ROUNDS],BC);
Substitution(a,Si,BC);
ShiftRow(a,1,BC);
for(r = ROUNDS-1; r > 0; r--) {
KeyAddition(a,rk[r],BC);
InvMixColumn(a,BC);
Substitution(a,Si,BC);
ShiftRow(a,1,BC);
}
KeyAddition(a,rk[0],BC);
return 0;
}
#if !GLADMAN_AES_128_ENABLE
static inline void KeyAddition128(
word8 a[4][BC_128_OPT],
word8 rk[4][MAXBC]) {
((word32 *)a)[0] ^= *((word32 *)(&rk[0]));
((word32 *)a)[1] ^= *((word32 *)(&rk[1]));
((word32 *)a)[2] ^= *((word32 *)(&rk[2]));
((word32 *)a)[3] ^= *((word32 *)(&rk[3]));
}
static void Substitution128(
word8 a[4][BC_128_OPT],
const word8 box[256]) {
int i, j;
for(i = 0; i < 4; i++) {
for(j = 0; j < BC_128_OPT; j++) {
a[i][j] = box[a[i][j]];
}
}
}
#if defined(__ppc__) && defined(__GNUC__)
static inline void rotateWordLeft(
word8 *word, unsigned rotCount) {
word32 lword = *((word32 *)word);
asm("rlwnm %0,%1,%2,0,31" : "=r"(lword) : "0"(lword), "r"(rotCount));
*((word32 *)word) = lword;
}
#else
static void rotateWordLeft(
word8 *word, unsigned rotCount) {
word8 tmp[BC_128_OPT] __attribute__((aligned(4)));
unsigned bytes = rotCount / 8;
tmp[0] = word[bytes & (BC_128_OPT-1)];
tmp[1] = word[(1+bytes) & (BC_128_OPT-1)];
tmp[2] = word[(2+bytes) & (BC_128_OPT-1)];
tmp[3] = word[(3+bytes) & (BC_128_OPT-1)];
*((word32 *)word) = *((word32 *)tmp);
}
#endif
static inline void ShiftRow128(
word8 a[4][BC_128_OPT],
word8 d) {
int i;
for(i = 1; i < 4; i++) {
rotateWordLeft(a[i], shifts128[i][d]);
}
}
static void MixColumn128(word8 a[4][BC_128_OPT]) {
word8 b[4][BC_128_OPT];
int i, j;
for(j = 0; j < BC_128_OPT; j++) {
for(i = 0; i < 4; i++) {
#if AES_MUL_BY_LOOKUP
b[i][j] = mulBy0x02[a[i][j]]
^ mulBy0x03[a[(i + 1) % 4][j]]
^ a[(i + 2) % 4][j]
^ a[(i + 3) % 4][j];
#else
b[i][j] = mul(2,a[i][j])
^ mul(3,a[(i + 1) % 4][j])
^ a[(i + 2) % 4][j]
^ a[(i + 3) % 4][j];
#endif
}
}
memmove(a, b, 4 * BC_128_OPT);
}
static void InvMixColumn128(word8 a[4][BC_128_OPT]) {
word8 b[4][BC_128_OPT];
int i, j;
for(j = 0; j < BC_128_OPT; j++) {
for(i = 0; i < 4; i++) {
#if AES_MUL_BY_LOOKUP
b[i][j] = mulBy0x0e[a[i][j]]
^ mulBy0x0b[a[(i + 1) % 4][j]]
^ mulBy0x0d[a[(i + 2) % 4][j]]
^ mulBy0x09[a[(i + 3) % 4][j]];
#else
b[i][j] = mul(0xe,a[i][j])
^ mul(0xb,a[(i + 1) % 4][j])
^ mul(0xd,a[(i + 2) % 4][j])
^ mul(0x9,a[(i + 3) % 4][j]);
#endif
}
}
memmove(a, b, 4 * BC_128_OPT);
}
int rijndaelKeySched128 (
word8 k[4][KC_128_OPT],
word8 W[MAXROUNDS+1][4][MAXBC]) {
int i, j, t, rconpointer = 0;
word8 tk[4][KC_128_OPT];
unsigned numSchedRows = (ROUNDS_128_OPT + 1) * BC_128_OPT;
for(j = 0; j < KC_128_OPT; j++)
for(i = 0; i < 4; i++)
tk[i][j] = k[i][j];
t = 0;
for(j = 0; (j < KC_128_OPT) && (t < numSchedRows); j++, t++) {
for(i = 0; i < 4; i++) {
W[t / BC_128_OPT][i][t % BC_128_OPT] = tk[i][j];
}
}
while (t < numSchedRows) {
for(i = 0; i < 4; i++) {
tk[i][0] ^= S[tk[(i+1)%4][KC_128_OPT-1]];
}
tk[0][0] ^= rcon[rconpointer++];
for(j = 1; j < KC_128_OPT; j++) {
for(i = 0; i < 4; i++) {
tk[i][j] ^= tk[i][j-1];
}
}
for(j = 0; (j < KC_128_OPT) && (t < numSchedRows); j++, t++) {
for(i = 0; i < 4; i++) {
W[t / BC_128_OPT][i][t % BC_128_OPT] = tk[i][j];
}
}
}
return 0;
}
int rijndaelEncrypt128 (
word8 a[4][BC_128_OPT],
word8 rk[MAXROUNDS+1][4][MAXBC])
{
int r;
KeyAddition128(a,rk[0]);
for(r = 1; r < ROUNDS_128_OPT; r++) {
Substitution128(a,S);
ShiftRow128(a,0);
MixColumn128(a);
KeyAddition128(a,rk[r]);
}
Substitution128(a,S);
ShiftRow128(a,0);
KeyAddition128(a,rk[ROUNDS_128_OPT]);
return 0;
}
int rijndaelDecrypt128 (
word8 a[4][BC_128_OPT],
word8 rk[MAXROUNDS+1][4][MAXBC])
{
int r;
KeyAddition128(a,rk[ROUNDS_128_OPT]);
Substitution128(a,Si);
ShiftRow128(a,1);
for(r = ROUNDS_128_OPT-1; r > 0; r--) {
KeyAddition128(a,rk[r]);
InvMixColumn128(a);
Substitution128(a,Si);
ShiftRow128(a,1);
}
KeyAddition128(a,rk[0]);
return 0;
}
#endif