1 /*
2  * Copyright (c) 2017, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <inttypes.h>
29 #include <secure_storage_ta.h>
30 #include <tee_internal_api.h>
31 #include <tee_internal_api_extensions.h>
32 
delete_object(uint32_t param_types,TEE_Param params[4])33 static TEE_Result delete_object(uint32_t param_types, TEE_Param params[4])
34 {
35 	const uint32_t exp_param_types =
36 		TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
37 				TEE_PARAM_TYPE_NONE,
38 				TEE_PARAM_TYPE_NONE,
39 				TEE_PARAM_TYPE_NONE);
40 	TEE_ObjectHandle object;
41 	TEE_Result res;
42 	char *obj_id;
43 	size_t obj_id_sz;
44 
45 	/*
46 	 * Safely get the invocation parameters
47 	 */
48 	if (param_types != exp_param_types)
49 		return TEE_ERROR_BAD_PARAMETERS;
50 
51 	obj_id_sz = params[0].memref.size;
52 	obj_id = TEE_Malloc(obj_id_sz, 0);
53 	if (!obj_id)
54 		return TEE_ERROR_OUT_OF_MEMORY;
55 
56 	TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz);
57 
58 	/*
59 	 * Check object exists and delete it
60 	 */
61 	res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
62 					obj_id, obj_id_sz,
63 					TEE_DATA_FLAG_ACCESS_READ |
64 					TEE_DATA_FLAG_ACCESS_WRITE_META, /* we must be allowed to delete it */
65 					&object);
66 	if (res != TEE_SUCCESS) {
67 		EMSG("Failed to open persistent object, res=0x%08x", res);
68 		TEE_Free(obj_id);
69 		return res;
70 	}
71 
72 	TEE_CloseAndDeletePersistentObject1(object);
73 	TEE_Free(obj_id);
74 
75 	return res;
76 }
77 
create_raw_object(uint32_t param_types,TEE_Param params[4])78 static TEE_Result create_raw_object(uint32_t param_types, TEE_Param params[4])
79 {
80 	const uint32_t exp_param_types =
81 		TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
82 				TEE_PARAM_TYPE_MEMREF_INPUT,
83 				TEE_PARAM_TYPE_NONE,
84 				TEE_PARAM_TYPE_NONE);
85 	TEE_ObjectHandle object;
86 	TEE_Result res;
87 	char *obj_id;
88 	size_t obj_id_sz;
89 	char *data;
90 	size_t data_sz;
91 	uint32_t obj_data_flag;
92 
93 	/*
94 	 * Safely get the invocation parameters
95 	 */
96 	if (param_types != exp_param_types)
97 		return TEE_ERROR_BAD_PARAMETERS;
98 
99 	obj_id_sz = params[0].memref.size;
100 	obj_id = TEE_Malloc(obj_id_sz, 0);
101 	if (!obj_id)
102 		return TEE_ERROR_OUT_OF_MEMORY;
103 
104 	TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz);
105 
106 	data_sz = params[1].memref.size;
107 	data = TEE_Malloc(data_sz, 0);
108 	if (!data)
109 		return TEE_ERROR_OUT_OF_MEMORY;
110 	TEE_MemMove(data, params[1].memref.buffer, data_sz);
111 
112 	/*
113 	 * Create object in secure storage and fill with data
114 	 */
115 	obj_data_flag = TEE_DATA_FLAG_ACCESS_READ |		/* we can later read the oject */
116 			TEE_DATA_FLAG_ACCESS_WRITE |		/* we can later write into the object */
117 			TEE_DATA_FLAG_ACCESS_WRITE_META |	/* we can later destroy or rename the object */
118 			TEE_DATA_FLAG_OVERWRITE;		/* destroy existing object of same ID */
119 
120 	res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
121 					obj_id, obj_id_sz,
122 					obj_data_flag,
123 					TEE_HANDLE_NULL,
124 					NULL, 0,		/* we may not fill it right now */
125 					&object);
126 	if (res != TEE_SUCCESS) {
127 		EMSG("TEE_CreatePersistentObject failed 0x%08x", res);
128 		TEE_Free(obj_id);
129 		TEE_Free(data);
130 		return res;
131 	}
132 
133 	res = TEE_WriteObjectData(object, data, data_sz);
134 	if (res != TEE_SUCCESS) {
135 		EMSG("TEE_WriteObjectData failed 0x%08x", res);
136 		TEE_CloseAndDeletePersistentObject1(object);
137 	} else {
138 		TEE_CloseObject(object);
139 	}
140 	TEE_Free(obj_id);
141 	TEE_Free(data);
142 	return res;
143 }
144 
read_raw_object(uint32_t param_types,TEE_Param params[4])145 static TEE_Result read_raw_object(uint32_t param_types, TEE_Param params[4])
146 {
147 	const uint32_t exp_param_types =
148 		TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
149 				TEE_PARAM_TYPE_MEMREF_OUTPUT,
150 				TEE_PARAM_TYPE_NONE,
151 				TEE_PARAM_TYPE_NONE);
152 	TEE_ObjectHandle object;
153 	TEE_ObjectInfo object_info;
154 	TEE_Result res;
155 	uint32_t read_bytes;
156 	char *obj_id;
157 	size_t obj_id_sz;
158 	char *data;
159 	size_t data_sz;
160 
161 	/*
162 	 * Safely get the invocation parameters
163 	 */
164 	if (param_types != exp_param_types)
165 		return TEE_ERROR_BAD_PARAMETERS;
166 
167 	obj_id_sz = params[0].memref.size;
168 	obj_id = TEE_Malloc(obj_id_sz, 0);
169 	if (!obj_id)
170 		return TEE_ERROR_OUT_OF_MEMORY;
171 
172 	TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz);
173 
174 	data_sz = params[1].memref.size;
175 	data = TEE_Malloc(data_sz, 0);
176 	if (!data)
177 		return TEE_ERROR_OUT_OF_MEMORY;
178 
179 	/*
180 	 * Check the object exist and can be dumped into output buffer
181 	 * then dump it.
182 	 */
183 	res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
184 					obj_id, obj_id_sz,
185 					TEE_DATA_FLAG_ACCESS_READ |
186 					TEE_DATA_FLAG_SHARE_READ,
187 					&object);
188 	if (res != TEE_SUCCESS) {
189 		EMSG("Failed to open persistent object, res=0x%08x", res);
190 		TEE_Free(obj_id);
191 		TEE_Free(data);
192 		return res;
193 	}
194 
195 	res = TEE_GetObjectInfo1(object, &object_info);
196 	if (res != TEE_SUCCESS) {
197 		EMSG("Failed to create persistent object, res=0x%08x", res);
198 		goto exit;
199 	}
200 
201 	if (object_info.dataSize > data_sz) {
202 		/*
203 		 * Provided buffer is too short.
204 		 * Return the expected size together with status "short buffer"
205 		 */
206 		params[1].memref.size = object_info.dataSize;
207 		res = TEE_ERROR_SHORT_BUFFER;
208 		goto exit;
209 	}
210 
211 	res = TEE_ReadObjectData(object, data, object_info.dataSize,
212 				 &read_bytes);
213 	if (res == TEE_SUCCESS)
214 		TEE_MemMove(params[1].memref.buffer, data, read_bytes);
215 	if (res != TEE_SUCCESS || read_bytes != object_info.dataSize) {
216 		EMSG("TEE_ReadObjectData failed 0x%08x, read %" PRIu32 " over %u",
217 				res, read_bytes, object_info.dataSize);
218 		goto exit;
219 	}
220 
221 	/* Return the number of byte effectively filled */
222 	params[1].memref.size = read_bytes;
223 exit:
224 	TEE_CloseObject(object);
225 	TEE_Free(obj_id);
226 	TEE_Free(data);
227 	return res;
228 }
229 
TA_CreateEntryPoint(void)230 TEE_Result TA_CreateEntryPoint(void)
231 {
232 	/* Nothing to do */
233 	return TEE_SUCCESS;
234 }
235 
TA_DestroyEntryPoint(void)236 void TA_DestroyEntryPoint(void)
237 {
238 	/* Nothing to do */
239 }
240 
TA_OpenSessionEntryPoint(uint32_t __unused param_types,TEE_Param __unused params[4],void __unused ** session)241 TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types,
242 				    TEE_Param __unused params[4],
243 				    void __unused **session)
244 {
245 	/* Nothing to do */
246 	return TEE_SUCCESS;
247 }
248 
TA_CloseSessionEntryPoint(void __unused * session)249 void TA_CloseSessionEntryPoint(void __unused *session)
250 {
251 	/* Nothing to do */
252 }
253 
TA_InvokeCommandEntryPoint(void __unused * session,uint32_t command,uint32_t param_types,TEE_Param params[4])254 TEE_Result TA_InvokeCommandEntryPoint(void __unused *session,
255 				      uint32_t command,
256 				      uint32_t param_types,
257 				      TEE_Param params[4])
258 {
259 	switch (command) {
260 	case TA_SECURE_STORAGE_CMD_WRITE_RAW:
261 		return create_raw_object(param_types, params);
262 	case TA_SECURE_STORAGE_CMD_READ_RAW:
263 		return read_raw_object(param_types, params);
264 	case TA_SECURE_STORAGE_CMD_DELETE:
265 		return delete_object(param_types, params);
266 	default:
267 		EMSG("Command ID 0x%x is not supported", command);
268 		return TEE_ERROR_NOT_SUPPORTED;
269 	}
270 }
271