blob: 3f009630c5b71367c6cfd370b25cdd1834049a27 [file] [log] [blame]
Maulik Patelad2f3db2023-05-17 15:41:36 +01001/*
2 * Copyright (c) 2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include "dpe_context_mngr.h"
9#include <assert.h>
10#include <string.h>
11#include "dice_protection_environment.h"
Maulik Patel2358bbb2023-07-21 10:56:56 +010012#include "dpe_certificate.h"
Maulik Patel58595d32023-06-22 10:08:53 +010013#include "dpe_crypto_interface.h"
Maulik Patelad2f3db2023-05-17 15:41:36 +010014#include "dpe_log.h"
Jamie Fox34681992023-09-04 18:14:06 +010015#include "dpe_plat.h"
Maulik Patelad2f3db2023-05-17 15:41:36 +010016#include "psa/crypto.h"
17
Maulik Pateldbfd5152023-05-30 17:02:42 +010018#ifdef DPE_TEST_MODE
19#define TEST_ROT_CDI_VAL { \
20 0xD2, 0x90, 0x66, 0x07, 0x2A, 0x2D, 0x2A, 0x00, \
21 0x91, 0x9D, 0xD9, 0x15, 0x14, 0xBE, 0x2D, 0xCC, \
22 0xA3, 0x9F, 0xDE, 0xC3, 0x35, 0x75, 0x84, 0x6E, \
23 0x4C, 0xB9, 0x28, 0xAC, 0x7A, 0x4E, 0X00, 0x7F \
24 }
25#endif /* DPE_TEST_MODE */
26
Maulik Patel58595d32023-06-22 10:08:53 +010027#define CONTEXT_DATA_MAX_SIZE sizeof(struct component_context_data_t)
28
Maulik Patelad2f3db2023-05-17 15:41:36 +010029static struct component_context_t component_ctx_array[MAX_NUM_OF_COMPONENTS];
30static struct layer_context_t layer_ctx_array[MAX_NUM_OF_LAYERS];
31
32static int get_free_component_context_index(void)
33{
34 int i;
35
36 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
37 if (!component_ctx_array[i].in_use) {
38 break;
39 }
40 }
41
42 if (i >= MAX_NUM_OF_COMPONENTS) {
43 /* No free index left in the array -- all used up! */
44 return -1;
45 }
46
47 return i;
48}
49
50static inline void invalidate_handle(int *handle)
51{
52 *handle = INVALID_HANDLE;
53}
54
55static dpe_error_t renew_nonce(int *handle)
56{
57 uint16_t nonce;
58
59 psa_status_t status = psa_generate_random((uint8_t *)&nonce, sizeof(nonce));
60 if (status != PSA_SUCCESS) {
61 return DPE_INTERNAL_ERROR;
62 }
63 *handle = SET_NONCE(*handle, nonce);
64
65 return DPE_NO_ERROR;
66}
67
68static dpe_error_t generate_new_handle(int *out_handle)
69{
70 /* Find the free component array element */
71 int free_component_idx = get_free_component_context_index();
72 if (free_component_idx < 0) {
73 return DPE_INSUFFICIENT_MEMORY;
74 }
75
76 *out_handle = SET_IDX(*out_handle, free_component_idx);
77
78 return renew_nonce(out_handle);
79}
80
81static void set_context_to_default(int i)
82{
83 component_ctx_array[i].in_use = false;
84 component_ctx_array[i].is_leaf = false;
85 component_ctx_array[i].nonce = INVALID_NONCE_VALUE;
86 component_ctx_array[i].parent_idx = INVALID_COMPONENT_IDX;
87 component_ctx_array[i].linked_layer_idx = INVALID_LAYER_IDX;
88 (void)memset(&component_ctx_array[i].data, 0, sizeof(struct component_context_data_t));
89 //TODO: Question: how to initialise MHU Id mapping?
90 /* Allow component to be derived by default */
91}
92
93static void invalidate_layer(int i)
94{
95 layer_ctx_array[i].state = LAYER_STATE_CLOSED;
96 layer_ctx_array[i].parent_layer_idx = INVALID_LAYER_IDX;
Maulik Patele6adc112023-08-18 14:21:51 +010097 (void)memset(&layer_ctx_array[i].attest_cdi_hash_input, 0,
98 sizeof(layer_ctx_array[i].attest_cdi_hash_input));
Maulik Patel58595d32023-06-22 10:08:53 +010099 (void)psa_destroy_key(layer_ctx_array[i].data.cdi_key_id);
100 (void)psa_destroy_key(layer_ctx_array[i].data.attest_key_id);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100101 (void)memset(&layer_ctx_array[i].data, 0, sizeof(struct layer_context_data_t));
102}
103
Maulik Patelad2f3db2023-05-17 15:41:36 +0100104static dpe_error_t copy_dice_input(struct component_context_t *dest_ctx,
105 const DiceInputValues *dice_inputs)
106{
107 size_t hash_len;
108 psa_status_t status;
109
110 memcpy(&dest_ctx->data.measurement_value, dice_inputs->code_hash,
111 DICE_HASH_SIZE);
112 memcpy(&dest_ctx->data.measurement_descriptor,
113 dice_inputs->code_descriptor,
114 dice_inputs->code_descriptor_size);
115
116 dest_ctx->data.measurement_descriptor_size =
117 dice_inputs->code_descriptor_size;
118
119 memcpy(&dest_ctx->data.signer_id, dice_inputs->authority_hash, DICE_HASH_SIZE);
120 memcpy(&dest_ctx->data.signer_id_descriptor,
121 dice_inputs->authority_descriptor,
122 dice_inputs->authority_descriptor_size);
123
124 dest_ctx->data.signer_id_descriptor_size =
125 dice_inputs->authority_descriptor_size;
126
127 if (dice_inputs->config_type == kDiceConfigTypeInline) {
128 /* Copy config_value */
129 memcpy(&dest_ctx->data.config_value, dice_inputs->config_value,
130 DICE_INLINE_CONFIG_SIZE);
131
132 } else {
133 /* Copy config descriptor */
134 memcpy(&dest_ctx->data.config_descriptor, dice_inputs->config_descriptor,
135 dice_inputs->config_descriptor_size);
136 dest_ctx->data.config_descriptor_size = dice_inputs->config_descriptor_size;
137
138 /* Calculate config value as hash of input config descriptor */
Maulik Patel2358bbb2023-07-21 10:56:56 +0100139 status = psa_hash_compute(DPE_HASH_ALG,
Maulik Patelad2f3db2023-05-17 15:41:36 +0100140 dice_inputs->config_descriptor,
141 dice_inputs->config_descriptor_size,
142 dest_ctx->data.config_value,
143 sizeof(dest_ctx->data.config_value),
144 &hash_len);
145
146 if (status != PSA_SUCCESS) {
147 return DPE_INTERNAL_ERROR;
148 }
149 }
150
151 dest_ctx->data.mode = dice_inputs->mode;
152 memcpy(&dest_ctx->data.hidden, dice_inputs->hidden, DICE_HIDDEN_SIZE);
153
154 return DPE_NO_ERROR;
155}
156
157static bool is_dice_input_valid(const DiceInputValues *dice_inputs)
158{
159 if ((dice_inputs->code_descriptor_size > DICE_CODE_DESCRIPTOR_MAX_SIZE) ||
160 (dice_inputs->authority_descriptor_size > DICE_AUTHORITY_DESCRIPTOR_MAX_SIZE) ||
161 (dice_inputs->config_descriptor_size > DICE_CONFIG_DESCRIPTOR_MAX_SIZE)) {
162 return false;
163 }
164
165 return true;
166}
167
168static bool is_input_handle_valid(int input_context_handle)
169{
170 uint16_t idx = GET_IDX(input_context_handle);
171 uint16_t nonce = GET_NONCE(input_context_handle);
172
173 /* Validate input handle id and nonce */
174 if ((idx >= MAX_NUM_OF_COMPONENTS) || (nonce == INVALID_NONCE_VALUE)) {
175 return false;
176 }
177
178 if (nonce == component_ctx_array[idx].nonce) {
179 return true;
180 }
181
182 return false;
183}
184
Maulik Patel58595d32023-06-22 10:08:53 +0100185/* Attest_CDI Input requires {measurement_value, config, authority, mode, hidden} in
186 * same order
187 */
188static psa_status_t get_component_data_for_attest_cdi(uint8_t *dest_buf,
189 size_t max_size,
190 size_t *dest_size,
191 const struct component_context_t *comp_ctx)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100192{
Maulik Patel58595d32023-06-22 10:08:53 +0100193 size_t out_size = 0;
194
195 if ((DICE_HASH_SIZE + DICE_INLINE_CONFIG_SIZE + DICE_HASH_SIZE +
196 sizeof(comp_ctx->data.mode) + DICE_HIDDEN_SIZE > max_size )) {
197 return PSA_ERROR_BUFFER_TOO_SMALL;
198 }
199
200 memcpy(&dest_buf[out_size], comp_ctx->data.measurement_value, DICE_HASH_SIZE);
201 out_size += DICE_HASH_SIZE;
202
203 memcpy(&dest_buf[out_size], comp_ctx->data.config_value, DICE_INLINE_CONFIG_SIZE);
204 out_size += DICE_INLINE_CONFIG_SIZE;
205
206 memcpy(&dest_buf[out_size], comp_ctx->data.signer_id, DICE_HASH_SIZE);
207 out_size += DICE_HASH_SIZE;
208
209 memcpy(&dest_buf[out_size], &comp_ctx->data.mode, sizeof(comp_ctx->data.mode));
210 out_size += sizeof(comp_ctx->data.mode);
211
212 memcpy(&dest_buf[out_size], comp_ctx->data.hidden, DICE_HIDDEN_SIZE);
213 out_size += DICE_HIDDEN_SIZE;
214
215 *dest_size = out_size;
216
217 return PSA_SUCCESS;
218}
219
220static psa_status_t compute_layer_cdi_attest_input(uint16_t curr_layer_idx)
221{
222 psa_status_t status;
223 uint8_t component_ctx_data[CONTEXT_DATA_MAX_SIZE];
224 size_t ctx_data_size, hash_len;
225 int idx;
226
227 psa_hash_operation_t hash_op = psa_hash_operation_init();
228 status = psa_hash_setup(&hash_op, DPE_HASH_ALG);
229 if (status != PSA_SUCCESS) {
230 return status;
231 }
232
233 //TODO:
234 /* How to combine measurements of multiple SW components into a single hash
235 * is not yet defined by the Open DICE profile. This implementation
236 * concatenates the data of all SW components which belong to the same layer
237 * and hash it.
238 */
239 for (idx = 0; idx < MAX_NUM_OF_COMPONENTS; idx++) {
240 if (component_ctx_array[idx].linked_layer_idx == curr_layer_idx) {
241 /* This component belongs to current layer */
242 /* Concatenate all context data for this component */
243 status = get_component_data_for_attest_cdi(component_ctx_data,
244 sizeof(component_ctx_data),
245 &ctx_data_size,
246 &component_ctx_array[idx]);
247 if (status != PSA_SUCCESS) {
248 return status;
249 }
250
251 status = psa_hash_update(&hash_op,
252 component_ctx_data,
253 ctx_data_size);
254 if (status != PSA_SUCCESS) {
255 return status;
256 }
257 }
258 }
259
Maulik Patele6adc112023-08-18 14:21:51 +0100260 if (layer_ctx_array[curr_layer_idx].data.attest_key_label_len != 0) {
261
262 status = psa_hash_update(&hash_op,
263 &layer_ctx_array[curr_layer_idx].data.attest_key_label[0],
264 layer_ctx_array[curr_layer_idx].data.attest_key_label_len);
265 if (status != PSA_SUCCESS) {
266 return status;
267 }
268 }
269
Maulik Patel58595d32023-06-22 10:08:53 +0100270 status = psa_hash_finish(&hash_op,
271 &layer_ctx_array[curr_layer_idx].attest_cdi_hash_input[0],
272 sizeof(layer_ctx_array[curr_layer_idx].attest_cdi_hash_input),
273 &hash_len);
274
275 assert(hash_len == DPE_HASH_ALG_SIZE);
276
277 return status;
278}
279
Maulik Patele6adc112023-08-18 14:21:51 +0100280static dpe_error_t create_layer_certificate(uint16_t layer_idx)
Maulik Patel58595d32023-06-22 10:08:53 +0100281{
Maulik Patel2358bbb2023-07-21 10:56:56 +0100282 uint16_t parent_layer_idx;
Maulik Patel58595d32023-06-22 10:08:53 +0100283 psa_status_t status;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100284 dpe_error_t err;
Maulik Patele6adc112023-08-18 14:21:51 +0100285 struct layer_context_t *layer_ctx, *parent_layer_ctx;
Maulik Patel58595d32023-06-22 10:08:53 +0100286
287 assert(layer_idx < MAX_NUM_OF_LAYERS);
Maulik Patele6adc112023-08-18 14:21:51 +0100288 layer_ctx = &layer_ctx_array[layer_idx];
289 /* Finalise the layer */
290 layer_ctx->state = LAYER_STATE_FINALISED;
291 parent_layer_idx = layer_ctx->parent_layer_idx;
292 assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
293 parent_layer_ctx = &layer_ctx_array[parent_layer_idx];
Maulik Patel58595d32023-06-22 10:08:53 +0100294
Maulik Patel2358bbb2023-07-21 10:56:56 +0100295 /* For RoT Layer, CDI and issuer seed values are calculated by BL1_1 */
Maulik Patele6adc112023-08-18 14:21:51 +0100296 if ((layer_idx != DPE_ROT_LAYER_IDX) &&
297 (!layer_ctx->is_external_pub_key_provided)) {
Maulik Patel58595d32023-06-22 10:08:53 +0100298
Maulik Patele6adc112023-08-18 14:21:51 +0100299 /* Except for RoT Layer with no external public key supplied */
Maulik Patel58595d32023-06-22 10:08:53 +0100300
301 status = compute_layer_cdi_attest_input(layer_idx);
302 if (status != PSA_SUCCESS) {
303 return DPE_INTERNAL_ERROR;
304 }
305
Maulik Patele6adc112023-08-18 14:21:51 +0100306 status = derive_attestation_cdi(layer_ctx, parent_layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100307 if (status != PSA_SUCCESS) {
308 return DPE_INTERNAL_ERROR;
309 }
310
Maulik Patele6adc112023-08-18 14:21:51 +0100311 status = derive_sealing_cdi(layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100312 if (status != PSA_SUCCESS) {
313 return DPE_INTERNAL_ERROR;
314 }
315 }
316
Maulik Patele6adc112023-08-18 14:21:51 +0100317 status = derive_wrapping_key(layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100318 if (status != PSA_SUCCESS) {
319 return DPE_INTERNAL_ERROR;
320 }
321
Maulik Patele6adc112023-08-18 14:21:51 +0100322 if (!layer_ctx->is_external_pub_key_provided) {
323 status = derive_attestation_key(layer_ctx);
324 if (status != PSA_SUCCESS) {
325 return DPE_INTERNAL_ERROR;
326 }
Maulik Patel58595d32023-06-22 10:08:53 +0100327 }
328
Maulik Patele6adc112023-08-18 14:21:51 +0100329 status = derive_id_from_public_key(layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100330 if (status != PSA_SUCCESS) {
331 return DPE_INTERNAL_ERROR;
332 }
333
Maulik Patel2358bbb2023-07-21 10:56:56 +0100334 err = encode_layer_certificate(layer_idx,
Maulik Patele6adc112023-08-18 14:21:51 +0100335 layer_ctx,
336 parent_layer_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100337 if (err != DPE_NO_ERROR) {
338 return err;
Maulik Patel58595d32023-06-22 10:08:53 +0100339 }
340
Maulik Patel2358bbb2023-07-21 10:56:56 +0100341 log_intermediate_certificate(layer_idx,
Maulik Patele6adc112023-08-18 14:21:51 +0100342 &layer_ctx->data.cert_buf[0],
343 layer_ctx->data.cert_buf_len);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100344
Maulik Patele6adc112023-08-18 14:21:51 +0100345 return store_layer_certificate(layer_ctx);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100346}
347
348static uint16_t open_new_layer(void)
349{
350 int i;
351
352 for (i = 0; i < MAX_NUM_OF_LAYERS; i++) {
353 if (layer_ctx_array[i].state == LAYER_STATE_CLOSED) {
354 layer_ctx_array[i].state = LAYER_STATE_OPEN;
355 return i;
356 }
357 }
358
Maulik Patel2358bbb2023-07-21 10:56:56 +0100359 //TODO: There is an open issue of layer creation as described below.
360 /* This is causing extra unintended layers to open. Since each layer
361 * has some context data and certificate buffer of 3k, it is
362 * causing RAM overflow. Hence until resoluton is reached, once all
363 * layers are opened, link new compenents to the last layer.
364 * ISSUE DESCRIPTION: We derive AP_BL31 as child of AP BL2 with create_certificate
365 * as true. Hence we finalize Platform layer. Then we derive AP_SPM as child of
366 * AP BL2, but since AP BL2 is finalised, we open new layer (Hypervisor layer).
367 * Then we derive AP SPx as child of AP BL2. Again, since AP BL2 is finalised,
368 * we open new layer! Here AP SPx should belong to same layer as AP SPM.
369 */
370 return MAX_NUM_OF_LAYERS - 1;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100371}
372
373static inline void link_layer(uint16_t child_layer, uint16_t parent_layer)
374{
375 layer_ctx_array[child_layer].parent_layer_idx = parent_layer;
376}
377
Maulik Patelad2f3db2023-05-17 15:41:36 +0100378static inline bool is_input_client_id_valid(int32_t client_id)
379{
380 //TODO: Waiting for implementation
381 return true;
382}
383
Maulik Patel2358bbb2023-07-21 10:56:56 +0100384static dpe_error_t assign_layer_to_context(struct component_context_t *new_ctx)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100385{
386 uint16_t new_layer_idx, parent_layer_idx;
387
388 assert(new_ctx->parent_idx < MAX_NUM_OF_COMPONENTS);
389
390 parent_layer_idx = component_ctx_array[new_ctx->parent_idx].linked_layer_idx;
391 assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
392
393 if (layer_ctx_array[parent_layer_idx].state == LAYER_STATE_FINALISED) {
394 /* Parent comp's layer of new child is finalised; open a new layer */
395 new_layer_idx = open_new_layer();
Maulik Patel2358bbb2023-07-21 10:56:56 +0100396 if (new_layer_idx == INVALID_LAYER_IDX) {
397 return DPE_INTERNAL_ERROR;
398 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100399 /* Link this context to the new layer */
400 new_ctx->linked_layer_idx = new_layer_idx;
401 /* New layer's parent is current layer */
402 link_layer(new_layer_idx, parent_layer_idx);
403
404 } else {
405 /* Parent comp's layer is not yet finalised, link
406 * new component to the same layer as parent
407 */
408 new_ctx->linked_layer_idx = parent_layer_idx;
409 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100410
411 return DPE_NO_ERROR;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100412}
413
Jamie Fox34681992023-09-04 18:14:06 +0100414/**
415 * \brief Create a root of trust component context.
416 *
417 * \param[out] rot_ctx_handle A new context handle for the RoT context.
418 *
419 * \return Returns error code of type dpe_error_t
420 */
421static dpe_error_t create_rot_context(int *rot_ctx_handle)
422{
Maulik Pateldbfd5152023-05-30 17:02:42 +0100423#ifdef DPE_TEST_MODE
424 uint8_t rot_cdi_input[DICE_CDI_SIZE] = TEST_ROT_CDI_VAL;
425#else
Jamie Fox34681992023-09-04 18:14:06 +0100426 int ret;
Jamie Fox34681992023-09-04 18:14:06 +0100427 uint8_t rot_cdi_input[DICE_CDI_SIZE];
Maulik Pateldbfd5152023-05-30 17:02:42 +0100428#endif /* DPE_TEST_MODE */
429 psa_status_t status;
Jamie Fox34681992023-09-04 18:14:06 +0100430 struct component_context_t *rot_comp_ctx = &component_ctx_array[0];
431 struct layer_context_t *rot_layer_ctx = &layer_ctx_array[DPE_ROT_LAYER_IDX];
432
433 /* Open RoT layer */
434 rot_layer_ctx->state = LAYER_STATE_OPEN;
435 /* Parent is same as child for RoT layer */
436 rot_layer_ctx->parent_layer_idx = DPE_ROT_LAYER_IDX;
437
Maulik Pateldbfd5152023-05-30 17:02:42 +0100438#ifndef DPE_TEST_MODE
Jamie Fox34681992023-09-04 18:14:06 +0100439 /* Get the RoT CDI input for the RoT layer */
440 ret = dpe_plat_get_rot_cdi(&rot_cdi_input[0],
441 sizeof(rot_cdi_input));
442 if (ret != 0) {
443 return DPE_INTERNAL_ERROR;
444 }
Maulik Pateldbfd5152023-05-30 17:02:42 +0100445#endif /* DPE_TEST_MODE */
Jamie Fox34681992023-09-04 18:14:06 +0100446
447 /* Import the CDI key for the RoT layer */
448 status = create_layer_cdi_key(&layer_ctx_array[DPE_ROT_LAYER_IDX],
449 &rot_cdi_input[0],
450 sizeof(rot_cdi_input));
451 if (status != PSA_SUCCESS) {
452 return DPE_INTERNAL_ERROR;
453 }
454
455 /* Init RoT context, ready to be derived in next call to DeriveChild */
456 rot_comp_ctx->in_use = true;
457 rot_comp_ctx->nonce = 0;
458 /* Parent is same as child for RoT context */
459 rot_comp_ctx->parent_idx = 0;
460 /* Link context to RoT Layer */
461 rot_comp_ctx->linked_layer_idx = DPE_ROT_LAYER_IDX;
462 rot_comp_ctx->expected_mhu_id = 0;
Jamie Fox34681992023-09-04 18:14:06 +0100463 *rot_ctx_handle = 0; /* index = 0, nonce = 0 */
464
465 return DPE_NO_ERROR;
466}
467
468dpe_error_t initialise_context_mngr(int *rot_ctx_handle)
469{
470 int i;
471
472 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
473 set_context_to_default(i);
474 }
475
476 for (i = 0; i < MAX_NUM_OF_LAYERS; i++) {
477 invalidate_layer(i);
478 }
479
480 return create_rot_context(rot_ctx_handle);
481}
482
Maulik Patelad2f3db2023-05-17 15:41:36 +0100483dpe_error_t derive_child_request(int input_ctx_handle,
484 bool retain_parent_context,
485 bool allow_child_to_derive,
486 bool create_certificate,
487 const DiceInputValues *dice_inputs,
488 int32_t client_id,
489 int *new_child_ctx_handle,
490 int *new_parent_ctx_handle)
491{
Maulik Patel58595d32023-06-22 10:08:53 +0100492 dpe_error_t err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100493 struct component_context_t *child_ctx, *parent_ctx, *new_ctx;
494 uint16_t input_child_idx, input_parent_idx;
495
Maulik Patelad2f3db2023-05-17 15:41:36 +0100496 log_derive_child(input_ctx_handle, retain_parent_context,
497 allow_child_to_derive, create_certificate, dice_inputs,
498 client_id);
499
Maulik Pateldbfd5152023-05-30 17:02:42 +0100500#ifdef DPE_TEST_MODE
501 if (input_ctx_handle == 0) {
502 /* Deriving RoT context for tests */
503 err = create_rot_context(&input_ctx_handle);
504 if (err != DPE_NO_ERROR) {
505 return err;
506 }
507 }
508#endif /* DPE_TEST_MODE */
509
Maulik Patelad2f3db2023-05-17 15:41:36 +0100510 /* Validate dice inputs */
511 if (!is_dice_input_valid(dice_inputs)) {
512 return DPE_INVALID_ARGUMENT;
513 }
514
515 /* Validate input handle */
516 if (!is_input_handle_valid(input_ctx_handle)) {
517 return DPE_INVALID_ARGUMENT;
518 }
519 /* Get child component index from the input handle */
520 input_child_idx = GET_IDX(input_ctx_handle);
521 /* Get parent index of input referenced child component */
522 input_parent_idx = component_ctx_array[input_child_idx].parent_idx;
523
524 /* Below check is for safety only; It should not happen
525 * input_child_idx is already checked above in is_input_handle_valid()
526 */
527 assert(input_parent_idx < MAX_NUM_OF_COMPONENTS);
528
529 child_ctx = &component_ctx_array[input_child_idx];
530 parent_ctx = &component_ctx_array[input_parent_idx];
531
532 //TODO: Question: how to get mhu id of incoming request?
533 if (!is_input_client_id_valid(client_id)) {
534 return DPE_INVALID_ARGUMENT;
535 }
536
537 /* Copy dice input to the child component context */
Maulik Patel58595d32023-06-22 10:08:53 +0100538 err = copy_dice_input(child_ctx, dice_inputs);
539 if (err != DPE_NO_ERROR) {
540 return err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100541 }
542
543 if (create_certificate) {
Maulik Patele6adc112023-08-18 14:21:51 +0100544 err = create_layer_certificate(child_ctx->linked_layer_idx);
Maulik Patel58595d32023-06-22 10:08:53 +0100545 if (err != DPE_NO_ERROR) {
546 return err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100547 }
548 }
549
550 if (allow_child_to_derive) {
551 /* Generate new handle for child for subsequent requests */
552 if (generate_new_handle(new_child_ctx_handle) != DPE_NO_ERROR) {
553 return DPE_INTERNAL_ERROR;
554 }
555 /* Update the component context array element as pointed by newly generated handle */
556 new_ctx = &component_ctx_array[GET_IDX(*new_child_ctx_handle)];
557 /* Update nonce in new child component context */
558 new_ctx->nonce = GET_NONCE(*new_child_ctx_handle);
559 /* Update parent idx in new child component context */
560 new_ctx->parent_idx = input_child_idx;
561 /* Mark new child component index as in use */
562 new_ctx->in_use = true;
Jamie Fox34681992023-09-04 18:14:06 +0100563 err = assign_layer_to_context(new_ctx);
564 if (err != DPE_NO_ERROR) {
565 return err;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100566 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100567 } else {
568 /* Child not deriving any children */
569 /* Tag this component as a leaf */
570 child_ctx->is_leaf = true;
571 invalidate_handle(new_child_ctx_handle);
572 /* Renew nonce of child context so it cannot be used again */
573 child_ctx->nonce = INVALID_NONCE_VALUE;
574 }
575
576 if (retain_parent_context) {
577 /* Parent deriving multiple children */
578 /* Generate new handle for child for the same parent for subsequent requests */
579 if (generate_new_handle(new_parent_ctx_handle) != DPE_NO_ERROR) {
580 return DPE_INTERNAL_ERROR;
581 }
582 /* Update the component context array element as pointed by newly generated handle */
583 new_ctx = &component_ctx_array[GET_IDX(*new_parent_ctx_handle)];
584 /* Update nonce in new child component context */
585 new_ctx->nonce = GET_NONCE(*new_parent_ctx_handle);
586 /* Update parent idx in new child component context */
587 new_ctx->parent_idx = input_parent_idx;
588 /* Mark new child component index as in use */
589 new_ctx->in_use = true;
Jamie Fox34681992023-09-04 18:14:06 +0100590 err = assign_layer_to_context(new_ctx);
591 if (err != DPE_NO_ERROR) {
592 return err;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100593 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100594 } else {
595 /* Parent not deriving any more children */
596 /* No need to return parent handle */
597 invalidate_handle(new_parent_ctx_handle);
598 /* Renew nonce of parent context so it cannot be used again */
599 parent_ctx->nonce = INVALID_NONCE_VALUE;
600 }
601
602 return DPE_NO_ERROR;
603}
Maulik Patel54d65f72023-06-28 13:04:36 +0100604
605dpe_error_t destroy_context_request(int input_ctx_handle,
606 bool destroy_recursively)
607{
608 uint16_t input_ctx_idx, linked_layer_idx;
609 int i;
610 bool is_layer_empty;
611
612 log_destroy_context(input_ctx_handle, destroy_recursively);
613
614 /* Get child component index and linked layer from the input handle */
615 input_ctx_idx = GET_IDX(input_ctx_handle);
616
Maulik Patel54d65f72023-06-28 13:04:36 +0100617 /* Validate input handle */
618 if (!is_input_handle_valid(input_ctx_handle)) {
619 return DPE_INVALID_ARGUMENT;
620 }
621 linked_layer_idx = component_ctx_array[input_ctx_idx].linked_layer_idx;
622
Jamie Fox34681992023-09-04 18:14:06 +0100623#ifndef DPE_TEST_MODE
Maulik Patel54d65f72023-06-28 13:04:36 +0100624 if (linked_layer_idx <= DPE_DESTROY_CONTEXT_THRESHOLD_LAYER_IDX) {
625 /* All layers till hypervisor cannot be destroyed dynamically */
626 return DPE_INVALID_ARGUMENT;
627 }
Jamie Fox34681992023-09-04 18:14:06 +0100628#endif /* !DPE_TEST_MODE */
Maulik Patel54d65f72023-06-28 13:04:36 +0100629
630
631 if (!destroy_recursively) {
632 set_context_to_default(input_ctx_idx);
633 } else {
634 //TODO: To be implemented
635 }
636
637 assert(linked_layer_idx < MAX_NUM_OF_LAYERS);
638
639 /* Close the layer if all of its contexts are destroyed */
640 is_layer_empty = true;
641 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
642 if (component_ctx_array[i].linked_layer_idx == linked_layer_idx) {
643 /* There are active component context in the layer */
644 is_layer_empty = false;
645 break;
646 }
647 }
648
649 if (is_layer_empty) {
650 invalidate_layer(linked_layer_idx);
651 }
652
653 return DPE_NO_ERROR;
654}
Maulik Patel2358bbb2023-07-21 10:56:56 +0100655
656struct component_context_t* get_component_if_linked_to_layer(uint16_t layer_idx,
657 uint16_t component_idx)
658{
659 /* Safety case */
660 if (component_idx >= MAX_NUM_OF_COMPONENTS) {
661 return NULL;
662 }
663
664 if (component_ctx_array[component_idx].linked_layer_idx == layer_idx) {
665 return &component_ctx_array[component_idx];
666 } else {
667 return NULL;
668 }
669}
670
Maulik Patele6adc112023-08-18 14:21:51 +0100671struct layer_context_t* get_layer_ctx_ptr(uint16_t layer_idx)
672{
673 /* Safety case */
674 if (layer_idx >= MAX_NUM_OF_LAYERS) {
675 return NULL;
676 }
677
678 return &layer_ctx_array[layer_idx];
679}
680
681dpe_error_t certify_key_request(int input_ctx_handle,
682 bool retain_context,
683 const uint8_t *public_key,
684 size_t public_key_size,
685 const uint8_t *label,
686 size_t label_size,
687 uint8_t *certificate_chain_buf,
688 size_t certificate_chain_buf_size,
689 size_t *certificate_chain_actual_size,
690 uint8_t *derived_public_key_buf,
691 size_t derived_public_key_buf_size,
692 size_t *derived_public_key_actual_size,
693 int *new_context_handle)
694{
695 uint16_t input_ctx_idx, input_layer_idx, parent_layer_idx;
696 dpe_error_t err;
697 psa_status_t status;
698 struct layer_context_t *parent_layer_ctx, *layer_ctx;
699
700 log_certify_key(input_ctx_handle, retain_context, public_key, public_key_size,
701 label, label_size);
702
703 /* Validate input handle */
704 if (!is_input_handle_valid(input_ctx_handle)) {
705 return DPE_INVALID_ARGUMENT;
706 }
707
708 if (label_size > DPE_EXTERNAL_LABEL_MAX_SIZE) {
709 return DPE_INVALID_ARGUMENT;
710 }
711
712 /* Get component index from the input handle */
713 input_ctx_idx = GET_IDX(input_ctx_handle);
714 /* Get current linked layer idx */
715 input_layer_idx = component_ctx_array[input_ctx_idx].linked_layer_idx;
716 assert(input_layer_idx < MAX_NUM_OF_LAYERS);
717
718 layer_ctx = &layer_ctx_array[input_layer_idx];
719 if (public_key_size > sizeof(layer_ctx->data.attest_pub_key)) {
720 return DPE_INVALID_ARGUMENT;
721 }
722
723 if ((public_key_size > 0) && (public_key != NULL)) {
724 layer_ctx->is_external_pub_key_provided = true;
725 /* Copy the public key provided */
726 memcpy(&layer_ctx->data.attest_pub_key[0],
727 public_key,
728 public_key_size);
729 layer_ctx->data.attest_pub_key_len = public_key_size;
730
731 /* If public key is provided, then provided label (if any) is ignored */
732 layer_ctx->data.attest_key_label_len = 0;
733
734 } else {
735 /* No external public key is provided */
736 layer_ctx->is_external_pub_key_provided = false;
737
738 if ((label_size > 0) && (label != NULL)) {
739 /* Copy the label provided */
740 memcpy(&layer_ctx->data.attest_key_label[0],
741 label,
742 label_size);
743 layer_ctx->data.attest_key_label_len = label_size;
744
745 } else {
746 layer_ctx->data.attest_key_label_len = 0;
747 }
748 }
749
750 /* Correct layer should already be assigned in last call of
751 * derive child command
752 */
753 /* Finalise the current layer & create leaf certificate */
754 err = create_layer_certificate(input_layer_idx);
755 if (err != DPE_NO_ERROR) {
756 return err;
757 }
758
759 /* Get parent layer derived public key to verify the certificate signature */
760 parent_layer_idx = layer_ctx_array[input_layer_idx].parent_layer_idx;
761 assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
762 parent_layer_ctx = &layer_ctx_array[parent_layer_idx];
763
764 if (derived_public_key_buf_size < sizeof(parent_layer_ctx->data.attest_pub_key)) {
765 return DPE_INVALID_ARGUMENT;
766 }
767
768 memcpy(derived_public_key_buf,
769 &parent_layer_ctx->data.attest_pub_key[0],
770 parent_layer_ctx->data.attest_pub_key_len);
771 *derived_public_key_actual_size = parent_layer_ctx->data.attest_pub_key_len;
772
773 /* Get certificate chain */
774 err = get_certificate_chain(input_layer_idx,
775 certificate_chain_buf,
776 certificate_chain_buf_size,
777 certificate_chain_actual_size);
778 if (err != DPE_NO_ERROR) {
779 return err;
780 }
781
782 log_certificate_chain(certificate_chain_buf, *certificate_chain_actual_size);
783
784 /* Renew handle for the same context */
785 *new_context_handle = input_ctx_handle;
786 status = renew_nonce(new_context_handle);
787 if (status != PSA_SUCCESS) {
788 return DPE_INTERNAL_ERROR;
789 }
790 component_ctx_array[input_ctx_idx].nonce = GET_NONCE(*new_context_handle);
791
792 /* Clear the context label and key contents */
793 memset(&layer_ctx->data.attest_key_label[0], 0u, layer_ctx->data.attest_key_label_len);
794 memset(&layer_ctx->data.attest_pub_key[0], 0u, layer_ctx->data.attest_pub_key_len);
795
796 return DPE_NO_ERROR;
797}