• 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_load_ext_mf.h"
13 #include <securec.h>
14 #include <ta_framework.h>
15 #include <tee_mem_mgmt_api.h>
16 #include <tee_log.h>
17 #include <dyn_conf_dispatch_inf.h>
18 
19 struct config {
20     char *key;
21     int type;
22 };
23 
24 // Add all valid configurations
25 static const struct config g_valid_config[] = { { "gpd.ta.distribution", TA_DISTRIBUTION },
26                                                 { "gpd.ta.api_level", TA_API_LEVEL },
27                                                 { "gpd.sdk.version", SDK_VERSION },
28                                                 { "gpd.ta.is_lib", IS_LIB },
29 
30                                                 { "gpd.ta.objectEnumEnable", SSA_ENUM_ENABLE },
31                                                 { "gpd.ta.dynConf", IS_DYN_CONF },
32                                                 { "gpd.ta.target_type", TARGET_TYPE },
33                                                 { "gpd.ta.sys_verify_ta", SYS_VERIFY_TA },
34                                                 { "gpd.elf.target_version", TARGET_VERSION },
35                                                 { "gpd.ta.hardWareType", HARD_WARE_TYPE},
36                                                 { "gpd.srv.is_need_release_ta_res", SRV_RELEASE_TA_RES},
37                                                 { "gpd.srv.crash_callback", SRV_CRASH_CALLBACK},
38                                                 { "gpd.srv.is_need_create_msg", SRV_NEED_CREATE_MSG},
39                                                 { "gpd.srv.is_need_release_msg", SRV_NEED_RELEASE_MSG},
40                                                 { NULL, UNSUPPORTED } };
41 
get_conf_type(const char * key,uint32_t key_size)42 static int get_conf_type(const char *key, uint32_t key_size)
43 {
44     if (key == NULL || key_size == 0)
45         return TEE_ERROR_BAD_PARAMETERS;
46     for (int i = 0; g_valid_config[i].key != NULL; i++) {
47         uint32_t len = strlen(g_valid_config[i].key);
48         if (len == key_size) {
49             int ret = TEE_MemCompare(g_valid_config[i].key, key, key_size);
50             if (ret == 0)
51                 return g_valid_config[i].type;
52         }
53     }
54     return UNSUPPORTED;
55 }
56 
str_to_bool(const char * str,size_t str_size,bool * value)57 static TEE_Result str_to_bool(const char *str, size_t str_size, bool *value)
58 {
59     if (value == NULL || str == NULL || str_size == 0)
60         return TEE_ERROR_BAD_PARAMETERS;
61     int ret = strcasecmp(str, "true");
62     if (ret == 0)
63         *value = true;
64     else
65         *value = false;
66     return TEE_SUCCESS;
67 }
68 
str_to_uint16(const char * str,size_t str_size,uint16_t * value,int32_t base)69 static TEE_Result str_to_uint16(const char *str, size_t str_size, uint16_t *value, int32_t base)
70 {
71     if (value == NULL || str == NULL || str_size == 0)
72         return TEE_ERROR_BAD_PARAMETERS;
73 
74     long val = strtol(str, NULL, base);
75 
76     bool temp_check = (val < 0 || val > 0xFFFF); // Max value of uint16_t
77     if (temp_check) {
78         tloge("Invalid string for type uint16_t");
79         return TEE_ERROR_GENERIC;
80     }
81     *value = (uint16_t)val;
82 
83     return TEE_SUCCESS;
84 }
85 
manifest_item_params_check(char * item,size_t item_size,manifest_extension_t * mani_ext)86 static bool manifest_item_params_check(char *item, size_t item_size, manifest_extension_t *mani_ext)
87 {
88     if (item == NULL)
89         return true;
90 
91     if (!((mani_ext != NULL && item_size > 0) || (item_size == 0)))
92         return true;
93 
94     return false;
95 }
96 
is_service_type(int type)97 static bool is_service_type(int type)
98 {
99     return (type == SRV_RELEASE_TA_RES || type == SRV_CRASH_CALLBACK ||
100         type == SRV_NEED_CREATE_MSG || type == SRV_NEED_RELEASE_MSG || type == SYS_VERIFY_TA);
101 }
102 
parse_service_manifest_item(int type,char * value,uint32_t size,manifest_extension_t * mani_ext)103 static TEE_Result parse_service_manifest_item(int type, char *value, uint32_t size, manifest_extension_t *mani_ext)
104 {
105     switch (type) {
106     case SRV_RELEASE_TA_RES:
107         return str_to_bool(value, size, &mani_ext->is_need_release_ta_res);
108     case SRV_CRASH_CALLBACK:
109         return str_to_bool(value, size, &mani_ext->crash_callback);
110     case SRV_NEED_CREATE_MSG:
111         return str_to_bool(value, size, &mani_ext->is_need_create_msg);
112     case SRV_NEED_RELEASE_MSG:
113         return str_to_bool(value, size, &mani_ext->is_need_release_msg);
114     case SYS_VERIFY_TA:
115         return str_to_bool(value, size, &mani_ext->sys_verify_ta);
116     default:
117         return TEE_ERROR_GENERIC;
118     }
119 
120     return TEE_SUCCESS;
121 }
122 
parse_ext_item(int type,char * value,manifest_extension_t * mani_ext)123 static TEE_Result parse_ext_item(int type, char *value, manifest_extension_t *mani_ext)
124 {
125     if (is_service_type(type))
126         return parse_service_manifest_item(type, value, strlen(value), mani_ext);
127     return TEE_SUCCESS;
128 }
tee_secure_img_parse_manifest_item(char * item,size_t item_size,manifest_extension_t * mani_ext,struct dyn_conf_t * dyn_conf)129 static TEE_Result tee_secure_img_parse_manifest_item(char *item, size_t item_size, manifest_extension_t *mani_ext,
130                                                      struct dyn_conf_t *dyn_conf)
131 {
132     char *ptr = NULL;
133     TEE_Result ret;
134 
135     if (manifest_item_params_check(item, item_size, mani_ext))
136         return TEE_ERROR_BAD_PARAMETERS;
137     // Skip the empty line of manifest extension configuration
138     if (item_size == 0)
139         return TEE_SUCCESS;
140 
141     // Get the key of the item
142     char *name = strtok_r(item, ":", &ptr);
143     // Get the value of the item
144     char *value = strtok_r(NULL, ":", &ptr);
145 
146     bool temp_check = (name == NULL || value == NULL);
147     if (temp_check)
148         return TEE_ERROR_GENERIC;
149 
150     int type = get_conf_type(name, strlen(name));
151 
152     switch (type) {
153     case TA_DISTRIBUTION:
154         return str_to_uint16(value, strlen(value), &mani_ext->distribution, HEX_BASE);
155     case TA_API_LEVEL:
156         return str_to_uint16(value, strlen(value), &mani_ext->api_level, HEX_BASE);
157     case SDK_VERSION:
158         return str_to_uint16(value, strlen(value), &mani_ext->sdk_version, HEX_BASE);
159     case IS_LIB:
160         return str_to_bool(value, strlen(value), &mani_ext->is_lib);
161     case SSA_ENUM_ENABLE:
162         return str_to_bool(value, strlen(value), &mani_ext->ssa_enum_enable);
163     case IS_DYN_CONF:
164         /* if dyn_conf is NULL, means that is not support dyn conf */
165         if (dyn_conf != NULL)
166             dyn_conf->dyn_conf_size = 1;
167         return TEE_SUCCESS;
168     case TARGET_TYPE:
169         return str_to_uint16(value, strlen(value), &mani_ext->target_type, HEX_BASE);
170     case TARGET_VERSION:
171         ret = str_to_uint16(value, strlen(value), &mani_ext->target_version, DECIMAL_BASE);
172         temp_check = (ret == TEE_SUCCESS && mani_ext->target_version == 0);
173         if (temp_check) {
174             tloge("target version : 0 is not valid\n");
175             ret = TEE_ERROR_BAD_PARAMETERS;
176         }
177         return ret;
178     case MEM_PAGE_ALIGN:
179         return str_to_bool(value, strlen(value), &mani_ext->mem_page_align);
180     case HARD_WARE_TYPE:
181         return str_to_uint16(value, strlen(value), &mani_ext->hardware_type, DECIMAL_BASE);
182     default:
183         return parse_ext_item(type, value, mani_ext);
184     }
185 }
186 
set_dyn_conf(const char * start,const char * end,struct dyn_conf_t * dyn_conf)187 static TEE_Result set_dyn_conf(const char *start, const char *end, struct dyn_conf_t *dyn_conf)
188 {
189     /*
190      * if dyn_conf is NULL, means that is not support dyn conf
191      * if dyn_conf->dyn_conf_buffer is not NULL, means dyn_conf_buffer has already been set_dyn_conf
192      * if dyn_conf_size is 0, means we haven't find gpd.ta.dynConf flag yet
193      */
194     if (dyn_conf == NULL || dyn_conf->dyn_conf_buffer != NULL || dyn_conf->dyn_conf_size == 0)
195         return TEE_SUCCESS;
196 
197     if ((uintptr_t)(end - start) <= (strlen(DYN_CONF_START) + 1) || (uintptr_t)(end - start) >= MAX_IMAGE_LEN) {
198         tloge("dyn conf size is invalied\n");
199         return TEE_ERROR_GENERIC;
200     }
201 
202     /* end - start is dyn_conf total size, we must del 'gpd.ta.dynConf:' from it */
203     dyn_conf->dyn_conf_size = (uintptr_t)(end - start) - (strlen(DYN_CONF_START) + 1);
204     dyn_conf->dyn_conf_buffer = malloc(dyn_conf->dyn_conf_size);
205     if (dyn_conf->dyn_conf_buffer == NULL) {
206         tloge("failed to load dyn conf buffer\n");
207         return TEE_ERROR_GENERIC;
208     }
209 
210     /* copy the dyn conf buffer, we should ignore 'gpd.ta.dynConf:', and copy rest of it */
211     errno_t rc = memcpy_s(dyn_conf->dyn_conf_buffer, dyn_conf->dyn_conf_size,
212                           start + strlen(DYN_CONF_START) + 1, dyn_conf->dyn_conf_size);
213     if (rc != EOK) {
214         tloge("Failed to copy extension");
215         free(dyn_conf->dyn_conf_buffer);
216         dyn_conf->dyn_conf_buffer = NULL;
217         return TEE_ERROR_SECURITY;
218     }
219 
220     return TEE_SUCCESS;
221 }
222 
check_extention_process_params(const char * extension,uint32_t extension_size,manifest_extension_t * mani_ext)223 static bool check_extention_process_params(const char *extension, uint32_t extension_size,
224                                     manifest_extension_t *mani_ext)
225 {
226     if (extension_size > MAX_IMAGE_LEN) {
227         tloge("manifest extension size too large: %u", extension_size);
228         return true;
229     }
230 
231     if (mani_ext == NULL || extension == NULL || extension_size == 0)
232         return true;
233 
234     if (extension != NULL && extension_size > 0)
235         return false;
236 
237     return true;
238 }
239 
240 #define EXTENSION_MAX 64
tee_secure_img_parse_manifest_extension(const char * extension,uint32_t extension_size,manifest_extension_t * mani_ext,struct dyn_conf_t * dyn_conf)241 TEE_Result tee_secure_img_parse_manifest_extension(const char *extension, uint32_t extension_size,
242                                                   manifest_extension_t *mani_ext, struct dyn_conf_t *dyn_conf)
243 {
244     TEE_Result ret = TEE_SUCCESS;
245 
246     if (check_extention_process_params(extension, extension_size, mani_ext))
247         return TEE_ERROR_BAD_PARAMETERS;
248 
249     uint32_t temp_extension_size = extension_size + 1;
250     char *temp_extension = TEE_Malloc(temp_extension_size, 0);
251     if (temp_extension == NULL) {
252         tloge(" Failed to malloc buffer for temp extension\n");
253         return TEE_ERROR_OUT_OF_MEMORY;
254     }
255 
256     if (memcpy_s(temp_extension, temp_extension_size, extension, extension_size) != EOK) {
257         tloge(" Failed to copy extension\n");
258         ret = TEE_ERROR_SECURITY;
259         goto free_buffer;
260     }
261 
262     const char *start = (char *)temp_extension;
263     const char *end = strchr(start, '\n');
264     while (end != NULL) {
265         char buff[EXTENSION_MAX] = {0};
266         uint32_t size = (uint32_t)(end - start);
267 
268         if ((uint32_t)(end - temp_extension) >= temp_extension_size) {
269             ret = TEE_SUCCESS;
270             goto free_buffer;
271         }
272 
273         if (size >= EXTENSION_MAX)
274             size = EXTENSION_MAX - 1;
275 
276         if (memcpy_s(buff, EXTENSION_MAX - 1, start, size) != EOK) {
277             tloge("Failed to copy extension");
278             ret = TEE_ERROR_SECURITY;
279             goto free_buffer;
280         }
281 
282         ret = tee_secure_img_parse_manifest_item(buff, size, mani_ext, dyn_conf);
283         if (ret != TEE_SUCCESS) {
284             tloge("Failed to parse manifest extension item: %s", buff);
285             goto free_buffer;
286         }
287 
288         ret = set_dyn_conf(start, end, dyn_conf);
289         if (ret != TEE_SUCCESS)
290             goto free_buffer;
291 
292         start = end + 1;
293         end = strchr(start, '\n');
294     }
295 free_buffer:
296     TEE_Free(temp_extension);
297     return ret;
298 }
299 
300