Home | History | Annotate | Download | only in rijndael
      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