• 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_file.h"
17 #include "upg_check_secure.h"
18 #include "upg_check_boot_bin.h"
19 #include "upg_user_verify.h"
20 
upg_check_image_id(hi_u32 image_id)21 hi_u32 upg_check_image_id(hi_u32 image_id)
22 {
23     if (image_id != PRODUCT_UPG_FILE_IMAGE_ID) {
24         upg_print("[upg check image id]fail,image id:0x%x \r\n", image_id);
25         return HI_ERR_UPG_IMAGE_ID;
26     }
27     return HI_ERR_SUCCESS;
28 }
29 
upg_check_file_type(hi_u8 file_type)30 hi_u32 upg_check_file_type(hi_u8 file_type)
31 {
32     if ((file_type == HI_UPG_FILE_KERNEL) || (file_type == HI_UPG_FILE_BOOT)) {
33         return HI_ERR_SUCCESS;
34     } else {
35         upg_print("[upg check file type]fail,file type:0x%x \r\n", file_type);
36         return HI_ERR_UPG_FILE_TYPE;
37     }
38 }
39 
upg_check_encrypt_info_is_match(hi_u8 encry_info)40 hi_bool upg_check_encrypt_info_is_match(hi_u8 encry_info)
41 {
42 #if defined(CONFIG_FLASH_ENCRYPT_SUPPORT)
43     if (encry_info != HI_UPG_FILE_ATTR_ENCRYPT) {
44         upg_print("[upg_check_encrypt_info]encrypt 0x%x \r\n", encry_info);
45         return HI_FALSE;
46     }
47 #else
48     if (encry_info != HI_UPG_FILE_ATTR_UNENCRYPT) {
49         upg_print("[upg_check_encrypt_info]unencrypt 0x%x \r\n", encry_info);
50         return HI_FALSE;
51     }
52 #endif
53     return HI_TRUE;
54 }
55 
upg_check_ota_info_is_match(hi_u8 file_type,hi_u8 ota_info)56 hi_bool upg_check_ota_info_is_match(hi_u8 file_type, hi_u8 ota_info)
57 {
58 #if defined(CONFIG_COMPRESSION_OTA_SUPPORT)
59     hi_unref_param(file_type);
60     if (ota_info != HI_UPG_FILE_ATTR_COMPRESSION) {
61         upg_print("[upg_check_ota_info]compression 0x%x \r\n", ota_info);
62         return HI_FALSE;
63     }
64 #else
65     hi_nv_ftm_startup_cfg cfg = { 0 };
66     hi_flash_partition_table *partition = hi_get_partition_table();
67     uintptr_t kernel_a_addr = partition->table[HI_FLASH_PARTITON_KERNEL_A].addr;
68     hi_u32 ret = upg_get_start_up_cfg(&cfg);
69     if (ret != HI_ERR_SUCCESS) {
70         upg_print("[upg_check_ota_info]get cfg fail:0x%x \r\n", ret);
71         return HI_FALSE;
72     }
73     /* check flashboot */
74     if (file_type == HI_UPG_FILE_BOOT) {
75         if (ota_info != (HI_UPG_FILE_ATTR_KERNELA  | HI_UPG_FILE_ATTR_KERNELB)) {
76             upg_print("[upg_check_ota_info]dual flashboot 0x%x \r\n", ota_info);
77             return HI_FALSE;
78         }
79         return HI_TRUE;
80     }
81 
82     if (cfg.addr_start == kernel_a_addr) {
83         if ((ota_info != HI_UPG_FILE_ATTR_KERNELB)) {
84             upg_print("[upg_check_ota_info]kernela 0x%x \r\n", ota_info);
85             return HI_FALSE;
86         }
87         return HI_TRUE;
88     }
89 
90     if ((ota_info != HI_UPG_FILE_ATTR_KERNELA)) {
91         upg_print("[upg_check_ota_info]kernelb 0x%x \r\n", ota_info);
92         return HI_FALSE;
93     }
94 #endif
95     return HI_TRUE;
96 }
97 
upg_check_file_attributes(hi_u8 file_type,hi_u8 file_attr)98 hi_u32 upg_check_file_attributes(hi_u8 file_type, hi_u8 file_attr)
99 {
100     hi_u8 file_info = file_attr;
101     hi_u8 ota_info = file_info & HI_UPG_OTA_SETTINGS_MASK;
102     hi_u8 encry_info = file_info >> 6; /* 6: ota settings bit number */
103 
104     upg_print("[upg check attributes]type-attr-encry-ota:0x%x-0x%x-0x%x-0x%x \r\n",
105               file_type, file_attr, encry_info, ota_info);
106     if (upg_check_encrypt_info_is_match(encry_info) == HI_FALSE) {
107         return HI_ERR_UPG_ENCRYPT_NOT_MATCH;
108     }
109 
110     if (upg_check_ota_info_is_match(file_type, ota_info) == HI_FALSE) {
111         return HI_ERR_UPG_OTA_NOT_MATCH;
112     }
113     upg_print("[upg check attributes]success \r\n");
114 
115     return HI_ERR_SUCCESS;
116 }
117 
upg_check_code_ver(hi_u8 ver)118 hi_u32 upg_check_code_ver(hi_u8 ver)
119 {
120     hi_u8 current_ver;
121     hi_u32 ret;
122 
123     if (ver > KERELN_VER_MAX) {
124         upg_print("[upg check code ver]file ver:%d \r\n", ver);
125         return HI_ERR_UPG_KERNEL_VER_OVER;
126     }
127 
128     ret = upg_get_efuse_code_ver(&current_ver);
129     if (ret != HI_ERR_SUCCESS) {
130         upg_print("[upg check code ver]get ver ret:0x%x \r\n", ret);
131         return ret;
132     }
133 
134     if (ver < current_ver) {
135         upg_print("[upg check code ver]current>file:%d-%d \r\n", current_ver, ver);
136         return HI_ERR_UPG_LOW_KERNEL_VER;
137     }
138 
139     if ((current_ver == KERELN_VER_MAX) && (ver > KERELN_VER_MAX)) {
140         upg_print("[upg check code ver]current-file:%d-%d \r\n", current_ver, ver);
141         return HI_ERR_UPG_FULL_KERNEL_VER;
142     }
143     return ret;
144 }
145 
upg_check_boot_ver(hi_u8 ver)146 hi_u32 upg_check_boot_ver(hi_u8 ver)
147 {
148     hi_u8 current_ver;
149     hi_u32 ret;
150 
151     if (ver > BOOT_VER_MAX) {
152         upg_print("[upg check boot ver]file ver:%d \r\n", ver);
153         return HI_ERR_UPG_BOOT_VER_OVER;
154     }
155 
156     ret = upg_get_efuse_boot_ver(&current_ver);
157     if (ret != HI_ERR_SUCCESS) {
158         upg_print("[upg check boot ver]get ver ret:0x%x \r\n", ret);
159         return ret;
160     }
161 
162     if (ver < current_ver) {
163         upg_print("[upg check boot ver]current>file:%d-%d \r\n", current_ver, ver);
164         return HI_ERR_UPG_LOW_BOOT_VER;
165     }
166 
167     if ((current_ver == BOOT_VER_MAX) && (ver > BOOT_VER_MAX)) {
168         upg_print("[upg check boot ver]current-file:%d-%d \r\n", current_ver, ver);
169         return HI_ERR_UPG_FULL_BOOT_VER;
170     }
171     return ret;
172 }
173 
upg_check_version(hi_u8 file_type,hi_u8 ver)174 hi_u32 upg_check_version(hi_u8 file_type, hi_u8 ver)
175 {
176     hi_u32 ret;
177     if (file_type == HI_UPG_FILE_KERNEL) {
178         ret = upg_check_code_ver(ver);
179     } else if (file_type == HI_UPG_FILE_BOOT) {
180         ret = upg_check_boot_ver(ver);
181     } else {
182         return HI_ERR_UPG_FILE_TYPE;
183     }
184     upg_print("[upg check ver]ret:0x%x \r\n", ret);
185     return ret;
186 }
187 
upg_check_file_len(hi_u8 file_type,hi_u32 file_len)188 hi_u32 upg_check_file_len(hi_u8 file_type, hi_u32 file_len)
189 {
190     hi_u32 max_len = 0;
191     hi_u32 ret = upg_get_max_file_len(file_type, &max_len);
192     if (ret != HI_ERR_SUCCESS) {
193         return ret;
194     }
195 
196     if (file_len > max_len) {
197         upg_print("[upg check file len]fail,filetype-filelen:0x%x-0x%x-0x%x. \r\n", file_type, file_len, max_len);
198         return HI_ERR_UPG_FILE_LEN_OVER;
199     }
200     return HI_ERR_SUCCESS;
201 }
202 
upg_get_common_head_from_flash(hi_u32 addr,hi_upg_common_head * head)203 hi_u32 upg_get_common_head_from_flash(hi_u32 addr, hi_upg_common_head *head)
204 {
205     hi_u32 ret = hi_flash_read(addr, sizeof(hi_upg_common_head), (hi_u8 *)head);
206     if (ret != HI_ERR_SUCCESS) {
207         upg_print("[upg get common head]fail,addr-ret:0x%x-0x%x \r\n", addr, ret);
208         return ret;
209     }
210     return ret;
211 }
212 
upg_get_section_head_from_flash(hi_u32 addr,hi_upg_section_head * section_head)213 hi_u32 upg_get_section_head_from_flash(hi_u32 addr, hi_upg_section_head *section_head)
214 {
215     hi_upg_common_head head = { 0 };
216     hi_u32 ret;
217 
218     if (section_head == HI_NULL) {
219         upg_print("[upg get section head]is null.\r\n");
220         return HI_ERR_UPG_NULL_POINTER;
221     }
222     ret = hi_flash_read(addr, sizeof(hi_upg_common_head), (hi_u8 *)(&head));
223     if (ret != HI_ERR_SUCCESS) {
224         upg_print("[upg get section head]common head read ret:0x%x \r\n", ret);
225         return ret;
226     }
227     ret = hi_flash_read(addr + head.section_offset, sizeof(hi_upg_section_head), (hi_u8 *)section_head);
228     if (ret != HI_ERR_SUCCESS) {
229         upg_print("[upg get section head]flash read ret:0x%x \r\n", ret);
230         return ret;
231     }
232 
233     return ret;
234 }
235 
upg_check_alg_param(HI_CONST hi_upg_common_head * head)236 hi_u32 upg_check_alg_param(HI_CONST hi_upg_common_head *head)
237 {
238     sign_alg_param alg_param = {0};
239 
240     if (head == HI_NULL) {
241         return HI_ERR_FAILURE;
242     }
243 
244     if (memcpy_s(&alg_param, sizeof(sign_alg_param), &(head->param), sizeof(sign_alg_param)) != EOK) {
245         return HI_ERR_FAILURE;
246     }
247     if ((alg_param.sign_alg != HI_MODE_PKCS_V15) && (alg_param.sign_alg != HI_MODE_PKCS_PSS) &&
248         (alg_param.sign_alg != HI_MODE_ECC)) {
249         return HI_ERR_UPG_SIGN_ALG;
250     }
251 
252     if (alg_param.sign_alg < HI_MODE_ECC) {
253         if (head->section_offset != (sizeof(hi_upg_common_head) + sizeof(upg_rsa_key) + sizeof(upg_rsa_sign))) {
254             return HI_ERR_UPG_RSA_HEAD_SIGN;
255         }
256         return HI_ERR_SUCCESS;
257     }
258 
259     if (head->section_offset != (sizeof(hi_upg_common_head) + sizeof(upg_ecc_key) + sizeof(upg_ecc_sign))) {
260         return HI_ERR_UPG_ECC_HEAD_SIGN;
261     }
262     return HI_ERR_SUCCESS;
263 }
264 
upg_check_head_common_info(const hi_upg_common_head * head,hi_u32 head_size)265 hi_u32 upg_check_head_common_info(const hi_upg_common_head *head, hi_u32 head_size)
266 {
267     hi_bool flag;
268 
269     if (head_size != sizeof(hi_upg_common_head)) {
270         return HI_ERR_UPG_HEAD_LEN;
271     }
272 
273     hi_u32 ret = upg_check_image_id(head->image_id);
274     if (ret != HI_ERR_SUCCESS) {
275         return ret;
276     }
277 
278     ret = upg_check_file_type(head->file_type);
279     if (ret != HI_ERR_SUCCESS) {
280         return ret;
281     }
282 
283     ret = upg_check_file_attributes(head->file_type, head->file_attr);
284     if (ret != HI_ERR_SUCCESS) {
285         return ret;
286     }
287 
288     ret = upg_check_file_len(head->file_type, head->file_len);
289     if (ret != HI_ERR_SUCCESS) {
290         return ret;
291     }
292 
293     if ((head->file_len != (head->section_offset + head->section_len)) ||
294         (head->section_offset != (sizeof(hi_upg_common_head) + sizeof(hi_upg_key) + sizeof(hi_upg_sign))) ||
295         (head->section_len < (sizeof(hi_upg_section_head) + sizeof(hi_upg_sign)))) {
296         upg_print("[upg check len]fail:0x%x-0x%x-0x%x \r\n", head->file_len, head->section_offset, head->section_len);
297         return HI_ERR_UPG_FILE_LEN;
298     }
299 
300     /* The RSA, ECC, and SHA256 authentication modes have the same key length. */
301     if (head->key_len != sizeof(upg_rsa_key)) {
302         return HI_ERR_UPG_KEY_LEN;
303     }
304 
305     ret = upg_is_secure_efuse(&flag);
306     if (ret != HI_ERR_SUCCESS) {
307         upg_print("[upg check head common]get secure efuse,err:0x%x \r\n", ret);
308         return ret;
309     }
310 
311     if (flag == HI_FALSE) {
312         upg_print("[upg check head common]not secure boot.\r\n");
313         return HI_ERR_SUCCESS;
314     }
315 
316     ret = upg_check_version(head->file_type, head->file_version);
317     if (ret != HI_ERR_SUCCESS) {
318         return ret;
319     }
320 
321     return upg_check_alg_param(head);
322 }
323 
upg_check_common_head(const hi_upg_common_head * head,hi_u32 head_size)324 hi_u32 upg_check_common_head(const hi_upg_common_head *head, hi_u32 head_size)
325 {
326     hi_u32 ret = upg_check_head_common_info(head, head_size);
327     if (ret != HI_ERR_SUCCESS) {
328         upg_print("[upg check common head]ret:0x%x \r\n", ret);
329         return ret;
330     }
331     ret = upg_user_define_verify(&(head->user_info));
332     if (ret != HI_ERR_SUCCESS) {
333         upg_print("[upg check common head]user verify fail,ret:0x%x\r\n", ret);
334     }
335     return ret;
336 }
337 
upg_verify_file(hi_u32 addr)338 hi_u32 upg_verify_file(hi_u32 addr)
339 {
340     hi_u32 ret = HI_ERR_UPG_MALLOC_FAIL;
341     hi_upg_head *upg_head = (hi_upg_head *)hi_malloc(HI_MOD_ID_UPG, sizeof(hi_upg_head));
342     hi_upg_common_head *common_head = HI_NULL;
343     hi_upg_section_head *section_head = HI_NULL;
344 
345     if (upg_head == HI_NULL) {
346         goto end;
347     }
348     ret = hi_flash_read(addr, sizeof(hi_upg_head), (hi_u8 *)upg_head);
349     if (ret != HI_ERR_SUCCESS) {
350         upg_print("[upg check file]get upg head addr:0x%x ret:0x%x \r\n", addr, ret);
351         goto end;
352     }
353     common_head = &(upg_head->common);
354     ret = upg_check_upg_file(addr, upg_head);
355     if (ret != HI_ERR_SUCCESS) {
356         upg_print("[upg check file]secure ret:0x%x \r\n", ret);
357         goto end;
358     }
359     /* Add check boot bin process. */
360     if (common_head->file_type == HI_UPG_FILE_BOOT) {
361         section_head = (hi_upg_section_head *)hi_malloc(HI_MOD_ID_UPG, sizeof(hi_upg_section_head));
362         if (section_head == HI_NULL) {
363             ret = HI_ERR_UPG_MALLOC_FAIL;
364             goto end;
365         }
366         memset_s(section_head, sizeof(hi_upg_section_head), 0, sizeof(hi_upg_section_head));
367         ret = hi_flash_read(addr + common_head->section_offset, sizeof(hi_upg_section_head), (hi_u8 *)section_head);
368         if (ret != HI_ERR_SUCCESS) {
369             upg_print("[upg get section head]flash read ret:0x%x \r\n", ret);
370             goto end;
371         }
372         ret = upg_check_boot_file(addr + section_head->section0_offset, section_head->section0_len);
373     }
374 end:
375     upg_mem_free(upg_head);
376     upg_mem_free(section_head);
377     return ret;
378 }
379