summaryrefslogtreecommitdiff
path: root/gnulib/lib/rijndael-api-fst.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnulib/lib/rijndael-api-fst.c')
m---------gnulib0
-rw-r--r--gnulib/lib/rijndael-api-fst.c521
2 files changed, 521 insertions, 0 deletions
diff --git a/gnulib b/gnulib
deleted file mode 160000
-Subproject 4fc10daa05477586fea99b6b3ca02a87d1102fa
diff --git a/gnulib/lib/rijndael-api-fst.c b/gnulib/lib/rijndael-api-fst.c
new file mode 100644
index 00000000..23ba9b23
--- /dev/null
+++ b/gnulib/lib/rijndael-api-fst.c
@@ -0,0 +1,521 @@
+/* rijndael-api-fst.c --- Rijndael cipher implementation.
+ * Copyright (C) 2005, 2006, 2009, 2010 Free Software Foundation, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+/* Adapted for gnulib by Simon Josefsson.
+ *
+ * Based on public domain "Optimised C code" retrieved from (SHA1
+ * 7c8e4b00d06685d1dbc6724a9e0d502353de339e):
+ * http://www.iaik.tu-graz.ac.at/research/krypto/AES/old/~rijmen/rijndael/rijndael-fst-3.0.zip
+ */
+
+#include <config.h>
+
+/**
+ * rijndael-api-fst.c
+ *
+ * @version 2.9 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Acknowledgements:
+ *
+ * We are deeply indebted to the following people for their bug reports,
+ * fixes, and improvement suggestions to this implementation. Though we
+ * tried to list all contributions, we apologise in advance for any
+ * missing reference.
+ *
+ * Andrew Bales <Andrew.Bales@Honeywell.com>
+ * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
+ * John Skodon <skodonj@webquill.com>
+ */
+
+#include "rijndael-alg-fst.h"
+#include "rijndael-api-fst.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+rijndael_rc
+rijndaelMakeKey (rijndaelKeyInstance *key, rijndael_direction direction,
+ size_t keyLen, const char *keyMaterial)
+{
+ size_t i;
+ char *keyMat;
+ char cipherKey[RIJNDAEL_MAXKB];
+
+ if (key == NULL)
+ {
+ return RIJNDAEL_BAD_KEY_INSTANCE;
+ }
+
+ if ((direction == RIJNDAEL_DIR_ENCRYPT)
+ || (direction == RIJNDAEL_DIR_DECRYPT))
+ {
+ key->direction = direction;
+ }
+ else
+ {
+ return RIJNDAEL_BAD_KEY_DIR;
+ }
+
+ if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256))
+ {
+ key->keyLen = keyLen;
+ }
+ else
+ {
+ return RIJNDAEL_BAD_KEY_MAT;
+ }
+
+ if (keyMaterial != NULL)
+ {
+ strncpy (key->keyMaterial, keyMaterial, keyLen / 4);
+ }
+
+ /* initialize key schedule: */
+ keyMat = key->keyMaterial;
+ for (i = 0; i < key->keyLen / 8; i++)
+ {
+ char t, v;
+
+ t = *keyMat++;
+ if ((t >= '0') && (t <= '9'))
+ v = (t - '0') << 4;
+ else if ((t >= 'a') && (t <= 'f'))
+ v = (t - 'a' + 10) << 4;
+ else if ((t >= 'A') && (t <= 'F'))
+ v = (t - 'A' + 10) << 4;
+ else
+ return RIJNDAEL_BAD_KEY_MAT;
+
+ t = *keyMat++;
+ if ((t >= '0') && (t <= '9'))
+ v ^= (t - '0');
+ else if ((t >= 'a') && (t <= 'f'))
+ v ^= (t - 'a' + 10);
+ else if ((t >= 'A') && (t <= 'F'))
+ v ^= (t - 'A' + 10);
+ else
+ return RIJNDAEL_BAD_KEY_MAT;
+
+ cipherKey[i] = v;
+ }
+ if (direction == RIJNDAEL_DIR_ENCRYPT)
+ {
+ key->Nr = rijndaelKeySetupEnc (key->rk, cipherKey, keyLen);
+ }
+ else
+ {
+ key->Nr = rijndaelKeySetupDec (key->rk, cipherKey, keyLen);
+ }
+ rijndaelKeySetupEnc (key->ek, cipherKey, keyLen);
+ return 0;
+}
+
+rijndael_rc
+rijndaelCipherInit (rijndaelCipherInstance *cipher, rijndael_mode mode,
+ const char *IV)
+{
+ if ((mode == RIJNDAEL_MODE_ECB) || (mode == RIJNDAEL_MODE_CBC)
+ || (mode == RIJNDAEL_MODE_CFB1))
+ {
+ cipher->mode = mode;
+ }
+ else
+ {
+ return RIJNDAEL_BAD_CIPHER_MODE;
+ }
+ if (IV != NULL)
+ {
+ int i;
+ for (i = 0; i < RIJNDAEL_MAX_IV_SIZE; i++)
+ {
+ int t, j;
+
+ t = IV[2 * i];
+ if ((t >= '0') && (t <= '9'))
+ j = (t - '0') << 4;
+ else if ((t >= 'a') && (t <= 'f'))
+ j = (t - 'a' + 10) << 4;
+ else if ((t >= 'A') && (t <= 'F'))
+ j = (t - 'A' + 10) << 4;
+ else
+ return RIJNDAEL_BAD_CIPHER_INSTANCE;
+
+ t = IV[2 * i + 1];
+ if ((t >= '0') && (t <= '9'))
+ j ^= (t - '0');
+ else if ((t >= 'a') && (t <= 'f'))
+ j ^= (t - 'a' + 10);
+ else if ((t >= 'A') && (t <= 'F'))
+ j ^= (t - 'A' + 10);
+ else
+ return RIJNDAEL_BAD_CIPHER_INSTANCE;
+
+ cipher->IV[i] = (uint8_t) j;
+ }
+ }
+ else
+ {
+ memset (cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
+ }
+ return 0;
+}
+
+int
+rijndaelBlockEncrypt (rijndaelCipherInstance *cipher,
+ const rijndaelKeyInstance *key,
+ const char *input,
+ size_t inputLen, char *outBuffer)
+{
+ size_t i, k, t, numBlocks;
+ char block[16], *iv;
+
+ if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_DECRYPT)
+ {
+ return RIJNDAEL_BAD_CIPHER_STATE;
+ }
+ if (input == NULL || inputLen <= 0)
+ {
+ return 0; /* nothing to do */
+ }
+
+ numBlocks = inputLen / 128;
+
+ switch (cipher->mode)
+ {
+ case RIJNDAEL_MODE_ECB:
+ for (i = numBlocks; i > 0; i--)
+ {
+ rijndaelEncrypt (key->rk, key->Nr, input, outBuffer);
+ input += 16;
+ outBuffer += 16;
+ }
+ break;
+
+ case RIJNDAEL_MODE_CBC:
+ iv = cipher->IV;
+ for (i = numBlocks; i > 0; i--)
+ {
+ ((uint32_t *) block)[0] = ((uint32_t *) input)[0] ^
+ ((uint32_t *) iv)[0];
+ ((uint32_t *) block)[1] = ((uint32_t *) input)[1] ^
+ ((uint32_t *) iv)[1];
+ ((uint32_t *) block)[2] = ((uint32_t *) input)[2] ^
+ ((uint32_t *) iv)[2];
+ ((uint32_t *) block)[3] = ((uint32_t *) input)[3] ^
+ ((uint32_t *) iv)[3];
+ rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
+ memcpy (cipher->IV, outBuffer, 16);
+ input += 16;
+ outBuffer += 16;
+ }
+ break;
+
+ case RIJNDAEL_MODE_CFB1:
+ iv = cipher->IV;
+ for (i = numBlocks; i > 0; i--)
+ {
+ memcpy (outBuffer, input, 16);
+ for (k = 0; k < 128; k++)
+ {
+ rijndaelEncrypt (key->ek, key->Nr, iv, block);
+ outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
+ for (t = 0; t < 15; t++)
+ {
+ iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
+ }
+ iv[15] = (iv[15] << 1) |
+ ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
+ }
+ outBuffer += 16;
+ input += 16;
+ }
+ break;
+
+ default:
+ return RIJNDAEL_BAD_CIPHER_STATE;
+ }
+
+ return 128 * numBlocks;
+}
+
+int
+rijndaelPadEncrypt (rijndaelCipherInstance *cipher,
+ const rijndaelKeyInstance *key,
+ const char *input,
+ size_t inputOctets, char *outBuffer)
+{
+ size_t i, numBlocks, padLen;
+ char block[16], *iv;
+
+ if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_DECRYPT)
+ {
+ return RIJNDAEL_BAD_CIPHER_STATE;
+ }
+ if (input == NULL || inputOctets <= 0)
+ {
+ return 0; /* nothing to do */
+ }
+
+ numBlocks = inputOctets / 16;
+
+ switch (cipher->mode)
+ {
+ case RIJNDAEL_MODE_ECB:
+ for (i = numBlocks; i > 0; i--)
+ {
+ rijndaelEncrypt (key->rk, key->Nr, input, outBuffer);
+ input += 16;
+ outBuffer += 16;
+ }
+ padLen = 16 - (inputOctets - 16 * numBlocks);
+ assert (padLen > 0 && padLen <= 16);
+ memcpy (block, input, 16 - padLen);
+ memset (block + 16 - padLen, padLen, padLen);
+ rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
+ break;
+
+ case RIJNDAEL_MODE_CBC:
+ iv = cipher->IV;
+ for (i = numBlocks; i > 0; i--)
+ {
+ ((uint32_t *) block)[0] = ((uint32_t *) input)[0] ^
+ ((uint32_t *) iv)[0];
+ ((uint32_t *) block)[1] = ((uint32_t *) input)[1] ^
+ ((uint32_t *) iv)[1];
+ ((uint32_t *) block)[2] = ((uint32_t *) input)[2] ^
+ ((uint32_t *) iv)[2];
+ ((uint32_t *) block)[3] = ((uint32_t *) input)[3] ^
+ ((uint32_t *) iv)[3];
+ rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
+ memcpy (cipher->IV, outBuffer, 16);
+ input += 16;
+ outBuffer += 16;
+ }
+ padLen = 16 - (inputOctets - 16 * numBlocks);
+ assert (padLen > 0 && padLen <= 16);
+ for (i = 0; i < 16 - padLen; i++)
+ {
+ block[i] = input[i] ^ iv[i];
+ }
+ for (i = 16 - padLen; i < 16; i++)
+ {
+ block[i] = (char) padLen ^ iv[i];
+ }
+ rijndaelEncrypt (key->rk, key->Nr, block, outBuffer);
+ memcpy (cipher->IV, outBuffer, 16);
+ break;
+
+ default:
+ return RIJNDAEL_BAD_CIPHER_STATE;
+ }
+
+ return 16 * (numBlocks + 1);
+}
+
+int
+rijndaelBlockDecrypt (rijndaelCipherInstance *cipher,
+ const rijndaelKeyInstance *key,
+ const char *input,
+ size_t inputLen, char *outBuffer)
+{
+ size_t i, k, t, numBlocks;
+ char block[16], *iv;
+
+ if (cipher == NULL
+ || key == NULL
+ || (cipher->mode != RIJNDAEL_MODE_CFB1
+ && key->direction == RIJNDAEL_DIR_ENCRYPT))
+ {
+ return RIJNDAEL_BAD_CIPHER_STATE;
+ }
+ if (input == NULL || inputLen <= 0)
+ {
+ return 0; /* nothing to do */
+ }
+
+ numBlocks = inputLen / 128;
+
+ switch (cipher->mode)
+ {
+ case RIJNDAEL_MODE_ECB:
+ for (i = numBlocks; i > 0; i--)
+ {
+ rijndaelDecrypt (key->rk, key->Nr, input, outBuffer);
+ input += 16;
+ outBuffer += 16;
+ }
+ break;
+
+ case RIJNDAEL_MODE_CBC:
+ iv = cipher->IV;
+ for (i = numBlocks; i > 0; i--)
+ {
+ rijndaelDecrypt (key->rk, key->Nr, input, block);
+ ((uint32_t *) block)[0] ^= ((uint32_t *) iv)[0];
+ ((uint32_t *) block)[1] ^= ((uint32_t *) iv)[1];
+ ((uint32_t *) block)[2] ^= ((uint32_t *) iv)[2];
+ ((uint32_t *) block)[3] ^= ((uint32_t *) iv)[3];
+ memcpy (cipher->IV, input, 16);
+ memcpy (outBuffer, block, 16);
+ input += 16;
+ outBuffer += 16;
+ }
+ break;
+
+ case RIJNDAEL_MODE_CFB1:
+ iv = cipher->IV;
+ for (i = numBlocks; i > 0; i--)
+ {
+ memcpy (outBuffer, input, 16);
+ for (k = 0; k < 128; k++)
+ {
+ rijndaelEncrypt (key->ek, key->Nr, iv, block);
+ for (t = 0; t < 15; t++)
+ {
+ iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
+ }
+ iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
+ outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
+ }
+ outBuffer += 16;
+ input += 16;
+ }
+ break;
+
+ default:
+ return RIJNDAEL_BAD_CIPHER_STATE;
+ }
+
+ return 128 * numBlocks;
+}
+
+int
+rijndaelPadDecrypt (rijndaelCipherInstance *cipher,
+ const rijndaelKeyInstance *key,
+ const char *input,
+ size_t inputOctets, char *outBuffer)
+{
+ size_t i, numBlocks, padLen;
+ char block[16];
+
+ if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_ENCRYPT)
+ {
+ return RIJNDAEL_BAD_CIPHER_STATE;
+ }
+ if (input == NULL || inputOctets <= 0)
+ {
+ return 0; /* nothing to do */
+ }
+ if (inputOctets % 16 != 0)
+ {
+ return RIJNDAEL_BAD_DATA;
+ }
+
+ numBlocks = inputOctets / 16;
+
+ switch (cipher->mode)
+ {
+ case RIJNDAEL_MODE_ECB:
+ /* all blocks but last */
+ for (i = numBlocks - 1; i > 0; i--)
+ {
+ rijndaelDecrypt (key->rk, key->Nr, input, outBuffer);
+ input += 16;
+ outBuffer += 16;
+ }
+ /* last block */
+ rijndaelDecrypt (key->rk, key->Nr, input, block);
+ padLen = block[15];
+ if (padLen >= 16)
+ {
+ return RIJNDAEL_BAD_DATA;
+ }
+ for (i = 16 - padLen; i < 16; i++)
+ {
+ if (block[i] != padLen)
+ {
+ return RIJNDAEL_BAD_DATA;
+ }
+ }
+ memcpy (outBuffer, block, 16 - padLen);
+ break;
+
+ case RIJNDAEL_MODE_CBC:
+ /* all blocks but last */
+ for (i = numBlocks - 1; i > 0; i--)
+ {
+ rijndaelDecrypt (key->rk, key->Nr, input, block);
+ ((uint32_t *) block)[0] ^= ((uint32_t *) cipher->IV)[0];
+ ((uint32_t *) block)[1] ^= ((uint32_t *) cipher->IV)[1];
+ ((uint32_t *) block)[2] ^= ((uint32_t *) cipher->IV)[2];
+ ((uint32_t *) block)[3] ^= ((uint32_t *) cipher->IV)[3];
+ memcpy (cipher->IV, input, 16);
+ memcpy (outBuffer, block, 16);
+ input += 16;
+ outBuffer += 16;
+ }
+ /* last block */
+ rijndaelDecrypt (key->rk, key->Nr, input, block);
+ ((uint32_t *) block)[0] ^= ((uint32_t *) cipher->IV)[0];
+ ((uint32_t *) block)[1] ^= ((uint32_t *) cipher->IV)[1];
+ ((uint32_t *) block)[2] ^= ((uint32_t *) cipher->IV)[2];
+ ((uint32_t *) block)[3] ^= ((uint32_t *) cipher->IV)[3];
+ padLen = block[15];
+ if (padLen <= 0 || padLen > 16)
+ {
+ return RIJNDAEL_BAD_DATA;
+ }
+ for (i = 16 - padLen; i < 16; i++)
+ {
+ if (block[i] != padLen)
+ {
+ return RIJNDAEL_BAD_DATA;
+ }
+ }
+ memcpy (outBuffer, block, 16 - padLen);
+ break;
+
+ default:
+ return RIJNDAEL_BAD_CIPHER_STATE;
+ }
+
+ return 16 * numBlocks - padLen;
+}