Blame view

lib/sha1.c 10.3 KB
566a494f5   Heiko Schocher   [PCS440EP] u...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  /*
   *  Heiko Schocher, DENX Software Engineering, hs@denx.de.
   *  based on:
   *  FIPS-180-1 compliant SHA-1 implementation
   *
   *  Copyright (C) 2003-2006  Christophe Devine
   *
   *  This library is free software; you can redistribute it and/or
   *  modify it under the terms of the GNU Lesser General Public
   *  License, version 2.1 as published by the Free Software Foundation.
   *
   *  This library is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   *  Lesser General Public License for more details.
   *
   *  You should have received a copy of the GNU Lesser General Public
   *  License along with this library; if not, write to the Free Software
   *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   *  MA  02110-1301  USA
   */
  /*
   *  The SHA-1 standard was published by NIST in 1993.
   *
   *  http://www.itl.nist.gov/fipspubs/fip180-1.htm
   */
  
  #ifndef _CRT_SECURE_NO_DEPRECATE
  #define _CRT_SECURE_NO_DEPRECATE 1
  #endif
7590378fb   Bartlomiej Sieka   Use watchdog-awar...
31
32
  #ifndef USE_HOSTCC
  #include <common.h>
a94f22f08   Andy Fleming   Fix build issue w...
33
  #include <linux/string.h>
338cc0384   Wolfgang Denk   tools/mkimage: fi...
34
35
  #else
  #include <string.h>
7590378fb   Bartlomiej Sieka   Use watchdog-awar...
36
37
  #endif /* USE_HOSTCC */
  #include <watchdog.h>
566a494f5   Heiko Schocher   [PCS440EP] u...
38
39
40
41
42
43
  #include "sha1.h"
  
  /*
   * 32-bit integer manipulation macros (big endian)
   */
  #ifndef GET_UINT32_BE
4ef218f6f   Wolfgang Denk   Coding style clea...
44
45
46
47
48
  #define GET_UINT32_BE(n,b,i) {				\
  	(n) = ( (unsigned long) (b)[(i)    ] << 24 )	\
  	    | ( (unsigned long) (b)[(i) + 1] << 16 )	\
  	    | ( (unsigned long) (b)[(i) + 2] <<  8 )	\
  	    | ( (unsigned long) (b)[(i) + 3]       );	\
566a494f5   Heiko Schocher   [PCS440EP] u...
49
50
51
  }
  #endif
  #ifndef PUT_UINT32_BE
4ef218f6f   Wolfgang Denk   Coding style clea...
52
53
54
55
56
  #define PUT_UINT32_BE(n,b,i) {				\
  	(b)[(i)    ] = (unsigned char) ( (n) >> 24 );	\
  	(b)[(i) + 1] = (unsigned char) ( (n) >> 16 );	\
  	(b)[(i) + 2] = (unsigned char) ( (n) >>  8 );	\
  	(b)[(i) + 3] = (unsigned char) ( (n)       );	\
566a494f5   Heiko Schocher   [PCS440EP] u...
57
58
59
60
61
62
  }
  #endif
  
  /*
   * SHA-1 context setup
   */
4ef218f6f   Wolfgang Denk   Coding style clea...
63
  void sha1_starts (sha1_context * ctx)
566a494f5   Heiko Schocher   [PCS440EP] u...
64
  {
4ef218f6f   Wolfgang Denk   Coding style clea...
65
66
67
68
69
70
71
72
  	ctx->total[0] = 0;
  	ctx->total[1] = 0;
  
  	ctx->state[0] = 0x67452301;
  	ctx->state[1] = 0xEFCDAB89;
  	ctx->state[2] = 0x98BADCFE;
  	ctx->state[3] = 0x10325476;
  	ctx->state[4] = 0xC3D2E1F0;
566a494f5   Heiko Schocher   [PCS440EP] u...
73
  }
a7d1d7657   Simon Glass   sha1: Use const w...
74
  static void sha1_process(sha1_context *ctx, const unsigned char data[64])
