aes.c (18982B)
1 /* 2 3 This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode. 4 Block size can be chosen in aes.h - available choices are AES128, AES192, AES256. 5 6 The implementation is verified against the test vectors in: 7 National Institute of Standards and Technology Special Publication 800-38A 2001 ED 8 9 ECB-AES128 10 ---------- 11 12 plain-text: 13 6bc1bee22e409f96e93d7e117393172a 14 ae2d8a571e03ac9c9eb76fac45af8e51 15 30c81c46a35ce411e5fbc1191a0a52ef 16 f69f2445df4f9b17ad2b417be66c3710 17 18 key: 19 2b7e151628aed2a6abf7158809cf4f3c 20 21 resulting cipher 22 3ad77bb40d7a3660a89ecaf32466ef97 23 f5d3d58503b9699de785895a96fdbaaf 24 43b1cd7f598ece23881b00e3ed030688 25 7b0c785e27e8ad3f8223207104725dd4 26 27 28 NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) 29 You should pad the end of the string with zeros if this is not the case. 30 For AES192/256 the key size is proportionally larger. 31 32 */ 33 34 35 /*****************************************************************************/ 36 /* Includes: */ 37 /*****************************************************************************/ 38 #include <string.h> // CBC mode, for memset 39 #include "aes.h" 40 41 /*****************************************************************************/ 42 /* Defines: */ 43 /*****************************************************************************/ 44 // The number of columns comprising a state in AES. This is a constant in AES. Value=4 45 #define Nb 4 46 47 #if defined(AES256) && (AES256 == 1) 48 #define Nk 8 49 #define Nr 14 50 #elif defined(AES192) && (AES192 == 1) 51 #define Nk 6 52 #define Nr 12 53 #else 54 #define Nk 4 // The number of 32 bit words in a key. 55 #define Nr 10 // The number of rounds in AES Cipher. 56 #endif 57 58 // jcallan@github points out that declaring Multiply as a function 59 // reduces code size considerably with the Keil ARM compiler. 60 // See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3 61 #ifndef MULTIPLY_AS_A_FUNCTION 62 #define MULTIPLY_AS_A_FUNCTION 0 63 #endif 64 65 66 67 68 /*****************************************************************************/ 69 /* Private variables: */ 70 /*****************************************************************************/ 71 // state - array holding the intermediate results during decryption. 72 typedef uint8_t state_t[4][4]; 73 74 75 76 // The lookup-tables are marked const so they can be placed in read-only storage instead of RAM 77 // The numbers below can be computed dynamically trading ROM for RAM - 78 // This can be useful in (embedded) bootloader applications, where ROM is often limited. 79 static const uint8_t sbox[256] = { 80 //0 1 2 3 4 5 6 7 8 9 A B C D E F 81 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 82 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 83 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 84 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 85 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 86 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 87 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 88 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 89 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 90 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 91 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 92 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 93 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 94 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 95 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 96 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; 97 98 #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 99 static const uint8_t rsbox[256] = { 100 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 101 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 102 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 103 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 104 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 105 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 106 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 107 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 108 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 109 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 110 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 111 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 112 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 113 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 114 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 115 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; 116 #endif 117 118 // The round constant word array, Rcon[i], contains the values given by 119 // x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) 120 static const uint8_t Rcon[11] = { 121 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; 122 123 /* 124 * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12), 125 * that you can remove most of the elements in the Rcon array, because they are unused. 126 * 127 * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon 128 * 129 * "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed), 130 * up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm." 131 */ 132 133 134 /*****************************************************************************/ 135 /* Private functions: */ 136 /*****************************************************************************/ 137 /* 138 static uint8_t getSBoxValue(uint8_t num) 139 { 140 return sbox[num]; 141 } 142 */ 143 #define getSBoxValue(num) (sbox[(num)]) 144 145 // This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. 146 static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) 147 { 148 unsigned i, j, k; 149 uint8_t tempa[4]; // Used for the column/row operations 150 151 // The first round key is the key itself. 152 for (i = 0; i < Nk; ++i) 153 { 154 RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; 155 RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; 156 RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; 157 RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; 158 } 159 160 // All other round keys are found from the previous round keys. 161 for (i = Nk; i < Nb * (Nr + 1); ++i) 162 { 163 { 164 k = (i - 1) * 4; 165 tempa[0]=RoundKey[k + 0]; 166 tempa[1]=RoundKey[k + 1]; 167 tempa[2]=RoundKey[k + 2]; 168 tempa[3]=RoundKey[k + 3]; 169 170 } 171 172 if (i % Nk == 0) 173 { 174 // This function shifts the 4 bytes in a word to the left once. 175 // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] 176 177 // Function RotWord() 178 { 179 const uint8_t u8tmp = tempa[0]; 180 tempa[0] = tempa[1]; 181 tempa[1] = tempa[2]; 182 tempa[2] = tempa[3]; 183 tempa[3] = u8tmp; 184 } 185 186 // SubWord() is a function that takes a four-byte input word and 187 // applies the S-box to each of the four bytes to produce an output word. 188 189 // Function Subword() 190 { 191 tempa[0] = getSBoxValue(tempa[0]); 192 tempa[1] = getSBoxValue(tempa[1]); 193 tempa[2] = getSBoxValue(tempa[2]); 194 tempa[3] = getSBoxValue(tempa[3]); 195 } 196 197 tempa[0] = tempa[0] ^ Rcon[i/Nk]; 198 } 199 #if defined(AES256) && (AES256 == 1) 200 if (i % Nk == 4) 201 { 202 // Function Subword() 203 { 204 tempa[0] = getSBoxValue(tempa[0]); 205 tempa[1] = getSBoxValue(tempa[1]); 206 tempa[2] = getSBoxValue(tempa[2]); 207 tempa[3] = getSBoxValue(tempa[3]); 208 } 209 } 210 #endif 211 j = i * 4; k=(i - Nk) * 4; 212 RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; 213 RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; 214 RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; 215 RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; 216 } 217 } 218 219 void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) 220 { 221 KeyExpansion(ctx->RoundKey, key); 222 } 223 #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 224 void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) 225 { 226 KeyExpansion(ctx->RoundKey, key); 227 memcpy (ctx->Iv, iv, AES_BLOCKLEN); 228 } 229 void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv) 230 { 231 memcpy (ctx->Iv, iv, AES_BLOCKLEN); 232 } 233 #endif 234 235 // This function adds the round key to state. 236 // The round key is added to the state by an XOR function. 237 static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) 238 { 239 uint8_t i,j; 240 for (i = 0; i < 4; ++i) 241 { 242 for (j = 0; j < 4; ++j) 243 { 244 (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; 245 } 246 } 247 } 248 249 // The SubBytes Function Substitutes the values in the 250 // state matrix with values in an S-box. 251 static void SubBytes(state_t* state) 252 { 253 uint8_t i, j; 254 for (i = 0; i < 4; ++i) 255 { 256 for (j = 0; j < 4; ++j) 257 { 258 (*state)[j][i] = getSBoxValue((*state)[j][i]); 259 } 260 } 261 } 262 263 // The ShiftRows() function shifts the rows in the state to the left. 264 // Each row is shifted with different offset. 265 // Offset = Row number. So the first row is not shifted. 266 static void ShiftRows(state_t* state) 267 { 268 uint8_t temp; 269 270 // Rotate first row 1 columns to left 271 temp = (*state)[0][1]; 272 (*state)[0][1] = (*state)[1][1]; 273 (*state)[1][1] = (*state)[2][1]; 274 (*state)[2][1] = (*state)[3][1]; 275 (*state)[3][1] = temp; 276 277 // Rotate second row 2 columns to left 278 temp = (*state)[0][2]; 279 (*state)[0][2] = (*state)[2][2]; 280 (*state)[2][2] = temp; 281 282 temp = (*state)[1][2]; 283 (*state)[1][2] = (*state)[3][2]; 284 (*state)[3][2] = temp; 285 286 // Rotate third row 3 columns to left 287 temp = (*state)[0][3]; 288 (*state)[0][3] = (*state)[3][3]; 289 (*state)[3][3] = (*state)[2][3]; 290 (*state)[2][3] = (*state)[1][3]; 291 (*state)[1][3] = temp; 292 } 293 294 static uint8_t xtime(uint8_t x) 295 { 296 return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); 297 } 298 299 // MixColumns function mixes the columns of the state matrix 300 static void MixColumns(state_t* state) 301 { 302 uint8_t i; 303 uint8_t Tmp, Tm, t; 304 for (i = 0; i < 4; ++i) 305 { 306 t = (*state)[i][0]; 307 Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; 308 Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; 309 Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; 310 Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; 311 Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; 312 } 313 } 314 315 // Multiply is used to multiply numbers in the field GF(2^8) 316 // Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary 317 // The compiler seems to be able to vectorize the operation better this way. 318 // See https://github.com/kokke/tiny-AES-c/pull/34 319 #if MULTIPLY_AS_A_FUNCTION 320 static uint8_t Multiply(uint8_t x, uint8_t y) 321 { 322 return (((y & 1) * x) ^ 323 ((y>>1 & 1) * xtime(x)) ^ 324 ((y>>2 & 1) * xtime(xtime(x))) ^ 325 ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ 326 ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */ 327 } 328 #else 329 #define Multiply(x, y) \ 330 ( ((y & 1) * x) ^ \ 331 ((y>>1 & 1) * xtime(x)) ^ \ 332 ((y>>2 & 1) * xtime(xtime(x))) ^ \ 333 ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ 334 ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ 335 336 #endif 337 338 #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 339 /* 340 static uint8_t getSBoxInvert(uint8_t num) 341 { 342 return rsbox[num]; 343 } 344 */ 345 #define getSBoxInvert(num) (rsbox[(num)]) 346 347 // MixColumns function mixes the columns of the state matrix. 348 // The method used to multiply may be difficult to understand for the inexperienced. 349 // Please use the references to gain more information. 350 static void InvMixColumns(state_t* state) 351 { 352 int i; 353 uint8_t a, b, c, d; 354 for (i = 0; i < 4; ++i) 355 { 356 a = (*state)[i][0]; 357 b = (*state)[i][1]; 358 c = (*state)[i][2]; 359 d = (*state)[i][3]; 360 361 (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); 362 (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); 363 (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); 364 (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); 365 } 366 } 367 368 369 // The SubBytes Function Substitutes the values in the 370 // state matrix with values in an S-box. 371 static void InvSubBytes(state_t* state) 372 { 373 uint8_t i, j; 374 for (i = 0; i < 4; ++i) 375 { 376 for (j = 0; j < 4; ++j) 377 { 378 (*state)[j][i] = getSBoxInvert((*state)[j][i]); 379 } 380 } 381 } 382 383 static void InvShiftRows(state_t* state) 384 { 385 uint8_t temp; 386 387 // Rotate first row 1 columns to right 388 temp = (*state)[3][1]; 389 (*state)[3][1] = (*state)[2][1]; 390 (*state)[2][1] = (*state)[1][1]; 391 (*state)[1][1] = (*state)[0][1]; 392 (*state)[0][1] = temp; 393 394 // Rotate second row 2 columns to right 395 temp = (*state)[0][2]; 396 (*state)[0][2] = (*state)[2][2]; 397 (*state)[2][2] = temp; 398 399 temp = (*state)[1][2]; 400 (*state)[1][2] = (*state)[3][2]; 401 (*state)[3][2] = temp; 402 403 // Rotate third row 3 columns to right 404 temp = (*state)[0][3]; 405 (*state)[0][3] = (*state)[1][3]; 406 (*state)[1][3] = (*state)[2][3]; 407 (*state)[2][3] = (*state)[3][3]; 408 (*state)[3][3] = temp; 409 } 410 #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 411 412 // Cipher is the main function that encrypts the PlainText. 413 static void Cipher(state_t* state, const uint8_t* RoundKey) 414 { 415 uint8_t round = 0; 416 417 // Add the First round key to the state before starting the rounds. 418 AddRoundKey(0, state, RoundKey); 419 420 // There will be Nr rounds. 421 // The first Nr-1 rounds are identical. 422 // These Nr rounds are executed in the loop below. 423 // Last one without MixColumns() 424 for (round = 1; ; ++round) 425 { 426 SubBytes(state); 427 ShiftRows(state); 428 if (round == Nr) { 429 break; 430 } 431 MixColumns(state); 432 AddRoundKey(round, state, RoundKey); 433 } 434 // Add round key to last round 435 AddRoundKey(Nr, state, RoundKey); 436 } 437 438 #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 439 static void InvCipher(state_t* state, const uint8_t* RoundKey) 440 { 441 uint8_t round = 0; 442 443 // Add the First round key to the state before starting the rounds. 444 AddRoundKey(Nr, state, RoundKey); 445 446 // There will be Nr rounds. 447 // The first Nr-1 rounds are identical. 448 // These Nr rounds are executed in the loop below. 449 // Last one without InvMixColumn() 450 for (round = (Nr - 1); ; --round) 451 { 452 InvShiftRows(state); 453 InvSubBytes(state); 454 AddRoundKey(round, state, RoundKey); 455 if (round == 0) { 456 break; 457 } 458 InvMixColumns(state); 459 } 460 461 } 462 #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 463 464 /*****************************************************************************/ 465 /* Public functions: */ 466 /*****************************************************************************/ 467 #if defined(ECB) && (ECB == 1) 468 469 470 void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) 471 { 472 // The next function call encrypts the PlainText with the Key using AES algorithm. 473 Cipher((state_t*)buf, ctx->RoundKey); 474 } 475 476 void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) 477 { 478 // The next function call decrypts the PlainText with the Key using AES algorithm. 479 InvCipher((state_t*)buf, ctx->RoundKey); 480 } 481 482 483 #endif // #if defined(ECB) && (ECB == 1) 484 485 486 487 488 489 #if defined(CBC) && (CBC == 1) 490 491 492 static void XorWithIv(uint8_t* buf, const uint8_t* Iv) 493 { 494 uint8_t i; 495 for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size 496 { 497 buf[i] ^= Iv[i]; 498 } 499 } 500 501 void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, size_t length) 502 { 503 size_t i; 504 uint8_t *Iv = ctx->Iv; 505 for (i = 0; i < length; i += AES_BLOCKLEN) 506 { 507 XorWithIv(buf, Iv); 508 Cipher((state_t*)buf, ctx->RoundKey); 509 Iv = buf; 510 buf += AES_BLOCKLEN; 511 } 512 /* store Iv in ctx for next call */ 513 memcpy(ctx->Iv, Iv, AES_BLOCKLEN); 514 } 515 516 void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) 517 { 518 size_t i; 519 uint8_t storeNextIv[AES_BLOCKLEN]; 520 for (i = 0; i < length; i += AES_BLOCKLEN) 521 { 522 memcpy(storeNextIv, buf, AES_BLOCKLEN); 523 InvCipher((state_t*)buf, ctx->RoundKey); 524 XorWithIv(buf, ctx->Iv); 525 memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); 526 buf += AES_BLOCKLEN; 527 } 528 529 } 530 531 #endif // #if defined(CBC) && (CBC == 1) 532 533 534 535 #if defined(CTR) && (CTR == 1) 536 537 /* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */ 538 void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) 539 { 540 uint8_t buffer[AES_BLOCKLEN]; 541 542 size_t i; 543 int bi; 544 for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) 545 { 546 if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */ 547 { 548 549 memcpy(buffer, ctx->Iv, AES_BLOCKLEN); 550 Cipher((state_t*)buffer,ctx->RoundKey); 551 552 /* Increment Iv and handle overflow */ 553 for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) 554 { 555 /* inc will overflow */ 556 if (ctx->Iv[bi] == 255) 557 { 558 ctx->Iv[bi] = 0; 559 continue; 560 } 561 ctx->Iv[bi] += 1; 562 break; 563 } 564 bi = 0; 565 } 566 567 buf[i] = (buf[i] ^ buffer[bi]); 568 } 569 } 570 571 #endif // #if defined(CTR) && (CTR == 1) 572