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(¤t_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(¤t_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