1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
4  */
5 
6 #include <config.h>
7 #include <drivers/stm32_bsec.h>
8 #include <kernel/pseudo_ta.h>
9 #include <kernel/user_access.h>
10 #include <kernel/user_mode_ctx.h>
11 #include <kernel/user_ta.h>
12 #include <mm/vm.h>
13 #include <pta_stm32mp_bsec.h>
14 #include <string.h>
15 #include <util.h>
16 
17 static_assert(IS_ENABLED(CFG_STM32_BSEC));
18 
19 #define PTA_NAME "bsec.pta"
20 
bsec_check_access(uint32_t otp_id)21 static TEE_Result bsec_check_access(uint32_t otp_id)
22 {
23 	if (!stm32_bsec_nsec_can_access_otp(otp_id))
24 		return TEE_ERROR_ACCESS_DENIED;
25 
26 	return TEE_SUCCESS;
27 }
28 
bsec_read_mem(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])29 static TEE_Result bsec_read_mem(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
30 {
31 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
32 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
33 						TEE_PARAM_TYPE_NONE,
34 						TEE_PARAM_TYPE_NONE);
35 	uint32_t *buf = (uint32_t *)params[1].memref.buffer;
36 	uint32_t otp_start = 0;
37 	size_t otp_length = 0;
38 	uint32_t otp_id = 0;
39 	TEE_Result res = TEE_ERROR_GENERIC;
40 	size_t size = params[1].memref.size;
41 	bool locked = false;
42 	unsigned int otp_base_offset = params[0].value.a;
43 	unsigned int bsec_command = params[0].value.b;
44 
45 	if (pt != exp_pt || !buf || !size ||
46 	    !IS_ALIGNED_WITH_TYPE(params[1].memref.buffer, uint32_t))
47 		return TEE_ERROR_BAD_PARAMETERS;
48 
49 	/* Check 32bits alignment */
50 	if (otp_base_offset % BSEC_BYTES_PER_WORD ||
51 	    size % BSEC_BYTES_PER_WORD)
52 		return TEE_ERROR_BAD_PARAMETERS;
53 
54 	otp_start = otp_base_offset / BSEC_BYTES_PER_WORD;
55 	otp_length = size / BSEC_BYTES_PER_WORD;
56 
57 	for (otp_id = otp_start; otp_id < otp_start + otp_length;
58 	     otp_id++, buf++) {
59 		res = bsec_check_access(otp_id);
60 		switch (bsec_command) {
61 		case PTA_BSEC_SHADOW_ACCESS:
62 			if (res) {
63 				/* Force 0 when access is not allowed */
64 				*buf = 0x0;
65 				continue;
66 			}
67 			/* Read shadow register */
68 			res = stm32_bsec_read_otp(buf, otp_id);
69 			FMSG("Read shadow %"PRIu32" val: %#"PRIx32, otp_id,
70 			     *buf);
71 			break;
72 		case PTA_BSEC_FUSE_ACCESS:
73 			/* Check access */
74 			if (res)
75 				goto out;
76 			/* Read fuse value */
77 			res = stm32_bsec_shadow_read_otp(buf, otp_id);
78 			FMSG("Read fuse %"PRIu32" val: %#"PRIx32, otp_id, *buf);
79 			break;
80 		case PTA_BSEC_LOCKS_ACCESS:
81 			if (res) {
82 				/* Force error when access is not allowed */
83 				*buf = PTA_BSEC_LOCK_ERROR;
84 				continue;
85 			}
86 			*buf = 0;
87 			/* Read lock value */
88 			res = stm32_bsec_read_permanent_lock(otp_id, &locked);
89 			if (res)
90 				goto out;
91 
92 			if (locked)
93 				*buf |= PTA_BSEC_LOCK_PERM;
94 
95 			res = stm32_bsec_read_sr_lock(otp_id, &locked);
96 			if (res)
97 				goto out;
98 
99 			if (locked)
100 				*buf |= PTA_BSEC_LOCK_SHADOW_R;
101 
102 			res = stm32_bsec_read_sw_lock(otp_id, &locked);
103 			if (res)
104 				goto out;
105 
106 			if (locked)
107 				*buf |= PTA_BSEC_LOCK_SHADOW_W;
108 
109 			res = stm32_bsec_read_sp_lock(otp_id, &locked);
110 			if (res)
111 				goto out;
112 
113 			if (locked)
114 				*buf |= PTA_BSEC_LOCK_SHADOW_P;
115 
116 			FMSG("Read lock %"PRIu32" val: %#"PRIx32, otp_id, *buf);
117 			break;
118 		default:
119 			FMSG("%"PRIu32" invalid operation: %"PRIu32, otp_id,
120 			     bsec_command);
121 			res = TEE_ERROR_BAD_PARAMETERS;
122 		}
123 
124 		if (res)
125 			goto out;
126 	}
127 
128 	FMSG("Buffer orig %p, size %zu", buf, size);
129 
130 	res = TEE_SUCCESS;
131 out:
132 	return res;
133 }
134 
bsec_write_mem(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])135 static TEE_Result bsec_write_mem(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
136 {
137 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
138 						TEE_PARAM_TYPE_MEMREF_INPUT,
139 						TEE_PARAM_TYPE_NONE,
140 						TEE_PARAM_TYPE_NONE);
141 
142 	uint32_t *buf = (uint32_t *)params[1].memref.buffer;
143 	size_t size = params[1].memref.size;
144 	uint32_t otp_start = 0;
145 	size_t otp_length = 0;
146 	uint32_t otp_id = 0;
147 	TEE_Result res = TEE_ERROR_GENERIC;
148 	unsigned int otp_base_offset = params[0].value.a;
149 	unsigned int bsec_command = params[0].value.b;
150 
151 	if (pt != exp_pt || !buf || !size ||
152 	    !IS_ALIGNED_WITH_TYPE(params[1].memref.buffer, uint32_t))
153 		return TEE_ERROR_BAD_PARAMETERS;
154 
155 	/* Check 32bits alignment */
156 	if (otp_base_offset % BSEC_BYTES_PER_WORD ||
157 	    size % BSEC_BYTES_PER_WORD)
158 		return TEE_ERROR_BAD_PARAMETERS;
159 
160 	otp_start = otp_base_offset / BSEC_BYTES_PER_WORD;
161 	otp_length = size / BSEC_BYTES_PER_WORD;
162 
163 	/* Initial check to ensure that all BSEC words are available */
164 	for (otp_id = otp_start; otp_id < otp_start + otp_length; otp_id++) {
165 		res = bsec_check_access(otp_id);
166 		if (res)
167 			return res;
168 	}
169 
170 	for (otp_id = otp_start; otp_id < otp_start + otp_length;
171 	     otp_id++, buf++) {
172 		switch (bsec_command) {
173 		case PTA_BSEC_SHADOW_ACCESS:
174 			/* Write shadow register */
175 			FMSG("Write shadow %"PRIx32" : %"PRIx32,
176 			     otp_id, *buf);
177 			res = stm32_bsec_write_otp(*buf, otp_id);
178 			break;
179 
180 		case PTA_BSEC_FUSE_ACCESS:
181 			/* Write fuse value */
182 			FMSG("Write fuse %"PRIx32" : %08"PRIx32,
183 			     otp_id, *buf);
184 			res = stm32_bsec_program_otp(*buf, otp_id);
185 			break;
186 
187 		case PTA_BSEC_LOCKS_ACCESS:
188 			if (*buf & PTA_BSEC_LOCK_PERM) {
189 				FMSG("Perm lock access OTP: %u", otp_id);
190 				res = stm32_bsec_permanent_lock_otp(otp_id);
191 				if (res)
192 					break;
193 			}
194 
195 			if (*buf & PTA_BSEC_LOCK_SHADOW_R) {
196 				FMSG("Shadow read lock");
197 				res = stm32_bsec_set_sr_lock(otp_id);
198 				if (res)
199 					break;
200 			}
201 
202 			if (*buf & PTA_BSEC_LOCK_SHADOW_W) {
203 				FMSG("Shadow write lock detected");
204 				res = stm32_bsec_set_sw_lock(otp_id);
205 				if (res)
206 					break;
207 			}
208 
209 			if (*buf & PTA_BSEC_LOCK_SHADOW_P) {
210 				FMSG("Shadow programming lock detected");
211 				res = stm32_bsec_set_sp_lock(otp_id);
212 			}
213 
214 			break;
215 
216 		default:
217 			FMSG("OTP %"PRIx32" invalid operation: %"PRIx32,
218 			     otp_id, bsec_command);
219 			res = TEE_ERROR_BAD_PARAMETERS;
220 		}
221 
222 		if (res)
223 			return res;
224 	}
225 
226 	return TEE_SUCCESS;
227 }
228 
bsec_pta_state(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])229 static TEE_Result bsec_pta_state(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
230 {
231 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
232 						TEE_PARAM_TYPE_NONE,
233 						TEE_PARAM_TYPE_NONE,
234 						TEE_PARAM_TYPE_NONE);
235 	TEE_Result res = TEE_ERROR_GENERIC;
236 	enum stm32_bsec_sec_state state = BSEC_STATE_INVALID;
237 	enum stm32_bsec_pta_sec_state pta_state = PTA_BSEC_STATE_INVALID;
238 
239 	if (pt != exp_pt)
240 		return TEE_ERROR_BAD_PARAMETERS;
241 
242 	res = stm32_bsec_get_state(&state);
243 	if (res)
244 		return res;
245 
246 	switch (state) {
247 	case BSEC_STATE_SEC_CLOSED:
248 		pta_state = PTA_BSEC_STATE_SEC_CLOSE;
249 		break;
250 	case BSEC_STATE_SEC_OPEN:
251 		pta_state = PTA_BSEC_STATE_SEC_OPEN;
252 		break;
253 	default:
254 		pta_state = PTA_BSEC_STATE_INVALID;
255 		break;
256 	}
257 
258 	params[0].value.a = pta_state;
259 
260 	return TEE_SUCCESS;
261 }
262 
bsec_pta_invoke_command(void * pSessionContext __unused,uint32_t cmd_id,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])263 static TEE_Result bsec_pta_invoke_command(void *pSessionContext __unused,
264 					  uint32_t cmd_id,
265 					  uint32_t param_types,
266 					  TEE_Param params[TEE_NUM_PARAMS])
267 {
268 	FMSG(PTA_NAME" command %#"PRIx32" ptypes %#"PRIx32,
269 	     cmd_id, param_types);
270 
271 	switch (cmd_id) {
272 	case PTA_BSEC_CMD_READ_OTP:
273 		return bsec_read_mem(param_types, params);
274 	case PTA_BSEC_CMD_WRITE_OTP:
275 		return bsec_write_mem(param_types, params);
276 	case PTA_BSEC_CMD_GET_STATE:
277 		return bsec_pta_state(param_types, params);
278 	default:
279 		break;
280 	}
281 
282 	return TEE_ERROR_NOT_IMPLEMENTED;
283 }
284 
pta_bsec_open_session(uint32_t ptypes __unused,TEE_Param par[TEE_NUM_PARAMS]__unused,void ** session __unused)285 static TEE_Result pta_bsec_open_session(uint32_t ptypes __unused,
286 					TEE_Param par[TEE_NUM_PARAMS] __unused,
287 					void **session __unused)
288 {
289 	uint32_t login = to_ta_session(ts_get_current_session())->clnt_id.login;
290 
291 	if (login == TEE_LOGIN_REE_KERNEL)
292 		return TEE_SUCCESS;
293 
294 	return TEE_ERROR_ACCESS_DENIED;
295 }
296 
297 pseudo_ta_register(.uuid = PTA_BSEC_UUID, .name = PTA_NAME,
298 		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT |
299 			    TA_FLAG_DEVICE_ENUM,
300 		   .open_session_entry_point = pta_bsec_open_session,
301 		   .invoke_command_entry_point = bsec_pta_invoke_command);
302