* rijndael-api-fst.c: Fix bugs in CBC mode for more than one
[gnulib.git] / lib / rijndael-api-fst.c
1 /* rijndael-api-fst.c --- Rijndael cipher implementation.
2  * Copyright (C) 2005 Free Software Foundation, Inc.
3  *
4  * This file is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published
6  * by the Free Software Foundation; either version 2, or (at your
7  * option) any later version.
8  *
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.
13  *
14  * You should have received a copy of the GNU 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.
18  *
19  */
20
21 /* Adapted for gnulib by Simon Josefsson.
22  *
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
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31
32 /**
33  * rijndael-api-fst.c
34  *
35  * @version 2.9 (December 2000)
36  *
37  * Optimised ANSI C code for the Rijndael cipher (now AES)
38  *
39  * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
40  * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
41  * @author Paulo Barreto <paulo.barreto@terra.com.br>
42  *
43  * This code is hereby placed in the public domain.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
46  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
49  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
52  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
54  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
55  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56  *
57  * Acknowledgements:
58  *
59  * We are deeply indebted to the following people for their bug reports,
60  * fixes, and improvement suggestions to this implementation. Though we
61  * tried to list all contributions, we apologise in advance for any
62  * missing reference.
63  *
64  * Andrew Bales <Andrew.Bales@Honeywell.com>
65  * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
66  * John Skodon <skodonj@webquill.com>
67  */
68
69 #include "rijndael-alg-fst.h"
70 #include "rijndael-api-fst.h"
71
72 #include <assert.h>
73 #include <stdlib.h>
74 #include <string.h>
75
76 rijndael_rc
77 rijndaelMakeKey (rijndaelKeyInstance *key, rijndael_direction direction,
78                  size_t keyLen, const char *keyMaterial)
79 {
80   size_t i;
81   char *keyMat;
82   char cipherKey[RIJNDAEL_MAXKB];
83
84   if (key == NULL)
85     {
86       return RIJNDAEL_BAD_KEY_INSTANCE;
87     }
88
89   if ((direction == RIJNDAEL_DIR_ENCRYPT)
90       || (direction == RIJNDAEL_DIR_DECRYPT))
91     {
92       key->direction = direction;
93     }
94   else
95     {
96       return RIJNDAEL_BAD_KEY_DIR;
97     }
98
99   if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256))
100     {
101       key->keyLen = keyLen;
102     }
103   else
104     {
105       return RIJNDAEL_BAD_KEY_MAT;
106     }
107
108   if (keyMaterial != NULL)
109     {
110       strncpy (key->keyMaterial, keyMaterial, keyLen / 4);
111     }
112
113   /* initialize key schedule: */
114   keyMat = key->keyMaterial;
115   for (i = 0; i < key->keyLen / 8; i++)
116     {
117       char t, v;
118
119       t = *keyMat++;
120       if ((t >= '0') && (t <= '9'))
121         v = (t - '0') << 4;
122       else if ((t >= 'a') && (t <= 'f'))
123         v = (t - 'a' + 10) << 4;
124       else if ((t >= 'A') && (t <= 'F'))
125         v = (t - 'A' + 10) << 4;
126       else
127         return RIJNDAEL_BAD_KEY_MAT;
128
129       t = *keyMat++;
130       if ((t >= '0') && (t <= '9'))
131         v ^= (t - '0');
132       else if ((t >= 'a') && (t <= 'f'))
133         v ^= (t - 'a' + 10);
134       else if ((t >= 'A') && (t <= 'F'))
135         v ^= (t - 'A' + 10);
136       else
137         return RIJNDAEL_BAD_KEY_MAT;
138
139       cipherKey[i] = v;
140     }
141   if (direction == RIJNDAEL_DIR_ENCRYPT)
142     {
143       key->Nr = rijndaelKeySetupEnc (key->rk, cipherKey, keyLen);
144     }
145   else
146     {
147       key->Nr = rijndaelKeySetupDec (key->rk, cipherKey, keyLen);
148     }
149   rijndaelKeySetupEnc (key->ek, cipherKey, keyLen);
150   return 0;
151 }
152
153 rijndael_rc
154 rijndaelCipherInit (rijndaelCipherInstance *cipher, rijndael_mode mode,
155                     const char *IV)
156 {
157   if ((mode == RIJNDAEL_MODE_ECB) || (mode == RIJNDAEL_MODE_CBC)
158       || (mode == RIJNDAEL_MODE_CFB1))
159     {
160       cipher->mode = mode;
161     }
162   else
163     {
164       return RIJNDAEL_BAD_CIPHER_MODE;
165     }
166   if (IV != NULL)
167     {
168       int i;
169       for (i = 0; i < RIJNDAEL_MAX_IV_SIZE; i++)
170         {
171           int t, j;
172
173           t = IV[2 * i];
174           if ((t >= '0') && (t <= '9'))
175             j = (t - '0') << 4;
176           else if ((t >= 'a') && (t <= 'f'))
177             j = (t - 'a' + 10) << 4;
178           else if ((t >= 'A') && (t <= 'F'))
179             j = (t - 'A' + 10) << 4;
180           else
181             return RIJNDAEL_BAD_CIPHER_INSTANCE;
182
183           t = IV[2 * i + 1];
184           if ((t >= '0') && (t <= '9'))
185             j ^= (t - '0');
186           else if ((t >= 'a') && (t <= 'f'))
187             j ^= (t - 'a' + 10);
188           else if ((t >= 'A') && (t <= 'F'))
189             j ^= (t - 'A' + 10);
190           else
191             return RIJNDAEL_BAD_CIPHER_INSTANCE;
192
193           cipher->IV[i] = (uint8_t) j;
194         }
195     }
196   else
197     {
198       memset (cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
199     }
200   return 0;
201 }
202
203 int
204 rijndaelBlockEncrypt (rijndaelCipherInstance *cipher,
205                       const rijndaelKeyInstance *key,
206                       const char *input,
207                       size_t inputLen, char *outBuffer)
208 {
209   size_t i, k, t, numBlocks;
210   char block[16], *iv;
211
212   if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_DECRYPT)
213     {
214       return RIJNDAEL_BAD_CIPHER_STATE;
215     }
216   if (input == NULL || inputLen <= 0)
217     {
218       return 0;                 /* nothing to do */
219     }
220
221   numBlocks = inputLen / 128;
222
223   switch (cipher->mode)
224     {
225     case RIJNDAEL_MODE_ECB:
226       for (i = numBlocks; i > 0; i--)
227         {
228           rijndaelEncrypt (key->rk, key->Nr, input, outBuffer);
229           input += 16;
230           outBuffer += 16;
231         }
232       break;
233
234     case RIJNDAEL_MODE_CBC:
235       iv = cipher->IV;
236       for (i = numBlocks; i > 0; i--)
237         {
238           ((uint32_t *) block)[0] = ((uint32_t *) input)[0] ^
239             ((uint32_t *) iv)[0];
240           ((uint32_t *) block)[1] = ((uint32_t *) input)[1] ^
241             ((uint32_t *) iv)[1];
242           ((uint32_t *) block)[2] = ((uint32_t *) input)[2] ^
243             ((uint32_t *) iv)[2];
244           ((uint32_t *) block)[3] = ((uint32_t *) input)[3] ^
245             ((uint32_t *) iv)[3];
246           rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
247           memcpy (cipher->IV, outBuffer, 16);
248           input += 16;
249           outBuffer += 16;
250         }
251       break;
252
253     case RIJNDAEL_MODE_CFB1:
254       iv = cipher->IV;
255       for (i = numBlocks; i > 0; i--)
256         {
257           memcpy (outBuffer, input, 16);
258           for (k = 0; k < 128; k++)
259             {
260               rijndaelEncrypt (key->ek, key->Nr, iv, block);
261               outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
262               for (t = 0; t < 15; t++)
263                 {
264                   iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
265                 }
266               iv[15] = (iv[15] << 1) |
267                 ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
268             }
269           outBuffer += 16;
270           input += 16;
271         }
272       break;
273
274     default:
275       return RIJNDAEL_BAD_CIPHER_STATE;
276     }
277
278   return 128 * numBlocks;
279 }
280
281 int
282 rijndaelPadEncrypt (rijndaelCipherInstance *cipher,
283                     const rijndaelKeyInstance *key,
284                     const char *input,
285                     size_t inputOctets, char *outBuffer)
286 {
287   size_t i, numBlocks, padLen;
288   char block[16], *iv;
289
290   if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_DECRYPT)
291     {
292       return RIJNDAEL_BAD_CIPHER_STATE;
293     }
294   if (input == NULL || inputOctets <= 0)
295     {
296       return 0;                 /* nothing to do */
297     }
298
299   numBlocks = inputOctets / 16;
300
301   switch (cipher->mode)
302     {
303     case RIJNDAEL_MODE_ECB:
304       for (i = numBlocks; i > 0; i--)
305         {
306           rijndaelEncrypt (key->rk, key->Nr, input, outBuffer);
307           input += 16;
308           outBuffer += 16;
309         }
310       padLen = 16 - (inputOctets - 16 * numBlocks);
311       assert (padLen > 0 && padLen <= 16);
312       memcpy (block, input, 16 - padLen);
313       memset (block + 16 - padLen, padLen, padLen);
314       rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
315       break;
316
317     case RIJNDAEL_MODE_CBC:
318       iv = cipher->IV;
319       for (i = numBlocks; i > 0; i--)
320         {
321           ((uint32_t *) block)[0] = ((uint32_t *) input)[0] ^
322             ((uint32_t *) iv)[0];
323           ((uint32_t *) block)[1] = ((uint32_t *) input)[1] ^
324             ((uint32_t *) iv)[1];
325           ((uint32_t *) block)[2] = ((uint32_t *) input)[2] ^
326             ((uint32_t *) iv)[2];
327           ((uint32_t *) block)[3] = ((uint32_t *) input)[3] ^
328             ((uint32_t *) iv)[3];
329           rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
330           memcpy (cipher->IV, outBuffer, 16);
331           input += 16;
332           outBuffer += 16;
333         }
334       padLen = 16 - (inputOctets - 16 * numBlocks);
335       assert (padLen > 0 && padLen <= 16);
336       for (i = 0; i < 16 - padLen; i++)
337         {
338           block[i] = input[i] ^ iv[i];
339         }
340       for (i = 16 - padLen; i < 16; i++)
341         {
342           block[i] = (char) padLen ^ iv[i];
343         }
344       rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
345       memcpy (cipher->IV, outBuffer, 16);
346       break;
347
348     default:
349       return RIJNDAEL_BAD_CIPHER_STATE;
350     }
351
352   return 16 * (numBlocks + 1);
353 }
354
355 int
356 rijndaelBlockDecrypt (rijndaelCipherInstance *cipher,
357                       const rijndaelKeyInstance *key,
358                       const char *input,
359                       size_t inputLen, char *outBuffer)
360 {
361   size_t i, k, t, numBlocks;
362   char block[16], *iv;
363
364   if (cipher == NULL ||
365       key == NULL ||
366       cipher->mode != RIJNDAEL_MODE_CFB1
367       && key->direction == RIJNDAEL_DIR_ENCRYPT)
368     {
369       return RIJNDAEL_BAD_CIPHER_STATE;
370     }
371   if (input == NULL || inputLen <= 0)
372     {
373       return 0;                 /* nothing to do */
374     }
375
376   numBlocks = inputLen / 128;
377
378   switch (cipher->mode)
379     {
380     case RIJNDAEL_MODE_ECB:
381       for (i = numBlocks; i > 0; i--)
382         {
383           rijndaelDecrypt (key->rk, key->Nr, input, outBuffer);
384           input += 16;
385           outBuffer += 16;
386         }
387       break;
388
389     case RIJNDAEL_MODE_CBC:
390       iv = cipher->IV;
391       for (i = numBlocks; i > 0; i--)
392         {
393           rijndaelDecrypt (key->rk, key->Nr, input, block);
394           ((uint32_t *) block)[0] ^= ((uint32_t *) iv)[0];
395           ((uint32_t *) block)[1] ^= ((uint32_t *) iv)[1];
396           ((uint32_t *) block)[2] ^= ((uint32_t *) iv)[2];
397           ((uint32_t *) block)[3] ^= ((uint32_t *) iv)[3];
398           memcpy (cipher->IV, input, 16);
399           memcpy (outBuffer, block, 16);
400           input += 16;
401           outBuffer += 16;
402         }
403       break;
404
405     case RIJNDAEL_MODE_CFB1:
406       iv = cipher->IV;
407       for (i = numBlocks; i > 0; i--)
408         {
409           memcpy (outBuffer, input, 16);
410           for (k = 0; k < 128; k++)
411             {
412               rijndaelEncrypt (key->ek, key->Nr, iv, block);
413               for (t = 0; t < 15; t++)
414                 {
415                   iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
416                 }
417               iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
418               outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
419             }
420           outBuffer += 16;
421           input += 16;
422         }
423       break;
424
425     default:
426       return RIJNDAEL_BAD_CIPHER_STATE;
427     }
428
429   return 128 * numBlocks;
430 }
431
432 int
433 rijndaelPadDecrypt (rijndaelCipherInstance *cipher,
434                     const rijndaelKeyInstance *key,
435                     const char *input,
436                     size_t inputOctets, char *outBuffer)
437 {
438   size_t i, numBlocks, padLen;
439   char block[16];
440
441   if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_ENCRYPT)
442     {
443       return RIJNDAEL_BAD_CIPHER_STATE;
444     }
445   if (input == NULL || inputOctets <= 0)
446     {
447       return 0;                 /* nothing to do */
448     }
449   if (inputOctets % 16 != 0)
450     {
451       return RIJNDAEL_BAD_DATA;
452     }
453
454   numBlocks = inputOctets / 16;
455
456   switch (cipher->mode)
457     {
458     case RIJNDAEL_MODE_ECB:
459       /* all blocks but last */
460       for (i = numBlocks - 1; i > 0; i--)
461         {
462           rijndaelDecrypt (key->rk, key->Nr, input, outBuffer);
463           input += 16;
464           outBuffer += 16;
465         }
466       /* last block */
467       rijndaelDecrypt (key->rk, key->Nr, input, block);
468       padLen = block[15];
469       if (padLen >= 16)
470         {
471           return RIJNDAEL_BAD_DATA;
472         }
473       for (i = 16 - padLen; i < 16; i++)
474         {
475           if (block[i] != padLen)
476             {
477               return RIJNDAEL_BAD_DATA;
478             }
479         }
480       memcpy (outBuffer, block, 16 - padLen);
481       break;
482
483     case RIJNDAEL_MODE_CBC:
484       /* all blocks but last */
485       for (i = numBlocks - 1; i > 0; i--)
486         {
487           rijndaelDecrypt (key->rk, key->Nr, input, block);
488           ((uint32_t *) block)[0] ^= ((uint32_t *) cipher->IV)[0];
489           ((uint32_t *) block)[1] ^= ((uint32_t *) cipher->IV)[1];
490           ((uint32_t *) block)[2] ^= ((uint32_t *) cipher->IV)[2];
491           ((uint32_t *) block)[3] ^= ((uint32_t *) cipher->IV)[3];
492           memcpy (cipher->IV, input, 16);
493           memcpy (outBuffer, block, 16);
494           input += 16;
495           outBuffer += 16;
496         }
497       /* last block */
498       rijndaelDecrypt (key->rk, key->Nr, input, block);
499       ((uint32_t *) block)[0] ^= ((uint32_t *) cipher->IV)[0];
500       ((uint32_t *) block)[1] ^= ((uint32_t *) cipher->IV)[1];
501       ((uint32_t *) block)[2] ^= ((uint32_t *) cipher->IV)[2];
502       ((uint32_t *) block)[3] ^= ((uint32_t *) cipher->IV)[3];
503       padLen = block[15];
504       if (padLen <= 0 || padLen > 16)
505         {
506           return RIJNDAEL_BAD_DATA;
507         }
508       for (i = 16 - padLen; i < 16; i++)
509         {
510           if (block[i] != padLen)
511             {
512               return RIJNDAEL_BAD_DATA;
513             }
514         }
515       memcpy (outBuffer, block, 16 - padLen);
516       break;
517
518     default:
519       return RIJNDAEL_BAD_CIPHER_STATE;
520     }
521
522   return 16 * numBlocks - padLen;
523 }