blob: 94ca197238ff4de68e6f7cb1e15123834eb21fb2 [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"
Tamas Ban769966d2024-09-27 14:35:05 +020016#include "t_cose_key.h"
Maulik Patel2358bbb2023-07-21 10:56:56 +010017#include "t_cose_sign1_sign.h"
18
19#define ID_HEX_SIZE (2 * DICE_ID_SIZE) /* Size of CDI encoded to ascii hex */
Maulik Patele6adc112023-08-18 14:21:51 +010020#define LABEL_HEX_SIZE (2 * DPE_EXTERNAL_LABEL_MAX_SIZE)
Maulik Patel2358bbb2023-07-21 10:56:56 +010021
Maulik Patel2358bbb2023-07-21 10:56:56 +010022static void convert_to_ascii_hex(const uint8_t *in,
23 size_t in_size,
24 char *out,
25 size_t out_size)
26{
27 const char hex_table[] = "0123456789abcdef";
28 size_t in_pos = 0;
29 size_t out_pos = 0;
30
31 for (in_pos = 0; in_pos < in_size && out_pos < out_size; in_pos++) {
Aditya Deshpande74a01ef2025-01-23 14:34:34 +000032 out[out_pos++] = hex_table[(in[in_pos] & 0xF0) >> 4];
Maulik Patel2358bbb2023-07-21 10:56:56 +010033 out[out_pos++] = hex_table[in[in_pos] & 0x0F];
34 }
35}
36
37static dpe_error_t t_cose_err_to_dpe_err(enum t_cose_err_t err)
38{
39 switch(err) {
40
41 case T_COSE_SUCCESS:
42 return DPE_NO_ERROR;
43
44 case T_COSE_ERR_TOO_SMALL:
45 return DPE_INSUFFICIENT_MEMORY;
46
47 default:
48 /* A lot of the errors are not mapped because they are
49 * primarily internal errors that should never happen. They
50 * end up here.
51 */
52 return DPE_INTERNAL_ERROR;
53 }
54}
55
Tamas Ban257471b2024-03-25 13:49:53 +010056static dpe_error_t certificate_encode_start(QCBOREncodeContext *cbor_enc_ctx,
57 struct t_cose_sign1_sign_ctx *signer_ctx,
Maulik Patel2358bbb2023-07-21 10:56:56 +010058 psa_key_handle_t private_key)
59{
60 enum t_cose_err_t t_cose_err;
61 struct t_cose_key attest_key;
62 UsefulBufC attest_key_id = {NULL, 0};
63
64 /* DPE Certificate is untagged COSE_Sign1 message */
Tamas Ban257471b2024-03-25 13:49:53 +010065 t_cose_sign1_sign_init(signer_ctx, T_COSE_OPT_OMIT_CBOR_TAG, DPE_T_COSE_ALG);
Maulik Patel2358bbb2023-07-21 10:56:56 +010066
67 attest_key.crypto_lib = T_COSE_CRYPTO_LIB_PSA;
68 attest_key.k.key_handle = private_key;
69
Tamas Ban257471b2024-03-25 13:49:53 +010070 t_cose_sign1_set_signing_key(signer_ctx, attest_key, attest_key_id);
Maulik Patel2358bbb2023-07-21 10:56:56 +010071
Tamas Ban257471b2024-03-25 13:49:53 +010072 /* It is expected that the CBOR encoder is already initialized */
Maulik Patel2358bbb2023-07-21 10:56:56 +010073
Tamas Ban257471b2024-03-25 13:49:53 +010074 /* This encodes and writes the cose headers to be into the CBOR context. */
75 t_cose_err = t_cose_sign1_encode_parameters(signer_ctx,
76 cbor_enc_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +010077 if (t_cose_err) {
78 return t_cose_err_to_dpe_err(t_cose_err);
79 }
80
Tamas Ban257471b2024-03-25 13:49:53 +010081 QCBOREncode_OpenMap(cbor_enc_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +010082
83 return DPE_NO_ERROR;
84}
85
Tamas Ban257471b2024-03-25 13:49:53 +010086static void add_key_usage_claim(QCBOREncodeContext *cbor_enc_ctx)
Maulik Patel2358bbb2023-07-21 10:56:56 +010087{
88 uint8_t key_usage = DPE_CERT_KEY_USAGE_CERT_SIGN;
89
90 /* Encode key usage as byte string */
Tamas Ban257471b2024-03-25 13:49:53 +010091 QCBOREncode_AddBytesToMapN(cbor_enc_ctx,
Maulik Patel2358bbb2023-07-21 10:56:56 +010092 DPE_CERT_LABEL_KEY_USAGE,
93 (UsefulBufC){ &key_usage,
94 sizeof(key_usage) });
95}
96
Tamas Ban257471b2024-03-25 13:49:53 +010097static void add_label_claim(QCBOREncodeContext *cbor_enc_ctx,
Maulik Patele6adc112023-08-18 14:21:51 +010098 const uint8_t *label,
99 size_t label_size)
100{
101 char label_hex[LABEL_HEX_SIZE];
102
103 /* If label is supplied, add label claim, else skip */
104 if ((label != NULL) && (label_size != 0)) {
105 convert_to_ascii_hex(&label[0],
106 label_size,
107 &label_hex[0],
108 sizeof(label_hex));
109
110 /* Encode label as text string */
Tamas Ban257471b2024-03-25 13:49:53 +0100111 QCBOREncode_AddTextToMapN(cbor_enc_ctx,
Maulik Patele6adc112023-08-18 14:21:51 +0100112 DPE_CERT_LABEL_EXTERNAL_LABEL,
113 (UsefulBufC){ &label_hex[0],
114 label_size });
115 }
116}
117
Tamas Ban257471b2024-03-25 13:49:53 +0100118static void add_cdi_export_claim(QCBOREncodeContext *cbor_enc_ctx,
Maulik Patel97a61fe2024-07-01 15:55:04 +0100119 const struct cert_context_t *cert_ctx)
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000120{
Tamas Ban257471b2024-03-25 13:49:53 +0100121 QCBOREncode_AddBoolToMapN(cbor_enc_ctx,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000122 DPE_CERT_LABEL_CDI_EXPORT,
Maulik Patel97a61fe2024-07-01 15:55:04 +0100123 cert_ctx->is_cdi_to_be_exported);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000124}
125
Tamas Ban257471b2024-03-25 13:49:53 +0100126static void add_subject_claim(QCBOREncodeContext *cbor_enc_ctx,
Maulik Patel97a61fe2024-07-01 15:55:04 +0100127 const struct cert_context_t *cert_ctx)
Maulik Patel2358bbb2023-07-21 10:56:56 +0100128{
129 char cdi_id_hex[ID_HEX_SIZE];
130
Maulik Patel97a61fe2024-07-01 15:55:04 +0100131 convert_to_ascii_hex(&cert_ctx->data.cdi_id[0],
132 sizeof(cert_ctx->data.cdi_id),
Maulik Patel2358bbb2023-07-21 10:56:56 +0100133 &cdi_id_hex[0],
134 sizeof(cdi_id_hex));
135 /* Encode subject as text string */
Tamas Ban257471b2024-03-25 13:49:53 +0100136 QCBOREncode_AddTextToMapN(cbor_enc_ctx,
Maulik Patel2358bbb2023-07-21 10:56:56 +0100137 DPE_CERT_LABEL_SUBJECT,
138 (UsefulBufC){ &cdi_id_hex[0],
139 sizeof(cdi_id_hex) });
140}
141
Tamas Ban257471b2024-03-25 13:49:53 +0100142static void encode_issuer_claim(QCBOREncodeContext *cbor_enc_ctx,
Jamie Fox93225232023-09-22 14:09:30 +0100143 const uint8_t *issuer,
144 size_t issuer_size)
Maulik Patel2358bbb2023-07-21 10:56:56 +0100145{
Maulik Patel2358bbb2023-07-21 10:56:56 +0100146 char cdi_id_hex[ID_HEX_SIZE];
147
Jamie Fox93225232023-09-22 14:09:30 +0100148 convert_to_ascii_hex(issuer,
149 issuer_size,
Maulik Patel2358bbb2023-07-21 10:56:56 +0100150 &cdi_id_hex[0],
151 sizeof(cdi_id_hex));
152
153 /* Encode issuer as text string */
Tamas Ban257471b2024-03-25 13:49:53 +0100154 QCBOREncode_AddTextToMapN(cbor_enc_ctx,
Maulik Patel2358bbb2023-07-21 10:56:56 +0100155 DPE_CERT_LABEL_ISSUER,
156 (UsefulBufC){ &cdi_id_hex[0],
157 sizeof(cdi_id_hex) });
158}
159
Tamas Ban769966d2024-09-27 14:35:05 +0200160static dpe_error_t encode_public_key(QCBOREncodeContext *cbor_enc_ctx,
161 psa_key_id_t attest_key_id)
Maulik Patel2358bbb2023-07-21 10:56:56 +0100162{
Tamas Ban769966d2024-09-27 14:35:05 +0200163 Q_USEFUL_BUF_MAKE_STACK_UB(cose_key_buf, MAX_ENCODED_COSE_KEY_SIZE);
164 struct t_cose_key attest_key;
165 struct q_useful_buf_c cose_key;
166 enum t_cose_err_t cose_res;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100167
Tamas Ban769966d2024-09-27 14:35:05 +0200168 /* Export the public key and encodes it to be a COSE_Key object */
169 attest_key.crypto_lib = T_COSE_CRYPTO_LIB_PSA;
170 attest_key.k.key_handle = attest_key_id;
171 cose_res = t_cose_key_encode(attest_key,
172 cose_key_buf,
173 &cose_key);
174 if (cose_res != T_COSE_SUCCESS) {
175 return DPE_INTERNAL_ERROR;
176 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100177
Tamas Ban769966d2024-09-27 14:35:05 +0200178 QCBOREncode_AddEncoded(cbor_enc_ctx, cose_key);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100179
Tamas Ban769966d2024-09-27 14:35:05 +0200180 return DPE_NO_ERROR;
181}
Maulik Patel2358bbb2023-07-21 10:56:56 +0100182
Tamas Ban769966d2024-09-27 14:35:05 +0200183static dpe_error_t add_public_key_claim(QCBOREncodeContext *cbor_enc_ctx,
184 psa_key_id_t attest_key_id)
185{
186 dpe_error_t err;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100187
Tamas Ban769966d2024-09-27 14:35:05 +0200188 /* COSE_Key is encoded as a map. This map is wrapped into the a
189 * byte string and it is further encoded as a map.
Tamas Ban8ed52802024-03-14 09:36:05 +0100190 */
Tamas Ban257471b2024-03-25 13:49:53 +0100191 QCBOREncode_BstrWrapInMapN(cbor_enc_ctx, DPE_CERT_LABEL_SUBJECT_PUBLIC_KEY);
Tamas Ban769966d2024-09-27 14:35:05 +0200192 err = encode_public_key(cbor_enc_ctx, attest_key_id);
193 if (err != DPE_NO_ERROR) {
194 return err;
195 }
196 QCBOREncode_CloseBstrWrap2(cbor_enc_ctx, false, NULL);
197
198 return DPE_NO_ERROR;
Maulik Patele6adc112023-08-18 14:21:51 +0100199}
200
Tamas Ban769966d2024-09-27 14:35:05 +0200201static dpe_error_t add_public_key_to_certificate_chain(QCBOREncodeContext *cbor_enc_ctx,
202 psa_key_id_t attest_key_id)
Maulik Patele6adc112023-08-18 14:21:51 +0100203{
Tamas Ban769966d2024-09-27 14:35:05 +0200204 dpe_error_t err;
Maulik Patele6adc112023-08-18 14:21:51 +0100205
Tamas Ban769966d2024-09-27 14:35:05 +0200206 /* COSE_Key is encoded as a map wrapped into a byte string */
Tamas Ban257471b2024-03-25 13:49:53 +0100207 QCBOREncode_BstrWrap(cbor_enc_ctx);
Tamas Ban769966d2024-09-27 14:35:05 +0200208 err = encode_public_key(cbor_enc_ctx, attest_key_id);
209 if (err != DPE_NO_ERROR) {
210 return err;
211 }
212 QCBOREncode_CloseBstrWrap2(cbor_enc_ctx, false, NULL);
213
214 return DPE_NO_ERROR;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100215}
216
Tamas Ban257471b2024-03-25 13:49:53 +0100217static dpe_error_t certificate_encode_finish(QCBOREncodeContext *cbor_enc_ctx,
218 struct t_cose_sign1_sign_ctx *signer_ctx,
219 bool finish_cbor_encoding,
Maulik Patel2358bbb2023-07-21 10:56:56 +0100220 UsefulBufC *completed_cert)
221{
222 QCBORError qcbor_result;
223 enum t_cose_err_t cose_return_value;
224
Tamas Ban257471b2024-03-25 13:49:53 +0100225 QCBOREncode_CloseMap(cbor_enc_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100226
227 /* -- Finish up the COSE_Sign1. This is where the signing happens -- */
Tamas Ban257471b2024-03-25 13:49:53 +0100228 cose_return_value = t_cose_sign1_encode_signature(signer_ctx,
229 cbor_enc_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100230 if (cose_return_value) {
231 /* Main errors are invoking the hash or signature */
232 return t_cose_err_to_dpe_err(cose_return_value);
233 }
234
Tamas Ban257471b2024-03-25 13:49:53 +0100235 /* If only a single certificate is created then encoding can be finished.
236 * Otherwise, when multiple certifcate is encoded in a raw
237 * (GetCertificateChain) then encoding will be finished
238 * by close_certificate_chain().
Maulik Patel2358bbb2023-07-21 10:56:56 +0100239 */
Tamas Ban257471b2024-03-25 13:49:53 +0100240 if (finish_cbor_encoding) {
241 /* Finally close off the CBOR formatting and get the pointer and length
242 * of the resulting COSE_Sign1.
243 */
244 qcbor_result = QCBOREncode_Finish(cbor_enc_ctx, completed_cert);
245 if (qcbor_result == QCBOR_ERR_BUFFER_TOO_SMALL) {
246 return DPE_INSUFFICIENT_MEMORY;
247 } else if (qcbor_result != QCBOR_SUCCESS) {
248 /* likely from array not closed, too many closes, ... */
249 return DPE_INTERNAL_ERROR;
Tamas Ban257471b2024-03-25 13:49:53 +0100250 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100251 }
Maulik Patel77186392024-04-15 12:39:04 +0100252
253 return DPE_NO_ERROR;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100254}
255
256static void encode_sw_component_measurements(QCBOREncodeContext *encode_ctx,
257 struct component_context_t *component_ctx)
258{
259 QCBOREncode_OpenMap(encode_ctx);
260
261 /* Encode measurement value as byte string */
262 QCBOREncode_AddBytesToMapN(encode_ctx,
263 DPE_CERT_LABEL_CODE_HASH,
264 (UsefulBufC){ &component_ctx->data.measurement_value,
265 DICE_HASH_SIZE });
266
267 /* Encode measurement descriptor version as byte string */
268 QCBOREncode_AddBytesToMapN(encode_ctx,
269 DPE_CERT_LABEL_CODE_DESCRIPTOR,
270 (UsefulBufC){ &component_ctx->data.measurement_descriptor,
271 component_ctx->data.measurement_descriptor_size });
272
273 /* Encode signer ID Hash as byte string */
274 QCBOREncode_AddBytesToMapN(encode_ctx,
275 DPE_CERT_LABEL_AUTHORITY_HASH,
276 (UsefulBufC){ &component_ctx->data.signer_id,
277 DICE_HASH_SIZE });
278
279 /* Encode signer ID descriptor as byte string */
280 QCBOREncode_AddBytesToMapN(encode_ctx,
281 DPE_CERT_LABEL_AUTHORITY_DESCRIPTOR,
282 (UsefulBufC){ &component_ctx->data.signer_id_descriptor,
283 component_ctx->data.signer_id_descriptor_size });
284
285 if (component_ctx->data.config_descriptor_size > 0) {
286 /* Encode config descriptor as byte string */
287 QCBOREncode_AddBytesToMapN(encode_ctx,
288 DPE_CERT_LABEL_CONFIGURATION_DESCRIPTOR,
289 (UsefulBufC){ &component_ctx->data.config_descriptor,
290 component_ctx->data.config_descriptor_size });
291 /* Encode config value as byte string */
292 QCBOREncode_AddBytesToMapN(encode_ctx,
293 DPE_CERT_LABEL_CONFIGURATION_HASH,
294 (UsefulBufC){ &component_ctx->data.config_value,
295 DICE_INLINE_CONFIG_SIZE });
296 } else {
297 /* Encode config value as byte string */
298 QCBOREncode_AddBytesToMapN(encode_ctx,
299 DPE_CERT_LABEL_CONFIGURATION_DESCRIPTOR,
300 (UsefulBufC){ &component_ctx->data.config_value,
301 DICE_INLINE_CONFIG_SIZE });
302 }
303
304 /* Encode mode value as byte string */
305 QCBOREncode_AddBytesToMapN(encode_ctx,
306 DPE_CERT_LABEL_MODE,
307 (UsefulBufC){ &component_ctx->data.mode,
308 sizeof(DiceMode) });
309
310 QCBOREncode_CloseMap(encode_ctx);
311}
312
Maulik Patel97a61fe2024-07-01 15:55:04 +0100313static dpe_error_t encode_sw_components_array(const struct cert_context_t *cert_ctx,
314 QCBOREncodeContext *cbor_enc_ctx)
Maulik Patel2358bbb2023-07-21 10:56:56 +0100315{
Maulik Patel009450d2024-04-23 12:03:10 +0100316 int i;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100317 struct component_context_t *component_ctx;
318
Tamas Bancb237ce2024-05-03 14:01:33 +0200319 /* Open array which stores SW components claims. */
320 QCBOREncode_OpenArrayInMapN(cbor_enc_ctx, DPE_CERT_LABEL_SW_COMPONENTS);
321
322 /* Add elements to the array if there is any */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100323 for (i = 0; i < cert_ctx->linked_components.count; i++) {
Maulik Patel00d06b62024-07-03 14:51:50 +0100324 component_ctx = cert_ctx->linked_components.ptr[i];
Tamas Bancb237ce2024-05-03 14:01:33 +0200325 if (component_ctx == NULL) {
326 return DPE_INTERNAL_ERROR;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100327 }
Tamas Bancb237ce2024-05-03 14:01:33 +0200328 encode_sw_component_measurements(cbor_enc_ctx, component_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100329 }
Maulik Patel009450d2024-04-23 12:03:10 +0100330
Tamas Bancb237ce2024-05-03 14:01:33 +0200331 /* Close array which stores SW components claims. */
332 QCBOREncode_CloseArray(cbor_enc_ctx);
333
Maulik Patel009450d2024-04-23 12:03:10 +0100334 return DPE_NO_ERROR;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100335}
336
Tamas Ban257471b2024-03-25 13:49:53 +0100337static dpe_error_t add_issuer_claim(QCBOREncodeContext *cbor_enc_ctx,
Maulik Patel97a61fe2024-07-01 15:55:04 +0100338 const struct cert_context_t *cert_ctx,
Jamie Fox93225232023-09-22 14:09:30 +0100339 psa_key_id_t root_attest_key_id,
Maulik Patel97a61fe2024-07-01 15:55:04 +0100340 const struct cert_context_t *parent_cert_ctx)
Jamie Fox93225232023-09-22 14:09:30 +0100341{
342 uint8_t rot_cdi_id[DICE_ID_SIZE];
343
Maulik Patel97a61fe2024-07-01 15:55:04 +0100344 if (cert_ctx->is_rot_cert_ctx) {
345 /* For the RoT certificate, issuer id is derived from the root attestation key */
Jamie Fox93225232023-09-22 14:09:30 +0100346 if (derive_cdi_id(root_attest_key_id, rot_cdi_id,
347 sizeof(rot_cdi_id)) != PSA_SUCCESS) {
348 return DPE_INTERNAL_ERROR;
349 }
350
Tamas Ban257471b2024-03-25 13:49:53 +0100351 encode_issuer_claim(cbor_enc_ctx,
Jamie Fox93225232023-09-22 14:09:30 +0100352 rot_cdi_id,
353 sizeof(rot_cdi_id));
354 } else {
Tamas Ban257471b2024-03-25 13:49:53 +0100355 encode_issuer_claim(cbor_enc_ctx,
Maulik Patel97a61fe2024-07-01 15:55:04 +0100356 parent_cert_ctx->data.cdi_id,
357 sizeof(parent_cert_ctx->data.cdi_id));
Jamie Fox93225232023-09-22 14:09:30 +0100358 }
359
360 return DPE_NO_ERROR;
361}
Maulik Patel2358bbb2023-07-21 10:56:56 +0100362
Maulik Patel97a61fe2024-07-01 15:55:04 +0100363static dpe_error_t encode_certificate_internal(const struct cert_context_t *cert_ctx,
364 QCBOREncodeContext *cbor_enc_ctx,
365 bool finish_cbor_encoding,
366 size_t *cert_actual_size)
Maulik Patel2358bbb2023-07-21 10:56:56 +0100367{
Tamas Ban257471b2024-03-25 13:49:53 +0100368 struct t_cose_sign1_sign_ctx signer_ctx;
Maulik Patel97a61fe2024-07-01 15:55:04 +0100369 struct cert_context_t *parent_cert_ctx;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100370 dpe_error_t err;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100371 UsefulBufC completed_cert;
Jamie Fox93225232023-09-22 14:09:30 +0100372 psa_key_id_t attest_key_id;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100373
Tamas Ban257471b2024-03-25 13:49:53 +0100374 /* Valid options: true & !NULL OR false & NULL */
375 assert(finish_cbor_encoding ^ (cert_actual_size == NULL));
376
Maulik Patel00d06b62024-07-03 14:51:50 +0100377 parent_cert_ctx = cert_ctx->parent_cert_ptr;
378 assert(parent_cert_ctx != NULL);
Tamas Ban257471b2024-03-25 13:49:53 +0100379
Maulik Patel97a61fe2024-07-01 15:55:04 +0100380 /* The RoT certificate is signed by the provisioned attestation key,
381 * all other certificates are signed by the parent certificate's attestation key.
Jamie Fox93225232023-09-22 14:09:30 +0100382 */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100383 if (cert_ctx->is_rot_cert_ctx) {
Jamie Fox93225232023-09-22 14:09:30 +0100384 attest_key_id = dpe_plat_get_root_attest_key_id();
385 } else {
Maulik Patel97a61fe2024-07-01 15:55:04 +0100386 attest_key_id = parent_cert_ctx->data.attest_key_id;
Jamie Fox93225232023-09-22 14:09:30 +0100387 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100388
Tamas Ban257471b2024-03-25 13:49:53 +0100389 /* Get started creating the certificate. This sets up the CBOR and
Maulik Patel2358bbb2023-07-21 10:56:56 +0100390 * COSE contexts which causes the COSE headers to be constructed.
391 */
Tamas Ban257471b2024-03-25 13:49:53 +0100392 err = certificate_encode_start(cbor_enc_ctx,
393 &signer_ctx,
Maulik Patel2358bbb2023-07-21 10:56:56 +0100394 attest_key_id);
395 if (err != DPE_NO_ERROR) {
396 return err;
397 }
398
399 /* Add all the required claims */
400 /* Add issuer/authority claim */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100401 err = add_issuer_claim(cbor_enc_ctx, cert_ctx, attest_key_id, parent_cert_ctx);
Jamie Fox93225232023-09-22 14:09:30 +0100402 if (err != DPE_NO_ERROR) {
403 return err;
404 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100405
406 /* Add subject claim */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100407 add_subject_claim(cbor_enc_ctx, cert_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100408
Maulik Patel97a61fe2024-07-01 15:55:04 +0100409 /* Encode all firmware measurements for the components linked to this
410 * certificate context
411 */
Maulik Patel2358bbb2023-07-21 10:56:56 +0100412 //TODO:
413 /* It is not yet defined in the open-dice profile how to represent
414 * multiple SW components in a single certificate; In current implementation,
415 * an array is created for all the components' measurements and within the
416 * array, there are multiple maps, one for each SW component
417 */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100418 err = encode_sw_components_array(cert_ctx, cbor_enc_ctx);
Maulik Patel009450d2024-04-23 12:03:10 +0100419 if (err != DPE_NO_ERROR) {
420 return err;
421 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100422
Maulik Patele6adc112023-08-18 14:21:51 +0100423 /* Add label claim */
Tamas Ban257471b2024-03-25 13:49:53 +0100424 add_label_claim(cbor_enc_ctx,
Maulik Patel97a61fe2024-07-01 15:55:04 +0100425 &cert_ctx->data.external_key_deriv_label[0],
426 cert_ctx->data.external_key_deriv_label_len);
Maulik Patele6adc112023-08-18 14:21:51 +0100427
Maulik Patel2358bbb2023-07-21 10:56:56 +0100428 /* Add public key claim */
Tamas Ban769966d2024-09-27 14:35:05 +0200429 err = add_public_key_claim(cbor_enc_ctx, cert_ctx->data.attest_key_id);
430 if (err != DPE_NO_ERROR) {
431 return err;
432 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100433
434 /* Add key usage claim */
Tamas Ban257471b2024-03-25 13:49:53 +0100435 add_key_usage_claim(cbor_enc_ctx);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100436
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000437 /* Add CDI exported claim */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100438 if (cert_ctx->is_cdi_to_be_exported) {
439 add_cdi_export_claim(cbor_enc_ctx, cert_ctx);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000440 }
441
Tamas Ban257471b2024-03-25 13:49:53 +0100442 /* Finish up creating the certificate. This is where the actual signature
443 * is generated.
Maulik Patel2358bbb2023-07-21 10:56:56 +0100444 */
Tamas Ban257471b2024-03-25 13:49:53 +0100445 err = certificate_encode_finish(cbor_enc_ctx, &signer_ctx,
446 finish_cbor_encoding, &completed_cert);
Maulik Patel2358bbb2023-07-21 10:56:56 +0100447 if (err != DPE_NO_ERROR) {
448 return err;
449 }
450
Tamas Ban257471b2024-03-25 13:49:53 +0100451 /* Update the final size of the certificate if requested */
452 if (cert_actual_size != NULL) {
453 *cert_actual_size = completed_cert.len;
454 }
Maulik Patel2358bbb2023-07-21 10:56:56 +0100455
456 return err;
457}
458
Maulik Patel97a61fe2024-07-01 15:55:04 +0100459dpe_error_t encode_certificate(const struct cert_context_t *cert_ctx,
460 uint8_t *cert_buf,
461 size_t cert_buf_size,
462 size_t *cert_actual_size)
Tamas Ban257471b2024-03-25 13:49:53 +0100463{
464 QCBOREncodeContext cbor_enc_ctx;
465
466 QCBOREncode_Init(&cbor_enc_ctx,
467 (UsefulBuf){ cert_buf,
468 cert_buf_size });
469
470 /* Only a single certificate is encoded */
Maulik Patel97a61fe2024-07-01 15:55:04 +0100471 return encode_certificate_internal(cert_ctx, &cbor_enc_ctx,
472 true, cert_actual_size);
Tamas Ban257471b2024-03-25 13:49:53 +0100473}
474
Maulik Patel97a61fe2024-07-01 15:55:04 +0100475dpe_error_t store_certificate(const struct cert_context_t *cert_ctx)
Maulik Patel2358bbb2023-07-21 10:56:56 +0100476{
477 //TODO:
Maulik Patel97a61fe2024-07-01 15:55:04 +0100478 (void)cert_ctx;
Maulik Patel2358bbb2023-07-21 10:56:56 +0100479 return DPE_NO_ERROR;
480}
Maulik Patele6adc112023-08-18 14:21:51 +0100481
Tamas Ban257471b2024-03-25 13:49:53 +0100482static void open_certificate_chain(QCBOREncodeContext *cbor_enc_ctx,
Maulik Patele6adc112023-08-18 14:21:51 +0100483 uint8_t *cert_chain_buf,
484 size_t cert_chain_buf_size)
485{
486 /* Set up encoding context with output buffer. */
Tamas Ban257471b2024-03-25 13:49:53 +0100487 QCBOREncode_Init(cbor_enc_ctx,
Maulik Patele6adc112023-08-18 14:21:51 +0100488 (UsefulBuf){ &cert_chain_buf[0],
489 cert_chain_buf_size });
Tamas Ban257471b2024-03-25 13:49:53 +0100490 QCBOREncode_OpenArray(cbor_enc_ctx);
Maulik Patele6adc112023-08-18 14:21:51 +0100491}
492
Tamas Ban257471b2024-03-25 13:49:53 +0100493static dpe_error_t close_certificate_chain(QCBOREncodeContext *cbor_enc_ctx,
Maulik Patele6adc112023-08-18 14:21:51 +0100494 size_t *cert_chain_actual_size)
495{
496 QCBORError encode_error;
497 UsefulBufC completed_cert_chain;
498
Tamas Ban257471b2024-03-25 13:49:53 +0100499 QCBOREncode_CloseArray(cbor_enc_ctx);
Maulik Patele6adc112023-08-18 14:21:51 +0100500
Tamas Ban257471b2024-03-25 13:49:53 +0100501 encode_error = QCBOREncode_Finish(cbor_enc_ctx,
Maulik Patele6adc112023-08-18 14:21:51 +0100502 &completed_cert_chain);
503
504 /* Check for any encoding errors. */
505 if (encode_error == QCBOR_ERR_BUFFER_TOO_SMALL) {
506 return DPE_INSUFFICIENT_MEMORY;
507 } else if (encode_error != QCBOR_SUCCESS) {
508 return DPE_INTERNAL_ERROR;
509 }
510
511 *cert_chain_actual_size = completed_cert_chain.len;
512
513 return DPE_NO_ERROR;
514}
515
Tamas Ban257471b2024-03-25 13:49:53 +0100516static dpe_error_t add_root_attestation_public_key(QCBOREncodeContext *cbor_enc_ctx)
Maulik Patele6adc112023-08-18 14:21:51 +0100517{
Tamas Ban769966d2024-09-27 14:35:05 +0200518 psa_key_id_t attest_key_id = dpe_plat_get_root_attest_key_id();
519 dpe_error_t err;
Maulik Patele6adc112023-08-18 14:21:51 +0100520
Tamas Ban769966d2024-09-27 14:35:05 +0200521 err = add_public_key_to_certificate_chain(cbor_enc_ctx, attest_key_id);
522 if (err != DPE_NO_ERROR) {
523 return err;
Maulik Patele6adc112023-08-18 14:21:51 +0100524 }
525
Maulik Patele6adc112023-08-18 14:21:51 +0100526 return DPE_NO_ERROR;
527}
528
Maulik Patel97a61fe2024-07-01 15:55:04 +0100529dpe_error_t get_certificate_chain(const struct cert_context_t *cert_ctx,
Maulik Patele6adc112023-08-18 14:21:51 +0100530 uint8_t *cert_chain_buf,
531 size_t cert_chain_buf_size,
532 size_t *cert_chain_actual_size)
533{
Tamas Ban257471b2024-03-25 13:49:53 +0100534 QCBOREncodeContext cbor_enc_ctx;
Maulik Patele6adc112023-08-18 14:21:51 +0100535 dpe_error_t err;
536 int i;
Maulik Patel00d06b62024-07-03 14:51:50 +0100537 const struct cert_context_t *cert_chain[MAX_NUM_OF_CERTIFICATES];
Maulik Patel97a61fe2024-07-01 15:55:04 +0100538 uint16_t cert_cnt = 0;
Maulik Patele6adc112023-08-18 14:21:51 +0100539
Tamas Ban257471b2024-03-25 13:49:53 +0100540 open_certificate_chain(&cbor_enc_ctx,
Maulik Patele6adc112023-08-18 14:21:51 +0100541 cert_chain_buf,
542 cert_chain_buf_size);
543
544 /* Add DICE/Root public key (IAK public key) as the first entry of array */
Tamas Ban257471b2024-03-25 13:49:53 +0100545 err = add_root_attestation_public_key(&cbor_enc_ctx);
Maulik Patele6adc112023-08-18 14:21:51 +0100546 if (err != DPE_NO_ERROR) {
547 return err;
548 }
549
Maulik Patel97a61fe2024-07-01 15:55:04 +0100550 /* Loop from leaf to the RoT certificate & save all the linked certificates in this chain */
Maulik Patel00d06b62024-07-03 14:51:50 +0100551 while ((cert_ctx != NULL) && (cert_cnt < MAX_NUM_OF_CERTIFICATES)) {
Maulik Patele6adc112023-08-18 14:21:51 +0100552
Maulik Patel00d06b62024-07-03 14:51:50 +0100553 /* Save certificate context pointer */
554 cert_chain[cert_cnt++] = cert_ctx;
Maulik Patele6adc112023-08-18 14:21:51 +0100555
Maulik Patel00d06b62024-07-03 14:51:50 +0100556 if (cert_ctx->is_rot_cert_ctx) {
Maulik Patele6adc112023-08-18 14:21:51 +0100557 /* This is the end of chain */
558 break;
559 }
560
Maulik Patel97a61fe2024-07-01 15:55:04 +0100561 /* Move to the parent certificate context */
Maulik Patel00d06b62024-07-03 14:51:50 +0100562 cert_ctx = cert_ctx->parent_cert_ptr;
Maulik Patele6adc112023-08-18 14:21:51 +0100563 }
564
Maulik Patel97a61fe2024-07-01 15:55:04 +0100565 /* Add certificate from RoT to leaf certificate order */
Maulik Patel00d06b62024-07-03 14:51:50 +0100566 for (i = cert_cnt - 1; i >= 0; i--) {
Tamas Ban257471b2024-03-25 13:49:53 +0100567 /* Might multiple certificate is encoded */
Maulik Patel00d06b62024-07-03 14:51:50 +0100568 err = encode_certificate_internal(cert_chain[i], &cbor_enc_ctx,
Maulik Patel97a61fe2024-07-01 15:55:04 +0100569 false, NULL);
Tamas Ban257471b2024-03-25 13:49:53 +0100570 if (err != DPE_NO_ERROR) {
571 return err;
572 }
Maulik Patele6adc112023-08-18 14:21:51 +0100573 }
574
Tamas Ban257471b2024-03-25 13:49:53 +0100575 return close_certificate_chain(&cbor_enc_ctx,
Maulik Patele6adc112023-08-18 14:21:51 +0100576 cert_chain_actual_size);
577}
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000578
Tamas Ban5179a4d2024-01-25 17:05:30 +0100579dpe_error_t encode_cdi(const uint8_t cdi_attest_buf[DICE_CDI_SIZE],
580 const uint8_t cdi_seal_buf[DICE_CDI_SIZE],
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000581 uint8_t *encoded_cdi_buf,
582 size_t encoded_cdi_buf_size,
583 size_t *encoded_cdi_actual_size)
584{
585 QCBOREncodeContext encode_ctx;
586 QCBORError encode_err;
587 UsefulBufC out;
588
589 QCBOREncode_Init(&encode_ctx, (UsefulBuf){ encoded_cdi_buf, encoded_cdi_buf_size });
590 QCBOREncode_OpenMap(&encode_ctx);
591
592 /* Encode CDI value as byte string */
593 QCBOREncode_AddBytesToMapN(&encode_ctx,
594 DPE_LABEL_CDI_ATTEST,
Tamas Ban5179a4d2024-01-25 17:05:30 +0100595 (UsefulBufC){ cdi_attest_buf, DICE_CDI_SIZE });
596
597 QCBOREncode_AddBytesToMapN(&encode_ctx,
598 DPE_LABEL_CDI_SEAL,
599 (UsefulBufC){ cdi_seal_buf, DICE_CDI_SIZE });
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000600
601 QCBOREncode_CloseMap(&encode_ctx);
602 encode_err = QCBOREncode_Finish(&encode_ctx, &out);
603
604 /* Check for any encoding errors. */
605 if (encode_err == QCBOR_ERR_BUFFER_TOO_SMALL) {
606 return DPE_INSUFFICIENT_MEMORY;
607 } else if (encode_err != QCBOR_SUCCESS) {
608 return DPE_INTERNAL_ERROR;
609 }
610
611 *encoded_cdi_actual_size = out.len;
612
613 return DPE_NO_ERROR;
614}