rijndael-api-fst.c revision 121085
1/* $KAME: rijndael-api-fst.c,v 1.18 2003/07/24 15:10:30 itojun Exp $ */ 2 3/** 4 * rijndael-api-fst.c 5 * 6 * @version 2.9 (December 2000) 7 * 8 * Optimised ANSI C code for the Rijndael cipher (now AES) 9 * 10 * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> 11 * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> 12 * @author Paulo Barreto <paulo.barreto@terra.com.br> 13 * 14 * This code is hereby placed in the public domain. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS 17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Acknowledgements: 29 * 30 * We are deeply indebted to the following people for their bug reports, 31 * fixes, and improvement suggestions to this implementation. Though we 32 * tried to list all contributions, we apologise in advance for any 33 * missing reference. 34 * 35 * Andrew Bales <Andrew.Bales@Honeywell.com> 36 * Markus Friedl <markus.friedl@informatik.uni-erlangen.de> 37 * John Skodon <skodonj@webquill.com> 38 */ 39 40#include <sys/cdefs.h> 41__FBSDID("$FreeBSD: head/sys/crypto/rijndael/rijndael-api-fst.c 121085 2003-10-14 13:37:37Z ume $"); 42 43#include <sys/param.h> 44#ifdef _KERNEL 45#include <sys/systm.h> 46#else 47#include <stdlib.h> 48#include <string.h> 49#endif 50 51#include <crypto/rijndael/rijndael_local.h> 52#include <crypto/rijndael/rijndael-alg-fst.h> 53#include <crypto/rijndael/rijndael-api-fst.h> 54 55int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) { 56 u_int8_t cipherKey[RIJNDAEL_MAXKB]; 57 58 if (key == NULL) { 59 return BAD_KEY_INSTANCE; 60 } 61 62 if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) { 63 key->direction = direction; 64 } else { 65 return BAD_KEY_DIR; 66 } 67 68 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { 69 key->keyLen = keyLen; 70 } else { 71 return BAD_KEY_MAT; 72 } 73 74 if (keyMaterial != NULL) { 75 memcpy(key->keyMaterial, keyMaterial, keyLen/8); 76 } 77 78 /* initialize key schedule: */ 79 memcpy(cipherKey, key->keyMaterial, keyLen/8); 80 if (direction == DIR_ENCRYPT) { 81 key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen); 82 } else { 83 key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen); 84 } 85 rijndaelKeySetupEnc(key->ek, cipherKey, keyLen); 86 return TRUE; 87} 88 89int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) { 90 if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) { 91 cipher->mode = mode; 92 } else { 93 return BAD_CIPHER_MODE; 94 } 95 if (IV != NULL) { 96 memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE); 97 } else { 98 memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE); 99 } 100 return TRUE; 101} 102 103int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key, 104 BYTE *input, int inputLen, BYTE *outBuffer) { 105 int i, k, t, numBlocks; 106#if 1 /*STRICT_ALIGN*/ 107 u_int8_t block[16], iv[16]; 108#else 109 u_int8_t block[16], *iv; 110#endif 111 112 if (cipher == NULL || 113 key == NULL || 114 key->direction == DIR_DECRYPT) { 115 return BAD_CIPHER_STATE; 116 } 117 if (input == NULL || inputLen <= 0) { 118 return 0; /* nothing to do */ 119 } 120 121 numBlocks = inputLen/128; 122 123 switch (cipher->mode) { 124 case MODE_ECB: 125 for (i = numBlocks; i > 0; i--) { 126 rijndaelEncrypt(key->rk, key->Nr, input, outBuffer); 127 input += 16; 128 outBuffer += 16; 129 } 130 break; 131 132 case MODE_CBC: 133#if 1 /*STRICT_ALIGN*/ 134 memcpy(iv, cipher->IV, 16); 135#else 136 iv = cipher->IV; 137#endif 138 for (i = numBlocks; i > 0; i--) { 139#if 1 /*STRICT_ALIGN*/ 140 memcpy(block, input, 16); 141 ((u_int32_t*)block)[0] ^= ((u_int32_t*)iv)[0]; 142 ((u_int32_t*)block)[1] ^= ((u_int32_t*)iv)[1]; 143 ((u_int32_t*)block)[2] ^= ((u_int32_t*)iv)[2]; 144 ((u_int32_t*)block)[3] ^= ((u_int32_t*)iv)[3]; 145#else 146 ((u_int32_t*)block)[0] = ((u_int32_t*)input)[0] ^ ((u_int32_t*)iv)[0]; 147 ((u_int32_t*)block)[1] = ((u_int32_t*)input)[1] ^ ((u_int32_t*)iv)[1]; 148 ((u_int32_t*)block)[2] = ((u_int32_t*)input)[2] ^ ((u_int32_t*)iv)[2]; 149 ((u_int32_t*)block)[3] = ((u_int32_t*)input)[3] ^ ((u_int32_t*)iv)[3]; 150#endif 151 rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 152#if 1 /*STRICT_ALIGN*/ 153 memcpy(iv, outBuffer, 16); 154#else 155 iv = outBuffer; 156#endif 157 input += 16; 158 outBuffer += 16; 159 } 160 break; 161 162 case MODE_CFB1: 163#if 1 /*STRICT_ALIGN*/ 164 memcpy(iv, cipher->IV, 16); 165#else 166 iv = cipher->IV; 167#endif 168 for (i = numBlocks; i > 0; i--) { 169 memcpy(outBuffer, input, 16); 170 for (k = 0; k < 128; k++) { 171 rijndaelEncrypt(key->ek, key->Nr, iv, block); 172 outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7); 173 for (t = 0; t < 15; t++) { 174 iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7); 175 } 176 iv[15] = (iv[15] << 1) | ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1); 177 } 178 outBuffer += 16; 179 input += 16; 180 } 181#if 1 /*STRICT_ALIGN*/ 182 memcpy(cipher->IV, iv, 16); 183#endif 184 break; 185 186 default: 187 return BAD_CIPHER_STATE; 188 } 189 190 return 128*numBlocks; 191} 192 193/** 194 * Encrypt data partitioned in octets, using RFC 2040-like padding. 195 * 196 * @param input data to be encrypted (octet sequence) 197 * @param inputOctets input length in octets (not bits) 198 * @param outBuffer encrypted output data 199 * 200 * @return length in octets (not bits) of the encrypted output buffer. 201 */ 202int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key, 203 BYTE *input, int inputOctets, BYTE *outBuffer) { 204 int i, numBlocks, padLen; 205 u_int8_t block[16], *iv; 206 207 if (cipher == NULL || 208 key == NULL || 209 key->direction == DIR_DECRYPT) { 210 return BAD_CIPHER_STATE; 211 } 212 if (input == NULL || inputOctets <= 0) { 213 return 0; /* nothing to do */ 214 } 215 216 numBlocks = inputOctets/16; 217 218 switch (cipher->mode) { 219 case MODE_ECB: 220 for (i = numBlocks; i > 0; i--) { 221 rijndaelEncrypt(key->rk, key->Nr, input, outBuffer); 222 input += 16; 223 outBuffer += 16; 224 } 225 padLen = 16 - (inputOctets - 16*numBlocks); 226 if (padLen <= 0 || padLen > 16) 227 return BAD_CIPHER_STATE; 228 memcpy(block, input, 16 - padLen); 229 memset(block + 16 - padLen, padLen, padLen); 230 rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 231 break; 232 233 case MODE_CBC: 234 iv = cipher->IV; 235 for (i = numBlocks; i > 0; i--) { 236 ((u_int32_t*)block)[0] = ((u_int32_t*)input)[0] ^ ((u_int32_t*)iv)[0]; 237 ((u_int32_t*)block)[1] = ((u_int32_t*)input)[1] ^ ((u_int32_t*)iv)[1]; 238 ((u_int32_t*)block)[2] = ((u_int32_t*)input)[2] ^ ((u_int32_t*)iv)[2]; 239 ((u_int32_t*)block)[3] = ((u_int32_t*)input)[3] ^ ((u_int32_t*)iv)[3]; 240 rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 241 iv = outBuffer; 242 input += 16; 243 outBuffer += 16; 244 } 245 padLen = 16 - (inputOctets - 16*numBlocks); 246 if (padLen <= 0 || padLen > 16) 247 return BAD_CIPHER_STATE; 248 for (i = 0; i < 16 - padLen; i++) { 249 block[i] = input[i] ^ iv[i]; 250 } 251 for (i = 16 - padLen; i < 16; i++) { 252 block[i] = (BYTE)padLen ^ iv[i]; 253 } 254 rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 255 break; 256 257 default: 258 return BAD_CIPHER_STATE; 259 } 260 261 return 16*(numBlocks + 1); 262} 263 264int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key, 265 BYTE *input, int inputLen, BYTE *outBuffer) { 266 int i, k, t, numBlocks; 267#if 1 /*STRICT_ALIGN*/ 268 u_int8_t block[16], iv[16]; 269#else 270 u_int8_t block[16], *iv; 271#endif 272 273 if (cipher == NULL || 274 key == NULL || 275 (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) { 276 return BAD_CIPHER_STATE; 277 } 278 if (input == NULL || inputLen <= 0) { 279 return 0; /* nothing to do */ 280 } 281 282 numBlocks = inputLen/128; 283 284 switch (cipher->mode) { 285 case MODE_ECB: 286 for (i = numBlocks; i > 0; i--) { 287 rijndaelDecrypt(key->rk, key->Nr, input, outBuffer); 288 input += 16; 289 outBuffer += 16; 290 } 291 break; 292 293 case MODE_CBC: 294#if 1 /*STRICT_ALIGN*/ 295 memcpy(iv, cipher->IV, 16); 296#else 297 iv = cipher->IV; 298#endif 299 for (i = numBlocks; i > 0; i--) { 300 rijndaelDecrypt(key->rk, key->Nr, input, block); 301 ((u_int32_t*)block)[0] ^= ((u_int32_t*)iv)[0]; 302 ((u_int32_t*)block)[1] ^= ((u_int32_t*)iv)[1]; 303 ((u_int32_t*)block)[2] ^= ((u_int32_t*)iv)[2]; 304 ((u_int32_t*)block)[3] ^= ((u_int32_t*)iv)[3]; 305#if 1 /*STRICT_ALIGN*/ 306 memcpy(iv, input, 16); 307#else 308 memcpy(cipher->IV, input, 16); 309#endif 310 memcpy(outBuffer, block, 16); 311 input += 16; 312 outBuffer += 16; 313 } 314#if 1 /*STRICT_ALIGN*/ 315 memcpy(cipher->IV, iv, 16); 316#endif 317 break; 318 319 case MODE_CFB1: 320#if 1 /*STRICT_ALIGN*/ 321 memcpy(iv, cipher->IV, 16); 322#else 323 iv = cipher->IV; 324#endif 325 for (i = numBlocks; i > 0; i--) { 326 memcpy(outBuffer, input, 16); 327 for (k = 0; k < 128; k++) { 328 rijndaelEncrypt(key->ek, key->Nr, iv, block); 329 for (t = 0; t < 15; t++) { 330 iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7); 331 } 332 iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1); 333 outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7); 334 } 335 outBuffer += 16; 336 input += 16; 337 } 338#if 1 /*STRICT_ALIGN*/ 339 memcpy(cipher->IV, iv, 16); 340#endif 341 break; 342 343 default: 344 return BAD_CIPHER_STATE; 345 } 346 347 return 128*numBlocks; 348} 349 350int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key, 351 BYTE *input, int inputOctets, BYTE *outBuffer) { 352 int i, numBlocks, padLen; 353 u_int8_t block[16]; 354 355 if (cipher == NULL || 356 key == NULL || 357 key->direction == DIR_ENCRYPT) { 358 return BAD_CIPHER_STATE; 359 } 360 if (input == NULL || inputOctets <= 0) { 361 return 0; /* nothing to do */ 362 } 363 if (inputOctets % 16 != 0) { 364 return BAD_DATA; 365 } 366 367 numBlocks = inputOctets/16; 368 369 switch (cipher->mode) { 370 case MODE_ECB: 371 /* all blocks but last */ 372 for (i = numBlocks - 1; i > 0; i--) { 373 rijndaelDecrypt(key->rk, key->Nr, input, outBuffer); 374 input += 16; 375 outBuffer += 16; 376 } 377 /* last block */ 378 rijndaelDecrypt(key->rk, key->Nr, input, block); 379 padLen = block[15]; 380 if (padLen >= 16) { 381 return BAD_DATA; 382 } 383 for (i = 16 - padLen; i < 16; i++) { 384 if (block[i] != padLen) { 385 return BAD_DATA; 386 } 387 } 388 memcpy(outBuffer, block, 16 - padLen); 389 break; 390 391 case MODE_CBC: 392 /* all blocks but last */ 393 for (i = numBlocks - 1; i > 0; i--) { 394 rijndaelDecrypt(key->rk, key->Nr, input, block); 395 ((u_int32_t*)block)[0] ^= ((u_int32_t*)cipher->IV)[0]; 396 ((u_int32_t*)block)[1] ^= ((u_int32_t*)cipher->IV)[1]; 397 ((u_int32_t*)block)[2] ^= ((u_int32_t*)cipher->IV)[2]; 398 ((u_int32_t*)block)[3] ^= ((u_int32_t*)cipher->IV)[3]; 399 memcpy(cipher->IV, input, 16); 400 memcpy(outBuffer, block, 16); 401 input += 16; 402 outBuffer += 16; 403 } 404 /* last block */ 405 rijndaelDecrypt(key->rk, key->Nr, input, block); 406 ((u_int32_t*)block)[0] ^= ((u_int32_t*)cipher->IV)[0]; 407 ((u_int32_t*)block)[1] ^= ((u_int32_t*)cipher->IV)[1]; 408 ((u_int32_t*)block)[2] ^= ((u_int32_t*)cipher->IV)[2]; 409 ((u_int32_t*)block)[3] ^= ((u_int32_t*)cipher->IV)[3]; 410 padLen = block[15]; 411 if (padLen <= 0 || padLen > 16) { 412 return BAD_DATA; 413 } 414 for (i = 16 - padLen; i < 16; i++) { 415 if (block[i] != padLen) { 416 return BAD_DATA; 417 } 418 } 419 memcpy(outBuffer, block, 16 - padLen); 420 break; 421 422 default: 423 return BAD_CIPHER_STATE; 424 } 425 426 return 16*numBlocks - padLen; 427} 428 429