blob: 2cd040a4bff49079a278414164a3952fa5441891 [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"
15#include "psa/crypto.h"
16
Maulik Patel58595d32023-06-22 10:08:53 +010017#ifdef TFM_S_REG_TEST
18#define TEST_ROT_CDI_VAL { \
19 0xD2, 0x90, 0x66, 0x07, 0x2A, 0x2D, 0x2A, 0x00, \
20 0x91, 0x9D, 0xD9, 0x15, 0x14, 0xBE, 0x2D, 0xCC, \
21 0xA3, 0x9F, 0xDE, 0xC3, 0x35, 0x75, 0x84, 0x6E, \
22 0x4C, 0xB9, 0x28, 0xAC, 0x7A, 0x4E, 0X00, 0x7F \
23 }
Maulik Patel2358bbb2023-07-21 10:56:56 +010024
25#define TEST_ROT_ISSUER_SEED { \
26 0xD2, 0x90, 0x66, 0x07, 0x2A, 0x2D, 0x2A, 0x00, \
27 0x91, 0x9D, 0xD9, 0x15, 0x14, 0xBE, 0x2D, 0xCC, \
28 0xA3, 0x9F, 0xDE, 0xC3, 0x35, 0x75, 0x84, 0x6E, \
29 0x4C, 0xB9, 0x28, 0xAC, 0x7A, 0x4E, 0X00, 0x7F \
30 }
31
Maulik Patel58595d32023-06-22 10:08:53 +010032#endif /* TFM_S_REG_TEST */
33
34#define CONTEXT_DATA_MAX_SIZE sizeof(struct component_context_data_t)
35
Maulik Patelad2f3db2023-05-17 15:41:36 +010036static struct component_context_t component_ctx_array[MAX_NUM_OF_COMPONENTS];
37static struct layer_context_t layer_ctx_array[MAX_NUM_OF_LAYERS];
38
39static int get_free_component_context_index(void)
40{
41 int i;
42
43 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
44 if (!component_ctx_array[i].in_use) {
45 break;
46 }
47 }
48
49 if (i >= MAX_NUM_OF_COMPONENTS) {
50 /* No free index left in the array -- all used up! */
51 return -1;
52 }
53
54 return i;
55}
56
57static inline void invalidate_handle(int *handle)
58{
59 *handle = INVALID_HANDLE;
60}
61
62static dpe_error_t renew_nonce(int *handle)
63{
64 uint16_t nonce;
65
66 psa_status_t status = psa_generate_random((uint8_t *)&nonce, sizeof(nonce));
67 if (status != PSA_SUCCESS) {
68 return DPE_INTERNAL_ERROR;
69 }
70 *handle = SET_NONCE(*handle, nonce);
71
72 return DPE_NO_ERROR;
73}
74
75static dpe_error_t generate_new_handle(int *out_handle)
76{
77 /* Find the free component array element */
78 int free_component_idx = get_free_component_context_index();
79 if (free_component_idx < 0) {
80 return DPE_INSUFFICIENT_MEMORY;
81 }
82
83 *out_handle = SET_IDX(*out_handle, free_component_idx);
84
85 return renew_nonce(out_handle);
86}
87
88static void set_context_to_default(int i)
89{
90 component_ctx_array[i].in_use = false;
91 component_ctx_array[i].is_leaf = false;
92 component_ctx_array[i].nonce = INVALID_NONCE_VALUE;
93 component_ctx_array[i].parent_idx = INVALID_COMPONENT_IDX;
94 component_ctx_array[i].linked_layer_idx = INVALID_LAYER_IDX;
95 (void)memset(&component_ctx_array[i].data, 0, sizeof(struct component_context_data_t));
96 //TODO: Question: how to initialise MHU Id mapping?
97 /* Allow component to be derived by default */
98}
99
100static void invalidate_layer(int i)
101{
102 layer_ctx_array[i].state = LAYER_STATE_CLOSED;
103 layer_ctx_array[i].parent_layer_idx = INVALID_LAYER_IDX;
Maulik Patele6adc112023-08-18 14:21:51 +0100104 (void)memset(&layer_ctx_array[i].attest_cdi_hash_input, 0,
105 sizeof(layer_ctx_array[i].attest_cdi_hash_input));
Maulik Patel58595d32023-06-22 10:08:53 +0100106 (void)psa_destroy_key(layer_ctx_array[i].data.cdi_key_id);
107 (void)psa_destroy_key(layer_ctx_array[i].data.attest_key_id);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100108 (void)memset(&layer_ctx_array[i].data, 0, sizeof(struct layer_context_data_t));
109}
110
111void initialise_all_dpe_contexts(void)
112{
113 int i;
114
115 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
116 set_context_to_default(i);
117 }
118
119 for (i = 0; i < MAX_NUM_OF_LAYERS; i++) {
120 invalidate_layer(i);
121 }
122}
123
124static dpe_error_t copy_dice_input(struct component_context_t *dest_ctx,
125 const DiceInputValues *dice_inputs)
126{
127 size_t hash_len;
128 psa_status_t status;
129
130 memcpy(&dest_ctx->data.measurement_value, dice_inputs->code_hash,
131 DICE_HASH_SIZE);
132 memcpy(&dest_ctx->data.measurement_descriptor,
133 dice_inputs->code_descriptor,
134 dice_inputs->code_descriptor_size);
135
136 dest_ctx->data.measurement_descriptor_size =
137 dice_inputs->code_descriptor_size;
138
139 memcpy(&dest_ctx->data.signer_id, dice_inputs->authority_hash, DICE_HASH_SIZE);
140 memcpy(&dest_ctx->data.signer_id_descriptor,
141 dice_inputs->authority_descriptor,
142 dice_inputs->authority_descriptor_size);
143
144 dest_ctx->data.signer_id_descriptor_size =
145 dice_inputs->authority_descriptor_size;
146
147 if (dice_inputs->config_type == kDiceConfigTypeInline) {
148 /* Copy config_value */
149 memcpy(&dest_ctx->data.config_value, dice_inputs->config_value,
150 DICE_INLINE_CONFIG_SIZE);
151
152 } else {
153 /* Copy config descriptor */
154 memcpy(&dest_ctx->data.config_descriptor, dice_inputs->config_descriptor,
155 dice_inputs->config_descriptor_size);
156 dest_ctx->data.config_descriptor_size = dice_inputs->config_descriptor_size;
157
158 /* Calculate config value as hash of input config descriptor */
Maulik Patel2358bbb2023-07-21 10:56:56 +0100159 status = psa_hash_compute(DPE_HASH_ALG,
Maulik Patelad2f3db2023-05-17 15:41:36 +0100160 dice_inputs->config_descriptor,
161 dice_inputs->config_descriptor_size,
162 dest_ctx->data.config_value,
163 sizeof(dest_ctx->data.config_value),
164 &hash_len);
165
166 if (status != PSA_SUCCESS) {
167 return DPE_INTERNAL_ERROR;
168 }
169 }
170
171 dest_ctx->data.mode = dice_inputs->mode;
172 memcpy(&dest_ctx->data.hidden, dice_inputs->hidden, DICE_HIDDEN_SIZE);
173
174 return DPE_NO_ERROR;
175}
176
177static bool is_dice_input_valid(const DiceInputValues *dice_inputs)
178{
179 if ((dice_inputs->code_descriptor_size > DICE_CODE_DESCRIPTOR_MAX_SIZE) ||
180 (dice_inputs->authority_descriptor_size > DICE_AUTHORITY_DESCRIPTOR_MAX_SIZE) ||
181 (dice_inputs->config_descriptor_size > DICE_CONFIG_DESCRIPTOR_MAX_SIZE)) {
182 return false;
183 }
184
185 return true;
186}
187
188static bool is_input_handle_valid(int input_context_handle)
189{
190 uint16_t idx = GET_IDX(input_context_handle);
191 uint16_t nonce = GET_NONCE(input_context_handle);
192
193 /* Validate input handle id and nonce */
194 if ((idx >= MAX_NUM_OF_COMPONENTS) || (nonce == INVALID_NONCE_VALUE)) {
195 return false;
196 }
197
198 if (nonce == component_ctx_array[idx].nonce) {
199 return true;
200 }
201
202 return false;
203}
204
Maulik Patel58595d32023-06-22 10:08:53 +0100205/* Attest_CDI Input requires {measurement_value, config, authority, mode, hidden} in
206 * same order
207 */
208static psa_status_t get_component_data_for_attest_cdi(uint8_t *dest_buf,
209 size_t max_size,
210 size_t *dest_size,
211 const struct component_context_t *comp_ctx)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100212{
Maulik Patel58595d32023-06-22 10:08:53 +0100213 size_t out_size = 0;
214
215 if ((DICE_HASH_SIZE + DICE_INLINE_CONFIG_SIZE + DICE_HASH_SIZE +
216 sizeof(comp_ctx->data.mode) + DICE_HIDDEN_SIZE > max_size )) {
217 return PSA_ERROR_BUFFER_TOO_SMALL;
218 }
219
220 memcpy(&dest_buf[out_size], comp_ctx->data.measurement_value, DICE_HASH_SIZE);
221 out_size += DICE_HASH_SIZE;
222
223 memcpy(&dest_buf[out_size], comp_ctx->data.config_value, DICE_INLINE_CONFIG_SIZE);
224 out_size += DICE_INLINE_CONFIG_SIZE;
225
226 memcpy(&dest_buf[out_size], comp_ctx->data.signer_id, DICE_HASH_SIZE);
227 out_size += DICE_HASH_SIZE;
228
229 memcpy(&dest_buf[out_size], &comp_ctx->data.mode, sizeof(comp_ctx->data.mode));
230 out_size += sizeof(comp_ctx->data.mode);
231
232 memcpy(&dest_buf[out_size], comp_ctx->data.hidden, DICE_HIDDEN_SIZE);
233 out_size += DICE_HIDDEN_SIZE;
234
235 *dest_size = out_size;
236
237 return PSA_SUCCESS;
238}
239
240static psa_status_t compute_layer_cdi_attest_input(uint16_t curr_layer_idx)
241{
242 psa_status_t status;
243 uint8_t component_ctx_data[CONTEXT_DATA_MAX_SIZE];
244 size_t ctx_data_size, hash_len;
245 int idx;
246
247 psa_hash_operation_t hash_op = psa_hash_operation_init();
248 status = psa_hash_setup(&hash_op, DPE_HASH_ALG);
249 if (status != PSA_SUCCESS) {
250 return status;
251 }
252
253 //TODO:
254 /* How to combine measurements of multiple SW components into a single hash
255 * is not yet defined by the Open DICE profile. This implementation
256 * concatenates the data of all SW components which belong to the same layer
257 * and hash it.
258 */
259 for (idx = 0; idx < MAX_NUM_OF_COMPONENTS; idx++) {
260 if (component_ctx_array[idx].linked_layer_idx == curr_layer_idx) {
261 /* This component belongs to current layer */
262 /* Concatenate all context data for this component */
263 status = get_component_data_for_attest_cdi(component_ctx_data,
264 sizeof(component_ctx_data),
265 &ctx_data_size,
266 &component_ctx_array[idx]);
267 if (status != PSA_SUCCESS) {
268 return status;
269 }
270
271 status = psa_hash_update(&hash_op,
272 component_ctx_data,
273 ctx_data_size);
274 if (status != PSA_SUCCESS) {
275 return status;
276 }
277 }
278 }
279
Maulik Patele6adc112023-08-18 14:21:51 +0100280 if (layer_ctx_array[curr_layer_idx].data.attest_key_label_len != 0) {
281
282 status = psa_hash_update(&hash_op,
283 &layer_ctx_array[curr_layer_idx].data.attest_key_label[0],
284 layer_ctx_array[curr_layer_idx].data.attest_key_label_len);
285 if (status != PSA_SUCCESS) {
286 return status;
287 }
288 }
289
Maulik Patel58595d32023-06-22 10:08:53 +0100290 status = psa_hash_finish(&hash_op,
291 &layer_ctx_array[curr_layer_idx].attest_cdi_hash_input[0],
292 sizeof(layer_ctx_array[curr_layer_idx].attest_cdi_hash_input),
293 &hash_len);
294
295 assert(hash_len == DPE_HASH_ALG_SIZE);
296
297 return status;
298}
299
Maulik Patele6adc112023-08-18 14:21:51 +0100300static dpe_error_t create_layer_certificate(uint16_t layer_idx)
Maulik Patel58595d32023-06-22 10:08:53 +0100301{
Maulik Patel2358bbb2023-07-21 10:56:56 +0100302 uint16_t parent_layer_idx;
Maulik Patel58595d32023-06-22 10:08:53 +0100303 psa_status_t status;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100304 dpe_error_t err;
Maulik Patele6adc112023-08-18 14:21:51 +0100305 struct layer_context_t *layer_ctx, *parent_layer_ctx;
Maulik Patel58595d32023-06-22 10:08:53 +0100306
307 assert(layer_idx < MAX_NUM_OF_LAYERS);
Maulik Patele6adc112023-08-18 14:21:51 +0100308 layer_ctx = &layer_ctx_array[layer_idx];
309 /* Finalise the layer */
310 layer_ctx->state = LAYER_STATE_FINALISED;
311 parent_layer_idx = layer_ctx->parent_layer_idx;
312 assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
313 parent_layer_ctx = &layer_ctx_array[parent_layer_idx];
Maulik Patel58595d32023-06-22 10:08:53 +0100314
Maulik Patel2358bbb2023-07-21 10:56:56 +0100315 /* For RoT Layer, CDI and issuer seed values are calculated by BL1_1 */
Maulik Patele6adc112023-08-18 14:21:51 +0100316 if ((layer_idx != DPE_ROT_LAYER_IDX) &&
317 (!layer_ctx->is_external_pub_key_provided)) {
Maulik Patel58595d32023-06-22 10:08:53 +0100318
Maulik Patele6adc112023-08-18 14:21:51 +0100319 /* Except for RoT Layer with no external public key supplied */
Maulik Patel58595d32023-06-22 10:08:53 +0100320
321 status = compute_layer_cdi_attest_input(layer_idx);
322 if (status != PSA_SUCCESS) {
323 return DPE_INTERNAL_ERROR;
324 }
325
Maulik Patele6adc112023-08-18 14:21:51 +0100326 status = derive_attestation_cdi(layer_ctx, parent_layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100327 if (status != PSA_SUCCESS) {
328 return DPE_INTERNAL_ERROR;
329 }
330
Maulik Patele6adc112023-08-18 14:21:51 +0100331 status = derive_sealing_cdi(layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100332 if (status != PSA_SUCCESS) {
333 return DPE_INTERNAL_ERROR;
334 }
335 }
336
Maulik Patele6adc112023-08-18 14:21:51 +0100337 status = derive_wrapping_key(layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100338 if (status != PSA_SUCCESS) {
339 return DPE_INTERNAL_ERROR;
340 }
341
Maulik Patele6adc112023-08-18 14:21:51 +0100342 if (!layer_ctx->is_external_pub_key_provided) {
343 status = derive_attestation_key(layer_ctx);
344 if (status != PSA_SUCCESS) {
345 return DPE_INTERNAL_ERROR;
346 }
Maulik Patel58595d32023-06-22 10:08:53 +0100347 }
348
Maulik Patele6adc112023-08-18 14:21:51 +0100349 status = derive_id_from_public_key(layer_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100350 if (status != PSA_SUCCESS) {
351 return DPE_INTERNAL_ERROR;
352 }
353
Maulik Patel2358bbb2023-07-21 10:56:56 +0100354 err = encode_layer_certificate(layer_idx,
Maulik Patele6adc112023-08-18 14:21:51 +0100355 layer_ctx,
356 parent_layer_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100357 if (err != DPE_NO_ERROR) {
358 return err;
Maulik Patel58595d32023-06-22 10:08:53 +0100359 }
360
Maulik Patel2358bbb2023-07-21 10:56:56 +0100361 log_intermediate_certificate(layer_idx,
Maulik Patele6adc112023-08-18 14:21:51 +0100362 &layer_ctx->data.cert_buf[0],
363 layer_ctx->data.cert_buf_len);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100364
Maulik Patele6adc112023-08-18 14:21:51 +0100365 return store_layer_certificate(layer_ctx);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100366}
367
368static uint16_t open_new_layer(void)
369{
370 int i;
371
372 for (i = 0; i < MAX_NUM_OF_LAYERS; i++) {
373 if (layer_ctx_array[i].state == LAYER_STATE_CLOSED) {
374 layer_ctx_array[i].state = LAYER_STATE_OPEN;
375 return i;
376 }
377 }
378
Maulik Patel2358bbb2023-07-21 10:56:56 +0100379 //TODO: There is an open issue of layer creation as described below.
380 /* This is causing extra unintended layers to open. Since each layer
381 * has some context data and certificate buffer of 3k, it is
382 * causing RAM overflow. Hence until resoluton is reached, once all
383 * layers are opened, link new compenents to the last layer.
384 * ISSUE DESCRIPTION: We derive AP_BL31 as child of AP BL2 with create_certificate
385 * as true. Hence we finalize Platform layer. Then we derive AP_SPM as child of
386 * AP BL2, but since AP BL2 is finalised, we open new layer (Hypervisor layer).
387 * Then we derive AP SPx as child of AP BL2. Again, since AP BL2 is finalised,
388 * we open new layer! Here AP SPx should belong to same layer as AP SPM.
389 */
390 return MAX_NUM_OF_LAYERS - 1;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100391}
392
393static inline void link_layer(uint16_t child_layer, uint16_t parent_layer)
394{
395 layer_ctx_array[child_layer].parent_layer_idx = parent_layer;
396}
397
398dpe_error_t derive_rot_context(const DiceInputValues *dice_inputs,
399 int *new_child_ctx_handle,
400 int *new_parent_ctx_handle)
401{
402 int status;
403 struct component_context_t *child_comp_ctx, *new_child_ctx;
404 uint16_t new_layer_idx;
405
406 log_derive_rot_context(dice_inputs);
407
408 /* Validate dice inputs */
409 if (!is_dice_input_valid(dice_inputs)) {
410 return DPE_INVALID_ARGUMENT;
411 }
412
413 child_comp_ctx = &component_ctx_array[0];
414 status = copy_dice_input(child_comp_ctx, dice_inputs);
415 if (status != DPE_NO_ERROR) {
416 return status;
417 }
418
419 child_comp_ctx->in_use = true;
420 /* Link context to RoT Layer */
421 child_comp_ctx->linked_layer_idx = DPE_ROT_LAYER_IDX;
Maulik Patele6adc112023-08-18 14:21:51 +0100422 /* There is no parent for RoT layer */
423 layer_ctx_array[DPE_ROT_LAYER_IDX].parent_layer_idx = 0;
424
Maulik Patelad2f3db2023-05-17 15:41:36 +0100425 /* Parent is same as child for RoT context */
426 child_comp_ctx->parent_idx = 0;
427 /* Parent not deriving any more children */
428 invalidate_handle(new_parent_ctx_handle);
429
430 //TODO: Update expected_mhu_id of derived child
431 /* Create certificate for RoT layer */
Maulik Patele6adc112023-08-18 14:21:51 +0100432 status = create_layer_certificate(DPE_ROT_LAYER_IDX);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100433 if (status != DPE_NO_ERROR) {
434 return status;
435 }
436
437 /* Generate new handle for child for subsequent requests */
438 if (generate_new_handle(new_child_ctx_handle) != DPE_NO_ERROR) {
439 return DPE_INTERNAL_ERROR;
440 }
441
442 /* Update the component context array element as pointed by newly generated handle */
443 new_child_ctx = &component_ctx_array[GET_IDX(*new_child_ctx_handle)];
444 new_child_ctx->nonce = GET_NONCE(*new_child_ctx_handle);
445 new_child_ctx->in_use = true;
446 /* New child's parent is current RoT component which is evaluated as 0 */
447 new_child_ctx->parent_idx = 0;
448
449 /* Open new layer since RoT layer is finalised and
450 * link the new child to this new layer
451 */
452 new_layer_idx = open_new_layer();
453 new_child_ctx->linked_layer_idx = new_layer_idx;
454
455 /* Link this new layer to the RoT Layer */
456 link_layer(new_layer_idx, DPE_ROT_LAYER_IDX);
457
458 return DPE_NO_ERROR;
459}
460
461static inline bool is_input_client_id_valid(int32_t client_id)
462{
463 //TODO: Waiting for implementation
464 return true;
465}
466
Maulik Patel2358bbb2023-07-21 10:56:56 +0100467static dpe_error_t assign_layer_to_context(struct component_context_t *new_ctx)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100468{
469 uint16_t new_layer_idx, parent_layer_idx;
470
471 assert(new_ctx->parent_idx < MAX_NUM_OF_COMPONENTS);
472
473 parent_layer_idx = component_ctx_array[new_ctx->parent_idx].linked_layer_idx;
474 assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
475
476 if (layer_ctx_array[parent_layer_idx].state == LAYER_STATE_FINALISED) {
477 /* Parent comp's layer of new child is finalised; open a new layer */
478 new_layer_idx = open_new_layer();
Maulik Patel2358bbb2023-07-21 10:56:56 +0100479 if (new_layer_idx == INVALID_LAYER_IDX) {
480 return DPE_INTERNAL_ERROR;
481 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100482 /* Link this context to the new layer */
483 new_ctx->linked_layer_idx = new_layer_idx;
484 /* New layer's parent is current layer */
485 link_layer(new_layer_idx, parent_layer_idx);
486
487 } else {
488 /* Parent comp's layer is not yet finalised, link
489 * new component to the same layer as parent
490 */
491 new_ctx->linked_layer_idx = parent_layer_idx;
492 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100493
494 return DPE_NO_ERROR;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100495}
496
497dpe_error_t derive_child_request(int input_ctx_handle,
498 bool retain_parent_context,
499 bool allow_child_to_derive,
500 bool create_certificate,
501 const DiceInputValues *dice_inputs,
502 int32_t client_id,
503 int *new_child_ctx_handle,
504 int *new_parent_ctx_handle)
505{
Maulik Patel58595d32023-06-22 10:08:53 +0100506 dpe_error_t err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100507 struct component_context_t *child_ctx, *parent_ctx, *new_ctx;
508 uint16_t input_child_idx, input_parent_idx;
509
510#ifdef TFM_S_REG_TEST
Maulik Patel58595d32023-06-22 10:08:53 +0100511 //TODO: Remove this TEST_ROT_CDI_VAL CDI once actual CDI is calculated by BL1_1
512 psa_status_t status;
513 uint8_t dpe_rot_cdi[DICE_CDI_SIZE] = TEST_ROT_CDI_VAL;
514
Maulik Patelad2f3db2023-05-17 15:41:36 +0100515 if (layer_ctx_array[DPE_ROT_LAYER_IDX].state != LAYER_STATE_FINALISED) {
Maulik Patel58595d32023-06-22 10:08:53 +0100516
517 status = create_layer_cdi_key(&layer_ctx_array[DPE_ROT_LAYER_IDX],
518 &dpe_rot_cdi[0],
519 sizeof(dpe_rot_cdi));
520 if (status != PSA_SUCCESS) {
521 return status;
522 }
523
Maulik Patelad2f3db2023-05-17 15:41:36 +0100524 return derive_rot_context(dice_inputs,
525 new_child_ctx_handle,
526 new_parent_ctx_handle);
527 }
528#endif /* TFM_S_REG_TEST */
529
530 log_derive_child(input_ctx_handle, retain_parent_context,
531 allow_child_to_derive, create_certificate, dice_inputs,
532 client_id);
533
534 /* Validate dice inputs */
535 if (!is_dice_input_valid(dice_inputs)) {
536 return DPE_INVALID_ARGUMENT;
537 }
538
539 /* Validate input handle */
540 if (!is_input_handle_valid(input_ctx_handle)) {
541 return DPE_INVALID_ARGUMENT;
542 }
543 /* Get child component index from the input handle */
544 input_child_idx = GET_IDX(input_ctx_handle);
545 /* Get parent index of input referenced child component */
546 input_parent_idx = component_ctx_array[input_child_idx].parent_idx;
547
548 /* Below check is for safety only; It should not happen
549 * input_child_idx is already checked above in is_input_handle_valid()
550 */
551 assert(input_parent_idx < MAX_NUM_OF_COMPONENTS);
552
553 child_ctx = &component_ctx_array[input_child_idx];
554 parent_ctx = &component_ctx_array[input_parent_idx];
555
556 //TODO: Question: how to get mhu id of incoming request?
557 if (!is_input_client_id_valid(client_id)) {
558 return DPE_INVALID_ARGUMENT;
559 }
560
561 /* Copy dice input to the child component context */
Maulik Patel58595d32023-06-22 10:08:53 +0100562 err = copy_dice_input(child_ctx, dice_inputs);
563 if (err != DPE_NO_ERROR) {
564 return err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100565 }
566
567 if (create_certificate) {
Maulik Patele6adc112023-08-18 14:21:51 +0100568 err = create_layer_certificate(child_ctx->linked_layer_idx);
Maulik Patel58595d32023-06-22 10:08:53 +0100569 if (err != DPE_NO_ERROR) {
570 return err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100571 }
572 }
573
574 if (allow_child_to_derive) {
575 /* Generate new handle for child for subsequent requests */
576 if (generate_new_handle(new_child_ctx_handle) != DPE_NO_ERROR) {
577 return DPE_INTERNAL_ERROR;
578 }
579 /* Update the component context array element as pointed by newly generated handle */
580 new_ctx = &component_ctx_array[GET_IDX(*new_child_ctx_handle)];
581 /* Update nonce in new child component context */
582 new_ctx->nonce = GET_NONCE(*new_child_ctx_handle);
583 /* Update parent idx in new child component context */
584 new_ctx->parent_idx = input_child_idx;
585 /* Mark new child component index as in use */
586 new_ctx->in_use = true;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100587 status = assign_layer_to_context(new_ctx);
588 if (status != DPE_NO_ERROR) {
589 return status;
590 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100591 } else {
592 /* Child not deriving any children */
593 /* Tag this component as a leaf */
594 child_ctx->is_leaf = true;
595 invalidate_handle(new_child_ctx_handle);
596 /* Renew nonce of child context so it cannot be used again */
597 child_ctx->nonce = INVALID_NONCE_VALUE;
598 }
599
600 if (retain_parent_context) {
601 /* Parent deriving multiple children */
602 /* Generate new handle for child for the same parent for subsequent requests */
603 if (generate_new_handle(new_parent_ctx_handle) != DPE_NO_ERROR) {
604 return DPE_INTERNAL_ERROR;
605 }
606 /* Update the component context array element as pointed by newly generated handle */
607 new_ctx = &component_ctx_array[GET_IDX(*new_parent_ctx_handle)];
608 /* Update nonce in new child component context */
609 new_ctx->nonce = GET_NONCE(*new_parent_ctx_handle);
610 /* Update parent idx in new child component context */
611 new_ctx->parent_idx = input_parent_idx;
612 /* Mark new child component index as in use */
613 new_ctx->in_use = true;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100614 status = assign_layer_to_context(new_ctx);
615 if (status != DPE_NO_ERROR) {
616 return status;
617 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100618 } else {
619 /* Parent not deriving any more children */
620 /* No need to return parent handle */
621 invalidate_handle(new_parent_ctx_handle);
622 /* Renew nonce of parent context so it cannot be used again */
623 parent_ctx->nonce = INVALID_NONCE_VALUE;
624 }
625
626 return DPE_NO_ERROR;
627}
Maulik Patel54d65f72023-06-28 13:04:36 +0100628
629dpe_error_t destroy_context_request(int input_ctx_handle,
630 bool destroy_recursively)
631{
632 uint16_t input_ctx_idx, linked_layer_idx;
633 int i;
634 bool is_layer_empty;
635
636 log_destroy_context(input_ctx_handle, destroy_recursively);
637
638 /* Get child component index and linked layer from the input handle */
639 input_ctx_idx = GET_IDX(input_ctx_handle);
640
641#ifdef TFM_S_REG_TEST
642 if (input_ctx_idx == 0) {
643 invalidate_layer(DPE_ROT_LAYER_IDX);
644 set_context_to_default(0);
645 return DPE_NO_ERROR;
646 }
647#endif /* TFM_S_REG_TEST */
648
649 /* Validate input handle */
650 if (!is_input_handle_valid(input_ctx_handle)) {
651 return DPE_INVALID_ARGUMENT;
652 }
653 linked_layer_idx = component_ctx_array[input_ctx_idx].linked_layer_idx;
654
655#ifndef TFM_S_REG_TEST
656 if (linked_layer_idx <= DPE_DESTROY_CONTEXT_THRESHOLD_LAYER_IDX) {
657 /* All layers till hypervisor cannot be destroyed dynamically */
658 return DPE_INVALID_ARGUMENT;
659 }
660#endif /* !TFM_S_REG_TEST */
661
662
663 if (!destroy_recursively) {
664 set_context_to_default(input_ctx_idx);
665 } else {
666 //TODO: To be implemented
667 }
668
669 assert(linked_layer_idx < MAX_NUM_OF_LAYERS);
670
671 /* Close the layer if all of its contexts are destroyed */
672 is_layer_empty = true;
673 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
674 if (component_ctx_array[i].linked_layer_idx == linked_layer_idx) {
675 /* There are active component context in the layer */
676 is_layer_empty = false;
677 break;
678 }
679 }
680
681 if (is_layer_empty) {
682 invalidate_layer(linked_layer_idx);
683 }
684
685 return DPE_NO_ERROR;
686}
Maulik Patel2358bbb2023-07-21 10:56:56 +0100687
688struct component_context_t* get_component_if_linked_to_layer(uint16_t layer_idx,
689 uint16_t component_idx)
690{
691 /* Safety case */
692 if (component_idx >= MAX_NUM_OF_COMPONENTS) {
693 return NULL;
694 }
695
696 if (component_ctx_array[component_idx].linked_layer_idx == layer_idx) {
697 return &component_ctx_array[component_idx];
698 } else {
699 return NULL;
700 }
701}
702
Maulik Patele6adc112023-08-18 14:21:51 +0100703struct layer_context_t* get_layer_ctx_ptr(uint16_t layer_idx)
704{
705 /* Safety case */
706 if (layer_idx >= MAX_NUM_OF_LAYERS) {
707 return NULL;
708 }
709
710 return &layer_ctx_array[layer_idx];
711}
712
713dpe_error_t certify_key_request(int input_ctx_handle,
714 bool retain_context,
715 const uint8_t *public_key,
716 size_t public_key_size,
717 const uint8_t *label,
718 size_t label_size,
719 uint8_t *certificate_chain_buf,
720 size_t certificate_chain_buf_size,
721 size_t *certificate_chain_actual_size,
722 uint8_t *derived_public_key_buf,
723 size_t derived_public_key_buf_size,
724 size_t *derived_public_key_actual_size,
725 int *new_context_handle)
726{
727 uint16_t input_ctx_idx, input_layer_idx, parent_layer_idx;
728 dpe_error_t err;
729 psa_status_t status;
730 struct layer_context_t *parent_layer_ctx, *layer_ctx;
731
732 log_certify_key(input_ctx_handle, retain_context, public_key, public_key_size,
733 label, label_size);
734
735 /* Validate input handle */
736 if (!is_input_handle_valid(input_ctx_handle)) {
737 return DPE_INVALID_ARGUMENT;
738 }
739
740 if (label_size > DPE_EXTERNAL_LABEL_MAX_SIZE) {
741 return DPE_INVALID_ARGUMENT;
742 }
743
744 /* Get component index from the input handle */
745 input_ctx_idx = GET_IDX(input_ctx_handle);
746 /* Get current linked layer idx */
747 input_layer_idx = component_ctx_array[input_ctx_idx].linked_layer_idx;
748 assert(input_layer_idx < MAX_NUM_OF_LAYERS);
749
750 layer_ctx = &layer_ctx_array[input_layer_idx];
751 if (public_key_size > sizeof(layer_ctx->data.attest_pub_key)) {
752 return DPE_INVALID_ARGUMENT;
753 }
754
755 if ((public_key_size > 0) && (public_key != NULL)) {
756 layer_ctx->is_external_pub_key_provided = true;
757 /* Copy the public key provided */
758 memcpy(&layer_ctx->data.attest_pub_key[0],
759 public_key,
760 public_key_size);
761 layer_ctx->data.attest_pub_key_len = public_key_size;
762
763 /* If public key is provided, then provided label (if any) is ignored */
764 layer_ctx->data.attest_key_label_len = 0;
765
766 } else {
767 /* No external public key is provided */
768 layer_ctx->is_external_pub_key_provided = false;
769
770 if ((label_size > 0) && (label != NULL)) {
771 /* Copy the label provided */
772 memcpy(&layer_ctx->data.attest_key_label[0],
773 label,
774 label_size);
775 layer_ctx->data.attest_key_label_len = label_size;
776
777 } else {
778 layer_ctx->data.attest_key_label_len = 0;
779 }
780 }
781
782 /* Correct layer should already be assigned in last call of
783 * derive child command
784 */
785 /* Finalise the current layer & create leaf certificate */
786 err = create_layer_certificate(input_layer_idx);
787 if (err != DPE_NO_ERROR) {
788 return err;
789 }
790
791 /* Get parent layer derived public key to verify the certificate signature */
792 parent_layer_idx = layer_ctx_array[input_layer_idx].parent_layer_idx;
793 assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
794 parent_layer_ctx = &layer_ctx_array[parent_layer_idx];
795
796 if (derived_public_key_buf_size < sizeof(parent_layer_ctx->data.attest_pub_key)) {
797 return DPE_INVALID_ARGUMENT;
798 }
799
800 memcpy(derived_public_key_buf,
801 &parent_layer_ctx->data.attest_pub_key[0],
802 parent_layer_ctx->data.attest_pub_key_len);
803 *derived_public_key_actual_size = parent_layer_ctx->data.attest_pub_key_len;
804
805 /* Get certificate chain */
806 err = get_certificate_chain(input_layer_idx,
807 certificate_chain_buf,
808 certificate_chain_buf_size,
809 certificate_chain_actual_size);
810 if (err != DPE_NO_ERROR) {
811 return err;
812 }
813
814 log_certificate_chain(certificate_chain_buf, *certificate_chain_actual_size);
815
816 /* Renew handle for the same context */
817 *new_context_handle = input_ctx_handle;
818 status = renew_nonce(new_context_handle);
819 if (status != PSA_SUCCESS) {
820 return DPE_INTERNAL_ERROR;
821 }
822 component_ctx_array[input_ctx_idx].nonce = GET_NONCE(*new_context_handle);
823
824 /* Clear the context label and key contents */
825 memset(&layer_ctx->data.attest_key_label[0], 0u, layer_ctx->data.attest_key_label_len);
826 memset(&layer_ctx->data.attest_pub_key[0], 0u, layer_ctx->data.attest_pub_key_len);
827
828 return DPE_NO_ERROR;
829}