mirror of
https://github.com/vanhauser-thc/thc-hydra.git
synced 2025-07-06 04:51:40 -07:00
Basic libgcrypt usage... no idea if it works, but it has to be better than nothing right?
This commit is contained in:
parent
0c2e02135d
commit
43e3040062
7 changed files with 43 additions and 1380 deletions
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
OPTS=-I. -O3
|
OPTS=-I. -O3
|
||||||
# -Wall -g -pedantic
|
# -Wall -g -pedantic
|
||||||
LIBS=-lm
|
LIBS=-lm -lgcrypt
|
||||||
BINDIR = /bin
|
BINDIR = /bin
|
||||||
MANDIR ?= /man/man1/
|
MANDIR ?= /man/man1/
|
||||||
DATADIR ?= /etc
|
DATADIR ?= /etc
|
||||||
|
@ -20,7 +20,7 @@ SRC = hydra-vnc.c hydra-pcnfs.c hydra-rexec.c hydra-nntp.c hydra-socks5.c \
|
||||||
hydra-oracle-sid.c hydra-http-proxy.c hydra-http-form.c hydra-irc.c \
|
hydra-oracle-sid.c hydra-http-proxy.c hydra-http-form.c hydra-irc.c \
|
||||||
hydra-rdp.c hydra-s7-300.c hydra-redis.c hydra-adam6500.c \
|
hydra-rdp.c hydra-s7-300.c hydra-redis.c hydra-adam6500.c \
|
||||||
crc32.c d3des.c bfg.c ntlm.c sasl.c hmacmd5.c hydra-mod.c hydra-rtsp.c hydra-time.c hydra-rpcap.c \
|
crc32.c d3des.c bfg.c ntlm.c sasl.c hmacmd5.c hydra-mod.c hydra-rtsp.c hydra-time.c hydra-rpcap.c \
|
||||||
hydra-radmin2.c twofish.c
|
hydra-radmin2.c
|
||||||
OBJ = hydra-vnc.o hydra-pcnfs.o hydra-rexec.o hydra-nntp.o hydra-socks5.o \
|
OBJ = hydra-vnc.o hydra-pcnfs.o hydra-rexec.o hydra-nntp.o hydra-socks5.o \
|
||||||
hydra-telnet.o hydra-cisco.o hydra-http.o hydra-ftp.o hydra-imap.o \
|
hydra-telnet.o hydra-cisco.o hydra-http.o hydra-ftp.o hydra-imap.o \
|
||||||
hydra-pop3.o hydra-smb.o hydra-icq.o hydra-cisco-enable.o hydra-ldap.o \
|
hydra-pop3.o hydra-smb.o hydra-icq.o hydra-cisco-enable.o hydra-ldap.o \
|
||||||
|
@ -32,7 +32,7 @@ OBJ = hydra-vnc.o hydra-pcnfs.o hydra-rexec.o hydra-nntp.o hydra-socks5.o \
|
||||||
hydra-http-proxy.o hydra-http-form.o hydra-irc.o hydra-redis.o \
|
hydra-http-proxy.o hydra-http-form.o hydra-irc.o hydra-redis.o \
|
||||||
hydra-rdp.o hydra-s7-300.c hydra-adam6500.o \
|
hydra-rdp.o hydra-s7-300.c hydra-adam6500.o \
|
||||||
crc32.o d3des.o bfg.o ntlm.o sasl.o hmacmd5.o hydra-mod.o hydra-rtsp.o hydra-time.o hydra-rpcap.o \
|
crc32.o d3des.o bfg.o ntlm.o sasl.o hmacmd5.o hydra-mod.o hydra-rtsp.o hydra-time.o hydra-rpcap.o \
|
||||||
hydra-radmin2.o twofish.o
|
hydra-radmin2.o
|
||||||
BINS = hydra pw-inspector
|
BINS = hydra pw-inspector
|
||||||
|
|
||||||
EXTRA_DIST = README README.arm README.palm CHANGES TODO INSTALL LICENSE \
|
EXTRA_DIST = README README.arm README.palm CHANGES TODO INSTALL LICENSE \
|
||||||
|
|
|
@ -2,17 +2,10 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
|
#include <gcrypt.h>
|
||||||
|
|
||||||
extern char *HYDRA_EXIT;
|
extern char *HYDRA_EXIT;
|
||||||
|
|
||||||
|
|
||||||
//Twofish references
|
|
||||||
#include "twofish/aes.h"
|
|
||||||
extern int makeKey(keyInstance *key, BYTE direction, int keyLen,CONST char *keyMaterial);
|
|
||||||
extern int cipherInit(cipherInstance *cipher, BYTE mode,CONST char *IV);
|
|
||||||
extern int blockEncrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input, int inputLen, BYTE *outBuffer);
|
|
||||||
extern int blockDecrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input, int inputLen, BYTE *outBuffer);
|
|
||||||
|
|
||||||
//RAdmin 2.x
|
//RAdmin 2.x
|
||||||
|
|
||||||
struct rmessage {
|
struct rmessage {
|
||||||
|
@ -185,18 +178,20 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL
|
||||||
char password[101];
|
char password[101];
|
||||||
unsigned char rawkey[16];
|
unsigned char rawkey[16];
|
||||||
char pkey[33];
|
char pkey[33];
|
||||||
char *IV = "FEDCBA9876543210A39D4A18F85B4A52";
|
char *IV = "\xFE\xDC\xBA\x98\x76\x54\x32\x10\xA3\x9D\x4A\x18\xF8\x5B\x4A\x52";
|
||||||
unsigned char encrypted[32];
|
unsigned char encrypted[32];
|
||||||
|
gcry_error_t err;
|
||||||
|
gcry_cipher_hd_t cipher;
|
||||||
|
|
||||||
//Initialization nonsense.
|
//Initialization nonsense.
|
||||||
MD5_CTX md5c;
|
MD5_CTX md5c;
|
||||||
keyInstance key;
|
|
||||||
cipherInstance cipher;
|
|
||||||
|
|
||||||
if(port != 0) {
|
if(port != 0) {
|
||||||
myport = port;
|
myport = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gcry_check_version(NULL);
|
||||||
|
|
||||||
memset(buffer, 0x00, sizeof(buffer));
|
memset(buffer, 0x00, sizeof(buffer));
|
||||||
memset(pkey, 0x00, 33);
|
memset(pkey, 0x00, 33);
|
||||||
memset(encrypted, 0x00, 32);
|
memset(encrypted, 0x00, 32);
|
||||||
|
@ -263,28 +258,48 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL
|
||||||
}
|
}
|
||||||
|
|
||||||
//3) Send challenge solution.
|
//3) Send challenge solution.
|
||||||
|
|
||||||
//3.a) generate a new message from the buffer
|
//3.a) generate a new message from the buffer
|
||||||
msg = buffer2message(buffer);
|
msg = buffer2message(buffer);
|
||||||
|
|
||||||
//3.b) encrypt data received using pkey & known IV
|
//3.b) encrypt data received using pkey & known IV
|
||||||
index = makeKey(&key, DIR_ENCRYPT, 128, pkey);
|
err= gcry_cipher_open(&cipher, GCRY_CIPHER_TWOFISH128, GCRY_CIPHER_MODE_CBC, 0);
|
||||||
if(index != TRUE) {
|
if(err) {
|
||||||
hydra_report(stderr, "Error: Child with pid %d terminating, make key error (%08x)\n", (int)getpid(), index);
|
hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_open error (%08x)\n", (int)getpid(), index);
|
||||||
hydra_child_exit(1);
|
hydra_child_exit(1);
|
||||||
}
|
}
|
||||||
|
err = gcry_cipher_setkey(cipher, pkey, 128);
|
||||||
|
if(err) {
|
||||||
|
hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setkey error (%08x)\n", (int)getpid(), index);
|
||||||
|
hydra_child_exit(1);
|
||||||
|
}
|
||||||
|
err = gcry_cipher_setiv(cipher, IV, 128);
|
||||||
|
if(err) {
|
||||||
|
hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setiv error (%08x)\n", (int)getpid(), index);
|
||||||
|
hydra_child_exit(1);
|
||||||
|
}
|
||||||
|
err = gcry_cipher_encrypt(cipher, encrypted, 32, msg->data, 32);
|
||||||
|
if(err) {
|
||||||
|
hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_encrypt error (%08x)\n", (int)getpid(), index);
|
||||||
|
hydra_child_exit(1);
|
||||||
|
}
|
||||||
|
gcry_cipher_close(cipher);
|
||||||
|
// index = makeKey(&key, DIR_ENCRYPT, 128, pkey);
|
||||||
|
// if(index != TRUE) {
|
||||||
|
// hydra_report(stderr, "Error: Child with pid %d terminating, make key error (%08x)\n", (int)getpid(), index);
|
||||||
|
// hydra_child_exit(1);
|
||||||
|
// }
|
||||||
|
|
||||||
index = cipherInit(&cipher, MODE_CBC, IV);
|
// index = cipherInit(&cipher, MODE_CBC, IV);
|
||||||
if(index != TRUE) {
|
// if(index != TRUE) {
|
||||||
hydra_report(stderr, "Error: Child with pid %d terminating, cipher init error(%08x)\n", (int)getpid(), index);
|
// hydra_report(stderr, "Error: Child with pid %d terminating, cipher init error(%08x)\n", (int)getpid(), index);
|
||||||
hydra_child_exit(1);
|
// hydra_child_exit(1);
|
||||||
}
|
// }
|
||||||
|
|
||||||
index = blockEncrypt(&cipher, &key, msg->data, 32 * 8, encrypted);
|
// index = blockEncrypt(&cipher, &key, msg->data, 32 * 8, encrypted);
|
||||||
if(index <= 0) {
|
// if(index <= 0) {
|
||||||
hydra_report(stderr, "Error: Child with pid %d terminating, encrypt error(%08x)\n", (int)getpid(), index);
|
// hydra_report(stderr, "Error: Child with pid %d terminating, encrypt error(%08x)\n", (int)getpid(), index);
|
||||||
hydra_child_exit(1);
|
// hydra_child_exit(1);
|
||||||
}
|
// }
|
||||||
|
|
||||||
//3.c) half sum - this is the solution to the challenge.
|
//3.c) half sum - this is the solution to the challenge.
|
||||||
for(index=0; index < 16; index++) {
|
for(index=0; index < 16; index++) {
|
||||||
|
|
704
twofish.c
704
twofish.c
|
@ -1,704 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
TWOFISH.C -- C API calls for TWOFISH AES submission
|
|
||||||
|
|
||||||
Submitters:
|
|
||||||
Bruce Schneier, Counterpane Systems
|
|
||||||
Doug Whiting, Hi/fn
|
|
||||||
John Kelsey, Counterpane Systems
|
|
||||||
Chris Hall, Counterpane Systems
|
|
||||||
David Wagner, UC Berkeley
|
|
||||||
|
|
||||||
Code Author: Doug Whiting, Hi/fn
|
|
||||||
|
|
||||||
Version 1.00 April 1998
|
|
||||||
|
|
||||||
Copyright 1998, Hi/fn and Counterpane Systems. All rights reserved.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
* Pedagogical version (non-optimized)
|
|
||||||
* Tab size is set to 4 characters in this file
|
|
||||||
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include "twofish/aes.h"
|
|
||||||
#include "twofish/table.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
+*****************************************************************************
|
|
||||||
* Constants/Macros/Tables
|
|
||||||
-****************************************************************************/
|
|
||||||
|
|
||||||
#define VALIDATE_PARMS 1 /* nonzero --> check all parameters */
|
|
||||||
#define FEISTEL 0 /* nonzero --> use Feistel version (slow) */
|
|
||||||
|
|
||||||
int tabEnable=0; /* are we gathering stats? */
|
|
||||||
BYTE tabUsed[256]; /* one bit per table */
|
|
||||||
|
|
||||||
#if FEISTEL
|
|
||||||
CONST char *moduleDescription="Pedagogical C code (Feistel)";
|
|
||||||
#else
|
|
||||||
CONST char *moduleDescription="Pedagogical C code";
|
|
||||||
#endif
|
|
||||||
CONST char *modeString = "";
|
|
||||||
|
|
||||||
#define P0_USED 0x01
|
|
||||||
#define P1_USED 0x02
|
|
||||||
#define B0_USED 0x04
|
|
||||||
#define B1_USED 0x08
|
|
||||||
#define B2_USED 0x10
|
|
||||||
#define B3_USED 0x20
|
|
||||||
#define ALL_USED 0x3F
|
|
||||||
|
|
||||||
/* number of rounds for various key sizes: 128, 192, 256 */
|
|
||||||
int numRounds[4]= {0,ROUNDS_128,ROUNDS_192,ROUNDS_256};
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
#ifdef GetCodeSize
|
|
||||||
#define DEBUG 1 /* force debug */
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#include "twofish/debug.h" /* debug display macros */
|
|
||||||
|
|
||||||
#ifdef GetCodeSize
|
|
||||||
extern DWORD Here(DWORD x); /* return caller's address! */
|
|
||||||
DWORD TwofishCodeStart(void) { return Here(0); };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
+*****************************************************************************
|
|
||||||
*
|
|
||||||
* Function Name: TableOp
|
|
||||||
*
|
|
||||||
* Function: Handle table use checking
|
|
||||||
*
|
|
||||||
* Arguments: op = what to do (see TAB_* defns in AES.H)
|
|
||||||
*
|
|
||||||
* Return: TRUE --> done (for TAB_QUERY)
|
|
||||||
*
|
|
||||||
* Notes: This routine is for use in generating the tables KAT file.
|
|
||||||
*
|
|
||||||
-****************************************************************************/
|
|
||||||
int TableOp(int op)
|
|
||||||
{
|
|
||||||
static int queryCnt=0;
|
|
||||||
int i;
|
|
||||||
switch (op)
|
|
||||||
{
|
|
||||||
case TAB_DISABLE:
|
|
||||||
tabEnable=0;
|
|
||||||
break;
|
|
||||||
case TAB_ENABLE:
|
|
||||||
tabEnable=1;
|
|
||||||
break;
|
|
||||||
case TAB_RESET:
|
|
||||||
queryCnt=0;
|
|
||||||
for (i=0;i<256;i++)
|
|
||||||
tabUsed[i]=0;
|
|
||||||
break;
|
|
||||||
case TAB_QUERY:
|
|
||||||
queryCnt++;
|
|
||||||
for (i=0;i<256;i++)
|
|
||||||
if (tabUsed[i] != ALL_USED)
|
|
||||||
return FALSE;
|
|
||||||
if (queryCnt < TAB_MIN_QUERY) /* do a certain minimum number */
|
|
||||||
return FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
+*****************************************************************************
|
|
||||||
*
|
|
||||||
* Function Name: ParseHexDword
|
|
||||||
*
|
|
||||||
* Function: Parse ASCII hex nibbles and fill in key/iv dwords
|
|
||||||
*
|
|
||||||
* Arguments: bit = # bits to read
|
|
||||||
* srcTxt = ASCII source
|
|
||||||
* d = ptr to dwords to fill in
|
|
||||||
* dstTxt = where to make a copy of ASCII source
|
|
||||||
* (NULL ok)
|
|
||||||
*
|
|
||||||
* Return: Zero if no error. Nonzero --> invalid hex or length
|
|
||||||
*
|
|
||||||
* Notes: Note that the parameter d is a DWORD array, not a byte array.
|
|
||||||
* This routine is coded to work both for little-endian and big-endian
|
|
||||||
* architectures. The character stream is interpreted as a LITTLE-ENDIAN
|
|
||||||
* byte stream, since that is how the Pentium works, but the conversion
|
|
||||||
* happens automatically below.
|
|
||||||
*
|
|
||||||
-****************************************************************************/
|
|
||||||
int ParseHexDword(int bits,CONST char *srcTxt,DWORD *d,char *dstTxt)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
DWORD b;
|
|
||||||
char c;
|
|
||||||
#if ALIGN32
|
|
||||||
char alignDummy[3]; /* keep dword alignment */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
union /* make sure LittleEndian is defined correctly */
|
|
||||||
{
|
|
||||||
BYTE b[4];
|
|
||||||
DWORD d[1];
|
|
||||||
} v;
|
|
||||||
v.d[0]=1;
|
|
||||||
if (v.b[0 ^ ADDR_XOR] != 1) /* sanity check on compile-time switch */
|
|
||||||
return BAD_ENDIAN;
|
|
||||||
|
|
||||||
#if VALIDATE_PARMS
|
|
||||||
#if ALIGN32
|
|
||||||
if (((int)d) & 3)
|
|
||||||
return BAD_ALIGN32;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i=0;i*32<bits;i++)
|
|
||||||
d[i]=0; /* first, zero the field */
|
|
||||||
|
|
||||||
for (i=0;i*4<bits;i++) /* parse one nibble at a time */
|
|
||||||
{ /* case out the hexadecimal characters */
|
|
||||||
c=srcTxt[i];
|
|
||||||
if (dstTxt) dstTxt[i]=c;
|
|
||||||
if ((c >= '0') && (c <= '9'))
|
|
||||||
b=c-'0';
|
|
||||||
else if ((c >= 'a') && (c <= 'f'))
|
|
||||||
b=c-'a'+10;
|
|
||||||
else if ((c >= 'A') && (c <= 'F'))
|
|
||||||
b=c-'A'+10;
|
|
||||||
else
|
|
||||||
return BAD_KEY_MAT; /* invalid hex character */
|
|
||||||
/* works for big and little endian! */
|
|
||||||
d[i/8] |= b << (4*((i^1)&7));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0; /* no error */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
+*****************************************************************************
|
|
||||||
*
|
|
||||||
* Function Name: f32
|
|
||||||
*
|
|
||||||
* Function: Run four bytes through keyed S-boxes and apply MDS matrix
|
|
||||||
*
|
|
||||||
* Arguments: x = input to f function
|
|
||||||
* k32 = pointer to key dwords
|
|
||||||
* keyLen = total key length (k32 --> keyLey/2 bits)
|
|
||||||
*
|
|
||||||
* Return: The output of the keyed permutation applied to x.
|
|
||||||
*
|
|
||||||
* Notes:
|
|
||||||
* This function is a keyed 32-bit permutation. It is the major building
|
|
||||||
* block for the Twofish round function, including the four keyed 8x8
|
|
||||||
* permutations and the 4x4 MDS matrix multiply. This function is used
|
|
||||||
* both for generating round subkeys and within the round function on the
|
|
||||||
* block being encrypted.
|
|
||||||
*
|
|
||||||
* This version is fairly slow and pedagogical, although a smartcard would
|
|
||||||
* probably perform the operation exactly this way in firmware. For
|
|
||||||
* ultimate performance, the entire operation can be completed with four
|
|
||||||
* lookups into four 256x32-bit tables, with three dword xors.
|
|
||||||
*
|
|
||||||
* The MDS matrix is defined in TABLE.H. To multiply by Mij, just use the
|
|
||||||
* macro Mij(x).
|
|
||||||
*
|
|
||||||
-****************************************************************************/
|
|
||||||
DWORD f32(DWORD x,CONST DWORD *k32,int keyLen)
|
|
||||||
{
|
|
||||||
BYTE b[4];
|
|
||||||
|
|
||||||
/* Run each byte thru 8x8 S-boxes, xoring with key byte at each stage. */
|
|
||||||
/* Note that each byte goes through a different combination of S-boxes.*/
|
|
||||||
|
|
||||||
*((DWORD *)b) = Bswap(x); /* make b[0] = LSB, b[3] = MSB */
|
|
||||||
switch (((keyLen + 63)/64) & 3)
|
|
||||||
{
|
|
||||||
case 0: /* 256 bits of key */
|
|
||||||
b[0] = p8(04)[b[0]] ^ b0(k32[3]);
|
|
||||||
b[1] = p8(14)[b[1]] ^ b1(k32[3]);
|
|
||||||
b[2] = p8(24)[b[2]] ^ b2(k32[3]);
|
|
||||||
b[3] = p8(34)[b[3]] ^ b3(k32[3]);
|
|
||||||
/* fall thru, having pre-processed b[0]..b[3] with k32[3] */
|
|
||||||
case 3: /* 192 bits of key */
|
|
||||||
b[0] = p8(03)[b[0]] ^ b0(k32[2]);
|
|
||||||
b[1] = p8(13)[b[1]] ^ b1(k32[2]);
|
|
||||||
b[2] = p8(23)[b[2]] ^ b2(k32[2]);
|
|
||||||
b[3] = p8(33)[b[3]] ^ b3(k32[2]);
|
|
||||||
/* fall thru, having pre-processed b[0]..b[3] with k32[2] */
|
|
||||||
case 2: /* 128 bits of key */
|
|
||||||
b[0] = p8(00)[p8(01)[p8(02)[b[0]] ^ b0(k32[1])] ^ b0(k32[0])];
|
|
||||||
b[1] = p8(10)[p8(11)[p8(12)[b[1]] ^ b1(k32[1])] ^ b1(k32[0])];
|
|
||||||
b[2] = p8(20)[p8(21)[p8(22)[b[2]] ^ b2(k32[1])] ^ b2(k32[0])];
|
|
||||||
b[3] = p8(30)[p8(31)[p8(32)[b[3]] ^ b3(k32[1])] ^ b3(k32[0])];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tabEnable)
|
|
||||||
{ /* we could give a "tighter" bound, but this works acceptably well */
|
|
||||||
tabUsed[b0(x)] |= (P_00 == 0) ? P0_USED : P1_USED;
|
|
||||||
tabUsed[b1(x)] |= (P_10 == 0) ? P0_USED : P1_USED;
|
|
||||||
tabUsed[b2(x)] |= (P_20 == 0) ? P0_USED : P1_USED;
|
|
||||||
tabUsed[b3(x)] |= (P_30 == 0) ? P0_USED : P1_USED;
|
|
||||||
|
|
||||||
tabUsed[b[0] ] |= B0_USED;
|
|
||||||
tabUsed[b[1] ] |= B1_USED;
|
|
||||||
tabUsed[b[2] ] |= B2_USED;
|
|
||||||
tabUsed[b[3] ] |= B3_USED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now perform the MDS matrix multiply inline. */
|
|
||||||
return ((M00(b[0]) ^ M01(b[1]) ^ M02(b[2]) ^ M03(b[3])) ) ^
|
|
||||||
((M10(b[0]) ^ M11(b[1]) ^ M12(b[2]) ^ M13(b[3])) << 8) ^
|
|
||||||
((M20(b[0]) ^ M21(b[1]) ^ M22(b[2]) ^ M23(b[3])) << 16) ^
|
|
||||||
((M30(b[0]) ^ M31(b[1]) ^ M32(b[2]) ^ M33(b[3])) << 24) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
+*****************************************************************************
|
|
||||||
*
|
|
||||||
* Function Name: RS_MDS_Encode
|
|
||||||
*
|
|
||||||
* Function: Use (12,8) Reed-Solomon code over GF(256) to produce
|
|
||||||
* a key S-box dword from two key material dwords.
|
|
||||||
*
|
|
||||||
* Arguments: k0 = 1st dword
|
|
||||||
* k1 = 2nd dword
|
|
||||||
*
|
|
||||||
* Return: Remainder polynomial generated using RS code
|
|
||||||
*
|
|
||||||
* Notes:
|
|
||||||
* Since this computation is done only once per reKey per 64 bits of key,
|
|
||||||
* the performance impact of this routine is imperceptible. The RS code
|
|
||||||
* chosen has "simple" coefficients to allow smartcard/hardware implementation
|
|
||||||
* without lookup tables.
|
|
||||||
*
|
|
||||||
-****************************************************************************/
|
|
||||||
DWORD RS_MDS_Encode(DWORD k0,DWORD k1)
|
|
||||||
{
|
|
||||||
int i,j;
|
|
||||||
DWORD r;
|
|
||||||
|
|
||||||
for (i=r=0;i<2;i++)
|
|
||||||
{
|
|
||||||
r ^= (i) ? k0 : k1; /* merge in 32 more key bits */
|
|
||||||
for (j=0;j<4;j++) /* shift one byte at a time */
|
|
||||||
RS_rem(r);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
+*****************************************************************************
|
|
||||||
*
|
|
||||||
* Function Name: reKey
|
|
||||||
*
|
|
||||||
* Function: Initialize the Twofish key schedule from key32
|
|
||||||
*
|
|
||||||
* Arguments: key = ptr to keyInstance to be initialized
|
|
||||||
*
|
|
||||||
* Return: TRUE on success
|
|
||||||
*
|
|
||||||
* Notes:
|
|
||||||
* Here we precompute all the round subkeys, although that is not actually
|
|
||||||
* required. For example, on a smartcard, the round subkeys can
|
|
||||||
* be generated on-the-fly using f32()
|
|
||||||
*
|
|
||||||
-****************************************************************************/
|
|
||||||
int reKey(keyInstance *key)
|
|
||||||
{
|
|
||||||
int i,k64Cnt;
|
|
||||||
int keyLen = key->keyLen;
|
|
||||||
int subkeyCnt = ROUND_SUBKEYS + 2*key->numRounds;
|
|
||||||
DWORD A,B;
|
|
||||||
DWORD k32e[MAX_KEY_BITS/64],k32o[MAX_KEY_BITS/64]; /* even/odd key dwords */
|
|
||||||
|
|
||||||
#if VALIDATE_PARMS
|
|
||||||
#if ALIGN32
|
|
||||||
if ((((int)key) & 3) || (((int)key->key32) & 3))
|
|
||||||
return BAD_ALIGN32;
|
|
||||||
#endif
|
|
||||||
if ((key->keyLen % 64) || (key->keyLen < MIN_KEY_BITS))
|
|
||||||
return BAD_KEY_INSTANCE;
|
|
||||||
if (subkeyCnt > TOTAL_SUBKEYS)
|
|
||||||
return BAD_KEY_INSTANCE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
k64Cnt=(keyLen+63)/64; /* round up to next multiple of 64 bits */
|
|
||||||
for (i=0;i<k64Cnt;i++)
|
|
||||||
{ /* split into even/odd key dwords */
|
|
||||||
k32e[i]=key->key32[2*i ];
|
|
||||||
k32o[i]=key->key32[2*i+1];
|
|
||||||
/* compute S-box keys using (12,8) Reed-Solomon code over GF(256) */
|
|
||||||
key->sboxKeys[k64Cnt-1-i]=RS_MDS_Encode(k32e[i],k32o[i]); /* reverse order */
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0;i<subkeyCnt/2;i++) /* compute round subkeys for PHT */
|
|
||||||
{
|
|
||||||
A = f32(i*SK_STEP ,k32e,keyLen); /* A uses even key dwords */
|
|
||||||
B = f32(i*SK_STEP+SK_BUMP,k32o,keyLen); /* B uses odd key dwords */
|
|
||||||
B = ROL(B,8);
|
|
||||||
key->subKeys[2*i ] = A+ B; /* combine with a PHT */
|
|
||||||
key->subKeys[2*i+1] = ROL(A+2*B,SK_ROTL);
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugDumpKey(key);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
+*****************************************************************************
|
|
||||||
*
|
|
||||||
* Function Name: makeKey
|
|
||||||
*
|
|
||||||
* Function: Initialize the Twofish key schedule
|
|
||||||
*
|
|
||||||
* Arguments: key = ptr to keyInstance to be initialized
|
|
||||||
* direction = DIR_ENCRYPT or DIR_DECRYPT
|
|
||||||
* keyLen = # bits of key text at *keyMaterial
|
|
||||||
* keyMaterial = ptr to hex ASCII chars representing key bits
|
|
||||||
*
|
|
||||||
* Return: TRUE on success
|
|
||||||
* else error code (e.g., BAD_KEY_DIR)
|
|
||||||
*
|
|
||||||
* Notes:
|
|
||||||
* This parses the key bits from keyMaterial. No crypto stuff happens here.
|
|
||||||
* The function reKey() is called to actually build the key schedule after
|
|
||||||
* the keyMaterial has been parsed.
|
|
||||||
*
|
|
||||||
-****************************************************************************/
|
|
||||||
int makeKey(keyInstance *key, BYTE direction, int keyLen,CONST char *keyMaterial)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
#if VALIDATE_PARMS /* first, sanity check on parameters */
|
|
||||||
if (key == NULL)
|
|
||||||
return BAD_KEY_INSTANCE;/* must have a keyInstance to initialize */
|
|
||||||
if ((direction != DIR_ENCRYPT) && (direction != DIR_DECRYPT))
|
|
||||||
return BAD_KEY_DIR; /* must have valid direction */
|
|
||||||
if ((keyLen > MAX_KEY_BITS) || (keyLen < 8))
|
|
||||||
return BAD_KEY_MAT; /* length must be valid */
|
|
||||||
key->keySig = VALID_SIG; /* show that we are initialized */
|
|
||||||
#if ALIGN32
|
|
||||||
if ((((int)key) & 3) || (((int)key->key32) & 3))
|
|
||||||
return BAD_ALIGN32;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
key->direction = direction; /* set our cipher direction */
|
|
||||||
key->keyLen = (keyLen+63) & ~63; /* round up to multiple of 64 */
|
|
||||||
key->numRounds = numRounds[(keyLen-1)/64];
|
|
||||||
for (i=0;i<MAX_KEY_BITS/32;i++) /* zero unused bits */
|
|
||||||
key->key32[i]=0;
|
|
||||||
key->keyMaterial[MAX_KEY_SIZE]=0; /* terminate ASCII string */
|
|
||||||
|
|
||||||
if ((keyMaterial == NULL) || (keyMaterial[0]==0))
|
|
||||||
return TRUE; /* allow a "dummy" call */
|
|
||||||
|
|
||||||
if (ParseHexDword(keyLen,keyMaterial,key->key32,key->keyMaterial))
|
|
||||||
return BAD_KEY_MAT;
|
|
||||||
|
|
||||||
return reKey(key); /* generate round subkeys */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
+*****************************************************************************
|
|
||||||
*
|
|
||||||
* Function Name: cipherInit
|
|
||||||
*
|
|
||||||
* Function: Initialize the Twofish cipher in a given mode
|
|
||||||
*
|
|
||||||
* Arguments: cipher = ptr to cipherInstance to be initialized
|
|
||||||
* mode = MODE_ECB, MODE_CBC, or MODE_CFB1
|
|
||||||
* IV = ptr to hex ASCII test representing IV bytes
|
|
||||||
*
|
|
||||||
* Return: TRUE on success
|
|
||||||
* else error code (e.g., BAD_CIPHER_MODE)
|
|
||||||
*
|
|
||||||
-****************************************************************************/
|
|
||||||
int cipherInit(cipherInstance *cipher, BYTE mode,CONST char *IV)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
#if VALIDATE_PARMS /* first, sanity check on parameters */
|
|
||||||
if (cipher == NULL)
|
|
||||||
return BAD_PARAMS; /* must have a cipherInstance to initialize */
|
|
||||||
if ((mode != MODE_ECB) && (mode != MODE_CBC) && (mode != MODE_CFB1))
|
|
||||||
return BAD_CIPHER_MODE; /* must have valid cipher mode */
|
|
||||||
cipher->cipherSig = VALID_SIG;
|
|
||||||
#if ALIGN32
|
|
||||||
if ((((int)cipher) & 3) || (((int)cipher->IV) & 3) || (((int)cipher->iv32) & 3))
|
|
||||||
return BAD_ALIGN32;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((mode != MODE_ECB) && (IV)) /* parse the IV */
|
|
||||||
{
|
|
||||||
if (ParseHexDword(BLOCK_SIZE,IV,cipher->iv32,NULL))
|
|
||||||
return BAD_IV_MAT;
|
|
||||||
for (i=0;i<BLOCK_SIZE/32;i++) /* make byte-oriented copy for CFB1 */
|
|
||||||
((DWORD *)cipher->IV)[i] = Bswap(cipher->iv32[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
cipher->mode = mode;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
+*****************************************************************************
|
|
||||||
*
|
|
||||||
* Function Name: blockEncrypt
|
|
||||||
*
|
|
||||||
* Function: Encrypt block(s) of data using Twofish
|
|
||||||
*
|
|
||||||
* Arguments: cipher = ptr to already initialized cipherInstance
|
|
||||||
* key = ptr to already initialized keyInstance
|
|
||||||
* input = ptr to data blocks to be encrypted
|
|
||||||
* inputLen = # bits to encrypt (multiple of blockSize)
|
|
||||||
* outBuffer = ptr to where to put encrypted blocks
|
|
||||||
*
|
|
||||||
* Return: # bits ciphered (>= 0)
|
|
||||||
* else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL)
|
|
||||||
*
|
|
||||||
* Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits.
|
|
||||||
* If inputLen is not a multiple of BLOCK_SIZE bits in those modes,
|
|
||||||
* an error BAD_INPUT_LEN is returned. In CFB1 mode, all block
|
|
||||||
* sizes can be supported.
|
|
||||||
*
|
|
||||||
-****************************************************************************/
|
|
||||||
int blockEncrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input,
|
|
||||||
int inputLen, BYTE *outBuffer)
|
|
||||||
{
|
|
||||||
int i,n,r; /* loop variables */
|
|
||||||
DWORD x[BLOCK_SIZE/32]; /* block being encrypted */
|
|
||||||
DWORD t0,t1,tmp; /* temp variables */
|
|
||||||
int rounds=key->numRounds; /* number of rounds */
|
|
||||||
BYTE bit,ctBit,carry; /* temps for CFB */
|
|
||||||
#if ALIGN32
|
|
||||||
BYTE alignDummy; /* keep 32-bit variable alignment on stack */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if VALIDATE_PARMS
|
|
||||||
if ((cipher == NULL) || (cipher->cipherSig != VALID_SIG))
|
|
||||||
return BAD_CIPHER_STATE;
|
|
||||||
if ((key == NULL) || (key->keySig != VALID_SIG))
|
|
||||||
return BAD_KEY_INSTANCE;
|
|
||||||
if ((rounds < 2) || (rounds > MAX_ROUNDS) || (rounds&1))
|
|
||||||
return BAD_KEY_INSTANCE;
|
|
||||||
if ((cipher->mode != MODE_CFB1) && (inputLen % BLOCK_SIZE))
|
|
||||||
return BAD_INPUT_LEN;
|
|
||||||
#if ALIGN32
|
|
||||||
if ( (((int)cipher) & 3) || (((int)key ) & 3) ||
|
|
||||||
(((int)input ) & 3) || (((int)outBuffer) & 3))
|
|
||||||
return BAD_ALIGN32;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (cipher->mode == MODE_CFB1)
|
|
||||||
{ /* use recursion here to handle CFB, one block at a time */
|
|
||||||
cipher->mode = MODE_ECB; /* do encryption in ECB */
|
|
||||||
for (n=0;n<inputLen;n++)
|
|
||||||
{
|
|
||||||
blockEncrypt(cipher,key,cipher->IV,BLOCK_SIZE,(BYTE *)x);
|
|
||||||
bit = 0x80 >> (n & 7);/* which bit position in byte */
|
|
||||||
ctBit = (input[n/8] & bit) ^ ((((BYTE *) x)[0] & 0x80) >> (n&7));
|
|
||||||
outBuffer[n/8] = (outBuffer[n/8] & ~ bit) | ctBit;
|
|
||||||
carry = ctBit >> (7 - (n&7));
|
|
||||||
for (i=BLOCK_SIZE/8-1;i>=0;i--)
|
|
||||||
{
|
|
||||||
bit = cipher->IV[i] >> 7; /* save next "carry" from shift */
|
|
||||||
cipher->IV[i] = (cipher->IV[i] << 1) ^ carry;
|
|
||||||
carry = bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cipher->mode = MODE_CFB1; /* restore mode for next time */
|
|
||||||
return inputLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* here for ECB, CBC modes */
|
|
||||||
for (n=0;n<inputLen;n+=BLOCK_SIZE,input+=BLOCK_SIZE/8,outBuffer+=BLOCK_SIZE/8)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
DebugDump(input,"\n",-1,0,0,0,1);
|
|
||||||
if (cipher->mode == MODE_CBC)
|
|
||||||
DebugDump(cipher->iv32,"",IV_ROUND,0,0,0,0);
|
|
||||||
#endif
|
|
||||||
for (i=0;i<BLOCK_SIZE/32;i++) /* copy in the block, add whitening */
|
|
||||||
{
|
|
||||||
x[i]=Bswap(((DWORD *)input)[i]) ^ key->subKeys[INPUT_WHITEN+i];
|
|
||||||
if (cipher->mode == MODE_CBC)
|
|
||||||
x[i] ^= Bswap(cipher->iv32[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugDump(x,"",0,0,0,0,0);
|
|
||||||
for (r=0;r<rounds;r++) /* main Twofish encryption loop */
|
|
||||||
{
|
|
||||||
#if FEISTEL
|
|
||||||
t0 = f32(ROR(x[0], (r+1)/2),key->sboxKeys,key->keyLen);
|
|
||||||
t1 = f32(ROL(x[1],8+(r+1)/2),key->sboxKeys,key->keyLen);
|
|
||||||
/* PHT, round keys */
|
|
||||||
x[2]^= ROL(t0 + t1 + key->subKeys[ROUND_SUBKEYS+2*r ], r /2);
|
|
||||||
x[3]^= ROR(t0 + 2*t1 + key->subKeys[ROUND_SUBKEYS+2*r+1],(r+2) /2);
|
|
||||||
|
|
||||||
DebugDump(x,"",r+1,2*(r&1),1,1,0);
|
|
||||||
#else
|
|
||||||
t0 = f32( x[0] ,key->sboxKeys,key->keyLen);
|
|
||||||
t1 = f32(ROL(x[1],8),key->sboxKeys,key->keyLen);
|
|
||||||
|
|
||||||
x[3] = ROL(x[3],1);
|
|
||||||
x[2]^= t0 + t1 + key->subKeys[ROUND_SUBKEYS+2*r ]; /* PHT, round keys */
|
|
||||||
x[3]^= t0 + 2*t1 + key->subKeys[ROUND_SUBKEYS+2*r+1];
|
|
||||||
x[2] = ROR(x[2],1);
|
|
||||||
|
|
||||||
DebugDump(x,"",r+1,2*(r&1),0,1,0);/* make format compatible with optimized code */
|
|
||||||
#endif
|
|
||||||
if (r < rounds-1) /* swap for next round */
|
|
||||||
{
|
|
||||||
tmp = x[0]; x[0]= x[2]; x[2] = tmp;
|
|
||||||
tmp = x[1]; x[1]= x[3]; x[3] = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if FEISTEL
|
|
||||||
x[0] = ROR(x[0],8); /* "final permutation" */
|
|
||||||
x[1] = ROL(x[1],8);
|
|
||||||
x[2] = ROR(x[2],8);
|
|
||||||
x[3] = ROL(x[3],8);
|
|
||||||
#endif
|
|
||||||
for (i=0;i<BLOCK_SIZE/32;i++) /* copy out, with whitening */
|
|
||||||
{
|
|
||||||
((DWORD *)outBuffer)[i] = Bswap(x[i] ^ key->subKeys[OUTPUT_WHITEN+i]);
|
|
||||||
if (cipher->mode == MODE_CBC)
|
|
||||||
cipher->iv32[i] = ((DWORD *)outBuffer)[i];
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
DebugDump(outBuffer,"",rounds+1,0,0,0,1);
|
|
||||||
if (cipher->mode == MODE_CBC)
|
|
||||||
DebugDump(cipher->iv32,"",IV_ROUND,0,0,0,0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return inputLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
+*****************************************************************************
|
|
||||||
*
|
|
||||||
* Function Name: blockDecrypt
|
|
||||||
*
|
|
||||||
* Function: Decrypt block(s) of data using Twofish
|
|
||||||
*
|
|
||||||
* Arguments: cipher = ptr to already initialized cipherInstance
|
|
||||||
* key = ptr to already initialized keyInstance
|
|
||||||
* input = ptr to data blocks to be decrypted
|
|
||||||
* inputLen = # bits to encrypt (multiple of blockSize)
|
|
||||||
* outBuffer = ptr to where to put decrypted blocks
|
|
||||||
*
|
|
||||||
* Return: # bits ciphered (>= 0)
|
|
||||||
* else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL)
|
|
||||||
*
|
|
||||||
* Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits.
|
|
||||||
* If inputLen is not a multiple of BLOCK_SIZE bits in those modes,
|
|
||||||
* an error BAD_INPUT_LEN is returned. In CFB1 mode, all block
|
|
||||||
* sizes can be supported.
|
|
||||||
*
|
|
||||||
-****************************************************************************/
|
|
||||||
int blockDecrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input,
|
|
||||||
int inputLen, BYTE *outBuffer)
|
|
||||||
{
|
|
||||||
int i,n,r; /* loop counters */
|
|
||||||
DWORD x[BLOCK_SIZE/32]; /* block being encrypted */
|
|
||||||
DWORD t0,t1; /* temp variables */
|
|
||||||
int rounds=key->numRounds; /* number of rounds */
|
|
||||||
BYTE bit,ctBit,carry; /* temps for CFB */
|
|
||||||
#if ALIGN32
|
|
||||||
BYTE alignDummy; /* keep 32-bit variable alignment on stack */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if VALIDATE_PARMS
|
|
||||||
if ((cipher == NULL) || (cipher->cipherSig != VALID_SIG))
|
|
||||||
return BAD_CIPHER_STATE;
|
|
||||||
if ((key == NULL) || (key->keySig != VALID_SIG))
|
|
||||||
return BAD_KEY_INSTANCE;
|
|
||||||
if ((rounds < 2) || (rounds > MAX_ROUNDS) || (rounds&1))
|
|
||||||
return BAD_KEY_INSTANCE;
|
|
||||||
if ((cipher->mode != MODE_CFB1) && (inputLen % BLOCK_SIZE))
|
|
||||||
return BAD_INPUT_LEN;
|
|
||||||
#if ALIGN32
|
|
||||||
if ( (((int)cipher) & 3) || (((int)key ) & 3) ||
|
|
||||||
(((int)input) & 3) || (((int)outBuffer) & 3))
|
|
||||||
return BAD_ALIGN32;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (cipher->mode == MODE_CFB1)
|
|
||||||
{ /* use blockEncrypt here to handle CFB, one block at a time */
|
|
||||||
cipher->mode = MODE_ECB; /* do encryption in ECB */
|
|
||||||
for (n=0;n<inputLen;n++)
|
|
||||||
{
|
|
||||||
blockEncrypt(cipher,key,cipher->IV,BLOCK_SIZE,(BYTE *)x);
|
|
||||||
bit = 0x80 >> (n & 7);
|
|
||||||
ctBit = input[n/8] & bit;
|
|
||||||
outBuffer[n/8] = (outBuffer[n/8] & ~ bit) |
|
|
||||||
(ctBit ^ ((((BYTE *) x)[0] & 0x80) >> (n&7)));
|
|
||||||
carry = ctBit >> (7 - (n&7));
|
|
||||||
for (i=BLOCK_SIZE/8-1;i>=0;i--)
|
|
||||||
{
|
|
||||||
bit = cipher->IV[i] >> 7; /* save next "carry" from shift */
|
|
||||||
cipher->IV[i] = (cipher->IV[i] << 1) ^ carry;
|
|
||||||
carry = bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cipher->mode = MODE_CFB1; /* restore mode for next time */
|
|
||||||
return inputLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* here for ECB, CBC modes */
|
|
||||||
for (n=0;n<inputLen;n+=BLOCK_SIZE,input+=BLOCK_SIZE/8,outBuffer+=BLOCK_SIZE/8)
|
|
||||||
{
|
|
||||||
DebugDump(input,"\n",rounds+1,0,0,0,1);
|
|
||||||
|
|
||||||
for (i=0;i<BLOCK_SIZE/32;i++) /* copy in the block, add whitening */
|
|
||||||
x[i]=Bswap(((DWORD *)input)[i]) ^ key->subKeys[OUTPUT_WHITEN+i];
|
|
||||||
|
|
||||||
for (r=rounds-1;r>=0;r--) /* main Twofish decryption loop */
|
|
||||||
{
|
|
||||||
t0 = f32( x[0] ,key->sboxKeys,key->keyLen);
|
|
||||||
t1 = f32(ROL(x[1],8),key->sboxKeys,key->keyLen);
|
|
||||||
|
|
||||||
DebugDump(x,"",r+1,2*(r&1),0,1,0);/* make format compatible with optimized code */
|
|
||||||
x[2] = ROL(x[2],1);
|
|
||||||
x[2]^= t0 + t1 + key->subKeys[ROUND_SUBKEYS+2*r ]; /* PHT, round keys */
|
|
||||||
x[3]^= t0 + 2*t1 + key->subKeys[ROUND_SUBKEYS+2*r+1];
|
|
||||||
x[3] = ROR(x[3],1);
|
|
||||||
|
|
||||||
if (r) /* unswap, except for last round */
|
|
||||||
{
|
|
||||||
t0 = x[0]; x[0]= x[2]; x[2] = t0;
|
|
||||||
t1 = x[1]; x[1]= x[3]; x[3] = t1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DebugDump(x,"",0,0,0,0,0);/* make final output match encrypt initial output */
|
|
||||||
|
|
||||||
for (i=0;i<BLOCK_SIZE/32;i++) /* copy out, with whitening */
|
|
||||||
{
|
|
||||||
x[i] ^= key->subKeys[INPUT_WHITEN+i];
|
|
||||||
if (cipher->mode == MODE_CBC)
|
|
||||||
{
|
|
||||||
x[i] ^= Bswap(cipher->iv32[i]);
|
|
||||||
cipher->iv32[i] = ((DWORD *)input)[i];
|
|
||||||
}
|
|
||||||
((DWORD *)outBuffer)[i] = Bswap(x[i]);
|
|
||||||
}
|
|
||||||
DebugDump(outBuffer,"",-1,0,0,0,1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return inputLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef GetCodeSize
|
|
||||||
DWORD TwofishCodeSize(void) { return Here(0)-TwofishCodeStart(); };
|
|
||||||
#endif
|
|
268
twofish/aes.h
268
twofish/aes.h
|
@ -1,268 +0,0 @@
|
||||||
/* aes.h */
|
|
||||||
|
|
||||||
/* ---------- See examples at end of this file for typical usage -------- */
|
|
||||||
|
|
||||||
/* AES Cipher header file for ANSI C Submissions
|
|
||||||
Lawrence E. Bassham III
|
|
||||||
Computer Security Division
|
|
||||||
National Institute of Standards and Technology
|
|
||||||
|
|
||||||
This sample is to assist implementers developing to the
|
|
||||||
Cryptographic API Profile for AES Candidate Algorithm Submissions.
|
|
||||||
Please consult this document as a cross-reference.
|
|
||||||
|
|
||||||
ANY CHANGES, WHERE APPROPRIATE, TO INFORMATION PROVIDED IN THIS FILE
|
|
||||||
MUST BE DOCUMENTED. CHANGES ARE ONLY APPROPRIATE WHERE SPECIFIED WITH
|
|
||||||
THE STRING "CHANGE POSSIBLE". FUNCTION CALLS AND THEIR PARAMETERS
|
|
||||||
CANNOT BE CHANGED. STRUCTURES CAN BE ALTERED TO ALLOW IMPLEMENTERS TO
|
|
||||||
INCLUDE IMPLEMENTATION SPECIFIC INFORMATION.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Includes:
|
|
||||||
Standard include files
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "platform.h" /* platform-specific defines */
|
|
||||||
|
|
||||||
/* Defines:
|
|
||||||
Add any additional defines you need
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define DIR_ENCRYPT 0 /* Are we encrpyting? */
|
|
||||||
#define DIR_DECRYPT 1 /* Are we decrpyting? */
|
|
||||||
#define MODE_ECB 1 /* Are we ciphering in ECB mode? */
|
|
||||||
#define MODE_CBC 2 /* Are we ciphering in CBC mode? */
|
|
||||||
#define MODE_CFB1 3 /* Are we ciphering in 1-bit CFB mode? */
|
|
||||||
|
|
||||||
#define TRUE 1
|
|
||||||
#define FALSE 0
|
|
||||||
|
|
||||||
#define BAD_KEY_DIR -1 /* Key direction is invalid (unknown value) */
|
|
||||||
#define BAD_KEY_MAT -2 /* Key material not of correct length */
|
|
||||||
#define BAD_KEY_INSTANCE -3 /* Key passed is not valid */
|
|
||||||
#define BAD_CIPHER_MODE -4 /* Params struct passed to cipherInit invalid */
|
|
||||||
#define BAD_CIPHER_STATE -5 /* Cipher in wrong state (e.g., not initialized) */
|
|
||||||
|
|
||||||
/* CHANGE POSSIBLE: inclusion of algorithm specific defines */
|
|
||||||
/* TWOFISH specific definitions */
|
|
||||||
#define MAX_KEY_SIZE 64 /* # of ASCII chars needed to represent a key */
|
|
||||||
#define MAX_IV_SIZE 16 /* # of bytes needed to represent an IV */
|
|
||||||
#define BAD_INPUT_LEN -6 /* inputLen not a multiple of block size */
|
|
||||||
#define BAD_PARAMS -7 /* invalid parameters */
|
|
||||||
#define BAD_IV_MAT -8 /* invalid IV text */
|
|
||||||
#define BAD_ENDIAN -9 /* incorrect endianness define */
|
|
||||||
#define BAD_ALIGN32 -10 /* incorrect 32-bit alignment */
|
|
||||||
|
|
||||||
#define BLOCK_SIZE 128 /* number of bits per block */
|
|
||||||
#define MAX_ROUNDS 16 /* max # rounds (for allocating subkey array) */
|
|
||||||
#define ROUNDS_128 16 /* default number of rounds for 128-bit keys*/
|
|
||||||
#define ROUNDS_192 16 /* default number of rounds for 192-bit keys*/
|
|
||||||
#define ROUNDS_256 16 /* default number of rounds for 256-bit keys*/
|
|
||||||
#define MAX_KEY_BITS 256 /* max number of bits of key */
|
|
||||||
#define MIN_KEY_BITS 128 /* min number of bits of key (zero pad) */
|
|
||||||
#define VALID_SIG 0x48534946 /* initialization signature ('FISH') */
|
|
||||||
#define MCT_OUTER 400 /* MCT outer loop */
|
|
||||||
#define MCT_INNER 10000 /* MCT inner loop */
|
|
||||||
#define REENTRANT 1 /* nonzero forces reentrant code (slightly slower) */
|
|
||||||
|
|
||||||
#define INPUT_WHITEN 0 /* subkey array indices */
|
|
||||||
#define OUTPUT_WHITEN ( INPUT_WHITEN + BLOCK_SIZE/32)
|
|
||||||
#define ROUND_SUBKEYS (OUTPUT_WHITEN + BLOCK_SIZE/32) /* use 2 * (# rounds) */
|
|
||||||
#define TOTAL_SUBKEYS (ROUND_SUBKEYS + 2*MAX_ROUNDS)
|
|
||||||
|
|
||||||
/* Typedefs:
|
|
||||||
Typedef'ed data storage elements. Add any algorithm specific
|
|
||||||
parameters at the bottom of the structs as appropriate.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef unsigned char BYTE;
|
|
||||||
typedef unsigned long DWORD; /* 32-bit unsigned quantity */
|
|
||||||
typedef DWORD fullSbox[4][256];
|
|
||||||
|
|
||||||
/* The structure for key information */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
BYTE direction; /* Key used for encrypting or decrypting? */
|
|
||||||
#if ALIGN32
|
|
||||||
BYTE dummyAlign[3]; /* keep 32-bit alignment */
|
|
||||||
#endif
|
|
||||||
int keyLen; /* Length of the key */
|
|
||||||
char keyMaterial[MAX_KEY_SIZE+4];/* Raw key data in ASCII */
|
|
||||||
|
|
||||||
/* Twofish-specific parameters: */
|
|
||||||
DWORD keySig; /* set to VALID_SIG by makeKey() */
|
|
||||||
int numRounds; /* number of rounds in cipher */
|
|
||||||
DWORD key32[MAX_KEY_BITS/32]; /* actual key bits, in dwords */
|
|
||||||
DWORD sboxKeys[MAX_KEY_BITS/64];/* key bits used for S-boxes */
|
|
||||||
DWORD subKeys[TOTAL_SUBKEYS]; /* round subkeys, input/output whitening bits */
|
|
||||||
#if REENTRANT
|
|
||||||
fullSbox sBox8x32; /* fully expanded S-box */
|
|
||||||
#if defined(COMPILE_KEY) && defined(USE_ASM)
|
|
||||||
#undef VALID_SIG
|
|
||||||
#define VALID_SIG 0x504D4F43 /* 'COMP': C is compiled with -DCOMPILE_KEY */
|
|
||||||
DWORD cSig1; /* set after first "compile" (zero at "init") */
|
|
||||||
void *encryptFuncPtr; /* ptr to asm encrypt function */
|
|
||||||
void *decryptFuncPtr; /* ptr to asm decrypt function */
|
|
||||||
DWORD codeSize; /* size of compiledCode */
|
|
||||||
DWORD cSig2; /* set after first "compile" */
|
|
||||||
BYTE compiledCode[5000]; /* make room for the code itself */
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
} keyInstance;
|
|
||||||
|
|
||||||
/* The structure for cipher information */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
BYTE mode; /* MODE_ECB, MODE_CBC, or MODE_CFB1 */
|
|
||||||
#if ALIGN32
|
|
||||||
BYTE dummyAlign[3]; /* keep 32-bit alignment */
|
|
||||||
#endif
|
|
||||||
BYTE IV[MAX_IV_SIZE]; /* CFB1 iv bytes (CBC uses iv32) */
|
|
||||||
|
|
||||||
/* Twofish-specific parameters: */
|
|
||||||
DWORD cipherSig; /* set to VALID_SIG by cipherInit() */
|
|
||||||
DWORD iv32[BLOCK_SIZE/32]; /* CBC IV bytes arranged as dwords */
|
|
||||||
} cipherInstance;
|
|
||||||
|
|
||||||
/* Function protoypes */
|
|
||||||
int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial);
|
|
||||||
|
|
||||||
int cipherInit(cipherInstance *cipher, BYTE mode, char *IV);
|
|
||||||
|
|
||||||
int blockEncrypt(cipherInstance *cipher, keyInstance *key, BYTE *input,
|
|
||||||
int inputLen, BYTE *outBuffer);
|
|
||||||
|
|
||||||
int blockDecrypt(cipherInstance *cipher, keyInstance *key, BYTE *input,
|
|
||||||
int inputLen, BYTE *outBuffer);
|
|
||||||
|
|
||||||
int reKey(keyInstance *key); /* do key schedule using modified key.keyDwords */
|
|
||||||
|
|
||||||
/* API to check table usage, for use in ECB_TBL KAT */
|
|
||||||
#define TAB_DISABLE 0
|
|
||||||
#define TAB_ENABLE 1
|
|
||||||
#define TAB_RESET 2
|
|
||||||
#define TAB_QUERY 3
|
|
||||||
#define TAB_MIN_QUERY 50
|
|
||||||
int TableOp(int op);
|
|
||||||
|
|
||||||
|
|
||||||
#define CONST /* helpful C++ syntax sugar, NOP for ANSI C */
|
|
||||||
|
|
||||||
#if BLOCK_SIZE == 128 /* optimize block copies */
|
|
||||||
#define Copy1(d,s,N) ((DWORD *)(d))[N] = ((DWORD *)(s))[N]
|
|
||||||
#define BlockCopy(d,s) { Copy1(d,s,0);Copy1(d,s,1);Copy1(d,s,2);Copy1(d,s,3); }
|
|
||||||
#else
|
|
||||||
#define BlockCopy(d,s) { memcpy(d,s,BLOCK_SIZE/8); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST_2FISH
|
|
||||||
/* ----- EXAMPLES -----
|
|
||||||
|
|
||||||
Unfortunately, the AES API is somewhat clumsy, and it is not entirely
|
|
||||||
obvious how to use the above functions. In particular, note that
|
|
||||||
makeKey() takes an ASCII hex nibble key string (e.g., 32 characters
|
|
||||||
for a 128-bit key), which is rarely the way that keys are internally
|
|
||||||
represented. The reKey() function uses instead the keyInstance.key32
|
|
||||||
array of key bits and is the preferred method. In fact, makeKey()
|
|
||||||
initializes some internal keyInstance state, then parse the ASCII
|
|
||||||
string into the binary key32, and calls reKey(). To initialize the
|
|
||||||
keyInstance state, use a 'dummy' call to makeKey(); i.e., set the
|
|
||||||
keyMaterial parameter to NULL. Then use reKey() for all key changes.
|
|
||||||
Similarly, cipherInit takes an IV string in ASCII hex, so a dummy setup
|
|
||||||
call with a null IV string will skip the ASCII parse.
|
|
||||||
|
|
||||||
Note that CFB mode is not well tested nor defined by AES, so using the
|
|
||||||
Twofish MODE_CFB it not recommended. If you wish to implement a CFB mode,
|
|
||||||
build it external to the Twofish code, using the Twofish functions only
|
|
||||||
in ECB mode.
|
|
||||||
|
|
||||||
Below is a sample piece of code showing how the code is typically used
|
|
||||||
to set up a key, encrypt, and decrypt. Error checking is somewhat limited
|
|
||||||
in this example. Pseudorandom bytes are used for all key and text.
|
|
||||||
|
|
||||||
If you compile TWOFISH2.C or TWOFISH.C as a DOS (or Windows Console) app
|
|
||||||
with this code enabled, the test will be run. For example, using
|
|
||||||
Borland C, you would compile using:
|
|
||||||
BCC32 -DTEST_2FISH twofish2.c
|
|
||||||
to run the test on the optimized code, or
|
|
||||||
BCC32 -DTEST_2FISH twofish.c
|
|
||||||
to run the test on the pedagogical code.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define MAX_BLK_CNT 4 /* max # blocks per call in TestTwofish */
|
|
||||||
int TestTwofish(int mode,int keySize) /* keySize must be 128, 192, or 256 */
|
|
||||||
{ /* return 0 iff test passes */
|
|
||||||
keyInstance ki; /* key information, including tables */
|
|
||||||
cipherInstance ci; /* keeps mode (ECB, CBC) and IV */
|
|
||||||
BYTE plainText[MAX_BLK_CNT*(BLOCK_SIZE/8)];
|
|
||||||
BYTE cipherText[MAX_BLK_CNT*(BLOCK_SIZE/8)];
|
|
||||||
BYTE decryptOut[MAX_BLK_CNT*(BLOCK_SIZE/8)];
|
|
||||||
BYTE iv[BLOCK_SIZE/8];
|
|
||||||
int i,byteCnt;
|
|
||||||
|
|
||||||
if (makeKey(&ki,DIR_ENCRYPT,keySize,NULL) != TRUE)
|
|
||||||
return 1; /* 'dummy' setup for a 128-bit key */
|
|
||||||
if (cipherInit(&ci,mode,NULL) != TRUE)
|
|
||||||
return 1; /* 'dummy' setup for cipher */
|
|
||||||
|
|
||||||
for (i=0;i<keySize/32;i++) /* select key bits */
|
|
||||||
ki.key32[i]=0x10003 * rand();
|
|
||||||
reKey(&ki); /* run the key schedule */
|
|
||||||
|
|
||||||
if (mode != MODE_ECB) /* set up random iv (if needed)*/
|
|
||||||
{
|
|
||||||
for (i=0;i<sizeof(iv);i++)
|
|
||||||
iv[i]=(BYTE) rand();
|
|
||||||
memcpy(ci.iv32,iv,sizeof(ci.iv32)); /* copy the IV to ci */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* select number of bytes to encrypt (multiple of block) */
|
|
||||||
/* e.g., byteCnt = 16, 32, 48, 64 */
|
|
||||||
byteCnt = (BLOCK_SIZE/8) * (1 + (rand() % MAX_BLK_CNT));
|
|
||||||
|
|
||||||
for (i=0;i<byteCnt;i++) /* generate test data */
|
|
||||||
plainText[i]=(BYTE) rand();
|
|
||||||
|
|
||||||
/* encrypt the bytes */
|
|
||||||
if (blockEncrypt(&ci,&ki, plainText,byteCnt*8,cipherText) != byteCnt*8)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* decrypt the bytes */
|
|
||||||
if (mode != MODE_ECB) /* first re-init the IV (if needed) */
|
|
||||||
memcpy(ci.iv32,iv,sizeof(ci.iv32));
|
|
||||||
|
|
||||||
if (blockDecrypt(&ci,&ki,cipherText,byteCnt*8,decryptOut) != byteCnt*8)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* make sure the decrypt output matches original plaintext */
|
|
||||||
if (memcmp(plainText,decryptOut,byteCnt))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0; /* tests passed! */
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(void)
|
|
||||||
{
|
|
||||||
int testCnt,keySize;
|
|
||||||
|
|
||||||
srand((unsigned) time(NULL)); /* randomize */
|
|
||||||
|
|
||||||
for (keySize=128;keySize<=256;keySize+=64)
|
|
||||||
for (testCnt=0;testCnt<10;testCnt++)
|
|
||||||
{
|
|
||||||
if (TestTwofish(MODE_ECB,keySize))
|
|
||||||
{ printf("ECB Failure at keySize=%d",keySize); return; }
|
|
||||||
if (TestTwofish(MODE_CBC,keySize))
|
|
||||||
{ printf("CBC Failure at keySize=%d",keySize); return; }
|
|
||||||
}
|
|
||||||
printf("Tests passed");
|
|
||||||
}
|
|
||||||
#endif /* TEST_2FISH */
|
|
|
@ -1,77 +0,0 @@
|
||||||
#ifdef DEBUG /* keep these macros common so they are same for both versions */
|
|
||||||
CONST int debugCompile = 1;
|
|
||||||
extern int debug;
|
|
||||||
extern void DebugIO(CONST char *s); /* display the debug output */
|
|
||||||
|
|
||||||
#define DebugDump(x,s,R,XOR,doRot,showT,needBswap) \
|
|
||||||
{ if (debug) _Dump(x,s,R,XOR,doRot,showT,needBswap,t0,t1); }
|
|
||||||
#define DebugDumpKey(key) { if (debug) _DumpKey(key); }
|
|
||||||
#define IV_ROUND -100
|
|
||||||
|
|
||||||
void _Dump(CONST void *p,CONST char *s,int R,int XOR,int doRot,int showT,int needBswap,
|
|
||||||
DWORD t0,DWORD t1)
|
|
||||||
{
|
|
||||||
char line[512]; /* build output here */
|
|
||||||
int i,n;
|
|
||||||
DWORD q[4];
|
|
||||||
|
|
||||||
if (R == IV_ROUND)
|
|
||||||
sprintf(line,"%sIV: ",s);
|
|
||||||
else
|
|
||||||
sprintf(line,"%sR[%2d]: ",s,R);
|
|
||||||
for (n=0;line[n];n++) ;
|
|
||||||
|
|
||||||
for (i=0;i<4;i++)
|
|
||||||
{
|
|
||||||
q[i]=((CONST DWORD *)p)[i^(XOR)];
|
|
||||||
if (needBswap) q[i]=Bswap(q[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(line+n,"x= %08lX %08lX %08lX %08lX.",
|
|
||||||
ROR(q[0],doRot*(R )/2),
|
|
||||||
ROL(q[1],doRot*(R )/2),
|
|
||||||
ROR(q[2],doRot*(R+1)/2),
|
|
||||||
ROL(q[3],doRot*(R+1)/2));
|
|
||||||
for (;line[n];n++) ;
|
|
||||||
|
|
||||||
if (showT)
|
|
||||||
sprintf(line+n," t0=%08lX. t1=%08lX.",t0,t1);
|
|
||||||
for (;line[n];n++) ;
|
|
||||||
|
|
||||||
sprintf(line+n,"\n");
|
|
||||||
DebugIO(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _DumpKey(CONST keyInstance *key)
|
|
||||||
{
|
|
||||||
char line[512];
|
|
||||||
int i;
|
|
||||||
int k64Cnt=(key->keyLen+63)/64; /* round up to next multiple of 64 bits */
|
|
||||||
int subkeyCnt = ROUND_SUBKEYS + 2*key->numRounds;
|
|
||||||
|
|
||||||
sprintf(line,";\n;makeKey: Input key --> S-box key [%s]\n",
|
|
||||||
(key->direction == DIR_ENCRYPT) ? "Encrypt" : "Decrypt");
|
|
||||||
DebugIO(line);
|
|
||||||
for (i=0;i<k64Cnt;i++) /* display in RS format */
|
|
||||||
{
|
|
||||||
sprintf(line,";%12s %08lX %08lX --> %08lX\n","",
|
|
||||||
key->key32[2*i+1],key->key32[2*i],key->sboxKeys[k64Cnt-1-i]);
|
|
||||||
DebugIO(line);
|
|
||||||
}
|
|
||||||
sprintf(line,";%11sSubkeys\n","");
|
|
||||||
DebugIO(line);
|
|
||||||
for (i=0;i<subkeyCnt/2;i++)
|
|
||||||
{
|
|
||||||
sprintf(line,";%12s %08lX %08lX%s\n","",key->subKeys[2*i],key->subKeys[2*i+1],
|
|
||||||
(2*i == INPUT_WHITEN) ? " Input whiten" :
|
|
||||||
(2*i == OUTPUT_WHITEN) ? " Output whiten" :
|
|
||||||
(2*i == ROUND_SUBKEYS) ? " Round subkeys" : "");
|
|
||||||
DebugIO(line);
|
|
||||||
}
|
|
||||||
DebugIO(";\n");
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
CONST int debugCompile = 0;
|
|
||||||
#define DebugDump(x,s,R,XOR,doRot,showT,needBswap)
|
|
||||||
#define DebugDumpKey(key)
|
|
||||||
#endif
|
|
|
@ -1,75 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
PLATFORM.H -- Platform-specific defines for TWOFISH code
|
|
||||||
|
|
||||||
Submitters:
|
|
||||||
Bruce Schneier, Counterpane Systems
|
|
||||||
Doug Whiting, Hi/fn
|
|
||||||
John Kelsey, Counterpane Systems
|
|
||||||
Chris Hall, Counterpane Systems
|
|
||||||
David Wagner, UC Berkeley
|
|
||||||
|
|
||||||
Code Author: Doug Whiting, Hi/fn
|
|
||||||
|
|
||||||
Version 1.00 April 1998
|
|
||||||
|
|
||||||
Copyright 1998, Hi/fn and Counterpane Systems. All rights reserved.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
* Tab size is set to 4 characters in this file
|
|
||||||
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/* use intrinsic rotate if possible */
|
|
||||||
#define ROL(x,n) (((x) << ((n) & 0x1F)) | ((x) >> (32-((n) & 0x1F))))
|
|
||||||
#define ROR(x,n) (((x) >> ((n) & 0x1F)) | ((x) << (32-((n) & 0x1F))))
|
|
||||||
|
|
||||||
#if (0) && defined(__BORLANDC__) && (__BORLANDC__ >= 0x462)
|
|
||||||
#error "!!!This does not work for some reason!!!"
|
|
||||||
#include <stdlib.h> /* get prototype for _lrotl() , _lrotr() */
|
|
||||||
#pragma inline __lrotl__
|
|
||||||
#pragma inline __lrotr__
|
|
||||||
#undef ROL /* get rid of inefficient definitions */
|
|
||||||
#undef ROR
|
|
||||||
#define ROL(x,n) __lrotl__(x,n) /* use compiler intrinsic rotations */
|
|
||||||
#define ROR(x,n) __lrotr__(x,n)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#include <stdlib.h> /* get prototypes for rotation functions */
|
|
||||||
#undef ROL
|
|
||||||
#undef ROR
|
|
||||||
#pragma intrinsic(_lrotl,_lrotr) /* use intrinsic compiler rotations */
|
|
||||||
#define ROL(x,n) _lrotl(x,n)
|
|
||||||
#define ROR(x,n) _lrotr(x,n)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(__i386__) && !defined(__x86_64__)
|
|
||||||
#ifdef __BORLANDC__
|
|
||||||
#define __i386__ 300 /* make sure this is defined for Intel CPUs */
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
|
|
||||||
#define LittleEndian 1 /* e.g., 1 for Pentium, 0 for 68K */
|
|
||||||
#define ALIGN32 0 /* need dword alignment? (no for Pentium) */
|
|
||||||
#else /* non-Intel platforms */
|
|
||||||
#define LittleEndian 0 /* (assume big endian */
|
|
||||||
#define ALIGN32 0 /* (assume need alignment for non-Intel) */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LittleEndian
|
|
||||||
#define Bswap(x) (x) /* NOP for little-endian machines */
|
|
||||||
#define ADDR_XOR 0 /* NOP for little-endian machines */
|
|
||||||
#else
|
|
||||||
#define Bswap(x) ((ROR(x,8) & 0xFF00FF00) | (ROL(x,8) & 0x00FF00FF))
|
|
||||||
#define ADDR_XOR 3 /* convert byte address in dword */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Macros for extracting bytes from dwords (correct for endianness) */
|
|
||||||
#define _b(x,N) (((BYTE *)&x)[((N) & 3) ^ ADDR_XOR]) /* pick bytes out of a dword */
|
|
||||||
|
|
||||||
#define b0(x) _b(x,0) /* extract LSB of DWORD */
|
|
||||||
#define b1(x) _b(x,1)
|
|
||||||
#define b2(x) _b(x,2)
|
|
||||||
#define b3(x) _b(x,3) /* extract MSB of DWORD */
|
|
||||||
|
|
228
twofish/table.h
228
twofish/table.h
|
@ -1,228 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
TABLE.H -- Tables, macros, constants for Twofish S-boxes and MDS matrix
|
|
||||||
|
|
||||||
Submitters:
|
|
||||||
Bruce Schneier, Counterpane Systems
|
|
||||||
Doug Whiting, Hi/fn
|
|
||||||
John Kelsey, Counterpane Systems
|
|
||||||
Chris Hall, Counterpane Systems
|
|
||||||
David Wagner, UC Berkeley
|
|
||||||
|
|
||||||
Code Author: Doug Whiting, Hi/fn
|
|
||||||
|
|
||||||
Version 1.00 April 1998
|
|
||||||
|
|
||||||
Copyright 1998, Hi/fn and Counterpane Systems. All rights reserved.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
* Tab size is set to 4 characters in this file
|
|
||||||
* These definitions should be used in optimized and unoptimized
|
|
||||||
versions to insure consistency.
|
|
||||||
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/* for computing subkeys */
|
|
||||||
#define SK_STEP 0x02020202u
|
|
||||||
#define SK_BUMP 0x01010101u
|
|
||||||
#define SK_ROTL 9
|
|
||||||
|
|
||||||
/* Reed-Solomon code parameters: (12,8) reversible code
|
|
||||||
g(x) = x**4 + (a + 1/a) x**3 + a x**2 + (a + 1/a) x + 1
|
|
||||||
where a = primitive root of field generator 0x14D */
|
|
||||||
#define RS_GF_FDBK 0x14D /* field generator */
|
|
||||||
#define RS_rem(x) \
|
|
||||||
{ BYTE b = (BYTE) (x >> 24); \
|
|
||||||
DWORD g2 = ((b << 1) ^ ((b & 0x80) ? RS_GF_FDBK : 0 )) & 0xFF; \
|
|
||||||
DWORD g3 = ((b >> 1) & 0x7F) ^ ((b & 1) ? RS_GF_FDBK >> 1 : 0 ) ^ g2 ; \
|
|
||||||
x = (x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Macros for the MDS matrix
|
|
||||||
* The MDS matrix is (using primitive polynomial 169):
|
|
||||||
* 01 EF 5B 5B
|
|
||||||
* 5B EF EF 01
|
|
||||||
* EF 5B 01 EF
|
|
||||||
* EF 01 EF 5B
|
|
||||||
*----------------------------------------------------------------
|
|
||||||
* More statistical properties of this matrix (from MDS.EXE output):
|
|
||||||
*
|
|
||||||
* Min Hamming weight (one byte difference) = 8. Max=26. Total = 1020.
|
|
||||||
* Prob[8]: 7 23 42 20 52 95 88 94 121 128 91
|
|
||||||
* 102 76 41 24 8 4 1 3 0 0 0
|
|
||||||
* Runs[8]: 2 4 5 6 7 8 9 11
|
|
||||||
* MSBs[8]: 1 4 15 8 18 38 40 43
|
|
||||||
* HW= 8: 05040705 0A080E0A 14101C14 28203828 50407050 01499101 A080E0A0
|
|
||||||
* HW= 9: 04050707 080A0E0E 10141C1C 20283838 40507070 80A0E0E0 C6432020 07070504
|
|
||||||
* 0E0E0A08 1C1C1410 38382820 70705040 E0E0A080 202043C6 05070407 0A0E080E
|
|
||||||
* 141C101C 28382038 50704070 A0E080E0 4320C620 02924B02 089A4508
|
|
||||||
* Min Hamming weight (two byte difference) = 3. Max=28. Total = 390150.
|
|
||||||
* Prob[3]: 7 18 55 149 270 914 2185 5761 11363 20719 32079
|
|
||||||
* 43492 51612 53851 52098 42015 31117 20854 11538 6223 2492 1033
|
|
||||||
* MDS OK, ROR: 6+ 7+ 8+ 9+ 10+ 11+ 12+ 13+ 14+ 15+ 16+
|
|
||||||
* 17+ 18+ 19+ 20+ 21+ 22+ 23+ 24+ 25+ 26+
|
|
||||||
*/
|
|
||||||
#define MDS_GF_FDBK 0x169 /* primitive polynomial for GF(256)*/
|
|
||||||
#define LFSR1(x) ( ((x) >> 1) ^ (((x) & 0x01) ? MDS_GF_FDBK/2 : 0))
|
|
||||||
#define LFSR2(x) ( ((x) >> 2) ^ (((x) & 0x02) ? MDS_GF_FDBK/2 : 0) \
|
|
||||||
^ (((x) & 0x01) ? MDS_GF_FDBK/4 : 0))
|
|
||||||
|
|
||||||
#define Mx_1(x) ((DWORD) (x)) /* force result to dword so << will work */
|
|
||||||
#define Mx_X(x) ((DWORD) ((x) ^ LFSR2(x))) /* 5B */
|
|
||||||
#define Mx_Y(x) ((DWORD) ((x) ^ LFSR1(x) ^ LFSR2(x))) /* EF */
|
|
||||||
|
|
||||||
#define M00 Mul_1
|
|
||||||
#define M01 Mul_Y
|
|
||||||
#define M02 Mul_X
|
|
||||||
#define M03 Mul_X
|
|
||||||
|
|
||||||
#define M10 Mul_X
|
|
||||||
#define M11 Mul_Y
|
|
||||||
#define M12 Mul_Y
|
|
||||||
#define M13 Mul_1
|
|
||||||
|
|
||||||
#define M20 Mul_Y
|
|
||||||
#define M21 Mul_X
|
|
||||||
#define M22 Mul_1
|
|
||||||
#define M23 Mul_Y
|
|
||||||
|
|
||||||
#define M30 Mul_Y
|
|
||||||
#define M31 Mul_1
|
|
||||||
#define M32 Mul_Y
|
|
||||||
#define M33 Mul_X
|
|
||||||
|
|
||||||
#define Mul_1 Mx_1
|
|
||||||
#define Mul_X Mx_X
|
|
||||||
#define Mul_Y Mx_Y
|
|
||||||
|
|
||||||
/* Define the fixed p0/p1 permutations used in keyed S-box lookup.
|
|
||||||
By changing the following constant definitions for P_ij, the S-boxes will
|
|
||||||
automatically get changed in all the Twofish source code. Note that P_i0 is
|
|
||||||
the "outermost" 8x8 permutation applied. See the f32() function to see
|
|
||||||
how these constants are to be used.
|
|
||||||
*/
|
|
||||||
#define P_00 1 /* "outermost" permutation */
|
|
||||||
#define P_01 0
|
|
||||||
#define P_02 0
|
|
||||||
#define P_03 (P_01^1) /* "extend" to larger key sizes */
|
|
||||||
#define P_04 1
|
|
||||||
|
|
||||||
#define P_10 0
|
|
||||||
#define P_11 0
|
|
||||||
#define P_12 1
|
|
||||||
#define P_13 (P_11^1)
|
|
||||||
#define P_14 0
|
|
||||||
|
|
||||||
#define P_20 1
|
|
||||||
#define P_21 1
|
|
||||||
#define P_22 0
|
|
||||||
#define P_23 (P_21^1)
|
|
||||||
#define P_24 0
|
|
||||||
|
|
||||||
#define P_30 0
|
|
||||||
#define P_31 1
|
|
||||||
#define P_32 1
|
|
||||||
#define P_33 (P_31^1)
|
|
||||||
#define P_34 1
|
|
||||||
|
|
||||||
#define p8(N) P8x8[P_##N] /* some syntax shorthand */
|
|
||||||
|
|
||||||
/* fixed 8x8 permutation S-boxes */
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* 07:07:14 05/30/98 [4x4] TestCnt=256. keySize=128. CRC=4BD14D9E.
|
|
||||||
* maxKeyed: dpMax = 18. lpMax =100. fixPt = 8. skXor = 0. skDup = 6.
|
|
||||||
* log2(dpMax[ 6..18])= --- 15.42 1.33 0.89 4.05 7.98 12.05
|
|
||||||
* log2(lpMax[ 7..12])= 9.32 1.01 1.16 4.23 8.02 12.45
|
|
||||||
* log2(fixPt[ 0.. 8])= 1.44 1.44 2.44 4.06 6.01 8.21 11.07 14.09 17.00
|
|
||||||
* log2(skXor[ 0.. 0])
|
|
||||||
* log2(skDup[ 0.. 6])= --- 2.37 0.44 3.94 8.36 13.04 17.99
|
|
||||||
***********************************************************************/
|
|
||||||
CONST BYTE P8x8[2][256]=
|
|
||||||
{
|
|
||||||
/* p0: */
|
|
||||||
/* dpMax = 10. lpMax = 64. cycleCnt= 1 1 1 0. */
|
|
||||||
/* 817D6F320B59ECA4.ECB81235F4A6709D.BA5E6D90C8F32471.D7F4126E9B3085CA. */
|
|
||||||
/* Karnaugh maps:
|
|
||||||
* 0111 0001 0011 1010. 0001 1001 1100 1111. 1001 1110 0011 1110. 1101 0101 1111 1001.
|
|
||||||
* 0101 1111 1100 0100. 1011 0101 0010 0000. 0101 1000 1100 0101. 1000 0111 0011 0010.
|
|
||||||
* 0000 1001 1110 1101. 1011 1000 1010 0011. 0011 1001 0101 0000. 0100 0010 0101 1011.
|
|
||||||
* 0111 0100 0001 0110. 1000 1011 1110 1001. 0011 0011 1001 1101. 1101 0101 0000 1100.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
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: */
|
|
||||||
/* dpMax = 10. lpMax = 64. cycleCnt= 2 0 0 1. */
|
|
||||||
/* 28BDF76E31940AC5.1E2B4C376DA5F908.4C75169A0ED82B3F.B951C3DE647F208A. */
|
|
||||||
/* Karnaugh maps:
|
|
||||||
* 0011 1001 0010 0111. 1010 0111 0100 0110. 0011 0001 1111 0100. 1111 1000 0001 1100.
|
|
||||||
* 1100 1111 1111 1010. 0011 0011 1110 0100. 1001 0110 0100 0011. 0101 0110 1011 1011.
|
|
||||||
* 0010 0100 0011 0101. 1100 1000 1000 1110. 0111 1111 0010 0110. 0000 1010 0000 0011.
|
|
||||||
* 1101 1000 0010 0001. 0110 1001 1110 0101. 0001 0100 0101 0111. 0011 1011 1111 0010.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
};
|
|
Loading…
Add table
Add a link
Reference in a new issue