diff options
Diffstat (limited to 'gnulib/lib/rijndael-api-fst.c')
m--------- | gnulib | 0 | ||||
-rw-r--r-- | gnulib/lib/rijndael-api-fst.c | 521 |
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; +} |