From 1732eff6bb00294b8d3c25245ed4fc29076b60b0 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sat, 12 Nov 2016 08:38:39 +0000 Subject: [PATCH 01/15] Initial working radmin 2.x cracker. Lots of additional work still left to be done. --- Makefile.am | 6 +- hydra-radmin2.c | 325 +++++++++++++++++++++ hydra.c | 11 +- hydra.h | 1 + twofish.c | 704 +++++++++++++++++++++++++++++++++++++++++++++ twofish/aes.h | 268 +++++++++++++++++ twofish/debug.h | 77 +++++ twofish/platform.h | 75 +++++ twofish/table.h | 228 +++++++++++++++ 9 files changed, 1692 insertions(+), 3 deletions(-) create mode 100644 hydra-radmin2.c create mode 100644 twofish.c create mode 100644 twofish/aes.h create mode 100644 twofish/debug.h create mode 100644 twofish/platform.h create mode 100644 twofish/table.h diff --git a/Makefile.am b/Makefile.am index c904b09..43fa77a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,8 @@ SRC = hydra-vnc.c hydra-pcnfs.c hydra-rexec.c hydra-nntp.c hydra-socks5.c \ hydra-oracle.c hydra-vmauthd.c hydra-asterisk.c hydra-firebird.c hydra-afp.c hydra-ncp.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 \ - 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 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-pop3.o hydra-smb.o hydra-icq.o hydra-cisco-enable.o hydra-ldap.o \ @@ -30,7 +31,8 @@ OBJ = hydra-vnc.o hydra-pcnfs.o hydra-rexec.o hydra-nntp.o hydra-socks5.o \ hydra-oracle-sid.o hydra-oracle.o hydra-vmauthd.o hydra-asterisk.o hydra-firebird.o hydra-afp.o hydra-ncp.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 \ - 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 BINS = hydra pw-inspector EXTRA_DIST = README README.arm README.palm CHANGES TODO INSTALL LICENSE \ diff --git a/hydra-radmin2.c b/hydra-radmin2.c new file mode 100644 index 0000000..662a173 --- /dev/null +++ b/hydra-radmin2.c @@ -0,0 +1,325 @@ +#include "hydra-mod.h" +#include +#include +#include + +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); + + +struct rmessage{ + char magic; //No touching! + unsigned int length; //Total message size of data. + unsigned int checksum; //Checksum from type to end of data. + char type; //Command type, table below. + unsigned char data[32]; //data to be sent. +}; + +void print_message(struct rmessage *msg) { + return; + int dlen = 0; + hydra_report(stderr, + "m:\t%02x\n" + "l:\t%08x\n" + "c:\t%08x\n" + "t:\t%02x\n", + msg->magic, + msg->length, + msg->checksum, + msg->type); + + hydra_report(stderr, "d:\t"); + for(dlen = 0; dlen < msg->length - 1; dlen++) { //-1 because of type. + hydra_report(stderr, "%02x", msg->data[dlen]); + } + hydra_report(stderr, "\n"); +} + +unsigned int checksum(struct rmessage *msg) { + int blen; + unsigned char *stream; + unsigned int sum; + blen = msg->length; //Get the real length. + blen += (4 - (blen % 4)); + stream = calloc(blen, sizeof(unsigned char)); + memcpy(stream, &msg->type, sizeof(unsigned char)); + memcpy(stream+1, msg->data, blen-1); + + sum = 0; + for(blen -= sizeof(unsigned int); blen > 0; blen -= sizeof(unsigned int)) { + sum += *(unsigned int *)(stream + blen); + } + sum += *(unsigned int *)stream; + + return sum; +} + + +void challenge_request(struct rmessage *msg) { + msg->magic = 0x01; + msg->length = 0x01; + msg->type = 0x1b; + msg->checksum = checksum(msg); + print_message(msg); +} + +void challenge_response(struct rmessage *msg, unsigned char *solution) { + msg->magic = 0x01; + msg->length = 0x21; + msg->type = 0x09; + memcpy(msg->data, solution, 0x20); + msg->checksum = checksum(msg); + print_message(msg); +} + + +unsigned char *message2buffer(struct rmessage *msg) { + unsigned char *data; + if(msg == NULL) { + hydra_report(stderr, "rmessage is null\n"); + hydra_child_exit(0); + return NULL; + } + + switch(msg->type) { + case 0x1b: //Challenge request + data = calloc (10, sizeof(unsigned char)); //TODO: check return + memcpy(data, &msg->magic, sizeof(char)); + *((int *)(data+1)) = htonl(msg->length); + *((int *)(data+5)) = htonl(msg->checksum); + memcpy((data+9), &msg->type, sizeof(char)); + break; + case 0x09: + data = calloc (42, sizeof(unsigned char)); //TODO: check return + memcpy(data, &msg->magic, sizeof(char)); + *((int *)(data+1)) = htonl(msg->length); + *((int *)(data+5)) = htonl(msg->checksum); + memcpy((data+9), &msg->type, sizeof(char)); + memcpy((data+10), msg->data, sizeof(char) * 32); + break; + default: + hydra_report(stderr, "unknown rmessage type\n"); + hydra_child_exit(0); + return NULL; + } + return data; +} + +struct rmessage *buffer2message(char *buffer) { + struct rmessage *msg; + msg = calloc(1, sizeof(struct rmessage)); + unsigned int sum = 0; + //TODO: check return + + //Start parsing... + msg->magic = buffer[0]; + buffer += sizeof(char); + msg->length = ntohl(*((unsigned int *)(buffer))); + buffer += sizeof(unsigned int); + msg->checksum = ntohl(*((unsigned int *)(buffer))); + buffer += sizeof(unsigned int); + msg->type = buffer[0]; + buffer += sizeof(char); + + //Verify known fields... + if(msg->magic != 0x01) { + hydra_report(stderr, "Bad magic\n"); + hydra_child_exit(0); + return NULL; + } + + switch(msg->type) { + case 0x1b: + if(msg->length != 0x21) { + hydra_report(stderr, "Bad length...%08x\n", msg->length); + hydra_child_exit(0); + return NULL; + } + memcpy(msg->data, buffer, 32); + break; + case 0x0a: + //Win! + case 0x0b: + //Lose! + break; + default: + hydra_report(stderr, "unknown rmessage type"); + hydra_child_exit(0); + return NULL; + } + return msg; +} + + +int start_radmin2(int s, char *ip, int port, unsigned char options, char *miscptr, FILE * fp) { +} + +void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname) { + int sock = -1; + int index; + int count; + int bytecount; + unsigned char *request; + struct rmessage *msg; + int myport = PORT_RADMIN2; + char buffer[42]; + unsigned char password[101]; + unsigned char rawkey[16]; + unsigned char pkey[33]; + char *IV = "FEDCBA9876543210A39D4A18F85B4A52"; + unsigned char encrypted[32]; + + //Initialization nonsense. + MD5_CTX md5c; + keyInstance key; + cipherInstance cipher; + + if(port != 0) { + myport = port; + } + + memset(buffer, 0x00, sizeof(buffer)); + memset(pkey, 0x00, 33); + memset(encrypted, 0x00, 32); + memset(password, 0x00, 100); + + //Phone the mother ship + hydra_register_socket(sp); + if( memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) { + return; + } + + // Get a password to work with. + strncpy(password, hydra_get_next_password(), 101); + MD5_Init(&md5c); + MD5_Update(&md5c, password, 100); + MD5_Final(rawkey, &md5c); + //Copy raw md5 data into ASCIIZ string + for(index = 0; index < 16; index++) { + count = sprintf((pkey+index*2), "%02x", rawkey[index]); + } + + /* Typical conversation goes as follows... + 0) connect to server + 1) request challenge + 2) receive 32 byte challenge response + 3) send 32 byte challenge solution + 4) receive 1 byte auth success/fail message + */ + // 0) Connect to the server + sock = hydra_connect_tcp(ip, myport); + if(sock < 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid()); + hydra_child_exit(1); + } + + // 1) request challenge (working) + msg = calloc(1, sizeof(struct rmessage)); + challenge_request(msg); + hydra_send(sock, message2buffer(msg), 10, 0); + free(msg); //We're done with challenge request messagee. + + //2) receive response (working) + index = 0; + while(index < 42) { //We're always expecting back a 42 byte buffer from a challenge request. + switch(hydra_data_ready(sock)) { + case -1: + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_child_exit(1); + break; + case 0: + //keep waiting... + break; + default: + bytecount = hydra_recv(sock, buffer+index, 42 - index); + if(bytecount < 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_child_exit(1); + } + index += bytecount; + } + } + + //3) Send challenge solution. + + //3.a) generate a new message from the buffer + msg = buffer2message(buffer); + + //3.b) encrypt data received using pkey & known IV + 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); + if(index != TRUE) { + hydra_report(stderr, "Error: Child with pid %d terminating, cipher init error(%08x)\n", (int)getpid(), index); + hydra_child_exit(1); + } + + index = blockEncrypt(&cipher, &key, msg->data, 32 * 8, encrypted); + if(index <= 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, encrypt error(%08x)\n", (int)getpid(), index); + hydra_child_exit(1); + } + + //3.c) half sum - this is the solution to the challenge. + for(index=0; index < 16; index++) { + *(encrypted+index) += *(encrypted+index+16); + } + memset((encrypted+16), 0x00, 16); + + //3.d) send half sum + challenge_response(msg, encrypted); + request = message2buffer(msg); + + hydra_send(sock, request, 42, 0); + //4) receive auth success/failure + index = 0; + while(index < 10) { //We're always expecting back a 42 byte buffer from a challenge request. + switch(hydra_data_ready(sock)) { + case -1: + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_child_exit(1); + break; + case 0: + //keep waiting... + break; + default: + bytecount = hydra_recv(sock, buffer+index, 10 - index); + if(bytecount < 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_child_exit(1); + } + index += bytecount; + } + } + msg = buffer2message(buffer); + if(msg->type == 0x0a) { + hydra_completed_pair_found(); + } + //5) Disconnect + hydra_disconnect(sock); +} + +int service_radmin2_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname) { + // called before the childrens are forked off, so this is the function + // which should be filled if initial connections and service setup has to be + // performed once only. + // + // fill if needed. + // + // return codes: + // 0 all OK + // -1 error, hydra will exit, so print a good error message here + + return 0; +} diff --git a/hydra.c b/hydra.c index 67f06fe..2061a31 100644 --- a/hydra.c +++ b/hydra.c @@ -57,6 +57,7 @@ extern void service_http_proxy_urlenum(char *ip, int sp, unsigned char options, extern void service_s7_300(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); extern void service_rtsp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); extern void service_rpcap(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); +extern void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); // ADD NEW SERVICES HERE @@ -147,13 +148,14 @@ extern int service_xmpp_init(char *ip, int sp, unsigned char options, char *misc extern int service_s7_300_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); extern int service_rtsp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); extern int service_rpcap_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); +extern int service_radmin2_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); // ADD NEW SERVICES HERE // ADD NEW SERVICES HERE char *SERVICES = - "adam6500 asterisk afp cisco cisco-enable cvs firebird ftp ftps http[s]-{head|get|post} http[s]-{get|post}-form http-proxy http-proxy-urlenum icq imap[s] irc ldap2[s] ldap3[-{cram|digest}md5][s] mssql mysql ncp nntp oracle oracle-listener oracle-sid pcanywhere pcnfs pop3[s] postgres rdp redis rexec rlogin rpcap rsh rtsp s7-300 sapr3 sip smb smtp[s] smtp-enum snmp socks5 ssh sshkey svn teamspeak telnet[s] vmauthd vnc xmpp"; + "adam6500 asterisk afp cisco cisco-enable cvs firebird ftp ftps http[s]-{head|get|post} http[s]-{get|post}-form http-proxy http-proxy-urlenum icq imap[s] irc ldap2[s] ldap3[-{cram|digest}md5][s] mssql mysql ncp nntp oracle oracle-listener oracle-sid pcanywhere pcnfs pop3[s] postgres radmin2 rdp redis rexec rlogin rpcap rsh rtsp s7-300 sapr3 sip smb smtp[s] smtp-enum snmp socks5 ssh sshkey svn teamspeak telnet[s] vmauthd vnc xmpp"; #define MAXBUF 520 #define MAXLINESIZE ( ( MAXBUF / 2 ) - 4 ) @@ -1263,6 +1265,8 @@ void hydra_service_init(int target_no) { x = service_rtsp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target); if (strcmp(hydra_options.service, "rpcap") == 0) x = service_rpcap_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target); + if (strcmp(hydra_options.service, "radmin2") == 0) + x = service_radmin2_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target); // ADD NEW SERVICES HERE @@ -1469,6 +1473,8 @@ int hydra_spawn_head(int head_no, int target_no) { service_rtsp(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[hydra_heads[head_no]->target_no]->target); if (strcmp(hydra_options.service, "rpcap") == 0) service_rpcap(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[hydra_heads[head_no]->target_no]->target); + if (strcmp(hydra_options.service, "radmin2") == 0) + service_radmin2(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[hydra_heads[head_no]->target_no]->target); // ADD NEW SERVICES HERE @@ -1569,6 +1575,7 @@ int hydra_lookup_port(char *service) { {"s7-300", PORT_S7_300, PORT_S7_300_SSL}, {"rtsp", PORT_RTSP, PORT_RTSP_SSL}, {"rpcap", PORT_RPCAP, PORT_RPCAP_SSL}, + {"radmin2", PORT_RADMIN2, PORT_RADMIN2}, // ADD NEW SERVICES HERE - add new port numbers to hydra.h {"", PORT_NOPORT, PORT_NOPORT} }; @@ -3267,6 +3274,8 @@ int main(int argc, char *argv[]) { // hydra_options.conwait = conwait = 1; i = 1; } + if (strcmp(hydra_options.service, "radmin2") == 0) + i = 1; // ADD NEW SERVICES HERE diff --git a/hydra.h b/hydra.h index 54373d4..f580e4b 100644 --- a/hydra.h +++ b/hydra.h @@ -136,6 +136,7 @@ #define PORT_RTSP_SSL 554 #define PORT_RPCAP 2002 #define PORT_RPCAP_SSL 2002 +#define PORT_RADMIN2 4899 #define False 0 #define True 1 diff --git a/twofish.c b/twofish.c new file mode 100644 index 0000000..841eb30 --- /dev/null +++ b/twofish.c @@ -0,0 +1,704 @@ +/*************************************************************************** + 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= '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;ikey32[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;isubKeys[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;ikey32[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;iIV)[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;nIV,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;nmode == MODE_CBC) + DebugDump(cipher->iv32,"",IV_ROUND,0,0,0,0); +#endif + for (i=0;isubKeys[INPUT_WHITEN+i]; + if (cipher->mode == MODE_CBC) + x[i] ^= Bswap(cipher->iv32[i]); + } + + DebugDump(x,"",0,0,0,0,0); + for (r=0;rsboxKeys,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;isubKeys[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;nIV,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;nsubKeys[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;isubKeys[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 diff --git a/twofish/aes.h b/twofish/aes.h new file mode 100644 index 0000000..570a95d --- /dev/null +++ b/twofish/aes.h @@ -0,0 +1,268 @@ +/* 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 +#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 +#include +#include +#include + +#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;ikeyLen+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 %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;isubKeys[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 diff --git a/twofish/platform.h b/twofish/platform.h new file mode 100644 index 0000000..400ea28 --- /dev/null +++ b/twofish/platform.h @@ -0,0 +1,75 @@ +/*************************************************************************** + 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 /* 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 /* 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 */ + diff --git a/twofish/table.h b/twofish/table.h new file mode 100644 index 0000000..5c3c590 --- /dev/null +++ b/twofish/table.h @@ -0,0 +1,228 @@ +/*************************************************************************** + 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 + } + }; From 44180b2c98aeb9e4dc214d874f58ce9ac43d843d Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sat, 12 Nov 2016 18:23:43 +0000 Subject: [PATCH 02/15] Adding documentation. Fixing memory leaks. --- hydra-radmin2.c | 62 +++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index 662a173..e84d47e 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -13,41 +13,31 @@ 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 struct rmessage{ - char magic; //No touching! + char magic; //Indicates version, probably? unsigned int length; //Total message size of data. unsigned int checksum; //Checksum from type to end of data. char type; //Command type, table below. unsigned char data[32]; //data to be sent. }; -void print_message(struct rmessage *msg) { - return; - int dlen = 0; - hydra_report(stderr, - "m:\t%02x\n" - "l:\t%08x\n" - "c:\t%08x\n" - "t:\t%02x\n", - msg->magic, - msg->length, - msg->checksum, - msg->type); - - hydra_report(stderr, "d:\t"); - for(dlen = 0; dlen < msg->length - 1; dlen++) { //-1 because of type. - hydra_report(stderr, "%02x", msg->data[dlen]); - } - hydra_report(stderr, "\n"); -} - +/* +* Usage: sum = checksum(message); +* Function: Returns a 4 byte little endian sum of the messages typecode+data. This data is zero padded for alignment. +* Example message (big endian): +* [01][00000021][0f43d461] sum([1b6e779a f37189bb c1b22982 c80d1f4d 66678ff9 4b10f0ce eabff6e8 f4fb8338 3b] + zeropad(3)]) +* Sum: is 0f43d461 (big endian) +*/ unsigned int checksum(struct rmessage *msg) { int blen; unsigned char *stream; unsigned int sum; blen = msg->length; //Get the real length. blen += (4 - (blen % 4)); + + //Allocate a worksapce. stream = calloc(blen, sizeof(unsigned char)); memcpy(stream, &msg->type, sizeof(unsigned char)); memcpy(stream+1, msg->data, blen-1); @@ -58,28 +48,40 @@ unsigned int checksum(struct rmessage *msg) { } sum += *(unsigned int *)stream; + //Free the workspace. + free(stream); + return sum; } - +/* +* Usage: challenge_request(message); +* Function: Modifies message to reflect a request for a challenge. Updates the checksum as appropriate. +*/ void challenge_request(struct rmessage *msg) { msg->magic = 0x01; msg->length = 0x01; msg->type = 0x1b; msg->checksum = checksum(msg); - print_message(msg); } +/* +* Usage: challenge_request(message); +* Function: Modifies message to reflect a response to a challenge. Updates the checksum as appropriate. +*/ void challenge_response(struct rmessage *msg, unsigned char *solution) { msg->magic = 0x01; msg->length = 0x21; msg->type = 0x09; memcpy(msg->data, solution, 0x20); msg->checksum = checksum(msg); - print_message(msg); } - +/* +* Usage: buffer = message2buffer(message); send(buffer, message->length + 10); free(buffer) +* Function: Allocates a buffer for transmission and fills the buffer with message data such that it is ready to transmit. +*/ +//TODO: conver to a sendMessage() function? unsigned char *message2buffer(struct rmessage *msg) { unsigned char *data; if(msg == NULL) { @@ -223,8 +225,10 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL // 1) request challenge (working) msg = calloc(1, sizeof(struct rmessage)); challenge_request(msg); - hydra_send(sock, message2buffer(msg), 10, 0); - free(msg); //We're done with challenge request messagee. + request = message2buffer(msg); + hydra_send(sock, request, 10, 0); + free(msg); + free(request); //2) receive response (working) index = 0; @@ -280,8 +284,10 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL //3.d) send half sum challenge_response(msg, encrypted); request = message2buffer(msg); - hydra_send(sock, request, 42, 0); + free(msg); + free(request); + //4) receive auth success/failure index = 0; while(index < 10) { //We're always expecting back a 42 byte buffer from a challenge request. From 756d8a631fae8ee472e193080af7960dd2174f41 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sat, 12 Nov 2016 18:37:10 +0000 Subject: [PATCH 03/15] Fixing warnings --- hydra-radmin2.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index e84d47e..aa870db 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -82,8 +82,8 @@ void challenge_response(struct rmessage *msg, unsigned char *solution) { * Function: Allocates a buffer for transmission and fills the buffer with message data such that it is ready to transmit. */ //TODO: conver to a sendMessage() function? -unsigned char *message2buffer(struct rmessage *msg) { - unsigned char *data; +char *message2buffer(struct rmessage *msg) { + char *data; if(msg == NULL) { hydra_report(stderr, "rmessage is null\n"); hydra_child_exit(0); @@ -117,7 +117,6 @@ unsigned char *message2buffer(struct rmessage *msg) { struct rmessage *buffer2message(char *buffer) { struct rmessage *msg; msg = calloc(1, sizeof(struct rmessage)); - unsigned int sum = 0; //TODO: check return //Start parsing... @@ -161,20 +160,20 @@ struct rmessage *buffer2message(char *buffer) { int start_radmin2(int s, char *ip, int port, unsigned char options, char *miscptr, FILE * fp) { + return 0; } void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname) { int sock = -1; int index; - int count; int bytecount; - unsigned char *request; + char *request; struct rmessage *msg; int myport = PORT_RADMIN2; char buffer[42]; - unsigned char password[101]; + char password[101]; unsigned char rawkey[16]; - unsigned char pkey[33]; + char pkey[33]; char *IV = "FEDCBA9876543210A39D4A18F85B4A52"; unsigned char encrypted[32]; From 3f73d1f16307d57f6fafe9715227d950e9cc8983 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sat, 12 Nov 2016 18:38:42 +0000 Subject: [PATCH 04/15] Oops missed a reference. --- hydra-radmin2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index aa870db..2dcaee0 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -204,7 +204,7 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL MD5_Final(rawkey, &md5c); //Copy raw md5 data into ASCIIZ string for(index = 0; index < 16; index++) { - count = sprintf((pkey+index*2), "%02x", rawkey[index]); + sprintf((pkey+index*2), "%02x", rawkey[index]); } /* Typical conversation goes as follows... From 2713a0d8168a1a268f432f44bef162d765d24a38 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sat, 12 Nov 2016 18:47:21 +0000 Subject: [PATCH 05/15] Including memory checks --- hydra-radmin2.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index 2dcaee0..74dd511 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -92,14 +92,22 @@ char *message2buffer(struct rmessage *msg) { switch(msg->type) { case 0x1b: //Challenge request - data = calloc (10, sizeof(unsigned char)); //TODO: check return + data = calloc (10, sizeof(unsigned char)); + if(data == NULL) { + hydra_report(stderr, "calloc failure\n"); + hydra_child_exit(0); + } memcpy(data, &msg->magic, sizeof(char)); *((int *)(data+1)) = htonl(msg->length); *((int *)(data+5)) = htonl(msg->checksum); memcpy((data+9), &msg->type, sizeof(char)); break; case 0x09: - data = calloc (42, sizeof(unsigned char)); //TODO: check return + data = calloc (42, sizeof(unsigned char)); + if(data == NULL) { + hydra_report(stderr, "calloc failure\n"); + hydra_child_exit(0); + } memcpy(data, &msg->magic, sizeof(char)); *((int *)(data+1)) = htonl(msg->length); *((int *)(data+5)) = htonl(msg->checksum); @@ -117,7 +125,10 @@ char *message2buffer(struct rmessage *msg) { struct rmessage *buffer2message(char *buffer) { struct rmessage *msg; msg = calloc(1, sizeof(struct rmessage)); - //TODO: check return + if(msg == NULL) { + hydra_report(stderr, "calloc failure\n"); + hydra_child_exit(0); + } //Start parsing... msg->magic = buffer[0]; From 0c2e02135d40f1922c7860c73d4f8d8759d3fb11 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sun, 13 Nov 2016 20:37:35 +0000 Subject: [PATCH 06/15] Formatting --- hydra-radmin2.c | 250 +++++++++++++++++++++++++----------------------- 1 file changed, 130 insertions(+), 120 deletions(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index 74dd511..c816b5c 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -15,7 +15,7 @@ extern int blockDecrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *inp //RAdmin 2.x -struct rmessage{ +struct rmessage { char magic; //Indicates version, probably? unsigned int length; //Total message size of data. unsigned int checksum; //Checksum from type to end of data. @@ -24,12 +24,12 @@ struct rmessage{ }; /* -* Usage: sum = checksum(message); -* Function: Returns a 4 byte little endian sum of the messages typecode+data. This data is zero padded for alignment. -* Example message (big endian): -* [01][00000021][0f43d461] sum([1b6e779a f37189bb c1b22982 c80d1f4d 66678ff9 4b10f0ce eabff6e8 f4fb8338 3b] + zeropad(3)]) -* Sum: is 0f43d461 (big endian) -*/ + * Usage: sum = checksum(message); + * Function: Returns a 4 byte little endian sum of the messages typecode+data. This data is zero padded for alignment. + * Example message (big endian): + * [01][00000021][0f43d461] sum([1b6e779a f37189bb c1b22982 c80d1f4d 66678ff9 4b10f0ce eabff6e8 f4fb8338 3b] + zeropad(3)]) + * Sum: is 0f43d461 (big endian) + */ unsigned int checksum(struct rmessage *msg) { int blen; unsigned char *stream; @@ -55,10 +55,10 @@ unsigned int checksum(struct rmessage *msg) { } /* -* Usage: challenge_request(message); -* Function: Modifies message to reflect a request for a challenge. Updates the checksum as appropriate. -*/ -void challenge_request(struct rmessage *msg) { + * Usage: challenge_request(message); + * Function: Modifies message to reflect a request for a challenge. Updates the checksum as appropriate. + */ +void challenge_request(struct rmessage *msg) { msg->magic = 0x01; msg->length = 0x01; msg->type = 0x1b; @@ -66,9 +66,9 @@ void challenge_request(struct rmessage *msg) { } /* -* Usage: challenge_request(message); -* Function: Modifies message to reflect a response to a challenge. Updates the checksum as appropriate. -*/ + * Usage: challenge_request(message); + * Function: Modifies message to reflect a response to a challenge. Updates the checksum as appropriate. + */ void challenge_response(struct rmessage *msg, unsigned char *solution) { msg->magic = 0x01; msg->length = 0x21; @@ -78,9 +78,9 @@ void challenge_response(struct rmessage *msg, unsigned char *solution) { } /* -* Usage: buffer = message2buffer(message); send(buffer, message->length + 10); free(buffer) -* Function: Allocates a buffer for transmission and fills the buffer with message data such that it is ready to transmit. -*/ + * Usage: buffer = message2buffer(message); send(buffer, message->length + 10); free(buffer) + * Function: Allocates a buffer for transmission and fills the buffer with message data such that it is ready to transmit. + */ //TODO: conver to a sendMessage() function? char *message2buffer(struct rmessage *msg) { char *data; @@ -207,123 +207,133 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL if( memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) { return; } - - // Get a password to work with. - strncpy(password, hydra_get_next_password(), 101); - MD5_Init(&md5c); - MD5_Update(&md5c, password, 100); - MD5_Final(rawkey, &md5c); - //Copy raw md5 data into ASCIIZ string - for(index = 0; index < 16; index++) { - sprintf((pkey+index*2), "%02x", rawkey[index]); - } - /* Typical conversation goes as follows... - 0) connect to server - 1) request challenge - 2) receive 32 byte challenge response - 3) send 32 byte challenge solution - 4) receive 1 byte auth success/fail message - */ - // 0) Connect to the server - sock = hydra_connect_tcp(ip, myport); - if(sock < 0) { - hydra_report(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid()); - hydra_child_exit(1); - } + while(1) { + // Get a password to work with. + strncpy(password, hydra_get_next_password(), 101); + MD5_Init(&md5c); + MD5_Update(&md5c, password, 100); + MD5_Final(rawkey, &md5c); + //Copy raw md5 data into ASCIIZ string + for(index = 0; index < 16; index++) { + sprintf((pkey+index*2), "%02x", rawkey[index]); + } - // 1) request challenge (working) - msg = calloc(1, sizeof(struct rmessage)); - challenge_request(msg); - request = message2buffer(msg); - hydra_send(sock, request, 10, 0); - free(msg); - free(request); + /* Typical conversation goes as follows... + 0) connect to server + 1) request challenge + 2) receive 32 byte challenge response + 3) send 32 byte challenge solution + 4) receive 1 byte auth success/fail message + */ + // 0) Connect to the server + sock = hydra_connect_tcp(ip, myport); + if(sock < 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid()); + hydra_child_exit(1); + } - //2) receive response (working) - index = 0; - while(index < 42) { //We're always expecting back a 42 byte buffer from a challenge request. - switch(hydra_data_ready(sock)) { - case -1: - hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); - hydra_child_exit(1); - break; - case 0: - //keep waiting... - break; - default: - bytecount = hydra_recv(sock, buffer+index, 42 - index); - if(bytecount < 0) { + // 1) request challenge (working) + msg = calloc(1, sizeof(struct rmessage)); + challenge_request(msg); + request = message2buffer(msg); + hydra_send(sock, request, 10, 0); + free(msg); + free(request); + + //2) receive response (working) + index = 0; + while(index < 42) { //We're always expecting back a 42 byte buffer from a challenge request. + switch(hydra_data_ready(sock)) { + case -1: hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); hydra_child_exit(1); - } - index += bytecount; + break; + case 0: + //keep waiting... + break; + default: + bytecount = hydra_recv(sock, buffer+index, 42 - index); + if(bytecount < 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_child_exit(1); + } + index += bytecount; + } } - } - - //3) Send challenge solution. - //3.a) generate a new message from the buffer - msg = buffer2message(buffer); + //3) Send challenge solution. - //3.b) encrypt data received using pkey & known IV - 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); - } + //3.a) generate a new message from the buffer + msg = buffer2message(buffer); - index = cipherInit(&cipher, MODE_CBC, IV); - if(index != TRUE) { - hydra_report(stderr, "Error: Child with pid %d terminating, cipher init error(%08x)\n", (int)getpid(), index); - hydra_child_exit(1); - } + //3.b) encrypt data received using pkey & known IV + 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 = blockEncrypt(&cipher, &key, msg->data, 32 * 8, encrypted); - if(index <= 0) { - hydra_report(stderr, "Error: Child with pid %d terminating, encrypt error(%08x)\n", (int)getpid(), index); - hydra_child_exit(1); - } - - //3.c) half sum - this is the solution to the challenge. - for(index=0; index < 16; index++) { - *(encrypted+index) += *(encrypted+index+16); - } - memset((encrypted+16), 0x00, 16); + index = cipherInit(&cipher, MODE_CBC, IV); + if(index != TRUE) { + hydra_report(stderr, "Error: Child with pid %d terminating, cipher init error(%08x)\n", (int)getpid(), index); + hydra_child_exit(1); + } - //3.d) send half sum - challenge_response(msg, encrypted); - request = message2buffer(msg); - hydra_send(sock, request, 42, 0); - free(msg); - free(request); + index = blockEncrypt(&cipher, &key, msg->data, 32 * 8, encrypted); + if(index <= 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, encrypt error(%08x)\n", (int)getpid(), index); + hydra_child_exit(1); + } - //4) receive auth success/failure - index = 0; - while(index < 10) { //We're always expecting back a 42 byte buffer from a challenge request. - switch(hydra_data_ready(sock)) { - case -1: - hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); - hydra_child_exit(1); - break; - case 0: - //keep waiting... - break; - default: - bytecount = hydra_recv(sock, buffer+index, 10 - index); - if(bytecount < 0) { + //3.c) half sum - this is the solution to the challenge. + for(index=0; index < 16; index++) { + *(encrypted+index) += *(encrypted+index+16); + } + memset((encrypted+16), 0x00, 16); + + //3.d) send half sum + challenge_response(msg, encrypted); + request = message2buffer(msg); + hydra_send(sock, request, 42, 0); + free(msg); + free(request); + + //4) receive auth success/failure + index = 0; + while(index < 10) { //We're always expecting back a 42 byte buffer from a challenge request. + switch(hydra_data_ready(sock)) { + case -1: hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); hydra_child_exit(1); - } - index += bytecount; + break; + case 0: + //keep waiting... + break; + default: + bytecount = hydra_recv(sock, buffer+index, 10 - index); + if(bytecount < 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_child_exit(1); + } + index += bytecount; + } } + msg = buffer2message(buffer); + switch(msg->type) { + case 0x0a: + hydra_completed_pair_found(); + break; + case 0x0b: + hydra_completed_pair(); + hydra_disconnect(sock); + break; + default: + hydra_report(stderr, "Error: Child with pid %d terminating, protocol error\n", (int)getpid()); + hydra_child_exit(2); + } + } - msg = buffer2message(buffer); - if(msg->type == 0x0a) { - hydra_completed_pair_found(); - } - //5) Disconnect - hydra_disconnect(sock); } int service_radmin2_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname) { @@ -334,8 +344,8 @@ int service_radmin2_init(char *ip, int sp, unsigned char options, char *miscptr, // fill if needed. // // return codes: - // 0 all OK - // -1 error, hydra will exit, so print a good error message here + // 0 all OK + // -1 error, hydra will exit, so print a good error message here return 0; } From 43e3040062223f7202b03179b96a7228b4b63ea2 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sun, 25 Dec 2016 03:24:06 +0000 Subject: [PATCH 07/15] Basic libgcrypt usage... no idea if it works, but it has to be better than nothing right? --- Makefile.am | 6 +- hydra-radmin2.c | 65 +++-- twofish.c | 704 --------------------------------------------- twofish/aes.h | 268 ----------------- twofish/debug.h | 77 ----- twofish/platform.h | 75 ----- twofish/table.h | 228 --------------- 7 files changed, 43 insertions(+), 1380 deletions(-) delete mode 100644 twofish.c delete mode 100644 twofish/aes.h delete mode 100644 twofish/debug.h delete mode 100644 twofish/platform.h delete mode 100644 twofish/table.h diff --git a/Makefile.am b/Makefile.am index 43fa77a..843bac6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ # OPTS=-I. -O3 # -Wall -g -pedantic -LIBS=-lm +LIBS=-lm -lgcrypt BINDIR = /bin MANDIR ?= /man/man1/ 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-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 \ - hydra-radmin2.c twofish.c + hydra-radmin2.c 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-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-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 \ - hydra-radmin2.o twofish.o + hydra-radmin2.o BINS = hydra pw-inspector EXTRA_DIST = README README.arm README.palm CHANGES TODO INSTALL LICENSE \ diff --git a/hydra-radmin2.c b/hydra-radmin2.c index c816b5c..c02f23c 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -2,17 +2,10 @@ #include #include #include +#include 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 struct rmessage { @@ -185,18 +178,20 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL char password[101]; unsigned char rawkey[16]; 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]; + gcry_error_t err; + gcry_cipher_hd_t cipher; //Initialization nonsense. MD5_CTX md5c; - keyInstance key; - cipherInstance cipher; if(port != 0) { myport = port; } + gcry_check_version(NULL); + memset(buffer, 0x00, sizeof(buffer)); memset(pkey, 0x00, 33); 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.a) generate a new message from the buffer msg = buffer2message(buffer); //3.b) encrypt data received using pkey & known IV - 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); + err= gcry_cipher_open(&cipher, GCRY_CIPHER_TWOFISH128, GCRY_CIPHER_MODE_CBC, 0); + if(err) { + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_open error (%08x)\n", (int)getpid(), index); 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); - if(index != TRUE) { - hydra_report(stderr, "Error: Child with pid %d terminating, cipher init error(%08x)\n", (int)getpid(), index); - hydra_child_exit(1); - } +// index = cipherInit(&cipher, MODE_CBC, IV); +// if(index != TRUE) { +// hydra_report(stderr, "Error: Child with pid %d terminating, cipher init error(%08x)\n", (int)getpid(), index); +// hydra_child_exit(1); +// } - index = blockEncrypt(&cipher, &key, msg->data, 32 * 8, encrypted); - if(index <= 0) { - hydra_report(stderr, "Error: Child with pid %d terminating, encrypt error(%08x)\n", (int)getpid(), index); - hydra_child_exit(1); - } +// index = blockEncrypt(&cipher, &key, msg->data, 32 * 8, encrypted); +// if(index <= 0) { +// hydra_report(stderr, "Error: Child with pid %d terminating, encrypt error(%08x)\n", (int)getpid(), index); +// hydra_child_exit(1); +// } //3.c) half sum - this is the solution to the challenge. for(index=0; index < 16; index++) { diff --git a/twofish.c b/twofish.c deleted file mode 100644 index 841eb30..0000000 --- a/twofish.c +++ /dev/null @@ -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= '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;ikey32[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;isubKeys[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;ikey32[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;iIV)[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;nIV,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;nmode == MODE_CBC) - DebugDump(cipher->iv32,"",IV_ROUND,0,0,0,0); -#endif - for (i=0;isubKeys[INPUT_WHITEN+i]; - if (cipher->mode == MODE_CBC) - x[i] ^= Bswap(cipher->iv32[i]); - } - - DebugDump(x,"",0,0,0,0,0); - for (r=0;rsboxKeys,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;isubKeys[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;nIV,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;nsubKeys[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;isubKeys[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 diff --git a/twofish/aes.h b/twofish/aes.h deleted file mode 100644 index 570a95d..0000000 --- a/twofish/aes.h +++ /dev/null @@ -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 -#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 -#include -#include -#include - -#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;ikeyLen+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 %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;isubKeys[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 diff --git a/twofish/platform.h b/twofish/platform.h deleted file mode 100644 index 400ea28..0000000 --- a/twofish/platform.h +++ /dev/null @@ -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 /* 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 /* 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 */ - diff --git a/twofish/table.h b/twofish/table.h deleted file mode 100644 index 5c3c590..0000000 --- a/twofish/table.h +++ /dev/null @@ -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 - } - }; From 050892bb73b5a0bb12ba58ea67ee9c0b24c513c5 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Tue, 27 Dec 2016 16:32:27 +0000 Subject: [PATCH 08/15] libgcrypt doens't appear to be working either. No errors so crypto is funny? dunno. --- hydra-radmin2.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index c02f23c..9ae609f 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -264,25 +264,27 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL //3.b) encrypt data received using pkey & known IV err= gcry_cipher_open(&cipher, GCRY_CIPHER_TWOFISH128, GCRY_CIPHER_MODE_CBC, 0); if(err) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_open error (%08x)\n", (int)getpid(), index); + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_open error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); hydra_child_exit(1); } - err = gcry_cipher_setkey(cipher, pkey, 128); + err = gcry_cipher_setkey(cipher, pkey, 16); if(err) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setkey error (%08x)\n", (int)getpid(), index); + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setkey error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); hydra_child_exit(1); } - err = gcry_cipher_setiv(cipher, IV, 128); + err = gcry_cipher_setiv(cipher, IV, 16); if(err) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setiv error (%08x)\n", (int)getpid(), index); + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setiv error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); 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_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_encrypt error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); hydra_child_exit(1); } gcry_cipher_close(cipher); + hydra_report(stderr, "Trying another one...\n"); + // 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); From ff7343e8728f0b7c92de24dc0f36bac5806752b4 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Tue, 27 Dec 2016 17:14:17 +0000 Subject: [PATCH 09/15] Yay gcrypt is working!!! --- hydra-radmin2.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index 9ae609f..bc2d428 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -1,7 +1,6 @@ #include "hydra-mod.h" #include #include -#include #include extern char *HYDRA_EXIT; @@ -177,14 +176,11 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL char buffer[42]; char password[101]; unsigned char rawkey[16]; - char pkey[33]; - char *IV = "\xFE\xDC\xBA\x98\x76\x54\x32\x10\xA3\x9D\x4A\x18\xF8\x5B\x4A\x52"; + unsigned char *IV = "\xFE\xDC\xBA\x98\x76\x54\x32\x10\xA3\x9D\x4A\x18\xF8\x5B\x4A\x52"; unsigned char encrypted[32]; gcry_error_t err; gcry_cipher_hd_t cipher; - - //Initialization nonsense. - MD5_CTX md5c; + gcry_md_hd_t md; if(port != 0) { myport = port; @@ -193,7 +189,6 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL gcry_check_version(NULL); memset(buffer, 0x00, sizeof(buffer)); - memset(pkey, 0x00, 33); memset(encrypted, 0x00, 32); memset(password, 0x00, 100); @@ -206,13 +201,19 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL while(1) { // Get a password to work with. strncpy(password, hydra_get_next_password(), 101); - MD5_Init(&md5c); - MD5_Update(&md5c, password, 100); - MD5_Final(rawkey, &md5c); - //Copy raw md5 data into ASCIIZ string - for(index = 0; index < 16; index++) { - sprintf((pkey+index*2), "%02x", rawkey[index]); + + err = gcry_md_open(&md, GCRY_MD_MD5, 0); + if(err) { + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_md_open error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); + hydra_child_exit(1); } + gcry_md_write(md, password, 100); + if(gcry_md_read(md, 0) == NULL) { + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_md_read error (%08x)\n", (int)getpid(), index); + hydra_child_exit(1); + } + memcpy(rawkey, gcry_md_read(md, 0), 16); + gcry_md_close(md); /* Typical conversation goes as follows... 0) connect to server @@ -267,22 +268,27 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_open error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); hydra_child_exit(1); } - err = gcry_cipher_setkey(cipher, pkey, 16); - if(err) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setkey error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); - hydra_child_exit(1); - } + err = gcry_cipher_setiv(cipher, IV, 16); if(err) { hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setiv error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); hydra_child_exit(1); - } + } + + err = gcry_cipher_setkey(cipher, rawkey, 16); + if(err) { + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setkey error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); + 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%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); hydra_child_exit(1); } + gcry_cipher_close(cipher); + hydra_report(stderr, "Trying another one...\n"); // index = makeKey(&key, DIR_ENCRYPT, 128, pkey); From 249c8f973bfd30e9609f2aa08ccc54cfea026c79 Mon Sep 17 00:00:00 2001 From: catatonic Date: Tue, 27 Dec 2016 10:20:59 -0700 Subject: [PATCH 10/15] Removing diagnostics --- hydra-radmin2.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index bc2d428..8a00d71 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -289,26 +289,6 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL gcry_cipher_close(cipher); - hydra_report(stderr, "Trying another one...\n"); - -// 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); -// if(index != TRUE) { -// hydra_report(stderr, "Error: Child with pid %d terminating, cipher init error(%08x)\n", (int)getpid(), index); -// hydra_child_exit(1); -// } - -// index = blockEncrypt(&cipher, &key, msg->data, 32 * 8, encrypted); -// if(index <= 0) { -// hydra_report(stderr, "Error: Child with pid %d terminating, encrypt error(%08x)\n", (int)getpid(), index); -// hydra_child_exit(1); -// } - //3.c) half sum - this is the solution to the challenge. for(index=0; index < 16; index++) { *(encrypted+index) += *(encrypted+index+16); From 5d88976bc621040e7d96eb0fe368af7f4875323f Mon Sep 17 00:00:00 2001 From: catatonic Date: Tue, 27 Dec 2016 15:01:15 -0700 Subject: [PATCH 11/15] Fixing issue were we are not correctly grabbing the next password "pair" --- hydra-radmin2.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index 8a00d71..dce8f05 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -189,8 +189,6 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL gcry_check_version(NULL); memset(buffer, 0x00, sizeof(buffer)); - memset(encrypted, 0x00, 32); - memset(password, 0x00, 100); //Phone the mother ship hydra_register_socket(sp); @@ -199,21 +197,6 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL } while(1) { - // Get a password to work with. - strncpy(password, hydra_get_next_password(), 101); - - err = gcry_md_open(&md, GCRY_MD_MD5, 0); - if(err) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_md_open error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); - hydra_child_exit(1); - } - gcry_md_write(md, password, 100); - if(gcry_md_read(md, 0) == NULL) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_md_read error (%08x)\n", (int)getpid(), index); - hydra_child_exit(1); - } - memcpy(rawkey, gcry_md_read(md, 0), 16); - gcry_md_close(md); /* Typical conversation goes as follows... 0) connect to server @@ -259,6 +242,28 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL } //3) Send challenge solution. + + // Get a password to work with. + memset(password, 0x00, sizeof(password)); + memset(encrypted, 0x00, sizeof(encrypted)); + hydra_get_next_pair(); + strncpy(password, hydra_get_next_password(), sizeof(password)-1); + hydra_report(stderr, "Trying: %s\n", password); + //MD5 the password to generate the password key, this is used with twofish below. + err = gcry_md_open(&md, GCRY_MD_MD5, 0); + if(err) { + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_md_open error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); + hydra_child_exit(1); + } + gcry_md_reset(md); + gcry_md_write(md, password, 100); + if(gcry_md_read(md, 0) == NULL) { + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_md_read error (%08x)\n", (int)getpid(), index); + hydra_child_exit(1); + } + memcpy(rawkey, gcry_md_read(md, 0), 16); + gcry_md_close(md); + //3.a) generate a new message from the buffer msg = buffer2message(buffer); @@ -335,7 +340,6 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL hydra_report(stderr, "Error: Child with pid %d terminating, protocol error\n", (int)getpid()); hydra_child_exit(2); } - } } From c5d98dc35298e1f8cf4c06606e36337fa738100a Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Tue, 27 Dec 2016 22:06:41 +0000 Subject: [PATCH 12/15] Removing diagnostics --- hydra-radmin2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index dce8f05..9985b52 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -248,7 +248,7 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL memset(encrypted, 0x00, sizeof(encrypted)); hydra_get_next_pair(); strncpy(password, hydra_get_next_password(), sizeof(password)-1); - hydra_report(stderr, "Trying: %s\n", password); + //MD5 the password to generate the password key, this is used with twofish below. err = gcry_md_open(&md, GCRY_MD_MD5, 0); if(err) { From 1503c8a381236b3f99ad57ed17c2c4dce501502c Mon Sep 17 00:00:00 2001 From: catatonic Date: Fri, 7 Jul 2017 19:34:52 +0000 Subject: [PATCH 13/15] Checking for gcrypt support & disabling radmin2 when it is unavailable. --- Makefile.am | 2 +- configure | 24 ++++++++++++++++++++++++ hydra-radmin2.c | 4 ++++ hydra.c | 12 ++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 843bac6..6e7b287 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ # OPTS=-I. -O3 # -Wall -g -pedantic -LIBS=-lm -lgcrypt +LIBS=-lm BINDIR = /bin MANDIR ?= /man/man1/ DATADIR ?= /etc diff --git a/configure b/configure index ef77d8f..766fd98 100755 --- a/configure +++ b/configure @@ -36,6 +36,7 @@ CURSES_IPATH="" CRYPTO_PATH="" IDN_PATH="" IDN_IPATH="" +GCRYPT_PATH="" PR29_IPATH="" PCRE_PATH="" PCRE_IPATH="" @@ -242,6 +243,22 @@ if [ "$SSL_IPATH" = "/usr/include" ]; then SSL_IPATH="" fi +echo "Checking for gcrypt (libgcrypt.so) ..." +for i in $LIBDIRS ; do + if [ "X" = "X$GCRYPT_PATH" ]; then + if [ -f "$i/libgcrypt.so" -o -f "$i/libgcrypt.dylib" -o -f "$i/libgcrypt.a" -o -f "$i/libgcrypt.dll.a" -o -f "$i/libgcrypt.la" ]; then + HAVE_GCRYPT="y" + fi + fi +done +if [ -n "$HAVE_GCRYPT" ]; then + echo " ... found" +else + echo " ... gcrypt not found, gcrypt support disabled" +fi + + + echo "Checking for idn (libidn.so) ..." for i in $LIBDIRS ; do if [ "X" = "X$IDN_PATH" ]; then @@ -1069,6 +1086,10 @@ fi if [ -n "$HAVE_ZLIB" ]; then XDEFINES="$XDEFINES -DHAVE_ZLIB" fi +if [ -n "$HAVE_GCRYPT" ]; then + XDEFINES="$XDEFINES -DHAVE_GCRYPT" +fi + OLDPATH="" for i in $SSL_PATH $FIREBIRD_PATH $WORACLE_LIB_PATH $PCRE_PATH $IDN_PATH $CRYPTO_PATH $SSH_PATH $NSL_PATH $SOCKET_PATH $RESOLV_PATH $SAPR3_PATH $POSTGRES_PATH $SVN_PATH $NCP_PATH $CURSES_PATH $ORACLE_PATH $AFP_PATH $MYSQL_PATH; do @@ -1124,6 +1145,9 @@ fi if [ -n "$ORACLE_IPATH" ]; then XIPATHS="$XIPATHS -I$ORACLE_IPATH" fi +if [ -n "$HAVE_GCRYPT" ]; then + XLIBS="$XLIBS -lgcrypt" +fi if [ -n "$HAVE_ZLIB" ]; then XLIBS="$XLIBS -lz" fi diff --git a/hydra-radmin2.c b/hydra-radmin2.c index 9985b52..7c09b3b 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -1,7 +1,9 @@ #include "hydra-mod.h" #include #include +#ifdef HAVE_GCRYPT #include +#endif extern char *HYDRA_EXIT; @@ -167,6 +169,7 @@ int start_radmin2(int s, char *ip, int port, unsigned char options, char *miscpt } void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname) { +#ifdef HAVE_GCRYPT int sock = -1; int index; int bytecount; @@ -341,6 +344,7 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL hydra_child_exit(2); } } +#endif } int service_radmin2_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname) { diff --git a/hydra.c b/hydra.c index 2061a31..2c90c5a 100644 --- a/hydra.c +++ b/hydra.c @@ -57,7 +57,9 @@ extern void service_http_proxy_urlenum(char *ip, int sp, unsigned char options, extern void service_s7_300(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); extern void service_rtsp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); extern void service_rpcap(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); +#ifdef HAVE_GCRYPT extern void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); +#endif // ADD NEW SERVICES HERE @@ -148,7 +150,9 @@ extern int service_xmpp_init(char *ip, int sp, unsigned char options, char *misc extern int service_s7_300_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); extern int service_rtsp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); extern int service_rpcap_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); +#ifdef HAVE_GCRYPT extern int service_radmin2_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname); +#endif // ADD NEW SERVICES HERE @@ -1265,8 +1269,10 @@ void hydra_service_init(int target_no) { x = service_rtsp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target); if (strcmp(hydra_options.service, "rpcap") == 0) x = service_rpcap_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target); +#ifdef HAVE_GCRYPT if (strcmp(hydra_options.service, "radmin2") == 0) x = service_radmin2_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[target_no]->target); +#endif // ADD NEW SERVICES HERE @@ -1473,8 +1479,10 @@ int hydra_spawn_head(int head_no, int target_no) { service_rtsp(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[hydra_heads[head_no]->target_no]->target); if (strcmp(hydra_options.service, "rpcap") == 0) service_rpcap(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[hydra_heads[head_no]->target_no]->target); +#ifdef HAVE_GCRYPT if (strcmp(hydra_options.service, "radmin2") == 0) service_radmin2(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port, hydra_targets[hydra_heads[head_no]->target_no]->target); +#endif // ADD NEW SERVICES HERE @@ -3275,7 +3283,11 @@ int main(int argc, char *argv[]) { i = 1; } if (strcmp(hydra_options.service, "radmin2") == 0) +#ifdef HAVE_GCRYPT i = 1; +#else + bail("Compiled without gcrypt support"); +#endif // ADD NEW SERVICES HERE From 444a912b3743678ba280fe41d9e3f3d854725837 Mon Sep 17 00:00:00 2001 From: Catatonic Date: Fri, 7 Jul 2017 15:39:49 -0700 Subject: [PATCH 14/15] Removing unused variable --- configure | 1 - 1 file changed, 1 deletion(-) diff --git a/configure b/configure index c463adc..f774b8c 100755 --- a/configure +++ b/configure @@ -40,7 +40,6 @@ CURSES_IPATH="" CRYPTO_PATH="" IDN_PATH="" IDN_IPATH="" -GCRYPT_PATH="" PR29_IPATH="" PCRE_PATH="" PCRE_IPATH="" From 2386d4517fb2b5a3fac3f23d93b9ea12f9c91063 Mon Sep 17 00:00:00 2001 From: catatonic Date: Sat, 8 Jul 2017 01:14:41 +0000 Subject: [PATCH 15/15] Improving data specificity more. --- hydra-radmin2.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/hydra-radmin2.c b/hydra-radmin2.c index afc5823..cba0431 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -92,8 +92,8 @@ char *message2buffer(struct rmessage *msg) { hydra_child_exit(0); } memcpy(data, &msg->magic, sizeof(char)); - *((int *)(data+1)) = htonl(msg->length); - *((int *)(data+5)) = htonl(msg->checksum); + *((int32_t *)(data+1)) = htonl(msg->length); + *((int32_t *)(data+5)) = htonl(msg->checksum); memcpy((data+9), &msg->type, sizeof(char)); break; case 0x09: @@ -103,8 +103,8 @@ char *message2buffer(struct rmessage *msg) { hydra_child_exit(0); } memcpy(data, &msg->magic, sizeof(char)); - *((int *)(data+1)) = htonl(msg->length); - *((int *)(data+5)) = htonl(msg->checksum); + *((int32_t *)(data+1)) = htonl(msg->length); + *((int32_t *)(data+5)) = htonl(msg->checksum); memcpy((data+9), &msg->type, sizeof(char)); memcpy((data+10), msg->data, sizeof(char) * 32); break; @@ -211,7 +211,7 @@ void service_radmin2(char *ip, int32_t sp, unsigned char options, char *miscptr, // 0) Connect to the server sock = hydra_connect_tcp(ip, myport); if(sock < 0) { - hydra_report(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid()); + hydra_report(stderr, "Error: Child with pid %d terminating, can not connect\n", (int32_t)getpid()); hydra_child_exit(1); } @@ -228,7 +228,7 @@ void service_radmin2(char *ip, int32_t sp, unsigned char options, char *miscptr, while(index < 42) { //We're always expecting back a 42 byte buffer from a challenge request. switch(hydra_data_ready(sock)) { case -1: - hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int32_t)getpid(), strerror(errno)); hydra_child_exit(1); break; case 0: @@ -237,7 +237,7 @@ void service_radmin2(char *ip, int32_t sp, unsigned char options, char *miscptr, default: bytecount = hydra_recv(sock, buffer+index, 42 - index); if(bytecount < 0) { - hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int32_t)getpid(), strerror(errno)); hydra_child_exit(1); } index += bytecount; @@ -255,13 +255,13 @@ void service_radmin2(char *ip, int32_t sp, unsigned char options, char *miscptr, //MD5 the password to generate the password key, this is used with twofish below. err = gcry_md_open(&md, GCRY_MD_MD5, 0); if(err) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_md_open error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_md_open error (%08x)\n%s/%s", (int32_t)getpid(), index, gcry_strsource(err), gcry_strerror(err)); hydra_child_exit(1); } gcry_md_reset(md); gcry_md_write(md, password, 100); if(gcry_md_read(md, 0) == NULL) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_md_read error (%08x)\n", (int)getpid(), index); + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_md_read error (%08x)\n", (int32_t)getpid(), index); hydra_child_exit(1); } memcpy(rawkey, gcry_md_read(md, 0), 16); @@ -273,25 +273,25 @@ void service_radmin2(char *ip, int32_t sp, unsigned char options, char *miscptr, //3.b) encrypt data received using pkey & known IV err= gcry_cipher_open(&cipher, GCRY_CIPHER_TWOFISH128, GCRY_CIPHER_MODE_CBC, 0); if(err) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_open error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_open error (%08x)\n%s/%s", (int32_t)getpid(), index, gcry_strsource(err), gcry_strerror(err)); hydra_child_exit(1); } err = gcry_cipher_setiv(cipher, IV, 16); if(err) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setiv error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setiv error (%08x)\n%s/%s", (int32_t)getpid(), index, gcry_strsource(err), gcry_strerror(err)); hydra_child_exit(1); } err = gcry_cipher_setkey(cipher, rawkey, 16); if(err) { - hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setkey error (%08x)\n%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_setkey error (%08x)\n%s/%s", (int32_t)getpid(), index, gcry_strsource(err), gcry_strerror(err)); 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%s/%s", (int)getpid(), index, gcry_strsource(err), gcry_strerror(err)); + hydra_report(stderr, "Error: Child with pid %d terminating, gcry_cipher_encrypt error (%08x)\n%s/%s", (int32_t)getpid(), index, gcry_strsource(err), gcry_strerror(err)); hydra_child_exit(1); } @@ -315,7 +315,7 @@ void service_radmin2(char *ip, int32_t sp, unsigned char options, char *miscptr, while(index < 10) { //We're always expecting back a 42 byte buffer from a challenge request. switch(hydra_data_ready(sock)) { case -1: - hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int32_t)getpid(), strerror(errno)); hydra_child_exit(1); break; case 0: @@ -324,7 +324,7 @@ void service_radmin2(char *ip, int32_t sp, unsigned char options, char *miscptr, default: bytecount = hydra_recv(sock, buffer+index, 10 - index); if(bytecount < 0) { - hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int32_t)getpid(), strerror(errno)); hydra_child_exit(1); } index += bytecount; @@ -340,7 +340,7 @@ void service_radmin2(char *ip, int32_t sp, unsigned char options, char *miscptr, hydra_disconnect(sock); break; default: - hydra_report(stderr, "Error: Child with pid %d terminating, protocol error\n", (int)getpid()); + hydra_report(stderr, "Error: Child with pid %d terminating, protocol error\n", (int32_t)getpid()); hydra_child_exit(2); } }