rijndael-api-fst.c revision 67958
1/* $KAME: $ */ 2 3/* 4 * rijndael-api-fst.c v2.3 April '2000 5 * 6 * Optimised ANSI C code 7 * 8 * authors: v1.0: Antoon Bosselaers 9 * v2.0: Vincent Rijmen 10 * v2.1: Vincent Rijmen 11 * v2.2: Vincent Rijmen 12 * v2.3: Paulo Barreto 13 * v2.4: Vincent Rijmen 14 * 15 * This code is placed in the public domain. 16 */ 17 18#include <sys/param.h> 19#include <sys/systm.h> 20#include <sys/types.h> 21#include <crypto/rijndael/rijndael-alg-fst.h> 22#include <crypto/rijndael/rijndael-api-fst.h> 23#include <crypto/rijndael/rijndael_local.h> 24 25int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) { 26 word8 k[MAXKC][4]; 27 int i; 28 char *keyMat; 29 30 if (key == NULL) { 31 return BAD_KEY_INSTANCE; 32 } 33 34 if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) { 35 key->direction = direction; 36 } else { 37 return BAD_KEY_DIR; 38 } 39 40 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { 41 key->keyLen = keyLen; 42 } else { 43 return BAD_KEY_MAT; 44 } 45 46 if (keyMaterial != NULL) { 47 strncpy(key->keyMaterial, keyMaterial, keyLen/4); 48 } 49 50 key->ROUNDS = keyLen/32 + 6; 51 52 /* initialize key schedule: */ 53 keyMat = key->keyMaterial; 54#ifndef BINARY_KEY_MATERIAL 55 for (i = 0; i < key->keyLen/8; i++) { 56 int t, j; 57 58 t = *keyMat++; 59 if ((t >= '0') && (t <= '9')) j = (t - '0') << 4; 60 else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4; 61 else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4; 62 else return BAD_KEY_MAT; 63 64 t = *keyMat++; 65 if ((t >= '0') && (t <= '9')) j ^= (t - '0'); 66 else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10); 67 else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10); 68 else return BAD_KEY_MAT; 69 70 k[i >> 2][i & 3] = (word8)j; 71 } 72#else 73 for (i = 0; i < key->keyLen/8; i++) { 74 k[i >> 2][i & 3] = (word8)keyMat[i]; 75 } 76#endif /* ?BINARY_KEY_MATERIAL */ 77 rijndaelKeySched(k, key->keySched, key->ROUNDS); 78 if (direction == DIR_DECRYPT) { 79 rijndaelKeyEncToDec(key->keySched, key->ROUNDS); 80 } 81 82 return TRUE; 83} 84 85int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) { 86 if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) { 87 cipher->mode = mode; 88 } else { 89 return BAD_CIPHER_MODE; 90 } 91 if (IV != NULL) { 92#ifndef BINARY_KEY_MATERIAL 93 int i; 94 for (i = 0; i < MAX_IV_SIZE; i++) { 95 int t, j; 96 97 t = IV[2*i]; 98 if ((t >= '0') && (t <= '9')) j = (t - '0') << 4; 99 else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4; 100 else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4; 101 else return BAD_CIPHER_INSTANCE; 102 103 t = IV[2*i+1]; 104 if ((t >= '0') && (t <= '9')) j ^= (t - '0'); 105 else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10); 106 else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10); 107 else return BAD_CIPHER_INSTANCE; 108 109 cipher->IV[i] = (word8)j; 110 } 111#else 112 bcopy(IV, cipher->IV, MAX_IV_SIZE); 113#endif /* ?BINARY_KEY_MATERIAL */ 114 } else { 115 bzero(cipher->IV, MAX_IV_SIZE); 116 } 117 return TRUE; 118} 119 120int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key, 121 BYTE *input, int inputLen, BYTE *outBuffer) { 122 int i, k, numBlocks; 123 word8 block[16], iv[4][4]; 124 125 if (cipher == NULL || 126 key == NULL || 127 key->direction == DIR_DECRYPT) { 128 return BAD_CIPHER_STATE; 129 } 130 if (input == NULL || inputLen <= 0) { 131 return 0; /* nothing to do */ 132 } 133 134 numBlocks = inputLen/128; 135 136 switch (cipher->mode) { 137 case MODE_ECB: 138 for (i = numBlocks; i > 0; i--) { 139 rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS); 140 input += 16; 141 outBuffer += 16; 142 } 143 break; 144 145 case MODE_CBC: 146#if 1 /*STRICT_ALIGN*/ 147 bcopy(cipher->IV, block, 16); 148 bcopy(input, iv, 16); 149 ((word32*)block)[0] ^= ((word32*)iv)[0]; 150 ((word32*)block)[1] ^= ((word32*)iv)[1]; 151 ((word32*)block)[2] ^= ((word32*)iv)[2]; 152 ((word32*)block)[3] ^= ((word32*)iv)[3]; 153#else 154 ((word32*)block)[0] = ((word32*)cipher->IV)[0] ^ ((word32*)input)[0]; 155 ((word32*)block)[1] = ((word32*)cipher->IV)[1] ^ ((word32*)input)[1]; 156 ((word32*)block)[2] = ((word32*)cipher->IV)[2] ^ ((word32*)input)[2]; 157 ((word32*)block)[3] = ((word32*)cipher->IV)[3] ^ ((word32*)input)[3]; 158#endif 159 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 160 input += 16; 161 for (i = numBlocks - 1; i > 0; i--) { 162#if 1 /*STRICT_ALIGN*/ 163 bcopy(outBuffer, block, 16); 164 ((word32*)block)[0] ^= ((word32*)iv)[0]; 165 ((word32*)block)[1] ^= ((word32*)iv)[1]; 166 ((word32*)block)[2] ^= ((word32*)iv)[2]; 167 ((word32*)block)[3] ^= ((word32*)iv)[3]; 168#else 169 ((word32*)block)[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0]; 170 ((word32*)block)[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1]; 171 ((word32*)block)[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2]; 172 ((word32*)block)[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3]; 173#endif 174 outBuffer += 16; 175 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 176 input += 16; 177 } 178 break; 179 180 case MODE_CFB1: 181#if 1 /*STRICT_ALIGN*/ 182 bcopy(cipher->IV, iv, 16); 183#else /* !STRICT_ALIGN */ 184 *((word32*)iv[0]) = *((word32*)(cipher->IV )); 185 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4)); 186 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8)); 187 *((word32*)iv[3]) = *((word32*)(cipher->IV+12)); 188#endif /* ?STRICT_ALIGN */ 189 for (i = numBlocks; i > 0; i--) { 190 for (k = 0; k < 128; k++) { 191 *((word32*) block ) = *((word32*)iv[0]); 192 *((word32*)(block+ 4)) = *((word32*)iv[1]); 193 *((word32*)(block+ 8)) = *((word32*)iv[2]); 194 *((word32*)(block+12)) = *((word32*)iv[3]); 195 rijndaelEncrypt(block, block, key->keySched, key->ROUNDS); 196 outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7); 197 iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7); 198 iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7); 199 iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7); 200 iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7); 201 iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7); 202 iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7); 203 iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7); 204 iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7); 205 iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7); 206 iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7); 207 iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7); 208 iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7); 209 iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7); 210 iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7); 211 iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7); 212 iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1); 213 } 214 } 215 break; 216 217 default: 218 return BAD_CIPHER_STATE; 219 } 220 221 return 128*numBlocks; 222} 223 224/** 225 * Encrypt data partitioned in octets, using RFC 2040-like padding. 226 * 227 * @param input data to be encrypted (octet sequence) 228 * @param inputOctets input length in octets (not bits) 229 * @param outBuffer encrypted output data 230 * 231 * @return length in octets (not bits) of the encrypted output buffer. 232 */ 233int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key, 234 BYTE *input, int inputOctets, BYTE *outBuffer) { 235 int i, numBlocks, padLen; 236 word8 block[16], *iv, *cp; 237 238 if (cipher == NULL || 239 key == NULL || 240 key->direction == DIR_DECRYPT) { 241 return BAD_CIPHER_STATE; 242 } 243 if (input == NULL || inputOctets <= 0) { 244 return 0; /* nothing to do */ 245 } 246 247 numBlocks = inputOctets/16; 248 249 switch (cipher->mode) { 250 case MODE_ECB: 251 for (i = numBlocks; i > 0; i--) { 252 rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS); 253 input += 16; 254 outBuffer += 16; 255 } 256 padLen = 16 - (inputOctets - 16*numBlocks); 257 if (padLen > 0 && padLen <= 16) 258 panic("rijndael_padEncrypt(ECB)"); 259 bcopy(input, block, 16 - padLen); 260 for (cp = block + 16 - padLen; cp < block + 16; cp++) 261 *cp = padLen; 262 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 263 break; 264 265 case MODE_CBC: 266 iv = cipher->IV; 267 for (i = numBlocks; i > 0; i--) { 268 ((word32*)block)[0] = ((word32*)input)[0] ^ ((word32*)iv)[0]; 269 ((word32*)block)[1] = ((word32*)input)[1] ^ ((word32*)iv)[1]; 270 ((word32*)block)[2] = ((word32*)input)[2] ^ ((word32*)iv)[2]; 271 ((word32*)block)[3] = ((word32*)input)[3] ^ ((word32*)iv)[3]; 272 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 273 iv = outBuffer; 274 input += 16; 275 outBuffer += 16; 276 } 277 padLen = 16 - (inputOctets - 16*numBlocks); 278 if (padLen > 0 && padLen <= 16) 279 panic("rijndael_padEncrypt(CBC)"); 280 for (i = 0; i < 16 - padLen; i++) { 281 block[i] = input[i] ^ iv[i]; 282 } 283 for (i = 16 - padLen; i < 16; i++) { 284 block[i] = (BYTE)padLen ^ iv[i]; 285 } 286 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 287 break; 288 289 default: 290 return BAD_CIPHER_STATE; 291 } 292 293 return 16*(numBlocks + 1); 294} 295 296int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key, 297 BYTE *input, int inputLen, BYTE *outBuffer) { 298 int i, k, numBlocks; 299 word8 block[16], iv[4][4]; 300 301 if (cipher == NULL || 302 key == NULL || 303 (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) { 304 return BAD_CIPHER_STATE; 305 } 306 if (input == NULL || inputLen <= 0) { 307 return 0; /* nothing to do */ 308 } 309 310 numBlocks = inputLen/128; 311 312 switch (cipher->mode) { 313 case MODE_ECB: 314 for (i = numBlocks; i > 0; i--) { 315 rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS); 316 input += 16; 317 outBuffer += 16; 318 } 319 break; 320 321 case MODE_CBC: 322#if 1 /*STRICT_ALIGN */ 323 bcopy(cipher->IV, iv, 16); 324#else 325 *((word32*)iv[0]) = *((word32*)(cipher->IV )); 326 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4)); 327 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8)); 328 *((word32*)iv[3]) = *((word32*)(cipher->IV+12)); 329#endif 330 for (i = numBlocks; i > 0; i--) { 331 rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 332 ((word32*)block)[0] ^= *((word32*)iv[0]); 333 ((word32*)block)[1] ^= *((word32*)iv[1]); 334 ((word32*)block)[2] ^= *((word32*)iv[2]); 335 ((word32*)block)[3] ^= *((word32*)iv[3]); 336#if 1 /*STRICT_ALIGN*/ 337 bcopy(input, iv, 16); 338 bcopy(block, outBuffer, 16); 339#else 340 *((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0]; 341 *((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1]; 342 *((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2]; 343 *((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3]; 344#endif 345 input += 16; 346 outBuffer += 16; 347 } 348 break; 349 350 case MODE_CFB1: 351#if 1 /*STRICT_ALIGN */ 352 bcopy(cipher->IV, iv, 16); 353#else 354 *((word32*)iv[0]) = *((word32*)(cipher->IV)); 355 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4)); 356 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8)); 357 *((word32*)iv[3]) = *((word32*)(cipher->IV+12)); 358#endif 359 for (i = numBlocks; i > 0; i--) { 360 for (k = 0; k < 128; k++) { 361 *((word32*) block ) = *((word32*)iv[0]); 362 *((word32*)(block+ 4)) = *((word32*)iv[1]); 363 *((word32*)(block+ 8)) = *((word32*)iv[2]); 364 *((word32*)(block+12)) = *((word32*)iv[3]); 365 rijndaelEncrypt(block, block, key->keySched, key->ROUNDS); 366 iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7); 367 iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7); 368 iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7); 369 iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7); 370 iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7); 371 iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7); 372 iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7); 373 iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7); 374 iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7); 375 iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7); 376 iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7); 377 iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7); 378 iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7); 379 iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7); 380 iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7); 381 iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1); 382 outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7); 383 } 384 } 385 break; 386 387 default: 388 return BAD_CIPHER_STATE; 389 } 390 391 return 128*numBlocks; 392} 393 394int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key, 395 BYTE *input, int inputOctets, BYTE *outBuffer) { 396 int i, numBlocks, padLen; 397 word8 block[16]; 398 word32 iv[4]; 399 400 if (cipher == NULL || 401 key == NULL || 402 key->direction == DIR_ENCRYPT) { 403 return BAD_CIPHER_STATE; 404 } 405 if (input == NULL || inputOctets <= 0) { 406 return 0; /* nothing to do */ 407 } 408 if (inputOctets % 16 != 0) { 409 return BAD_DATA; 410 } 411 412 numBlocks = inputOctets/16; 413 414 switch (cipher->mode) { 415 case MODE_ECB: 416 /* all blocks but last */ 417 for (i = numBlocks - 1; i > 0; i--) { 418 rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS); 419 input += 16; 420 outBuffer += 16; 421 } 422 /* last block */ 423 rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 424 padLen = block[15]; 425 if (padLen >= 16) { 426 return BAD_DATA; 427 } 428 for (i = 16 - padLen; i < 16; i++) { 429 if (block[i] != padLen) { 430 return BAD_DATA; 431 } 432 } 433 bcopy(block, outBuffer, 16 - padLen); 434 break; 435 436 case MODE_CBC: 437 bcopy(cipher->IV, iv, 16); 438 /* all blocks but last */ 439 for (i = numBlocks - 1; i > 0; i--) { 440 rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 441 ((word32*)block)[0] ^= iv[0]; 442 ((word32*)block)[1] ^= iv[1]; 443 ((word32*)block)[2] ^= iv[2]; 444 ((word32*)block)[3] ^= iv[3]; 445 bcopy(input, iv, 16); 446 bcopy(block, outBuffer, 16); 447 input += 16; 448 outBuffer += 16; 449 } 450 /* last block */ 451 rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 452 ((word32*)block)[0] ^= iv[0]; 453 ((word32*)block)[1] ^= iv[1]; 454 ((word32*)block)[2] ^= iv[2]; 455 ((word32*)block)[3] ^= iv[3]; 456 padLen = block[15]; 457 if (padLen <= 0 || padLen > 16) { 458 return BAD_DATA; 459 } 460 for (i = 16 - padLen; i < 16; i++) { 461 if (block[i] != padLen) { 462 return BAD_DATA; 463 } 464 } 465 bcopy(block, outBuffer, 16 - padLen); 466 break; 467 468 default: 469 return BAD_CIPHER_STATE; 470 } 471 472 return 16*numBlocks - padLen; 473} 474 475#ifdef INTERMEDIATE_VALUE_KAT 476/** 477 * cipherUpdateRounds: 478 * 479 * Encrypts/Decrypts exactly one full block a specified number of rounds. 480 * Only used in the Intermediate Value Known Answer Test. 481 * 482 * Returns: 483 * TRUE - on success 484 * BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized) 485 */ 486int rijndael_cipherUpdateRounds(cipherInstance *cipher, keyInstance *key, 487 BYTE *input, int inputLen, BYTE *outBuffer, int rounds) { 488 int j; 489 word8 block[4][4]; 490 491 if (cipher == NULL || key == NULL) { 492 return BAD_CIPHER_STATE; 493 } 494 495 for (j = 3; j >= 0; j--) { 496 /* parse input stream into rectangular array */ 497 *((word32*)block[j]) = *((word32*)(input+4*j)); 498 } 499 500 switch (key->direction) { 501 case DIR_ENCRYPT: 502 rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds); 503 break; 504 505 case DIR_DECRYPT: 506 rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds); 507 break; 508 509 default: 510 return BAD_KEY_DIR; 511 } 512 513 for (j = 3; j >= 0; j--) { 514 /* parse rectangular array into output ciphertext bytes */ 515 *((word32*)(outBuffer+4*j)) = *((word32*)block[j]); 516 } 517 518 return TRUE; 519} 520#endif /* INTERMEDIATE_VALUE_KAT */ 521