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