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
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
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.
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
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"
75 rijndaelMakeKey (rijndaelKeyInstance
*key
, rijndael_direction direction
,
76 size_t keyLen
, const char *keyMaterial
)
80 char cipherKey
[RIJNDAEL_MAXKB
];
84 return RIJNDAEL_BAD_KEY_INSTANCE
;
87 if ((direction
== RIJNDAEL_DIR_ENCRYPT
)
88 || (direction
== RIJNDAEL_DIR_DECRYPT
))
90 key
->direction
= direction
;
94 return RIJNDAEL_BAD_KEY_DIR
;
97 if ((keyLen
== 128) || (keyLen
== 192) || (keyLen
== 256))
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
++)
118 if ((t
>= '0') && (t
<= '9'))
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;
125 return RIJNDAEL_BAD_KEY_MAT
;
128 if ((t
>= '0') && (t
<= '9'))
130 else if ((t
>= 'a') && (t
<= 'f'))
132 else if ((t
>= 'A') && (t
<= 'F'))
135 return RIJNDAEL_BAD_KEY_MAT
;
139 if (direction
== RIJNDAEL_DIR_ENCRYPT
)
141 key
->Nr
= rijndaelKeySetupEnc (key
->rk
, cipherKey
, keyLen
);
145 key
->Nr
= rijndaelKeySetupDec (key
->rk
, cipherKey
, keyLen
);
147 rijndaelKeySetupEnc (key
->ek
, cipherKey
, keyLen
);
152 rijndaelCipherInit (rijndaelCipherInstance
*cipher
, rijndael_mode mode
,
155 if ((mode
== RIJNDAEL_MODE_ECB
) || (mode
== RIJNDAEL_MODE_CBC
)
156 || (mode
== RIJNDAEL_MODE_CFB1
))
162 return RIJNDAEL_BAD_CIPHER_MODE
;
167 for (i
= 0; i
< RIJNDAEL_MAX_IV_SIZE
; i
++)
172 if ((t
>= '0') && (t
<= '9'))
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;
179 return RIJNDAEL_BAD_CIPHER_INSTANCE
;
182 if ((t
>= '0') && (t
<= '9'))
184 else if ((t
>= 'a') && (t
<= 'f'))
186 else if ((t
>= 'A') && (t
<= 'F'))
189 return RIJNDAEL_BAD_CIPHER_INSTANCE
;
191 cipher
->IV
[i
] = (uint8_t) j
;
196 memset (cipher
->IV
, 0, RIJNDAEL_MAX_IV_SIZE
);
202 rijndaelBlockEncrypt (rijndaelCipherInstance
*cipher
,
203 const rijndaelKeyInstance
*key
,
205 size_t inputLen
, char *outBuffer
)
207 size_t i
, k
, t
, numBlocks
;
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
);
232 case RIJNDAEL_MODE_CBC
:
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);
251 case RIJNDAEL_MODE_CFB1
:
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);
273 return RIJNDAEL_BAD_CIPHER_STATE
;
276 return 128 * numBlocks
;
280 rijndaelPadEncrypt (rijndaelCipherInstance
*cipher
,
281 const rijndaelKeyInstance
*key
,
283 size_t inputOctets
, char *outBuffer
)
285 size_t i
, numBlocks
, padLen
;
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
);
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
);
315 case RIJNDAEL_MODE_CBC
:
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);
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);
347 return RIJNDAEL_BAD_CIPHER_STATE
;
350 return 16 * (numBlocks
+ 1);
354 rijndaelBlockDecrypt (rijndaelCipherInstance
*cipher
,
355 const rijndaelKeyInstance
*key
,
357 size_t inputLen
, char *outBuffer
)
359 size_t i
, k
, t
, numBlocks
;
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
);
387 case RIJNDAEL_MODE_CBC
:
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);
403 case RIJNDAEL_MODE_CFB1
:
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);
424 return RIJNDAEL_BAD_CIPHER_STATE
;
427 return 128 * numBlocks
;
431 rijndaelPadDecrypt (rijndaelCipherInstance
*cipher
,
432 const rijndaelKeyInstance
*key
,
434 size_t inputOctets
, char *outBuffer
)
436 size_t i
, numBlocks
, padLen
;
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
);
465 rijndaelDecrypt (key
->rk
, key
->Nr
, input
, block
);
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
);
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);
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];
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
);
517 return RIJNDAEL_BAD_CIPHER_STATE
;
520 return 16 * numBlocks
- padLen
;