blob: b2381e14642324de8903c69ec3bc065489e4e1d5 [file] [log] [blame]
Jamie Foxab30e712023-03-30 17:48:36 +01001/*
Tamas Band0983e92024-01-25 16:32:51 +01002 * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
Jamie Foxab30e712023-03-30 17:48:36 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include "dpe_cmd_decode.h"
9
10#include <string.h>
11
12#include "dpe_client.h"
Maulik Patelad2f3db2023-05-17 15:41:36 +010013#include "dpe_context_mngr.h"
Maulik Patele6adc112023-08-18 14:21:51 +010014#include "dpe_crypto_config.h"
Jamie Foxab30e712023-03-30 17:48:36 +010015#include "qcbor/qcbor_encode.h"
16#include "qcbor/qcbor_decode.h"
17#include "qcbor/qcbor_spiffy_decode.h"
18
Maulik Patelfbe9bff2024-02-09 14:05:25 +000019#define CHECK_CBOR_ERROR(decode_ctx) \
20 qcbor_err = QCBORDecode_GetAndResetError(decode_ctx); \
21 if ((qcbor_err != QCBOR_SUCCESS) && (qcbor_err != QCBOR_ERR_LABEL_NOT_FOUND)) { \
22 return DPE_INVALID_COMMAND; \
23 }
24
Tamas Band0983e92024-01-25 16:32:51 +010025/*
26 * The goal to reuse the cmd_buf allocated in dpe_req_mngr.c to create the
27 * big objects (certificate, certificate_chain) in place rather then allocate
28 * a separate buffer on the stack and later copy them to cmd_buf.
29 *
30 * The temporary buffer is allocated from the end of the cmd_buf. When the
31 * reply is encoded then the content of the temp buf is moved to its final
32 * place in the cmd_buf.
33 *
34 * Overlapping copy is not an issue because QCBOR relies on memmove under the
35 * hood which handles this scenario.
36 *
37 * Note:
38 * Make sure that the beginning of the encoded reply does not overwrite the
39 * data in the temp buf. That is why the temp buff is allocated at the end of
40 * cmd_buf.
41 */
42#define REUSE_CMD_BUF(size) (uint8_t *)encode_ctx->OutBuf.UB.ptr + \
43 encode_ctx->OutBuf.UB.len - \
44 (size)
45
Jamie Foxab30e712023-03-30 17:48:36 +010046static dpe_error_t decode_dice_inputs(QCBORDecodeContext *decode_ctx,
47 DiceInputValues *input)
48{
49 QCBORError qcbor_err;
50 UsefulBufC out = { NULL, 0 };
51 int64_t out_int;
52
53 /* The DICE inputs are encoded as a map wrapped into a byte string */
54 QCBORDecode_EnterBstrWrappedFromMapN(decode_ctx,
Maulik Patela81605b2023-10-24 12:17:03 +010055 DPE_DERIVE_CONTEXT_INPUT_DATA,
Jamie Foxab30e712023-03-30 17:48:36 +010056 QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL);
57 QCBORDecode_EnterMap(decode_ctx, NULL);
58
59 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CODE_HASH, &out);
60 if (out.len != sizeof(input->code_hash)) {
61 return DPE_INVALID_COMMAND;
62 }
63 memcpy(input->code_hash, out.ptr, out.len);
64
65 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CODE_DESCRIPTOR, &out);
66 input->code_descriptor = out.ptr;
67 input->code_descriptor_size = out.len;
68
69 QCBORDecode_GetInt64InMapN(decode_ctx, DICE_CONFIG_TYPE, &out_int);
70
71 /* Check error state before interpreting config type */
72 qcbor_err = QCBORDecode_GetError(decode_ctx);
73 if (qcbor_err != QCBOR_SUCCESS) {
74 return DPE_INVALID_COMMAND;
75 }
76
77 if (out_int < kDiceConfigTypeInline ||
78 out_int > kDiceConfigTypeDescriptor) {
79 return DPE_INVALID_COMMAND;
80 }
81 input->config_type = (DiceConfigType)out_int;
82
83 /* Only one of config value or config descriptor needs to be provided */
84 if (input->config_type == kDiceConfigTypeInline) {
85 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CONFIG_VALUE, &out);
86 if (out.len != sizeof(input->config_value)) {
87 return DPE_INVALID_COMMAND;
88 }
89 memcpy(input->config_value, out.ptr, out.len);
90
91 /* Config descriptor is not provided */
92 input->config_descriptor = NULL;
93 input->config_descriptor_size = 0;
94 } else {
95 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CONFIG_DESCRIPTOR,
96 &out);
97 input->config_descriptor = out.ptr;
98 input->config_descriptor_size = out.len;
99
100 /* Config value is not provided */
101 memset(input->config_value, 0, sizeof(input->config_value));
102 }
103
104 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_AUTHORITY_HASH, &out);
105 if (out.len != sizeof(input->authority_hash)) {
106 return DPE_INVALID_COMMAND;
107 }
108 memcpy(input->authority_hash, out.ptr, out.len);
109
110 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_AUTHORITY_DESCRIPTOR,
111 &out);
112 input->authority_descriptor = out.ptr;
113 input->authority_descriptor_size = out.len;
114
115 QCBORDecode_GetInt64InMapN(decode_ctx, DICE_MODE, &out_int);
116 if (out_int < kDiceModeNotInitialized || out_int > kDiceModeMaintenance) {
117 return DPE_INVALID_COMMAND;
118 }
119 input->mode = (DiceMode)out_int;
120
121 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_HIDDEN, &out);
122 if (out.len != sizeof(input->hidden)) {
123 return DPE_INVALID_COMMAND;
124 }
125 memcpy(input->hidden, out.ptr, out.len);
126
127 QCBORDecode_ExitMap(decode_ctx);
128 QCBORDecode_ExitBstrWrapped(decode_ctx);
129
Maulik Pateld936d742024-01-08 14:16:46 +0000130 qcbor_err = QCBORDecode_GetError(decode_ctx);
131 if (qcbor_err != QCBOR_SUCCESS) {
132 return DPE_INVALID_COMMAND;
133 }
134
Jamie Foxab30e712023-03-30 17:48:36 +0100135 return DPE_NO_ERROR;
136}
137
Maulik Patela81605b2023-10-24 12:17:03 +0100138static dpe_error_t decode_derive_context(QCBORDecodeContext *decode_ctx,
139 QCBOREncodeContext *encode_ctx,
140 int32_t client_id)
Jamie Foxab30e712023-03-30 17:48:36 +0100141{
142 dpe_error_t dpe_err;
143 QCBORError qcbor_err;
144 UsefulBufC out;
145 int context_handle;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000146 int32_t target_locality;
Jamie Foxab30e712023-03-30 17:48:36 +0100147 bool retain_parent_context;
Maulik Patela81605b2023-10-24 12:17:03 +0100148 bool allow_new_context_to_derive;
Jamie Foxab30e712023-03-30 17:48:36 +0100149 bool create_certificate;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000150 bool return_certificate;
151 bool allow_new_context_to_export;
152 bool export_cdi;
Jamie Foxab30e712023-03-30 17:48:36 +0100153 DiceInputValues dice_inputs;
Maulik Patela81605b2023-10-24 12:17:03 +0100154 int new_context_handle;
Jamie Foxab30e712023-03-30 17:48:36 +0100155 int new_parent_context_handle;
Tamas Band0983e92024-01-25 16:32:51 +0100156 uint8_t *new_certificate_buf = REUSE_CMD_BUF(DICE_CERT_SIZE);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000157 uint8_t exported_cdi_buf[DICE_MAX_ENCODED_CDI_SIZE];
Maulik Patelcb14cde2024-01-23 12:39:53 +0000158 uint32_t cert_id;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000159 size_t new_certificate_actual_size = 0;
160 size_t exported_cdi_actual_size = 0;
Jamie Foxab30e712023-03-30 17:48:36 +0100161
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000162 /* Initialise optional parameters with their default value in case
163 * they are not encoded in the input command
164 */
165 cert_id = DPE_CERT_ID_INVALID;
166 retain_parent_context = false;
167 allow_new_context_to_derive = true;
168 create_certificate = true;
169 return_certificate = false;
170 allow_new_context_to_export = false;
171 export_cdi = false;
172
Maulik Patela81605b2023-10-24 12:17:03 +0100173 /* Decode DeriveContext command */
Jamie Foxab30e712023-03-30 17:48:36 +0100174 QCBORDecode_EnterMap(decode_ctx, NULL);
175
Maulik Patela81605b2023-10-24 12:17:03 +0100176 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DERIVE_CONTEXT_CONTEXT_HANDLE,
Jamie Foxab30e712023-03-30 17:48:36 +0100177 &out);
Maulik Patelcb14cde2024-01-23 12:39:53 +0000178 qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
179 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
Jamie Foxab30e712023-03-30 17:48:36 +0100180 return DPE_INVALID_COMMAND;
181 }
182 memcpy(&context_handle, out.ptr, out.len);
183
Maulik Patelcb14cde2024-01-23 12:39:53 +0000184 QCBORDecode_GetUInt64InMapN(decode_ctx, DPE_DERIVE_CONTEXT_CERT_ID, &cert_id);
185 /* Check if cert_id was encoded in the received command buffer */
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000186 CHECK_CBOR_ERROR(decode_ctx);
Maulik Patelcb14cde2024-01-23 12:39:53 +0000187
Maulik Patela81605b2023-10-24 12:17:03 +0100188 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_RETAIN_PARENT_CONTEXT,
Jamie Foxab30e712023-03-30 17:48:36 +0100189 &retain_parent_context);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000190 CHECK_CBOR_ERROR(decode_ctx);
Jamie Foxab30e712023-03-30 17:48:36 +0100191
Maulik Patela81605b2023-10-24 12:17:03 +0100192 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_DERIVE,
193 &allow_new_context_to_derive);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000194 CHECK_CBOR_ERROR(decode_ctx);
Jamie Foxab30e712023-03-30 17:48:36 +0100195
Maulik Patela81605b2023-10-24 12:17:03 +0100196 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_CREATE_CERTIFICATE,
Jamie Foxab30e712023-03-30 17:48:36 +0100197 &create_certificate);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000198 CHECK_CBOR_ERROR(decode_ctx);
Jamie Foxab30e712023-03-30 17:48:36 +0100199
200 dpe_err = decode_dice_inputs(decode_ctx, &dice_inputs);
201 if (dpe_err != DPE_NO_ERROR) {
202 return dpe_err;
203 }
204
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000205 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DERIVE_CONTEXT_TARGET_LOCALITY,
206 &out);
207 if (out.len != sizeof(target_locality)) {
208 return DPE_INVALID_COMMAND;
209 }
210 memcpy(&target_locality, out.ptr, out.len);
211
212 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_RETURN_CERTIFICATE,
213 &return_certificate);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000214 CHECK_CBOR_ERROR(decode_ctx);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000215
216 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_EXPORT,
217 &allow_new_context_to_export);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000218 CHECK_CBOR_ERROR(decode_ctx);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000219
220 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_EXPORT_CDI,
221 &export_cdi);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000222 CHECK_CBOR_ERROR(decode_ctx);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000223
Jamie Foxab30e712023-03-30 17:48:36 +0100224 QCBORDecode_ExitMap(decode_ctx);
225
226 /* Exit top level array */
227 QCBORDecode_ExitArray(decode_ctx);
228
229 /* Finish and check for errors before using decoded values */
230 qcbor_err = QCBORDecode_Finish(decode_ctx);
231 if (qcbor_err != QCBOR_SUCCESS) {
232 return DPE_INVALID_COMMAND;
233 }
234
Maulik Patelcb14cde2024-01-23 12:39:53 +0000235 dpe_err = derive_context_request(context_handle, cert_id, retain_parent_context,
Maulik Patela81605b2023-10-24 12:17:03 +0100236 allow_new_context_to_derive, create_certificate,
237 &dice_inputs, client_id,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000238 target_locality,
239 return_certificate,
240 allow_new_context_to_export,
241 export_cdi,
Maulik Patela81605b2023-10-24 12:17:03 +0100242 &new_context_handle,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000243 &new_parent_context_handle,
244 new_certificate_buf,
Tamas Band0983e92024-01-25 16:32:51 +0100245 DICE_CERT_SIZE,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000246 &new_certificate_actual_size,
247 exported_cdi_buf,
248 sizeof(exported_cdi_buf),
249 &exported_cdi_actual_size);
Jamie Foxab30e712023-03-30 17:48:36 +0100250 if (dpe_err != DPE_NO_ERROR) {
251 return dpe_err;
252 }
253
254 /* Encode response */
255 QCBOREncode_OpenArray(encode_ctx);
256 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
257
258 QCBOREncode_OpenMap(encode_ctx);
Maulik Patela81605b2023-10-24 12:17:03 +0100259 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_DERIVE_CONTEXT_NEW_CONTEXT_HANDLE,
260 (UsefulBufC){ &new_context_handle,
261 sizeof(new_context_handle) });
Jamie Foxab30e712023-03-30 17:48:36 +0100262 QCBOREncode_AddBytesToMapN(encode_ctx,
Maulik Patela81605b2023-10-24 12:17:03 +0100263 DPE_DERIVE_CONTEXT_PARENT_CONTEXT_HANDLE,
Jamie Foxab30e712023-03-30 17:48:36 +0100264 (UsefulBufC){ &new_parent_context_handle,
265 sizeof(new_parent_context_handle) });
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000266
267 /* The certificate is already encoded into a CBOR array by the function
268 * add_encoded_layer_certificate. Add it as a byte string so that its
269 * decoding can be skipped and the CBOR returned to the caller.
270 */
271 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_DERIVE_CONTEXT_NEW_CERTIFICATE,
272 (UsefulBufC){ new_certificate_buf,
273 new_certificate_actual_size });
274
275 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_DERIVE_CONTEXT_EXPORTED_CDI,
276 (UsefulBufC){ exported_cdi_buf,
277 exported_cdi_actual_size });
278
Jamie Foxab30e712023-03-30 17:48:36 +0100279 QCBOREncode_CloseMap(encode_ctx);
280
281 QCBOREncode_CloseArray(encode_ctx);
282
283 return DPE_NO_ERROR;
284}
285
Maulik Patel54d65f72023-06-28 13:04:36 +0100286static dpe_error_t decode_destroy_context(QCBORDecodeContext *decode_ctx,
287 QCBOREncodeContext *encode_ctx)
288{
289 dpe_error_t dpe_err;
290 QCBORError qcbor_err;
291 UsefulBufC out;
292 int context_handle;
293 bool destroy_recursively;
294
295 /* Decode Destroy context command */
296 QCBORDecode_EnterMap(decode_ctx, NULL);
297
298 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DESTROY_CONTEXT_HANDLE,
299 &out);
300 if (out.len != sizeof(context_handle)) {
301 return DPE_INVALID_COMMAND;
302 }
303 memcpy(&context_handle, out.ptr, out.len);
304
305 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DESTROY_CONTEXT_RECURSIVELY,
306 &destroy_recursively);
307
308 QCBORDecode_ExitMap(decode_ctx);
309
310 /* Exit top level array */
311 QCBORDecode_ExitArray(decode_ctx);
312
313 /* Finish and check for errors before using decoded values */
314 qcbor_err = QCBORDecode_Finish(decode_ctx);
315 if (qcbor_err != QCBOR_SUCCESS) {
316 return DPE_INVALID_COMMAND;
317 }
318
319 dpe_err = destroy_context_request(context_handle, destroy_recursively);
320 if (dpe_err != DPE_NO_ERROR) {
321 return dpe_err;
322 }
323
324 /* Encode response */
325 QCBOREncode_OpenArray(encode_ctx);
326 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
327 QCBOREncode_CloseArray(encode_ctx);
328
329 return DPE_NO_ERROR;
330}
331
Jamie Foxab30e712023-03-30 17:48:36 +0100332static dpe_error_t decode_certify_key(QCBORDecodeContext *decode_ctx,
333 QCBOREncodeContext *encode_ctx)
334{
335 QCBORError qcbor_err;
336 UsefulBufC out;
337 dpe_error_t dpe_err;
338 int context_handle;
339 bool retain_context;
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000340 const uint8_t *public_key = NULL;
Jamie Foxab30e712023-03-30 17:48:36 +0100341 size_t public_key_size;
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000342 const uint8_t *label = NULL;
Jamie Foxab30e712023-03-30 17:48:36 +0100343 size_t label_size;
Tamas Band0983e92024-01-25 16:32:51 +0100344 uint8_t *certificate_buf = REUSE_CMD_BUF(DICE_CERT_SIZE);
Maulik Patelcbded682023-12-07 11:50:16 +0000345 size_t certificate_actual_size;
Maulik Patele6adc112023-08-18 14:21:51 +0100346 uint8_t derived_public_key_buf[DPE_ATTEST_PUB_KEY_SIZE];
Jamie Foxab30e712023-03-30 17:48:36 +0100347 size_t derived_public_key_actual_size;
348 int new_context_handle;
349
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000350 /* Initialise optional parameters with their default value in case
351 * they are not encoded in the input command
352 */
353 retain_context = false;
354 public_key_size = 0;
355 label_size = 0;
356
Jamie Foxab30e712023-03-30 17:48:36 +0100357 /* Decode CertifyKey command */
358 QCBORDecode_EnterMap(decode_ctx, NULL);
359
360 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_CONTEXT_HANDLE,
361 &out);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000362 qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
363 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
Jamie Foxab30e712023-03-30 17:48:36 +0100364 return DPE_INVALID_COMMAND;
365 }
366 memcpy(&context_handle, out.ptr, out.len);
367
368 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_CERTIFY_KEY_RETAIN_CONTEXT,
369 &retain_context);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000370 CHECK_CBOR_ERROR(decode_ctx);
Jamie Foxab30e712023-03-30 17:48:36 +0100371
372 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_PUBLIC_KEY,
373 &out);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000374 qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
375 if (qcbor_err == QCBOR_SUCCESS) {
376 public_key = out.ptr;
377 public_key_size = out.len;
378 } else if (qcbor_err == QCBOR_ERR_LABEL_NOT_FOUND) {
379 /* Do nothing - argument already initialised to default value */
380 } else {
381 return DPE_INVALID_COMMAND;
382 }
Jamie Foxab30e712023-03-30 17:48:36 +0100383
384 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_LABEL, &out);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000385 qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
386 if (qcbor_err == QCBOR_SUCCESS) {
387 label = out.ptr;
388 label_size = out.len;
389 } else if (qcbor_err == QCBOR_ERR_LABEL_NOT_FOUND) {
390 /* Do nothing - argument already initialised to default value */
391 } else {
392 return DPE_INVALID_COMMAND;
393 }
Jamie Foxab30e712023-03-30 17:48:36 +0100394
395 QCBORDecode_ExitMap(decode_ctx);
396
397 /* Exit top level array */
398 QCBORDecode_ExitArray(decode_ctx);
399
400 /* Finish and check for errors before using decoded values */
401 qcbor_err = QCBORDecode_Finish(decode_ctx);
402 if (qcbor_err != QCBOR_SUCCESS) {
403 return DPE_INVALID_COMMAND;
404 }
405
Maulik Patele6adc112023-08-18 14:21:51 +0100406 dpe_err = certify_key_request(context_handle, retain_context, public_key,
407 public_key_size, label, label_size,
Maulik Patelcbded682023-12-07 11:50:16 +0000408 certificate_buf,
Tamas Band0983e92024-01-25 16:32:51 +0100409 DICE_CERT_SIZE,
Maulik Patelcbded682023-12-07 11:50:16 +0000410 &certificate_actual_size,
Maulik Patele6adc112023-08-18 14:21:51 +0100411 derived_public_key_buf,
412 sizeof(derived_public_key_buf),
413 &derived_public_key_actual_size,
414 &new_context_handle);
Jamie Foxab30e712023-03-30 17:48:36 +0100415 if (dpe_err != DPE_NO_ERROR) {
416 return dpe_err;
417 }
418
419 /* Encode response */
420 QCBOREncode_OpenArray(encode_ctx);
421 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
422
423 QCBOREncode_OpenMap(encode_ctx);
424
425 /* The certificate chain is already encoded into a CBOR array by the certify
426 * key implementation. Add it as a byte string so that its decoding can be
427 * skipped and the CBOR returned to the caller.
428 */
Maulik Patelcbded682023-12-07 11:50:16 +0000429 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_CERTIFY_KEY_CERTIFICATE,
430 (UsefulBufC){ certificate_buf,
431 certificate_actual_size });
Jamie Foxab30e712023-03-30 17:48:36 +0100432
433 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_CERTIFY_KEY_DERIVED_PUBLIC_KEY,
434 (UsefulBufC){ derived_public_key_buf,
435 derived_public_key_actual_size });
436 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_CERTIFY_KEY_NEW_CONTEXT_HANDLE,
437 (UsefulBufC){ &new_context_handle,
438 sizeof(new_context_handle) });
439
440 QCBOREncode_CloseMap(encode_ctx);
441
442 QCBOREncode_CloseArray(encode_ctx);
443
444 return DPE_NO_ERROR;
445}
446
Maulik Patel83a6b592023-12-05 15:20:30 +0000447static dpe_error_t decode_get_certificate_chain(QCBORDecodeContext *decode_ctx,
448 QCBOREncodeContext *encode_ctx)
449{
450 QCBORError qcbor_err;
451 UsefulBufC out;
452 dpe_error_t dpe_err;
453 int context_handle;
454 bool retain_context;
455 bool clear_from_context;
Tamas Band0983e92024-01-25 16:32:51 +0100456 uint8_t *certificate_chain_buf = REUSE_CMD_BUF(DICE_CERT_CHAIN_SIZE);
Maulik Patel83a6b592023-12-05 15:20:30 +0000457 size_t certificate_chain_actual_size;
458 int new_context_handle;
459
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000460 /* Initialise optional parameters with their default value in case
461 * they are not encoded in the input command
462 */
463 retain_context = false;
464 clear_from_context = false;
465
Maulik Patel83a6b592023-12-05 15:20:30 +0000466 /* Decode GetCertificateChain command */
467 QCBORDecode_EnterMap(decode_ctx, NULL);
468
469 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_CONTEXT_HANDLE,
470 &out);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000471 qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
472 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
Maulik Patel83a6b592023-12-05 15:20:30 +0000473 return DPE_INVALID_COMMAND;
474 }
475 memcpy(&context_handle, out.ptr, out.len);
476
477 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_RETAIN_CONTEXT,
478 &retain_context);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000479 CHECK_CBOR_ERROR(decode_ctx);
Maulik Patel83a6b592023-12-05 15:20:30 +0000480
481 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_CLEAR_FROM_CONTEXT,
482 &clear_from_context);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000483 CHECK_CBOR_ERROR(decode_ctx);
Maulik Patel83a6b592023-12-05 15:20:30 +0000484
485 QCBORDecode_ExitMap(decode_ctx);
486
487 /* Exit top level array */
488 QCBORDecode_ExitArray(decode_ctx);
489
490 /* Finish and check for errors before using decoded values */
491 qcbor_err = QCBORDecode_Finish(decode_ctx);
492 if (qcbor_err != QCBOR_SUCCESS) {
493 return DPE_INVALID_COMMAND;
494 }
495
496 dpe_err = get_certificate_chain_request(context_handle,
497 retain_context,
498 clear_from_context,
499 certificate_chain_buf,
Tamas Band0983e92024-01-25 16:32:51 +0100500 DICE_CERT_CHAIN_SIZE,
Maulik Patel83a6b592023-12-05 15:20:30 +0000501 &certificate_chain_actual_size,
502 &new_context_handle);
503 if (dpe_err != DPE_NO_ERROR) {
504 return dpe_err;
505 }
506
507 /* Encode response */
508 QCBOREncode_OpenArray(encode_ctx);
509 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
510
511 QCBOREncode_OpenMap(encode_ctx);
512
513 /* The certificate chain is already encoded into a CBOR array by the get certificate
514 * chain implementation. Add it as a byte string so that its decoding can be
515 * skipped and the CBOR returned to the caller.
516 */
517 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_GET_CERTIFICATE_CHAIN_CERTIFICATE_CHAIN,
518 (UsefulBufC){ certificate_chain_buf,
519 certificate_chain_actual_size });
520
521 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_GET_CERTIFICATE_CHAIN_NEW_CONTEXT_HANDLE,
522 (UsefulBufC){ &new_context_handle,
523 sizeof(new_context_handle) });
524
525 QCBOREncode_CloseMap(encode_ctx);
526
527 QCBOREncode_CloseArray(encode_ctx);
528
529 return DPE_NO_ERROR;
530}
531
Jamie Foxab30e712023-03-30 17:48:36 +0100532static void encode_error_only(QCBOREncodeContext *encode_ctx,
533 dpe_error_t dpe_err)
534{
535 QCBOREncode_OpenArray(encode_ctx);
536 QCBOREncode_AddInt64(encode_ctx, dpe_err);
537 QCBOREncode_CloseArray(encode_ctx);
538}
539
540int32_t dpe_command_decode(int32_t client_id,
541 const char *cmd_input, size_t cmd_input_size,
542 char *cmd_output, size_t *cmd_output_size)
543{
544 dpe_error_t dpe_err;
545 QCBORError qcbor_err;
546 QCBORDecodeContext decode_ctx;
547 QCBOREncodeContext encode_ctx;
548 UsefulBufC out;
549 uint64_t command_id;
550
551 QCBORDecode_Init(&decode_ctx, (UsefulBufC){ cmd_input, cmd_input_size },
552 QCBOR_DECODE_MODE_NORMAL);
553 QCBOREncode_Init(&encode_ctx, (UsefulBuf){ cmd_output, *cmd_output_size });
554
555 /* Enter top level array */
556 QCBORDecode_EnterArray(&decode_ctx, NULL);
557
558 /* Get the command ID */
559 QCBORDecode_GetUInt64(&decode_ctx, &command_id);
560
561 /* Check for errors before interpreting the decoded command ID */
562 qcbor_err = QCBORDecode_GetError(&decode_ctx);
563
564 if (qcbor_err == QCBOR_SUCCESS) {
565 switch (command_id) {
Maulik Patela81605b2023-10-24 12:17:03 +0100566 case DPE_DERIVE_CONTEXT:
567 dpe_err = decode_derive_context(&decode_ctx, &encode_ctx, client_id);
Jamie Foxab30e712023-03-30 17:48:36 +0100568 break;
569 case DPE_CERTIFY_KEY:
570 dpe_err = decode_certify_key(&decode_ctx, &encode_ctx);
571 break;
Maulik Patel83a6b592023-12-05 15:20:30 +0000572 case DPE_GET_CERTIFICATE_CHAIN:
573 dpe_err = decode_get_certificate_chain(&decode_ctx, &encode_ctx);
574 break;
Maulik Patel54d65f72023-06-28 13:04:36 +0100575 case DPE_DESTROY_CONTEXT:
576 dpe_err = decode_destroy_context(&decode_ctx, &encode_ctx);
577 break;
Jamie Foxab30e712023-03-30 17:48:36 +0100578 default:
579 dpe_err = DPE_INVALID_COMMAND;
580 break;
581 }
582 } else {
583 dpe_err = DPE_INVALID_COMMAND;
584 }
585
586 /* If an unhandled DPE error was returned, then encode it into a response */
587 if (dpe_err != DPE_NO_ERROR) {
588 encode_error_only(&encode_ctx, dpe_err);
589 }
590
591 qcbor_err = QCBOREncode_Finish(&encode_ctx, &out);
592 if (qcbor_err != QCBOR_SUCCESS) {
593 return -1;
594 }
595
596 *cmd_output_size = out.len;
597
598 return 0;
599}