Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

sha1.c

00001 /*
00002  * $Id: sha1.c,v 12.0 2004/11/17 03:43:56 bostic Exp $
00003  */
00004 
00005 #include "db_config.h"
00006 
00007 /*
00008 SHA-1 in C
00009 By Steve Reid <[email protected]>
00010 100% Public Domain
00011 
00012 -----------------
00013 Modified 7/98 
00014 By James H. Brown <[email protected]>
00015 Still 100% Public Domain
00016 
00017 Corrected a problem which generated improper hash values on 16 bit machines
00018 Routine SHA1Update changed from
00019         void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
00020 len)
00021 to
00022         void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
00023 long len)
00024 
00025 The 'len' parameter was declared an int which works fine on 32 bit machines.
00026 However, on 16 bit machines an int is too small for the shifts being done
00027 against
00028 it.  This caused the hash function to generate incorrect values if len was
00029 greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
00030 
00031 Since the file IO in main() reads 16K at a time, any file 8K or larger would
00032 be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
00033 "a"s).
00034 
00035 I also changed the declaration of variables i & j in SHA1Update to 
00036 unsigned long from unsigned int for the same reason.
00037 
00038 These changes should make no difference to any 32 bit implementations since
00039 an
00040 int and a long are the same size in those environments.
00041 
00042 --
00043 I also corrected a few compiler warnings generated by Borland C.
00044 1. Added #include <process.h> for exit() prototype
00045 2. Removed unused variable 'j' in SHA1Final
00046 3. Changed exit(0) to return(0) at end of main.
00047 
00048 ALL changes I made can be located by searching for comments containing 'JHB'
00049 -----------------
00050 Modified 8/98
00051 By Steve Reid <[email protected]>
00052 Still 100% public domain
00053 
00054 1- Removed #include <process.h> and used return() instead of exit()
00055 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
00056 3- Changed email address from [email protected] to [email protected]
00057 
00058 -----------------
00059 Modified 4/01
00060 By Saul Kravitz <[email protected]>
00061 Still 100% PD
00062 Modified to run on Compaq Alpha hardware.  
00063 
00064 
00065 */
00066 
00067 /*
00068 Test Vectors (from FIPS PUB 180-1)
00069 "abc"
00070   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
00071 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
00072   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
00073 A million repetitions of "a"
00074   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
00075 */
00076 
00077 #define SHA1HANDSOFF
00078 
00079 #ifndef NO_SYSTEM_INCLUDES
00080 #include <string.h>
00081 #endif
00082 
00083 #include "db_int.h"
00084 #include "dbinc/hmac.h"
00085 
00086 /* #include <process.h> */      /* prototype for exit() - JHB */
00087 /* Using return() instead of exit() - SWR */
00088 
00089 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
00090 
00091 /* blk0() and blk() perform the initial expand. */
00092 /* I got the idea of expanding during the round function from SSLeay */
00093 #define blk0(i) is_bigendian ? block->l[i] : \
00094     (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
00095     |(rol(block->l[i],8)&0x00FF00FF))
00096 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
00097     ^block->l[(i+2)&15]^block->l[i&15],1))
00098 
00099 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
00100 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
00101 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
00102 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
00103 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
00104 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
00105 
00106 
00107 #ifdef VERBOSE  /* SAK */
00108 static void __db_SHAPrintContext __P((SHA1_CTX *, char *));
00109 static void
00110 __db_SHAPrintContext(context, msg)
00111         SHA1_CTX *context;
00112         char *msg;
00113 {
00114   printf("%s (%d,%d) %x %x %x %x %x\n",
00115          msg,
00116          context->count[0], context->count[1], 
00117          context->state[0],
00118          context->state[1],
00119          context->state[2],
00120          context->state[3],
00121          context->state[4]);
00122 }
00123 #endif
00124 
00125 /* Hash a single 512-bit block. This is the core of the algorithm. */
00126 
00127 /*
00128  * __db_SHA1Transform --
00129  * 
00130  * PUBLIC: void __db_SHA1Transform __P((u_int32_t *, unsigned char *));
00131  */
00132 void
00133 __db_SHA1Transform(state, buffer)
00134         u_int32_t *state;
00135         unsigned char *buffer;
00136 {
00137 u_int32_t a, b, c, d, e;
00138 typedef union {
00139     unsigned char c[64];
00140     u_int32_t l[16];
00141 } CHAR64LONG16;
00142 CHAR64LONG16* block;
00143 static int is_bigendian = -1;
00144 #ifdef SHA1HANDSOFF
00145     unsigned char workspace[64];
00146 
00147     block = (CHAR64LONG16*)workspace;
00148     memcpy(block, buffer, 64);
00149 #else
00150     block = (CHAR64LONG16*)buffer;
00151 #endif
00152     if (is_bigendian == -1)
00153         is_bigendian = __db_isbigendian();
00154     /* Copy context->state[] to working vars */
00155     a = state[0];
00156     b = state[1];
00157     c = state[2];
00158     d = state[3];
00159     e = state[4];
00160     /* 4 rounds of 20 operations each. Loop unrolled. */
00161     R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
00162     R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
00163     R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
00164     R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
00165     R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
00166     R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
00167     R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
00168     R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
00169     R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
00170     R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
00171     R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
00172     R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
00173     R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
00174     R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
00175     R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
00176     R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
00177     R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
00178     R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
00179     R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
00180     R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
00181     /* Add the working vars back into context.state[] */
00182     state[0] += a;
00183     state[1] += b;
00184     state[2] += c;
00185     state[3] += d;
00186     state[4] += e;
00187     /* Wipe variables */
00188     a = b = c = d = e = 0;
00189 }
00190 
00191 
00192 /* SHA1Init - Initialize new context */
00193 
00194 /*   
00195  * __db_SHA1Init --
00196  *      Initialize new context
00197  *
00198  * PUBLIC: void __db_SHA1Init __P((SHA1_CTX *));
00199  */
00200 void
00201 __db_SHA1Init(context)
00202         SHA1_CTX *context;
00203 {
00204     /* SHA1 initialization constants */
00205     context->state[0] = 0x67452301;
00206     context->state[1] = 0xEFCDAB89;
00207     context->state[2] = 0x98BADCFE;
00208     context->state[3] = 0x10325476;
00209     context->state[4] = 0xC3D2E1F0;
00210     context->count[0] = context->count[1] = 0;
00211 }
00212 
00213 
00214 /* Run your data through this. */
00215 
00216 /*
00217  * __db_SHA1Update --
00218  *      Run your data through this.
00219  *
00220  * PUBLIC: void __db_SHA1Update __P((SHA1_CTX *, unsigned char *,
00221  * PUBLIC:     size_t));
00222  */
00223 void
00224 __db_SHA1Update(context, data, len)
00225         SHA1_CTX *context;
00226         unsigned char *data;
00227         size_t len;
00228 {
00229 u_int32_t i, j; /* JHB */
00230 
00231 #ifdef VERBOSE
00232     __db_SHAPrintContext(context, "before");
00233 #endif
00234     j = (context->count[0] >> 3) & 63;
00235     if ((context->count[0] += (u_int32_t)len << 3) < (len << 3)) context->count[1]++;
00236     context->count[1] += (u_int32_t)(len >> 29);
00237     if ((j + len) > 63) {
00238         memcpy(&context->buffer[j], data, (i = 64-j));
00239         __db_SHA1Transform(context->state, context->buffer);
00240         for ( ; i + 63 < len; i += 64) {
00241             __db_SHA1Transform(context->state, &data[i]);
00242         }
00243         j = 0;
00244     }
00245     else i = 0;
00246     memcpy(&context->buffer[j], &data[i], len - i);
00247 #ifdef VERBOSE
00248     __db_SHAPrintContext(context, "after ");
00249 #endif
00250 }
00251 
00252 
00253 /* Add padding and return the message digest. */
00254 
00255 /*
00256  * __db_SHA1Final --
00257  *      Add padding and return the message digest.
00258  *
00259  * PUBLIC: void __db_SHA1Final __P((unsigned char *, SHA1_CTX *));
00260  */
00261 void
00262 __db_SHA1Final(digest, context)
00263         unsigned char *digest;
00264         SHA1_CTX *context;
00265 {
00266 u_int32_t i;    /* JHB */
00267 unsigned char finalcount[8];
00268 
00269     for (i = 0; i < 8; i++) {
00270         finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
00271          >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
00272     }
00273     __db_SHA1Update(context, (unsigned char *)"\200", 1);
00274     while ((context->count[0] & 504) != 448) {
00275         __db_SHA1Update(context, (unsigned char *)"\0", 1);
00276     }
00277     __db_SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform()
00278 */
00279     for (i = 0; i < 20; i++) {
00280         digest[i] = (unsigned char)
00281          ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
00282     }
00283     /* Wipe variables */
00284     i = 0;      /* JHB */
00285     memset(context->buffer, 0, 64);
00286     memset(context->state, 0, 20);
00287     memset(context->count, 0, 8);
00288     memset(finalcount, 0, 8);   /* SWR */
00289 #ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
00290     __db_SHA1Transform(context->state, context->buffer);
00291 #endif
00292 }
00293   
00294 /*************************************************************/
00295 

Generated on Sun Dec 25 12:14:30 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2