1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

suit/transport/mock: Use common storage backend

This commit is contained in:
Koen Zandberg 2020-09-28 23:14:16 +02:00
parent edeffdcd54
commit b72d510690
No known key found for this signature in database
GPG Key ID: 0895A893E6D2985B
3 changed files with 94 additions and 70 deletions

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2020 Koen Zandberg
* 2020 Inria
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup sys_suit_transport_mock SUIT secure firmware OTA mock transport
* @ingroup sys_suit
* @brief SUIT firmware mock transport
*
* @{
*
* @brief Mock transport backend definitions for SUIT manifests
* @author Koen Zandberg <koen@bergzand.net>
*
* The mock transport is a noop transport. Payloads are preloaded in flash and
* provided as an array of @ref suit_transport_mock_payload_t to the module.
*
* Both the array of payloads named `payloads` and the size with name
* `num_payloads` must be provided.
*/
#ifndef SUIT_TRANSPORT_MOCK_H
#define SUIT_TRANSPORT_MOCK_H
#include "suit.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Mock payload.
*/
typedef struct {
const uint8_t *buf; /**< Ptr to the memory space containing the payload */
size_t len; /**< Length of the payload in bytes */
} suit_transport_mock_payload_t;
/**
* @brief 'fetch' a payload
*
* The payload fetched from the payloads array is indicated by the @ref
* suit_manifest_t::component_current member
*
* @param[in] manifest suit manifest context
*
* @returns SUIT_OK if valid
* @returns negative otherwise
*/
int suit_transport_mock_fetch(const suit_manifest_t *manifest);
#ifdef __cplusplus
}
#endif
#endif /* SUIT_TRANSPORT_MOCK_H */
/** @} */

View File

