xref: /optee_os/ta/avb/entry.c (revision b29b419506fae13a625818e4ee4868b7d487bb44)
1*b29b4195SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*b29b4195SJens Wiklander /* Copyright (c) 2018, Linaro Limited */
3*b29b4195SJens Wiklander 
4*b29b4195SJens Wiklander #include <ta_avb.h>
5*b29b4195SJens Wiklander #include <tee_internal_api.h>
6*b29b4195SJens Wiklander #include <tee_internal_api_extensions.h>
7*b29b4195SJens Wiklander 
8*b29b4195SJens Wiklander #define DEFAULT_LOCK_STATE	0
9*b29b4195SJens Wiklander 
10*b29b4195SJens Wiklander static const uint32_t storageid = TEE_STORAGE_PRIVATE_RPMB;
11*b29b4195SJens Wiklander static const char obj_name[] = "rb_state";
12*b29b4195SJens Wiklander 
13*b29b4195SJens Wiklander static TEE_Result get_slot_offset(size_t slot, size_t *offset)
14*b29b4195SJens Wiklander {
15*b29b4195SJens Wiklander 	if (slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
16*b29b4195SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
17*b29b4195SJens Wiklander 
18*b29b4195SJens Wiklander 	*offset = sizeof(uint32_t) /* lock_state */ + slot * sizeof(uint64_t);
19*b29b4195SJens Wiklander 	return TEE_SUCCESS;
20*b29b4195SJens Wiklander }
21*b29b4195SJens Wiklander 
22*b29b4195SJens Wiklander static TEE_Result create_state(uint32_t lock_state, TEE_ObjectHandle *h)
23*b29b4195SJens Wiklander {
24*b29b4195SJens Wiklander 	const uint32_t flags = TEE_DATA_FLAG_ACCESS_READ |
25*b29b4195SJens Wiklander 			       TEE_DATA_FLAG_ACCESS_WRITE |
26*b29b4195SJens Wiklander 			       TEE_DATA_FLAG_OVERWRITE;
27*b29b4195SJens Wiklander 
28*b29b4195SJens Wiklander 	return TEE_CreatePersistentObject(storageid, obj_name, sizeof(obj_name),
29*b29b4195SJens Wiklander 					  flags, NULL, &lock_state,
30*b29b4195SJens Wiklander 					  sizeof(lock_state), h);
31*b29b4195SJens Wiklander }
32*b29b4195SJens Wiklander 
33*b29b4195SJens Wiklander static TEE_Result open_state(uint32_t default_lock_state, TEE_ObjectHandle *h)
34*b29b4195SJens Wiklander {
35*b29b4195SJens Wiklander 	uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE;
36*b29b4195SJens Wiklander 	TEE_Result res;
37*b29b4195SJens Wiklander 
38*b29b4195SJens Wiklander 	res = TEE_OpenPersistentObject(storageid, obj_name,
39*b29b4195SJens Wiklander 				       sizeof(obj_name), flags, h);
40*b29b4195SJens Wiklander 	if (!res)
41*b29b4195SJens Wiklander 		return TEE_SUCCESS;
42*b29b4195SJens Wiklander 
43*b29b4195SJens Wiklander 	return create_state(default_lock_state, h);
44*b29b4195SJens Wiklander }
45*b29b4195SJens Wiklander 
46*b29b4195SJens Wiklander static TEE_Result read_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
47*b29b4195SJens Wiklander {
48*b29b4195SJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
49*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_VALUE_OUTPUT,
50*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_NONE,
51*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_NONE);
52*b29b4195SJens Wiklander 	size_t slot_offset;
53*b29b4195SJens Wiklander 	uint64_t idx;
54*b29b4195SJens Wiklander 	uint32_t count;
55*b29b4195SJens Wiklander 	TEE_Result res;
56*b29b4195SJens Wiklander 	TEE_ObjectHandle h;
57*b29b4195SJens Wiklander 
58*b29b4195SJens Wiklander 	if (pt != exp_pt)
59*b29b4195SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
60*b29b4195SJens Wiklander 
61*b29b4195SJens Wiklander 	res = get_slot_offset(params[0].value.a, &slot_offset);
62*b29b4195SJens Wiklander 	if (res)
63*b29b4195SJens Wiklander 		return res;
64*b29b4195SJens Wiklander 
65*b29b4195SJens Wiklander 	res = open_state(DEFAULT_LOCK_STATE, &h);
66*b29b4195SJens Wiklander 	if (res)
67*b29b4195SJens Wiklander 		return res;
68*b29b4195SJens Wiklander 
69*b29b4195SJens Wiklander 	res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET);
70*b29b4195SJens Wiklander 	if (res)
71*b29b4195SJens Wiklander 		goto out;
72*b29b4195SJens Wiklander 
73*b29b4195SJens Wiklander 	res =  TEE_ReadObjectData(h, &idx, sizeof(idx), &count);
74*b29b4195SJens Wiklander 	if (res)
75*b29b4195SJens Wiklander 		goto out;
76*b29b4195SJens Wiklander 	if (count != sizeof(idx)) {
77*b29b4195SJens Wiklander 		idx = 0; /* Not yet written slots are reported as 0 */
78*b29b4195SJens Wiklander 
79*b29b4195SJens Wiklander 		if (count) {
80*b29b4195SJens Wiklander 			/*
81*b29b4195SJens Wiklander 			 * Somehow the file didn't even hold a complete
82*b29b4195SJens Wiklander 			 * slot index entry.  Write it as 0.
83*b29b4195SJens Wiklander 			 */
84*b29b4195SJens Wiklander 			res = TEE_SeekObjectData(h, slot_offset,
85*b29b4195SJens Wiklander 						 TEE_DATA_SEEK_SET);
86*b29b4195SJens Wiklander 			if (res)
87*b29b4195SJens Wiklander 				goto out;
88*b29b4195SJens Wiklander 			res = TEE_WriteObjectData(h, &idx, sizeof(idx));
89*b29b4195SJens Wiklander 			if (res)
90*b29b4195SJens Wiklander 				goto out;
91*b29b4195SJens Wiklander 		}
92*b29b4195SJens Wiklander 	}
93*b29b4195SJens Wiklander 
94*b29b4195SJens Wiklander 	params[1].value.a = idx >> 32;
95*b29b4195SJens Wiklander 	params[1].value.b = idx;
96*b29b4195SJens Wiklander out:
97*b29b4195SJens Wiklander 	TEE_CloseObject(h);
98*b29b4195SJens Wiklander 	return res;
99*b29b4195SJens Wiklander }
100*b29b4195SJens Wiklander 
101*b29b4195SJens Wiklander static TEE_Result write_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
102*b29b4195SJens Wiklander {
103*b29b4195SJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
104*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_VALUE_INPUT,
105*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_NONE,
106*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_NONE);
107*b29b4195SJens Wiklander 	size_t slot_offset;
108*b29b4195SJens Wiklander 	uint64_t widx;
109*b29b4195SJens Wiklander 	uint64_t idx;
110*b29b4195SJens Wiklander 	uint32_t count;
111*b29b4195SJens Wiklander 	TEE_Result res;
112*b29b4195SJens Wiklander 	TEE_ObjectHandle h;
113*b29b4195SJens Wiklander 
114*b29b4195SJens Wiklander 	if (pt != exp_pt)
115*b29b4195SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
116*b29b4195SJens Wiklander 
117*b29b4195SJens Wiklander 	res = get_slot_offset(params[0].value.a, &slot_offset);
118*b29b4195SJens Wiklander 	if (res)
119*b29b4195SJens Wiklander 		return res;
120*b29b4195SJens Wiklander 	widx = ((uint64_t)params[1].value.a << 32) | params[1].value.b;
121*b29b4195SJens Wiklander 
122*b29b4195SJens Wiklander 	res = open_state(DEFAULT_LOCK_STATE, &h);
123*b29b4195SJens Wiklander 	if (res)
124*b29b4195SJens Wiklander 		return res;
125*b29b4195SJens Wiklander 
126*b29b4195SJens Wiklander 	res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET);
127*b29b4195SJens Wiklander 	if (res)
128*b29b4195SJens Wiklander 		goto out;
129*b29b4195SJens Wiklander 
130*b29b4195SJens Wiklander 	res =  TEE_ReadObjectData(h, &idx, sizeof(idx), &count);
131*b29b4195SJens Wiklander 	if (res)
132*b29b4195SJens Wiklander 		goto out;
133*b29b4195SJens Wiklander 	if (count != sizeof(idx))
134*b29b4195SJens Wiklander 		idx = 0; /* Not yet written slots are reported as 0 */
135*b29b4195SJens Wiklander 
136*b29b4195SJens Wiklander 	if (widx < idx) {
137*b29b4195SJens Wiklander 		res = TEE_ERROR_SECURITY;
138*b29b4195SJens Wiklander 		goto out;
139*b29b4195SJens Wiklander 	}
140*b29b4195SJens Wiklander 
141*b29b4195SJens Wiklander 	res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET);
142*b29b4195SJens Wiklander 	if (res)
143*b29b4195SJens Wiklander 		goto out;
144*b29b4195SJens Wiklander 
145*b29b4195SJens Wiklander 	res = TEE_WriteObjectData(h, &widx, sizeof(widx));
146*b29b4195SJens Wiklander out:
147*b29b4195SJens Wiklander 	TEE_CloseObject(h);
148*b29b4195SJens Wiklander 	return res;
149*b29b4195SJens Wiklander }
150*b29b4195SJens Wiklander 
151*b29b4195SJens Wiklander static TEE_Result read_lock_state(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
152*b29b4195SJens Wiklander {
153*b29b4195SJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
154*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_NONE,
155*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_NONE,
156*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_NONE);
157*b29b4195SJens Wiklander 	uint32_t lock_state;
158*b29b4195SJens Wiklander 	uint32_t count;
159*b29b4195SJens Wiklander 	TEE_Result res;
160*b29b4195SJens Wiklander 	TEE_ObjectHandle h;
161*b29b4195SJens Wiklander 
162*b29b4195SJens Wiklander 	if (pt != exp_pt)
163*b29b4195SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
164*b29b4195SJens Wiklander 
165*b29b4195SJens Wiklander 	res = open_state(DEFAULT_LOCK_STATE, &h);
166*b29b4195SJens Wiklander 	if (res)
167*b29b4195SJens Wiklander 		return res;
168*b29b4195SJens Wiklander 
169*b29b4195SJens Wiklander 	res =  TEE_ReadObjectData(h, &lock_state, sizeof(lock_state), &count);
170*b29b4195SJens Wiklander 	if (res)
171*b29b4195SJens Wiklander 		goto out;
172*b29b4195SJens Wiklander 	if (count != sizeof(lock_state)) {
173*b29b4195SJens Wiklander 		/*
174*b29b4195SJens Wiklander 		 * Client need write the lock state to recover, this can
175*b29b4195SJens Wiklander 		 * normally not happen.
176*b29b4195SJens Wiklander 		 */
177*b29b4195SJens Wiklander 		res = TEE_ERROR_CORRUPT_OBJECT;
178*b29b4195SJens Wiklander 		goto out;
179*b29b4195SJens Wiklander 	}
180*b29b4195SJens Wiklander 
181*b29b4195SJens Wiklander 	params[0].value.a = lock_state;
182*b29b4195SJens Wiklander out:
183*b29b4195SJens Wiklander 	TEE_CloseObject(h);
184*b29b4195SJens Wiklander 	return res;
185*b29b4195SJens Wiklander }
186*b29b4195SJens Wiklander 
187*b29b4195SJens Wiklander static TEE_Result write_lock_state(uint32_t pt,
188*b29b4195SJens Wiklander 				   TEE_Param params[TEE_NUM_PARAMS])
189*b29b4195SJens Wiklander {
190*b29b4195SJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
191*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_NONE,
192*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_NONE,
193*b29b4195SJens Wiklander 						TEE_PARAM_TYPE_NONE);
194*b29b4195SJens Wiklander 	uint32_t wlock_state;
195*b29b4195SJens Wiklander 	uint32_t lock_state;
196*b29b4195SJens Wiklander 	uint32_t count;
197*b29b4195SJens Wiklander 	TEE_Result res;
198*b29b4195SJens Wiklander 	TEE_ObjectHandle h;
199*b29b4195SJens Wiklander 
200*b29b4195SJens Wiklander 	if (pt != exp_pt)
201*b29b4195SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
202*b29b4195SJens Wiklander 
203*b29b4195SJens Wiklander 	wlock_state = params[0].value.a;
204*b29b4195SJens Wiklander 
205*b29b4195SJens Wiklander 	res = open_state(wlock_state, &h);
206*b29b4195SJens Wiklander 	if (res)
207*b29b4195SJens Wiklander 		return res;
208*b29b4195SJens Wiklander 
209*b29b4195SJens Wiklander 	res =  TEE_ReadObjectData(h, &lock_state, sizeof(lock_state), &count);
210*b29b4195SJens Wiklander 	if (res)
211*b29b4195SJens Wiklander 		goto out;
212*b29b4195SJens Wiklander 	if (count == sizeof(lock_state) && lock_state == wlock_state)
213*b29b4195SJens Wiklander 		goto out;
214*b29b4195SJens Wiklander 
215*b29b4195SJens Wiklander 	res = create_state(wlock_state, &h);
216*b29b4195SJens Wiklander out:
217*b29b4195SJens Wiklander 	TEE_CloseObject(h);
218*b29b4195SJens Wiklander 	return res;
219*b29b4195SJens Wiklander }
220*b29b4195SJens Wiklander 
221*b29b4195SJens Wiklander TEE_Result TA_CreateEntryPoint(void)
222*b29b4195SJens Wiklander {
223*b29b4195SJens Wiklander 	return TEE_SUCCESS;
224*b29b4195SJens Wiklander }
225*b29b4195SJens Wiklander 
226*b29b4195SJens Wiklander void TA_DestroyEntryPoint(void)
227*b29b4195SJens Wiklander {
228*b29b4195SJens Wiklander }
229*b29b4195SJens Wiklander 
230*b29b4195SJens Wiklander TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused,
231*b29b4195SJens Wiklander 				    TEE_Param params[4] __unused,
232*b29b4195SJens Wiklander 				    void **session __unused)
233*b29b4195SJens Wiklander {
234*b29b4195SJens Wiklander 	return TEE_SUCCESS;
235*b29b4195SJens Wiklander }
236*b29b4195SJens Wiklander 
237*b29b4195SJens Wiklander void TA_CloseSessionEntryPoint(void *sess __unused)
238*b29b4195SJens Wiklander {
239*b29b4195SJens Wiklander }
240*b29b4195SJens Wiklander 
241*b29b4195SJens Wiklander TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd,
242*b29b4195SJens Wiklander 				      uint32_t pt,
243*b29b4195SJens Wiklander 				      TEE_Param params[TEE_NUM_PARAMS])
244*b29b4195SJens Wiklander {
245*b29b4195SJens Wiklander 	switch (cmd) {
246*b29b4195SJens Wiklander 	case TA_AVB_CMD_READ_ROLLBACK_INDEX:
247*b29b4195SJens Wiklander 		return read_rb_idx(pt, params);
248*b29b4195SJens Wiklander 	case TA_AVB_CMD_WRITE_ROLLBACK_INDEX:
249*b29b4195SJens Wiklander 		return write_rb_idx(pt, params);
250*b29b4195SJens Wiklander 	case TA_AVB_CMD_READ_LOCK_STATE:
251*b29b4195SJens Wiklander 		return read_lock_state(pt, params);
252*b29b4195SJens Wiklander 	case TA_AVB_CMD_WRITE_LOCK_STATE:
253*b29b4195SJens Wiklander 		return write_lock_state(pt, params);
254*b29b4195SJens Wiklander 	default:
255*b29b4195SJens Wiklander 		EMSG("Command ID 0x%x is not supported", cmd);
256*b29b4195SJens Wiklander 		return TEE_ERROR_NOT_SUPPORTED;
257*b29b4195SJens Wiklander 	}
258*b29b4195SJens Wiklander }
259