xref: /netbsd-src/external/bsd/wpa/dist/src/crypto/sha1-internal.c (revision 3d6c0713cbbf51a549dcd172f2c1ea93f7781249)
18dbcf02cSchristos /*
28dbcf02cSchristos  * SHA1 hash implementation and interface functions
38dbcf02cSchristos  * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
48dbcf02cSchristos  *
5e604d861Schristos  * This software may be distributed under the terms of the BSD license.
6e604d861Schristos  * See README for more details.
78dbcf02cSchristos  */
88dbcf02cSchristos 
98dbcf02cSchristos #include "includes.h"
108dbcf02cSchristos 
118dbcf02cSchristos #include "common.h"
128dbcf02cSchristos #include "sha1.h"
138dbcf02cSchristos #include "sha1_i.h"
148dbcf02cSchristos #include "md5.h"
158dbcf02cSchristos #include "crypto.h"
168dbcf02cSchristos 
178dbcf02cSchristos typedef struct SHA1Context SHA1_CTX;
188dbcf02cSchristos 
198dbcf02cSchristos void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
208dbcf02cSchristos 
218dbcf02cSchristos 
223c260e60Schristos #ifdef CONFIG_CRYPTO_INTERNAL
238dbcf02cSchristos /**
248dbcf02cSchristos  * sha1_vector - SHA-1 hash for data vector
258dbcf02cSchristos  * @num_elem: Number of elements in the data vector
268dbcf02cSchristos  * @addr: Pointers to the data areas
278dbcf02cSchristos  * @len: Lengths of the data blocks
288dbcf02cSchristos  * @mac: Buffer for the hash
298dbcf02cSchristos  * Returns: 0 on success, -1 of failure
308dbcf02cSchristos  */
sha1_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)318dbcf02cSchristos int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
328dbcf02cSchristos {
338dbcf02cSchristos 	SHA1_CTX ctx;
348dbcf02cSchristos 	size_t i;
358dbcf02cSchristos 
3636ebd06eSchristos 	if (TEST_FAIL())
3736ebd06eSchristos 		return -1;
3836ebd06eSchristos 
398dbcf02cSchristos 	SHA1Init(&ctx);
408dbcf02cSchristos 	for (i = 0; i < num_elem; i++)
418dbcf02cSchristos 		SHA1Update(&ctx, addr[i], len[i]);
428dbcf02cSchristos 	SHA1Final(mac, &ctx);
438dbcf02cSchristos 	return 0;
448dbcf02cSchristos }
453c260e60Schristos #endif /* CONFIG_CRYPTO_INTERNAL */
468dbcf02cSchristos 
478dbcf02cSchristos 
488dbcf02cSchristos /* ===== start - public domain SHA1 implementation ===== */
498dbcf02cSchristos 
508dbcf02cSchristos /*
518dbcf02cSchristos SHA-1 in C
528dbcf02cSchristos By Steve Reid <sreid@sea-to-sky.net>
538dbcf02cSchristos 100% Public Domain
548dbcf02cSchristos 
558dbcf02cSchristos -----------------
568dbcf02cSchristos Modified 7/98
578dbcf02cSchristos By James H. Brown <jbrown@burgoyne.com>
588dbcf02cSchristos Still 100% Public Domain
598dbcf02cSchristos 
608dbcf02cSchristos Corrected a problem which generated improper hash values on 16 bit machines
618dbcf02cSchristos Routine SHA1Update changed from
628dbcf02cSchristos 	void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
638dbcf02cSchristos len)
648dbcf02cSchristos to
658dbcf02cSchristos 	void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
668dbcf02cSchristos long len)
678dbcf02cSchristos 
688dbcf02cSchristos The 'len' parameter was declared an int which works fine on 32 bit machines.
698dbcf02cSchristos However, on 16 bit machines an int is too small for the shifts being done
708dbcf02cSchristos against
718dbcf02cSchristos it.  This caused the hash function to generate incorrect values if len was
728dbcf02cSchristos greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
738dbcf02cSchristos 
748dbcf02cSchristos Since the file IO in main() reads 16K at a time, any file 8K or larger would
758dbcf02cSchristos be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
768dbcf02cSchristos "a"s).
778dbcf02cSchristos 
788dbcf02cSchristos I also changed the declaration of variables i & j in SHA1Update to
798dbcf02cSchristos unsigned long from unsigned int for the same reason.
808dbcf02cSchristos 
818dbcf02cSchristos These changes should make no difference to any 32 bit implementations since
828dbcf02cSchristos an
838dbcf02cSchristos int and a long are the same size in those environments.
848dbcf02cSchristos 
858dbcf02cSchristos --
868dbcf02cSchristos I also corrected a few compiler warnings generated by Borland C.
878dbcf02cSchristos 1. Added #include <process.h> for exit() prototype
888dbcf02cSchristos 2. Removed unused variable 'j' in SHA1Final
898dbcf02cSchristos 3. Changed exit(0) to return(0) at end of main.
908dbcf02cSchristos 
918dbcf02cSchristos ALL changes I made can be located by searching for comments containing 'JHB'
928dbcf02cSchristos -----------------
938dbcf02cSchristos Modified 8/98
948dbcf02cSchristos By Steve Reid <sreid@sea-to-sky.net>
958dbcf02cSchristos Still 100% public domain
968dbcf02cSchristos 
978dbcf02cSchristos 1- Removed #include <process.h> and used return() instead of exit()
988dbcf02cSchristos 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
998dbcf02cSchristos 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
1008dbcf02cSchristos 
1018dbcf02cSchristos -----------------
1028dbcf02cSchristos Modified 4/01
1038dbcf02cSchristos By Saul Kravitz <Saul.Kravitz@celera.com>
1048dbcf02cSchristos Still 100% PD
1058dbcf02cSchristos Modified to run on Compaq Alpha hardware.
1068dbcf02cSchristos 
1078dbcf02cSchristos -----------------
1088dbcf02cSchristos Modified 4/01
1098dbcf02cSchristos By Jouni Malinen <j@w1.fi>
1108dbcf02cSchristos Minor changes to match the coding style used in Dynamics.
1118dbcf02cSchristos 
1128dbcf02cSchristos Modified September 24, 2004
1138dbcf02cSchristos By Jouni Malinen <j@w1.fi>
1148dbcf02cSchristos Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
1158dbcf02cSchristos 
1168dbcf02cSchristos */
1178dbcf02cSchristos 
1188dbcf02cSchristos /*
1198dbcf02cSchristos Test Vectors (from FIPS PUB 180-1)
1208dbcf02cSchristos "abc"
1218dbcf02cSchristos   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
1228dbcf02cSchristos "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
1238dbcf02cSchristos   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
1248dbcf02cSchristos A million repetitions of "a"
1258dbcf02cSchristos   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
1268dbcf02cSchristos */
1278dbcf02cSchristos 
1288dbcf02cSchristos #define SHA1HANDSOFF
1298dbcf02cSchristos 
1308dbcf02cSchristos #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
1318dbcf02cSchristos 
1328dbcf02cSchristos /* blk0() and blk() perform the initial expand. */
1338dbcf02cSchristos /* I got the idea of expanding during the round function from SSLeay */
1348dbcf02cSchristos #ifndef WORDS_BIGENDIAN
1358dbcf02cSchristos #define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
1368dbcf02cSchristos 	(rol(block->l[i], 8) & 0x00FF00FF))
1378dbcf02cSchristos #else
1388dbcf02cSchristos #define blk0(i) block->l[i]
1398dbcf02cSchristos #endif
1408dbcf02cSchristos #define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
1418dbcf02cSchristos 	block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
1428dbcf02cSchristos 
1438dbcf02cSchristos /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
1448dbcf02cSchristos #define R0(v,w,x,y,z,i) \
1458dbcf02cSchristos 	z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
1468dbcf02cSchristos 	w = rol(w, 30);
1478dbcf02cSchristos #define R1(v,w,x,y,z,i) \
1488dbcf02cSchristos 	z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
1498dbcf02cSchristos 	w = rol(w, 30);
1508dbcf02cSchristos #define R2(v,w,x,y,z,i) \
1518dbcf02cSchristos 	z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
1528dbcf02cSchristos #define R3(v,w,x,y,z,i) \
1538dbcf02cSchristos 	z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
1548dbcf02cSchristos 	w = rol(w, 30);
1558dbcf02cSchristos #define R4(v,w,x,y,z,i) \
1568dbcf02cSchristos 	z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
1578dbcf02cSchristos 	w=rol(w, 30);
1588dbcf02cSchristos 
1598dbcf02cSchristos 
1608dbcf02cSchristos #ifdef VERBOSE  /* SAK */
SHAPrintContext(SHA1_CTX * context,char * msg)1618dbcf02cSchristos void SHAPrintContext(SHA1_CTX *context, char *msg)
1628dbcf02cSchristos {
1638dbcf02cSchristos 	printf("%s (%d,%d) %x %x %x %x %x\n",
1648dbcf02cSchristos 	       msg,
1658dbcf02cSchristos 	       context->count[0], context->count[1],
1668dbcf02cSchristos 	       context->state[0],
1678dbcf02cSchristos 	       context->state[1],
1688dbcf02cSchristos 	       context->state[2],
1698dbcf02cSchristos 	       context->state[3],
1708dbcf02cSchristos 	       context->state[4]);
1718dbcf02cSchristos }
1728dbcf02cSchristos #endif
1738dbcf02cSchristos 
1748dbcf02cSchristos /* Hash a single 512-bit block. This is the core of the algorithm. */
1758dbcf02cSchristos 
SHA1Transform(u32 state[5],const unsigned char buffer[64])1768dbcf02cSchristos void SHA1Transform(u32 state[5], const unsigned char buffer[64])
1778dbcf02cSchristos {
1788dbcf02cSchristos 	u32 a, b, c, d, e;
1798dbcf02cSchristos 	typedef union {
1808dbcf02cSchristos 		unsigned char c[64];
1818dbcf02cSchristos 		u32 l[16];
1828dbcf02cSchristos 	} CHAR64LONG16;
1838dbcf02cSchristos 	CHAR64LONG16* block;
1848dbcf02cSchristos #ifdef SHA1HANDSOFF
1858dbcf02cSchristos 	CHAR64LONG16 workspace;
1868dbcf02cSchristos 	block = &workspace;
1878dbcf02cSchristos 	os_memcpy(block, buffer, 64);
1888dbcf02cSchristos #else
1898dbcf02cSchristos 	block = (CHAR64LONG16 *) buffer;
1908dbcf02cSchristos #endif
1918dbcf02cSchristos 	/* Copy context->state[] to working vars */
1928dbcf02cSchristos 	a = state[0];
1938dbcf02cSchristos 	b = state[1];
1948dbcf02cSchristos 	c = state[2];
1958dbcf02cSchristos 	d = state[3];
1968dbcf02cSchristos 	e = state[4];
1978dbcf02cSchristos 	/* 4 rounds of 20 operations each. Loop unrolled. */
1988dbcf02cSchristos 	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);
1998dbcf02cSchristos 	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);
2008dbcf02cSchristos 	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);
2018dbcf02cSchristos 	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);
2028dbcf02cSchristos 	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);
2038dbcf02cSchristos 	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);
2048dbcf02cSchristos 	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);
2058dbcf02cSchristos 	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);
2068dbcf02cSchristos 	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);
2078dbcf02cSchristos 	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);
2088dbcf02cSchristos 	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);
2098dbcf02cSchristos 	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);
2108dbcf02cSchristos 	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);
2118dbcf02cSchristos 	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);
2128dbcf02cSchristos 	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);
2138dbcf02cSchristos 	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);
2148dbcf02cSchristos 	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);
2158dbcf02cSchristos 	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);
2168dbcf02cSchristos 	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);
2178dbcf02cSchristos 	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);
2188dbcf02cSchristos 	/* Add the working vars back into context.state[] */
2198dbcf02cSchristos 	state[0] += a;
2208dbcf02cSchristos 	state[1] += b;
2218dbcf02cSchristos 	state[2] += c;
2228dbcf02cSchristos 	state[3] += d;
2238dbcf02cSchristos 	state[4] += e;
2248dbcf02cSchristos 	/* Wipe variables */
2258dbcf02cSchristos 	a = b = c = d = e = 0;
2268dbcf02cSchristos #ifdef SHA1HANDSOFF
227*3d6c0713Schristos 	forced_memzero(block, 64);
2288dbcf02cSchristos #endif
2298dbcf02cSchristos }
2308dbcf02cSchristos 
2318dbcf02cSchristos 
2328dbcf02cSchristos /* SHA1Init - Initialize new context */
2338dbcf02cSchristos 
SHA1Init(SHA1_CTX * context)2348dbcf02cSchristos void SHA1Init(SHA1_CTX* context)
2358dbcf02cSchristos {
2368dbcf02cSchristos 	/* SHA1 initialization constants */
2378dbcf02cSchristos 	context->state[0] = 0x67452301;
2388dbcf02cSchristos 	context->state[1] = 0xEFCDAB89;
2398dbcf02cSchristos 	context->state[2] = 0x98BADCFE;
2408dbcf02cSchristos 	context->state[3] = 0x10325476;
2418dbcf02cSchristos 	context->state[4] = 0xC3D2E1F0;
2428dbcf02cSchristos 	context->count[0] = context->count[1] = 0;
2438dbcf02cSchristos }
2448dbcf02cSchristos 
2458dbcf02cSchristos 
2468dbcf02cSchristos /* Run your data through this. */
2478dbcf02cSchristos 
SHA1Update(SHA1_CTX * context,const void * _data,u32 len)2488dbcf02cSchristos void SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
2498dbcf02cSchristos {
2508dbcf02cSchristos 	u32 i, j;
2518dbcf02cSchristos 	const unsigned char *data = _data;
2528dbcf02cSchristos 
2538dbcf02cSchristos #ifdef VERBOSE
2548dbcf02cSchristos 	SHAPrintContext(context, "before");
2558dbcf02cSchristos #endif
2568dbcf02cSchristos 	j = (context->count[0] >> 3) & 63;
2578dbcf02cSchristos 	if ((context->count[0] += len << 3) < (len << 3))
2588dbcf02cSchristos 		context->count[1]++;
2598dbcf02cSchristos 	context->count[1] += (len >> 29);
2608dbcf02cSchristos 	if ((j + len) > 63) {
2618dbcf02cSchristos 		os_memcpy(&context->buffer[j], data, (i = 64-j));
2628dbcf02cSchristos 		SHA1Transform(context->state, context->buffer);
2638dbcf02cSchristos 		for ( ; i + 63 < len; i += 64) {
2648dbcf02cSchristos 			SHA1Transform(context->state, &data[i]);
2658dbcf02cSchristos 		}
2668dbcf02cSchristos 		j = 0;
2678dbcf02cSchristos 	}
2688dbcf02cSchristos 	else i = 0;
2698dbcf02cSchristos 	os_memcpy(&context->buffer[j], &data[i], len - i);
2708dbcf02cSchristos #ifdef VERBOSE
2718dbcf02cSchristos 	SHAPrintContext(context, "after ");
2728dbcf02cSchristos #endif
2738dbcf02cSchristos }
2748dbcf02cSchristos 
2758dbcf02cSchristos 
2768dbcf02cSchristos /* Add padding and return the message digest. */
2778dbcf02cSchristos 
SHA1Final(unsigned char digest[20],SHA1_CTX * context)2788dbcf02cSchristos void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
2798dbcf02cSchristos {
2808dbcf02cSchristos 	u32 i;
2818dbcf02cSchristos 	unsigned char finalcount[8];
2828dbcf02cSchristos 
2838dbcf02cSchristos 	for (i = 0; i < 8; i++) {
2848dbcf02cSchristos 		finalcount[i] = (unsigned char)
2858dbcf02cSchristos 			((context->count[(i >= 4 ? 0 : 1)] >>
2868dbcf02cSchristos 			  ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
2878dbcf02cSchristos 	}
2888dbcf02cSchristos 	SHA1Update(context, (unsigned char *) "\200", 1);
2898dbcf02cSchristos 	while ((context->count[0] & 504) != 448) {
2908dbcf02cSchristos 		SHA1Update(context, (unsigned char *) "\0", 1);
2918dbcf02cSchristos 	}
2928dbcf02cSchristos 	SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform()
2938dbcf02cSchristos 					      */
2948dbcf02cSchristos 	for (i = 0; i < 20; i++) {
2958dbcf02cSchristos 		digest[i] = (unsigned char)
2968dbcf02cSchristos 			((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
2978dbcf02cSchristos 			 255);
2988dbcf02cSchristos 	}
2998dbcf02cSchristos 	/* Wipe variables */
3008dbcf02cSchristos 	os_memset(context->buffer, 0, 64);
3018dbcf02cSchristos 	os_memset(context->state, 0, 20);
3028dbcf02cSchristos 	os_memset(context->count, 0, 8);
303*3d6c0713Schristos 	forced_memzero(finalcount, sizeof(finalcount));
3048dbcf02cSchristos }
3058dbcf02cSchristos 
3068dbcf02cSchristos /* ===== end - public domain SHA1 implementation ===== */
307