blob: 542521a26e2c1dc6f26f6a3271bc706e3248df57 [file] [log] [blame]
Googlera8fd56b2024-10-24 14:04:51 +08001/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
2/*
3 * arch/arm/cpu/armv8/hard_sha2.c
4 *
5 * Copyright (C) 2020 Amlogic, Inc. All rights reserved.
6 *
7 */
8
9#include <common.h>
10#include <linux/string.h>
11#include <u-boot/sha256.h>
12#include <asm/arch/secure_apb.h>
13
14
15#ifndef __AP_DMA_H__
16#define __AP_DMA_H__
17
18
19typedef struct dma_dsc {
20 union {
21 uint32_t d32;
22 struct {
23 unsigned length:17;
24 unsigned irq:1;
25 unsigned eoc:1;
26 unsigned loop:1;
27 unsigned mode:4;
28 unsigned begin:1;
29 unsigned end:1;
30 unsigned op_mode:2;
31 unsigned enc_sha_only:1;
32 unsigned block:1;
33 unsigned error:1;
34 unsigned owner:1;
35 } b;
36 } dsc_cfg;
37 uint32_t src_addr;
38 uint32_t tgt_addr;
39} dma_dsc_t;
40
41#endif /* __AP_DMA_H__ */
42
43static sha2_ctx *cur_ctx;
44
45static void hw_init(uint32_t is224)
46{
47 cur_ctx->digest_len = is224 ? 224 : 256;
48 cur_ctx->tot_len = 0;
49}
50
51static void hw_update(const uint8_t *input, uint32_t ilen,
52 uint8_t *hash, uint8_t last_update)
53{
54 dma_dsc_t dsc;
55 unsigned char szTempSHA2[32];
56
57 if (!last_update && (ilen % 64)) {
58 serial_puts("Err:sha5\n");
59 // sha2 usage problem
60 return;
61 }
62
63 struct {
64 unsigned long lSource;
65 unsigned long lTarget;
66 unsigned int nLength;
67 unsigned int nBlkFlag;
68 }arrSteps[2];
69
70 unsigned int index = 0;
71 memset((void *)arrSteps, 0, sizeof(arrSteps));
72
73 arrSteps[0].lSource = (unsigned long)input;
74
75 arrSteps[0].lTarget = (unsigned long)hash;
76 arrSteps[1].lTarget = (unsigned long)szTempSHA2;
77
78 int nStep_len = (128<<10)- 64; //17bit length
79 /*If input length bigger than (128KB - 64bytes),default use block mode is 1. */
80
81 if (ilen > nStep_len)
82 {
83 arrSteps[0].nLength = ilen >> 9;
84 arrSteps[0].nBlkFlag = 1;
85 arrSteps[1].lSource = arrSteps[0].lSource + (arrSteps[0].nLength << 9);
86 arrSteps[1].nLength = ilen % 512;
87 arrSteps[1].nBlkFlag = 0;
88 }
89 else
90 {
91 arrSteps[0].nLength = ilen;
92 arrSteps[0].nBlkFlag = 0;
93 }
94
95 for (index = 0; index < sizeof(arrSteps) / sizeof(arrSteps[0]); index++)
96 {
97 dsc.src_addr = arrSteps[index].lSource;
98 dsc.tgt_addr = arrSteps[index].lTarget;
99 dsc.dsc_cfg.d32 = 0;
100 dsc.dsc_cfg.b.length = arrSteps[index].nLength;
101 dsc.dsc_cfg.b.enc_sha_only = 1;
102 dsc.dsc_cfg.b.mode = cur_ctx->digest_len == 224 ? 7 : 6;
103 dsc.dsc_cfg.b.begin = cur_ctx->tot_len == 0; // first
104 dsc.dsc_cfg.b.end = last_update;
105 dsc.dsc_cfg.b.eoc = 1;
106 dsc.dsc_cfg.b.owner = 1;
107 dsc.dsc_cfg.b.block = arrSteps[index].nBlkFlag;
108
109 flush_dcache_range((unsigned long)&dsc,(unsigned long)&dsc+sizeof(dsc));
110 invalidate_dcache_range((unsigned long)dsc.tgt_addr,(unsigned long)dsc.tgt_addr + 32);
111
112 *P_DMA_STS0 = 0xf;
113 *P_DMA_T0 = (uint64_t)&dsc | 2;
114
115 if (arrSteps[index].nBlkFlag)
116 {
117 cur_ctx->tot_len += arrSteps[index].nLength << 9;
118 }
119 else
120 cur_ctx->tot_len += arrSteps[index].nLength;
121
122 while (*P_DMA_STS0 == 0);
123
124 if (!dsc.dsc_cfg.b.block)
125 return;
126 }
127}
128
129static void SHA2_HW_init(sha2_ctx *ctx, uint32_t digest_len)
130{
131 if (cur_ctx != NULL) {
132 serial_puts("Err:sha4\n");
133 // sha2 usage problem
134 return;
135 }
136 cur_ctx = ctx;
137
138 hw_init(digest_len == 224);
139
140 ctx->len = 0;
141}
142
143static void SHA2_HW_update(sha2_ctx *ctx, const uint8_t *data, uint32_t len)
144{
145 unsigned int fill_len, data_len, rem_len,offset;
146
147 if (cur_ctx != ctx) {
148 serial_puts("Err:sha3\n");
149 // sha2 usage problem
150 return;
151 }
152 /* This method updates the hash for the input data in blocks, except the last
153 * partial|full block, which is saved in ctx->block. The last partial|full
154 * block will be added to the hash in SHA2_final.
155 */
156 data_len = len;
157 offset = 0;
158 /* fill saved block from beginning of input data */
159 if (ctx->len) {
160 fill_len = SHA256_BLOCK_SIZE - ctx->len;
161 memcpy(&ctx->block[ctx->len], data, fill_len);
162 /* after memcpy,must flush data to ddr */
163 flush_dcache_range((unsigned long)ctx->block,(unsigned long)ctx->block+128);
164 data_len -= fill_len;
165 offset = fill_len;
166 ctx->len += fill_len;
167 }
168 if (ctx->len == SHA256_BLOCK_SIZE && data_len > 0) {
169 /* saved block is full and is not last block, hash it */
170 hw_update(ctx->block, SHA256_BLOCK_SIZE,ctx->buf, 0);
171 ctx->len = 0;
172 }
173 if (data_len > SHA256_BLOCK_SIZE) {
174 /* still have more than 1 block. hash up until last [partial|full] block */
175 rem_len = data_len % SHA256_BLOCK_SIZE;
176
177 if (rem_len == 0) {
178 rem_len = SHA256_BLOCK_SIZE;
179 }
180
181 data_len -= rem_len;
182 hw_update(&data[offset], data_len,ctx->buf, 0);
183 offset += data_len;
184 } else {
185 rem_len = data_len;
186 }
187
188 if (rem_len) {
189 /* save the remaining data */
190 memcpy(ctx->block, &data[offset], rem_len);
191 /* after memcpy,must flush data to ddr */
192 flush_dcache_range((unsigned long)ctx->block,(unsigned long)ctx->block+128);
193 ctx->len = rem_len;
194 }
195}
196
197static uint8_t *SHA2_HW_final(sha2_ctx *ctx)
198{
199 if (cur_ctx != ctx) {
200 serial_puts("Err:sha1\n");
201 // sha2 usage problem
202 return ctx->buf;
203 }
204 if (ctx->len == 0 || ctx->len > SHA256_BLOCK_SIZE) {
205 serial_puts("Err:sha2\n");
206 // internal sha2 problem
207 return ctx->buf;
208 }
209 hw_update(ctx->block, ctx->len,ctx->buf, 1);
210 cur_ctx = NULL;
211 return ctx->buf;
212}
213
214void sha256_starts(sha256_context * ctx)
215{
216 /*if ctx is not null,set zero*/
217 if (ctx)
218 memset(ctx,0,sizeof(sha256_context));
219
220 SHA2_HW_init(ctx, 256);
221}
222
223void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)
224{
225 int nOffset = 0;
226 int nStep = (128<<19) ; //64MB
227
228 if (length > nStep)
229 {
230 for (;nOffset< length;)
231 {
232 SHA2_HW_update(ctx, input+nOffset, nStep);
233 nOffset+=nStep;
234 if ((length - nOffset ) < nStep)
235 nStep = length - nOffset;
236 }
237 }
238 else
239 {
240 SHA2_HW_update(ctx, input, length);
241 }
242}
243
244void sha256_finish(sha256_context * ctx, uint8_t digest[SHA256_SUM_LEN])
245{
246 SHA2_HW_final(ctx);
247 /*before memcpy,must invalidate dcache.so memcpy data from ddr*/
248 invalidate_dcache_range((unsigned long)digest,(unsigned long)(digest+32));
249 invalidate_dcache_range((unsigned long)ctx->buf,(unsigned long)(ctx->buf+32));
250 memcpy(digest,ctx->buf,32);
251}
252
253void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
254 unsigned char *output, unsigned int chunk_sz)
255{
256 flush_dcache_range((unsigned long)input,(unsigned long)input+ilen);
257
258 sha2_ctx sha_ctx;
259
260 sha256_starts(&sha_ctx);
261
262 sha256_update(&sha_ctx, input, ilen);
263
264 sha256_finish(&sha_ctx, output);
265}
266