1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #include <attestation.h>
7 #include <attestation_token.h>
8 #include <debug.h>
9 #include <granule.h>
10 #include <measurement.h>
11 #include <realm.h>
12 #include <realm_attest.h>
13 #include <smc-rsi.h>
14 #include <smc.h>
15 #include <string.h>
16 #include <utils_def.h>
17 
18 #define MAX_EXTENDED_SIZE		(64U)
19 
20 /*
21  * Return the Realm Personalization Value.
22  *
23  * Arguments:
24  * rd    - The Realm descriptor.
25  * claim - The structure to return the Realm Personalization Value claim
26  */
get_rpv(struct rd * rd,struct q_useful_buf_c * claim)27 static void get_rpv(struct rd *rd, struct q_useful_buf_c *claim)
28 {
29 	claim->ptr = (uint8_t *)&(rd->rpv[0]);
30 	claim->len = RPV_SIZE;
31 }
32 
33 /*
34  * Save the input parameters in the context for later iterations to check for
35  * consistency.
36  */
save_input_parameters(struct rec * rec)37 static void save_input_parameters(struct rec *rec)
38 {
39 	rec->token_sign_ctx.token_ipa = rec->regs[1];
40 	(void)memcpy(rec->token_sign_ctx.challenge, &rec->regs[2],
41 		     ATTEST_CHALLENGE_SIZE);
42 }
43 
44 /*
45  * Verify that in all the iterations the input parameters are the same
46  * as in the initial call.
47  */
verify_input_parameters_consistency(struct rec * rec)48 static bool verify_input_parameters_consistency(struct rec *rec)
49 {
50 	return rec->token_sign_ctx.token_ipa == rec->regs[1];
51 }
52 
53 /*
54  * Function to continue with the sign operation.
55  * It returns void as the result will be updated in the
56  * struct attest_result passed as argument.
57  */
attest_token_continue_sign_state(struct rec * rec,struct attest_result * res)58 static void attest_token_continue_sign_state(struct rec *rec,
59 					     struct attest_result *res)
60 {
61 	/*
62 	 * Sign and finish creating the token.
63 	 */
64 	enum attest_token_err_t ret =
65 		attest_realm_token_sign(&(rec->token_sign_ctx.ctx),
66 					&(rec->rmm_realm_token));
67 
68 	if ((ret == ATTEST_TOKEN_ERR_COSE_SIGN_IN_PROGRESS) ||
69 		(ret == ATTEST_TOKEN_ERR_SUCCESS)) {
70 		/*
71 		 * Return to RSI handler function after each iteration
72 		 * to check is there anything else to do (pending IRQ)
73 		 * or next signing iteration can be executed.
74 		 */
75 		res->incomplete = true;
76 		res->smc_res.x[0] = RSI_INCOMPLETE;
77 
78 		/* If this was the last signing cycle */
79 		if (ret == ATTEST_TOKEN_ERR_SUCCESS) {
80 			rec->token_sign_ctx.state =
81 				ATTEST_SIGN_TOKEN_WRITE_IN_PROGRESS;
82 		}
83 	} else {
84 		/* Accessible only in case of failure during token signing */
85 		ERROR("FATAL_ERROR: Realm token creation failed\n");
86 		panic();
87 	}
88 }
89 
90 /*
91  * Function to continue with the token write operation.
92  * It returns void as the result will be updated in the
93  * struct attest_result passed as argument.
94  */
attest_token_continue_write_state(struct rec * rec,struct attest_result * res)95 static void attest_token_continue_write_state(struct rec *rec,
96 					      struct attest_result *res)
97 {
98 	struct rd *rd = NULL;
99 	struct granule *gr;
100 	uint8_t *realm_att_token;
101 	unsigned long realm_att_token_ipa = rec->regs[1];
102 	enum s2_walk_status walk_status;
103 	struct s2_walk_result walk_res = { 0UL };
104 	struct q_useful_buf     attest_token_buf;
105 	size_t    attest_token_len;
106 
107 	/*
108 	 * The refcount on rd and rec will protect from any changes
109 	 * while REC is running.
110 	 */
111 	rd = granule_map(rec->realm_info.g_rd, SLOT_RD);
112 
113 	/*
114 	 * Translate realm granule IPA to PA. If returns with
115 	 * WALK_SUCCESS then the last level page table (llt),
116 	 * which holds the realm_att_token_buf mapping, is locked.
117 	 */
118 	walk_status = realm_ipa_to_pa(rd, realm_att_token_ipa, &walk_res);
119 	buffer_unmap(rd);
120 
121 	/* Walk parameter validity was checked by RSI_ATTESTATION_TOKEN_INIT */
122 	assert(walk_status != WALK_INVALID_PARAMS);
123 
124 	if (walk_status == WALK_FAIL) {
125 		if (s2_walk_result_match_ripas(&walk_res, RMI_EMPTY)) {
126 			res->smc_res.x[0] = RSI_ERROR_INPUT;
127 		} else {
128 			/*
129 			 * Translation failed, IPA is not mapped. Return to NS host to
130 			 * fix the issue.
131 			 */
132 			res->walk_result.abort = true;
133 			res->walk_result.rtt_level = walk_res.rtt_level;
134 			res->smc_res.x[0] = RSI_INCOMPLETE;
135 		}
136 		return;
137 	}
138 
139 	/* Map realm data granule to RMM address space */
140 	gr = find_granule(walk_res.pa);
141 	realm_att_token = granule_map(gr, SLOT_RSI_CALL);
142 
143 	attest_token_buf.ptr = realm_att_token;
144 	attest_token_buf.len = ATTEST_TOKEN_BUFFER_SIZE;
145 
146 	attest_token_len = attest_cca_token_create(&attest_token_buf,
147 						   &rec->rmm_realm_token);
148 
149 	/* Unmap realm granule */
150 	buffer_unmap(realm_att_token);
151 
152 	/* Unlock last level page table (walk_res.g_llt) */
153 	granule_unlock(walk_res.llt);
154 
155 	/* Write output parameters */
156 	if (attest_token_len == 0) {
157 		res->smc_res.x[0] = RSI_ERROR_INPUT;
158 	} else {
159 		res->smc_res.x[0] = RSI_SUCCESS;
160 		res->smc_res.x[1] = attest_token_len;
161 	}
162 
163 	/* The signing has either succeeded or failed. Reset the state. */
164 	rec->token_sign_ctx.state = ATTEST_SIGN_NOT_STARTED;
165 }
166 
handle_rsi_attest_token_init(struct rec * rec)167 unsigned long handle_rsi_attest_token_init(struct rec *rec)
168 {
169 	struct rd *rd = NULL;
170 	unsigned long ret;
171 	unsigned long realm_buf_ipa = rec->regs[1];
172 	struct q_useful_buf rmm_realm_token_buf = {
173 		rec->rmm_realm_token_buf, sizeof(rec->rmm_realm_token_buf)};
174 	struct q_useful_buf_c rpv;
175 	int att_ret;
176 
177 	assert(rec != NULL);
178 
179 	/*
180 	 * Calling RSI_ATTESTATION_TOKEN_INIT any time aborts any ongoing
181 	 * operation.
182 	 * TODO: This can be moved to attestation lib
183 	 */
184 	if (rec->token_sign_ctx.state != ATTEST_SIGN_NOT_STARTED) {
185 		int restart;
186 
187 		rec->token_sign_ctx.state = ATTEST_SIGN_NOT_STARTED;
188 		restart = attestation_heap_reinit_pe(rec->aux_data.attest_heap_buf,
189 						      REC_HEAP_PAGES * SZ_4K);
190 		if (restart != 0) {
191 			/* There is no provision for this failure so panic */
192 			panic();
193 		}
194 	}
195 
196 	if (!GRANULE_ALIGNED(realm_buf_ipa)) {
197 		return RSI_ERROR_INPUT;
198 	}
199 
200 	/*
201 	 * rd lock is acquired so that measurement cannot be updated
202 	 * simultaneously by another rec
203 	 */
204 	granule_lock(rec->realm_info.g_rd, GRANULE_STATE_RD);
205 	rd = granule_map(rec->realm_info.g_rd, SLOT_RD);
206 	if (!addr_in_par(rd, realm_buf_ipa)) {
207 		ret = RSI_ERROR_INPUT;
208 		goto out_unmap_rd;
209 	}
210 
211 	/*
212 	 * Save the input parameters in the context for later iterations
213 	 * to check.
214 	 */
215 	save_input_parameters(rec);
216 
217 	get_rpv(rd, &rpv);
218 	att_ret = attest_realm_token_create(rd->algorithm, rd->measurement,
219 					    MEASUREMENT_SLOT_NR,
220 					    &rpv,
221 					    &rec->token_sign_ctx,
222 					    &rmm_realm_token_buf);
223 	if (att_ret != 0) {
224 		ERROR("FATAL_ERROR: Realm token creation failed,\n");
225 		panic();
226 	}
227 
228 	rec->token_sign_ctx.state = ATTEST_SIGN_IN_PROGRESS;
229 	ret = RSI_SUCCESS;
230 
231 out_unmap_rd:
232 	buffer_unmap(rd);
233 	granule_unlock(rec->realm_info.g_rd);
234 	return ret;
235 }
236 
attest_realm_token_sign_continue_start(void)237 void attest_realm_token_sign_continue_start(void)
238 {
239 	fpu_save_my_state();
240 }
241 
attest_realm_token_sign_continue_finish(void)242 void attest_realm_token_sign_continue_finish(void)
243 {
244 	fpu_restore_my_state();
245 }
246 
handle_rsi_attest_token_continue(struct rec * rec,struct attest_result * res)247 void handle_rsi_attest_token_continue(struct rec *rec,
248 				      struct attest_result *res)
249 {
250 	assert(rec != NULL);
251 	assert(res != NULL);
252 
253 	/* Initialize attest_result */
254 	res->incomplete = false;
255 	res->walk_result.abort = false;
256 
257 	if (!verify_input_parameters_consistency(rec)) {
258 		res->smc_res.x[0] = RSI_ERROR_INPUT;
259 		return;
260 	}
261 
262 	switch (rec->token_sign_ctx.state) {
263 	case ATTEST_SIGN_NOT_STARTED:
264 		/*
265 		 * Before this call the initial attestation token call
266 		 * (SMC_RSI_ATTEST_TOKEN_INIT) must have been executed
267 		 * successfully.
268 		 */
269 		res->smc_res.x[0] = RSI_ERROR_STATE;
270 		break;
271 	case ATTEST_SIGN_IN_PROGRESS:
272 		attest_token_continue_sign_state(rec, res);
273 		break;
274 	case ATTEST_SIGN_TOKEN_WRITE_IN_PROGRESS:
275 		attest_token_continue_write_state(rec, res);
276 		break;
277 	default:
278 		/* Any other state is considered an error. */
279 		assert(false);
280 	}
281 }
282 
handle_rsi_extend_measurement(struct rec * rec)283 unsigned long handle_rsi_extend_measurement(struct rec *rec)
284 {
285 	struct granule *g_rd;
286 	struct rd *rd;
287 	unsigned long index;
288 	unsigned long rd_addr;
289 	size_t size;
290 	unsigned long ret;
291 	void *extend_measurement;
292 	unsigned char *current_measurement;
293 	int __unused meas_ret;
294 
295 	/*
296 	 * rd lock is acquired so that measurement cannot be updated
297 	 * simultaneously by another rec
298 	 */
299 	rd_addr = granule_addr(rec->realm_info.g_rd);
300 	g_rd = find_lock_granule(rd_addr, GRANULE_STATE_RD);
301 
302 	assert(g_rd != NULL);
303 
304 	rd = granule_map(rec->realm_info.g_rd, SLOT_RD);
305 
306 	/*
307 	 * X1:     index
308 	 * X2:     size
309 	 * X3-X10: measurement value
310 	 */
311 	index = rec->regs[1];
312 
313 	if ((index == RIM_MEASUREMENT_SLOT) ||
314 	    (index >= MEASUREMENT_SLOT_NR)) {
315 		ret = RSI_ERROR_INPUT;
316 		goto out_unmap_rd;
317 	}
318 
319 	size  = rec->regs[2];
320 
321 	if (size > MAX_EXTENDED_SIZE) {
322 		ret = RSI_ERROR_INPUT;
323 		goto out_unmap_rd;
324 	}
325 
326 	extend_measurement = &rec->regs[3];
327 	current_measurement = rd->measurement[index];
328 
329 	measurement_extend(rd->algorithm,
330 			   current_measurement,
331 			   extend_measurement,
332 			   size,
333 			   current_measurement);
334 
335 	ret = RSI_SUCCESS;
336 
337 out_unmap_rd:
338 	buffer_unmap(rd);
339 	granule_unlock(g_rd);
340 	return ret;
341 }
342 
handle_rsi_read_measurement(struct rec * rec)343 unsigned long handle_rsi_read_measurement(struct rec *rec)
344 {
345 	struct rd *rd;
346 	unsigned long idx;
347 	size_t measurement_size;
348 
349 	assert(rec != NULL);
350 
351 	/* X1: Index */
352 	idx = rec->regs[1];
353 
354 	if (idx >= MEASUREMENT_SLOT_NR) {
355 		return RSI_ERROR_INPUT;
356 	}
357 
358 	/*
359 	 * rd lock is acquired so that measurement cannot be updated
360 	 * simultaneously by another rec
361 	 */
362 	granule_lock(rec->realm_info.g_rd, GRANULE_STATE_RD);
363 	rd = granule_map(rec->realm_info.g_rd, SLOT_RD);
364 
365 	measurement_size = measurement_get_size(rd->algorithm);
366 
367 	(void)memcpy(&rec->regs[1], rd->measurement[idx], measurement_size);
368 
369 	/* Zero-initialize the unused area */
370 	if (measurement_size < MAX_MEASUREMENT_SIZE) {
371 		(void)memset((char *)(&rec->regs[1]) + measurement_size,
372 			     0, MAX_MEASUREMENT_SIZE - measurement_size);
373 	}
374 
375 	buffer_unmap(rd);
376 	granule_unlock(rec->realm_info.g_rd);
377 
378 	return RSI_SUCCESS;
379 }
380