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