1/*	$NetBSD$	*/
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
39int 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
79int 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
93int 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 */
207int 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
270int 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
368int 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 */
460int 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