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