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