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(¶m, 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(¶m);
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(¶m);
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