Annotation of embedaddon/ipsec-tools/src/racoon/missing/crypto/rijndael/rijndael-api-fst.c, revision 1.1
1.1 ! misho 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 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>