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