xref: /optee_os/ta/avb/entry.c (revision 5a913ee74d3c71af2a2860ce8a4e7aeab2916f9b)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 	TEE_Result res;
259 	TEE_ObjectHandle h;
260 
261 	char name_full[TEE_OBJECT_ID_MAX_LEN];
262 	uint32_t name_full_sz;
263 
264 	if (pt != exp_pt)
265 		return TEE_ERROR_BAD_PARAMETERS;
266 
267 	char *name_buf = params[0].memref.buffer;
268 	uint32_t name_buf_sz = params[0].memref.size;
269 
270 	char *value = params[1].memref.buffer;
271 	uint32_t value_sz = params[1].memref.size;
272 
273 	res = get_named_object_name(name_buf, name_buf_sz,
274 				    name_full, &name_full_sz);
275 	if (res)
276 		return res;
277 
278 	res = TEE_CreatePersistentObject(storageid, name_full,
279 					 name_full_sz,
280 					 flags, NULL, value,
281 					 value_sz, &h);
282 	if (res)
283 		EMSG("Can't create named object value, res = 0x%x", res);
284 
285 	TEE_CloseObject(h);
286 
287 	return res;
288 }
289 
290 static TEE_Result read_persist_value(uint32_t pt,
291 				      TEE_Param params[TEE_NUM_PARAMS])
292 {
293 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
294 						TEE_PARAM_TYPE_MEMREF_INOUT,
295 						TEE_PARAM_TYPE_NONE,
296 						TEE_PARAM_TYPE_NONE);
297 	uint32_t flags = TEE_DATA_FLAG_ACCESS_READ |
298 			 TEE_DATA_FLAG_ACCESS_WRITE;
299 	TEE_Result res;
300 	TEE_ObjectHandle h;
301 
302 	char name_full[TEE_OBJECT_ID_MAX_LEN];
303 	uint32_t name_full_sz;
304 	uint32_t count;
305 
306 	if (pt != exp_pt)
307 		return TEE_ERROR_BAD_PARAMETERS;
308 
309 	char *name_buf = params[0].memref.buffer;
310 	uint32_t name_buf_sz = params[0].memref.size;
311 
312 	char *value = params[1].memref.buffer;
313 	uint32_t value_sz = params[1].memref.size;
314 
315 	res = get_named_object_name(name_buf, name_buf_sz,
316 				    name_full, &name_full_sz);
317 	if (res)
318 		return res;
319 
320 	res = TEE_OpenPersistentObject(storageid, name_full,
321 				       name_full_sz, flags, &h);
322 	if (res) {
323 		EMSG("Can't open named object value, res = 0x%x", res);
324 		return res;
325 	}
326 
327 	res =  TEE_ReadObjectData(h, value, value_sz, &count);
328 	if (res) {
329 		EMSG("Can't read named object value, res = 0x%x", res);
330 		goto out;
331 	}
332 
333 	params[1].memref.size = count;
334 out:
335 	TEE_CloseObject(h);
336 
337 	return res;
338 }
339 
340 TEE_Result TA_CreateEntryPoint(void)
341 {
342 	return TEE_SUCCESS;
343 }
344 
345 void TA_DestroyEntryPoint(void)
346 {
347 }
348 
349 TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused,
350 				    TEE_Param params[4] __unused,
351 				    void **session __unused)
352 {
353 	return TEE_SUCCESS;
354 }
355 
356 void TA_CloseSessionEntryPoint(void *sess __unused)
357 {
358 }
359 
360 TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd,
361 				      uint32_t pt,
362 				      TEE_Param params[TEE_NUM_PARAMS])
363 {
364 	switch (cmd) {
365 	case TA_AVB_CMD_READ_ROLLBACK_INDEX:
366 		return read_rb_idx(pt, params);
367 	case TA_AVB_CMD_WRITE_ROLLBACK_INDEX:
368 		return write_rb_idx(pt, params);
369 	case TA_AVB_CMD_READ_LOCK_STATE:
370 		return read_lock_state(pt, params);
371 	case TA_AVB_CMD_WRITE_LOCK_STATE:
372 		return write_lock_state(pt, params);
373 	case TA_AVB_CMD_READ_PERSIST_VALUE:
374 		return read_persist_value(pt, params);
375 	case TA_AVB_CMD_WRITE_PERSIST_VALUE:
376 		return write_persist_value(pt, params);
377 	default:
378 		EMSG("Command ID 0x%x is not supported", cmd);
379 		return TEE_ERROR_NOT_SUPPORTED;
380 	}
381 }
382