1 /*	$FreeBSD: src/sys/crypto/rijndael/rijndael-api-fst.c,v 1.2.2.1 2001/07/03 11:01:35 ume Exp $	*/
2 /*	$DragonFly: src/sys/crypto/rijndael/rijndael-api-fst.c,v 1.2 2003/06/17 04:28:20 dillon Exp $	*/
3 /*	$KAME: rijndael-api-fst.c,v 1.10 2001/05/27 09:34:18 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 <sys/param.h>
21 #include <sys/types.h>
22 #ifdef _KERNEL
23 #include <sys/systm.h>
24 #else
25 #include <string.h>
26 #endif
27 #include <crypto/rijndael/rijndael-alg-fst.h>
28 #include <crypto/rijndael/rijndael-api-fst.h>
29 #include <crypto/rijndael/rijndael_local.h>
30 
31 int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) {
32 	word8 k[MAXKC][4];
33 	int i;
34 	char *keyMat;
35 
36 	if (key == NULL) {
37 		return BAD_KEY_INSTANCE;
38 	}
39 
40 	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
41 		key->direction = direction;
42 	} else {
43 		return BAD_KEY_DIR;
44 	}
45 
46 	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
47 		key->keyLen = keyLen;
48 	} else {
49 		return BAD_KEY_MAT;
50 	}
51 
52 	if (keyMaterial != NULL) {
53 		bcopy(keyMaterial, key->keyMaterial, keyLen/8);
54 	}
55 
56 	key->ROUNDS = keyLen/32 + 6;
57 
58 	/* initialize key schedule: */
59 	keyMat = key->keyMaterial;
60 	for (i = 0; i < key->keyLen/8; i++) {
61 		k[i >> 2][i & 3] = (word8)keyMat[i];
62 	}
63 	rijndaelKeySched(k, key->keySched, key->ROUNDS);
64 	if (direction == DIR_DECRYPT) {
65 		rijndaelKeyEncToDec(key->keySched, key->ROUNDS);
66 	}
67 
68 	return TRUE;
69 }
70 
71 int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
72 	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
73 		cipher->mode = mode;
74 	} else {
75 		return BAD_CIPHER_MODE;
76 	}
77 	if (IV != NULL) {
78 		bcopy(IV, cipher->IV, MAX_IV_SIZE);
79 	} else {
80 		bzero(cipher->IV, MAX_IV_SIZE);
81 	}
82 	return TRUE;
83 }
84 
85 int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
86 		BYTE *input, int inputLen, BYTE *outBuffer) {
87 	int i, k, numBlocks;
88 	word8 block[16], iv[4][4];
89 
90 	if (cipher == NULL ||
91 		key == NULL ||
92 		key->direction == DIR_DECRYPT) {
93 		return BAD_CIPHER_STATE;
94 	}
95 	if (input == NULL || inputLen <= 0) {
96 		return 0; /* nothing to do */
97 	}
98 
99 	numBlocks = inputLen/128;
100 
101 	switch (cipher->mode) {
102 	case MODE_ECB:
103 		for (i = numBlocks; i > 0; i--) {
104 			rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
105 			input += 16;
106 			outBuffer += 16;
107 		}
108 		break;
109 
110 	case MODE_CBC:
111 #if 1 /*STRICT_ALIGN*/
112 		bcopy(cipher->IV, block, 16);
113 		bcopy(input, iv, 16);
114 		((word32*)block)[0] ^= ((word32*)iv)[0];
115 		((word32*)block)[1] ^= ((word32*)iv)[1];
116 		((word32*)block)[2] ^= ((word32*)iv)[2];
117 		((word32*)block)[3] ^= ((word32*)iv)[3];
118 #else
119 		((word32*)block)[0] = ((word32*)cipher->IV)[0] ^ ((word32*)input)[0];
120 		((word32*)block)[1] = ((word32*)cipher->IV)[1] ^ ((word32*)input)[1];
121 		((word32*)block)[2] = ((word32*)cipher->IV)[2] ^ ((word32*)input)[2];
122 		((word32*)block)[3] = ((word32*)cipher->IV)[3] ^ ((word32*)input)[3];
123 #endif
124 		rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
125 		input += 16;
126 		for (i = numBlocks - 1; i > 0; i--) {
127 #if 1 /*STRICT_ALIGN*/
128 			bcopy(outBuffer, block, 16);
129 			((word32*)block)[0] ^= ((word32*)iv)[0];
130 			((word32*)block)[1] ^= ((word32*)iv)[1];
131 			((word32*)block)[2] ^= ((word32*)iv)[2];
132 			((word32*)block)[3] ^= ((word32*)iv)[3];
133 #else
134 			((word32*)block)[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0];
135 			((word32*)block)[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1];
136 			((word32*)block)[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2];
137 			((word32*)block)[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3];
138 #endif
139 			outBuffer += 16;
140 			rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
141 			input += 16;
142 		}
143 		break;
144 
145 	case MODE_CFB1:
146 #if 1 /*STRICT_ALIGN*/
147 		bcopy(cipher->IV, iv, 16);
148 #else  /* !STRICT_ALIGN */
149 		*((word32*)iv[0]) = *((word32*)(cipher->IV   ));
150 		*((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
151 		*((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
152 		*((word32*)iv[3]) = *((word32*)(cipher->IV+12));
153 #endif /* ?STRICT_ALIGN */
154 		for (i = numBlocks; i > 0; i--) {
155 			for (k = 0; k < 128; k++) {
156 				*((word32*) block    ) = *((word32*)iv[0]);
157 				*((word32*)(block+ 4)) = *((word32*)iv[1]);
158 				*((word32*)(block+ 8)) = *((word32*)iv[2]);
159 				*((word32*)(block+12)) = *((word32*)iv[3]);
160 				rijndaelEncrypt(block, block, key->keySched, key->ROUNDS);
161 				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
162 				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
163 				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
164 				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
165 				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
166 				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
167 				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
168 				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
169 				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
170 				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
171 				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
172 				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
173 				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
174 				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
175 				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
176 				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
177 				iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
178 			}
179 		}
180 		break;
181 
182 	default:
183 		return BAD_CIPHER_STATE;
184 	}
185 
186 	return 128*numBlocks;
187 }
188 
189 /**
190  * Encrypt data partitioned in octets, using RFC 2040-like padding.
191  *
192  * @param   input           data to be encrypted (octet sequence)
193  * @param   inputOctets		input length in octets (not bits)
194  * @param   outBuffer       encrypted output data
195  *
196  * @return	length in octets (not bits) of the encrypted output buffer.
197  */
198 int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
199 		BYTE *input, int inputOctets, BYTE *outBuffer) {
200 	int i, numBlocks, padLen;
201 	word8 block[16], *iv, *cp;
202 
203 	if (cipher == NULL ||
204 		key == NULL ||
205 		key->direction == DIR_DECRYPT) {
206 		return BAD_CIPHER_STATE;
207 	}
208 	if (input == NULL || inputOctets <= 0) {
209 		return 0; /* nothing to do */
210 	}
211 
212 	numBlocks = inputOctets/16;
213 
214 	switch (cipher->mode) {
215 	case MODE_ECB:
216 		for (i = numBlocks; i > 0; i--) {
217 			rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
218 			input += 16;
219 			outBuffer += 16;
220 		}
221 		padLen = 16 - (inputOctets - 16*numBlocks);
222 		if (padLen > 0 && padLen <= 16)
223 			panic("rijndael_padEncrypt(ECB)");
224 		bcopy(input, block, 16 - padLen);
225 		for (cp = block + 16 - padLen; cp < block + 16; cp++)
226 			*cp = padLen;
227 		rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
228 		break;
229 
230 	case MODE_CBC:
231 		iv = cipher->IV;
232 		for (i = numBlocks; i > 0; i--) {
233 			((word32*)block)[0] = ((word32*)input)[0] ^ ((word32*)iv)[0];
234 			((word32*)block)[1] = ((word32*)input)[1] ^ ((word32*)iv)[1];
235 			((word32*)block)[2] = ((word32*)input)[2] ^ ((word32*)iv)[2];
236 			((word32*)block)[3] = ((word32*)input)[3] ^ ((word32*)iv)[3];
237 			rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
238 			iv = outBuffer;
239 			input += 16;
240 			outBuffer += 16;
241 		}
242 		padLen = 16 - (inputOctets - 16*numBlocks);
243 		if (padLen > 0 && padLen <= 16)
244 			panic("rijndael_padEncrypt(CBC)");
245 		for (i = 0; i < 16 - padLen; i++) {
246 			block[i] = input[i] ^ iv[i];
247 		}
248 		for (i = 16 - padLen; i < 16; i++) {
249 			block[i] = (BYTE)padLen ^ iv[i];
250 		}
251 		rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
252 		break;
253 
254 	default:
255 		return BAD_CIPHER_STATE;
256 	}
257 
258 	return 16*(numBlocks + 1);
259 }
260 
261 int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
262 		BYTE *input, int inputLen, BYTE *outBuffer) {
263 	int i, k, numBlocks;
264 	word8 block[16], iv[4][4];
265 
266 	if (cipher == NULL ||
267 		key == NULL ||
268 		(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
269 		return BAD_CIPHER_STATE;
270 	}
271 	if (input == NULL || inputLen <= 0) {
272 		return 0; /* nothing to do */
273 	}
274 
275 	numBlocks = inputLen/128;
276 
277 	switch (cipher->mode) {
278 	case MODE_ECB:
279 		for (i = numBlocks; i > 0; i--) {
280 			rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
281 			input += 16;
282 			outBuffer += 16;
283 		}
284 		break;
285 
286 	case MODE_CBC:
287 #if 1 /*STRICT_ALIGN */
288 		bcopy(cipher->IV, iv, 16);
289 #else
290 		*((word32*)iv[0]) = *((word32*)(cipher->IV   ));
291 		*((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
292 		*((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
293 		*((word32*)iv[3]) = *((word32*)(cipher->IV+12));
294 #endif
295 		for (i = numBlocks; i > 0; i--) {
296 			rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
297 			((word32*)block)[0] ^= *((word32*)iv[0]);
298 			((word32*)block)[1] ^= *((word32*)iv[1]);
299 			((word32*)block)[2] ^= *((word32*)iv[2]);
300 			((word32*)block)[3] ^= *((word32*)iv[3]);
301 #if 1 /*STRICT_ALIGN*/
302 			bcopy(input, iv, 16);
303 			bcopy(block, outBuffer, 16);
304 #else
305 			*((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0];
306 			*((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1];
307 			*((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2];
308 			*((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3];
309 #endif
310 			input += 16;
311 			outBuffer += 16;
312 		}
313 		break;
314 
315 	case MODE_CFB1:
316 #if 1 /*STRICT_ALIGN */
317 		bcopy(cipher->IV, iv, 16);
318 #else
319 		*((word32*)iv[0]) = *((word32*)(cipher->IV));
320 		*((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
321 		*((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
322 		*((word32*)iv[3]) = *((word32*)(cipher->IV+12));
323 #endif
324 		for (i = numBlocks; i > 0; i--) {
325 			for (k = 0; k < 128; k++) {
326 				*((word32*) block    ) = *((word32*)iv[0]);
327 				*((word32*)(block+ 4)) = *((word32*)iv[1]);
328 				*((word32*)(block+ 8)) = *((word32*)iv[2]);
329 				*((word32*)(block+12)) = *((word32*)iv[3]);
330 				rijndaelEncrypt(block, block, key->keySched, key->ROUNDS);
331 				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
332 				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
333 				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
334 				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
335 				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
336 				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
337 				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
338 				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
339 				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
340 				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
341 				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
342 				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
343 				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
344 				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
345 				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
346 				iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
347 				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
348 			}
349 		}
350 		break;
351 
352 	default:
353 		return BAD_CIPHER_STATE;
354 	}
355 
356 	return 128*numBlocks;
357 }
358 
359 int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
360 		BYTE *input, int inputOctets, BYTE *outBuffer) {
361 	int i, numBlocks, padLen;
362 	word8 block[16];
363 	word32 iv[4];
364 
365 	if (cipher == NULL ||
366 		key == NULL ||
367 		key->direction == DIR_ENCRYPT) {
368 		return BAD_CIPHER_STATE;
369 	}
370 	if (input == NULL || inputOctets <= 0) {
371 		return 0; /* nothing to do */
372 	}
373 	if (inputOctets % 16 != 0) {
374 		return BAD_DATA;
375 	}
376 
377 	numBlocks = inputOctets/16;
378 
379 	switch (cipher->mode) {
380 	case MODE_ECB:
381 		/* all blocks but last */
382 		for (i = numBlocks - 1; i > 0; i--) {
383 			rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
384 			input += 16;
385 			outBuffer += 16;
386 		}
387 		/* last block */
388 		rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
389 		padLen = block[15];
390 		if (padLen >= 16) {
391 			return BAD_DATA;
392 		}
393 		for (i = 16 - padLen; i < 16; i++) {
394 			if (block[i] != padLen) {
395 				return BAD_DATA;
396 			}
397 		}
398 		bcopy(block, outBuffer, 16 - padLen);
399 		break;
400 
401 	case MODE_CBC:
402 		bcopy(cipher->IV, iv, 16);
403 		/* all blocks but last */
404 		for (i = numBlocks - 1; i > 0; i--) {
405 			rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
406 			((word32*)block)[0] ^= iv[0];
407 			((word32*)block)[1] ^= iv[1];
408 			((word32*)block)[2] ^= iv[2];
409 			((word32*)block)[3] ^= iv[3];
410 			bcopy(input, iv, 16);
411 			bcopy(block, outBuffer, 16);
412 			input += 16;
413 			outBuffer += 16;
414 		}
415 		/* last block */
416 		rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
417 		((word32*)block)[0] ^= iv[0];
418 		((word32*)block)[1] ^= iv[1];
419 		((word32*)block)[2] ^= iv[2];
420 		((word32*)block)[3] ^= iv[3];
421 		padLen = block[15];
422 		if (padLen <= 0 || padLen > 16) {
423 			return BAD_DATA;
424 		}
425 		for (i = 16 - padLen; i < 16; i++) {
426 			if (block[i] != padLen) {
427 				return BAD_DATA;
428 			}
429 		}
430 		bcopy(block, outBuffer, 16 - padLen);
431 		break;
432 
433 	default:
434 		return BAD_CIPHER_STATE;
435 	}
436 
437 	return 16*numBlocks - padLen;
438 }
439 
440 #ifdef INTERMEDIATE_VALUE_KAT
441 /**
442  *	cipherUpdateRounds:
443  *
444  *	Encrypts/Decrypts exactly one full block a specified number of rounds.
445  *	Only used in the Intermediate Value Known Answer Test.
446  *
447  *	Returns:
448  *		TRUE - on success
449  *		BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
450  */
451 int rijndael_cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
452 		BYTE *input, int inputLen, BYTE *outBuffer, int rounds) {
453 	int j;
454 	word8 block[4][4];
455 
456 	if (cipher == NULL || key == NULL) {
457 		return BAD_CIPHER_STATE;
458 	}
459 
460 	for (j = 3; j >= 0; j--) {
461 		/* parse input stream into rectangular array */
462   		*((word32*)block[j]) = *((word32*)(input+4*j));
463 	}
464 
465 	switch (key->direction) {
466 	case DIR_ENCRYPT:
467 		rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds);
468 		break;
469 
470 	case DIR_DECRYPT:
471 		rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds);
472 		break;
473 
474 	default:
475 		return BAD_KEY_DIR;
476 	}
477 
478 	for (j = 3; j >= 0; j--) {
479 		/* parse rectangular array into output ciphertext bytes */
480 		*((word32*)(outBuffer+4*j)) = *((word32*)block[j]);
481 	}
482 
483 	return TRUE;
484 }
485 #endif /* INTERMEDIATE_VALUE_KAT */
486