xref: /optee_os/ta/avb/entry.c (revision 4bc2a199d122c30f05bcc61e43da128ffabd46fb)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /* Copyright (c) 2018, Linaro Limited */
3 
4 #include <ta_avb.h>
5 #include <tee_internal_api.h>
6 #include <tee_internal_api_extensions.h>
7 
8 #include <string.h>
9 
10 #define DEFAULT_LOCK_STATE	0
11 
12 static const uint32_t storageid = TEE_STORAGE_PRIVATE_RPMB;
13 static const char rb_obj_name[] = "rb_state";
14 static const char *named_value_prefix = "named_value_";
15 
get_slot_offset(size_t slot,size_t * offset)16 static TEE_Result get_slot_offset(size_t slot, size_t *offset)
17 {
18 	if (slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
19 		return TEE_ERROR_BAD_PARAMETERS;
20 
21 	*offset = sizeof(uint32_t) /* lock_state */ + slot * sizeof(uint64_t);
22 	return TEE_SUCCESS;
23 }
24 
create_rb_state(uint32_t lock_state,TEE_ObjectHandle * h)25 static TEE_Result create_rb_state(uint32_t lock_state, TEE_ObjectHandle *h)
26 {
27 	const uint32_t flags = TEE_DATA_FLAG_ACCESS_READ |
28 			       TEE_DATA_FLAG_ACCESS_WRITE |
29 			       TEE_DATA_FLAG_OVERWRITE;
30 
31 	return TEE_CreatePersistentObject(storageid, rb_obj_name,
32 					  sizeof(rb_obj_name), flags, NULL,
33 					  &lock_state, sizeof(lock_state), h);
34 }
35 
open_rb_state(uint32_t default_lock_state,TEE_ObjectHandle * h)36 static TEE_Result open_rb_state(uint32_t default_lock_state,
37 				TEE_ObjectHandle *h)
38 {
39 	uint32_t flags = TEE_DATA_FLAG_ACCESS_READ |
40 			 TEE_DATA_FLAG_ACCESS_WRITE;
41 	TEE_Result res;
42 
43 	res = TEE_OpenPersistentObject(storageid, rb_obj_name,
44 				       sizeof(rb_obj_name), flags, h);
45 	if (!res)
46 		return TEE_SUCCESS;
47 
48 	return create_rb_state(default_lock_state, h);
49 }
50 
get_named_object_name(char * name_orig,uint32_t name_orig_size,char * name,uint32_t * name_size)51 static TEE_Result get_named_object_name(char *name_orig,
52 					uint32_t name_orig_size,
53 					char *name, uint32_t *name_size)
54 {
55 	size_t pref_len = strlen(named_value_prefix);
56 
57 	if (name_orig_size + pref_len >
58 	    TEE_OBJECT_ID_MAX_LEN)
59 		return TEE_ERROR_BAD_PARAMETERS;
60 
61 	/* Start with prefix */
62 	TEE_MemMove(name, named_value_prefix, pref_len);
63 
64 	/* Concatenate provided object name */
65 	TEE_MemMove(name + pref_len, name_orig, name_orig_size);
66 
67 	*name_size = name_orig_size + pref_len;
68 
69 	return TEE_SUCCESS;
70 }
71 
read_rb_idx(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])72 static TEE_Result read_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
73 {
74 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
75 						TEE_PARAM_TYPE_VALUE_OUTPUT,
76 						TEE_PARAM_TYPE_NONE,
77 						TEE_PARAM_TYPE_NONE);
78 	size_t slot_offset;
79 	uint64_t idx;
80 	size_t count;
81 	TEE_Result res;
82 	TEE_ObjectHandle h;
83 
84 	if (pt != exp_pt)
85 		return TEE_ERROR_BAD_PARAMETERS;
86 
87 	res = get_slot_offset(params[0].value.a, &slot_offset);
88 	if (res)
89 		return res;
90 
91 	res = open_rb_state(DEFAULT_LOCK_STATE, &h);
92 	if (res)
93 		return res;
94 
95 	res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET);
96 	if (res)
97 		goto out;
98 
99 	res =  TEE_ReadObjectData(h, &idx, sizeof(idx), &count);
100 	if (res)
101 		goto out;
102 	if (count != sizeof(idx)) {
103 		idx = 0; /* Not yet written slots are reported as 0 */
104 
105 		if (count) {
106 			/*
107 			 * Somehow the file didn't even hold a complete
108 			 * slot index entry.  Write it as 0.
109 			 */
110 			res = TEE_SeekObjectData(h, slot_offset,
111 						 TEE_DATA_SEEK_SET);
112 			if (res)
113 				goto out;
114 			res = TEE_WriteObjectData(h, &idx, sizeof(idx));
115 			if (res)
116 				goto out;
117 		}
118 	}
119 
120 	params[1].value.a = idx >> 32;
121 	params[1].value.b = idx;
122 out:
123 	TEE_CloseObject(h);
124 	return res;
125 }
126 
write_rb_idx(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])127 static TEE_Result write_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
128 {
129 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
130 						TEE_PARAM_TYPE_VALUE_INPUT,
131 						TEE_PARAM_TYPE_NONE,
132 						TEE_PARAM_TYPE_NONE);
133 	size_t slot_offset;
134 	uint64_t widx;
135 	uint64_t idx;
136 	size_t count;
137 	TEE_Result res;
138 	TEE_ObjectHandle h;
139 
140 	if (pt != exp_pt)
141 		return TEE_ERROR_BAD_PARAMETERS;
142 
143 	res = get_slot_offset(params[0].value.a, &slot_offset);
144 	if (res)
145 		return res;
146 	widx = ((uint64_t)params[1].value.a << 32) | params[1].value.b;
147 
148 	res = open_rb_state(DEFAULT_LOCK_STATE, &h);
149 	if (res)
150 		return res;
151 
152 	res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET);
153 	if (res)
154 		goto out;
155 
156 	res =  TEE_ReadObjectData(h, &idx, sizeof(idx), &count);
157 	if (res)
158 		goto out;
159 	if (count != sizeof(idx))
160 		idx = 0; /* Not yet written slots are reported as 0 */
161 
162 	if (widx < idx) {
163 		res = TEE_ERROR_SECURITY;
164 		goto out;
165 	}
166 
167 	res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET);
168 	if (res)
169 		goto out;
170 
171 	res = TEE_WriteObjectData(h, &widx, sizeof(widx));
172 out:
173 	TEE_CloseObject(h);
174 	return res;
175 }
176 
read_lock_state(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])177 static TEE_Result read_lock_state(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
178 {
179 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
180 						TEE_PARAM_TYPE_NONE,
181 						TEE_PARAM_TYPE_NONE,
182 						TEE_PARAM_TYPE_NONE);
183 	uint32_t lock_state;
184 	size_t count;
185 	TEE_Result res;
186 	TEE_ObjectHandle h;
187 
188 	if (pt != exp_pt)
189 		return TEE_ERROR_BAD_PARAMETERS;
190 
191 	res = open_rb_state(DEFAULT_LOCK_STATE, &h);
192 	if (res)
193 		return res;
194 
195 	res =  TEE_ReadObjectData(h, &lock_state, sizeof(lock_state), &count);
196 	if (res)
197 		goto out;
198 	if (count != sizeof(lock_state)) {
199 		/*
200 		 * Client need write the lock state to recover, this can
201 		 * normally not happen.
202 		 */
203 		res = TEE_ERROR_CORRUPT_OBJECT;
204 		goto out;
205 	}
206 
207 	params[0].value.a = lock_state;
208 out:
209 	TEE_CloseObject(h);
210 	return res;
211 }
212 
write_lock_state(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])213 static TEE_Result write_lock_state(uint32_t pt,
214 				   TEE_Param params[TEE_NUM_PARAMS])
215 {
216 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
217 						TEE_PARAM_TYPE_NONE,
218 						TEE_PARAM_TYPE_NONE,
219 						TEE_PARAM_TYPE_NONE);
220 	uint32_t wlock_state;
221 	uint32_t lock_state;
222 	size_t count;
223 	TEE_Result res;
224 	TEE_ObjectHandle h;
225 
226 	if (pt != exp_pt)
227 		return TEE_ERROR_BAD_PARAMETERS;
228 
229 	wlock_state = params[0].value.a;
230 
231 	res = open_rb_state(wlock_state, &h);
232 	if (res)
233 		return res;
234 
235 	res =  TEE_ReadObjectData(h, &lock_state, sizeof(lock_state), &count);
236 	if (res)
237 		goto out;
238 	if (count == sizeof(lock_state) && lock_state == wlock_state)
239 		goto out;
240 
241 	res = TEE_SeekObjectData(h, 0, TEE_DATA_SEEK_SET);
242 	if (res)
243 		goto out;
244 
245 	res = TEE_WriteObjectData(h, &wlock_state, sizeof(wlock_state));
246 out:
247 	TEE_CloseObject(h);
248 	return res;
249 }
250 
write_persist_value(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])251 static TEE_Result write_persist_value(uint32_t pt,
252 				      TEE_Param params[TEE_NUM_PARAMS])
253 {
254 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
255 						TEE_PARAM_TYPE_MEMREF_INPUT,
256 						TEE_PARAM_TYPE_NONE,
257 						TEE_PARAM_TYPE_NONE);
258 	const uint32_t flags = TEE_DATA_FLAG_ACCESS_READ |
259 			       TEE_DATA_FLAG_ACCESS_WRITE |
260 			       TEE_DATA_FLAG_OVERWRITE;
261 	char name_full[TEE_OBJECT_ID_MAX_LEN] = { };
262 	TEE_ObjectHandle h = TEE_HANDLE_NULL;
263 	TEE_Result res = TEE_SUCCESS;
264 	uint32_t name_full_sz = 0;
265 	uint32_t name_buf_sz = 0;
266 	uint32_t value_sz = 0;
267 	char *name_buf = NULL;
268 	char *value = NULL;
269 
270 	if (pt != exp_pt)
271 		return TEE_ERROR_BAD_PARAMETERS;
272 
273 	name_buf = params[0].memref.buffer;
274 	name_buf_sz = params[0].memref.size;
275 	value_sz = params[1].memref.size;
276 	value = TEE_Malloc(value_sz, 0);
277 	if (!value)
278 		return TEE_ERROR_OUT_OF_MEMORY;
279 
280 	TEE_MemMove(value, params[1].memref.buffer, value_sz);
281 
282 	res = get_named_object_name(name_buf, name_buf_sz,
283 				    name_full, &name_full_sz);
284 	if (res)
285 		goto out;
286 
287 	res = TEE_CreatePersistentObject(storageid, name_full,
288 					 name_full_sz,
289 					 flags, NULL, value,
290 					 value_sz, &h);
291 	if (res)
292 		EMSG("Can't create named object value, res = 0x%x", res);
293 
294 	TEE_CloseObject(h);
295 out:
296 	TEE_Free(value);
297 
298 	return res;
299 }
300 
read_persist_value(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])301 static TEE_Result read_persist_value(uint32_t pt,
302 				      TEE_Param params[TEE_NUM_PARAMS])
303 {
304 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
305 						TEE_PARAM_TYPE_MEMREF_INOUT,
306 						TEE_PARAM_TYPE_NONE,
307 						TEE_PARAM_TYPE_NONE);
308 	uint32_t flags = TEE_DATA_FLAG_ACCESS_READ |
309 			 TEE_DATA_FLAG_ACCESS_WRITE;
310 	TEE_Result res = TEE_SUCCESS;
311 	TEE_ObjectHandle h = TEE_HANDLE_NULL;
312 	char name_full[TEE_OBJECT_ID_MAX_LEN];
313 	uint32_t name_full_sz = 0;
314 	uint32_t name_buf_sz = 0;
315 	char *name_buf = NULL;
316 	uint32_t value_sz = 0;
317 	char *value = NULL;
318 	size_t count = 0;
319 
320 	if (pt != exp_pt)
321 		return TEE_ERROR_BAD_PARAMETERS;
322 
323 	name_buf = params[0].memref.buffer;
324 	name_buf_sz = params[0].memref.size;
325 	value_sz = params[1].memref.size;
326 	value = TEE_Malloc(value_sz, 0);
327 	if (!value)
328 		return TEE_ERROR_OUT_OF_MEMORY;
329 
330 	res = get_named_object_name(name_buf, name_buf_sz,
331 				    name_full, &name_full_sz);
332 	if (res)
333 		goto out_free;
334 
335 	res = TEE_OpenPersistentObject(storageid, name_full,
336 				       name_full_sz, flags, &h);
337 	if (res) {
338 		EMSG("Can't open named object value, res = 0x%x", res);
339 		goto out_free;
340 	}
341 
342 	res =  TEE_ReadObjectData(h, value, value_sz, &count);
343 	if (res) {
344 		EMSG("Can't read named object value, res = 0x%x", res);
345 		goto out;
346 	}
347 
348 	TEE_MemMove(params[1].memref.buffer, value,
349 		    value_sz);
350 
351 	params[1].memref.size = count;
352 out:
353 	TEE_CloseObject(h);
354 out_free:
355 	TEE_Free(value);
356 
357 	return res;
358 }
359 
TA_CreateEntryPoint(void)360 TEE_Result TA_CreateEntryPoint(void)
361 {
362 	return TEE_SUCCESS;
363 }
364 
TA_DestroyEntryPoint(void)365 void TA_DestroyEntryPoint(void)
366 {
367 }
368 
TA_OpenSessionEntryPoint(uint32_t pt __unused,TEE_Param params[4]__unused,void ** session __unused)369 TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused,
370 				    TEE_Param params[4] __unused,
371 				    void **session __unused)
372 {
373 	return TEE_SUCCESS;
374 }
375 
TA_CloseSessionEntryPoint(void * sess __unused)376 void TA_CloseSessionEntryPoint(void *sess __unused)
377 {
378 }
379 
TA_InvokeCommandEntryPoint(void * sess __unused,uint32_t cmd,uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])380 TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd,
381 				      uint32_t pt,
382 				      TEE_Param params[TEE_NUM_PARAMS])
383 {
384 	switch (cmd) {
385 	case TA_AVB_CMD_READ_ROLLBACK_INDEX:
386 		return read_rb_idx(pt, params);
387 	case TA_AVB_CMD_WRITE_ROLLBACK_INDEX:
388 		return write_rb_idx(pt, params);
389 	case TA_AVB_CMD_READ_LOCK_STATE:
390 		return read_lock_state(pt, params);
391 	case TA_AVB_CMD_WRITE_LOCK_STATE:
392 		return write_lock_state(pt, params);
393 	case TA_AVB_CMD_READ_PERSIST_VALUE:
394 		return read_persist_value(pt, params);
395 	case TA_AVB_CMD_WRITE_PERSIST_VALUE:
396 		return write_persist_value(pt, params);
397 	default:
398 		EMSG("Command ID 0x%x is not supported", cmd);
399 		return TEE_ERROR_NOT_SUPPORTED;
400 	}
401 }
402