1214501Srpaulo/* 2214501Srpaulo * SHA1 hash implementation and interface functions 3214501Srpaulo * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "includes.h" 10214501Srpaulo 11214501Srpaulo#include "common.h" 12214501Srpaulo#include "sha1.h" 13214501Srpaulo#include "sha1_i.h" 14214501Srpaulo#include "md5.h" 15214501Srpaulo#include "crypto.h" 16214501Srpaulo 17214501Srpaulotypedef struct SHA1Context SHA1_CTX; 18214501Srpaulo 19214501Srpaulovoid SHA1Transform(u32 state[5], const unsigned char buffer[64]); 20214501Srpaulo 21214501Srpaulo 22214501Srpaulo/** 23214501Srpaulo * sha1_vector - SHA-1 hash for data vector 24214501Srpaulo * @num_elem: Number of elements in the data vector 25214501Srpaulo * @addr: Pointers to the data areas 26214501Srpaulo * @len: Lengths of the data blocks 27214501Srpaulo * @mac: Buffer for the hash 28214501Srpaulo * Returns: 0 on success, -1 of failure 29214501Srpaulo */ 30214501Srpauloint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 31214501Srpaulo{ 32214501Srpaulo SHA1_CTX ctx; 33214501Srpaulo size_t i; 34214501Srpaulo 35214501Srpaulo SHA1Init(&ctx); 36214501Srpaulo for (i = 0; i < num_elem; i++) 37214501Srpaulo SHA1Update(&ctx, addr[i], len[i]); 38214501Srpaulo SHA1Final(mac, &ctx); 39214501Srpaulo return 0; 40214501Srpaulo} 41214501Srpaulo 42214501Srpaulo 43214501Srpaulo/* ===== start - public domain SHA1 implementation ===== */ 44214501Srpaulo 45214501Srpaulo/* 46214501SrpauloSHA-1 in C 47214501SrpauloBy Steve Reid <sreid@sea-to-sky.net> 48214501Srpaulo100% Public Domain 49214501Srpaulo 50214501Srpaulo----------------- 51214501SrpauloModified 7/98 52214501SrpauloBy James H. Brown <jbrown@burgoyne.com> 53214501SrpauloStill 100% Public Domain 54214501Srpaulo 55214501SrpauloCorrected a problem which generated improper hash values on 16 bit machines 56214501SrpauloRoutine SHA1Update changed from 57214501Srpaulo void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int 58214501Srpaulolen) 59214501Srpauloto 60214501Srpaulo void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned 61214501Srpaulolong len) 62214501Srpaulo 63214501SrpauloThe 'len' parameter was declared an int which works fine on 32 bit machines. 64214501SrpauloHowever, on 16 bit machines an int is too small for the shifts being done 65214501Srpauloagainst 66214501Srpauloit. This caused the hash function to generate incorrect values if len was 67214501Srpaulogreater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). 68214501Srpaulo 69214501SrpauloSince the file IO in main() reads 16K at a time, any file 8K or larger would 70214501Srpaulobe guaranteed to generate the wrong hash (e.g. Test Vector #3, a million 71214501Srpaulo"a"s). 72214501Srpaulo 73214501SrpauloI also changed the declaration of variables i & j in SHA1Update to 74214501Srpaulounsigned long from unsigned int for the same reason. 75214501Srpaulo 76214501SrpauloThese changes should make no difference to any 32 bit implementations since 77214501Srpauloan 78214501Srpauloint and a long are the same size in those environments. 79214501Srpaulo 80214501Srpaulo-- 81214501SrpauloI also corrected a few compiler warnings generated by Borland C. 82214501Srpaulo1. Added #include <process.h> for exit() prototype 83214501Srpaulo2. Removed unused variable 'j' in SHA1Final 84214501Srpaulo3. Changed exit(0) to return(0) at end of main. 85214501Srpaulo 86214501SrpauloALL changes I made can be located by searching for comments containing 'JHB' 87214501Srpaulo----------------- 88214501SrpauloModified 8/98 89214501SrpauloBy Steve Reid <sreid@sea-to-sky.net> 90214501SrpauloStill 100% public domain 91214501Srpaulo 92214501Srpaulo1- Removed #include <process.h> and used return() instead of exit() 93214501Srpaulo2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) 94214501Srpaulo3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net 95214501Srpaulo 96214501Srpaulo----------------- 97214501SrpauloModified 4/01 98214501SrpauloBy Saul Kravitz <Saul.Kravitz@celera.com> 99214501SrpauloStill 100% PD 100214501SrpauloModified to run on Compaq Alpha hardware. 101214501Srpaulo 102214501Srpaulo----------------- 103214501SrpauloModified 4/01 104214501SrpauloBy Jouni Malinen <j@w1.fi> 105214501SrpauloMinor changes to match the coding style used in Dynamics. 106214501Srpaulo 107214501SrpauloModified September 24, 2004 108214501SrpauloBy Jouni Malinen <j@w1.fi> 109214501SrpauloFixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined. 110214501Srpaulo 111214501Srpaulo*/ 112214501Srpaulo 113214501Srpaulo/* 114214501SrpauloTest Vectors (from FIPS PUB 180-1) 115214501Srpaulo"abc" 116214501Srpaulo A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 117214501Srpaulo"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 118214501Srpaulo 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 119214501SrpauloA million repetitions of "a" 120214501Srpaulo 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 121214501Srpaulo*/ 122214501Srpaulo 123214501Srpaulo#define SHA1HANDSOFF 124214501Srpaulo 125214501Srpaulo#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 126214501Srpaulo 127214501Srpaulo/* blk0() and blk() perform the initial expand. */ 128214501Srpaulo/* I got the idea of expanding during the round function from SSLeay */ 129214501Srpaulo#ifndef WORDS_BIGENDIAN 130214501Srpaulo#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \ 131214501Srpaulo (rol(block->l[i], 8) & 0x00FF00FF)) 132214501Srpaulo#else 133214501Srpaulo#define blk0(i) block->l[i] 134214501Srpaulo#endif 135214501Srpaulo#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ 136214501Srpaulo block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) 137214501Srpaulo 138214501Srpaulo/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 139214501Srpaulo#define R0(v,w,x,y,z,i) \ 140214501Srpaulo z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ 141214501Srpaulo w = rol(w, 30); 142214501Srpaulo#define R1(v,w,x,y,z,i) \ 143214501Srpaulo z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ 144214501Srpaulo w = rol(w, 30); 145214501Srpaulo#define R2(v,w,x,y,z,i) \ 146214501Srpaulo z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); 147214501Srpaulo#define R3(v,w,x,y,z,i) \ 148214501Srpaulo z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ 149214501Srpaulo w = rol(w, 30); 150214501Srpaulo#define R4(v,w,x,y,z,i) \ 151214501Srpaulo z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ 152214501Srpaulo w=rol(w, 30); 153214501Srpaulo 154214501Srpaulo 155214501Srpaulo#ifdef VERBOSE /* SAK */ 156214501Srpaulovoid SHAPrintContext(SHA1_CTX *context, char *msg) 157214501Srpaulo{ 158214501Srpaulo printf("%s (%d,%d) %x %x %x %x %x\n", 159214501Srpaulo msg, 160214501Srpaulo context->count[0], context->count[1], 161214501Srpaulo context->state[0], 162214501Srpaulo context->state[1], 163214501Srpaulo context->state[2], 164214501Srpaulo context->state[3], 165214501Srpaulo context->state[4]); 166214501Srpaulo} 167214501Srpaulo#endif 168214501Srpaulo 169214501Srpaulo/* Hash a single 512-bit block. This is the core of the algorithm. */ 170214501Srpaulo 171214501Srpaulovoid SHA1Transform(u32 state[5], const unsigned char buffer[64]) 172214501Srpaulo{ 173214501Srpaulo u32 a, b, c, d, e; 174214501Srpaulo typedef union { 175214501Srpaulo unsigned char c[64]; 176214501Srpaulo u32 l[16]; 177214501Srpaulo } CHAR64LONG16; 178214501Srpaulo CHAR64LONG16* block; 179214501Srpaulo#ifdef SHA1HANDSOFF 180214501Srpaulo CHAR64LONG16 workspace; 181214501Srpaulo block = &workspace; 182214501Srpaulo os_memcpy(block, buffer, 64); 183214501Srpaulo#else 184214501Srpaulo block = (CHAR64LONG16 *) buffer; 185214501Srpaulo#endif 186214501Srpaulo /* Copy context->state[] to working vars */ 187214501Srpaulo a = state[0]; 188214501Srpaulo b = state[1]; 189214501Srpaulo c = state[2]; 190214501Srpaulo d = state[3]; 191214501Srpaulo e = state[4]; 192214501Srpaulo /* 4 rounds of 20 operations each. Loop unrolled. */ 193214501Srpaulo 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); 194214501Srpaulo 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); 195214501Srpaulo 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); 196214501Srpaulo 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); 197214501Srpaulo 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); 198214501Srpaulo 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); 199214501Srpaulo 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); 200214501Srpaulo 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); 201214501Srpaulo 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); 202214501Srpaulo 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); 203214501Srpaulo 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); 204214501Srpaulo 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); 205214501Srpaulo 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); 206214501Srpaulo 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); 207214501Srpaulo 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); 208214501Srpaulo 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); 209214501Srpaulo 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); 210214501Srpaulo 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); 211214501Srpaulo 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); 212214501Srpaulo 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); 213214501Srpaulo /* Add the working vars back into context.state[] */ 214214501Srpaulo state[0] += a; 215214501Srpaulo state[1] += b; 216214501Srpaulo state[2] += c; 217214501Srpaulo state[3] += d; 218214501Srpaulo state[4] += e; 219214501Srpaulo /* Wipe variables */ 220214501Srpaulo a = b = c = d = e = 0; 221214501Srpaulo#ifdef SHA1HANDSOFF 222214501Srpaulo os_memset(block, 0, 64); 223214501Srpaulo#endif 224214501Srpaulo} 225214501Srpaulo 226214501Srpaulo 227214501Srpaulo/* SHA1Init - Initialize new context */ 228214501Srpaulo 229214501Srpaulovoid SHA1Init(SHA1_CTX* context) 230214501Srpaulo{ 231214501Srpaulo /* SHA1 initialization constants */ 232214501Srpaulo context->state[0] = 0x67452301; 233214501Srpaulo context->state[1] = 0xEFCDAB89; 234214501Srpaulo context->state[2] = 0x98BADCFE; 235214501Srpaulo context->state[3] = 0x10325476; 236214501Srpaulo context->state[4] = 0xC3D2E1F0; 237214501Srpaulo context->count[0] = context->count[1] = 0; 238214501Srpaulo} 239214501Srpaulo 240214501Srpaulo 241214501Srpaulo/* Run your data through this. */ 242214501Srpaulo 243214501Srpaulovoid SHA1Update(SHA1_CTX* context, const void *_data, u32 len) 244214501Srpaulo{ 245214501Srpaulo u32 i, j; 246214501Srpaulo const unsigned char *data = _data; 247214501Srpaulo 248214501Srpaulo#ifdef VERBOSE 249214501Srpaulo SHAPrintContext(context, "before"); 250214501Srpaulo#endif 251214501Srpaulo j = (context->count[0] >> 3) & 63; 252214501Srpaulo if ((context->count[0] += len << 3) < (len << 3)) 253214501Srpaulo context->count[1]++; 254214501Srpaulo context->count[1] += (len >> 29); 255214501Srpaulo if ((j + len) > 63) { 256214501Srpaulo os_memcpy(&context->buffer[j], data, (i = 64-j)); 257214501Srpaulo SHA1Transform(context->state, context->buffer); 258214501Srpaulo for ( ; i + 63 < len; i += 64) { 259214501Srpaulo SHA1Transform(context->state, &data[i]); 260214501Srpaulo } 261214501Srpaulo j = 0; 262214501Srpaulo } 263214501Srpaulo else i = 0; 264214501Srpaulo os_memcpy(&context->buffer[j], &data[i], len - i); 265214501Srpaulo#ifdef VERBOSE 266214501Srpaulo SHAPrintContext(context, "after "); 267214501Srpaulo#endif 268214501Srpaulo} 269214501Srpaulo 270214501Srpaulo 271214501Srpaulo/* Add padding and return the message digest. */ 272214501Srpaulo 273214501Srpaulovoid SHA1Final(unsigned char digest[20], SHA1_CTX* context) 274214501Srpaulo{ 275214501Srpaulo u32 i; 276214501Srpaulo unsigned char finalcount[8]; 277214501Srpaulo 278214501Srpaulo for (i = 0; i < 8; i++) { 279214501Srpaulo finalcount[i] = (unsigned char) 280214501Srpaulo ((context->count[(i >= 4 ? 0 : 1)] >> 281214501Srpaulo ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ 282214501Srpaulo } 283214501Srpaulo SHA1Update(context, (unsigned char *) "\200", 1); 284214501Srpaulo while ((context->count[0] & 504) != 448) { 285214501Srpaulo SHA1Update(context, (unsigned char *) "\0", 1); 286214501Srpaulo } 287214501Srpaulo SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() 288214501Srpaulo */ 289214501Srpaulo for (i = 0; i < 20; i++) { 290214501Srpaulo digest[i] = (unsigned char) 291214501Srpaulo ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 292214501Srpaulo 255); 293214501Srpaulo } 294214501Srpaulo /* Wipe variables */ 295214501Srpaulo i = 0; 296214501Srpaulo os_memset(context->buffer, 0, 64); 297214501Srpaulo os_memset(context->state, 0, 20); 298214501Srpaulo os_memset(context->count, 0, 8); 299214501Srpaulo os_memset(finalcount, 0, 8); 300214501Srpaulo} 301214501Srpaulo 302214501Srpaulo/* ===== end - public domain SHA1 implementation ===== */ 303