$search
00001 /* 00002 * SHA1 hash implementation and interface functions 00003 * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "sha1.h" 00019 #include "sha1_i.h" 00020 #include "md5.h" 00021 #include "crypto.h" 00022 00023 typedef struct SHA1Context SHA1_CTX; 00024 00025 void SHA1Transform(u32 state[5], const unsigned char buffer[64]); 00026 00027 00036 int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 00037 { 00038 SHA1_CTX ctx; 00039 size_t i; 00040 00041 SHA1Init(&ctx); 00042 for (i = 0; i < num_elem; i++) 00043 SHA1Update(&ctx, addr[i], len[i]); 00044 SHA1Final(mac, &ctx); 00045 return 0; 00046 } 00047 00048 00049 /* ===== start - public domain SHA1 implementation ===== */ 00050 00051 /* 00052 SHA-1 in C 00053 By Steve Reid <sreid@sea-to-sky.net> 00054 100% Public Domain 00055 00056 ----------------- 00057 Modified 7/98 00058 By James H. Brown <jbrown@burgoyne.com> 00059 Still 100% Public Domain 00060 00061 Corrected a problem which generated improper hash values on 16 bit machines 00062 Routine SHA1Update changed from 00063 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int 00064 len) 00065 to 00066 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned 00067 long len) 00068 00069 The 'len' parameter was declared an int which works fine on 32 bit machines. 00070 However, on 16 bit machines an int is too small for the shifts being done 00071 against 00072 it. This caused the hash function to generate incorrect values if len was 00073 greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). 00074 00075 Since the file IO in main() reads 16K at a time, any file 8K or larger would 00076 be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million 00077 "a"s). 00078 00079 I also changed the declaration of variables i & j in SHA1Update to 00080 unsigned long from unsigned int for the same reason. 00081 00082 These changes should make no difference to any 32 bit implementations since 00083 an 00084 int and a long are the same size in those environments. 00085 00086 -- 00087 I also corrected a few compiler warnings generated by Borland C. 00088 1. Added #include <process.h> for exit() prototype 00089 2. Removed unused variable 'j' in SHA1Final 00090 3. Changed exit(0) to return(0) at end of main. 00091 00092 ALL changes I made can be located by searching for comments containing 'JHB' 00093 ----------------- 00094 Modified 8/98 00095 By Steve Reid <sreid@sea-to-sky.net> 00096 Still 100% public domain 00097 00098 1- Removed #include <process.h> and used return() instead of exit() 00099 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) 00100 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net 00101 00102 ----------------- 00103 Modified 4/01 00104 By Saul Kravitz <Saul.Kravitz@celera.com> 00105 Still 100% PD 00106 Modified to run on Compaq Alpha hardware. 00107 00108 ----------------- 00109 Modified 4/01 00110 By Jouni Malinen <j@w1.fi> 00111 Minor changes to match the coding style used in Dynamics. 00112 00113 Modified September 24, 2004 00114 By Jouni Malinen <j@w1.fi> 00115 Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined. 00116 00117 */ 00118 00119 /* 00120 Test Vectors (from FIPS PUB 180-1) 00121 "abc" 00122 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 00123 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 00124 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 00125 A million repetitions of "a" 00126 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 00127 */ 00128 00129 #define SHA1HANDSOFF 00130 00131 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 00132 00133 /* blk0() and blk() perform the initial expand. */ 00134 /* I got the idea of expanding during the round function from SSLeay */ 00135 #ifndef WORDS_BIGENDIAN 00136 #define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \ 00137 (rol(block->l[i], 8) & 0x00FF00FF)) 00138 #else 00139 #define blk0(i) block->l[i] 00140 #endif 00141 #define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ 00142 block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) 00143 00144 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 00145 #define R0(v,w,x,y,z,i) \ 00146 z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ 00147 w = rol(w, 30); 00148 #define R1(v,w,x,y,z,i) \ 00149 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ 00150 w = rol(w, 30); 00151 #define R2(v,w,x,y,z,i) \ 00152 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); 00153 #define R3(v,w,x,y,z,i) \ 00154 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ 00155 w = rol(w, 30); 00156 #define R4(v,w,x,y,z,i) \ 00157 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ 00158 w=rol(w, 30); 00159 00160 00161 #ifdef VERBOSE /* SAK */ 00162 void SHAPrintContext(SHA1_CTX *context, char *msg) 00163 { 00164 printf("%s (%d,%d) %x %x %x %x %x\n", 00165 msg, 00166 context->count[0], context->count[1], 00167 context->state[0], 00168 context->state[1], 00169 context->state[2], 00170 context->state[3], 00171 context->state[4]); 00172 } 00173 #endif 00174 00175 /* Hash a single 512-bit block. This is the core of the algorithm. */ 00176 00177 void SHA1Transform(u32 state[5], const unsigned char buffer[64]) 00178 { 00179 u32 a, b, c, d, e; 00180 typedef union { 00181 unsigned char c[64]; 00182 u32 l[16]; 00183 } CHAR64LONG16; 00184 CHAR64LONG16* block; 00185 #ifdef SHA1HANDSOFF 00186 CHAR64LONG16 workspace; 00187 block = &workspace; 00188 os_memcpy(block, buffer, 64); 00189 #else 00190 block = (CHAR64LONG16 *) buffer; 00191 #endif 00192 /* Copy context->state[] to working vars */ 00193 a = state[0]; 00194 b = state[1]; 00195 c = state[2]; 00196 d = state[3]; 00197 e = state[4]; 00198 /* 4 rounds of 20 operations each. Loop unrolled. */ 00199 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); 00200 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); 00201 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); 00202 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); 00203 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); 00204 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); 00205 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); 00206 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); 00207 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); 00208 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); 00209 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); 00210 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); 00211 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); 00212 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); 00213 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); 00214 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); 00215 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); 00216 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); 00217 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); 00218 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); 00219 /* Add the working vars back into context.state[] */ 00220 state[0] += a; 00221 state[1] += b; 00222 state[2] += c; 00223 state[3] += d; 00224 state[4] += e; 00225 /* Wipe variables */ 00226 a = b = c = d = e = 0; 00227 #ifdef SHA1HANDSOFF 00228 os_memset(block, 0, 64); 00229 #endif 00230 } 00231 00232 00233 /* SHA1Init - Initialize new context */ 00234 00235 void SHA1Init(SHA1_CTX* context) 00236 { 00237 /* SHA1 initialization constants */ 00238 context->state[0] = 0x67452301; 00239 context->state[1] = 0xEFCDAB89; 00240 context->state[2] = 0x98BADCFE; 00241 context->state[3] = 0x10325476; 00242 context->state[4] = 0xC3D2E1F0; 00243 context->count[0] = context->count[1] = 0; 00244 } 00245 00246 00247 /* Run your data through this. */ 00248 00249 void SHA1Update(SHA1_CTX* context, const void *_data, u32 len) 00250 { 00251 u32 i, j; 00252 const unsigned char *data = _data; 00253 00254 #ifdef VERBOSE 00255 SHAPrintContext(context, "before"); 00256 #endif 00257 j = (context->count[0] >> 3) & 63; 00258 if ((context->count[0] += len << 3) < (len << 3)) 00259 context->count[1]++; 00260 context->count[1] += (len >> 29); 00261 if ((j + len) > 63) { 00262 os_memcpy(&context->buffer[j], data, (i = 64-j)); 00263 SHA1Transform(context->state, context->buffer); 00264 for ( ; i + 63 < len; i += 64) { 00265 SHA1Transform(context->state, &data[i]); 00266 } 00267 j = 0; 00268 } 00269 else i = 0; 00270 os_memcpy(&context->buffer[j], &data[i], len - i); 00271 #ifdef VERBOSE 00272 SHAPrintContext(context, "after "); 00273 #endif 00274 } 00275 00276 00277 /* Add padding and return the message digest. */ 00278 00279 void SHA1Final(unsigned char digest[20], SHA1_CTX* context) 00280 { 00281 u32 i; 00282 unsigned char finalcount[8]; 00283 00284 for (i = 0; i < 8; i++) { 00285 finalcount[i] = (unsigned char) 00286 ((context->count[(i >= 4 ? 0 : 1)] >> 00287 ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ 00288 } 00289 SHA1Update(context, (unsigned char *) "\200", 1); 00290 while ((context->count[0] & 504) != 448) { 00291 SHA1Update(context, (unsigned char *) "\0", 1); 00292 } 00293 SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() 00294 */ 00295 for (i = 0; i < 20; i++) { 00296 digest[i] = (unsigned char) 00297 ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 00298 255); 00299 } 00300 /* Wipe variables */ 00301 i = 0; 00302 os_memset(context->buffer, 0, 64); 00303 os_memset(context->state, 0, 20); 00304 os_memset(context->count, 0, 8); 00305 os_memset(finalcount, 0, 8); 00306 } 00307 00308 /* ===== end - public domain SHA1 implementation ===== */