Updated `NEWS'.
[gnutls.git] / lgl / rijndael-api-fst.c
blobbfa49b5b55eae40cdc219e4363e882e9cafb4a93
1 /* rijndael-api-fst.c --- Rijndael cipher implementation.
2 * Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4 * This file is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; either version 2.1, or (at your
7 * option) any later version.
9 * This file is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this file; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
21 /* Adapted for gnulib by Simon Josefsson.
23 * Based on public domain "Optimised C code" retrieved from (SHA1
24 * 7c8e4b00d06685d1dbc6724a9e0d502353de339e):
25 * http://www.iaik.tu-graz.ac.at/research/krypto/AES/old/~rijmen/rijndael/rijndael-fst-3.0.zip
28 #include <config.h>
30 /**
31 * rijndael-api-fst.c
33 * @version 2.9 (December 2000)
35 * Optimised ANSI C code for the Rijndael cipher (now AES)
37 * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
38 * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
39 * @author Paulo Barreto <paulo.barreto@terra.com.br>
41 * This code is hereby placed in the public domain.
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
44 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
47 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
48 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
49 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
50 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
52 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
53 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55 * Acknowledgements:
57 * We are deeply indebted to the following people for their bug reports,
58 * fixes, and improvement suggestions to this implementation. Though we
59 * tried to list all contributions, we apologise in advance for any
60 * missing reference.
62 * Andrew Bales <Andrew.Bales@Honeywell.com>
63 * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
64 * John Skodon <skodonj@webquill.com>
67 #include "rijndael-alg-fst.h"
68 #include "rijndael-api-fst.h"
70 #include <assert.h>
71 #include <stdlib.h>
72 #include <string.h>
74 rijndael_rc
75 rijndaelMakeKey (rijndaelKeyInstance *key, rijndael_direction direction,
76 size_t keyLen, const char *keyMaterial)
78 size_t i;
79 char *keyMat;
80 char cipherKey[RIJNDAEL_MAXKB];
82 if (key == NULL)
84 return RIJNDAEL_BAD_KEY_INSTANCE;
87 if ((direction == RIJNDAEL_DIR_ENCRYPT)
88 || (direction == RIJNDAEL_DIR_DECRYPT))
90 key->direction = direction;
92 else
94 return RIJNDAEL_BAD_KEY_DIR;
97 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256))
99 key->keyLen = keyLen;
101 else
103 return RIJNDAEL_BAD_KEY_MAT;
106 if (keyMaterial != NULL)
108 strncpy (key->keyMaterial, keyMaterial, keyLen / 4);
111 /* initialize key schedule: */
112 keyMat = key->keyMaterial;
113 for (i = 0; i < key->keyLen / 8; i++)
115 char t, v;
117 t = *keyMat++;
118 if ((t >= '0') && (t <= '9'))
119 v = (t - '0') << 4;
120 else if ((t >= 'a') && (t <= 'f'))
121 v = (t - 'a' + 10) << 4;
122 else if ((t >= 'A') && (t <= 'F'))
123 v = (t - 'A' + 10) << 4;
124 else
125 return RIJNDAEL_BAD_KEY_MAT;
127 t = *keyMat++;
128 if ((t >= '0') && (t <= '9'))
129 v ^= (t - '0');
130 else if ((t >= 'a') && (t <= 'f'))
131 v ^= (t - 'a' + 10);
132 else if ((t >= 'A') && (t <= 'F'))
133 v ^= (t - 'A' + 10);
134 else
135 return RIJNDAEL_BAD_KEY_MAT;
137 cipherKey[i] = v;
139 if (direction == RIJNDAEL_DIR_ENCRYPT)
141 key->Nr = rijndaelKeySetupEnc (key->rk, cipherKey, keyLen);
143 else
145 key->Nr = rijndaelKeySetupDec (key->rk, cipherKey, keyLen);
147 rijndaelKeySetupEnc (key->ek, cipherKey, keyLen);
148 return 0;
151 rijndael_rc
152 rijndaelCipherInit (rijndaelCipherInstance *cipher, rijndael_mode mode,
153 const char *IV)
155 if ((mode == RIJNDAEL_MODE_ECB) || (mode == RIJNDAEL_MODE_CBC)
156 || (mode == RIJNDAEL_MODE_CFB1))
158 cipher->mode = mode;
160 else
162 return RIJNDAEL_BAD_CIPHER_MODE;
164 if (IV != NULL)
166 int i;
167 for (i = 0; i < RIJNDAEL_MAX_IV_SIZE; i++)
169 int t, j;
171 t = IV[2 * i];
172 if ((t >= '0') && (t <= '9'))
173 j = (t - '0') << 4;
174 else if ((t >= 'a') && (t <= 'f'))
175 j = (t - 'a' + 10) << 4;
176 else if ((t >= 'A') && (t <= 'F'))
177 j = (t - 'A' + 10) << 4;
178 else
179 return RIJNDAEL_BAD_CIPHER_INSTANCE;
181 t = IV[2 * i + 1];
182 if ((t >= '0') && (t <= '9'))
183 j ^= (t - '0');
184 else if ((t >= 'a') && (t <= 'f'))
185 j ^= (t - 'a' + 10);
186 else if ((t >= 'A') && (t <= 'F'))
187 j ^= (t - 'A' + 10);
188 else
189 return RIJNDAEL_BAD_CIPHER_INSTANCE;
191 cipher->IV[i] = (uint8_t) j;
194 else
196 memset (cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
198 return 0;
202 rijndaelBlockEncrypt (rijndaelCipherInstance *cipher,
203 const rijndaelKeyInstance *key,
204 const char *input,
205 size_t inputLen, char *outBuffer)
207 size_t i, k, t, numBlocks;
208 char block[16], *iv;
210 if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_DECRYPT)
212 return RIJNDAEL_BAD_CIPHER_STATE;
214 if (input == NULL || inputLen <= 0)
216 return 0; /* nothing to do */
219 numBlocks = inputLen / 128;
221 switch (cipher->mode)
223 case RIJNDAEL_MODE_ECB:
224 for (i = numBlocks; i > 0; i--)
226 rijndaelEncrypt (key->rk, key->Nr, input, outBuffer);
227 input += 16;
228 outBuffer += 16;
230 break;
232 case RIJNDAEL_MODE_CBC:
233 iv = cipher->IV;
234 for (i = numBlocks; i > 0; i--)
236 ((uint32_t *) block)[0] = ((uint32_t *) input)[0] ^
237 ((uint32_t *) iv)[0];
238 ((uint32_t *) block)[1] = ((uint32_t *) input)[1] ^
239 ((uint32_t *) iv)[1];
240 ((uint32_t *) block)[2] = ((uint32_t *) input)[2] ^
241 ((uint32_t *) iv)[2];
242 ((uint32_t *) block)[3] = ((uint32_t *) input)[3] ^
243 ((uint32_t *) iv)[3];
244 rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
245 memcpy (cipher->IV, outBuffer, 16);
246 input += 16;
247 outBuffer += 16;
249 break;
251 case RIJNDAEL_MODE_CFB1:
252 iv = cipher->IV;
253 for (i = numBlocks; i > 0; i--)
255 memcpy (outBuffer, input, 16);
256 for (k = 0; k < 128; k++)
258 rijndaelEncrypt (key->ek, key->Nr, iv, block);
259 outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
260 for (t = 0; t < 15; t++)
262 iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
264 iv[15] = (iv[15] << 1) |
265 ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
267 outBuffer += 16;
268 input += 16;
270 break;
272 default:
273 return RIJNDAEL_BAD_CIPHER_STATE;
276 return 128 * numBlocks;
280 rijndaelPadEncrypt (rijndaelCipherInstance *cipher,
281 const rijndaelKeyInstance *key,
282 const char *input,
283 size_t inputOctets, char *outBuffer)
285 size_t i, numBlocks, padLen;
286 char block[16], *iv;
288 if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_DECRYPT)
290 return RIJNDAEL_BAD_CIPHER_STATE;
292 if (input == NULL || inputOctets <= 0)
294 return 0; /* nothing to do */
297 numBlocks = inputOctets / 16;
299 switch (cipher->mode)
301 case RIJNDAEL_MODE_ECB:
302 for (i = numBlocks; i > 0; i--)
304 rijndaelEncrypt (key->rk, key->Nr, input, outBuffer);
305 input += 16;
306 outBuffer += 16;
308 padLen = 16 - (inputOctets - 16 * numBlocks);
309 assert (padLen > 0 && padLen <= 16);
310 memcpy (block, input, 16 - padLen);
311 memset (block + 16 - padLen, padLen, padLen);
312 rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
313 break;
315 case RIJNDAEL_MODE_CBC:
316 iv = cipher->IV;
317 for (i = numBlocks; i > 0; i--)
319 ((uint32_t *) block)[0] = ((uint32_t *) input)[0] ^
320 ((uint32_t *) iv)[0];
321 ((uint32_t *) block)[1] = ((uint32_t *) input)[1] ^
322 ((uint32_t *) iv)[1];
323 ((uint32_t *) block)[2] = ((uint32_t *) input)[2] ^
324 ((uint32_t *) iv)[2];
325 ((uint32_t *) block)[3] = ((uint32_t *) input)[3] ^
326 ((uint32_t *) iv)[3];
327 rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
328 memcpy (cipher->IV, outBuffer, 16);
329 input += 16;
330 outBuffer += 16;
332 padLen = 16 - (inputOctets - 16 * numBlocks);
333 assert (padLen > 0 && padLen <= 16);
334 for (i = 0; i < 16 - padLen; i++)
336 block[i] = input[i] ^ iv[i];
338 for (i = 16 - padLen; i < 16; i++)
340 block[i] = (char) padLen ^ iv[i];
342 rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
343 memcpy (cipher->IV, outBuffer, 16);
344 break;
346 default:
347 return RIJNDAEL_BAD_CIPHER_STATE;
350 return 16 * (numBlocks + 1);
354 rijndaelBlockDecrypt (rijndaelCipherInstance *cipher,
355 const rijndaelKeyInstance *key,
356 const char *input,
357 size_t inputLen, char *outBuffer)
359 size_t i, k, t, numBlocks;
360 char block[16], *iv;
362 if (cipher == NULL
363 || key == NULL
364 || (cipher->mode != RIJNDAEL_MODE_CFB1
365 && key->direction == RIJNDAEL_DIR_ENCRYPT))
367 return RIJNDAEL_BAD_CIPHER_STATE;
369 if (input == NULL || inputLen <= 0)
371 return 0; /* nothing to do */
374 numBlocks = inputLen / 128;
376 switch (cipher->mode)
378 case RIJNDAEL_MODE_ECB:
379 for (i = numBlocks; i > 0; i--)
381 rijndaelDecrypt (key->rk, key->Nr, input, outBuffer);
382 input += 16;
383 outBuffer += 16;
385 break;
387 case RIJNDAEL_MODE_CBC:
388 iv = cipher->IV;
389 for (i = numBlocks; i > 0; i--)
391 rijndaelDecrypt (key->rk, key->Nr, input, block);
392 ((uint32_t *) block)[0] ^= ((uint32_t *) iv)[0];
393 ((uint32_t *) block)[1] ^= ((uint32_t *) iv)[1];
394 ((uint32_t *) block)[2] ^= ((uint32_t *) iv)[2];
395 ((uint32_t *) block)[3] ^= ((uint32_t *) iv)[3];
396 memcpy (cipher->IV, input, 16);
397 memcpy (outBuffer, block, 16);
398 input += 16;
399 outBuffer += 16;
401 break;
403 case RIJNDAEL_MODE_CFB1:
404 iv = cipher->IV;
405 for (i = numBlocks; i > 0; i--)
407 memcpy (outBuffer, input, 16);
408 for (k = 0; k < 128; k++)
410 rijndaelEncrypt (key->ek, key->Nr, iv, block);
411 for (t = 0; t < 15; t++)
413 iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
415 iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
416 outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
418 outBuffer += 16;
419 input += 16;
421 break;
423 default:
424 return RIJNDAEL_BAD_CIPHER_STATE;
427 return 128 * numBlocks;
431 rijndaelPadDecrypt (rijndaelCipherInstance *cipher,
432 const rijndaelKeyInstance *key,
433 const char *input,
434 size_t inputOctets, char *outBuffer)
436 size_t i, numBlocks, padLen;
437 char block[16];
439 if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_ENCRYPT)
441 return RIJNDAEL_BAD_CIPHER_STATE;
443 if (input == NULL || inputOctets <= 0)
445 return 0; /* nothing to do */
447 if (inputOctets % 16 != 0)
449 return RIJNDAEL_BAD_DATA;
452 numBlocks = inputOctets / 16;
454 switch (cipher->mode)
456 case RIJNDAEL_MODE_ECB:
457 /* all blocks but last */
458 for (i = numBlocks - 1; i > 0; i--)
460 rijndaelDecrypt (key->rk, key->Nr, input, outBuffer);
461 input += 16;
462 outBuffer += 16;
464 /* last block */
465 rijndaelDecrypt (key->rk, key->Nr, input, block);
466 padLen = block[15];
467 if (padLen >= 16)
469 return RIJNDAEL_BAD_DATA;
471 for (i = 16 - padLen; i < 16; i++)
473 if (block[i] != padLen)
475 return RIJNDAEL_BAD_DATA;
478 memcpy (outBuffer, block, 16 - padLen);
479 break;
481 case RIJNDAEL_MODE_CBC:
482 /* all blocks but last */
483 for (i = numBlocks - 1; i > 0; i--)
485 rijndaelDecrypt (key->rk, key->Nr, input, block);
486 ((uint32_t *) block)[0] ^= ((uint32_t *) cipher->IV)[0];
487 ((uint32_t *) block)[1] ^= ((uint32_t *) cipher->IV)[1];
488 ((uint32_t *) block)[2] ^= ((uint32_t *) cipher->IV)[2];
489 ((uint32_t *) block)[3] ^= ((uint32_t *) cipher->IV)[3];
490 memcpy (cipher->IV, input, 16);
491 memcpy (outBuffer, block, 16);
492 input += 16;
493 outBuffer += 16;
495 /* last block */
496 rijndaelDecrypt (key->rk, key->Nr, input, block);
497 ((uint32_t *) block)[0] ^= ((uint32_t *) cipher->IV)[0];
498 ((uint32_t *) block)[1] ^= ((uint32_t *) cipher->IV)[1];
499 ((uint32_t *) block)[2] ^= ((uint32_t *) cipher->IV)[2];
500 ((uint32_t *) block)[3] ^= ((uint32_t *) cipher->IV)[3];
501 padLen = block[15];
502 if (padLen <= 0 || padLen > 16)
504 return RIJNDAEL_BAD_DATA;
506 for (i = 16 - padLen; i < 16; i++)
508 if (block[i] != padLen)
510 return RIJNDAEL_BAD_DATA;
513 memcpy (outBuffer, block, 16 - padLen);
514 break;
516 default:
517 return RIJNDAEL_BAD_CIPHER_STATE;
520 return 16 * numBlocks - padLen;