566a494f5   Heiko Schocher   [PCS440EP] u...
75
  {
4ef218f6f   Wolfgang Denk   Coding style clea...
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  	unsigned long temp, W[16], A, B, C, D, E;
  
  	GET_UINT32_BE (W[0], data, 0);
  	GET_UINT32_BE (W[1], data, 4);
  	GET_UINT32_BE (W[2], data, 8);
  	GET_UINT32_BE (W[3], data, 12);
  	GET_UINT32_BE (W[4], data, 16);
  	GET_UINT32_BE (W[5], data, 20);
  	GET_UINT32_BE (W[6], data, 24);
  	GET_UINT32_BE (W[7], data, 28);
  	GET_UINT32_BE (W[8], data, 32);
  	GET_UINT32_BE (W[9], data, 36);
  	GET_UINT32_BE (W[10], data, 40);
  	GET_UINT32_BE (W[11], data, 44);
  	GET_UINT32_BE (W[12], data, 48);
  	GET_UINT32_BE (W[13], data, 52);
  	GET_UINT32_BE (W[14], data, 56);
  	GET_UINT32_BE (W[15], data, 60);
  
  #define S(x,n)	((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
  
  #define R(t) (						\
  	temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^	\
  	       W[(t - 14) & 0x0F] ^ W[ t      & 0x0F],	\
  	( W[t & 0x0F] = S(temp,1) )			\
566a494f5   Heiko Schocher   [PCS440EP] u...
101
  )
4ef218f6f   Wolfgang Denk   Coding style clea...
102
103
  #define P(a,b,c,d,e,x)	{				\
  	e += S(a,5) + F(b,c,d) + K + x; b = S(b,30);	\
566a494f5   Heiko Schocher   [PCS440EP] u...
104
  }
4ef218f6f   Wolfgang Denk   Coding style clea...
105
106
107
108
109
  	A = ctx->state[0];
  	B = ctx->state[1];
  	C = ctx->state[2];
  	D = ctx->state[3];
  	E = ctx->state[4];
566a494f5   Heiko Schocher   [PCS440EP] u...
110
111
112
  
  #define F(x,y,z) (z ^ (x & (y ^ z)))
  #define K 0x5A827999
4ef218f6f   Wolfgang Denk   Coding style clea...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  	P (A, B, C, D, E, W[0]);
  	P (E, A, B, C, D, W[1]);
  	P (D, E, A, B, C, W[2]);
  	P (C, D, E, A, B, W[3]);
  	P (B, C, D, E, A, W[4]);
  	P (A, B, C, D, E, W[5]);
  	P (E, A, B, C, D, W[6]);
  	P (D, E, A, B, C, W[7]);
  	P (C, D, E, A, B, W[8]);
  	P (B, C, D, E, A, W[9]);
  	P (A, B, C, D, E, W[10]);
  	P (E, A, B, C, D, W[11]);
  	P (D, E, A, B, C, W[12]);
  	P (C, D, E, A, B, W[13]);
  	P (B, C, D, E, A, W[14]);
  	P (A, B, C, D, E, W[15]);
  	P (E, A, B, C, D, R (16));
  	P (D, E, A, B, C, R (17));
  	P (C, D, E, A, B, R (18));
  	P (B, C, D, E, A, R (19));
566a494f5   Heiko Schocher   [PCS440EP] u...
133
134
135
136
137
138
  
  #undef K
  #undef F
  
  #define F(x,y,z) (x ^ y ^ z)
  #define K 0x6ED9EBA1
4ef218f6f   Wolfgang Denk   Coding style clea...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  	P (A, B, C, D, E, R (20));
  	P (E, A, B, C, D, R (21));
  	P (D, E, A, B, C, R (22));
  	P (C, D, E, A, B, R (23));
  	P (B, C, D, E, A, R (24));
  	P (A, B, C, D, E, R (25));
  	P (E, A, B, C, D, R (26));
  	P (D, E, A, B, C, R (27));
  	P (C, D, E, A, B, R (28));
  	P (B, C, D, E, A, R (29));
  	P (A, B, C, D, E, R (30));
  	P (E, A, B, C, D, R (31));
  	P (D, E, A, B, C, R (32));
  	P (C, D, E, A, B, R (33));
  	P (B, C, D, E, A, R (34));
  	P (A, B, C, D, E, R (35));
  	P (E, A, B, C, D, R (36));
  	P (D, E, A, B, C, R (37));
  	P (C, D, E, A, B, R (38));
  	P (B, C, D, E, A, R (39));
