• 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 <upg_check_secure.h>
17 #include <brain_pool_p256r1.h>
18 #include <hi_efuse.h>
19 #include <upg_common.h>
20 
21 #if defined(CONFIG_FLASH_ENCRYPT_SUPPORT)
22 #include "kernel_crypto.h"
23 #endif
24 
25 hi_u8 g_upg_tool_block[HI_BLOCK_SIZE];
26 
upg_is_secure_efuse(hi_bool * secure_flag)27 hi_u32 upg_is_secure_efuse(hi_bool *secure_flag)
28 {
29     hi_u8 data = 0;
30     hi_u32 ret = hi_efuse_read(HI_EFUSE_SEC_BOOT_RW_ID, (hi_u8 *)(&data), (hi_u8)(sizeof(hi_u8)));
31     if (ret != HI_ERR_SUCCESS) {
32         upg_print("[upg]secure efuse read err:0x%x \r\n", ret);
33         return ret;
34     }
35 
36     if (data == UPG_SEC_BOOT_FLAG) {
37         *secure_flag = HI_FALSE;
38     } else {
39         *secure_flag = HI_TRUE;
40     }
41     return HI_ERR_SUCCESS;
42 }
43 
upg_hash_one_content(hi_u32 flash_addr,hi_u32 total_size,hi_u8 * hash,hi_u32 hash_size)44 hi_u32 upg_hash_one_content(hi_u32 flash_addr, hi_u32 total_size, hi_u8 *hash, hi_u32 hash_size)
45 {
46     hi_u8 *block = g_upg_tool_block;
47     uintptr_t offset;
48     uintptr_t this_size;
49     hi_cipher_hash_atts hash_atts;
50 
51     (hi_void) memset_s(&hash_atts, sizeof(hash_atts), 0, sizeof(hash_atts));
52     hash_atts.sha_type = HI_CIPHER_HASH_TYPE_SHA256;
53     hi_u32 ret = hi_cipher_hash_start((hi_cipher_hash_atts *)(&hash_atts));
54     if (ret != HI_ERR_SUCCESS) {
55         upg_print("[upg hash one content]cipher start ret:0x%x \r\n", ret);
56         return ret;
57     }
58 
59     for (offset = 0; offset < total_size;) {
60         this_size = ((total_size - offset) > HI_BLOCK_SIZE) ? HI_BLOCK_SIZE : (total_size - offset);
61 
62         ret = (hi_u32)memcpy_s(block, this_size, (hi_u8 *)(HI_FLASH_BASE + flash_addr + offset), this_size);
63         if (ret != HI_ERR_SUCCESS) {
64             upg_print("[upg hash one content]flash read ret:0x%x \r\n", ret);
65             (hi_void) hi_cipher_hash_final(hash, hash_size);
66             return ret;
67         }
68 
69         ret = hi_cipher_hash_update((uintptr_t)block, this_size);
70         if (ret != HI_ERR_SUCCESS) {
71             upg_print("[upg hash one content]hash update ret:0x%x \r\n", ret);
72             return ret;
73         }
74         offset += this_size;
75     }
76     return hi_cipher_hash_final(hash, hash_size);
77 }
78 
upg_hash_more_content(HI_CONST upg_verify_param * param,hi_u8 * hash,hi_u32 hash_size)79 hi_u32 upg_hash_more_content(HI_CONST upg_verify_param *param, hi_u8 *hash, hi_u32 hash_size)
80 {
81     hi_u8 *block = g_upg_tool_block;
82     uintptr_t offset;
83     uintptr_t this_size;
84     hi_cipher_hash_atts hash_atts;
85 
86     (hi_void) memset_s(&hash_atts, sizeof(hash_atts), 0, sizeof(hash_atts));
87     hash_atts.sha_type = HI_CIPHER_HASH_TYPE_SHA256;
88     hi_u32 ret = hi_cipher_hash_start((hi_cipher_hash_atts *)(&hash_atts));
89     if (ret != HI_ERR_SUCCESS) {
90         upg_print("[upg hash more content]cipher start ret:0x%x \r\n", ret);
91         return ret;
92     }
93 
94     for (hi_u32 i = 0; i < param->buffer_count; i++) {
95         uintptr_t size = param->total_size[i];
96         for (offset = 0; offset < size;) {
97             this_size = ((size - offset) > HI_BLOCK_SIZE) ? HI_BLOCK_SIZE : (size - offset);
98             if (param->flash_flag[i]) {
99                 ret = (hi_u32)memcpy_s(block, this_size, (hi_u8 *)(HI_FLASH_BASE + param->flash_addr[i] + offset),
100                     this_size);
101             } else {
102                 ret = (hi_u32)memcpy_s(block, HI_BLOCK_SIZE, (hi_u8 *)(param->flash_addr[i] + offset), this_size);
103             }
104             if (ret != HI_ERR_SUCCESS) {
105                 upg_print("[upg hash more content]get content ret:0x%x \r\n", ret);
106                 (hi_void) hi_cipher_hash_final(hash, hash_size);
107                 return ret;
108             }
109 
110             ret = hi_cipher_hash_update((uintptr_t)block, this_size);
111             if (ret != HI_ERR_SUCCESS) {
112                 upg_print("[upg hash more content]hash update ret:0x%x \r\n", ret);
113                 return ret;
114             }
115             offset += this_size;
116         }
117     }
118     return hi_cipher_hash_final(hash, hash_size);
119 }
120 
upg_convert_cipher_err(hi_u32 buffer_cnt,hi_u32 cipher_err)121 hi_u32 upg_convert_cipher_err(hi_u32 buffer_cnt, hi_u32 cipher_err)
122 {
123     hi_u32 ret = cipher_err;
124 
125     if (cipher_err != HI_ERR_FAILURE) {
126         return ret;
127     }
128     if (buffer_cnt < 2) { /* 2: code section buf cnt */
129         ret = HI_ERR_UPG_COMMON_HASH;
130     } else {
131         ret = HI_ERR_UPG_SECTION_HASH;
132     }
133     return ret;
134 }
135 
upg_secure_verify(HI_CONST upg_verify_param * param)136 hi_u32 upg_secure_verify(HI_CONST upg_verify_param *param)
137 {
138     hi_bool flag;
139     hi_u8 hash[SHA_256_LEN] = { 0 };
140     hi_u32 ret = upg_hash_more_content(param, hash, sizeof(hash));
141     if (ret != HI_ERR_SUCCESS) {
142         upg_print("[upg secure verify]hash more content ret:0x%x \r\n", ret);
143         return ret;
144     }
145     ret = upg_is_secure_efuse(&flag);
146     if (ret != HI_ERR_SUCCESS) {
147         return ret;
148     }
149 
150     if (flag != HI_TRUE) {
151         if (memcmp(param->sign, hash, SHA_256_LEN) != EOK) {
152             ret = HI_ERR_UPG_SECTION_SHA256;
153         }
154         /* Common head only check one content. */
155         if ((ret != HI_ERR_SUCCESS) && (param->buffer_count < 2)) { /* 2: code section buf cnt */
156             ret = HI_ERR_UPG_COMMON_SHA256;
157         }
158         return ret;
159     }
160     if (param->pad_mode == HI_MODE_ECC) {
161         hi_cipher_ecc_verify ecc_verify = {
162             .px = param->key_n,
163             .py = param->key_e,
164             .hash = hash,
165             .hash_len = PKE_LEN_32_BYTES,
166             .r = (hi_u8 *)param->sign,
167             .s = (hi_u8 *)param->sign + ECC_32_BYTES,
168         };
169         ret = hi_cipher_ecc_verify_hash(&g_brain_pool_p256r1_verify, &ecc_verify);
170     } else {
171         hi_cipher_rsa_verify rsa_verify = {
172             .n = param->key_n,
173             .e = param->key_e,
174             .klen = RSA_2048_LEN,
175             .scheme = (hi_cipher_rsa_sign_scheme)(param->pad_mode),
176         };
177         ret = hi_cipher_rsa_verify_hash(&rsa_verify, hash, PKE_LEN_32_BYTES, param->sign, sizeof(upg_rsa_sign));
178     }
179     ret = upg_convert_cipher_err(param->buffer_count, ret);
180     upg_print("[upg secure verify]sign ret-mode:0x%x-0x%x \r\n", ret, param->pad_mode);
181     return ret;
182 }
183 
upg_get_subkey(hi_u8 * key,hi_u32 key_length,HI_CONST hi_upg_head * upg_head)184 hi_void upg_get_subkey(hi_u8 *key, hi_u32 key_length, HI_CONST hi_upg_head *upg_head)
185 {
186     hi_u32 key2_offset = sizeof(hi_upg_common_head) + key_length;
187     memset_s(key, key_length, 0, key_length);
188     if (upg_head->common.param.sign_alg == HI_MODE_ECC) {
189         if (memcpy_s(key, key_length, (hi_u8 *)upg_head + key2_offset, ECC_256_LEN) != EOK) {
190             return;
191         }
192     } else {
193         if (memcpy_s(key + key_length - RSA_EXP_E_LEN, RSA_EXP_E_LEN, (hi_u8 *)upg_head + key2_offset, RSA_EXP_E_LEN)
194             != EOK) {
195             return;
196         }
197     }
198 }
199 
upg_crypto_set_secure_verify_param(upg_verify_param * param,hi_u32 flash_addr,const hi_upg_common_head * head)200 hi_void upg_crypto_set_secure_verify_param(upg_verify_param *param, hi_u32 flash_addr,
201     const hi_upg_common_head *head)
202 {
203     param->flash_addr[0] = (uintptr_t)flash_addr + head->section_offset;
204     param->total_size[0] = sizeof(hi_upg_section_head);
205     param->flash_flag[0] = HI_TRUE;
206 #if defined(CONFIG_FLASH_ENCRYPT_SUPPORT) && (!defined(CONFIG_COMPRESSION_OTA_SUPPORT))
207     encrypt_ctx *para = encrypt_get_ctx();
208     para->raw_buf = (hi_u8 *)hi_malloc(0, CRYPTO_KERNEL_LENGTH);
209     if (para->raw_buf == HI_NULL) {
210         return;
211     }
212 
213     hi_u32 ret = crypto_decrypt(para);
214     if (ret != HI_ERR_SUCCESS) {
215         param->buffer_count = 0;
216         return;
217     }
218 
219     param->flash_addr[1] = (uintptr_t)(para->raw_buf);
220     param->total_size[1] = para->encrypt_size;
221     param->flash_flag[1] = HI_FALSE;
222     param->flash_addr[FLASH_ADDR_NUM - 1] = flash_addr + head->section_offset + sizeof(hi_upg_section_head) +
223                                             sizeof(hi_upg_sign) + para->encrypt_size;
224     param->total_size[TOTAL_SIZE_NUM - 1] = head->section_len - sizeof(hi_upg_section_head) - sizeof(hi_upg_sign) -
225                                             para->encrypt_size;
226     param->flash_flag[FLASH_FLAG_NUM - 1] = HI_TRUE;
227     param->buffer_count = 3; /* 3 segments */
228 #else
229     param->flash_addr[1] = flash_addr + head->section_offset + sizeof(hi_upg_section_head) + sizeof(hi_upg_sign);
230     param->total_size[1] = head->section_len - sizeof(hi_upg_section_head) - sizeof(hi_upg_sign);
231     param->flash_flag[1] = HI_TRUE;
232     param->buffer_count = 2; /* 2 segments */
233 #endif
234 }
235 
upg_set_secure_verify_param(upg_verify_param * param,hi_u32 flash_addr,const hi_upg_common_head * head)236 hi_void upg_set_secure_verify_param(upg_verify_param *param, hi_u32 flash_addr, const hi_upg_common_head *head)
237 {
238     if (head->file_type == HI_UPG_FILE_KERNEL) {
239         upg_crypto_set_secure_verify_param(param, flash_addr, head);
240     } else if (head->file_type == HI_UPG_FILE_BOOT) {
241         param->flash_addr[0] = (uintptr_t)flash_addr + head->section_offset;
242         param->total_size[0] = sizeof(hi_upg_section_head);
243         param->flash_flag[0] = HI_TRUE;
244         param->flash_addr[1] = flash_addr + head->section_offset + sizeof(hi_upg_section_head) + sizeof(hi_upg_sign);
245         param->total_size[1] = head->section_len - sizeof(hi_upg_section_head) - sizeof(hi_upg_sign);
246         param->flash_flag[1] = HI_TRUE;
247         param->buffer_count = 2; /* 2 segments */
248     }
249 }
250 
upg_check_upg_file_code(hi_u32 flash_addr,hi_upg_head * upg_head)251 hi_u32 upg_check_upg_file_code(hi_u32 flash_addr, hi_upg_head *upg_head)
252 {
253     hi_upg_common_head *head = &(upg_head->common);
254     hi_u32 key_length = 0;
255     hi_u8 *key2 = HI_NULL;
256     hi_bool flag;
257     hi_u32 ret = upg_is_secure_efuse(&flag);
258     if (ret != HI_ERR_SUCCESS) {
259         return ret;
260     }
261     hi_u8 *code_sign = hi_malloc(HI_MOD_ID_UPG, sizeof(hi_upg_sign));
262     if (code_sign == HI_NULL) {
263         return HI_ERR_UPG_MALLOC_FAIL;
264     }
265     ret = hi_flash_read(flash_addr + head->section_offset + sizeof(hi_upg_section_head),
266                         sizeof(hi_upg_sign), (hi_u8 *)code_sign);
267     if (ret != HI_ERR_SUCCESS) {
268         upg_print("[upg verify code]flash read ret:0x%x \r\n", ret);
269         goto end;
270     }
271     if (flag == HI_TRUE) {
272         key_length = (head->param.sign_alg == HI_MODE_ECC) ? ECC_256_LEN : RSA_2048_LEN;
273         key2 = hi_malloc(HI_MOD_ID_UPG, key_length);
274         if (key2 == HI_NULL) {
275             ret = HI_ERR_UPG_MALLOC_FAIL;
276             upg_print("[upg verify code] malloc fail. \r\n");
277             goto end;
278         }
279         upg_get_subkey(key2, key_length, upg_head);
280     }
281     upg_verify_param param = { 0 };
282     upg_set_secure_verify_param(&param, flash_addr, head);
283     param.key_n = (hi_u8 *)upg_head + sizeof(hi_upg_common_head);
284     param.key_e = key2;
285     param.key_len = key_length;
286     param.sign = code_sign;
287     param.pad_mode = (hi_padding_mode)head->param.sign_alg;
288     ret = upg_secure_verify(&param);
289 
290 #if (defined(CONFIG_FLASH_ENCRYPT_SUPPORT)) && (!defined(CONFIG_COMPRESSION_OTA_SUPPORT))
291     encrypt_ctx *para = encrypt_get_ctx();
292     crypto_mem_free(para->raw_buf);
293 #endif
294 end:
295     upg_mem_free(code_sign);
296     upg_clear_contset((hi_u8 *)key2, key_length);
297     upg_mem_free(key2);
298     return ret;
299 }
300 
upg_check_upg_file_head(hi_upg_head * upg_head)301 hi_u32 upg_check_upg_file_head(hi_upg_head *upg_head)
302 {
303     hi_upg_common_head *head = &(upg_head->common);
304     hi_u8 *key = HI_NULL;
305     hi_u32 key_length = 0; /* 2 key length: (px+py) or (key_n+key_e) */
306     hi_bool flag;
307     hi_u32 ret = upg_is_secure_efuse(&flag);
308     if (ret != HI_ERR_SUCCESS) {
309         return ret;
310     }
311 
312     if (flag == HI_TRUE) {
313         key_length = (head->param.sign_alg < HI_MODE_ECC) ? RSA_KEY_LEN : ECC_KEY_LEN;
314         key = hi_malloc(HI_MOD_ID_UPG, key_length);
315         if (key == HI_NULL) {
316             ret = HI_ERR_UPG_MALLOC_FAIL;
317             upg_print("[upg verify code] malloc fail. \r\n");
318             goto end;
319         }
320         memset_s(key, key_length, 0, key_length);
321 
322         /* Get key from flash */
323         if (head->param.sign_alg == HI_MODE_ECC) {
324             ret = upg_get_ecc_key_from_boot(key, key_length);
325         } else {
326             ret = upg_get_rsa_key_from_boot(key, key_length);
327         }
328         if (ret != HI_ERR_SUCCESS) {
329             upg_print("[upg verify head]fail ret:0x%x.\r\n", ret);
330             goto end;
331         }
332     }
333     upg_verify_param param = { 0 };
334     param.flash_addr[0] = (uintptr_t)upg_head;
335     param.total_size[0] = sizeof(hi_upg_common_head) + head->key_len;
336     param.buffer_count = 1; /* 1 segments */
337     param.key_n = key;
338     param.key_len = (key_length / 2); /* 2: ken len include (px+py) or (key_n+key_e) */
339     param.key_e = key + param.key_len;
340     param.sign = (hi_u8 *)upg_head + sizeof(hi_upg_common_head) + head->key_len;
341     param.pad_mode = (hi_padding_mode)head->param.sign_alg;
342     ret = upg_secure_verify(&param);
343 end:
344     upg_clear_contset((hi_u8 *)key, key_length);
345     upg_mem_free(key);
346     return ret;
347 }
348 
upg_check_upg_file(hi_u32 flash_addr,hi_upg_head * upg_head)349 hi_u32 upg_check_upg_file(hi_u32 flash_addr, hi_upg_head *upg_head)
350 {
351     hi_u32 ret = upg_check_upg_file_head(upg_head);
352     if (ret != HI_ERR_SUCCESS) {
353         upg_print("[upg check secure info]verify head,ret:0x%x \r\n", ret);
354         return ret;
355     }
356 
357     ret = upg_check_upg_file_code(flash_addr, upg_head);
358     if (ret != HI_ERR_SUCCESS) {
359         upg_print("[upg check secure info]verify code,ret:0x%x \r\n", ret);
360         return ret;
361     }
362     return HI_ERR_SUCCESS;
363 }
364 
365