xref: /freebsd/sys/crypto/rijndael/rijndael-api-fst.c (revision 9aaf4e3be61fc20a84347b7c2c524256a4b93a43)
1 /*	$KAME: rijndael-api-fst.c,v 1.10 2001/05/27 09:34:18 itojun Exp $	*/
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 #ifdef _KERNEL
20 #include <sys/systm.h>
21 #else
22 #include <string.h>
23 #endif
24 
25 #include <crypto/rijndael/rijndael_local.h>
26 #include <crypto/rijndael/rijndael-api-fst.h>
27 
28 #ifndef TRUE
29 #define TRUE 1
30 #endif
31 
32 typedef uint8_t	BYTE;
33 
34 int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen,
35 	const char *keyMaterial) {
36 
37 	if (key == NULL) {
38 		return BAD_KEY_INSTANCE;
39 	}
40 
41 	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
42 		key->direction = direction;
43 	} else {
44 		return BAD_KEY_DIR;
45 	}
46 
47 	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
48 		key->keyLen = keyLen;
49 	} else {
50 		return BAD_KEY_MAT;
51 	}
52 
53 	if (keyMaterial != NULL) {
54 		memcpy(key->keyMaterial, keyMaterial, keyLen/8);
55 	}
56 
57 	/* initialize key schedule: */
58 	if (direction == DIR_ENCRYPT) {
59 		key->Nr = rijndaelKeySetupEnc(key->rk, key->keyMaterial, keyLen);
60 	} else {
61 		key->Nr = rijndaelKeySetupDec(key->rk, key->keyMaterial, keyLen);
62 	}
63 	rijndaelKeySetupEnc(key->ek, key->keyMaterial, keyLen);
64 	return TRUE;
65 }
66 
67 int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
68 	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
69 		cipher->mode = mode;
70 	} else {
71 		return BAD_CIPHER_MODE;
72 	}
73 	if (IV != NULL) {
74 		memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE);
75 	} else {
76 		memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
77 	}
78 	return TRUE;
79 }
80 
81 int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
82 		const BYTE *input, int inputLen, BYTE *outBuffer) {
83 	int i, k, numBlocks;
84 	uint8_t block[16], iv[4][4];
85 
86 	if (cipher == NULL ||
87 		key == NULL ||
88 		key->direction == DIR_DECRYPT) {
89 		return BAD_CIPHER_STATE;
90 	}
91 	if (input == NULL || inputLen <= 0) {
92 		return 0; /* nothing to do */
93 	}
94 
95 	numBlocks = inputLen/128;
96 
97 	switch (cipher->mode) {
98 	case MODE_ECB:
99 		for (i = numBlocks; i > 0; i--) {
100 			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
101 			input += 16;
102 			outBuffer += 16;
103 		}
104 		break;
105 
106 	case MODE_CBC:
107 #if 1 /*STRICT_ALIGN*/
108 		memcpy(block, cipher->IV, 16);
109 		memcpy(iv, input, 16);
110 		((uint32_t*)block)[0] ^= ((uint32_t*)iv)[0];
111 		((uint32_t*)block)[1] ^= ((uint32_t*)iv)[1];
112 		((uint32_t*)block)[2] ^= ((uint32_t*)iv)[2];
113 		((uint32_t*)block)[3] ^= ((uint32_t*)iv)[3];
114 #else
115 		((uint32_t*)block)[0] = ((uint32_t*)cipher->IV)[0] ^ ((uint32_t*)input)[0];
116 		((uint32_t*)block)[1] = ((uint32_t*)cipher->IV)[1] ^ ((uint32_t*)input)[1];
117 		((uint32_t*)block)[2] = ((uint32_t*)cipher->IV)[2] ^ ((uint32_t*)input)[2];
118 		((uint32_t*)block)[3] = ((uint32_t*)cipher->IV)[3] ^ ((uint32_t*)input)[3];
119 #endif
120 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
121 		input += 16;
122 		for (i = numBlocks - 1; i > 0; i--) {
123 #if 1 /*STRICT_ALIGN*/
124 			memcpy(block, outBuffer, 16);
125 			memcpy(iv, input, 16);
126 			((uint32_t*)block)[0] ^= ((uint32_t*)iv)[0];
127 			((uint32_t*)block)[1] ^= ((uint32_t*)iv)[1];
128 			((uint32_t*)block)[2] ^= ((uint32_t*)iv)[2];
129 			((uint32_t*)block)[3] ^= ((uint32_t*)iv)[3];
130 #else
131 			((uint32_t*)block)[0] = ((uint32_t*)outBuffer)[0] ^ ((uint32_t*)input)[0];
132 			((uint32_t*)block)[1] = ((uint32_t*)outBuffer)[1] ^ ((uint32_t*)input)[1];
133 			((uint32_t*)block)[2] = ((uint32_t*)outBuffer)[2] ^ ((uint32_t*)input)[2];
134 			((uint32_t*)block)[3] = ((uint32_t*)outBuffer)[3] ^ ((uint32_t*)input)[3];
135 #endif
136 			outBuffer += 16;
137 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
138 			input += 16;
139 		}
140 		break;
141 
142 	case MODE_CFB1:
143 #if 1 /*STRICT_ALIGN*/
144 		memcpy(iv, cipher->IV, 16);
145 #else  /* !STRICT_ALIGN */
146 		*((uint32_t*)iv[0]) = *((uint32_t*)(cipher->IV   ));
147 		*((uint32_t*)iv[1]) = *((uint32_t*)(cipher->IV+ 4));
148 		*((uint32_t*)iv[2]) = *((uint32_t*)(cipher->IV+ 8));
149 		*((uint32_t*)iv[3]) = *((uint32_t*)(cipher->IV+12));
150 #endif /* ?STRICT_ALIGN */
151 		for (i = numBlocks; i > 0; i--) {
152 			for (k = 0; k < 128; k++) {
153 				*((uint32_t*) block    ) = *((uint32_t*)iv[0]);
154 				*((uint32_t*)(block+ 4)) = *((uint32_t*)iv[1]);
155 				*((uint32_t*)(block+ 8)) = *((uint32_t*)iv[2]);
156 				*((uint32_t*)(block+12)) = *((uint32_t*)iv[3]);
157 				rijndaelEncrypt(key->ek, key->Nr, block,
158 				    block);
159 				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
160 				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
161 				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
162 				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
163 				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
164 				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
165 				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
166 				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
167 				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
168 				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
169 				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
170 				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
171 				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
172 				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
173 				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
174 				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
175 				iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
176 			}
177 		}
178 		break;
179 
180 	default:
181 		return BAD_CIPHER_STATE;
182 	}
183 
184 	explicit_bzero(block, sizeof(block));
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 		const BYTE *input, int inputOctets, BYTE *outBuffer) {
199 	int i, numBlocks, padLen;
200 	uint8_t 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(key->rk, key->Nr, input, outBuffer);
217 			input += 16;
218 			outBuffer += 16;
219 		}
220 		padLen = 16 - (inputOctets - 16*numBlocks);
221 		if (padLen <= 0 || padLen > 16)
222 			return BAD_CIPHER_STATE;
223 		memcpy(block, input, 16 - padLen);
224 		for (cp = block + 16 - padLen; cp < block + 16; cp++)
225 			*cp = padLen;
226 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
227 		break;
228 
229 	case MODE_CBC:
230 		iv = cipher->IV;
231 		for (i = numBlocks; i > 0; i--) {
232 			((uint32_t*)block)[0] = ((const uint32_t*)input)[0] ^ ((uint32_t*)iv)[0];
233 			((uint32_t*)block)[1] = ((const uint32_t*)input)[1] ^ ((uint32_t*)iv)[1];
234 			((uint32_t*)block)[2] = ((const uint32_t*)input)[2] ^ ((uint32_t*)iv)[2];
235 			((uint32_t*)block)[3] = ((const uint32_t*)input)[3] ^ ((uint32_t*)iv)[3];
236 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
237 			iv = outBuffer;
238 			input += 16;
239 			outBuffer += 16;
240 		}
241 		padLen = 16 - (inputOctets - 16*numBlocks);
242 		if (padLen <= 0 || padLen > 16)
243 			return BAD_CIPHER_STATE;
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(key->rk, key->Nr, block, outBuffer);
251 		break;
252 
253 	default:
254 		return BAD_CIPHER_STATE;
255 	}
256 
257 	explicit_bzero(block, sizeof(block));
258 	return 16*(numBlocks + 1);
259 }
260 
261 int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
262 		const BYTE *input, int inputLen, BYTE *outBuffer) {
263 	int i, k, numBlocks;
264 	uint8_t 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(key->rk, key->Nr, input, outBuffer);
281 			input += 16;
282 			outBuffer += 16;
283 		}
284 		break;
285 
286 	case MODE_CBC:
287 #if 1 /*STRICT_ALIGN */
288 		memcpy(iv, cipher->IV, 16);
289 #else
290 		*((uint32_t*)iv[0]) = *((uint32_t*)(cipher->IV   ));
291 		*((uint32_t*)iv[1]) = *((uint32_t*)(cipher->IV+ 4));
292 		*((uint32_t*)iv[2]) = *((uint32_t*)(cipher->IV+ 8));
293 		*((uint32_t*)iv[3]) = *((uint32_t*)(cipher->IV+12));
294 #endif
295 		for (i = numBlocks; i > 0; i--) {
296 			rijndaelDecrypt(key->rk, key->Nr, input, block);
297 			((uint32_t*)block)[0] ^= *((uint32_t*)iv[0]);
298 			((uint32_t*)block)[1] ^= *((uint32_t*)iv[1]);
299 			((uint32_t*)block)[2] ^= *((uint32_t*)iv[2]);
300 			((uint32_t*)block)[3] ^= *((uint32_t*)iv[3]);
301 #if 1 /*STRICT_ALIGN*/
302 			memcpy(iv, input, 16);
303 			memcpy(outBuffer, block, 16);
304 #else
305 			*((uint32_t*)iv[0]) = ((uint32_t*)input)[0]; ((uint32_t*)outBuffer)[0] = ((uint32_t*)block)[0];
306 			*((uint32_t*)iv[1]) = ((uint32_t*)input)[1]; ((uint32_t*)outBuffer)[1] = ((uint32_t*)block)[1];
307 			*((uint32_t*)iv[2]) = ((uint32_t*)input)[2]; ((uint32_t*)outBuffer)[2] = ((uint32_t*)block)[2];
308 			*((uint32_t*)iv[3]) = ((uint32_t*)input)[3]; ((uint32_t*)outBuffer)[3] = ((uint32_t*)block)[3];
309 #endif
310 			input += 16;
311 			outBuffer += 16;
312 		}
313 		break;
314 
315 	case MODE_CFB1:
316 #if 1 /*STRICT_ALIGN */
317 		memcpy(iv, cipher->IV, 16);
318 #else
319 		*((uint32_t*)iv[0]) = *((uint32_t*)(cipher->IV));
320 		*((uint32_t*)iv[1]) = *((uint32_t*)(cipher->IV+ 4));
321 		*((uint32_t*)iv[2]) = *((uint32_t*)(cipher->IV+ 8));
322 		*((uint32_t*)iv[3]) = *((uint32_t*)(cipher->IV+12));
323 #endif
324 		for (i = numBlocks; i > 0; i--) {
325 			for (k = 0; k < 128; k++) {
326 				*((uint32_t*) block    ) = *((uint32_t*)iv[0]);
327 				*((uint32_t*)(block+ 4)) = *((uint32_t*)iv[1]);
328 				*((uint32_t*)(block+ 8)) = *((uint32_t*)iv[2]);
329 				*((uint32_t*)(block+12)) = *((uint32_t*)iv[3]);
330 				rijndaelEncrypt(key->ek, key->Nr, block,
331 				    block);
332 				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
333 				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
334 				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
335 				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
336 				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
337 				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
338 				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
339 				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
340 				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
341 				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
342 				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
343 				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
344 				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
345 				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
346 				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
347 				iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
348 				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
349 			}
350 		}
351 		break;
352 
353 	default:
354 		return BAD_CIPHER_STATE;
355 	}
356 
357 	explicit_bzero(block, sizeof(block));
358 	return 128*numBlocks;
359 }
360 
361 int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
362 		const BYTE *input, int inputOctets, BYTE *outBuffer) {
363 	int i, numBlocks, padLen, rval;
364 	uint8_t block[16];
365 	uint32_t iv[4];
366 
367 	if (cipher == NULL ||
368 		key == NULL ||
369 		key->direction == DIR_ENCRYPT) {
370 		return BAD_CIPHER_STATE;
371 	}
372 	if (input == NULL || inputOctets <= 0) {
373 		return 0; /* nothing to do */
374 	}
375 	if (inputOctets % 16 != 0) {
376 		return BAD_DATA;
377 	}
378 
379 	numBlocks = inputOctets/16;
380 
381 	switch (cipher->mode) {
382 	case MODE_ECB:
383 		/* all blocks but last */
384 		for (i = numBlocks - 1; i > 0; i--) {
385 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
386 			input += 16;
387 			outBuffer += 16;
388 		}
389 		/* last block */
390 		rijndaelDecrypt(key->rk, key->Nr, input, block);
391 		padLen = block[15];
392 		if (padLen >= 16) {
393 			rval = BAD_DATA;
394 			goto out;
395 		}
396 		for (i = 16 - padLen; i < 16; i++) {
397 			if (block[i] != padLen) {
398 				rval = BAD_DATA;
399 				goto out;
400 			}
401 		}
402 		memcpy(outBuffer, block, 16 - padLen);
403 		break;
404 
405 	case MODE_CBC:
406 		memcpy(iv, cipher->IV, 16);
407 		/* all blocks but last */
408 		for (i = numBlocks - 1; i > 0; i--) {
409 			rijndaelDecrypt(key->rk, key->Nr, input, block);
410 			((uint32_t*)block)[0] ^= iv[0];
411 			((uint32_t*)block)[1] ^= iv[1];
412 			((uint32_t*)block)[2] ^= iv[2];
413 			((uint32_t*)block)[3] ^= iv[3];
414 			memcpy(iv, input, 16);
415 			memcpy(outBuffer, block, 16);
416 			input += 16;
417 			outBuffer += 16;
418 		}
419 		/* last block */
420 		rijndaelDecrypt(key->rk, key->Nr, input, block);
421 		((uint32_t*)block)[0] ^= iv[0];
422 		((uint32_t*)block)[1] ^= iv[1];
423 		((uint32_t*)block)[2] ^= iv[2];
424 		((uint32_t*)block)[3] ^= iv[3];
425 		padLen = block[15];
426 		if (padLen <= 0 || padLen > 16) {
427 			rval = BAD_DATA;
428 			goto out;
429 		}
430 		for (i = 16 - padLen; i < 16; i++) {
431 			if (block[i] != padLen) {
432 				rval = BAD_DATA;
433 				goto out;
434 			}
435 		}
436 		memcpy(outBuffer, block, 16 - padLen);
437 		break;
438 
439 	default:
440 		return BAD_CIPHER_STATE;
441 	}
442 
443 	rval = 16*numBlocks - padLen;
444 
445 out:
446 	explicit_bzero(block, sizeof(block));
447 	return rval;
448 }
449