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