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