RadioShuttle Lib for the STM32 L4 Heltec Board

Dependents:   Turtle_RadioShuttle

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers aes.c Source File

aes.c

00001 /*
00002 Downloaded from here: https://github.com/kokke/tiny-AES128-C
00003 This is an implementation of the AES128 algorithm, specifically ECB and CBC mode.
00004 
00005 The implementation is verified against the test vectors in:
00006   National Institute of Standards and Technology Special Publication 800-38A 2001 ED
00007 
00008 ECB-AES128
00009 ----------
00010 
00011   plain-text:
00012     6bc1bee22e409f96e93d7e117393172a
00013     ae2d8a571e03ac9c9eb76fac45af8e51
00014     30c81c46a35ce411e5fbc1191a0a52ef
00015     f69f2445df4f9b17ad2b417be66c3710
00016 
00017   key:
00018     2b7e151628aed2a6abf7158809cf4f3c
00019 
00020   resulting cipher
00021     3ad77bb40d7a3660a89ecaf32466ef97 
00022     f5d3d58503b9699de785895a96fdbaaf 
00023     43b1cd7f598ece23881b00e3ed030688 
00024     7b0c785e27e8ad3f8223207104725dd4 
00025 
00026 
00027 NOTE:   String length must be evenly divisible by 16byte (str_len % 16 == 0)
00028         You should pad the end of the string with zeros if this is not the case.
00029 
00030 */
00031 
00032 
00033 /*****************************************************************************/
00034 /* Includes:                                                                 */
00035 /*****************************************************************************/
00036 #include <stdint.h>
00037 #include <string.h> // CBC mode, for memset
00038 #include "aes.h"
00039 
00040 /*****************************************************************************/
00041 /* Defines:                                                                  */
00042 /*****************************************************************************/
00043 // The number of columns comprising a state in AES. This is a constant in AES. Value=4
00044 #define Nb 4
00045 // The number of 32 bit words in a key.
00046 #define Nk 4
00047 
00048 // jcallan@github points out that declaring Multiply as a function 
00049 // reduces code size considerably with the Keil ARM compiler.
00050 // See this link for more information: https://github.com/kokke/tiny-AES128-C/pull/3
00051 #ifndef MULTIPLY_AS_A_FUNCTION
00052   #define MULTIPLY_AS_A_FUNCTION 1
00053 #endif
00054 
00055 /*
00056  * simple re-defines do use the existing code with a context
00057  */
00058 #define state       ctx->state
00059 #define RoundKey    ctx->RoundKey
00060 #define Iv          ctx->InitialVector
00061 #define KEYLEN      AES128_KEYLEN   
00062 
00063 // The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
00064 // The numbers below can be computed dynamically trading ROM for RAM - 
00065 // This can be useful in (embedded) bootloader applications, where ROM is often limited.
00066 static const uint8_t sbox[256] =   {
00067   //0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F
00068   0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
00069   0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
00070   0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
00071   0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
00072   0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
00073   0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
00074   0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
00075   0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
00076   0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
00077   0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
00078   0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
00079   0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
00080   0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
00081   0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
00082   0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
00083   0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
00084 
00085 static const uint8_t rsbox[256] =
00086 { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
00087   0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
00088   0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
00089   0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
00090   0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
00091   0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
00092   0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
00093   0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
00094   0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
00095   0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
00096   0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
00097   0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
00098   0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
00099   0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
00100   0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
00101   0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
00102 
00103 
00104 // The round constant word array, Rcon[i], contains the values given by 
00105 // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
00106 // Note that i starts at 1, not 0).
00107 static const uint8_t Rcon[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
00108 
00109 
00110 /*****************************************************************************/
00111 /* Private functions:                                                        */
00112 /*****************************************************************************/
00113 static uint8_t getSBoxValue(uint8_t num)
00114 {
00115   return sbox[num];
00116 }
00117 
00118 static uint8_t getSBoxInvert(uint8_t num)
00119 {
00120   return rsbox[num];
00121 }
00122 
00123 // This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. 
00124 static void KeyExpansion(AES_CTX *ctx, const uint8_t* Key)
00125 {
00126   uint32_t i, j, k;
00127   uint8_t tempa[4]; // Used for the column/row operations
00128   
00129   // The first round key is the key itself.
00130   for(i = 0; i < Nk; ++i)
00131   {
00132     RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
00133     RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
00134     RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
00135     RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
00136   }
00137 
00138   // All other round keys are found from the previous round keys.
00139   for(; (i < (Nb * (Nr + 1))); ++i)
00140   {
00141     for(j = 0; j < 4; ++j)
00142     {
00143       tempa[j]=RoundKey[(i-1) * 4 + j];
00144     }
00145     if (i % Nk == 0)
00146     {
00147       // This function rotates the 4 bytes in a word to the left once.
00148       // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
00149 
00150       // Function RotWord()
00151       {
00152         k = tempa[0];
00153         tempa[0] = tempa[1];
00154         tempa[1] = tempa[2];
00155         tempa[2] = tempa[3];
00156         tempa[3] = k;
00157       }
00158 
00159       // SubWord() is a function that takes a four-byte input word and 
00160       // applies the S-box to each of the four bytes to produce an output word.
00161 
00162       // Function Subword()
00163       {
00164         tempa[0] = getSBoxValue(tempa[0]);
00165         tempa[1] = getSBoxValue(tempa[1]);
00166         tempa[2] = getSBoxValue(tempa[2]);
00167         tempa[3] = getSBoxValue(tempa[3]);
00168       }
00169 
00170       tempa[0] =  tempa[0] ^ Rcon[(i/Nk)-1];
00171     }
00172     else if (Nk > 6 && i % Nk == 4)
00173     {
00174       // Function Subword()
00175       {
00176         tempa[0] = getSBoxValue(tempa[0]);
00177         tempa[1] = getSBoxValue(tempa[1]);
00178         tempa[2] = getSBoxValue(tempa[2]);
00179         tempa[3] = getSBoxValue(tempa[3]);
00180       }
00181     }
00182     RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0];
00183     RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1];
00184     RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2];
00185     RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3];
00186   }
00187 }
00188 
00189 // This function adds the round key to state.
00190 // The round key is added to the state by an XOR function.
00191 static void AddRoundKey(AES_CTX *ctx, uint8_t round)
00192 {
00193   uint8_t i,j;
00194   for(i=0;i<4;++i)
00195   {
00196     for(j = 0; j < 4; ++j)
00197     {
00198       (*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j];
00199     }
00200   }
00201 }
00202 
00203 // The SubBytes Function Substitutes the values in the
00204 // state matrix with values in an S-box.
00205 static void SubBytes(AES_CTX *ctx)
00206 {
00207   uint8_t i, j;
00208   for(i = 0; i < 4; ++i)
00209   {
00210     for(j = 0; j < 4; ++j)
00211     {
00212       (*state)[j][i] = getSBoxValue((*state)[j][i]);
00213     }
00214   }
00215 }
00216 
00217 // The ShiftRows() function shifts the rows in the state to the left.
00218 // Each row is shifted with different offset.
00219 // Offset = Row number. So the first row is not shifted.
00220 static void ShiftRows(AES_CTX *ctx)
00221 {
00222   uint8_t temp;
00223 
00224   // Rotate first row 1 columns to left  
00225   temp           = (*state)[0][1];
00226   (*state)[0][1] = (*state)[1][1];
00227   (*state)[1][1] = (*state)[2][1];
00228   (*state)[2][1] = (*state)[3][1];
00229   (*state)[3][1] = temp;
00230 
00231   // Rotate second row 2 columns to left  
00232   temp           = (*state)[0][2];
00233   (*state)[0][2] = (*state)[2][2];
00234   (*state)[2][2] = temp;
00235 
00236   temp       = (*state)[1][2];
00237   (*state)[1][2] = (*state)[3][2];
00238   (*state)[3][2] = temp;
00239 
00240   // Rotate third row 3 columns to left
00241   temp       = (*state)[0][3];
00242   (*state)[0][3] = (*state)[3][3];
00243   (*state)[3][3] = (*state)[2][3];
00244   (*state)[2][3] = (*state)[1][3];
00245   (*state)[1][3] = temp;
00246 }
00247 
00248 static uint8_t xtime(uint8_t x)
00249 {
00250   return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
00251 }
00252 
00253 // MixColumns function mixes the columns of the state matrix
00254 static void MixColumns(AES_CTX *ctx)
00255 {
00256   uint8_t i;
00257   uint8_t Tmp,Tm,t;
00258   for(i = 0; i < 4; ++i)
00259   {  
00260     t   = (*state)[i][0];
00261     Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
00262     Tm  = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm);  (*state)[i][0] ^= Tm ^ Tmp ;
00263     Tm  = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm);  (*state)[i][1] ^= Tm ^ Tmp ;
00264     Tm  = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm);  (*state)[i][2] ^= Tm ^ Tmp ;
00265     Tm  = (*state)[i][3] ^ t ;        Tm = xtime(Tm);  (*state)[i][3] ^= Tm ^ Tmp ;
00266   }
00267 }
00268 
00269 // Multiply is used to multiply numbers in the field GF(2^8)
00270 #if MULTIPLY_AS_A_FUNCTION
00271 static uint8_t Multiply(uint8_t x, uint8_t y)
00272 {
00273   return (((y & 1) * x) ^
00274        ((y>>1 & 1) * xtime(x)) ^
00275        ((y>>2 & 1) * xtime(xtime(x))) ^
00276        ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^
00277        ((y>>4 & 1) * xtime(xtime(xtime(xtime(x))))));
00278   }
00279 #else
00280 #define Multiply(x, y)                                \
00281       (  ((y & 1) * x) ^                              \
00282       ((y>>1 & 1) * xtime(x)) ^                       \
00283       ((y>>2 & 1) * xtime(xtime(x))) ^                \
00284       ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^         \
00285       ((y>>4 & 1) * xtime(xtime(xtime(xtime(x))))))   \
00286 
00287 #endif
00288 
00289 // MixColumns function mixes the columns of the state matrix.
00290 // The method used to multiply may be difficult to understand for the inexperienced.
00291 // Please use the references to gain more information.
00292 static void InvMixColumns(AES_CTX *ctx)
00293 {
00294   int i;
00295   uint8_t a,b,c,d;
00296   for(i=0;i<4;++i)
00297   { 
00298     a = (*state)[i][0];
00299     b = (*state)[i][1];
00300     c = (*state)[i][2];
00301     d = (*state)[i][3];
00302 
00303     (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
00304     (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
00305     (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
00306     (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
00307   }
00308 }
00309 
00310 
00311 // The SubBytes Function Substitutes the values in the
00312 // state matrix with values in an S-box.
00313 static void InvSubBytes(AES_CTX *ctx)
00314 {
00315   uint8_t i,j;
00316   for(i=0;i<4;++i)
00317   {
00318     for(j=0;j<4;++j)
00319     {
00320       (*state)[j][i] = getSBoxInvert((*state)[j][i]);
00321     }
00322   }
00323 }
00324 
00325 static void InvShiftRows(AES_CTX *ctx)
00326 {
00327   uint8_t temp;
00328 
00329   // Rotate first row 1 columns to right  
00330   temp=(*state)[3][1];
00331   (*state)[3][1]=(*state)[2][1];
00332   (*state)[2][1]=(*state)[1][1];
00333   (*state)[1][1]=(*state)[0][1];
00334   (*state)[0][1]=temp;
00335 
00336   // Rotate second row 2 columns to right 
00337   temp=(*state)[0][2];
00338   (*state)[0][2]=(*state)[2][2];
00339   (*state)[2][2]=temp;
00340 
00341   temp=(*state)[1][2];
00342   (*state)[1][2]=(*state)[3][2];
00343   (*state)[3][2]=temp;
00344 
00345   // Rotate third row 3 columns to right
00346   temp=(*state)[0][3];
00347   (*state)[0][3]=(*state)[1][3];
00348   (*state)[1][3]=(*state)[2][3];
00349   (*state)[2][3]=(*state)[3][3];
00350   (*state)[3][3]=temp;
00351 }
00352 
00353 
00354 // Cipher is the main function that encrypts the PlainText.
00355 static void Cipher(AES_CTX *ctx)
00356 {
00357   uint8_t round = 0;
00358 
00359   // Add the First round key to the state before starting the rounds.
00360   AddRoundKey(ctx, 0);
00361   
00362   // There will be Nr rounds.
00363   // The first Nr-1 rounds are identical.
00364   // These Nr-1 rounds are executed in the loop below.
00365   for(round = 1; round < Nr; ++round)
00366   {
00367     SubBytes(ctx);
00368     ShiftRows(ctx);
00369     MixColumns(ctx);
00370     AddRoundKey(ctx, round);
00371   }
00372   
00373   // The last round is given below.
00374   // The MixColumns function is not here in the last round.
00375   SubBytes(ctx);
00376   ShiftRows(ctx);
00377   AddRoundKey(ctx, Nr);
00378 }
00379 
00380 static void InvCipher(AES_CTX *ctx)
00381 {
00382   uint8_t round=0;
00383 
00384   // Add the First round key to the state before starting the rounds.
00385   AddRoundKey(ctx, Nr);
00386 
00387   // There will be Nr rounds.
00388   // The first Nr-1 rounds are identical.
00389   // These Nr-1 rounds are executed in the loop below.
00390   for(round=Nr-1;round>0;round--)
00391   {
00392     InvShiftRows(ctx);
00393     InvSubBytes(ctx);
00394     AddRoundKey(ctx, round);
00395     InvMixColumns(ctx);
00396   }
00397   
00398   // The last round is given below.
00399   // The MixColumns function is not here in the last round.
00400   InvShiftRows(ctx);
00401   InvSubBytes(ctx);
00402   AddRoundKey(ctx, 0);
00403 }
00404 
00405 
00406 /*****************************************************************************/
00407 /* Public functions:                                                         */
00408 /*****************************************************************************/
00409 
00410 
00411 void AES128_InitContext(AES_CTX *ctx, const uint8_t* key, const uint8_t* initialVector)
00412 {
00413     // The KeyExpansion routine must be called before encryption.
00414     KeyExpansion(ctx, key);
00415     if (initialVector)
00416         memcpy(ctx->InitialVector, initialVector, KEYLEN);
00417     
00418 }
00419 #ifdef ECB_MODE
00420 
00421 
00422 void AES128_ECB_encrypt(AES_CTX *ctx, const uint8_t* input, uint8_t* output)
00423 {
00424   // Copy input to output, and work in-memory on output
00425   memcpy(output, input, KEYLEN);
00426   state = (state_t*)output;
00427 
00428   // The next function call encrypts the PlainText with the Key using AES algorithm.
00429   Cipher(ctx);
00430 }
00431 
00432 void AES128_ECB_decrypt(AES_CTX *ctx, const uint8_t* input, uint8_t *output)
00433 {
00434   // Copy input to output, and work in-memory on output
00435   memcpy(output, input, KEYLEN);
00436   state = (state_t*)output;
00437 
00438   InvCipher(ctx);
00439 }
00440 
00441 
00442 #endif // ECB_MODE
00443 
00444 
00445 
00446 
00447 #ifdef CBC_MODE
00448 
00449 
00450 static void XorWithIv(AES_CTX *ctx, uint8_t* buf)
00451 {
00452     if (sizeof(int) == 4) {
00453         uint32_t *data = (uint32_t *)buf;
00454         uint32_t *iVec = (uint32_t *)Iv;
00455         
00456         *data++ ^= *iVec++;
00457         *data++ ^= *iVec++;
00458         *data++ ^= *iVec++;
00459         *data++ ^= *iVec++;
00460     } else {
00461         uint8_t i;
00462         for(i = 0; i < KEYLEN; ++i)
00463         {
00464             buf[i] ^= Iv[i];
00465         }
00466     }
00467 }
00468 
00469 void AES128_CBC_encrypt_buffer(AES_CTX *ctx, uint8_t* output, const uint8_t* input, uint32_t length)
00470 {
00471   uintptr_t i;
00472   uint8_t remainders = length % KEYLEN; /* Remaining bytes in the last non-full block */
00473 
00474 
00475   for(i = 0; i < length; i += KEYLEN)
00476   {
00477     memcpy(output, input, KEYLEN);
00478     XorWithIv(ctx, output);
00479     state = (state_t*)output;
00480     Cipher(ctx);
00481     memcpy(ctx->InitialVector, output, KEYLEN);
00482     input += KEYLEN;
00483     output += KEYLEN;
00484   }
00485 
00486   if(remainders)
00487   {
00488     memcpy(output, input, KEYLEN);
00489     memset(output + remainders, 0, KEYLEN - remainders); /* add 0-padding */
00490     state = (state_t*)output;
00491     Cipher(ctx);
00492   }
00493 }
00494 
00495 void AES128_CBC_decrypt_buffer(AES_CTX *ctx, uint8_t* output, const uint8_t* input, uint32_t length)
00496 {
00497   uintptr_t i;
00498   uint8_t remainders = length % KEYLEN; /* Remaining bytes in the last non-full block */
00499   
00500     
00501   for(i = 0; i < length; i += KEYLEN)
00502   {
00503     memcpy(output, input, KEYLEN);
00504     state = (state_t*)output;
00505     InvCipher(ctx);
00506     XorWithIv(ctx, output);
00507     memcpy(ctx->InitialVector, input, KEYLEN);
00508     input += KEYLEN;
00509     output += KEYLEN;
00510   }
00511 
00512   if(remainders)
00513   {
00514     memcpy(output, input, KEYLEN);
00515     memset(output+remainders, 0, KEYLEN - remainders); /* add 0-padding */
00516     state = (state_t*)output;
00517     InvCipher(ctx);
00518   }
00519 }
00520 
00521 
00522 #endif // CBC_MODE
00523 
00524