blob: 48ebff040796048ce58ba8cc578638891f8cd8e0 [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>
11#include <realm.h>
AlexeiFedorov5b186ad2023-04-26 14:43:18 +010012#include <rsi-handler.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000013#include <smc-rsi.h>
14#include <smc.h>
15#include <string.h>
16#include <utils_def.h>
17
AlexeiFedorovefe2aec2023-06-08 16:17:00 +010018#define MAX_EXTENDED_SIZE (64U)
AlexeiFedorov7b3c3042023-06-28 15:41:11 +010019#define MAX_MEASUREMENT_WORDS (MAX_MEASUREMENT_SIZE / sizeof(unsigned long))
Soby Mathewb4c6df42022-11-09 11:13:29 +000020/*
21 * Return the Realm Personalization Value.
22 *
23 * Arguments:
24 * rd - The Realm descriptor.
Mate Toth-Pal071aa562023-07-04 09:09:26 +020025 * claim_ptr - The start address of the Realm Personalization Value claim
26 * claim_len - The length of the Realm Personalization Value claim
Soby Mathewb4c6df42022-11-09 11:13:29 +000027 */
Mate Toth-Pal071aa562023-07-04 09:09:26 +020028static void get_rpv(struct rd *rd, void **claim_ptr, size_t *claim_len)
Soby Mathewb4c6df42022-11-09 11:13:29 +000029{
Mate Toth-Pal071aa562023-07-04 09:09:26 +020030 *claim_ptr = (uint8_t *)&(rd->rpv[0]);
31 *claim_len = RPV_SIZE;
Soby Mathewb4c6df42022-11-09 11:13:29 +000032}
33
34/*
AlexeiFedorov97844202023-04-27 15:17:35 +010035 * Function to continue with the token write operation
Soby Mathewb4c6df42022-11-09 11:13:29 +000036 */
37static void attest_token_continue_write_state(struct rec *rec,
AlexeiFedorov97844202023-04-27 15:17:35 +010038 struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +000039{
Soby Mathewb4c6df42022-11-09 11:13:29 +000040 struct granule *gr;
AlexeiFedorovea68b552023-10-03 11:11:47 +010041 uintptr_t realm_att_token;
Soby Mathewb4c6df42022-11-09 11:13:29 +000042 unsigned long realm_att_token_ipa = rec->regs[1];
AlexeiFedorovea68b552023-10-03 11:11:47 +010043 unsigned long offset = rec->regs[2];
44 unsigned long size = rec->regs[3];
Soby Mathewb4c6df42022-11-09 11:13:29 +000045 enum s2_walk_status walk_status;
46 struct s2_walk_result walk_res = { 0UL };
AlexeiFedorovea68b552023-10-03 11:11:47 +010047 size_t attest_token_len, length;
AlexeiFedorovec35c542023-04-27 17:52:02 +010048 struct rec_attest_data *attest_data = rec->aux_data.attest_data;
AlexeiFedorovea68b552023-10-03 11:11:47 +010049 uintptr_t cca_token_buf = rec->aux_data.cca_token_buf;
Juan Pablo Conde79ca2562024-08-12 17:05:41 -050050 enum attest_token_err_t ret;
Soby Mathewb4c6df42022-11-09 11:13:29 +000051
52 /*
Soby Mathewb4c6df42022-11-09 11:13:29 +000053 * Translate realm granule IPA to PA. If returns with
54 * WALK_SUCCESS then the last level page table (llt),
55 * which holds the realm_att_token_buf mapping, is locked.
56 */
AlexeiFedorovd2e1bbd2023-04-18 15:18:39 +010057 walk_status = realm_ipa_to_pa(rec, realm_att_token_ipa, &walk_res);
Soby Mathewb4c6df42022-11-09 11:13:29 +000058
59 /* Walk parameter validity was checked by RSI_ATTESTATION_TOKEN_INIT */
60 assert(walk_status != WALK_INVALID_PARAMS);
61
62 if (walk_status == WALK_FAIL) {
AlexeiFedorovd2e1bbd2023-04-18 15:18:39 +010063 if (walk_res.ripas_val == RIPAS_EMPTY) {
Soby Mathewb4c6df42022-11-09 11:13:29 +000064 res->smc_res.x[0] = RSI_ERROR_INPUT;
65 } else {
66 /*
AlexeiFedorov97844202023-04-27 15:17:35 +010067 * Translation failed, IPA is not mapped.
68 * Return to NS host to fix the issue.
Soby Mathewb4c6df42022-11-09 11:13:29 +000069 */
AlexeiFedorov97844202023-04-27 15:17:35 +010070 res->action = STAGE_2_TRANSLATION_FAULT;
71 res->rtt_level = walk_res.rtt_level;
Soby Mathewb4c6df42022-11-09 11:13:29 +000072 }
73 return;
74 }
75
Soby Mathew19eb4332023-11-20 14:03:23 +000076 /* If size of buffer is 0, then return early. */
AlexeiFedorovea68b552023-10-03 11:11:47 +010077 if (size == 0UL) {
Soby Mathew19eb4332023-11-20 14:03:23 +000078 res->smc_res.x[0] = RSI_INCOMPLETE;
79 goto out_unlock;
AlexeiFedorovea68b552023-10-03 11:11:47 +010080 }
81
Soby Mathewb4c6df42022-11-09 11:13:29 +000082 /* Map realm data granule to RMM address space */
Jean-Philippe Brucker9cd62682025-01-22 15:29:04 +000083 gr = find_lock_granule(walk_res.pa, GRANULE_STATE_DATA);
Javier Almansa Sobrino2f717dd2024-02-12 20:49:46 +000084 realm_att_token = (uintptr_t)buffer_granule_map(gr, SLOT_RSI_CALL);
AlexeiFedorovea68b552023-10-03 11:11:47 +010085 assert(realm_att_token != 0UL);
Soby Mathewb4c6df42022-11-09 11:13:29 +000086
Mate Toth-Pal4feff402024-08-30 10:53:32 +020087 if (attest_data->rmm_cca_token_copied_len == 0UL) {
Juan Pablo Conde79ca2562024-08-12 17:05:41 -050088 ret = attest_cca_token_create(
89 &attest_data->token_sign_ctx,
90 (void *)cca_token_buf,
91 REC_ATTEST_TOKEN_BUF_SIZE,
92 &attest_data->rmm_realm_token_buf,
93 attest_data->rmm_realm_token_len,
94 &attest_token_len);
Soby Mathewb4c6df42022-11-09 11:13:29 +000095
Juan Pablo Conde79ca2562024-08-12 17:05:41 -050096 if (ret != ATTEST_TOKEN_ERR_SUCCESS) {
AlexeiFedorovea68b552023-10-03 11:11:47 +010097 res->smc_res.x[0] = RSI_ERROR_INPUT;
AlexeiFedorovea68b552023-10-03 11:11:47 +010098 goto out_unmap;
99 }
100
Mate Toth-Pal4feff402024-08-30 10:53:32 +0200101 attest_data->rmm_cca_token_len = attest_token_len;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100102 } else {
Mate Toth-Pal4feff402024-08-30 10:53:32 +0200103 attest_token_len = attest_data->rmm_cca_token_len;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100104 }
105
106 length = (size < attest_token_len) ? size : attest_token_len;
107
108 /* Copy attestation token */
109 (void)memcpy((void *)(realm_att_token + offset),
110 (void *)(cca_token_buf +
Mate Toth-Pal4feff402024-08-30 10:53:32 +0200111 attest_data->rmm_cca_token_copied_len),
AlexeiFedorovea68b552023-10-03 11:11:47 +0100112 length);
113
114 attest_token_len -= length;
115
116 if (attest_token_len != 0UL) {
Mate Toth-Pal4feff402024-08-30 10:53:32 +0200117 attest_data->rmm_cca_token_len = attest_token_len;
118 attest_data->rmm_cca_token_copied_len += length;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100119
120 res->smc_res.x[0] = RSI_INCOMPLETE;
121 } else {
AlexeiFedorovea68b552023-10-03 11:11:47 +0100122 res->smc_res.x[0] = RSI_SUCCESS;
Soby Mathewda53d222024-08-29 16:37:26 +0100123 /* Token creation is complete, reset realm token length */
124 attest_data->rmm_realm_token_len = 0;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100125 }
126
127 res->smc_res.x[1] = length;
128
129out_unmap:
Soby Mathewb4c6df42022-11-09 11:13:29 +0000130 /* Unmap realm granule */
AlexeiFedorovea68b552023-10-03 11:11:47 +0100131 buffer_unmap((void *)realm_att_token);
Jean-Philippe Brucker9cd62682025-01-22 15:29:04 +0000132 granule_unlock(gr);
Soby Mathew19eb4332023-11-20 14:03:23 +0000133out_unlock:
Soby Mathewb4c6df42022-11-09 11:13:29 +0000134 /* Unlock last level page table (walk_res.g_llt) */
135 granule_unlock(walk_res.llt);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000136}
137
AlexeiFedorov97844202023-04-27 15:17:35 +0100138void handle_rsi_attest_token_init(struct rec *rec, struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000139{
AlexeiFedorovea68b552023-10-03 11:11:47 +0100140 struct rd *rd;
AlexeiFedorovec35c542023-04-27 17:52:02 +0100141 struct rec_attest_data *attest_data;
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200142 void *rpv_ptr;
143 size_t rpv_len;
Soby Mathewfdbc4b42024-11-07 06:54:42 +0000144 enum attest_token_err_t ret;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000145 int att_ret;
146
147 assert(rec != NULL);
148
AlexeiFedorovec35c542023-04-27 17:52:02 +0100149 attest_data = rec->aux_data.attest_data;
AlexeiFedorov97844202023-04-27 15:17:35 +0100150 res->action = UPDATE_REC_RETURN_TO_REALM;
151
Soby Mathew376ffa42024-10-04 14:01:59 +0100152 /* Initialize length fields in attestation data */
153 attest_data->rmm_realm_token_len = 0;
154 attest_data->rmm_cca_token_copied_len = 0;
155 attest_data->rmm_cca_token_len = 0;
156
Soby Mathewb4c6df42022-11-09 11:13:29 +0000157 /*
158 * Calling RSI_ATTESTATION_TOKEN_INIT any time aborts any ongoing
159 * operation.
Soby Mathewb4c6df42022-11-09 11:13:29 +0000160 */
Soby Mathewfdbc4b42024-11-07 06:54:42 +0000161 ret = attest_token_ctx_init(&attest_data->token_sign_ctx,
Soby Mathewf3622132024-07-19 07:31:40 +0100162 rec->aux_data.attest_heap_buf,
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100163 REC_HEAP_SIZE,
164 granule_addr(rec->g_rec));
Soby Mathewfdbc4b42024-11-07 06:54:42 +0000165 if (ret != ATTEST_TOKEN_ERR_SUCCESS) {
Juan Pablo Condead871f92024-09-17 15:44:45 -0500166 ERROR("Failed to initialize attestation token context.\n");
167 res->smc_res.x[0] = RSI_ERROR_UNKNOWN;
168 return;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000169 }
170
Soby Mathewb4c6df42022-11-09 11:13:29 +0000171 /*
172 * rd lock is acquired so that measurement cannot be updated
173 * simultaneously by another rec
174 */
175 granule_lock(rec->realm_info.g_rd, GRANULE_STATE_RD);
Javier Almansa Sobrino2f717dd2024-02-12 20:49:46 +0000176 rd = buffer_granule_map(rec->realm_info.g_rd, SLOT_RD);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100177 assert(rd != NULL);
178
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200179 get_rpv(rd, &rpv_ptr, &rpv_len);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000180 att_ret = attest_realm_token_create(rd->algorithm, rd->measurement,
181 MEASUREMENT_SLOT_NR,
Mate Toth-Pal071aa562023-07-04 09:09:26 +0200182 rpv_ptr,
183 rpv_len,
Mate Toth-Pal4feff402024-08-30 10:53:32 +0200184 (const void *)&rec->regs[1],
185 ATTEST_CHALLENGE_SIZE,
AlexeiFedorovec35c542023-04-27 17:52:02 +0100186 &attest_data->token_sign_ctx,
187 attest_data->rmm_realm_token_buf,
188 sizeof(attest_data->rmm_realm_token_buf));
AlexeiFedorovea68b552023-10-03 11:11:47 +0100189 buffer_unmap(rd);
190 granule_unlock(rec->realm_info.g_rd);
191
Soby Mathewb4c6df42022-11-09 11:13:29 +0000192 if (att_ret != 0) {
Juan Pablo Condead871f92024-09-17 15:44:45 -0500193 ERROR("Realm token creation failed.\n");
194 res->smc_res.x[0] = RSI_ERROR_UNKNOWN;
195 return;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000196 }
197
AlexeiFedorovea68b552023-10-03 11:11:47 +0100198 res->smc_res.x[0] = RSI_SUCCESS;
AlexeiFedorov755a70b2023-10-12 12:31:45 +0100199 res->smc_res.x[1] = REC_ATTEST_TOKEN_BUF_SIZE;
AlexeiFedorov97844202023-04-27 15:17:35 +0100200}
201
202/*
203 * Return 'false' if no IRQ is pending,
204 * return 'true' if there is an IRQ pending, and need to return to Host.
205 */
206static bool check_pending_irq(void)
207{
208 return (read_isr_el1() != 0UL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000209}
210
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100211static __unused int write_response_to_rec(struct rec *curr_rec,
212 uintptr_t resp_granule)
213{
214 struct granule *rec_granule = NULL;
215 struct rec *rec = NULL;
216 void *rec_aux = NULL;
217 struct token_sign_cntxt *ctx = NULL;
218 struct rec_attest_data *attest_data = NULL;
219 bool unmap_unlock_needed = false;
220 int ret = 0;
221
222 /*
223 * Check if the granule is the same as the current REC. If it is, the current
224 * code path is guaranteed to have a reference on the REC and the REC
225 * cannot be deleted. It also means that the REC is mapped at the usual
226 * SLOT_REC, so we can avoid locking and mapping the REC and the AUX
227 * granules.
228 */
229 if (resp_granule != granule_addr(curr_rec->g_rec)) {
230
231 rec_granule = find_lock_granule(
232 resp_granule, GRANULE_STATE_REC);
AlexeiFedorovc1795042024-10-07 11:54:39 +0100233 if (rec_granule == NULL) {
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100234 /*
235 * REC must have been destroyed, drop the response.
236 */
237 VERBOSE("REC granule %lx not found\n", resp_granule);
238 return 0;
239 }
240
241 rec = buffer_granule_map(rec_granule, SLOT_EL3_TOKEN_SIGN_REC);
242 assert(rec != NULL);
243
244 /*
245 * Map auxiliary granules. Note that the aux granules are mapped at a
246 * different high VA than during realm creation since this function
247 * may be executing with another rec mapped at the same high VA.
248 * Any accesses to aux granules via initialized pointers such as
249 * attest_data, need to be recaluclated at the new high VA.
250 */
Arunachalam Ganapathy78417802024-05-17 15:01:50 +0100251 rec_aux = buffer_rec_aux_granules_map_el3_token_sign_slot(
252 rec->g_aux,
253 rec->num_rec_aux);
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100254 assert(rec_aux != NULL);
255
256 unmap_unlock_needed = true;
257 attest_data = (struct rec_attest_data *)((uintptr_t)rec_aux + REC_HEAP_SIZE +
258 REC_PMU_SIZE + REC_SIMD_SIZE);
259 } else {
260 rec = curr_rec;
261 attest_data = rec->aux_data.attest_data;
262 }
263 ctx = &attest_data->token_sign_ctx;
264
265 if (attest_el3_token_write_response_to_ctx(ctx, resp_granule) != 0) {
266 ret = -EPERM;
267 }
268
269 if (unmap_unlock_needed) {
Arunachalam Ganapathy78417802024-05-17 15:01:50 +0100270 buffer_rec_aux_unmap(rec_aux, rec->num_rec_aux);
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100271 buffer_unmap(rec);
272 granule_unlock(rec_granule);
273 }
274
275 return ret;
276}
277
Soby Mathewb4c6df42022-11-09 11:13:29 +0000278void handle_rsi_attest_token_continue(struct rec *rec,
AlexeiFedorov97844202023-04-27 15:17:35 +0100279 struct rmi_rec_exit *rec_exit,
280 struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000281{
AlexeiFedorovec35c542023-04-27 17:52:02 +0100282 struct rec_attest_data *attest_data;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100283 unsigned long realm_buf_ipa, offset, size;
AlexeiFedorovec35c542023-04-27 17:52:02 +0100284
Soby Mathewb4c6df42022-11-09 11:13:29 +0000285 assert(rec != NULL);
AlexeiFedorov97844202023-04-27 15:17:35 +0100286 assert(rec_exit != NULL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000287
AlexeiFedorovec35c542023-04-27 17:52:02 +0100288 attest_data = rec->aux_data.attest_data;
AlexeiFedorov97844202023-04-27 15:17:35 +0100289 res->action = UPDATE_REC_RETURN_TO_REALM;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000290
AlexeiFedorovea68b552023-10-03 11:11:47 +0100291 realm_buf_ipa = rec->regs[1];
292 offset = rec->regs[2];
293 size = rec->regs[3];
294
295 if (!GRANULE_ALIGNED(realm_buf_ipa) ||
296 (offset >= GRANULE_SIZE) ||
297 ((offset + size) > GRANULE_SIZE) ||
298 ((offset + size) < offset)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000299 res->smc_res.x[0] = RSI_ERROR_INPUT;
300 return;
301 }
302
AlexeiFedorovea68b552023-10-03 11:11:47 +0100303 if (!addr_in_rec_par(rec, realm_buf_ipa)) {
304 res->smc_res.x[0] = RSI_ERROR_INPUT;
305 return;
306 }
AlexeiFedorov97844202023-04-27 15:17:35 +0100307
Soby Mathewf3622132024-07-19 07:31:40 +0100308 /* Sign the token */
309 while (attest_data->rmm_realm_token_len == 0U) {
310 enum attest_token_err_t ret;
AlexeiFedorovea68b552023-10-03 11:11:47 +0100311
Soby Mathewf3622132024-07-19 07:31:40 +0100312 ret = attest_realm_token_sign(&(attest_data->token_sign_ctx),
313 &(attest_data->rmm_realm_token_len));
314
315 if (ret == ATTEST_TOKEN_ERR_INVALID_STATE) {
316 /*
317 * Before this call the initial attestation token call
318 * (SMC_RSI_ATTEST_TOKEN_INIT) must have been executed
319 * successfully.
320 */
321 res->smc_res.x[0] = RSI_ERROR_STATE;
322 return;
323 } else if ((ret != ATTEST_TOKEN_ERR_COSE_SIGN_IN_PROGRESS) &&
324 (ret != ATTEST_TOKEN_ERR_SUCCESS)) {
325 /* Accessible only in case of failure during token signing */
Juan Pablo Condead871f92024-09-17 15:44:45 -0500326 ERROR("Realm token signing failed.\n");
327 res->smc_res.x[0] = RSI_ERROR_UNKNOWN;
328 return;
Soby Mathewf3622132024-07-19 07:31:40 +0100329 }
330
331 res->smc_res.x[0] = RSI_INCOMPLETE;
332
333 /*
334 * Return to RSI handler function after each iteration
335 * to check is there anything else to do (pending IRQ)
336 * or next signing iteration can be executed.
337 */
AlexeiFedorovea68b552023-10-03 11:11:47 +0100338 if (check_pending_irq()) {
339 res->action = UPDATE_REC_EXIT_TO_HOST;
340 rec_exit->exit_reason = RMI_EXIT_IRQ;
341 return;
AlexeiFedorov97844202023-04-27 15:17:35 +0100342 }
Soby Mathew9d2bd2b2024-10-03 12:29:10 +0100343
344#if ATTEST_EL3_TOKEN_SIGN
345 /*
346 * Pull response from EL3, find the corresponding rec granule
347 * and attestation context, and have the attestation library
348 * write the response to the context.
349 */
350 uintptr_t granule = 0UL;
351 int el3_token_sign_ret;
352
353 el3_token_sign_ret = attest_el3_token_sign_pull_response_from_el3(&granule);
354 if (el3_token_sign_ret == -EAGAIN) {
355 continue;
356 }
357
358 if (el3_token_sign_ret != 0) {
359 ERROR("Failed to pull response from EL3: %d\n", el3_token_sign_ret);
360 res->smc_res.x[0] = RSI_ERROR_UNKNOWN;
361 return;
362 }
363
364 el3_token_sign_ret = write_response_to_rec(rec, granule);
365 if (el3_token_sign_ret != 0) {
366 ERROR("Failed to write response to REC: %d\n", el3_token_sign_ret);
367 res->smc_res.x[0] = RSI_ERROR_UNKNOWN;
368 return;
369 }
370#endif
371 /*
372 * If there are no interrupts pending, then continue to pull
373 * requests from EL3 until this RECs request is done.
374 */
Soby Mathewb4c6df42022-11-09 11:13:29 +0000375 }
AlexeiFedorovea68b552023-10-03 11:11:47 +0100376
AlexeiFedorovea68b552023-10-03 11:11:47 +0100377 attest_token_continue_write_state(rec, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000378}
379
AlexeiFedorov97844202023-04-27 15:17:35 +0100380void handle_rsi_measurement_extend(struct rec *rec, struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000381{
382 struct granule *g_rd;
383 struct rd *rd;
384 unsigned long index;
385 unsigned long rd_addr;
386 size_t size;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000387 void *extend_measurement;
388 unsigned char *current_measurement;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000389
AlexeiFedorov97844202023-04-27 15:17:35 +0100390 assert(rec != NULL);
391
392 res->action = UPDATE_REC_RETURN_TO_REALM;
393
Soby Mathewb4c6df42022-11-09 11:13:29 +0000394 /*
395 * rd lock is acquired so that measurement cannot be updated
396 * simultaneously by another rec
397 */
398 rd_addr = granule_addr(rec->realm_info.g_rd);
399 g_rd = find_lock_granule(rd_addr, GRANULE_STATE_RD);
400
401 assert(g_rd != NULL);
402
Javier Almansa Sobrino2f717dd2024-02-12 20:49:46 +0000403 rd = buffer_granule_map(rec->realm_info.g_rd, SLOT_RD);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100404 assert(rd != NULL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000405
406 /*
407 * X1: index
408 * X2: size
409 * X3-X10: measurement value
410 */
411 index = rec->regs[1];
412
413 if ((index == RIM_MEASUREMENT_SLOT) ||
414 (index >= MEASUREMENT_SLOT_NR)) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100415 res->smc_res.x[0] = RSI_ERROR_INPUT;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000416 goto out_unmap_rd;
417 }
418
419 size = rec->regs[2];
420
421 if (size > MAX_EXTENDED_SIZE) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100422 res->smc_res.x[0] = RSI_ERROR_INPUT;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000423 goto out_unmap_rd;
424 }
425
426 extend_measurement = &rec->regs[3];
427 current_measurement = rd->measurement[index];
428
429 measurement_extend(rd->algorithm,
430 current_measurement,
431 extend_measurement,
432 size,
Juan Pablo Conded3084982024-09-18 17:05:49 -0500433 current_measurement,
434 MAX_MEASUREMENT_SIZE);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000435
AlexeiFedorov97844202023-04-27 15:17:35 +0100436 res->smc_res.x[0] = RSI_SUCCESS;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000437
438out_unmap_rd:
439 buffer_unmap(rd);
440 granule_unlock(g_rd);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000441}
442
AlexeiFedorov97844202023-04-27 15:17:35 +0100443void handle_rsi_measurement_read(struct rec *rec, struct rsi_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000444{
445 struct rd *rd;
446 unsigned long idx;
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100447 unsigned int i, cnt;
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200448 unsigned long *measurement_value_part;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000449
450 assert(rec != NULL);
451
AlexeiFedorov97844202023-04-27 15:17:35 +0100452 res->action = UPDATE_REC_RETURN_TO_REALM;
453
Soby Mathewb4c6df42022-11-09 11:13:29 +0000454 /* X1: Index */
455 idx = rec->regs[1];
456
457 if (idx >= MEASUREMENT_SLOT_NR) {
AlexeiFedorov97844202023-04-27 15:17:35 +0100458 res->smc_res.x[0] = RSI_ERROR_INPUT;
459 return;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000460 }
461
462 /*
463 * rd lock is acquired so that measurement cannot be updated
464 * simultaneously by another rec
465 */
466 granule_lock(rec->realm_info.g_rd, GRANULE_STATE_RD);
Javier Almansa Sobrino2f717dd2024-02-12 20:49:46 +0000467 rd = buffer_granule_map(rec->realm_info.g_rd, SLOT_RD);
AlexeiFedorov9a9062c2023-08-21 15:41:48 +0100468 assert(rd != NULL);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000469
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100470 /* Number of 8-bytes words in measurement */
AlexeiFedorov4faab852023-08-30 15:06:49 +0100471 cnt = (unsigned int)(measurement_get_size(rd->algorithm) /
472 sizeof(unsigned long));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000473
AlexeiFedorovea68b552023-10-03 11:11:47 +0100474 assert(cnt >= (SMC_RESULT_REGS - 1U));
Soby Mathew1ceb0082024-10-10 17:22:38 +0100475 assert(cnt < ARRAY_SIZE(rec->regs));
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200476
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100477 /* Copy the part of the measurement to res->smc_res.x[] */
AlexeiFedorovea68b552023-10-03 11:11:47 +0100478 for (i = 0U; i < (SMC_RESULT_REGS - 1U); i++) {
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200479 measurement_value_part = (unsigned long *)
480 &(rd->measurement[idx][i * sizeof(unsigned long)]);
481 res->smc_res.x[i + 1U] = *measurement_value_part;
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100482 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000483
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100484 /* Copy the rest of the measurement to the rec->regs[] */
485 for (; i < cnt; i++) {
Mate Toth-Pal59b52d02023-08-18 14:14:19 +0200486 measurement_value_part = (unsigned long *)
487 &(rd->measurement[idx][i * sizeof(unsigned long)]);
488 rec->regs[i + 1U] = *measurement_value_part;
AlexeiFedorovefe2aec2023-06-08 16:17:00 +0100489 }
490
491 /* Zero-initialize unused area */
492 for (; i < MAX_MEASUREMENT_WORDS; i++) {
493 rec->regs[i + 1U] = 0UL;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000494 }
495
496 buffer_unmap(rd);
497 granule_unlock(rec->realm_info.g_rd);
498
AlexeiFedorov97844202023-04-27 15:17:35 +0100499 res->smc_res.x[0] = RSI_SUCCESS;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000500}