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 ((word32*)block)[0] ^= ((word32*)iv)[0]; 129 ((word32*)block)[1] ^= ((word32*)iv)[1]; 130 ((word32*)block)[2] ^= ((word32*)iv)[2]; 131 ((word32*)block)[3] ^= ((word32*)iv)[3]; 132 #else 133 ((word32*)block)[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0]; 134 ((word32*)block)[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1]; 135 ((word32*)block)[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2]; 136 ((word32*)block)[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3]; 137 #endif 138 outBuffer += 16; 139 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 140 input += 16; 141 } 142 break; 143 144 case MODE_CFB1: 145 #if 1 /*STRICT_ALIGN*/ 146 bcopy(cipher->IV, iv, 16); 147 #else /* !STRICT_ALIGN */ 148 *((word32*)iv[0]) = *((word32*)(cipher->IV )); 149 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4)); 150 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8)); 151 *((word32*)iv[3]) = *((word32*)(cipher->IV+12)); 152 #endif /* ?STRICT_ALIGN */ 153 for (i = numBlocks; i > 0; i--) { 154 for (k = 0; k < 128; k++) { 155 *((word32*) block ) = *((word32*)iv[0]); 156 *((word32*)(block+ 4)) = *((word32*)iv[1]); 157 *((word32*)(block+ 8)) = *((word32*)iv[2]); 158 *((word32*)(block+12)) = *((word32*)iv[3]); 159 rijndaelEncrypt(block, block, key->keySched, key->ROUNDS); 160 outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7); 161 iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7); 162 iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7); 163 iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7); 164 iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7); 165 iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7); 166 iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7); 167 iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7); 168 iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7); 169 iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7); 170 iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7); 171 iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7); 172 iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7); 173 iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7); 174 iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7); 175 iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7); 176 iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1); 177 } 178 } 179 break; 180 181 default: 182 return BAD_CIPHER_STATE; 183 } 184 185 return 128*numBlocks; 186 } 187 188 /** 189 * Encrypt data partitioned in octets, using RFC 2040-like padding. 190 * 191 * @param input data to be encrypted (octet sequence) 192 * @param inputOctets input length in octets (not bits) 193 * @param outBuffer encrypted output data 194 * 195 * @return length in octets (not bits) of the encrypted output buffer. 196 */ 197 int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key, 198 BYTE *input, int inputOctets, BYTE *outBuffer) { 199 int i, numBlocks, padLen; 200 word8 block[16], *iv, *cp; 201 202 if (cipher == NULL || 203 key == NULL || 204 key->direction == DIR_DECRYPT) { 205 return BAD_CIPHER_STATE; 206 } 207 if (input == NULL || inputOctets <= 0) { 208 return 0; /* nothing to do */ 209 } 210 211 numBlocks = inputOctets/16; 212 213 switch (cipher->mode) { 214 case MODE_ECB: 215 for (i = numBlocks; i > 0; i--) { 216 rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS); 217 input += 16; 218 outBuffer += 16; 219 } 220 padLen = 16 - (inputOctets - 16*numBlocks); 221 if (padLen > 0 && padLen <= 16) 222 panic("rijndael_padEncrypt(ECB)"); 223 bcopy(input, block, 16 - padLen); 224 for (cp = block + 16 - padLen; cp < block + 16; cp++) 225 *cp = padLen; 226 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 227 break; 228 229 case MODE_CBC: 230 iv = cipher->IV; 231 for (i = numBlocks; i > 0; i--) { 232 ((word32*)block)[0] = ((word32*)input)[0] ^ ((word32*)iv)[0]; 233 ((word32*)block)[1] = ((word32*)input)[1] ^ ((word32*)iv)[1]; 234 ((word32*)block)[2] = ((word32*)input)[2] ^ ((word32*)iv)[2]; 235 ((word32*)block)[3] = ((word32*)input)[3] ^ ((word32*)iv)[3]; 236 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 237 iv = outBuffer; 238 input += 16; 239 outBuffer += 16; 240 } 241 padLen = 16 - (inputOctets - 16*numBlocks); 242 if (padLen > 0 && padLen <= 16) 243 panic("rijndael_padEncrypt(CBC)"); 244 for (i = 0; i < 16 - padLen; i++) { 245 block[i] = input[i] ^ iv[i]; 246 } 247 for (i = 16 - padLen; i < 16; i++) { 248 block[i] = (BYTE)padLen ^ iv[i]; 249 } 250 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 251 break; 252 253 default: 254 return BAD_CIPHER_STATE; 255 } 256 257 return 16*(numBlocks + 1); 258 } 259 260 int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key, 261 BYTE *input, int inputLen, BYTE *outBuffer) { 262 int i, k, numBlocks; 263 word8 block[16], iv[4][4]; 264 265 if (cipher == NULL || 266 key == NULL || 267 (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) { 268 return BAD_CIPHER_STATE; 269 } 270 if (input == NULL || inputLen <= 0) { 271 return 0; /* nothing to do */ 272 } 273 274 numBlocks = inputLen/128; 275 276 switch (cipher->mode) { 277 case MODE_ECB: 278 for (i = numBlocks; i > 0; i--) { 279 rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS); 280 input += 16; 281 outBuffer += 16; 282 } 283 break; 284 285 case MODE_CBC: 286 #if 1 /*STRICT_ALIGN */ 287 bcopy(cipher->IV, iv, 16); 288 #else 289 *((word32*)iv[0]) = *((word32*)(cipher->IV )); 290 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4)); 291 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8)); 292 *((word32*)iv[3]) = *((word32*)(cipher->IV+12)); 293 #endif 294 for (i = numBlocks; i > 0; i--) { 295 rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 296 ((word32*)block)[0] ^= *((word32*)iv[0]); 297 ((word32*)block)[1] ^= *((word32*)iv[1]); 298 ((word32*)block)[2] ^= *((word32*)iv[2]); 299 ((word32*)block)[3] ^= *((word32*)iv[3]); 300 #if 1 /*STRICT_ALIGN*/ 301 bcopy(input, iv, 16); 302 bcopy(block, outBuffer, 16); 303 #else 304 *((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0]; 305 *((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1]; 306 *((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2]; 307 *((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3]; 308 #endif 309 input += 16; 310 outBuffer += 16; 311 } 312 break; 313 314 case MODE_CFB1: 315 #if 1 /*STRICT_ALIGN */ 316 bcopy(cipher->IV, iv, 16); 317 #else 318 *((word32*)iv[0]) = *((word32*)(cipher->IV)); 319 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4)); 320 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8)); 321 *((word32*)iv[3]) = *((word32*)(cipher->IV+12)); 322 #endif 323 for (i = numBlocks; i > 0; i--) { 324 for (k = 0; k < 128; k++) { 325 *((word32*) block ) = *((word32*)iv[0]); 326 *((word32*)(block+ 4)) = *((word32*)iv[1]); 327 *((word32*)(block+ 8)) = *((word32*)iv[2]); 328 *((word32*)(block+12)) = *((word32*)iv[3]); 329 rijndaelEncrypt(block, block, key->keySched, key->ROUNDS); 330 iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7); 331 iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7); 332 iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7); 333 iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7); 334 iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7); 335 iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7); 336 iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7); 337 iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7); 338 iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7); 339 iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7); 340 iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7); 341 iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7); 342 iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7); 343 iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7); 344 iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7); 345 iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1); 346 outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7); 347 } 348 } 349 break; 350 351 default: 352 return BAD_CIPHER_STATE; 353 } 354 355 return 128*numBlocks; 356 } 357 358 int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key, 359 BYTE *input, int inputOctets, BYTE *outBuffer) { 360 int i, numBlocks, padLen; 361 word8 block[16]; 362 word32 iv[4]; 363 364 if (cipher == NULL || 365 key == NULL || 366 key->direction == DIR_ENCRYPT) { 367 return BAD_CIPHER_STATE; 368 } 369 if (input == NULL || inputOctets <= 0) { 370 return 0; /* nothing to do */ 371 } 372 if (inputOctets % 16 != 0) { 373 return BAD_DATA; 374 } 375 376 numBlocks = inputOctets/16; 377 378 switch (cipher->mode) { 379 case MODE_ECB: 380 /* all blocks but last */ 381 for (i = numBlocks - 1; i > 0; i--) { 382 rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS); 383 input += 16; 384 outBuffer += 16; 385 } 386 /* last block */ 387 rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 388 padLen = block[15]; 389 if (padLen >= 16) { 390 return BAD_DATA; 391 } 392 for (i = 16 - padLen; i < 16; i++) { 393 if (block[i] != padLen) { 394 return BAD_DATA; 395 } 396 } 397 bcopy(block, outBuffer, 16 - padLen); 398 break; 399 400 case MODE_CBC: 401 bcopy(cipher->IV, iv, 16); 402 /* all blocks but last */ 403 for (i = numBlocks - 1; i > 0; i--) { 404 rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 405 ((word32*)block)[0] ^= iv[0]; 406 ((word32*)block)[1] ^= iv[1]; 407 ((word32*)block)[2] ^= iv[2]; 408 ((word32*)block)[3] ^= iv[3]; 409 bcopy(input, iv, 16); 410 bcopy(block, outBuffer, 16); 411 input += 16; 412 outBuffer += 16; 413 } 414 /* last block */ 415 rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 416 ((word32*)block)[0] ^= iv[0]; 417 ((word32*)block)[1] ^= iv[1]; 418 ((word32*)block)[2] ^= iv[2]; 419 ((word32*)block)[3] ^= iv[3]; 420 padLen = block[15]; 421 if (padLen <= 0 || padLen > 16) { 422 return BAD_DATA; 423 } 424 for (i = 16 - padLen; i < 16; i++) { 425 if (block[i] != padLen) { 426 return BAD_DATA; 427 } 428 } 429 bcopy(block, outBuffer, 16 - padLen); 430 break; 431 432 default: 433 return BAD_CIPHER_STATE; 434 } 435 436 return 16*numBlocks - padLen; 437 } 438 439 #ifdef INTERMEDIATE_VALUE_KAT 440 /** 441 * cipherUpdateRounds: 442 * 443 * Encrypts/Decrypts exactly one full block a specified number of rounds. 444 * Only used in the Intermediate Value Known Answer Test. 445 * 446 * Returns: 447 * TRUE - on success 448 * BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized) 449 */ 450 int rijndael_cipherUpdateRounds(cipherInstance *cipher, keyInstance *key, 451 BYTE *input, int inputLen, BYTE *outBuffer, int rounds) { 452 int j; 453 word8 block[4][4]; 454 455 if (cipher == NULL || key == NULL) { 456 return BAD_CIPHER_STATE; 457 } 458 459 for (j = 3; j >= 0; j--) { 460 /* parse input stream into rectangular array */ 461 *((word32*)block[j]) = *((word32*)(input+4*j)); 462 } 463 464 switch (key->direction) { 465 case DIR_ENCRYPT: 466 rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds); 467 break; 468 469 case DIR_DECRYPT: 470 rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds); 471 break; 472 473 default: 474 return BAD_KEY_DIR; 475 } 476 477 for (j = 3; j >= 0; j--) { 478 /* parse rectangular array into output ciphertext bytes */ 479 *((word32*)(outBuffer+4*j)) = *((word32*)block[j]); 480 } 481 482 return TRUE; 483 } 484 #endif /* INTERMEDIATE_VALUE_KAT */ 485