566a494f5   Heiko Schocher   [PCS440EP] u...
159
160
161
162
163
164
  
  #undef K
  #undef F
  
  #define F(x,y,z) ((x & y) | (z & (x | y)))
  #define K 0x8F1BBCDC
4ef218f6f   Wolfgang Denk   Coding style clea...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  	P (A, B, C, D, E, R (40));
  	P (E, A, B, C, D, R (41));
  	P (D, E, A, B, C, R (42));
  	P (C, D, E, A, B, R (43));
  	P (B, C, D, E, A, R (44));
  	P (A, B, C, D, E, R (45));
  	P (E, A, B, C, D, R (46));
  	P (D, E, A, B, C, R (47));
  	P (C, D, E, A, B, R (48));
  	P (B, C, D, E, A, R (49));
  	P (A, B, C, D, E, R (50));
  	P (E, A, B, C, D, R (51));
  	P (D, E, A, B, C, R (52));
  	P (C, D, E, A, B, R (53));
  	P (B, C, D, E, A, R (54));
  	P (A, B, C, D, E, R (55));
  	P (E, A, B, C, D, R (56));
  	P (D, E, A, B, C, R (57));
  	P (C, D, E, A, B, R (58));
  	P (B, C, D, E, A, R (59));
566a494f5   Heiko Schocher   [PCS440EP] u...
185
186
187
188
189
190
  
  #undef K
  #undef F
  
  #define F(x,y,z) (x ^ y ^ z)
  #define K 0xCA62C1D6
4ef218f6f   Wolfgang Denk   Coding style clea...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  	P (A, B, C, D, E, R (60));
  	P (E, A, B, C, D, R (61));
  	P (D, E, A, B, C, R (62));
  	P (C, D, E, A, B, R (63));
  	P (B, C, D, E, A, R (64));
  	P (A, B, C, D, E, R (65));
  	P (E, A, B, C, D, R (66));
  	P (D, E, A, B, C, R (67));
  	P (C, D, E, A, B, R (68));
  	P (B, C, D, E, A, R (69));
  	P (A, B, C, D, E, R (70));
  	P (E, A, B, C, D, R (71));
  	P (D, E, A, B, C, R (72));
  	P (C, D, E, A, B, R (73));
  	P (B, C, D, E, A, R (74));
  	P (A, B, C, D, E, R (75));
  	P (E, A, B, C, D, R (76));
  	P (D, E, A, B, C, R (77));
  	P (C, D, E, A, B, R (78));
  	P (B, C, D, E, A, R (79));
566a494f5   Heiko Schocher   [PCS440EP] u...
211
212
213
  
  #undef K
  #undef F
4ef218f6f   Wolfgang Denk   Coding style clea...
214
215
216
217
218
  	ctx->state[0] += A;
  	ctx->state[1] += B;
  	ctx->state[2] += C;
  	ctx->state[3] += D;
  	ctx->state[4] += E;
566a494f5   Heiko Schocher   [PCS440EP] u...
219
220
221
222
223
  }
  
  /*
   * SHA-1 process buffer
   */
a7d1d7657   Simon Glass   sha1: Use const w...
224
225
  void sha1_update(sha1_context *ctx, const unsigned char *input,
  		 unsigned int ilen)
566a494f5   Heiko Schocher   [PCS440EP] u...
226
  {
4ef218f6f   Wolfgang Denk   Coding style clea...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  	int fill;
  	unsigned long left;
  
  	if (ilen <= 0)
  		return;
  
  	left = ctx->total[0] & 0x3F;
  	fill = 64 - left;
  
  	ctx->total[0] += ilen;
  	ctx->total[0] &= 0xFFFFFFFF;
  
  	if (ctx->total[0] < (unsigned long) ilen)
  		ctx->total[1]++;
  
  	if (left && ilen >= fill) {
  		memcpy ((void *) (ctx->buffer + left), (void *) input, fill);
  		sha1_process (ctx, ctx->buffer);
  		input += fill;
  		ilen -= fill;
  		left = 0;
  	}
  
  	while (ilen >= 64) {
  		sha1_process (ctx, input);
  		input += 64;
  		ilen -= 64;
  	}
  
  	if (ilen > 0) {
  		memcpy ((void *) (ctx->buffer + left), (void *) input, ilen);
  	}
566a494f5   Heiko Schocher   [PCS440EP] u...
259
  }
