/****************************************************************/ /* 802.11i HMAC-SHA-1 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 NIST HMAC-SHA-1 algorithm as used */ /* the IEEE 802.11i security spec. */ /* */ /* Supported message length is limited to 4096 characters */ /* ToDo: */ /* Sort out endian tolerance. Currently little endian. */ /****************************************************************/ #include #include #define MAX_MESSAGE_LENGTH 4096 /********************************************/ /* Test Cases */ /* An array of test cases taken from the */ /* 802.11i specification. */ /********************************************/ #define NUM_TEST_CASES 10 int test_case_length[] = {9,8,28,50,50,20,54,73,54,73}; unsigned char test_cases[] = { /* "Sample #1" */ 0x53,0x61,0x6d,0x70,0x6c,0x65,0x20,0x23,0x31, /* "Hi There" */ 0x48,0x69,0x20,0x54,0x68,0x65,0x72,0x65, /* "what do ya want for nothing?" */ 0x77,0x68,0x61,0x74,0x20,0x64,0x6f,0x20,0x79,0x61, 0x20,0x77,0x61,0x6e,0x74,0x20,0x66,0x6f,0x72,0x20, 0x6e,0x6f,0x74,0x68,0x69,0x6e,0x67,0x3f, 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd, 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd, 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd, 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd, 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd, /* "Test With Truncation" */ 0x54,0x65,0x73,0x74,0x20,0x57,0x69,0x74,0x68,0x20,0x54,0x72,0x75,0x6e,0x63,0x61, 0x74,0x69,0x6f,0x6e, /* "Test Using Larger Than Block-Size Key - Hash Key First" */ 0x54,0x65,0x73,0x74,0x20,0x55,0x73,0x69,0x6e,0x67,0x20,0x4c,0x61,0x72,0x67,0x65, 0x72,0x20,0x54,0x68,0x61,0x6e,0x20,0x42,0x6c,0x6f,0x63,0x6b,0x2d,0x53,0x69,0x7a, 0x65,0x20,0x4b,0x65,0x79,0x20,0x2d,0x20,0x48,0x61,0x73,0x68,0x20,0x4b,0x65,0x79, 0x20,0x46,0x69,0x72,0x73,0x74, /* "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" */ 0x54,0x65,0x73,0x74,0x20,0x55,0x73,0x69,0x6e,0x67,0x20,0x4c,0x61,0x72,0x67,0x65, 0x72,0x20,0x54,0x68,0x61,0x6e,0x20,0x42,0x6c,0x6f,0x63,0x6b,0x2d,0x53,0x69,0x7a, 0x65,0x20,0x4b,0x65,0x79,0x20,0x61,0x6e,0x64,0x20,0x4c,0x61,0x72,0x67,0x65,0x72, 0x20,0x54,0x68,0x61,0x6e,0x20,0x4f,0x6e,0x65,0x20,0x42,0x6c,0x6f,0x63,0x6b,0x2d, 0x53,0x69,0x7a,0x65,0x20,0x44,0x61,0x74,0x61, /* "Test Using Larger Than Block-Size Key - Hash Key First" */ 0x54,0x65,0x73,0x74,0x20,0x55,0x73,0x69,0x6e,0x67,0x20,0x4c,0x61,0x72,0x67,0x65, 0x72,0x20,0x54,0x68,0x61,0x6e,0x20,0x42,0x6c,0x6f,0x63,0x6b,0x2d,0x53,0x69,0x7a, 0x65,0x20,0x4b,0x65,0x79,0x20,0x2d,0x20,0x48,0x61,0x73,0x68,0x20,0x4b,0x65,0x79, 0x20,0x46,0x69,0x72,0x73,0x74, /* "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" */ 0x54,0x65,0x73,0x74,0x20,0x55,0x73,0x69,0x6e,0x67,0x20,0x4c,0x61,0x72,0x67,0x65, 0x72,0x20,0x54,0x68,0x61,0x6e,0x20,0x42,0x6c,0x6f,0x63,0x6b,0x2d,0x53,0x69,0x7a, 0x65,0x20,0x4b,0x65,0x79,0x20,0x61,0x6e,0x64,0x20,0x4c,0x61,0x72,0x67,0x65,0x72, 0x20,0x54,0x68,0x61,0x6e,0x20,0x4f,0x6e,0x65,0x20,0x42,0x6c,0x6f,0x63,0x6b,0x2d, 0x53,0x69,0x7a,0x65,0x20,0x44,0x61,0x74,0x61 }; int key_lengths[] = { 64, 20,4,20,25,20,80,80,80,80 }; unsigned char keys[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b, 0x4a,0x65,0x66,0x65, /* "Jefe" */ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a, 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14, 0x15,0x16,0x17,0x18,0x19, 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, 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, 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, 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, 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 }; /*****************************/ /**** Function Prototypes ****/ /*****************************/ unsigned long int ft( int t, unsigned long int x, unsigned long int y, unsigned long int z ); int get_testcase( int test_case, unsigned char *plaintext, unsigned char *key, int *key_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