313 lines
7.6 KiB
C
313 lines
7.6 KiB
C
|
/* rijndael-api-ref.c v2.1 April 2000
|
||
|
* Reference ANSI C code
|
||
|
* authors: v2.0 Paulo Barreto
|
||
|
* Vincent Rijmen, K.U.Leuven
|
||
|
* v2.1 Vincent Rijmen, K.U.Leuven
|
||
|
*
|
||
|
* This code is placed in the public domain.
|
||
|
*/
|
||
|
#include "mvOs.h"
|
||
|
|
||
|
#include "mvAes.h"
|
||
|
#include "mvAesAlg.h"
|
||
|
|
||
|
|
||
|
/* Defines:
|
||
|
Add any additional defines you need
|
||
|
*/
|
||
|
|
||
|
#define MODE_ECB 1 /* Are we ciphering in ECB mode? */
|
||
|
#define MODE_CBC 2 /* Are we ciphering in CBC mode? */
|
||
|
#define MODE_CFB1 3 /* Are we ciphering in 1-bit CFB mode? */
|
||
|
|
||
|
|
||
|
int aesMakeKey(MV_U8 *expandedKey, MV_U8 *keyMaterial, int keyLen, int blockLen)
|
||
|
{
|
||
|
MV_U8 W[MAXROUNDS+1][4][MAXBC];
|
||
|
MV_U8 k[4][MAXKC];
|
||
|
MV_U8 j;
|
||
|
int i, rounds, KC;
|
||
|
|
||
|
if (expandedKey == NULL)
|
||
|
{
|
||
|
return AES_BAD_KEY_INSTANCE;
|
||
|
}
|
||
|
|
||
|
if (!((keyLen == 128) || (keyLen == 192) || (keyLen == 256)))
|
||
|
{
|
||
|
return AES_BAD_KEY_MAT;
|
||
|
}
|
||
|
|
||
|
if (keyMaterial == NULL)
|
||
|
{
|
||
|
return AES_BAD_KEY_MAT;
|
||
|
}
|
||
|
|
||
|
/* initialize key schedule: */
|
||
|
for(i=0; i<keyLen/8; i++)
|
||
|
{
|
||
|
j = keyMaterial[i];
|
||
|
k[i % 4][i / 4] = j;
|
||
|
}
|
||
|
|
||
|
rijndaelKeySched (k, keyLen, blockLen, W);
|
||
|
#ifdef MV_AES_DEBUG
|
||
|
{
|
||
|
MV_U8* pW = &W[0][0][0];
|
||
|
int x;
|
||
|
|
||
|
mvOsPrintf("Expended Key: size = %d\n", sizeof(W));
|
||
|
for(i=0; i<sizeof(W); i++)
|
||
|
{
|
||
|
mvOsPrintf("%02x ", pW[i]);
|
||
|
}
|
||
|
for(i=0; i<MAXROUNDS+1; i++)
|
||
|
{
|
||
|
mvOsPrintf("\n Round #%02d: ", i);
|
||
|
for(x=0; x<MAXBC; x++)
|
||
|
{
|
||
|
mvOsPrintf("%02x%02x%02x%02x ",
|
||
|
W[i][0][x], W[i][1][x], W[i][2][x], W[i][3][x]);
|
||
|
}
|
||
|
mvOsPrintf("\n");
|
||
|
}
|
||
|
}
|
||
|
#endif /* MV_AES_DEBUG */
|
||
|
switch (keyLen)
|
||
|
{
|
||
|
case 128:
|
||
|
rounds = 10;
|
||
|
KC = 4;
|
||
|
break;
|
||
|
case 192:
|
||
|
rounds = 12;
|
||
|
KC = 6;
|
||
|
break;
|
||
|
case 256:
|
||
|
rounds = 14;
|
||
|
KC = 8;
|
||
|
break;
|
||
|
default :
|
||
|
return (-1);
|
||
|
}
|
||
|
|
||
|
for(i=0; i<MAXBC; i++)
|
||
|
{
|
||
|
for(j=0; j<4; j++)
|
||
|
{
|
||
|
expandedKey[i*4+j] = W[rounds][j][i];
|
||
|
}
|
||
|
}
|
||
|
for(; i<KC; i++)
|
||
|
{
|
||
|
for(j=0; j<4; j++)
|
||
|
{
|
||
|
expandedKey[i*4+j] = W[rounds-1][j][i+MAXBC-KC];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int aesBlockEncrypt128(MV_U8 mode, MV_U8 *IV, MV_U8 *expandedKey, int keyLen,
|
||
|
MV_U32 *plain, int numBlocks, MV_U32 *cipher)
|
||
|
{
|
||
|
int i, j, t;
|
||
|
MV_U8 block[4][MAXBC];
|
||
|
int rounds;
|
||
|
char *input, *outBuffer;
|
||
|
|
||
|
input = (char*)plain;
|
||
|
outBuffer = (char*)cipher;
|
||
|
|
||
|
/* check parameter consistency: */
|
||
|
if( (expandedKey == NULL) || ((keyLen != 128) && (keyLen != 192) && (keyLen != 256)))
|
||
|
{
|
||
|
return AES_BAD_KEY_MAT;
|
||
|
}
|
||
|
if ((mode != MODE_ECB && mode != MODE_CBC))
|
||
|
{
|
||
|
return AES_BAD_CIPHER_STATE;
|
||
|
}
|
||
|
|
||
|
switch (keyLen)
|
||
|
{
|
||
|
case 128: rounds = 10; break;
|
||
|
case 192: rounds = 12; break;
|
||
|
case 256: rounds = 14; break;
|
||
|
default : return (-3); /* this cannot happen */
|
||
|
}
|
||
|
|
||
|
|
||
|
switch (mode)
|
||
|
{
|
||
|
case MODE_ECB:
|
||
|
for (i = 0; i < numBlocks; i++)
|
||
|
{
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
for(t = 0; t < 4; t++)
|
||
|
/* parse input stream into rectangular array */
|
||
|
block[t][j] = input[16*i+4*j+t] & 0xFF;
|
||
|
}
|
||
|
rijndaelEncrypt128(block, (MV_U8 (*)[4][MAXBC])expandedKey, rounds);
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
/* parse rectangular array into output ciphertext bytes */
|
||
|
for(t = 0; t < 4; t++)
|
||
|
outBuffer[16*i+4*j+t] = (MV_U8) block[t][j];
|
||
|
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case MODE_CBC:
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
for(t = 0; t < 4; t++)
|
||
|
/* parse initial value into rectangular array */
|
||
|
block[t][j] = IV[t+4*j] & 0xFF;
|
||
|
}
|
||
|
for (i = 0; i < numBlocks; i++)
|
||
|
{
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
for(t = 0; t < 4; t++)
|
||
|
/* parse input stream into rectangular array and exor with
|
||
|
IV or the previous ciphertext */
|
||
|
block[t][j] ^= input[16*i+4*j+t] & 0xFF;
|
||
|
}
|
||
|
rijndaelEncrypt128(block, (MV_U8 (*)[4][MAXBC])expandedKey, rounds);
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
/* parse rectangular array into output ciphertext bytes */
|
||
|
for(t = 0; t < 4; t++)
|
||
|
outBuffer[16*i+4*j+t] = (MV_U8) block[t][j];
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default: return AES_BAD_CIPHER_STATE;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int aesBlockDecrypt128(MV_U8 mode, MV_U8 *IV, MV_U8 *expandedKey, int keyLen,
|
||
|
MV_U32 *srcData, int numBlocks, MV_U32 *dstData)
|
||
|
{
|
||
|
int i, j, t;
|
||
|
MV_U8 block[4][MAXBC];
|
||
|
MV_U8 iv[4][MAXBC];
|
||
|
int rounds;
|
||
|
char *input, *outBuffer;
|
||
|
|
||
|
input = (char*)srcData;
|
||
|
outBuffer = (char*)dstData;
|
||
|
|
||
|
if (expandedKey == NULL)
|
||
|
{
|
||
|
return AES_BAD_KEY_MAT;
|
||
|
}
|
||
|
|
||
|
/* check parameter consistency: */
|
||
|
if (keyLen != 128 && keyLen != 192 && keyLen != 256)
|
||
|
{
|
||
|
return AES_BAD_KEY_MAT;
|
||
|
}
|
||
|
if ((mode != MODE_ECB && mode != MODE_CBC))
|
||
|
{
|
||
|
return AES_BAD_CIPHER_STATE;
|
||
|
}
|
||
|
|
||
|
switch (keyLen)
|
||
|
{
|
||
|
case 128: rounds = 10; break;
|
||
|
case 192: rounds = 12; break;
|
||
|
case 256: rounds = 14; break;
|
||
|
default : return (-3); /* this cannot happen */
|
||
|
}
|
||
|
|
||
|
|
||
|
switch (mode)
|
||
|
{
|
||
|
case MODE_ECB:
|
||
|
for (i = 0; i < numBlocks; i++)
|
||
|
{
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
for(t = 0; t < 4; t++)
|
||
|
{
|
||
|
/* parse input stream into rectangular array */
|
||
|
block[t][j] = input[16*i+4*j+t] & 0xFF;
|
||
|
}
|
||
|
}
|
||
|
rijndaelDecrypt128(block, (MV_U8 (*)[4][MAXBC])expandedKey, rounds);
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
/* parse rectangular array into output ciphertext bytes */
|
||
|
for(t = 0; t < 4; t++)
|
||
|
outBuffer[16*i+4*j+t] = (MV_U8) block[t][j];
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case MODE_CBC:
|
||
|
/* first block */
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
for(t = 0; t < 4; t++)
|
||
|
{
|
||
|
/* parse input stream into rectangular array */
|
||
|
block[t][j] = input[4*j+t] & 0xFF;
|
||
|
iv[t][j] = block[t][j];
|
||
|
}
|
||
|
}
|
||
|
rijndaelDecrypt128(block, (MV_U8 (*)[4][MAXBC])expandedKey, rounds);
|
||
|
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
/* exor the IV and parse rectangular array into output ciphertext bytes */
|
||
|
for(t = 0; t < 4; t++)
|
||
|
{
|
||
|
outBuffer[4*j+t] = (MV_U8) (block[t][j] ^ IV[t+4*j]);
|
||
|
IV[t+4*j] = iv[t][j];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* next blocks */
|
||
|
for (i = 1; i < numBlocks; i++)
|
||
|
{
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
for(t = 0; t < 4; t++)
|
||
|
{
|
||
|
/* parse input stream into rectangular array */
|
||
|
iv[t][j] = input[16*i+4*j+t] & 0xFF;
|
||
|
block[t][j] = iv[t][j];
|
||
|
}
|
||
|
}
|
||
|
rijndaelDecrypt128(block, (MV_U8 (*)[4][MAXBC])expandedKey, rounds);
|
||
|
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
/* exor previous ciphertext block and parse rectangular array
|
||
|
into output ciphertext bytes */
|
||
|
for(t = 0; t < 4; t++)
|
||
|
{
|
||
|
outBuffer[16*i+4*j+t] = (MV_U8) (block[t][j] ^ IV[t+4*j]);
|
||
|
IV[t+4*j] = iv[t][j];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default: return AES_BAD_CIPHER_STATE;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|