blob: 0dea14672ba5ce6323f9d64fa87e380fb167dd43 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
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#ifndef USE_HOSTCC
33#include <common.h>
34#include <linux/string.h>
35#else
36#include <string.h>
37#endif /* USE_HOSTCC */
38#include <watchdog.h>
39#include "sha1.h"
40
41asmlinkage int neon_en_check(void);
42asmlinkage void neon_enable(void);
43asmlinkage void neon_disable(void);
44asmlinkage void sha1_transform_neon(void *state_h, const char *data,
45 unsigned int rounds);
46
47/*
48 * 32-bit integer manipulation macros (big endian)
49 */
50#ifndef PUT_UINT32_BE
51#define PUT_UINT32_BE(n,b,i) { \
52 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
53 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
54 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
55 (b)[(i) + 3] = (unsigned char) ( (n) ); \
56}
57#endif
58
59/*
60 * SHA-1 context setup
61 */
62void sha1_starts (sha1_context * ctx)
63{
64 ctx->total[0] = 0;
65 ctx->total[1] = 0;
66
67 ctx->state[0] = 0x67452301;
68 ctx->state[1] = 0xEFCDAB89;
69 ctx->state[2] = 0x98BADCFE;
70 ctx->state[3] = 0x10325476;
71 ctx->state[4] = 0xC3D2E1F0;
72}
73
74static inline void sha1_process(sha1_context *ctx,
75 const unsigned char *data, uint32_t blks)
76{
77 int neon_en = neon_en_check();
78
79 if (!neon_en)
80 neon_enable();
81
82 sha1_transform_neon(ctx->state, data, blks);
83
84 if (!neon_en)
85 neon_disable();
86}
87
88/*
89 * SHA-1 process buffer
90 */
91void sha1_update(sha1_context *ctx, const unsigned char *input,
92 unsigned int ilen)
93{
94 int fill;
95 unsigned long left;
96 uint32_t blks;
97
98 if (ilen <= 0)
99 return;
100
101 left = ctx->total[0] & 0x3F;
102 fill = 64 - left;
103
104 ctx->total[0] += ilen;
105 ctx->total[0] &= 0xFFFFFFFF;
106
107 if (ctx->total[0] < (unsigned long) ilen)
108 ctx->total[1]++;
109
110 if (left && ilen >= fill) {
111 memcpy ((void *) (ctx->buffer + left), (void *) input, fill);
112 sha1_process (ctx, ctx->buffer, 1);
113 input += fill;
114 ilen -= fill;
115 left = 0;
116 }
117
118 blks = ilen / 64;
119 while (ilen >= 64) {
120 sha1_process (ctx, input, blks);
121 input += 64 * blks;
122 ilen -= 64 * blks;
123 }
124
125 if (ilen > 0) {
126 memcpy ((void *) (ctx->buffer + left), (void *) input, ilen);
127 }
128}
129
130static const unsigned char sha1_padding[64] = {
131 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
135};
136
137/*
138 * SHA-1 final digest
139 */
140void sha1_finish (sha1_context * ctx, unsigned char output[20])
141{
142 unsigned long last, padn;
143 unsigned long high, low;
144 unsigned char msglen[8];
145
146 high = (ctx->total[0] >> 29)
147 | (ctx->total[1] << 3);
148 low = (ctx->total[0] << 3);
149
150 PUT_UINT32_BE (high, msglen, 0);
151 PUT_UINT32_BE (low, msglen, 4);
152
153 last = ctx->total[0] & 0x3F;
154 padn = (last < 56) ? (56 - last) : (120 - last);
155
156 sha1_update (ctx, (unsigned char *) sha1_padding, padn);
157 sha1_update (ctx, msglen, 8);
158
159 PUT_UINT32_BE (ctx->state[0], output, 0);
160 PUT_UINT32_BE (ctx->state[1], output, 4);
161 PUT_UINT32_BE (ctx->state[2], output, 8);
162 PUT_UINT32_BE (ctx->state[3], output, 12);
163 PUT_UINT32_BE (ctx->state[4], output, 16);
164}
165
166/*
167 * Output = SHA-1( input buffer )
168 */
169void sha1_csum(const unsigned char *input, unsigned int ilen,
170 unsigned char *output)
171{
172 sha1_context ctx;
173
174 sha1_starts (&ctx);
175 sha1_update (&ctx, input, ilen);
176 sha1_finish (&ctx, output);
177}
178
179/*
180 * Output = SHA-1( input buffer ). Trigger the watchdog every 'chunk_sz'
181 * bytes of input processed.
182 */
183void sha1_csum_wd(const unsigned char *input, unsigned int ilen,
184 unsigned char *output, unsigned int chunk_sz)
185{
186 sha1_context ctx;
187#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
188 const unsigned char *end, *curr;
189 int chunk;
190#endif
191
192 sha1_starts (&ctx);
193
194#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
195 curr = input;
196 end = input + ilen;
197 while (curr < end) {
198 chunk = end - curr;
199 if (chunk > chunk_sz)
200 chunk = chunk_sz;
201 sha1_update (&ctx, curr, chunk);
202 curr += chunk;
203 WATCHDOG_RESET ();
204 }
205#else
206 sha1_update (&ctx, input, ilen);
207#endif
208
209 sha1_finish (&ctx, output);
210}
211
212/*
213 * Output = HMAC-SHA-1( input buffer, hmac key )
214 */
215void sha1_hmac(const unsigned char *key, int keylen,
216 const unsigned char *input, unsigned int ilen,
217 unsigned char *output)
218{
219 int i;
220 sha1_context ctx;
221 unsigned char k_ipad[64];
222 unsigned char k_opad[64];
223 unsigned char tmpbuf[20];
224
225 memset (k_ipad, 0x36, 64);
226 memset (k_opad, 0x5C, 64);
227
228 for (i = 0; i < keylen; i++) {
229 if (i >= 64)
230 break;
231
232 k_ipad[i] ^= key[i];
233 k_opad[i] ^= key[i];
234 }
235
236 sha1_starts (&ctx);
237 sha1_update (&ctx, k_ipad, 64);
238 sha1_update (&ctx, input, ilen);
239 sha1_finish (&ctx, tmpbuf);
240
241 sha1_starts (&ctx);
242 sha1_update (&ctx, k_opad, 64);
243 sha1_update (&ctx, tmpbuf, 20);
244 sha1_finish (&ctx, output);
245
246 memset (k_ipad, 0, 64);
247 memset (k_opad, 0, 64);
248 memset (tmpbuf, 0, 20);
249 memset (&ctx, 0, sizeof (sha1_context));
250}
251
252static const char _sha1_src[] = "_sha1_src";
253
254#ifdef SELF_TEST
255/*
256 * FIPS-180-1 test vectors
257 */
258static const char sha1_test_str[3][57] = {
259 {"abc"},
260 {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
261 {""}
262};
263
264static const unsigned char sha1_test_sum[3][20] = {
265 {0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
266 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D},
267 {0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
268 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1},
269 {0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
270 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F}
271};
272
273/*
274 * Checkup routine
275 */
276int sha1_self_test (void)
277{
278 int i, j;
279 unsigned char buf[1000];
280 unsigned char sha1sum[20];
281 sha1_context ctx;
282
283 for (i = 0; i < 3; i++) {
284 printf (" SHA-1 test #%d: ", i + 1);
285
286 sha1_starts (&ctx);
287
288 if (i < 2)
289 sha1_update (&ctx, (unsigned char *) sha1_test_str[i],
290 strlen (sha1_test_str[i]));
291 else {
292 memset (buf, 'a', 1000);
293 for (j = 0; j < 1000; j++)
294 sha1_update (&ctx, buf, 1000);
295 }
296
297 sha1_finish (&ctx, sha1sum);
298
299 if (memcmp (sha1sum, sha1_test_sum[i], 20) != 0) {
300 printf ("failed\n");
301 return (1);
302 }
303
304 printf ("passed\n");
305 }
306
307 printf ("\n");
308 return (0);
309}
310#else
311int sha1_self_test (void)
312{
313 return (0);
314}
315#endif