1 /* rijndael-api-fst.c --- Rijndael cipher implementation.
2 * Copyright (C) 2005-2006, 2009-2020 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 General Public License as published
6 * by the Free Software Foundation; either version 2, 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 General Public License
15 * along with this file; if not, see <https://www.gnu.org/licenses/>.
19 /* Adapted for gnulib by Simon Josefsson.
21 * Based on public domain "Optimised C code" retrieved from (SHA1
22 * 7c8e4b00d06685d1dbc6724a9e0d502353de339e):
23 * https://web.archive.org/web/20060618010435/http://www.iaik.tu-graz.ac.at/research/krypto/AES/old/~rijmen/rijndael/rijndael-fst-3.0.zip
31 * @version 2.9 (December 2000)
33 * Optimised ANSI C code for the Rijndael cipher (now AES)
35 * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
36 * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
37 * @author Paulo Barreto <paulo.barreto@terra.com.br>
39 * This code is hereby placed in the public domain.
41 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
42 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
45 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
46 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
47 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
48 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
50 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
51 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55 * We are deeply indebted to the following people for their bug reports,
56 * fixes, and improvement suggestions to this implementation. Though we
57 * tried to list all contributions, we apologise in advance for any
60 * Andrew Bales <Andrew.Bales@Honeywell.com>
61 * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
62 * John Skodon <skodonj@webquill.com>
65 #include "rijndael-alg-fst.h"
66 #include "rijndael-api-fst.h"
73 rijndaelMakeKey (rijndaelKeyInstance
*key
, rijndael_direction direction
,
74 size_t keyLen
, const char *keyMaterial
)
78 char cipherKey
[RIJNDAEL_MAXKB
];
82 return RIJNDAEL_BAD_KEY_INSTANCE
;
85 if ((direction
== RIJNDAEL_DIR_ENCRYPT
)
86 || (direction
== RIJNDAEL_DIR_DECRYPT
))
88 key
->direction
= direction
;
92 return RIJNDAEL_BAD_KEY_DIR
;
95 if ((keyLen
== 128) || (keyLen
== 192) || (keyLen
== 256))
101 return RIJNDAEL_BAD_KEY_MAT
;
104 if (keyMaterial
!= NULL
)
106 strncpy (key
->keyMaterial
, keyMaterial
, keyLen
/ 4);
109 /* initialize key schedule: */
110 keyMat
= key
->keyMaterial
;
111 for (i
= 0; i
< key
->keyLen
/ 8; i
++)
116 if ((t
>= '0') && (t
<= '9'))
118 else if ((t
>= 'a') && (t
<= 'f'))
119 v
= (t
- 'a' + 10) << 4;
120 else if ((t
>= 'A') && (t
<= 'F'))
121 v
= (t
- 'A' + 10) << 4;
123 return RIJNDAEL_BAD_KEY_MAT
;
126 if ((t
>= '0') && (t
<= '9'))
128 else if ((t
>= 'a') && (t
<= 'f'))
130 else if ((t
>= 'A') && (t
<= 'F'))
133 return RIJNDAEL_BAD_KEY_MAT
;
137 if (direction
== RIJNDAEL_DIR_ENCRYPT
)
139 key
->Nr
= rijndaelKeySetupEnc (key
->rk
, cipherKey
, keyLen
);
143 key
->Nr
= rijndaelKeySetupDec (key
->rk
, cipherKey
, keyLen
);
145 rijndaelKeySetupEnc (key
->ek
, cipherKey
, keyLen
);
150 rijndaelCipherInit (rijndaelCipherInstance
*cipher
, rijndael_mode mode
,
153 if ((mode
== RIJNDAEL_MODE_ECB
) || (mode
== RIJNDAEL_MODE_CBC
)
154 || (mode
== RIJNDAEL_MODE_CFB1
))
160 return RIJNDAEL_BAD_CIPHER_MODE
;
165 for (i
= 0; i
< RIJNDAEL_MAX_IV_SIZE
; i
++)
170 if ((t
>= '0') && (t
<= '9'))
172 else if ((t
>= 'a') && (t
<= 'f'))
173 j
= (t
- 'a' + 10) << 4;
174 else if ((t
>= 'A') && (t
<= 'F'))
175 j
= (t
- 'A' + 10) << 4;
177 return RIJNDAEL_BAD_CIPHER_INSTANCE
;
180 if ((t
>= '0') && (t
<= '9'))
182 else if ((t
>= 'a') && (t
<= 'f'))
184 else if ((t
>= 'A') && (t
<= 'F'))
187 return RIJNDAEL_BAD_CIPHER_INSTANCE
;
189 cipher
->IV
[i
] = (uint8_t) j
;
194 memset (cipher
->IV
, 0, RIJNDAEL_MAX_IV_SIZE
);
200 rijndaelBlockEncrypt (rijndaelCipherInstance
*cipher
,
201 const rijndaelKeyInstance
*key
,
203 size_t inputLen
, char *outBuffer
)
205 size_t i
, k
, t
, numBlocks
;
206 union { char bytes
[16]; uint32_t words
[4]; } block
;
209 if (cipher
== NULL
|| key
== NULL
|| key
->direction
== RIJNDAEL_DIR_DECRYPT
)
211 return RIJNDAEL_BAD_CIPHER_STATE
;
213 if (input
== NULL
|| inputLen
<= 0)
215 return 0; /* nothing to do */
218 numBlocks
= inputLen
/ 128;
220 switch (cipher
->mode
)
222 case RIJNDAEL_MODE_ECB
:
223 for (i
= numBlocks
; i
> 0; i
--)
225 rijndaelEncrypt (key
->rk
, key
->Nr
, input
, outBuffer
);
231 case RIJNDAEL_MODE_CBC
:
233 for (i
= numBlocks
; i
> 0; i
--)
235 block
.words
[0] = ((uint32_t *) input
)[0] ^ ((uint32_t *) iv
)[0];
236 block
.words
[1] = ((uint32_t *) input
)[1] ^ ((uint32_t *) iv
)[1];
237 block
.words
[2] = ((uint32_t *) input
)[2] ^ ((uint32_t *) iv
)[2];
238 block
.words
[3] = ((uint32_t *) input
)[3] ^ ((uint32_t *) iv
)[3];
239 rijndaelEncrypt (key
->rk
, key
->Nr
, block
.bytes
, outBuffer
);
240 memcpy (cipher
->IV
, outBuffer
, 16);
246 case RIJNDAEL_MODE_CFB1
:
248 for (i
= numBlocks
; i
> 0; i
--)
250 memcpy (outBuffer
, input
, 16);
251 for (k
= 0; k
< 128; k
++)
253 rijndaelEncrypt (key
->ek
, key
->Nr
, iv
, block
.bytes
);
254 outBuffer
[k
>> 3] ^= (block
.bytes
[0] & 0x80U
) >> (k
& 7);
255 for (t
= 0; t
< 15; t
++)
257 iv
[t
] = (iv
[t
] << 1) | (iv
[t
+ 1] >> 7);
259 iv
[15] = (iv
[15] << 1) |
260 ((outBuffer
[k
>> 3] >> (7 - (k
& 7))) & 1);
268 return RIJNDAEL_BAD_CIPHER_STATE
;
271 return 128 * numBlocks
;
275 rijndaelPadEncrypt (rijndaelCipherInstance
*cipher
,
276 const rijndaelKeyInstance
*key
,
278 size_t inputOctets
, char *outBuffer
)
280 size_t i
, numBlocks
, padLen
;
281 union { char bytes
[16]; uint32_t words
[4]; } block
;
284 if (cipher
== NULL
|| key
== NULL
|| key
->direction
== RIJNDAEL_DIR_DECRYPT
)
286 return RIJNDAEL_BAD_CIPHER_STATE
;
288 if (input
== NULL
|| inputOctets
<= 0)
290 return 0; /* nothing to do */
293 numBlocks
= inputOctets
/ 16;
295 switch (cipher
->mode
)
297 case RIJNDAEL_MODE_ECB
:
298 for (i
= numBlocks
; i
> 0; i
--)
300 rijndaelEncrypt (key
->rk
, key
->Nr
, input
, outBuffer
);
304 padLen
= 16 - (inputOctets
- 16 * numBlocks
);
305 assert (padLen
> 0 && padLen
<= 16);
306 memcpy (block
.bytes
, input
, 16 - padLen
);
307 memset (block
.bytes
+ 16 - padLen
, padLen
, padLen
);
308 rijndaelEncrypt (key
->rk
, key
->Nr
, block
.bytes
, outBuffer
);
311 case RIJNDAEL_MODE_CBC
:
313 for (i
= numBlocks
; i
> 0; i
--)
315 block
.words
[0] = ((uint32_t *) input
)[0] ^ ((uint32_t *) iv
)[0];
316 block
.words
[1] = ((uint32_t *) input
)[1] ^ ((uint32_t *) iv
)[1];
317 block
.words
[2] = ((uint32_t *) input
)[2] ^ ((uint32_t *) iv
)[2];
318 block
.words
[3] = ((uint32_t *) input
)[3] ^ ((uint32_t *) iv
)[3];
319 rijndaelEncrypt (key
->rk
, key
->Nr
, block
.bytes
, outBuffer
);
320 memcpy (cipher
->IV
, outBuffer
, 16);
324 padLen
= 16 - (inputOctets
- 16 * numBlocks
);
325 assert (padLen
> 0 && padLen
<= 16);
326 for (i
= 0; i
< 16 - padLen
; i
++)
328 block
.bytes
[i
] = input
[i
] ^ iv
[i
];
330 for (i
= 16 - padLen
; i
< 16; i
++)
332 block
.bytes
[i
] = (char) padLen
^ iv
[i
];
334 rijndaelEncrypt (key
->rk
, key
->Nr
, block
.bytes
, outBuffer
);
335 memcpy (cipher
->IV
, outBuffer
, 16);
339 return RIJNDAEL_BAD_CIPHER_STATE
;
342 return 16 * (numBlocks
+ 1);
346 rijndaelBlockDecrypt (rijndaelCipherInstance
*cipher
,
347 const rijndaelKeyInstance
*key
,
349 size_t inputLen
, char *outBuffer
)
351 size_t i
, k
, t
, numBlocks
;
352 union { char bytes
[16]; uint32_t words
[4]; } block
;
357 || (cipher
->mode
!= RIJNDAEL_MODE_CFB1
358 && key
->direction
== RIJNDAEL_DIR_ENCRYPT
))
360 return RIJNDAEL_BAD_CIPHER_STATE
;
362 if (input
== NULL
|| inputLen
<= 0)
364 return 0; /* nothing to do */
367 numBlocks
= inputLen
/ 128;
369 switch (cipher
->mode
)
371 case RIJNDAEL_MODE_ECB
:
372 for (i
= numBlocks
; i
> 0; i
--)
374 rijndaelDecrypt (key
->rk
, key
->Nr
, input
, outBuffer
);
380 case RIJNDAEL_MODE_CBC
:
382 for (i
= numBlocks
; i
> 0; i
--)
384 rijndaelDecrypt (key
->rk
, key
->Nr
, input
, block
.bytes
);
385 block
.words
[0] ^= ((uint32_t *) iv
)[0];
386 block
.words
[1] ^= ((uint32_t *) iv
)[1];
387 block
.words
[2] ^= ((uint32_t *) iv
)[2];
388 block
.words
[3] ^= ((uint32_t *) iv
)[3];
389 memcpy (cipher
->IV
, input
, 16);
390 memcpy (outBuffer
, block
.bytes
, 16);
396 case RIJNDAEL_MODE_CFB1
:
398 for (i
= numBlocks
; i
> 0; i
--)
400 memcpy (outBuffer
, input
, 16);
401 for (k
= 0; k
< 128; k
++)
403 rijndaelEncrypt (key
->ek
, key
->Nr
, iv
, block
.bytes
);
404 for (t
= 0; t
< 15; t
++)
406 iv
[t
] = (iv
[t
] << 1) | (iv
[t
+ 1] >> 7);
408 iv
[15] = (iv
[15] << 1) | ((input
[k
>> 3] >> (7 - (k
& 7))) & 1);
409 outBuffer
[k
>> 3] ^= (block
.bytes
[0] & 0x80U
) >> (k
& 7);
417 return RIJNDAEL_BAD_CIPHER_STATE
;
420 return 128 * numBlocks
;
424 rijndaelPadDecrypt (rijndaelCipherInstance
*cipher
,
425 const rijndaelKeyInstance
*key
,
427 size_t inputOctets
, char *outBuffer
)
429 size_t i
, numBlocks
, padLen
;
430 union { char bytes
[16]; uint32_t words
[4]; } block
;
433 if (cipher
== NULL
|| key
== NULL
|| key
->direction
== RIJNDAEL_DIR_ENCRYPT
)
435 return RIJNDAEL_BAD_CIPHER_STATE
;
437 if (input
== NULL
|| inputOctets
<= 0)
439 return 0; /* nothing to do */
441 if (inputOctets
% 16 != 0)
443 return RIJNDAEL_BAD_DATA
;
446 numBlocks
= inputOctets
/ 16;
448 switch (cipher
->mode
)
450 case RIJNDAEL_MODE_ECB
:
451 /* all blocks but last */
452 for (i
= numBlocks
- 1; i
> 0; i
--)
454 rijndaelDecrypt (key
->rk
, key
->Nr
, input
, outBuffer
);
459 rijndaelDecrypt (key
->rk
, key
->Nr
, input
, block
.bytes
);
460 padLen
= block
.bytes
[15];
463 return RIJNDAEL_BAD_DATA
;
465 for (i
= 16 - padLen
; i
< 16; i
++)
467 if (block
.bytes
[i
] != padLen
)
469 return RIJNDAEL_BAD_DATA
;
472 memcpy (outBuffer
, block
.bytes
, 16 - padLen
);
475 case RIJNDAEL_MODE_CBC
:
477 /* all blocks but last */
478 for (i
= numBlocks
- 1; i
> 0; i
--)
480 rijndaelDecrypt (key
->rk
, key
->Nr
, input
, block
.bytes
);
481 block
.words
[0] ^= ((uint32_t *) iv
)[0];
482 block
.words
[1] ^= ((uint32_t *) iv
)[1];
483 block
.words
[2] ^= ((uint32_t *) iv
)[2];
484 block
.words
[3] ^= ((uint32_t *) iv
)[3];
485 memcpy (iv
, input
, 16);
486 memcpy (outBuffer
, block
.bytes
, 16);
491 rijndaelDecrypt (key
->rk
, key
->Nr
, input
, block
.bytes
);
492 block
.words
[0] ^= ((uint32_t *) iv
)[0];
493 block
.words
[1] ^= ((uint32_t *) iv
)[1];
494 block
.words
[2] ^= ((uint32_t *) iv
)[2];
495 block
.words
[3] ^= ((uint32_t *) iv
)[3];
496 padLen
= block
.bytes
[15];
497 if (padLen
<= 0 || padLen
> 16)
499 return RIJNDAEL_BAD_DATA
;
501 for (i
= 16 - padLen
; i
< 16; i
++)
503 if (block
.bytes
[i
] != padLen
)
505 return RIJNDAEL_BAD_DATA
;
508 memcpy (outBuffer
, block
.bytes
, 16 - padLen
);
512 return RIJNDAEL_BAD_CIPHER_STATE
;
515 return 16 * numBlocks
- padLen
;