suit: Introduce per-component flags

This commit is contained in:
Koen Zandberg 2020-09-26 12:30:24 +02:00
parent 4a133a7d30
commit d9cf10c109
No known key found for this signature in database
GPG Key ID: 0895A893E6D2985B
3 changed files with 66 additions and 12 deletions

View File

@ -64,6 +64,12 @@ extern "C" {
*/ */
#define SUIT_VERSION (1) #define SUIT_VERSION (1)
/**
* @name SUIT manifest status flags
*
* These flags apply to the full manifest.
* @{
*/
/** /**
* @brief COSE signature OK * @brief COSE signature OK
*/ */
@ -73,6 +79,7 @@ extern "C" {
* @brief COSE payload matches SUIT manifest digest * @brief COSE payload matches SUIT manifest digest
*/ */
#define SUIT_STATE_FULLY_AUTHENTICATED (1 << 2) #define SUIT_STATE_FULLY_AUTHENTICATED (1 << 2)
/** @} */
/** /**
* @brief SUIT error codes * @brief SUIT error codes
@ -165,12 +172,25 @@ typedef struct {
uint16_t offset; /**< offset to the start of the content */ uint16_t offset; /**< offset to the start of the content */
} suit_param_ref_t; } suit_param_ref_t;
/**
* @name SUIT component flags.
*
* These state flags apply to individual components inside a manifest.
* @{
*/
#define SUIT_COMPONENT_STATE_FETCHED 0x01 /**< Component is fetched */
#define SUIT_COMPONENT_STATE_FETCH_FAILED 0x02 /**< Component fetched but failed */
#define SUIT_COMPONENT_STATE_VERIFIED 0x04 /**< Component is verified */
#define SUIT_COMPONENT_STATE_FINALIZED 0x08 /**< Component successfully installed */
/** @} */
/** /**
* @brief SUIT component struct as decoded from the manifest * @brief SUIT component struct as decoded from the manifest
* *
* The parameters are references to CBOR-encoded information in the manifest. * The parameters are references to CBOR-encoded information in the manifest.
*/ */
typedef struct { typedef struct {
uint16_t state; /**< Component status flags */
suit_param_ref_t identifier; /**< Component identifier */ suit_param_ref_t identifier; /**< Component identifier */
suit_param_ref_t param_vendor_id; /**< Vendor ID */ suit_param_ref_t param_vendor_id; /**< Vendor ID */
suit_param_ref_t param_class_id; /**< Class ID */ suit_param_ref_t param_class_id; /**< Class ID */
@ -209,10 +229,6 @@ typedef struct {
* @brief Bit flags used to determine if SUIT manifest contains components * @brief Bit flags used to determine if SUIT manifest contains components
*/ */
#define SUIT_MANIFEST_HAVE_COMPONENTS (0x1) #define SUIT_MANIFEST_HAVE_COMPONENTS (0x1)
/**
* @brief Bit flags used to determine if SUIT manifest contains an image
*/
#define SUIT_MANIFEST_HAVE_IMAGE (0x2)
/** /**
* @brief Component index representing all components * @brief Component index representing all components
@ -253,6 +269,32 @@ int suit_parse(suit_manifest_t *manifest, const uint8_t *buf, size_t len);
*/ */
int suit_policy_check(suit_manifest_t *manifest); int suit_policy_check(suit_manifest_t *manifest);
/**
* @brief Set a component flag
*
* @param component Component to set flag for
* @param flag Flag to set
*/
static inline void suit_component_set_flag(suit_component_t *component,
uint16_t flag)
{
component->state |= flag;
}
/**
* @brief Check a component flag
*
* @param component Component to check a flag for
* @param flag Flag to check
*
* @returns True if the flag is set
*/
static inline bool suit_component_check_flag(suit_component_t *component,
uint16_t flag)
{
return (component->state & flag);
}
/** /**
* @brief Helper function for writing bytes on flash a specified offset * @brief Helper function for writing bytes on flash a specified offset
* *

View File

@ -279,6 +279,12 @@ static int _dtv_fetch(suit_manifest_t *manifest, int key,
suit_component_t *comp = _get_component(manifest); suit_component_t *comp = _get_component(manifest);
/* Deny the fetch if the component was already fetched before */
if (suit_component_check_flag(comp, SUIT_COMPONENT_STATE_FETCHED)) {
LOG_ERROR("Component already fetched before\n");
return SUIT_ERR_INVALID_MANIFEST;
}
nanocbor_value_t param_uri; nanocbor_value_t param_uri;
suit_param_ref_to_cbor(manifest, &comp->param_uri, suit_param_ref_to_cbor(manifest, &comp->param_uri,
&param_uri); &param_uri);
@ -316,13 +322,16 @@ static int _dtv_fetch(suit_manifest_t *manifest, int key,
return res; return res;
} }
suit_component_set_flag(comp, SUIT_COMPONENT_STATE_FETCHED);
if (res) { if (res) {
LOG_INFO("image download failed\n)"); suit_component_set_flag(comp, SUIT_COMPONENT_STATE_FETCH_FAILED);
/* TODO: The leftover data from a failed fetch should be purged. It
* could contain potential malicous data from an attacker */
LOG_INFO("image download failed with code %i\n", res);
return res; return res;
} }
manifest->state |= SUIT_MANIFEST_HAVE_IMAGE;
LOG_DEBUG("Update OK\n"); LOG_DEBUG("Update OK\n");
return SUIT_OK; return SUIT_OK;
} }
@ -363,6 +372,14 @@ static int _dtv_verify_image_match(suit_manifest_t *manifest, int key,
return SUIT_ERR_INVALID_MANIFEST; return SUIT_ERR_INVALID_MANIFEST;
} }
/* Only check the component if it is fetched, but not failed */
if (!suit_component_check_flag(comp, SUIT_COMPONENT_STATE_FETCHED) ||
suit_component_check_flag(comp, SUIT_COMPONENT_STATE_FETCH_FAILED)) {
LOG_ERROR("Fetch failed, or nothing fetched, nothing to check: %u\n",
comp->state);
return SUIT_ERR_INVALID_MANIFEST;
}
LOG_INFO("Verifying image digest\n"); LOG_INFO("Verifying image digest\n");
nanocbor_value_t _v; nanocbor_value_t _v;
if (suit_param_ref_to_cbor(manifest, &comp->param_digest, &_v) == 0) { if (suit_param_ref_to_cbor(manifest, &comp->param_digest, &_v) == 0) {

View File

@ -374,11 +374,6 @@ static void _suit_handle_url(const char *url)
return; return;
} }
LOG_INFO("suit_parse() success\n");
if (!(manifest.state & SUIT_MANIFEST_HAVE_IMAGE)) {
LOG_INFO("manifest parsed, but no image fetched\n");
return;
}
#endif #endif
if (res == 0) { if (res == 0) {
LOG_INFO("suit_coap: finalizing image flash\n"); LOG_INFO("suit_coap: finalizing image flash\n");