blob: 485bf71666b7ea31e6b8fca40e7da7be0b3f8ec6 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6#include <attestation.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +00007#include <debug.h>
8#include <granule.h>
9#include <measurement.h>
10#include <realm.h>
AlexeiFedorov5b186ad2023-04-26 14:43:18 +010011#include <rsi-handler.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000012#include <smc-rsi.h>
13#include <smc.h>
14#include <string.h>
15#include <utils_def.h>
16
AlexeiFedorovefe2aec2023-06-08 16:17:00 +010017#define MAX_EXTENDED_SIZE (64U)
AlexeiFedorov7b3c3042023-06-28 15:41:11 +010018#define MAX_MEASUREMENT_WORDS (MAX_MEASUREMENT_SIZE / sizeof(unsigned long))
Soby Mathewb4c6df42022-11-09 11:13:29 +000019/*
20 * Return the Realm Personalization Value.
21 *
22 * Arguments:
23 * rd - The Realm descriptor.
Mate Toth-Pal071aa562023-07-04 09:09:26 +020024 * claim_ptr - The start address of the Realm Personalization Value claim
25 * claim_len - The length of the Realm Personalization Value claim
Soby Mathewb4c6df42022-11-09 11:13:29 +000026 */
Mate Toth-Pal071aa562023-07-04 09:09:26 +020027static void get_rpv(struct rd *rd, void **claim_ptr, size_t *claim_len)
Soby Mathewb4c6df42022-11-09 11:13:29 +000028{
Mate Toth-Pal071aa562023-07-04 09:09:26 +020029 *claim_ptr = (uint8_t *)&(rd->rpv[0]);
30 *claim_len = RPV_SIZE;
Soby Mathewb4c6df42022-11-09 11:13:29 +000031}
32
33/*
34 * Save the input parameters in the context for later iterations to check for
35 * consistency.
36 */
37static void save_input_parameters(struct rec *rec)
38{
AlexeiFedorovec35c542023-04-27 17:52:02 +010039 struct rec_attest_data *attest_data = rec->aux_data.attest_data;
40
41 attest_data->token_sign_ctx.token_ipa = rec->regs[1];
42 (void)memcpy(attest_data->token_sign_ctx.challenge, &rec->regs[2],
Soby Mathewb4c6df42022-11-09 11:13:29 +000043 ATTEST_CHALLENGE_SIZE);
44}
45
46/*
47 * Verify that in all the iterations the input parameters are the same
48 * as in the initial call.
49 */
50static bool verify_input_parameters_consistency(struct rec *rec)
51{
AlexeiFedorovec35c542023-04-27 17:52:02 +010052 struct rec_attest_data *attest_data = rec->aux_data.attest_data;
53
54 return attest_data->token_sign_ctx.token_ipa == rec->regs[1];
Soby Mathewb4c6df42022-11-09 11:13:29 +000055}
56
57/*
AlexeiFedorov97844202023-04-27 15:17:35 +010058 * Function to continue with the sign operation
Soby Mathewb4c6df42022-11-09 11:13:29 +000059 */
AlexeiFedorovec35c542023-04-27 17:52:02 +010060static void attest_token_continue_sign_state(
61 struct rec_attest_data *attest_data,
62 struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +000063{
64 /*
65 * Sign and finish creating the token.
66 */
67 enum attest_token_err_t ret =
AlexeiFedorovec35c542023-04-27 17:52:02 +010068 attest_realm_token_sign(&(attest_data->token_sign_ctx.ctx),
69 &(attest_data->rmm_realm_token_len));
Soby Mathewb4c6df42022-11-09 11:13:29 +000070
71 if ((ret == ATTEST_TOKEN_ERR_COSE_SIGN_IN_PROGRESS) ||
72 (ret == ATTEST_TOKEN_ERR_SUCCESS)) {
73 /*
74 * Return to RSI handler function after each iteration
75 * to check is there anything else to do (pending IRQ)
76 * or next signing iteration can be executed.
77 */
Soby Mathewb4c6df42022-11-09 11:13:29 +000078 res->smc_res.x[0] = RSI_INCOMPLETE;
79
80 /* If this was the last signing cycle */
81 if (ret == ATTEST_TOKEN_ERR_SUCCESS) {
AlexeiFedorovec35c542023-04-27 17:52:02 +010082 attest_data->token_sign_ctx.state =
Soby Mathewb4c6df42022-11-09 11:13:29 +000083 ATTEST_SIGN_TOKEN_WRITE_IN_PROGRESS;
84 }
85 } else {
86 /* Accessible only in case of failure during token signing */
87 ERROR("FATAL_ERROR: Realm token creation failed\n");
88 panic();
89 }
90}
91
92/*
AlexeiFedorov97844202023-04-27 15:17:35 +010093 * Function to continue with the token write operation
Soby Mathewb4c6df42022-11-09 11:13:29 +000094 */
95static void attest_token_continue_write_state(struct rec *rec,
AlexeiFedorov97844202023-04-27 15:17:35 +010096 struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +000097{
Soby Mathewb4c6df42022-11-09 11:13:29 +000098 struct granule *gr;
99 uint8_t *realm_att_token;
100 unsigned long realm_att_token_ipa = rec->regs[1];
101 enum s2_walk_status walk_status;
102 struct s2_walk_result walk_res = { 0UL };
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200103 size_t attest_token_len;
AlexeiFedorovec35c542023-04-27 17:52:02 +0100104 struct rec_attest_data *attest_data = rec->aux_data.attest_data;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000105
106 /*
Soby Mathewb4c6df42022-11-09 11:13:29 +0000107 * Translate realm granule IPA to PA. If returns with
108 * WALK_SUCCESS then the last level page table (llt),
109 * which holds the realm_att_token_buf mapping, is locked.
110 */
AlexeiFedorovd2e1bbd2023-04-18 15:18:39 +0100111 walk_status = realm_ipa_to_pa(rec, realm_att_token_ipa, &walk_res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000112
113 /* Walk parameter validity was checked by RSI_ATTESTATION_TOKEN_INIT */
114 assert(walk_status != WALK_INVALID_PARAMS);
115
116 if (walk_status == WALK_FAIL) {
AlexeiFedorovd2e1bbd2023-04-18 15:18:39 +0100117 if (walk_res.ripas_val == RIPAS_EMPTY) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000118 res->smc_res.x[0] = RSI_ERROR_INPUT;
119 } else {
120 /*
AlexeiFedorov97844202023-04-27 15:17:35 +0100121 * Translation failed, IPA is not mapped.
122 * Return to NS host to fix the issue.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000123 */
AlexeiFedorov97844202023-04-27 15:17:35 +0100124 res->action = STAGE_2_TRANSLATION_FAULT;
125 res->rtt_level = walk_res.rtt_level;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000126 }
127 return;
128 }
129
130 /* Map realm data granule to RMM address space */
131 gr = find_granule(walk_res.pa);
132 realm_att_token = granule_map(gr, SLOT_RSI_CALL);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100133 assert(realm_att_token != NULL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000134
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200135 attest_token_len = attest_cca_token_create(realm_att_token,
AlexeiFedorovec35c542023-04-27 17:52:02 +0100136 ATTEST_TOKEN_BUFFER_SIZE,
137 &attest_data->rmm_realm_token_buf,
138 attest_data->rmm_realm_token_len);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000139
140 /* Unmap realm granule */
141 buffer_unmap(realm_att_token);
142
143 /* Unlock last level page table (walk_res.g_llt) */
144 granule_unlock(walk_res.llt);
145
146 /* Write output parameters */
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100147 if (attest_token_len == 0UL) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000148 res->smc_res.x[0] = RSI_ERROR_INPUT;
149 } else {
150 res->smc_res.x[0] = RSI_SUCCESS;
151 res->smc_res.x[1] = attest_token_len;
152 }
153
154 /* The signing has either succeeded or failed. Reset the state. */
AlexeiFedorovec35c542023-04-27 17:52:02 +0100155 attest_data->token_sign_ctx.state = ATTEST_SIGN_NOT_STARTED;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000156}
157
AlexeiFedorov97844202023-04-27 15:17:35 +0100158void handle_rsi_attest_token_init(struct rec *rec, struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000159{
160 struct rd *rd = NULL;
AlexeiFedorovec35c542023-04-27 17:52:02 +0100161 unsigned long realm_buf_ipa;
162 struct rec_attest_data *attest_data;
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200163 void *rpv_ptr;
164 size_t rpv_len;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000165 int att_ret;
166
167 assert(rec != NULL);
168
AlexeiFedorovec35c542023-04-27 17:52:02 +0100169 realm_buf_ipa = rec->regs[1];
170 attest_data = rec->aux_data.attest_data;
171
AlexeiFedorov97844202023-04-27 15:17:35 +0100172 res->action = UPDATE_REC_RETURN_TO_REALM;
173
Soby Mathewb4c6df42022-11-09 11:13:29 +0000174 /*
175 * Calling RSI_ATTESTATION_TOKEN_INIT any time aborts any ongoing
176 * operation.
177 * TODO: This can be moved to attestation lib
178 */
AlexeiFedorovec35c542023-04-27 17:52:02 +0100179 if (attest_data->token_sign_ctx.state != ATTEST_SIGN_NOT_STARTED) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000180 int restart;
181
AlexeiFedorovec35c542023-04-27 17:52:02 +0100182 attest_data->token_sign_ctx.state = ATTEST_SIGN_NOT_STARTED;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000183 restart = attestation_heap_reinit_pe(rec->aux_data.attest_heap_buf,
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000184 REC_HEAP_SIZE);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000185 if (restart != 0) {
186 /* There is no provision for this failure so panic */
187 panic();
188 }
189 }
190
191 if (!GRANULE_ALIGNED(realm_buf_ipa)) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100192 res->smc_res.x[0] = RSI_ERROR_INPUT;
193 return;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000194 }
195
196 /*
197 * rd lock is acquired so that measurement cannot be updated
198 * simultaneously by another rec
199 */
200 granule_lock(rec->realm_info.g_rd, GRANULE_STATE_RD);
201 rd = granule_map(rec->realm_info.g_rd, SLOT_RD);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100202 assert(rd != NULL);
203
Soby Mathewb4c6df42022-11-09 11:13:29 +0000204 if (!addr_in_par(rd, realm_buf_ipa)) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100205 res->smc_res.x[0] = RSI_ERROR_INPUT;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000206 goto out_unmap_rd;
207 }
208
209 /*
210 * Save the input parameters in the context for later iterations
211 * to check.
212 */
213 save_input_parameters(rec);
214
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200215 get_rpv(rd, &rpv_ptr, &rpv_len);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000216 att_ret = attest_realm_token_create(rd->algorithm, rd->measurement,
217 MEASUREMENT_SLOT_NR,
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200218 rpv_ptr,
219 rpv_len,
AlexeiFedorovec35c542023-04-27 17:52:02 +0100220 &attest_data->token_sign_ctx,
221 attest_data->rmm_realm_token_buf,
222 sizeof(attest_data->rmm_realm_token_buf));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000223 if (att_ret != 0) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100224 ERROR("FATAL_ERROR: Realm token creation failed\n");
Soby Mathewb4c6df42022-11-09 11:13:29 +0000225 panic();
226 }
227
AlexeiFedorovec35c542023-04-27 17:52:02 +0100228 attest_data->token_sign_ctx.state = ATTEST_SIGN_IN_PROGRESS;
AlexeiFedorov97844202023-04-27 15:17:35 +0100229 res->smc_res.x[0] = RSI_SUCCESS;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000230
231out_unmap_rd:
232 buffer_unmap(rd);
233 granule_unlock(rec->realm_info.g_rd);
AlexeiFedorov97844202023-04-27 15:17:35 +0100234}
235
236/*
237 * Return 'false' if no IRQ is pending,
238 * return 'true' if there is an IRQ pending, and need to return to Host.
239 */
240static bool check_pending_irq(void)
241{
242 return (read_isr_el1() != 0UL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000243}
244
Soby Mathewb4c6df42022-11-09 11:13:29 +0000245void handle_rsi_attest_token_continue(struct rec *rec,
AlexeiFedorov97844202023-04-27 15:17:35 +0100246 struct rmi_rec_exit *rec_exit,
247 struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000248{
AlexeiFedorovec35c542023-04-27 17:52:02 +0100249 struct rec_attest_data *attest_data;
250
Soby Mathewb4c6df42022-11-09 11:13:29 +0000251 assert(rec != NULL);
AlexeiFedorov97844202023-04-27 15:17:35 +0100252 assert(rec_exit != NULL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000253
AlexeiFedorovec35c542023-04-27 17:52:02 +0100254 attest_data = rec->aux_data.attest_data;
AlexeiFedorov97844202023-04-27 15:17:35 +0100255 res->action = UPDATE_REC_RETURN_TO_REALM;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000256
257 if (!verify_input_parameters_consistency(rec)) {
258 res->smc_res.x[0] = RSI_ERROR_INPUT;
259 return;
260 }
261
AlexeiFedorov97844202023-04-27 15:17:35 +0100262 while (true) {
AlexeiFedorovec35c542023-04-27 17:52:02 +0100263 switch (attest_data->token_sign_ctx.state) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100264 case ATTEST_SIGN_NOT_STARTED:
265 /*
266 * Before this call the initial attestation token call
267 * (SMC_RSI_ATTEST_TOKEN_INIT) must have been executed
268 * successfully.
269 */
270 res->smc_res.x[0] = RSI_ERROR_STATE;
271 break;
272 case ATTEST_SIGN_IN_PROGRESS:
AlexeiFedorovec35c542023-04-27 17:52:02 +0100273 attest_token_continue_sign_state(attest_data, res);
AlexeiFedorov97844202023-04-27 15:17:35 +0100274 break;
275 case ATTEST_SIGN_TOKEN_WRITE_IN_PROGRESS:
276 attest_token_continue_write_state(rec, res);
277 break;
278 default:
279 /* Any other state is considered an error */
280 panic();
281 }
282
283 if (res->smc_res.x[0] == RSI_INCOMPLETE) {
284 if (check_pending_irq()) {
285 res->action = UPDATE_REC_EXIT_TO_HOST;
286 res->smc_res.x[0] = RSI_INCOMPLETE;
287 rec_exit->exit_reason = RMI_EXIT_IRQ;
288 break;
289 }
AlexeiFedorove5dcae22023-08-29 12:58:18 +0100290 if (((unsigned int)res->action &
291 FLAG_EXIT_TO_HOST) != 0U) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100292 break;
293 }
294 } else {
295 break;
296 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000297 }
298}
299
AlexeiFedorov97844202023-04-27 15:17:35 +0100300void handle_rsi_measurement_extend(struct rec *rec, struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000301{
302 struct granule *g_rd;
303 struct rd *rd;
304 unsigned long index;
305 unsigned long rd_addr;
306 size_t size;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000307 void *extend_measurement;
308 unsigned char *current_measurement;
309 int __unused meas_ret;
310
AlexeiFedorov97844202023-04-27 15:17:35 +0100311 assert(rec != NULL);
312
313 res->action = UPDATE_REC_RETURN_TO_REALM;
314
Soby Mathewb4c6df42022-11-09 11:13:29 +0000315 /*
316 * rd lock is acquired so that measurement cannot be updated
317 * simultaneously by another rec
318 */
319 rd_addr = granule_addr(rec->realm_info.g_rd);
320 g_rd = find_lock_granule(rd_addr, GRANULE_STATE_RD);
321
322 assert(g_rd != NULL);
323
324 rd = granule_map(rec->realm_info.g_rd, SLOT_RD);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100325 assert(rd != NULL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000326
327 /*
328 * X1: index
329 * X2: size
330 * X3-X10: measurement value
331 */
332 index = rec->regs[1];
333
334 if ((index == RIM_MEASUREMENT_SLOT) ||
335 (index >= MEASUREMENT_SLOT_NR)) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100336 res->smc_res.x[0] = RSI_ERROR_INPUT;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000337 goto out_unmap_rd;
338 }
339
340 size = rec->regs[2];
341
342 if (size > MAX_EXTENDED_SIZE) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100343 res->smc_res.x[0] = RSI_ERROR_INPUT;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000344 goto out_unmap_rd;
345 }
346
347 extend_measurement = &rec->regs[3];
348 current_measurement = rd->measurement[index];
349
350 measurement_extend(rd->algorithm,
351 current_measurement,
352 extend_measurement,
353 size,
354 current_measurement);
355
AlexeiFedorov97844202023-04-27 15:17:35 +0100356 res->smc_res.x[0] = RSI_SUCCESS;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000357
358out_unmap_rd:
359 buffer_unmap(rd);
360 granule_unlock(g_rd);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000361}
362
AlexeiFedorov97844202023-04-27 15:17:35 +0100363void handle_rsi_measurement_read(struct rec *rec, struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000364{
365 struct rd *rd;
366 unsigned long idx;
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100367 unsigned int i, cnt;
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200368 unsigned long *measurement_value_part;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000369
370 assert(rec != NULL);
371
AlexeiFedorov97844202023-04-27 15:17:35 +0100372 res->action = UPDATE_REC_RETURN_TO_REALM;
373
Soby Mathewb4c6df42022-11-09 11:13:29 +0000374 /* X1: Index */
375 idx = rec->regs[1];
376
377 if (idx >= MEASUREMENT_SLOT_NR) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100378 res->smc_res.x[0] = RSI_ERROR_INPUT;
379 return;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000380 }
381
382 /*
383 * rd lock is acquired so that measurement cannot be updated
384 * simultaneously by another rec
385 */
386 granule_lock(rec->realm_info.g_rd, GRANULE_STATE_RD);
387 rd = granule_map(rec->realm_info.g_rd, SLOT_RD);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100388 assert(rd != NULL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000389
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100390 /* Number of 8-bytes words in measurement */
AlexeiFedorov4faab852023-08-30 15:06:49 +0100391 cnt = (unsigned int)(measurement_get_size(rd->algorithm) /
392 sizeof(unsigned long));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000393
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200394 assert(cnt >= SMC_RESULT_REGS - 1U);
395 assert(cnt < ARRAY_LEN(rec->regs));
396
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100397 /* Copy the part of the measurement to res->smc_res.x[] */
398 for (i = 0U; i < SMC_RESULT_REGS - 1U; i++) {
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200399 measurement_value_part = (unsigned long *)
400 &(rd->measurement[idx][i * sizeof(unsigned long)]);
401 res->smc_res.x[i + 1U] = *measurement_value_part;
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100402 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000403
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100404 /* Copy the rest of the measurement to the rec->regs[] */
405 for (; i < cnt; i++) {
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200406 measurement_value_part = (unsigned long *)
407 &(rd->measurement[idx][i * sizeof(unsigned long)]);
408 rec->regs[i + 1U] = *measurement_value_part;
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100409 }
410
411 /* Zero-initialize unused area */
412 for (; i < MAX_MEASUREMENT_WORDS; i++) {
413 rec->regs[i + 1U] = 0UL;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000414 }
415
416 buffer_unmap(rd);
417 granule_unlock(rec->realm_info.g_rd);
418
AlexeiFedorov97844202023-04-27 15:17:35 +0100419 res->smc_res.x[0] = RSI_SUCCESS;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000420}