168 lines
6.2 KiB
C
168 lines
6.2 KiB
C
#include "set_firmware.h"
|
|
|
|
#include <string.h>
|
|
|
|
size_t setp_fw_begin_encode(const setp_fw_begin_t *value, uint8_t *out, size_t capacity)
|
|
{
|
|
size_t total;
|
|
if ((value == NULL) || (out == NULL)
|
|
|| (value->block_size == 0U)
|
|
|| (value->block_size > SETP_MAX_PAYLOAD - SETP_FW_DATA_HEADER_SIZE)
|
|
|| ((value->signature_length != 0U) && (value->signature == NULL))) {
|
|
return 0U;
|
|
}
|
|
total = (size_t)SETP_FW_BEGIN_FIXED_SIZE + value->signature_length;
|
|
if ((total > SETP_MAX_PAYLOAD) || (capacity < total)
|
|
|| (((value->flags & SETP_FW_FLAG_SIGNED) != 0U)
|
|
&& (value->signature_length == 0U))) {
|
|
return 0U;
|
|
}
|
|
setp_put_u32(&out[0], value->image_size);
|
|
setp_put_u32(&out[4], value->image_crc32);
|
|
setp_put_u32(&out[8], value->image_version);
|
|
setp_put_u32(&out[12], value->base_address);
|
|
out[16] = value->slot;
|
|
out[17] = value->flags;
|
|
setp_put_u16(&out[18], value->block_size);
|
|
(void)memcpy(&out[20], value->sha256, SETP_SHA256_SIZE);
|
|
setp_put_u32(&out[52], value->signing_key_id);
|
|
setp_put_u16(&out[56], value->signature_length);
|
|
if (value->signature_length != 0U) {
|
|
(void)memcpy(&out[SETP_FW_BEGIN_FIXED_SIZE], value->signature,
|
|
value->signature_length);
|
|
}
|
|
return total;
|
|
}
|
|
|
|
bool setp_fw_begin_decode(const uint8_t *payload, uint16_t length, setp_fw_begin_t *out)
|
|
{
|
|
uint16_t signature_length;
|
|
if ((payload == NULL) || (out == NULL) || (length < SETP_FW_BEGIN_FIXED_SIZE)) {
|
|
return false;
|
|
}
|
|
out->image_size = setp_get_u32(&payload[0]);
|
|
out->image_crc32 = setp_get_u32(&payload[4]);
|
|
out->image_version = setp_get_u32(&payload[8]);
|
|
out->base_address = setp_get_u32(&payload[12]);
|
|
out->slot = payload[16];
|
|
out->flags = payload[17];
|
|
out->block_size = setp_get_u16(&payload[18]);
|
|
(void)memcpy(out->sha256, &payload[20], SETP_SHA256_SIZE);
|
|
out->signing_key_id = setp_get_u32(&payload[52]);
|
|
signature_length = setp_get_u16(&payload[56]);
|
|
if (length != SETP_FW_BEGIN_FIXED_SIZE + signature_length) {
|
|
return false;
|
|
}
|
|
out->signature_length = signature_length;
|
|
out->signature = signature_length != 0U ? &payload[SETP_FW_BEGIN_FIXED_SIZE] : NULL;
|
|
return (out->block_size != 0U)
|
|
&& (out->block_size <= SETP_MAX_PAYLOAD - SETP_FW_DATA_HEADER_SIZE)
|
|
&& (((out->flags & SETP_FW_FLAG_SIGNED) == 0U) || (signature_length != 0U));
|
|
}
|
|
|
|
size_t setp_fw_data_encode(uint32_t offset, uint16_t flags,
|
|
const uint8_t *data, uint16_t data_length,
|
|
uint8_t *out, size_t capacity)
|
|
{
|
|
size_t total = (size_t)SETP_FW_DATA_HEADER_SIZE + data_length;
|
|
if ((data == NULL) || (out == NULL) || (data_length == 0U)
|
|
|| (total > SETP_MAX_PAYLOAD) || (capacity < total)) {
|
|
return 0U;
|
|
}
|
|
setp_put_u32(&out[0], offset);
|
|
setp_put_u16(&out[4], data_length);
|
|
setp_put_u16(&out[6], flags);
|
|
setp_put_u32(&out[8], setp_crc32(data, data_length));
|
|
(void)memcpy(&out[SETP_FW_DATA_HEADER_SIZE], data, data_length);
|
|
return total;
|
|
}
|
|
|
|
bool setp_fw_data_decode(const uint8_t *payload, uint16_t length, setp_fw_data_t *out)
|
|
{
|
|
uint16_t data_length;
|
|
if ((payload == NULL) || (out == NULL) || (length < SETP_FW_DATA_HEADER_SIZE)) {
|
|
return false;
|
|
}
|
|
data_length = setp_get_u16(&payload[4]);
|
|
if ((data_length == 0U) || (length != SETP_FW_DATA_HEADER_SIZE + data_length)) {
|
|
return false;
|
|
}
|
|
out->offset = setp_get_u32(&payload[0]);
|
|
out->data_length = data_length;
|
|
out->flags = setp_get_u16(&payload[6]);
|
|
out->data_crc32 = setp_get_u32(&payload[8]);
|
|
out->data = &payload[SETP_FW_DATA_HEADER_SIZE];
|
|
return setp_crc32(out->data, out->data_length) == out->data_crc32;
|
|
}
|
|
|
|
size_t setp_fw_end_encode(const setp_fw_end_t *value, uint8_t *out, size_t capacity)
|
|
{
|
|
if ((value == NULL) || (out == NULL) || (capacity < SETP_FW_END_SIZE)) {
|
|
return 0U;
|
|
}
|
|
setp_put_u32(&out[0], value->image_size);
|
|
setp_put_u32(&out[4], value->image_crc32);
|
|
(void)memcpy(&out[8], value->sha256, SETP_SHA256_SIZE);
|
|
return SETP_FW_END_SIZE;
|
|
}
|
|
|
|
bool setp_fw_end_decode(const uint8_t *payload, uint16_t length, setp_fw_end_t *out)
|
|
{
|
|
if ((payload == NULL) || (out == NULL) || (length != SETP_FW_END_SIZE)) {
|
|
return false;
|
|
}
|
|
out->image_size = setp_get_u32(&payload[0]);
|
|
out->image_crc32 = setp_get_u32(&payload[4]);
|
|
(void)memcpy(out->sha256, &payload[8], SETP_SHA256_SIZE);
|
|
return true;
|
|
}
|
|
|
|
size_t setp_fw_status_encode(const setp_fw_status_t *value, uint8_t *out, size_t capacity)
|
|
{
|
|
if ((value == NULL) || (out == NULL) || (capacity < SETP_FW_STATUS_SIZE)) {
|
|
return 0U;
|
|
}
|
|
out[0] = value->state;
|
|
out[1] = value->active_slot;
|
|
setp_put_u16(&out[2], value->max_block_size);
|
|
setp_put_u32(&out[4], value->next_offset);
|
|
setp_put_u32(&out[8], value->image_size);
|
|
setp_put_u16(&out[12], value->last_error);
|
|
setp_put_u16(&out[14], value->flags);
|
|
return SETP_FW_STATUS_SIZE;
|
|
}
|
|
|
|
bool setp_fw_status_decode(const uint8_t *payload, uint16_t length, setp_fw_status_t *out)
|
|
{
|
|
if ((payload == NULL) || (out == NULL) || (length != SETP_FW_STATUS_SIZE)) {
|
|
return false;
|
|
}
|
|
out->state = payload[0];
|
|
out->active_slot = payload[1];
|
|
out->max_block_size = setp_get_u16(&payload[2]);
|
|
out->next_offset = setp_get_u32(&payload[4]);
|
|
out->image_size = setp_get_u32(&payload[8]);
|
|
out->last_error = setp_get_u16(&payload[12]);
|
|
out->flags = setp_get_u16(&payload[14]);
|
|
return true;
|
|
}
|
|
|
|
size_t setp_fw_manifest_encode(const setp_fw_begin_t *value,
|
|
uint8_t *out, size_t capacity)
|
|
{
|
|
static const uint8_t prefix[8] = {
|
|
'S', 'E', 'T', 'P', 'F', 'W', '2', 0U
|
|
};
|
|
if ((value == NULL) || (out == NULL) || (capacity < SETP_FW_MANIFEST_SIZE)) {
|
|
return 0U;
|
|
}
|
|
(void)memcpy(out, prefix, sizeof(prefix));
|
|
setp_put_u32(&out[8], value->image_size);
|
|
setp_put_u32(&out[12], value->image_crc32);
|
|
setp_put_u32(&out[16], value->image_version);
|
|
setp_put_u32(&out[20], value->base_address);
|
|
out[24] = value->slot;
|
|
(void)memcpy(&out[25], value->sha256, SETP_SHA256_SIZE);
|
|
return SETP_FW_MANIFEST_SIZE;
|
|
}
|