blob: 644fb7c1f100ae5ca80106a04333602c83b5ddd2 [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
Tamas Banfcc06e32024-03-25 13:47:33 +010010#include <assert.h>
Jamie Foxab30e712023-03-30 17:48:36 +010011#include <string.h>
12
13#include "dpe_client.h"
Maulik Patelad2f3db2023-05-17 15:41:36 +010014#include "dpe_context_mngr.h"
Maulik Patele6adc112023-08-18 14:21:51 +010015#include "dpe_crypto_config.h"
Jamie Foxab30e712023-03-30 17:48:36 +010016#include "qcbor/qcbor_encode.h"
17#include "qcbor/qcbor_decode.h"
18#include "qcbor/qcbor_spiffy_decode.h"
19
Tamas Banfcc06e32024-03-25 13:47:33 +010020/*
21 * The goal to reuse the cmd_buf allocated in dpe_req_mngr.c to create the
22 * big objects (certificate, certificate_chain) in place rather then allocate
23 * a separate buffer on the stack and later copy them to cmd_buf.
24 *
25 * The temporary buffer is allocated from the beginning + some offset of the
26 * cmd_buf. The offset is a placeholder for the first few bytes of the
27 * response. The size of temp buf is till the end of the cmd_buf. Usually not
28 * the entire size is necessary it is just convenient to allocate as much. When
29 * the response is encoded then the content of the temp buf is moved to its
30 * final location within the cmd_buf.
31 *
32 * Overlapping copy is not an issue because QCBOR relies on memmove under the
33 * hood which handles this scenario.
34 *
35 * Note:
36 * Only a single temp buffer can be allocated with this trick per DPE command.
37 */
38#define DPE_RESPONSE_HEADER_SIZE 20
39#define ALLOC_TEMP_BUF (uint8_t *)encode_ctx->OutBuf.UB.ptr + \
40 DPE_RESPONSE_HEADER_SIZE
41
42#define SIZEOF_TEMP_BUF encode_ctx->OutBuf.UB.len - \
43 DPE_RESPONSE_HEADER_SIZE
44
45/* Decreasing the placeholder size a bit because UsefulOutBuf_GetEndPosition()
46 * cannot determine the exact number of bytes to encode array and map objects
47 * until they are closed. Allocating 1 byte for both allows encoding up to
48 * 23 elements per type (map or array) in a single byte, so at the end it
49 * consumes 2 bytes. It is very unlikely to have more elements in a map or array
50 * than 23 in a DPE response.
51 */
52#define CHECK_OVERFLOW_TO_TEMP_BUF assert((DPE_RESPONSE_HEADER_SIZE - 2) > \
53 UsefulOutBuf_GetEndPosition(&encode_ctx->OutBuf))
54
Maulik Patel8a969fd2024-03-01 14:43:03 +000055#define COUNT_ARGS(arg) (arg)++
56
57#define CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx) \
58 qcbor_err = QCBORDecode_GetAndResetError(decode_ctx); \
59 if (qcbor_err == QCBOR_SUCCESS) { \
60 /* Valid label found - optional argument present */ \
61 COUNT_ARGS(num_of_valid_arguments); \
62 } else if (qcbor_err != QCBOR_ERR_LABEL_NOT_FOUND) { \
Maulik Patel6f892252024-03-05 16:39:38 +000063 return DPE_INVALID_ARGUMENT; \
Maulik Patel8a969fd2024-03-01 14:43:03 +000064 } else { \
65 /* We have NOT found the optional argument, do not update the count */ \
Maulik Patelfbe9bff2024-02-09 14:05:25 +000066 }
67
Jamie Foxab30e712023-03-30 17:48:36 +010068static dpe_error_t decode_dice_inputs(QCBORDecodeContext *decode_ctx,
69 DiceInputValues *input)
70{
71 QCBORError qcbor_err;
72 UsefulBufC out = { NULL, 0 };
73 int64_t out_int;
Maulik Patelf4230182024-04-15 13:56:02 +010074 uint16_t num_of_input_arguments, num_of_valid_arguments = 0;
75 QCBORItem item;
Jamie Foxab30e712023-03-30 17:48:36 +010076
77 /* The DICE inputs are encoded as a map wrapped into a byte string */
78 QCBORDecode_EnterBstrWrappedFromMapN(decode_ctx,
Maulik Patela81605b2023-10-24 12:17:03 +010079 DPE_DERIVE_CONTEXT_INPUT_DATA,
Jamie Foxab30e712023-03-30 17:48:36 +010080 QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL);
Maulik Patelf4230182024-04-15 13:56:02 +010081 QCBORDecode_EnterMap(decode_ctx, &item);
82 qcbor_err = QCBORDecode_GetError(decode_ctx);
83 if ((qcbor_err != QCBOR_SUCCESS) ||
84 (item.uDataType != QCBOR_TYPE_MAP)) {
85 /* We expect a map of Dice inputs here */
86 return DPE_INVALID_ARGUMENT;
87 }
88 /* Save the number of items found in the map */
89 num_of_input_arguments = item.val.uCount;
Jamie Foxab30e712023-03-30 17:48:36 +010090
91 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CODE_HASH, &out);
Maulik Patelf4230182024-04-15 13:56:02 +010092 qcbor_err = QCBORDecode_GetError(decode_ctx);
93 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(input->code_hash))) {
Maulik Patel6f892252024-03-05 16:39:38 +000094 return DPE_INVALID_ARGUMENT;
Jamie Foxab30e712023-03-30 17:48:36 +010095 }
96 memcpy(input->code_hash, out.ptr, out.len);
Maulik Patelf4230182024-04-15 13:56:02 +010097 COUNT_ARGS(num_of_valid_arguments);
Jamie Foxab30e712023-03-30 17:48:36 +010098
99 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CODE_DESCRIPTOR, &out);
Maulik Patelf4230182024-04-15 13:56:02 +0100100 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
101 if (qcbor_err == QCBOR_SUCCESS) {
102 /* Valid argument was found */
103 input->code_descriptor = out.ptr;
104 input->code_descriptor_size = out.len;
105 }
Jamie Foxab30e712023-03-30 17:48:36 +0100106
107 QCBORDecode_GetInt64InMapN(decode_ctx, DICE_CONFIG_TYPE, &out_int);
108
109 /* Check error state before interpreting config type */
110 qcbor_err = QCBORDecode_GetError(decode_ctx);
111 if (qcbor_err != QCBOR_SUCCESS) {
Maulik Patel6f892252024-03-05 16:39:38 +0000112 return DPE_INVALID_ARGUMENT;
Jamie Foxab30e712023-03-30 17:48:36 +0100113 }
114
115 if (out_int < kDiceConfigTypeInline ||
116 out_int > kDiceConfigTypeDescriptor) {
Maulik Patel6f892252024-03-05 16:39:38 +0000117 return DPE_INVALID_ARGUMENT;
Jamie Foxab30e712023-03-30 17:48:36 +0100118 }
Maulik Patelf4230182024-04-15 13:56:02 +0100119 COUNT_ARGS(num_of_valid_arguments);
Jamie Foxab30e712023-03-30 17:48:36 +0100120 input->config_type = (DiceConfigType)out_int;
121
122 /* Only one of config value or config descriptor needs to be provided */
123 if (input->config_type == kDiceConfigTypeInline) {
124 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CONFIG_VALUE, &out);
Maulik Patelf4230182024-04-15 13:56:02 +0100125 qcbor_err = QCBORDecode_GetError(decode_ctx);
126 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(input->config_value))) {
Maulik Patel6f892252024-03-05 16:39:38 +0000127 return DPE_INVALID_ARGUMENT;
Jamie Foxab30e712023-03-30 17:48:36 +0100128 }
Maulik Patelf4230182024-04-15 13:56:02 +0100129 COUNT_ARGS(num_of_valid_arguments);
Jamie Foxab30e712023-03-30 17:48:36 +0100130 memcpy(input->config_value, out.ptr, out.len);
131
132 /* Config descriptor is not provided */
133 input->config_descriptor = NULL;
134 input->config_descriptor_size = 0;
135 } else {
136 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CONFIG_DESCRIPTOR,
137 &out);
Maulik Patelf4230182024-04-15 13:56:02 +0100138 qcbor_err = QCBORDecode_GetError(decode_ctx);
139 if (qcbor_err != QCBOR_SUCCESS) {
140 return DPE_INVALID_ARGUMENT;
141 }
142 COUNT_ARGS(num_of_valid_arguments);
Jamie Foxab30e712023-03-30 17:48:36 +0100143 input->config_descriptor = out.ptr;
144 input->config_descriptor_size = out.len;
145
146 /* Config value is not provided */
147 memset(input->config_value, 0, sizeof(input->config_value));
148 }
149
150 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_AUTHORITY_HASH, &out);
Maulik Patelf4230182024-04-15 13:56:02 +0100151 qcbor_err = QCBORDecode_GetError(decode_ctx);
152 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(input->authority_hash))) {
Maulik Patel6f892252024-03-05 16:39:38 +0000153 return DPE_INVALID_ARGUMENT;
Jamie Foxab30e712023-03-30 17:48:36 +0100154 }
Maulik Patelf4230182024-04-15 13:56:02 +0100155 COUNT_ARGS(num_of_valid_arguments);
Jamie Foxab30e712023-03-30 17:48:36 +0100156 memcpy(input->authority_hash, out.ptr, out.len);
157
158 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_AUTHORITY_DESCRIPTOR,
159 &out);
Maulik Patelf4230182024-04-15 13:56:02 +0100160 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
161 if (qcbor_err == QCBOR_SUCCESS) {
162 /* Valid argument was found */
163 input->authority_descriptor = out.ptr;
164 input->authority_descriptor_size = out.len;
165 }
Jamie Foxab30e712023-03-30 17:48:36 +0100166
167 QCBORDecode_GetInt64InMapN(decode_ctx, DICE_MODE, &out_int);
168 if (out_int < kDiceModeNotInitialized || out_int > kDiceModeMaintenance) {
Maulik Patel6f892252024-03-05 16:39:38 +0000169 return DPE_INVALID_ARGUMENT;
Jamie Foxab30e712023-03-30 17:48:36 +0100170 }
Maulik Patelf4230182024-04-15 13:56:02 +0100171 COUNT_ARGS(num_of_valid_arguments);
Jamie Foxab30e712023-03-30 17:48:36 +0100172 input->mode = (DiceMode)out_int;
173
174 QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_HIDDEN, &out);
175 if (out.len != sizeof(input->hidden)) {
Maulik Patel6f892252024-03-05 16:39:38 +0000176 return DPE_INVALID_ARGUMENT;
Jamie Foxab30e712023-03-30 17:48:36 +0100177 }
Maulik Patelf4230182024-04-15 13:56:02 +0100178 COUNT_ARGS(num_of_valid_arguments);
Jamie Foxab30e712023-03-30 17:48:36 +0100179 memcpy(input->hidden, out.ptr, out.len);
180
181 QCBORDecode_ExitMap(decode_ctx);
182 QCBORDecode_ExitBstrWrapped(decode_ctx);
183
Maulik Pateld936d742024-01-08 14:16:46 +0000184 qcbor_err = QCBORDecode_GetError(decode_ctx);
185 if (qcbor_err != QCBOR_SUCCESS) {
Maulik Patel6f892252024-03-05 16:39:38 +0000186 return DPE_INVALID_ARGUMENT;
Maulik Pateld936d742024-01-08 14:16:46 +0000187 }
188
Maulik Patelf4230182024-04-15 13:56:02 +0100189 if (num_of_input_arguments > num_of_valid_arguments) {
190 /* Extra unsupported arguments encoded in command map */
191 return DPE_INVALID_ARGUMENT;
192 }
193
Jamie Foxab30e712023-03-30 17:48:36 +0100194 return DPE_NO_ERROR;
195}
196
Maulik Patela81605b2023-10-24 12:17:03 +0100197static dpe_error_t decode_derive_context(QCBORDecodeContext *decode_ctx,
198 QCBOREncodeContext *encode_ctx,
199 int32_t client_id)
Jamie Foxab30e712023-03-30 17:48:36 +0100200{
201 dpe_error_t dpe_err;
202 QCBORError qcbor_err;
203 UsefulBufC out;
204 int context_handle;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000205 int32_t target_locality;
Jamie Foxab30e712023-03-30 17:48:36 +0100206 bool retain_parent_context;
Maulik Patela81605b2023-10-24 12:17:03 +0100207 bool allow_new_context_to_derive;
Jamie Foxab30e712023-03-30 17:48:36 +0100208 bool create_certificate;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000209 bool return_certificate;
210 bool allow_new_context_to_export;
211 bool export_cdi;
Maulik Patelf4230182024-04-15 13:56:02 +0100212 DiceInputValues dice_inputs = {0};
Maulik Patela81605b2023-10-24 12:17:03 +0100213 int new_context_handle;
Jamie Foxab30e712023-03-30 17:48:36 +0100214 int new_parent_context_handle;
Tamas Banfcc06e32024-03-25 13:47:33 +0100215 uint8_t *new_certificate_buf = ALLOC_TEMP_BUF;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000216 uint8_t exported_cdi_buf[DICE_MAX_ENCODED_CDI_SIZE];
Maulik Patelcb14cde2024-01-23 12:39:53 +0000217 uint32_t cert_id;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000218 size_t new_certificate_actual_size = 0;
219 size_t exported_cdi_actual_size = 0;
Maulik Patel8a969fd2024-03-01 14:43:03 +0000220 QCBORItem item;
221 uint16_t num_of_input_arguments, num_of_valid_arguments = 0;
Jamie Foxab30e712023-03-30 17:48:36 +0100222
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000223 /* Initialise optional parameters with their default value in case
224 * they are not encoded in the input command
225 */
226 cert_id = DPE_CERT_ID_INVALID;
227 retain_parent_context = false;
228 allow_new_context_to_derive = true;
229 create_certificate = true;
230 return_certificate = false;
231 allow_new_context_to_export = false;
232 export_cdi = false;
233
Maulik Patela81605b2023-10-24 12:17:03 +0100234 /* Decode DeriveContext command */
Maulik Patel8a969fd2024-03-01 14:43:03 +0000235 QCBORDecode_EnterMap(decode_ctx, &item);
236 qcbor_err = QCBORDecode_GetError(decode_ctx);
237 if ((qcbor_err != QCBOR_SUCCESS) ||
238 (item.uDataType != QCBOR_TYPE_MAP)) {
239 /* We expect a map of Derive Context command arguments here */
240 return DPE_INVALID_COMMAND;
241 }
242 /* Save the number of items found in the map */
243 num_of_input_arguments = item.val.uCount;
Jamie Foxab30e712023-03-30 17:48:36 +0100244
Maulik Patela81605b2023-10-24 12:17:03 +0100245 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DERIVE_CONTEXT_CONTEXT_HANDLE,
Jamie Foxab30e712023-03-30 17:48:36 +0100246 &out);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000247 qcbor_err = QCBORDecode_GetError(decode_ctx);
Maulik Patelcb14cde2024-01-23 12:39:53 +0000248 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
Maulik Patel6f892252024-03-05 16:39:38 +0000249 return DPE_INVALID_ARGUMENT;
Jamie Foxab30e712023-03-30 17:48:36 +0100250 }
251 memcpy(&context_handle, out.ptr, out.len);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000252 COUNT_ARGS(num_of_valid_arguments);
Jamie Foxab30e712023-03-30 17:48:36 +0100253
Maulik Patelcb14cde2024-01-23 12:39:53 +0000254 QCBORDecode_GetUInt64InMapN(decode_ctx, DPE_DERIVE_CONTEXT_CERT_ID, &cert_id);
255 /* Check if cert_id was encoded in the received command buffer */
Maulik Patel8a969fd2024-03-01 14:43:03 +0000256 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Maulik Patelcb14cde2024-01-23 12:39:53 +0000257
Maulik Patela81605b2023-10-24 12:17:03 +0100258 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_RETAIN_PARENT_CONTEXT,
Jamie Foxab30e712023-03-30 17:48:36 +0100259 &retain_parent_context);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000260 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Jamie Foxab30e712023-03-30 17:48:36 +0100261
Maulik Patela81605b2023-10-24 12:17:03 +0100262 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_DERIVE,
263 &allow_new_context_to_derive);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000264 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Jamie Foxab30e712023-03-30 17:48:36 +0100265
Maulik Patela81605b2023-10-24 12:17:03 +0100266 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_CREATE_CERTIFICATE,
Jamie Foxab30e712023-03-30 17:48:36 +0100267 &create_certificate);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000268 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Jamie Foxab30e712023-03-30 17:48:36 +0100269
270 dpe_err = decode_dice_inputs(decode_ctx, &dice_inputs);
271 if (dpe_err != DPE_NO_ERROR) {
272 return dpe_err;
273 }
Maulik Patel8a969fd2024-03-01 14:43:03 +0000274 COUNT_ARGS(num_of_valid_arguments);
Jamie Foxab30e712023-03-30 17:48:36 +0100275
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000276 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DERIVE_CONTEXT_TARGET_LOCALITY,
277 &out);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000278 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
279 if (qcbor_err == QCBOR_SUCCESS) {
280 /* Valid argument was found */
281 if (out.len != sizeof(target_locality)) {
282 return DPE_INVALID_ARGUMENT;
283 }
284 memcpy(&target_locality, out.ptr, out.len);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000285 }
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000286
287 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_RETURN_CERTIFICATE,
288 &return_certificate);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000289 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000290
291 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_EXPORT,
292 &allow_new_context_to_export);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000293 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000294
295 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_EXPORT_CDI,
296 &export_cdi);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000297 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000298
Jamie Foxab30e712023-03-30 17:48:36 +0100299 QCBORDecode_ExitMap(decode_ctx);
300
301 /* Exit top level array */
302 QCBORDecode_ExitArray(decode_ctx);
303
304 /* Finish and check for errors before using decoded values */
305 qcbor_err = QCBORDecode_Finish(decode_ctx);
306 if (qcbor_err != QCBOR_SUCCESS) {
307 return DPE_INVALID_COMMAND;
308 }
309
Maulik Patel8a969fd2024-03-01 14:43:03 +0000310 if (num_of_input_arguments > num_of_valid_arguments) {
311 /* Extra unsupported arguments encoded in command map */
312 return DPE_INVALID_ARGUMENT;
313 }
314
Maulik Patelcb14cde2024-01-23 12:39:53 +0000315 dpe_err = derive_context_request(context_handle, cert_id, retain_parent_context,
Maulik Patela81605b2023-10-24 12:17:03 +0100316 allow_new_context_to_derive, create_certificate,
317 &dice_inputs, client_id,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000318 target_locality,
319 return_certificate,
320 allow_new_context_to_export,
321 export_cdi,
Maulik Patela81605b2023-10-24 12:17:03 +0100322 &new_context_handle,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000323 &new_parent_context_handle,
324 new_certificate_buf,
Tamas Banfcc06e32024-03-25 13:47:33 +0100325 SIZEOF_TEMP_BUF,
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000326 &new_certificate_actual_size,
327 exported_cdi_buf,
328 sizeof(exported_cdi_buf),
329 &exported_cdi_actual_size);
Jamie Foxab30e712023-03-30 17:48:36 +0100330 if (dpe_err != DPE_NO_ERROR) {
331 return dpe_err;
332 }
333
334 /* Encode response */
335 QCBOREncode_OpenArray(encode_ctx);
336 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
337
338 QCBOREncode_OpenMap(encode_ctx);
Maulik Patela81605b2023-10-24 12:17:03 +0100339 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_DERIVE_CONTEXT_NEW_CONTEXT_HANDLE,
340 (UsefulBufC){ &new_context_handle,
341 sizeof(new_context_handle) });
Jamie Foxab30e712023-03-30 17:48:36 +0100342 QCBOREncode_AddBytesToMapN(encode_ctx,
Maulik Patela81605b2023-10-24 12:17:03 +0100343 DPE_DERIVE_CONTEXT_PARENT_CONTEXT_HANDLE,
Jamie Foxab30e712023-03-30 17:48:36 +0100344 (UsefulBufC){ &new_parent_context_handle,
345 sizeof(new_parent_context_handle) });
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000346
347 /* The certificate is already encoded into a CBOR array by the function
Tamas Ban257471b2024-03-25 13:49:53 +0100348 * encode_layer_certificate(). Add it as a byte string so that its
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000349 * decoding can be skipped and the CBOR returned to the caller.
350 */
Tamas Banfcc06e32024-03-25 13:47:33 +0100351 CHECK_OVERFLOW_TO_TEMP_BUF;
Maulik Patel9fd8bd22023-10-30 10:58:30 +0000352 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_DERIVE_CONTEXT_NEW_CERTIFICATE,
353 (UsefulBufC){ new_certificate_buf,
354 new_certificate_actual_size });
355
356 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_DERIVE_CONTEXT_EXPORTED_CDI,
357 (UsefulBufC){ exported_cdi_buf,
358 exported_cdi_actual_size });
359
Jamie Foxab30e712023-03-30 17:48:36 +0100360 QCBOREncode_CloseMap(encode_ctx);
361
362 QCBOREncode_CloseArray(encode_ctx);
363
364 return DPE_NO_ERROR;
365}
366
Maulik Patel54d65f72023-06-28 13:04:36 +0100367static dpe_error_t decode_destroy_context(QCBORDecodeContext *decode_ctx,
368 QCBOREncodeContext *encode_ctx)
369{
370 dpe_error_t dpe_err;
371 QCBORError qcbor_err;
372 UsefulBufC out;
373 int context_handle;
374 bool destroy_recursively;
Maulik Pateldc446492024-03-18 14:52:15 +0000375 QCBORItem item;
376 uint16_t num_of_input_arguments, num_of_valid_arguments = 0;
377
378 /* Initialise optional parameters with their default value in case
379 * they are not encoded in the input command
380 */
381 destroy_recursively = false;
Maulik Patel54d65f72023-06-28 13:04:36 +0100382
383 /* Decode Destroy context command */
Maulik Pateldc446492024-03-18 14:52:15 +0000384 QCBORDecode_EnterMap(decode_ctx, &item);
385 qcbor_err = QCBORDecode_GetError(decode_ctx);
386 if ((qcbor_err != QCBOR_SUCCESS) ||
387 (item.uDataType != QCBOR_TYPE_MAP)) {
388 /* We expect a map of Derive Context command arguments here */
389 return DPE_INVALID_COMMAND;
390 }
391 /* Save the number of items found in the map */
392 num_of_input_arguments = item.val.uCount;
Maulik Patel54d65f72023-06-28 13:04:36 +0100393
394 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DESTROY_CONTEXT_HANDLE,
395 &out);
Maulik Pateldc446492024-03-18 14:52:15 +0000396 qcbor_err = QCBORDecode_GetError(decode_ctx);
397 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
Maulik Patel6f892252024-03-05 16:39:38 +0000398 return DPE_INVALID_ARGUMENT;
Maulik Patel54d65f72023-06-28 13:04:36 +0100399 }
400 memcpy(&context_handle, out.ptr, out.len);
Maulik Pateldc446492024-03-18 14:52:15 +0000401 COUNT_ARGS(num_of_valid_arguments);
Maulik Patel54d65f72023-06-28 13:04:36 +0100402
403 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DESTROY_CONTEXT_RECURSIVELY,
404 &destroy_recursively);
Maulik Pateldc446492024-03-18 14:52:15 +0000405 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Maulik Patel54d65f72023-06-28 13:04:36 +0100406
407 QCBORDecode_ExitMap(decode_ctx);
408
409 /* Exit top level array */
410 QCBORDecode_ExitArray(decode_ctx);
411
412 /* Finish and check for errors before using decoded values */
413 qcbor_err = QCBORDecode_Finish(decode_ctx);
414 if (qcbor_err != QCBOR_SUCCESS) {
415 return DPE_INVALID_COMMAND;
416 }
417
Maulik Pateldc446492024-03-18 14:52:15 +0000418 if (num_of_input_arguments > num_of_valid_arguments) {
419 /* Extra unsupported arguments encoded in command map */
420 return DPE_INVALID_ARGUMENT;
421 }
422
Maulik Patel54d65f72023-06-28 13:04:36 +0100423 dpe_err = destroy_context_request(context_handle, destroy_recursively);
424 if (dpe_err != DPE_NO_ERROR) {
425 return dpe_err;
426 }
427
428 /* Encode response */
429 QCBOREncode_OpenArray(encode_ctx);
430 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
431 QCBOREncode_CloseArray(encode_ctx);
432
433 return DPE_NO_ERROR;
434}
435
Jamie Foxab30e712023-03-30 17:48:36 +0100436static dpe_error_t decode_certify_key(QCBORDecodeContext *decode_ctx,
437 QCBOREncodeContext *encode_ctx)
438{
439 QCBORError qcbor_err;
440 UsefulBufC out;
441 dpe_error_t dpe_err;
442 int context_handle;
443 bool retain_context;
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000444 const uint8_t *public_key = NULL;
Jamie Foxab30e712023-03-30 17:48:36 +0100445 size_t public_key_size;
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000446 const uint8_t *label = NULL;
Jamie Foxab30e712023-03-30 17:48:36 +0100447 size_t label_size;
Tamas Banfcc06e32024-03-25 13:47:33 +0100448 uint8_t *certificate_buf = ALLOC_TEMP_BUF;
Maulik Patelcbded682023-12-07 11:50:16 +0000449 size_t certificate_actual_size;
Maulik Patele6adc112023-08-18 14:21:51 +0100450 uint8_t derived_public_key_buf[DPE_ATTEST_PUB_KEY_SIZE];
Jamie Foxab30e712023-03-30 17:48:36 +0100451 size_t derived_public_key_actual_size;
452 int new_context_handle;
Maulik Patel8a969fd2024-03-01 14:43:03 +0000453 QCBORItem item;
454 uint16_t num_of_input_arguments, num_of_valid_arguments = 0;
Jamie Foxab30e712023-03-30 17:48:36 +0100455
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000456 /* Initialise optional parameters with their default value in case
457 * they are not encoded in the input command
458 */
459 retain_context = false;
460 public_key_size = 0;
461 label_size = 0;
462
Jamie Foxab30e712023-03-30 17:48:36 +0100463 /* Decode CertifyKey command */
Maulik Patel8a969fd2024-03-01 14:43:03 +0000464 QCBORDecode_EnterMap(decode_ctx, &item);
465 qcbor_err = QCBORDecode_GetError(decode_ctx);
466 if ((qcbor_err != QCBOR_SUCCESS) ||
467 (item.uDataType != QCBOR_TYPE_MAP)) {
468 /* We expect a map of Certify Key command arguments here */
469 return DPE_INVALID_COMMAND;
470 }
471 /* Save the number of items found in the map */
472 num_of_input_arguments = item.val.uCount;
Jamie Foxab30e712023-03-30 17:48:36 +0100473
474 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_CONTEXT_HANDLE,
475 &out);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000476 qcbor_err = QCBORDecode_GetError(decode_ctx);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000477 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
Maulik Patel6f892252024-03-05 16:39:38 +0000478 return DPE_INVALID_ARGUMENT;
Jamie Foxab30e712023-03-30 17:48:36 +0100479 }
480 memcpy(&context_handle, out.ptr, out.len);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000481 COUNT_ARGS(num_of_valid_arguments);
Jamie Foxab30e712023-03-30 17:48:36 +0100482
483 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_CERTIFY_KEY_RETAIN_CONTEXT,
484 &retain_context);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000485 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Jamie Foxab30e712023-03-30 17:48:36 +0100486
487 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_PUBLIC_KEY,
488 &out);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000489 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000490 if (qcbor_err == QCBOR_SUCCESS) {
Maulik Patel8a969fd2024-03-01 14:43:03 +0000491 /* Valid argument was found */
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000492 public_key = out.ptr;
493 public_key_size = out.len;
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000494 }
Jamie Foxab30e712023-03-30 17:48:36 +0100495
496 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_LABEL, &out);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000497 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000498 if (qcbor_err == QCBOR_SUCCESS) {
Maulik Patel8a969fd2024-03-01 14:43:03 +0000499 /* Valid argument was found */
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000500 label = out.ptr;
501 label_size = out.len;
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000502 }
Jamie Foxab30e712023-03-30 17:48:36 +0100503
504 QCBORDecode_ExitMap(decode_ctx);
505
506 /* Exit top level array */
507 QCBORDecode_ExitArray(decode_ctx);
508
509 /* Finish and check for errors before using decoded values */
510 qcbor_err = QCBORDecode_Finish(decode_ctx);
511 if (qcbor_err != QCBOR_SUCCESS) {
512 return DPE_INVALID_COMMAND;
513 }
514
Maulik Patel8a969fd2024-03-01 14:43:03 +0000515 if (num_of_input_arguments > num_of_valid_arguments) {
516 /* Extra unsupported arguments encoded in command map */
517 return DPE_INVALID_ARGUMENT;
518 }
519
Maulik Patele6adc112023-08-18 14:21:51 +0100520 dpe_err = certify_key_request(context_handle, retain_context, public_key,
521 public_key_size, label, label_size,
Maulik Patelcbded682023-12-07 11:50:16 +0000522 certificate_buf,
Tamas Banfcc06e32024-03-25 13:47:33 +0100523 SIZEOF_TEMP_BUF,
Maulik Patelcbded682023-12-07 11:50:16 +0000524 &certificate_actual_size,
Maulik Patele6adc112023-08-18 14:21:51 +0100525 derived_public_key_buf,
526 sizeof(derived_public_key_buf),
527 &derived_public_key_actual_size,
528 &new_context_handle);
Jamie Foxab30e712023-03-30 17:48:36 +0100529 if (dpe_err != DPE_NO_ERROR) {
530 return dpe_err;
531 }
532
533 /* Encode response */
534 QCBOREncode_OpenArray(encode_ctx);
535 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
536
537 QCBOREncode_OpenMap(encode_ctx);
538
539 /* The certificate chain is already encoded into a CBOR array by the certify
540 * key implementation. Add it as a byte string so that its decoding can be
541 * skipped and the CBOR returned to the caller.
542 */
Tamas Banfcc06e32024-03-25 13:47:33 +0100543 CHECK_OVERFLOW_TO_TEMP_BUF;
Maulik Patelcbded682023-12-07 11:50:16 +0000544 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_CERTIFY_KEY_CERTIFICATE,
545 (UsefulBufC){ certificate_buf,
546 certificate_actual_size });
Jamie Foxab30e712023-03-30 17:48:36 +0100547
548 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_CERTIFY_KEY_DERIVED_PUBLIC_KEY,
549 (UsefulBufC){ derived_public_key_buf,
550 derived_public_key_actual_size });
551 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_CERTIFY_KEY_NEW_CONTEXT_HANDLE,
552 (UsefulBufC){ &new_context_handle,
553 sizeof(new_context_handle) });
554
555 QCBOREncode_CloseMap(encode_ctx);
556
557 QCBOREncode_CloseArray(encode_ctx);
558
559 return DPE_NO_ERROR;
560}
561
Maulik Patel83a6b592023-12-05 15:20:30 +0000562static dpe_error_t decode_get_certificate_chain(QCBORDecodeContext *decode_ctx,
563 QCBOREncodeContext *encode_ctx)
564{
565 QCBORError qcbor_err;
566 UsefulBufC out;
567 dpe_error_t dpe_err;
568 int context_handle;
569 bool retain_context;
570 bool clear_from_context;
Tamas Banfcc06e32024-03-25 13:47:33 +0100571 uint8_t *certificate_chain_buf = ALLOC_TEMP_BUF;
Maulik Patel83a6b592023-12-05 15:20:30 +0000572 size_t certificate_chain_actual_size;
573 int new_context_handle;
Maulik Patel8a969fd2024-03-01 14:43:03 +0000574 QCBORItem item;
575 uint16_t num_of_input_arguments, num_of_valid_arguments = 0;
Maulik Patel83a6b592023-12-05 15:20:30 +0000576
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000577 /* Initialise optional parameters with their default value in case
578 * they are not encoded in the input command
579 */
580 retain_context = false;
581 clear_from_context = false;
582
Maulik Patel83a6b592023-12-05 15:20:30 +0000583 /* Decode GetCertificateChain command */
Maulik Patel8a969fd2024-03-01 14:43:03 +0000584 QCBORDecode_EnterMap(decode_ctx, &item);
585 qcbor_err = QCBORDecode_GetError(decode_ctx);
586 if ((qcbor_err != QCBOR_SUCCESS) ||
587 (item.uDataType != QCBOR_TYPE_MAP)) {
588 /* We expect a map of Get Certificate Chain command arguments here */
589 return DPE_INVALID_COMMAND;
590 }
591 /* Save the number of items found in the map */
592 num_of_input_arguments = item.val.uCount;
Maulik Patel83a6b592023-12-05 15:20:30 +0000593
594 QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_CONTEXT_HANDLE,
595 &out);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000596 qcbor_err = QCBORDecode_GetError(decode_ctx);
Maulik Patelfbe9bff2024-02-09 14:05:25 +0000597 if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
Maulik Patel6f892252024-03-05 16:39:38 +0000598 return DPE_INVALID_ARGUMENT;
Maulik Patel83a6b592023-12-05 15:20:30 +0000599 }
600 memcpy(&context_handle, out.ptr, out.len);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000601 COUNT_ARGS(num_of_valid_arguments);
Maulik Patel83a6b592023-12-05 15:20:30 +0000602
603 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_RETAIN_CONTEXT,
604 &retain_context);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000605 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Maulik Patel83a6b592023-12-05 15:20:30 +0000606
607 QCBORDecode_GetBoolInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_CLEAR_FROM_CONTEXT,
608 &clear_from_context);
Maulik Patel8a969fd2024-03-01 14:43:03 +0000609 CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
Maulik Patel83a6b592023-12-05 15:20:30 +0000610
611 QCBORDecode_ExitMap(decode_ctx);
612
613 /* Exit top level array */
614 QCBORDecode_ExitArray(decode_ctx);
615
616 /* Finish and check for errors before using decoded values */
617 qcbor_err = QCBORDecode_Finish(decode_ctx);
618 if (qcbor_err != QCBOR_SUCCESS) {
619 return DPE_INVALID_COMMAND;
620 }
621
Maulik Patel8a969fd2024-03-01 14:43:03 +0000622 if (num_of_input_arguments > num_of_valid_arguments) {
623 /* Extra unsupported arguments encoded in command map */
624 return DPE_INVALID_ARGUMENT;
625 }
626
Maulik Patel83a6b592023-12-05 15:20:30 +0000627 dpe_err = get_certificate_chain_request(context_handle,
628 retain_context,
629 clear_from_context,
630 certificate_chain_buf,
Tamas Banfcc06e32024-03-25 13:47:33 +0100631 SIZEOF_TEMP_BUF,
Maulik Patel83a6b592023-12-05 15:20:30 +0000632 &certificate_chain_actual_size,
633 &new_context_handle);
634 if (dpe_err != DPE_NO_ERROR) {
635 return dpe_err;
636 }
637
638 /* Encode response */
639 QCBOREncode_OpenArray(encode_ctx);
640 QCBOREncode_AddInt64(encode_ctx, DPE_NO_ERROR);
641
642 QCBOREncode_OpenMap(encode_ctx);
643
644 /* The certificate chain is already encoded into a CBOR array by the get certificate
645 * chain implementation. Add it as a byte string so that its decoding can be
646 * skipped and the CBOR returned to the caller.
647 */
Tamas Banfcc06e32024-03-25 13:47:33 +0100648 CHECK_OVERFLOW_TO_TEMP_BUF;
Maulik Patel83a6b592023-12-05 15:20:30 +0000649 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_GET_CERTIFICATE_CHAIN_CERTIFICATE_CHAIN,
650 (UsefulBufC){ certificate_chain_buf,
651 certificate_chain_actual_size });
652
653 QCBOREncode_AddBytesToMapN(encode_ctx, DPE_GET_CERTIFICATE_CHAIN_NEW_CONTEXT_HANDLE,
654 (UsefulBufC){ &new_context_handle,
655 sizeof(new_context_handle) });
656
657 QCBOREncode_CloseMap(encode_ctx);
658
659 QCBOREncode_CloseArray(encode_ctx);
660
661 return DPE_NO_ERROR;
662}
663
Jamie Foxab30e712023-03-30 17:48:36 +0100664static void encode_error_only(QCBOREncodeContext *encode_ctx,
665 dpe_error_t dpe_err)
666{
667 QCBOREncode_OpenArray(encode_ctx);
668 QCBOREncode_AddInt64(encode_ctx, dpe_err);
669 QCBOREncode_CloseArray(encode_ctx);
670}
671
672int32_t dpe_command_decode(int32_t client_id,
673 const char *cmd_input, size_t cmd_input_size,
674 char *cmd_output, size_t *cmd_output_size)
675{
676 dpe_error_t dpe_err;
677 QCBORError qcbor_err;
678 QCBORDecodeContext decode_ctx;
679 QCBOREncodeContext encode_ctx;
680 UsefulBufC out;
681 uint64_t command_id;
682
683 QCBORDecode_Init(&decode_ctx, (UsefulBufC){ cmd_input, cmd_input_size },
684 QCBOR_DECODE_MODE_NORMAL);
685 QCBOREncode_Init(&encode_ctx, (UsefulBuf){ cmd_output, *cmd_output_size });
686
687 /* Enter top level array */
688 QCBORDecode_EnterArray(&decode_ctx, NULL);
689
690 /* Get the command ID */
691 QCBORDecode_GetUInt64(&decode_ctx, &command_id);
692
693 /* Check for errors before interpreting the decoded command ID */
694 qcbor_err = QCBORDecode_GetError(&decode_ctx);
695
696 if (qcbor_err == QCBOR_SUCCESS) {
697 switch (command_id) {
Maulik Patela81605b2023-10-24 12:17:03 +0100698 case DPE_DERIVE_CONTEXT:
699 dpe_err = decode_derive_context(&decode_ctx, &encode_ctx, client_id);
Jamie Foxab30e712023-03-30 17:48:36 +0100700 break;
701 case DPE_CERTIFY_KEY:
702 dpe_err = decode_certify_key(&decode_ctx, &encode_ctx);
703 break;
Maulik Patel83a6b592023-12-05 15:20:30 +0000704 case DPE_GET_CERTIFICATE_CHAIN:
705 dpe_err = decode_get_certificate_chain(&decode_ctx, &encode_ctx);
706 break;
Maulik Patel54d65f72023-06-28 13:04:36 +0100707 case DPE_DESTROY_CONTEXT:
708 dpe_err = decode_destroy_context(&decode_ctx, &encode_ctx);
709 break;
Jamie Foxab30e712023-03-30 17:48:36 +0100710 default:
711 dpe_err = DPE_INVALID_COMMAND;
712 break;
713 }
714 } else {
715 dpe_err = DPE_INVALID_COMMAND;
716 }
717
718 /* If an unhandled DPE error was returned, then encode it into a response */
719 if (dpe_err != DPE_NO_ERROR) {
720 encode_error_only(&encode_ctx, dpe_err);
721 }
722
723 qcbor_err = QCBOREncode_Finish(&encode_ctx, &out);
724 if (qcbor_err != QCBOR_SUCCESS) {
725 return -1;
726 }
727
728 *cmd_output_size = out.len;
729
730 return 0;
731}