blob: f6265b9d1d95346a455f98d0682159e3032d7d8f [file] [log] [blame]
Maulik Patelad2f3db2023-05-17 15:41:36 +01001/*
Tamas Bana5e2f582024-01-25 16:59:26 +01002 * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
Maulik Patelad2f3db2023-05-17 15:41:36 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include "dpe_context_mngr.h"
9#include <assert.h>
10#include <string.h>
Maulik Patel009450d2024-04-23 12:03:10 +010011#include "array.h"
Maulik Patelad2f3db2023-05-17 15:41:36 +010012#include "dice_protection_environment.h"
Maulik Patel2358bbb2023-07-21 10:56:56 +010013#include "dpe_certificate.h"
Maulik Patelcb14cde2024-01-23 12:39:53 +000014#include "dpe_client.h"
Maulik Patel58595d32023-06-22 10:08:53 +010015#include "dpe_crypto_interface.h"
Maulik Patelad2f3db2023-05-17 15:41:36 +010016#include "dpe_log.h"
Jamie Fox34681992023-09-04 18:14:06 +010017#include "dpe_plat.h"
Maulik Patelad2f3db2023-05-17 15:41:36 +010018#include "psa/crypto.h"
19
Maulik Patel58595d32023-06-22 10:08:53 +010020#define CONTEXT_DATA_MAX_SIZE sizeof(struct component_context_data_t)
21
Maulik Patelad2f3db2023-05-17 15:41:36 +010022static struct component_context_t component_ctx_array[MAX_NUM_OF_COMPONENTS];
Maulik Patel97a61fe2024-07-01 15:55:04 +010023static struct cert_context_t cert_ctx_array[MAX_NUM_OF_CERTIFICATES];
Maulik Patelad2f3db2023-05-17 15:41:36 +010024
Maulik Patel97a61fe2024-07-01 15:55:04 +010025static dpe_error_t store_linked_component(struct cert_context_t *cert_ctx,
Maulik Patel00d06b62024-07-03 14:51:50 +010026 struct component_context_t *comp_ctx)
Maulik Patel009450d2024-04-23 12:03:10 +010027{
Maulik Patel97a61fe2024-07-01 15:55:04 +010028 if (cert_ctx->linked_components.count >=
Maulik Patel00d06b62024-07-03 14:51:50 +010029 ARRAY_SIZE(cert_ctx->linked_components.ptr)) {
30 /* linked_components.ctx[] is full */
Maulik Patel009450d2024-04-23 12:03:10 +010031 return DPE_INSUFFICIENT_MEMORY;
32 }
33
Maulik Patel00d06b62024-07-03 14:51:50 +010034 cert_ctx->linked_components.ptr[cert_ctx->linked_components.count] = comp_ctx;
Maulik Patel97a61fe2024-07-01 15:55:04 +010035 cert_ctx->linked_components.count++;
Maulik Patel009450d2024-04-23 12:03:10 +010036
37 return DPE_NO_ERROR;
38}
39
Maulik Patel97a61fe2024-07-01 15:55:04 +010040static void remove_linked_component(struct cert_context_t *cert_ctx,
Maulik Patel00d06b62024-07-03 14:51:50 +010041 const struct component_context_t *comp_ctx)
Maulik Patel009450d2024-04-23 12:03:10 +010042{
43 int i, pos;
44
45 /* Find the position of the input component */
Maulik Patel00d06b62024-07-03 14:51:50 +010046 for (i = 0; i < ARRAY_SIZE(cert_ctx->linked_components.ptr); i++) {
47 if (cert_ctx->linked_components.ptr[i] == comp_ctx) {
Maulik Patel009450d2024-04-23 12:03:10 +010048 pos = i;
49 break;
50 }
51 }
52
Maulik Patel00d06b62024-07-03 14:51:50 +010053 assert(i < ARRAY_SIZE(cert_ctx->linked_components.ptr));
Maulik Patel009450d2024-04-23 12:03:10 +010054
55 /* Left shift remaining elements by 1 from current position */
Maulik Patel00d06b62024-07-03 14:51:50 +010056 for(i = pos; i < ARRAY_SIZE(cert_ctx->linked_components.ptr) - 1; i++) {
57 cert_ctx->linked_components.ptr[i] = cert_ctx->linked_components.ptr[i + 1];
Maulik Patel009450d2024-04-23 12:03:10 +010058 }
Maulik Patel00d06b62024-07-03 14:51:50 +010059 cert_ctx->linked_components.ptr[i] = NULL;
Maulik Patel97a61fe2024-07-01 15:55:04 +010060 cert_ctx->linked_components.count--;
Maulik Patel009450d2024-04-23 12:03:10 +010061}
62
Maulik Patelad2f3db2023-05-17 15:41:36 +010063static int get_free_component_context_index(void)
64{
65 int i;
66
67 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
68 if (!component_ctx_array[i].in_use) {
69 break;
70 }
71 }
72
73 if (i >= MAX_NUM_OF_COMPONENTS) {
74 /* No free index left in the array -- all used up! */
75 return -1;
76 }
77
78 return i;
79}
80
Maulik Patelad2f3db2023-05-17 15:41:36 +010081static dpe_error_t renew_nonce(int *handle)
82{
83 uint16_t nonce;
84
85 psa_status_t status = psa_generate_random((uint8_t *)&nonce, sizeof(nonce));
86 if (status != PSA_SUCCESS) {
87 return DPE_INTERNAL_ERROR;
88 }
89 *handle = SET_NONCE(*handle, nonce);
90
91 return DPE_NO_ERROR;
92}
93
Maulik Patel00d06b62024-07-03 14:51:50 +010094static void set_context_to_default(struct component_context_t *comp_ctx)
Maulik Patelad2f3db2023-05-17 15:41:36 +010095{
Maulik Patel00d06b62024-07-03 14:51:50 +010096 comp_ctx->in_use = false;
97 comp_ctx->is_allowed_to_derive = true;
Maulik Patel9fd8bd22023-10-30 10:58:30 +000098 /* export CDI attribute is inherited and once disabled, a derived context
99 * and subsequent derivations cannot export CDI, hence enable by default
100 */
Maulik Patel00d06b62024-07-03 14:51:50 +0100101 comp_ctx->is_export_cdi_allowed = true;
102 comp_ctx->nonce = INVALID_NONCE_VALUE;
103 comp_ctx->parent_comp_ctx = NULL;
104 comp_ctx->linked_cert_ctx = NULL;
105 (void)memset(&comp_ctx->data, 0, sizeof(struct component_context_data_t));
106 comp_ctx->target_locality = DEFAULT_TARGET_LOCALITY;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100107 /* Allow component to be derived by default */
108}
109
Maulik Patel00d06b62024-07-03 14:51:50 +0100110static void initialise_certificate_context(struct cert_context_t *cert_ctx)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100111{
Maulik Patel009450d2024-04-23 12:03:10 +0100112 int j;
113
Maulik Patel00d06b62024-07-03 14:51:50 +0100114 cert_ctx->parent_cert_ptr = NULL;
115 cert_ctx->state = CERT_CTX_UNASSIGNED;
116 cert_ctx->parent_cert_ptr = NULL;
117 cert_ctx->is_cdi_to_be_exported = false;
118 cert_ctx->is_rot_cert_ctx = false;
119 cert_ctx->cert_id = DPE_CERT_ID_INVALID;
120 (void)memset(&cert_ctx->attest_cdi_hash_input, 0,
121 sizeof(cert_ctx->attest_cdi_hash_input));
122 (void)memset(&cert_ctx->data, 0, sizeof(struct cert_context_data_t));
123 cert_ctx->data.cdi_key_id = PSA_KEY_ID_NULL;
124 cert_ctx->data.attest_key_id = PSA_KEY_ID_NULL;
125 cert_ctx->linked_components.count = 0;
126 for (j = 0; j < ARRAY_SIZE(cert_ctx->linked_components.ptr); j++) {
127 cert_ctx->linked_components.ptr[j] = NULL;
Maulik Patel009450d2024-04-23 12:03:10 +0100128 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100129}
130
Maulik Patel00d06b62024-07-03 14:51:50 +0100131static void free_certificate_context(struct cert_context_t *cert_ctx)
Maulik Patelfb2db1c2024-04-12 11:11:21 +0100132{
Maulik Patel00d06b62024-07-03 14:51:50 +0100133 destroy_certificate_context_keys(cert_ctx);
134 initialise_certificate_context(cert_ctx);
Maulik Patelfb2db1c2024-04-12 11:11:21 +0100135}
136
Maulik Patelad2f3db2023-05-17 15:41:36 +0100137static dpe_error_t copy_dice_input(struct component_context_t *dest_ctx,
138 const DiceInputValues *dice_inputs)
139{
140 size_t hash_len;
141 psa_status_t status;
142
143 memcpy(&dest_ctx->data.measurement_value, dice_inputs->code_hash,
144 DICE_HASH_SIZE);
145 memcpy(&dest_ctx->data.measurement_descriptor,
146 dice_inputs->code_descriptor,
147 dice_inputs->code_descriptor_size);
148
149 dest_ctx->data.measurement_descriptor_size =
150 dice_inputs->code_descriptor_size;
151
152 memcpy(&dest_ctx->data.signer_id, dice_inputs->authority_hash, DICE_HASH_SIZE);
153 memcpy(&dest_ctx->data.signer_id_descriptor,
154 dice_inputs->authority_descriptor,
155 dice_inputs->authority_descriptor_size);
156
157 dest_ctx->data.signer_id_descriptor_size =
158 dice_inputs->authority_descriptor_size;
159
160 if (dice_inputs->config_type == kDiceConfigTypeInline) {
161 /* Copy config_value */
162 memcpy(&dest_ctx->data.config_value, dice_inputs->config_value,
163 DICE_INLINE_CONFIG_SIZE);
164
165 } else {
166 /* Copy config descriptor */
167 memcpy(&dest_ctx->data.config_descriptor, dice_inputs->config_descriptor,
168 dice_inputs->config_descriptor_size);
169 dest_ctx->data.config_descriptor_size = dice_inputs->config_descriptor_size;
170
171 /* Calculate config value as hash of input config descriptor */
Maulik Patel2358bbb2023-07-21 10:56:56 +0100172 status = psa_hash_compute(DPE_HASH_ALG,
Maulik Patelad2f3db2023-05-17 15:41:36 +0100173 dice_inputs->config_descriptor,
174 dice_inputs->config_descriptor_size,
175 dest_ctx->data.config_value,
176 sizeof(dest_ctx->data.config_value),
177 &hash_len);
178
179 if (status != PSA_SUCCESS) {
180 return DPE_INTERNAL_ERROR;
181 }
182 }
183
184 dest_ctx->data.mode = dice_inputs->mode;
185 memcpy(&dest_ctx->data.hidden, dice_inputs->hidden, DICE_HIDDEN_SIZE);
186
187 return DPE_NO_ERROR;
188}
189
190static bool is_dice_input_valid(const DiceInputValues *dice_inputs)
191{
192 if ((dice_inputs->code_descriptor_size > DICE_CODE_DESCRIPTOR_MAX_SIZE) ||
193 (dice_inputs->authority_descriptor_size > DICE_AUTHORITY_DESCRIPTOR_MAX_SIZE) ||
194 (dice_inputs->config_descriptor_size > DICE_CONFIG_DESCRIPTOR_MAX_SIZE)) {
195 return false;
196 }
197
198 return true;
199}
200
201static bool is_input_handle_valid(int input_context_handle)
202{
203 uint16_t idx = GET_IDX(input_context_handle);
204 uint16_t nonce = GET_NONCE(input_context_handle);
205
206 /* Validate input handle id and nonce */
207 if ((idx >= MAX_NUM_OF_COMPONENTS) || (nonce == INVALID_NONCE_VALUE)) {
208 return false;
209 }
210
211 if (nonce == component_ctx_array[idx].nonce) {
212 return true;
213 }
214
215 return false;
216}
217
Maulik Patel58595d32023-06-22 10:08:53 +0100218/* Attest_CDI Input requires {measurement_value, config, authority, mode, hidden} in
219 * same order
220 */
221static psa_status_t get_component_data_for_attest_cdi(uint8_t *dest_buf,
222 size_t max_size,
223 size_t *dest_size,
224 const struct component_context_t *comp_ctx)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100225{
Maulik Patel58595d32023-06-22 10:08:53 +0100226 size_t out_size = 0;
227
228 if ((DICE_HASH_SIZE + DICE_INLINE_CONFIG_SIZE + DICE_HASH_SIZE +
229 sizeof(comp_ctx->data.mode) + DICE_HIDDEN_SIZE > max_size )) {
230 return PSA_ERROR_BUFFER_TOO_SMALL;
231 }
232
233 memcpy(&dest_buf[out_size], comp_ctx->data.measurement_value, DICE_HASH_SIZE);
234 out_size += DICE_HASH_SIZE;
235
236 memcpy(&dest_buf[out_size], comp_ctx->data.config_value, DICE_INLINE_CONFIG_SIZE);
237 out_size += DICE_INLINE_CONFIG_SIZE;
238
239 memcpy(&dest_buf[out_size], comp_ctx->data.signer_id, DICE_HASH_SIZE);
240 out_size += DICE_HASH_SIZE;
241
242 memcpy(&dest_buf[out_size], &comp_ctx->data.mode, sizeof(comp_ctx->data.mode));
243 out_size += sizeof(comp_ctx->data.mode);
244
245 memcpy(&dest_buf[out_size], comp_ctx->data.hidden, DICE_HIDDEN_SIZE);
246 out_size += DICE_HIDDEN_SIZE;
247
248 *dest_size = out_size;
249
250 return PSA_SUCCESS;
251}
252
Maulik Patel97a61fe2024-07-01 15:55:04 +0100253static psa_status_t compute_attestation_cdi_input(struct cert_context_t *cert_ctx)
Maulik Patel58595d32023-06-22 10:08:53 +0100254{
255 psa_status_t status;
256 uint8_t component_ctx_data[CONTEXT_DATA_MAX_SIZE];
257 size_t ctx_data_size, hash_len;
Maulik Patel00d06b62024-07-03 14:51:50 +0100258 int i;
Maulik Patel009450d2024-04-23 12:03:10 +0100259 uint16_t num_of_linked_components;
Maulik Patel00d06b62024-07-03 14:51:50 +0100260 struct component_context_t *comp_ctx;
Maulik Patel009450d2024-04-23 12:03:10 +0100261
Maulik Patel97a61fe2024-07-01 15:55:04 +0100262 num_of_linked_components = cert_ctx->linked_components.count;
Maulik Patel009450d2024-04-23 12:03:10 +0100263 if (num_of_linked_components == 0) {
264 /* No components to hash */
265 return PSA_SUCCESS;
266 }
Maulik Patel58595d32023-06-22 10:08:53 +0100267
268 psa_hash_operation_t hash_op = psa_hash_operation_init();
269 status = psa_hash_setup(&hash_op, DPE_HASH_ALG);
270 if (status != PSA_SUCCESS) {
271 return status;
272 }
273
274 //TODO:
275 /* How to combine measurements of multiple SW components into a single hash
276 * is not yet defined by the Open DICE profile. This implementation
Maulik Patel97a61fe2024-07-01 15:55:04 +0100277 * concatenates the data of all SW components which belong to the same
278 * certificate and hash it.
Maulik Patel58595d32023-06-22 10:08:53 +0100279 */
Maulik Patel009450d2024-04-23 12:03:10 +0100280 for (i = 0; i < num_of_linked_components; i++) {
Maulik Patel00d06b62024-07-03 14:51:50 +0100281 comp_ctx = cert_ctx->linked_components.ptr[i];
Maulik Patel009450d2024-04-23 12:03:10 +0100282 status = get_component_data_for_attest_cdi(component_ctx_data,
283 sizeof(component_ctx_data),
284 &ctx_data_size,
Maulik Patel00d06b62024-07-03 14:51:50 +0100285 comp_ctx);
Maulik Patel009450d2024-04-23 12:03:10 +0100286 if (status != PSA_SUCCESS) {
287 return status;
288 }
Maulik Patel58595d32023-06-22 10:08:53 +0100289
Maulik Patel009450d2024-04-23 12:03:10 +0100290 status = psa_hash_update(&hash_op,
291 component_ctx_data,
292 ctx_data_size);
293 if (status != PSA_SUCCESS) {
294 return status;
Maulik Patel58595d32023-06-22 10:08:53 +0100295 }
296 }
297
298 status = psa_hash_finish(&hash_op,
Maulik Patel97a61fe2024-07-01 15:55:04 +0100299 &cert_ctx->attest_cdi_hash_input[0],
300 sizeof(cert_ctx->attest_cdi_hash_input),
Maulik Patel58595d32023-06-22 10:08:53 +0100301 &hash_len);
302
303 assert(hash_len == DPE_HASH_ALG_SIZE);
304
305 return status;
306}
307
Maulik Patel97a61fe2024-07-01 15:55:04 +0100308static dpe_error_t get_encoded_cdi_to_export(struct cert_context_t *cert_ctx,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000309 uint8_t *exported_cdi_buf,
310 size_t exported_cdi_buf_size,
311 size_t *exported_cdi_actual_size)
312{
Tamas Ban5179a4d2024-01-25 17:05:30 +0100313 uint8_t cdi_attest_buf[DICE_CDI_SIZE];
314 uint8_t cdi_seal_buf[DICE_CDI_SIZE];
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000315 psa_status_t status;
316 dpe_error_t err;
317
Tamas Ban5179a4d2024-01-25 17:05:30 +0100318 /* Get CDIs value */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100319 status = get_certificate_cdi_value(cert_ctx,
320 cdi_attest_buf,
321 cdi_seal_buf);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000322 if (status != PSA_SUCCESS) {
323 return DPE_INTERNAL_ERROR;
324 }
325
326 /* Encode CDI value */
Tamas Ban5179a4d2024-01-25 17:05:30 +0100327 err = encode_cdi(cdi_attest_buf,
328 cdi_seal_buf,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000329 exported_cdi_buf,
330 exported_cdi_buf_size,
331 exported_cdi_actual_size);
332 if (err != DPE_NO_ERROR) {
333 return err;
334 }
Maulik Patel97a61fe2024-07-01 15:55:04 +0100335 cert_ctx->is_cdi_to_be_exported = true;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000336
337 return DPE_NO_ERROR;
338}
339
Maulik Patel00d06b62024-07-03 14:51:50 +0100340static dpe_error_t prepare_certificate(struct cert_context_t *cert_ctx)
Maulik Patel58595d32023-06-22 10:08:53 +0100341{
Maulik Patel58595d32023-06-22 10:08:53 +0100342 psa_status_t status;
Maulik Patel00d06b62024-07-03 14:51:50 +0100343 struct cert_context_t *parent_cert_ctx;
344
345 parent_cert_ctx = cert_ctx->parent_cert_ptr;
346 assert(parent_cert_ctx != NULL);
Maulik Patel58595d32023-06-22 10:08:53 +0100347
Maulik Patel97a61fe2024-07-01 15:55:04 +0100348 /* For RoT certificate, CDI and issuer seed values are calculated by BL1_1 */
349 if ((!cert_ctx->is_rot_cert_ctx) &&
350 (!cert_ctx->is_external_pub_key_provided)) {
Maulik Patel58595d32023-06-22 10:08:53 +0100351
Maulik Patel97a61fe2024-07-01 15:55:04 +0100352 /* Except for RoT certificate with no external public key supplied */
Maulik Patel58595d32023-06-22 10:08:53 +0100353
Maulik Patel97a61fe2024-07-01 15:55:04 +0100354 status = compute_attestation_cdi_input(cert_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100355 if (status != PSA_SUCCESS) {
356 return DPE_INTERNAL_ERROR;
357 }
358
Maulik Patel97a61fe2024-07-01 15:55:04 +0100359 status = derive_attestation_cdi(cert_ctx, parent_cert_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100360 if (status != PSA_SUCCESS) {
361 return DPE_INTERNAL_ERROR;
362 }
363
Maulik Patel97a61fe2024-07-01 15:55:04 +0100364 status = derive_sealing_cdi(cert_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100365 if (status != PSA_SUCCESS) {
366 return DPE_INTERNAL_ERROR;
367 }
368 }
369
Maulik Patel97a61fe2024-07-01 15:55:04 +0100370 status = derive_wrapping_key(cert_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100371 if (status != PSA_SUCCESS) {
372 return DPE_INTERNAL_ERROR;
373 }
374
Maulik Patel97a61fe2024-07-01 15:55:04 +0100375 if (!cert_ctx->is_external_pub_key_provided) {
376 status = derive_attestation_key(cert_ctx);
Maulik Patele6adc112023-08-18 14:21:51 +0100377 if (status != PSA_SUCCESS) {
378 return DPE_INTERNAL_ERROR;
379 }
Maulik Patel58595d32023-06-22 10:08:53 +0100380 }
381
Maulik Patel97a61fe2024-07-01 15:55:04 +0100382 status = derive_id_from_public_key(cert_ctx);
Maulik Patel58595d32023-06-22 10:08:53 +0100383 if (status != PSA_SUCCESS) {
384 return DPE_INTERNAL_ERROR;
385 }
386
Tamas Ban257471b2024-03-25 13:49:53 +0100387 return DPE_NO_ERROR;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100388}
389
Maulik Patel00d06b62024-07-03 14:51:50 +0100390static struct cert_context_t* assign_new_certificate_context(void)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100391{
392 int i;
393
Maulik Patel97a61fe2024-07-01 15:55:04 +0100394 for (i = 0; i < MAX_NUM_OF_CERTIFICATES; i++) {
395 if (cert_ctx_array[i].state == CERT_CTX_UNASSIGNED) {
396 cert_ctx_array[i].state = CERT_CTX_ASSIGNED;
Maulik Patel00d06b62024-07-03 14:51:50 +0100397 return &cert_ctx_array[i];
Maulik Patelad2f3db2023-05-17 15:41:36 +0100398 }
399 }
400
Maulik Patel00d06b62024-07-03 14:51:50 +0100401 return NULL;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100402}
403
Maulik Patel9b13e162024-04-24 14:18:17 +0100404static bool is_client_authorised(int32_t client_id, int32_t target_locality)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100405{
Maulik Patel9b13e162024-04-24 14:18:17 +0100406 int32_t client_locality;
407
408 if (target_locality == LOCALITY_NONE) {
409 /* Context is not bound to any locality */
410 return true;
411 }
412 /* Get the corresponding client locality */
413 client_locality = dpe_plat_get_client_locality(client_id);
414
415 return (client_locality == target_locality);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100416}
417
Maulik Patel00d06b62024-07-03 14:51:50 +0100418static bool is_cert_id_used(uint32_t cert_id, struct cert_context_t **cert_ctx)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100419{
Maulik Patelcb14cde2024-01-23 12:39:53 +0000420 int i;
421
Maulik Patel97a61fe2024-07-01 15:55:04 +0100422 for (i = 0; i < MAX_NUM_OF_CERTIFICATES; i++) {
423 if (cert_ctx_array[i].cert_id == cert_id) {
Maulik Patel00d06b62024-07-03 14:51:50 +0100424 *cert_ctx = &cert_ctx_array[i];
Maulik Patelcb14cde2024-01-23 12:39:53 +0000425 return true;
426 }
427 }
428
429 /* No certificate ID match found */
430 return false;
431}
432
Maulik Patel97a61fe2024-07-01 15:55:04 +0100433static dpe_error_t assign_certificate_to_component(struct component_context_t *new_ctx,
434 uint32_t cert_id)
Maulik Patelcb14cde2024-01-23 12:39:53 +0000435{
Maulik Patel00d06b62024-07-03 14:51:50 +0100436 struct cert_context_t *parent_cert_ctx, *cert_ctx_to_link = NULL;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100437
Maulik Patel00d06b62024-07-03 14:51:50 +0100438 assert(new_ctx->parent_comp_ctx != NULL);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100439
Maulik Patel00d06b62024-07-03 14:51:50 +0100440 parent_cert_ctx = new_ctx->parent_comp_ctx->linked_cert_ctx;
441 assert(parent_cert_ctx != NULL);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100442
Maulik Patelcb14cde2024-01-23 12:39:53 +0000443 if (cert_id != DPE_CERT_ID_INVALID) {
Tamas Ban33f1aec2024-06-04 12:15:18 +0200444 /* Cert_id was sent by the client */
Maulik Patelcb14cde2024-01-23 12:39:53 +0000445 if (cert_id == DPE_CERT_ID_SAME_AS_PARENT) {
Maulik Patel00d06b62024-07-03 14:51:50 +0100446 if (parent_cert_ctx->state == CERT_CTX_FINALISED) {
Maulik Patel97a61fe2024-07-01 15:55:04 +0100447 /* Cannot add to the certificate context which is already finalised */
Maulik Patelcb14cde2024-01-23 12:39:53 +0000448 return DPE_INTERNAL_ERROR;
449 }
450 /* Derived context belongs to the same certificate as its parent component */
Maulik Patel00d06b62024-07-03 14:51:50 +0100451 new_ctx->linked_cert_ctx = parent_cert_ctx;
Maulik Patelcb14cde2024-01-23 12:39:53 +0000452
Maulik Patel00d06b62024-07-03 14:51:50 +0100453 } else if (is_cert_id_used(cert_id, &cert_ctx_to_link)) {
Maulik Patel97a61fe2024-07-01 15:55:04 +0100454 /* Cert_id is already in use but certificate context must be assigned, because
Maulik Patel00d06b62024-07-03 14:51:50 +0100455 * cert_id is invalidated when certificate context gets finalised.
Tamas Ban33f1aec2024-06-04 12:15:18 +0200456 */
Maulik Patel00d06b62024-07-03 14:51:50 +0100457 assert(cert_ctx_to_link->state != CERT_CTX_FINALISED);
Tamas Ban33f1aec2024-06-04 12:15:18 +0200458
Maulik Patel97a61fe2024-07-01 15:55:04 +0100459 /* Use the same certificate context that is associated with cert_id */
Maulik Patel00d06b62024-07-03 14:51:50 +0100460 new_ctx->linked_cert_ctx = cert_ctx_to_link;
Maulik Patel97a61fe2024-07-01 15:55:04 +0100461 /* Linked certificate context's parent is already assigned */
Maulik Patelcb14cde2024-01-23 12:39:53 +0000462
463 } else {
Maulik Patel97a61fe2024-07-01 15:55:04 +0100464 /* Assign new certificate context and link derived context to it */
Maulik Patel00d06b62024-07-03 14:51:50 +0100465 cert_ctx_to_link = assign_new_certificate_context();
466 if (cert_ctx_to_link == NULL) {
Maulik Patelcb14cde2024-01-23 12:39:53 +0000467 return DPE_INTERNAL_ERROR;
468 }
Maulik Patel97a61fe2024-07-01 15:55:04 +0100469 /* Link this context to the new certificate context */
Maulik Patel00d06b62024-07-03 14:51:50 +0100470 new_ctx->linked_cert_ctx = cert_ctx_to_link;
Maulik Patel97a61fe2024-07-01 15:55:04 +0100471 /* New certificate context's parent is parent component's certificate context */
Maulik Patel00d06b62024-07-03 14:51:50 +0100472 cert_ctx_to_link->parent_cert_ptr = parent_cert_ctx;
473 cert_ctx_to_link->cert_id = cert_id;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100474 }
Maulik Patelad2f3db2023-05-17 15:41:36 +0100475
476 } else {
Maulik Patelcb14cde2024-01-23 12:39:53 +0000477 /* cert id was not sent by the client */
478 //TODO: To be implemented; return error for now.
479 return DPE_INVALID_ARGUMENT;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100480 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100481
482 return DPE_NO_ERROR;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100483}
484
Jamie Fox34681992023-09-04 18:14:06 +0100485/**
486 * \brief Create a root of trust component context.
487 *
488 * \param[out] rot_ctx_handle A new context handle for the RoT context.
489 *
490 * \return Returns error code of type dpe_error_t
491 */
492static dpe_error_t create_rot_context(int *rot_ctx_handle)
493{
Jamie Fox34681992023-09-04 18:14:06 +0100494 struct component_context_t *rot_comp_ctx = &component_ctx_array[0];
Maulik Patel00d06b62024-07-03 14:51:50 +0100495 struct cert_context_t *rot_cert_ctx = &cert_ctx_array[0];
Jamie Fox34681992023-09-04 18:14:06 +0100496
Maulik Patel97a61fe2024-07-01 15:55:04 +0100497 rot_cert_ctx->is_rot_cert_ctx = true;
Maulik Patel00d06b62024-07-03 14:51:50 +0100498 rot_cert_ctx->parent_cert_ptr = NULL;
Maulik Patel97a61fe2024-07-01 15:55:04 +0100499 /* Get the RoT CDI key for the RoT certificate */
500 rot_cert_ctx->data.cdi_key_id = dpe_plat_get_rot_cdi_key_id();
Maulik Patela81605b2023-10-24 12:17:03 +0100501 /* Init RoT context, ready to be derived in next call to DeriveContext */
Jamie Fox34681992023-09-04 18:14:06 +0100502 rot_comp_ctx->nonce = 0;
Maulik Patelacc3f4a2024-03-25 18:34:05 +0000503 /* Set the target locality for RoT context */
504 rot_comp_ctx->target_locality = LOCALITY_RSE_S;
Maulik Patel00d06b62024-07-03 14:51:50 +0100505 /* Parent component for derived RoT context is same.
506 * It is not set to NULL as later on when creating certificate and
507 * parent_comp_ctx pointer is checked against NULL value */
508 rot_comp_ctx->parent_comp_ctx = rot_comp_ctx;
Maulik Patel97a61fe2024-07-01 15:55:04 +0100509 /* Link context to RoT certificate */
Maulik Patel00d06b62024-07-03 14:51:50 +0100510 rot_comp_ctx->linked_cert_ctx = rot_cert_ctx;
Jamie Fox34681992023-09-04 18:14:06 +0100511 rot_comp_ctx->expected_mhu_id = 0;
Jamie Fox34681992023-09-04 18:14:06 +0100512 *rot_ctx_handle = 0; /* index = 0, nonce = 0 */
513
514 return DPE_NO_ERROR;
515}
516
517dpe_error_t initialise_context_mngr(int *rot_ctx_handle)
518{
519 int i;
520
521 for (i = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
Maulik Patel00d06b62024-07-03 14:51:50 +0100522 set_context_to_default(&component_ctx_array[i]);
Jamie Fox34681992023-09-04 18:14:06 +0100523 }
524
Maulik Patel97a61fe2024-07-01 15:55:04 +0100525 for (i = 0; i < MAX_NUM_OF_CERTIFICATES; i++) {
Maulik Patel00d06b62024-07-03 14:51:50 +0100526 initialise_certificate_context(&cert_ctx_array[i]);
Jamie Fox34681992023-09-04 18:14:06 +0100527 }
528
529 return create_rot_context(rot_ctx_handle);
530}
531
Maulik Patel00d06b62024-07-03 14:51:50 +0100532static void free_certificate_context_if_empty(struct cert_context_t *cert_ctx)
Maulik Patel9a893122024-04-15 13:48:38 +0100533{
Maulik Patel00d06b62024-07-03 14:51:50 +0100534 if (cert_ctx->linked_components.count == 0) {
535 free_certificate_context(cert_ctx);
Maulik Patel9a893122024-04-15 13:48:38 +0100536 }
537}
538
Maulik Patela81605b2023-10-24 12:17:03 +0100539dpe_error_t derive_context_request(int input_ctx_handle,
Maulik Patelcb14cde2024-01-23 12:39:53 +0000540 uint32_t cert_id,
Maulik Patela81605b2023-10-24 12:17:03 +0100541 bool retain_parent_context,
542 bool allow_new_context_to_derive,
543 bool create_certificate,
544 const DiceInputValues *dice_inputs,
545 int32_t client_id,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000546 int32_t target_locality,
547 bool return_certificate,
548 bool allow_new_context_to_export,
549 bool export_cdi,
Maulik Patela81605b2023-10-24 12:17:03 +0100550 int *new_context_handle,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000551 int *new_parent_context_handle,
552 uint8_t *new_certificate_buf,
553 size_t new_certificate_buf_size,
554 size_t *new_certificate_actual_size,
555 uint8_t *exported_cdi_buf,
556 size_t exported_cdi_buf_size,
557 size_t *exported_cdi_actual_size)
Maulik Patelad2f3db2023-05-17 15:41:36 +0100558{
Maulik Patel58595d32023-06-22 10:08:53 +0100559 dpe_error_t err;
Maulik Patela81605b2023-10-24 12:17:03 +0100560 struct component_context_t *parent_ctx, *derived_ctx;
Maulik Patel00d06b62024-07-03 14:51:50 +0100561 uint16_t parent_ctx_idx;
Maulik Patela81605b2023-10-24 12:17:03 +0100562 int free_component_idx;
Maulik Patel00d06b62024-07-03 14:51:50 +0100563 struct cert_context_t *cert_ctx = NULL;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100564
Maulik Patelcb14cde2024-01-23 12:39:53 +0000565 log_derive_context(input_ctx_handle, cert_id, retain_parent_context,
Maulik Patela81605b2023-10-24 12:17:03 +0100566 allow_new_context_to_derive, create_certificate, dice_inputs,
567 client_id);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100568
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000569 if (export_cdi && !create_certificate) {
570 return DPE_INVALID_ARGUMENT;
571 }
572
Maulik Patelad2f3db2023-05-17 15:41:36 +0100573 /* Validate dice inputs */
574 if (!is_dice_input_valid(dice_inputs)) {
575 return DPE_INVALID_ARGUMENT;
576 }
577
578 /* Validate input handle */
579 if (!is_input_handle_valid(input_ctx_handle)) {
580 return DPE_INVALID_ARGUMENT;
581 }
Maulik Patela81605b2023-10-24 12:17:03 +0100582 /* Get parent component index from the input handle */
583 parent_ctx_idx = GET_IDX(input_ctx_handle);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100584
585 /* Below check is for safety only; It should not happen
Maulik Patela81605b2023-10-24 12:17:03 +0100586 * parent_ctx_idx is already checked above in is_input_handle_valid()
Maulik Patelad2f3db2023-05-17 15:41:36 +0100587 */
Maulik Patela81605b2023-10-24 12:17:03 +0100588 assert(parent_ctx_idx < MAX_NUM_OF_COMPONENTS);
Maulik Patelad2f3db2023-05-17 15:41:36 +0100589
Maulik Patela81605b2023-10-24 12:17:03 +0100590 parent_ctx = &component_ctx_array[parent_ctx_idx];
Maulik Patelad2f3db2023-05-17 15:41:36 +0100591
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000592 /* Check if parent context is allowed to derive */
593 if (!parent_ctx->is_allowed_to_derive) {
594 return DPE_INVALID_ARGUMENT;
595 }
596
Maulik Patel9b13e162024-04-24 14:18:17 +0100597 if (!is_client_authorised(client_id, parent_ctx->target_locality)) {
Maulik Patelad2f3db2023-05-17 15:41:36 +0100598 return DPE_INVALID_ARGUMENT;
599 }
600
Maulik Patela81605b2023-10-24 12:17:03 +0100601 /* Get next free component index to add new derived context */
602 free_component_idx = get_free_component_context_index();
603 if (free_component_idx < 0) {
604 return DPE_INSUFFICIENT_MEMORY;
605 }
606
607 derived_ctx = &component_ctx_array[free_component_idx];
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000608 if (parent_ctx->is_export_cdi_allowed && allow_new_context_to_export) {
609 /* If parent context has export enabled and input allow_new_context_to_export
610 * is true, then allow context CDI to be exported for derived context
611 */
612 derived_ctx->is_export_cdi_allowed = true;
613 } else {
614 /* Export of new context CDI is NOT allowed */
615 derived_ctx->is_export_cdi_allowed = false;
616 if (export_cdi) {
617 return DPE_INVALID_ARGUMENT;
618 }
619 }
620
Maulik Patela81605b2023-10-24 12:17:03 +0100621 /* Copy dice input to the new derived component context */
622 err = copy_dice_input(derived_ctx, dice_inputs);
Maulik Patel58595d32023-06-22 10:08:53 +0100623 if (err != DPE_NO_ERROR) {
624 return err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100625 }
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000626 derived_ctx->target_locality = target_locality;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100627
Maulik Patel00d06b62024-07-03 14:51:50 +0100628 /* Update parent component in new derived component context */
629 derived_ctx->parent_comp_ctx = parent_ctx;
Maulik Patela81605b2023-10-24 12:17:03 +0100630 /* Mark new derived component index as in use */
631 derived_ctx->in_use = true;
Maulik Pateld2806072024-02-02 10:30:08 +0000632 derived_ctx->is_allowed_to_derive = allow_new_context_to_derive;
Maulik Patel97a61fe2024-07-01 15:55:04 +0100633 /* Assign certificate to the component */
634 err = assign_certificate_to_component(derived_ctx, cert_id);
Maulik Patela81605b2023-10-24 12:17:03 +0100635 if (err != DPE_NO_ERROR) {
636 return err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100637 }
638
Maulik Patel00d06b62024-07-03 14:51:50 +0100639 cert_ctx = derived_ctx->linked_cert_ctx;
640 assert(cert_ctx != NULL);
641 err = store_linked_component(cert_ctx, derived_ctx);
Maulik Patel9a893122024-04-15 13:48:38 +0100642 if (err != DPE_NO_ERROR) {
643 goto clean_up_and_exit;
644 }
Maulik Patel9a893122024-04-15 13:48:38 +0100645
646 if (create_certificate) {
Maulik Patel97a61fe2024-07-01 15:55:04 +0100647 cert_ctx->is_cdi_to_be_exported = export_cdi;
Maulik Patel9a893122024-04-15 13:48:38 +0100648
Maulik Patel97a61fe2024-07-01 15:55:04 +0100649 /* Finalise the certificate context */
650 cert_ctx->state = CERT_CTX_FINALISED;
651 cert_ctx->cert_id = DPE_CERT_ID_INVALID; /* make same cert_id reusable */
Maulik Patel00d06b62024-07-03 14:51:50 +0100652 err = prepare_certificate(cert_ctx);
Maulik Patel9a893122024-04-15 13:48:38 +0100653 if (err != DPE_NO_ERROR) {
654 goto clean_up_and_exit;
655 }
656
657 if (return_certificate) {
Maulik Patel97a61fe2024-07-01 15:55:04 +0100658 /* Encode and return generated certificate */
659 err = encode_certificate(cert_ctx,
660 new_certificate_buf,
661 new_certificate_buf_size,
662 new_certificate_actual_size);
Maulik Patel9a893122024-04-15 13:48:38 +0100663 if (err != DPE_NO_ERROR) {
664 goto clean_up_and_exit;
665 }
666 }
667 }
668
669 if (export_cdi) {
Maulik Patel97a61fe2024-07-01 15:55:04 +0100670 err = get_encoded_cdi_to_export(cert_ctx,
Maulik Patel9a893122024-04-15 13:48:38 +0100671 exported_cdi_buf,
672 exported_cdi_buf_size,
673 exported_cdi_actual_size);
674 if (err != DPE_NO_ERROR) {
675 goto clean_up_and_exit;
676 }
677 }
678
Maulik Patelad2f3db2023-05-17 15:41:36 +0100679 if (retain_parent_context) {
Maulik Patela81605b2023-10-24 12:17:03 +0100680 /* Retain and return parent handle with renewed nonce */
681 *new_parent_context_handle = input_ctx_handle;
682 err = renew_nonce(new_parent_context_handle);
Jamie Fox34681992023-09-04 18:14:06 +0100683 if (err != DPE_NO_ERROR) {
Maulik Patel9a893122024-04-15 13:48:38 +0100684 goto clean_up_and_exit;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100685 }
Maulik Patela81605b2023-10-24 12:17:03 +0100686 parent_ctx->nonce = GET_NONCE(*new_parent_context_handle);
687
Maulik Patelad2f3db2023-05-17 15:41:36 +0100688 } else {
Maulik Patela81605b2023-10-24 12:17:03 +0100689 /* Return invalid handle */
690 *new_parent_context_handle = INVALID_HANDLE;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100691 parent_ctx->nonce = INVALID_NONCE_VALUE;
692 }
693
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000694 if (!export_cdi) {
Maulik Patela81605b2023-10-24 12:17:03 +0100695 /* Return handle to derived context */
696 *new_context_handle = SET_IDX(*new_context_handle, free_component_idx);
697 err = renew_nonce(new_context_handle);
698 if (err != DPE_NO_ERROR) {
699 return err;
700 }
701 /* Update nonce in new derived component context */
702 derived_ctx->nonce = GET_NONCE(*new_context_handle);
703
704 } else {
705 /* Return invalid handle */
706 *new_context_handle = INVALID_HANDLE;
707 derived_ctx->nonce = INVALID_NONCE_VALUE;
708 }
709
Maulik Patel9a2a5672024-03-14 13:43:58 +0000710 log_derive_context_output_handles(*new_parent_context_handle,
711 *new_context_handle);
Maulik Patela81605b2023-10-24 12:17:03 +0100712
Maulik Patel97a61fe2024-07-01 15:55:04 +0100713 /* Log component context, certificate context & certificate if no error */
Maulik Patel5ac87802024-03-14 14:22:19 +0000714 log_dpe_component_ctx_metadata(derived_ctx, free_component_idx);
Maulik Patel00d06b62024-07-03 14:51:50 +0100715 if (cert_ctx != NULL) {
716 log_dpe_cert_ctx_metadata(cert_ctx);
717 }
Jamie Fox4b8a6d62024-04-11 15:19:08 +0100718 if (return_certificate) {
Maulik Patel00d06b62024-07-03 14:51:50 +0100719 log_intermediate_certificate(new_certificate_buf,
Tamas Ban257471b2024-03-25 13:49:53 +0100720 *new_certificate_actual_size);
Maulik Patel5ac87802024-03-14 14:22:19 +0000721 }
722
Maulik Patelad2f3db2023-05-17 15:41:36 +0100723 return DPE_NO_ERROR;
Maulik Patel9a893122024-04-15 13:48:38 +0100724
725clean_up_and_exit:
Maulik Patel00d06b62024-07-03 14:51:50 +0100726 set_context_to_default(derived_ctx);
727 free_certificate_context_if_empty(cert_ctx);
Maulik Patel9a893122024-04-15 13:48:38 +0100728
729 return err;
Maulik Patelad2f3db2023-05-17 15:41:36 +0100730}
Maulik Patel54d65f72023-06-28 13:04:36 +0100731
732dpe_error_t destroy_context_request(int input_ctx_handle,
733 bool destroy_recursively)
734{
Maulik Patel00d06b62024-07-03 14:51:50 +0100735 uint16_t input_ctx_idx;
Maulik Patel97a61fe2024-07-01 15:55:04 +0100736 struct cert_context_t *cert_ctx;
Maulik Patel54d65f72023-06-28 13:04:36 +0100737
738 log_destroy_context(input_ctx_handle, destroy_recursively);
739
Maulik Patel97a61fe2024-07-01 15:55:04 +0100740 /* Get component index and linked certificate context from the input handle */
Maulik Patel54d65f72023-06-28 13:04:36 +0100741 input_ctx_idx = GET_IDX(input_ctx_handle);
742
Maulik Patel54d65f72023-06-28 13:04:36 +0100743 /* Validate input handle */
744 if (!is_input_handle_valid(input_ctx_handle)) {
745 return DPE_INVALID_ARGUMENT;
746 }
Maulik Patel00d06b62024-07-03 14:51:50 +0100747 cert_ctx = component_ctx_array[input_ctx_idx].linked_cert_ctx;
Maulik Patel54d65f72023-06-28 13:04:36 +0100748
Jamie Fox34681992023-09-04 18:14:06 +0100749#ifndef DPE_TEST_MODE
Maulik Patel00d06b62024-07-03 14:51:50 +0100750 //TODO: Prevent destruction of context if it belongs to RoT, Platform, AP FW
751 // or any platform configuration dependent certificate.
Jamie Fox34681992023-09-04 18:14:06 +0100752#endif /* !DPE_TEST_MODE */
Maulik Patel54d65f72023-06-28 13:04:36 +0100753
Maulik Patel00d06b62024-07-03 14:51:50 +0100754 assert(cert_ctx != NULL);
Maulik Patel54d65f72023-06-28 13:04:36 +0100755
756 if (!destroy_recursively) {
Maulik Patel00d06b62024-07-03 14:51:50 +0100757 set_context_to_default(&component_ctx_array[input_ctx_idx]);
758 remove_linked_component(cert_ctx, &component_ctx_array[input_ctx_idx]);
Maulik Patel54d65f72023-06-28 13:04:36 +0100759 } else {
760 //TODO: To be implemented
761 }
762
Maulik Patel97a61fe2024-07-01 15:55:04 +0100763 /* Free the certificate context if all of its components are destroyed */
Maulik Patel00d06b62024-07-03 14:51:50 +0100764 free_certificate_context_if_empty(cert_ctx);
Maulik Patel54d65f72023-06-28 13:04:36 +0100765
766 return DPE_NO_ERROR;
767}
Maulik Patel2358bbb2023-07-21 10:56:56 +0100768
Maulik Patele6adc112023-08-18 14:21:51 +0100769dpe_error_t certify_key_request(int input_ctx_handle,
770 bool retain_context,
771 const uint8_t *public_key,
772 size_t public_key_size,
773 const uint8_t *label,
774 size_t label_size,
Maulik Patelcbded682023-12-07 11:50:16 +0000775 uint8_t *certificate_buf,
776 size_t certificate_buf_size,
777 size_t *certificate_actual_size,
Maulik Patele6adc112023-08-18 14:21:51 +0100778 uint8_t *derived_public_key_buf,
779 size_t derived_public_key_buf_size,
780 size_t *derived_public_key_actual_size,
781 int *new_context_handle)
782{
Maulik Patel00d06b62024-07-03 14:51:50 +0100783 uint16_t input_ctx_idx;
Maulik Patele6adc112023-08-18 14:21:51 +0100784 dpe_error_t err;
785 psa_status_t status;
Maulik Patel97a61fe2024-07-01 15:55:04 +0100786 struct cert_context_t *parent_cert_ctx, *input_cert_ctx;
787 struct cert_context_t leaf_cert_ctx = {0};
Maulik Patele6adc112023-08-18 14:21:51 +0100788
789 log_certify_key(input_ctx_handle, retain_context, public_key, public_key_size,
790 label, label_size);
791
792 /* Validate input handle */
793 if (!is_input_handle_valid(input_ctx_handle)) {
794 return DPE_INVALID_ARGUMENT;
795 }
796
797 if (label_size > DPE_EXTERNAL_LABEL_MAX_SIZE) {
798 return DPE_INVALID_ARGUMENT;
799 }
800
801 /* Get component index from the input handle */
802 input_ctx_idx = GET_IDX(input_ctx_handle);
Maulik Patel97a61fe2024-07-01 15:55:04 +0100803 /* Get current linked certificate context idx */
Maulik Patel00d06b62024-07-03 14:51:50 +0100804 input_cert_ctx = component_ctx_array[input_ctx_idx].linked_cert_ctx;
805 assert(input_cert_ctx != NULL);
Maulik Patele6adc112023-08-18 14:21:51 +0100806
Maulik Patel97a61fe2024-07-01 15:55:04 +0100807 if (input_cert_ctx->state == CERT_CTX_FINALISED) {
808 /* Input certificate context is finalised,
809 * new leaf certificate context is its child now
810 */
Maulik Patel00d06b62024-07-03 14:51:50 +0100811 leaf_cert_ctx.parent_cert_ptr = input_cert_ctx;
Tamas Baneb8d7f12024-04-03 13:55:22 +0200812 /* Linked components count already initialised to 0 */
813
814 } else {
Maulik Patel97a61fe2024-07-01 15:55:04 +0100815 /* Input certificate context is not finalised,
816 * new leaf certificate context share the same components as in the
817 * input certificate context
Tamas Baneb8d7f12024-04-03 13:55:22 +0200818 */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100819 memcpy(&leaf_cert_ctx.linked_components, &input_cert_ctx->linked_components,
820 sizeof(input_cert_ctx->linked_components));
Maulik Patel00d06b62024-07-03 14:51:50 +0100821 leaf_cert_ctx.parent_cert_ptr = input_cert_ctx->parent_cert_ptr;
Tamas Baneb8d7f12024-04-03 13:55:22 +0200822 }
Maulik Patel7cc80872024-04-04 12:00:29 +0100823
Maulik Patel97a61fe2024-07-01 15:55:04 +0100824 if (public_key_size > sizeof(leaf_cert_ctx.data.attest_pub_key)) {
Maulik Patele6adc112023-08-18 14:21:51 +0100825 return DPE_INVALID_ARGUMENT;
826 }
827
828 if ((public_key_size > 0) && (public_key != NULL)) {
Maulik Patel97a61fe2024-07-01 15:55:04 +0100829 leaf_cert_ctx.is_external_pub_key_provided = true;
Maulik Patele6adc112023-08-18 14:21:51 +0100830 /* Copy the public key provided */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100831 memcpy(&leaf_cert_ctx.data.attest_pub_key[0],
Maulik Patele6adc112023-08-18 14:21:51 +0100832 public_key,
833 public_key_size);
Maulik Patel97a61fe2024-07-01 15:55:04 +0100834 leaf_cert_ctx.data.attest_pub_key_len = public_key_size;
Maulik Patele6adc112023-08-18 14:21:51 +0100835
836 /* If public key is provided, then provided label (if any) is ignored */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100837 leaf_cert_ctx.data.external_key_deriv_label_len = 0;
Maulik Patele6adc112023-08-18 14:21:51 +0100838
839 } else {
840 /* No external public key is provided */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100841 leaf_cert_ctx.is_external_pub_key_provided = false;
Maulik Patele6adc112023-08-18 14:21:51 +0100842
843 if ((label_size > 0) && (label != NULL)) {
844 /* Copy the label provided */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100845 memcpy(&leaf_cert_ctx.data.external_key_deriv_label[0],
Maulik Patele6adc112023-08-18 14:21:51 +0100846 label,
847 label_size);
Maulik Patel97a61fe2024-07-01 15:55:04 +0100848 leaf_cert_ctx.data.external_key_deriv_label_len = label_size;
Maulik Patele6adc112023-08-18 14:21:51 +0100849
850 } else {
Maulik Patel97a61fe2024-07-01 15:55:04 +0100851 leaf_cert_ctx.data.external_key_deriv_label_len = 0;
Maulik Patele6adc112023-08-18 14:21:51 +0100852 }
853 }
854
Maulik Patel97a61fe2024-07-01 15:55:04 +0100855 /* Get parent certificate's derived public key to verify the certificate signature */
Maulik Patel00d06b62024-07-03 14:51:50 +0100856 parent_cert_ctx = leaf_cert_ctx.parent_cert_ptr;
857 assert(parent_cert_ctx != NULL);
Maulik Patel009450d2024-04-23 12:03:10 +0100858
Maulik Patel97a61fe2024-07-01 15:55:04 +0100859 /* Correct certificate context should already be assigned in last call of
Maulik Patela81605b2023-10-24 12:17:03 +0100860 * derive context command
Maulik Patele6adc112023-08-18 14:21:51 +0100861 */
Maulik Patelcbded682023-12-07 11:50:16 +0000862 /* Create leaf certificate */
Maulik Patel00d06b62024-07-03 14:51:50 +0100863 err = prepare_certificate(&leaf_cert_ctx);
Tamas Ban257471b2024-03-25 13:49:53 +0100864 if (err != DPE_NO_ERROR) {
865 return err;
866 }
867
Maulik Patel97a61fe2024-07-01 15:55:04 +0100868 err = encode_certificate(&leaf_cert_ctx,
Tamas Ban257471b2024-03-25 13:49:53 +0100869 certificate_buf,
870 certificate_buf_size,
871 certificate_actual_size);
Maulik Patele6adc112023-08-18 14:21:51 +0100872 if (err != DPE_NO_ERROR) {
873 return err;
874 }
875
Maulik Patel97a61fe2024-07-01 15:55:04 +0100876 if (derived_public_key_buf_size < sizeof(parent_cert_ctx->data.attest_pub_key)) {
Maulik Patele6adc112023-08-18 14:21:51 +0100877 return DPE_INVALID_ARGUMENT;
878 }
879
880 memcpy(derived_public_key_buf,
Maulik Patel97a61fe2024-07-01 15:55:04 +0100881 &parent_cert_ctx->data.attest_pub_key[0],
882 parent_cert_ctx->data.attest_pub_key_len);
883 *derived_public_key_actual_size = parent_cert_ctx->data.attest_pub_key_len;
Maulik Patele6adc112023-08-18 14:21:51 +0100884
Maulik Patel91edd632024-02-26 07:44:41 +0000885 /* Renew handle for the same context, if requested */
886 if (retain_context) {
887 *new_context_handle = input_ctx_handle;
888 status = renew_nonce(new_context_handle);
889 if (status != PSA_SUCCESS) {
890 return DPE_INTERNAL_ERROR;
891 }
892 component_ctx_array[input_ctx_idx].nonce = GET_NONCE(*new_context_handle);
893
894 } else {
895 *new_context_handle = INVALID_HANDLE;
896 component_ctx_array[input_ctx_idx].nonce = INVALID_NONCE_VALUE;
Maulik Patele6adc112023-08-18 14:21:51 +0100897 }
Maulik Patele6adc112023-08-18 14:21:51 +0100898
Maulik Patel9a2a5672024-03-14 13:43:58 +0000899 log_certify_key_output_handle(*new_context_handle);
Maulik Patel00d06b62024-07-03 14:51:50 +0100900 log_intermediate_certificate(certificate_buf,
Tamas Ban257471b2024-03-25 13:49:53 +0100901 *certificate_actual_size);
Maulik Patele6adc112023-08-18 14:21:51 +0100902
Maulik Patel97a61fe2024-07-01 15:55:04 +0100903 destroy_certificate_context_keys(&leaf_cert_ctx);
Tamas Baneb8d7f12024-04-03 13:55:22 +0200904
Maulik Patele6adc112023-08-18 14:21:51 +0100905 return DPE_NO_ERROR;
906}
Maulik Patel83a6b592023-12-05 15:20:30 +0000907
908dpe_error_t get_certificate_chain_request(int input_ctx_handle,
909 bool retain_context,
910 bool clear_from_context,
911 uint8_t *certificate_chain_buf,
912 size_t certificate_chain_buf_size,
913 size_t *certificate_chain_actual_size,
914 int *new_context_handle)
915{
916 dpe_error_t err;
Maulik Patel00d06b62024-07-03 14:51:50 +0100917 uint16_t input_ctx_idx;
Maulik Patel83a6b592023-12-05 15:20:30 +0000918 psa_status_t status;
Maulik Patel97a61fe2024-07-01 15:55:04 +0100919 struct cert_context_t *cert_ctx;
Maulik Patel83a6b592023-12-05 15:20:30 +0000920
Tamas Bana5e2f582024-01-25 16:59:26 +0100921 log_get_certificate_chain(input_ctx_handle, retain_context,
922 clear_from_context, certificate_chain_buf_size);
Maulik Patel83a6b592023-12-05 15:20:30 +0000923
924 /* Validate input handle */
925 if (!is_input_handle_valid(input_ctx_handle)) {
926 return DPE_INVALID_ARGUMENT;
927 }
928
929 /* Get component index from the input handle */
930 input_ctx_idx = GET_IDX(input_ctx_handle);
Maulik Patel97a61fe2024-07-01 15:55:04 +0100931 /* Get current linked certificate context idx */
Maulik Patel00d06b62024-07-03 14:51:50 +0100932 cert_ctx = component_ctx_array[input_ctx_idx].linked_cert_ctx;
933 assert(cert_ctx != NULL);
Maulik Patel97a61fe2024-07-01 15:55:04 +0100934 if (cert_ctx->state != CERT_CTX_FINALISED) {
Maulik Patelf2820972024-04-03 10:24:45 +0100935 /* If the context has accumulated info and not yet part of a certificate,
936 * return an invalid-argument error
937 */
938 return DPE_INVALID_ARGUMENT;
939 }
940
Maulik Patel97a61fe2024-07-01 15:55:04 +0100941 err = get_certificate_chain(cert_ctx,
Maulik Patel83a6b592023-12-05 15:20:30 +0000942 certificate_chain_buf,
943 certificate_chain_buf_size,
944 certificate_chain_actual_size);
945 if (err != DPE_NO_ERROR) {
946 return err;
947 }
948
949 log_certificate_chain(certificate_chain_buf, *certificate_chain_actual_size);
950
951 /* Renew handle for the same context, if requested */
952 if (retain_context) {
953 *new_context_handle = input_ctx_handle;
954 status = renew_nonce(new_context_handle);
955 if (status != PSA_SUCCESS) {
956 return DPE_INTERNAL_ERROR;
957 }
958 component_ctx_array[input_ctx_idx].nonce = GET_NONCE(*new_context_handle);
959
960 if (clear_from_context) {
Tamas Ban257471b2024-03-25 13:49:53 +0100961 //TODO: Reimplement the clear_from_context functionality after memory
962 // optimization; Certificates are not ready made and they are not
Maulik Patel97a61fe2024-07-01 15:55:04 +0100963 // stored in the certificate context anymore. They are created on-the-fly
Tamas Ban257471b2024-03-25 13:49:53 +0100964 // when requested. Add a test as well.
Maulik Patel83a6b592023-12-05 15:20:30 +0000965 }
966
967 } else {
968 *new_context_handle = INVALID_HANDLE;
969 component_ctx_array[input_ctx_idx].nonce = INVALID_NONCE_VALUE;
970 }
Maulik Patel9a2a5672024-03-14 13:43:58 +0000971 log_get_certificate_chain_output_handle(*new_context_handle);
Maulik Patel83a6b592023-12-05 15:20:30 +0000972
973 return DPE_NO_ERROR;
974}