• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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