fchmod-tests, fchmodat tests, lchmod tests: Add more tests.
[gnulib.git] / lib / rijndael-api-fst.c
blobf829cda45ec60b59414170ddf00337a53f0ce463
1 /* rijndael-api-fst.c --- Rijndael cipher implementation.
2 * Copyright (C) 2005-2006, 2009-2021 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
26 #include <config.h>
28 /**
29 * rijndael-api-fst.c
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.
53 * Acknowledgements:
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
58 * missing reference.
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"
68 #include <assert.h>
69 #include <stdlib.h>
70 #include <string.h>
72 rijndael_rc
73 rijndaelMakeKey (rijndaelKeyInstance *key, rijndael_direction direction,
74 size_t keyLen, const char *keyMaterial)
76 size_t i;
77 char *keyMat;
78 char cipherKey[RIJNDAEL_MAXKB];
80 if (key == NULL)
82 return RIJNDAEL_BAD_KEY_INSTANCE;
85 if ((direction == RIJNDAEL_DIR_ENCRYPT)
86 || (direction == RIJNDAEL_DIR_DECRYPT))
88 key->direction = direction;
90 else
92 return RIJNDAEL_BAD_KEY_DIR;
95 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256))
97 key->keyLen = keyLen;
99 else
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++)
113 char t, v;
115 t = *keyMat++;
116 if ((t >= '0') && (t <= '9'))
117 v = (t - '0') << 4;
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;
122 else
123 return RIJNDAEL_BAD_KEY_MAT;
125 t = *keyMat++;
126 if ((t >= '0') && (t <= '9'))
127 v ^= (t - '0');
128 else if ((t >= 'a') && (t <= 'f'))
129 v ^= (t - 'a' + 10);
130 else if ((t >= 'A') && (t <= 'F'))
131 v ^= (t - 'A' + 10);
132 else
133 return RIJNDAEL_BAD_KEY_MAT;
135 cipherKey[i] = v;
137 if (direction == RIJNDAEL_DIR_ENCRYPT)
139 key->Nr = rijndaelKeySetupEnc (key->rk, cipherKey, keyLen);
141 else
143 key->Nr = rijndaelKeySetupDec (key->rk, cipherKey, keyLen);
145 rijndaelKeySetupEnc (key->ek, cipherKey, keyLen);
146 return 0;
149 rijndael_rc
150 rijndaelCipherInit (rijndaelCipherInstance *cipher, rijndael_mode mode,
151 const char *IV)
153 if ((mode == RIJNDAEL_MODE_ECB) || (mode == RIJNDAEL_MODE_CBC)
154 || (mode == RIJNDAEL_MODE_CFB1))
156 cipher->mode = mode;
158 else
160 return RIJNDAEL_BAD_CIPHER_MODE;
162 if (IV != NULL)
164 int i;
165 for (i = 0; i < RIJNDAEL_MAX_IV_SIZE; i++)
167 int t, j;
169 t = IV[2 * i];
170 if ((t >= '0') && (t <= '9'))
171 j = (t - '0') << 4;
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;
176 else
177 return RIJNDAEL_BAD_CIPHER_INSTANCE;
179 t = IV[2 * i + 1];
180 if ((t >= '0') && (t <= '9'))
181 j ^= (t - '0');
182 else if ((t >= 'a') && (t <= 'f'))
183 j ^= (t - 'a' + 10);
184 else if ((t >= 'A') && (t <= 'F'))
185 j ^= (t - 'A' + 10);
186 else
187 return RIJNDAEL_BAD_CIPHER_INSTANCE;
189 cipher->IV[i] = (uint8_t) j;
192 else
194 memset (cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
196 return 0;
200 rijndaelBlockEncrypt (rijndaelCipherInstance *cipher,
201 const rijndaelKeyInstance *key,
202 const char *input,
203 size_t inputLen, char *outBuffer)
205 size_t i, k, t, numBlocks;
206 union { char bytes[16]; uint32_t words[4]; } block;
207 char *iv;
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);
226 input += 16;
227 outBuffer += 16;
229 break;
231 case RIJNDAEL_MODE_CBC:
232 iv = cipher->IV;
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);
241 input += 16;
242 outBuffer += 16;
244 break;
246 case RIJNDAEL_MODE_CFB1:
247 iv = cipher->IV;
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);
262 outBuffer += 16;
263 input += 16;
265 break;
267 default:
268 return RIJNDAEL_BAD_CIPHER_STATE;
271 return 128 * numBlocks;
275 rijndaelPadEncrypt (rijndaelCipherInstance *cipher,
276 const rijndaelKeyInstance *key,
277 const char *input,
278 size_t inputOctets, char *outBuffer)
280 size_t i, numBlocks, padLen;
281 union { char bytes[16]; uint32_t words[4]; } block;
282 char *iv;
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);
301 input += 16;
302 outBuffer += 16;
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);
309 break;
311 case RIJNDAEL_MODE_CBC:
312 iv = cipher->IV;
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);
321 input += 16;
322 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);
336 break;
338 default:
339 return RIJNDAEL_BAD_CIPHER_STATE;
342 return 16 * (numBlocks + 1);
346 rijndaelBlockDecrypt (rijndaelCipherInstance *cipher,
347 const rijndaelKeyInstance *key,
348 const char *input,
349 size_t inputLen, char *outBuffer)
351 size_t i, k, t, numBlocks;
352 union { char bytes[16]; uint32_t words[4]; } block;
353 char *iv;
355 if (cipher == NULL
356 || key == NULL
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);
375 input += 16;
376 outBuffer += 16;
378 break;
380 case RIJNDAEL_MODE_CBC:
381 iv = cipher->IV;
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);
391 input += 16;
392 outBuffer += 16;
394 break;
396 case RIJNDAEL_MODE_CFB1:
397 iv = cipher->IV;
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);
411 outBuffer += 16;
412 input += 16;
414 break;
416 default:
417 return RIJNDAEL_BAD_CIPHER_STATE;
420 return 128 * numBlocks;
424 rijndaelPadDecrypt (rijndaelCipherInstance *cipher,
425 const rijndaelKeyInstance *key,
426 const char *input,
427 size_t inputOctets, char *outBuffer)
429 size_t i, numBlocks, padLen;
430 union { char bytes[16]; uint32_t words[4]; } block;
431 char *iv;
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);
455 input += 16;
456 outBuffer += 16;
458 /* last block */
459 rijndaelDecrypt (key->rk, key->Nr, input, block.bytes);
460 padLen = block.bytes[15];
461 if (padLen >= 16)
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);
473 break;
475 case RIJNDAEL_MODE_CBC:
476 iv = cipher->IV;
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);
487 input += 16;
488 outBuffer += 16;
490 /* last block */
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);
509 break;
511 default:
512 return RIJNDAEL_BAD_CIPHER_STATE;
515 return 16 * numBlocks - padLen;