blob: 1b93b8c75a4ce4be489fa4fb042c1008e59c868b [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>
Javier Almansa Sobrino2f717dd2024-02-12 20:49:46 +00007#include <buffer.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +00008#include <debug.h>
9#include <granule.h>
10#include <measurement.h>
Jean-Philippe Bruckerda47f862025-01-23 14:40:19 +000011#include <mec.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000012#include <realm.h>
AlexeiFedorov5b186ad2023-04-26 14:43:18 +010013#include <rsi-handler.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000014#include <smc-rsi.h>
15#include <smc.h>
16#include <string.h>
17#include <utils_def.h>
18
AlexeiFedorovefe2aec2023-06-08 16:17:00 +010019#define MAX_EXTENDED_SIZE (64U)
AlexeiFedorov7b3c3042023-06-28 15:41:11 +010020#define MAX_MEASUREMENT_WORDS (MAX_MEASUREMENT_SIZE / sizeof(unsigned long))
Soby Mathewb4c6df42022-11-09 11:13:29 +000021/*
22 * Return the Realm Personalization Value.
23 *
24 * Arguments:
25 * rd - The Realm descriptor.
Mate Toth-Pal071aa562023-07-04 09:09:26 +020026 * claim_ptr - The start address of the Realm Personalization Value claim
27 * claim_len - The length of the Realm Personalization Value claim
Soby Mathewb4c6df42022-11-09 11:13:29 +000028 */
Mate Toth-Pal071aa562023-07-04 09:09:26 +020029static void get_rpv(struct rd *rd, void **claim_ptr, size_t *claim_len)
Soby Mathewb4c6df42022-11-09 11:13:29 +000030{
Mate Toth-Pal071aa562023-07-04 09:09:26 +020031 *claim_ptr = (uint8_t *)&(rd->rpv[0]);
32 *claim_len = RPV_SIZE;
Soby Mathewb4c6df42022-11-09 11:13:29 +000033}
34
35/*
AlexeiFedorov97844202023-04-27 15:17:35 +010036 * Function to continue with the token write operation
Soby Mathewb4c6df42022-11-09 11:13:29 +000037 */
38static void attest_token_continue_write_state(struct rec *rec,
AlexeiFedorov97844202023-04-27 15:17:35 +010039 struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +000040{
Soby Mathewb4c6df42022-11-09 11:13:29 +000041 struct granule *gr;
AlexeiFedorovea68b552023-10-03 11:11:47 +010042 uintptr_t realm_att_token;
Soby Mathewb4c6df42022-11-09 11:13:29 +000043 unsigned long realm_att_token_ipa = rec->regs[1];
AlexeiFedorovea68b552023-10-03 11:11:47 +010044 unsigned long offset = rec->regs[2];
45 unsigned long size = rec->regs[3];
Soby Mathewb4c6df42022-11-09 11:13:29 +000046 enum s2_walk_status walk_status;
47 struct s2_walk_result walk_res = { 0UL };
AlexeiFedorovea68b552023-10-03 11:11:47 +010048 size_t attest_token_len, length;
AlexeiFedorovec35c542023-04-27 17:52:02 +010049 struct rec_attest_data *attest_data = rec->aux_data.attest_data;
AlexeiFedorovea68b552023-10-03 11:11:47 +010050 uintptr_t cca_token_buf = rec->aux_data.cca_token_buf;
Juan Pablo Conde79ca2562024-08-12 17:05:41 -050051 enum attest_token_err_t ret;
Soby Mathewb4c6df42022-11-09 11:13:29 +000052
53 /*
Soby Mathewb4c6df42022-11-09 11:13:29 +000054 * Translate realm granule IPA to PA. If returns with
55 * WALK_SUCCESS then the last level page table (llt),
56 * which holds the realm_att_token_buf mapping, is locked.
57 */
AlexeiFedorovd2e1bbd2023-04-18 15:18:39 +010058 walk_status = realm_ipa_to_pa(rec, realm_att_token_ipa, &walk_res);
Soby Mathewb4c6df42022-11-09 11:13:29 +000059
60 /* Walk parameter validity was checked by RSI_ATTESTATION_TOKEN_INIT */
61 assert(walk_status != WALK_INVALID_PARAMS);
62
63 if (walk_status == WALK_FAIL) {
AlexeiFedorovd2e1bbd2023-04-18 15:18:39 +010064 if (walk_res.ripas_val == RIPAS_EMPTY) {
Soby Mathewb4c6df42022-11-09 11:13:29 +000065 res->smc_res.x[0] = RSI_ERROR_INPUT;
66 } else {
67 /*
AlexeiFedorov97844202023-04-27 15:17:35 +010068 * Translation failed, IPA is not mapped.
69 * Return to NS host to fix the issue.
Soby Mathewb4c6df42022-11-09 11:13:29 +000070 */
AlexeiFedorov97844202023-04-27 15:17:35 +010071 res->action = STAGE_2_TRANSLATION_FAULT;
72 res->rtt_level = walk_res.rtt_level;
Soby Mathewb4c6df42022-11-09 11:13:29 +000073 }
74 return;
75 }
76
Soby Mathew19eb4332023-11-20 14:03:23 +000077 /* If size of buffer is 0, then return early. */
AlexeiFedorovea68b552023-10-03 11:11:47 +010078 if (size == 0UL) {
Soby Mathew19eb4332023-11-20 14:03:23 +000079 res->smc_res.x[0] = RSI_INCOMPLETE;
80 goto out_unlock;
AlexeiFedorovea68b552023-10-03 11:11:47 +010081 }
82
Soby Mathewb4c6df42022-11-09 11:13:29 +000083 /* Map realm data granule to RMM address space */
Jean-Philippe Brucker9cd62682025-01-22 15:29:04 +000084 gr = find_lock_granule(walk_res.pa, GRANULE_STATE_DATA);
Jean-Philippe Brucker43299d92025-01-22 10:33:50 +000085 realm_att_token = (uintptr_t)buffer_granule_map(gr, SLOT_REALM);
AlexeiFedorovea68b552023-10-03 11:11:47 +010086 assert(realm_att_token != 0UL);
Soby Mathewb4c6df42022-11-09 11:13:29 +000087
Mate Toth-Pal4feff402024-08-30 10:53:32 +020088 if (attest_data->rmm_cca_token_copied_len == 0UL) {
Juan Pablo Conde79ca2562024-08-12 17:05:41 -050089 ret = attest_cca_token_create(
90 &attest_data->token_sign_ctx,
91 (void *)cca_token_buf,
92 REC_ATTEST_TOKEN_BUF_SIZE,
93 &attest_data->rmm_realm_token_buf,
94 attest_data->rmm_realm_token_len,
95 &attest_token_len);
Soby Mathewb4c6df42022-11-09 11:13:29 +000096
Juan Pablo Conde79ca2562024-08-12 17:05:41 -050097 if (ret != ATTEST_TOKEN_ERR_SUCCESS) {
AlexeiFedorovea68b552023-10-03 11:11:47 +010098 res->smc_res.x[0] = RSI_ERROR_INPUT;
AlexeiFedorovea68b552023-10-03 11:11:47 +010099 goto out_unmap;
100 }
101
Mate Toth-Pal4feff402024-08-30 10:53:32 +0200102 attest_data->rmm_cca_token_len = attest_token_len;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100103 } else {
Mate Toth-Pal4feff402024-08-30 10:53:32 +0200104 attest_token_len = attest_data->rmm_cca_token_len;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100105 }
106
107 length = (size < attest_token_len) ? size : attest_token_len;
108
109 /* Copy attestation token */
110 (void)memcpy((void *)(realm_att_token + offset),
111 (void *)(cca_token_buf +
Mate Toth-Pal4feff402024-08-30 10:53:32 +0200112 attest_data->rmm_cca_token_copied_len),
AlexeiFedorovea68b552023-10-03 11:11:47 +0100113 length);
114
115 attest_token_len -= length;
116
117 if (attest_token_len != 0UL) {
Mate Toth-Pal4feff402024-08-30 10:53:32 +0200118 attest_data->rmm_cca_token_len = attest_token_len;
119 attest_data->rmm_cca_token_copied_len += length;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100120
121 res->smc_res.x[0] = RSI_INCOMPLETE;
122 } else {
AlexeiFedorovea68b552023-10-03 11:11:47 +0100123 res->smc_res.x[0] = RSI_SUCCESS;
Soby Mathewda53d222024-08-29 16:37:26 +0100124 /* Token creation is complete, reset realm token length */
125 attest_data->rmm_realm_token_len = 0;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100126 }
127
128 res->smc_res.x[1] = length;
129
130out_unmap:
Soby Mathewb4c6df42022-11-09 11:13:29 +0000131 /* Unmap realm granule */
AlexeiFedorovea68b552023-10-03 11:11:47 +0100132 buffer_unmap((void *)realm_att_token);
Jean-Philippe Brucker9cd62682025-01-22 15:29:04 +0000133 granule_unlock(gr);
Soby Mathew19eb4332023-11-20 14:03:23 +0000134out_unlock:
Soby Mathewb4c6df42022-11-09 11:13:29 +0000135 /* Unlock last level page table (walk_res.g_llt) */
136 granule_unlock(walk_res.llt);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000137}
138
AlexeiFedorov97844202023-04-27 15:17:35 +0100139void handle_rsi_attest_token_init(struct rec *rec, struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000140{
AlexeiFedorovea68b552023-10-03 11:11:47 +0100141 struct rd *rd;
AlexeiFedorovec35c542023-04-27 17:52:02 +0100142 struct rec_attest_data *attest_data;
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200143 void *rpv_ptr;
144 size_t rpv_len;
Soby Mathewfdbc4b42024-11-07 06:54:42 +0000145 enum attest_token_err_t ret;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000146 int att_ret;
147
148 assert(rec != NULL);
149
AlexeiFedorovec35c542023-04-27 17:52:02 +0100150 attest_data = rec->aux_data.attest_data;
AlexeiFedorov97844202023-04-27 15:17:35 +0100151 res->action = UPDATE_REC_RETURN_TO_REALM;
152
Soby Mathew376ffa42024-10-04 14:01:59 +0100153 /* Initialize length fields in attestation data */
154 attest_data->rmm_realm_token_len = 0;
155 attest_data->rmm_cca_token_copied_len = 0;
156 attest_data->rmm_cca_token_len = 0;
157
Soby Mathewb4c6df42022-11-09 11:13:29 +0000158 /*
159 * Calling RSI_ATTESTATION_TOKEN_INIT any time aborts any ongoing
160 * operation.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000161 */
Soby Mathewfdbc4b42024-11-07 06:54:42 +0000162 ret = attest_token_ctx_init(&attest_data->token_sign_ctx,
Soby Mathewf3622132024-07-19 07:31:40 +0100163 rec->aux_data.attest_heap_buf,
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100164 REC_HEAP_SIZE,
165 granule_addr(rec->g_rec));
Soby Mathewfdbc4b42024-11-07 06:54:42 +0000166 if (ret != ATTEST_TOKEN_ERR_SUCCESS) {
Juan Pablo Condead871f92024-09-17 15:44:45 -0500167 ERROR("Failed to initialize attestation token context.\n");
168 res->smc_res.x[0] = RSI_ERROR_UNKNOWN;
169 return;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000170 }
171
Soby Mathewb4c6df42022-11-09 11:13:29 +0000172 /*
173 * rd lock is acquired so that measurement cannot be updated
174 * simultaneously by another rec
175 */
176 granule_lock(rec->realm_info.g_rd, GRANULE_STATE_RD);
Javier Almansa Sobrino2f717dd2024-02-12 20:49:46 +0000177 rd = buffer_granule_map(rec->realm_info.g_rd, SLOT_RD);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100178 assert(rd != NULL);
179
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200180 get_rpv(rd, &rpv_ptr, &rpv_len);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000181 att_ret = attest_realm_token_create(rd->algorithm, rd->measurement,
182 MEASUREMENT_SLOT_NR,
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200183 rpv_ptr,
184 rpv_len,
Jean-Philippe Bruckerda47f862025-01-23 14:40:19 +0000185 mecid_is_private(rd->mecid),
Mate Toth-Pal4feff402024-08-30 10:53:32 +0200186 (const void *)&rec->regs[1],
187 ATTEST_CHALLENGE_SIZE,
AlexeiFedorovec35c542023-04-27 17:52:02 +0100188 &attest_data->token_sign_ctx,
189 attest_data->rmm_realm_token_buf,
190 sizeof(attest_data->rmm_realm_token_buf));
AlexeiFedorovea68b552023-10-03 11:11:47 +0100191 buffer_unmap(rd);
192 granule_unlock(rec->realm_info.g_rd);
193
Soby Mathewb4c6df42022-11-09 11:13:29 +0000194 if (att_ret != 0) {
Juan Pablo Condead871f92024-09-17 15:44:45 -0500195 ERROR("Realm token creation failed.\n");
196 res->smc_res.x[0] = RSI_ERROR_UNKNOWN;
197 return;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000198 }
199
AlexeiFedorovea68b552023-10-03 11:11:47 +0100200 res->smc_res.x[0] = RSI_SUCCESS;
AlexeiFedorov755a70b2023-10-12 12:31:45 +0100201 res->smc_res.x[1] = REC_ATTEST_TOKEN_BUF_SIZE;
AlexeiFedorov97844202023-04-27 15:17:35 +0100202}
203
204/*
205 * Return 'false' if no IRQ is pending,
206 * return 'true' if there is an IRQ pending, and need to return to Host.
207 */
208static bool check_pending_irq(void)
209{
210 return (read_isr_el1() != 0UL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000211}
212
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100213static __unused int write_response_to_rec(struct rec *curr_rec,
214 uintptr_t resp_granule)
215{
216 struct granule *rec_granule = NULL;
217 struct rec *rec = NULL;
218 void *rec_aux = NULL;
219 struct token_sign_cntxt *ctx = NULL;
220 struct rec_attest_data *attest_data = NULL;
221 bool unmap_unlock_needed = false;
222 int ret = 0;
223
224 /*
225 * Check if the granule is the same as the current REC. If it is, the current
226 * code path is guaranteed to have a reference on the REC and the REC
227 * cannot be deleted. It also means that the REC is mapped at the usual
228 * SLOT_REC, so we can avoid locking and mapping the REC and the AUX
229 * granules.
230 */
231 if (resp_granule != granule_addr(curr_rec->g_rec)) {
232
233 rec_granule = find_lock_granule(
234 resp_granule, GRANULE_STATE_REC);
AlexeiFedorovc1795042024-10-07 11:54:39 +0100235 if (rec_granule == NULL) {
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100236 /*
237 * REC must have been destroyed, drop the response.
238 */
239 VERBOSE("REC granule %lx not found\n", resp_granule);
240 return 0;
241 }
242
243 rec = buffer_granule_map(rec_granule, SLOT_EL3_TOKEN_SIGN_REC);
244 assert(rec != NULL);
245
246 /*
247 * Map auxiliary granules. Note that the aux granules are mapped at a
248 * different high VA than during realm creation since this function
249 * may be executing with another rec mapped at the same high VA.
250 * Any accesses to aux granules via initialized pointers such as
251 * attest_data, need to be recaluclated at the new high VA.
252 */
Arunachalam Ganapathy78417802024-05-17 15:01:50 +0100253 rec_aux = buffer_rec_aux_granules_map_el3_token_sign_slot(
254 rec->g_aux,
255 rec->num_rec_aux);
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100256 assert(rec_aux != NULL);
257
258 unmap_unlock_needed = true;
259 attest_data = (struct rec_attest_data *)((uintptr_t)rec_aux + REC_HEAP_SIZE +
260 REC_PMU_SIZE + REC_SIMD_SIZE);
261 } else {
262 rec = curr_rec;
263 attest_data = rec->aux_data.attest_data;
264 }
265 ctx = &attest_data->token_sign_ctx;
266
267 if (attest_el3_token_write_response_to_ctx(ctx, resp_granule) != 0) {
268 ret = -EPERM;
269 }
270
271 if (unmap_unlock_needed) {
Arunachalam Ganapathy78417802024-05-17 15:01:50 +0100272 buffer_rec_aux_unmap(rec_aux, rec->num_rec_aux);
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100273 buffer_unmap(rec);
274 granule_unlock(rec_granule);
275 }
276
277 return ret;
278}
279
Soby Mathewb4c6df42022-11-09 11:13:29 +0000280void handle_rsi_attest_token_continue(struct rec *rec,
AlexeiFedorov97844202023-04-27 15:17:35 +0100281 struct rmi_rec_exit *rec_exit,
282 struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000283{
AlexeiFedorovec35c542023-04-27 17:52:02 +0100284 struct rec_attest_data *attest_data;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100285 unsigned long realm_buf_ipa, offset, size;
AlexeiFedorovec35c542023-04-27 17:52:02 +0100286
Soby Mathewb4c6df42022-11-09 11:13:29 +0000287 assert(rec != NULL);
AlexeiFedorov97844202023-04-27 15:17:35 +0100288 assert(rec_exit != NULL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000289
AlexeiFedorovec35c542023-04-27 17:52:02 +0100290 attest_data = rec->aux_data.attest_data;
AlexeiFedorov97844202023-04-27 15:17:35 +0100291 res->action = UPDATE_REC_RETURN_TO_REALM;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000292
AlexeiFedorovea68b552023-10-03 11:11:47 +0100293 realm_buf_ipa = rec->regs[1];
294 offset = rec->regs[2];
295 size = rec->regs[3];
296
297 if (!GRANULE_ALIGNED(realm_buf_ipa) ||
298 (offset >= GRANULE_SIZE) ||
299 ((offset + size) > GRANULE_SIZE) ||
300 ((offset + size) < offset)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000301 res->smc_res.x[0] = RSI_ERROR_INPUT;
302 return;
303 }
304
AlexeiFedorovea68b552023-10-03 11:11:47 +0100305 if (!addr_in_rec_par(rec, realm_buf_ipa)) {
306 res->smc_res.x[0] = RSI_ERROR_INPUT;
307 return;
308 }
AlexeiFedorov97844202023-04-27 15:17:35 +0100309
Soby Mathewf3622132024-07-19 07:31:40 +0100310 /* Sign the token */
311 while (attest_data->rmm_realm_token_len == 0U) {
312 enum attest_token_err_t ret;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100313
Soby Mathewf3622132024-07-19 07:31:40 +0100314 ret = attest_realm_token_sign(&(attest_data->token_sign_ctx),
315 &(attest_data->rmm_realm_token_len));
316
317 if (ret == ATTEST_TOKEN_ERR_INVALID_STATE) {
318 /*
319 * Before this call the initial attestation token call
320 * (SMC_RSI_ATTEST_TOKEN_INIT) must have been executed
321 * successfully.
322 */
323 res->smc_res.x[0] = RSI_ERROR_STATE;
324 return;
325 } else if ((ret != ATTEST_TOKEN_ERR_COSE_SIGN_IN_PROGRESS) &&
326 (ret != ATTEST_TOKEN_ERR_SUCCESS)) {
327 /* Accessible only in case of failure during token signing */
Juan Pablo Condead871f92024-09-17 15:44:45 -0500328 ERROR("Realm token signing failed.\n");
329 res->smc_res.x[0] = RSI_ERROR_UNKNOWN;
330 return;
Soby Mathewf3622132024-07-19 07:31:40 +0100331 }
332
333 res->smc_res.x[0] = RSI_INCOMPLETE;
334
335 /*
336 * Return to RSI handler function after each iteration
337 * to check is there anything else to do (pending IRQ)
338 * or next signing iteration can be executed.
339 */
AlexeiFedorovea68b552023-10-03 11:11:47 +0100340 if (check_pending_irq()) {
341 res->action = UPDATE_REC_EXIT_TO_HOST;
342 rec_exit->exit_reason = RMI_EXIT_IRQ;
343 return;
AlexeiFedorov97844202023-04-27 15:17:35 +0100344 }
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100345
346#if ATTEST_EL3_TOKEN_SIGN
347 /*
348 * Pull response from EL3, find the corresponding rec granule
349 * and attestation context, and have the attestation library
350 * write the response to the context.
351 */
352 uintptr_t granule = 0UL;
353 int el3_token_sign_ret;
354
355 el3_token_sign_ret = attest_el3_token_sign_pull_response_from_el3(&granule);
356 if (el3_token_sign_ret == -EAGAIN) {
357 continue;
358 }
359
360 if (el3_token_sign_ret != 0) {
361 ERROR("Failed to pull response from EL3: %d\n", el3_token_sign_ret);
362 res->smc_res.x[0] = RSI_ERROR_UNKNOWN;
363 return;
364 }
365
366 el3_token_sign_ret = write_response_to_rec(rec, granule);
367 if (el3_token_sign_ret != 0) {
368 ERROR("Failed to write response to REC: %d\n", el3_token_sign_ret);
369 res->smc_res.x[0] = RSI_ERROR_UNKNOWN;
370 return;
371 }
372#endif
373 /*
374 * If there are no interrupts pending, then continue to pull
375 * requests from EL3 until this RECs request is done.
376 */
Soby Mathewb4c6df42022-11-09 11:13:29 +0000377 }
AlexeiFedorovea68b552023-10-03 11:11:47 +0100378
AlexeiFedorovea68b552023-10-03 11:11:47 +0100379 attest_token_continue_write_state(rec, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000380}
381
AlexeiFedorov97844202023-04-27 15:17:35 +0100382void handle_rsi_measurement_extend(struct rec *rec, struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000383{
384 struct granule *g_rd;
385 struct rd *rd;
386 unsigned long index;
387 unsigned long rd_addr;
388 size_t size;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000389 void *extend_measurement;
390 unsigned char *current_measurement;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000391
AlexeiFedorov97844202023-04-27 15:17:35 +0100392 assert(rec != NULL);
393
394 res->action = UPDATE_REC_RETURN_TO_REALM;
395
Soby Mathewb4c6df42022-11-09 11:13:29 +0000396 /*
397 * rd lock is acquired so that measurement cannot be updated
398 * simultaneously by another rec
399 */
400 rd_addr = granule_addr(rec->realm_info.g_rd);
401 g_rd = find_lock_granule(rd_addr, GRANULE_STATE_RD);
402
403 assert(g_rd != NULL);
404
Javier Almansa Sobrino2f717dd2024-02-12 20:49:46 +0000405 rd = buffer_granule_map(rec->realm_info.g_rd, SLOT_RD);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100406 assert(rd != NULL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000407
408 /*
409 * X1: index
410 * X2: size
411 * X3-X10: measurement value
412 */
413 index = rec->regs[1];
414
415 if ((index == RIM_MEASUREMENT_SLOT) ||
416 (index >= MEASUREMENT_SLOT_NR)) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100417 res->smc_res.x[0] = RSI_ERROR_INPUT;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000418 goto out_unmap_rd;
419 }
420
421 size = rec->regs[2];
422
423 if (size > MAX_EXTENDED_SIZE) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100424 res->smc_res.x[0] = RSI_ERROR_INPUT;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000425 goto out_unmap_rd;
426 }
427
428 extend_measurement = &rec->regs[3];
429 current_measurement = rd->measurement[index];
430
431 measurement_extend(rd->algorithm,
432 current_measurement,
433 extend_measurement,
434 size,
Juan Pablo Conded3084982024-09-18 17:05:49 -0500435 current_measurement,
436 MAX_MEASUREMENT_SIZE);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000437
AlexeiFedorov97844202023-04-27 15:17:35 +0100438 res->smc_res.x[0] = RSI_SUCCESS;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000439
440out_unmap_rd:
441 buffer_unmap(rd);
442 granule_unlock(g_rd);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000443}
444
AlexeiFedorov97844202023-04-27 15:17:35 +0100445void handle_rsi_measurement_read(struct rec *rec, struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000446{
447 struct rd *rd;
448 unsigned long idx;
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100449 unsigned int i, cnt;
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200450 unsigned long *measurement_value_part;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000451
452 assert(rec != NULL);
453
AlexeiFedorov97844202023-04-27 15:17:35 +0100454 res->action = UPDATE_REC_RETURN_TO_REALM;
455
Soby Mathewb4c6df42022-11-09 11:13:29 +0000456 /* X1: Index */
457 idx = rec->regs[1];
458
459 if (idx >= MEASUREMENT_SLOT_NR) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100460 res->smc_res.x[0] = RSI_ERROR_INPUT;
461 return;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000462 }
463
464 /*
465 * rd lock is acquired so that measurement cannot be updated
466 * simultaneously by another rec
467 */
468 granule_lock(rec->realm_info.g_rd, GRANULE_STATE_RD);
Javier Almansa Sobrino2f717dd2024-02-12 20:49:46 +0000469 rd = buffer_granule_map(rec->realm_info.g_rd, SLOT_RD);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100470 assert(rd != NULL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000471
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100472 /* Number of 8-bytes words in measurement */
AlexeiFedorov4faab852023-08-30 15:06:49 +0100473 cnt = (unsigned int)(measurement_get_size(rd->algorithm) /
474 sizeof(unsigned long));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000475
AlexeiFedorovea68b552023-10-03 11:11:47 +0100476 assert(cnt >= (SMC_RESULT_REGS - 1U));
Soby Mathew1ceb0082024-10-10 17:22:38 +0100477 assert(cnt < ARRAY_SIZE(rec->regs));
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200478
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100479 /* Copy the part of the measurement to res->smc_res.x[] */
AlexeiFedorovea68b552023-10-03 11:11:47 +0100480 for (i = 0U; i < (SMC_RESULT_REGS - 1U); i++) {
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200481 measurement_value_part = (unsigned long *)
482 &(rd->measurement[idx][i * sizeof(unsigned long)]);
483 res->smc_res.x[i + 1U] = *measurement_value_part;
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100484 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000485
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100486 /* Copy the rest of the measurement to the rec->regs[] */
487 for (; i < cnt; i++) {
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200488 measurement_value_part = (unsigned long *)
489 &(rd->measurement[idx][i * sizeof(unsigned long)]);
490 rec->regs[i + 1U] = *measurement_value_part;
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100491 }
492
493 /* Zero-initialize unused area */
494 for (; i < MAX_MEASUREMENT_WORDS; i++) {
495 rec->regs[i + 1U] = 0UL;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000496 }
497
498 buffer_unmap(rd);
499 granule_unlock(rec->realm_info.g_rd);
500
AlexeiFedorov97844202023-04-27 15:17:35 +0100501 res->smc_res.x[0] = RSI_SUCCESS;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000502}