1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "boot_upg_tool.h"
17
18 #if defined(CONFIG_FLASH_ENCRYPT_SUPPORT)
19 #include <crypto.h>
20 #endif
21
22 hi_u8 g_upg_tool_block[HI_BLOCK_SIZE];
23 static hi_u32 g_compress_src_addr = 0;
24 static hi_u32 g_compress_dst_addr = 0;
25
kernel_comprss_flash_read(hi_u32 offset,hi_u8 * buffer,hi_u32 size)26 hi_u32 kernel_comprss_flash_read(hi_u32 offset, hi_u8 *buffer, hi_u32 size)
27 {
28 hi_u32 ret;
29 #if defined(CONFIG_FLASH_ENCRYPT_SUPPORT)
30 ret = crypto_kernel_read(g_compress_src_addr, offset, buffer, size);
31 if (ret == HI_ERR_SUCCESS) {
32 ret = 0;
33 }
34 #else
35 ret = hi_flash_read(g_compress_src_addr + offset, size, buffer);
36 if (ret == HI_ERR_SUCCESS) {
37 ret = 0;
38 }
39 #endif
40
41 return ret;
42 }
43
kernel_comprss_flash_write(hi_u32 offset,hi_u8 * buffer,hi_u32 size)44 hi_u32 kernel_comprss_flash_write(hi_u32 offset, hi_u8 *buffer, hi_u32 size)
45 {
46 hi_u32 ret;
47 hi_u32 tmp_size = size + 1;
48
49 #if defined(CONFIG_FLASH_ENCRYPT_SUPPORT)
50 ret = crypto_kernel_write(g_compress_dst_addr, offset, buffer, size);
51 if (ret != HI_ERR_SUCCESS) {
52 return tmp_size;
53 }
54 #else
55 ret = hi_flash_write(g_compress_dst_addr + offset, size, buffer, HI_FALSE);
56 if (ret != HI_ERR_SUCCESS) {
57 return tmp_size;
58 }
59 #endif
60 return size;
61 }
62
kernel_comprss_flash_hash(hi_u32 offset,hi_u8 * buffer,hi_u32 size)63 hi_u32 kernel_comprss_flash_hash(hi_u32 offset, hi_u8 *buffer, hi_u32 size)
64 {
65 hi_u32 cs;
66 hi_u32 ret = HI_ERR_SUCCESS;
67 hi_u32 hash_size = size + 1;
68
69 if (offset >= sizeof(hi_upg_file_head)) {
70 ret = hi_cipher_hash_update((uintptr_t)buffer, size);
71 if (ret == HI_ERR_SUCCESS) {
72 hash_size = size;
73 } else {
74 boot_msg4("code hash ret-size-offset-headsize", ret, size, offset, hash_size);
75 }
76 return hash_size;
77 }
78
79 /* offset less than sizeof(hi_upg_file_head) */
80 if ((offset + size) > sizeof(hi_upg_file_head)) {
81 hi_u32 cy_size = sizeof(hi_upg_file_head) - offset;
82 cs = (uintptr_t)(g_compress_dst_addr + offset) ^ cy_size ^ (uintptr_t)buffer ^ cy_size;
83 (hi_void) memcpy_s((hi_void *)(uintptr_t)(g_compress_dst_addr + offset), cy_size, buffer, cy_size, cs);
84
85 /* Cal hash of common section head */
86 ret = hi_cipher_hash_update((uintptr_t)(g_compress_dst_addr + sizeof(hi_upg_head)),
87 sizeof(hi_upg_section_head));
88 if (ret != HI_ERR_SUCCESS) {
89 boot_msg4("head hash updata ret-size-offset-hashsize", ret, size, offset, hash_size);
90 return hash_size;
91 }
92 /* Cal hash of common section */
93 ret = hi_cipher_hash_update((uintptr_t)(buffer + cy_size), (size - cy_size));
94 } else {
95 cs = (uintptr_t)(g_compress_dst_addr + offset) ^ size ^ (uintptr_t)buffer ^ size;
96 (hi_void) memcpy_s((hi_void *)(uintptr_t)(g_compress_dst_addr + offset), size, buffer, size, cs);
97 }
98 if (ret == HI_ERR_SUCCESS) {
99 hash_size = size;
100 } else {
101 boot_msg4("code head hash ret-size-offset-hashsize", ret, size, offset, hash_size);
102 }
103 return hash_size;
104 }
105
boot_upg_copy_flash_2_flash(hi_u32 src_addr,hi_u32 src_size,hi_u32 dst_addr,hi_u32 dst_size,hi_bool comprss)106 hi_u32 boot_upg_copy_flash_2_flash(hi_u32 src_addr, hi_u32 src_size, hi_u32 dst_addr, hi_u32 dst_size, hi_bool comprss)
107 {
108 hi_u8 lzma_head[13] = { 0 }; /* head 13B */
109 hi_u32 ret = HI_ERR_UPG_PARAMETER;
110
111 if (!comprss) {
112 boot_msg0("Not support uncompressed file.");
113 return ret;
114 } else {
115 boot_msg4("src-size-dst-size", src_addr, src_size, dst_addr, dst_size);
116 hi_flash_read(src_addr, 13, lzma_head); /* read 13B */
117 g_compress_src_addr = src_addr;
118 g_compress_dst_addr = dst_addr;
119 ret = hi_lzma_decompress(lzma_head, sizeof(lzma_head), src_size, kernel_comprss_flash_read,
120 kernel_comprss_flash_write);
121 }
122 return ret;
123 }
124
boot_upg_hash_one_content(hi_u32 flash_addr,hi_u32 total_size,hi_u8 * hash,hi_u32 hash_size)125 hi_u32 boot_upg_hash_one_content(hi_u32 flash_addr, hi_u32 total_size, hi_u8 *hash, hi_u32 hash_size)
126 {
127 hi_u32 ret;
128 hi_u8 *block = g_upg_tool_block;
129
130 ret = hi_cipher_hash_start();
131 if (ret != HI_ERR_SUCCESS) {
132 boot_msg1("[bootupg hash one content]start ret:", ret);
133 return ret;
134 }
135
136 for (uintptr_t offset = 0; offset < total_size;) {
137 uintptr_t this_size = (total_size - offset > HI_BLOCK_SIZE) ? HI_BLOCK_SIZE : (total_size - offset);
138 ret = hi_flash_read(flash_addr + offset, this_size, block);
139 if (ret != HI_ERR_SUCCESS) {
140 (hi_void) hi_cipher_hash_final(hash, hash_size);
141 return ret;
142 }
143
144 ret = hi_cipher_hash_update((uintptr_t)block, this_size);
145 if (ret != HI_ERR_SUCCESS) {
146 boot_msg1("[bootupg hash one content]update ret:", ret);
147 return ret;
148 }
149 offset += this_size;
150 }
151 return hi_cipher_hash_final(hash, hash_size);
152 }
153
boot_upg_hash_more_content(HI_CONST upg_verify_param * param,hi_u8 * hash,hi_u32 hash_size)154 hi_u32 boot_upg_hash_more_content(HI_CONST upg_verify_param *param, hi_u8 *hash, hi_u32 hash_size)
155 {
156 hi_u32 cs;
157 hi_u8 *block = g_upg_tool_block;
158
159 hi_u32 ret = hi_cipher_hash_start();
160 if (ret != HI_ERR_SUCCESS) {
161 boot_msg1("[bootupg hash more content]cipher start ret:", ret);
162 return ret;
163 }
164
165 for (hi_u8 i = 0; i < param->buffer_count; i++) {
166 uintptr_t size = param->total_size[i];
167 for (uintptr_t offset = 0; offset < size;) {
168 uintptr_t this_size = ((size - offset) > HI_BLOCK_SIZE) ? HI_BLOCK_SIZE : (size - offset);
169 if (param->flash_flag[i]) {
170 ret = hi_flash_read(param->flash_addr[i] + offset, this_size, block);
171 } else {
172 cs = (uintptr_t)block ^ HI_BLOCK_SIZE ^ (uintptr_t)(param->flash_addr[i] + offset) ^ this_size;
173 ret = (hi_u32)memcpy_s(block, HI_BLOCK_SIZE, (hi_u8 *)(param->flash_addr[i] + offset), this_size, cs);
174 }
175 if (ret != HI_ERR_SUCCESS) {
176 (hi_void) hi_cipher_hash_final(hash, hash_size);
177 return ret;
178 }
179
180 ret = hi_cipher_hash_update((uintptr_t)block, this_size);
181 if (ret != HI_ERR_SUCCESS) {
182 boot_msg1("[bootupg hash more content]hash update ret: ", ret);
183 return ret;
184 }
185 offset += this_size;
186 }
187 }
188 return hi_cipher_hash_final(hash, hash_size);
189 }
190
boot_upg_lzma_secure_verify(const upg_verify_param * param,hi_u8 * hash,hi_u32 hash_size)191 hi_u32 boot_upg_lzma_secure_verify(const upg_verify_param *param, hi_u8 *hash, hi_u32 hash_size)
192 {
193 hi_u8 out_hash[SHA_256_LEN] = { 0 };
194 hi_u32 ret;
195
196 if (hash_size != SHA_256_LEN) {
197 return HI_ERR_UPG_PARAMETER;
198 }
199
200 if (param->pad_mode == HI_MODE_ECC) {
201 hi_cipher_ecc_verify ecc_verify = {
202 .px = param->key_n,
203 .py = param->key_e,
204 .hash = hash,
205 .hash_len = PKE_LEN_32_BYTES,
206 .r = (hi_u8 *)param->sign,
207 .s = (hi_u8 *)param->sign + ECC_32_BYTES,
208 .out_r = out_hash,
209 };
210 ret = hi_cipher_ecc_verify_hash(&g_brain_pool_p256r1_verify, &ecc_verify);
211 } else {
212 hi_cipher_rsa_verify rsa_verify = {
213 .n = param->key_n,
214 .e = param->key_e,
215 .klen = param->key_len,
216 .scheme = (hi_cipher_rsa_sign_scheme)(param->pad_mode),
217 };
218 hi_cipher_rsa_data rsa_data = {
219 .hash = hash,
220 .out_hash = out_hash,
221 .hash_len = PKE_LEN_32_BYTES,
222 .sign = param->sign,
223 .sign_len = sizeof(upg_rsa_sign),
224 };
225 ret = hi_cipher_rsa_verify_hash(&rsa_verify, &rsa_data);
226 }
227 return ret;
228 }
229
boot_upg_lzma_secure_verify_code(const hi_upg_file_head * upg_head,hi_u8 * hash,hi_u32 hash_size)230 hi_u32 boot_upg_lzma_secure_verify_code(const hi_upg_file_head *upg_head, hi_u8 *hash, hi_u32 hash_size)
231 {
232 hi_u32 cs;
233 hi_u32 ret;
234 hi_u32 key_length = (upg_head->common.param.sign_alg == HI_MODE_ECC) ? ECC_256_LEN : RSA_2048_LEN;
235 hi_u32 key2_offset = sizeof(hi_upg_common_head) + key_length;
236 hi_u8 *key_e = g_upg_tool_block;
237
238 if (key_length > HI_BLOCK_SIZE) {
239 boot_msg1("[bootupg lzma verify code]key size", key_length);
240 return HI_ERR_UPG_PARAMETER;
241 }
242 cs = (uintptr_t)key_e ^ HI_BLOCK_SIZE ^ 0 ^ HI_BLOCK_SIZE;
243 memset_s(key_e, HI_BLOCK_SIZE, 0, HI_BLOCK_SIZE, cs);
244
245 if (upg_head->common.param.sign_alg == HI_MODE_ECC) {
246 cs = (uintptr_t)key_e ^ ECC_256_LEN ^ (uintptr_t)((hi_u8 *)upg_head + key2_offset) ^ ECC_256_LEN;
247 (hi_void) memcpy_s(key_e, key_length, (hi_u8 *)upg_head + key2_offset, ECC_256_LEN, cs);
248 } else {
249 cs = (uintptr_t)(key_e + key_length - RSA_EXP_E_LEN) ^ RSA_EXP_E_LEN ^
250 (uintptr_t)((hi_u8 *)upg_head + key2_offset) ^ RSA_EXP_E_LEN;
251 (hi_void)memcpy_s(key_e + key_length - RSA_EXP_E_LEN, RSA_EXP_E_LEN,
252 (hi_u8 *)upg_head + key2_offset, RSA_EXP_E_LEN, cs);
253 }
254
255 upg_verify_param param = { 0 };
256 param.key_n = (hi_u8 *)upg_head + sizeof(hi_upg_common_head);
257 param.key_e = key_e;
258 param.key_len = key_length;
259 param.sign = (hi_u8 *)upg_head + sizeof(hi_upg_head) + sizeof(hi_upg_section_head);
260 param.pad_mode = (hi_padding_mode)upg_head->common.param.sign_alg;
261 ret = boot_upg_lzma_secure_verify(¶m, hash, hash_size);
262 if (ret != HI_ERR_SUCCESS) {
263 boot_msg1("[bootupg lzma verify code]ret", ret);
264 }
265 return ret;
266 }
267
boot_upg_lzma_unsecure_verify_code(const hi_upg_file_head * upg_head,hi_u8 * hash,hi_u32 hash_size)268 hi_u32 boot_upg_lzma_unsecure_verify_code(const hi_upg_file_head *upg_head, hi_u8 *hash, hi_u32 hash_size)
269 {
270 if (hash_size != SHA_256_LEN) {
271 return HI_ERR_UPG_PARAMETER;
272 }
273
274 if (memcmp((hi_u8 *)upg_head + sizeof(hi_upg_head) + sizeof(hi_upg_section_head), hash, hash_size) != EOK) {
275 return HI_ERR_UPG_SECTION_SHA256;
276 }
277 return HI_ERR_SUCCESS;
278 }
279
boot_upg_check_before_decompress(hi_u32 addr_write,const hi_upg_section_head * section_head,const hi_upg_file_head * file_head)280 hi_u32 boot_upg_check_before_decompress(hi_u32 addr_write, const hi_upg_section_head *section_head,
281 const hi_upg_file_head *file_head)
282 {
283 hi_u8 lzma_head[13] = { 0 }; /* head 13B */
284 hi_u32 ret;
285 hi_u8 hash[SHA_256_LEN] = { 0 };
286
287 hi_flash_read(addr_write + section_head->section0_offset, 13, lzma_head); /* read 13B */
288 g_compress_src_addr = addr_write + section_head->section0_offset;
289 g_compress_dst_addr = (hi_u32)(uintptr_t)file_head;
290
291 ret = hi_cipher_hash_start();
292 if (ret != HI_ERR_SUCCESS) {
293 boot_msg1("[bootupg before decompress]hash start fail", ret);
294 return ret;
295 }
296 ret = hi_lzma_decompress(lzma_head, sizeof(lzma_head), section_head->section0_len, kernel_comprss_flash_read,
297 kernel_comprss_flash_hash);
298 if (ret != HI_ERR_SUCCESS) {
299 boot_msg1("[bootupg before decompress]decompress fail", ret);
300 return ret;
301 }
302 (hi_void)hi_cipher_hash_final(hash, SHA_256_LEN);
303
304 /* verify common & code section */
305 hi_upg_head *common_section = (hi_upg_head *)(uintptr_t)g_compress_dst_addr;
306 if (boot_upg_is_secure_efuse() == HI_TRUE) {
307 ret = boot_upg_secure_verify_head(common_section);
308 if (ret != HI_ERR_SUCCESS) {
309 boot_msg1("[bootupg before decompress]verify head hash ret", ret);
310 return ret;
311 }
312 ret = boot_upg_lzma_secure_verify_code(file_head, hash, SHA_256_LEN);
313 } else {
314 ret = boot_upg_unsecure_verify_head(common_section);
315 if (ret != HI_ERR_SUCCESS) {
316 boot_msg1("[bootupg before decompress]verify head sha256 ret", ret);
317 return ret;
318 }
319 ret = boot_upg_lzma_unsecure_verify_code(file_head, hash, SHA_256_LEN);
320 }
321
322 if (ret != HI_ERR_SUCCESS) {
323 boot_msg1("[bootupg before decompress]verfiy code fail", ret);
324 }
325 return ret;
326 }
327
328