diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1092e46..753e3c5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -96,7 +96,7 @@ add_library(n2n STATIC
src/sn_utils.c
src/wire.c
src/minilzo.c
- src/twofish.c
+ src/tf.c
src/transform_null.c
src/transform_tf.c
src/transform_aes.c
diff --git a/include/n2n.h b/include/n2n.h
index 8c0e4fa..dc08248 100644
--- a/include/n2n.h
+++ b/include/n2n.h
@@ -406,7 +406,7 @@ typedef struct n2n_sn
/* ************************************** */
#include "header_encryption.h"
-#include "twofish.h"
+#include "tf.h"
#ifndef TRACE_ERROR
#define TRACE_ERROR 0, __FILE__, __LINE__
@@ -420,7 +420,7 @@ typedef struct n2n_sn
/* Transop Init Functions */
int n2n_transop_null_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt);
-int n2n_transop_twofish_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt);
+int n2n_transop_tf_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt);
#ifdef N2N_HAVE_AES
int n2n_transop_aes_cbc_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt);
#endif
diff --git a/include/tf.h b/include/tf.h
new file mode 100644
index 0000000..f4ea3cc
--- /dev/null
+++ b/include/tf.h
@@ -0,0 +1,82 @@
+/**
+ * (C) 2007-20 - ntop.org and contributors
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program; if not see see
+ *
+ */
+
+
+// taken (and modified) from github/fudanchii/twofish as of August 2020
+// which itself is a modified copy of Andrew T. Csillag's implementation
+// published on github/drewcsillag/twofish
+
+
+/*
+The MIT License (MIT)
+
+Copyright (c) 2015 Andrew T. Csillag
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef TF_H
+#define TF_H
+
+#include
+#include
+#include
+
+
+#define TF_BLOCK_SIZE 16
+#define TF_IV_SIZE (TF_BLOCK_SIZE)
+
+
+typedef struct tf_context_t {
+ int N;
+ uint32_t K[40];
+ uint32_t QF[4][256];
+} tf_context_t;
+
+
+int tf_ecb_decrypt (unsigned char *out, const unsigned char *in, tf_context_t *ctx);
+
+int tf_ecb_encrypt (unsigned char *out, const unsigned char *in, tf_context_t *ctx);
+
+int tf_cbc_encrypt (unsigned char *out, const unsigned char *in, size_t in_len,
+ const unsigned char *iv, tf_context_t *ctx);
+
+int tf_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len,
+ const unsigned char *iv, tf_context_t *ctx);
+
+int tf_init (const unsigned char *key, size_t key_size, tf_context_t **ctx);
+
+
+#endif // TF_H
diff --git a/include/twofish.h b/include/twofish.h
deleted file mode 100644
index d42e640..0000000
--- a/include/twofish.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/* $Id: twofish.h,v 2.0 2002/08/11 22:32:25 fknobbe Exp $
- *
- *
- * Copyright (C) 1997-2000 The Cryptix Foundation Limited.
- * Copyright (C) 2000 Farm9.
- * Copyright (C) 2001 Frank Knobbe.
- * All rights reserved.
- *
- * For Cryptix code:
- * Use, modification, copying and distribution of this software is subject
- * the terms and conditions of the Cryptix General Licence. You should have
- * received a copy of the Cryptix General Licence along with this library;
- * if not, you can download a copy from http://www.cryptix.org/ .
- *
- * For Farm9:
- * --- jojo@farm9.com, August 2000, converted from Java to C++, added CBC mode and
- * ciphertext stealing technique, added AsciiTwofish class for easy encryption
- * decryption of text strings
- *
- * Frank Knobbe :
- * --- April 2001, converted from C++ to C, prefixed global variables
- * with TwoFish, substituted some defines, changed functions to make use of
- * variables supplied in a struct, modified and added routines for modular calls.
- * Cleaned up the code so that defines are used instead of fixed 16's and 32's.
- * Created two general purpose crypt routines for one block and multiple block
- * encryption using Joh's CBC code.
- * Added crypt routines that use a header (with a magic and data length).
- * (Basically a major rewrite).
- *
- * Note: Routines labeled _TwoFish are private and should not be used
- * (or with extreme caution).
- *
- */
-
-#ifndef __TWOFISH_LIBRARY_HEADER__
-#define __TWOFISH_LIBRARY_HEADER__
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef TRUE
-#define TRUE !FALSE
-#endif
-#ifndef bool
-#define bool int
-#endif
-
-#ifdef WIN32
-#include "win32/n2n_win32.h"
-#endif
-
-#ifndef _MSC_VER
-/* Not shipped with Visual Studio (as stated by the stdint.h wikipedia page) */
-#include /* defines uintN_t types */
-#endif
-
-#ifdef __sun__ /* Should be HAVE_SYS_TYPES */
-/* The following are redefinitions if sys/types.h has been included too.*/
-typedef uint32_t uint32_t;
-typedef uint8_t uint8_t;
-#endif /* #ifdef __sun__ */
-
-/* Constants */
-
-#define TwoFish_DEFAULT_PW_LEN 32
-#define TwoFish_MAGIC "TwoFish" /* to indentify a successful decryption */
-
-enum
-{ TwoFish_KEY_SIZE = 256, /* Valid values: 64, 128, 192, 256 */
- /* User 256, other key sizes have not been tested. */
- /* (But should work. I substitutes as much as */
- /* I could with this define.) */
- TwoFish_ROUNDS = 16,
- TwoFish_BLOCK_SIZE = 16, /* bytes in a data-block */
- TwoFish_KEY_LENGTH = TwoFish_KEY_SIZE/8, /* 32= 256-bit key */
- TwoFish_TOTAL_SUBKEYS = 4+4+2*TwoFish_ROUNDS,
- TwoFish_MAGIC_LEN = TwoFish_BLOCK_SIZE-8,
- TwoFish_SK_BUMP = 0x01010101,
- TwoFish_SK_ROTL = 9,
- TwoFish_P_00 = 1,
- TwoFish_P_01 = 0,
- TwoFish_P_02 = 0,
- TwoFish_P_03 = TwoFish_P_01 ^ 1,
- TwoFish_P_04 = 1,
- TwoFish_P_10 = 0,
- TwoFish_P_11 = 0,
- TwoFish_P_12 = 1,
- TwoFish_P_13 = TwoFish_P_11 ^ 1,
- TwoFish_P_14 = 0,
- TwoFish_P_20 = 1,
- TwoFish_P_21 = 1,
- TwoFish_P_22 = 0,
- TwoFish_P_23 = TwoFish_P_21 ^ 1,
- TwoFish_P_24 = 0,
- TwoFish_P_30 = 0,
- TwoFish_P_31 = 1,
- TwoFish_P_32 = 1,
- TwoFish_P_33 = TwoFish_P_31 ^ 1,
- TwoFish_P_34 = 1,
- TwoFish_GF256_FDBK = 0x169,
- TwoFish_GF256_FDBK_2 = 0x169 / 2,
- TwoFish_GF256_FDBK_4 = 0x169 / 4,
- TwoFish_RS_GF_FDBK = 0x14D, /* field generator */
- TwoFish_MDS_GF_FDBK = 0x169 /* primitive polynomial for GF(256) */
-};
-
-
-/* Global data structure for callers */
-
-typedef struct
-{
- uint32_t sBox[4 * 256]; /* Key dependent S-box */
- uint32_t subKeys[TwoFish_TOTAL_SUBKEYS]; /* Subkeys */
- uint8_t key[TwoFish_KEY_LENGTH]; /* Encryption Key */
- uint8_t *output; /* Pointer to output buffer */
- uint8_t qBlockPlain[TwoFish_BLOCK_SIZE]; /* Used by CBC */
- uint8_t qBlockCrypt[TwoFish_BLOCK_SIZE];
- uint8_t prevCipher[TwoFish_BLOCK_SIZE];
- struct /* Header for crypt functions. Has to be at least one block long. */
- { uint32_t salt; /* Random salt in first block (will salt the rest through CBC) */
- uint8_t length[4]; /* The amount of data following the header */
- uint8_t magic[TwoFish_MAGIC_LEN]; /* Magic to identify successful decryption */
- } header;
- bool qBlockDefined;
- bool dontflush;
-} TWOFISH;
-
-/**** Public Functions ****/
-
-/* TwoFish Initialization
- *
- * This routine generates a global data structure for use with TwoFish,
- * initializes important values (such as subkeys, sBoxes), generates subkeys
- * and precomputes the MDS matrix if not already done.
- *
- * Input: User supplied key of correct length (TwoFish_KEY_LENGTH, 256 bits = 32 bytes by default)
- *
- * Output: Pointer to TWOFISH structure. This data structure contains key dependent data.
- * This pointer is used with all other crypt functions.
- */
-TWOFISH *TwoFishInit(const uint8_t *userkey);
-
-
-/* TwoFish Destroy
- *
- * Nothing else but a free...
- *
- * Input: Pointer to the TwoFish structure.
- *
- */
-void TwoFishDestroy(TWOFISH *tfdata);
-
-
-/* TwoFish Alloc
- *
- * Allocates enough memory for the output buffer as required.
- *
- * Input: Length of the plaintext.
- * Boolean flag for BinHex Output.
- * Pointer to the TwoFish structure.
- *
- * Output: Returns a pointer to the memory allocated.
- */
-void *TwoFishAlloc(uint32_t len,bool binhex,bool decrypt,TWOFISH *tfdata);
-
-
-/* TwoFish Free
- *
- * Free's the allocated buffer.
- *
- * Input: Pointer to the TwoFish structure
- *
- * Output: (none)
- */
-void TwoFishFree(TWOFISH *tfdata);
-
-
-/* TwoFish Set Output
- *
- * If you want to allocate the output buffer yourself,
- * then you can set it with this function.
- *
- * Input: Pointer to your output buffer
- * Pointer to the TwoFish structure
- *
- * Output: (none)
- */
-void TwoFishSetOutput(uint8_t *outp,TWOFISH *tfdata);
-
-
-/* TwoFish Raw Encryption
- *
- * Does not use header, but does use CBC (if more than one block has to be encrypted).
- *
- * Input: Pointer to the buffer of the plaintext to be encrypted.
- * Pointer to the buffer receiving the ciphertext.
- * The length of the plaintext buffer.
- * The TwoFish structure.
- *
- * Output: The amount of bytes encrypted if successful, otherwise 0.
- */
-uint32_t TwoFishEncryptRaw(uint8_t *in,uint8_t *out,uint32_t len,TWOFISH *tfdata);
-
-/* TwoFish Raw Decryption
- *
- * Does not use header, but does use CBC (if more than one block has to be decrypted).
- *
- * Input: Pointer to the buffer of the ciphertext to be decrypted.
- * Pointer to the buffer receiving the plaintext.
- * The length of the ciphertext buffer (at least one cipher block).
- * The TwoFish structure.
- *
- * Output: The amount of bytes decrypted if successful, otherwise 0.
- */
-uint32_t TwoFishDecryptRaw(uint8_t *in,uint8_t *out,uint32_t len,TWOFISH *tfdata);
-
-
-/* TwoFish Encryption
- *
- * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
- * this routine will alloc the memory. In addition, it will include a small 'header'
- * containing the magic and some salt. That way the decrypt routine can check if the
- * packet got decrypted successfully, and return 0 instead of garbage.
- *
- * Input: Pointer to the buffer of the plaintext to be encrypted.
- * Pointer to the pointer to the buffer receiving the ciphertext.
- * The pointer either points to user allocated output buffer space, or to NULL, in which case
- * this routine will set the pointer to the buffer allocated through the struct.
- * The length of the plaintext buffer.
- * Can be -1 if the input is a null terminated string, in which case we'll count for you.
- * Boolean flag for BinHex Output (if used, output will be twice as large as input).
- * Note: BinHex conversion overwrites (converts) input buffer!
- * The TwoFish structure.
- *
- * Output: The amount of bytes encrypted if successful, otherwise 0.
- */
-uint32_t TwoFishEncrypt(uint8_t *in,uint8_t **out,signed long len,bool binhex,TWOFISH *tfdata);
-
-
-/* TwoFish Decryption
- *
- * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
- * this routine will alloc the memory. In addition, it will check the small 'header'
- * containing the magic. If magic does not match we return 0. Otherwise we return the
- * amount of bytes decrypted (should be the same as the length in the header).
- *
- * Input: Pointer to the buffer of the ciphertext to be decrypted.
- * Pointer to the pointer to the buffer receiving the plaintext.
- * The pointer either points to user allocated output buffer space, or to NULL, in which case
- * this routine will set the pointer to the buffer allocated through the struct.
- * The length of the ciphertext buffer.
- * Can be -1 if the input is a null terminated binhex string, in which case we'll count for you.
- * Boolean flag for BinHex Input (if used, plaintext will be half as large as input).
- * Note: BinHex conversion overwrites (converts) input buffer!
- * The TwoFish structure.
- *
- * Output: The amount of bytes decrypted if successful, otherwise 0.
- */
-uint32_t TwoFishDecrypt(uint8_t *in,uint8_t **out,signed long len,bool binhex,TWOFISH *tfdata);
-
-
-/**** Private Functions ****/
-
-uint8_t TwoFish__b(uint32_t x,int n);
-void _TwoFish_BinHex(uint8_t *buf,uint32_t len,bool bintohex);
-uint32_t _TwoFish_CryptRawCBC(uint8_t *in,uint8_t *out,uint32_t len,bool decrypt,TWOFISH *tfdata);
-uint32_t _TwoFish_CryptRaw16(uint8_t *in,uint8_t *out,uint32_t len,bool decrypt,TWOFISH *tfdata);
-uint32_t _TwoFish_CryptRaw(uint8_t *in,uint8_t *out,uint32_t len,bool decrypt,TWOFISH *tfdata);
-void _TwoFish_PrecomputeMDSmatrix(void);
-void _TwoFish_MakeSubKeys(TWOFISH *tfdata);
-void _TwoFish_qBlockPush(uint8_t *p,uint8_t *c,TWOFISH *tfdata);
-void _TwoFish_qBlockPop(uint8_t *p,uint8_t *c,TWOFISH *tfdata);
-void _TwoFish_ResetCBC(TWOFISH *tfdata);
-void _TwoFish_FlushOutput(uint8_t *b,uint32_t len,TWOFISH *tfdata);
-void _TwoFish_BlockCrypt(uint8_t *in,uint8_t *out,uint32_t size,int decrypt,TWOFISH *tfdata);
-void _TwoFish_BlockCrypt16(uint8_t *in,uint8_t *out,bool decrypt,TWOFISH *tfdata);
-uint32_t _TwoFish_RS_MDS_Encode(uint32_t k0,uint32_t k1);
-uint32_t _TwoFish_F32(uint32_t k64Cnt,uint32_t x,uint32_t *k32);
-uint32_t _TwoFish_Fe320(uint32_t *lsBox,uint32_t x);
-uint32_t _TwoFish_Fe323(uint32_t *lsBox,uint32_t x);
-uint32_t _TwoFish_Fe32(uint32_t *lsBox,uint32_t x,uint32_t R);
-
-
-#endif
diff --git a/src/edge_utils.c b/src/edge_utils.c
index bbd9dc4..7217499 100644
--- a/src/edge_utils.c
+++ b/src/edge_utils.c
@@ -219,7 +219,7 @@ n2n_edge_t* edge_init(const n2n_edge_conf_t *conf, int *rv) {
/* Set active transop */
switch(transop_id) {
case N2N_TRANSFORM_ID_TWOFISH:
- rc = n2n_transop_twofish_init(&eee->conf, &eee->transop);
+ rc = n2n_transop_tf_init(&eee->conf, &eee->transop);
break;
#ifdef N2N_HAVE_AES
case N2N_TRANSFORM_ID_AESCBC:
diff --git a/src/tf.c b/src/tf.c
new file mode 100644
index 0000000..59fdadc
--- /dev/null
+++ b/src/tf.c
@@ -0,0 +1,505 @@
+/**
+ * (C) 2007-20 - ntop.org and contributors
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program; if not see see
+ *
+ */
+
+
+// taken (and modified) from github/fudanchii/twofish as of August 2020
+// which itself is a modified copy of Andrew T. Csillag's implementation
+// published on github/drewcsillag/twofish
+
+
+/*
+The MIT License (MIT)
+
+Copyright (c) 2015 Andrew T. Csillag
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#include "tf.h"
+
+
+const uint8_t RS[4][8] = { { 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, },
+ { 0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5, },
+ { 0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19, },
+ { 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03 } };
+
+const uint8_t Q0[] = { 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
+ 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
+ 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
+ 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
+ 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
+ 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
+ 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
+ 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
+ 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
+ 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
+ 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
+ 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
+ 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
+ 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
+ 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
+ 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0 };
+
+const uint8_t Q1[] = { 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
+ 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
+ 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
+ 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
+ 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
+ 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
+ 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
+ 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
+ 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
+ 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
+ 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
+ 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
+ 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
+ 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
+ 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
+ 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 };
+
+const uint8_t mult5B[] = { 0x00, 0x5B, 0xB6, 0xED, 0x05, 0x5E, 0xB3, 0xE8, 0x0A, 0x51, 0xBC, 0xE7, 0x0F, 0x54, 0xB9, 0xE2,
+ 0x14, 0x4F, 0xA2, 0xF9, 0x11, 0x4A, 0xA7, 0xFC, 0x1E, 0x45, 0xA8, 0xF3, 0x1B, 0x40, 0xAD, 0xF6,
+ 0x28, 0x73, 0x9E, 0xC5, 0x2D, 0x76, 0x9B, 0xC0, 0x22, 0x79, 0x94, 0xCF, 0x27, 0x7C, 0x91, 0xCA,
+ 0x3C, 0x67, 0x8A, 0xD1, 0x39, 0x62, 0x8F, 0xD4, 0x36, 0x6D, 0x80, 0xDB, 0x33, 0x68, 0x85, 0xDE,
+ 0x50, 0x0B, 0xE6, 0xBD, 0x55, 0x0E, 0xE3, 0xB8, 0x5A, 0x01, 0xEC, 0xB7, 0x5F, 0x04, 0xE9, 0xB2,
+ 0x44, 0x1F, 0xF2, 0xA9, 0x41, 0x1A, 0xF7, 0xAC, 0x4E, 0x15, 0xF8, 0xA3, 0x4B, 0x10, 0xFD, 0xA6,
+ 0x78, 0x23, 0xCE, 0x95, 0x7D, 0x26, 0xCB, 0x90, 0x72, 0x29, 0xC4, 0x9F, 0x77, 0x2C, 0xC1, 0x9A,
+ 0x6C, 0x37, 0xDA, 0x81, 0x69, 0x32, 0xDF, 0x84, 0x66, 0x3D, 0xD0, 0x8B, 0x63, 0x38, 0xD5, 0x8E,
+ 0xA0, 0xFB, 0x16, 0x4D, 0xA5, 0xFE, 0x13, 0x48, 0xAA, 0xF1, 0x1C, 0x47, 0xAF, 0xF4, 0x19, 0x42,
+ 0xB4, 0xEF, 0x02, 0x59, 0xB1, 0xEA, 0x07, 0x5C, 0xBE, 0xE5, 0x08, 0x53, 0xBB, 0xE0, 0x0D, 0x56,
+ 0x88, 0xD3, 0x3E, 0x65, 0x8D, 0xD6, 0x3B, 0x60, 0x82, 0xD9, 0x34, 0x6F, 0x87, 0xDC, 0x31, 0x6A,
+ 0x9C, 0xC7, 0x2A, 0x71, 0x99, 0xC2, 0x2F, 0x74, 0x96, 0xCD, 0x20, 0x7B, 0x93, 0xC8, 0x25, 0x7E,
+ 0xF0, 0xAB, 0x46, 0x1D, 0xF5, 0xAE, 0x43, 0x18, 0xFA, 0xA1, 0x4C, 0x17, 0xFF, 0xA4, 0x49, 0x12,
+ 0xE4, 0xBF, 0x52, 0x09, 0xE1, 0xBA, 0x57, 0x0C, 0xEE, 0xB5, 0x58, 0x03, 0xEB, 0xB0, 0x5D, 0x06,
+ 0xD8, 0x83, 0x6E, 0x35, 0xDD, 0x86, 0x6B, 0x30, 0xD2, 0x89, 0x64, 0x3F, 0xD7, 0x8C, 0x61, 0x3A,
+ 0xCC, 0x97, 0x7A, 0x21, 0xC9, 0x92, 0x7F, 0x24, 0xC6, 0x9D, 0x70, 0x2B, 0xC3, 0x98, 0x75, 0x2E };
+
+const uint8_t multEF[] = { 0x00, 0xEF, 0xB7, 0x58, 0x07, 0xE8, 0xB0, 0x5F, 0x0E, 0xE1, 0xB9, 0x56, 0x09, 0xE6, 0xBE, 0x51,
+ 0x1C, 0xF3, 0xAB, 0x44, 0x1B, 0xF4, 0xAC, 0x43, 0x12, 0xFD, 0xA5, 0x4A, 0x15, 0xFA, 0xA2, 0x4D,
+ 0x38, 0xD7, 0x8F, 0x60, 0x3F, 0xD0, 0x88, 0x67, 0x36, 0xD9, 0x81, 0x6E, 0x31, 0xDE, 0x86, 0x69,
+ 0x24, 0xCB, 0x93, 0x7C, 0x23, 0xCC, 0x94, 0x7B, 0x2A, 0xC5, 0x9D, 0x72, 0x2D, 0xC2, 0x9A, 0x75,
+ 0x70, 0x9F, 0xC7, 0x28, 0x77, 0x98, 0xC0, 0x2F, 0x7E, 0x91, 0xC9, 0x26, 0x79, 0x96, 0xCE, 0x21,
+ 0x6C, 0x83, 0xDB, 0x34, 0x6B, 0x84, 0xDC, 0x33, 0x62, 0x8D, 0xD5, 0x3A, 0x65, 0x8A, 0xD2, 0x3D,
+ 0x48, 0xA7, 0xFF, 0x10, 0x4F, 0xA0, 0xF8, 0x17, 0x46, 0xA9, 0xF1, 0x1E, 0x41, 0xAE, 0xF6, 0x19,
+ 0x54, 0xBB, 0xE3, 0x0C, 0x53, 0xBC, 0xE4, 0x0B, 0x5A, 0xB5, 0xED, 0x02, 0x5D, 0xB2, 0xEA, 0x05,
+ 0xE0, 0x0F, 0x57, 0xB8, 0xE7, 0x08, 0x50, 0xBF, 0xEE, 0x01, 0x59, 0xB6, 0xE9, 0x06, 0x5E, 0xB1,
+ 0xFC, 0x13, 0x4B, 0xA4, 0xFB, 0x14, 0x4C, 0xA3, 0xF2, 0x1D, 0x45, 0xAA, 0xF5, 0x1A, 0x42, 0xAD,
+ 0xD8, 0x37, 0x6F, 0x80, 0xDF, 0x30, 0x68, 0x87, 0xD6, 0x39, 0x61, 0x8E, 0xD1, 0x3E, 0x66, 0x89,
+ 0xC4, 0x2B, 0x73, 0x9C, 0xC3, 0x2C, 0x74, 0x9B, 0xCA, 0x25, 0x7D, 0x92, 0xCD, 0x22, 0x7A, 0x95,
+ 0x90, 0x7F, 0x27, 0xC8, 0x97, 0x78, 0x20, 0xCF, 0x9E, 0x71, 0x29, 0xC6, 0x99, 0x76, 0x2E, 0xC1,
+ 0x8C, 0x63, 0x3B, 0xD4, 0x8B, 0x64, 0x3C, 0xD3, 0x82, 0x6D, 0x35, 0xDA, 0x85, 0x6A, 0x32, 0xDD,
+ 0xA8, 0x47, 0x1F, 0xF0, 0xAF, 0x40, 0x18, 0xF7, 0xA6, 0x49, 0x11, 0xFE, 0xA1, 0x4E, 0x16, 0xF9,
+ 0xB4, 0x5B, 0x03, 0xEC, 0xB3, 0x5C, 0x04, 0xEB, 0xBA, 0x55, 0x0D, 0xE2, 0xBD, 0x52, 0x0A, 0xE5 };
+
+#define RS_MOD 0x14D
+#define RHO 0x01010101L
+
+#define ROL(x,n) (((x) << ((n) & 0x1F)) | ((x) >> (32-((n) & 0x1F))))
+#define ROR(x,n) (((x) >> ((n) & 0x1F)) | ((x) << (32-((n) & 0x1F))))
+
+#define _b(x, N) (((x) >> (N*8)) & 0xFF)
+
+#define b0(x) ((uint8_t)(x))
+#define b1(x) ((uint8_t)((x) >> 8))
+#define b2(x) ((uint8_t)((x) >> 16))
+#define b3(x) ((uint8_t)((x) >> 24))
+
+#define U8ARRAY_TO_U32(r) ((r[0] << 24) ^ (r[1] << 16) ^ (r[2] << 8) ^ r[3])
+#define U8S_TO_U32(r0, r1, r2, r3) ((r0 << 24) ^ (r1 << 16) ^ (r2 << 8) ^ r3)
+
+
+/* multiply two polynomials represented as u32's, actually called with bytes */
+uint32_t polyMult(uint32_t a, uint32_t b) {
+
+ uint32_t t=0;
+
+ while(a) {
+ if(a&1) t^=b;
+ b <<= 1;
+ a >>= 1;
+ }
+
+ return t;
+}
+
+
+/* take the polynomial t and return the t % modulus in GF(256) */
+uint32_t gfMod(uint32_t t, uint32_t modulus) {
+
+ int i;
+ uint32_t tt;
+
+ modulus <<= 7;
+ for(i = 0; i < 8; i++) {
+ tt = t ^ modulus;
+ if(tt < t) t = tt;
+ modulus >>= 1;
+ }
+
+ return t;
+}
+
+
+/*multiply a and b and return the modulus */
+#define gfMult(a, b, modulus) gfMod(polyMult(a, b), modulus)
+
+
+/* return a u32 containing the result of multiplying the RS Code matrix by the sd matrix */
+uint32_t RSMatrixMultiply(uint8_t sd[8]) {
+
+ int j, k;
+ uint8_t t;
+ uint8_t result[4];
+
+ for(j = 0; j < 4; j++) {
+ t = 0;
+ for(k = 0; k < 8; k++) {
+ t ^= gfMult(RS[j][k], sd[k], RS_MOD);
+ }
+ result[3-j] = t;
+ }
+
+ return U8ARRAY_TO_U32(result);
+}
+
+
+/* the Zero-keyed h function (used by the key setup routine) */
+uint32_t h(uint32_t X, uint32_t L[4], int k) {
+
+ uint8_t y0, y1, y2, y3;
+ uint8_t z0, z1, z2, z3;
+
+ y0 = b0(X);
+ y1 = b1(X);
+ y2 = b2(X);
+ y3 = b3(X);
+
+ switch(k) {
+ case 4:
+ y0 = Q1[y0] ^ b0(L[3]);
+ y1 = Q0[y1] ^ b1(L[3]);
+ y2 = Q0[y2] ^ b2(L[3]);
+ y3 = Q1[y3] ^ b3(L[3]);
+ case 3:
+ y0 = Q1[y0] ^ b0(L[2]);
+ y1 = Q1[y1] ^ b1(L[2]);
+ y2 = Q0[y2] ^ b2(L[2]);
+ y3 = Q0[y3] ^ b3(L[2]);
+ case 2:
+ y0 = Q1[ Q0 [ Q0[y0] ^ b0(L[1]) ] ^ b0(L[0]) ];
+ y1 = Q0[ Q0 [ Q1[y1] ^ b1(L[1]) ] ^ b1(L[0]) ];
+ y2 = Q1[ Q1 [ Q0[y2] ^ b2(L[1]) ] ^ b2(L[0]) ];
+ y3 = Q0[ Q1 [ Q1[y3] ^ b3(L[1]) ] ^ b3(L[0]) ];
+ }
+
+ /* inline the MDS matrix multiply */
+ z0 = multEF[y0] ^ y1 ^ multEF[y2] ^ mult5B[y3];
+ z1 = multEF[y0] ^ mult5B[y1] ^ y2 ^ multEF[y3];
+ z2 = mult5B[y0] ^ multEF[y1] ^ multEF[y2] ^ y3;
+ z3 = y0 ^ multEF[y1] ^ mult5B[y2] ^ mult5B[y3];
+
+ return U8S_TO_U32(z0, z1, z2, z3);
+}
+
+
+/* given the Sbox keys, create the fully keyed QF */
+void fullKey(uint32_t L[4], int k, uint32_t QF[4][256]) {
+
+ uint8_t y0, y1, y2, y3;
+ int i;
+
+ /* for all input values to the Q permutations */
+ for(i=0; i<256; i++) {
+ /* run the Q permutations */
+ y0 = i; y1=i; y2=i; y3=i;
+ switch(k) {
+ case 4:
+ y0 = Q1[y0] ^ b0(L[3]);
+ y1 = Q0[y1] ^ b1(L[3]);
+ y2 = Q0[y2] ^ b2(L[3]);
+ y3 = Q1[y3] ^ b3(L[3]);
+ case 3:
+ y0 = Q1[y0] ^ b0(L[2]);
+ y1 = Q1[y1] ^ b1(L[2]);
+ y2 = Q0[y2] ^ b2(L[2]);
+ y3 = Q0[y3] ^ b3(L[2]);
+ case 2:
+ y0 = Q1[ Q0 [ Q0[y0] ^ b0(L[1]) ] ^ b0(L[0]) ];
+ y1 = Q0[ Q0 [ Q1[y1] ^ b1(L[1]) ] ^ b1(L[0]) ];
+ y2 = Q1[ Q1 [ Q0[y2] ^ b2(L[1]) ] ^ b2(L[0]) ];
+ y3 = Q0[ Q1 [ Q1[y3] ^ b3(L[1]) ] ^ b3(L[0]) ];
+ }
+
+ /* now do the partial MDS matrix multiplies */
+ QF[0][i] = ((multEF[y0] << 24)
+ | (multEF[y0] << 16)
+ | (mult5B[y0] << 8)
+ | y0);
+ QF[1][i] = ((y1 << 24)
+ | (mult5B[y1] << 16)
+ | (multEF[y1] << 8)
+ | multEF[y1]);
+ QF[2][i] = ((multEF[y2] << 24)
+ | (y2 << 16)
+ | (multEF[y2] << 8)
+ | mult5B[y2]);
+ QF[3][i] = ((mult5B[y3] << 24)
+ | (multEF[y3] << 16)
+ | (y3 << 8)
+ | mult5B[y3]);
+ }
+}
+
+// -------------------------------------------------------------------------------------
+
+/* fully keyed h (aka g) function */
+#define fkh(X) (S[0][b0(X)]^S[1][b1(X)]^S[2][b2(X)]^S[3][b3(X)])
+
+// -------------------------------------------------------------------------------------
+
+/* one encryption round */
+#define ENC_ROUND(R0, R1, R2, R3, round) \
+ T0 = fkh(R0); \
+ T1 = fkh(ROL(R1, 8)); \
+ R2 = ROR(R2 ^ (T1 + T0 + K[2*round+8]), 1); \
+ R3 = ROL(R3, 1) ^ (2*T1 + T0 + K[2*round+9]);
+
+
+void twofish_internal_encrypt(uint32_t K[40], uint32_t S[4][256], uint8_t PT[16]) {
+
+ uint32_t R0, R1, R2, R3;
+ uint32_t T0, T1;
+
+ /* load/byteswap/whiten input */
+ R3 = K[3] ^ le32toh(((uint32_t*)PT)[3]);
+ R2 = K[2] ^ le32toh(((uint32_t*)PT)[2]);
+ R1 = K[1] ^ le32toh(((uint32_t*)PT)[1]);
+ R0 = K[0] ^ le32toh(((uint32_t*)PT)[0]);
+
+ ENC_ROUND(R0, R1, R2, R3, 0);
+ ENC_ROUND(R2, R3, R0, R1, 1);
+ ENC_ROUND(R0, R1, R2, R3, 2);
+ ENC_ROUND(R2, R3, R0, R1, 3);
+ ENC_ROUND(R0, R1, R2, R3, 4);
+ ENC_ROUND(R2, R3, R0, R1, 5);
+ ENC_ROUND(R0, R1, R2, R3, 6);
+ ENC_ROUND(R2, R3, R0, R1, 7);
+ ENC_ROUND(R0, R1, R2, R3, 8);
+ ENC_ROUND(R2, R3, R0, R1, 9);
+ ENC_ROUND(R0, R1, R2, R3, 10);
+ ENC_ROUND(R2, R3, R0, R1, 11);
+ ENC_ROUND(R0, R1, R2, R3, 12);
+ ENC_ROUND(R2, R3, R0, R1, 13);
+ ENC_ROUND(R0, R1, R2, R3, 14);
+ ENC_ROUND(R2, R3, R0, R1, 15);
+
+ /* load/byteswap/whiten output */
+ ((uint32_t*)PT)[3] = htole32(R1 ^ K[7]);
+ ((uint32_t*)PT)[2] = htole32(R0 ^ K[6]);
+ ((uint32_t*)PT)[1] = htole32(R3 ^ K[5]);
+ ((uint32_t*)PT)[0] = htole32(R2 ^ K[4]);
+}
+
+// -------------------------------------------------------------------------------------
+
+/* one decryption round */
+#define DEC_ROUND(R0, R1, R2, R3, round) \
+ T0 = fkh(R0); \
+ T1 = fkh(ROL(R1, 8)); \
+ R2 = ROL(R2, 1) ^ (T0 + T1 + K[2*round+8]); \
+ R3 = ROR(R3 ^ (T0 + 2*T1 + K[2*round+9]), 1);
+
+
+void twofish_internal_decrypt(uint32_t K[40], uint32_t S[4][256], uint8_t PT[16], const uint8_t CT[16]) {
+
+ uint32_t T0, T1;
+ uint32_t R0, R1, R2, R3;
+
+ /* load/byteswap/whiten input */
+ R3 = K[7] ^ le32toh(((uint32_t*)CT)[3]);
+ R2 = K[6] ^ le32toh(((uint32_t*)CT)[2]);
+ R1 = K[5] ^ le32toh(((uint32_t*)CT)[1]);
+ R0 = K[4] ^ le32toh(((uint32_t*)CT)[0]);
+
+ DEC_ROUND(R0, R1, R2, R3, 15);
+ DEC_ROUND(R2, R3, R0, R1, 14);
+ DEC_ROUND(R0, R1, R2, R3, 13);
+ DEC_ROUND(R2, R3, R0, R1, 12);
+ DEC_ROUND(R0, R1, R2, R3, 11);
+ DEC_ROUND(R2, R3, R0, R1, 10);
+ DEC_ROUND(R0, R1, R2, R3, 9);
+ DEC_ROUND(R2, R3, R0, R1, 8);
+ DEC_ROUND(R0, R1, R2, R3, 7);
+ DEC_ROUND(R2, R3, R0, R1, 6);
+ DEC_ROUND(R0, R1, R2, R3, 5);
+ DEC_ROUND(R2, R3, R0, R1, 4);
+ DEC_ROUND(R0, R1, R2, R3, 3);
+ DEC_ROUND(R2, R3, R0, R1, 2);
+ DEC_ROUND(R0, R1, R2, R3, 1);
+ DEC_ROUND(R2, R3, R0, R1, 0);
+
+ /* load/byteswap/whiten output */
+ ((uint32_t*)PT)[3] = htole32(R1 ^ K[3]);
+ ((uint32_t*)PT)[2] = htole32(R0 ^ K[2]);
+ ((uint32_t*)PT)[1] = htole32(R3 ^ K[1]);
+ ((uint32_t*)PT)[0] = htole32(R2 ^ K[0]);
+}
+
+// -------------------------------------------------------------------------------------
+
+/* the key schedule routine */
+void keySched(const uint8_t M[], int N, uint32_t **S, uint32_t K[40], int *k) {
+
+ uint32_t Mo[4], Me[4];
+ int i, j;
+ uint8_t vector[8];
+ uint32_t A, B;
+
+ *k = (N + 63) / 64;
+ *S = (uint32_t*)malloc(sizeof(uint32_t) * (*k));
+
+ for(i = 0; i < *k; i++) {
+ Me[i] = le32toh(((uint32_t*)M)[2*i]);
+ Mo[i] = le32toh(((uint32_t*)M)[2*i+1]);
+ }
+
+ for(i = 0; i < *k; i++) {
+ for(j = 0; j < 4; j++)
+ vector[j] = _b(Me[i], j);
+ for(j = 0; j < 4; j++)
+ vector[j+4] = _b(Mo[i], j);
+ (*S)[(*k)-i-1] = RSMatrixMultiply(vector);
+ }
+ for(i = 0; i < 20; i++) {
+ A = h(2*i*RHO, Me, *k);
+ B = ROL(h(2*i*RHO + RHO, Mo, *k), 8);
+ K[2*i] = A+B;
+ K[2*i+1] = ROL(A + 2*B, 9);
+ }
+}
+
+// -------------------------------------------------------------------------------------
+
+// test field
+//#define fix_xor(target, source) for (int _i = 0; _i < 16; _i++) { (target)[_i] = (target)[_i] ^ (source)[_i]; }
+//#define fix_xor(target, source) for (int _i = 0; _i < 16; _i+=4) { *(uint32_t*)&(target)[_i] = *(uint32_t*)&(target)[_i] ^ *(uint32_t*)&(source)[_i]; }
+#define fix_xor(target, source) *(uint32_t*)&(target)[0] = *(uint32_t*)&(target)[0] ^ *(uint32_t*)&(source)[0]; *(uint32_t*)&(target)[4] = *(uint32_t*)&(target)[4] ^ *(uint32_t*)&(source)[4]; \
+ *(uint32_t*)&(target)[8] = *(uint32_t*)&(target)[8] ^ *(uint32_t*)&(source)[8]; *(uint32_t*)&(target)[12] = *(uint32_t*)&(target)[12] ^ *(uint32_t*)&(source)[12];
+//#define fix_xor(target, source) *(uint64_t*)&(target)[0] = *(uint64_t*)&(target)[0] ^ *(uint64_t*)&(source)[0]; *(uint64_t*)&(target)[8] = *(uint64_t*)&(target)[8] ^ *(uint64_t*)&(source)[8];
+//#include
+//#define fix_xor(target, source) __m128i target128 = _mm_loadu_si128((__m128i*)target); __m128i source128 = _mm_loadu_si128((__m128i*)source); target128 = _mm_xor_si128(target128, source128); _mm_storeu_si128((__m128i*)(target), target128);
+
+// -------------------------------------------------------------------------------------
+
+
+/** public API **/
+
+
+int tf_ecb_decrypt (unsigned char *out, const unsigned char *in, tf_context_t *ctx) {
+
+ twofish_internal_decrypt(ctx->K, ctx->QF, out, in);
+ return TF_BLOCK_SIZE;
+}
+
+// not used
+int tf_ecb_encrypt (unsigned char *out, const unsigned char *in, tf_context_t *ctx) {
+
+ memcpy (out, in, TF_BLOCK_SIZE);
+ twofish_internal_encrypt(ctx->K, ctx->QF, out);
+ return TF_BLOCK_SIZE;
+}
+
+
+int tf_cbc_encrypt (unsigned char *out, const unsigned char *in, size_t in_len,
+ const unsigned char *iv, tf_context_t *ctx) {
+
+ uint8_t tmp[TF_BLOCK_SIZE];
+ size_t i;
+ size_t n;
+
+ memcpy(tmp, iv, TF_BLOCK_SIZE);
+
+ n = in_len / TF_BLOCK_SIZE;
+ for(i=0; i < n; i++) {
+ fix_xor(tmp, &in[i * TF_BLOCK_SIZE]);
+ twofish_internal_encrypt(ctx->K, ctx->QF, tmp);
+ memcpy(&out[i * TF_BLOCK_SIZE], tmp, TF_BLOCK_SIZE);
+ }
+ return n * TF_BLOCK_SIZE;
+}
+
+
+int tf_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len,
+ const unsigned char *iv, tf_context_t *ctx) {
+
+ uint8_t tmp[TF_BLOCK_SIZE];
+ uint8_t old[TF_BLOCK_SIZE];
+ size_t i;
+ size_t n;
+
+ memcpy(tmp, iv, TF_BLOCK_SIZE);
+
+ n = in_len / TF_BLOCK_SIZE;
+ for(i=0; i < n; i++) {
+ memcpy(old, &in[i * TF_BLOCK_SIZE], TF_BLOCK_SIZE);
+ twofish_internal_decrypt(ctx->K, ctx->QF, &out[i * TF_BLOCK_SIZE], &in[i * TF_BLOCK_SIZE]);
+ fix_xor(&out[i * TF_BLOCK_SIZE], tmp);
+ memcpy(tmp, old, TF_BLOCK_SIZE);
+ }
+
+ return n * TF_BLOCK_SIZE;
+}
+
+/**
+ * By definition twofish can only accept key up to 256 bit
+ * we wont do any checking here and will assume user already
+ * know about it. Twofish is undefined for key larger than 256 bit
+ */
+int tf_init (const unsigned char *key, size_t key_size, tf_context_t **ctx) {
+
+ int k;
+ uint32_t *S;
+
+ *ctx = calloc(1, sizeof(tf_context_t));
+ if(!(*ctx)) {
+ return -1;
+ }
+ (*ctx)->N = key_size;
+ keySched(key, key_size, &S, (*ctx)->K, &k);
+ fullKey(S, k, (*ctx)->QF);
+ free(S); // allocated in keySched(...)
+
+ return 0;
+}
diff --git a/src/transform_tf.c b/src/transform_tf.c
index c583cc1..e40c1d8 100644
--- a/src/transform_tf.c
+++ b/src/transform_tf.c
@@ -16,158 +16,219 @@
*
*/
+
#include "n2n.h"
+// size of random value prepended to plaintext defaults to TF_BLOCK_SIZE;
+// gradually abandoning security, lower values could be chosen;
+// however, minimum transmission size with cipher text stealing scheme is one
+// block; as network packets should be longer anyway, only low level programmer
+// might encounter an issue with lower values here
+#define TF_PREAMBLE_SIZE (TF_BLOCK_SIZE)
+
+// cbc mode is being used with random value prepended to plaintext
+// instead of iv so, actual iv is null_iv
+const uint8_t null_iv[TF_IV_SIZE] = {0};
+
typedef struct transop_tf {
- TWOFISH* enc_tf; /* tx state */
- TWOFISH* dec_tf; /* rx state */
+ tf_context_t *ctx;
} transop_tf_t;
-static int transop_deinit_twofish( n2n_trans_op_t * arg ) {
+/* ****************************************************** */
+
+static int transop_deinit_tf(n2n_trans_op_t *arg) {
transop_tf_t *priv = (transop_tf_t *)arg->priv;
- if(priv) {
- TwoFishDestroy(priv->enc_tf); /* deallocate TWOFISH */
- TwoFishDestroy(priv->dec_tf); /* deallocate TWOFISH */
- free(priv);
- }
+ if(priv->ctx) free(priv->ctx);
+
+ if(priv) free(priv);
return 0;
}
-#define TRANSOP_TF_NONCE_SIZE 4
+/* ****************************************************** */
+
+// the Twofish packet format consists of
+//
+// - a random TF_PREAMBLE_SIZE-sized value prepended to plaintext
+// encrypted together with the...
+// - ... payload data
+//
+// [VV|DDDDDDDDDDDDDDDDDDDDD]
+// | <---- encrypted ----> |
+//
+static int transop_encode_tf(n2n_trans_op_t * arg,
+ uint8_t * outbuf,
+ size_t out_len,
+ const uint8_t * inbuf,
+ size_t in_len,
+ const uint8_t * peer_mac) {
-/** The twofish packet format consists of:
- *
- * - ciphertext encrypted from a 32-bit nonce followed by the payload.
- *
- * [nnnnDDDDDDDDDDDDDDDDDDDDD]
- * |<------ encrypted ------>|
- */
-static int transop_encode_twofish( n2n_trans_op_t * arg,
- uint8_t * outbuf,
- size_t out_len,
- const uint8_t * inbuf,
- size_t in_len,
- const uint8_t * peer_mac)
-{
- int len=-1;
transop_tf_t * priv = (transop_tf_t *)arg->priv;
- uint8_t assembly[N2N_PKT_BUF_SIZE];
- uint32_t * pnonce;
-
- if ( (in_len + TRANSOP_TF_NONCE_SIZE) <= N2N_PKT_BUF_SIZE )
- {
- if ( (in_len + TRANSOP_TF_NONCE_SIZE) <= out_len )
- {
- traceEvent(TRACE_DEBUG, "encode_twofish %lu", in_len);
-
- /* The assembly buffer is a source for encrypting data. The nonce is
- * written in first followed by the packet payload. The whole
- * contents of assembly are encrypted. */
- pnonce = (uint32_t *)assembly;
- *pnonce = n2n_rand();
- memcpy( assembly + TRANSOP_TF_NONCE_SIZE, inbuf, in_len );
-
- /* Encrypt the assembly contents and write the ciphertext after the SA. */
- len = TwoFishEncryptRaw( assembly, /* source */
- outbuf,
- in_len + TRANSOP_TF_NONCE_SIZE, /* enc size */
- priv->enc_tf);
- if ( len <= 0 )
- {
- traceEvent( TRACE_ERROR, "encode_twofish encryption failed." );
- }
+ // the assembly buffer is a source for encrypting data
+ // the whole contents of assembly are encrypted
+ uint8_t assembly[N2N_PKT_BUF_SIZE];
+ size_t idx = 0;
+ int padded_len;
+ uint8_t padding;
+ uint8_t buf[TF_BLOCK_SIZE];
+
+ if(in_len <= N2N_PKT_BUF_SIZE) {
+ if((in_len + TF_PREAMBLE_SIZE + TF_BLOCK_SIZE) <= out_len) {
+
+ traceEvent(TRACE_DEBUG, "transop_encode_tf %lu bytes plaintext", in_len);
+
+ // full block sized random value (128 bit)
+ // !!! replace with 2 calls to encode_uint64(...) as as available
+ // !!! which is still under consideration in pull request 'revAes'
+ encode_uint32(assembly, &idx, n2n_rand());
+ encode_uint32(assembly, &idx, n2n_rand());
+ encode_uint32(assembly, &idx, n2n_rand());
+ encode_uint32(assembly, &idx, n2n_rand());
+
+ // adjust for maybe differently chosen TF_PREAMBLE_SIZE
+ idx = TF_PREAMBLE_SIZE;
+
+ // the plaintext data
+ encode_buf(assembly, &idx, inbuf, in_len);
+
+ // round up to next whole TF block size
+ padded_len = (((idx - 1) / TF_BLOCK_SIZE) + 1) * TF_BLOCK_SIZE;
+ padding = (padded_len-idx);
+ // pad the following bytes with zero, fixed length (TF_BLOCK_SIZE) seems to compile
+ // to slightly faster code than run-time dependant 'padding'
+ memset (assembly + idx, 0, TF_BLOCK_SIZE);
+ tf_cbc_encrypt(outbuf, assembly, padded_len, null_iv, priv->ctx);
+
+ if(padding) {
+ // exchange last two cipher blocks
+ memcpy (buf, outbuf + padded_len - TF_BLOCK_SIZE, TF_BLOCK_SIZE);
+ memcpy (outbuf + padded_len - TF_BLOCK_SIZE, outbuf + padded_len - 2 * TF_BLOCK_SIZE, TF_BLOCK_SIZE);
+ memcpy (outbuf + padded_len - 2 * TF_BLOCK_SIZE, buf, TF_BLOCK_SIZE);
}
- else
- {
- traceEvent( TRACE_ERROR, "encode_twofish outbuf too small." );
- }
- }
- else
- {
- traceEvent( TRACE_ERROR, "encode_twofish inbuf too big to encrypt." );
- }
+ } else
+ traceEvent(TRACE_ERROR, "transop_encode_tf outbuf too small");
+ } else
+ traceEvent(TRACE_ERROR, "transop_encode_tf inbuf too big to encrypt");
- return len;
+ return idx;
}
+/* ****************************************************** */
+
+// see transop_encode_tf for packet format
+static int transop_decode_tf(n2n_trans_op_t * arg,
+ uint8_t * outbuf,
+ size_t out_len,
+ const uint8_t * inbuf,
+ size_t in_len,
+ const uint8_t * peer_mac) {
-static int transop_decode_twofish( n2n_trans_op_t * arg,
- uint8_t * outbuf,
- size_t out_len,
- const uint8_t * inbuf,
- size_t in_len,
- const uint8_t * peer_mac)
-{
- int len=0;
transop_tf_t * priv = (transop_tf_t *)arg->priv;
uint8_t assembly[N2N_PKT_BUF_SIZE];
- if ( ( in_len <= N2N_PKT_BUF_SIZE ) /* Cipher text fits in assembly */
- && (in_len >= TRANSOP_TF_NONCE_SIZE ) /* Has at least nonce */
- ) {
+ uint8_t rest;
+ size_t penultimate_block;
+ uint8_t buf[TF_BLOCK_SIZE];
+ int len=-1;
- traceEvent(TRACE_DEBUG, "decode_twofish %lu", in_len);
+ if( ((in_len - TF_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) // cipher text fits in assembly
+ && (in_len >= TF_PREAMBLE_SIZE) // has at least random number
+ && (in_len >= TF_BLOCK_SIZE) // minimum size requirement for cipher text stealing
+ ) {
+
+ traceEvent(TRACE_DEBUG, "transop_decode_tf %lu bytes ciphertext", in_len);
+
+ rest = in_len % TF_BLOCK_SIZE;
+ if(rest) {
+ // cipher text stealing
+ penultimate_block = ((in_len / TF_BLOCK_SIZE) - 1) * TF_BLOCK_SIZE;
+ // everything normal up to penultimate block
+ memcpy(assembly, inbuf, penultimate_block);
+ // prepare new penultimate block in buf
+ tf_ecb_decrypt(buf, inbuf + penultimate_block, priv->ctx);
+ memcpy(buf, inbuf + in_len - rest, rest);
+ // former penultimate block becomes new ultimate block
+ memcpy(assembly + penultimate_block + TF_BLOCK_SIZE, inbuf + penultimate_block, TF_BLOCK_SIZE);
+ // write new penultimate block from buf
+ memcpy(assembly + penultimate_block, buf, TF_BLOCK_SIZE);
+ // regular cbc decryption on the re-arranged ciphertext
+
+ tf_cbc_decrypt(assembly, assembly, in_len + TF_BLOCK_SIZE - rest, null_iv, priv->ctx);
+
+ // check for expected zero padding and give a warning otherwise
+ if (memcmp(assembly + in_len, null_iv, TF_BLOCK_SIZE - rest)) {
+ traceEvent(TRACE_WARNING, "transop_decode_tf payload decryption failed with unexpected cipher text stealing padding");
+ return -1;
+ }
+ } else {
+ // regular cbc decryption on multiple block-sized payload
+ tf_cbc_decrypt(assembly, inbuf, in_len, null_iv, priv->ctx);
+ }
+ len = in_len - TF_PREAMBLE_SIZE;
+ memcpy(outbuf,
+ assembly + TF_PREAMBLE_SIZE,
+ len);
+ } else
+ traceEvent(TRACE_ERROR, "transop_decode_tf inbuf wrong size (%ul) to decrypt", in_len);
- len = TwoFishDecryptRaw( (void *)inbuf,
- assembly, /* destination */
- in_len,
- priv->dec_tf);
+ return len;
+}
- if(len > 0) {
- /* Step over 4-byte random nonce value */
- len -= TRANSOP_TF_NONCE_SIZE; /* size of ethernet packet */
+/* ****************************************************** */
- memcpy( outbuf,
- assembly + TRANSOP_TF_NONCE_SIZE,
- len );
- } else
- traceEvent(TRACE_ERROR, "decode_twofish decryption failed");
- } else
- traceEvent( TRACE_ERROR, "decode_twofish inbuf wrong size (%ul) to decrypt.", in_len );
+static int setup_tf_key(transop_tf_t *priv, const uint8_t *password, ssize_t password_len) {
- return len;
+ unsigned char key[32]; // tf key length, equals hash length
+ size_t key_size;
+
+ // the input password always gets hashed to make a more unpredictable use of the key space
+ // just think of usually reset MSB of ASCII coded password bytes
+ pearson_hash_256(key, password, password_len);
+
+ key_size = 32; // 256 bit
+
+ // setup the key and have corresponding context created
+ if (tf_init (key, key_size * 8, &(priv->ctx))) {
+ traceEvent(TRACE_ERROR, "setup_tf_key %u-bit key setup unsuccessful",
+ key_size * 8);
+ return -1;
+ }
+
+ traceEvent(TRACE_DEBUG, "setup_tf_key %u-bit key setup completed",
+ key_size * 8);
+ return 0;
}
-static void transop_tick_twofish( n2n_trans_op_t * arg, time_t now ) {}
+/* ****************************************************** */
-/* Twofish initialization function */
-int n2n_transop_twofish_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
+static void transop_tick_tf(n2n_trans_op_t * arg, time_t now) { ; }
+
+/* ****************************************************** */
+
+// Twofish initialization function
+int n2n_transop_tf_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
transop_tf_t *priv;
const u_char *encrypt_key = (const u_char *)conf->encrypt_key;
size_t encrypt_key_len = strlen(conf->encrypt_key);
- uint8_t key_hash[32];
memset(ttt, 0, sizeof(*ttt));
ttt->transform_id = N2N_TRANSFORM_ID_TWOFISH;
- ttt->tick = transop_tick_twofish;
- ttt->deinit = transop_deinit_twofish;
- ttt->fwd = transop_encode_twofish;
- ttt->rev = transop_decode_twofish;
+ ttt->tick = transop_tick_tf;
+ ttt->deinit = transop_deinit_tf;
+ ttt->fwd = transop_encode_tf;
+ ttt->rev = transop_decode_tf;
priv = (transop_tf_t*) calloc(1, sizeof(transop_tf_t));
if(!priv) {
- traceEvent(TRACE_ERROR, "cannot allocate transop_tf_t memory");
+ traceEvent(TRACE_ERROR, "n2n_transop_tf_cbc_init cannot allocate transop_tf_t memory");
return(-1);
}
ttt->priv = priv;
- /* This is a preshared key setup. Both Tx and Rx are using the same security association. */
- pearson_hash_256 (key_hash, encrypt_key, encrypt_key_len);
- priv->enc_tf = TwoFishInit(key_hash);
- priv->dec_tf = TwoFishInit(key_hash);
-
- if((!priv->enc_tf) || (!priv->dec_tf)) {
- if(priv->enc_tf) TwoFishDestroy(priv->enc_tf);
- if(priv->dec_tf) TwoFishDestroy(priv->dec_tf);
- free(priv);
- traceEvent(TRACE_ERROR, "TwoFishInit failed");
- return(-2);
- }
-
- return(0);
+ // setup the cipher and key
+ return(setup_tf_key(priv, encrypt_key, encrypt_key_len));
}
diff --git a/src/twofish.c b/src/twofish.c
deleted file mode 100644
index ebda2e6..0000000
--- a/src/twofish.c
+++ /dev/null
@@ -1,1002 +0,0 @@
-/* $Id: twofish.c,v 2.0 2002/08/11 22:32:25 fknobbe Exp $
- *
- *
- * Copyright (C) 1997-2000 The Cryptix Foundation Limited.
- * Copyright (C) 2000 Farm9.
- * Copyright (C) 2001 Frank Knobbe.
- * All rights reserved.
- *
- * For Cryptix code:
- * Use, modification, copying and distribution of this software is subject
- * the terms and conditions of the Cryptix General Licence. You should have
- * received a copy of the Cryptix General Licence along with this library;
- * if not, you can download a copy from http://www.cryptix.org/ .
- *
- * For Farm9:
- * --- jojo@farm9.com, August 2000, converted from Java to C++, added CBC mode and
- * ciphertext stealing technique, added AsciiTwofish class for easy encryption
- * decryption of text strings
- *
- * Frank Knobbe :
- * --- April 2001, converted from C++ to C, prefixed global variables
- * with TwoFish, substituted some defines, changed functions to make use of
- * variables supplied in a struct, modified and added routines for modular calls.
- * Cleaned up the code so that defines are used instead of fixed 16's and 32's.
- * Created two general purpose crypt routines for one block and multiple block
- * encryption using Joh's CBC code.
- * Added crypt routines that use a header (with a magic and data length).
- * (Basically a major rewrite).
- *
- * Note: Routines labeled _TwoFish are private and should not be used
- * (or with extreme caution).
- *
- */
-
-#ifndef __TWOFISH_LIBRARY_SOURCE__
-#define __TWOFISH_LIBRARY_SOURCE__
-
-#include "n2n.h"
-
-/* Fixed 8x8 permutation S-boxes */
-static const uint8_t TwoFish_P[2][256] =
- {
- { /* p0 */
- 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78,
- 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
- 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30,
- 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
- 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE,
- 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
- 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45,
- 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
- 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF,
- 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
- 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED,
- 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
- 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B,
- 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
- 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F,
- 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
- 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17,
- 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
- 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68,
- 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
- 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42,
- 0x4A, 0x5E, 0xC1, 0xE0
- },
- { /* p1 */
- 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B,
- 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
- 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B,
- 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
- 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54,
- 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
- 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7,
- 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
- 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF,
- 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
- 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D,
- 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
- 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21,
- 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
- 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E,
- 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
- 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44,
- 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
- 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B,
- 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
- 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56,
- 0x55, 0x09, 0xBE, 0x91
- }
- };
-
-static bool TwoFish_MDSready=FALSE;
-static uint32_t TwoFish_MDS[4][256]; /* TwoFish_MDS matrix */
-
-
-#define TwoFish_LFSR1(x) (((x)>>1)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/2:0))
-#define TwoFish_LFSR2(x) (((x)>>2)^(((x)&0x02)?TwoFish_MDS_GF_FDBK/2:0)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/4:0))
-
-#define TwoFish_Mx_1(x) ((uint32_t)(x)) /* force result to dword so << will work */
-#define TwoFish_Mx_X(x) ((uint32_t)((x)^TwoFish_LFSR2(x))) /* 5B */
-#define TwoFish_Mx_Y(x) ((uint32_t)((x)^TwoFish_LFSR1(x)^TwoFish_LFSR2(x))) /* EF */
-#define TwoFish_RS_rem(x) { uint8_t b=(uint8_t)(x>>24); uint32_t g2=((b<<1)^((b&0x80)?TwoFish_RS_GF_FDBK:0))&0xFF; uint32_t g3=((b>>1)&0x7F)^((b&1)?TwoFish_RS_GF_FDBK>>1:0)^g2; x=(x<<8)^(g3<<24)^(g2<<16)^(g3<<8)^b; }
-
-/*#define TwoFish__b(x,N) (((uint8_t *)&x)[((N)&3)^TwoFish_ADDR_XOR])*/ /* pick bytes out of a dword */
-
-#define TwoFish_b0(x) TwoFish__b(x,0) /* extract LSB of uint32_t */
-#define TwoFish_b1(x) TwoFish__b(x,1)
-#define TwoFish_b2(x) TwoFish__b(x,2)
-#define TwoFish_b3(x) TwoFish__b(x,3) /* extract MSB of uint32_t */
-
-uint8_t TwoFish__b(uint32_t x,int n)
-{ n&=3;
- while(n-->0)
- x>>=8;
- return (uint8_t)x;
-}
-
-
-/* TwoFish Initialization
- *
- * This routine generates a global data structure for use with TwoFish,
- * initializes important values (such as subkeys, sBoxes), generates subkeys
- * and precomputes the MDS matrix if not already done.
- *
- * Input: User supplied key of correct length (TwoFish_KEY_LENGTH, 256 bits = 32 bytes by default)
- *
- * Output: Pointer to TWOFISH structure. This data structure contains key dependent data.
- * This pointer is used with all other crypt functions.
- */
-
-TWOFISH *TwoFishInit(const uint8_t *userkey)
-{ TWOFISH *tfdata;
-
- tfdata=(TWOFISH *)malloc(sizeof(TWOFISH)); /* allocate the TwoFish structure */
- if(tfdata!=NULL)
- {
- memcpy(tfdata->key, userkey, TwoFish_KEY_LENGTH);
-
- if(!TwoFish_MDSready)
- _TwoFish_PrecomputeMDSmatrix(); /* "Wake Up, Neo" */
- _TwoFish_MakeSubKeys(tfdata); /* generate subkeys */
- _TwoFish_ResetCBC(tfdata); /* reset the CBC */
- tfdata->output=NULL; /* nothing to output yet */
- tfdata->dontflush=FALSE; /* reset decrypt skip block flag */
- }
- return tfdata; /* return the data pointer */
-}
-
-
-void TwoFishDestroy(TWOFISH *tfdata)
-{ if(tfdata!=NULL)
- free(tfdata);
-}
-
-
-/* en/decryption with CBC mode */
-uint32_t _TwoFish_CryptRawCBC(uint8_t *in,uint8_t *out,uint32_t len,bool decrypt,TWOFISH *tfdata)
-{ uint32_t rl;
-
- rl=len; /* remember how much data to crypt. */
- while(len>TwoFish_BLOCK_SIZE) /* and now we process block by block. */
- { _TwoFish_BlockCrypt(in,out,TwoFish_BLOCK_SIZE,decrypt,tfdata); /* de/encrypt it. */
- in+=TwoFish_BLOCK_SIZE; /* adjust pointers. */
- out+=TwoFish_BLOCK_SIZE;
- len-=TwoFish_BLOCK_SIZE;
- }
- if(len>0) /* if we have less than a block left... */
- _TwoFish_BlockCrypt(in,out,len,decrypt,tfdata); /* ...then we de/encrypt that too. */
- if(tfdata->qBlockDefined && !tfdata->dontflush) /* in case len was exactly one block... */
- _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); /* ...we need to write the... */
- /* ...remaining bytes of the buffer */
- return rl;
-}
-
-/* en/decryption on one block only */
-uint32_t _TwoFish_CryptRaw16(uint8_t *in,uint8_t *out,uint32_t len,bool decrypt,TWOFISH *tfdata)
-{ /* qBlockPlain already zero'ed through ResetCBC */
- memcpy(tfdata->qBlockPlain,in,len); /* toss the data into it. */
- _TwoFish_BlockCrypt16(tfdata->qBlockPlain,tfdata->qBlockCrypt,decrypt,tfdata); /* encrypt just that block without CBC. */
- memcpy(out,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE); /* and return what we got */
- return TwoFish_BLOCK_SIZE;
-}
-
-/* en/decryption without reset of CBC and output assignment */
-uint32_t _TwoFish_CryptRaw(uint8_t *in,uint8_t *out,uint32_t len,bool decrypt,TWOFISH *tfdata)
-{
- if(in!=NULL && out!=NULL && len>0 && tfdata!=NULL) /* if we have valid data, then... */
- { if(len>TwoFish_BLOCK_SIZE) /* ...check if we have more than one block. */
- return _TwoFish_CryptRawCBC(in,out,len,decrypt,tfdata); /* if so, use the CBC routines... */
- else
- return _TwoFish_CryptRaw16(in,out,len,decrypt,tfdata); /* ...otherwise just do one block. */
- }
- return 0;
-}
-
-
-/* TwoFish Raw Encryption
- *
- * Does not use header, but does use CBC (if more than one block has to be encrypted).
- *
- * Input: Pointer to the buffer of the plaintext to be encrypted.
- * Pointer to the buffer receiving the ciphertext.
- * The length of the plaintext buffer.
- * The TwoFish structure.
- *
- * Output: The amount of bytes encrypted if successful, otherwise 0.
- */
-
-uint32_t TwoFishEncryptRaw(uint8_t *in,
- uint8_t *out,
- uint32_t len,
- TWOFISH *tfdata)
-{ _TwoFish_ResetCBC(tfdata); /* reset CBC flag. */
- tfdata->output=out; /* output straight into output buffer. */
- return _TwoFish_CryptRaw(in,out,len,FALSE,tfdata); /* and go for it. */
-}
-
-/* TwoFish Raw Decryption
- *
- * Does not use header, but does use CBC (if more than one block has to be decrypted).
- *
- * Input: Pointer to the buffer of the ciphertext to be decrypted.
- * Pointer to the buffer receiving the plaintext.
- * The length of the ciphertext buffer (at least one cipher block).
- * The TwoFish structure.
- *
- * Output: The amount of bytes decrypted if successful, otherwise 0.
- */
-
-uint32_t TwoFishDecryptRaw(uint8_t *in,
- uint8_t *out,
- uint32_t len,
- TWOFISH *tfdata)
-{ _TwoFish_ResetCBC(tfdata); /* reset CBC flag. */
- tfdata->output=out; /* output straight into output buffer. */
- return _TwoFish_CryptRaw(in,out,len,TRUE,tfdata); /* and go for it. */
-}
-
-/* TwoFish Free
- *
- * Free's the allocated buffer.
- *
- * Input: Pointer to the TwoFish structure
- *
- * Output: (none)
- */
-
-void TwoFishFree(TWOFISH *tfdata)
-{ if(tfdata->output!=NULL) /* if a valid buffer is present... */
- { free(tfdata->output); /* ...then we free it for you... */
- tfdata->output=NULL; /* ...and mark as such. */
- }
-}
-
-/* TwoFish Set Output
- *
- * If you want to allocate the output buffer yourself,
- * then you can set it with this function.
- *
- * Input: Pointer to your output buffer
- * Pointer to the TwoFish structure
- *
- * Output: (none)
- */
-
-void TwoFishSetOutput(uint8_t *outp,TWOFISH *tfdata)
-{ tfdata->output=outp; /* (do we really need a function for this?) */
-}
-
-/* TwoFish Alloc
- *
- * Allocates enough memory for the output buffer that would be required
- *
- * Input: Length of the plaintext.
- * Boolean flag for BinHex Output.
- * Pointer to the TwoFish structure.
- *
- * Output: Returns a pointer to the memory allocated.
- */
-
-void *TwoFishAlloc(uint32_t len,bool binhex,bool decrypt,TWOFISH *tfdata)
-{
- /* TwoFishFree(tfdata); */ /* (don't for now) discard whatever was allocated earlier. */
- if(decrypt) /* if decrypting... */
- { if(binhex) /* ...and input is binhex encoded... */
- len/=2; /* ...use half as much for output. */
- len-=TwoFish_BLOCK_SIZE; /* Also, subtract the size of the header. */
- }
- else
- { len+=TwoFish_BLOCK_SIZE; /* the size is just increased by the header... */
- if(binhex)
- len*=2; /* ...and doubled if output is to be binhexed. */
- }
- tfdata->output=malloc(len+TwoFish_BLOCK_SIZE);/* grab some memory...plus some extra (it's running over somewhere, crashes without extra padding) */
-
- return tfdata->output; /* ...and return to caller. */
-}
-
-/* bin2hex and hex2bin conversion */
-void _TwoFish_BinHex(uint8_t *buf,uint32_t len,bool bintohex)
-{ uint8_t *pi,*po,c;
-
- if(bintohex)
- { for(pi=buf+len-1,po=buf+(2*len)-1;len>0;pi--,po--,len--) /* let's start from the end of the bin block. */
- { c=*pi; /* grab value. */
- c&=15; /* use lower 4 bits. */
- if(c>9) /* convert to ascii. */
- c+=('a'-10);
- else
- c+='0';
- *po--=c; /* set the lower nibble. */
- c=*pi; /* grab value again. */
- c>>=4; /* right shift 4 bits. */
- c&=15; /* make sure we only have 4 bits. */
- if(c>9) /* convert to ascii. */
- c+=('a'-10);
- else
- c+='0';
- *po=c; /* set the higher nibble. */
- } /* and keep going. */
- }
- else
- { for(pi=buf,po=buf;len>0;pi++,po++,len-=2) /* let's start from the beginning of the hex block. */
- { c=tolower(*pi++)-'0'; /* grab higher nibble. */
- if(c>9) /* convert to value. */
- c-=('0'-9);
- *po=c<<4; /* left shit 4 bits. */
- c=tolower(*pi)-'0'; /* grab lower nibble. */
- if(c>9) /* convert to value. */
- c-=('0'-9);
- *po|=c; /* and add to value. */
- }
- }
-}
-
-
-/* TwoFish Encryption
- *
- * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
- * this routine will alloc the memory. In addition, it will include a small 'header'
- * containing the magic and some salt. That way the decrypt routine can check if the
- * packet got decrypted successfully, and return 0 instead of garbage.
- *
- * Input: Pointer to the buffer of the plaintext to be encrypted.
- * Pointer to the pointer to the buffer receiving the ciphertext.
- * The pointer either points to user allocated output buffer space, or to NULL, in which case
- * this routine will set the pointer to the buffer allocated through the struct.
- * The length of the plaintext buffer.
- * Can be -1 if the input is a null terminated string, in which case we'll count for you.
- * Boolean flag for BinHex Output (if used, output will be twice as large as input).
- * Note: BinHex conversion overwrites (converts) input buffer!
- * The TwoFish structure.
- *
- * Output: The amount of bytes encrypted if successful, otherwise 0.
- */
-
-uint32_t TwoFishEncrypt(uint8_t *in,
- uint8_t **out,
- signed long len,
- bool binhex,
- TWOFISH *tfdata)
-{ uint32_t ilen,olen;
-
-
-#if 0
-/* This is so broken it doesn't deserve to live. */
- if(len== -1) /* if we got -1 for len, we'll assume IN is a... */
- ilen=strlen(in); /* ...\0 terminated string and figure len out ourselves... */
- else
- ilen=len; /* ...otherwise we trust you supply a correct length. */
-#endif
-
- ilen = len;
-
- if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */
- { if(*out==NULL) /* if OUT points to a NULL pointer... */
- *out=TwoFishAlloc(ilen,binhex,FALSE,tfdata); /* ...we'll (re-)allocate buffer space. */
- if(*out!=NULL)
- { tfdata->output=*out; /* set output buffer. */
- tfdata->header.salt=n2n_rand()*65536+n2n_rand(); /* toss in some salt. */
- tfdata->header.length[0]= (uint8_t)(ilen);
- tfdata->header.length[1]= (uint8_t)(ilen>>8);
- tfdata->header.length[2]= (uint8_t)(ilen>>16);
- tfdata->header.length[3]= (uint8_t)(ilen>>24);
- memcpy(tfdata->header.magic,TwoFish_MAGIC,TwoFish_MAGIC_LEN); /* set the magic. */
- olen=TwoFish_BLOCK_SIZE; /* set output counter. */
- _TwoFish_ResetCBC(tfdata); /* reset the CBC flag */
- _TwoFish_BlockCrypt((uint8_t *)&(tfdata->header),*out,olen,FALSE,tfdata); /* encrypt first block (without flush on 16 byte boundary). */
- olen+=_TwoFish_CryptRawCBC(in,*out+TwoFish_BLOCK_SIZE,ilen,FALSE,tfdata); /* and encrypt the rest (we do not reset the CBC flag). */
- if(binhex) /* if binhex... */
- { _TwoFish_BinHex(*out,olen,TRUE); /* ...convert output to binhex... */
- olen*=2; /* ...and size twice as large. */
- }
- tfdata->output=*out;
- return olen;
- }
- }
- return 0;
-}
-
-/* TwoFish Decryption
- *
- * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
- * this routine will alloc the memory. In addition, it will check the small 'header'
- * containing the magic. If magic does not match we return 0. Otherwise we return the
- * amount of bytes decrypted (should be the same as the length in the header).
- *
- * Input: Pointer to the buffer of the ciphertext to be decrypted.
- * Pointer to the pointer to the buffer receiving the plaintext.
- * The pointer either points to user allocated output buffer space, or to NULL, in which case
- * this routine will set the pointer to the buffer allocated through the struct.
- * The length of the ciphertext buffer.
- * Can be -1 if the input is a null terminated binhex string, in which case we'll count for you.
- * Boolean flag for BinHex Input (if used, plaintext will be half as large as input).
- * Note: BinHex conversion overwrites (converts) input buffer!
- * The TwoFish structure.
- *
- * Output: The amount of bytes decrypted if successful, otherwise 0.
- */
-
-uint32_t TwoFishDecrypt(uint8_t *in,
- uint8_t **out,
- signed long len,
- bool binhex,
- TWOFISH *tfdata)
-{ uint32_t ilen,elen,olen;
- const uint8_t cmagic[TwoFish_MAGIC_LEN]=TwoFish_MAGIC;
- uint8_t *tbuf;
-
-
-
-#if 0
-/* This is so broken it doesn't deserve to live. */
- if(len== -1) /* if we got -1 for len, we'll assume IN is a... */
- ilen=strlen(in); /* ...\0 terminated string and figure len out ourselves... */
- else
- ilen=len; /* ...otherwise we trust you supply a correct length. */
-#endif
-
- ilen = len;
-
- if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */
- { if(*out==NULL) /* if OUT points to a NULL pointer... */
- *out=TwoFishAlloc(ilen,binhex,TRUE,tfdata); /* ...we'll (re-)allocate buffer space. */
- if(*out!=NULL)
- { if(binhex) /* if binhex... */
- { _TwoFish_BinHex(in,ilen,FALSE); /* ...convert input to values... */
- ilen/=2; /* ...and size half as much. */
- }
- _TwoFish_ResetCBC(tfdata); /* reset the CBC flag. */
-
- tbuf=(uint8_t *)malloc(ilen+TwoFish_BLOCK_SIZE); /* get memory for data and header. */
- if(tbuf==NULL)
- return 0;
- tfdata->output=tbuf; /* set output to temp buffer. */
-
- olen=_TwoFish_CryptRawCBC(in,tbuf,ilen,TRUE,tfdata)-TwoFish_BLOCK_SIZE; /* decrypt the whole thing. */
- memcpy(&(tfdata->header),tbuf,TwoFish_BLOCK_SIZE); /* copy first block into header. */
- tfdata->output=*out;
- for(elen=0;elenheader.magic[elen]!=cmagic[elen])
- break;
- if(elen==TwoFish_MAGIC_LEN) /* if magic matches then... */
- { elen=(tfdata->header.length[0]) |
- (tfdata->header.length[1])<<8 |
- (tfdata->header.length[2])<<16 |
- (tfdata->header.length[3])<<24; /* .. we know how much to expect. */
- if(elen>olen) /* adjust if necessary. */
- elen=olen;
- memcpy(*out,tbuf+TwoFish_BLOCK_SIZE,elen); /* copy data into intended output. */
- free(tbuf);
- return elen;
- }
- free(tbuf);
- }
- }
- return 0;
-}
-
-void _TwoFish_PrecomputeMDSmatrix(void) /* precompute the TwoFish_MDS matrix */
-{ uint32_t m1[2];
- uint32_t mX[2];
- uint32_t mY[2];
- uint32_t i, j;
-
- for (i = 0; i < 256; i++)
- { j = TwoFish_P[0][i] & 0xFF; /* compute all the matrix elements */
- m1[0] = j;
- mX[0] = TwoFish_Mx_X( j ) & 0xFF;
- mY[0] = TwoFish_Mx_Y( j ) & 0xFF;
-
- j = TwoFish_P[1][i] & 0xFF;
- m1[1] = j;
- mX[1] = TwoFish_Mx_X( j ) & 0xFF;
- mY[1] = TwoFish_Mx_Y( j ) & 0xFF;
-
- TwoFish_MDS[0][i] = m1[TwoFish_P_00] | /* fill matrix w/ above elements */
- mX[TwoFish_P_00] << 8 |
- mY[TwoFish_P_00] << 16 |
- mY[TwoFish_P_00] << 24;
- TwoFish_MDS[1][i] = mY[TwoFish_P_10] |
- mY[TwoFish_P_10] << 8 |
- mX[TwoFish_P_10] << 16 |
- m1[TwoFish_P_10] << 24;
- TwoFish_MDS[2][i] = mX[TwoFish_P_20] |
- mY[TwoFish_P_20] << 8 |
- m1[TwoFish_P_20] << 16 |
- mY[TwoFish_P_20] << 24;
- TwoFish_MDS[3][i] = mX[TwoFish_P_30] |
- m1[TwoFish_P_30] << 8 |
- mY[TwoFish_P_30] << 16 |
- mX[TwoFish_P_30] << 24;
- }
- TwoFish_MDSready=TRUE;
-}
-
-
-void _TwoFish_MakeSubKeys(TWOFISH *tfdata) /* Expand a user-supplied key material into a session key. */
-{ uint32_t k64Cnt = TwoFish_KEY_LENGTH / 8;
- uint32_t k32e[4]; /* even 32-bit entities */
- uint32_t k32o[4]; /* odd 32-bit entities */
- uint32_t sBoxKey[4];
- uint32_t offset,i,j;
- uint32_t A, B, q=0;
- uint32_t k0,k1,k2,k3;
- uint32_t b0,b1,b2,b3;
-
- /* split user key material into even and odd 32-bit entities and */
- /* compute S-box keys using (12, 8) Reed-Solomon code over GF(256) */
-
-
- for (offset=0,i=0,j=k64Cnt-1;i<4 && offsetkey[offset++];
- k32e[i]|= tfdata->key[offset++]<<8;
- k32e[i]|= tfdata->key[offset++]<<16;
- k32e[i]|= tfdata->key[offset++]<<24;
- k32o[i] = tfdata->key[offset++];
- k32o[i]|= tfdata->key[offset++]<<8;
- k32o[i]|= tfdata->key[offset++]<<16;
- k32o[i]|= tfdata->key[offset++]<<24;
- sBoxKey[j] = _TwoFish_RS_MDS_Encode( k32e[i], k32o[i] ); /* reverse order */
- }
-
- /* compute the round decryption subkeys for PHT. these same subkeys */
- /* will be used in encryption but will be applied in reverse order. */
- i=0;
- while(i < TwoFish_TOTAL_SUBKEYS)
- { A = _TwoFish_F32( k64Cnt, q, k32e ); /* A uses even key entities */
- q += TwoFish_SK_BUMP;
-
- B = _TwoFish_F32( k64Cnt, q, k32o ); /* B uses odd key entities */
- q += TwoFish_SK_BUMP;
-
- B = B << 8 | B >> 24;
-
- A += B;
- tfdata->subKeys[i++] = A; /* combine with a PHT */
-
- A += B;
- tfdata->subKeys[i++] = A << TwoFish_SK_ROTL | A >> (32-TwoFish_SK_ROTL);
- }
-
- /* fully expand the table for speed */
- k0 = sBoxKey[0];
- k1 = sBoxKey[1];
- k2 = sBoxKey[2];
- k3 = sBoxKey[3];
-
- for (i = 0; i < 256; i++)
- { b0 = b1 = b2 = b3 = i;
- switch (k64Cnt & 3)
- { case 1: /* 64-bit keys */
- tfdata->sBox[ 2*i ] = TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0]) ^ TwoFish_b0(k0)];
- tfdata->sBox[ 2*i+1] = TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1]) ^ TwoFish_b1(k0)];
- tfdata->sBox[0x200+2*i ] = TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2]) ^ TwoFish_b2(k0)];
- tfdata->sBox[0x200+2*i+1] = TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3]) ^ TwoFish_b3(k0)];
- break;
- case 0: /* 256-bit keys (same as 4) */
- b0 = (TwoFish_P[TwoFish_P_04][b0]) ^ TwoFish_b0(k3);
- b1 = (TwoFish_P[TwoFish_P_14][b1]) ^ TwoFish_b1(k3);
- b2 = (TwoFish_P[TwoFish_P_24][b2]) ^ TwoFish_b2(k3);
- b3 = (TwoFish_P[TwoFish_P_34][b3]) ^ TwoFish_b3(k3);
- case 3: /* 192-bit keys */
- b0 = (TwoFish_P[TwoFish_P_03][b0]) ^ TwoFish_b0(k2);
- b1 = (TwoFish_P[TwoFish_P_13][b1]) ^ TwoFish_b1(k2);
- b2 = (TwoFish_P[TwoFish_P_23][b2]) ^ TwoFish_b2(k2);
- b3 = (TwoFish_P[TwoFish_P_33][b3]) ^ TwoFish_b3(k2);
- case 2: /* 128-bit keys */
- tfdata->sBox[ 2*i ]=
- TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0]) ^
- TwoFish_b0(k1)]) ^ TwoFish_b0(k0)];
-
- tfdata->sBox[ 2*i+1]=
- TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1]) ^
- TwoFish_b1(k1)]) ^ TwoFish_b1(k0)];
-
- tfdata->sBox[0x200+2*i ]=
- TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2]) ^
- TwoFish_b2(k1)]) ^ TwoFish_b2(k0)];
-
- tfdata->sBox[0x200+2*i+1]=
- TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3]) ^
- TwoFish_b3(k1)]) ^ TwoFish_b3(k0)];
- }
- }
-}
-
-
-/**
- * Encrypt or decrypt exactly one block of plaintext in CBC mode.
- * Use "ciphertext stealing" technique described on pg. 196
- * of "Applied Cryptography" to encrypt the final partial
- * (i.e. <16 byte) block if necessary.
- *
- * jojo: the "ciphertext stealing" requires we read ahead and have
- * special handling for the last two blocks. Because of this, the
- * output from the TwoFish algorithm is handled internally here.
- * It would be better to have a higher level handle this as well as
- * CBC mode. Unfortunately, I've mixed the two together, which is
- * pretty crappy... The Java version separates these out correctly.
- *
- * fknobbe: I have reduced the CBC mode to work on memory buffer only.
- * Higher routines should use an intermediate buffer and handle
- * their output seperately (mainly so the data can be flushed
- * in one chunk, not seperate 16 byte blocks...)
- *
- * @param in The plaintext.
- * @param out The ciphertext
- * @param size how much to encrypt
- * @param tfdata: Pointer to the global data structure containing session keys.
- * @return none
- */
-void _TwoFish_BlockCrypt(uint8_t *in,uint8_t *out,uint32_t size,int decrypt,TWOFISH *tfdata)
-{ uint8_t PnMinusOne[TwoFish_BLOCK_SIZE];
- uint8_t CnMinusOne[TwoFish_BLOCK_SIZE];
- uint8_t CBCplusCprime[TwoFish_BLOCK_SIZE];
- uint8_t Pn[TwoFish_BLOCK_SIZE];
- uint8_t *p,*pout;
- uint32_t i;
-
- /* here is where we implement CBC mode and cipher block stealing */
- if(size==TwoFish_BLOCK_SIZE)
- { /* if we are encrypting, CBC means we XOR the plain text block with the */
- /* previous cipher text block before encrypting */
- if(!decrypt && tfdata->qBlockDefined)
- { for(p=in,i=0;iqBlockCrypt[i]; /* FK: I'm copying the xor'ed input into Pn... */
- }
- else
- memcpy(Pn,in,TwoFish_BLOCK_SIZE); /* FK: same here. we work of Pn all the time. */
-
- /* TwoFish block level encryption or decryption */
- _TwoFish_BlockCrypt16(Pn,out,decrypt,tfdata);
-
- /* if we are decrypting, CBC means we XOR the result of the decryption */
- /* with the previous cipher text block to get the resulting plain text */
- if(decrypt && tfdata->qBlockDefined)
- { for (p=out,i=0;iqBlockPlain[i];
- }
-
- /* save the input and output blocks, since CBC needs these for XOR */
- /* operations */
- _TwoFish_qBlockPush(Pn,out,tfdata);
- }
- else
- { /* cipher block stealing, we are at Pn, */
- /* but since Cn-1 must now be replaced with CnC' */
- /* we pop it off, and recalculate Cn-1 */
-
- if(decrypt)
- { /* We are on an odd block, and had to do cipher block stealing, */
- /* so the PnMinusOne has to be derived differently. */
-
- /* First we decrypt it into CBC and C' */
- _TwoFish_qBlockPop(CnMinusOne,PnMinusOne,tfdata);
- _TwoFish_BlockCrypt16(CnMinusOne,CBCplusCprime,decrypt,tfdata);
-
- /* we then xor the first few bytes with the "in" bytes (Cn) */
- /* to recover Pn, which we put in out */
- for(p=in,pout=out,i=0;iprevCipher[i];
-
- /* So at this point, out has PnMinusOne */
- _TwoFish_qBlockPush(CnMinusOne,PnMinusOne,tfdata);
- _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata);
- _TwoFish_FlushOutput(out,size,tfdata);
- }
- else
- { _TwoFish_qBlockPop(PnMinusOne,CnMinusOne,tfdata);
- memset(Pn,0,TwoFish_BLOCK_SIZE);
- memcpy(Pn,in,size);
- for(i=0;iqBlockCrypt,TwoFish_BLOCK_SIZE,tfdata);
- _TwoFish_FlushOutput(CnMinusOne,size,tfdata); /* old Cn-1 becomes new partial Cn */
- }
- tfdata->qBlockDefined=FALSE;
- }
-}
-
-void _TwoFish_qBlockPush(uint8_t *p,uint8_t *c,TWOFISH *tfdata)
-{ if(tfdata->qBlockDefined)
- _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata);
- memcpy(tfdata->prevCipher,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE);
- memcpy(tfdata->qBlockPlain,p,TwoFish_BLOCK_SIZE);
- memcpy(tfdata->qBlockCrypt,c,TwoFish_BLOCK_SIZE);
- tfdata->qBlockDefined=TRUE;
-}
-
-void _TwoFish_qBlockPop(uint8_t *p,uint8_t *c,TWOFISH *tfdata)
-{ memcpy(p,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE );
- memcpy(c,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE );
- tfdata->qBlockDefined=FALSE;
-}
-
-/* Reset's the CBC flag and zero's PrevCipher (through qBlockPlain) (important) */
-void _TwoFish_ResetCBC(TWOFISH *tfdata)
-{ tfdata->qBlockDefined=FALSE;
- memset(tfdata->qBlockPlain,0,TwoFish_BLOCK_SIZE);
-}
-
-void _TwoFish_FlushOutput(uint8_t *b,uint32_t len,TWOFISH *tfdata)
-{ uint32_t i;
-
- for(i=0;idontflush;i++)
- *tfdata->output++ = *b++;
- tfdata->dontflush=FALSE;
-}
-
-void _TwoFish_BlockCrypt16(uint8_t *in,uint8_t *out,bool decrypt,TWOFISH *tfdata)
-{ uint32_t x0,x1,x2,x3;
- uint32_t k,t0,t1,R;
-
-
- x0=*in++;
- x0|=(*in++ << 8 );
- x0|=(*in++ << 16);
- x0|=(*in++ << 24);
- x1=*in++;
- x1|=(*in++ << 8 );
- x1|=(*in++ << 16);
- x1|=(*in++ << 24);
- x2=*in++;
- x2|=(*in++ << 8 );
- x2|=(*in++ << 16);
- x2|=(*in++ << 24);
- x3=*in++;
- x3|=(*in++ << 8 );
- x3|=(*in++ << 16);
- x3|=(*in++ << 24);
-
- if(decrypt)
- { x0 ^= tfdata->subKeys[4]; /* swap input and output whitening keys when decrypting */
- x1 ^= tfdata->subKeys[5];
- x2 ^= tfdata->subKeys[6];
- x3 ^= tfdata->subKeys[7];
-
- k = 7+(TwoFish_ROUNDS*2);
- for (R = 0; R < TwoFish_ROUNDS; R += 2)
- { t0 = _TwoFish_Fe320( tfdata->sBox, x0);
- t1 = _TwoFish_Fe323( tfdata->sBox, x1);
- x3 ^= t0 + (t1<<1) + tfdata->subKeys[k--];
- x3 = x3 >> 1 | x3 << 31;
- x2 = x2 << 1 | x2 >> 31;
- x2 ^= t0 + t1 + tfdata->subKeys[k--];
-
- t0 = _TwoFish_Fe320( tfdata->sBox, x2);
- t1 = _TwoFish_Fe323( tfdata->sBox, x3);
- x1 ^= t0 + (t1<<1) + tfdata->subKeys[k--];
- x1 = x1 >> 1 | x1 << 31;
- x0 = x0 << 1 | x0 >> 31;
- x0 ^= t0 + t1 + tfdata->subKeys[k--];
- }
-
- x2 ^= tfdata->subKeys[0];
- x3 ^= tfdata->subKeys[1];
- x0 ^= tfdata->subKeys[2];
- x1 ^= tfdata->subKeys[3];
- }
- else
- { x0 ^= tfdata->subKeys[0];
- x1 ^= tfdata->subKeys[1];
- x2 ^= tfdata->subKeys[2];
- x3 ^= tfdata->subKeys[3];
-
- k = 8;
- for (R = 0; R < TwoFish_ROUNDS; R += 2)
- { t0 = _TwoFish_Fe320( tfdata->sBox, x0);
- t1 = _TwoFish_Fe323( tfdata->sBox, x1);
- x2 ^= t0 + t1 + tfdata->subKeys[k++];
- x2 = x2 >> 1 | x2 << 31;
- x3 = x3 << 1 | x3 >> 31;
- x3 ^= t0 + (t1<<1) + tfdata->subKeys[k++];
-
- t0 = _TwoFish_Fe320( tfdata->sBox, x2);
- t1 = _TwoFish_Fe323( tfdata->sBox, x3);
- x0 ^= t0 + t1 + tfdata->subKeys[k++];
- x0 = x0 >> 1 | x0 << 31;
- x1 = x1 << 1 | x1 >> 31;
- x1 ^= t0 + (t1<<1) + tfdata->subKeys[k++];
- }
-
- x2 ^= tfdata->subKeys[4];
- x3 ^= tfdata->subKeys[5];
- x0 ^= tfdata->subKeys[6];
- x1 ^= tfdata->subKeys[7];
- }
-
- *out++ = (uint8_t)(x2 );
- *out++ = (uint8_t)(x2 >> 8);
- *out++ = (uint8_t)(x2 >> 16);
- *out++ = (uint8_t)(x2 >> 24);
-
- *out++ = (uint8_t)(x3 );
- *out++ = (uint8_t)(x3 >> 8);
- *out++ = (uint8_t)(x3 >> 16);
- *out++ = (uint8_t)(x3 >> 24);
-
- *out++ = (uint8_t)(x0 );
- *out++ = (uint8_t)(x0 >> 8);
- *out++ = (uint8_t)(x0 >> 16);
- *out++ = (uint8_t)(x0 >> 24);
-
- *out++ = (uint8_t)(x1 );
- *out++ = (uint8_t)(x1 >> 8);
- *out++ = (uint8_t)(x1 >> 16);
- *out++ = (uint8_t)(x1 >> 24);
-}
-
-/**
- * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box
- * 32-bit entity from two key material 32-bit entities.
- *
- * @param k0 1st 32-bit entity.
- * @param k1 2nd 32-bit entity.
- * @return Remainder polynomial generated using RS code
- */
-uint32_t _TwoFish_RS_MDS_Encode(uint32_t k0,uint32_t k1)
-{ uint32_t i,r;
-
- for(r=k1,i=0;i<4;i++) /* shift 1 byte at a time */
- TwoFish_RS_rem(r);
- r ^= k0;
- for(i=0;i<4;i++)
- TwoFish_RS_rem(r);
-
- return r;
-}
-
-uint32_t _TwoFish_F32(uint32_t k64Cnt,uint32_t x,uint32_t *k32)
-{ uint8_t b0,b1,b2,b3;
- uint32_t k0,k1,k2,k3,result = 0;
-
- b0=TwoFish_b0(x);
- b1=TwoFish_b1(x);
- b2=TwoFish_b2(x);
- b3=TwoFish_b3(x);
- k0=k32[0];
- k1=k32[1];
- k2=k32[2];
- k3=k32[3];
-
- switch (k64Cnt & 3)
- { case 1: /* 64-bit keys */
- result =
- TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0] & 0xFF) ^ TwoFish_b0(k0)] ^
- TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1] & 0xFF) ^ TwoFish_b1(k0)] ^
- TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2] & 0xFF) ^ TwoFish_b2(k0)] ^
- TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3] & 0xFF) ^ TwoFish_b3(k0)];
- break;
- case 0: /* 256-bit keys (same as 4) */
- b0 = (TwoFish_P[TwoFish_P_04][b0] & 0xFF) ^ TwoFish_b0(k3);
- b1 = (TwoFish_P[TwoFish_P_14][b1] & 0xFF) ^ TwoFish_b1(k3);
- b2 = (TwoFish_P[TwoFish_P_24][b2] & 0xFF) ^ TwoFish_b2(k3);
- b3 = (TwoFish_P[TwoFish_P_34][b3] & 0xFF) ^ TwoFish_b3(k3);
-
- case 3: /* 192-bit keys */
- b0 = (TwoFish_P[TwoFish_P_03][b0] & 0xFF) ^ TwoFish_b0(k2);
- b1 = (TwoFish_P[TwoFish_P_13][b1] & 0xFF) ^ TwoFish_b1(k2);
- b2 = (TwoFish_P[TwoFish_P_23][b2] & 0xFF) ^ TwoFish_b2(k2);
- b3 = (TwoFish_P[TwoFish_P_33][b3] & 0xFF) ^ TwoFish_b3(k2);
- case 2: /* 128-bit keys (optimize for this case) */
- result =
- TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0] & 0xFF) ^ TwoFish_b0(k1)] & 0xFF) ^ TwoFish_b0(k0)] ^
- TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1] & 0xFF) ^ TwoFish_b1(k1)] & 0xFF) ^ TwoFish_b1(k0)] ^
- TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2] & 0xFF) ^ TwoFish_b2(k1)] & 0xFF) ^ TwoFish_b2(k0)] ^
- TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3] & 0xFF) ^ TwoFish_b3(k1)] & 0xFF) ^ TwoFish_b3(k0)];
- break;
- }
- return result;
-}
-
-uint32_t _TwoFish_Fe320(uint32_t *lsBox,uint32_t x)
-{ return lsBox[ TwoFish_b0(x)<<1 ]^
- lsBox[ ((TwoFish_b1(x)<<1)|1)]^
- lsBox[0x200+ (TwoFish_b2(x)<<1) ]^
- lsBox[0x200+((TwoFish_b3(x)<<1)|1)];
-}
-
-uint32_t _TwoFish_Fe323(uint32_t *lsBox,uint32_t x)
-{ return lsBox[ (TwoFish_b3(x)<<1) ]^
- lsBox[ ((TwoFish_b0(x)<<1)|1)]^
- lsBox[0x200+ (TwoFish_b1(x)<<1) ]^
- lsBox[0x200+((TwoFish_b2(x)<<1)|1)];
-}
-
-uint32_t _TwoFish_Fe32(uint32_t *lsBox,uint32_t x,uint32_t R)
-{ return lsBox[ 2*TwoFish__b(x,R ) ]^
- lsBox[ 2*TwoFish__b(x,R+1)+1]^
- lsBox[0x200+2*TwoFish__b(x,R+2) ]^
- lsBox[0x200+2*TwoFish__b(x,R+3)+1];
-}
-
-
-#endif
-
-/* ******************************************* */
-#if defined TWOFISH_UNIT_TEST
-#include
-
-#define TEST_DATA_SIZE 327
-
-int main(int argc, char* argv[])
-{
- int i;
- int n;
-
- char outbuf[4096];
- char * outp = outbuf;
-
- uint8_t key[] = { 0xfc, 0x77, 0x1a, 0xda, 0xaa,
- 0xfc, 0x77, 0x1a, 0xda, 0xaa,
- 0xfc, 0x77, 0x1a, 0xda, 0xaa,
- 0xfc, 0x77, 0x1a, 0xda, 0xaa,
- 0xfc, 0x77, 0x1a, 0xda, 0xaa,
- 0xfc, 0x77, 0x1a, 0xda, 0xaa,
- 0xfc, 0x77 };
-
- TWOFISH *tfa = TwoFishInit( key );
- TWOFISH *tfb = TwoFishInit( key );
-
- uint8_t out[2048], out2[2048];
- uint8_t in[TEST_DATA_SIZE];
-
- for ( i=0; i