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