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