/****************************************************************/
/* SHA-1 Test Code */
/* (c) 2002, David Johnston */
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/* Author: David Johnston */
/* Email (home): dj@deadhat.com */
/* Email (general): david.johnston@ieee.org */
/* Version 0.1 */
/* */
/* Supported message length is limited to 4096 characters */
/* ToDo: */
/* Sort out endian tolerance. Currently little endian. */
/* Remove debug code */
/****************************************************************/
#include
#include
#define MAX_MESSAGE_LENGTH 4096
/* #define DEBUG */
/********************************************/
/* Test Cases */
/* An array of test cases taken from the */
/* NIST SHA-1 specification. */
/********************************************/
#define NUM_TEST_CASES 2
int test_case_length[] = {3,56};
unsigned char test_cases[] = /* Test Case 1 */
{
0x61,0x62,0x63,
/* Test Case 2 */
0x61,0x62,0x63,0x64, /* abcd */
0x62,0x63,0x64,0x65, /* bcde */
0x63,0x64,0x65,0x66, /* cdef */
0x64,0x65,0x66,0x67, /* defg */
0x65,0x66,0x67,0x68, /* efgh */
0x66,0x67,0x68,0x69, /* fghi */
0x67,0x68,0x69,0x6a, /* ghij */
0x68,0x69,0x6a,0x6b, /* hijk */
0x69,0x6a,0x6b,0x6c, /* ijkl */
0x6a,0x6b,0x6c,0x6d, /* jklm */
0x6b,0x6c,0x6d,0x6e, /* klmn */
0x6c,0x6d,0x6e,0x6f, /* lmno */
0x6d,0x6e,0x6f,0x70, /* mnop */
0x6e,0x6f,0x70,0x71 /* nopq */
};
/*****************************/
/**** Function Prototypes ****/
/*****************************/
void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out);
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);
void sha1 (
unsigned char *message,
int message_length,
unsigned char *digest
);
/****************************************/
/* sha1() */
/* Performs the NIST SHA-1 algorithm */
/****************************************/
unsigned long int ft(
int t,
unsigned long int x,
unsigned long int y,
unsigned long int z
)
{
unsigned long int a,b,c;
if (t < 20)
{
a = x & y;
b = (~x) & z;
c = a ^ b;
}
else if (t < 40)
{
c = x ^ y ^ z;
}
else if (t < 60)
{
a = x & y;
b = a ^ (x & z);
c = b ^ (y & z);
}
else if (t < 80)
{
c = (x ^ y) ^ z;
}
return c;
}
unsigned long int k(int t)
{
unsigned long int c;
if (t < 20)
{
c = 0x5a827999;
}
else if (t < 40)
{
c = 0x6ed9eba1;
}
else if (t < 60)
{
c = 0x8f1bbcdc;
}
else if (t < 80)
{
c = 0xca62c1d6;
}
return c;
}
unsigned long int rotr(int bits, unsigned long int a)
{
unsigned long int c,d,e,f,g;
c = (0x0001 << bits)-1;
d = ~c;
e = (a & d) >> 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 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 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);
}
/************************************************/
/* get_testcase() */
/* Copies a test case from the test case data */
/************************************************/
int get_testcase( int test_case,
unsigned char *plaintext)
{
int i;
unsigned char *ptr;
ptr = test_cases;
for (i=0; i< (test_case-1); i++) /* Iterate through test cases */
{
ptr = ptr + test_case_length[i];
}
for (i=0; i< test_case_length[test_case-1]; i++)
{
plaintext[i] = *ptr++;
}
return test_case_length[test_case-1];
}
/****************************************************/
/* main() */
/* Iterate through the test cases, passing them */
/* through the sha-1 algorithm to produce test */
/* vectors */
/****************************************************/
int main()
{
int length;
int test_case;
int num_blocks;
int block_remainder;
int i;
int j;
unsigned char plaintext[MAX_MESSAGE_LENGTH+9];
unsigned char digest[20];
for (test_case = 1; test_case < (NUM_TEST_CASES+1); test_case++)
{
length = get_testcase(test_case, plaintext);
num_blocks = length / 16; /* Calculate number of 16 byte blocks */
block_remainder = length % 16;
printf ("TEST CASE %d\n",test_case);
printf ("\tLength = %d\n",length);
printf ("\tDATA =\n");
for (i=0;i 0) /* Print the final line */
{
printf("\t\t");
for (j=0; j