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