Commit 1de9f703 authored by Brendan Moran's avatar Brendan Moran
Browse files

Remove Suitloader files

parent 08bac153
# suitloader
# pull-cbor
Demonstration bootloader to be used with SUIT manifests as described in [draft-ietf-suit-manifest](https://datatracker.ietf.org/doc/draft-ietf-suit-manifest/). This bootloader is derived from [mbed-bootloader](https://github.com/ARMmbed/mbed-bootloader).
This is a CBOR library optimised for very constrained devices:
* it allocates no memory.
* it compiles to under 512 bytes.
* it includes (type only) schema validation.
## Build instructions
This parser does not extract to Document Object Model. Instead, it has three possible operations for each CBOR element it encounters:
1. Install `mbed-cli` https://github.com/ARMmbed/mbed-cli
1. Run `mbed deploy` to pull in dependencies
1. Compile by running `mbed compile -t GCC_ARM -m NRF52840_DK --profile release`
1. recurse into a container object and continue parsing
2. invoke a handler function
3. store a reference to the object at a specified pointer
The "schema" used by the parser is 8 bytes per element, which is substantially less than the code required to validate the types in a CBOR DOM or without a schema.
// ----------------------------------------------------------------------------
// Copyright 2016-2017 ARM Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------
#include "bootloader_common.h"
/* buffer used in storage operations */
uint8_t buffer_array[BUFFER_SIZE];
/* variable for exposing the most recent event */
uint32_t event_callback = CLEAR_EVENT;
/* lookup table for printing hexadecimal values */
const char hexTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
#if DEVICE_SERIAL && SHOW_SERIAL_OUTPUT
#include "hal/serial_api.h"
static serial_t uart = { 0 };
/* module variable for keeping track of initialization */
static bool not_initialized = true;
/**
* @brief Initialization serial port if needed.
*.
*/
static void init_serial()
{
if (not_initialized)
{
not_initialized = false;
serial_init(&uart, STDIO_UART_TX, STDIO_UART_RX);
#if MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE
serial_baud(&uart, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE);
#endif
}
}
/**
* @brief Function that directly outputs to serial port in blocking mode.
*
* @param string outputed to serial port.
*/
void boot_debug(const char *s)
{
init_serial();
while(*s) {
serial_putc(&uart, *s);
s++;
}
}
#else
/**
* @brief Fake function for boot debug.
*
* @param unused.
*/
void boot_debug(const char *s)
{
(void)s;
}
#endif // DEVICE_SERIAL && SHOW_SERIAL_OUTPUT
/**
* @brief Event handler for UCP callbacks.
*
* @param event Event
*/
void arm_ucp_event_handler(uint32_t event)
{
event_callback = event;
}
// ----------------------------------------------------------------------------
// Copyright 2016-2017 ARM Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------
#ifndef BOOTLOADER_COMMON_H
#define BOOTLOADER_COMMON_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SIZEOF_SHA256 (256/8)
#ifndef BUFFER_SIZE
#define BUFFER_SIZE (16 * 1024)
#endif
#define CLEAR_EVENT 0xFFFFFFFF
enum {
RESULT_SUCCESS,
RESULT_ERROR,
RESULT_EMPTY
};
extern uint8_t buffer_array[BUFFER_SIZE];
extern uint32_t event_callback;
extern const char hexTable[16];
void arm_ucp_event_handler(uint32_t event);
void boot_debug(const char *s);
#define MBED_BOOTLOADER_ASSERT(condition, ...) { \
if (!(condition)) { \
boot_debug("[ERR ] ASSERT\r\n"); \
/* coverity[no_escape] */ \
while (1) __WFI(); \
} \
}
#ifdef __cplusplus
}
#endif
#endif // BOOTLOADER_COMMON_H
// ----------------------------------------------------------------------------
// Copyright 2016-2017 ARM Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------
#ifndef MBEDTLS_CUSTOM_CONFIG_H
#define MBEDTLS_CUSTOM_CONFIG_H
/* System support */
#define MBEDTLS_HAVE_ASM
#define MBEDTLS_SHA256_SMALLER
#define MBEDTLS_CIPHER_MODE_CTR
#undef MBEDTLS_SHA512_C
#undef MBEDTLS_MD5_C
#undef MBEDTLS_MD4_C
#undef MBEDTLS_SHA1_C
// Remove RSA, save 20KB at total
#undef MBEDTLS_RSA_C
#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
// Remove error messages, save 10KB of ROM
#undef MBEDTLS_ERROR_C
// Remove selftesting and save 11KB of ROM
#undef MBEDTLS_SELF_TEST
// Reduces ROM size by 30 kB
#undef MBEDTLS_ERROR_STRERROR_DUMMY
#undef MBEDTLS_VERSION_FEATURES
#undef MBEDTLS_DEBUG_C
#include "mbedtls/check_config.h"
#endif /* MBEDTLS_CUSTOM_CONFIG_H */
// ----------------------------------------------------------------------------
// Copyright 2016-2017 ARM Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------
#ifndef __BOOTLOADER_PLATFORM_H__
#define __BOOTLOADER_PLATFORM_H__
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
bool existsErrorMessageLeadingToReboot(void);
const char *errorMessageLeadingToReboot(void);
void forwardControlToApplication(void);
#ifdef __cplusplus
}
#endif
#endif /*#ifndef __BOOTLOADER_PLATFORM_H__*/
// ----------------------------------------------------------------------------
// Copyright 2020 ARM Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
#include "mbed.h"
#include "bootloader_platform.h"
#include "bootloader_common.h"
#include "mbed_application.h"
#include "suit_bootloader.h"
const uint8_t vendor_id[16] = {
0xfa, 0x6b, 0x4a, 0x53, 0xd5, 0xad, 0x5f, 0xdf,
0xbe, 0x9d, 0xe6, 0x63, 0xe4, 0xd4, 0x1f, 0xfe
};
const uint8_t class_id[16] = {
0x14, 0x92, 0xaf, 0x14, 0x25, 0x69, 0x5e, 0x48,
0xbf, 0x42, 0x9b, 0x2d, 0x51, 0xf2, 0xab, 0x45
};
const uint8_t public_key[] = {
0x84, 0x96, 0x81, 0x1a, 0xae, 0x0b, 0xaa, 0xab,
0xd2, 0x61, 0x57, 0x18, 0x9e, 0xec, 0xda, 0x26,
0xbe, 0xaa, 0x8b, 0xf1, 0x1b, 0x6f, 0x3f, 0xe6,
0xe2, 0xb5, 0x65, 0x9c, 0x85, 0xdb, 0xc0, 0xad,
0x3b, 0x1f, 0x2a, 0x4b, 0x6c, 0x09, 0x81, 0x31,
0xc0, 0xa3, 0x6d, 0xac, 0xd1, 0xd7, 0x8b, 0xd3,
0x81, 0xdc, 0xdf, 0xb0, 0x9c, 0x05, 0x2d, 0xb3,
0x39, 0x91, 0xdb, 0x73, 0x38, 0xb4, 0xa8, 0x96,
};
const size_t public_key_size = sizeof(public_key);
const entrypoint_t entrypoints[] = {
{
SUIT_BOOTLOADER_SLOT_A_OFFSET + SUIT_BOOTLOADER_HEADER_SIZE,
SUIT_BOOTLOADER_SLOT_A_OFFSET
},
{
SUIT_BOOTLOADER_SLOT_B_OFFSET + SUIT_BOOTLOADER_HEADER_SIZE,
SUIT_BOOTLOADER_SLOT_B_OFFSET
}
};
const size_t n_entrypoints = ARRAY_SIZE(entrypoints);
int main(void)
{
/*************************************************************************/
/* Print bootloader information */
/*************************************************************************/
boot_debug("\r\n"
" __----'''----__\r\n"
" / ``--._.--'' \\ \r\n"
" _..---`-._ / \\ _.-'---.._ \r\n"
".' \\ `-./\\_/\\.-' / '.\r\n"
"| \\ / \\ / |\r\n"
"| \\ | | / . |\r\n"
"| \\ | | / /_\\ |\r\n"
"| \\ | | / |\r\n"
"| \\ | | / |\r\n"
"| SUIT \\| |/ LOADER |\r\n"
"| \\ / |\r\n"
"| \\ / |\r\n"
"| ' |\r\n"
"\r\n");
#if MBED_CONF_MBED_TRACE_ENABLE
mbed_trace_init();
mbed_trace_print_function_set(boot_debug);
#endif // MBED_CONF_MBED_TRACE_ENABLE
#if MBED_CONF_MBED_BOOTLOADER_STARTUP_DELAY
ThisThread::sleep_for(MBED_CONF_MBED_BOOTLOADER_STARTUP_DELAY);
#endif // MBED_CONF_MBED_BOOTLOADER_STARTUP_DELAY
/*************************************************************************/
/* Choose and execute a SUIT manifest */
/*************************************************************************/
int rc = suit_bootloader();
boot_debug("Failed to jump to application!\r\n");
return -1;
}
// ----------------------------------------------------------------------------
// Copyright 2020 ARM Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------
#include "suit_parser.h"
#include "suit_bootloader.h"
#include "mbedtls/sha256.h" /* SHA-256 only */
// #include "mbedtls/md.h" /* generic interface */
#include "uecc/uECC.h"
#include "mbed_application.h"
#include <stdio.h>
#include <string.h>
size_t bl_slot_index;
int suit_platform_do_run() {
int rc = -1;
if (bl_slot_index < n_entrypoints) {
rc = 0;
mbed_start_application((uintptr_t)entrypoints[bl_slot_index].app_offset);
}
return rc;
}
int suit_platform_get_image_ref(
const uint8_t *component_id,
const uint8_t **image
) {
if (bl_slot_index >= n_entrypoints) {
return -1;
}
*image = (const uint8_t *)((uintptr_t)entrypoints[bl_slot_index].app_offset);
return 0;
}
void compute_sha256(uint8_t *hash, const uint8_t *msg, size_t msg_len) {
mbedtls_sha256_context ctx;
mbedtls_sha256_init (&ctx);
mbedtls_sha256_starts_ret (&ctx, 0);
mbedtls_sha256_update_ret(&ctx, msg, msg_len);
mbedtls_sha256_finish_ret(&ctx, hash);
mbedtls_sha256_free(&ctx);
}
int suit_platform_verify_image(
const uint8_t *component_id,
int digest_type,
const uint8_t* expected_digest,
size_t image_size
) {
if (bl_slot_index >= n_entrypoints) {
return -1;
}
const uint8_t *image = (const uint8_t *)((uintptr_t)entrypoints[bl_slot_index].app_offset);
uint8_t hash[32];
compute_sha256(hash, image, image_size);
// no secret information in this hash, so memcmp is fine
return memcmp(hash, expected_digest, sizeof(hash));
}
int suit_platform_verify_sha256(
const uint8_t *expected_digest,
const uint8_t *data,
size_t data_len)
{
uint8_t hash[32];
compute_sha256(hash, data, data_len);
if (0==memcmp(hash, expected_digest, sizeof(hash))) {
return CBOR_ERR_NONE;
}
else {
RETURN_ERROR( SUIT_ERROR_DIGEST_MISMATCH);
}
}
int suit_platform_verify_digest(int alg, const uint8_t *exp, size_t exp_len, const uint8_t *data, size_t data_len)
{
switch (alg) {
// TODO: expected digest length.
case SUIT_DIGEST_TYPE_SHA256:
return suit_platform_verify_sha256(exp, data, data_len);
}
RETURN_ERROR(SUIT_ERROR_DIGEST_MISMATCH);
}
int ES256_verify(
const uint8_t *msg, size_t msg_len,
const uint8_t *sig, size_t sig_len,
const uint8_t *pub, size_t pub_len)
{
//TODO: SHA
uint8_t hash[32] = {0};
compute_sha256(hash, msg, msg_len);
if (uECC_verify(pub, hash, sig)) {
return CBOR_ERR_NONE;
}
else {
RETURN_ERROR(SUIT_ERR_SIG);
}
}
int COSEAuthVerify(
const uint8_t *msg, size_t msg_len,
const uint8_t *sig, size_t sig_len,
const uint8_t *kid, size_t kid_len,
int alg)
{
int rc;
//TODO: Lookup public key by key-id
switch (alg) {
case COSE_ES256:
rc = ES256_verify(
msg, msg_len,
sig, sig_len,
public_key, public_key_size);
break;
default:
SET_ERROR(rc, CBOR_ERR_UNIMPLEMENTED);
break;
}
return rc;
}
int suit_bootloader() {
int rc = 1;
size_t max_seq_idx = 0;
uint64_t max_seq = -1;
uint8_t ok = 0;
while (!ok && max_seq) {
uint64_t new_max_seq = 0;
ok = 0;
for (bl_slot_index = 0; bl_slot_index < n_entrypoints; bl_slot_index++) {
uint64_t seqnum;
rc = suit_get_seq(
(const uint8_t *)entrypoints[bl_slot_index].manifest,
SUIT_BOOTLOADER_HEADER_SIZE,
&seqnum);
if (rc == CBOR_ERR_NONE && seqnum < max_seq && seqnum > new_max_seq) {
new_max_seq = seqnum;
max_seq_idx = bl_slot_index;
ok = 1;
}
}
if (ok) {
bl_slot_index = max_seq_idx;
rc = suit_do_process_manifest(
(const uint8_t *)entrypoints[bl_slot_index].manifest,
SUIT_BOOTLOADER_HEADER_SIZE);
if (rc != CBOR_ERR_NONE) {
ok = 0;
}
}
max_seq = new_max_seq;
}
return rc;
}
// ----------------------------------------------------------------------------
// Copyright 2020 ARM Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------
#ifndef _BOOTLOADER_H_
#define _BOOTLOADER_H_
#include <stddef.h>
#include <stdint.h>
#define MANIFEST_MAX_SIZE 1024
#ifdef __cplusplus
extern "C" {
#endif
typedef struct entrypoint_s {
const uintptr_t app_offset;
const uintptr_t manifest;
} entrypoint_t;
extern const uint8_t public_key[];
extern const size_t public_key_size;
extern const uint8_t class_id[16];
extern const uint8_t vendor_id[16];
extern const entrypoint_t entrypoints [];
extern const size_t n_entrypoints;
int suit_bootloader();
#ifdef __cplusplus
} // extern "C"
#endif
#endif // _BOOTLOADER_H_
Copyright (c) 2014, Kenneth MacKay
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED