blob: c4f2623dbd45f1d248109a431d9cff3f3484427b [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
Tamas Band0983e92024-01-25 16:32:51 +010019/*
20 * The goal to reuse the cmd_buf allocated in dpe_req_mngr.c to create the
21 * big objects (certificate, certificate_chain) in place rather then allocate
22 * a separate buffer on the stack and later copy them to cmd_buf.
23 *
24 * The temporary buffer is allocated from the end of the cmd_buf. When the
25 * reply is encoded then the content of the temp buf is moved to its final
26 * place in the cmd_buf.
27 *
28 * Overlapping copy is not an issue because QCBOR relies on memmove under the
29 * hood which handles this scenario.
30 *
31 * Note:
32 * Make sure that the beginning of the encoded reply does not overwrite the
33 * data in the temp buf. That is why the temp buff is allocated at the end of
34 * cmd_buf.
35 */
36#define REUSE_CMD_BUF(size) (uint8_t *)encode_ctx->OutBuf.UB.ptr + \
37 encode_ctx->OutBuf.UB.len - \
38 (size)
39
Jamie Foxab30e712023-03-30 17:48:36 +010040static dpe_error_t decode_dice_inputs(QCBORDecodeContext *decode_ctx,
41 DiceInputValues *input)
42{
43 QCBORError qcbor_err;
44 UsefulBufC out = { NULL, 0 };
45 int64_t out_int;
46
47 /* The DICE inputs are encoded as a map wrapped into a byte string */
48 QCBORDecode_EnterBstrWrappedFromMapN(decode_ctx,
Maulik Patela81605b2023-10-24 12:17:03 +010049 DPE_DERIVE_CONTEXT_INPUT_DATA,
Jamie Foxab30e712023-03-30 17:48:36 +010050 QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL);
51 QCBORDecode_EnterMap(decode_ctx, NULL);
52
53 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CODE_HASH, &out);
54 if (out.len != sizeof(input->code_hash)) {
55 return DPE_INVALID_COMMAND;
56 }
57 memcpy(input->code_hash, out.ptr, out.len);
58
59 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CODE_DESCRIPTOR, &out);
60 input->code_descriptor = out.ptr;
61 input->code_descriptor_size = out.len;
62
63 QCBORDecode_GetInt64InMapN(decode_ctx, DICE_CONFIG_TYPE, &out_int);
64
65 /* Check error state before interpreting config type */
66 qcbor_err = QCBORDecode_GetError(decode_ctx);
67 if (qcbor_err != QCBOR_SUCCESS) {
68 return DPE_INVALID_COMMAND;
69 }
70
71 if (out_int < kDiceConfigTypeInline ||
72 out_int > kDiceConfigTypeDescriptor) {
73 return DPE_INVALID_COMMAND;
74 }
75 input->config_type = (DiceConfigType)out_int;
76
77 /* Only one of config value or config descriptor needs to be provided */
78 if (input->config_type == kDiceConfigTypeInline) {
79 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CONFIG_VALUE, &out);
80 if (out.len != sizeof(input->config_value)) {
81 return DPE_INVALID_COMMAND;
82 }
83 memcpy(input->config_value, out.ptr, out.len);
84
85 /* Config descriptor is not provided */
86 input->config_descriptor = NULL;
87 input->config_descriptor_size = 0;
88 } else {
89 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CONFIG_DESCRIPTOR,
90 &out);
91 input->config_descriptor = out.ptr;
92 input->config_descriptor_size = out.len;
93
94 /* Config value is not provided */
95 memset(input->config_value, 0, sizeof(input->config_value));
96 }
97
98 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_AUTHORITY_HASH, &out);
99 if (out.len != sizeof(input->authority_hash)) {
100 return DPE_INVALID_COMMAND;
101 }
102 memcpy(input->authority_hash, out.ptr, out.len);
103
104 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_AUTHORITY_DESCRIPTOR,
105 &out);
106 input->authority_descriptor = out.ptr;
107 input->authority_descriptor_size = out.len;
108
109 QCBORDecode_GetInt64InMapN(decode_ctx, DICE_MODE, &out_int);
110 if (out_int < kDiceModeNotInitialized || out_int > kDiceModeMaintenance) {
111 return DPE_INVALID_COMMAND;
112 }
113 input->mode = (DiceMode)out_int;
114
115 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_HIDDEN, &out);
116 if (out.len != sizeof(input->hidden)) {
117 return DPE_INVALID_COMMAND;
118 }
119 memcpy(input->hidden, out.ptr, out.len);
120
121 QCBORDecode_ExitMap(decode_ctx);
122 QCBORDecode_ExitBstrWrapped(decode_ctx);
123
Maulik Pateld936d742024-01-08 14:16:46 +0000124 qcbor_err = QCBORDecode_GetError(decode_ctx);
125 if (qcbor_err != QCBOR_SUCCESS) {
126 return DPE_INVALID_COMMAND;
127 }
128
Jamie Foxab30e712023-03-30 17:48:36 +0100129 return DPE_NO_ERROR;
130}
131
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000132//TODO: Handle the omission of parameters from DPE commands.
Maulik Patela81605b2023-10-24 12:17:03 +0100133static dpe_error_t decode_derive_context(QCBORDecodeContext *decode_ctx,
134 QCBOREncodeContext *encode_ctx,
135 int32_t client_id)
Jamie Foxab30e712023-03-30 17:48:36 +0100136{
137 dpe_error_t dpe_err;
138 QCBORError qcbor_err;
139 UsefulBufC out;
140 int context_handle;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000141 int32_t target_locality;
Jamie Foxab30e712023-03-30 17:48:36 +0100142 bool retain_parent_context;
Maulik Patela81605b2023-10-24 12:17:03 +0100143 bool allow_new_context_to_derive;
Jamie Foxab30e712023-03-30 17:48:36 +0100144 bool create_certificate;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000145 bool return_certificate;
146 bool allow_new_context_to_export;
147 bool export_cdi;
Jamie Foxab30e712023-03-30 17:48:36 +0100148 DiceInputValues dice_inputs;
Maulik Patela81605b2023-10-24 12:17:03 +0100149 int new_context_handle;
Jamie Foxab30e712023-03-30 17:48:36 +0100150 int new_parent_context_handle;
Tamas Band0983e92024-01-25 16:32:51 +0100151 uint8_t *new_certificate_buf = REUSE_CMD_BUF(DICE_CERT_SIZE);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000152 uint8_t exported_cdi_buf[DICE_MAX_ENCODED_CDI_SIZE];
Maulik Patelcb14cde2024-01-23 12:39:53 +0000153 uint32_t cert_id;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000154 size_t new_certificate_actual_size = 0;
155 size_t exported_cdi_actual_size = 0;
Jamie Foxab30e712023-03-30 17:48:36 +0100156
Maulik Patela81605b2023-10-24 12:17:03 +0100157 /* Decode DeriveContext command */
Jamie Foxab30e712023-03-30 17:48:36 +0100158 QCBORDecode_EnterMap(decode_ctx, NULL);
159
Maulik Patela81605b2023-10-24 12:17:03 +0100160 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DERIVE_CONTEXT_CONTEXT_HANDLE,
Jamie Foxab30e712023-03-30 17:48:36 +0100161 &out);
Maulik Patelcb14cde2024-01-23 12:39:53 +0000162 qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
163 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
Jamie Foxab30e712023-03-30 17:48:36 +0100164 return DPE_INVALID_COMMAND;
165 }
166 memcpy(&context_handle, out.ptr, out.len);
167
Maulik Patelcb14cde2024-01-23 12:39:53 +0000168 QCBORDecode_GetUInt64InMapN(decode_ctx, DPE_DERIVE_CONTEXT_CERT_ID, &cert_id);
169 /* Check if cert_id was encoded in the received command buffer */
170 qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
171 if (qcbor_err != QCBOR_SUCCESS) {
172 cert_id = DPE_CERT_ID_INVALID;
173 }
174
Maulik Patela81605b2023-10-24 12:17:03 +0100175 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_RETAIN_PARENT_CONTEXT,
Jamie Foxab30e712023-03-30 17:48:36 +0100176 &retain_parent_context);
177
Maulik Patela81605b2023-10-24 12:17:03 +0100178 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_DERIVE,
179 &allow_new_context_to_derive);
Jamie Foxab30e712023-03-30 17:48:36 +0100180
Maulik Patela81605b2023-10-24 12:17:03 +0100181 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_CREATE_CERTIFICATE,
Jamie Foxab30e712023-03-30 17:48:36 +0100182 &create_certificate);
183
184 dpe_err = decode_dice_inputs(decode_ctx, &dice_inputs);
185 if (dpe_err != DPE_NO_ERROR) {
186 return dpe_err;
187 }
188
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000189 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DERIVE_CONTEXT_TARGET_LOCALITY,
190 &out);
191 if (out.len != sizeof(target_locality)) {
192 return DPE_INVALID_COMMAND;
193 }
194 memcpy(&target_locality, out.ptr, out.len);
195
196 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_RETURN_CERTIFICATE,
197 &return_certificate);
198
199 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_EXPORT,
200 &allow_new_context_to_export);
201
202 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_EXPORT_CDI,
203 &export_cdi);
204
Jamie Foxab30e712023-03-30 17:48:36 +0100205 QCBORDecode_ExitMap(decode_ctx);
206
207 /* Exit top level array */
208 QCBORDecode_ExitArray(decode_ctx);
209
210 /* Finish and check for errors before using decoded values */
211 qcbor_err = QCBORDecode_Finish(decode_ctx);
212 if (qcbor_err != QCBOR_SUCCESS) {
213 return DPE_INVALID_COMMAND;
214 }
215
Maulik Patelcb14cde2024-01-23 12:39:53 +0000216 dpe_err = derive_context_request(context_handle, cert_id, retain_parent_context,
Maulik Patela81605b2023-10-24 12:17:03 +0100217 allow_new_context_to_derive, create_certificate,
218 &dice_inputs, client_id,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000219 target_locality,
220 return_certificate,
221 allow_new_context_to_export,
222 export_cdi,
Maulik Patela81605b2023-10-24 12:17:03 +0100223 &new_context_handle,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000224 &new_parent_context_handle,
225 new_certificate_buf,
Tamas Band0983e92024-01-25 16:32:51 +0100226 DICE_CERT_SIZE,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000227 &new_certificate_actual_size,
228 exported_cdi_buf,
229 sizeof(exported_cdi_buf),
230 &exported_cdi_actual_size);
Jamie Foxab30e712023-03-30 17:48:36 +0100231 if (dpe_err != DPE_NO_ERROR) {
232 return dpe_err;
233 }
234
235 /* Encode response */
236 QCBOREncode_OpenArray(encode_ctx);
237 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
238
239 QCBOREncode_OpenMap(encode_ctx);
Maulik Patela81605b2023-10-24 12:17:03 +0100240 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_DERIVE_CONTEXT_NEW_CONTEXT_HANDLE,
241 (UsefulBufC){ &new_context_handle,
242 sizeof(new_context_handle) });
Jamie Foxab30e712023-03-30 17:48:36 +0100243 QCBOREncode_AddBytesToMapN(encode_ctx,
Maulik Patela81605b2023-10-24 12:17:03 +0100244 DPE_DERIVE_CONTEXT_PARENT_CONTEXT_HANDLE,
Jamie Foxab30e712023-03-30 17:48:36 +0100245 (UsefulBufC){ &new_parent_context_handle,
246 sizeof(new_parent_context_handle) });
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000247
248 /* The certificate is already encoded into a CBOR array by the function
249 * add_encoded_layer_certificate. Add it as a byte string so that its
250 * decoding can be skipped and the CBOR returned to the caller.
251 */
252 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_DERIVE_CONTEXT_NEW_CERTIFICATE,
253 (UsefulBufC){ new_certificate_buf,
254 new_certificate_actual_size });
255
256 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_DERIVE_CONTEXT_EXPORTED_CDI,
257 (UsefulBufC){ exported_cdi_buf,
258 exported_cdi_actual_size });
259
Jamie Foxab30e712023-03-30 17:48:36 +0100260 QCBOREncode_CloseMap(encode_ctx);
261
262 QCBOREncode_CloseArray(encode_ctx);
263
264 return DPE_NO_ERROR;
265}
266
Maulik Patel54d65f72023-06-28 13:04:36 +0100267static dpe_error_t decode_destroy_context(QCBORDecodeContext *decode_ctx,
268 QCBOREncodeContext *encode_ctx)
269{
270 dpe_error_t dpe_err;
271 QCBORError qcbor_err;
272 UsefulBufC out;
273 int context_handle;
274 bool destroy_recursively;
275
276 /* Decode Destroy context command */
277 QCBORDecode_EnterMap(decode_ctx, NULL);
278
279 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DESTROY_CONTEXT_HANDLE,
280 &out);
281 if (out.len != sizeof(context_handle)) {
282 return DPE_INVALID_COMMAND;
283 }
284 memcpy(&context_handle, out.ptr, out.len);
285
286 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DESTROY_CONTEXT_RECURSIVELY,
287 &destroy_recursively);
288
289 QCBORDecode_ExitMap(decode_ctx);
290
291 /* Exit top level array */
292 QCBORDecode_ExitArray(decode_ctx);
293
294 /* Finish and check for errors before using decoded values */
295 qcbor_err = QCBORDecode_Finish(decode_ctx);
296 if (qcbor_err != QCBOR_SUCCESS) {
297 return DPE_INVALID_COMMAND;
298 }
299
300 dpe_err = destroy_context_request(context_handle, destroy_recursively);
301 if (dpe_err != DPE_NO_ERROR) {
302 return dpe_err;
303 }
304
305 /* Encode response */
306 QCBOREncode_OpenArray(encode_ctx);
307 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
308 QCBOREncode_CloseArray(encode_ctx);
309
310 return DPE_NO_ERROR;
311}
312
Jamie Foxab30e712023-03-30 17:48:36 +0100313static dpe_error_t decode_certify_key(QCBORDecodeContext *decode_ctx,
314 QCBOREncodeContext *encode_ctx)
315{
316 QCBORError qcbor_err;
317 UsefulBufC out;
318 dpe_error_t dpe_err;
319 int context_handle;
320 bool retain_context;
321 const uint8_t *public_key;
322 size_t public_key_size;
323 const uint8_t *label;
324 size_t label_size;
Tamas Band0983e92024-01-25 16:32:51 +0100325 uint8_t *certificate_buf = REUSE_CMD_BUF(DICE_CERT_SIZE);
Maulik Patelcbded682023-12-07 11:50:16 +0000326 size_t certificate_actual_size;
Maulik Patele6adc112023-08-18 14:21:51 +0100327 uint8_t derived_public_key_buf[DPE_ATTEST_PUB_KEY_SIZE];
Jamie Foxab30e712023-03-30 17:48:36 +0100328 size_t derived_public_key_actual_size;
329 int new_context_handle;
330
331 /* Decode CertifyKey command */
332 QCBORDecode_EnterMap(decode_ctx, NULL);
333
334 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_CONTEXT_HANDLE,
335 &out);
336 if (out.len != sizeof(context_handle)) {
337 return DPE_INVALID_COMMAND;
338 }
339 memcpy(&context_handle, out.ptr, out.len);
340
341 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_CERTIFY_KEY_RETAIN_CONTEXT,
342 &retain_context);
343
344 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_PUBLIC_KEY,
345 &out);
346 public_key = out.ptr;
347 public_key_size = out.len;
348
349 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_LABEL, &out);
350 label = out.ptr;
351 label_size = out.len;
352
353 QCBORDecode_ExitMap(decode_ctx);
354
355 /* Exit top level array */
356 QCBORDecode_ExitArray(decode_ctx);
357
358 /* Finish and check for errors before using decoded values */
359 qcbor_err = QCBORDecode_Finish(decode_ctx);
360 if (qcbor_err != QCBOR_SUCCESS) {
361 return DPE_INVALID_COMMAND;
362 }
363
Maulik Patele6adc112023-08-18 14:21:51 +0100364 dpe_err = certify_key_request(context_handle, retain_context, public_key,
365 public_key_size, label, label_size,
Maulik Patelcbded682023-12-07 11:50:16 +0000366 certificate_buf,
Tamas Band0983e92024-01-25 16:32:51 +0100367 DICE_CERT_SIZE,
Maulik Patelcbded682023-12-07 11:50:16 +0000368 &certificate_actual_size,
Maulik Patele6adc112023-08-18 14:21:51 +0100369 derived_public_key_buf,
370 sizeof(derived_public_key_buf),
371 &derived_public_key_actual_size,
372 &new_context_handle);
Jamie Foxab30e712023-03-30 17:48:36 +0100373 if (dpe_err != DPE_NO_ERROR) {
374 return dpe_err;
375 }
376
377 /* Encode response */
378 QCBOREncode_OpenArray(encode_ctx);
379 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
380
381 QCBOREncode_OpenMap(encode_ctx);
382
383 /* The certificate chain is already encoded into a CBOR array by the certify
384 * key implementation. Add it as a byte string so that its decoding can be
385 * skipped and the CBOR returned to the caller.
386 */
Maulik Patelcbded682023-12-07 11:50:16 +0000387 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_CERTIFY_KEY_CERTIFICATE,
388 (UsefulBufC){ certificate_buf,
389 certificate_actual_size });
Jamie Foxab30e712023-03-30 17:48:36 +0100390
391 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_CERTIFY_KEY_DERIVED_PUBLIC_KEY,
392 (UsefulBufC){ derived_public_key_buf,
393 derived_public_key_actual_size });
394 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_CERTIFY_KEY_NEW_CONTEXT_HANDLE,
395 (UsefulBufC){ &new_context_handle,
396 sizeof(new_context_handle) });
397
398 QCBOREncode_CloseMap(encode_ctx);
399
400 QCBOREncode_CloseArray(encode_ctx);
401
402 return DPE_NO_ERROR;
403}
404
Maulik Patel83a6b592023-12-05 15:20:30 +0000405static dpe_error_t decode_get_certificate_chain(QCBORDecodeContext *decode_ctx,
406 QCBOREncodeContext *encode_ctx)
407{
408 QCBORError qcbor_err;
409 UsefulBufC out;
410 dpe_error_t dpe_err;
411 int context_handle;
412 bool retain_context;
413 bool clear_from_context;
Tamas Band0983e92024-01-25 16:32:51 +0100414 uint8_t *certificate_chain_buf = REUSE_CMD_BUF(DICE_CERT_CHAIN_SIZE);
Maulik Patel83a6b592023-12-05 15:20:30 +0000415 size_t certificate_chain_actual_size;
416 int new_context_handle;
417
418 /* Decode GetCertificateChain command */
419 QCBORDecode_EnterMap(decode_ctx, NULL);
420
421 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_CONTEXT_HANDLE,
422 &out);
423 if (out.len != sizeof(context_handle)) {
424 return DPE_INVALID_COMMAND;
425 }
426 memcpy(&context_handle, out.ptr, out.len);
427
428 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_RETAIN_CONTEXT,
429 &retain_context);
430
431 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_CLEAR_FROM_CONTEXT,
432 &clear_from_context);
433
434 QCBORDecode_ExitMap(decode_ctx);
435
436 /* Exit top level array */
437 QCBORDecode_ExitArray(decode_ctx);
438
439 /* Finish and check for errors before using decoded values */
440 qcbor_err = QCBORDecode_Finish(decode_ctx);
441 if (qcbor_err != QCBOR_SUCCESS) {
442 return DPE_INVALID_COMMAND;
443 }
444
445 dpe_err = get_certificate_chain_request(context_handle,
446 retain_context,
447 clear_from_context,
448 certificate_chain_buf,
Tamas Band0983e92024-01-25 16:32:51 +0100449 DICE_CERT_CHAIN_SIZE,
Maulik Patel83a6b592023-12-05 15:20:30 +0000450 &certificate_chain_actual_size,
451 &new_context_handle);
452 if (dpe_err != DPE_NO_ERROR) {
453 return dpe_err;
454 }
455
456 /* Encode response */
457 QCBOREncode_OpenArray(encode_ctx);
458 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
459
460 QCBOREncode_OpenMap(encode_ctx);
461
462 /* The certificate chain is already encoded into a CBOR array by the get certificate
463 * chain implementation. Add it as a byte string so that its decoding can be
464 * skipped and the CBOR returned to the caller.
465 */
466 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_GET_CERTIFICATE_CHAIN_CERTIFICATE_CHAIN,
467 (UsefulBufC){ certificate_chain_buf,
468 certificate_chain_actual_size });
469
470 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_GET_CERTIFICATE_CHAIN_NEW_CONTEXT_HANDLE,
471 (UsefulBufC){ &new_context_handle,
472 sizeof(new_context_handle) });
473
474 QCBOREncode_CloseMap(encode_ctx);
475
476 QCBOREncode_CloseArray(encode_ctx);
477
478 return DPE_NO_ERROR;
479}
480
Jamie Foxab30e712023-03-30 17:48:36 +0100481static void encode_error_only(QCBOREncodeContext *encode_ctx,
482 dpe_error_t dpe_err)
483{
484 QCBOREncode_OpenArray(encode_ctx);
485 QCBOREncode_AddInt64(encode_ctx, dpe_err);
486 QCBOREncode_CloseArray(encode_ctx);
487}
488
489int32_t dpe_command_decode(int32_t client_id,
490 const char *cmd_input, size_t cmd_input_size,
491 char *cmd_output, size_t *cmd_output_size)
492{
493 dpe_error_t dpe_err;
494 QCBORError qcbor_err;
495 QCBORDecodeContext decode_ctx;
496 QCBOREncodeContext encode_ctx;
497 UsefulBufC out;
498 uint64_t command_id;
499
500 QCBORDecode_Init(&decode_ctx, (UsefulBufC){ cmd_input, cmd_input_size },
501 QCBOR_DECODE_MODE_NORMAL);
502 QCBOREncode_Init(&encode_ctx, (UsefulBuf){ cmd_output, *cmd_output_size });
503
504 /* Enter top level array */
505 QCBORDecode_EnterArray(&decode_ctx, NULL);
506
507 /* Get the command ID */
508 QCBORDecode_GetUInt64(&decode_ctx, &command_id);
509
510 /* Check for errors before interpreting the decoded command ID */
511 qcbor_err = QCBORDecode_GetError(&decode_ctx);
512
513 if (qcbor_err == QCBOR_SUCCESS) {
514 switch (command_id) {
Maulik Patela81605b2023-10-24 12:17:03 +0100515 case DPE_DERIVE_CONTEXT:
516 dpe_err = decode_derive_context(&decode_ctx, &encode_ctx, client_id);
Jamie Foxab30e712023-03-30 17:48:36 +0100517 break;
518 case DPE_CERTIFY_KEY:
519 dpe_err = decode_certify_key(&decode_ctx, &encode_ctx);
520 break;
Maulik Patel83a6b592023-12-05 15:20:30 +0000521 case DPE_GET_CERTIFICATE_CHAIN:
522 dpe_err = decode_get_certificate_chain(&decode_ctx, &encode_ctx);
523 break;
Maulik Patel54d65f72023-06-28 13:04:36 +0100524 case DPE_DESTROY_CONTEXT:
525 dpe_err = decode_destroy_context(&decode_ctx, &encode_ctx);
526 break;
Jamie Foxab30e712023-03-30 17:48:36 +0100527 default:
528 dpe_err = DPE_INVALID_COMMAND;
529 break;
530 }
531 } else {
532 dpe_err = DPE_INVALID_COMMAND;
533 }
534
535 /* If an unhandled DPE error was returned, then encode it into a response */
536 if (dpe_err != DPE_NO_ERROR) {
537 encode_error_only(&encode_ctx, dpe_err);
538 }
539
540 qcbor_err = QCBOREncode_Finish(&encode_ctx, &out);
541 if (qcbor_err != QCBOR_SUCCESS) {
542 return -1;
543 }
544
545 *cmd_output_size = out.len;
546
547 return 0;
548}