From f21f781b45692405e2ea61ef9bf8cfd2ba331739 Mon Sep 17 00:00:00 2001 From: Ruud de Rooij <ruud@debian.org> Date: Thu, 4 Mar 1999 19:48:36 +0100 Subject: [PATCH] Initial twofish support Rev: src/symmetric/generate_q.c:1.1 Rev: src/symmetric/include/twofish.h:1.1 Rev: src/symmetric/twofish.c:1.1 --- generate_q.c | 115 ++++++++++ include/twofish.h | 101 ++++++++ twofish.c | 574 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 790 insertions(+) create mode 100644 generate_q.c create mode 100644 include/twofish.h create mode 100644 twofish.c diff --git a/generate_q.c b/generate_q.c new file mode 100644 index 00000000..49e06d2a --- /dev/null +++ b/generate_q.c @@ -0,0 +1,115 @@ +/* + * generate_q - Generates the permutations q0 and q1 for twofish. + * Copyright (C) 1999 Ruud de Rooij <ruud@debian.org> + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> + +typedef unsigned char byte; + +#define ror4(x) (((x) >> 1) | (((x) & 1) << 3)) + +static byte q0(byte x) +{ + + static byte t0[16] = { 0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, + 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4 }; + static byte t1[16] = { 0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, + 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD }; + static byte t2[16] = { 0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, + 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1 }; + static byte t3[16] = { 0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, + 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA }; + + byte a0 = x / 16; + byte b0 = x % 16; + + byte a1 = a0 ^ b0; + byte b1 = a0 ^ ror4(b0) ^ ((8*a0) % 16); + + byte a2 = t0[a1]; + byte b2 = t1[b1]; + + byte a3 = a2 ^ b2; + byte b3 = a2 ^ ror4(b2) ^ ((8*a2) % 16); + + byte a4 = t2[a3]; + byte b4 = t3[b3]; + + byte y = 16*b4 + a4; + + return y; +} + +static byte q1(byte x) +{ + static byte t0[16] = { 0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, + 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5 }; + static byte t1[16] = { 0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, + 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8 }; + static byte t2[16] = { 0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, + 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF }; + static byte t3[16] = { 0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, + 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA }; + + byte a0 = x / 16; + byte b0 = x % 16; + + byte a1 = a0 ^ b0; + byte b1 = a0 ^ ror4(b0) ^ ((8*a0) % 16); + + byte a2 = t0[a1]; + byte b2 = t1[b1]; + + byte a3 = a2 ^ b2; + byte b3 = a2 ^ ror4(b2) ^ ((8*a2) % 16); + + byte a4 = t2[a3]; + byte b4 = t3[b3]; + + byte y = 16*b4 + a4; + + return y; +} + +int +main(void) +{ + int i, j; + + printf("static byte q0[] = { "); + for (i = 0; i < 32; i++) { + for (j = 0; j < 8; j++) + printf("0x%02X, ", q0(i*8+j)); + if (i == 31) + printf("};\n\n"); + else + printf("\n "); + } + + printf("static byte q1[] = { "); + for (i = 0; i < 32; i++) { + for (j = 0; j < 8; j++) + printf("0x%02X, ", q1(i*8+j)); + if (i == 31) + printf("};\n"); + else + printf("\n "); + } + + return 0; +} diff --git a/include/twofish.h b/include/twofish.h new file mode 100644 index 00000000..9b3356dc --- /dev/null +++ b/include/twofish.h @@ -0,0 +1,101 @@ +/* + * twofish - An implementation of the twofish cipher. + * Copyright (C) 1999 Ruud de Rooij <ruud@debian.org> + * + * Modifications for lsh + * Copyright (C) 1999 J.H.M. Dassen (Ray) <jdassen@wi.LeidenUniv.nl> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Twofish is a 128-bit block cipher that accepts a variable-length + * key up to 256 bits, designed by Bruce Schneier and others. See + * http://www.counterpane.com/twofish.html for details. + */ + +#if !defined(TWOFISH_H) +#define TWOFISH_H + +#include <stdlib.h> /* For size_t */ + +#include "crypto_types.h" + +#define TWOFISH_BLOCKSIZE 16 /* bytes */ + + +/* Other key lengths are possible, but in the context of the ssh protocols, + * 256 bits is the default. */ +#define TWOFISH_KEYSIZE 32 /* bytes */ + +/* Allow keys of size 128 <= bits <= 256 */ + +#define TWOFISH_MIN_KEYSIZE 16 /* bytes */ +#define TWOFISH_MAX_KEYSIZE 32 /* bytes */ + +typedef struct { + UINT32 keys[40]; + UINT32 s_box[4][256]; +} TWOFISH_context; + +/* TWOFISH_context * twofish_setup(size_t keysize, const void * key); + * + * Set up internal tables required for twofish encryption and decryption. + * + * The key size is specified in bytes. Key sizes up to 32 bytes are + * supported. Larger key sizes are silently truncated. The function + * returns a pointer which must be passed as the first argument to + * twofish_encrypt() and twofish_decrypt(). When no more encryption or + * decryption with this key is to be performed, the storage for the tables + * can be reclaimed with the free() function. + * If no memory is available to store the tables, twofish_setup() + * returns NULL. + */ + +TWOFISH_context * twofish_setup(size_t keysize, const void *key); + +/* void twofish_encrypt(void * context, + * const void * plaintext, + * void * ciphertext); + * + * Encrypt 16 bytes of data with the twofish algorithm. + * + * Before this function can be used, twofish_setup() must be used in order to + * set up various tables required for the encryption algorithm. + * The first argument is the handle returned from twofish_setup(). + * This function always encrypts 16 bytes of plaintext to 16 bytes of + * ciphertext. The memory areas of the plaintext and the ciphertext can + * overlap. + */ + +void twofish_encrypt(void *context, const void *plaintext, void *ciphertext); + +/* void twofish_decrypt(void * context, + * const void * ciphertext, + * void * plaintext); + * + * Decrypt 16 bytes of data with the twofish algorithm. + * + * Before this function can be used, twofish_setup() must be used in order to + * set up various tables required for the decryption algorithm. + * The first argument is the handle returned from twofish_setup(). + * This function always decrypts 16 bytes of ciphertext to 16 bytes of + * plaintext. The memory areas of the plaintext and the ciphertext can + * overlap. + */ + +void twofish_decrypt(void *context, const void *ciphertext, void *plaintext); + +#endif diff --git a/twofish.c b/twofish.c new file mode 100644 index 00000000..ea029730 --- /dev/null +++ b/twofish.c @@ -0,0 +1,574 @@ +/* + * twofish - An implementation of the twofish cipher. + * Copyright (C) 1999 Ruud de Rooij <ruud@debian.org> + * + * Modifications for lsh, integrated testing + * Copyright (C) 1999 J.H.M. Dassen (Ray) <jdassen@wi.LeidenUniv.nl> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ------------------------------------------------------------------------- */ + +#include "twofish.h" + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +UNUSED static char cvs_id[] = +"$Id$"; + +/* ------------------------------------------------------------------------- */ + +/* Type definitions for byte and word. word refers to a 32-bit unsigned + * value. + */ + +typedef UINT8 byte; +typedef UINT32 word; + +/* Bitwise rotations on 32-bit words. These are defined as macros that + * evaluate their argument twice, so do not apply to any expressions with + * side effects. + */ + +#define rol1(x) (((x) << 1) | (((x) & 0x80000000) >> 31)) +#define rol8(x) (((x) << 8) | (((x) & 0xFF000000) >> 24)) +#define rol9(x) (((x) << 9) | (((x) & 0xFF800000) >> 23)) +#define ror1(x) (((x) >> 1) | (((x) & 0x00000001) << 31)) + +/* void bytes_to_words(word * dest, const byte * src, int n); + * void words_to_bytes(byte * dest, const byte * src, int n); + * + * Copy n*4 bytes to n words and vice versa. + */ + +#if defined(__i386__) + +/* In the i386 case, these are simply memcpy's since the memory layout + * of an array of bytes and an array of words is identical. + */ + +#define bytes_to_words(dest,src,n) memcpy(dest,src,(n)*4) +#define words_to_bytes(dest,src,n) memcpy(dest,src,(n)*4) + +#else + +/* These versions are independent of endianness and word size. */ + +static void +bytes_to_words(word *dest, const byte *src, int n) +{ + while (n-- > 0) { + *dest++ = src[0] | src[1] << 8 | src[2] << 16 | src[3] << 24; + src += 4; + } +} + +static void +words_to_bytes(byte *dest, const word *src, int n) +{ + while (n-- > 0) { + *dest++ = *src; + *dest++ = *src >> 8; + *dest++ = *src >> 16; + *dest++ = *src >> 24; + src++; + } +} + +#endif + +/* ------------------------------------------------------------------------- */ + +/* The permutations q0 and q1. These are fixed permutations on 8-bit values. + * The permutations have been computed using the program generate_q + * which is distributed along with this file. + */ + +static byte 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, }; + +static byte 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, }; + +/* ------------------------------------------------------------------------- */ + +/* byte gf_multiply(byte p, byte a, byte b) + * + * Multiplication in GF(2^8). + * + * This function multiplies a times b in the Galois Field GF(2^8) with + * primitive polynomial p. + * The representation of the polynomials a, b, and p uses bits with + * values 2^i to represent the terms x^i. The polynomial p contains an + * implicit term x^8. + * + * Note that addition and subtraction in GF(2^8) is simply the XOR + * operation. + */ + +static byte +gf_multiply(byte p, byte a, byte b) +{ + word shift = b; + byte result = 0; + while (a) { + if (a & 1) result ^= shift; + a = a >> 1; + shift = shift << 1; + if (shift & 0x100) shift ^= p; + } + return result; +} + +/* ------------------------------------------------------------------------- */ + +/* The matrix RS as specified in section 4.3 the twofish paper. */ + +static byte rs_matrix[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 } }; + +/* word compute_s(word m1, word m2); + * + * Computes the value RS * M, where M is a byte vector composed of the + * bytes of m1 and m2. Arithmetic is done in GF(2^8) with primitive + * polynomial x^8 + x^6 + x^3 + x^2 + 1. + * + * This function is used to compute the sub-keys S which are in turn used + * to generate the S-boxes. + */ + +static word +compute_s(word m1, word m2) +{ + word s = 0; + int i; + for (i = 0; i < 4; i++) + s |= (( gf_multiply(0x4D, m1, rs_matrix[i][0]) + ^ gf_multiply(0x4D, m1 >> 8, rs_matrix[i][1]) + ^ gf_multiply(0x4D, m1 >> 16, rs_matrix[i][2]) + ^ gf_multiply(0x4D, m1 >> 24, rs_matrix[i][3]) + ^ gf_multiply(0x4D, m2, rs_matrix[i][4]) + ^ gf_multiply(0x4D, m2 >> 8, rs_matrix[i][5]) + ^ gf_multiply(0x4D, m2 >> 16, rs_matrix[i][6]) + ^ gf_multiply(0x4D, m2 >> 24, rs_matrix[i][7])) << (i*8)); + return s; +} + +/* ------------------------------------------------------------------------- */ + +/* This table describes which q S-boxes are used for each byte in each stage + * of the function h, cf. figure 2 of the twofish paper. + */ + +static byte * q_table[4][5] = { { q1, q1, q0, q0, q1 }, + { q0, q1, q1, q0, q0 }, + { q0, q0, q0, q1, q1 }, + { q1, q0, q1, q1, q0 } }; + +/* The matrix MDS as specified in section 4.3.2 of the twofish paper. */ + +static byte mds_matrix[4][4] = { { 0x01, 0xEF, 0x5B, 0x5B }, + { 0x5B, 0xEF, 0xEF, 0x01 }, + { 0xEF, 0x5B, 0x01, 0xEF }, + { 0xEF, 0x01, 0xEF, 0x5B } }; + +/* word h_byte(int k, int i, byte x, byte l0, byte l1, byte l2, byte l3); + * + * Perform the h function (section 4.3.2) on one byte. It consists of + * repeated applications of the q permutation, followed by a XOR with + * part of a sub-key. Finally, the value is multiplied by one column of + * the MDS matrix. To obtain the result for a full word, the results of + * h for the individual bytes are XORed. + * + * k is the key size (/ 64 bits), i is the byte number (0 = LSB), x is the + * actual byte to apply the function to; l0, l1, l2, and l3 are the + * appropriate bytes from the subkey. Note that only l0..lk are used. + */ + +static word +h_byte(int k, int i, byte x, byte l0, byte l1, byte l2, byte l3) +{ + byte y = q_table[i][4][l0 ^ + q_table[i][3][l1 ^ + q_table[i][2][k == 2 ? x : l2 ^ + q_table[i][1][k == 3 ? x : l3 ^ q_table[i][0][x]]]]]; + + return ((word)gf_multiply(0x69, mds_matrix[0][i], y)) | + ((word)gf_multiply(0x69, mds_matrix[1][i], y) << 8) | + ((word)gf_multiply(0x69, mds_matrix[2][i], y) << 16) | + ((word)gf_multiply(0x69, mds_matrix[3][i], y) << 24); +} + +/* word h(int k, byte x, word l0, word l1, word l2, word l3); + * + * Perform the function h on a word. See the description of h_byte() above. + */ + +static word +h(int k, byte x, word l0, word l1, word l2, word l3) +{ + return h_byte(k, 0, x, l0, l1, l2, l3) + ^ h_byte(k, 1, x, l0 >> 8, l1 >> 8, l2 >> 8, l3 >> 8) + ^ h_byte(k, 2, x, l0 >> 16, l1 >> 16, l2 >> 16, l3 >> 16) + ^ h_byte(k, 3, x, l0 >> 24, l1 >> 24, l2 >> 24, l3 >> 24); +} + + +/* + * Sanity check using the test vectors from appendix 2 of the Twofish paper. + */ +static int +twofish_selftest(void) { + byte testkey128[16] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + byte ciphertext128[16] = + { + 0x5D, 0x9D, 0x4E, 0xEF, 0xFA, 0x91, 0x51, 0x57, + 0x55, 0x24, 0xF1, 0x15, 0x81, 0x5A, 0x12, 0xE0 }; + + byte testkey192[24] = + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + byte ciphertext192[16] = + { 0xE7, 0x54, 0x49, 0x21, 0x2B, 0xEE, 0xF9, 0xF4, + 0xA3, 0x90, 0xBD, 0x86, 0x0A, 0x64, 0x09, 0x41 }; + + byte testkey256[32] = + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; + byte ciphertext256[16] = + { 0x37, 0xFE, 0x26, 0xFF, 0x1C, 0xF6, 0x61, 0x75, + 0xF5, 0xDD, 0xF4, 0xC3, 0x3B, 0x97, 0xA2, 0x05 }; + + TWOFISH_context * context; + int i; + byte plaintext[16], ciphertext[16]; + + context = twofish_setup(16, testkey128); + bzero(plaintext, 16); + + for (i = 0 ; i < 50; i++) { + twofish_encrypt(context, plaintext, ciphertext); + memcpy(plaintext, ciphertext, 16); + } + if (!memcmp(ciphertext, ciphertext128, 16)) { + return 0; + } + + context = twofish_setup(24, testkey192); + bzero(plaintext, 16); + + for (i = 0 ; i < 50; i++) { + twofish_encrypt(context, plaintext, ciphertext); + memcpy(plaintext, ciphertext, 16); + } + if (!memcmp(ciphertext, ciphertext192, 16)) { + return 0; + } + + context = twofish_setup(32, testkey256); + bzero(plaintext, 16); + + for (i = 0 ; i < 50; i++) { + twofish_encrypt(context, plaintext, ciphertext); + memcpy(plaintext, ciphertext, 16); + } + if (!memcmp(ciphertext, ciphertext256, 16)) { + return 0; + } + + return 1; +} + +/* ------------------------------------------------------------------------- */ + +/* API */ + +/* Structure which contains the tables containing the subkeys and the + * key-dependent s-boxes. + */ + + +/* TWOFISH_context * twofish_setup(size_t keysize, const void * key); + * + * Set up internal tables required for twofish encryption and decryption. + * + * The key size is specified in bytes. Key sizes up to 32 bytes are + * supported. Larger key sizes are silently truncated. The function + * returns a pointer which must be passed as the first argument to + * twofish_encrypt() and twofish_decrypt(). When no more encryption or + * decryption with this key is to be performed, the storage for the tables + * can be reclaimed with the free() function. + * If no memory is available to store the tables, twofish_setup() + * returns NULL. + */ + +TWOFISH_context * +twofish_setup(size_t keysize, const void *key) +{ + TWOFISH_context * context = malloc(sizeof (TWOFISH_context)); + byte key_copy[32]; + word m[8], s[4], t; + int i, j, k; + +#ifndef NDEBUG + static int initialized = 0; + + if (!initialized) { + initialized = 1; + assert(twofish_selftest()); + } +#endif + + if (!context) + return NULL; + + /* Extend or truncate key as necessary */ + + memset(key_copy, 0, 32); + if (keysize > 32) keysize =32; + memcpy(key_copy, key, keysize); + + bytes_to_words(m, key_copy, keysize/4); + + if (keysize <= 16) + k = 2; + else if (keysize <= 24) + k = 3; + else + k = 4; + + /* Compute sub-keys */ + + for (i = 0; i < 20; i++) { + t = h(k, 2*i+1, m[1], m[3], m[5], m[7]); + t = rol8(t); + t += (context->keys[2*i] = + t + h(k, 2*i, m[0], m[2], m[4], m[6])); + t = rol9(t); + context->keys[2*i+1] = t; + } + + /* Compute key-dependent S-boxes */ + + for (i = 0; i < k; i++) + s[k-1-i] = compute_s(m[2*i], m[2*i+1]); + + for (i = 0; i < 4; i++) + for (j = 0; j < 256; j++) + context->s_box[i][j] = h_byte(k, i, j, s[0] >> (i*8), + s[1] >> (i*8), + s[2] >> (i*8), + s[3] >> (i*8)); + return context; +} + +/* void twofish_encrypt(void * context, + * const void * plaintext, + * void * ciphertext); + * + * Encrypt 16 bytes of data with the twofish algorithm. + * + * Before this function can be used, twofish_setup() must be used in order to + * set up various tables required for the encryption algorithm. + * The first argument is the handle returned from twofish_setup(). + * This function always encrypts 16 bytes of plaintext to 16 bytes of + * ciphertext. The memory areas of the plaintext and the ciphertext can + * overlap. + */ + +void +twofish_encrypt(void *context, const void *plaintext, void *ciphertext) +{ + word words[4]; + word r0, r1, r2, r3, t0, t1; + int i; + word * keys = ((TWOFISH_context *)context)->keys; + word (*s_box)[256] = ((TWOFISH_context *)context)->s_box; + + bytes_to_words(words, plaintext, 4); + + r0 = words[0] ^ keys[0]; + r1 = words[1] ^ keys[1]; + r2 = words[2] ^ keys[2]; + r3 = words[3] ^ keys[3]; + + for (i = 0; i < 8; i++) { + t1 = s_box[1][r1 & 0xFF] + ^ s_box[2][(r1 >> 8) & 0xFF] + ^ s_box[3][(r1 >> 16) & 0xFF] + ^ s_box[0][(r1 >> 24) & 0xFF]; + t0 = ( s_box[0][r0 & 0xFF] + ^ s_box[1][(r0 >> 8) & 0xFF] + ^ s_box[2][(r0 >> 16) & 0xFF] + ^ s_box[3][(r0 >> 24) & 0xFF]) + t1; + r3 = (t1 + t0 + keys[4*i+9]) ^ rol1(r3); + r2 = (t0 + keys[4*i+8]) ^ r2; + r2 = ror1(r2); + + t1 = s_box[1][r3 & 0xFF] + ^ s_box[2][(r3 >> 8) & 0xFF] + ^ s_box[3][(r3 >> 16) & 0xFF] + ^ s_box[0][(r3 >> 24) & 0xFF]; + t0 = ( s_box[0][r2 & 0xFF] + ^ s_box[1][(r2 >> 8) & 0xFF] + ^ s_box[2][(r2 >> 16) & 0xFF] + ^ s_box[3][(r2 >> 24) & 0xFF]) + t1; + r1 = (t1 + t0 + keys[4*i+11]) ^ rol1(r1); + r0 = (t0 + keys[4*i+10]) ^ r0; + r0 = ror1(r0); + } + + words[0] = r2 ^ keys[4]; + words[1] = r3 ^ keys[5]; + words[2] = r0 ^ keys[6]; + words[3] = r1 ^ keys[7]; + + words_to_bytes(ciphertext, words, 4); +} + +/* void twofish_decrypt(void * context, + * const void * ciphertext, + * void * plaintext); + * + * Decrypt 16 bytes of data with the twofish algorithm. + * + * Before this function can be used, twofish_setup() must be used in order to + * set up various tables required for the decryption algorithm. + * The first argument is the handle returned from twofish_setup(). + * This function always decrypts 16 bytes of ciphertext to 16 bytes of + * plaintext. The memory areas of the plaintext and the ciphertext can + * overlap. + */ + +void +twofish_decrypt(void *context, const void *ciphertext, void *plaintext) +{ + word words[4]; + word r0, r1, r2, r3, t0, t1; + int i; + word * keys = ((TWOFISH_context *)context)->keys; + word (*s_box)[256] = ((TWOFISH_context *)context)->s_box; + + bytes_to_words(words, ciphertext, 4); + + r0 = words[2] ^ keys[6]; + r1 = words[3] ^ keys[7]; + r2 = words[0] ^ keys[4]; + r3 = words[1] ^ keys[5]; + + for (i = 0; i < 8; i++) { + t1 = s_box[1][r3 & 0xFF] + ^ s_box[2][(r3 >> 8) & 0xFF] + ^ s_box[3][(r3 >> 16) & 0xFF] + ^ s_box[0][(r3 >> 24) & 0xFF]; + t0 = ( s_box[0][r2 & 0xFF] + ^ s_box[1][(r2 >> 8) & 0xFF] + ^ s_box[2][(r2 >> 16) & 0xFF] + ^ s_box[3][(r2 >> 24) & 0xFF]) + t1; + r1 = (t1 + t0 + keys[39-4*i]) ^ r1; + r1 = ror1(r1); + r0 = (t0 + keys[38-4*i]) ^ rol1(r0); + + t1 = s_box[1][r1 & 0xFF] + ^ s_box[2][(r1 >> 8) & 0xFF] + ^ s_box[3][(r1 >> 16) & 0xFF] + ^ s_box[0][(r1 >> 24) & 0xFF]; + t0 = ( s_box[0][r0 & 0xFF] + ^ s_box[1][(r0 >> 8) & 0xFF] + ^ s_box[2][(r0 >> 16) & 0xFF] + ^ s_box[3][(r0 >> 24) & 0xFF]) + t1; + r3 = (t1 + t0 + keys[37-4*i]) ^ r3; + r3 = ror1(r3); + r2 = (t0 + keys[36-4*i]) ^ rol1(r2); + } + + words[0] = r0 ^ keys[0]; + words[1] = r1 ^ keys[1]; + words[2] = r2 ^ keys[2]; + words[3] = r3 ^ keys[3]; + + words_to_bytes(plaintext, words, 4); +} -- GitLab