4ef218f6f   Wolfgang Denk   Coding style clea...
260
261
262
263
264
  static const unsigned char sha1_padding[64] = {
  	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
566a494f5   Heiko Schocher   [PCS440EP] u...
265
266
267
268
269
  };
  
  /*
   * SHA-1 final digest
   */
4ef218f6f   Wolfgang Denk   Coding style clea...
270
  void sha1_finish (sha1_context * ctx, unsigned char output[20])
566a494f5   Heiko Schocher   [PCS440EP] u...
271
  {
4ef218f6f   Wolfgang Denk   Coding style clea...
272
273
274
  	unsigned long last, padn;
  	unsigned long high, low;
  	unsigned char msglen[8];
566a494f5   Heiko Schocher   [PCS440EP] u...
275

4ef218f6f   Wolfgang Denk   Coding style clea...
276
277
278
  	high = (ctx->total[0] >> 29)
  		| (ctx->total[1] << 3);
  	low = (ctx->total[0] << 3);
566a494f5   Heiko Schocher   [PCS440EP] u...
279

4ef218f6f   Wolfgang Denk   Coding style clea...
280
281
  	PUT_UINT32_BE (high, msglen, 0);
  	PUT_UINT32_BE (low, msglen, 4);
566a494f5   Heiko Schocher   [PCS440EP] u...
282

4ef218f6f   Wolfgang Denk   Coding style clea...
283
284
  	last = ctx->total[0] & 0x3F;
  	padn = (last < 56) ? (56 - last) : (120 - last);
566a494f5   Heiko Schocher   [PCS440EP] u...
285

4ef218f6f   Wolfgang Denk   Coding style clea...
286
287
  	sha1_update (ctx, (unsigned char *) sha1_padding, padn);
  	sha1_update (ctx, msglen, 8);
566a494f5   Heiko Schocher   [PCS440EP] u...
288

4ef218f6f   Wolfgang Denk   Coding style clea...
289
290
291
292
293
  	PUT_UINT32_BE (ctx->state[0], output, 0);
  	PUT_UINT32_BE (ctx->state[1], output, 4);
  	PUT_UINT32_BE (ctx->state[2], output, 8);
  	PUT_UINT32_BE (ctx->state[3], output, 12);
  	PUT_UINT32_BE (ctx->state[4], output, 16);
566a494f5   Heiko Schocher   [PCS440EP] u...
294
295
296
297
298
  }
  
  /*
   * Output = SHA-1( input buffer )
   */
a7d1d7657   Simon Glass   sha1: Use const w...
299
300
  void sha1_csum(const unsigned char *input, unsigned int ilen,
  	       unsigned char *output)
566a494f5   Heiko Schocher   [PCS440EP] u...
301
  {
4ef218f6f   Wolfgang Denk   Coding style clea...
302
  	sha1_context ctx;
566a494f5   Heiko Schocher   [PCS440EP] u...
303

4ef218f6f   Wolfgang Denk   Coding style clea...
304
305
306
  	sha1_starts (&ctx);
  	sha1_update (&ctx, input, ilen);
  	sha1_finish (&ctx, output);
566a494f5   Heiko Schocher   [PCS440EP] u...
307
308
309
  }
  
  /*
215b01bba   Bartlomiej Sieka   Add support for c...
310
311
312
   * Output = SHA-1( input buffer ). Trigger the watchdog every 'chunk_sz'
   * bytes of input processed.
   */
a7d1d7657   Simon Glass   sha1: Use const w...
313
314
  void sha1_csum_wd(const unsigned char *input, unsigned int ilen,
  		  unsigned char *output, unsigned int chunk_sz)
215b01bba   Bartlomiej Sieka   Add support for c...
315
316
317
  {
  	sha1_context ctx;
  #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
a7d1d7657   Simon Glass   sha1: Use const w...
318
  	const unsigned char *end, *curr;
215b01bba   Bartlomiej Sieka   Add support for c...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  	int chunk;
  #endif
  
  	sha1_starts (&ctx);
  
  #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
  	curr = input;
  	end = input + ilen;
  	while (curr < end) {
  		chunk = end - curr;
  		if (chunk > chunk_sz)
  			chunk = chunk_sz;
  		sha1_update (&ctx, curr, chunk);
  		curr += chunk;
  		WATCHDOG_RESET ();
  	}
  #else
  	sha1_update (&ctx, input, ilen);
  #endif
  
  	sha1_finish (&ctx, output);
  }
  
  /*
566a494f5   Heiko Schocher   [PCS440EP] u...
343
344
   * Output = HMAC-SHA-1( input buffer, hmac key )
   */
