blob: 913b3f5510ab18bd240175a37b32db35f87a589d [file] [log] [blame]
Maulik Patel2358bbb2023-07-21 10:56:56 +01001/*
Tamas Ban5179a4d2024-01-25 17:05:30 +01002 * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
Maulik Patel2358bbb2023-07-21 10:56:56 +01003 *
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
Tamas Ban8ed52802024-03-14 09:36:05 +0100202 /*
203 * From psa/crypto.h:
204 *
205 * For other elliptic curve public keys (key types for which
206 * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed
207 * representation defined by SEC1 &sect;2.3.3 as the content of an ECPoint.
208 * Let `m` be the bit size associated with the curve, i.e. the bit size of
209 * `q` for a curve over `F_q`. The representation consists of:
210 * - The byte 0x04;
211 * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
212 * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
213
214 * Furthermore, as per rfc5480 section-2.2:
215 *
216 * The first octet of the OCTET STRING indicates whether the key is
217 * compressed or uncompressed. The uncompressed form is indicated by 0x04
218 * and the compressed form is indicated by either 0x02 or 0x03.
219 */
Maulik Patel2358bbb2023-07-21 10:56:56 +0100220 QCBOREncode_AddBytesToMapN(&me->cbor_enc_ctx,
221 DPE_CERT_LABEL_COSE_KEY_EC2_X,
Tamas Ban8ed52802024-03-14 09:36:05 +0100222 (UsefulBufC){ &pub_key[1],
Maulik Patele6adc112023-08-18 14:21:51 +0100223 pub_key_size / 2 });
Maulik Patel2358bbb2023-07-21 10:56:56 +0100224
225 QCBOREncode_AddBytesToMapN(&me->cbor_enc_ctx,
226 DPE_CERT_LABEL_COSE_KEY_EC2_Y,
Tamas Ban8ed52802024-03-14 09:36:05 +0100227 (UsefulBufC){ &pub_key[1 + (pub_key_size / 2)],
Maulik Patele6adc112023-08-18 14:21:51 +0100228 pub_key_size / 2 });
Maulik Patel2358bbb2023-07-21 10:56:56 +0100229
230 QCBOREncode_CloseMap(&me->cbor_enc_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100231
Maulik Patele6adc112023-08-18 14:21:51 +0100232}
233
234static void add_public_key_claim(struct dpe_cert_encode_ctx *me,
235 const uint8_t *pub_key,
236 size_t pub_key_size)
237{
238 UsefulBufC wrapped;
239
240 /* Cose key is encoded as a map. This map is wrapped into the a
241 * byte string and it is further encoded as a map */
242 QCBOREncode_BstrWrapInMapN(&me->cbor_enc_ctx, DPE_CERT_LABEL_SUBJECT_PUBLIC_KEY);
243 encode_public_key(me, pub_key, pub_key_size);
244 QCBOREncode_CloseBstrWrap2(&me->cbor_enc_ctx, true, &wrapped);
245 assert(wrapped.len <= DICE_MAX_ENCODED_PUBLIC_KEY_SIZE);
246}
247
248static void add_public_key_to_certificate_chain(struct dpe_cert_encode_ctx *me,
249 const uint8_t *pub_key,
250 size_t pub_key_size)
251{
252 UsefulBufC wrapped;
253
254 /* Cose key is encoded as a map wrapped into a byte string */
255 QCBOREncode_BstrWrap(&me->cbor_enc_ctx);
256 encode_public_key(me, pub_key, pub_key_size);
257 QCBOREncode_CloseBstrWrap2(&me->cbor_enc_ctx, true, &wrapped);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100258 assert(wrapped.len <= DICE_MAX_ENCODED_PUBLIC_KEY_SIZE);
259}
260
261static dpe_error_t certificate_encode_finish(struct dpe_cert_encode_ctx *me,
262 UsefulBufC *completed_cert)
263{
264 QCBORError qcbor_result;
265 enum t_cose_err_t cose_return_value;
266
267 QCBOREncode_CloseMap(&(me->cbor_enc_ctx));
268
269 /* -- Finish up the COSE_Sign1. This is where the signing happens -- */
270 cose_return_value = t_cose_sign1_encode_signature(&(me->signer_ctx),
271 &(me->cbor_enc_ctx));
272 if (cose_return_value) {
273 /* Main errors are invoking the hash or signature */
274 return t_cose_err_to_dpe_err(cose_return_value);
275 }
276
277 /* Finally close off the CBOR formatting and get the pointer and length
278 * of the resulting COSE_Sign1
279 */
280 qcbor_result = QCBOREncode_Finish(&(me->cbor_enc_ctx), completed_cert);
281 if (qcbor_result == QCBOR_ERR_BUFFER_TOO_SMALL) {
282 return DPE_INSUFFICIENT_MEMORY;
283
284 } else if (qcbor_result != QCBOR_SUCCESS) {
285 /* likely from array not closed, too many closes, ... */
286 return DPE_INTERNAL_ERROR;
287
288 } else {
289 return DPE_NO_ERROR;
290 }
291}
292
293static void encode_sw_component_measurements(QCBOREncodeContext *encode_ctx,
294 struct component_context_t *component_ctx)
295{
296 QCBOREncode_OpenMap(encode_ctx);
297
298 /* Encode measurement value as byte string */
299 QCBOREncode_AddBytesToMapN(encode_ctx,
300 DPE_CERT_LABEL_CODE_HASH,
301 (UsefulBufC){ &component_ctx->data.measurement_value,
302 DICE_HASH_SIZE });
303
304 /* Encode measurement descriptor version as byte string */
305 QCBOREncode_AddBytesToMapN(encode_ctx,
306 DPE_CERT_LABEL_CODE_DESCRIPTOR,
307 (UsefulBufC){ &component_ctx->data.measurement_descriptor,
308 component_ctx->data.measurement_descriptor_size });
309
310 /* Encode signer ID Hash as byte string */
311 QCBOREncode_AddBytesToMapN(encode_ctx,
312 DPE_CERT_LABEL_AUTHORITY_HASH,
313 (UsefulBufC){ &component_ctx->data.signer_id,
314 DICE_HASH_SIZE });
315
316 /* Encode signer ID descriptor as byte string */
317 QCBOREncode_AddBytesToMapN(encode_ctx,
318 DPE_CERT_LABEL_AUTHORITY_DESCRIPTOR,
319 (UsefulBufC){ &component_ctx->data.signer_id_descriptor,
320 component_ctx->data.signer_id_descriptor_size });
321
322 if (component_ctx->data.config_descriptor_size > 0) {
323 /* Encode config descriptor as byte string */
324 QCBOREncode_AddBytesToMapN(encode_ctx,
325 DPE_CERT_LABEL_CONFIGURATION_DESCRIPTOR,
326 (UsefulBufC){ &component_ctx->data.config_descriptor,
327 component_ctx->data.config_descriptor_size });
328 /* Encode config value as byte string */
329 QCBOREncode_AddBytesToMapN(encode_ctx,
330 DPE_CERT_LABEL_CONFIGURATION_HASH,
331 (UsefulBufC){ &component_ctx->data.config_value,
332 DICE_INLINE_CONFIG_SIZE });
333 } else {
334 /* Encode config value as byte string */
335 QCBOREncode_AddBytesToMapN(encode_ctx,
336 DPE_CERT_LABEL_CONFIGURATION_DESCRIPTOR,
337 (UsefulBufC){ &component_ctx->data.config_value,
338 DICE_INLINE_CONFIG_SIZE });
339 }
340
341 /* Encode mode value as byte string */
342 QCBOREncode_AddBytesToMapN(encode_ctx,
343 DPE_CERT_LABEL_MODE,
344 (UsefulBufC){ &component_ctx->data.mode,
345 sizeof(DiceMode) });
346
347 QCBOREncode_CloseMap(encode_ctx);
348}
349
350static void encode_layer_sw_components_array(uint16_t layer_idx,
351 struct dpe_cert_encode_ctx *me)
352{
353 int i, cnt;
354 struct component_context_t *component_ctx;
355
356 for (i = 0, cnt = 0; i < MAX_NUM_OF_COMPONENTS; i++) {
357 component_ctx = get_component_if_linked_to_layer(layer_idx, i);
358 if (component_ctx != NULL) {
359 /* This component belongs to current layer */
360 cnt++;
361
362 if (cnt == 1) {
363 /* Open array which stores SW components claims. */
364 QCBOREncode_OpenArrayInMapN(&me->cbor_enc_ctx,
365 DPE_CERT_LABEL_SW_COMPONENTS);
366 }
367 encode_sw_component_measurements(&me->cbor_enc_ctx, component_ctx);
368 }
369 }
370
371 if (cnt != 0) {
372 /* Close array which stores SW components claims. */
373 QCBOREncode_CloseArray(&me->cbor_enc_ctx);
374 }
375}
376
Jamie Fox93225232023-09-22 14:09:30 +0100377static dpe_error_t add_issuer_claim(struct dpe_cert_encode_ctx *me,
378 uint16_t layer_idx,
379 psa_key_id_t root_attest_key_id,
380 const struct layer_context_t *parent_layer_ctx)
381{
382 uint8_t rot_cdi_id[DICE_ID_SIZE];
383
384 if (layer_idx == DPE_ROT_LAYER_IDX) {
385 /* For the RoT layer, issuer id is derived from the root attestation key */
386 if (derive_cdi_id(root_attest_key_id, rot_cdi_id,
387 sizeof(rot_cdi_id)) != PSA_SUCCESS) {
388 return DPE_INTERNAL_ERROR;
389 }
390
391 encode_issuer_claim(me,
392 rot_cdi_id,
393 sizeof(rot_cdi_id));
394 } else {
395 encode_issuer_claim(me,
396 parent_layer_ctx->data.cdi_id,
397 sizeof(parent_layer_ctx->data.cdi_id));
398 }
399
400 return DPE_NO_ERROR;
401}
Maulik Patel2358bbb2023-07-21 10:56:56 +0100402
403dpe_error_t encode_layer_certificate(uint16_t layer_idx,
404 struct layer_context_t *layer_ctx,
405 const struct layer_context_t *parent_layer_ctx)
406{
407 dpe_error_t err;
408 struct dpe_cert_encode_ctx dpe_cert_ctx;
409 UsefulBuf cert;
410 UsefulBufC completed_cert;
Jamie Fox93225232023-09-22 14:09:30 +0100411 psa_key_id_t attest_key_id;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100412
Jamie Fox93225232023-09-22 14:09:30 +0100413 /* The RoT layer certificate is signed by the provisioned attestation key,
414 * all other layers are signed by the parent layer's key.
415 */
416 if (layer_idx == DPE_ROT_LAYER_IDX) {
417 attest_key_id = dpe_plat_get_root_attest_key_id();
418 } else {
419 attest_key_id = parent_layer_ctx->data.attest_key_id;
420 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100421
422 /* Get started creating the certificate/token. This sets up the CBOR and
423 * COSE contexts which causes the COSE headers to be constructed.
424 */
425 cert.ptr = &layer_ctx->data.cert_buf[0];
426 cert.len = sizeof(layer_ctx->data.cert_buf);
427
428 err = certificate_encode_start(&dpe_cert_ctx,
429 cert,
430 attest_key_id);
431 if (err != DPE_NO_ERROR) {
432 return err;
433 }
434
435 /* Add all the required claims */
436 /* Add issuer/authority claim */
Jamie Fox93225232023-09-22 14:09:30 +0100437 err = add_issuer_claim(&dpe_cert_ctx, layer_idx, attest_key_id, parent_layer_ctx);
438 if (err != DPE_NO_ERROR) {
439 return err;
440 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100441
442 /* Add subject claim */
443 add_subject_claim(&dpe_cert_ctx, layer_ctx);
444
445 /* Encode all firmware measurements for the components linked to this layer */
446 //TODO:
447 /* It is not yet defined in the open-dice profile how to represent
448 * multiple SW components in a single certificate; In current implementation,
449 * an array is created for all the components' measurements and within the
450 * array, there are multiple maps, one for each SW component
451 */
452 encode_layer_sw_components_array(layer_idx, &dpe_cert_ctx);
453
Maulik Patele6adc112023-08-18 14:21:51 +0100454 /* Add label claim */
455 add_label_claim(&dpe_cert_ctx,
Maulik Patel4fed7812023-12-08 09:55:22 +0000456 &layer_ctx->data.external_key_deriv_label[0],
457 layer_ctx->data.external_key_deriv_label_len);
Maulik Patele6adc112023-08-18 14:21:51 +0100458
Maulik Patel2358bbb2023-07-21 10:56:56 +0100459 /* Add public key claim */
Maulik Patele6adc112023-08-18 14:21:51 +0100460 add_public_key_claim(&dpe_cert_ctx,
461 &layer_ctx->data.attest_pub_key[0],
462 layer_ctx->data.attest_pub_key_len);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100463
464 /* Add key usage claim */
465 add_key_usage_claim(&dpe_cert_ctx);
466
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000467 /* Add CDI exported claim */
468 if (layer_ctx->is_cdi_to_be_exported) {
469 add_cdi_export_claim(&dpe_cert_ctx, layer_ctx);
470 }
471
Maulik Patel2358bbb2023-07-21 10:56:56 +0100472 /* Finish up creating the token. This is where the actual signature
473 * is generated. This finishes up the CBOR encoding too.
474 */
475 err = certificate_encode_finish(&dpe_cert_ctx, &completed_cert);
476 if (err != DPE_NO_ERROR) {
477 return err;
478 }
479
480 /* Update the final size of the token/certificate */
481 layer_ctx->data.cert_buf_len = completed_cert.len;
482
483 return err;
484}
485
486dpe_error_t store_layer_certificate(struct layer_context_t *layer_ctx)
487{
488 //TODO:
489 (void)layer_ctx;
490 return DPE_NO_ERROR;
491}
Maulik Patele6adc112023-08-18 14:21:51 +0100492
493static void open_certificate_chain(struct dpe_cert_encode_ctx *me,
494 uint8_t *cert_chain_buf,
495 size_t cert_chain_buf_size)
496{
497 /* Set up encoding context with output buffer. */
498 QCBOREncode_Init(&me->cbor_enc_ctx,
499 (UsefulBuf){ &cert_chain_buf[0],
500 cert_chain_buf_size });
501 QCBOREncode_OpenArray(&me->cbor_enc_ctx);
502}
503
504static void add_certificate_to_chain(struct dpe_cert_encode_ctx *me,
505 struct layer_context_t *layer_ctx)
506{
507 /* Add already encoded layers certificate to the chain */
508 QCBOREncode_AddEncoded(&me->cbor_enc_ctx,
509 (UsefulBufC){ &layer_ctx->data.cert_buf[0],
510 layer_ctx->data.cert_buf_len });
511}
512
513static dpe_error_t close_certificate_chain(struct dpe_cert_encode_ctx *me,
514 size_t *cert_chain_actual_size)
515{
516 QCBORError encode_error;
517 UsefulBufC completed_cert_chain;
518
519 QCBOREncode_CloseArray(&me->cbor_enc_ctx);
520
521 encode_error = QCBOREncode_Finish(&me->cbor_enc_ctx,
522 &completed_cert_chain);
523
524 /* Check for any encoding errors. */
525 if (encode_error == QCBOR_ERR_BUFFER_TOO_SMALL) {
526 return DPE_INSUFFICIENT_MEMORY;
527 } else if (encode_error != QCBOR_SUCCESS) {
528 return DPE_INTERNAL_ERROR;
529 }
530
531 *cert_chain_actual_size = completed_cert_chain.len;
532
533 return DPE_NO_ERROR;
534}
535
536static dpe_error_t add_root_attestation_public_key(struct dpe_cert_encode_ctx *me)
537{
538 psa_status_t status;
539 psa_key_id_t attest_key_id;
540 uint8_t attest_pub_key[DPE_ATTEST_PUB_KEY_SIZE];
541 size_t attest_pub_key_len;
542
543 attest_key_id = dpe_plat_get_root_attest_key_id();
544
545 status = psa_export_public_key(attest_key_id, attest_pub_key,
546 sizeof(attest_pub_key), &attest_pub_key_len);
547 if (status != PSA_SUCCESS) {
548 return DPE_INTERNAL_ERROR;
549 }
550
551 add_public_key_to_certificate_chain(me, &attest_pub_key[0], attest_pub_key_len);
552
553 return DPE_NO_ERROR;
554}
555
556dpe_error_t get_certificate_chain(uint16_t layer_idx,
557 uint8_t *cert_chain_buf,
558 size_t cert_chain_buf_size,
559 size_t *cert_chain_actual_size)
560{
561 struct layer_context_t *layer_ctx;
562 struct dpe_cert_encode_ctx dpe_cert_chain_ctx;
563 dpe_error_t err;
564 int i;
565 uint16_t layer_chain[MAX_NUM_OF_LAYERS];
566 uint16_t layer_cnt = 0;
567
568 open_certificate_chain(&dpe_cert_chain_ctx,
569 cert_chain_buf,
570 cert_chain_buf_size);
571
572 /* Add DICE/Root public key (IAK public key) as the first entry of array */
573 err = add_root_attestation_public_key(&dpe_cert_chain_ctx);
574 if (err != DPE_NO_ERROR) {
575 return err;
576 }
577
578 /* Loop from leaf to the RoT layer & save all the linked layers in this chain */
579 while ((layer_idx >= DPE_ROT_LAYER_IDX) && (layer_cnt < MAX_NUM_OF_LAYERS)) {
580
581 /* Save layer idx */
582 layer_chain[layer_cnt++] = layer_idx;
583
584 if (layer_idx == DPE_ROT_LAYER_IDX) {
585 /* This is the end of chain */
586 break;
587 }
588
589 layer_ctx = get_layer_ctx_ptr(layer_idx);
590 assert(layer_ctx->parent_layer_idx < layer_idx);
591 /* Move to the parent layer */
592 layer_idx = layer_ctx->parent_layer_idx;
593 }
594
595 i = (layer_cnt > 0) ? layer_cnt - 1 : 0;
596
597 /* Add certificate from RoT to leaf layer order */
598 while (i >= DPE_ROT_LAYER_IDX) {
599 layer_ctx = get_layer_ctx_ptr(layer_chain[i]);
600 assert(layer_ctx != NULL);
601 add_certificate_to_chain(&dpe_cert_chain_ctx, layer_ctx);
602 i--;
603 }
604
605 return close_certificate_chain(&dpe_cert_chain_ctx,
606 cert_chain_actual_size);
607}
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000608
Tamas Ban5179a4d2024-01-25 17:05:30 +0100609dpe_error_t encode_cdi(const uint8_t cdi_attest_buf[DICE_CDI_SIZE],
610 const uint8_t cdi_seal_buf[DICE_CDI_SIZE],
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000611 uint8_t *encoded_cdi_buf,
612 size_t encoded_cdi_buf_size,
613 size_t *encoded_cdi_actual_size)
614{
615 QCBOREncodeContext encode_ctx;
616 QCBORError encode_err;
617 UsefulBufC out;
618
619 QCBOREncode_Init(&encode_ctx, (UsefulBuf){ encoded_cdi_buf, encoded_cdi_buf_size });
620 QCBOREncode_OpenMap(&encode_ctx);
621
622 /* Encode CDI value as byte string */
623 QCBOREncode_AddBytesToMapN(&encode_ctx,
624 DPE_LABEL_CDI_ATTEST,
Tamas Ban5179a4d2024-01-25 17:05:30 +0100625 (UsefulBufC){ cdi_attest_buf, DICE_CDI_SIZE });
626
627 QCBOREncode_AddBytesToMapN(&encode_ctx,
628 DPE_LABEL_CDI_SEAL,
629 (UsefulBufC){ cdi_seal_buf, DICE_CDI_SIZE });
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000630
631 QCBOREncode_CloseMap(&encode_ctx);
632 encode_err = QCBOREncode_Finish(&encode_ctx, &out);
633
634 /* Check for any encoding errors. */
635 if (encode_err == QCBOR_ERR_BUFFER_TOO_SMALL) {
636 return DPE_INSUFFICIENT_MEMORY;
637 } else if (encode_err != QCBOR_SUCCESS) {
638 return DPE_INTERNAL_ERROR;
639 }
640
641 *encoded_cdi_actual_size = out.len;
642
643 return DPE_NO_ERROR;
644}
645
Maulik Patel83a6b592023-12-05 15:20:30 +0000646void clear_certificate_chain(uint16_t layer_idx,
647 struct layer_context_t *layer_ctx)
648{
649 uint16_t layer_cnt = 0;
650
651 // Q - Confirm - Clear all the certificate info till threshold layer?
652 while ((layer_idx >= DPE_DESTROY_CONTEXT_THRESHOLD_LAYER_IDX) &&
653 (layer_cnt < MAX_NUM_OF_LAYERS)) {
654
655 layer_cnt++;
656 memset(&layer_ctx->data.cert_buf[0], 0, layer_ctx->data.cert_buf_len);
657
658 if (layer_idx == DPE_DESTROY_CONTEXT_THRESHOLD_LAYER_IDX) {
659 /* Cannot clear data from this point onwards */
660 break;
661 }
662
663 layer_ctx = get_layer_ctx_ptr(layer_idx);
664 assert(layer_ctx->parent_layer_idx < layer_idx);
665 /* Move to the parent layer */
666 layer_idx = layer_ctx->parent_layer_idx;
667 }
668}
669
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000670dpe_error_t add_encoded_layer_certificate(const uint8_t *cert_buf,
671 size_t cert_buf_size,
672 uint8_t *encoded_cert_buf,
673 size_t encoded_cert_buf_size,
674 size_t *encoded_cert_actual_size)
675{
676 QCBOREncodeContext encode_ctx;
677 QCBORError encode_err;
678 UsefulBufC out;
679
680 QCBOREncode_Init(&encode_ctx, (UsefulBuf){ encoded_cert_buf, encoded_cert_buf_size });
681 QCBOREncode_OpenMap(&encode_ctx);
682
683 /* Encode CDI value as byte string */
684 QCBOREncode_AddBytesToMapN(&encode_ctx,
685 DPE_LABEL_CERT,
686 (UsefulBufC){ cert_buf, cert_buf_size });
687
688 QCBOREncode_CloseMap(&encode_ctx);
689 encode_err = QCBOREncode_Finish(&encode_ctx, &out);
690
691 /* Check for any encoding errors. */
692 if (encode_err == QCBOR_ERR_BUFFER_TOO_SMALL) {
693 return DPE_INSUFFICIENT_MEMORY;
694 } else if (encode_err != QCBOR_SUCCESS) {
695 return DPE_INTERNAL_ERROR;
696 }
697
698 *encoded_cert_actual_size = out.len;
699
700 return DPE_NO_ERROR;
701}