DPE: Handle unsupported parameters
For DeriveContext, CertifyKey and GetCertificateChain commands,
return INVALID_ARGUMENT if any extra unsupported parameters are passed
as input arguments.
Signed-off-by: Maulik Patel <maulik.patel@arm.com>
Change-Id: I2abc8ea4455d712c1514649b4467c72ae8d3c518
diff --git a/partitions/dice_protection_environment/dpe_cmd_decode.c b/partitions/dice_protection_environment/dpe_cmd_decode.c
index b2381e1..b5c7dad 100644
--- a/partitions/dice_protection_environment/dpe_cmd_decode.c
+++ b/partitions/dice_protection_environment/dpe_cmd_decode.c
@@ -16,10 +16,17 @@
#include "qcbor/qcbor_decode.h"
#include "qcbor/qcbor_spiffy_decode.h"
-#define CHECK_CBOR_ERROR(decode_ctx) \
- qcbor_err = QCBORDecode_GetAndResetError(decode_ctx); \
- if ((qcbor_err != QCBOR_SUCCESS) && (qcbor_err != QCBOR_ERR_LABEL_NOT_FOUND)) { \
- return DPE_INVALID_COMMAND; \
+#define COUNT_ARGS(arg) (arg)++
+
+#define CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx) \
+ qcbor_err = QCBORDecode_GetAndResetError(decode_ctx); \
+ if (qcbor_err == QCBOR_SUCCESS) { \
+ /* Valid label found - optional argument present */ \
+ COUNT_ARGS(num_of_valid_arguments); \
+ } else if (qcbor_err != QCBOR_ERR_LABEL_NOT_FOUND) { \
+ return DPE_INVALID_COMMAND; \
+ } else { \
+ /* We have NOT found the optional argument, do not update the count */ \
}
/*
@@ -158,6 +165,8 @@
uint32_t cert_id;
size_t new_certificate_actual_size = 0;
size_t exported_cdi_actual_size = 0;
+ QCBORItem item;
+ uint16_t num_of_input_arguments, num_of_valid_arguments = 0;
/* Initialise optional parameters with their default value in case
* they are not encoded in the input command
@@ -171,55 +180,69 @@
export_cdi = false;
/* Decode DeriveContext command */
- 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 Derive Context command arguments here */
+ return DPE_INVALID_COMMAND;
+ }
+ /* Save the number of items found in the map */
+ num_of_input_arguments = item.val.uCount;
QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DERIVE_CONTEXT_CONTEXT_HANDLE,
&out);
- qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
+ qcbor_err = QCBORDecode_GetError(decode_ctx);
if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
return DPE_INVALID_COMMAND;
}
memcpy(&context_handle, out.ptr, out.len);
+ COUNT_ARGS(num_of_valid_arguments);
QCBORDecode_GetUInt64InMapN(decode_ctx, DPE_DERIVE_CONTEXT_CERT_ID, &cert_id);
/* Check if cert_id was encoded in the received command buffer */
- CHECK_CBOR_ERROR(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_RETAIN_PARENT_CONTEXT,
&retain_parent_context);
- CHECK_CBOR_ERROR(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_DERIVE,
&allow_new_context_to_derive);
- CHECK_CBOR_ERROR(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_CREATE_CERTIFICATE,
&create_certificate);
- CHECK_CBOR_ERROR(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
dpe_err = decode_dice_inputs(decode_ctx, &dice_inputs);
if (dpe_err != DPE_NO_ERROR) {
return dpe_err;
}
+ COUNT_ARGS(num_of_valid_arguments);
QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_DERIVE_CONTEXT_TARGET_LOCALITY,
&out);
- if (out.len != sizeof(target_locality)) {
- return DPE_INVALID_COMMAND;
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
+ if (qcbor_err == QCBOR_SUCCESS) {
+ /* Valid argument was found */
+ if (out.len != sizeof(target_locality)) {
+ return DPE_INVALID_ARGUMENT;
+ }
+ memcpy(&target_locality, out.ptr, out.len);
}
- memcpy(&target_locality, out.ptr, out.len);
QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_RETURN_CERTIFICATE,
&return_certificate);
- CHECK_CBOR_ERROR(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_EXPORT,
&allow_new_context_to_export);
- CHECK_CBOR_ERROR(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
QCBORDecode_GetBoolInMapN(decode_ctx, DPE_DERIVE_CONTEXT_EXPORT_CDI,
&export_cdi);
- CHECK_CBOR_ERROR(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
QCBORDecode_ExitMap(decode_ctx);
@@ -232,6 +255,11 @@
return DPE_INVALID_COMMAND;
}
+ if (num_of_input_arguments > num_of_valid_arguments) {
+ /* Extra unsupported arguments encoded in command map */
+ return DPE_INVALID_ARGUMENT;
+ }
+
dpe_err = derive_context_request(context_handle, cert_id, retain_parent_context,
allow_new_context_to_derive, create_certificate,
&dice_inputs, client_id,
@@ -346,6 +374,8 @@
uint8_t derived_public_key_buf[DPE_ATTEST_PUB_KEY_SIZE];
size_t derived_public_key_actual_size;
int new_context_handle;
+ QCBORItem item;
+ uint16_t num_of_input_arguments, num_of_valid_arguments = 0;
/* Initialise optional parameters with their default value in case
* they are not encoded in the input command
@@ -355,41 +385,44 @@
label_size = 0;
/* Decode CertifyKey command */
- 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 Certify Key command arguments here */
+ return DPE_INVALID_COMMAND;
+ }
+ /* Save the number of items found in the map */
+ num_of_input_arguments = item.val.uCount;
QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_CONTEXT_HANDLE,
&out);
- qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
+ qcbor_err = QCBORDecode_GetError(decode_ctx);
if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
return DPE_INVALID_COMMAND;
}
memcpy(&context_handle, out.ptr, out.len);
+ COUNT_ARGS(num_of_valid_arguments);
QCBORDecode_GetBoolInMapN(decode_ctx, DPE_CERTIFY_KEY_RETAIN_CONTEXT,
&retain_context);
- CHECK_CBOR_ERROR(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_PUBLIC_KEY,
&out);
- qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
if (qcbor_err == QCBOR_SUCCESS) {
+ /* Valid argument was found */
public_key = out.ptr;
public_key_size = out.len;
- } else if (qcbor_err == QCBOR_ERR_LABEL_NOT_FOUND) {
- /* Do nothing - argument already initialised to default value */
- } else {
- return DPE_INVALID_COMMAND;
}
QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_CERTIFY_KEY_LABEL, &out);
- qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
if (qcbor_err == QCBOR_SUCCESS) {
+ /* Valid argument was found */
label = out.ptr;
label_size = out.len;
- } else if (qcbor_err == QCBOR_ERR_LABEL_NOT_FOUND) {
- /* Do nothing - argument already initialised to default value */
- } else {
- return DPE_INVALID_COMMAND;
}
QCBORDecode_ExitMap(decode_ctx);
@@ -403,6 +436,11 @@
return DPE_INVALID_COMMAND;
}
+ if (num_of_input_arguments > num_of_valid_arguments) {
+ /* Extra unsupported arguments encoded in command map */
+ return DPE_INVALID_ARGUMENT;
+ }
+
dpe_err = certify_key_request(context_handle, retain_context, public_key,
public_key_size, label, label_size,
certificate_buf,
@@ -456,6 +494,8 @@
uint8_t *certificate_chain_buf = REUSE_CMD_BUF(DICE_CERT_CHAIN_SIZE);
size_t certificate_chain_actual_size;
int new_context_handle;
+ QCBORItem item;
+ uint16_t num_of_input_arguments, num_of_valid_arguments = 0;
/* Initialise optional parameters with their default value in case
* they are not encoded in the input command
@@ -464,23 +504,32 @@
clear_from_context = false;
/* Decode GetCertificateChain command */
- 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 Get Certificate Chain command arguments here */
+ return DPE_INVALID_COMMAND;
+ }
+ /* Save the number of items found in the map */
+ num_of_input_arguments = item.val.uCount;
QCBORDecode_GetByteStringInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_CONTEXT_HANDLE,
&out);
- qcbor_err = QCBORDecode_GetAndResetError(decode_ctx);
+ qcbor_err = QCBORDecode_GetError(decode_ctx);
if ((qcbor_err != QCBOR_SUCCESS) || (out.len != sizeof(context_handle))) {
return DPE_INVALID_COMMAND;
}
memcpy(&context_handle, out.ptr, out.len);
+ COUNT_ARGS(num_of_valid_arguments);
QCBORDecode_GetBoolInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_RETAIN_CONTEXT,
&retain_context);
- CHECK_CBOR_ERROR(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
QCBORDecode_GetBoolInMapN(decode_ctx, DPE_GET_CERTIFICATE_CHAIN_CLEAR_FROM_CONTEXT,
&clear_from_context);
- CHECK_CBOR_ERROR(decode_ctx);
+ CHECK_AND_COUNT_OPTIONAL_ARGUMENT(decode_ctx);
QCBORDecode_ExitMap(decode_ctx);
@@ -493,6 +542,11 @@
return DPE_INVALID_COMMAND;
}
+ if (num_of_input_arguments > num_of_valid_arguments) {
+ /* Extra unsupported arguments encoded in command map */
+ return DPE_INVALID_ARGUMENT;
+ }
+
dpe_err = get_certificate_chain_request(context_handle,
retain_context,
clear_from_context,