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