1 /*	$NetBSD: rijndael-api-fst.c,v 1.24 2011/05/14 16:46:55 jmmv Exp $	*/
2 
3 /**
4  * rijndael-api-fst.c
5  *
6  * @version 2.9 (December 2000)
7  *
8  * Optimised ANSI C code for the Rijndael cipher (now AES)
9  *
10  * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
11  * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
12  * @author Paulo Barreto <paulo.barreto@terra.com.br>
13  *
14  * This code is hereby placed in the public domain.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * Acknowledgements:
29  *
30  * We are deeply indebted to the following people for their bug reports,
31  * fixes, and improvement suggestions to this implementation. Though we
32  * tried to list all contributions, we apologise in advance for any
33  * missing reference.
34  *
35  * Andrew Bales <Andrew.Bales@Honeywell.com>
36  * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
37  * John Skodon <skodonj@webquill.com>
38  */
39 
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: rijndael-api-fst.c,v 1.24 2011/05/14 16:46:55 jmmv Exp $");
42 
43 #include <sys/param.h>
44 #ifdef _KERNEL
45 #include <sys/systm.h>
46 #else
47 #include <stdlib.h>
48 #include <string.h>
49 #endif
50 
51 #include <crypto/rijndael/rijndael_local.h>
52 #include <crypto/rijndael/rijndael-alg-fst.h>
53 #include <crypto/rijndael/rijndael-api-fst.h>
54 
xor16(uint8_t * d,const uint8_t * a,const uint8_t * b)55 static void xor16(uint8_t *d, const uint8_t *a, const uint8_t* b)
56 {
57 	for (size_t i = 0; i < 4; i++) {
58 		*d++ = *a++ ^ *b++;
59 		*d++ = *a++ ^ *b++;
60 		*d++ = *a++ ^ *b++;
61 		*d++ = *a++ ^ *b++;
62 	}
63 }
64 
65 int
rijndael_makeKey(keyInstance * key,BYTE direction,int keyLen,const char * keyMaterial)66 rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen,
67     const char *keyMaterial)
68 {
69 	u_int8_t cipherKey[RIJNDAEL_MAXKB];
70 
71 	if (key == NULL) {
72 		return BAD_KEY_INSTANCE;
73 	}
74 
75 	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
76 		key->direction = direction;
77 	} else {
78 		return BAD_KEY_DIR;
79 	}
80 
81 	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
82 		key->keyLen = keyLen;
83 	} else {
84 		return BAD_KEY_MAT;
85 	}
86 
87 	if (keyMaterial != NULL) {
88 		memcpy(key->keyMaterial, keyMaterial, keyLen/8);
89 	}
90 
91 	/* initialize key schedule: */
92 	memcpy(cipherKey, key->keyMaterial, keyLen/8);
93 	if (direction == DIR_ENCRYPT) {
94 		key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
95 	} else {
96 		key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
97 	}
98 	rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
99 	return TRUE;
100 }
101 
102 int
rijndael_cipherInit(cipherInstance * cipher,BYTE mode,const char * IV)103 rijndael_cipherInit(cipherInstance *cipher, BYTE mode, const char *IV)
104 {
105 	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
106 		cipher->mode = mode;
107 	} else {
108 		return BAD_CIPHER_MODE;
109 	}
110 	if (IV != NULL) {
111 		memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE);
112 	} else {
113 		memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
114 	}
115 	return TRUE;
116 }
117 
118 int
rijndael_blockEncrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputLen,BYTE * outBuffer)119 rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
120     const BYTE *input, int inputLen, BYTE *outBuffer)
121 {
122 	int i, k, t, numBlocks;
123 	u_int8_t block[16], *iv;
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(key->rk, key->Nr, input, outBuffer);
140 			input += 16;
141 			outBuffer += 16;
142 		}
143 		break;
144 
145 	case MODE_CBC:
146 		iv = (u_int8_t *)cipher->IV;
147 		for (i = numBlocks; i > 0; i--) {
148 			xor16(block, input, iv);
149 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
150 			iv = outBuffer;
151 			input += 16;
152 			outBuffer += 16;
153 		}
154 		break;
155 
156 	case MODE_CFB1:
157 		iv = (u_int8_t *)cipher->IV;
158 		for (i = numBlocks; i > 0; i--) {
159 			memcpy(outBuffer, input, 16);
160 			for (k = 0; k < 128; k++) {
161 				rijndaelEncrypt(key->ek, key->Nr, iv, block);
162 				outBuffer[k >> 3] ^=
163 				    (block[0] & 0x80U) >> (k & 7);
164 				for (t = 0; t < 15; t++) {
165 					iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
166 				}
167 				iv[15] = (iv[15] << 1) |
168 				    ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
169 			}
170 			outBuffer += 16;
171 			input += 16;
172 		}
173 		break;
174 
175 	default:
176 		return BAD_CIPHER_STATE;
177 	}
178 
179 	return 128 * numBlocks;
180 }
181 
182 /**
183  * Encrypt data partitioned in octets, using RFC 2040-like padding.
184  *
185  * @param   input           data to be encrypted (octet sequence)
186  * @param   inputOctets		input length in octets (not bits)
187  * @param   outBuffer       encrypted output data
188  *
189  * @return	length in octets (not bits) of the encrypted output buffer.
190  */
191 int
rijndael_padEncrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputOctets,BYTE * outBuffer)192 rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
193     const BYTE *input, int inputOctets, BYTE *outBuffer)
194 {
195 	int i, numBlocks, padLen;
196 	u_int8_t block[16], *iv;
197 
198 	if (cipher == NULL ||
199 		key == NULL ||
200 		key->direction == DIR_DECRYPT) {
201 		return BAD_CIPHER_STATE;
202 	}
203 	if (input == NULL || inputOctets <= 0) {
204 		return 0; /* nothing to do */
205 	}
206 
207 	numBlocks = inputOctets / 16;
208 
209 	switch (cipher->mode) {
210 	case MODE_ECB:
211 		for (i = numBlocks; i > 0; i--) {
212 			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
213 			input += 16;
214 			outBuffer += 16;
215 		}
216 		padLen = 16 - (inputOctets - 16*numBlocks);
217 		memcpy(block, input, 16 - padLen);
218 		memset(block + 16 - padLen, padLen, padLen);
219 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
220 		break;
221 
222 	case MODE_CBC:
223 		iv = (u_int8_t *)cipher->IV;
224 		for (i = numBlocks; i > 0; i--) {
225 			xor16(block, input, iv);
226 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
227 			iv = outBuffer;
228 			input += 16;
229 			outBuffer += 16;
230 		}
231 		padLen = 16 - (inputOctets - 16*numBlocks);
232 		for (i = 0; i < 16 - padLen; i++) {
233 			block[i] = input[i] ^ iv[i];
234 		}
235 		for (i = 16 - padLen; i < 16; i++) {
236 			block[i] = (BYTE)padLen ^ iv[i];
237 		}
238 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
239 		break;
240 
241 	default:
242 		return BAD_CIPHER_STATE;
243 	}
244 
245 	return 16 * (numBlocks + 1);
246 }
247 
248 int
rijndael_blockDecrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputLen,BYTE * outBuffer)249 rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
250     const BYTE *input, int inputLen, BYTE *outBuffer)
251 {
252 	int i, k, t, numBlocks;
253 	u_int8_t block[16], *iv;
254 
255 	if (cipher == NULL ||
256 		key == NULL ||
257 		(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
258 		return BAD_CIPHER_STATE;
259 	}
260 	if (input == NULL || inputLen <= 0) {
261 		return 0; /* nothing to do */
262 	}
263 
264 	numBlocks = inputLen/128;
265 
266 	switch (cipher->mode) {
267 	case MODE_ECB:
268 		for (i = numBlocks; i > 0; i--) {
269 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
270 			input += 16;
271 			outBuffer += 16;
272 		}
273 		break;
274 
275 	case MODE_CBC:
276 		iv = (u_int8_t *)cipher->IV;
277 		for (i = numBlocks; i > 0; i--) {
278 			rijndaelDecrypt(key->rk, key->Nr, input, block);
279 			xor16(block, block, iv);
280 			memcpy(cipher->IV, input, 16);
281 			memcpy(outBuffer, block, 16);
282 			input += 16;
283 			outBuffer += 16;
284 		}
285 		break;
286 
287     case MODE_CFB1:
288 		iv = (u_int8_t *)cipher->IV;
289 		for (i = numBlocks; i > 0; i--) {
290 			memcpy(outBuffer, input, 16);
291 			for (k = 0; k < 128; k++) {
292 				rijndaelEncrypt(key->ek, key->Nr, iv, block);
293 				for (t = 0; t < 15; t++) {
294 					iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
295 				}
296 				iv[15] = (iv[15] << 1) |
297 				    ((input[k >> 3] >> (7 - (k & 7))) & 1);
298 				outBuffer[k >> 3] ^= (block[0] & 0x80U) >>
299 				    (k & 7);
300 			}
301 			outBuffer += 16;
302 			input += 16;
303 		}
304 		break;
305 
306 	default:
307 		return BAD_CIPHER_STATE;
308 	}
309 
310 	return 128 * numBlocks;
311 }
312 
313 int
rijndael_padDecrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputOctets,BYTE * outBuffer)314 rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
315     const BYTE *input, int inputOctets, BYTE *outBuffer)
316 {
317 	int i, numBlocks, padLen;
318 	u_int8_t block[16], *iv;
319 
320 	if (cipher == NULL ||
321 		key == NULL ||
322 		key->direction == DIR_ENCRYPT) {
323 		return BAD_CIPHER_STATE;
324 	}
325 	if (input == NULL || inputOctets <= 0) {
326 		return 0; /* nothing to do */
327 	}
328 	if (inputOctets % 16 != 0) {
329 		return BAD_DATA;
330 	}
331 
332 	numBlocks = inputOctets/16;
333 
334 	switch (cipher->mode) {
335 	case MODE_ECB:
336 		/* all blocks but last */
337 		for (i = numBlocks - 1; i > 0; i--) {
338 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
339 			input += 16;
340 			outBuffer += 16;
341 		}
342 		/* last block */
343 		rijndaelDecrypt(key->rk, key->Nr, input, block);
344 		padLen = block[15];
345 		if (padLen >= 16) {
346 			return BAD_DATA;
347 		}
348 		for (i = 16 - padLen; i < 16; i++) {
349 			if (block[i] != padLen) {
350 				return BAD_DATA;
351 			}
352 		}
353 		memcpy(outBuffer, block, 16 - padLen);
354 		break;
355 
356 	case MODE_CBC:
357 		iv = (u_int8_t *)cipher->IV;
358 		/* all blocks but last */
359 		for (i = numBlocks - 1; i > 0; i--) {
360 			rijndaelDecrypt(key->rk, key->Nr, input, block);
361 			xor16(block, block, iv);
362 			memcpy(cipher->IV, input, 16);
363 			memcpy(outBuffer, block, 16);
364 			input += 16;
365 			outBuffer += 16;
366 		}
367 		/* last block */
368 		rijndaelDecrypt(key->rk, key->Nr, input, block);
369 		xor16(block, block, iv);
370 		padLen = block[15];
371 		if (padLen <= 0 || padLen > 16) {
372 			return BAD_DATA;
373 		}
374 		for (i = 16 - padLen; i < 16; i++) {
375 			if (block[i] != padLen) {
376 				return BAD_DATA;
377 			}
378 		}
379 		memcpy(outBuffer, block, 16 - padLen);
380 		break;
381 
382 	default:
383 		return BAD_CIPHER_STATE;
384 	}
385 
386 	return 16 * numBlocks - padLen;
387 }
388