blob: 59b7c9ec3483f4040027153d80c8ae4c5a34c738 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#include <common.h>
2#include <sha256.h>
3#include <config.h>
4#include <asm/arch/cpu.h>
5#include <asm/io.h>
6#include <malloc.h>
7#include <sha256.h>
8#include "asr_bcm.h"
9#include "asr_hash.h"
10
11static hash_state md;
12
13static void hash_sw_reset(void)
14{
15 uint32_t val;
16
17 val = (0x1 << 0x3);
18 bcm_write32(HASH_CONTROL, val);
19 val = 0x0;
20 bcm_write32(HASH_CONTROL, val);
21
22 return;
23}
24
25static int hash_set_mode(HASH_MODE_T mode, HASH_ALGO_T algo)
26{
27 uint32_t val;
28
29 val = bcm_read32(HASH_CONFIG);
30 val &= ~0xf;
31 val |= algo;
32 if (mode == HASH_HMAC)
33 val |= (0x1 << 0x3);
34 bcm_write32(HASH_CONFIG, val);
35
36 return 0;
37}
38
39static int hash_kick(void)
40{
41 uint32_t val;
42 uint32_t cnt;
43
44 val = bcm_read32(HASH_COMMAND);
45 val |= (0x1 << 0x0);
46 bcm_write32(HASH_COMMAND, val);
47
48 cnt = 1;
49 /* wait for command */
50
51 do {
52 val = bcm_read32(HASH_STATUS);
53 if (cnt == 1000000) {
54 printf("hash kick wait busy %u times..0x%08x\n", cnt, val);
55 return -1;
56 }
57 val &= 0xE;
58 udelay(1);
59 cnt++;
60 } while(val != 0);
61
62 cnt = 1;
63 do {
64 val = bcm_read32(HASH_STATUS);
65 if (cnt == 1000000) {
66 printf("hash kick wait busy %u times..0x%08x\n", cnt, val);
67 return -1;
68 }
69 val &= 0x1;
70 udelay(1);
71 cnt++;
72 } while(val == 0);
73
74 /* clear status so next command can be issued */
75 bcm_write32(HASH_STATUS, val);
76
77 return 0;
78}
79
80static int hash_config_op(HASH_OP_MODE_T op_mode)
81{
82 uint32_t val;
83 int ret = 0;
84
85 if (op_mode < HASH_INIT || op_mode > HASH_FINAL)
86 return -1;
87
88 val = bcm_read32(HASH_CONTROL);
89 val &= ~(0x3 << 0x0);
90 val |= op_mode;
91 bcm_write32(HASH_CONTROL, val);
92
93 ret = hash_kick();
94 return ret;
95}
96
97static int hash_save_context(hash_state *md, int alg)
98{
99 int i;
100 switch(alg) {
101 case HASH_SHA384:
102 case HASH_SHA512:
103 for (i = 0; i < 8; i++) {
104 md->sha512.state[i] = bcm_read32(HASH_DIGEST(i));
105 md->sha512.state[i+8] = bcm_read32(HASH_DIGEST_H(i));
106 }
107 break;
108 case HASH_SHA256:
109 case HASH_SHA224:
110 for (i = 0; i < 8; i++) {
111 md->sha256.state[i] = bcm_read32(HASH_DIGEST(i));
112 }
113 break;
114 case HASH_SHA1:
115 for (i = 0; i < 5; i++) {
116 md->sha1.state[i] = bcm_read32(HASH_DIGEST(i));
117 }
118 break;
119 case HASH_MD5:
120 for (i = 0; i < 4; i++) {
121 md->md5.state[i] = bcm_read32(HASH_DIGEST(i));
122 }
123 break;
124 default:
125 printf("hash save context: invalid alg!\r\n");
126 return -1;
127 }
128 return 0;
129}
130
131static int hash_restore_context(hash_state *md, int alg)
132{
133 int i;
134 switch(alg) {
135 case HASH_SHA384:
136 case HASH_SHA512:
137 for (i = 0; i < 8; i++) {
138 bcm_write32(HASH_DIGEST(i), md->sha512.state[i]);
139 bcm_write32(HASH_DIGEST_H(i), md->sha512.state[i+8]);
140 }
141 break;
142 case HASH_SHA256:
143 case HASH_SHA224:
144 for (i = 0; i < 8; i++) {
145 bcm_write32(HASH_DIGEST(i), md->sha256.state[i]);
146 }
147 break;
148 case HASH_SHA1:
149 for (i = 0; i < 5; i++) {
150 bcm_write32(HASH_DIGEST(i), md->sha1.state[i]);
151 }
152 break;
153 case HASH_MD5:
154 for (i = 0; i < 4; i++) {
155 bcm_write32(HASH_DIGEST(i), md->md5.state[i]);
156 }
157 break;
158 default:
159 printf("hash restore context: invalid alg!\r\n");
160 return -1;
161 }
162
163 return 0;
164}
165
166static int hash_compress_aligned(hash_state *md, int alg, uint8_t *in, int data_len)
167{
168 int ret = 0;
169 if (((uint32_t)in & 0x3) || (data_len == 0))
170 return -1;
171
172 adec_engine_hw_reset(ACC_ENG_DMA);
173 abus_set_mode(ABUS_GRP_A_HASH, ABUS_GRP_B_AES, ABUS_CROSS, ABUS_STRAIGHT);
174 dma_input_config(0, 0);
175 ret = hash_restore_context(md, alg);
176 if (ret)
177 goto error;
178
179 ret = dma_input_address((uint32_t)virt_to_phys((void *)in), \
180 ROUND_UP_TO_WORD_CNT(data_len), 0);
181 if (ret)
182 goto error;
183
184 flush_dcache_range(in, (uint32_t)in + 4*ROUND_UP_TO_WORD_CNT(data_len));
185 dma_input_start();
186 bcm_write32(HASH_INCOME_SEG_SZ, data_len);
187 ret = hash_config_op(HASH_UPDATE);
188 if (ret) {
189 dma_input_stop();
190 goto error;
191 }
192
193 dma_wait_input_finish();
194 dma_input_stop();
195
196 ret = hash_save_context(md, alg);
197 if (ret)
198 goto error;
199
200error:
201 return ret;
202}
203
204static int hash_compress(hash_state *md, int alg, uint8_t *in, int blks, int blk_sz)
205{
206 uint8_t *dma_in = NULL;
207 int data_len = blks * blk_sz;
208 int ret, n;
209 uint8_t *ptr_in;
210
211 if (((uint32_t)in & 0x3) == 0) {
212 dma_in = in;
213 ret = hash_compress_aligned(md, alg, dma_in, data_len);
214 return ret;
215 }
216
217 n = MIN(data_len, HASH_ALIGN_BUF_SIZE);
218 dma_in = (uint8_t *)malloc(n + 0x10);
219 if (!dma_in) {
220 ret = -1;
221 goto exit;
222 }
223 dma_in = (uint8_t *)(((uint32_t)(dma_in)) & (~0x3));
224
225 ptr_in = in;
226 do {
227 n = MIN(data_len, HASH_ALIGN_BUF_SIZE);
228 memcpy((void *)dma_in, (void *)ptr_in, n);
229 ret = hash_compress_aligned(md, alg, dma_in, n);
230 if (ret) {
231 goto exit;
232 }
233 data_len -= n;
234 ptr_in +=n;
235 } while(data_len > 0);
236
237exit:
238 if (dma_in)
239 free(dma_in);
240 return ret;
241}
242
243static int hash_tail_process(hash_state *md, uint8_t *out, int out_size, \
244 uint64_t total_size, int tail_size, unsigned char *dma_addr, int alg)
245{
246 int ret = 0;
247 int reg_val, i;
248
249 adec_engine_hw_reset(ACC_ENG_DMA);
250 abus_set_mode(ABUS_GRP_A_HASH, ABUS_GRP_B_AES, ABUS_CROSS, ABUS_STRAIGHT);
251 dma_input_config(0, 0);
252 ret = hash_restore_context(md, alg);
253 if (ret)
254 goto error;
255
256 ret = dma_input_address((uint32_t)virt_to_phys((void *)dma_addr), \
257 ROUND_UP_TO_WORD_CNT(tail_size), 0);
258 if (ret)
259 goto error;
260
261 if (tail_size) {
262 flush_dcache_range(dma_addr, (uint32_t)dma_addr + 4*ROUND_UP_TO_WORD_CNT(tail_size));
263 dma_input_start();
264 }
265
266 bcm_write32(HASH_INCOME_SEG_SZ, tail_size);
267 bcm_write32(HASH_TOTAL_MSG_SZ_L, (total_size & 0xffffffff));
268 bcm_write32(HASH_TOTAL_MSG_SZ_H, (total_size >> 32));
269
270 reg_val = bcm_read32(HASH_CONTROL);
271 reg_val |= (0x1 << 0x2);
272 bcm_write32(HASH_CONTROL, reg_val);
273
274 ret = hash_config_op(HASH_FINAL);
275 if (ret) {
276 if (tail_size)
277 dma_input_stop();
278 goto error;
279 }
280
281 if (tail_size) {
282 dma_wait_input_finish();
283 dma_input_stop();
284 }
285
286 /* copy digest out */
287 if (alg == HASH_SHA384 || alg == HASH_SHA512) {
288 for (i = 0; i < (out_size / 8); i++) {
289 reg_val = bcm_read32(HASH_DIGEST(i));
290 out[4 + i * 8] = (uint8_t)(reg_val & 0xFF);
291 out[5 + i * 8] = (uint8_t)((reg_val >> 8) & 0xFF);
292 out[6 + i * 8] = (uint8_t)((reg_val >> 16) & 0xFF);
293 out[7 + i * 8] = (uint8_t)((reg_val >> 24) & 0xFF);
294 reg_val = bcm_read32(HASH_DIGEST_H(i));
295 out[0 + i * 8] = (uint8_t)(reg_val & 0xFF);
296 out[1 + i * 8] = (uint8_t)((reg_val >> 8) & 0xFF);
297 out[2 + i * 8] = (uint8_t)((reg_val >> 16) & 0xFF);
298 out[3 + i * 8] = (uint8_t)((reg_val >> 24) & 0xFF);
299 }
300 } else {
301 for (i = 0; i < (out_size / 4); i++) {
302 reg_val = bcm_read32(HASH_DIGEST(i));
303 out[0 + i * 4] = (uint8_t)(reg_val & 0xFF);
304 out[1 + i * 4] = (uint8_t)((reg_val >> 8) & 0xFF);
305 out[2 + i * 4] = (uint8_t)((reg_val >> 16) & 0xFF);
306 out[3 + i * 4] = (uint8_t)((reg_val >> 24) & 0xFF);
307 }
308 }
309
310error:
311 bcm_enable(0);
312 return ret;
313}
314
315static int hash_init(hash_state *md, int alg)
316{
317 int ret;
318 if (md) {
319 memset(md, 0, sizeof(hash_state));
320 md->block_size = BLOCK_ALGIN_SIZE;
321 } else
322 return -1;
323
324 bcm_enable(1);
325 adec_engine_hw_reset(ACC_ENG_HASH);
326 hash_sw_reset();
327
328 ret = hash_set_mode(HASH_SIMPLE, alg);
329 if (ret)
330 goto error;
331 ret = hash_config_op(HASH_INIT);
332 if (ret)
333 goto error;
334 ret = hash_save_context(md, alg);
335 if (ret)
336 goto error;
337
338 return 0;
339
340error:
341 bcm_enable(0);
342 return ret;
343}
344
345/* Only block algnie is processed at a time */
346static int hash_process(hash_state *md, int alg, uint8_t *in, uint32_t inlen)
347{
348 uint32_t n, blocks;
349 int err;
350 if (md->curlen > sizeof(md->buf)) {
351 return -1;
352 }
353
354 while (inlen > 0) {
355 if (md->curlen == 0 && inlen >= md->block_size) {
356 blocks = inlen / md->block_size;
357 err = hash_compress(md, alg, in, blocks, md->block_size);
358 if (err)
359 return err;
360 md->length += blocks * md->block_size * 8;
361 in += blocks * md->block_size;
362 inlen -= blocks * md->block_size;
363 } else {
364 n = MIN(inlen, (md->block_size - md->curlen));
365 memcpy(md->buf + md->curlen, in, n);
366 md->curlen += n;
367 in += n;
368 inlen -= n;
369 if (md->curlen == md->block_size) {
370 err = hash_compress(md, alg, in, md->buf, md->block_size);
371 if (err)
372 return err;
373 md->length += 8*md->block_size;
374 md->curlen = 0;
375 }
376 }
377 }
378
379 return 0;
380}
381
382static int hash_done(hash_state *md, int alg, uint8_t *out)
383{
384 uint32_t out_len;
385
386 switch(alg) {
387 case HASH_SHA512:
388 out_len = HASH_LEN_SHA512;
389 break;
390 case HASH_SHA384:
391 out_len = HASH_LEN_SHA384;
392 break;
393 case HASH_SHA256:
394 out_len = HASH_LEN_SHA256;
395 break;
396 case HASH_SHA224:
397 out_len = HASH_LEN_SHA224;
398 break;
399 case HASH_SHA1:
400 out_len = HASH_LEN_SHA1;
401 break;
402 case HASH_MD5:
403 out_len = HASH_LEN_MD5;
404 break;
405 default:
406 printf("err: not support hash alg\n");
407 return -1;
408 }
409
410 return hash_tail_process(md, out, out_len, \
411 (md->length / 8 + md->curlen), md->curlen, md->buf, alg);
412}
413
414void sha256_starts_bcm(sha256_context *ctx)
415{
416 hash_init(&md, HASH_SHA256);
417 return;
418}
419
420void sha256_update_bcm(sha256_context *ctx, const uint8_t *input, uint32_t length)
421{
422 hash_process(&md, HASH_SHA256, input, length);
423 return;
424}
425
426void sha256_finish_bcm(sha256_context *ctx, uint8_t digest[32])
427{
428 hash_done(&md, HASH_SHA256, digest);
429 return;
430}
431
432#ifdef BCM_HASH_SELFTEST
433static int hash_handle(int alg, uint8_t *in, uint32_t inlen, uint8_t *out)
434{
435 int ret = 0;
436
437 ret = hash_init(&md, alg);
438 if (ret)
439 return ret;
440 ret = hash_process(&md, alg, in, inlen);
441 if (ret)
442 return ret;
443 ret = hash_done(&md, alg, out);
444 if (ret)
445 return ret;
446 return ret;
447}
448
449static int sha1(uint8_t *in, uint32_t inlen, uint8_t *out)
450{
451 return hash_handle(HASH_SHA1, in, inlen, out);
452}
453
454static int sha256(uint8_t *in, uint32_t inlen, uint8_t *out)
455{
456 return hash_handle(HASH_SHA256, in, inlen, out);
457}
458int bcm_sha_test(void)
459{
460 int ret = 0;
461 uint32_t i;
462 unsigned char out_sha1[20] = {0};
463 unsigned char out_sha256[32] = {0};
464
465 const struct {
466 const char *msg;
467 uint8_t hash[20];
468 } sha1_tests[] = {
469 {
470 "abc",
471 { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06,
472 0x81, 0x6a, 0xba, 0x3e, 0x25, 0x71,
473 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0,
474 0xd8, 0x9d
475 }
476 },
477 {
478 "asjhsdjljfdsdjjkdfwyqeuwouzxkmcxjkmwqds"
479 "jklfdfjlkdfkfsfkjlfskjdflioherfjjfdjkfd"
480 "nkfdfdojjodfjdfjflj;sljjlfkklnfnkgbhhoi"
481 "gfhigfopojpfjojpoffkjlfskjdflioherfjjfd"
482 "jkfdnkfdfdojjodfjdfjfljnfnkgbhhoigfhigf"
483 "oponfnkgbhhoigfhigfopojpfjoewiroiowiods"
484 "djkisijdknknkskdnknflnnesniewinoinknmdn"
485 "kknknsdnjjfsnnkfnkknslnklknfnknkflksnlk"
486 "lskldklklklnmlflmlmlfmlfml",
487 {
488 0xc4, 0x53, 0xca, 0x24, 0xfa, 0xe5,
489 0x39, 0x53, 0x08, 0x8c, 0x57, 0x1a,
490 0x96, 0xe9, 0x64, 0x7f, 0xd5, 0xf9,
491 0x13, 0x91
492 }
493 }
494 };
495
496 const struct {
497 const char *msg;
498 uint8_t hash[32];
499 } sha256_tests[] = {
500 {
501 "abc",
502 { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01,
503 0xCF, 0xEA, 0x41, 0x41, 0x40, 0xDE,
504 0x5D, 0xAE, 0x22, 0x23, 0xB0, 0x03,
505 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
506 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00,
507 0x15, 0xAD
508 }
509 },
510 {
511 "asjhsdjljfdsdjjkdfwyqeuwouzxkmcxjkmwq",
512 { 0x4d, 0xcb, 0x3b, 0xd5, 0x54, 0x96,
513 0xb7, 0xaa, 0xf8, 0xee, 0x2e, 0x28,
514 0x28, 0x29, 0x9c, 0x6b, 0xda, 0x1a,
515 0xdf, 0x5a, 0x21, 0x64, 0x17, 0xc7,
516 0xc7, 0x9e, 0x33, 0x2c, 0x99, 0xb5,
517 0x28, 0x3f
518 }
519 }
520 };
521
522 uint32_t start, time;
523 for (i = 0; i < sizeof(sha1_tests) / sizeof(sha1_tests[0]); i++) {
524 start = get_ticks();
525 ret = sha1(sha1_tests[i].msg, strlen(sha1_tests[i].msg), out_sha1);
526 time = get_ticks();
527 if (ret)
528 return ret;
529
530 printf("sha1 hw T = %d\r\n", (time-start));
531
532 if (memcmp(out_sha1, sha1_tests[i].hash, sizeof(out_sha1))) {
533 printf("sha1 test %d failed\r\n", i);
534 } else {
535 printf("sha1 test %d pass\r\n", i);
536 }
537 }
538
539 for (i = 0; i < sizeof(sha256_tests) / sizeof(sha256_tests[0]); i++) {
540 start = get_ticks();
541 ret = sha256(sha256_tests[i].msg, strlen(sha256_tests[i].msg), out_sha256);
542 time = get_ticks();
543 if (ret)
544 return ret;
545
546 printf("sha256 hw T = %d\r\n", (time-start));
547
548 if (memcmp(out_sha256, sha256_tests[i].hash, sizeof(out_sha256))) {
549 printf("sha256 test %d failed\r\n", i);
550 } else {
551 printf("sha256 test %d pass\r\n", i);
552 }
553 }
554
555 return 0;
556}
557#endif