blob: 69506592f7148b2fa39dfffc75895c03118cded0 [file] [log] [blame]
Heiko Schocher566a4942007-06-22 19:11:54 +02001/*
2 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
3 * based on:
4 * FIPS-180-1 compliant SHA-1 implementation
5 *
6 * Copyright (C) 2003-2006 Christophe Devine
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License, version 2.1 as published by the Free Software Foundation.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301 USA
21 */
22/*
23 * The SHA-1 standard was published by NIST in 1993.
24 *
25 * http://www.itl.nist.gov/fipspubs/fip180-1.htm
26 */
27
28#ifndef _CRT_SECURE_NO_DEPRECATE
29#define _CRT_SECURE_NO_DEPRECATE 1
30#endif
31
32#include <linux/string.h>
33#include "sha1.h"
34
35/*
36 * 32-bit integer manipulation macros (big endian)
37 */
38#ifndef GET_UINT32_BE
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020039#define GET_UINT32_BE(n,b,i) { \
40 (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
41 | ( (unsigned long) (b)[(i) + 1] << 16 ) \
42 | ( (unsigned long) (b)[(i) + 2] << 8 ) \
43 | ( (unsigned long) (b)[(i) + 3] ); \
Heiko Schocher566a4942007-06-22 19:11:54 +020044}
45#endif
46#ifndef PUT_UINT32_BE
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020047#define PUT_UINT32_BE(n,b,i) { \
48 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
49 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
50 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
51 (b)[(i) + 3] = (unsigned char) ( (n) ); \
Heiko Schocher566a4942007-06-22 19:11:54 +020052}
53#endif
54
55/*
56 * SHA-1 context setup
57 */
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020058void sha1_starts (sha1_context * ctx)
Heiko Schocher566a4942007-06-22 19:11:54 +020059{
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020060 ctx->total[0] = 0;
61 ctx->total[1] = 0;
Heiko Schocher566a4942007-06-22 19:11:54 +020062
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020063 ctx->state[0] = 0x67452301;
64 ctx->state[1] = 0xEFCDAB89;
65 ctx->state[2] = 0x98BADCFE;
66 ctx->state[3] = 0x10325476;
67 ctx->state[4] = 0xC3D2E1F0;
Heiko Schocher566a4942007-06-22 19:11:54 +020068}
69
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020070static void sha1_process (sha1_context * ctx, unsigned char data[64])
Heiko Schocher566a4942007-06-22 19:11:54 +020071{
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020072 unsigned long temp, W[16], A, B, C, D, E;
Heiko Schocher566a4942007-06-22 19:11:54 +020073
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020074 GET_UINT32_BE (W[0], data, 0);
75 GET_UINT32_BE (W[1], data, 4);
76 GET_UINT32_BE (W[2], data, 8);
77 GET_UINT32_BE (W[3], data, 12);
78 GET_UINT32_BE (W[4], data, 16);
79 GET_UINT32_BE (W[5], data, 20);
80 GET_UINT32_BE (W[6], data, 24);
81 GET_UINT32_BE (W[7], data, 28);
82 GET_UINT32_BE (W[8], data, 32);
83 GET_UINT32_BE (W[9], data, 36);
84 GET_UINT32_BE (W[10], data, 40);
85 GET_UINT32_BE (W[11], data, 44);
86 GET_UINT32_BE (W[12], data, 48);
87 GET_UINT32_BE (W[13], data, 52);
88 GET_UINT32_BE (W[14], data, 56);
89 GET_UINT32_BE (W[15], data, 60);
Heiko Schocher566a4942007-06-22 19:11:54 +020090
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020091#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
Heiko Schocher566a4942007-06-22 19:11:54 +020092
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020093#define R(t) ( \
94 temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
95 W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
96 ( W[t & 0x0F] = S(temp,1) ) \
Heiko Schocher566a4942007-06-22 19:11:54 +020097)
98
Wolfgang Denk4ef218f2007-07-10 00:01:28 +020099#define P(a,b,c,d,e,x) { \
100 e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
Heiko Schocher566a4942007-06-22 19:11:54 +0200101}
102
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200103 A = ctx->state[0];
104 B = ctx->state[1];
105 C = ctx->state[2];
106 D = ctx->state[3];
107 E = ctx->state[4];
Heiko Schocher566a4942007-06-22 19:11:54 +0200108
109#define F(x,y,z) (z ^ (x & (y ^ z)))
110#define K 0x5A827999
111
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200112 P (A, B, C, D, E, W[0]);
113 P (E, A, B, C, D, W[1]);
114 P (D, E, A, B, C, W[2]);
115 P (C, D, E, A, B, W[3]);
116 P (B, C, D, E, A, W[4]);
117 P (A, B, C, D, E, W[5]);
118 P (E, A, B, C, D, W[6]);
119 P (D, E, A, B, C, W[7]);
120 P (C, D, E, A, B, W[8]);
121 P (B, C, D, E, A, W[9]);
122 P (A, B, C, D, E, W[10]);
123 P (E, A, B, C, D, W[11]);
124 P (D, E, A, B, C, W[12]);
125 P (C, D, E, A, B, W[13]);
126 P (B, C, D, E, A, W[14]);
127 P (A, B, C, D, E, W[15]);
128 P (E, A, B, C, D, R (16));
129 P (D, E, A, B, C, R (17));
130 P (C, D, E, A, B, R (18));
131 P (B, C, D, E, A, R (19));
Heiko Schocher566a4942007-06-22 19:11:54 +0200132
133#undef K
134#undef F
135
136#define F(x,y,z) (x ^ y ^ z)
137#define K 0x6ED9EBA1
138
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200139 P (A, B, C, D, E, R (20));
140 P (E, A, B, C, D, R (21));
141 P (D, E, A, B, C, R (22));
142 P (C, D, E, A, B, R (23));
143 P (B, C, D, E, A, R (24));
144 P (A, B, C, D, E, R (25));
145 P (E, A, B, C, D, R (26));
146 P (D, E, A, B, C, R (27));
147 P (C, D, E, A, B, R (28));
148 P (B, C, D, E, A, R (29));
149 P (A, B, C, D, E, R (30));
150 P (E, A, B, C, D, R (31));
151 P (D, E, A, B, C, R (32));
152 P (C, D, E, A, B, R (33));
153 P (B, C, D, E, A, R (34));
154 P (A, B, C, D, E, R (35));
155 P (E, A, B, C, D, R (36));
156 P (D, E, A, B, C, R (37));
157 P (C, D, E, A, B, R (38));
158 P (B, C, D, E, A, R (39));
Heiko Schocher566a4942007-06-22 19:11:54 +0200159
160#undef K
161#undef F
162
163#define F(x,y,z) ((x & y) | (z & (x | y)))
164#define K 0x8F1BBCDC
165
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200166 P (A, B, C, D, E, R (40));
167 P (E, A, B, C, D, R (41));
168 P (D, E, A, B, C, R (42));
169 P (C, D, E, A, B, R (43));
170 P (B, C, D, E, A, R (44));
171 P (A, B, C, D, E, R (45));
172 P (E, A, B, C, D, R (46));
173 P (D, E, A, B, C, R (47));
174 P (C, D, E, A, B, R (48));
175 P (B, C, D, E, A, R (49));
176 P (A, B, C, D, E, R (50));
177 P (E, A, B, C, D, R (51));
178 P (D, E, A, B, C, R (52));
179 P (C, D, E, A, B, R (53));
180 P (B, C, D, E, A, R (54));
181 P (A, B, C, D, E, R (55));
182 P (E, A, B, C, D, R (56));
183 P (D, E, A, B, C, R (57));
184 P (C, D, E, A, B, R (58));
185 P (B, C, D, E, A, R (59));
Heiko Schocher566a4942007-06-22 19:11:54 +0200186
187#undef K
188#undef F
189
190#define F(x,y,z) (x ^ y ^ z)
191#define K 0xCA62C1D6
192
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200193 P (A, B, C, D, E, R (60));
194 P (E, A, B, C, D, R (61));
195 P (D, E, A, B, C, R (62));
196 P (C, D, E, A, B, R (63));
197 P (B, C, D, E, A, R (64));
198 P (A, B, C, D, E, R (65));
199 P (E, A, B, C, D, R (66));
200 P (D, E, A, B, C, R (67));
201 P (C, D, E, A, B, R (68));
202 P (B, C, D, E, A, R (69));
203 P (A, B, C, D, E, R (70));
204 P (E, A, B, C, D, R (71));
205 P (D, E, A, B, C, R (72));
206 P (C, D, E, A, B, R (73));
207 P (B, C, D, E, A, R (74));
208 P (A, B, C, D, E, R (75));
209 P (E, A, B, C, D, R (76));
210 P (D, E, A, B, C, R (77));
211 P (C, D, E, A, B, R (78));
212 P (B, C, D, E, A, R (79));
Heiko Schocher566a4942007-06-22 19:11:54 +0200213
214#undef K
215#undef F
216
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200217 ctx->state[0] += A;
218 ctx->state[1] += B;
219 ctx->state[2] += C;
220 ctx->state[3] += D;
221 ctx->state[4] += E;
Heiko Schocher566a4942007-06-22 19:11:54 +0200222}
223
224/*
225 * SHA-1 process buffer
226 */
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200227void sha1_update (sha1_context * ctx, unsigned char *input, int ilen)
Heiko Schocher566a4942007-06-22 19:11:54 +0200228{
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200229 int fill;
230 unsigned long left;
Heiko Schocher566a4942007-06-22 19:11:54 +0200231
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200232 if (ilen <= 0)
233 return;
Heiko Schocher566a4942007-06-22 19:11:54 +0200234
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200235 left = ctx->total[0] & 0x3F;
236 fill = 64 - left;
Heiko Schocher566a4942007-06-22 19:11:54 +0200237
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200238 ctx->total[0] += ilen;
239 ctx->total[0] &= 0xFFFFFFFF;
Heiko Schocher566a4942007-06-22 19:11:54 +0200240
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200241 if (ctx->total[0] < (unsigned long) ilen)
242 ctx->total[1]++;
Heiko Schocher566a4942007-06-22 19:11:54 +0200243
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200244 if (left && ilen >= fill) {
245 memcpy ((void *) (ctx->buffer + left), (void *) input, fill);
246 sha1_process (ctx, ctx->buffer);
247 input += fill;
248 ilen -= fill;
249 left = 0;
250 }
Heiko Schocher566a4942007-06-22 19:11:54 +0200251
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200252 while (ilen >= 64) {
253 sha1_process (ctx, input);
254 input += 64;
255 ilen -= 64;
256 }
Heiko Schocher566a4942007-06-22 19:11:54 +0200257
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200258 if (ilen > 0) {
259 memcpy ((void *) (ctx->buffer + left), (void *) input, ilen);
260 }
Heiko Schocher566a4942007-06-22 19:11:54 +0200261}
262
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200263static const unsigned char sha1_padding[64] = {
264 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
265 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Heiko Schocher566a4942007-06-22 19:11:54 +0200268};
269
270/*
271 * SHA-1 final digest
272 */
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200273void sha1_finish (sha1_context * ctx, unsigned char output[20])
Heiko Schocher566a4942007-06-22 19:11:54 +0200274{
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200275 unsigned long last, padn;
276 unsigned long high, low;
277 unsigned char msglen[8];
Heiko Schocher566a4942007-06-22 19:11:54 +0200278
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200279 high = (ctx->total[0] >> 29)
280 | (ctx->total[1] << 3);
281 low = (ctx->total[0] << 3);
Heiko Schocher566a4942007-06-22 19:11:54 +0200282
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200283 PUT_UINT32_BE (high, msglen, 0);
284 PUT_UINT32_BE (low, msglen, 4);
Heiko Schocher566a4942007-06-22 19:11:54 +0200285
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200286 last = ctx->total[0] & 0x3F;
287 padn = (last < 56) ? (56 - last) : (120 - last);
Heiko Schocher566a4942007-06-22 19:11:54 +0200288
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200289 sha1_update (ctx, (unsigned char *) sha1_padding, padn);
290 sha1_update (ctx, msglen, 8);
Heiko Schocher566a4942007-06-22 19:11:54 +0200291
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200292 PUT_UINT32_BE (ctx->state[0], output, 0);
293 PUT_UINT32_BE (ctx->state[1], output, 4);
294 PUT_UINT32_BE (ctx->state[2], output, 8);
295 PUT_UINT32_BE (ctx->state[3], output, 12);
296 PUT_UINT32_BE (ctx->state[4], output, 16);
Heiko Schocher566a4942007-06-22 19:11:54 +0200297}
298
299/*
300 * Output = SHA-1( input buffer )
301 */
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200302void sha1_csum (unsigned char *input, int ilen, unsigned char output[20])
Heiko Schocher566a4942007-06-22 19:11:54 +0200303{
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200304 sha1_context ctx;
Heiko Schocher566a4942007-06-22 19:11:54 +0200305
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200306 sha1_starts (&ctx);
307 sha1_update (&ctx, input, ilen);
308 sha1_finish (&ctx, output);
Heiko Schocher566a4942007-06-22 19:11:54 +0200309}
310
311/*
Bartlomiej Sieka215b01b2008-04-22 12:27:56 +0200312 * Output = SHA-1( input buffer ). Trigger the watchdog every 'chunk_sz'
313 * bytes of input processed.
314 */
315void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20],
316 unsigned int chunk_sz)
317{
318 sha1_context ctx;
319#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
320 unsigned char *end, *curr;
321 int chunk;
322#endif
323
324 sha1_starts (&ctx);
325
326#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
327 curr = input;
328 end = input + ilen;
329 while (curr < end) {
330 chunk = end - curr;
331 if (chunk > chunk_sz)
332 chunk = chunk_sz;
333 sha1_update (&ctx, curr, chunk);
334 curr += chunk;
335 WATCHDOG_RESET ();
336 }
337#else
338 sha1_update (&ctx, input, ilen);
339#endif
340
341 sha1_finish (&ctx, output);
342}
343
344/*
Heiko Schocher566a4942007-06-22 19:11:54 +0200345 * Output = HMAC-SHA-1( input buffer, hmac key )
346 */
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200347void sha1_hmac (unsigned char *key, int keylen,
348 unsigned char *input, int ilen, unsigned char output[20])
Heiko Schocher566a4942007-06-22 19:11:54 +0200349{
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200350 int i;
351 sha1_context ctx;
352 unsigned char k_ipad[64];
353 unsigned char k_opad[64];
354 unsigned char tmpbuf[20];
Heiko Schocher566a4942007-06-22 19:11:54 +0200355
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200356 memset (k_ipad, 0x36, 64);
357 memset (k_opad, 0x5C, 64);
Heiko Schocher566a4942007-06-22 19:11:54 +0200358
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200359 for (i = 0; i < keylen; i++) {
360 if (i >= 64)
361 break;
Heiko Schocher566a4942007-06-22 19:11:54 +0200362
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200363 k_ipad[i] ^= key[i];
364 k_opad[i] ^= key[i];
365 }
Heiko Schocher566a4942007-06-22 19:11:54 +0200366
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200367 sha1_starts (&ctx);
368 sha1_update (&ctx, k_ipad, 64);
369 sha1_update (&ctx, input, ilen);
370 sha1_finish (&ctx, tmpbuf);
Heiko Schocher566a4942007-06-22 19:11:54 +0200371
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200372 sha1_starts (&ctx);
373 sha1_update (&ctx, k_opad, 64);
374 sha1_update (&ctx, tmpbuf, 20);
375 sha1_finish (&ctx, output);
Heiko Schocher566a4942007-06-22 19:11:54 +0200376
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200377 memset (k_ipad, 0, 64);
378 memset (k_opad, 0, 64);
379 memset (tmpbuf, 0, 20);
380 memset (&ctx, 0, sizeof (sha1_context));
Heiko Schocher566a4942007-06-22 19:11:54 +0200381}
382
383static const char _sha1_src[] = "_sha1_src";
384
385#ifdef SELF_TEST
386/*
387 * FIPS-180-1 test vectors
388 */
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200389static const char sha1_test_str[3][57] = {
390 {"abc"},
391 {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
392 {""}
Heiko Schocher566a4942007-06-22 19:11:54 +0200393};
394
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200395static const unsigned char sha1_test_sum[3][20] = {
396 {0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
397 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D},
398 {0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
399 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1},
400 {0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
401 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F}
Heiko Schocher566a4942007-06-22 19:11:54 +0200402};
403
404/*
405 * Checkup routine
406 */
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200407int sha1_self_test (void)
Heiko Schocher566a4942007-06-22 19:11:54 +0200408{
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200409 int i, j;
410 unsigned char buf[1000];
411 unsigned char sha1sum[20];
412 sha1_context ctx;
Heiko Schocher566a4942007-06-22 19:11:54 +0200413
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200414 for (i = 0; i < 3; i++) {
415 printf (" SHA-1 test #%d: ", i + 1);
Heiko Schocher566a4942007-06-22 19:11:54 +0200416
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200417 sha1_starts (&ctx);
Heiko Schocher566a4942007-06-22 19:11:54 +0200418
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200419 if (i < 2)
420 sha1_update (&ctx, (unsigned char *) sha1_test_str[i],
421 strlen (sha1_test_str[i]));
422 else {
423 memset (buf, 'a', 1000);
424 for (j = 0; j < 1000; j++)
425 sha1_update (&ctx, buf, 1000);
426 }
Heiko Schocher566a4942007-06-22 19:11:54 +0200427
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200428 sha1_finish (&ctx, sha1sum);
Heiko Schocher566a4942007-06-22 19:11:54 +0200429
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200430 if (memcmp (sha1sum, sha1_test_sum[i], 20) != 0) {
431 printf ("failed\n");
432 return (1);
433 }
Heiko Schocher566a4942007-06-22 19:11:54 +0200434
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200435 printf ("passed\n");
436 }
Heiko Schocher566a4942007-06-22 19:11:54 +0200437
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200438 printf ("\n");
439 return (0);
Heiko Schocher566a4942007-06-22 19:11:54 +0200440}
441#else
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200442int sha1_self_test (void)
Heiko Schocher566a4942007-06-22 19:11:54 +0200443{
Wolfgang Denk4ef218f2007-07-10 00:01:28 +0200444 return (0);
Heiko Schocher566a4942007-06-22 19:11:54 +0200445}
446#endif