/****************************************************************/ /* 802.11i PRF Test Code */ /* (c) 2002, David Johnston */ /* Author: David Johnston */ /* Email (home): dj@deadhat.com */ /* Email (general): david.johnston@ieee.org */ /* Version 0.1 */ /* */ /* This code implements the PRF-[128,192,236,384,512,768] */ /* algorithms as defined in the IEEE 802.11i security spec. */ /* */ /* Supported message length is limited to 4096 characters */ /****************************************************************/ #include #include #define MAX_MESSAGE_LENGTH 4096 /********************************************/ /* Test Cases */ /* An array of test cases taken from the */ /* 802.11i specification. */ /********************************************/ #define NUM_TEST_CASES 5 int result_lengths[] = {192,256,384,512,768}; int key_lengths[] = {20,4,80,20,80}; unsigned char keys[] = { 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 'J','e','f','e', 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, }; int prefix_lengths[] = {6,8,8,8,8}; unsigned char prefixes[] = { 'p','r','e','f','i','x', 'p','r','e','f','i','x','-','2', 'p','r','e','f','i','x','-','3', 'p','r','e','f','i','x','-','4', 'p','r','e','f','i','x','-','5' }; int data_lengths[] = {8,28,54,14,73}; unsigned char datas[] = { 'H','i',' ','T','h','e','r','e', 'w','h','a','t',' ','d','o',' ','y','a',' ', 'w','a','n','t',' ','f','o','r',' ','n','o','t','h','i','n','g','?', 'T','e','s','t',' ','U','s','i','n','g',' ','L','a','r','g','e','r',' ', 'T','h','a','n',' ','B','l','o','c','k','-','S','i','z','e',' ', 'K','e','y',' ','-',' ','H','a','s','h',' ','K','e','y',' ','F','i','r','s','t', 'H','i',' ','T','h','e','r','e',' ','A','g','a','i','n', 'T','e','s','t',' ','U','s','i','n','g',' ','L','a','r','g','e','r',' ', 'T','h','a','n',' ','B','l','o','c','k','-','S','i','z','e',' ', 'K','e','y',' ','a','n','d',' ','L','a','r','g','e','r',' ','T','h','a','n',' ', 'O','n','e',' ','B','l','o','c','k','-','S','i','z','e',' ','D','a','t','a' }; /*****************************/ /**** Function Prototypes ****/ /*****************************/ unsigned long int ft( int t, unsigned long int x, unsigned long int y, unsigned long int z ); void get_testcase( int test_case, unsigned char *key, int *key_length_ptr, unsigned char *prefix, int *prefix_length_ptr, unsigned char *data, int *data_length_ptr, int *result_length_ptr); void sha1 ( unsigned char *message, int message_length, unsigned char *digest ); /**************************/ /* Debug out */ /**************************/ #ifdef HMAC_DEBUG debug_out( unsigned char *label, unsigned char *data, int data_length ) { int i,j; int num_blocks; int block_remainder; num_blocks = data_length / 16; block_remainder = data_length % 16; printf("%s\n",label); for (i=0; i< num_blocks;i++) { printf("\t"); for (j=0; j< 16;j++) { printf("%02x ", data[j + (i*16)]); } printf("\n"); } if (block_remainder > 0) { printf("\t"); for (j=0; j> bits; f = (a & c) << (32 - bits); g = e | f; return (g & 0xffffffff ); } unsigned long int rotl(int bits, unsigned long int a) { unsigned long int c,d,e,f,g; c = (0x0001 << (32-bits))-1; d = ~c; e = (a & c) << bits; f = (a & d) >> (32 - bits); g = e | f; return (g & 0xffffffff ); } void sha1 ( unsigned char *message, int message_length, unsigned char *digest ) { int i; int num_blocks; int block_remainder; int padded_length; unsigned long int l; unsigned long int t; unsigned long int h[5]; unsigned long int a,b,c,d,e; unsigned long int w[80]; unsigned long int temp; #ifdef SHA1_DEBUG int x,y; #endif /* Calculate the number of 512 bit blocks */ padded_length = message_length + 8; /* Add length for l */ padded_length = padded_length + 1; /* Add the 0x01 bit postfix */ l = message_length * 8; num_blocks = padded_length / 64; block_remainder = padded_length % 64; if (block_remainder > 0) { num_blocks++; } padded_length = padded_length + (64 - block_remainder); /* clear the padding field */ for (i = message_length; i < (num_blocks * 64); i++) { message[i] = 0x00; } /* insert b1 padding bit */ message[message_length] = 0x80; /* Insert l */ message[(num_blocks*64)-1] = (unsigned char)( l & 0xff); message[(num_blocks*64)-2] = (unsigned char)((l >> 8) & 0xff); message[(num_blocks*64)-3] = (unsigned char)((l >> 16) & 0xff); message[(num_blocks*64)-4] = (unsigned char)((l >> 24) & 0xff); /* Set initial hash state */ h[0] = 0x67452301; h[1] = 0xefcdab89; h[2] = 0x98badcfe; h[3] = 0x10325476; h[4] = 0xc3d2e1f0; #ifdef SHA1_DEBUG printf("INITIAL message_length = %d\n", message_length); printf("INITIAL padded_length = %d\n", padded_length); printf("INITIAL num_blocks = %d\n", num_blocks); for (x=0;x> 8) & 0xff); digest[1] = (unsigned char) ((h[0] >> 16) & 0xff); digest[0] = (unsigned char) ((h[0] >> 24) & 0xff); digest[7] = (unsigned char) ( h[1] & 0xff); digest[6] = (unsigned char) ((h[1] >> 8) & 0xff); digest[5] = (unsigned char) ((h[1] >> 16) & 0xff); digest[4] = (unsigned char) ((h[1] >> 24) & 0xff); digest[11] = (unsigned char) ( h[2] & 0xff); digest[10] = (unsigned char) ((h[2] >> 8) & 0xff); digest[9] = (unsigned char) ((h[2] >> 16) & 0xff); digest[8] = (unsigned char) ((h[2] >> 24) & 0xff); digest[15] = (unsigned char) ( h[3] & 0xff); digest[14] = (unsigned char) ((h[3] >> 8) & 0xff); digest[13] = (unsigned char) ((h[3] >> 16) & 0xff); digest[12] = (unsigned char) ((h[3] >> 24) & 0xff); digest[19] = (unsigned char) ( h[4] & 0xff); digest[18] = (unsigned char) ((h[4] >> 8) & 0xff); digest[17] = (unsigned char) ((h[4] >> 16) & 0xff); digest[16] = (unsigned char) ((h[4] >> 24) & 0xff); } /******************************************************/ /* hmac-sha1() */ /* Performs the hmac-sha1 keyed secure hash algorithm */ /******************************************************/ void hmac_sha1( unsigned char *key, int key_length, unsigned char *data, int data_length, unsigned char *digest ) { int b = 64; /* blocksize */ unsigned char ipad = 0x36; unsigned char opad = 0x5c; unsigned char k0[64]; unsigned char k0xorIpad[64]; unsigned char step7data[64]; unsigned char step5data[MAX_MESSAGE_LENGTH+128]; unsigned char step8data[64+20]; int i; for (i=0; i<64; i++) { k0[i] = 0x00; } if (key_length != b) /* Step 1 */ { /* Step 2 */ if (key_length > b) { sha1(key, key_length, digest); for (i=0;i<20;i++) { k0[i]=digest[i]; } } else if (key_length < b) /* Step 3 */ { for (i=0; i 0) /* Print the final line */ { printf("\t\t"); for (j=0; j 0) /* Print the final line */ { printf("\t\t"); for (j=0; j