0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #include <stdint.h>
0039 #include <string.h> // CBC mode, for memset
0040 #include "exaes.h"
0041
0042
0043
0044
0045
0046 #define Nb 4
0047 #define BLOCKLEN 16
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
0061 #define KEYLEN 16
0062 #define Nr 10
0063 #define keyExpSize 176
0064 #endif
0065
0066
0067
0068
0069 #ifndef MULTIPLY_AS_A_FUNCTION
0070 #define MULTIPLY_AS_A_FUNCTION 0
0071 #endif
0072
0073
0074
0075
0076
0077
0078 typedef uint8_t state_t[4][4];
0079 static __thread state_t* state;
0080
0081
0082 static __thread uint8_t RoundKey[keyExpSize];
0083
0084
0085 static __thread const uint8_t* Key;
0086
0087 #if defined(CBC) && CBC
0088
0089 static __thread uint8_t* Iv;
0090 #endif
0091
0092
0093
0094
0095 static const uint8_t sbox[256] = {
0096
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
0133
0134 static const uint8_t Rcon[11] = {
0135 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
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
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
0182 static void KeyExpansion(void)
0183 {
0184 uint32_t i, k;
0185 uint8_t tempa[4];
0186
0187
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
0197
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
0210
0211
0212
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
0222
0223
0224
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
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
0254
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
0268
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
0282
0283
0284 static void ShiftRows(void)
0285 {
0286 uint8_t temp;
0287
0288
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
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
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
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
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
0354
0355
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
0376
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
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
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
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
0419 static void Cipher(void)
0420 {
0421 uint8_t round = 0;
0422
0423
0424 AddRoundKey(0);
0425
0426
0427
0428
0429 for (round = 1; round < Nr; ++round)
0430 {
0431 SubBytes();
0432 ShiftRows();
0433 MixColumns();
0434 AddRoundKey(round);
0435 }
0436
0437
0438
0439 SubBytes();
0440 ShiftRows();
0441 AddRoundKey(Nr);
0442 }
0443
0444 static void InvCipher(void)
0445 {
0446 uint8_t round=0;
0447
0448
0449 AddRoundKey(Nr);
0450
0451
0452
0453
0454 for (round = (Nr - 1); round > 0; --round)
0455 {
0456 InvShiftRows();
0457 InvSubBytes();
0458 AddRoundKey(round);
0459 InvMixColumns();
0460 }
0461
0462
0463
0464 InvShiftRows();
0465 InvSubBytes();
0466 AddRoundKey(0);
0467 }
0468
0469
0470
0471
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
0479 memcpy(output, input, length);
0480 state = (state_t*)output;
0481
0482 Key = key;
0483 KeyExpansion();
0484
0485
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
0492 memcpy(output, input, length);
0493 state = (state_t*)output;
0494
0495
0496 Key = key;
0497 KeyExpansion();
0498
0499 InvCipher();
0500 }
0501
0502
0503 #endif
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)
0516 {
0517 buf[i] ^= Iv[i];
0518 }
0519 }
0520
0521
0522
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;
0527
0528
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
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
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;
0568
0569
0570 if (0 != key)
0571 {
0572 Key = key;
0573 KeyExpansion();
0574 }
0575
0576
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