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