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 #include "config_xor.h"
40 
41 #include <stdlib.h>
42 #include <string.h>
43 
44 
45 #ifdef SH_ENCRYPT
46 
47 #include "rijndael-api-fst.h"
48 
xor16(u8 * d,const u8 * a,const u8 * b)49 static void xor16(u8 *d, const u8 *a, const u8* b)
50 {
51   size_t i;
52 
53 	for (i = 0; i < 4; i++) {
54 		*d++ = *a++ ^ *b++;
55 		*d++ = *a++ ^ *b++;
56 		*d++ = *a++ ^ *b++;
57 		*d++ = *a++ ^ *b++;
58 	}
59 }
60 
61 int
rijndael_makeKey(keyInstance * key,BYTE direction,int keyLen,const char * keyMaterial)62 rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen,
63     const char *keyMaterial)
64 {
65 	u8 cipherKey[RIJNDAEL_MAXKB];
66 	int i;
67 
68 	if (key == NULL) {
69 		return BAD_KEY_INSTANCE;
70 	}
71 
72 	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
73 		key->direction = direction;
74 	} else {
75 		return BAD_KEY_DIR;
76 	}
77 
78 	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
79 		key->keyLen = keyLen;
80 	} else {
81 		return BAD_KEY_MAT;
82 	}
83 
84 	if (keyMaterial != NULL) {
85 	        char temp[RIJNDAEL_MAX_KEY_SIZE];
86 		for (i = 0; i < key->keyLen/8; i++) {
87 		  int t, j;
88 
89 		  t = *keyMaterial++;
90 		  if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
91 		  else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
92 		  else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
93 		  else return BAD_KEY_MAT;
94 
95 		  t = *keyMaterial++;
96 		  if ((t >= '0') && (t <= '9')) j ^= (t - '0');
97 		  else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
98 		  else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
99 		  else return BAD_KEY_MAT;
100 
101 		  temp[i] = (u8)j;
102 		}
103 
104 		/* memcpy(key->keyMaterial, keyMaterial, keyLen/8); */
105 		memcpy(key->keyMaterial, temp, keyLen/8);
106 	}
107 
108 	/* initialize key schedule: */
109 	memcpy(cipherKey, key->keyMaterial, keyLen/8);
110 	if (direction == DIR_ENCRYPT) {
111 		key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
112 	} else {
113 		key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
114 	}
115 	rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
116 	return TRUE;
117 }
118 
119 int
rijndael_cipherInit(cipherInstance * cipher,BYTE mode,const char * IV)120 rijndael_cipherInit(cipherInstance *cipher, BYTE mode, const char *IV)
121 {
122 	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
123 		cipher->mode = mode;
124 	} else {
125 		return BAD_CIPHER_MODE;
126 	}
127 	if (IV != NULL) {
128 		memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE);
129 	} else {
130 		memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
131 	}
132 	return TRUE;
133 }
134 
135 int
rijndael_blockEncrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputLen,BYTE * outBuffer)136 rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
137     const BYTE *input, int inputLen, BYTE *outBuffer)
138 {
139 	int i, k, t, numBlocks;
140 	u8 block[16], *iv;
141 
142 	if (cipher == NULL ||
143 		key == NULL ||
144 		key->direction == DIR_DECRYPT) {
145 		return BAD_CIPHER_STATE;
146 	}
147 	if (input == NULL || inputLen <= 0) {
148 		return 0; /* nothing to do */
149 	}
150 
151 	numBlocks = inputLen/128;
152 
153 	switch (cipher->mode) {
154 	case MODE_ECB:
155 		for (i = numBlocks; i > 0; i--) {
156 			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
157 			input += 16;
158 			outBuffer += 16;
159 		}
160 		break;
161 
162 	case MODE_CBC:
163 		iv = (u8 *)cipher->IV;
164 		for (i = numBlocks; i > 0; i--) {
165 			xor16(block, input, iv);
166 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
167 			iv = outBuffer;
168 			input += 16;
169 			outBuffer += 16;
170 		}
171 		break;
172 
173 	case MODE_CFB1:
174 		iv = (u8 *)cipher->IV;
175 		for (i = numBlocks; i > 0; i--) {
176 			memcpy(outBuffer, input, 16);
177 			for (k = 0; k < 128; k++) {
178 				rijndaelEncrypt(key->ek, key->Nr, iv, block);
179 				outBuffer[k >> 3] ^=
180 				    (block[0] & 0x80U) >> (k & 7);
181 				for (t = 0; t < 15; t++) {
182 					iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
183 				}
184 				iv[15] = (iv[15] << 1) |
185 				    ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
186 			}
187 			outBuffer += 16;
188 			input += 16;
189 		}
190 		break;
191 
192 	default:
193 		return BAD_CIPHER_STATE;
194 	}
195 
196 	return 128 * numBlocks;
197 }
198 
199 /**
200  * Encrypt data partitioned in octets, using RFC 2040-like padding.
201  *
202  * @param   input           data to be encrypted (octet sequence)
203  * @param   inputOctets		input length in octets (not bits)
204  * @param   outBuffer       encrypted output data
205  *
206  * @return	length in octets (not bits) of the encrypted output buffer.
207  */
208 int
rijndael_padEncrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputOctets,BYTE * outBuffer)209 rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
210     const BYTE *input, int inputOctets, BYTE *outBuffer)
211 {
212 	int i, numBlocks, padLen;
213 	u8 block[16], *iv;
214 
215 	if (cipher == NULL ||
216 		key == NULL ||
217 		key->direction == DIR_DECRYPT) {
218 		return BAD_CIPHER_STATE;
219 	}
220 	if (input == NULL || inputOctets <= 0) {
221 		return 0; /* nothing to do */
222 	}
223 
224 	numBlocks = inputOctets / 16;
225 
226 	switch (cipher->mode) {
227 	case MODE_ECB:
228 		for (i = numBlocks; i > 0; i--) {
229 			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
230 			input += 16;
231 			outBuffer += 16;
232 		}
233 		padLen = 16 - (inputOctets - 16*numBlocks);
234 		memcpy(block, input, 16 - padLen);
235 		memset(block + 16 - padLen, padLen, padLen);
236 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
237 		break;
238 
239 	case MODE_CBC:
240 		iv = (u8 *)cipher->IV;
241 		for (i = numBlocks; i > 0; i--) {
242 			xor16(block, input, iv);
243 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
244 			iv = outBuffer;
245 			input += 16;
246 			outBuffer += 16;
247 		}
248 		padLen = 16 - (inputOctets - 16*numBlocks);
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(key->rk, key->Nr, block, outBuffer);
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,const BYTE * input,int inputLen,BYTE * outBuffer)266 rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
267     const BYTE *input, int inputLen, BYTE *outBuffer)
268 {
269 	int i, k, t, numBlocks;
270 	u8 block[16], *iv;
271 
272 	if (cipher == NULL ||
273 		key == NULL ||
274 		(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
275 		return BAD_CIPHER_STATE;
276 	}
277 	if (input == NULL || inputLen <= 0) {
278 		return 0; /* nothing to do */
279 	}
280 
281 	numBlocks = inputLen/128;
282 
283 	switch (cipher->mode) {
284 	case MODE_ECB:
285 		for (i = numBlocks; i > 0; i--) {
286 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
287 			input += 16;
288 			outBuffer += 16;
289 		}
290 		break;
291 
292 	case MODE_CBC:
293 		iv = (u8 *)cipher->IV;
294 		for (i = numBlocks; i > 0; i--) {
295 			rijndaelDecrypt(key->rk, key->Nr, input, block);
296 			xor16(block, block, iv);
297 			if (numBlocks > 1)
298 			  memcpy(cipher->IV, input, 16);
299 			memcpy(outBuffer, block, 16);
300 			input += 16;
301 			outBuffer += 16;
302 		}
303 		break;
304 
305     case MODE_CFB1:
306 		iv = (u8 *)cipher->IV;
307 		for (i = numBlocks; i > 0; i--) {
308 			memcpy(outBuffer, input, 16);
309 			for (k = 0; k < 128; k++) {
310 				rijndaelEncrypt(key->ek, key->Nr, iv, block);
311 				for (t = 0; t < 15; t++) {
312 					iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
313 				}
314 				iv[15] = (iv[15] << 1) |
315 				    ((input[k >> 3] >> (7 - (k & 7))) & 1);
316 				outBuffer[k >> 3] ^= (block[0] & 0x80U) >>
317 				    (k & 7);
318 			}
319 			outBuffer += 16;
320 			input += 16;
321 		}
322 		break;
323 
324 	default:
325 		return BAD_CIPHER_STATE;
326 	}
327 
328 	return 128 * numBlocks;
329 }
330 
331 int
rijndael_padDecrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputOctets,BYTE * outBuffer)332 rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
333     const BYTE *input, int inputOctets, BYTE *outBuffer)
334 {
335 	int i, numBlocks, padLen;
336 	u8 block[16], *iv;
337 
338 	if (cipher == NULL ||
339 		key == NULL ||
340 		key->direction == DIR_ENCRYPT) {
341 		return BAD_CIPHER_STATE;
342 	}
343 	if (input == NULL || inputOctets <= 0) {
344 		return 0; /* nothing to do */
345 	}
346 	if (inputOctets % 16 != 0) {
347 		return BAD_DATA;
348 	}
349 
350 	numBlocks = inputOctets/16;
351 
352 	switch (cipher->mode) {
353 	case MODE_ECB:
354 		/* all blocks but last */
355 		for (i = numBlocks - 1; i > 0; i--) {
356 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
357 			input += 16;
358 			outBuffer += 16;
359 		}
360 		/* last block */
361 		rijndaelDecrypt(key->rk, key->Nr, input, block);
362 		padLen = block[15];
363 		if (padLen >= 16) {
364 			return BAD_DATA;
365 		}
366 		for (i = 16 - padLen; i < 16; i++) {
367 			if (block[i] != padLen) {
368 				return BAD_DATA;
369 			}
370 		}
371 		memcpy(outBuffer, block, 16 - padLen);
372 		break;
373 
374 	case MODE_CBC:
375 		iv = (u8 *)cipher->IV;
376 		/* all blocks but last */
377 		for (i = numBlocks - 1; i > 0; i--) {
378 			rijndaelDecrypt(key->rk, key->Nr, input, block);
379 			xor16(block, block, iv);
380 			memcpy(cipher->IV, input, 16);
381 			memcpy(outBuffer, block, 16);
382 			input += 16;
383 			outBuffer += 16;
384 		}
385 		/* last block */
386 		rijndaelDecrypt(key->rk, key->Nr, input, block);
387 		xor16(block, block, iv);
388 		padLen = block[15];
389 		if (padLen <= 0 || padLen > 16) {
390 			return BAD_DATA;
391 		}
392 		for (i = 16 - padLen; i < 16; i++) {
393 			if (block[i] != padLen) {
394 				return BAD_DATA;
395 			}
396 		}
397 		memcpy(outBuffer, block, 16 - padLen);
398 		break;
399 
400 	default:
401 		return BAD_CIPHER_STATE;
402 	}
403 
404 	return 16 * numBlocks - padLen;
405 }
406 
407 #endif
408