#include "AESAssembly.h"
#if defined UseAESedp
#if defined UseAESedp_GeneralC
static void XorBlock(AESData *a, const AESData *b, const AESData *c)
{
a->w[0] = b->w[0] ^ c->w[0];
a->w[1] = b->w[1] ^ c->w[1];
a->w[2] = b->w[2] ^ c->w[2];
a->w[3] = b->w[3] ^ c->w[3];
}
#include "Data.c" // Include tables with precalculated AES functions.
static Word InvMixColumn(Word w)
{
union { Word w; Byte b[4]; } b = { w };
Byte
s0 = b.b[0],
s1 = b.b[1],
s2 = b.b[2],
s3 = b.b[3];
return
AESInvMixColumnTable[0][s0]
^ AESInvMixColumnTable[1][s1]
^ AESInvMixColumnTable[2][s2]
^ AESInvMixColumnTable[3][s3];
}
static void AESExpandKey(Word *ExpandedKey, const AESKey *Key, long Nk)
{
const Word (*T)[256] = AESSubBytesWordTable;
const Byte *R = AESRcon;
Word * const E = ExpandedKey;
switch (Nk)
{
default:
case 4:
{
const int Nr = 10;
Word
e0 = E[0] = Key->w[0],
e1 = E[1] = Key->w[1],
e2 = E[2] = Key->w[2],
e3 = E[3] = Key->w[3];
for (int i = Nk; i < Nb * (Nr + 1); i += Nk)
{
Word temp;
{
Byte * const b = (Byte *) &e3;
Byte b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
temp = T[0][b1] ^ T[1][b2] ^ T[2][b3] ^ T[3][b0];
}
temp ^= *++R;
E[i+0] = e0 ^= temp;
E[i+1] = e1 ^= e0;
E[i+2] = e2 ^= e1;
E[i+3] = e3 ^= e2;
}
break;
}
case 6:
{
const int Nr = 12;
for (int i = 0; i < Nk; ++i)
E[i] = Key->w[i];
Word temp = E[Nk-1];
for (int i = Nk; 1; i += Nk)
{
{
Byte * const b = (Byte *) &temp;
Byte b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
temp = T[0][b1] ^ T[1][b2] ^ T[2][b3] ^ T[3][b0];
temp ^= *++R;
}
E[i+0] = temp ^= E[i+0-Nk];
E[i+1] = temp ^= E[i+1-Nk];
E[i+2] = temp ^= E[i+2-Nk];
E[i+3] = temp ^= E[i+3-Nk];
if (Nb * Nr <= i)
break;
E[i+4] = temp ^= E[i+4-Nk];
E[i+5] = temp ^= E[i+5-Nk];
}
break;
}
case 8:
{
const int Nr = 14;
for (int i = 0; i < Nk; ++i)
E[i] = Key->w[i];
Word temp = E[Nk-1];
for (int i = Nk; 1; i += Nk)
{
{
Byte * const b = (Byte *) &temp;
Byte b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
temp = T[0][b1] ^ T[1][b2] ^ T[2][b3] ^ T[3][b0];
temp ^= *++R;
}
E[i+0] = temp ^= E[i+0-Nk];
E[i+1] = temp ^= E[i+1-Nk];
E[i+2] = temp ^= E[i+2-Nk];
E[i+3] = temp ^= E[i+3-Nk];
if (Nb * Nr <= i)
break;
{
Byte * const b = (Byte *) &temp;
Byte b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
temp = T[0][b0] ^ T[1][b1] ^ T[2][b2] ^ T[3][b3];
}
E[i+4] = temp ^= E[i+4-Nk];
E[i+5] = temp ^= E[i+5-Nk];
E[i+6] = temp ^= E[i+6-Nk];
E[i+7] = temp ^= E[i+7-Nk];
}
break;
}
}
}
static void AESEncryptWithExpandedKey(Byte *Ciphertext, const Byte *Plaintext,
const AESData *ExpandedKey, long Nr)
{
AESData State;
XorBlock(&State, (const AESData *) Plaintext, &ExpandedKey[0]);
{
const Word (*T)[256] = AESEncryptTable;
for (int round = 1; round < Nr; ++round)
{
const AESData *Key = &ExpandedKey[round];
const union { Word w; Byte b[4]; }
w0 = { State.w[0] },
w1 = { State.w[1] },
w2 = { State.w[2] },
w3 = { State.w[3] };
State.w[0] = Key->w[0]
^ T[0][w0.b[0]] ^ T[1][w1.b[1]] ^ T[2][w2.b[2]] ^ T[3][w3.b[3]];
State.w[1] = Key->w[1]
^ T[0][w1.b[0]] ^ T[1][w2.b[1]] ^ T[2][w3.b[2]] ^ T[3][w0.b[3]];
State.w[2] = Key->w[2]
^ T[0][w2.b[0]] ^ T[1][w3.b[1]] ^ T[2][w0.b[2]] ^ T[3][w1.b[3]];
State.w[3] = Key->w[3]
^ T[0][w3.b[0]] ^ T[1][w0.b[1]] ^ T[2][w1.b[2]] ^ T[3][w2.b[3]];
}
}
{
const Word (*T)[256] = AESSubBytesWordTable;
const AESData *Key = &ExpandedKey[Nr];
const union { Word w; Byte b[4]; }
w0 = { State.w[0] },
w1 = { State.w[1] },
w2 = { State.w[2] },
w3 = { State.w[3] };
State.w[0] = Key->w[0]
^ T[0][w0.b[0]] ^ T[1][w1.b[1]] ^ T[2][w2.b[2]] ^ T[3][w3.b[3]];
State.w[1] = Key->w[1]
^ T[0][w1.b[0]] ^ T[1][w2.b[1]] ^ T[2][w3.b[2]] ^ T[3][w0.b[3]];
State.w[2] = Key->w[2]
^ T[0][w2.b[0]] ^ T[1][w3.b[1]] ^ T[2][w0.b[2]] ^ T[3][w1.b[3]];
State.w[3] = Key->w[3]
^ T[0][w3.b[0]] ^ T[1][w0.b[1]] ^ T[2][w1.b[2]] ^ T[3][w2.b[3]];
}
* (AESData *) Ciphertext = State;
}
static void AESDecryptWithExpandedKey(Byte *Plaintext, const Byte *Ciphertext,
const AESData *ExpandedKey, long Nr)
{
AESData State;
XorBlock(&State, (const AESData *) Ciphertext, &ExpandedKey[Nr]);
{
const Word (*T)[256] = AESDecryptTable;
for (int round = Nr-1; 0 < round; --round)
{
const AESData *Key = &ExpandedKey[round];
const union { Word w; Byte b[4]; }
w0 = { State.w[0] },
w1 = { State.w[1] },
w2 = { State.w[2] },
w3 = { State.w[3] };
State.w[0] = Key->w[0]
^ T[0][w0.b[0]] ^ T[1][w3.b[1]] ^ T[2][w2.b[2]] ^ T[3][w1.b[3]];
State.w[1] = Key->w[1]
^ T[0][w1.b[0]] ^ T[1][w0.b[1]] ^ T[2][w3.b[2]] ^ T[3][w2.b[3]];
State.w[2] = Key->w[2]
^ T[0][w2.b[0]] ^ T[1][w1.b[1]] ^ T[2][w0.b[2]] ^ T[3][w3.b[3]];
State.w[3] = Key->w[3]
^ T[0][w3.b[0]] ^ T[1][w2.b[1]] ^ T[2][w1.b[2]] ^ T[3][w0.b[3]];
}
}
{
const Word (*T)[256] = AESInvSubBytesWordTable;
const AESData *Key = &ExpandedKey[0];
const union { Word w; Byte b[4]; }
w0 = { State.w[0] },
w1 = { State.w[1] },
w2 = { State.w[2] },
w3 = { State.w[3] };
State.w[0] = Key->w[0]
^ T[0][w0.b[0]] ^ T[1][w3.b[1]] ^ T[2][w2.b[2]] ^ T[3][w1.b[3]];
State.w[1] = Key->w[1]
^ T[0][w1.b[0]] ^ T[1][w0.b[1]] ^ T[2][w3.b[2]] ^ T[3][w2.b[3]];
State.w[2] = Key->w[2]
^ T[0][w2.b[0]] ^ T[1][w1.b[1]] ^ T[2][w0.b[2]] ^ T[3][w3.b[3]];
State.w[3] = Key->w[3]
^ T[0][w3.b[0]] ^ T[1][w2.b[1]] ^ T[2][w1.b[2]] ^ T[3][w0.b[3]];
}
* (AESData *) Plaintext = State;
}
#else // defined UseAESedp_GeneralC
void AESExpandKeyForEncryption(Word *ExpandedKey, const AESKey *Key,
long Nk);
void AESExpandKeyForDecryption(Word *ExpandedKey, const AESKey *Key,
long Nk);
void AESEncryptWithExpandedKey(Byte *OutputText, const Byte *InputText,
const AESData *ExpandedKey, long Nr);
void AESDecryptWithExpandedKey(Byte *OutputText, const Byte *InputText,
const AESData *ExpandedKey, long Nr);
void AESEncryptCBC(void *Output, const void *Input,
void *ChainBuffer, void *Key, long Blocks, long Rounds);
void AESDecryptCBC(void *Output, const void *Input,
void *ChainBuffer, void *Key, long Blocks, long Rounds);
#endif // defined UseAESedp_GeneralC
int aes_cc_set_key(
aes_cc_ctx *Context, const void *Key, aes_32t KeyLength, int ForEncryption )
{
if (KeyLength != 16 && KeyLength != 24 && KeyLength != 32)
return -1;
const int Nk = KeyLength / 4;
Context->encrypt.rn = Nk + 6;
#if defined UseAESedp_GeneralC
AESExpandKey(Context->encrypt.ks, Key, Nk);
if (!ForEncryption)
{
Word *E = Context->encrypt.ks;
int Nr = Context->encrypt.rn;
for (int i = Nb; i < Nr * Nb; ++i)
E[i] = InvMixColumn(E[i]);
}
#else
if (ForEncryption)
AESExpandKeyForEncryption(Context->encrypt.ks, Key, Nk);
else
AESExpandKeyForDecryption(Context->encrypt.ks, Key, Nk);
#endif
Context->encrypt.cbcEnable = 0;
return 0;
}
#include <string.h> // For memcpy.
void aes_cc_set_iv(aes_cc_ctx *Context, int ForEncryption, const void *IV)
{
if (IV == 0)
Context->encrypt.cbcEnable = 0;
else
{
Context->encrypt.cbcEnable = 1;
memcpy(Context->encrypt.chainBuf, IV, sizeof Context->encrypt.chainBuf);
}
}
void aes_cc_encrypt(
aes_cc_ctx *Context, const void *Input, aes_32t Blocks, void *Output )
{
const AESData *I = Input;
AESData *O = Output;
if (Context->encrypt.cbcEnable)
{
#if defined UseAESedp_GeneralC
AESData State = * (AESData *) Context->encrypt.chainBuf;
while (Blocks--)
{
XorBlock(&State, &State, I++);
AESEncryptWithExpandedKey(State.b, State.b,
(const void *) Context->encrypt.ks,
Context->encrypt.rn);
*O++ = State;
}
* (AESData *) Context->encrypt.chainBuf = State;
#else AESEncryptCBC(O, I, Context->encrypt.chainBuf,
Context->encrypt.ks, Blocks, Context->encrypt.rn);
#endif }
else
{
aes_32t i;
for (i = 0; i < Blocks; ++i)
AESEncryptWithExpandedKey(O[i].b, I[i].b,
(const void *) Context->encrypt.ks, Context->encrypt.rn);
}
}
aes_rval aes_encrypt_cbc(
const unsigned char *Input,
const unsigned char *InitialValue,
unsigned int Blocks,
unsigned char *Output,
aes_encrypt_ctx *Context)
{
const AESData *I = (const AESData *) Input;
AESData *O = ( AESData *) Output;
if (Context->cbcEnable || InitialValue)
{
#if defined UseAESedp_GeneralC
AESData State = InitialValue
? * (const AESData *) InitialValue
: * (const AESData *) Context->chainBuf;
while (Blocks--)
{
XorBlock(&State, &State, I++);
AESEncryptWithExpandedKey(State.b, State.b,
(const void *) Context->ks,
Context->rn);
*O++ = State;
}
* (AESData *) Context->chainBuf = State;
#else AESEncryptCBC(O, I, Context->chainBuf,
Context->ks, Blocks, Context->rn);
#endif }
else
{
aes_32t i;
for (i = 0; i < Blocks; ++i)
AESEncryptWithExpandedKey(O[i].b, I[i].b,
(const void *) Context->ks, Context->rn);
}
}
void aes_cc_decrypt(
aes_cc_ctx *Context, const void *Input, aes_32t Blocks, void *Output )
{
const AESData *I = Input;
AESData *O = Output;
if (Context->encrypt.cbcEnable)
{
#if defined UseAESedp_GeneralC
AESData NextChainValue = * (AESData *) Context->encrypt.chainBuf;
while (Blocks--)
{
AESData ChainValue = NextChainValue, State;
NextChainValue = *I++;
AESDecryptWithExpandedKey(State.b, NextChainValue.b,
(const void *) Context->encrypt.ks, Context->encrypt.rn);
XorBlock(O++, &State, &ChainValue);
}
* (AESData *) Context->encrypt.chainBuf = NextChainValue;
#else AESDecryptCBC(O, I, Context->encrypt.chainBuf,
Context->encrypt.ks, Blocks, Context->encrypt.rn);
#endif }
else
{
aes_32t i;
for (i = 0; i < Blocks; ++i)
AESDecryptWithExpandedKey(O[i].b, I[i].b,
(const void *) Context->encrypt.ks, Context->encrypt.rn);
}
}
aes_rval aes_decrypt_cbc(
const unsigned char *Input,
const unsigned char *InitialValue,
unsigned int Blocks,
unsigned char *Output,
aes_decrypt_ctx *Context)
{
const AESData *I = (const AESData *) Input;
AESData *O = ( AESData *) Output;
if (Context->cbcEnable || InitialValue)
{
#if defined UseAESedp_GeneralC
AESData NextChainValue = InitialValue
? * (const AESData *) InitialValue
: * (const AESData *) Context->chainBuf;
while (Blocks--)
{
AESData ChainValue = NextChainValue, State;
NextChainValue = *I++;
AESDecryptWithExpandedKey(State.b, NextChainValue.b,
(const void *) Context->ks, Context->rn);
XorBlock(O++, &State, &ChainValue);
}
* (AESData *) Context->chainBuf = NextChainValue;
#else AESDecryptCBC(O, I, Context->chainBuf,
Context->ks, Blocks, Context->rn);
#endif }
else
{
aes_32t i;
for (i = 0; i < Blocks; ++i)
AESDecryptWithExpandedKey(O[i].b, I[i].b,
(const void *) Context->ks, Context->rn);
}
}
#endif // defined UseAESedp