b7053a5b7cd9e8d322dc496331b14ecbe7bd0836
[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           iv = outBuffer;
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           iv = outBuffer;
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       break;
346
347     default:
348       return RIJNDAEL_BAD_CIPHER_STATE;
349     }
350
351   return 16 * (numBlocks + 1);
352 }
353
354 int
355 rijndaelBlockDecrypt (rijndaelCipherInstance *cipher,
356                       const rijndaelKeyInstance *key,
357                       const char *input,
358                       size_t inputLen, char *outBuffer)
359 {
360   size_t i, k, t, numBlocks;
361   char block[16], *iv;
362
363   if (cipher == NULL ||
364       key == NULL ||
365       cipher->mode != RIJNDAEL_MODE_CFB1
366       && key->direction == RIJNDAEL_DIR_ENCRYPT)
367     {
368       return RIJNDAEL_BAD_CIPHER_STATE;
369     }
370   if (input == NULL || inputLen <= 0)
371     {
372       return 0;                 /* nothing to do */
373     }
374
375   numBlocks = inputLen / 128;
376
377   switch (cipher->mode)
378     {
379     case RIJNDAEL_MODE_ECB:
380       for (i = numBlocks; i > 0; i--)
381         {
382           rijndaelDecrypt (key->rk, key->Nr, input, outBuffer);
383           input += 16;
384           outBuffer += 16;
385         }
386       break;
387
388     case RIJNDAEL_MODE_CBC:
389       iv = cipher->IV;
390       for (i = numBlocks; i > 0; i--)
391         {
392           rijndaelDecrypt (key->rk, key->Nr, input, block);
393           ((uint32_t *) block)[0] ^= ((uint32_t *) iv)[0];
394           ((uint32_t *) block)[1] ^= ((uint32_t *) iv)[1];
395           ((uint32_t *) block)[2] ^= ((uint32_t *) iv)[2];
396           ((uint32_t *) block)[3] ^= ((uint32_t *) iv)[3];
397           memcpy (cipher->IV, input, 16);
398           memcpy (outBuffer, block, 16);
399           input += 16;
400           outBuffer += 16;
401         }
402       break;
403
404     case RIJNDAEL_MODE_CFB1:
405       iv = cipher->IV;
406       for (i = numBlocks; i > 0; i--)
407         {
408           memcpy (outBuffer, input, 16);
409           for (k = 0; k < 128; k++)
410             {
411               rijndaelEncrypt (key->ek, key->Nr, iv, block);
412               for (t = 0; t < 15; t++)
413                 {
414                   iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
415                 }
416               iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
417               outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
418             }
419           outBuffer += 16;
420           input += 16;
421         }
422       break;
423
424     default:
425       return RIJNDAEL_BAD_CIPHER_STATE;
426     }
427
428   return 128 * numBlocks;
429 }
430
431 int
432 rijndaelPadDecrypt (rijndaelCipherInstance *cipher,
433                     const rijndaelKeyInstance *key,
434                     const char *input,
435                     size_t inputOctets, char *outBuffer)
436 {
437   size_t i, numBlocks, padLen;
438   char block[16];
439
440   if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_ENCRYPT)
441     {
442       return RIJNDAEL_BAD_CIPHER_STATE;
443     }
444   if (input == NULL || inputOctets <= 0)
445     {
446       return 0;                 /* nothing to do */
447     }
448   if (inputOctets % 16 != 0)
449     {
450       return RIJNDAEL_BAD_DATA;
451     }
452
453   numBlocks = inputOctets / 16;
454
455   switch (cipher->mode)
456     {
457     case RIJNDAEL_MODE_ECB:
458       /* all blocks but last */
459       for (i = numBlocks - 1; i > 0; i--)
460         {
461           rijndaelDecrypt (key->rk, key->Nr, input, outBuffer);
462           input += 16;
463           outBuffer += 16;
464         }
465       /* last block */
466       rijndaelDecrypt (key->rk, key->Nr, input, block);
467       padLen = block[15];
468       if (padLen >= 16)
469         {
470           return RIJNDAEL_BAD_DATA;
471         }
472       for (i = 16 - padLen; i < 16; i++)
473         {
474           if (block[i] != padLen)
475             {
476               return RIJNDAEL_BAD_DATA;
477             }
478         }
479       memcpy (outBuffer, block, 16 - padLen);
480       break;
481
482     case RIJNDAEL_MODE_CBC:
483       /* all blocks but last */
484       for (i = numBlocks - 1; i > 0; i--)
485         {
486           rijndaelDecrypt (key->rk, key->Nr, input, block);
487           ((uint32_t *) block)[0] ^= ((uint32_t *) cipher->IV)[0];
488           ((uint32_t *) block)[1] ^= ((uint32_t *) cipher->IV)[1];
489           ((uint32_t *) block)[2] ^= ((uint32_t *) cipher->IV)[2];
490           ((uint32_t *) block)[3] ^= ((uint32_t *) cipher->IV)[3];
491           memcpy (cipher->IV, input, 16);
492           memcpy (outBuffer, block, 16);
493           input += 16;
494           outBuffer += 16;
495         }
496       /* last block */
497       rijndaelDecrypt (key->rk, key->Nr, input, block);
498       ((uint32_t *) block)[0] ^= ((uint32_t *) cipher->IV)[0];
499       ((uint32_t *) block)[1] ^= ((uint32_t *) cipher->IV)[1];
500       ((uint32_t *) block)[2] ^= ((uint32_t *) cipher->IV)[2];
501       ((uint32_t *) block)[3] ^= ((uint32_t *) cipher->IV)[3];
502       padLen = block[15];
503       if (padLen <= 0 || padLen > 16)
504         {
505           return RIJNDAEL_BAD_DATA;
506         }
507       for (i = 16 - padLen; i < 16; i++)
508         {
509           if (block[i] != padLen)
510             {
511               return RIJNDAEL_BAD_DATA;
512             }
513         }
514       memcpy (outBuffer, block, 16 - padLen);
515       break;
516
517     default:
518       return RIJNDAEL_BAD_CIPHER_STATE;
519     }
520
521   return 16 * numBlocks - padLen;
522 }