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