a7d1d7657   Simon Glass   sha1: Use const w...
345
346
347
  void sha1_hmac(const unsigned char *key, int keylen,
  	       const unsigned char *input, unsigned int ilen,
  	       unsigned char *output)
566a494f5   Heiko Schocher   [PCS440EP] u...
348
  {
4ef218f6f   Wolfgang Denk   Coding style clea...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
  	int i;
  	sha1_context ctx;
  	unsigned char k_ipad[64];
  	unsigned char k_opad[64];
  	unsigned char tmpbuf[20];
  
  	memset (k_ipad, 0x36, 64);
  	memset (k_opad, 0x5C, 64);
  
  	for (i = 0; i < keylen; i++) {
  		if (i >= 64)
  			break;
  
  		k_ipad[i] ^= key[i];
  		k_opad[i] ^= key[i];
  	}
  
  	sha1_starts (&ctx);
  	sha1_update (&ctx, k_ipad, 64);
  	sha1_update (&ctx, input, ilen);
  	sha1_finish (&ctx, tmpbuf);
  
  	sha1_starts (&ctx);
  	sha1_update (&ctx, k_opad, 64);
  	sha1_update (&ctx, tmpbuf, 20);
  	sha1_finish (&ctx, output);
  
  	memset (k_ipad, 0, 64);
  	memset (k_opad, 0, 64);
  	memset (tmpbuf, 0, 20);
  	memset (&ctx, 0, sizeof (sha1_context));
566a494f5   Heiko Schocher   [PCS440EP] u...
380
381
382
383
384
385
386
387
  }
  
  static const char _sha1_src[] = "_sha1_src";
  
  #ifdef SELF_TEST
  /*
   * FIPS-180-1 test vectors
   */
4ef218f6f   Wolfgang Denk   Coding style clea...
388
389
390
391
  static const char sha1_test_str[3][57] = {
  	{"abc"},
  	{"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
  	{""}
566a494f5   Heiko Schocher   [PCS440EP] u...
392
  };
4ef218f6f   Wolfgang Denk   Coding style clea...
393
394
395
396
397
398
399
  static const unsigned char sha1_test_sum[3][20] = {
  	{0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
  	 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D},
  	{0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
  	 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1},
  	{0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
  	 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F}
566a494f5   Heiko Schocher   [PCS440EP] u...
400
401
402
403
404
  };
  
  /*
   * Checkup routine
   */
4ef218f6f   Wolfgang Denk   Coding style clea...
405
  int sha1_self_test (void)
566a494f5   Heiko Schocher   [PCS440EP] u...
406
  {
4ef218f6f   Wolfgang Denk   Coding style clea...
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
  	int i, j;
  	unsigned char buf[1000];
  	unsigned char sha1sum[20];
  	sha1_context ctx;
  
  	for (i = 0; i < 3; i++) {
  		printf ("  SHA-1 test #%d: ", i + 1);
  
  		sha1_starts (&ctx);
  
  		if (i < 2)
  			sha1_update (&ctx, (unsigned char *) sha1_test_str[i],
  				     strlen (sha1_test_str[i]));
  		else {
  			memset (buf, 'a', 1000);
  			for (j = 0; j < 1000; j++)
  				sha1_update (&ctx, buf, 1000);
  		}
  
  		sha1_finish (&ctx, sha1sum);
  
  		if (memcmp (sha1sum, sha1_test_sum[i], 20) != 0) {
  			printf ("failed
  ");
  			return (1);
  		}
  
  		printf ("passed
  ");
  	}
  
  	printf ("
  ");
  	return (0);
566a494f5   Heiko Schocher   [PCS440EP] u...
441
442
  }
  #else
4ef218f6f   Wolfgang Denk   Coding style clea...
443
  int sha1_self_test (void)
566a494f5   Heiko Schocher   [PCS440EP] u...
444
  {
4ef218f6f   Wolfgang Denk   Coding style clea...
445
  	return (0);
566a494f5   Heiko Schocher   [PCS440EP] u...
446
447
  }
  #endif