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
13 #include "tee_trusted_storage_api.h"
14 #include "tee_mem_mgmt_api.h"
15 #include "tee_log.h"
16 #include "securec.h"
17 #include "tee_ext_api.h"
18
19 #define PARAM_COUNT 4
20 #define MAX_AES_KEY_SIZE 256
21 #define ARRAY_SIZE 32
22
23 enum {
24 CMD_STORE_KEY_DEMO = 1,
25 CMD_STORE_DATA_DEMO = 2,
26 CMD_ENUMERATOR_DEMO = 3,
27 };
28
29 const char *g_write_buffer = "It is a test for persist object!";
30
store_key_sample(void)31 TEE_Result store_key_sample(void)
32 {
33 uint32_t storage_id = TEE_OBJECT_STORAGE_PRIVATE;
34 TEE_ObjectHandle transient_key = NULL;
35 TEE_ObjectHandle persistent_key = NULL;
36 TEE_Result ret;
37 uint32_t w_flags = TEE_DATA_FLAG_ACCESS_WRITE;
38 uint32_t r_flags = TEE_DATA_FLAG_ACCESS_READ;
39 char attr_buffer[ARRAY_SIZE] = "test save attribute\n";
40 void *object_id = "store_key_sample.txt";
41 void *aes_key = NULL;
42
43 tlogd("store_key_sample start:============");
44
45 /* Allocating Storage Space for Keys */
46 ret = TEE_AllocateTransientObject(TEE_TYPE_AES, MAX_AES_KEY_SIZE, (&transient_key));
47 if (ret != TEE_SUCCESS) {
48 tloge("Failed to execute allocate transient object:ret = 0x%x", ret);
49 return ret;
50 }
51
52 TEE_Attribute *aes_attribute = (TEE_Attribute *)TEE_Malloc(sizeof(TEE_Attribute), 0);
53 if (aes_attribute == NULL) {
54 tloge("Failed to malloc");
55 TEE_FreeTransientObject(transient_key);
56 return TEE_ERROR_OUT_OF_MEMORY;
57 }
58
59 TEE_InitRefAttribute(aes_attribute, TEE_ATTR_SECRET_VALUE, attr_buffer, sizeof(attr_buffer));
60 ret = TEE_PopulateTransientObject(transient_key, aes_attribute, 1);
61 if (ret != TEE_SUCCESS) {
62 tloge("Failed to execute populate transient object:ret = %d", ret);
63 goto cleanup_1;
64 }
65
66 /* Create a persistent file to store the key */
67 ret = TEE_CreatePersistentObject(storage_id, object_id, strlen(object_id), w_flags, transient_key, NULL, 0,
68 (&persistent_key));
69 if (ret != TEE_SUCCESS) {
70 tloge("Failed to create object:ret = 0x%x", ret);
71 goto cleanup_1;
72 }
73 TEE_CloseObject(persistent_key);
74
75 /* Open the object to obtain key. */
76 ret = TEE_OpenPersistentObject(storage_id, object_id, strlen(object_id),
77 r_flags | TEE_DATA_FLAG_ACCESS_WRITE_META, (&persistent_key));
78 if (ret != TEE_SUCCESS) {
79 tloge("Failed to execute open persistent object:ret = %x", ret);
80 TEE_Free(aes_key);
81 return ret;
82 }
83 TEE_CloseObject(persistent_key);
84 persistent_key = NULL;
85 cleanup_1:
86 TEE_Free(aes_attribute);
87 TEE_FreeTransientObject(transient_key);
88 return ret;
89 }
90
check_store_data(uint32_t storage_id,void * create_object_id)91 TEE_Result check_store_data(uint32_t storage_id, void *create_object_id)
92 {
93 char *read_buffer = NULL;
94 uint32_t count = 0;
95 TEE_ObjectHandle persistent_data = NULL;
96 TEE_ObjectInfo object_info = {0};
97 uint32_t r_flags = TEE_DATA_FLAG_ACCESS_READ;
98 TEE_Result ret;
99
100 /* Open the created file and read data. */
101 ret = TEE_OpenPersistentObject(storage_id, create_object_id, strlen(create_object_id),
102 r_flags, (&persistent_data));
103 if (ret != TEE_SUCCESS) {
104 tloge("Failed to open file:ret = 0x%x", ret);
105 return ret;
106 }
107
108 ret = TEE_GetObjectInfo1(persistent_data, &object_info);
109 if (ret != TEE_SUCCESS) {
110 tloge("Failed to open file:ret = 0x%x", ret);
111 TEE_CloseObject(persistent_data);
112 return ret;
113 }
114
115 read_buffer = TEE_Malloc(object_info.dataSize + 1, 0);
116 if (read_buffer == NULL) {
117 tloge("Failed to open file:ret = 0x%x", ret);
118 TEE_CloseObject(persistent_data);
119 return ret;
120 }
121
122 /* Read data that has been stored in secure storage */
123 ret = TEE_ReadObjectData(persistent_data, read_buffer, object_info.dataSize, &count);
124 if (ret != TEE_SUCCESS) {
125 TEE_CloseObject(persistent_data);
126 TEE_Free(read_buffer);
127 return ret;
128 }
129 if (TEE_MemCompare(g_write_buffer, read_buffer, strlen(g_write_buffer)) != 0) {
130 TEE_CloseObject(persistent_data);
131 TEE_Free(read_buffer);
132 return TEE_FAIL;
133 }
134 tlogi("Succeed to Compare Date");
135 /* close permanent object */
136 TEE_CloseObject(persistent_data);
137 TEE_Free(read_buffer);
138 return TEE_SUCCESS;
139 }
140
store_data_sample(void)141 TEE_Result store_data_sample(void)
142 {
143 uint32_t storage_id = TEE_OBJECT_STORAGE_PRIVATE;
144 uint32_t w_flags = TEE_DATA_FLAG_ACCESS_WRITE;
145 void *create_object_id = "store_data_sample.txt";
146 TEE_ObjectHandle persistent_data = NULL;
147 TEE_Result ret;
148
149 tlogd("store_data_sample start:============");
150
151 /*
152 * Create a permanent object: The flag is a write operation.
153 * (The initialData, objectinfo, and attributes are written to the physical media.)
154 */
155 ret = TEE_CreatePersistentObject(storage_id, create_object_id, strlen(create_object_id), w_flags,
156 TEE_HANDLE_NULL, NULL, 0, (&persistent_data));
157 if (ret != TEE_SUCCESS) {
158 tloge("Failed to create file: ret = 0x%x", ret);
159 return ret;
160 }
161
162 ret = TEE_WriteObjectData(persistent_data, g_write_buffer, strlen(g_write_buffer));
163 if (ret != TEE_SUCCESS) {
164 tloge("Failed to write file: ret = 0x%x", ret);
165 /*
166 * After a file is opened or created, the exception branch must close the file.
167 * Otherwise, memory leakage occurs.
168 */
169 TEE_CloseObject(persistent_data);
170 return ret;
171 }
172 TEE_CloseObject(persistent_data);
173
174 return check_store_data(storage_id, create_object_id);
175 }
176
177 #define HASH_LEN 32
178 #define DIR_LEN 64
179 #define HASH_NAME_BUFF_LEN (2 * HASH_LEN + 1 + DIR_LEN)
180
enumerator_sample()181 TEE_Result enumerator_sample()
182 {
183 TEE_Result ret;
184 TEE_ObjectEnumHandle object_enumerator = NULL;
185 TEE_ObjectInfo obj_info = {0};
186 uint8_t object_id[HASH_NAME_BUFF_LEN] = {0};
187 size_t object_id_len = HASH_NAME_BUFF_LEN;
188
189 ret = TEE_AllocatePersistentObjectEnumerator(&object_enumerator);
190 if (ret != TEE_SUCCESS) {
191 tloge("Failed to allocate objectEnumerator");
192 return ret;
193 }
194
195 ret = TEE_StartPersistentObjectEnumerator(object_enumerator, TEE_OBJECT_STORAGE_PRIVATE);
196 if (ret != TEE_SUCCESS) {
197 tloge("Failed to start object_enumerator");
198 goto clean;
199 }
200
201 ret = TEE_GetNextPersistentObject(object_enumerator, &obj_info, object_id, &object_id_len);
202 if (ret != TEE_SUCCESS) {
203 tloge("Failed get next persistent object");
204 }
205 clean:
206 TEE_FreePersistentObjectEnumerator(object_enumerator);
207 return ret;
208 }
209
TA_CreateEntryPoint(void)210 TEE_Result TA_CreateEntryPoint(void)
211 {
212 TEE_Result ret;
213
214 tlogd("----- TA entry point ----- ");
215 /* When you develop your own CA, you need to change the name to your own path and CA name. */
216 ret = AddCaller_CA_exec("/vendor/bin/secstorage_demo_ca", 0);
217 if (ret == TEE_SUCCESS) {
218 tlogd("TA entry point: add ca whitelist success");
219 } else {
220 tloge("TA entry point: add ca whitelist failed");
221 return TEE_ERROR_GENERIC;
222 }
223 return TEE_SUCCESS;
224 }
225
TA_OpenSessionEntryPoint(uint32_t parm_type,TEE_Param params[PARAM_COUNT],void ** session_context)226 TEE_Result TA_OpenSessionEntryPoint(uint32_t parm_type,
227 TEE_Param params[PARAM_COUNT], void** session_context)
228 {
229 (void)parm_type;
230 (void)params;
231 (void)session_context;
232 tlogd("---- TA open session -------- ");
233
234 return TEE_SUCCESS;
235 }
236
TA_InvokeCommandEntryPoint(void * session_context,uint32_t cmd_id,uint32_t parm_type,TEE_Param params[PARAM_COUNT])237 TEE_Result TA_InvokeCommandEntryPoint(void* session_context, uint32_t cmd_id, uint32_t parm_type,
238 TEE_Param params[PARAM_COUNT])
239 {
240 TEE_Result ret;
241 (void)session_context;
242 (void)params;
243 tlogd("---- TA invoke command ----------- ");
244 if (!check_param_type(parm_type,
245 TEE_PARAM_TYPE_NONE,
246 TEE_PARAM_TYPE_NONE,
247 TEE_PARAM_TYPE_NONE,
248 TEE_PARAM_TYPE_NONE)) {
249 tloge("Bad expected parameter types");
250 return TEE_ERROR_BAD_PARAMETERS;
251 }
252
253 switch (cmd_id) {
254 case CMD_STORE_KEY_DEMO:
255 ret = store_key_sample();
256 if (ret != TEE_SUCCESS) {
257 tloge("InvokeCommand Failed 0x%x. cmd is %u", ret, cmd_id);
258 return ret;
259 }
260 break;
261 case CMD_STORE_DATA_DEMO:
262 ret = store_data_sample();
263 if (ret != TEE_SUCCESS) {
264 tloge("InvokeCommand Failed 0x%x. cmd is %u", ret, cmd_id);
265 return ret;
266 }
267 break;
268 case CMD_ENUMERATOR_DEMO:
269 ret = enumerator_sample();
270 if (ret != TEE_SUCCESS) {
271 tloge("InvokeCommand Failed 0x%x. cmd is %u", ret, cmd_id);
272 return ret;
273 }
274 break;
275 default:
276 tloge("Unknown cmd is %u", cmd_id);
277 ret = TEE_ERROR_BAD_PARAMETERS;
278 }
279
280 return ret;
281 }
282
TA_CloseSessionEntryPoint(void * session_context)283 void TA_CloseSessionEntryPoint(void* session_context)
284 {
285 (void)session_context;
286 tlogd("---- close session ----- ");
287 }
288
TA_DestroyEntryPoint(void)289 void TA_DestroyEntryPoint(void)
290 {
291 tlogd("---- destory TA ---- ");
292 }
293