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