blob: c067d97c39d88d868fe3a8ee9e71b9c8871a5f00 [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 Patel58595d32023-06-22 10:08:53 +010018#define CONTEXT_DATA_MAX_SIZE sizeof(struct component_context_data_t)
19
Maulik Patelad2f3db2023-05-17 15:41:36 +010020static struct component_context_t component_ctx_array[MAX_NUM_OF_COMPONENTS];
21static struct layer_context_t layer_ctx_array[MAX_NUM_OF_LAYERS];
22
23static int get_free_component_context_index(void)
24{
25 int i;
26
27 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
28 if (!component_ctx_array[i].in_use) {
29 break;
30 }
31 }
32
33 if (i >= MAX_NUM_OF_COMPONENTS) {
34 /* No free index left in the array -- all used up! */
35 return -1;
36 }
37
38 return i;
39}
40
41static inline void invalidate_handle(int *handle)
42{
43 *handle = INVALID_HANDLE;
44}
45
46static dpe_error_t renew_nonce(int *handle)
47{
48 uint16_t nonce;
49
50 psa_status_t status = psa_generate_random((uint8_t *)&nonce, sizeof(nonce));
51 if (status != PSA_SUCCESS) {
52 return DPE_INTERNAL_ERROR;
53 }
54 *handle = SET_NONCE(*handle, nonce);
55
56 return DPE_NO_ERROR;
57}
58
59static dpe_error_t generate_new_handle(int *out_handle)
60{
61 /* Find the free component array element */
62 int free_component_idx = get_free_component_context_index();
63 if (free_component_idx < 0) {
64 return DPE_INSUFFICIENT_MEMORY;
65 }
66
67 *out_handle = SET_IDX(*out_handle, free_component_idx);
68
69 return renew_nonce(out_handle);
70}
71
72static void set_context_to_default(int i)
73{
74 component_ctx_array[i].in_use = false;
75 component_ctx_array[i].is_leaf = false;
76 component_ctx_array[i].nonce = INVALID_NONCE_VALUE;
77 component_ctx_array[i].parent_idx = INVALID_COMPONENT_IDX;
78 component_ctx_array[i].linked_layer_idx = INVALID_LAYER_IDX;
79 (void)memset(&component_ctx_array[i].data, 0, sizeof(struct component_context_data_t));
80 //TODO: Question: how to initialise MHU Id mapping?
81 /* Allow component to be derived by default */
82}
83
84static void invalidate_layer(int i)
85{
86 layer_ctx_array[i].state = LAYER_STATE_CLOSED;
87 layer_ctx_array[i].parent_layer_idx = INVALID_LAYER_IDX;
Maulik Patele6adc112023-08-18 14:21:51 +010088 (void)memset(&layer_ctx_array[i].attest_cdi_hash_input, 0,
89 sizeof(layer_ctx_array[i].attest_cdi_hash_input));
Maulik Patel58595d32023-06-22 10:08:53 +010090 (void)psa_destroy_key(layer_ctx_array[i].data.cdi_key_id);
91 (void)psa_destroy_key(layer_ctx_array[i].data.attest_key_id);
Maulik Patelad2f3db2023-05-17 15:41:36 +010092 (void)memset(&layer_ctx_array[i].data, 0, sizeof(struct layer_context_data_t));
93}
94
Maulik Patelad2f3db2023-05-17 15:41:36 +010095static dpe_error_t copy_dice_input(struct component_context_t *dest_ctx,
96 const DiceInputValues *dice_inputs)
97{
98 size_t hash_len;
99 psa_status_t status;
100
101 memcpy(&dest_ctx->data.measurement_value, dice_inputs->code_hash,
102 DICE_HASH_SIZE);
103 memcpy(&dest_ctx->data.measurement_descriptor,
104 dice_inputs->code_descriptor,
105 dice_inputs->code_descriptor_size);
106
107 dest_ctx->data.measurement_descriptor_size =
108 dice_inputs->code_descriptor_size;
109
110 memcpy(&dest_ctx->data.signer_id, dice_inputs->authority_hash, DICE_HASH_SIZE);
111 memcpy(&dest_ctx->data.signer_id_descriptor,
112 dice_inputs->authority_descriptor,
113 dice_inputs->authority_descriptor_size);
114
115 dest_ctx->data.signer_id_descriptor_size =
116 dice_inputs->authority_descriptor_size;
117
118 if (dice_inputs->config_type == kDiceConfigTypeInline) {
119 /* Copy config_value */
120 memcpy(&dest_ctx->data.config_value, dice_inputs->config_value,
121 DICE_INLINE_CONFIG_SIZE);
122
123 } else {
124 /* Copy config descriptor */
125 memcpy(&dest_ctx->data.config_descriptor, dice_inputs->config_descriptor,
126 dice_inputs->config_descriptor_size);
127 dest_ctx->data.config_descriptor_size = dice_inputs->config_descriptor_size;
128
129 /* Calculate config value as hash of input config descriptor */
Maulik Patel2358bbb2023-07-21 10:56:56 +0100130 status = psa_hash_compute(DPE_HASH_ALG,
Maulik Patelad2f3db2023-05-17 15:41:36 +0100131 dice_inputs->config_descriptor,
132 dice_inputs->config_descriptor_size,
133 dest_ctx->data.config_value,
134 sizeof(dest_ctx->data.config_value),
135 &hash_len);
136
137 if (status != PSA_SUCCESS) {
138 return DPE_INTERNAL_ERROR;
139 }
140 }
141
142 dest_ctx->data.mode = dice_inputs->mode;
143 memcpy(&dest_ctx->data.hidden, dice_inputs->hidden, DICE_HIDDEN_SIZE);
144
145 return DPE_NO_ERROR;
146}
147
148static bool is_dice_input_valid(const DiceInputValues *dice_inputs)
149{
150 if ((dice_inputs->code_descriptor_size > DICE_CODE_DESCRIPTOR_MAX_SIZE) ||
151 (dice_inputs->authority_descriptor_size > DICE_AUTHORITY_DESCRIPTOR_MAX_SIZE) ||
152 (dice_inputs->config_descriptor_size > DICE_CONFIG_DESCRIPTOR_MAX_SIZE)) {
153 return false;
154 }
155
156 return true;
157}
158
159static bool is_input_handle_valid(int input_context_handle)
160{
161 uint16_t idx = GET_IDX(input_context_handle);
162 uint16_t nonce = GET_NONCE(input_context_handle);
163
164 /* Validate input handle id and nonce */
165 if ((idx >= MAX_NUM_OF_COMPONENTS) || (nonce == INVALID_NONCE_VALUE)) {
166 return false;
167 }
168
169 if (nonce == component_ctx_array[idx].nonce) {
170 return true;
171 }
172
173 return false;
174}
175
Maulik Patel58595d32023-06-22 10:08:53 +0100176/* Attest_CDI Input requires {measurement_value, config, authority, mode, hidden} in
177 * same order
178 */
179static psa_status_t get_component_data_for_attest_cdi(uint8_t *dest_buf,
180 size_t max_size,
181 size_t *dest_size,
182 const struct component_context_t *comp_ctx)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100183{
Maulik Patel58595d32023-06-22 10:08:53 +0100184 size_t out_size = 0;
185
186 if ((DICE_HASH_SIZE + DICE_INLINE_CONFIG_SIZE + DICE_HASH_SIZE +
187 sizeof(comp_ctx->data.mode) + DICE_HIDDEN_SIZE > max_size )) {
188 return PSA_ERROR_BUFFER_TOO_SMALL;
189 }
190
191 memcpy(&dest_buf[out_size], comp_ctx->data.measurement_value, DICE_HASH_SIZE);
192 out_size += DICE_HASH_SIZE;
193
194 memcpy(&dest_buf[out_size], comp_ctx->data.config_value, DICE_INLINE_CONFIG_SIZE);
195 out_size += DICE_INLINE_CONFIG_SIZE;
196
197 memcpy(&dest_buf[out_size], comp_ctx->data.signer_id, DICE_HASH_SIZE);
198 out_size += DICE_HASH_SIZE;
199
200 memcpy(&dest_buf[out_size], &comp_ctx->data.mode, sizeof(comp_ctx->data.mode));
201 out_size += sizeof(comp_ctx->data.mode);
202
203 memcpy(&dest_buf[out_size], comp_ctx->data.hidden, DICE_HIDDEN_SIZE);
204 out_size += DICE_HIDDEN_SIZE;
205
206 *dest_size = out_size;
207
208 return PSA_SUCCESS;
209}
210
211static psa_status_t compute_layer_cdi_attest_input(uint16_t curr_layer_idx)
212{
213 psa_status_t status;
214 uint8_t component_ctx_data[CONTEXT_DATA_MAX_SIZE];
215 size_t ctx_data_size, hash_len;
216 int idx;
217
218 psa_hash_operation_t hash_op = psa_hash_operation_init();
219 status = psa_hash_setup(&hash_op, DPE_HASH_ALG);
220 if (status != PSA_SUCCESS) {
221 return status;
222 }
223
224 //TODO:
225 /* How to combine measurements of multiple SW components into a single hash
226 * is not yet defined by the Open DICE profile. This implementation
227 * concatenates the data of all SW components which belong to the same layer
228 * and hash it.
229 */
230 for (idx = 0; idx < MAX_NUM_OF_COMPONENTS; idx++) {
231 if (component_ctx_array[idx].linked_layer_idx == curr_layer_idx) {
232 /* This component belongs to current layer */
233 /* Concatenate all context data for this component */
234 status = get_component_data_for_attest_cdi(component_ctx_data,
235 sizeof(component_ctx_data),
236 &ctx_data_size,
237 &component_ctx_array[idx]);
238 if (status != PSA_SUCCESS) {
239 return status;
240 }
241
242 status = psa_hash_update(&hash_op,
243 component_ctx_data,
244 ctx_data_size);
245 if (status != PSA_SUCCESS) {
246 return status;
247 }
248 }
249 }
250
Maulik Patele6adc112023-08-18 14:21:51 +0100251 if (layer_ctx_array[curr_layer_idx].data.attest_key_label_len != 0) {
252
253 status = psa_hash_update(&hash_op,
254 &layer_ctx_array[curr_layer_idx].data.attest_key_label[0],
255 layer_ctx_array[curr_layer_idx].data.attest_key_label_len);
256 if (status != PSA_SUCCESS) {
257 return status;
258 }
259 }
260
Maulik Patel58595d32023-06-22 10:08:53 +0100261 status = psa_hash_finish(&hash_op,
262 &layer_ctx_array[curr_layer_idx].attest_cdi_hash_input[0],
263 sizeof(layer_ctx_array[curr_layer_idx].attest_cdi_hash_input),
264 &hash_len);
265
266 assert(hash_len == DPE_HASH_ALG_SIZE);
267
268 return status;
269}
270
Maulik Patele6adc112023-08-18 14:21:51 +0100271static dpe_error_t create_layer_certificate(uint16_t layer_idx)
Maulik Patel58595d32023-06-22 10:08:53 +0100272{
Maulik Patel2358bbb2023-07-21 10:56:56 +0100273 uint16_t parent_layer_idx;
Maulik Patel58595d32023-06-22 10:08:53 +0100274 psa_status_t status;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100275 dpe_error_t err;
Maulik Patele6adc112023-08-18 14:21:51 +0100276 struct layer_context_t *layer_ctx, *parent_layer_ctx;
Maulik Patel58595d32023-06-22 10:08:53 +0100277
278 assert(layer_idx < MAX_NUM_OF_LAYERS);
Maulik Patele6adc112023-08-18 14:21:51 +0100279 layer_ctx = &layer_ctx_array[layer_idx];
280 /* Finalise the layer */
281 layer_ctx->state = LAYER_STATE_FINALISED;
282 parent_layer_idx = layer_ctx->parent_layer_idx;
283 assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
284 parent_layer_ctx = &layer_ctx_array[parent_layer_idx];
Maulik Patel58595d32023-06-22 10:08:53 +0100285
Maulik Patel2358bbb2023-07-21 10:56:56 +0100286 /* For RoT Layer, CDI and issuer seed values are calculated by BL1_1 */
Maulik Patele6adc112023-08-18 14:21:51 +0100287 if ((layer_idx != DPE_ROT_LAYER_IDX) &&
288 (!layer_ctx->is_external_pub_key_provided)) {
Maulik Patel58595d32023-06-22 10:08:53 +0100289
Maulik Patele6adc112023-08-18 14:21:51 +0100290 /* Except for RoT Layer with no external public key supplied */
Maulik Patel58595d32023-06-22 10:08:53 +0100291
292 status = compute_layer_cdi_attest_input(layer_idx);
293 if (status != PSA_SUCCESS) {
294 return DPE_INTERNAL_ERROR;
295 }
296
Maulik Patele6adc112023-08-18 14:21:51 +0100297 status = derive_attestation_cdi(layer_ctx, parent_layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100298 if (status != PSA_SUCCESS) {
299 return DPE_INTERNAL_ERROR;
300 }
301
Maulik Patele6adc112023-08-18 14:21:51 +0100302 status = derive_sealing_cdi(layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100303 if (status != PSA_SUCCESS) {
304 return DPE_INTERNAL_ERROR;
305 }
306 }
307
Maulik Patele6adc112023-08-18 14:21:51 +0100308 status = derive_wrapping_key(layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100309 if (status != PSA_SUCCESS) {
310 return DPE_INTERNAL_ERROR;
311 }
312
Maulik Patele6adc112023-08-18 14:21:51 +0100313 if (!layer_ctx->is_external_pub_key_provided) {
314 status = derive_attestation_key(layer_ctx);
315 if (status != PSA_SUCCESS) {
316 return DPE_INTERNAL_ERROR;
317 }
Maulik Patel58595d32023-06-22 10:08:53 +0100318 }
319
Maulik Patele6adc112023-08-18 14:21:51 +0100320 status = derive_id_from_public_key(layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100321 if (status != PSA_SUCCESS) {
322 return DPE_INTERNAL_ERROR;
323 }
324
Maulik Patel2358bbb2023-07-21 10:56:56 +0100325 err = encode_layer_certificate(layer_idx,
Maulik Patele6adc112023-08-18 14:21:51 +0100326 layer_ctx,
327 parent_layer_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100328 if (err != DPE_NO_ERROR) {
329 return err;
Maulik Patel58595d32023-06-22 10:08:53 +0100330 }
331
Maulik Patel2358bbb2023-07-21 10:56:56 +0100332 log_intermediate_certificate(layer_idx,
Maulik Patele6adc112023-08-18 14:21:51 +0100333 &layer_ctx->data.cert_buf[0],
334 layer_ctx->data.cert_buf_len);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100335
Maulik Patele6adc112023-08-18 14:21:51 +0100336 return store_layer_certificate(layer_ctx);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100337}
338
339static uint16_t open_new_layer(void)
340{
341 int i;
342
343 for (i = 0; i < MAX_NUM_OF_LAYERS; i++) {
344 if (layer_ctx_array[i].state == LAYER_STATE_CLOSED) {
345 layer_ctx_array[i].state = LAYER_STATE_OPEN;
346 return i;
347 }
348 }
349
Maulik Patel2358bbb2023-07-21 10:56:56 +0100350 //TODO: There is an open issue of layer creation as described below.
351 /* This is causing extra unintended layers to open. Since each layer
352 * has some context data and certificate buffer of 3k, it is
353 * causing RAM overflow. Hence until resoluton is reached, once all
354 * layers are opened, link new compenents to the last layer.
355 * ISSUE DESCRIPTION: We derive AP_BL31 as child of AP BL2 with create_certificate
356 * as true. Hence we finalize Platform layer. Then we derive AP_SPM as child of
357 * AP BL2, but since AP BL2 is finalised, we open new layer (Hypervisor layer).
358 * Then we derive AP SPx as child of AP BL2. Again, since AP BL2 is finalised,
359 * we open new layer! Here AP SPx should belong to same layer as AP SPM.
360 */
361 return MAX_NUM_OF_LAYERS - 1;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100362}
363
364static inline void link_layer(uint16_t child_layer, uint16_t parent_layer)
365{
366 layer_ctx_array[child_layer].parent_layer_idx = parent_layer;
367}
368
Maulik Patelad2f3db2023-05-17 15:41:36 +0100369static inline bool is_input_client_id_valid(int32_t client_id)
370{
371 //TODO: Waiting for implementation
372 return true;
373}
374
Maulik Patel2358bbb2023-07-21 10:56:56 +0100375static dpe_error_t assign_layer_to_context(struct component_context_t *new_ctx)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100376{
377 uint16_t new_layer_idx, parent_layer_idx;
378
379 assert(new_ctx->parent_idx < MAX_NUM_OF_COMPONENTS);
380
381 parent_layer_idx = component_ctx_array[new_ctx->parent_idx].linked_layer_idx;
382 assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
383
384 if (layer_ctx_array[parent_layer_idx].state == LAYER_STATE_FINALISED) {
385 /* Parent comp's layer of new child is finalised; open a new layer */
386 new_layer_idx = open_new_layer();
Maulik Patel2358bbb2023-07-21 10:56:56 +0100387 if (new_layer_idx == INVALID_LAYER_IDX) {
388 return DPE_INTERNAL_ERROR;
389 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100390 /* Link this context to the new layer */
391 new_ctx->linked_layer_idx = new_layer_idx;
392 /* New layer's parent is current layer */
393 link_layer(new_layer_idx, parent_layer_idx);
394
395 } else {
396 /* Parent comp's layer is not yet finalised, link
397 * new component to the same layer as parent
398 */
399 new_ctx->linked_layer_idx = parent_layer_idx;
400 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100401
402 return DPE_NO_ERROR;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100403}
404
Jamie Fox34681992023-09-04 18:14:06 +0100405/**
406 * \brief Create a root of trust component context.
407 *
408 * \param[out] rot_ctx_handle A new context handle for the RoT context.
409 *
410 * \return Returns error code of type dpe_error_t
411 */
412static dpe_error_t create_rot_context(int *rot_ctx_handle)
413{
414 int ret;
415 psa_status_t status;
416 uint8_t rot_cdi_input[DICE_CDI_SIZE];
417 struct component_context_t *rot_comp_ctx = &component_ctx_array[0];
418 struct layer_context_t *rot_layer_ctx = &layer_ctx_array[DPE_ROT_LAYER_IDX];
419
420 /* Open RoT layer */
421 rot_layer_ctx->state = LAYER_STATE_OPEN;
422 /* Parent is same as child for RoT layer */
423 rot_layer_ctx->parent_layer_idx = DPE_ROT_LAYER_IDX;
424
425 /* Get the RoT CDI input for the RoT layer */
426 ret = dpe_plat_get_rot_cdi(&rot_cdi_input[0],
427 sizeof(rot_cdi_input));
428 if (ret != 0) {
429 return DPE_INTERNAL_ERROR;
430 }
431
432 /* Import the CDI key for the RoT layer */
433 status = create_layer_cdi_key(&layer_ctx_array[DPE_ROT_LAYER_IDX],
434 &rot_cdi_input[0],
435 sizeof(rot_cdi_input));
436 if (status != PSA_SUCCESS) {
437 return DPE_INTERNAL_ERROR;
438 }
439
440 /* Init RoT context, ready to be derived in next call to DeriveChild */
441 rot_comp_ctx->in_use = true;
442 rot_comp_ctx->nonce = 0;
443 /* Parent is same as child for RoT context */
444 rot_comp_ctx->parent_idx = 0;
445 /* Link context to RoT Layer */
446 rot_comp_ctx->linked_layer_idx = DPE_ROT_LAYER_IDX;
447 rot_comp_ctx->expected_mhu_id = 0;
448
449 *rot_ctx_handle = 0; /* index = 0, nonce = 0 */
450
451 return DPE_NO_ERROR;
452}
453
454dpe_error_t initialise_context_mngr(int *rot_ctx_handle)
455{
456 int i;
457
458 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
459 set_context_to_default(i);
460 }
461
462 for (i = 0; i < MAX_NUM_OF_LAYERS; i++) {
463 invalidate_layer(i);
464 }
465
466 return create_rot_context(rot_ctx_handle);
467}
468
Maulik Patelad2f3db2023-05-17 15:41:36 +0100469dpe_error_t derive_child_request(int input_ctx_handle,
470 bool retain_parent_context,
471 bool allow_child_to_derive,
472 bool create_certificate,
473 const DiceInputValues *dice_inputs,
474 int32_t client_id,
475 int *new_child_ctx_handle,
476 int *new_parent_ctx_handle)
477{
Maulik Patel58595d32023-06-22 10:08:53 +0100478 dpe_error_t err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100479 struct component_context_t *child_ctx, *parent_ctx, *new_ctx;
480 uint16_t input_child_idx, input_parent_idx;
481
Maulik Patelad2f3db2023-05-17 15:41:36 +0100482 log_derive_child(input_ctx_handle, retain_parent_context,
483 allow_child_to_derive, create_certificate, dice_inputs,
484 client_id);
485
486 /* Validate dice inputs */
487 if (!is_dice_input_valid(dice_inputs)) {
488 return DPE_INVALID_ARGUMENT;
489 }
490
491 /* Validate input handle */
492 if (!is_input_handle_valid(input_ctx_handle)) {
493 return DPE_INVALID_ARGUMENT;
494 }
495 /* Get child component index from the input handle */
496 input_child_idx = GET_IDX(input_ctx_handle);
497 /* Get parent index of input referenced child component */
498 input_parent_idx = component_ctx_array[input_child_idx].parent_idx;
499
500 /* Below check is for safety only; It should not happen
501 * input_child_idx is already checked above in is_input_handle_valid()
502 */
503 assert(input_parent_idx < MAX_NUM_OF_COMPONENTS);
504
505 child_ctx = &component_ctx_array[input_child_idx];
506 parent_ctx = &component_ctx_array[input_parent_idx];
507
508 //TODO: Question: how to get mhu id of incoming request?
509 if (!is_input_client_id_valid(client_id)) {
510 return DPE_INVALID_ARGUMENT;
511 }
512
513 /* Copy dice input to the child component context */
Maulik Patel58595d32023-06-22 10:08:53 +0100514 err = copy_dice_input(child_ctx, dice_inputs);
515 if (err != DPE_NO_ERROR) {
516 return err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100517 }
518
519 if (create_certificate) {
Maulik Patele6adc112023-08-18 14:21:51 +0100520 err = create_layer_certificate(child_ctx->linked_layer_idx);
Maulik Patel58595d32023-06-22 10:08:53 +0100521 if (err != DPE_NO_ERROR) {
522 return err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100523 }
524 }
525
526 if (allow_child_to_derive) {
527 /* Generate new handle for child for subsequent requests */
528 if (generate_new_handle(new_child_ctx_handle) != DPE_NO_ERROR) {
529 return DPE_INTERNAL_ERROR;
530 }
531 /* Update the component context array element as pointed by newly generated handle */
532 new_ctx = &component_ctx_array[GET_IDX(*new_child_ctx_handle)];
533 /* Update nonce in new child component context */
534 new_ctx->nonce = GET_NONCE(*new_child_ctx_handle);
535 /* Update parent idx in new child component context */
536 new_ctx->parent_idx = input_child_idx;
537 /* Mark new child component index as in use */
538 new_ctx->in_use = true;
Jamie Fox34681992023-09-04 18:14:06 +0100539 err = assign_layer_to_context(new_ctx);
540 if (err != DPE_NO_ERROR) {
541 return err;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100542 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100543 } else {
544 /* Child not deriving any children */
545 /* Tag this component as a leaf */
546 child_ctx->is_leaf = true;
547 invalidate_handle(new_child_ctx_handle);
548 /* Renew nonce of child context so it cannot be used again */
549 child_ctx->nonce = INVALID_NONCE_VALUE;
550 }
551
552 if (retain_parent_context) {
553 /* Parent deriving multiple children */
554 /* Generate new handle for child for the same parent for subsequent requests */
555 if (generate_new_handle(new_parent_ctx_handle) != DPE_NO_ERROR) {
556 return DPE_INTERNAL_ERROR;
557 }
558 /* Update the component context array element as pointed by newly generated handle */
559 new_ctx = &component_ctx_array[GET_IDX(*new_parent_ctx_handle)];
560 /* Update nonce in new child component context */
561 new_ctx->nonce = GET_NONCE(*new_parent_ctx_handle);
562 /* Update parent idx in new child component context */
563 new_ctx->parent_idx = input_parent_idx;
564 /* Mark new child component index as in use */
565 new_ctx->in_use = true;
Jamie Fox34681992023-09-04 18:14:06 +0100566 err = assign_layer_to_context(new_ctx);
567 if (err != DPE_NO_ERROR) {
568 return err;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100569 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100570 } else {
571 /* Parent not deriving any more children */
572 /* No need to return parent handle */
573 invalidate_handle(new_parent_ctx_handle);
574 /* Renew nonce of parent context so it cannot be used again */
575 parent_ctx->nonce = INVALID_NONCE_VALUE;
576 }
577
578 return DPE_NO_ERROR;
579}
Maulik Patel54d65f72023-06-28 13:04:36 +0100580
581dpe_error_t destroy_context_request(int input_ctx_handle,
582 bool destroy_recursively)
583{
584 uint16_t input_ctx_idx, linked_layer_idx;
585 int i;
586 bool is_layer_empty;
587
588 log_destroy_context(input_ctx_handle, destroy_recursively);
589
590 /* Get child component index and linked layer from the input handle */
591 input_ctx_idx = GET_IDX(input_ctx_handle);
592
Maulik Patel54d65f72023-06-28 13:04:36 +0100593 /* Validate input handle */
594 if (!is_input_handle_valid(input_ctx_handle)) {
595 return DPE_INVALID_ARGUMENT;
596 }
597 linked_layer_idx = component_ctx_array[input_ctx_idx].linked_layer_idx;
598
Jamie Fox34681992023-09-04 18:14:06 +0100599#ifndef DPE_TEST_MODE
Maulik Patel54d65f72023-06-28 13:04:36 +0100600 if (linked_layer_idx <= DPE_DESTROY_CONTEXT_THRESHOLD_LAYER_IDX) {
601 /* All layers till hypervisor cannot be destroyed dynamically */
602 return DPE_INVALID_ARGUMENT;
603 }
Jamie Fox34681992023-09-04 18:14:06 +0100604#endif /* !DPE_TEST_MODE */
Maulik Patel54d65f72023-06-28 13:04:36 +0100605
606
607 if (!destroy_recursively) {
608 set_context_to_default(input_ctx_idx);
609 } else {
610 //TODO: To be implemented
611 }
612
613 assert(linked_layer_idx < MAX_NUM_OF_LAYERS);
614
615 /* Close the layer if all of its contexts are destroyed */
616 is_layer_empty = true;
617 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
618 if (component_ctx_array[i].linked_layer_idx == linked_layer_idx) {
619 /* There are active component context in the layer */
620 is_layer_empty = false;
621 break;
622 }
623 }
624
625 if (is_layer_empty) {
626 invalidate_layer(linked_layer_idx);
627 }
628
629 return DPE_NO_ERROR;
630}
Maulik Patel2358bbb2023-07-21 10:56:56 +0100631
632struct component_context_t* get_component_if_linked_to_layer(uint16_t layer_idx,
633 uint16_t component_idx)
634{
635 /* Safety case */
636 if (component_idx >= MAX_NUM_OF_COMPONENTS) {
637 return NULL;
638 }
639
640 if (component_ctx_array[component_idx].linked_layer_idx == layer_idx) {
641 return &component_ctx_array[component_idx];
642 } else {
643 return NULL;
644 }
645}
646
Maulik Patele6adc112023-08-18 14:21:51 +0100647struct layer_context_t* get_layer_ctx_ptr(uint16_t layer_idx)
648{
649 /* Safety case */
650 if (layer_idx >= MAX_NUM_OF_LAYERS) {
651 return NULL;
652 }
653
654 return &layer_ctx_array[layer_idx];
655}
656
657dpe_error_t certify_key_request(int input_ctx_handle,
658 bool retain_context,
659 const uint8_t *public_key,
660 size_t public_key_size,
661 const uint8_t *label,
662 size_t label_size,
663 uint8_t *certificate_chain_buf,
664 size_t certificate_chain_buf_size,
665 size_t *certificate_chain_actual_size,
666 uint8_t *derived_public_key_buf,
667 size_t derived_public_key_buf_size,
668 size_t *derived_public_key_actual_size,
669 int *new_context_handle)
670{
671 uint16_t input_ctx_idx, input_layer_idx, parent_layer_idx;
672 dpe_error_t err;
673 psa_status_t status;
674 struct layer_context_t *parent_layer_ctx, *layer_ctx;
675
676 log_certify_key(input_ctx_handle, retain_context, public_key, public_key_size,
677 label, label_size);
678
679 /* Validate input handle */
680 if (!is_input_handle_valid(input_ctx_handle)) {
681 return DPE_INVALID_ARGUMENT;
682 }
683
684 if (label_size > DPE_EXTERNAL_LABEL_MAX_SIZE) {
685 return DPE_INVALID_ARGUMENT;
686 }
687
688 /* Get component index from the input handle */
689 input_ctx_idx = GET_IDX(input_ctx_handle);
690 /* Get current linked layer idx */
691 input_layer_idx = component_ctx_array[input_ctx_idx].linked_layer_idx;
692 assert(input_layer_idx < MAX_NUM_OF_LAYERS);
693
694 layer_ctx = &layer_ctx_array[input_layer_idx];
695 if (public_key_size > sizeof(layer_ctx->data.attest_pub_key)) {
696 return DPE_INVALID_ARGUMENT;
697 }
698
699 if ((public_key_size > 0) && (public_key != NULL)) {
700 layer_ctx->is_external_pub_key_provided = true;
701 /* Copy the public key provided */
702 memcpy(&layer_ctx->data.attest_pub_key[0],
703 public_key,
704 public_key_size);
705 layer_ctx->data.attest_pub_key_len = public_key_size;
706
707 /* If public key is provided, then provided label (if any) is ignored */
708 layer_ctx->data.attest_key_label_len = 0;
709
710 } else {
711 /* No external public key is provided */
712 layer_ctx->is_external_pub_key_provided = false;
713
714 if ((label_size > 0) && (label != NULL)) {
715 /* Copy the label provided */
716 memcpy(&layer_ctx->data.attest_key_label[0],
717 label,
718 label_size);
719 layer_ctx->data.attest_key_label_len = label_size;
720
721 } else {
722 layer_ctx->data.attest_key_label_len = 0;
723 }
724 }
725
726 /* Correct layer should already be assigned in last call of
727 * derive child command
728 */
729 /* Finalise the current layer & create leaf certificate */
730 err = create_layer_certificate(input_layer_idx);
731 if (err != DPE_NO_ERROR) {
732 return err;
733 }
734
735 /* Get parent layer derived public key to verify the certificate signature */
736 parent_layer_idx = layer_ctx_array[input_layer_idx].parent_layer_idx;
737 assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
738 parent_layer_ctx = &layer_ctx_array[parent_layer_idx];
739
740 if (derived_public_key_buf_size < sizeof(parent_layer_ctx->data.attest_pub_key)) {
741 return DPE_INVALID_ARGUMENT;
742 }
743
744 memcpy(derived_public_key_buf,
745 &parent_layer_ctx->data.attest_pub_key[0],
746 parent_layer_ctx->data.attest_pub_key_len);
747 *derived_public_key_actual_size = parent_layer_ctx->data.attest_pub_key_len;
748
749 /* Get certificate chain */
750 err = get_certificate_chain(input_layer_idx,
751 certificate_chain_buf,
752 certificate_chain_buf_size,
753 certificate_chain_actual_size);
754 if (err != DPE_NO_ERROR) {
755 return err;
756 }
757
758 log_certificate_chain(certificate_chain_buf, *certificate_chain_actual_size);
759
760 /* Renew handle for the same context */
761 *new_context_handle = input_ctx_handle;
762 status = renew_nonce(new_context_handle);
763 if (status != PSA_SUCCESS) {
764 return DPE_INTERNAL_ERROR;
765 }
766 component_ctx_array[input_ctx_idx].nonce = GET_NONCE(*new_context_handle);
767
768 /* Clear the context label and key contents */
769 memset(&layer_ctx->data.attest_key_label[0], 0u, layer_ctx->data.attest_key_label_len);
770 memset(&layer_ctx->data.attest_pub_key[0], 0u, layer_ctx->data.attest_pub_key_len);
771
772 return DPE_NO_ERROR;
773}