DPE: Handle unsupported and erroneous dice inputs
For DeriveContext command, return INVALID_ARGUMENT if any extra
unsupported parameters are passed as dice input arguments. Also
return the same if the required inputs are missing.
Signed-off-by: Maulik Patel <maulik.patel@arm.com>
Change-Id: Ifbe8b7708722fac001acd5c6c5115cd9d9318465
diff --git a/partitions/dice_protection_environment/dpe_cmd_decode.c b/partitions/dice_protection_environment/dpe_cmd_decode.c
index ad5f811..644fb7c 100644
--- a/partitions/dice_protection_environment/dpe_cmd_decode.c
+++ b/partitions/dice_protection_environment/dpe_cmd_decode.c
@@ -71,22 +71,38 @@
QCBORError qcbor_err;
UsefulBufC out = { NULL, 0 };
int64_t out_int;
+ uint16_t num_of_input_arguments, num_of_valid_arguments = 0;
+ QCBORItem item;
/* The DICE inputs are encoded as a map wrapped into a byte string */
QCBORDecode_EnterBstrWrappedFromMapN(decode_ctx,
DPE_DERIVE_CONTEXT_INPUT_DATA,
QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL);
- QCBORDecode_EnterMap(decode_ctx, NULL);
+ QCBORDecode_EnterMap(decode_ctx, &item);
+ qcbor_err = QCBORDecode_GetError(decode_ctx);
+ if ((qcbor_err != QCBOR_SUCCESS) ||
+ (item.uDataType != QCBOR_TYPE_MAP)) {
+ /* We expect a map of Dice inputs here */
+ return DPE_INVALID_ARGUMENT;
+ }
+ /* Save the number of items found in the map */
+ num_of_input_arguments = item.val.uCount;
QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CODE_HASH, &out);
- if (out.len != sizeof(input->code_hash)) {
+ qcbor_err = QCBORDecode_GetError(decode_ctx);
+ if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(input->code_hash))) {
return DPE_INVALID_ARGUMENT;
}
memcpy(input->code_hash, out.ptr, out.len);
+ COUNT_ARGS(num_of_valid_arguments);
QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CODE_DESCRIPTOR, &out);
- input->code_descriptor = out.ptr;
- input->code_descriptor_size = out.len;
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
+ if (qcbor_err == QCBOR_SUCCESS) {
+ /* Valid argument was found */
+ input->code_descriptor = out.ptr;
+ input->code_descriptor_size = out.len;
+ }
QCBORDecode_GetInt64InMapN(decode_ctx, DICE_CONFIG_TYPE, &out_int);
@@ -100,14 +116,17 @@
out_int > kDiceConfigTypeDescriptor) {
return DPE_INVALID_ARGUMENT;
}
+ COUNT_ARGS(num_of_valid_arguments);
input->config_type = (DiceConfigType)out_int;
/* Only one of config value or config descriptor needs to be provided */
if (input->config_type == kDiceConfigTypeInline) {
QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CONFIG_VALUE, &out);
- if (out.len != sizeof(input->config_value)) {
+ qcbor_err = QCBORDecode_GetError(decode_ctx);
+ if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(input->config_value))) {
return DPE_INVALID_ARGUMENT;
}
+ COUNT_ARGS(num_of_valid_arguments);
memcpy(input->config_value, out.ptr, out.len);
/* Config descriptor is not provided */
@@ -116,6 +135,11 @@
} else {
QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_CONFIG_DESCRIPTOR,
&out);
+ qcbor_err = QCBORDecode_GetError(decode_ctx);
+ if (qcbor_err != QCBOR_SUCCESS) {
+ return DPE_INVALID_ARGUMENT;
+ }
+ COUNT_ARGS(num_of_valid_arguments);
input->config_descriptor = out.ptr;
input->config_descriptor_size = out.len;
@@ -124,26 +148,34 @@
}
QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_AUTHORITY_HASH, &out);
- if (out.len != sizeof(input->authority_hash)) {
+ qcbor_err = QCBORDecode_GetError(decode_ctx);
+ if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(input->authority_hash))) {
return DPE_INVALID_ARGUMENT;
}
+ COUNT_ARGS(num_of_valid_arguments);
memcpy(input->authority_hash, out.ptr, out.len);
QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_AUTHORITY_DESCRIPTOR,
&out);
- input->authority_descriptor = out.ptr;
- input->authority_descriptor_size = out.len;
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
+ if (qcbor_err == QCBOR_SUCCESS) {
+ /* Valid argument was found */
+ input->authority_descriptor = out.ptr;
+ input->authority_descriptor_size = out.len;
+ }
QCBORDecode_GetInt64InMapN(decode_ctx, DICE_MODE, &out_int);
if (out_int < kDiceModeNotInitialized || out_int > kDiceModeMaintenance) {
return DPE_INVALID_ARGUMENT;
}
+ COUNT_ARGS(num_of_valid_arguments);
input->mode = (DiceMode)out_int;
QCBORDecode_GetByteStringInMapN(decode_ctx, DICE_HIDDEN, &out);
if (out.len != sizeof(input->hidden)) {
return DPE_INVALID_ARGUMENT;
}
+ COUNT_ARGS(num_of_valid_arguments);
memcpy(input->hidden, out.ptr, out.len);
QCBORDecode_ExitMap(decode_ctx);
@@ -154,6 +186,11 @@
return DPE_INVALID_ARGUMENT;
}
+ if (num_of_input_arguments > num_of_valid_arguments) {
+ /* Extra unsupported arguments encoded in command map */
+ return DPE_INVALID_ARGUMENT;
+ }
+
return DPE_NO_ERROR;
}
@@ -172,7 +209,7 @@
bool return_certificate;
bool allow_new_context_to_export;
bool export_cdi;
- DiceInputValues dice_inputs;
+ DiceInputValues dice_inputs = {0};
int new_context_handle;
int new_parent_context_handle;
uint8_t *new_certificate_buf = ALLOC_TEMP_BUF;