Back to home page

Enduro/X

 
 

    


0001 /*
0002 
0003 This is an implementation of the EXAES algorithm, specifically ECB and CBC mode.
0004 Block size can be chosen in exaes.h - available choices are EXAES128, EXAES192, EXAES256.
0005 
0006 The implementation is verified against the test vectors in:
0007   National Institute of Standards and Technology Special Publication 800-38A 2001 ED
0008 
0009 ECB-EXAES128
0010 ----------
0011 
0012   plain-text:
0013     6bc1bee22e409f96e93d7e117393172a
0014     ae2d8a571e03ac9c9eb76fac45af8e51
0015     30c81c46a35ce411e5fbc1191a0a52ef
0016     f69f2445df4f9b17ad2b417be66c3710
0017 
0018   key:
0019     2b7e151628aed2a6abf7158809cf4f3c
0020 
0021   resulting cipher
0022     3ad77bb40d7a3660a89ecaf32466ef97 
0023     f5d3d58503b9699de785895a96fdbaaf 
0024     43b1cd7f598ece23881b00e3ed030688 
0025     7b0c785e27e8ad3f8223207104725dd4 
0026 
0027 
0028 NOTE:   String length must be evenly divisible by 16byte (str_len % 16 == 0)
0029         You should pad the end of the string with zeros if this is not the case.
0030         For EXAES192/256 the key size is proportionally larger.
0031 
0032 */
0033 
0034 
0035 /*****************************************************************************/
0036 /* Includes:                                                                 */
0037 /*****************************************************************************/
0038 #include <stdint.h>
0039 #include <string.h> // CBC mode, for memset
0040 #include "exaes.h"
0041 
0042 /*****************************************************************************/
0043 /* Defines:                                                                  */
0044 /*****************************************************************************/
0045 // The number of columns comprising a state in EXAES. This is a constant in EXAES. Value=4
0046 #define Nb 4
0047 #define BLOCKLEN 16 //Block length in bytes EXAES is 128b block only
0048 
0049 #if defined(EXAES256) && (EXAES256 == 1)
0050     #define Nk 8
0051     #define KEYLEN 32
0052     #define Nr 14
0053     #define keyExpSize 240
0054 #elif defined(EXAES192) && (EXAES192 == 1)
0055     #define Nk 6
0056     #define KEYLEN 24
0057     #define Nr 12
0058     #define keyExpSize 208
0059 #else
0060     #define Nk 4        // The number of 32 bit words in a key.
0061     #define KEYLEN 16   // Key length in bytes
0062     #define Nr 10       // The number of rounds in EXAES Cipher.
0063     #define keyExpSize 176
0064 #endif
0065 
0066 // jcallan@github points out that declaring Multiply as a function 
0067 // reduces code size considerably with the Keil ARM compiler.
0068 // See this link for more information: https://github.com/kokke/tiny-EXAES128-C/pull/3
0069 #ifndef MULTIPLY_AS_A_FUNCTION
0070   #define MULTIPLY_AS_A_FUNCTION 0
0071 #endif
0072 
0073 
0074 /*****************************************************************************/
0075 /* Private variables:                                                        */
0076 /*****************************************************************************/
0077 // state - array holding the intermediate results during decryption.
0078 typedef uint8_t state_t[4][4];
0079 static __thread state_t* state;
0080 
0081 // The array that stores the round keys.
0082 static __thread uint8_t RoundKey[keyExpSize];
0083 
0084 // The Key input to the EXAES Program
0085 static __thread const uint8_t* Key;
0086 
0087 #if defined(CBC) && CBC
0088   // Initial Vector used only for CBC mode
0089   static __thread uint8_t* Iv;
0090 #endif
0091 
0092 // The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
0093 // The numbers below can be computed dynamically trading ROM for RAM - 
0094 // This can be useful in (embedded) bootloader applications, where ROM is often limited.
0095 static const uint8_t sbox[256] = {
0096   //0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F
0097   0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0098   0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0099   0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0100   0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0101   0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0102   0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0103   0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0104   0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0105   0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0106   0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0107   0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0108   0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0109   0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0110   0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0111   0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0112   0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
0113 
0114 static const uint8_t rsbox[256] = {
0115   0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0116   0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0117   0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0118   0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0119   0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0120   0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0121   0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0122   0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0123   0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0124   0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0125   0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0126   0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0127   0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0128   0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0129   0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0130   0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
0131 
0132 // The round constant word array, Rcon[i], contains the values given by 
0133 // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
0134 static const uint8_t Rcon[11] = {
0135   0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
0136 
0137 /*
0138  * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-EXAES128-C/pull/12),
0139  * that you can remove most of the elements in the Rcon array, because they are unused.
0140  *
0141  * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon
0142  * 
0143  * "Only the first some of these constants are actually used – up to rcon[10] for EXAES-128 (as 11 round keys are needed), 
0144  *  up to rcon[8] for EXAES-192, up to rcon[7] for EXAES-256. rcon[0] is not used in EXAES algorithm."
0145  *
0146  * ... which is why the full array below has been 'disabled' below.
0147  */
0148 #if 0
0149 static const uint8_t Rcon[256] = {
0150   0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
0151   0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
0152   0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
0153   0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
0154   0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
0155   0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
0156   0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
0157   0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
0158   0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
0159   0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
0160   0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
0161   0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
0162   0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
0163   0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
0164   0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
0165   0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d };
0166 #endif
0167 
0168 /*****************************************************************************/
0169 /* Private functions:                                                        */
0170 /*****************************************************************************/
0171 static uint8_t getSBoxValue(uint8_t num)
0172 {
0173   return sbox[num];
0174 }
0175 
0176 static uint8_t getSBoxInvert(uint8_t num)
0177 {
0178   return rsbox[num];
0179 }
0180 
0181 // This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. 
0182 static void KeyExpansion(void)
0183 {
0184   uint32_t i, k;
0185   uint8_t tempa[4]; // Used for the column/row operations
0186   
0187   // The first round key is the key itself.
0188   for (i = 0; i < Nk; ++i)
0189   {
0190     RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
0191     RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
0192     RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
0193     RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
0194   }
0195 
0196   // All other round keys are found from the previous round keys.
0197   //i == Nk
0198   for (; i < Nb * (Nr + 1); ++i)
0199   {
0200     {
0201       tempa[0]=RoundKey[(i-1) * 4 + 0];
0202       tempa[1]=RoundKey[(i-1) * 4 + 1];
0203       tempa[2]=RoundKey[(i-1) * 4 + 2];
0204       tempa[3]=RoundKey[(i-1) * 4 + 3];
0205     }
0206 
0207     if (i % Nk == 0)
0208     {
0209       // This function shifts the 4 bytes in a word to the left once.
0210       // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
0211 
0212       // Function RotWord()
0213       {
0214         k = tempa[0];
0215         tempa[0] = tempa[1];
0216         tempa[1] = tempa[2];
0217         tempa[2] = tempa[3];
0218         tempa[3] = k;
0219       }
0220 
0221       // SubWord() is a function that takes a four-byte input word and 
0222       // applies the S-box to each of the four bytes to produce an output word.
0223 
0224       // Function Subword()
0225       {
0226         tempa[0] = getSBoxValue(tempa[0]);
0227         tempa[1] = getSBoxValue(tempa[1]);
0228         tempa[2] = getSBoxValue(tempa[2]);
0229         tempa[3] = getSBoxValue(tempa[3]);
0230       }
0231 
0232       tempa[0] =  tempa[0] ^ Rcon[i/Nk];
0233     }
0234 #if defined(EXAES256) && (EXAES256 == 1)
0235     if (i % Nk == 4)
0236     {
0237       // Function Subword()
0238       {
0239         tempa[0] = getSBoxValue(tempa[0]);
0240         tempa[1] = getSBoxValue(tempa[1]);
0241         tempa[2] = getSBoxValue(tempa[2]);
0242         tempa[3] = getSBoxValue(tempa[3]);
0243       }
0244     }
0245 #endif
0246     RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0];
0247     RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1];
0248     RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2];
0249     RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3];
0250   }
0251 }
0252 
0253 // This function adds the round key to state.
0254 // The round key is added to the state by an XOR function.
0255 static void AddRoundKey(uint8_t round)
0256 {
0257   uint8_t i,j;
0258   for (i=0;i<4;++i)
0259   {
0260     for (j = 0; j < 4; ++j)
0261     {
0262       (*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j];
0263     }
0264   }
0265 }
0266 
0267 // The SubBytes Function Substitutes the values in the
0268 // state matrix with values in an S-box.
0269 static void SubBytes(void)
0270 {
0271   uint8_t i, j;
0272   for (i = 0; i < 4; ++i)
0273   {
0274     for (j = 0; j < 4; ++j)
0275     {
0276       (*state)[j][i] = getSBoxValue((*state)[j][i]);
0277     }
0278   }
0279 }
0280 
0281 // The ShiftRows() function shifts the rows in the state to the left.
0282 // Each row is shifted with different offset.
0283 // Offset = Row number. So the first row is not shifted.
0284 static void ShiftRows(void)
0285 {
0286   uint8_t temp;
0287 
0288   // Rotate first row 1 columns to left  
0289   temp           = (*state)[0][1];
0290   (*state)[0][1] = (*state)[1][1];
0291   (*state)[1][1] = (*state)[2][1];
0292   (*state)[2][1] = (*state)[3][1];
0293   (*state)[3][1] = temp;
0294 
0295   // Rotate second row 2 columns to left  
0296   temp           = (*state)[0][2];
0297   (*state)[0][2] = (*state)[2][2];
0298   (*state)[2][2] = temp;
0299 
0300   temp           = (*state)[1][2];
0301   (*state)[1][2] = (*state)[3][2];
0302   (*state)[3][2] = temp;
0303 
0304   // Rotate third row 3 columns to left
0305   temp           = (*state)[0][3];
0306   (*state)[0][3] = (*state)[3][3];
0307   (*state)[3][3] = (*state)[2][3];
0308   (*state)[2][3] = (*state)[1][3];
0309   (*state)[1][3] = temp;
0310 }
0311 
0312 static uint8_t xtime(uint8_t x)
0313 {
0314   return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
0315 }
0316 
0317 // MixColumns function mixes the columns of the state matrix
0318 static void MixColumns(void)
0319 {
0320   uint8_t i;
0321   uint8_t Tmp,Tm,t;
0322   for (i = 0; i < 4; ++i)
0323   {  
0324     t   = (*state)[i][0];
0325     Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
0326     Tm  = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm);  (*state)[i][0] ^= Tm ^ Tmp ;
0327     Tm  = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm);  (*state)[i][1] ^= Tm ^ Tmp ;
0328     Tm  = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm);  (*state)[i][2] ^= Tm ^ Tmp ;
0329     Tm  = (*state)[i][3] ^ t ;              Tm = xtime(Tm);  (*state)[i][3] ^= Tm ^ Tmp ;
0330   }
0331 }
0332 
0333 // Multiply is used to multiply numbers in the field GF(2^8)
0334 #if MULTIPLY_AS_A_FUNCTION
0335 static uint8_t Multiply(uint8_t x, uint8_t y)
0336 {
0337   return (((y & 1) * x) ^
0338        ((y>>1 & 1) * xtime(x)) ^
0339        ((y>>2 & 1) * xtime(xtime(x))) ^
0340        ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^
0341        ((y>>4 & 1) * xtime(xtime(xtime(xtime(x))))));
0342   }
0343 #else
0344 #define Multiply(x, y)                                \
0345       (  ((y & 1) * x) ^                              \
0346       ((y>>1 & 1) * xtime(x)) ^                       \
0347       ((y>>2 & 1) * xtime(xtime(x))) ^                \
0348       ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^         \
0349       ((y>>4 & 1) * xtime(xtime(xtime(xtime(x))))))   \
0350 
0351 #endif
0352 
0353 // MixColumns function mixes the columns of the state matrix.
0354 // The method used to multiply may be difficult to understand for the inexperienced.
0355 // Please use the references to gain more information.
0356 static void InvMixColumns(void)
0357 {
0358   int i;
0359   uint8_t a, b, c, d;
0360   for (i = 0; i < 4; ++i)
0361   { 
0362     a = (*state)[i][0];
0363     b = (*state)[i][1];
0364     c = (*state)[i][2];
0365     d = (*state)[i][3];
0366 
0367     (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
0368     (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
0369     (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
0370     (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
0371   }
0372 }
0373 
0374 
0375 // The SubBytes Function Substitutes the values in the
0376 // state matrix with values in an S-box.
0377 static void InvSubBytes(void)
0378 {
0379   uint8_t i,j;
0380   for (i = 0; i < 4; ++i)
0381   {
0382     for (j = 0; j < 4; ++j)
0383     {
0384       (*state)[j][i] = getSBoxInvert((*state)[j][i]);
0385     }
0386   }
0387 }
0388 
0389 static void InvShiftRows(void)
0390 {
0391   uint8_t temp;
0392 
0393   // Rotate first row 1 columns to right  
0394   temp = (*state)[3][1];
0395   (*state)[3][1] = (*state)[2][1];
0396   (*state)[2][1] = (*state)[1][1];
0397   (*state)[1][1] = (*state)[0][1];
0398   (*state)[0][1] = temp;
0399 
0400   // Rotate second row 2 columns to right 
0401   temp = (*state)[0][2];
0402   (*state)[0][2] = (*state)[2][2];
0403   (*state)[2][2] = temp;
0404 
0405   temp = (*state)[1][2];
0406   (*state)[1][2] = (*state)[3][2];
0407   (*state)[3][2] = temp;
0408 
0409   // Rotate third row 3 columns to right
0410   temp = (*state)[0][3];
0411   (*state)[0][3] = (*state)[1][3];
0412   (*state)[1][3] = (*state)[2][3];
0413   (*state)[2][3] = (*state)[3][3];
0414   (*state)[3][3] = temp;
0415 }
0416 
0417 
0418 // Cipher is the main function that encrypts the PlainText.
0419 static void Cipher(void)
0420 {
0421   uint8_t round = 0;
0422 
0423   // Add the First round key to the state before starting the rounds.
0424   AddRoundKey(0); 
0425   
0426   // There will be Nr rounds.
0427   // The first Nr-1 rounds are identical.
0428   // These Nr-1 rounds are executed in the loop below.
0429   for (round = 1; round < Nr; ++round)
0430   {
0431     SubBytes();
0432     ShiftRows();
0433     MixColumns();
0434     AddRoundKey(round);
0435   }
0436   
0437   // The last round is given below.
0438   // The MixColumns function is not here in the last round.
0439   SubBytes();
0440   ShiftRows();
0441   AddRoundKey(Nr);
0442 }
0443 
0444 static void InvCipher(void)
0445 {
0446   uint8_t round=0;
0447 
0448   // Add the First round key to the state before starting the rounds.
0449   AddRoundKey(Nr); 
0450 
0451   // There will be Nr rounds.
0452   // The first Nr-1 rounds are identical.
0453   // These Nr-1 rounds are executed in the loop below.
0454   for (round = (Nr - 1); round > 0; --round)
0455   {
0456     InvShiftRows();
0457     InvSubBytes();
0458     AddRoundKey(round);
0459     InvMixColumns();
0460   }
0461   
0462   // The last round is given below.
0463   // The MixColumns function is not here in the last round.
0464   InvShiftRows();
0465   InvSubBytes();
0466   AddRoundKey(0);
0467 }
0468 
0469 
0470 /*****************************************************************************/
0471 /* Public functions:                                                         */
0472 /*****************************************************************************/
0473 #if defined(ECB) && (ECB == 1)
0474 
0475 
0476 void EXAES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t* output, const uint32_t length)
0477 {
0478   // Copy input to output, and work in-memory on output
0479   memcpy(output, input, length);
0480   state = (state_t*)output;
0481 
0482   Key = key;
0483   KeyExpansion();
0484 
0485   // The next function call encrypts the PlainText with the Key using EXAES algorithm.
0486   Cipher();
0487 }
0488 
0489 void EXAES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
0490 {
0491   // Copy input to output, and work in-memory on output
0492   memcpy(output, input, length);
0493   state = (state_t*)output;
0494 
0495   // The KeyExpansion routine must be called before encryption.
0496   Key = key;
0497   KeyExpansion();
0498 
0499   InvCipher();
0500 }
0501 
0502 
0503 #endif // #if defined(ECB) && (ECB == 1)
0504 
0505 
0506 
0507 
0508 
0509 #if defined(CBC) && (CBC == 1)
0510 
0511 
0512 static void XorWithIv(uint8_t* buf)
0513 {
0514   uint8_t i;
0515   for (i = 0; i < BLOCKLEN; ++i) //WAS for(i = 0; i < KEYLEN; ++i) but the block in EXAES is always 128bit so 16 bytes!
0516   {
0517     buf[i] ^= Iv[i];
0518   }
0519 }
0520 
0521 //Warning ! This will try to read full block !!!
0522 //Thus input must be with exact size !!!!
0523 void EXAES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
0524 {
0525   uintptr_t i;
0526   uint8_t extra = length % BLOCKLEN; /* Remaining bytes in the last non-full block */
0527 
0528   // Skip the key expansion if key is passed as 0
0529   if (0 != key)
0530   {
0531     Key = key;
0532     KeyExpansion();
0533   }
0534 
0535   if (iv != 0)
0536   {
0537     Iv = (uint8_t*)iv;
0538   }
0539 
0540 
0541   //Fix for the mem read overflow
0542   for (i = 0; i < length-extra; i += BLOCKLEN)
0543   {
0544     memcpy(output, input, BLOCKLEN);
0545     XorWithIv(output);
0546     state = (state_t*)output;
0547     Cipher();
0548     Iv = output;
0549     input += BLOCKLEN;
0550     output += BLOCKLEN;
0551     //printf("Step %d - %d", i/16, i);
0552   }
0553 
0554   if (extra)
0555   {
0556     memcpy(output, input, extra);
0557     memset((output + extra), 0, (BLOCKLEN - extra));
0558     XorWithIv(output);
0559     state = (state_t*)output;
0560     Cipher();
0561   }
0562 }
0563 
0564 void EXAES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
0565 {
0566   uintptr_t i;
0567   uint8_t extra = length % BLOCKLEN; /* Remaining bytes in the last non-full block */
0568 
0569   // Skip the key expansion if key is passed as 0
0570   if (0 != key)
0571   {
0572     Key = key;
0573     KeyExpansion();
0574   }
0575 
0576   // If iv is passed as 0, we continue to encrypt without re-setting the Iv
0577   if (iv != 0)
0578   {
0579     Iv = (uint8_t*)iv;
0580   }
0581 
0582   for (i = 0; i < length; i += BLOCKLEN)
0583   {
0584     memcpy(output, input, BLOCKLEN);
0585     state = (state_t*)output;
0586     InvCipher();
0587     XorWithIv(output);
0588     Iv = input;
0589     input += BLOCKLEN;
0590     output += BLOCKLEN;
0591   }
0592 
0593   if (extra)
0594   {
0595     memcpy(output, input, extra);
0596     state = (state_t*)output;
0597     InvCipher();
0598   }
0599 }
0600 
0601 #endif // #if defined(CBC) && (CBC == 1)