1/** 2 * rijndael-api-fst.c 3 * 4 * @version 2.9 (December 2000) 5 * 6 * Optimised ANSI C code for the Rijndael cipher (now AES) 7 * 8 * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> 9 * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> 10 * @author Paulo Barreto <paulo.barreto@terra.com.br> 11 * 12 * This code is hereby placed in the public domain. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS 15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 21 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * Acknowledgements: 27 * 28 * We are deeply indebted to the following people for their bug reports, 29 * fixes, and improvement suggestions to this implementation. Though we 30 * tried to list all contributions, we apologise in advance for any 31 * missing reference. 32 * 33 * Andrew Bales <Andrew.Bales@Honeywell.com> 34 * Markus Friedl <markus.friedl@informatik.uni-erlangen.de> 35 * John Skodon <skodonj@webquill.com> 36 */ 37#include "db_config.h" 38 39#include "db_int.h" 40#include "dbinc/crypto.h" 41 42#include "crypto/rijndael/rijndael-alg-fst.h" 43#include "crypto/rijndael/rijndael-api-fst.h" 44 45/* 46 * __db_makeKey -- 47 * 48 * PUBLIC: int __db_makeKey __P((keyInstance *, int, int, char *)); 49 */ 50int 51__db_makeKey(key, direction, keyLen, keyMaterial) 52 keyInstance *key; 53 int direction; 54 int keyLen; 55 char *keyMaterial; 56{ 57 u8 cipherKey[MAXKB]; 58 59 if (key == NULL) { 60 return BAD_KEY_INSTANCE; 61 } 62 63 if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) { 64 key->direction = direction; 65 } else { 66 return BAD_KEY_DIR; 67 } 68 69 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { 70 key->keyLen = keyLen; 71 } else { 72 return BAD_KEY_MAT; 73 } 74 75 if (keyMaterial != NULL) { 76 memcpy(cipherKey, keyMaterial, key->keyLen/8); 77 } 78 79 if (direction == DIR_ENCRYPT) { 80 key->Nr = __db_rijndaelKeySetupEnc(key->rk, cipherKey, keyLen); 81 } else { 82 key->Nr = __db_rijndaelKeySetupDec(key->rk, cipherKey, keyLen); 83 } 84 __db_rijndaelKeySetupEnc(key->ek, cipherKey, keyLen); 85 return TRUE; 86} 87 88/* 89 * __db_cipherInit -- 90 * 91 * PUBLIC: int __db_cipherInit __P((cipherInstance *, int, char *)); 92 */ 93int 94__db_cipherInit(cipher, mode, IV) 95 cipherInstance *cipher; 96 int mode; 97 char *IV; 98{ 99 if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) { 100 cipher->mode = mode; 101 } else { 102 return BAD_CIPHER_MODE; 103 } 104 if (IV != NULL) { 105 memcpy(cipher->IV, IV, MAX_IV_SIZE); 106 } 107 return TRUE; 108} 109 110/* 111 * __db_blockEncrypt -- 112 * 113 * PUBLIC: int __db_blockEncrypt __P((cipherInstance *, keyInstance *, u_int8_t *, 114 * PUBLIC: size_t, u_int8_t *)); 115 */ 116int 117__db_blockEncrypt(cipher, key, input, inputLen, outBuffer) 118 cipherInstance *cipher; 119 keyInstance *key; 120 u_int8_t *input; 121 size_t inputLen; 122 u_int8_t *outBuffer; 123{ 124 int i, k, t, numBlocks; 125 u8 block[16], *iv; 126 u32 tmpiv[4]; 127 128 if (cipher == NULL || 129 key == NULL || 130 key->direction == DIR_DECRYPT) { 131 return BAD_CIPHER_STATE; 132 } 133 if (input == NULL || inputLen <= 0) { 134 return 0; /* nothing to do */ 135 } 136 137 numBlocks = (int)(inputLen/128); 138 139 switch (cipher->mode) { 140 case MODE_ECB: 141 for (i = numBlocks; i > 0; i--) { 142 __db_rijndaelEncrypt(key->rk, key->Nr, input, outBuffer); 143 input += 16; 144 outBuffer += 16; 145 } 146 break; 147 148 case MODE_CBC: 149 iv = cipher->IV; 150 for (i = numBlocks; i > 0; i--) { 151 memcpy(tmpiv, iv, MAX_IV_SIZE); 152 ((u32*)block)[0] = ((u32*)input)[0] ^ tmpiv[0]; 153 ((u32*)block)[1] = ((u32*)input)[1] ^ tmpiv[1]; 154 ((u32*)block)[2] = ((u32*)input)[2] ^ tmpiv[2]; 155 ((u32*)block)[3] = ((u32*)input)[3] ^ tmpiv[3]; 156 __db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 157 iv = outBuffer; 158 input += 16; 159 outBuffer += 16; 160 } 161 break; 162 163 case MODE_CFB1: 164 iv = cipher->IV; 165 for (i = numBlocks; i > 0; i--) { 166 memcpy(outBuffer, input, 16); 167 for (k = 0; k < 128; k++) { 168 __db_rijndaelEncrypt(key->ek, key->Nr, iv, block); 169 outBuffer[k >> 3] ^= (block[0] & (u_int)0x80) >> (k & 7); 170 for (t = 0; t < 15; t++) { 171 iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7); 172 } 173 iv[15] = (iv[15] << 1) | ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1); 174 } 175 outBuffer += 16; 176 input += 16; 177 } 178 break; 179 180 default: 181 return BAD_CIPHER_STATE; 182 } 183 184 return 128*numBlocks; 185} 186 187/** 188 * Encrypt data partitioned in octets, using RFC 2040-like padding. 189 * 190 * @param input data to be encrypted (octet sequence) 191 * @param inputOctets input length in octets (not bits) 192 * @param outBuffer encrypted output data 193 * 194 * @return length in octets (not bits) of the encrypted output buffer. 195 */ 196/* 197 * __db_padEncrypt -- 198 * 199 * PUBLIC: int __db_padEncrypt __P((cipherInstance *, keyInstance *, u_int8_t *, 200 * PUBLIC: int, u_int8_t *)); 201 */ 202int 203__db_padEncrypt(cipher, key, input, inputOctets, outBuffer) 204 cipherInstance *cipher; 205 keyInstance *key; 206 u_int8_t *input; 207 int inputOctets; 208 u_int8_t *outBuffer; 209{ 210 int i, numBlocks, padLen; 211 u8 block[16], *iv; 212 u32 tmpiv[4]; 213 214 if (cipher == NULL || 215 key == NULL || 216 key->direction == DIR_DECRYPT) { 217 return BAD_CIPHER_STATE; 218 } 219 if (input == NULL || inputOctets <= 0) { 220 return 0; /* nothing to do */ 221 } 222 223 numBlocks = inputOctets/16; 224 225 switch (cipher->mode) { 226 case MODE_ECB: 227 for (i = numBlocks; i > 0; i--) { 228 __db_rijndaelEncrypt(key->rk, key->Nr, input, outBuffer); 229 input += 16; 230 outBuffer += 16; 231 } 232 padLen = 16 - (inputOctets - 16*numBlocks); 233 DB_ASSERT(NULL, padLen > 0 && padLen <= 16); 234 memcpy(block, input, 16 - padLen); 235 memset(block + 16 - padLen, padLen, padLen); 236 __db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 237 break; 238 239 case MODE_CBC: 240 iv = cipher->IV; 241 for (i = numBlocks; i > 0; i--) { 242 memcpy(tmpiv, iv, MAX_IV_SIZE); 243 ((u32*)block)[0] = ((u32*)input)[0] ^ tmpiv[0]; 244 ((u32*)block)[1] = ((u32*)input)[1] ^ tmpiv[1]; 245 ((u32*)block)[2] = ((u32*)input)[2] ^ tmpiv[2]; 246 ((u32*)block)[3] = ((u32*)input)[3] ^ tmpiv[3]; 247 __db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 248 iv = outBuffer; 249 input += 16; 250 outBuffer += 16; 251 } 252 padLen = 16 - (inputOctets - 16*numBlocks); 253 DB_ASSERT(NULL, padLen > 0 && padLen <= 16); 254 for (i = 0; i < 16 - padLen; i++) { 255 block[i] = input[i] ^ iv[i]; 256 } 257 for (i = 16 - padLen; i < 16; i++) { 258 block[i] = (u_int8_t)padLen ^ iv[i]; 259 } 260 __db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 261 break; 262 263 default: 264 return BAD_CIPHER_STATE; 265 } 266 267 return 16*(numBlocks + 1); 268} 269 270/* 271 * __db_blockDecrypt -- 272 * 273 * PUBLIC: int __db_blockDecrypt __P((cipherInstance *, keyInstance *, u_int8_t *, 274 * PUBLIC: size_t, u_int8_t *)); 275 */ 276int 277__db_blockDecrypt(cipher, key, input, inputLen, outBuffer) 278 cipherInstance *cipher; 279 keyInstance *key; 280 u_int8_t *input; 281 size_t inputLen; 282 u_int8_t *outBuffer; 283{ 284 int i, k, t, numBlocks; 285 u8 block[16], *iv; 286 u32 tmpiv[4]; 287 288 if (cipher == NULL || 289 key == NULL || 290 (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) { 291 return BAD_CIPHER_STATE; 292 } 293 if (input == NULL || inputLen <= 0) { 294 return 0; /* nothing to do */ 295 } 296 297 numBlocks = (int)(inputLen/128); 298 299 switch (cipher->mode) { 300 case MODE_ECB: 301 for (i = numBlocks; i > 0; i--) { 302 __db_rijndaelDecrypt(key->rk, key->Nr, input, outBuffer); 303 input += 16; 304 outBuffer += 16; 305 } 306 break; 307 308 case MODE_CBC: 309 memcpy(tmpiv, cipher->IV, MAX_IV_SIZE); 310 for (i = numBlocks; i > 0; i--) { 311 __db_rijndaelDecrypt(key->rk, key->Nr, input, block); 312 ((u32*)block)[0] ^= tmpiv[0]; 313 ((u32*)block)[1] ^= tmpiv[1]; 314 ((u32*)block)[2] ^= tmpiv[2]; 315 ((u32*)block)[3] ^= tmpiv[3]; 316 memcpy(tmpiv, input, 16); 317 memcpy(outBuffer, block, 16); 318 input += 16; 319 outBuffer += 16; 320 } 321 break; 322 323 case MODE_CFB1: 324 iv = cipher->IV; 325 for (i = numBlocks; i > 0; i--) { 326 memcpy(outBuffer, input, 16); 327 for (k = 0; k < 128; k++) { 328 __db_rijndaelEncrypt(key->ek, key->Nr, iv, block); 329 for (t = 0; t < 15; t++) { 330 iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7); 331 } 332 iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1); 333 outBuffer[k >> 3] ^= (block[0] & (u_int)0x80) >> (k & 7); 334 } 335 outBuffer += 16; 336 input += 16; 337 } 338 break; 339 340 default: 341 return BAD_CIPHER_STATE; 342 } 343 344 return 128*numBlocks; 345} 346 347/* 348 * __db_padDecrypt -- 349 * 350 * PUBLIC: int __db_padDecrypt __P((cipherInstance *, keyInstance *, u_int8_t *, 351 * PUBLIC: int, u_int8_t *)); 352 */ 353int 354__db_padDecrypt(cipher, key, input, inputOctets, outBuffer) 355 cipherInstance *cipher; 356 keyInstance *key; 357 u_int8_t *input; 358 int inputOctets; 359 u_int8_t *outBuffer; 360{ 361 int i, numBlocks, padLen; 362 u8 block[16]; 363 u32 tmpiv[4]; 364 365 if (cipher == NULL || 366 key == NULL || 367 key->direction == DIR_ENCRYPT) { 368 return BAD_CIPHER_STATE; 369 } 370 if (input == NULL || inputOctets <= 0) { 371 return 0; /* nothing to do */ 372 } 373 if (inputOctets % 16 != 0) { 374 return BAD_DATA; 375 } 376 377 numBlocks = inputOctets/16; 378 379 switch (cipher->mode) { 380 case MODE_ECB: 381 /* all blocks but last */ 382 for (i = numBlocks - 1; i > 0; i--) { 383 __db_rijndaelDecrypt(key->rk, key->Nr, input, outBuffer); 384 input += 16; 385 outBuffer += 16; 386 } 387 /* last block */ 388 __db_rijndaelDecrypt(key->rk, key->Nr, input, block); 389 padLen = block[15]; 390 if (padLen >= 16) { 391 return BAD_DATA; 392 } 393 for (i = 16 - padLen; i < 16; i++) { 394 if (block[i] != padLen) { 395 return BAD_DATA; 396 } 397 } 398 memcpy(outBuffer, block, 16 - padLen); 399 break; 400 401 case MODE_CBC: 402 /* all blocks but last */ 403 memcpy(tmpiv, cipher->IV, MAX_IV_SIZE); 404 for (i = numBlocks - 1; i > 0; i--) { 405 __db_rijndaelDecrypt(key->rk, key->Nr, input, block); 406 ((u32*)block)[0] ^= tmpiv[0]; 407 ((u32*)block)[1] ^= tmpiv[1]; 408 ((u32*)block)[2] ^= tmpiv[2]; 409 ((u32*)block)[3] ^= tmpiv[3]; 410 memcpy(tmpiv, input, 16); 411 memcpy(outBuffer, block, 16); 412 input += 16; 413 outBuffer += 16; 414 } 415 /* last block */ 416 __db_rijndaelDecrypt(key->rk, key->Nr, input, block); 417 ((u32*)block)[0] ^= tmpiv[0]; 418 ((u32*)block)[1] ^= tmpiv[1]; 419 ((u32*)block)[2] ^= tmpiv[2]; 420 ((u32*)block)[3] ^= tmpiv[3]; 421 padLen = block[15]; 422 if (padLen <= 0 || padLen > 16) { 423 return BAD_DATA; 424 } 425 for (i = 16 - padLen; i < 16; i++) { 426 if (block[i] != padLen) { 427 return BAD_DATA; 428 } 429 } 430 memcpy(outBuffer, block, 16 - padLen); 431 break; 432 433 default: 434 return BAD_CIPHER_STATE; 435 } 436 437 return 16*numBlocks - padLen; 438} 439 440#ifdef INTERMEDIATE_VALUE_KAT 441/** 442 * cipherUpdateRounds: 443 * 444 * Encrypts/Decrypts exactly one full block a specified number of rounds. 445 * Only used in the Intermediate Value Known Answer Test. 446 * 447 * Returns: 448 * TRUE - on success 449 * BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized) 450 */ 451/* 452 * __db_cipherUpdateRounds -- 453 * 454 * PUBLIC: int __db_cipherUpdateRounds __P((cipherInstance *, keyInstance *, 455 * PUBLIC: u_int8_t *, int, u_int8_t *, int)); 456 */ 457int 458__db_cipherUpdateRounds(cipher, key, input, inputLen, outBuffer, rounds) 459 cipherInstance *cipher; 460 keyInstance *key; 461 u_int8_t *input; 462 size_t inputLen; 463 u_int8_t *outBuffer; 464 int rounds; 465{ 466 u8 block[16]; 467 468 if (cipher == NULL || key == NULL) { 469 return BAD_CIPHER_STATE; 470 } 471 472 memcpy(block, input, 16); 473 474 switch (key->direction) { 475 case DIR_ENCRYPT: 476 __db_rijndaelEncryptRound(key->rk, key->Nr, block, rounds); 477 break; 478 479 case DIR_DECRYPT: 480 __db_rijndaelDecryptRound(key->rk, key->Nr, block, rounds); 481 break; 482 483 default: 484 return BAD_KEY_DIR; 485 } 486 487 memcpy(outBuffer, block, 16); 488 489 return TRUE; 490} 491#endif /* INTERMEDIATE_VALUE_KAT */ 492