@ -47,9 +47,9 @@ static int _get_component_size(suit_manifest_t *manifest,
uint32_t *img_size) uint32_t *img_size)
{ {
nanocbor_value_t param_size; nanocbor_value_t param_size;
if ((suit_param_ref_to_cbor(manifest, &comp->param_size, &param_size) == 0) || if ((suit_param_ref_to_cbor(manifest, &comp->param_size, &param_size) == 0)
(nanocbor_get_uint32(&param_size, img_size) < 0)) { || (nanocbor_get_uint32(&param_size, img_size) < 0)) { return
return SUIT_ERR_INVALID_MANIFEST; SUIT_ERR_INVALID_MANIFEST;
} }
return SUIT_OK; return SUIT_OK;
} }
@ -201,8 +201,7 @@ static int _dtv_run_seq_cond(suit_manifest_t *manifest,
(void)key; (void)key;
LOG_DEBUG("Starting conditional sequence handler\n"); LOG_DEBUG("Starting conditional sequence handler\n");
return suit_handle_manifest_structure_bstr(manifest, it, return suit_handle_manifest_structure_bstr(manifest, it,
suit_command_sequence_handlers, suit_command_sequence_handlers, suit_command_sequence_handlers_len);
suit_command_sequence_handlers_len);
} }
static int _dtv_try_each(suit_manifest_t *manifest, static int _dtv_try_each(suit_manifest_t *manifest,
@ -223,8 +222,8 @@ static int _dtv_try_each(suit_manifest_t *manifest,
/* `_container` should be CBOR _bstr wrapped according to the spec, but /* `_container` should be CBOR _bstr wrapped according to the spec, but
* it is not */ * it is not */
res = suit_handle_manifest_structure_bstr(manifest, &_container, res = suit_handle_manifest_structure_bstr(manifest, &_container,
suit_command_sequence_handlers, suit_command_sequence_handlers,
suit_command_sequence_handlers_len); suit_command_sequence_handlers_len);
nanocbor_skip(&container); nanocbor_skip(&container);
@ -366,7 +365,7 @@ static int _dtv_fetch(suit_manifest_t *manifest, int key,
#endif #endif
#ifdef MODULE_SUIT_TRANSPORT_MOCK #ifdef MODULE_SUIT_TRANSPORT_MOCK
else if (strncmp(manifest->urlbuf, "test://", 7) == 0) { else if (strncmp(manifest->urlbuf, "test://", 7) == 0) {
res = SUIT_OK; res = suit_transport_mock_fetch(manifest);
} }
#endif #endif
else { else {
@ -379,7 +378,7 @@ static int _dtv_fetch(suit_manifest_t *manifest, int key,
if (res) { if (res) {
suit_component_set_flag(comp, SUIT_COMPONENT_STATE_FETCH_FAILED); suit_component_set_flag(comp, SUIT_COMPONENT_STATE_FETCH_FAILED);
/* TODO: The leftover data from a failed fetch should be purged. It /* TODO: The leftover data from a failed fetch should be purged. It
* could contain potential malicous data from an attacker */ * could contain potential malicious data from an attacker */
LOG_INFO("image download failed with code %i\n", res); LOG_INFO("image download failed with code %i\n", res);
return res; return res;
} }
@ -388,7 +387,8 @@ static int _dtv_fetch(suit_manifest_t *manifest, int key,
return SUIT_OK; return SUIT_OK;
} }
static int _get_digest(nanocbor_value_t *bstr, const uint8_t **digest, size_t *digest_len) static int _get_digest(nanocbor_value_t *bstr, const uint8_t **digest, size_t
*digest_len)
{ {
/* Bstr is a byte string with a cbor array containing the type and the /* Bstr is a byte string with a cbor array containing the type and the
* digest */ * digest */
@ -407,7 +407,8 @@ static int _get_digest(nanocbor_value_t *bstr, const uint8_t **digest, size_t *d
return nanocbor_get_bstr(&arr_it, digest, digest_len); return nanocbor_get_bstr(&arr_it, digest, digest_len);
} }
static int _validate_payload(suit_component_t *component, const uint8_t *digest, size_t payload_size) static int _validate_payload(suit_component_t *component, const uint8_t *digest,
size_t payload_size)
{ {
uint8_t payload_digest[SHA256_DIGEST_LENGTH]; uint8_t payload_digest[SHA256_DIGEST_LENGTH];
suit_storage_t *storage = component->storage_backend; suit_storage_t *storage = component->storage_backend;
@ -446,7 +447,6 @@ static int _validate_payload(suit_component_t *component, const uint8_t *digest,
SUIT_OK : SUIT_ERR_DIGEST_MISMATCH; SUIT_OK : SUIT_ERR_DIGEST_MISMATCH;
} }
static int _dtv_verify_image_match(suit_manifest_t *manifest, int key, static int _dtv_verify_image_match(suit_manifest_t *manifest, int key,
nanocbor_value_t *_it) nanocbor_value_t *_it)
{ {
@ -463,7 +463,8 @@ static int _dtv_verify_image_match(suit_manifest_t *manifest, int key,
/* Only check the component if it is fetched, but not failed */ /* Only check the component if it is fetched, but not failed */
if (!suit_component_check_flag(comp, SUIT_COMPONENT_STATE_FETCHED) || if (!suit_component_check_flag(comp, SUIT_COMPONENT_STATE_FETCHED) ||
suit_component_check_flag(comp, SUIT_COMPONENT_STATE_FETCH_FAILED)) { suit_component_check_flag(comp,
SUIT_COMPONENT_STATE_FETCH_FAILED)) {
LOG_ERROR("Fetch failed, or nothing fetched, nothing to check: %u\n", LOG_ERROR("Fetch failed, or nothing fetched, nothing to check: %u\n",
comp->state); comp->state);
return SUIT_ERR_INVALID_MANIFEST; return SUIT_ERR_INVALID_MANIFEST;
@ -513,4 +514,5 @@ const suit_manifest_handler_t suit_command_sequence_handlers[] = {
}; };
/* end{code-style-ignore} */ /* end{code-style-ignore} */
const size_t suit_command_sequence_handlers_len = ARRAY_SIZE(suit_command_sequence_handlers); const size_t suit_command_sequence_handlers_len =
ARRAY_SIZE(suit_command_sequence_handlers);

View File

@ -11,71 +11,32 @@
#include <stdbool.h> #include <stdbool.h>
#include "kernel_defines.h" #include "kernel_defines.h"
#include "cpu_conf.h" #include "log.h"
#include "riotboot/flashwrite.h" #include "suit.h"
#include "riotboot/hdr.h" #include "suit/storage.h"
#include "suit/transport/mock.h"
#define SLOT0_OFFSET 0x1000 /* Must be defined by the test */
#define SLOT1_OFFSET 0x2000 extern const suit_transport_mock_payload_t payloads[];
extern const size_t num_payloads;
static riotboot_hdr_t _riotboot_slots[] = { static const suit_component_t *_get_component(const suit_manifest_t *manifest)
{ .magic_number = RIOTBOOT_MAGIC,
.version = 1,
.start_addr=0x100000,
},
{ .magic_number = RIOTBOOT_MAGIC,
.version = 2,
.start_addr=0x200000,
},
};
const riotboot_hdr_t * const riotboot_slots[] = {
&_riotboot_slots[0],
&_riotboot_slots[1],
};
const unsigned riotboot_slot_numof = ARRAY_SIZE(riotboot_slots);
static int _current_slot;
int riotboot_slot_current(void)
{ {
return _current_slot; assert(manifest->component_current < CONFIG_SUIT_COMPONENT_MAX);
return &manifest->components[manifest->component_current];
} }
int riotboot_slot_other(void) int suit_transport_mock_fetch(const suit_manifest_t *manifest)
{ {
return (_current_slot == 0) ? 1 : 0; size_t file = manifest->component_current;
} const suit_component_t *comp = _get_component(manifest);
const riotboot_hdr_t *riotboot_slot_get_hdr(unsigned slot) assert(file < num_payloads);
{
assert(slot < riotboot_slot_numof);
return riotboot_slots[slot]; LOG_INFO("Mock writing payload %d\n", (unsigned)file);
}
size_t riotboot_slot_offset(unsigned slot) suit_storage_write(comp->storage_backend, manifest, payloads[file].buf, 0,
{ payloads[file].len);
return (slot == 0) ? SLOT0_OFFSET : SLOT1_OFFSET;
}
int riotboot_flashwrite_init_raw(riotboot_flashwrite_t *state, int target_slot,
size_t offset)
{
(void)state;
(void)target_slot;
(void)offset;
puts("riotboot_flashwrite_init_raw() empty mock");
return 0;
}
int riotboot_flashwrite_verify_sha256(const uint8_t *sha256_digest,
size_t img_size, int target_slot)
{
(void)sha256_digest;
(void)img_size;
(void)target_slot;
return 0; return 0;
} }