1e28a4053SRui Paulo /*
2e28a4053SRui Paulo * SHA1 hash implementation and interface functions
3e28a4053SRui Paulo * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
4e28a4053SRui Paulo *
5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo * See README for more details.
7e28a4053SRui Paulo */
8e28a4053SRui Paulo
9e28a4053SRui Paulo #include "includes.h"
10e28a4053SRui Paulo
11e28a4053SRui Paulo #include "common.h"
12e28a4053SRui Paulo #include "sha1.h"
13e28a4053SRui Paulo #include "sha1_i.h"
14e28a4053SRui Paulo #include "md5.h"
15e28a4053SRui Paulo #include "crypto.h"
16e28a4053SRui Paulo
17e28a4053SRui Paulo typedef struct SHA1Context SHA1_CTX;
18e28a4053SRui Paulo
19e28a4053SRui Paulo void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
20e28a4053SRui Paulo
21e28a4053SRui Paulo
225b9c547cSRui Paulo #ifdef CONFIG_CRYPTO_INTERNAL
23e28a4053SRui Paulo /**
24e28a4053SRui Paulo * sha1_vector - SHA-1 hash for data vector
25e28a4053SRui Paulo * @num_elem: Number of elements in the data vector
26e28a4053SRui Paulo * @addr: Pointers to the data areas
27e28a4053SRui Paulo * @len: Lengths of the data blocks
28e28a4053SRui Paulo * @mac: Buffer for the hash
29e28a4053SRui Paulo * Returns: 0 on success, -1 of failure
30e28a4053SRui Paulo */
sha1_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)31e28a4053SRui Paulo int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
32e28a4053SRui Paulo {
33e28a4053SRui Paulo SHA1_CTX ctx;
34e28a4053SRui Paulo size_t i;
35e28a4053SRui Paulo
36780fb4a2SCy Schubert if (TEST_FAIL())
37780fb4a2SCy Schubert return -1;
38780fb4a2SCy Schubert
39e28a4053SRui Paulo SHA1Init(&ctx);
40e28a4053SRui Paulo for (i = 0; i < num_elem; i++)
41e28a4053SRui Paulo SHA1Update(&ctx, addr[i], len[i]);
42e28a4053SRui Paulo SHA1Final(mac, &ctx);
43e28a4053SRui Paulo return 0;
44e28a4053SRui Paulo }
455b9c547cSRui Paulo #endif /* CONFIG_CRYPTO_INTERNAL */
46e28a4053SRui Paulo
47e28a4053SRui Paulo
48e28a4053SRui Paulo /* ===== start - public domain SHA1 implementation ===== */
49e28a4053SRui Paulo
50e28a4053SRui Paulo /*
51e28a4053SRui Paulo SHA-1 in C
52e28a4053SRui Paulo By Steve Reid <sreid@sea-to-sky.net>
53e28a4053SRui Paulo 100% Public Domain
54e28a4053SRui Paulo
55e28a4053SRui Paulo -----------------
56e28a4053SRui Paulo Modified 7/98
57e28a4053SRui Paulo By James H. Brown <jbrown@burgoyne.com>
58e28a4053SRui Paulo Still 100% Public Domain
59e28a4053SRui Paulo
60e28a4053SRui Paulo Corrected a problem which generated improper hash values on 16 bit machines
61e28a4053SRui Paulo Routine SHA1Update changed from
62e28a4053SRui Paulo void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
63e28a4053SRui Paulo len)
64e28a4053SRui Paulo to
65e28a4053SRui Paulo void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
66e28a4053SRui Paulo long len)
67e28a4053SRui Paulo
68e28a4053SRui Paulo The 'len' parameter was declared an int which works fine on 32 bit machines.
69e28a4053SRui Paulo However, on 16 bit machines an int is too small for the shifts being done
70e28a4053SRui Paulo against
71e28a4053SRui Paulo it. This caused the hash function to generate incorrect values if len was
72e28a4053SRui Paulo greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
73e28a4053SRui Paulo
74e28a4053SRui Paulo Since the file IO in main() reads 16K at a time, any file 8K or larger would
75e28a4053SRui Paulo be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
76e28a4053SRui Paulo "a"s).
77e28a4053SRui Paulo
78e28a4053SRui Paulo I also changed the declaration of variables i & j in SHA1Update to
79e28a4053SRui Paulo unsigned long from unsigned int for the same reason.
80e28a4053SRui Paulo
81e28a4053SRui Paulo These changes should make no difference to any 32 bit implementations since
82e28a4053SRui Paulo an
83e28a4053SRui Paulo int and a long are the same size in those environments.
84e28a4053SRui Paulo
85e28a4053SRui Paulo --
86e28a4053SRui Paulo I also corrected a few compiler warnings generated by Borland C.
87e28a4053SRui Paulo 1. Added #include <process.h> for exit() prototype
88e28a4053SRui Paulo 2. Removed unused variable 'j' in SHA1Final
89e28a4053SRui Paulo 3. Changed exit(0) to return(0) at end of main.
90e28a4053SRui Paulo
91e28a4053SRui Paulo ALL changes I made can be located by searching for comments containing 'JHB'
92e28a4053SRui Paulo -----------------
93e28a4053SRui Paulo Modified 8/98
94e28a4053SRui Paulo By Steve Reid <sreid@sea-to-sky.net>
95e28a4053SRui Paulo Still 100% public domain
96e28a4053SRui Paulo
97e28a4053SRui Paulo 1- Removed #include <process.h> and used return() instead of exit()
98e28a4053SRui Paulo 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
99e28a4053SRui Paulo 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
100e28a4053SRui Paulo
101e28a4053SRui Paulo -----------------
102e28a4053SRui Paulo Modified 4/01
103e28a4053SRui Paulo By Saul Kravitz <Saul.Kravitz@celera.com>
104e28a4053SRui Paulo Still 100% PD
105e28a4053SRui Paulo Modified to run on Compaq Alpha hardware.
106e28a4053SRui Paulo
107e28a4053SRui Paulo -----------------
108e28a4053SRui Paulo Modified 4/01
109e28a4053SRui Paulo By Jouni Malinen <j@w1.fi>
110e28a4053SRui Paulo Minor changes to match the coding style used in Dynamics.
111e28a4053SRui Paulo
112e28a4053SRui Paulo Modified September 24, 2004
113e28a4053SRui Paulo By Jouni Malinen <j@w1.fi>
114e28a4053SRui Paulo Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
115e28a4053SRui Paulo
116e28a4053SRui Paulo */
117e28a4053SRui Paulo
118e28a4053SRui Paulo /*
119e28a4053SRui Paulo Test Vectors (from FIPS PUB 180-1)
120e28a4053SRui Paulo "abc"
121e28a4053SRui Paulo A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
122e28a4053SRui Paulo "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
123e28a4053SRui Paulo 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
124e28a4053SRui Paulo A million repetitions of "a"
125e28a4053SRui Paulo 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
126e28a4053SRui Paulo */
127e28a4053SRui Paulo
128e28a4053SRui Paulo #define SHA1HANDSOFF
129e28a4053SRui Paulo
130e28a4053SRui Paulo #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
131e28a4053SRui Paulo
132e28a4053SRui Paulo /* blk0() and blk() perform the initial expand. */
133e28a4053SRui Paulo /* I got the idea of expanding during the round function from SSLeay */
134e28a4053SRui Paulo #ifndef WORDS_BIGENDIAN
135e28a4053SRui Paulo #define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
136e28a4053SRui Paulo (rol(block->l[i], 8) & 0x00FF00FF))
137e28a4053SRui Paulo #else
138e28a4053SRui Paulo #define blk0(i) block->l[i]
139e28a4053SRui Paulo #endif
140e28a4053SRui Paulo #define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
141e28a4053SRui Paulo block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
142e28a4053SRui Paulo
143e28a4053SRui Paulo /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
144e28a4053SRui Paulo #define R0(v,w,x,y,z,i) \
145e28a4053SRui Paulo z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
146e28a4053SRui Paulo w = rol(w, 30);
147e28a4053SRui Paulo #define R1(v,w,x,y,z,i) \
148e28a4053SRui Paulo z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
149e28a4053SRui Paulo w = rol(w, 30);
150e28a4053SRui Paulo #define R2(v,w,x,y,z,i) \
151e28a4053SRui Paulo z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
152e28a4053SRui Paulo #define R3(v,w,x,y,z,i) \
153e28a4053SRui Paulo z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
154e28a4053SRui Paulo w = rol(w, 30);
155e28a4053SRui Paulo #define R4(v,w,x,y,z,i) \
156e28a4053SRui Paulo z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
157e28a4053SRui Paulo w=rol(w, 30);
158e28a4053SRui Paulo
159e28a4053SRui Paulo
160e28a4053SRui Paulo #ifdef VERBOSE /* SAK */
SHAPrintContext(SHA1_CTX * context,char * msg)161e28a4053SRui Paulo void SHAPrintContext(SHA1_CTX *context, char *msg)
162e28a4053SRui Paulo {
163e28a4053SRui Paulo printf("%s (%d,%d) %x %x %x %x %x\n",
164e28a4053SRui Paulo msg,
165e28a4053SRui Paulo context->count[0], context->count[1],
166e28a4053SRui Paulo context->state[0],
167e28a4053SRui Paulo context->state[1],
168e28a4053SRui Paulo context->state[2],
169e28a4053SRui Paulo context->state[3],
170e28a4053SRui Paulo context->state[4]);
171e28a4053SRui Paulo }
172e28a4053SRui Paulo #endif
173e28a4053SRui Paulo
174e28a4053SRui Paulo /* Hash a single 512-bit block. This is the core of the algorithm. */
175e28a4053SRui Paulo
SHA1Transform(u32 state[5],const unsigned char buffer[64])176e28a4053SRui Paulo void SHA1Transform(u32 state[5], const unsigned char buffer[64])
177e28a4053SRui Paulo {
178e28a4053SRui Paulo u32 a, b, c, d, e;
179e28a4053SRui Paulo typedef union {
180e28a4053SRui Paulo unsigned char c[64];
181e28a4053SRui Paulo u32 l[16];
182e28a4053SRui Paulo } CHAR64LONG16;
183e28a4053SRui Paulo CHAR64LONG16* block;
184e28a4053SRui Paulo #ifdef SHA1HANDSOFF
185e28a4053SRui Paulo CHAR64LONG16 workspace;
186e28a4053SRui Paulo block = &workspace;
187e28a4053SRui Paulo os_memcpy(block, buffer, 64);
188e28a4053SRui Paulo #else
189e28a4053SRui Paulo block = (CHAR64LONG16 *) buffer;
190e28a4053SRui Paulo #endif
191e28a4053SRui Paulo /* Copy context->state[] to working vars */
192e28a4053SRui Paulo a = state[0];
193e28a4053SRui Paulo b = state[1];
194e28a4053SRui Paulo c = state[2];
195e28a4053SRui Paulo d = state[3];
196e28a4053SRui Paulo e = state[4];
197e28a4053SRui Paulo /* 4 rounds of 20 operations each. Loop unrolled. */
198e28a4053SRui Paulo 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);
199e28a4053SRui Paulo 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);
200e28a4053SRui Paulo 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);
201e28a4053SRui Paulo 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);
202e28a4053SRui Paulo 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);
203e28a4053SRui Paulo 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);
204e28a4053SRui Paulo 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);
205e28a4053SRui Paulo 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);
206e28a4053SRui Paulo 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);
207e28a4053SRui Paulo 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);
208e28a4053SRui Paulo 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);
209e28a4053SRui Paulo 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);
210e28a4053SRui Paulo 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);
211e28a4053SRui Paulo 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);
212e28a4053SRui Paulo 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);
213e28a4053SRui Paulo 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);
214e28a4053SRui Paulo 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);
215e28a4053SRui Paulo 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);
216e28a4053SRui Paulo 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);
217e28a4053SRui Paulo 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);
218e28a4053SRui Paulo /* Add the working vars back into context.state[] */
219e28a4053SRui Paulo state[0] += a;
220e28a4053SRui Paulo state[1] += b;
221e28a4053SRui Paulo state[2] += c;
222e28a4053SRui Paulo state[3] += d;
223e28a4053SRui Paulo state[4] += e;
224e28a4053SRui Paulo /* Wipe variables */
225e28a4053SRui Paulo a = b = c = d = e = 0;
226e28a4053SRui Paulo #ifdef SHA1HANDSOFF
227*206b73d0SCy Schubert forced_memzero(block, 64);
228e28a4053SRui Paulo #endif
229e28a4053SRui Paulo }
230e28a4053SRui Paulo
231e28a4053SRui Paulo
232e28a4053SRui Paulo /* SHA1Init - Initialize new context */
233e28a4053SRui Paulo
SHA1Init(SHA1_CTX * context)234e28a4053SRui Paulo void SHA1Init(SHA1_CTX* context)
235e28a4053SRui Paulo {
236e28a4053SRui Paulo /* SHA1 initialization constants */
237e28a4053SRui Paulo context->state[0] = 0x67452301;
238e28a4053SRui Paulo context->state[1] = 0xEFCDAB89;
239e28a4053SRui Paulo context->state[2] = 0x98BADCFE;
240e28a4053SRui Paulo context->state[3] = 0x10325476;
241e28a4053SRui Paulo context->state[4] = 0xC3D2E1F0;
242e28a4053SRui Paulo context->count[0] = context->count[1] = 0;
243e28a4053SRui Paulo }
244e28a4053SRui Paulo
245e28a4053SRui Paulo
246e28a4053SRui Paulo /* Run your data through this. */
247e28a4053SRui Paulo
SHA1Update(SHA1_CTX * context,const void * _data,u32 len)248e28a4053SRui Paulo void SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
249e28a4053SRui Paulo {
250e28a4053SRui Paulo u32 i, j;
251e28a4053SRui Paulo const unsigned char *data = _data;
252e28a4053SRui Paulo
253e28a4053SRui Paulo #ifdef VERBOSE
254e28a4053SRui Paulo SHAPrintContext(context, "before");
255e28a4053SRui Paulo #endif
256e28a4053SRui Paulo j = (context->count[0] >> 3) & 63;
257e28a4053SRui Paulo if ((context->count[0] += len << 3) < (len << 3))
258e28a4053SRui Paulo context->count[1]++;
259e28a4053SRui Paulo context->count[1] += (len >> 29);
260e28a4053SRui Paulo if ((j + len) > 63) {
261e28a4053SRui Paulo os_memcpy(&context->buffer[j], data, (i = 64-j));
262e28a4053SRui Paulo SHA1Transform(context->state, context->buffer);
263e28a4053SRui Paulo for ( ; i + 63 < len; i += 64) {
264e28a4053SRui Paulo SHA1Transform(context->state, &data[i]);
265e28a4053SRui Paulo }
266e28a4053SRui Paulo j = 0;
267e28a4053SRui Paulo }
268e28a4053SRui Paulo else i = 0;
269e28a4053SRui Paulo os_memcpy(&context->buffer[j], &data[i], len - i);
270e28a4053SRui Paulo #ifdef VERBOSE
271e28a4053SRui Paulo SHAPrintContext(context, "after ");
272e28a4053SRui Paulo #endif
273e28a4053SRui Paulo }
274e28a4053SRui Paulo
275e28a4053SRui Paulo
276e28a4053SRui Paulo /* Add padding and return the message digest. */
277e28a4053SRui Paulo
SHA1Final(unsigned char digest[20],SHA1_CTX * context)278e28a4053SRui Paulo void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
279e28a4053SRui Paulo {
280e28a4053SRui Paulo u32 i;
281e28a4053SRui Paulo unsigned char finalcount[8];
282e28a4053SRui Paulo
283e28a4053SRui Paulo for (i = 0; i < 8; i++) {
284e28a4053SRui Paulo finalcount[i] = (unsigned char)
285e28a4053SRui Paulo ((context->count[(i >= 4 ? 0 : 1)] >>
286e28a4053SRui Paulo ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
287e28a4053SRui Paulo }
288e28a4053SRui Paulo SHA1Update(context, (unsigned char *) "\200", 1);
289e28a4053SRui Paulo while ((context->count[0] & 504) != 448) {
290e28a4053SRui Paulo SHA1Update(context, (unsigned char *) "\0", 1);
291e28a4053SRui Paulo }
292e28a4053SRui Paulo SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform()
293e28a4053SRui Paulo */
294e28a4053SRui Paulo for (i = 0; i < 20; i++) {
295e28a4053SRui Paulo digest[i] = (unsigned char)
296e28a4053SRui Paulo ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
297e28a4053SRui Paulo 255);
298e28a4053SRui Paulo }
299e28a4053SRui Paulo /* Wipe variables */
300e28a4053SRui Paulo os_memset(context->buffer, 0, 64);
301e28a4053SRui Paulo os_memset(context->state, 0, 20);
302e28a4053SRui Paulo os_memset(context->count, 0, 8);
303*206b73d0SCy Schubert forced_memzero(finalcount, sizeof(finalcount));
304e28a4053SRui Paulo }
305e28a4053SRui Paulo
306e28a4053SRui Paulo /* ===== end - public domain SHA1 implementation ===== */
307