blob: d3230e0dd9f9abf4b26c738fd9fbe87570bdebcd [file] [log] [blame]
Maulik Patel2358bbb2023-07-21 10:56:56 +01001/*
2 * Copyright (c) 2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <assert.h>
9#include "dpe_certificate.h"
10#include "dpe_context_mngr.h"
11#include "dpe_crypto_config.h"
12#include "dpe_crypto_interface.h"
Maulik Patele6adc112023-08-18 14:21:51 +010013#include "dpe_plat.h"
Maulik Patel2358bbb2023-07-21 10:56:56 +010014#include "qcbor/qcbor_encode.h"
15#include "t_cose_common.h"
16#include "t_cose_sign1_sign.h"
17
18#define ID_HEX_SIZE (2 * DICE_ID_SIZE) /* Size of CDI encoded to ascii hex */
Maulik Patele6adc112023-08-18 14:21:51 +010019#define LABEL_HEX_SIZE (2 * DPE_EXTERNAL_LABEL_MAX_SIZE)
Maulik Patel2358bbb2023-07-21 10:56:56 +010020
21struct dpe_cert_encode_ctx {
22 QCBOREncodeContext cbor_enc_ctx;
23 struct t_cose_sign1_sign_ctx signer_ctx;
24};
25
26static void convert_to_ascii_hex(const uint8_t *in,
27 size_t in_size,
28 char *out,
29 size_t out_size)
30{
31 const char hex_table[] = "0123456789abcdef";
32 size_t in_pos = 0;
33 size_t out_pos = 0;
34
35 for (in_pos = 0; in_pos < in_size && out_pos < out_size; in_pos++) {
36 out[out_pos++] = hex_table[(in[in_pos] & 0xF0 >> 4)];
37 out[out_pos++] = hex_table[in[in_pos] & 0x0F];
38 }
39}
40
41static dpe_error_t t_cose_err_to_dpe_err(enum t_cose_err_t err)
42{
43 switch(err) {
44
45 case T_COSE_SUCCESS:
46 return DPE_NO_ERROR;
47
48 case T_COSE_ERR_TOO_SMALL:
49 return DPE_INSUFFICIENT_MEMORY;
50
51 default:
52 /* A lot of the errors are not mapped because they are
53 * primarily internal errors that should never happen. They
54 * end up here.
55 */
56 return DPE_INTERNAL_ERROR;
57 }
58}
59
60static dpe_error_t certificate_encode_start(struct dpe_cert_encode_ctx *me,
61 const UsefulBuf out_buf,
62 psa_key_handle_t private_key)
63{
64 enum t_cose_err_t t_cose_err;
65 struct t_cose_key attest_key;
66 UsefulBufC attest_key_id = {NULL, 0};
67
68 /* DPE Certificate is untagged COSE_Sign1 message */
69 t_cose_sign1_sign_init(&(me->signer_ctx), T_COSE_OPT_OMIT_CBOR_TAG, DPE_T_COSE_ALG);
70
71 attest_key.crypto_lib = T_COSE_CRYPTO_LIB_PSA;
72 attest_key.k.key_handle = private_key;
73
74 t_cose_sign1_set_signing_key(&(me->signer_ctx),
75 attest_key,
76 attest_key_id);
77
78 /* Spin up the CBOR encoder */
79 QCBOREncode_Init(&(me->cbor_enc_ctx), out_buf);
80
81 /* This will cause the cose headers to be encoded and written into
82 * out_buf using me->cbor_enc_ctx
83 */
84 t_cose_err = t_cose_sign1_encode_parameters(&(me->signer_ctx),
85 &(me->cbor_enc_ctx));
86 if (t_cose_err) {
87 return t_cose_err_to_dpe_err(t_cose_err);
88 }
89
90 QCBOREncode_OpenMap(&(me->cbor_enc_ctx));
91
92 return DPE_NO_ERROR;
93}
94
95static void add_key_usage_claim(struct dpe_cert_encode_ctx *me)
96{
97 uint8_t key_usage = DPE_CERT_KEY_USAGE_CERT_SIGN;
98
99 /* Encode key usage as byte string */
100 QCBOREncode_AddBytesToMapN(&me->cbor_enc_ctx,
101 DPE_CERT_LABEL_KEY_USAGE,
102 (UsefulBufC){ &key_usage,
103 sizeof(key_usage) });
104}
105
Maulik Patele6adc112023-08-18 14:21:51 +0100106static void add_label_claim(struct dpe_cert_encode_ctx *me,
107 const uint8_t *label,
108 size_t label_size)
109{
110 char label_hex[LABEL_HEX_SIZE];
111
112 /* If label is supplied, add label claim, else skip */
113 if ((label != NULL) && (label_size != 0)) {
114 convert_to_ascii_hex(&label[0],
115 label_size,
116 &label_hex[0],
117 sizeof(label_hex));
118
119 /* Encode label as text string */
120 QCBOREncode_AddTextToMapN(&me->cbor_enc_ctx,
121 DPE_CERT_LABEL_EXTERNAL_LABEL,
122 (UsefulBufC){ &label_hex[0],
123 label_size });
124 }
125}
126
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000127static void add_cdi_export_claim(struct dpe_cert_encode_ctx *me,
128 struct layer_context_t *layer_ctx)
129{
130 QCBOREncode_AddBoolToMapN(&me->cbor_enc_ctx,
131 DPE_CERT_LABEL_CDI_EXPORT,
132 layer_ctx->is_cdi_to_be_exported);
133}
134
Maulik Patel2358bbb2023-07-21 10:56:56 +0100135static void add_subject_claim(struct dpe_cert_encode_ctx *me,
136 struct layer_context_t *layer_ctx)
137{
138 char cdi_id_hex[ID_HEX_SIZE];
139
140 convert_to_ascii_hex(&layer_ctx->data.cdi_id[0],
141 sizeof(layer_ctx->data.cdi_id),
142 &cdi_id_hex[0],
143 sizeof(cdi_id_hex));
144 /* Encode subject as text string */
145 QCBOREncode_AddTextToMapN(&me->cbor_enc_ctx,
146 DPE_CERT_LABEL_SUBJECT,
147 (UsefulBufC){ &cdi_id_hex[0],
148 sizeof(cdi_id_hex) });
149}
150
Jamie Fox93225232023-09-22 14:09:30 +0100151static void encode_issuer_claim(struct dpe_cert_encode_ctx *me,
152 const uint8_t *issuer,
153 size_t issuer_size)
Maulik Patel2358bbb2023-07-21 10:56:56 +0100154{
Maulik Patel2358bbb2023-07-21 10:56:56 +0100155 char cdi_id_hex[ID_HEX_SIZE];
156
Jamie Fox93225232023-09-22 14:09:30 +0100157 convert_to_ascii_hex(issuer,
158 issuer_size,
Maulik Patel2358bbb2023-07-21 10:56:56 +0100159 &cdi_id_hex[0],
160 sizeof(cdi_id_hex));
161
162 /* Encode issuer as text string */
163 QCBOREncode_AddTextToMapN(&me->cbor_enc_ctx,
164 DPE_CERT_LABEL_ISSUER,
165 (UsefulBufC){ &cdi_id_hex[0],
166 sizeof(cdi_id_hex) });
167}
168
Maulik Patele6adc112023-08-18 14:21:51 +0100169static void encode_public_key(struct dpe_cert_encode_ctx *me,
170 const uint8_t *pub_key,
171 size_t pub_key_size)
Maulik Patel2358bbb2023-07-21 10:56:56 +0100172{
173 /* As per RFC8152 */
174 const int64_t cose_key_type_value = DPE_T_COSE_KEY_TYPE_VAL;
175 const int64_t cose_key_ops_value = DPE_T_COSE_KEY_OPS_VAL;
176 const int64_t cose_key_ec2_curve_value = DPE_T_COSE_KEY_EC2_CURVE_VAL;
177 const int64_t cose_key_alg_value = DPE_T_COSE_KEY_ALG_VAL;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100178
Maulik Patel2358bbb2023-07-21 10:56:56 +0100179 QCBOREncode_OpenMap(&me->cbor_enc_ctx);
180
181 /* Add the key type as int */
182 QCBOREncode_AddInt64ToMapN(&me->cbor_enc_ctx,
183 DPE_CERT_LABEL_COSE_KEY_TYPE,
184 cose_key_type_value);
185
186 /* Add the algorithm as int */
187 QCBOREncode_AddInt64ToMapN(&me->cbor_enc_ctx,
188 DPE_CERT_LABEL_COSE_KEY_ALG,
189 cose_key_alg_value);
190
191 /* Add the key operation as [+ (tstr/int)] */
192 QCBOREncode_OpenArrayInMapN(&me->cbor_enc_ctx, DPE_CERT_LABEL_COSE_KEY_OPS);
193 QCBOREncode_AddInt64(&me->cbor_enc_ctx,
194 cose_key_ops_value);
195 QCBOREncode_CloseArray(&me->cbor_enc_ctx);
196
197 /* Add the curve */
198 QCBOREncode_AddInt64ToMapN(&me->cbor_enc_ctx,
199 DPE_CERT_LABEL_COSE_KEY_EC2_CURVE,
200 cose_key_ec2_curve_value);
201
202 /* Add the subject public key x and y coordinates */
203 QCBOREncode_AddBytesToMapN(&me->cbor_enc_ctx,
204 DPE_CERT_LABEL_COSE_KEY_EC2_X,
Maulik Patele6adc112023-08-18 14:21:51 +0100205 (UsefulBufC){ &pub_key[0],
206 pub_key_size / 2 });
Maulik Patel2358bbb2023-07-21 10:56:56 +0100207
208 QCBOREncode_AddBytesToMapN(&me->cbor_enc_ctx,
209 DPE_CERT_LABEL_COSE_KEY_EC2_Y,
Maulik Patele6adc112023-08-18 14:21:51 +0100210 (UsefulBufC){ &pub_key[pub_key_size / 2],
211 pub_key_size / 2 });
Maulik Patel2358bbb2023-07-21 10:56:56 +0100212
213 QCBOREncode_CloseMap(&me->cbor_enc_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100214
Maulik Patele6adc112023-08-18 14:21:51 +0100215}
216
217static void add_public_key_claim(struct dpe_cert_encode_ctx *me,
218 const uint8_t *pub_key,
219 size_t pub_key_size)
220{
221 UsefulBufC wrapped;
222
223 /* Cose key is encoded as a map. This map is wrapped into the a
224 * byte string and it is further encoded as a map */
225 QCBOREncode_BstrWrapInMapN(&me->cbor_enc_ctx, DPE_CERT_LABEL_SUBJECT_PUBLIC_KEY);
226 encode_public_key(me, pub_key, pub_key_size);
227 QCBOREncode_CloseBstrWrap2(&me->cbor_enc_ctx, true, &wrapped);
228 assert(wrapped.len <= DICE_MAX_ENCODED_PUBLIC_KEY_SIZE);
229}
230
231static void add_public_key_to_certificate_chain(struct dpe_cert_encode_ctx *me,
232 const uint8_t *pub_key,
233 size_t pub_key_size)
234{
235 UsefulBufC wrapped;
236
237 /* Cose key is encoded as a map wrapped into a byte string */
238 QCBOREncode_BstrWrap(&me->cbor_enc_ctx);
239 encode_public_key(me, pub_key, pub_key_size);
240 QCBOREncode_CloseBstrWrap2(&me->cbor_enc_ctx, true, &wrapped);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100241 assert(wrapped.len <= DICE_MAX_ENCODED_PUBLIC_KEY_SIZE);
242}
243
244static dpe_error_t certificate_encode_finish(struct dpe_cert_encode_ctx *me,
245 UsefulBufC *completed_cert)
246{
247 QCBORError qcbor_result;
248 enum t_cose_err_t cose_return_value;
249
250 QCBOREncode_CloseMap(&(me->cbor_enc_ctx));
251
252 /* -- Finish up the COSE_Sign1. This is where the signing happens -- */
253 cose_return_value = t_cose_sign1_encode_signature(&(me->signer_ctx),
254 &(me->cbor_enc_ctx));
255 if (cose_return_value) {
256 /* Main errors are invoking the hash or signature */
257 return t_cose_err_to_dpe_err(cose_return_value);
258 }
259
260 /* Finally close off the CBOR formatting and get the pointer and length
261 * of the resulting COSE_Sign1
262 */
263 qcbor_result = QCBOREncode_Finish(&(me->cbor_enc_ctx), completed_cert);
264 if (qcbor_result == QCBOR_ERR_BUFFER_TOO_SMALL) {
265 return DPE_INSUFFICIENT_MEMORY;
266
267 } else if (qcbor_result != QCBOR_SUCCESS) {
268 /* likely from array not closed, too many closes, ... */
269 return DPE_INTERNAL_ERROR;
270
271 } else {
272 return DPE_NO_ERROR;
273 }
274}
275
276static void encode_sw_component_measurements(QCBOREncodeContext *encode_ctx,
277 struct component_context_t *component_ctx)
278{
279 QCBOREncode_OpenMap(encode_ctx);
280
281 /* Encode measurement value as byte string */
282 QCBOREncode_AddBytesToMapN(encode_ctx,
283 DPE_CERT_LABEL_CODE_HASH,
284 (UsefulBufC){ &component_ctx->data.measurement_value,
285 DICE_HASH_SIZE });
286
287 /* Encode measurement descriptor version as byte string */
288 QCBOREncode_AddBytesToMapN(encode_ctx,
289 DPE_CERT_LABEL_CODE_DESCRIPTOR,
290 (UsefulBufC){ &component_ctx->data.measurement_descriptor,
291 component_ctx->data.measurement_descriptor_size });
292
293 /* Encode signer ID Hash as byte string */
294 QCBOREncode_AddBytesToMapN(encode_ctx,
295 DPE_CERT_LABEL_AUTHORITY_HASH,
296 (UsefulBufC){ &component_ctx->data.signer_id,
297 DICE_HASH_SIZE });
298
299 /* Encode signer ID descriptor as byte string */
300 QCBOREncode_AddBytesToMapN(encode_ctx,
301 DPE_CERT_LABEL_AUTHORITY_DESCRIPTOR,
302 (UsefulBufC){ &component_ctx->data.signer_id_descriptor,
303 component_ctx->data.signer_id_descriptor_size });
304
305 if (component_ctx->data.config_descriptor_size > 0) {
306 /* Encode config descriptor as byte string */
307 QCBOREncode_AddBytesToMapN(encode_ctx,
308 DPE_CERT_LABEL_CONFIGURATION_DESCRIPTOR,
309 (UsefulBufC){ &component_ctx->data.config_descriptor,
310 component_ctx->data.config_descriptor_size });
311 /* Encode config value as byte string */
312 QCBOREncode_AddBytesToMapN(encode_ctx,
313 DPE_CERT_LABEL_CONFIGURATION_HASH,
314 (UsefulBufC){ &component_ctx->data.config_value,
315 DICE_INLINE_CONFIG_SIZE });
316 } else {
317 /* Encode config value as byte string */
318 QCBOREncode_AddBytesToMapN(encode_ctx,
319 DPE_CERT_LABEL_CONFIGURATION_DESCRIPTOR,
320 (UsefulBufC){ &component_ctx->data.config_value,
321 DICE_INLINE_CONFIG_SIZE });
322 }
323
324 /* Encode mode value as byte string */
325 QCBOREncode_AddBytesToMapN(encode_ctx,
326 DPE_CERT_LABEL_MODE,
327 (UsefulBufC){ &component_ctx->data.mode,
328 sizeof(DiceMode) });
329
330 QCBOREncode_CloseMap(encode_ctx);
331}
332
333static void encode_layer_sw_components_array(uint16_t layer_idx,
334 struct dpe_cert_encode_ctx *me)
335{
336 int i, cnt;
337 struct component_context_t *component_ctx;
338
339 for (i = 0, cnt = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
340 component_ctx = get_component_if_linked_to_layer(layer_idx, i);
341 if (component_ctx != NULL) {
342 /* This component belongs to current layer */
343 cnt++;
344
345 if (cnt == 1) {
346 /* Open array which stores SW components claims. */
347 QCBOREncode_OpenArrayInMapN(&me->cbor_enc_ctx,
348 DPE_CERT_LABEL_SW_COMPONENTS);
349 }
350 encode_sw_component_measurements(&me->cbor_enc_ctx, component_ctx);
351 }
352 }
353
354 if (cnt != 0) {
355 /* Close array which stores SW components claims. */
356 QCBOREncode_CloseArray(&me->cbor_enc_ctx);
357 }
358}
359
Jamie Fox93225232023-09-22 14:09:30 +0100360static dpe_error_t add_issuer_claim(struct dpe_cert_encode_ctx *me,
361 uint16_t layer_idx,
362 psa_key_id_t root_attest_key_id,
363 const struct layer_context_t *parent_layer_ctx)
364{
365 uint8_t rot_cdi_id[DICE_ID_SIZE];
366
367 if (layer_idx == DPE_ROT_LAYER_IDX) {
368 /* For the RoT layer, issuer id is derived from the root attestation key */
369 if (derive_cdi_id(root_attest_key_id, rot_cdi_id,
370 sizeof(rot_cdi_id)) != PSA_SUCCESS) {
371 return DPE_INTERNAL_ERROR;
372 }
373
374 encode_issuer_claim(me,
375 rot_cdi_id,
376 sizeof(rot_cdi_id));
377 } else {
378 encode_issuer_claim(me,
379 parent_layer_ctx->data.cdi_id,
380 sizeof(parent_layer_ctx->data.cdi_id));
381 }
382
383 return DPE_NO_ERROR;
384}
Maulik Patel2358bbb2023-07-21 10:56:56 +0100385
386dpe_error_t encode_layer_certificate(uint16_t layer_idx,
387 struct layer_context_t *layer_ctx,
388 const struct layer_context_t *parent_layer_ctx)
389{
390 dpe_error_t err;
391 struct dpe_cert_encode_ctx dpe_cert_ctx;
392 UsefulBuf cert;
393 UsefulBufC completed_cert;
Jamie Fox93225232023-09-22 14:09:30 +0100394 psa_key_id_t attest_key_id;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100395
Jamie Fox93225232023-09-22 14:09:30 +0100396 /* The RoT layer certificate is signed by the provisioned attestation key,
397 * all other layers are signed by the parent layer's key.
398 */
399 if (layer_idx == DPE_ROT_LAYER_IDX) {
400 attest_key_id = dpe_plat_get_root_attest_key_id();
401 } else {
402 attest_key_id = parent_layer_ctx->data.attest_key_id;
403 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100404
405 /* Get started creating the certificate/token. This sets up the CBOR and
406 * COSE contexts which causes the COSE headers to be constructed.
407 */
408 cert.ptr = &layer_ctx->data.cert_buf[0];
409 cert.len = sizeof(layer_ctx->data.cert_buf);
410
411 err = certificate_encode_start(&dpe_cert_ctx,
412 cert,
413 attest_key_id);
414 if (err != DPE_NO_ERROR) {
415 return err;
416 }
417
418 /* Add all the required claims */
419 /* Add issuer/authority claim */
Jamie Fox93225232023-09-22 14:09:30 +0100420 err = add_issuer_claim(&dpe_cert_ctx, layer_idx, attest_key_id, parent_layer_ctx);
421 if (err != DPE_NO_ERROR) {
422 return err;
423 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100424
425 /* Add subject claim */
426 add_subject_claim(&dpe_cert_ctx, layer_ctx);
427
428 /* Encode all firmware measurements for the components linked to this layer */
429 //TODO:
430 /* It is not yet defined in the open-dice profile how to represent
431 * multiple SW components in a single certificate; In current implementation,
432 * an array is created for all the components' measurements and within the
433 * array, there are multiple maps, one for each SW component
434 */
435 encode_layer_sw_components_array(layer_idx, &dpe_cert_ctx);
436
Maulik Patele6adc112023-08-18 14:21:51 +0100437 /* Add label claim */
438 add_label_claim(&dpe_cert_ctx,
Maulik Patel4fed7812023-12-08 09:55:22 +0000439 &layer_ctx->data.external_key_deriv_label[0],
440 layer_ctx->data.external_key_deriv_label_len);
Maulik Patele6adc112023-08-18 14:21:51 +0100441
Maulik Patel2358bbb2023-07-21 10:56:56 +0100442 /* Add public key claim */
Maulik Patele6adc112023-08-18 14:21:51 +0100443 add_public_key_claim(&dpe_cert_ctx,
444 &layer_ctx->data.attest_pub_key[0],
445 layer_ctx->data.attest_pub_key_len);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100446
447 /* Add key usage claim */
448 add_key_usage_claim(&dpe_cert_ctx);
449
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000450 /* Add CDI exported claim */
451 if (layer_ctx->is_cdi_to_be_exported) {
452 add_cdi_export_claim(&dpe_cert_ctx, layer_ctx);
453 }
454
Maulik Patel2358bbb2023-07-21 10:56:56 +0100455 /* Finish up creating the token. This is where the actual signature
456 * is generated. This finishes up the CBOR encoding too.
457 */
458 err = certificate_encode_finish(&dpe_cert_ctx, &completed_cert);
459 if (err != DPE_NO_ERROR) {
460 return err;
461 }
462
463 /* Update the final size of the token/certificate */
464 layer_ctx->data.cert_buf_len = completed_cert.len;
465
466 return err;
467}
468
469dpe_error_t store_layer_certificate(struct layer_context_t *layer_ctx)
470{
471 //TODO:
472 (void)layer_ctx;
473 return DPE_NO_ERROR;
474}
Maulik Patele6adc112023-08-18 14:21:51 +0100475
476static void open_certificate_chain(struct dpe_cert_encode_ctx *me,
477 uint8_t *cert_chain_buf,
478 size_t cert_chain_buf_size)
479{
480 /* Set up encoding context with output buffer. */
481 QCBOREncode_Init(&me->cbor_enc_ctx,
482 (UsefulBuf){ &cert_chain_buf[0],
483 cert_chain_buf_size });
484 QCBOREncode_OpenArray(&me->cbor_enc_ctx);
485}
486
487static void add_certificate_to_chain(struct dpe_cert_encode_ctx *me,
488 struct layer_context_t *layer_ctx)
489{
490 /* Add already encoded layers certificate to the chain */
491 QCBOREncode_AddEncoded(&me->cbor_enc_ctx,
492 (UsefulBufC){ &layer_ctx->data.cert_buf[0],
493 layer_ctx->data.cert_buf_len });
494}
495
496static dpe_error_t close_certificate_chain(struct dpe_cert_encode_ctx *me,
497 size_t *cert_chain_actual_size)
498{
499 QCBORError encode_error;
500 UsefulBufC completed_cert_chain;
501
502 QCBOREncode_CloseArray(&me->cbor_enc_ctx);
503
504 encode_error = QCBOREncode_Finish(&me->cbor_enc_ctx,
505 &completed_cert_chain);
506
507 /* Check for any encoding errors. */
508 if (encode_error == QCBOR_ERR_BUFFER_TOO_SMALL) {
509 return DPE_INSUFFICIENT_MEMORY;
510 } else if (encode_error != QCBOR_SUCCESS) {
511 return DPE_INTERNAL_ERROR;
512 }
513
514 *cert_chain_actual_size = completed_cert_chain.len;
515
516 return DPE_NO_ERROR;
517}
518
519static dpe_error_t add_root_attestation_public_key(struct dpe_cert_encode_ctx *me)
520{
521 psa_status_t status;
522 psa_key_id_t attest_key_id;
523 uint8_t attest_pub_key[DPE_ATTEST_PUB_KEY_SIZE];
524 size_t attest_pub_key_len;
525
526 attest_key_id = dpe_plat_get_root_attest_key_id();
527
528 status = psa_export_public_key(attest_key_id, attest_pub_key,
529 sizeof(attest_pub_key), &attest_pub_key_len);
530 if (status != PSA_SUCCESS) {
531 return DPE_INTERNAL_ERROR;
532 }
533
534 add_public_key_to_certificate_chain(me, &attest_pub_key[0], attest_pub_key_len);
535
536 return DPE_NO_ERROR;
537}
538
539dpe_error_t get_certificate_chain(uint16_t layer_idx,
540 uint8_t *cert_chain_buf,
541 size_t cert_chain_buf_size,
542 size_t *cert_chain_actual_size)
543{
544 struct layer_context_t *layer_ctx;
545 struct dpe_cert_encode_ctx dpe_cert_chain_ctx;
546 dpe_error_t err;
547 int i;
548 uint16_t layer_chain[MAX_NUM_OF_LAYERS];
549 uint16_t layer_cnt = 0;
550
551 open_certificate_chain(&dpe_cert_chain_ctx,
552 cert_chain_buf,
553 cert_chain_buf_size);
554
555 /* Add DICE/Root public key (IAK public key) as the first entry of array */
556 err = add_root_attestation_public_key(&dpe_cert_chain_ctx);
557 if (err != DPE_NO_ERROR) {
558 return err;
559 }
560
561 /* Loop from leaf to the RoT layer & save all the linked layers in this chain */
562 while ((layer_idx >= DPE_ROT_LAYER_IDX) && (layer_cnt < MAX_NUM_OF_LAYERS)) {
563
564 /* Save layer idx */
565 layer_chain[layer_cnt++] = layer_idx;
566
567 if (layer_idx == DPE_ROT_LAYER_IDX) {
568 /* This is the end of chain */
569 break;
570 }
571
572 layer_ctx = get_layer_ctx_ptr(layer_idx);
573 assert(layer_ctx->parent_layer_idx < layer_idx);
574 /* Move to the parent layer */
575 layer_idx = layer_ctx->parent_layer_idx;
576 }
577
578 i = (layer_cnt > 0) ? layer_cnt - 1 : 0;
579
580 /* Add certificate from RoT to leaf layer order */
581 while (i >= DPE_ROT_LAYER_IDX) {
582 layer_ctx = get_layer_ctx_ptr(layer_chain[i]);
583 assert(layer_ctx != NULL);
584 add_certificate_to_chain(&dpe_cert_chain_ctx, layer_ctx);
585 i--;
586 }
587
588 return close_certificate_chain(&dpe_cert_chain_ctx,
589 cert_chain_actual_size);
590}
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000591
592dpe_error_t encode_cdi(const uint8_t *cdi,
593 size_t cdi_size,
594 uint8_t *encoded_cdi_buf,
595 size_t encoded_cdi_buf_size,
596 size_t *encoded_cdi_actual_size)
597{
598 QCBOREncodeContext encode_ctx;
599 QCBORError encode_err;
600 UsefulBufC out;
601
602 QCBOREncode_Init(&encode_ctx, (UsefulBuf){ encoded_cdi_buf, encoded_cdi_buf_size });
603 QCBOREncode_OpenMap(&encode_ctx);
604
605 /* Encode CDI value as byte string */
606 QCBOREncode_AddBytesToMapN(&encode_ctx,
607 DPE_LABEL_CDI_ATTEST,
608 (UsefulBufC){ cdi, cdi_size });
609
610 QCBOREncode_CloseMap(&encode_ctx);
611 encode_err = QCBOREncode_Finish(&encode_ctx, &out);
612
613 /* Check for any encoding errors. */
614 if (encode_err == QCBOR_ERR_BUFFER_TOO_SMALL) {
615 return DPE_INSUFFICIENT_MEMORY;
616 } else if (encode_err != QCBOR_SUCCESS) {
617 return DPE_INTERNAL_ERROR;
618 }
619
620 *encoded_cdi_actual_size = out.len;
621
622 return DPE_NO_ERROR;
623}
624
Maulik Patel83a6b592023-12-05 15:20:30 +0000625void clear_certificate_chain(uint16_t layer_idx,
626 struct layer_context_t *layer_ctx)
627{
628 uint16_t layer_cnt = 0;
629
630 // Q - Confirm - Clear all the certificate info till threshold layer?
631 while ((layer_idx >= DPE_DESTROY_CONTEXT_THRESHOLD_LAYER_IDX) &&
632 (layer_cnt < MAX_NUM_OF_LAYERS)) {
633
634 layer_cnt++;
635 memset(&layer_ctx->data.cert_buf[0], 0, layer_ctx->data.cert_buf_len);
636
637 if (layer_idx == DPE_DESTROY_CONTEXT_THRESHOLD_LAYER_IDX) {
638 /* Cannot clear data from this point onwards */
639 break;
640 }
641
642 layer_ctx = get_layer_ctx_ptr(layer_idx);
643 assert(layer_ctx->parent_layer_idx < layer_idx);
644 /* Move to the parent layer */
645 layer_idx = layer_ctx->parent_layer_idx;
646 }
647}
648
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000649dpe_error_t add_encoded_layer_certificate(const uint8_t *cert_buf,
650 size_t cert_buf_size,
651 uint8_t *encoded_cert_buf,
652 size_t encoded_cert_buf_size,
653 size_t *encoded_cert_actual_size)
654{
655 QCBOREncodeContext encode_ctx;
656 QCBORError encode_err;
657 UsefulBufC out;
658
659 QCBOREncode_Init(&encode_ctx, (UsefulBuf){ encoded_cert_buf, encoded_cert_buf_size });
660 QCBOREncode_OpenMap(&encode_ctx);
661
662 /* Encode CDI value as byte string */
663 QCBOREncode_AddBytesToMapN(&encode_ctx,
664 DPE_LABEL_CERT,
665 (UsefulBufC){ cert_buf, cert_buf_size });
666
667 QCBOREncode_CloseMap(&encode_ctx);
668 encode_err = QCBOREncode_Finish(&encode_ctx, &out);
669
670 /* Check for any encoding errors. */
671 if (encode_err == QCBOR_ERR_BUFFER_TOO_SMALL) {
672 return DPE_INSUFFICIENT_MEMORY;
673 } else if (encode_err != QCBOR_SUCCESS) {
674 return DPE_INTERNAL_ERROR;
675 }
676
677 *encoded_cert_actual_size = out.len;
678
679 return DPE_NO_ERROR;
680}