root/maint/gnulib/lib/rijndael-api-fst.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rijndaelMakeKey
  2. rijndaelCipherInit
  3. rijndaelBlockEncrypt
  4. rijndaelPadEncrypt
  5. rijndaelBlockDecrypt
  6. rijndaelPadDecrypt

   1 /* rijndael-api-fst.c --- Rijndael cipher implementation.
   2  * Copyright (C) 2005-2006, 2009-2021 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 Lesser General Public License as
   6  * published by the Free Software Foundation; either version 2.1 of the
   7  * License, or (at your option) any later version.
   8  *
   9  * This file is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  * GNU Lesser General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU Lesser General Public License
  15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  16  *
  17  */
  18 
  19 /* Adapted for gnulib by Simon Josefsson.
  20  *
  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
  24  */
  25 
  26 #include <config.h>
  27 
  28 /**
  29  * rijndael-api-fst.c
  30  *
  31  * @version 2.9 (December 2000)
  32  *
  33  * Optimised ANSI C code for the Rijndael cipher (now AES)
  34  *
  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>
  38  *
  39  * This code is hereby placed in the public domain.
  40  *
  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.
  52  *
  53  * Acknowledgements:
  54  *
  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.
  59  *
  60  * Andrew Bales <Andrew.Bales@Honeywell.com>
  61  * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
  62  * John Skodon <skodonj@webquill.com>
  63  */
  64 
  65 #include "rijndael-alg-fst.h"
  66 #include "rijndael-api-fst.h"
  67 
  68 #include <assert.h>
  69 #include <stdlib.h>
  70 #include <string.h>
  71 
  72 rijndael_rc
  73 rijndaelMakeKey (rijndaelKeyInstance *key, rijndael_direction direction,
     /* [previous][next][first][last][top][bottom][index][help] */
  74                  size_t keyLen, const char *keyMaterial)
  75 {
  76   size_t i;
  77   char *keyMat;
  78   char cipherKey[RIJNDAEL_MAXKB];
  79 
  80   if (key == NULL)
  81     {
  82       return RIJNDAEL_BAD_KEY_INSTANCE;
  83     }
  84 
  85   if ((direction == RIJNDAEL_DIR_ENCRYPT)
  86       || (direction == RIJNDAEL_DIR_DECRYPT))
  87     {
  88       key->direction = direction;
  89     }
  90   else
  91     {
  92       return RIJNDAEL_BAD_KEY_DIR;
  93     }
  94 
  95   if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256))
  96     {
  97       key->keyLen = keyLen;
  98     }
  99   else
 100     {
 101       return RIJNDAEL_BAD_KEY_MAT;
 102     }
 103 
 104   if (keyMaterial != NULL)
 105     {
 106       strncpy (key->keyMaterial, keyMaterial, keyLen / 4);
 107     }
 108 
 109   /* initialize key schedule: */
 110   keyMat = key->keyMaterial;
 111   for (i = 0; i < key->keyLen / 8; i++)
 112     {
 113       char t, v;
 114 
 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;
 124 
 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;
 134 
 135       cipherKey[i] = v;
 136     }
 137   if (direction == RIJNDAEL_DIR_ENCRYPT)
 138     {
 139       key->Nr = rijndaelKeySetupEnc (key->rk, cipherKey, keyLen);
 140     }
 141   else
 142     {
 143       key->Nr = rijndaelKeySetupDec (key->rk, cipherKey, keyLen);
 144     }
 145   rijndaelKeySetupEnc (key->ek, cipherKey, keyLen);
 146   return 0;
 147 }
 148 
 149 rijndael_rc
 150 rijndaelCipherInit (rijndaelCipherInstance *cipher, rijndael_mode mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 151                     const char *IV)
 152 {
 153   if ((mode == RIJNDAEL_MODE_ECB) || (mode == RIJNDAEL_MODE_CBC)
 154       || (mode == RIJNDAEL_MODE_CFB1))
 155     {
 156       cipher->mode = mode;
 157     }
 158   else
 159     {
 160       return RIJNDAEL_BAD_CIPHER_MODE;
 161     }
 162   if (IV != NULL)
 163     {
 164       int i;
 165       for (i = 0; i < RIJNDAEL_MAX_IV_SIZE; i++)
 166         {
 167           int t, j;
 168 
 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;
 178 
 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;
 188 
 189           cipher->IV[i] = (uint8_t) j;
 190         }
 191     }
 192   else
 193     {
 194       memset (cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
 195     }
 196   return 0;
 197 }
 198 
 199 int
 200 rijndaelBlockEncrypt (rijndaelCipherInstance *cipher,
     /* [previous][next][first][last][top][bottom][index][help] */
 201                       const rijndaelKeyInstance *key,
 202                       const char *input,
 203                       size_t inputLen, char *outBuffer)
 204 {
 205   size_t i, k, t, numBlocks;
 206   union { char bytes[16]; uint32_t words[4]; } block;
 207   char *iv;
 208 
 209   if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_DECRYPT)
 210     {
 211       return RIJNDAEL_BAD_CIPHER_STATE;
 212     }
 213   if (input == NULL || inputLen <= 0)
 214     {
 215       return 0;                 /* nothing to do */
 216     }
 217 
 218   numBlocks = inputLen / 128;
 219 
 220   switch (cipher->mode)
 221     {
 222     case RIJNDAEL_MODE_ECB:
 223       for (i = numBlocks; i > 0; i--)
 224         {
 225           rijndaelEncrypt (key->rk, key->Nr, input, outBuffer);
 226           input += 16;
 227           outBuffer += 16;
 228         }
 229       break;
 230 
 231     case RIJNDAEL_MODE_CBC:
 232       iv = cipher->IV;
 233       for (i = numBlocks; i > 0; i--)
 234         {
 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;
 243         }
 244       break;
 245 
 246     case RIJNDAEL_MODE_CFB1:
 247       iv = cipher->IV;
 248       for (i = numBlocks; i > 0; i--)
 249         {
 250           memcpy (outBuffer, input, 16);
 251           for (k = 0; k < 128; k++)
 252             {
 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++)
 256                 {
 257                   iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
 258                 }
 259               iv[15] = (iv[15] << 1) |
 260                 ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
 261             }
 262           outBuffer += 16;
 263           input += 16;
 264         }
 265       break;
 266 
 267     default:
 268       return RIJNDAEL_BAD_CIPHER_STATE;
 269     }
 270 
 271   return 128 * numBlocks;
 272 }
 273 
 274 int
 275 rijndaelPadEncrypt (rijndaelCipherInstance *cipher,
     /* [previous][next][first][last][top][bottom][index][help] */
 276                     const rijndaelKeyInstance *key,
 277                     const char *input,
 278                     size_t inputOctets, char *outBuffer)
 279 {
 280   size_t i, numBlocks, padLen;
 281   union { char bytes[16]; uint32_t words[4]; } block;
 282   char *iv;
 283 
 284   if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_DECRYPT)
 285     {
 286       return RIJNDAEL_BAD_CIPHER_STATE;
 287     }
 288   if (input == NULL || inputOctets <= 0)
 289     {
 290       return 0;                 /* nothing to do */
 291     }
 292 
 293   numBlocks = inputOctets / 16;
 294 
 295   switch (cipher->mode)
 296     {
 297     case RIJNDAEL_MODE_ECB:
 298       for (i = numBlocks; i > 0; i--)
 299         {
 300           rijndaelEncrypt (key->rk, key->Nr, input, outBuffer);
 301           input += 16;
 302           outBuffer += 16;
 303         }
 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;
 310 
 311     case RIJNDAEL_MODE_CBC:
 312       iv = cipher->IV;
 313       for (i = numBlocks; i > 0; i--)
 314         {
 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;
 323         }
 324       padLen = 16 - (inputOctets - 16 * numBlocks);
 325       assert (padLen > 0 && padLen <= 16);
 326       for (i = 0; i < 16 - padLen; i++)
 327         {
 328           block.bytes[i] = input[i] ^ iv[i];
 329         }
 330       for (i = 16 - padLen; i < 16; i++)
 331         {
 332           block.bytes[i] = (char) padLen ^ iv[i];
 333         }
 334       rijndaelEncrypt (key->rk, key->Nr, block.bytes, outBuffer);
 335       memcpy (cipher->IV, outBuffer, 16);
 336       break;
 337 
 338     default:
 339       return RIJNDAEL_BAD_CIPHER_STATE;
 340     }
 341 
 342   return 16 * (numBlocks + 1);
 343 }
 344 
 345 int
 346 rijndaelBlockDecrypt (rijndaelCipherInstance *cipher,
     /* [previous][next][first][last][top][bottom][index][help] */
 347                       const rijndaelKeyInstance *key,
 348                       const char *input,
 349                       size_t inputLen, char *outBuffer)
 350 {
 351   size_t i, k, t, numBlocks;
 352   union { char bytes[16]; uint32_t words[4]; } block;
 353   char *iv;
 354 
 355   if (cipher == NULL
 356       || key == NULL
 357       || (cipher->mode != RIJNDAEL_MODE_CFB1
 358           && key->direction == RIJNDAEL_DIR_ENCRYPT))
 359     {
 360       return RIJNDAEL_BAD_CIPHER_STATE;
 361     }
 362   if (input == NULL || inputLen <= 0)
 363     {
 364       return 0;                 /* nothing to do */
 365     }
 366 
 367   numBlocks = inputLen / 128;
 368 
 369   switch (cipher->mode)
 370     {
 371     case RIJNDAEL_MODE_ECB:
 372       for (i = numBlocks; i > 0; i--)
 373         {
 374           rijndaelDecrypt (key->rk, key->Nr, input, outBuffer);
 375           input += 16;
 376           outBuffer += 16;
 377         }
 378       break;
 379 
 380     case RIJNDAEL_MODE_CBC:
 381       iv = cipher->IV;
 382       for (i = numBlocks; i > 0; i--)
 383         {
 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;
 393         }
 394       break;
 395 
 396     case RIJNDAEL_MODE_CFB1:
 397       iv = cipher->IV;
 398       for (i = numBlocks; i > 0; i--)
 399         {
 400           memcpy (outBuffer, input, 16);
 401           for (k = 0; k < 128; k++)
 402             {
 403               rijndaelEncrypt (key->ek, key->Nr, iv, block.bytes);
 404               for (t = 0; t < 15; t++)
 405                 {
 406                   iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
 407                 }
 408               iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
 409               outBuffer[k >> 3] ^= (block.bytes[0] & 0x80U) >> (k & 7);
 410             }
 411           outBuffer += 16;
 412           input += 16;
 413         }
 414       break;
 415 
 416     default:
 417       return RIJNDAEL_BAD_CIPHER_STATE;
 418     }
 419 
 420   return 128 * numBlocks;
 421 }
 422 
 423 int
 424 rijndaelPadDecrypt (rijndaelCipherInstance *cipher,
     /* [previous][next][first][last][top][bottom][index][help] */
 425                     const rijndaelKeyInstance *key,
 426                     const char *input,
 427                     size_t inputOctets, char *outBuffer)
 428 {
 429   size_t i, numBlocks, padLen;
 430   union { char bytes[16]; uint32_t words[4]; } block;
 431   char *iv;
 432 
 433   if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_ENCRYPT)
 434     {
 435       return RIJNDAEL_BAD_CIPHER_STATE;
 436     }
 437   if (input == NULL || inputOctets <= 0)
 438     {
 439       return 0;                 /* nothing to do */
 440     }
 441   if (inputOctets % 16 != 0)
 442     {
 443       return RIJNDAEL_BAD_DATA;
 444     }
 445 
 446   numBlocks = inputOctets / 16;
 447 
 448   switch (cipher->mode)
 449     {
 450     case RIJNDAEL_MODE_ECB:
 451       /* all blocks but last */
 452       for (i = numBlocks - 1; i > 0; i--)
 453         {
 454           rijndaelDecrypt (key->rk, key->Nr, input, outBuffer);
 455           input += 16;
 456           outBuffer += 16;
 457         }
 458       /* last block */
 459       rijndaelDecrypt (key->rk, key->Nr, input, block.bytes);
 460       padLen = block.bytes[15];
 461       if (padLen >= 16)
 462         {
 463           return RIJNDAEL_BAD_DATA;
 464         }
 465       for (i = 16 - padLen; i < 16; i++)
 466         {
 467           if (block.bytes[i] != padLen)
 468             {
 469               return RIJNDAEL_BAD_DATA;
 470             }
 471         }
 472       memcpy (outBuffer, block.bytes, 16 - padLen);
 473       break;
 474 
 475     case RIJNDAEL_MODE_CBC:
 476       iv = cipher->IV;
 477       /* all blocks but last */
 478       for (i = numBlocks - 1; i > 0; i--)
 479         {
 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;
 489         }
 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)
 498         {
 499           return RIJNDAEL_BAD_DATA;
 500         }
 501       for (i = 16 - padLen; i < 16; i++)
 502         {
 503           if (block.bytes[i] != padLen)
 504             {
 505               return RIJNDAEL_BAD_DATA;
 506             }
 507         }
 508       memcpy (outBuffer, block.bytes, 16 - padLen);
 509       break;
 510 
 511     default:
 512       return RIJNDAEL_BAD_CIPHER_STATE;
 513     }
 514 
 515   return 16 * numBlocks - padLen;
 516 }

/* [previous][next][first][last][top][bottom][index][help] */