blob: 6823fd5dcc4e6a02e5ab32f8149dc847679c677d [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
Maulik Patelc97c7752023-10-17 20:06:29 +0100550 /* Renew nonce of child context so it cannot be used again */
551 child_ctx->nonce = INVALID_NONCE_VALUE;
552
Maulik Patelad2f3db2023-05-17 15:41:36 +0100553 if (allow_child_to_derive) {
554 /* Generate new handle for child for subsequent requests */
555 if (generate_new_handle(new_child_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_child_ctx_handle)];
560 /* Update nonce in new child component context */
561 new_ctx->nonce = GET_NONCE(*new_child_ctx_handle);
562 /* Update parent idx in new child component context */
563 new_ctx->parent_idx = input_child_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 /* Child not deriving any children */
572 /* Tag this component as a leaf */
573 child_ctx->is_leaf = true;
574 invalidate_handle(new_child_ctx_handle);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100575 }
576
577 if (retain_parent_context) {
578 /* Parent deriving multiple children */
579 /* Generate new handle for child for the same parent for subsequent requests */
580 if (generate_new_handle(new_parent_ctx_handle) != DPE_NO_ERROR) {
581 return DPE_INTERNAL_ERROR;
582 }
583 /* Update the component context array element as pointed by newly generated handle */
584 new_ctx = &component_ctx_array[GET_IDX(*new_parent_ctx_handle)];
585 /* Update nonce in new child component context */
586 new_ctx->nonce = GET_NONCE(*new_parent_ctx_handle);
587 /* Update parent idx in new child component context */
588 new_ctx->parent_idx = input_parent_idx;
589 /* Mark new child component index as in use */
590 new_ctx->in_use = true;
Jamie Fox34681992023-09-04 18:14:06 +0100591 err = assign_layer_to_context(new_ctx);
592 if (err != DPE_NO_ERROR) {
593 return err;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100594 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100595 } else {
596 /* Parent not deriving any more children */
597 /* No need to return parent handle */
598 invalidate_handle(new_parent_ctx_handle);
599 /* Renew nonce of parent context so it cannot be used again */
600 parent_ctx->nonce = INVALID_NONCE_VALUE;
601 }
602
603 return DPE_NO_ERROR;
604}
Maulik Patel54d65f72023-06-28 13:04:36 +0100605
606dpe_error_t destroy_context_request(int input_ctx_handle,
607 bool destroy_recursively)
608{
609 uint16_t input_ctx_idx, linked_layer_idx;
610 int i;
611 bool is_layer_empty;
612
613 log_destroy_context(input_ctx_handle, destroy_recursively);
614
615 /* Get child component index and linked layer from the input handle */
616 input_ctx_idx = GET_IDX(input_ctx_handle);
617
Maulik Patel54d65f72023-06-28 13:04:36 +0100618 /* Validate input handle */
619 if (!is_input_handle_valid(input_ctx_handle)) {
620 return DPE_INVALID_ARGUMENT;
621 }
622 linked_layer_idx = component_ctx_array[input_ctx_idx].linked_layer_idx;
623
Jamie Fox34681992023-09-04 18:14:06 +0100624#ifndef DPE_TEST_MODE
Maulik Patel54d65f72023-06-28 13:04:36 +0100625 if (linked_layer_idx <= DPE_DESTROY_CONTEXT_THRESHOLD_LAYER_IDX) {
626 /* All layers till hypervisor cannot be destroyed dynamically */
627 return DPE_INVALID_ARGUMENT;
628 }
Jamie Fox34681992023-09-04 18:14:06 +0100629#endif /* !DPE_TEST_MODE */
Maulik Patel54d65f72023-06-28 13:04:36 +0100630
631
632 if (!destroy_recursively) {
633 set_context_to_default(input_ctx_idx);
634 } else {
635 //TODO: To be implemented
636 }
637
638 assert(linked_layer_idx < MAX_NUM_OF_LAYERS);
639
640 /* Close the layer if all of its contexts are destroyed */
641 is_layer_empty = true;
642 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
643 if (component_ctx_array[i].linked_layer_idx == linked_layer_idx) {
644 /* There are active component context in the layer */
645 is_layer_empty = false;
646 break;
647 }
648 }
649
650 if (is_layer_empty) {
651 invalidate_layer(linked_layer_idx);
652 }
653
654 return DPE_NO_ERROR;
655}
Maulik Patel2358bbb2023-07-21 10:56:56 +0100656
657struct component_context_t* get_component_if_linked_to_layer(uint16_t layer_idx,
658 uint16_t component_idx)
659{
660 /* Safety case */
661 if (component_idx >= MAX_NUM_OF_COMPONENTS) {
662 return NULL;
663 }
664
665 if (component_ctx_array[component_idx].linked_layer_idx == layer_idx) {
666 return &component_ctx_array[component_idx];
667 } else {
668 return NULL;
669 }
670}
671
Maulik Patele6adc112023-08-18 14:21:51 +0100672struct layer_context_t* get_layer_ctx_ptr(uint16_t layer_idx)
673{
674 /* Safety case */
675 if (layer_idx >= MAX_NUM_OF_LAYERS) {
676 return NULL;
677 }
678
679 return &layer_ctx_array[layer_idx];
680}
681
682dpe_error_t certify_key_request(int input_ctx_handle,
683 bool retain_context,
684 const uint8_t *public_key,
685 size_t public_key_size,
686 const uint8_t *label,
687 size_t label_size,
688 uint8_t *certificate_chain_buf,
689 size_t certificate_chain_buf_size,
690 size_t *certificate_chain_actual_size,
691 uint8_t *derived_public_key_buf,
692 size_t derived_public_key_buf_size,
693 size_t *derived_public_key_actual_size,
694 int *new_context_handle)
695{
696 uint16_t input_ctx_idx, input_layer_idx, parent_layer_idx;
697 dpe_error_t err;
698 psa_status_t status;
699 struct layer_context_t *parent_layer_ctx, *layer_ctx;
700
701 log_certify_key(input_ctx_handle, retain_context, public_key, public_key_size,
702 label, label_size);
703
704 /* Validate input handle */
705 if (!is_input_handle_valid(input_ctx_handle)) {
706 return DPE_INVALID_ARGUMENT;
707 }
708
709 if (label_size > DPE_EXTERNAL_LABEL_MAX_SIZE) {
710 return DPE_INVALID_ARGUMENT;
711 }
712
713 /* Get component index from the input handle */
714 input_ctx_idx = GET_IDX(input_ctx_handle);
715 /* Get current linked layer idx */
716 input_layer_idx = component_ctx_array[input_ctx_idx].linked_layer_idx;
717 assert(input_layer_idx < MAX_NUM_OF_LAYERS);
718
719 layer_ctx = &layer_ctx_array[input_layer_idx];
720 if (public_key_size > sizeof(layer_ctx->data.attest_pub_key)) {
721 return DPE_INVALID_ARGUMENT;
722 }
723
724 if ((public_key_size > 0) && (public_key != NULL)) {
725 layer_ctx->is_external_pub_key_provided = true;
726 /* Copy the public key provided */
727 memcpy(&layer_ctx->data.attest_pub_key[0],
728 public_key,
729 public_key_size);
730 layer_ctx->data.attest_pub_key_len = public_key_size;
731
732 /* If public key is provided, then provided label (if any) is ignored */
733 layer_ctx->data.attest_key_label_len = 0;
734
735 } else {
736 /* No external public key is provided */
737 layer_ctx->is_external_pub_key_provided = false;
738
739 if ((label_size > 0) && (label != NULL)) {
740 /* Copy the label provided */
741 memcpy(&layer_ctx->data.attest_key_label[0],
742 label,
743 label_size);
744 layer_ctx->data.attest_key_label_len = label_size;
745
746 } else {
747 layer_ctx->data.attest_key_label_len = 0;
748 }
749 }
750
751 /* Correct layer should already be assigned in last call of
752 * derive child command
753 */
754 /* Finalise the current layer & create leaf certificate */
755 err = create_layer_certificate(input_layer_idx);
756 if (err != DPE_NO_ERROR) {
757 return err;
758 }
759
760 /* Get parent layer derived public key to verify the certificate signature */
761 parent_layer_idx = layer_ctx_array[input_layer_idx].parent_layer_idx;
762 assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
763 parent_layer_ctx = &layer_ctx_array[parent_layer_idx];
764
765 if (derived_public_key_buf_size < sizeof(parent_layer_ctx->data.attest_pub_key)) {
766 return DPE_INVALID_ARGUMENT;
767 }
768
769 memcpy(derived_public_key_buf,
770 &parent_layer_ctx->data.attest_pub_key[0],
771 parent_layer_ctx->data.attest_pub_key_len);
772 *derived_public_key_actual_size = parent_layer_ctx->data.attest_pub_key_len;
773
774 /* Get certificate chain */
775 err = get_certificate_chain(input_layer_idx,
776 certificate_chain_buf,
777 certificate_chain_buf_size,
778 certificate_chain_actual_size);
779 if (err != DPE_NO_ERROR) {
780 return err;
781 }
782
783 log_certificate_chain(certificate_chain_buf, *certificate_chain_actual_size);
784
785 /* Renew handle for the same context */
786 *new_context_handle = input_ctx_handle;
787 status = renew_nonce(new_context_handle);
788 if (status != PSA_SUCCESS) {
789 return DPE_INTERNAL_ERROR;
790 }
791 component_ctx_array[input_ctx_idx].nonce = GET_NONCE(*new_context_handle);
792
793 /* Clear the context label and key contents */
794 memset(&layer_ctx->data.attest_key_label[0], 0u, layer_ctx->data.attest_key_label_len);
795 memset(&layer_ctx->data.attest_pub_key[0], 0u, layer_ctx->data.attest_pub_key_len);
796
797 return DPE_NO_ERROR;
798}