1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include "tee_elf_verify.h"
13 #include <fileio.h>
14 #include "tee_elf_verify.h"
15 #include "tee_mem_mgmt_api.h"
16 #include "tee_inner_uuid.h"
17 #include "tee_log.h"
18 #include "tee_crypto_api.h"
19 #include "securec.h"
20 #include "permission_service.h"
21 #include "tee_crypto_hal.h"
22 #include "tee_load_ext_mf.h"
23 #include "ta_verify_key.h"
24 #include "tee_elf_verify_openssl.h"
25 #include "tee_perm_img.h"
26 #include "tee_comm_elf_verify.h"
27 #include "tee_v3_elf_verify.h"
28 #include "tee_elf_verify_inner.h"
29
30 /*
31 * use g_img_info&g_image_hd save the infomation
32 * when loading the image
33 */
34 static load_img_info g_img_info = { { { 0 }, { 0 }, NULL, NULL, NULL, { 0 } },
35 NULL, NULL, 0, 0, 0, false };
36 static ta_property_t *g_ta_property_ptr = NULL;
37
38 static ta_payload_layer_t g_ta_payload = { { 0 }, NULL, NULL, 0 };
39 static uint32_t g_img_size = 0;
40
get_ta_property_ptr(void)41 ta_property_t *get_ta_property_ptr(void)
42 {
43 return g_ta_property_ptr;
44 }
45
get_img_info(void)46 load_img_info *get_img_info(void)
47 {
48 return &g_img_info;
49 }
50
get_ta_payload(void)51 ta_payload_layer_t *get_ta_payload(void)
52 {
53 return &g_ta_payload;
54 }
55
get_img_size(void)56 uint32_t get_img_size(void)
57 {
58 return g_img_size;
59 }
60
overflow_check(uint32_t a,uint32_t b)61 bool overflow_check(uint32_t a, uint32_t b)
62 {
63 if (a > UINT32_MAX_VALUE - b)
64 return true;
65 return false;
66 }
67
copy_hash_data(elf_hash_data * hash_data,uint8_t * hash_src,uint32_t hash_src_size)68 void copy_hash_data(elf_hash_data *hash_data, uint8_t *hash_src, uint32_t hash_src_size)
69 {
70 if (hash_data == NULL || hash_src == NULL)
71 return;
72
73 if (hash_data != NULL && hash_data->hash_size >= MAX_IMAGE_HASH_SIZE) {
74 if (memcpy_s(hash_data->elf_hash, hash_data->hash_size, hash_src, hash_src_size) != 0) {
75 tloge("copy hash data fail\n");
76 hash_data->hash_size = 0;
77 return;
78 }
79 hash_data->hash_size = hash_src_size;
80 }
81 }
82
boundary_check(uint32_t max_size,uint32_t input_size)83 bool boundary_check(uint32_t max_size, uint32_t input_size)
84 {
85 if (input_size > max_size) {
86 tloge("Failed to pass boundary check, max: 0x%x, size: 0x%x\n", max_size, input_size);
87 return true;
88 }
89 return false;
90 }
91
tee_secure_img_duplicate_buff(const uint8_t * src,uint32_t src_size,uint8_t ** dst)92 TEE_Result tee_secure_img_duplicate_buff(const uint8_t *src, uint32_t src_size, uint8_t **dst)
93 {
94 if (src == NULL || dst == NULL || src_size == 0)
95 return TEE_ERROR_BAD_PARAMETERS;
96
97 *dst = TEE_Malloc(src_size, 0);
98 if (*dst == NULL) {
99 tloge(" Failed to malloc buffer for dst\n");
100 return TEE_ERROR_OUT_OF_MEMORY;
101 }
102
103 errno_t rc = memcpy_s(*dst, src_size, src, src_size);
104 if (rc != EOK) {
105 tloge(" Failed to copy from src to dst\n");
106 TEE_Free(*dst);
107 *dst = NULL;
108 return TEE_ERROR_SECURITY;
109 }
110
111 return TEE_SUCCESS;
112 }
113
tee_secure_img_manifest_extention_process(const uint8_t * extension,uint32_t extension_size,manifest_extension_t * mani_ext,struct dyn_conf_t * dyn_conf)114 TEE_Result tee_secure_img_manifest_extention_process(const uint8_t *extension, uint32_t extension_size,
115 manifest_extension_t *mani_ext, struct dyn_conf_t *dyn_conf)
116 {
117 if (extension_size == 0)
118 return TEE_SUCCESS;
119 if (extension == NULL)
120 return TEE_ERROR_BAD_PARAMETERS;
121
122 g_img_info.manifest_buf = (int8_t *)extension;
123 TEE_Result ret = tee_secure_img_parse_manifest_extension((char *)g_img_info.manifest_buf,
124 extension_size, mani_ext, dyn_conf);
125 if (ret != TEE_SUCCESS) {
126 tloge("Failed to parse manifest extension\n");
127 return ret;
128 }
129
130 return TEE_SUCCESS;
131 }
132
133 /*
134 * 1.process_header func's TA header format is inconsistent in v1 & v2
135 * 2.others funcs v1 & v2 is the same, so process_header is not in the struct
136 */
137 static const struct process_version g_process_header[] = {
138 #ifdef DYN_TA_SUPPORT_V3
139 { CIPHER_LAYER_VERSION, free_verify_v3, secure_img_copy_rsp_v3, tee_secure_img_unpack_v3, 0, 0 },
140 #endif
141 };
142
process_header(const uint8_t * share_buf,uint32_t buf_len,uint32_t img_version)143 static TEE_Result process_header(const uint8_t *share_buf, uint32_t buf_len, uint32_t img_version)
144 {
145 TEE_Result ret = TEE_SUCCESS;
146
147 switch (img_version) {
148 #ifdef DYN_TA_SUPPORT_V3
149 case CIPHER_LAYER_VERSION:
150 ret = process_header_v3(share_buf, buf_len);
151 break;
152 #endif
153 default:
154 tloge("Unknown image version error\n");
155 return TEE_ERROR_NOT_SUPPORTED;
156 }
157 if (ret != TEE_SUCCESS)
158 tloge("process header failed, ret=0x%x, img version=%u\n", ret, img_version);
159
160 return ret;
161 }
162
secure_img_load_unpack(const elf_verify_req * req,elf_hash_data * hash_data)163 static TEE_Result secure_img_load_unpack(const elf_verify_req *req,
164 elf_hash_data *hash_data)
165 {
166 TEE_Result ret;
167 int32_t fp = -1;
168
169 (void)hash_data;
170 fp = open(req->tmp_file, O_RDWR, RWRIGHT, (uint64_t)0);
171 if (fp < 0) {
172 tloge("reopen file fail\n");
173 goto unpack_error;
174 }
175
176 void *file_buf = (int8_t *)vfs_mmap(fp, g_img_size, 0);
177 if (file_buf == NULL) {
178 tloge("remap fail, size %u\n", (uint32_t)g_img_size);
179 goto unpack_error;
180 }
181
182 close(fp);
183 fp = -1;
184
185 g_img_info.img_buf = (int8_t *)file_buf;
186 g_img_info.img_offset = 0;
187 g_img_info.img_size = req->img_size;
188
189 ret = process_header((const uint8_t *)g_img_info.img_buf, g_img_info.img_size, g_img_info.img_version);
190 if (ret != TEE_SUCCESS)
191 return ret;
192
193 for (uint32_t i = 0; i < ARRAY_SIZE(g_process_header); ++i) {
194 if (g_process_header[i].tee_secure_img_unpack != NULL &&
195 g_img_info.img_version == g_process_header[i].version) {
196 ret = g_process_header[i].tee_secure_img_unpack(g_process_header[i].rsa_algo_len,
197 g_process_header[i].ta_hd_len, (uint8_t *)(g_img_info.img_buf),
198 g_img_info.img_size, hash_data);
199 if (ret != TEE_SUCCESS)
200 tloge("process header failed, ret=0x%x, img version=%u\n", ret, g_img_info.img_version);
201
202 return ret;
203 }
204 }
205
206 unpack_error:
207 if (fp >= 0)
208 close(fp);
209 return TEE_ERROR_BAD_PARAMETERS;
210 }
211
unpack_copy_check_params(const elf_verify_req * req)212 static TEE_Result unpack_copy_check_params(const elf_verify_req *req)
213 {
214 g_img_info.img_version = req->version;
215 g_img_size = PAGE_ALIGN_UP(req->img_size + ADDITIONAL_BUF_SIZE);
216 if (g_img_size < req->img_size)
217 return TEE_ERROR_BAD_PARAMETERS; /* overflow_check */
218
219 uint32_t filename_len = strnlen(req->tmp_file, MAX_TAFS_NAME_LEN);
220 if (filename_len == 0 || filename_len >= MAX_TAFS_NAME_LEN)
221 return TEE_ERROR_BAD_PARAMETERS;
222
223 return TEE_SUCCESS;
224 }
225
free_verify(void)226 static TEE_Result free_verify(void)
227 {
228 for (uint32_t i = 0; i < ARRAY_SIZE(g_process_header); ++i) {
229 if (g_process_header[i].tee_free_func != NULL && g_img_info.img_version == g_process_header[i].version) {
230 g_process_header[i].tee_free_func();
231 return TEE_SUCCESS;
232 }
233 }
234
235 tloge("Unsupported ver: %d\n", g_img_info.img_version);
236 return TEE_ERROR_BAD_PARAMETERS;
237 }
238
secure_img_copy_rsp(elf_verify_reply * rep)239 static TEE_Result secure_img_copy_rsp(elf_verify_reply *rep)
240 {
241 rep->conf_registed = g_ta_payload.conf_registed;
242
243 for (uint32_t i = 0; i < ARRAY_SIZE(g_process_header); ++i) {
244 if (g_process_header[i].img_copy_rsp != NULL && g_img_info.img_version == g_process_header[i].version) {
245 TEE_Result ret = g_process_header[i].img_copy_rsp(rep);
246 if (ret != TEE_SUCCESS)
247 tloge("process header failed, ret=0x%x, img version=%u\n", ret, g_img_info.img_version);
248
249 return ret;
250 }
251 }
252 tloge("Unsupported vers: %d\n", g_img_info.img_version);
253 return TEE_ERROR_BAD_PARAMETERS;
254 }
255
256 #define HEX_BYTE_STR_LEN 2
257 #define UUID_STR_FORMAT_LEN 37
258
get_uuid_str(const TEE_UUID * uuid,char * buff,uint32_t len)259 static TEE_Result get_uuid_str(const TEE_UUID *uuid, char *buff, uint32_t len)
260 {
261 if (uuid == NULL || buff == NULL || len < UUID_STR_FORMAT_LEN) {
262 tloge("invalid parameter\n");
263 return TEE_ERROR_GENERIC;
264 }
265
266 int ret = snprintf_s(buff, len, UUID_STR_FORMAT_LEN - 1, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
267 uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion, uuid->clockSeqAndNode[0],
268 uuid->clockSeqAndNode[1], uuid->clockSeqAndNode[2], uuid->clockSeqAndNode[3],
269 uuid->clockSeqAndNode[4], uuid->clockSeqAndNode[5], uuid->clockSeqAndNode[6],
270 uuid->clockSeqAndNode[7]); // refer uuid format definitions
271 if (ret <= 0) {
272 tloge("convert uuid to string failed\n");
273 return TEE_ERROR_GENERIC;
274 }
275 return TEE_SUCCESS;
276 }
277
print_uuid_and_hash(TEE_UUID * uuid,uint8_t * hash_data,size_t size)278 static void print_uuid_and_hash(TEE_UUID *uuid, uint8_t *hash_data, size_t size)
279 {
280 if (uuid == NULL || hash_data == NULL || size > MAX_IMAGE_HASH_SIZE) {
281 tloge("bad params of print_uuid_hash\n");
282 return;
283 }
284 size_t str_buffer_len = size * HEX_BYTE_STR_LEN + 1;
285 char *str_buffer = NULL;
286 char *str_uuid = NULL;
287 TEE_Result ret;
288 str_buffer = (char*)TEE_Malloc(str_buffer_len, 0);
289 if (str_buffer == NULL) {
290 tloge("out of mem\n");
291 goto clear;
292 }
293 str_uuid = (char*)TEE_Malloc(UUID_STR_FORMAT_LEN, 0);
294 if (str_uuid == NULL) {
295 tloge("out of mem\n");
296 goto clear;
297 }
298
299 ret = get_uuid_str(uuid, str_uuid, UUID_STR_FORMAT_LEN);
300 if (ret != TEE_SUCCESS) {
301 tloge("get_uuid_str failed\n");
302 goto clear;
303 }
304
305 str_buffer[0] = '\0';
306 /* the initial len value makes sure the first loop can run normally */
307 int len = 1;
308 for (uint32_t i = 0; i < size; i++) {
309 if (len <= 0 || str_buffer_len - strlen(str_buffer) <= 1) {
310 tloge("str_buffer is too short for hash data left\n");
311 goto clear;
312 }
313 len = snprintf_s(str_buffer + strlen(str_buffer), str_buffer_len - strlen(str_buffer),
314 str_buffer_len - strlen(str_buffer) - 1, "%02x", hash_data[i]);
315 }
316 if (len <= 0) {
317 tloge("write hash data failed\n");
318 goto clear;
319 }
320 /* make sure the string buffer has a '\0' */
321 str_buffer[str_buffer_len - 1] = '\0';
322 tlogi("[TA_UUID]%s[TA_UUID];[IMAGE_HASH]%s[IMAGE_HASH]\n", str_uuid, str_buffer);
323 clear:
324 if (str_uuid != NULL)
325 TEE_Free(str_uuid);
326 if (str_buffer != NULL)
327 TEE_Free(str_buffer);
328 }
329
secure_elf_verify(const elf_verify_req * req,elf_verify_reply * rep)330 TEE_Result secure_elf_verify(const elf_verify_req *req, elf_verify_reply *rep)
331 {
332 TEE_Result ret, tee_ret;
333 elf_hash_data hash_data;
334 (void)memset_s(&hash_data, sizeof(hash_data), 0, sizeof(hash_data));
335
336 if (req == NULL || rep == NULL) {
337 tloge("bad parameter\n");
338 return TEE_ERROR_BAD_PARAMETERS;
339 }
340 if (unpack_copy_check_params(req) != TEE_SUCCESS) {
341 tloge("check req params failed\n");
342 ret = TEE_ERROR_BAD_PARAMETERS;
343 goto reply;
344 }
345 g_ta_property_ptr = &(g_img_info.manifest.mani_info.ta_property);
346
347 hash_data.elf_hash = (uint8_t*)TEE_Malloc(MAX_IMAGE_HASH_SIZE, 0);
348 hash_data.hash_size = MAX_IMAGE_HASH_SIZE;
349 if (hash_data.elf_hash == NULL) {
350 hash_data.hash_size = 0;
351 tloge("malloc for hash data failed!\n");
352 }
353
354 ret = secure_img_load_unpack(req, &hash_data);
355 if (ret != TEE_SUCCESS) {
356 tloge("img unpack fail 0x%x\n", ret);
357 if (g_img_info.dyn_conf_registed || g_ta_payload.conf_registed)
358 (void)secure_img_copy_rsp(rep);
359 goto reply;
360 }
361
362 ret = secure_img_copy_rsp(rep);
363 if (ret != TEE_SUCCESS)
364 tloge("copy elf verify response failed 0x%x\n", ret);
365 if (hash_data.hash_size != 0 && rep != NULL)
366 print_uuid_and_hash(&(rep->srv_uuid), hash_data.elf_hash, hash_data.hash_size);
367
368 reply:
369 tee_ret = free_verify();
370 if (hash_data.elf_hash != NULL)
371 TEE_Free(hash_data.elf_hash);
372 if (tee_ret != TEE_SUCCESS)
373 tlogd("free verify fail\n");
374
375 if (ret != TEE_SUCCESS)
376 return ret;
377
378 return tee_ret;
379 }
380