• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&param, 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