sha1.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 /*
00031 SHA-1 in C
00032 By Steve Reid <sreid@sea-to-sky.net>
00033 100% Public Domain
00034 
00035 -----------------
00036 Modified 7/98 
00037 By James H. Brown <jbrown@burgoyne.com>
00038 Still 100% Public Domain
00039 
00040 Corrected a problem which generated improper hash values on 16 bit machines
00041 Routine SHA1Update changed from
00042     void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
00043 len)
00044 to
00045     void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
00046 long len)
00047 
00048 The 'len' parameter was declared an int which works fine on 32 bit machines.
00049 However, on 16 bit machines an int is too small for the shifts being done
00050 against
00051 it.  This caused the hash function to generate incorrect values if len was
00052 greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
00053 
00054 Since the file IO in main() reads 16K at a time, any file 8K or larger would
00055 be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
00056 "a"s).
00057 
00058 I also changed the declaration of variables i & j in SHA1Update to 
00059 unsigned long from unsigned int for the same reason.
00060 
00061 These changes should make no difference to any 32 bit implementations since
00062 an
00063 int and a long are the same size in those environments.
00064 
00065 --
00066 I also corrected a few compiler warnings generated by Borland C.
00067 1. Added #include <process.h> for exit() prototype
00068 2. Removed unused variable 'j' in SHA1Final
00069 3. Changed exit(0) to return(0) at end of main.
00070 
00071 ALL changes I made can be located by searching for comments containing 'JHB'
00072 -----------------
00073 Modified 8/98
00074 By Steve Reid <sreid@sea-to-sky.net>
00075 Still 100% public domain
00076 
00077 1- Removed #include <process.h> and used return() instead of exit()
00078 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
00079 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
00080 
00081 -----------------
00082 Modified 4/01
00083 By Saul Kravitz <Saul.Kravitz@celera.com>
00084 Still 100% PD
00085 Modified to run on Compaq Alpha hardware.  
00086 
00087 
00088 */
00089 
00090 /*
00091 Test Vectors (from FIPS PUB 180-1)
00092 "abc"
00093   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
00094 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
00095   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
00096 A million repetitions of "a"
00097   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
00098 */
00099 
00100 /* #define SHA1HANDSOFF  */
00101 
00102 
00103 #include <stdio.h>
00104 #include <string.h>
00105 
00106 #include "common/h/Types.h"
00107 #include "common/h/sha1.h"
00108 /* #include <process.h> */  /* prototype for exit() - JHB */
00109 /* Using return() instead of exit() - SWR */
00110 
00111 typedef struct {
00112     uint32_t state[5];
00113     uint32_t count[2];
00114     unsigned char buffer[64];
00115 } SHA1_CTX;
00116 
00117 void SHA1Transform(uint32_t state[5], unsigned char buffer[64]);
00118 void SHA1Init(SHA1_CTX* context);
00119 void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len);  /*JHB */
00120 void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
00121 
00122 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
00123 
00124 /* blk0() and blk() perform the initial expand. */
00125 /* I got the idea of expanding during the round function from SSLeay */
00126 #if defined(arch_power) //Big Endian
00127 #define blk0(i) block->l[i]
00128 #else
00129 #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
00130     |(rol(block->l[i],8)&0x00FF00FF))
00131 #endif
00132 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
00133     ^block->l[(i+2)&15]^block->l[i&15],1))
00134 
00135 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
00136 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
00137 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
00138 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
00139 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
00140 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
00141 
00142 
00143 #ifdef VERBOSE  /* SAK */
00144 void SHAPrintContext(SHA1_CTX *context, char *msg){
00145   printf("%s (%d,%d) %x %x %x %x %x\n",
00146      msg,
00147      context->count[0], context->count[1], 
00148      context->state[0],
00149      context->state[1],
00150      context->state[2],
00151      context->state[3],
00152      context->state[4]);
00153 }
00154 #endif
00155 
00156 /* Hash a single 512-bit block. This is the core of the algorithm. */
00157 
00158 void SHA1Transform(uint32_t state[5], unsigned char buffer[64])
00159 {
00160 uint32_t a, b, c, d, e;
00161 typedef union {
00162     unsigned char c[64];
00163     uint32_t l[16];
00164 } CHAR64LONG16;
00165 CHAR64LONG16* block;
00166 #ifdef SHA1HANDSOFF
00167 static unsigned char workspace[64];
00168     block = (CHAR64LONG16*)workspace;
00169     memcpy(block, buffer, 64);
00170 #else
00171     block = (CHAR64LONG16*)(void*)buffer;
00172 #endif
00173     /* Copy context->state[] to working vars */
00174     a = state[0];
00175     b = state[1];
00176     c = state[2];
00177     d = state[3];
00178     e = state[4];
00179     /* 4 rounds of 20 operations each. Loop unrolled. */
00180     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);
00181     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);
00182     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);
00183     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);
00184     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);
00185     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);
00186     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);
00187     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);
00188     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);
00189     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);
00190     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);
00191     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);
00192     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);
00193     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);
00194     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);
00195     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);
00196     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);
00197     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);
00198     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);
00199     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);
00200     /* Add the working vars back into context.state[] */
00201     state[0] += a;
00202     state[1] += b;
00203     state[2] += c;
00204     state[3] += d;
00205     state[4] += e;
00206     /* Wipe variables */
00207     a = b = c = d = e = 0;
00208 }
00209 
00210 
00211 /* SHA1Init - Initialize new context */
00212 
00213 void SHA1Init(SHA1_CTX* context)
00214 {
00215     /* SHA1 initialization constants */
00216     context->state[0] = 0x67452301;
00217     context->state[1] = 0xEFCDAB89;
00218     context->state[2] = 0x98BADCFE;
00219     context->state[3] = 0x10325476;
00220     context->state[4] = 0xC3D2E1F0;
00221     context->count[0] = context->count[1] = 0;
00222 }
00223 
00224 
00225 /* Run your data through this. */
00226 
00227 void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len)   /*JHB */
00228 {
00229 uint32_t i, j;  /* JHB */
00230 
00231 #ifdef VERBOSE
00232     SHAPrintContext(context, "before");
00233 #endif
00234     j = (context->count[0] >> 3) & 63;
00235     if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
00236     context->count[1] += (len >> 29);
00237     if ((j + len) > 63) {
00238         memcpy(&context->buffer[j], data, (i = 64-j));
00239         SHA1Transform(context->state, context->buffer);
00240         for ( ; i + 63 < len; i += 64) {
00241             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     SHAPrintContext(context, "after ");
00249 #endif
00250 }
00251 
00252 
00253 /* Add padding and return the message digest. */
00254 
00255 void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
00256 {
00257 uint32_t i; /* JHB */
00258 unsigned char finalcount[8];
00259 
00260     for (i = 0; i < 8; i++) {
00261         finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
00262          >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
00263     }
00264     SHA1Update(context, (unsigned char *)const_cast< char *>("\200"), 1);
00265     while ((context->count[0] & 504) != 448) {
00266         SHA1Update(context, (unsigned char *)const_cast<char *>("\0"), 1);
00267     }
00268     SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
00269     for (i = 0; i < 20; i++) {
00270         digest[i] = (unsigned char)
00271          ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
00272     }
00273     /* Wipe variables */
00274     i = 0;  /* JHB */
00275     memset(context->buffer, 0, 64);
00276     memset(context->state, 0, 20);
00277     memset(context->count, 0, 8);
00278     memset(finalcount, 0, 8);   /* SWR */
00279 #ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
00280     SHA1Transform(context->state, context->buffer);
00281 #endif
00282 }
00283   
00284 /*************************************************************/
00285 
00286 char *sha1_file(const char *filename, char *result_ptr)
00287 {
00288     static char result[SHA1_STRING_LEN] = {0};
00289 
00290     SHA1_CTX ctx;
00291     unsigned char buf[16384];
00292 
00293     if (result_ptr == NULL)
00294         result_ptr = result;
00295 
00296     FILE *fd = fopen(filename, "r");
00297     if (!fd) return NULL;
00298 
00299     SHA1Init(&ctx);
00300     while (!feof(fd)) {
00301         unsigned long len = fread((char *)buf, sizeof(char), sizeof(buf), fd);
00302     if (ferror(fd)) {
00303         fclose(fd);
00304         return NULL;
00305     }
00306     SHA1Update(&ctx, buf, len);
00307     }
00308     SHA1Final(buf, &ctx);
00309 
00310     fclose(fd);
00311 
00312     for (unsigned int i = 0; i < SHA1_DIGEST_LEN; ++i)
00313         sprintf(&result_ptr[i*2], "%02x", buf[i]);
00314 
00315     return result_ptr;
00316 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1