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