Initial commit

Initial commit.
This commit is contained in:
kntran1
2026-03-23 14:40:39 -05:00
parent e84b2b4166
commit 4e2a5258a5
872 changed files with 165227 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2019 Linaro Limited
*
* 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 H_BOOTUTIL_BENCH_H__
#define H_BOOTUTIL_BENCH_H__
#include "ignore.h"
#ifdef MCUBOOT_USE_BENCH
/* The platform-specific benchmark code should define a
* `bench_state_t` type that holds the information needed for the
* benchmark. This is generally something small, such as an integer
* holding the state. This should also define plat_bench_start and
* plat_bench_end, which likely have to be macros so that log messages
* come from the right place in the code. */
#include <platform-bench.h>
/*
* These are simple barrier-type benchmarks. If a platform has
* benchmarks that are enabled, calling `boot_bench_start()` before a
* block of code and `boot_bench_stop()` after that block of code will
* present this information in some manner (usually through logging).
* The details of what is measured and how it is printed are specific
* to the platform and the implementation. A pointer to the
* platform-specific state should be passed in.
*/
#define boot_bench_start(_state) do { \
plat_bench_start(_state); \
} while (0)
#define boot_bench_stop(_state) do { \
plat_bench_stop(_state); \
} while (0)
#else /* not MCUBOOT_USE_BENCH */
/* The type needs to take space. As long as it remains unused, the C
* compiler should eliminate this value entirely. */
typedef int bench_state_t;
/* Without benchmarking enabled, these are just empty. */
#define boot_bench_start(_state) do { \
IGNORE(_state); \
} while(0)
#define boot_bench_stop(_state) do { \
IGNORE(_state); \
} while(0)
#endif /* not MCUBOOT_USE_BENCH */
#endif /* not H_BOOTUTIL_BENCH_H__ */

View File

@@ -0,0 +1,181 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* Original license:
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
* @file
* @brief Hooks definition implementation API
*
* This file contains API interface definition for hooks which can be
* implemented to overide or to amend some of MCUboot's native routines.
*/
#ifndef H_BOOTUTIL_HOOKS
#define H_BOOTUTIL_HOOKS
#ifdef MCUBOOT_IMAGE_ACCESS_HOOKS
#define BOOT_HOOK_CALL(f, ret_default, ...) f(__VA_ARGS__)
#define BOOT_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, ...) \
do { \
FIH_CALL(f, fih_rc, __VA_ARGS__); \
} while(0);
#else
#define BOOT_HOOK_CALL(f, ret_default, ...) ret_default
#define BOOT_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, ...) \
do { \
fih_rc = fih_ret_default; \
} while(0);
#endif
/** Hook for provide image header data.
*
* This Hook may be used to overide image header read implementation or doing
* a custom action before.
*
* @param img_index the index of the image pair
* @param slot slot number
* @param img_head image header structure to be populated
*
* @retval 0: header was read/populated, skip direct header data read
* BOOT_HOOK_REGULAR: follow the normal execution path,
* otherwise an error-code value.
*/
int boot_read_image_header_hook(int img_index, int slot,
struct image_header *img_head);
/** Hook for Validate image hash/signature
*
* This Hook may be used to overide image validation procedure or doing
* a custom action before.
*
* @param img_index the index of the image pair
* @param slot slot number
*
* @retval FIH_SUCCESS: image is valid, skip direct validation
* FIH_FAILURE: image is invalid, skip direct validation
* FIH_BOOT_HOOK_REGULAR: follow the normal execution path.
*/
fih_ret boot_image_check_hook(int img_index, int slot);
/** Hook for implement image update
*
* This hook is for for implementing an alternative mechanism of image update or
* doing a custom action before.
*
* @param img_index the index of the image pair
* @param img_head the image header of the secondary image
* @param area the flash area of the secondary image.
*
* @retval 0: update was done, skip performing the update
* BOOT_HOOK_REGULAR: follow the normal execution path,
* otherwise an error-code value.
*/
int boot_perform_update_hook(int img_index, struct image_header *img_head,
const struct flash_area *area);
/** Hook for implement image's post copying action
*
* This hook is for implement action which might be done right after image was
* copied to the primary slot. This hook is called in MCUBOOT_OVERWRITE_ONLY
* mode only.
*
* @param img_index the index of the image pair
* @param area the flash area of the primary image.
* @param size size of copied image.
*
* @retval 0: success, mcuboot will follow normal code execution flow after
* execution of this call.
* non-zero: an error, mcuboot will return from
* boot_copy_image() with error.
* Update will be undone so might be resume on the next boot.
*/
int boot_copy_region_post_hook(int img_index, const struct flash_area *area,
size_t size);
/** Hook for implement image's post recovery upload action
*
* This hook is for implement action which might be done right after image was
* copied to the primary slot. This hook is called in serial recovery upload
* operation.
*
* @param img_index the index of the image pair
* @param area the flash area of the primary image.
* @param size size of copied image.
*
* @retval 0: success, mcuboot will follow normal code execution flow after
* execution of this call.
* non-zero: an error, will be transferred as part of comand response
* as "rc" entry.
*/
int boot_serial_uploaded_hook(int img_index, const struct flash_area *area,
size_t size);
/** Hook for implement the image's slot installation status fetch operation for
* the MGMT custom command.
*
* The image's slot installation status is custom property. It's detailed
* definition depends on user implementation. It is only defined that the status
* will be set to 0 if this hook not provides another value.
*
* @param img_index the index of the image pair
* @param slot slot number
* @param img_install_stat the image installation status to be populated
*
* @retval 0: the installaton status was fetched successfully,
* BOOT_HOOK_REGULAR: follow the normal execution path, status will be
* set to 0
* otherwise an error-code value. Error-code is ignored, but it is up to
* the implementation to reflect this error in img_install_stat.
*/
int boot_img_install_stat_hook(int image_index, int slot,
int *img_install_stat);
/** Hook will be invoked when boot_serial requests device reset.
* The hook may be used to prevent device reset.
*
* @param force set to true when request tries to force reset.
*
* @retval 0 when reset should be performed;
* BOOT_RESET_REQUEST_HOOK_BUSY when some processing is still in
* progress;
* BOOT_RESET_REQUEST_HOOK_TIMEOUT internal process timed out;
* BOOT_RESET_REQUEST_HOOK_CHECK_FAILED internal code failed to
* obtian status;
* BOOT_RESET_REQUEST_HOOK_INTERNAL_ERROR unspecified internal
* error while checking status.
*/
int boot_reset_request_hook(bool force);
#define BOOT_RESET_REQUEST_HOOK_BUSY 1
#define BOOT_RESET_REQUEST_HOOK_TIMEOUT 2
#define BOOT_RESET_REQUEST_HOOK_CHECK_FAILED 3
#define BOOT_RESET_REQUEST_HOOK_INTERNAL_ERROR 4
#endif /*H_BOOTUTIL_HOOKS*/

View File

@@ -0,0 +1,52 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* Original license:
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
* @file
* @brief Hooks definition implementation API
*
* This file contains API interface definition for hooks which can be
* implemented for overide some of MCUboot's native routines.
*/
#ifndef H_BOOTUTIL_PUBLIC_HOOKS
#define H_BOOTUTIL_PUBLIC_HOOKS
#include "bootutil/boot_hooks.h"
/** Hook for provide primary image swap state.
*
* @param img_index the index of the image pair
* @param state image swap state structure to be populated
*
* @retval 0: header was read/populated
* FIH_FAILURE: image is invalid,
* BOOT_HOOK_REGULAR if hook not implemented for the image-slot,
* othervise an error-code value.
*/
int boot_read_swap_state_primary_slot_hook(int image_index,
struct boot_swap_state *state);
#endif /*H_BOOTUTIL_PUBLIC_HOOKS*/

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2018-2021 Arm Limited
*
* 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 __BOOT_RECORD_H__
#define __BOOT_RECORD_H__
#include <stdint.h>
#include <stddef.h>
#include "bootutil/image.h"
#include "bootutil/bootutil.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Error codes for using the shared memory area. */
enum shared_memory_status {
SHARED_MEMORY_OK = 0,
SHARED_MEMORY_OVERFLOW,
SHARED_MEMORY_OVERWRITE,
SHARED_MEMORY_GEN_ERROR,
SHARED_MEMORY_WRITE_ERROR,
SHARED_MEMORY_READ_ERROR,
};
/**
* @brief Add a data item to the shared data area between bootloader and
* runtime SW
*
* @param[in] major_type TLV major type, identify consumer
* @param[in] minor_type TLV minor type, identify TLV type
* @param[in] size length of added data
* @param[in] data pointer to data
*
* @return 0 on success; nonzero on failure.
*/
int boot_add_data_to_shared_area(uint8_t major_type,
uint16_t minor_type,
size_t size,
const uint8_t *data);
/**
* Add an image's all boot status information to the shared memory area
* between the bootloader and runtime SW.
*
* @param[in] sw_module Identifier of the SW component.
* @param[in] hdr Pointer to the image header stored in RAM.
* @param[in] fap Pointer to the flash area where image is stored.
*
* @return 0 on success; nonzero on failure.
*/
int boot_save_boot_status(uint8_t sw_module,
const struct image_header *hdr,
const struct flash_area *fap);
/**
* Add application specific data to the shared memory area between the
* bootloader and runtime SW.
*
* @param[in] hdr Pointer to the image header stored in RAM.
* @param[in] fap Pointer to the flash area where image is stored.
* @param[in] slot The currently active slot being booted.
* @param[in] max_app_sizes The maximum sizes of images that can be loaded.
*
* @return 0 on success; nonzero on failure.
*/
int boot_save_shared_data(const struct image_header *hdr,
const struct flash_area *fap,
const uint8_t active_slot,
const struct image_max_size *max_app_sizes);
#ifdef __cplusplus
}
#endif
#endif /* __BOOT_RECORD_H__ */

View File

@@ -0,0 +1,188 @@
/*
* Copyright (c) 2018-2020 Arm Limited
* Copyright (c) 2020 Linaro Limited
*
* 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 __BOOT_STATUS_H__
#define __BOOT_STATUS_H__
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* The shared data between boot loader and runtime SW is TLV encoded. The
* shared data is stored in a well known location in memory and this is a
* contract between boot loader and runtime SW.
*
* The structure of shared data must be the following:
* - At the beginning there must be a header: struct shared_data_tlv_header
* This contains a magic number and a size field which covers the entire
* size of the shared data area including this header.
* - After the header there come the entries which are composed from an entry
* header structure: struct shared_data_tlv_entry and the data. In the entry
* header is a type field (tly_type) which identify the consumer of the
* entry in the runtime SW and specify the subtype of that data item. There
* is a size field (tlv_len) which covers the size of the the data. After
* this structure comes the actual data.
*
* - Arbitrary number and size of data entry can be in the shared memory area.
*
* This table gives of overview about the tlv_type field in the entry header.
* The tlv_type always composed from a major and minor number. Major number
* identifies the addressee in runtime SW, who should process the data entry.
* Minor number used to encode more info about the data entry. The actual
* definition of minor number could change per major number.
*
* In case of boot status data, which can be processed by an attestation
* service the minor number is split further to two part: sw_module and claim.
* The sw_module identifies the SW component in the system which the data item
* belongs to and the claim part identifies the exact type of the data.
*
* |---------------------------------------|
* | tlv_type (16) |
* |---------------------------------------|
* | tlv_major(4)| tlv_minor(12) |
* |---------------------------------------|
* | MAJOR_IAS | sw_module(6) | claim(6) |
* |---------------------------------------|
*/
/* General macros to handle TLV type */
#define MAJOR_MASK 0xF /* 4 bit */
#define MAJOR_POS 12 /* 12 bit */
#define MINOR_MASK 0xFFF /* 12 bit */
#define SET_TLV_TYPE(major, minor) \
(((uint16_t)((major) & MAJOR_MASK) << MAJOR_POS) \
| ((minor) & MINOR_MASK))
#define GET_MAJOR(tlv_type) ((uint16_t)(tlv_type) >> MAJOR_POS)
#define GET_MINOR(tlv_type) ((tlv_type) & MINOR_MASK)
/* Magic value which marks the beginning of shared data area in memory */
#define SHARED_DATA_TLV_INFO_MAGIC 0x2016
/* Initial attestation specific macros */
/**
* Major numbers (4 bit) to identify the
* consumer of shared data in runtime SW.
*/
#define TLV_MAJOR_IAS 0x1
#define TLV_MAJOR_BLINFO 0x2
/* Initial attestation: Claim per SW components / SW modules */
/* Bits: 0-2 */
#define SW_VERSION 0x00
#define SW_SIGNER_ID 0x01
/* Reserved 0x02 */
#define SW_TYPE 0x03
/* Bits: 3-5 */
#define SW_MEASURE_VALUE 0x08
#define SW_MEASURE_TYPE 0x09
#define SW_BOOT_RECORD 0x3F
#define MODULE_POS 6 /* 6 bit */
#define CLAIM_MASK 0x3F /* 6 bit */
#define MEASUREMENT_CLAIM_POS 3 /* 3 bit */
#define GET_IAS_MODULE(tlv_type) ((uint16_t)GET_MINOR(tlv_type) >> MODULE_POS)
#define GET_IAS_CLAIM(tlv_type) (GET_MINOR(tlv_type) & CLAIM_MASK)
#define SET_IAS_MINOR(sw_module, claim) \
(((uint16_t)(sw_module) << MODULE_POS) | (claim))
/* Bootloader information */
#define BLINFO_MODE 0x00
#define BLINFO_SIGNATURE_TYPE 0x01
#define BLINFO_RECOVERY 0x02
#define BLINFO_RUNNING_SLOT 0x03
#define BLINFO_BOOTLOADER_VERSION 0x04
#define BLINFO_MAX_APPLICATION_SIZE 0x05 /* Same as BLINFO_MAX_APPLICATION_SIZE_IMAGE_0, legacy name */
#define BLINFO_MAX_APPLICATION_SIZE_IMAGE_0 BLINFO_MAX_APPLICATION_SIZE
#define BLINFO_MAX_APPLICATION_SIZE_IMAGE_1 0x06
#define BLINFO_MAX_APPLICATION_SIZE_IMAGE_2 0x07
#define BLINFO_MAX_APPLICATION_SIZE_IMAGE_3 0x08
#define BLINFO_MAX_APPLICATION_SIZE_IMAGE_4 0x09
enum mcuboot_mode {
MCUBOOT_MODE_SINGLE_SLOT,
MCUBOOT_MODE_SWAP_USING_SCRATCH,
MCUBOOT_MODE_UPGRADE_ONLY,
MCUBOOT_MODE_SWAP_USING_MOVE,
MCUBOOT_MODE_DIRECT_XIP,
MCUBOOT_MODE_DIRECT_XIP_WITH_REVERT,
MCUBOOT_MODE_RAM_LOAD,
MCUBOOT_MODE_FIRMWARE_LOADER
};
enum mcuboot_signature_type {
MCUBOOT_SIGNATURE_TYPE_NONE,
MCUBOOT_SIGNATURE_TYPE_RSA,
MCUBOOT_SIGNATURE_TYPE_ECDSA_P256,
MCUBOOT_SIGNATURE_TYPE_ED25519
};
enum mcuboot_recovery_mode {
MCUBOOT_RECOVERY_MODE_NONE,
MCUBOOT_RECOVERY_MODE_SERIAL_RECOVERY,
MCUBOOT_RECOVERY_MODE_DFU,
};
/**
* Shared data TLV header. All fields in little endian.
*
* -----------------------------------
* | tlv_magic(16) | tlv_tot_len(16) |
* -----------------------------------
*/
struct shared_data_tlv_header {
uint16_t tlv_magic;
uint16_t tlv_tot_len; /* size of whole TLV area (including this header) */
};
#define SHARED_DATA_HEADER_SIZE sizeof(struct shared_data_tlv_header)
/**
* Shared data TLV entry header format. All fields in little endian.
*
* -------------------------------
* | tlv_type(16) | tlv_len(16) |
* -------------------------------
* | Raw data |
* -------------------------------
*/
struct shared_data_tlv_entry {
uint16_t tlv_type;
uint16_t tlv_len; /* TLV data length (not including this header). */
};
#define SHARED_DATA_ENTRY_HEADER_SIZE sizeof(struct shared_data_tlv_entry)
#define SHARED_DATA_ENTRY_SIZE(size) (size + SHARED_DATA_ENTRY_HEADER_SIZE)
/* Structure to store the boot data for the runtime SW. */
struct shared_boot_data {
struct shared_data_tlv_header header;
uint8_t data[];
};
#ifdef __cplusplus
}
#endif
#endif /* __BOOT_STATUS_H__ */

View File

@@ -0,0 +1,104 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2017-2019 Linaro LTD
* Copyright (c) 2016-2019 JUUL Labs
* Copyright (c) 2019-2021 Arm Limited
*
* Original license:
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_BOOTUTIL_
#define H_BOOTUTIL_
#include <inttypes.h>
#include "bootutil/fault_injection_hardening.h"
#include "bootutil/bootutil_public.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef MCUBOOT_IMAGE_NUMBER
#define BOOT_IMAGE_NUMBER MCUBOOT_IMAGE_NUMBER
#else
#define BOOT_IMAGE_NUMBER 1
#endif
_Static_assert(BOOT_IMAGE_NUMBER > 0, "Invalid value for BOOT_IMAGE_NUMBER");
struct image_header;
/**
* A response object provided by the boot loader code; indicates where to jump
* to execute the main image.
*/
struct boot_rsp {
/** A pointer to the header of the image to be executed. */
const struct image_header *br_hdr;
/**
* The flash offset of the image to execute. Indicates the position of
* the image header within its flash device.
*/
uint8_t br_flash_dev_id;
uint32_t br_image_off;
};
/* This is not actually used by mcuboot's code but can be used by apps
* when attempting to read/write a trailer.
*/
struct image_trailer {
uint8_t swap_type;
uint8_t pad1[BOOT_MAX_ALIGN - 1];
uint8_t copy_done;
uint8_t pad2[BOOT_MAX_ALIGN - 1];
uint8_t image_ok;
uint8_t pad3[BOOT_MAX_ALIGN - 1];
#if BOOT_MAX_ALIGN > BOOT_MAGIC_SZ
uint8_t pad4[BOOT_MAGIC_ALIGN_SIZE - BOOT_MAGIC_SZ];
#endif
uint8_t magic[BOOT_MAGIC_SZ];
};
struct image_max_size {
bool calculated;
uint32_t max_size;
};
/* you must have pre-allocated all the entries within this structure */
fih_ret boot_go(struct boot_rsp *rsp);
fih_ret boot_go_for_image_id(struct boot_rsp *rsp, uint32_t image_id);
struct boot_loader_state;
void boot_state_clear(struct boot_loader_state *state);
fih_ret context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp);
const struct image_max_size *boot_get_max_app_size(void);
#define SPLIT_GO_OK (0)
#define SPLIT_GO_NON_MATCHING (-1)
#define SPLIT_GO_ERR (-2)
fih_ret split_go(int loader_slot, int split_slot, void **entry);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,59 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2017 Linaro Limited
*
* 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 H_BOOTUTIL_LOG_H_
#define H_BOOTUTIL_LOG_H_
#include "ignore.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <mcuboot_config/mcuboot_config.h>
#ifdef MCUBOOT_HAVE_LOGGING
#include <mcuboot_config/mcuboot_logging.h>
#define BOOT_LOG_ERR(...) MCUBOOT_LOG_ERR(__VA_ARGS__)
#define BOOT_LOG_WRN(...) MCUBOOT_LOG_WRN(__VA_ARGS__)
#define BOOT_LOG_INF(...) MCUBOOT_LOG_INF(__VA_ARGS__)
#define BOOT_LOG_DBG(...) MCUBOOT_LOG_DBG(__VA_ARGS__)
#define BOOT_LOG_SIM(...) MCUBOOT_LOG_SIM(__VA_ARGS__)
#define BOOT_LOG_MODULE_DECLARE(module) MCUBOOT_LOG_MODULE_DECLARE(module)
#define BOOT_LOG_MODULE_REGISTER(module) MCUBOOT_LOG_MODULE_REGISTER(module)
#else
#define BOOT_LOG_ERR(...) IGNORE(__VA_ARGS__)
#define BOOT_LOG_WRN(...) IGNORE(__VA_ARGS__)
#define BOOT_LOG_INF(...) IGNORE(__VA_ARGS__)
#define BOOT_LOG_DBG(...) IGNORE(__VA_ARGS__)
#define BOOT_LOG_SIM(...) IGNORE(__VA_ARGS__)
#define BOOT_LOG_MODULE_DECLARE(module)
#define BOOT_LOG_MODULE_REGISTER(module)
#endif /* MCUBOOT_HAVE_LOGGING */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,316 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2017-2019 Linaro LTD
* Copyright (c) 2016-2019 JUUL Labs
* Copyright (c) 2019-2021 Arm Limited
* Copyright (c) 2020-2021 Nordic Semiconductor ASA
*
* Original license:
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
* @file
* @brief Public MCUBoot interface API
*
* This file contains API which can be combined with the application in order
* to interact with the MCUBoot bootloader. This API are shared code-base betwen
* MCUBoot and the application which controls DFU process.
*/
#ifndef H_BOOTUTIL_PUBLIC
#define H_BOOTUTIL_PUBLIC
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <flash_map_backend/flash_map_backend.h>
#include <mcuboot_config/mcuboot_config.h>
#include <bootutil/image.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ALIGN_UP
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#endif
#ifndef ALIGN_DOWN
#define ALIGN_DOWN(num, align) ((num) & ~((align) - 1))
#endif
/** Attempt to boot the contents of the primary slot. */
#define BOOT_SWAP_TYPE_NONE 1
/**
* Swap to the secondary slot.
* Absent a confirm command, revert back on next boot.
*/
#define BOOT_SWAP_TYPE_TEST 2
/**
* Swap to the secondary slot,
* and permanently switch to booting its contents.
*/
#define BOOT_SWAP_TYPE_PERM 3
/** Swap back to alternate slot. A confirm changes this state to NONE. */
#define BOOT_SWAP_TYPE_REVERT 4
/** Swap failed because image to be run is not valid */
#define BOOT_SWAP_TYPE_FAIL 5
/** Swapping encountered an unrecoverable error */
#define BOOT_SWAP_TYPE_PANIC 0xff
#define BOOT_MAGIC_SZ 16
#ifdef MCUBOOT_BOOT_MAX_ALIGN
#if defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_SCRATCH)
_Static_assert(MCUBOOT_BOOT_MAX_ALIGN >= 8 && MCUBOOT_BOOT_MAX_ALIGN <= 32,
"Unsupported value for MCUBOOT_BOOT_MAX_ALIGN for SWAP upgrade modes");
#endif
#define BOOT_MAX_ALIGN MCUBOOT_BOOT_MAX_ALIGN
#define BOOT_MAGIC_ALIGN_SIZE ALIGN_UP(BOOT_MAGIC_SZ, BOOT_MAX_ALIGN)
#else
#define BOOT_MAX_ALIGN 8
#define BOOT_MAGIC_ALIGN_SIZE BOOT_MAGIC_SZ
#endif
#define BOOT_MAGIC_GOOD 1
#define BOOT_MAGIC_BAD 2
#define BOOT_MAGIC_UNSET 3
#define BOOT_MAGIC_ANY 4 /* NOTE: control only, not dependent on sector */
#define BOOT_MAGIC_NOTGOOD 5 /* NOTE: control only, not dependent on sector */
/*
* NOTE: leave BOOT_FLAG_SET equal to one, this is written to flash!
*/
#define BOOT_FLAG_SET 1
#define BOOT_FLAG_BAD 2
#define BOOT_FLAG_UNSET 3
#define BOOT_FLAG_ANY 4 /* NOTE: control only, not dependent on sector */
#define BOOT_EFLASH 1
#define BOOT_EFILE 2
#define BOOT_EBADIMAGE 3
#define BOOT_EBADVECT 4
#define BOOT_EBADSTATUS 5
#define BOOT_ENOMEM 6
#define BOOT_EBADARGS 7
#define BOOT_EBADVERSION 8
#define BOOT_EFLASH_SEC 9
#define BOOT_HOOK_REGULAR 1
/*
* Extract the swap type and image number from image trailers's swap_info
* filed.
*/
#define BOOT_GET_SWAP_TYPE(swap_info) ((swap_info) & 0x0F)
#define BOOT_GET_IMAGE_NUM(swap_info) ((swap_info) >> 4)
/* Construct the swap_info field from swap type and image number */
#define BOOT_SET_SWAP_INFO(swap_info, image, type) { \
assert((image) < 0xF); \
assert((type) < 0xF); \
(swap_info) = (image) << 4 \
| (type); \
}
#ifdef MCUBOOT_HAVE_ASSERT_H
#include "mcuboot_config/mcuboot_assert.h"
#else
#include <assert.h>
#ifndef ASSERT
#define ASSERT assert
#endif
#endif
struct boot_swap_state {
uint8_t magic; /* One of the BOOT_MAGIC_[...] values. */
uint8_t swap_type; /* One of the BOOT_SWAP_TYPE_[...] values. */
uint8_t copy_done; /* One of the BOOT_FLAG_[...] values. */
uint8_t image_ok; /* One of the BOOT_FLAG_[...] values. */
uint8_t image_num; /* Boot status belongs to this image */
};
/**
* @brief Determines the action, if any, that mcuboot will take on a image pair.
*
* @param image_index Image pair index.
*
* @return a BOOT_SWAP_TYPE_[...] constant on success, negative errno code on
* fail.
*/
int boot_swap_type_multi(int image_index);
/**
* @brief Determines the action, if any, that mcuboot will take.
*
* Works the same as a boot_swap_type_multi(0) call;
*
* @return a BOOT_SWAP_TYPE_[...] constant on success, negative errno code on
* fail.
*/
int boot_swap_type(void);
/**
* Marks the image with the given index in the secondary slot as pending. On the
* next reboot, the system will perform a one-time boot of the the secondary
* slot image.
*
* @param image_index Image pair index.
*
* @param permanent Whether the image should be used permanently or
* only tested once:
* 0=run image once, then confirm or revert.
* 1=run image forever.
*
* @return 0 on success; nonzero on failure.
*/
int boot_set_pending_multi(int image_index, int permanent);
/**
* Marks the image with index 0 in the secondary slot as pending. On the next
* reboot, the system will perform a one-time boot of the the secondary slot
* image. Note that this API is kept for compatibility. The
* boot_set_pending_multi() API is recommended.
*
* @param permanent Whether the image should be used permanently or
* only tested once:
* 0=run image once, then confirm or revert.
* 1=run image forever.
*
* @return 0 on success; nonzero on failure.
*/
int boot_set_pending(int permanent);
/**
* Marks the image with the given index in the primary slot as confirmed. The
* system will continue booting into the image in the primary slot until told to
* boot from a different slot.
*
* @param image_index Image pair index.
*
* @return 0 on success; nonzero on failure.
*/
int boot_set_confirmed_multi(int image_index);
/**
* Marks the image with index 0 in the primary slot as confirmed. The system
* will continue booting into the image in the primary slot until told to boot
* from a different slot. Note that this API is kept for compatibility. The
* boot_set_confirmed_multi() API is recommended.
*
* @return 0 on success; nonzero on failure.
*/
int boot_set_confirmed(void);
/**
* @brief Get offset of the swap info field in the image trailer.
*
* @param fap Flash are for which offset is determined.
*
* @retval offset of the swap info field.
*/
uint32_t boot_swap_info_off(const struct flash_area *fap);
/**
* @brief Get value of image-ok flag of the image.
*
* If called from chin-loaded image the image-ok flag value can be used to check
* whether application itself is already confirmed.
*
* @param fap Flash area of the image.
* @param image_ok[out] image-ok value.
*
* @return 0 on success; nonzero on failure.
*/
int boot_read_image_ok(const struct flash_area *fap, uint8_t *image_ok);
/**
* @brief Read the image swap state
*
* @param flash_area_id id of flash partition from which state will be read;
* @param state pointer to structure for storing swap state.
*
* @return 0 on success; non-zero error code on failure;
*/
int
boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state);
/**
* @brief Read the image swap state
*
* @param fa pointer to flash_area object;
* @param state pointer to structure for storing swap state.
*
* @return 0 on success; non-zero error code on failure.
*/
int
boot_read_swap_state(const struct flash_area *fa,
struct boot_swap_state *state);
/**
* @brief Set next image application slot by flash area pointer
*
* @param fa pointer to flash_area representing image to set for next boot;
* @param active should be true if @fa points to currently running image
* slot, false otherwise;
* @param confirm confirms image; when @p active is true, this is considered
* true, regardless of passed value.
*
* It is users responsibility to identify whether @p fa provided as parameter
* is currently running/active image and provide proper value to @p active.
* Failing to do so may render device non-upgradeable.
*
* Note that in multi-image setup running/active application is the one
* that is currently being executed by any MCU core, from the pair of
* slots dedicated to that MCU core. As confirming application currently
* running on a given slot should be, preferably, done after functional
* tests prove application to function correctly, it may not be a good idea
* to cross-confirm running images.
* An application should only confirm slots designated to MCU core it is
* running on.
*
* @return 0 on success; non-zero error code on failure.
*/
int
boot_set_next(const struct flash_area *fa, bool active, bool confirm);
/**
* Attempts to load image header from flash; verifies flash header fields.
*
* @param[in] fa_p flash area pointer
* @param[out] hdr buffer for image header
*
* @return 0 on success, error code otherwise
*/
int
boot_image_load_header(const struct flash_area *fa_p,
struct image_header *hdr);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,35 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_BOOTUTIL_TEST_
#define H_BOOTUTIL_TEST_
#ifdef __cplusplus
extern "C" {
#endif
int boot_test_all(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2021-2023 Arm Limited
*
* 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 H_BOOTUTIL_CAPS_H_
#define H_BOOTUTIL_CAPS_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* The bootloader can be compile with different capabilities selected
* at compile time. This function provides runtime access to these
* capabilities. This is intended primarily for testing, although
* these will possibly be available at runtime to the application
* running within the bootloader.
*/
uint32_t bootutil_get_caps(void);
#define BOOTUTIL_CAP_RSA2048 (1<<0)
/* reserved (1<<1) */
#define BOOTUTIL_CAP_ECDSA_P256 (1<<2)
#define BOOTUTIL_CAP_SWAP_USING_SCRATCH (1<<3)
#define BOOTUTIL_CAP_OVERWRITE_UPGRADE (1<<4)
#define BOOTUTIL_CAP_ENC_RSA (1<<5)
#define BOOTUTIL_CAP_ENC_KW (1<<6)
#define BOOTUTIL_CAP_VALIDATE_PRIMARY_SLOT (1<<7)
#define BOOTUTIL_CAP_RSA3072 (1<<8)
#define BOOTUTIL_CAP_ED25519 (1<<9)
#define BOOTUTIL_CAP_ENC_EC256 (1<<10)
#define BOOTUTIL_CAP_SWAP_USING_MOVE (1<<11)
#define BOOTUTIL_CAP_DOWNGRADE_PREVENTION (1<<12)
#define BOOTUTIL_CAP_ENC_X25519 (1<<13)
#define BOOTUTIL_CAP_BOOTSTRAP (1<<14)
#define BOOTUTIL_CAP_AES256 (1<<15)
#define BOOTUTIL_CAP_RAM_LOAD (1<<16)
#define BOOTUTIL_CAP_DIRECT_XIP (1<<17)
#define BOOTUTIL_CAP_HW_ROLLBACK_PROT (1<<18)
#define BOOTUTIL_CAP_ECDSA_P384 (1<<19)
/*
* Query the number of images this bootloader is configured for. This
* is also primarily used for testing.
*/
uint32_t bootutil_get_num_images(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,158 @@
/*
* This module provides a thin abstraction over some of the crypto
* primitives to make it easier to swap out the used crypto library.
*
* At this point, there are two choices: MCUBOOT_USE_MBED_TLS, or
* MCUBOOT_USE_TINYCRYPT. It is a compile error there is not exactly
* one of these defined.
*/
#ifndef __BOOTUTIL_CRYPTO_AES_CTR_H_
#define __BOOTUTIL_CRYPTO_AES_CTR_H_
#include <string.h>
#include "mcuboot_config/mcuboot_config.h"
#if (defined(MCUBOOT_USE_MBED_TLS) + \
defined(MCUBOOT_USE_TINYCRYPT) + defined(MCUBOOT_USE_PSA_CRYPTO)) != 1
#error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT or PSA"
#endif
#if defined(MCUBOOT_USE_MBED_TLS)
#include <mbedtls/aes.h>
#include "bootutil/enc_key_public.h"
#define BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE BOOT_ENC_KEY_SIZE
#define BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE (16)
#endif /* MCUBOOT_USE_MBED_TLS */
#if defined(MCUBOOT_USE_TINYCRYPT)
#if defined(MCUBOOT_AES_256)
#error "Cannot use AES-256 for encryption with Tinycrypt library."
#endif
#include <string.h>
#include <tinycrypt/aes.h>
#include <tinycrypt/ctr_mode.h>
#include <tinycrypt/constants.h>
#define BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE TC_AES_KEY_SIZE
#define BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE TC_AES_BLOCK_SIZE
#endif /* MCUBOOT_USE_TINYCRYPT */
#if defined(MCUBOOT_USE_PSA_CRYPTO)
#include <psa/crypto.h>
#include "bootutil/enc_key_public.h"
#define BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE BOOT_ENC_KEY_SIZE
#define BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE (16)
#endif
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MCUBOOT_USE_PSA_CRYPTO)
typedef struct {
/* Fixme: This should not be, here, psa_key_id should be passed */
uint8_t key[BOOT_ENC_KEY_SIZE];
} bootutil_aes_ctr_context;
void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx);
static inline void bootutil_aes_ctr_drop(bootutil_aes_ctr_context *ctx)
{
memset(ctx, 0, sizeof(ctx));
}
static inline int bootutil_aes_ctr_set_key(bootutil_aes_ctr_context *ctx, const uint8_t *k)
{
memcpy(ctx->key, k, sizeof(ctx->key));
return 0;
}
int bootutil_aes_ctr_encrypt(bootutil_aes_ctr_context *ctx, uint8_t *counter,
const uint8_t *m, uint32_t mlen, size_t blk_off, uint8_t *c);
int bootutil_aes_ctr_decrypt(bootutil_aes_ctr_context *ctx, uint8_t *counter,
const uint8_t *c, uint32_t clen, size_t blk_off, uint8_t *m);
#endif
#if defined(MCUBOOT_USE_MBED_TLS)
typedef mbedtls_aes_context bootutil_aes_ctr_context;
static inline void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx)
{
(void)mbedtls_aes_init(ctx);
}
static inline void bootutil_aes_ctr_drop(bootutil_aes_ctr_context *ctx)
{
mbedtls_aes_free(ctx);
}
static inline int bootutil_aes_ctr_set_key(bootutil_aes_ctr_context *ctx, const uint8_t *k)
{
return mbedtls_aes_setkey_enc(ctx, k, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE * 8);
}
static inline int bootutil_aes_ctr_encrypt(bootutil_aes_ctr_context *ctx, uint8_t *counter, const uint8_t *m, uint32_t mlen, size_t blk_off, uint8_t *c)
{
uint8_t stream_block[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
return mbedtls_aes_crypt_ctr(ctx, mlen, &blk_off, counter, stream_block, m, c);
}
static inline int bootutil_aes_ctr_decrypt(bootutil_aes_ctr_context *ctx, uint8_t *counter, const uint8_t *c, uint32_t clen, size_t blk_off, uint8_t *m)
{
uint8_t stream_block[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
return mbedtls_aes_crypt_ctr(ctx, clen, &blk_off, counter, stream_block, c, m);
}
#endif /* MCUBOOT_USE_MBED_TLS */
#if defined(MCUBOOT_USE_TINYCRYPT)
typedef struct tc_aes_key_sched_struct bootutil_aes_ctr_context;
static inline void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx)
{
(void)ctx;
}
static inline void bootutil_aes_ctr_drop(bootutil_aes_ctr_context *ctx)
{
(void)ctx;
}
static inline int bootutil_aes_ctr_set_key(bootutil_aes_ctr_context *ctx, const uint8_t *k)
{
int rc;
rc = tc_aes128_set_encrypt_key(ctx, k);
if (rc != TC_CRYPTO_SUCCESS) {
return -1;
}
return 0;
}
static int _bootutil_aes_ctr_crypt(bootutil_aes_ctr_context *ctx, uint8_t *counter, const uint8_t *in, uint32_t inlen, uint32_t blk_off, uint8_t *out)
{
int rc;
rc = tc_ctr_mode(out, inlen, in, inlen, counter, &blk_off, ctx);
if (rc != TC_CRYPTO_SUCCESS) {
return -1;
}
return 0;
}
static inline int bootutil_aes_ctr_encrypt(bootutil_aes_ctr_context *ctx, uint8_t *counter, const uint8_t *m, uint32_t mlen, uint32_t blk_off, uint8_t *c)
{
return _bootutil_aes_ctr_crypt(ctx, counter, m, mlen, blk_off, c);
}
static inline int bootutil_aes_ctr_decrypt(bootutil_aes_ctr_context *ctx, uint8_t *counter, const uint8_t *c, uint32_t clen, uint32_t blk_off, uint8_t *m)
{
return _bootutil_aes_ctr_crypt(ctx, counter, c, clen, blk_off, m);
}
#endif /* MCUBOOT_USE_TINYCRYPT */
#ifdef __cplusplus
}
#endif
#endif /* __BOOTUTIL_CRYPTO_AES_CTR_H_ */

View File

@@ -0,0 +1,142 @@
/*
* This module provides a thin abstraction over some of the crypto
* primitives to make it easier to swap out the used crypto library.
*
* At this point, there are two choices: MCUBOOT_USE_MBED_TLS, or
* MCUBOOT_USE_TINYCRYPT. It is a compile error there is not exactly
* one of these defined.
*/
#ifndef __BOOTUTIL_CRYPTO_AES_KW_H_
#define __BOOTUTIL_CRYPTO_AES_KW_H_
#include "mcuboot_config/mcuboot_config.h"
#if (defined(MCUBOOT_USE_MBED_TLS) + \
defined(MCUBOOT_USE_TINYCRYPT)) != 1
#error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT"
#endif
#if defined(MCUBOOT_USE_MBED_TLS)
#include <mbedtls/aes.h>
#include <mbedtls/nist_kw.h>
#endif /* MCUBOOT_USE_MBED_TLS */
#if defined(MCUBOOT_USE_TINYCRYPT)
#if defined(MCUBOOT_AES_256)
#error "Cannot use AES-256 for encryption with Tinycrypt library."
#endif
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#endif /* MCUBOOT_USE_TINYCRYPT */
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MCUBOOT_USE_MBED_TLS)
typedef mbedtls_nist_kw_context bootutil_aes_kw_context;
static inline void bootutil_aes_kw_init(bootutil_aes_kw_context *ctx)
{
(void)mbedtls_nist_kw_init(ctx);
}
static inline void bootutil_aes_kw_drop(bootutil_aes_kw_context *ctx)
{
mbedtls_nist_kw_free(ctx);
}
static inline int bootutil_aes_kw_set_unwrap_key(bootutil_aes_kw_context *ctx, const uint8_t *k, uint32_t klen)
{
return mbedtls_nist_kw_setkey(ctx, MBEDTLS_CIPHER_ID_AES, k, klen * 8, 0);
}
static inline int bootutil_aes_kw_unwrap(bootutil_aes_kw_context *ctx, const uint8_t *wrapped_key, uint32_t wrapped_key_len, uint8_t *key, uint32_t key_len)
{
size_t olen;
return mbedtls_nist_kw_unwrap(ctx, MBEDTLS_KW_MODE_KW, wrapped_key, wrapped_key_len, key, &olen, key_len);
}
#endif /* MCUBOOT_USE_MBED_TLS */
#if defined(MCUBOOT_USE_TINYCRYPT)
typedef struct tc_aes_key_sched_struct bootutil_aes_kw_context;
static inline void bootutil_aes_kw_init(bootutil_aes_kw_context *ctx)
{
(void)ctx;
}
static inline void bootutil_aes_kw_drop(bootutil_aes_kw_context *ctx)
{
(void)ctx;
}
static inline int bootutil_aes_kw_set_unwrap_key(bootutil_aes_kw_context *ctx, const uint8_t *k, uint32_t klen)
{
int rc;
if (klen != 16) {
return -1;
}
rc = tc_aes128_set_decrypt_key(ctx, k);
if (rc != TC_CRYPTO_SUCCESS) {
return -1;
}
return 0;
}
/*
* Implements AES key unwrapping following RFC-3394 section 2.2.2, using
* tinycrypt for AES-128 decryption.
*/
static int bootutil_aes_kw_unwrap(bootutil_aes_kw_context *ctx, const uint8_t *wrapped_key, uint32_t wrapped_key_len, uint8_t *key, uint32_t key_len)
{
uint8_t A[8];
uint8_t B[16];
int8_t i, j, k;
if (wrapped_key_len != 24 || key_len != 16) {
return -1;
}
for (k = 0; k < 8; k++) {
A[k] = wrapped_key[k];
key[k] = wrapped_key[8 + k];
key[8 + k] = wrapped_key[16 + k];
}
for (j = 5; j >= 0; j--) {
for (i = 2; i > 0; i--) {
for (k = 0; k < 8; k++) {
B[k] = A[k];
B[8 + k] = key[((i-1) * 8) + k];
}
B[7] ^= 2 * j + i;
if (tc_aes_decrypt((uint8_t *)&B, (uint8_t *)&B, ctx) != TC_CRYPTO_SUCCESS) {
return -1;
}
for (k = 0; k < 8; k++) {
A[k] = B[k];
key[((i-1) * 8) + k] = B[8 + k];
}
}
}
for (i = 0, k = 0; i < 8; i++) {
k |= A[i] ^ 0xa6;
}
if (k) {
return -1;
}
return 0;
}
#endif /* MCUBOOT_USE_TINYCRYPT */
#ifdef __cplusplus
}
#endif
#endif /* __BOOTUTIL_CRYPTO_AES_KW_H_ */

View File

@@ -0,0 +1,29 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2021 Arm Limited
*/
#ifndef __BOOTUTIL_CRYPTO_COMMON_H__
#define __BOOTUTIL_CRYPTO_COMMON_H__
/* The check below can be performed even for those cases
* where MCUBOOT_USE_MBED_TLS has not been defined
*/
#include "mbedtls/version.h"
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
#define MBEDTLS_CONTEXT_MEMBER(X) MBEDTLS_PRIVATE(X)
#else
#define MBEDTLS_CONTEXT_MEMBER(X) X
#endif
/* Newer versions of Mbed TLS have removed the private accessor requirement for
* the ASN1 fields.
*/
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) && (MBEDTLS_VERSION_NUMBER < 0x03010000)
#define ASN1_CONTEXT_MEMBER(X) MBEDTLS_PRIVATE(X)
#else
#define ASN1_CONTEXT_MEMBER(X) X
#endif
#endif /* __BOOTUTIL_CRYPTO_COMMON_H__ */

View File

@@ -0,0 +1,154 @@
/*
* This module provides a thin abstraction over some of the crypto
* primitives to make it easier to swap out the used crypto library.
*
* At this point, there are two choices: MCUBOOT_USE_MBED_TLS, or
* MCUBOOT_USE_TINYCRYPT. It is a compile error there is not exactly
* one of these defined.
*/
#ifndef __BOOTUTIL_CRYPTO_ECDH_P256_H_
#define __BOOTUTIL_CRYPTO_ECDH_P256_H_
#include "mcuboot_config/mcuboot_config.h"
#if (defined(MCUBOOT_USE_MBED_TLS) + \
defined(MCUBOOT_USE_TINYCRYPT)) != 1
#error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT"
#endif
#if defined(MCUBOOT_USE_MBED_TLS)
#include <mbedtls/ecp.h>
#include <mbedtls/ecdh.h>
#define EC256_PUBK_LEN (65)
#endif /* MCUBOOT_USE_MBED_TLS */
#if defined(MCUBOOT_USE_TINYCRYPT)
#include <tinycrypt/ecc_dh.h>
#include <tinycrypt/constants.h>
#define BOOTUTIL_CRYPTO_ECDH_P256_HASH_SIZE (4 * 8)
#endif /* MCUBOOT_USE_TINYCRYPT */
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MCUBOOT_USE_TINYCRYPT)
typedef uintptr_t bootutil_ecdh_p256_context;
static inline void bootutil_ecdh_p256_init(bootutil_ecdh_p256_context *ctx)
{
(void)ctx;
}
static inline void bootutil_ecdh_p256_drop(bootutil_ecdh_p256_context *ctx)
{
(void)ctx;
}
static inline int bootutil_ecdh_p256_shared_secret(bootutil_ecdh_p256_context *ctx, const uint8_t *pk, const uint8_t *sk, uint8_t *z)
{
int rc;
(void)ctx;
if (pk[0] != 0x04) {
return -1;
}
rc = uECC_valid_public_key(&pk[1], uECC_secp256r1());
if (rc != 0) {
return -1;
}
rc = uECC_shared_secret(&pk[1], sk, z, uECC_secp256r1());
if (rc != TC_CRYPTO_SUCCESS) {
return -1;
}
return 0;
}
#endif /* MCUBOOT_USE_TINYCRYPT */
#if defined(MCUBOOT_USE_MBED_TLS)
#define NUM_ECC_BYTES 32
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
static int fake_rng(void *p_rng, unsigned char *output, size_t len);
#endif
typedef struct bootutil_ecdh_p256_context {
mbedtls_ecp_group grp;
mbedtls_ecp_point P;
mbedtls_mpi z;
mbedtls_mpi d;
} bootutil_ecdh_p256_context;
static inline void bootutil_ecdh_p256_init(bootutil_ecdh_p256_context *ctx)
{
mbedtls_mpi_init(&ctx->z);
mbedtls_mpi_init(&ctx->d);
mbedtls_ecp_group_init(&ctx->grp);
mbedtls_ecp_point_init(&ctx->P);
if (mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1) != 0) {
mbedtls_ecp_group_free(&ctx->grp);
mbedtls_ecp_point_free(&ctx->P);
}
}
static inline void bootutil_ecdh_p256_drop(bootutil_ecdh_p256_context *ctx)
{
mbedtls_mpi_free(&ctx->d);
mbedtls_mpi_free(&ctx->z);
mbedtls_ecp_group_free(&ctx->grp);
mbedtls_ecp_point_free(&ctx->P);
}
static inline int bootutil_ecdh_p256_shared_secret(bootutil_ecdh_p256_context *ctx, const uint8_t *pk, const uint8_t *sk, uint8_t *z)
{
int rc;
rc = mbedtls_ecp_point_read_binary(&ctx->grp,
&ctx->P,
pk,
EC256_PUBK_LEN);
if (rc != 0) {
mbedtls_ecp_group_free(&ctx->grp);
mbedtls_ecp_point_free(&ctx->P);
return -1;
}
rc = mbedtls_ecp_check_pubkey(&ctx->grp, &ctx->P);
if (rc != 0) {
mbedtls_ecp_group_free(&ctx->grp);
mbedtls_ecp_point_free(&ctx->P);
return -1;
}
mbedtls_mpi_read_binary(&ctx->d, sk, NUM_ECC_BYTES);
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
rc = mbedtls_ecdh_compute_shared(&ctx->grp,
&ctx->z,
&ctx->P,
&ctx->d,
fake_rng,
NULL);
#else
rc = mbedtls_ecdh_compute_shared(&ctx->grp,
&ctx->z,
&ctx->P,
&ctx->d,
NULL,
NULL);
#endif
mbedtls_mpi_write_binary(&ctx->z, z, NUM_ECC_BYTES);
return rc;
}
#endif /* MCUBOOT_USE_MBED_TLS */
#ifdef __cplusplus
}
#endif
#endif /* __BOOTUTIL_CRYPTO_ECDH_P256_H_ */

View File

@@ -0,0 +1,57 @@
/*
* This module provides a thin abstraction over some of the crypto
* primitives to make it easier to swap out the used crypto library.
*
* At this point, there are two choices: MCUBOOT_USE_MBED_TLS, or
* MCUBOOT_USE_TINYCRYPT. It is a compile error there is not exactly
* one of these defined.
*/
#ifndef __BOOTUTIL_CRYPTO_ECDH_X25519_H_
#define __BOOTUTIL_CRYPTO_ECDH_X25519_H_
#include "mcuboot_config/mcuboot_config.h"
#if (defined(MCUBOOT_USE_MBED_TLS) + \
defined(MCUBOOT_USE_TINYCRYPT)) != 1
#error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MCUBOOT_USE_TINYCRYPT) || defined(MCUBOOT_USE_MBED_TLS)
extern int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
const uint8_t peer_public_value[32]);
typedef uintptr_t bootutil_ecdh_x25519_context;
static inline void bootutil_ecdh_x25519_init(bootutil_ecdh_x25519_context *ctx)
{
(void)ctx;
}
static inline void bootutil_ecdh_x25519_drop(bootutil_ecdh_x25519_context *ctx)
{
(void)ctx;
}
static inline int bootutil_ecdh_x25519_shared_secret(bootutil_ecdh_x25519_context *ctx, const uint8_t *pk, const uint8_t *sk, uint8_t *z)
{
int rc;
(void)ctx;
rc = X25519(z, sk, pk);
if (rc != 0) {
return -1;
}
return 0;
}
#endif /* MCUBOOT_USE_TINYCRYPT */
#ifdef __cplusplus
}
#endif
#endif /* __BOOTUTIL_CRYPTO_ECDH_X25519_H_ */

View File

@@ -0,0 +1,672 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2023-2024 Arm Limited
*/
/*
* This module provides a thin abstraction over some of the crypto
* primitives to make it easier to swap out the used crypto library.
*
* At this point, the choices are: MCUBOOT_USE_TINYCRYPT, MCUBOOT_USE_CC310,
* MCUBOOT_USE_MBED_TLS, MCUBOOT_USE_PSA_CRYPTO. Note that support for
* MCUBOOT_USE_PSA_CRYPTO is still experimental and it might not support all
* the crypto abstractions that MCUBOOT_USE_MBED_TLS supports. For this
* reason, it's allowed to have both of them defined, and for crypto modules
* that support both abstractions, the MCUBOOT_USE_PSA_CRYPTO will take
* precedence.
*/
#ifndef __BOOTUTIL_CRYPTO_ECDSA_H_
#define __BOOTUTIL_CRYPTO_ECDSA_H_
#include <stdint.h>
#include "mcuboot_config/mcuboot_config.h"
#if defined(MCUBOOT_USE_PSA_CRYPTO) || defined(MCUBOOT_USE_MBED_TLS)
#define MCUBOOT_USE_PSA_OR_MBED_TLS
#endif /* MCUBOOT_USE_PSA_CRYPTO || MCUBOOT_USE_MBED_TLS */
#if defined(MCUBOOT_SIGN_EC384) && \
!defined(MCUBOOT_USE_PSA_CRYPTO)
#error "P384 requires PSA_CRYPTO to be defined"
#endif
#if (defined(MCUBOOT_USE_TINYCRYPT) + \
defined(MCUBOOT_USE_CC310) + \
defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \
defined(MCUBOOT_USE_PSA_OR_MBED_TLS)) != 1
#error "One crypto backend must be defined: either CC310/TINYCRYPT/MBED_TLS/PSA_CRYPTO"
#endif
#if defined(MCUBOOT_USE_TINYCRYPT)
#include <tinycrypt/ecc_dsa.h>
#include <tinycrypt/constants.h>
#endif /* MCUBOOT_USE_TINYCRYPT */
#if defined(MCUBOOT_USE_CC310)
#include <cc310_glue.h>
#endif /* MCUBOOT_USE_CC310 */
#if defined(MCUBOOT_USE_PSA_CRYPTO)
#include <psa/crypto.h>
#include <string.h>
#elif defined(MCUBOOT_USE_MBED_TLS)
#include <mbedtls/ecdsa.h>
/* Indicate to the caller that the verify function needs the raw ASN.1
* signature, not a decoded one. */
#define MCUBOOT_ECDSA_NEED_ASN1_SIG
#endif /* MCUBOOT_USE_MBED_TLS */
/*TODO: remove this after cypress port mbedtls to abstract crypto api */
#if defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_MBED_TLS)
#define NUM_ECC_BYTES (256 / 8)
#endif
/* Universal defines */
#define BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE (32)
#include "mbedtls/oid.h"
#include "mbedtls/asn1.h"
#include "bootutil/sign_key.h"
#include "common.h"
#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO)
#include <bl_crypto.h>
#define NUM_ECC_BYTES (256 / 8)
#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */
#ifdef __cplusplus
extern "C" {
#endif
#if (defined(MCUBOOT_USE_TINYCRYPT) || defined(MCUBOOT_USE_MBED_TLS) || \
defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO)) \
&& !defined(MCUBOOT_USE_PSA_CRYPTO)
/*
* Declaring these like this adds NULL termination.
*/
static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
/*
* Parse a public key. Helper function.
*/
static int bootutil_import_key(uint8_t **cp, uint8_t *end)
{
size_t len;
mbedtls_asn1_buf alg;
mbedtls_asn1_buf param;
if (mbedtls_asn1_get_tag(cp, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
return -1;
}
end = *cp + len;
/* ECParameters (RFC5480) */
if (mbedtls_asn1_get_alg(cp, end, &alg, &param)) {
return -2;
}
/* id-ecPublicKey (RFC5480) */
if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
return -3;
}
/* namedCurve (RFC5480) */
if (param.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 ||
memcmp(param.ASN1_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
return -4;
}
/* ECPoint (RFC5480) */
if (mbedtls_asn1_get_bitstring_null(cp, end, &len)) {
return -6;
}
if (*cp + len != end) {
return -7;
}
if (len != 2 * NUM_ECC_BYTES + 1) {
return -8;
}
return 0;
}
#endif /* (MCUBOOT_USE_TINYCRYPT || MCUBOOT_USE_MBED_TLS || MCUBOOT_USE_CC310) && !MCUBOOT_USE_PSA_CRYPTO */
/*
* cp points to ASN1 string containing an integer.
* Verify the tag, and that the length is 32 bytes. Helper function.
*/
static int bootutil_read_bigint(uint8_t i[NUM_ECC_BYTES], uint8_t **cp, uint8_t *end)
{
size_t len;
if (mbedtls_asn1_get_tag(cp, end, &len, MBEDTLS_ASN1_INTEGER)) {
return -3;
}
if (len >= NUM_ECC_BYTES) {
memcpy(i, *cp + len - NUM_ECC_BYTES, NUM_ECC_BYTES);
} else {
memset(i, 0, NUM_ECC_BYTES - len);
memcpy(i + NUM_ECC_BYTES - len, *cp, len);
}
*cp += len;
return 0;
}
/*
* Read in signature. Signature has r and s encoded as integers. Helper function.
*/
static int bootutil_decode_sig(uint8_t signature[NUM_ECC_BYTES * 2], uint8_t *cp, uint8_t *end)
{
int rc;
size_t len;
rc = mbedtls_asn1_get_tag(&cp, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
if (rc) {
return -1;
}
if (cp + len > end) {
return -2;
}
rc = bootutil_read_bigint(signature, &cp, end);
if (rc) {
return -3;
}
rc = bootutil_read_bigint(signature + NUM_ECC_BYTES, &cp, end);
if (rc) {
return -4;
}
return 0;
}
#if defined(MCUBOOT_USE_TINYCRYPT)
typedef uintptr_t bootutil_ecdsa_context;
static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx)
{
(void)ctx;
}
static inline void bootutil_ecdsa_drop(bootutil_ecdsa_context *ctx)
{
(void)ctx;
}
static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx,
uint8_t *pk, size_t pk_len,
uint8_t *hash, size_t hash_len,
uint8_t *sig, size_t sig_len)
{
int rc;
(void)ctx;
(void)pk_len;
(void)sig_len;
(void)hash_len;
uint8_t signature[2 * NUM_ECC_BYTES];
rc = bootutil_decode_sig(signature, sig, sig + sig_len);
if (rc) {
return -1;
}
/* Only support uncompressed keys. */
if (pk[0] != 0x04) {
return -1;
}
pk++;
rc = uECC_verify(pk, hash, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE, signature, uECC_secp256r1());
if (rc != TC_CRYPTO_SUCCESS) {
return -1;
}
return 0;
}
static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx,
uint8_t **cp,uint8_t *end)
{
(void)ctx;
return bootutil_import_key(cp, end);
}
#endif /* MCUBOOT_USE_TINYCRYPT */
#if defined(MCUBOOT_USE_CC310)
typedef uintptr_t bootutil_ecdsa_context;
static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx)
{
(void)ctx;
}
static inline void bootutil_ecdsa_drop(bootutil_ecdsa_context *ctx)
{
(void)ctx;
}
static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx,
uint8_t *pk, size_t pk_len,
uint8_t *hash, size_t hash_len,
uint8_t *sig, size_t sig_len)
{
(void)ctx;
(void)pk_len;
(void)hash_len;
uint8_t dsig[2 * NUM_ECC_BYTES];
if (bootutil_decode_sig(dsig, sig, sig + sig_len)) {
return -1;
}
/* Only support uncompressed keys. */
if (pk[0] != 0x04) {
return -1;
}
pk++;
return cc310_ecdsa_verify_secp256r1(hash, pk, dsig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE);
}
static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx,
uint8_t **cp,uint8_t *end)
{
(void)ctx;
return bootutil_import_key(cp, end);
}
#endif /* MCUBOOT_USE_CC310 */
#if defined(MCUBOOT_USE_PSA_CRYPTO)
typedef struct {
psa_key_id_t key_id;
size_t curve_byte_count;
psa_algorithm_t required_algorithm;
} bootutil_ecdsa_context;
/* ECDSA public key with format specified in RFC5280 et al. in ASN.1 syntax
*
* SEQUENCE {
* SEQUENCE {
* OBJECT idEcPublicKey
* OBJECT namedCurve
* }
* BIT STRING publicKey
* }
*
* ECDSA signature format specified in RFC3279 et al. in ASN.1 syntax
*
* SEQUENCE {
* INTEGER r
* INTEGER s
* }
*
*/
/* Offset in bytes from the start of the encoding to the length field
* of the innermost SEQUENCE in the ECDSA public key
*/
#define PUB_KEY_LEN_OFF (3)
/* Offset in bytes from the start of the publicKey encoding of the BIT STRING */
#define PUB_KEY_VAL_OFF (3)
/* Computes the pointer to the idEcPublicKey OID from the base of the encoding */
#define PUB_KEY_OID_OFFSET(p) (*p + PUB_KEY_LEN_OFF+1)
/* Computes the pointer to the namedCurve OID from the base of the encoding */
#define CURVE_TYPE_OID_OFFSET(p) PUB_KEY_OID_OFFSET(p) + sizeof(IdEcPublicKey)
/* This helper function gets a pointer to the bitstring associated to the publicKey
* as encoded per RFC 5280. This function assumes that the public key encoding is not
* bigger than 127 bytes (i.e. usually up until 384 bit curves)
*
* \param[in,out] p Double pointer to a buffer containing the RFC 5280 of the ECDSA public key.
* On output, the pointer is updated to point to the start of the public key
* in BIT STRING form.
* \param[out] size Pointer to a buffer containing the size of the public key extracted
*
*/
static inline void get_public_key_from_rfc5280_encoding(uint8_t **p, size_t *size)
{
uint8_t *key_start = (*p) + (PUB_KEY_LEN_OFF + 1 + (*p)[PUB_KEY_LEN_OFF] + PUB_KEY_VAL_OFF);
*p = key_start;
*size = key_start[-2]-1; /* -2 from PUB_KEY_VAL_OFF to get the length, -1 to remove the ASN.1 padding byte count */
}
/* This helper function parses a signature as specified in RFC3279 into a pair
* (r,s) of contiguous bytes
*
* \param[in] sig Pointer to a buffer containing the encoded signature
* \param[in] num_of_curve_bytes The required number of bytes for r and s
* \param[out] r_s_pair Buffer containing the (r,s) pair extracted. It's caller
* responsibility to ensure the buffer is big enough to
* hold the parsed (r,s) pair.
*/
static void parse_signature_from_rfc5480_encoding(const uint8_t *sig,
size_t num_of_curve_bytes,
uint8_t *r_s_pair)
{
const uint8_t *sig_ptr = NULL;
/* r or s can be greater than the expected size by one, due to the way
* ASN.1 encodes signed integers. If either r or s starts with a bit 1,
* a zero byte will be added in front of the encoding
*/
/* sig[0] == 0x30, sig[1] == <length>, sig[2] == 0x02 */
/* Move r in place */
size_t r_len = sig[3];
sig_ptr = &sig[4];
if (r_len >= num_of_curve_bytes) {
sig_ptr = sig_ptr + r_len - num_of_curve_bytes;
memcpy(&r_s_pair[0], sig_ptr, num_of_curve_bytes);
if(r_len % 2) {
r_len--;
}
} else {
/* For encodings that reduce the size of r or s in case of zeros */
memcpy(&r_s_pair[num_of_curve_bytes - r_len], sig_ptr, r_len);
}
/* Move s in place */
size_t s_len = sig_ptr[r_len+1]; /* + 1 to skip SEQUENCE */
sig_ptr = &sig_ptr[r_len+2];
if (s_len >= num_of_curve_bytes) {
sig_ptr = sig_ptr + s_len - num_of_curve_bytes;
memcpy(&r_s_pair[num_of_curve_bytes], sig_ptr, num_of_curve_bytes);
} else {
/* For encodings that reduce the size of r or s in case of zeros */
memcpy(&r_s_pair[2*num_of_curve_bytes - s_len], sig_ptr, s_len);
}
}
// OID id-ecPublicKey 1.2.840.10045.2.1.
static const uint8_t IdEcPublicKey[] = {0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01};
#if defined(MCUBOOT_SIGN_EC256)
// OID secp256r1 1.2.840.10045.3.1.7.
static const uint8_t Secp256r1[] = {0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
#endif /* MCUBOOT_SIGN_EC256 */
#if defined(MCUBOOT_SIGN_EC384)
// OID secp384r1 1.3.132.0.34
static const uint8_t Secp384r1[] = {0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22};
#endif /* MCUBOOT_SIGN_EC384 */
static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx)
{
#if !defined(MCUBOOT_BUILTIN_KEY)
ctx->key_id = PSA_KEY_ID_NULL;
ctx->curve_byte_count = 0;
ctx->required_algorithm = 0;
#else /* !MCUBOOT_BUILTIN_KEY */
/* The incoming key ID is equal to the image index. The key ID value must be
* shifted (by one in this case) because zero is reserved (PSA_KEY_ID_NULL)
* and considered invalid.
*/
ctx->key_id++; /* Make sure it is not equal to 0. */
#if defined(MCUBOOT_SIGN_EC256)
ctx->curve_byte_count = 32;
ctx->required_algorithm = PSA_ALG_SHA_256;
#endif /* MCUBOOT_SIGN_EC256 */
#if defined(MCUBOOT_SIGN_EC384)
ctx->curve_byte_count = 48;
ctx->required_algorithm = PSA_ALG_SHA_384;
#endif /* MCUBOOT_SIGN_EC384 */
#endif /* !MCUBOOT_BUILTIN_KEY */
}
static inline void bootutil_ecdsa_drop(bootutil_ecdsa_context *ctx)
{
if (ctx->key_id != PSA_KEY_ID_NULL) {
(void)psa_destroy_key(ctx->key_id);
}
}
#if !defined(MCUBOOT_BUILTIN_KEY)
/*
* Parse a ECDSA public key with format specified in RFC5280 et al.
*
* OID for icEcPublicKey is 1.2.840.10045.2.1
* OIDs for supported curves are as follows:
* secp256r1 (prime256v1): 1.2.840.10045.3.1.7
* secp384r1: 1.3.132.0.34
*/
static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx,
uint8_t **cp, uint8_t *end)
{
psa_key_attributes_t key_attributes = psa_key_attributes_init();
size_t key_size;
(void)end;
/* public key oid is valid */
if (memcmp(PUB_KEY_OID_OFFSET(cp), IdEcPublicKey, sizeof(IdEcPublicKey))) {
return (int)PSA_ERROR_INVALID_ARGUMENT;
}
#if defined(MCUBOOT_SIGN_EC256)
if (!memcmp(CURVE_TYPE_OID_OFFSET(cp), Secp256r1, sizeof(Secp256r1))) {
ctx->curve_byte_count = 32;
ctx->required_algorithm = PSA_ALG_SHA_256;
} else
#endif /* MCUBOOT_SIGN_EC256 */
#if defined(MCUBOOT_SIGN_EC384)
if (!memcmp(CURVE_TYPE_OID_OFFSET(cp), Secp384r1, sizeof(Secp384r1))) {
ctx->curve_byte_count = 48;
ctx->required_algorithm = PSA_ALG_SHA_384;
} else
#endif /* MCUBOOT_SIGN_EC384 */
{
return (int)PSA_ERROR_INVALID_ARGUMENT;
}
get_public_key_from_rfc5280_encoding(cp, &key_size);
/* Set attributes and import key */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(ctx->required_algorithm));
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
return (int)psa_import_key(&key_attributes, *cp, key_size, &ctx->key_id);
}
#endif /* !MCUBOOT_BUILTIN_KEY */
/* Verify the signature against the provided hash. The signature gets parsed from
* the encoding first, then PSA Crypto has a dedicated API for ECDSA verification
*/
static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx,
uint8_t *pk, size_t pk_len,
uint8_t *hash, size_t hlen,
uint8_t *sig, size_t slen)
{
(void)pk;
(void)pk_len;
(void)slen;
uint8_t reformatted_signature[96] = {0}; /* Enough for P-384 signature sizes */
parse_signature_from_rfc5480_encoding(sig, ctx->curve_byte_count,reformatted_signature);
return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm),
hash, hlen, reformatted_signature, 2*ctx->curve_byte_count);
}
#elif defined(MCUBOOT_USE_MBED_TLS)
typedef mbedtls_ecdsa_context bootutil_ecdsa_context;
static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx)
{
mbedtls_ecdsa_init(ctx);
}
static inline void bootutil_ecdsa_drop(bootutil_ecdsa_context *ctx)
{
mbedtls_ecdsa_free(ctx);
}
#ifdef CY_MBEDTLS_HW_ACCELERATION
/*
* Parse the public key used for signing.
*/
static int bootutil_parse_eckey(bootutil_ecdsa_context *ctx, uint8_t **p, uint8_t *end)
{
size_t len;
mbedtls_asn1_buf alg;
mbedtls_asn1_buf param;
if (mbedtls_asn1_get_tag(p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
return -1;
}
end = *p + len;
if (mbedtls_asn1_get_alg(p, end, &alg, &param)) {
return -2;
}
if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
return -3;
}
if (param.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1||
memcmp(param.ASN1_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
return -4;
}
if (mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1)) {
return -5;
}
if (mbedtls_asn1_get_bitstring_null(p, end, &len)) {
return -6;
}
if (*p + len != end) {
return -7;
}
if (mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q, *p, end - *p)) {
return -8;
}
if (mbedtls_ecp_check_pubkey(&ctx->grp, &ctx->Q)) {
return -9;
}
return 0;
}
static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx,
uint8_t *pk, size_t pk_len,
uint8_t *hash, size_t hash_len,
uint8_t *sig, size_t sig_len)
{
(void)pk;
(void)pk_len;
/*
* This is simplified, as the hash length is also 32 bytes.
*/
while (sig[sig_len - 1] == '\0') {
sig_len--;
}
return mbedtls_ecdsa_read_signature(&ctx, hash, hash_len, sig, sig_len);
}
#else /* CY_MBEDTLS_HW_ACCELERATION */
static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx,
uint8_t *pk, size_t pk_len,
uint8_t *hash, size_t hash_len,
uint8_t *sig, size_t sig_len)
{
int rc;
(void)sig;
(void)hash;
(void)hash_len;
rc = mbedtls_ecp_group_load(&ctx->MBEDTLS_CONTEXT_MEMBER(grp), MBEDTLS_ECP_DP_SECP256R1);
if (rc) {
return -1;
}
rc = mbedtls_ecp_point_read_binary(&ctx->MBEDTLS_CONTEXT_MEMBER(grp), &ctx->MBEDTLS_CONTEXT_MEMBER(Q), pk, pk_len);
if (rc) {
return -1;
}
rc = mbedtls_ecp_check_pubkey(&ctx->MBEDTLS_CONTEXT_MEMBER(grp), &ctx->MBEDTLS_CONTEXT_MEMBER(Q));
if (rc) {
return -1;
}
rc = mbedtls_ecdsa_read_signature(ctx, hash, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE,
sig, sig_len);
if (rc) {
return -1;
}
return 0;
}
#endif /* CY_MBEDTLS_HW_ACCELERATION */
static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx,
uint8_t **cp,uint8_t *end)
{
int rc;
#ifdef CY_MBEDTLS_HW_ACCELERATION
rc = bootutil_parse_eckey(&ctx, cp, end);
#else
(void)ctx;
rc = bootutil_import_key(cp, end);
#endif
return rc;
}
#endif /* MCUBOOT_USE_MBED_TLS */
#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO)
typedef uintptr_t bootutil_ecdsa_context;
static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx)
{
(void)ctx;
}
static inline void bootutil_ecdsa_drop(bootutil_ecdsa_context *ctx)
{
(void)ctx;
}
static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx,
uint8_t *pk, size_t pk_len,
uint8_t *hash, size_t hash_len,
uint8_t *sig, size_t sig_len)
{
(void)ctx;
(void)pk_len;
(void)hash_len;
uint8_t dsig[2 * NUM_ECC_BYTES];
if (bootutil_decode_sig(dsig, sig, sig + sig_len)) {
return -1;
}
/* Only support uncompressed keys. */
if (pk[0] != 0x04) {
return -1;
}
pk++;
return bl_secp256r1_validate(hash, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE, pk, dsig);
}
static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx,
uint8_t **cp,uint8_t *end)
{
(void)ctx;
return bootutil_import_key(cp, end);
}
#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */
#ifdef __cplusplus
}
#endif
#endif /* __BOOTUTIL_CRYPTO_ECDSA_H_ */

View File

@@ -0,0 +1,134 @@
/*
* This module provides a thin abstraction over some of the crypto
* primitives to make it easier to swap out the used crypto library.
*
* At this point, there are two choices: MCUBOOT_USE_MBED_TLS, or
* MCUBOOT_USE_TINYCRYPT. It is a compile error there is not exactly
* one of these defined.
*/
#ifndef __BOOTUTIL_CRYPTO_HMAC_SHA256_H_
#define __BOOTUTIL_CRYPTO_HMAC_SHA256_H_
#include "mcuboot_config/mcuboot_config.h"
#if (defined(MCUBOOT_USE_MBED_TLS) + \
defined(MCUBOOT_USE_TINYCRYPT)) != 1
#error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT"
#endif
#if defined(MCUBOOT_USE_MBED_TLS)
#include <stdint.h>
#include <stddef.h>
#include <mbedtls/cmac.h>
#include <mbedtls/md.h>
#endif /* MCUBOOT_USE_MBED_TLS */
#if defined(MCUBOOT_USE_TINYCRYPT)
#include <tinycrypt/sha256.h>
#include <tinycrypt/utils.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/hmac.h>
#endif /* MCUBOOT_USE_TINYCRYPT */
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MCUBOOT_USE_TINYCRYPT)
typedef struct tc_hmac_state_struct bootutil_hmac_sha256_context;
static inline void bootutil_hmac_sha256_init(bootutil_hmac_sha256_context *ctx)
{
(void)ctx;
}
static inline void bootutil_hmac_sha256_drop(bootutil_hmac_sha256_context *ctx)
{
(void)ctx;
}
static inline int bootutil_hmac_sha256_set_key(bootutil_hmac_sha256_context *ctx, const uint8_t *key, unsigned int key_size)
{
int rc;
rc = tc_hmac_set_key(ctx, key, key_size);
if (rc != TC_CRYPTO_SUCCESS) {
return -1;
}
rc = tc_hmac_init(ctx);
if (rc != TC_CRYPTO_SUCCESS) {
return -1;
}
return 0;
}
static inline int bootutil_hmac_sha256_update(bootutil_hmac_sha256_context *ctx, const void *data, unsigned int data_length)
{
int rc;
rc = tc_hmac_update(ctx, data, data_length);
if (rc != TC_CRYPTO_SUCCESS) {
return -1;
}
return 0;
}
static inline int bootutil_hmac_sha256_finish(bootutil_hmac_sha256_context *ctx, uint8_t *tag, unsigned int taglen)
{
int rc;
rc = tc_hmac_final(tag, taglen, ctx);
if (rc != TC_CRYPTO_SUCCESS) {
return -1;
}
return 0;
}
#endif /* MCUBOOT_USE_TINYCRYPT */
#if defined(MCUBOOT_USE_MBED_TLS)
/**
* The generic message-digest context.
*/
typedef mbedtls_md_context_t bootutil_hmac_sha256_context;
static inline void bootutil_hmac_sha256_init(bootutil_hmac_sha256_context *ctx)
{
mbedtls_md_init(ctx);
}
static inline void bootutil_hmac_sha256_drop(bootutil_hmac_sha256_context *ctx)
{
mbedtls_md_free(ctx);
}
static inline int bootutil_hmac_sha256_set_key(bootutil_hmac_sha256_context *ctx, const uint8_t *key, unsigned int key_size)
{
int rc;
rc = mbedtls_md_setup(ctx, mbedtls_md_info_from_string("SHA256"), 1);
if (rc != 0) {
return rc;
}
rc = mbedtls_md_hmac_starts(ctx, key, key_size);
return rc;
}
static inline int bootutil_hmac_sha256_update(bootutil_hmac_sha256_context *ctx, const void *data, unsigned int data_length)
{
return mbedtls_md_hmac_update(ctx, data, data_length);
}
static inline int bootutil_hmac_sha256_finish(bootutil_hmac_sha256_context *ctx, uint8_t *tag, unsigned int taglen)
{
(void)taglen;
/*
* HMAC the key and check that our received MAC matches the generated tag
*/
return mbedtls_md_hmac_finish(ctx, tag);
}
#endif /* MCUBOOT_USE_MBED_TLS */
#ifdef __cplusplus
}
#endif
#endif /* __BOOTUTIL_CRYPTO_HMAC_SHA256_H_ */

View File

@@ -0,0 +1,356 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2023 Arm Limited
*/
/*
* This module provides a thin abstraction over some of the crypto
* primitives to make it easier to swap out the used crypto library.
*
* At this point, the choices are: MCUBOOT_USE_MBED_TLS and
* MCUBOOT_USE_PSA_CRYPTO. Note that support for MCUBOOT_USE_PSA_CRYPTO is
* still experimental and it might not support all the crypto abstractions
* that MCUBOOT_USE_MBED_TLS supports. For this reason, it's allowed to have
* both of them defined, and for crypto modules that support both abstractions,
* the MCUBOOT_USE_PSA_CRYPTO will take precedence.
*/
/*
* Note: The source file that includes this header should either define one of the
* two options BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED or BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED
* This will make the signature functions or encryption functions visible without
* generating a "defined but not used" compiler warning
*/
#ifndef __BOOTUTIL_CRYPTO_RSA_H_
#define __BOOTUTIL_CRYPTO_RSA_H_
#include "mcuboot_config/mcuboot_config.h"
#if defined(MCUBOOT_USE_PSA_CRYPTO) || defined(MCUBOOT_USE_MBED_TLS)
#define MCUBOOT_USE_PSA_OR_MBED_TLS
#endif /* MCUBOOT_USE_PSA_CRYPTO || MCUBOOT_USE_MBED_TLS */
#if (defined(MCUBOOT_USE_PSA_OR_MBED_TLS)) != 1
#error "One crypto backend must be defined: either MBED_TLS/PSA_CRYPTO"
#endif
#if defined(MCUBOOT_USE_PSA_CRYPTO)
#include <psa/crypto.h>
#include "bootutil/enc_key_public.h"
#elif defined(MCUBOOT_USE_MBED_TLS)
#include "mbedtls/rsa.h"
#include "mbedtls/version.h"
#if defined(BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED)
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
#include "rsa_alt_helpers.h"
#else
#include "mbedtls/rsa_internal.h"
#endif
#endif /* BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED */
#include "mbedtls/asn1.h"
#include "bootutil/crypto/common.h"
#endif /* MCUBOOT_USE_MBED_TLS */
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MCUBOOT_USE_PSA_CRYPTO)
typedef struct {
psa_key_id_t key_id;
} bootutil_rsa_context;
static inline void bootutil_rsa_init(bootutil_rsa_context *ctx)
{
ctx->key_id = PSA_KEY_ID_NULL;
}
static inline void bootutil_rsa_drop(bootutil_rsa_context *ctx)
{
if (ctx->key_id != PSA_KEY_ID_NULL) {
(void)psa_destroy_key(ctx->key_id);
}
}
#if defined(BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED)
static int bootutil_rsa_oaep_decrypt(
bootutil_rsa_context *ctx,
size_t *olen,
const uint8_t *input,
uint8_t *output,
size_t output_max_len)
{
psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
/* Perform an additional defensive check to compare the modulus of the RSA
* key to the expected input of the decryption function, i.e. TLV_ENC_RSA_SZ
*/
psa_key_attributes_t key_attr = psa_key_attributes_init();
status = psa_get_key_attributes(ctx->key_id, &key_attr);
if (status != PSA_SUCCESS) {
return -1;
}
size_t input_size = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attr));
if (input_size != TLV_ENC_RSA_SZ) {
return -1;
}
status = psa_asymmetric_decrypt(ctx->key_id, PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256),
input, TLV_ENC_RSA_SZ, NULL, 0,
output, output_max_len, olen);
return (int)status;
}
/*
* Parse a RSA private key with format specified in RFC3447 A.1.2
*
* The key is meant to be used for OAEP decrypt hence algorithm and usage are hardcoded
*/
static int
bootutil_rsa_parse_private_key(bootutil_rsa_context *ctx, uint8_t **p, uint8_t *end)
{
psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
psa_key_attributes_t key_attributes = psa_key_attributes_init();
/* Set attributes and import key */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&key_attributes, PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256));
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
status = psa_import_key(&key_attributes, *p, (end - *p), &ctx->key_id);
return (int)status;
}
#endif /* BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED */
#if defined(BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED)
/*
* Parse a RSA public key with format specified in RFC3447 A.1.1
*
* The key is meant to be used for PSS signature verification hence algorithm and usage are hardcoded
*/
static int
bootutil_rsa_parse_public_key(bootutil_rsa_context *ctx, uint8_t **p, uint8_t *end)
{
psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
psa_key_attributes_t key_attributes = psa_key_attributes_init();
/* Set attributes and import key */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attributes, PSA_ALG_RSA_PSS(PSA_ALG_SHA_256));
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
status = psa_import_key(&key_attributes, *p, (end - *p), &ctx->key_id);
return (int)status;
}
/* Get the modulus (N) length in bytes */
static size_t bootutil_rsa_get_len(const bootutil_rsa_context *ctx)
{
psa_key_attributes_t key_attributes = psa_key_attributes_init();
psa_status_t status = psa_get_key_attributes(ctx->key_id, &key_attributes);
if (status != PSA_SUCCESS) {
return 0;
}
return PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attributes));
}
/* PSA Crypto has a dedicated API for RSASSA-PSS verification */
static inline int bootutil_rsassa_pss_verify(const bootutil_rsa_context *ctx,
uint8_t *hash, size_t hlen, uint8_t *sig, size_t slen)
{
return (int) psa_verify_hash(ctx->key_id, PSA_ALG_RSA_PSS(PSA_ALG_SHA_256),
hash, hlen, sig, slen);
}
#endif /* BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED */
#elif defined(MCUBOOT_USE_MBED_TLS)
typedef mbedtls_rsa_context bootutil_rsa_context;
static inline void bootutil_rsa_init(bootutil_rsa_context *ctx)
{
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
mbedtls_rsa_init(ctx);
mbedtls_rsa_set_padding(ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
#else
mbedtls_rsa_init(ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
#endif
}
static inline void bootutil_rsa_drop(bootutil_rsa_context *ctx)
{
mbedtls_rsa_free(ctx);
}
#if defined(BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED) && (MBEDTLS_VERSION_NUMBER >= 0x03000000)
static int fake_rng(void *p_rng, unsigned char *output, size_t len);
#endif /* BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED && MBEDTLS_VERSION_NUMBER >= 3.0 */
#if defined(BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED)
static inline int bootutil_rsa_oaep_decrypt(
bootutil_rsa_context *ctx,
size_t *olen,
const uint8_t *input,
uint8_t *output,
size_t output_max_len)
{
int rc = -1;
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
rc = mbedtls_rsa_rsaes_oaep_decrypt(ctx, fake_rng, NULL,
NULL, 0, olen, input, output, output_max_len);
#else
rc = mbedtls_rsa_rsaes_oaep_decrypt(ctx, NULL, NULL, MBEDTLS_RSA_PRIVATE,
NULL, 0, olen, input, output, output_max_len);
#endif
return rc;
}
/*
* Parse a RSA private key with format specified in RFC3447 A.1.2
*/
static int
bootutil_rsa_parse_private_key(bootutil_rsa_context *ctx, uint8_t **p, uint8_t *end)
{
size_t len;
if (mbedtls_asn1_get_tag(p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
return -1;
}
if (*p + len != end) {
return -2;
}
/* Non-optional fields. */
if ( /* version */
mbedtls_asn1_get_int(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(ver)) != 0 ||
/* public modulus */
mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N)) != 0 ||
/* public exponent */
mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E)) != 0 ||
/* private exponent */
mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(D)) != 0 ||
/* primes */
mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(P)) != 0 ||
mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(Q)) != 0) {
return -3;
}
#if !defined(MBEDTLS_RSA_NO_CRT)
/*
* DP/DQ/QP are only used inside mbedTLS if it was built with the
* Chinese Remainder Theorem enabled (default). In case it is disabled
* we parse, or if not available, we calculate those values.
*/
if (*p < end) {
if ( /* d mod (p-1) and d mod (q-1) */
mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(DP)) != 0 ||
mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(DQ)) != 0 ||
/* q ^ (-1) mod p */
mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(QP)) != 0) {
return -4;
}
} else {
if (mbedtls_rsa_deduce_crt(&ctx->MBEDTLS_CONTEXT_MEMBER(P),
&ctx->MBEDTLS_CONTEXT_MEMBER(Q),
&ctx->MBEDTLS_CONTEXT_MEMBER(D),
&ctx->MBEDTLS_CONTEXT_MEMBER(DP),
&ctx->MBEDTLS_CONTEXT_MEMBER(DQ),
&ctx->MBEDTLS_CONTEXT_MEMBER(QP)) != 0) {
return -5;
}
}
#endif /* !MBEDTLS_RSA_NO_CRT */
ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));
if (mbedtls_rsa_check_privkey(ctx) != 0) {
return -6;
}
return 0;
}
#endif /* BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED */
#if defined(BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED)
/*
* Parse a RSA public key with format specified in RFC3447 A.1.1
*/
static int
bootutil_rsa_parse_public_key(bootutil_rsa_context *ctx, uint8_t **p, uint8_t *end)
{
int rc;
size_t len;
if ((rc = mbedtls_asn1_get_tag(p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
return -1;
}
if (*p + len != end) {
return -2;
}
if ((rc = mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N))) != 0 ||
(rc = mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E))) != 0) {
return -3;
}
ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));
if (*p != end) {
return -4;
}
/* The Mbed TLS version is more than 2.6.1 */
#if MBEDTLS_VERSION_NUMBER > 0x02060100
rc = mbedtls_rsa_import(ctx, &ctx->MBEDTLS_CONTEXT_MEMBER(N), NULL,
NULL, NULL, &ctx->MBEDTLS_CONTEXT_MEMBER(E));
if (rc != 0) {
return -5;
}
#endif
rc = mbedtls_rsa_check_pubkey(ctx);
if (rc != 0) {
return -6;
}
ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));
return 0;
}
/* Get the modulus (N) length in bytes */
static inline size_t bootutil_rsa_get_len(const bootutil_rsa_context *ctx)
{
return mbedtls_rsa_get_len(ctx);
}
/* Performs modular exponentiation using the public key output = input^E mod N */
static inline int bootutil_rsa_public(bootutil_rsa_context *ctx, const uint8_t *input, uint8_t *output)
{
return mbedtls_rsa_public(ctx, input, output);
}
#endif /* BOOTUTIL_CRYPTO_RSA_SIGN_ENABLED */
#endif /* MCUBOOT_USE_MBED_TLS */
#ifdef __cplusplus
}
#endif
#endif /* __BOOTUTIL_CRYPTO_RSA_H_ */

View File

@@ -0,0 +1,250 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2017-2019 Linaro LTD
* Copyright (c) 2017-2019 JUUL Labs
* Copyright (c) 2021-2023 Arm Limited
*/
/*
* This module provides a thin abstraction over some of the crypto
* primitives to make it easier to swap out the used crypto library.
*
* At this point, the choices are: MCUBOOT_USE_MBED_TLS, MCUBOOT_USE_TINYCRYPT,
* MCUBOOT_USE_PSA_CRYPTO, MCUBOOT_USE_CC310. Note that support for MCUBOOT_USE_PSA_CRYPTO
* is still experimental and it might not support all the crypto abstractions
* that MCUBOOT_USE_MBED_TLS supports. For this reason, it's allowed to have
* both of them defined, and for crypto modules that support both abstractions,
* the MCUBOOT_USE_PSA_CRYPTO will take precedence.
*/
#ifndef __BOOTUTIL_CRYPTO_SHA_H_
#define __BOOTUTIL_CRYPTO_SHA_H_
#include "mcuboot_config/mcuboot_config.h"
#include "mcuboot_config/mcuboot_logging.h"
#if defined(MCUBOOT_USE_PSA_CRYPTO) || defined(MCUBOOT_USE_MBED_TLS)
#define MCUBOOT_USE_PSA_OR_MBED_TLS
#endif /* MCUBOOT_USE_PSA_CRYPTO || MCUBOOT_USE_MBED_TLS */
#if (defined(MCUBOOT_USE_PSA_OR_MBED_TLS) + \
defined(MCUBOOT_USE_TINYCRYPT) + \
defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \
defined(MCUBOOT_USE_CC310)) != 1
#error "One crypto backend must be defined: either CC310/MBED_TLS/TINYCRYPT/PSA_CRYPTO"
#endif
#if defined(MCUBOOT_SHA512)
#define IMAGE_HASH_SIZE (64)
#define EXPECTED_HASH_TLV IMAGE_TLV_SHA512
#elif defined(MCUBOOT_SIGN_EC384)
#define IMAGE_HASH_SIZE (48)
#define EXPECTED_HASH_TLV IMAGE_TLV_SHA384
#else
#define IMAGE_HASH_SIZE (32)
#define EXPECTED_HASH_TLV IMAGE_TLV_SHA256
#endif /* MCUBOOT_SIGN */
/* Universal defines for SHA-256 */
#define BOOTUTIL_CRYPTO_SHA256_BLOCK_SIZE (64)
#define BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE (32)
#if defined(MCUBOOT_USE_PSA_CRYPTO)
#include <psa/crypto.h>
#elif defined(MCUBOOT_USE_MBED_TLS)
#include <mbedtls/sha256.h>
#include <mbedtls/version.h>
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
#include <mbedtls/compat-2.x.h>
#endif
#endif /* MCUBOOT_USE_MBED_TLS */
#if defined(MCUBOOT_USE_TINYCRYPT)
#include <tinycrypt/sha256.h>
#include <tinycrypt/constants.h>
#endif /* MCUBOOT_USE_TINYCRYPT */
#if defined(MCUBOOT_USE_CC310)
#include <cc310_glue.h>
#endif /* MCUBOOT_USE_CC310 */
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MCUBOOT_USE_PSA_CRYPTO)
typedef psa_hash_operation_t bootutil_sha_context;
static inline int bootutil_sha_init(bootutil_sha_context *ctx)
{
*ctx = psa_hash_operation_init();
#if defined(MCUBOOT_SHA512)
psa_status_t status = psa_hash_setup(ctx, PSA_ALG_SHA_512);
#elif defined(MCUBOOT_SIGN_EC384)
psa_status_t status = psa_hash_setup(ctx, PSA_ALG_SHA_384);
#else
psa_status_t status = psa_hash_setup(ctx, PSA_ALG_SHA_256);
#endif
return (int)status;
}
static inline int bootutil_sha_drop(bootutil_sha_context *ctx)
{
return (int)psa_hash_abort(ctx);
}
static inline int bootutil_sha_update(bootutil_sha_context *ctx,
const void *data,
uint32_t data_len)
{
return (int)psa_hash_update(ctx, data, data_len);
}
static inline int bootutil_sha_finish(bootutil_sha_context *ctx,
uint8_t *output)
{
size_t hash_length = 0;
/* Assumes the output buffer is at least the expected size of the hash */
#if defined(MCUBOOT_SHA512)
return (int)psa_hash_finish(ctx, output, PSA_HASH_LENGTH(PSA_ALG_SHA_512), &hash_length);
#elif defined(MCUBOOT_SIGN_EC384)
return (int)psa_hash_finish(ctx, output, PSA_HASH_LENGTH(PSA_ALG_SHA_384), &hash_length);
#else
return (int)psa_hash_finish(ctx, output, PSA_HASH_LENGTH(PSA_ALG_SHA_256), &hash_length);
#endif
}
#elif defined(MCUBOOT_USE_MBED_TLS)
typedef mbedtls_sha256_context bootutil_sha_context;
static inline int bootutil_sha_init(bootutil_sha_context *ctx)
{
mbedtls_sha256_init(ctx);
return mbedtls_sha256_starts_ret(ctx, 0);
}
static inline int bootutil_sha_drop(bootutil_sha_context *ctx)
{
mbedtls_sha256_free(ctx);
return 0;
}
static inline int bootutil_sha_update(bootutil_sha_context *ctx,
const void *data,
uint32_t data_len)
{
return mbedtls_sha256_update_ret(ctx, data, data_len);
}
static inline int bootutil_sha_finish(bootutil_sha_context *ctx,
uint8_t *output)
{
return mbedtls_sha256_finish_ret(ctx, output);
}
#endif /* MCUBOOT_USE_MBED_TLS */
#if defined(MCUBOOT_USE_TINYCRYPT)
typedef struct tc_sha256_state_struct bootutil_sha_context;
static inline int bootutil_sha_init(bootutil_sha_context *ctx)
{
tc_sha256_init(ctx);
return 0;
}
static inline int bootutil_sha_drop(bootutil_sha_context *ctx)
{
(void)ctx;
return 0;
}
static inline int bootutil_sha_update(bootutil_sha_context *ctx,
const void *data,
uint32_t data_len)
{
return tc_sha256_update(ctx, data, data_len);
}
static inline int bootutil_sha_finish(bootutil_sha_context *ctx,
uint8_t *output)
{
return tc_sha256_final(output, ctx);
}
#endif /* MCUBOOT_USE_TINYCRYPT */
#if defined(MCUBOOT_USE_CC310)
static inline int bootutil_sha_init(bootutil_sha_context *ctx)
{
cc310_sha256_init(ctx);
return 0;
}
static inline int bootutil_sha_drop(bootutil_sha_context *ctx)
{
(void)ctx;
nrf_cc310_disable();
return 0;
}
static inline int bootutil_sha_update(bootutil_sha_context *ctx,
const void *data,
uint32_t data_len)
{
cc310_sha256_update(ctx, data, data_len);
return 0;
}
static inline int bootutil_sha_finish(bootutil_sha_context *ctx,
uint8_t *output)
{
cc310_sha256_finalize(ctx, output);
return 0;
}
#endif /* MCUBOOT_USE_CC310 */
#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO)
#include <bl_crypto.h>
typedef bl_sha256_ctx_t bootutil_sha_context;
static inline void bootutil_sha_init(bootutil_sha_context *ctx)
{
bl_sha256_init(ctx);
}
static inline void bootutil_sha_drop(bootutil_sha_context *ctx)
{
(void)ctx;
}
static inline int bootutil_sha_update(bootutil_sha_context *ctx,
const void *data,
uint32_t data_len)
{
return bl_sha256_update(ctx, data, data_len);
}
static inline int bootutil_sha_finish(bootutil_sha_context *ctx,
uint8_t *output)
{
bl_sha256_finalize(ctx, output);
return 0;
}
#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */
#ifdef __cplusplus
}
#endif
#endif /* __BOOTUTIL_CRYPTO_SHA_H_ */

View File

@@ -0,0 +1,83 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2018-2019 JUUL Labs
* Copyright (c) 2019 Arm Limited
*
* Original license:
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 BOOTUTIL_ENC_KEY_H
#define BOOTUTIL_ENC_KEY_H
#include <stdbool.h>
#include <stdint.h>
#include <flash_map_backend/flash_map_backend.h>
#include "bootutil/crypto/aes_ctr.h"
#include "bootutil/image.h"
#include "bootutil/sign_key.h"
#include "bootutil/enc_key_public.h"
#ifdef __cplusplus
extern "C" {
#endif
#define BOOT_ENC_TLV_ALIGN_SIZE ALIGN_UP(BOOT_ENC_TLV_SIZE, BOOT_MAX_ALIGN)
struct enc_key_data {
uint8_t valid;
bootutil_aes_ctr_context aes_ctr;
};
/**
* Retrieve the private key for image encryption.
*
* @param[out] private_key structure to store the private key and
* its length.
*
* @return 0 on success; nonzero on failure.
*
*/
int boot_enc_retrieve_private_key(struct bootutil_key **private_key);
struct boot_status;
/* Decrypt random, symmetric encryption key */
int boot_decrypt_key(const uint8_t *buf, uint8_t *enckey);
int boot_enc_init(struct enc_key_data *enc_state, uint8_t slot);
int boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot);
int boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
const struct boot_status *bs);
int boot_enc_load(struct enc_key_data *enc_state, int slot,
const struct image_header *hdr, const struct flash_area *fap,
struct boot_status *bs);
bool boot_enc_valid(struct enc_key_data *enc_state, int slot);
void boot_enc_encrypt(struct enc_key_data *enc_state, int slot,
uint32_t off, uint32_t sz, uint32_t blk_off, uint8_t *buf);
void boot_enc_decrypt(struct enc_key_data *enc_state, int slot,
uint32_t off, uint32_t sz, uint32_t blk_off, uint8_t *buf);
void boot_enc_zeroize(struct enc_key_data *enc_state);
#ifdef __cplusplus
}
#endif
#endif /* BOOTUTIL_ENC_KEY_H */

View File

@@ -0,0 +1,66 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2018-2019 JUUL Labs
* Copyright (c) 2019-2021 Arm Limited
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* Original license:
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 BOOTUTIL_ENC_KEY_PUBLIC_H
#define BOOTUTIL_ENC_KEY_PUBLIC_H
#include <mcuboot_config/mcuboot_config.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ALIGN_UP
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#endif
#ifdef MCUBOOT_AES_256
#define BOOT_ENC_KEY_SIZE 32
#else
#define BOOT_ENC_KEY_SIZE 16
#endif
#define BOOT_ENC_KEY_ALIGN_SIZE ALIGN_UP(BOOT_ENC_KEY_SIZE, BOOT_MAX_ALIGN)
#define TLV_ENC_RSA_SZ 256
#define TLV_ENC_KW_SZ (BOOT_ENC_KEY_SIZE + 8)
#define TLV_ENC_EC256_SZ (65 + 32 + BOOT_ENC_KEY_SIZE)
#define TLV_ENC_X25519_SZ (32 + 32 + BOOT_ENC_KEY_SIZE)
#if defined(MCUBOOT_ENCRYPT_RSA)
#define BOOT_ENC_TLV_SIZE TLV_ENC_RSA_SZ
#elif defined(MCUBOOT_ENCRYPT_EC256)
#define BOOT_ENC_TLV_SIZE TLV_ENC_EC256_SZ
#elif defined(MCUBOOT_ENCRYPT_X25519)
#define BOOT_ENC_TLV_SIZE TLV_ENC_X25519_SZ
#else
#define BOOT_ENC_TLV_SIZE TLV_ENC_KW_SZ
#endif
#ifdef __cplusplus
}
#endif
#endif /* BOOTUTIL_ENC_KEY_PUBLIC_H */

View File

@@ -0,0 +1,371 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2020 Arm Limited
*/
#ifndef __FAULT_INJECTION_HARDENING_H__
#define __FAULT_INJECTION_HARDENING_H__
/* Fault injection mitigation library.
*
* Has support for different measures, which can either be enabled/disabled
* separately or by defining one of the MCUBOOT_FIH_PROFILEs.
*
* NOTE: These constructs against fault injection attacks are not guaranteed to
* be secure for all compilers, but execution is going to be correct and
* including them will certainly help to harden the code.
*
* FIH_ENABLE_DOUBLE_VARS makes critical variables into a tuple (x, x ^ msk).
* Then the correctness of x can be checked by XORing the two tuple values
* together. This also means that comparisons between fih_ints can be verified
* by doing x == y && x_msk == y_msk.
*
* FIH_ENABLE_GLOBAL_FAIL makes all while(1) failure loops redirect to a global
* failure loop. This loop has mitigations against loop escapes / unlooping.
* This also means that any unlooping won't immediately continue executing the
* function that was executing before the failure.
*
* FIH_ENABLE_CFI (Control Flow Integrity) creates a global counter that is
* incremented before every FIH_CALL of vulnerable functions. On the function
* return the counter is decremented, and after the return it is verified that
* the counter has the same value as before this process. This can be used to
* verify that the function has actually been called. This protection is
* intended to discover that important functions are called in an expected
* sequence and neither of them is missed due to an instruction skip which could
* be a result of glitching attack. It does not provide protection against ROP
* or JOP attacks.
*
* FIH_ENABLE_DELAY causes random delays. This makes it hard to cause faults
* precisely. It requires an RNG. An mbedtls integration is provided in
* fault_injection_hardening_delay_mbedtls.h, but any RNG that has an entropy
* source can be used by implementing the fih_delay_random_uchar function.
*
* The basic call pattern is:
*
* FIH_DECLARE(fih_rc, FIH_FAILURE);
* FIH_CALL(vulnerable_function, fih_rc, arg1, arg2);
* if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
* FIH_PANIC;
* }
*
* Note that any function called by FIH_CALL must only return using FIH_RETURN,
* as otherwise the CFI counter will not be decremented and the CFI check will
* fail causing a panic.
*/
#include "mcuboot_config/mcuboot_config.h"
#if defined(MCUBOOT_FIH_PROFILE_HIGH)
#define FIH_ENABLE_DELAY /* Requires an entropy source */
#define FIH_ENABLE_DOUBLE_VARS
#define FIH_ENABLE_GLOBAL_FAIL
#define FIH_ENABLE_CFI
#elif defined(MCUBOOT_FIH_PROFILE_MEDIUM)
#define FIH_ENABLE_DOUBLE_VARS
#define FIH_ENABLE_GLOBAL_FAIL
#define FIH_ENABLE_CFI
#elif defined(MCUBOOT_FIH_PROFILE_LOW)
#define FIH_ENABLE_GLOBAL_FAIL
#define FIH_ENABLE_CFI
#elif !defined(MCUBOOT_FIH_PROFILE_OFF)
#define MCUBOOT_FIH_PROFILE_OFF
#endif /* MCUBOOT_FIH_PROFILE */
#ifdef FIH_ENABLE_DELAY
#include "fault_injection_hardening_delay_rng.h"
#endif /* FIH_ENABLE_DELAY */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Non-zero success value to defend against register resets. Zero is the most
* common value for a corrupted register so complex bit-patterns are used
*/
#ifndef MCUBOOT_FIH_PROFILE_OFF
#define FIH_POSITIVE_VALUE 0x1AAAAAAA
#define FIH_NEGATIVE_VALUE 0x15555555
#define FIH_CONST1 0x1FCDEA88
#define FIH_CONST2 0x19C1F6E1
#else
#define FIH_POSITIVE_VALUE 0
#define FIH_NEGATIVE_VALUE -1
#define FIH_CONST1 1
#define FIH_CONST2 1
#endif
/* A volatile mask is used to prevent compiler optimization - the mask is xored
* with the variable to create the backup and the integrity can be checked with
* another xor. The mask value doesn't _really_ matter that much, as long as
* it has reasonably high hamming weight.
*/
#define _FIH_MASK_VALUE 0xBEEF
#ifdef FIH_ENABLE_DOUBLE_VARS
/* All ints are replaced with two int - the normal one and a backup which is
* XORed with the mask.
*/
extern volatile int _fih_mask;
typedef volatile struct {
volatile int val;
volatile int msk;
} fih_int;
typedef volatile int fih_ret;
#else
typedef int fih_int;
typedef int fih_ret;
#endif /* FIH_ENABLE_DOUBLE_VARS */
extern fih_ret FIH_SUCCESS;
extern fih_ret FIH_FAILURE;
extern fih_ret FIH_NO_BOOTABLE_IMAGE;
extern fih_ret FIH_BOOT_HOOK_REGULAR;
#ifdef FIH_ENABLE_GLOBAL_FAIL
/* Global failure handler - more resistant to unlooping. noinline and used are
* used to prevent optimization
*/
__attribute__((noinline)) __attribute__((used))
void fih_panic_loop(void);
#define FIH_PANIC fih_panic_loop()
#else
#define FIH_PANIC while (1) {}
#endif /* FIH_ENABLE_GLOBAL_FAIL */
/* NOTE: For functions to be inlined outside their compilation unit they have to
* have the body in the header file. This is required as function calls are easy
* to skip.
*/
#ifdef FIH_ENABLE_DELAY
/* Delaying logic, with randomness from a CSPRNG */
__attribute__((always_inline)) inline
int fih_delay(void)
{
unsigned char delay;
int foo = 0;
volatile int rc;
delay = fih_delay_random_uchar();
for (volatile int i = 0; i < delay; i++) {
foo++;
}
rc = 1;
/* rc is volatile so if it is the return value then the function cannot be
* optimized
*/
return rc;
}
#else
__attribute__((always_inline)) inline
int fih_delay_init(void)
{
return 1;
}
__attribute__((always_inline)) inline
int fih_delay(void)
{
return 1;
}
#endif /* FIH_ENABLE_DELAY */
#ifdef FIH_ENABLE_DOUBLE_VARS
__attribute__((always_inline)) inline
void fih_int_validate(fih_int x)
{
if (x.val != (x.msk ^ _fih_mask)) {
FIH_PANIC;
}
}
/* Convert a fih_int to an int. Validate for tampering. */
__attribute__((always_inline)) inline
int fih_int_decode(fih_int x)
{
fih_int_validate(x);
return x.val;
}
/* Convert an int to a fih_int, can be used to encode specific error codes. */
__attribute__((always_inline)) inline
fih_int fih_int_encode(int x)
{
fih_int ret = {x, x ^ _fih_mask};
return ret;
}
/* Standard equality. If A == B then 1, else 0 */
#define FIH_EQ(x, y) ((x == y) && fih_delay() && !(y != x))
#define FIH_NOT_EQ(x, y) ((x != y) || !fih_delay() || !(y == x))
#define FIH_SET(x, y) x = y; if(fih_delay() && (x != y)) FIH_PANIC
#else
/* NOOP */
__attribute__((always_inline)) inline
void fih_int_validate(fih_int x)
{
(void) x;
return;
}
/* NOOP */
__attribute__((always_inline)) inline
int fih_int_decode(fih_int x)
{
return x;
}
/* NOOP */
__attribute__((always_inline)) inline
fih_int fih_int_encode(int x)
{
return x;
}
#define FIH_EQ(x, y) (x == y)
#define FIH_NOT_EQ(x, y) (x != y)
#define FIH_SET(x, y) x = y
#endif /* FIH_ENABLE_DOUBLE_VARS */
#define FIH_DECLARE(var, val) \
fih_ret FIH_SET(var, val)
/* C has a common return pattern where 0 is a correct value and all others are
* errors. This function converts 0 to FIH_SUCCESS and any other number to a
* value that is not FIH_SUCCESS
*/
__attribute__((always_inline)) inline
fih_ret fih_ret_encode_zero_equality(int x)
{
if (x) {
return FIH_FAILURE;
} else {
return FIH_SUCCESS;
}
}
#ifdef FIH_ENABLE_CFI
extern fih_int _fih_cfi_ctr;
#endif /* FIH_ENABLE_CFI */
fih_int fih_cfi_get_and_increment(void);
void fih_cfi_validate(fih_int saved);
void fih_cfi_decrement(void);
/* Label for interacting with FIH testing tool. Can be parsed from the elf file
* after compilation. Does not require debug symbols.
*/
#if defined(__ICCARM__)
#define FIH_LABEL(str, lin, cnt) __asm volatile ("FIH_LABEL_" str "_" #lin "_" #cnt "::" ::);
#elif defined(__APPLE__)
#define FIH_LABEL(str) do {} while (0)
#else
#define FIH_LABEL(str) __asm volatile ("FIH_LABEL_" str "_%=:" ::);
#endif
/* Main FIH calling macro. return variable is second argument. Does some setup
* before and validation afterwards. Inserts labels for use with testing script.
*
* First perform the precall step - this gets the current value of the CFI
* counter and saves it to a local variable, and then increments the counter.
*
* Then set the return variable to FIH_FAILURE as a base case.
*
* Then perform the function call. As part of the funtion FIH_RET must be called
* which will decrement the counter.
*
* The postcall step gets the value of the counter and compares it to the
* previously saved value. If this is equal then the function call and all child
* function calls were performed.
*/
#if defined(__ICCARM__)
#define FIH_CALL(f, ret, ...) FIH_CALL2(f, ret, __LINE__, __COUNTER__, __VA_ARGS__)
#define FIH_CALL2(f, ret, l, c, ...) \
do { \
FIH_LABEL("FIH_CALL_START", l, c); \
FIH_CFI_PRECALL_BLOCK; \
ret = FIH_FAILURE; \
if (fih_delay()) { \
ret = f(__VA_ARGS__); \
} \
FIH_CFI_POSTCALL_BLOCK; \
FIH_LABEL("FIH_CALL_END", l, c); \
} while (0)
#else
#define FIH_CALL(f, ret, ...) \
do { \
FIH_LABEL("FIH_CALL_START"); \
FIH_CFI_PRECALL_BLOCK; \
ret = FIH_FAILURE; \
if (fih_delay()) { \
ret = f(__VA_ARGS__); \
} \
FIH_CFI_POSTCALL_BLOCK; \
FIH_LABEL("FIH_CALL_END"); \
} while (0)
#endif
/* FIH return changes the state of the internal state machine. If you do a
* FIH_CALL then you need to do a FIH_RET else the state machine will detect
* tampering and panic.
*/
#define FIH_RET(ret) \
do { \
FIH_CFI_PRERET; \
return ret; \
} while (0)
#ifdef FIH_ENABLE_CFI
/* Macro wrappers for functions - Even when the functions have zero body this
* saves a few bytes on noop functions as it doesn't generate the call/ret
*
* CFI precall function saves the CFI counter and then increments it - the
* postcall then checks if the counter is equal to the saved value. In order for
* this to be the case a FIH_RET must have been performed inside the called
* function in order to decrement the counter, so the function must have been
* called.
*/
#define FIH_CFI_PRECALL_BLOCK \
fih_int _fih_cfi_saved_value = fih_cfi_get_and_increment()
#define FIH_CFI_POSTCALL_BLOCK \
fih_cfi_validate(_fih_cfi_saved_value)
#define FIH_CFI_PRERET \
fih_cfi_decrement()
#else
#define FIH_CFI_PRECALL_BLOCK
#define FIH_CFI_POSTCALL_BLOCK
#define FIH_CFI_PRERET
#endif /* FIH_ENABLE_CFI */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __FAULT_INJECTION_HARDENING_H__ */

View File

@@ -0,0 +1,30 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2020 Arm Limited
*/
#ifndef __FAULT_INJECTION_HARDENING_DELAY_RNG_H__
#define __FAULT_INJECTION_HARDENING_DELAY_RNG_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* \brief Set up the RNG for use with random delays. Called once at startup.
*/
int fih_delay_init(void);
/**
* \brief Get a random unsigned char from an RNG seeded with an entropy source.
*
* \return A random value that fits inside an unsigned char.
*/
unsigned char fih_delay_random_uchar(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __FAULT_INJECTION_HARDENING_DELAY_RNG_H__ */

View File

@@ -0,0 +1,70 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2017 Nordic Semiconductor ASA
*
* Original license:
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_IGNORE_
#define H_IGNORE_
#ifdef __cplusplus
extern "C" {
#endif
/**
* These macros prevent the "set but not used" warnings for log writes below
* the log level.
*/
#define IGN_1(X) ((void)(X))
#define IGN_2(X, ...) ((void)(X));IGN_1(__VA_ARGS__)
#define IGN_3(X, ...) ((void)(X));IGN_2(__VA_ARGS__)
#define IGN_4(X, ...) ((void)(X));IGN_3(__VA_ARGS__)
#define IGN_5(X, ...) ((void)(X));IGN_4(__VA_ARGS__)
#define IGN_6(X, ...) ((void)(X));IGN_5(__VA_ARGS__)
#define IGN_7(X, ...) ((void)(X));IGN_6(__VA_ARGS__)
#define IGN_8(X, ...) ((void)(X));IGN_7(__VA_ARGS__)
#define IGN_9(X, ...) ((void)(X));IGN_8(__VA_ARGS__)
#define IGN_10(X, ...) ((void)(X));IGN_9(__VA_ARGS__)
#define IGN_11(X, ...) ((void)(X));IGN_10(__VA_ARGS__)
#define IGN_12(X, ...) ((void)(X));IGN_11(__VA_ARGS__)
#define IGN_13(X, ...) ((void)(X));IGN_12(__VA_ARGS__)
#define IGN_14(X, ...) ((void)(X));IGN_13(__VA_ARGS__)
#define IGN_15(X, ...) ((void)(X));IGN_14(__VA_ARGS__)
#define IGN_16(X, ...) ((void)(X));IGN_15(__VA_ARGS__)
#define IGN_17(X, ...) ((void)(X));IGN_16(__VA_ARGS__)
#define IGN_18(X, ...) ((void)(X));IGN_17(__VA_ARGS__)
#define IGN_19(X, ...) ((void)(X));IGN_18(__VA_ARGS__)
#define IGN_20(X, ...) ((void)(X));IGN_19(__VA_ARGS__)
#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
_13, _14, _15, _16, _17, _18, _19, _20, NAME, ...) NAME
#define IGNORE(...) \
GET_MACRO(__VA_ARGS__, IGN_20, IGN_19, IGN_18, IGN_17, IGN_16, IGN_15, \
IGN_14, IGN_13, IGN_12, IGN_11, IGN_10, IGN_9, IGN_8, IGN_7, \
IGN_6, IGN_5, IGN_4, IGN_3, IGN_2, IGN_1)(__VA_ARGS__)
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,228 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2016-2019 Linaro LTD
* Copyright (c) 2016-2019 JUUL Labs
* Copyright (c) 2019-2023 Arm Limited
*
* Original license:
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_IMAGE_
#define H_IMAGE_
#include <inttypes.h>
#include <stdbool.h>
#include "bootutil/fault_injection_hardening.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __packed
#define __packed __attribute__((__packed__))
#endif
struct flash_area;
#define IMAGE_MAGIC 0x96f3b83d
#define IMAGE_MAGIC_V1 0x96f3b83c
#define IMAGE_MAGIC_NONE 0xffffffff
#define IMAGE_TLV_INFO_MAGIC 0x6907
#define IMAGE_TLV_PROT_INFO_MAGIC 0x6908
#define IMAGE_HEADER_SIZE 32
#define IMAGE_HASH_LEN 32 /* Size of SHA256 TLV hash */
/*
* Image header flags.
*/
#define IMAGE_F_PIC 0x00000001 /* Not supported. */
#define IMAGE_F_ENCRYPTED_AES128 0x00000004 /* Encrypted using AES128. */
#define IMAGE_F_ENCRYPTED_AES256 0x00000008 /* Encrypted using AES256. */
#define IMAGE_F_NON_BOOTABLE 0x00000010 /* Split image app. */
/*
* Indicates that this image should be loaded into RAM instead of run
* directly from flash. The address to load should be in the
* ih_load_addr field of the header.
*/
#define IMAGE_F_RAM_LOAD 0x00000020
/*
* Indicates that ih_load_addr stores information on flash/ROM address the
* image has been built for.
*/
#define IMAGE_F_ROM_FIXED 0x00000100
/*
* Flags that indicate if the image data is compressed
*/
#define IMAGE_F_COMPRESSED_LZMA1 0x00000200
#define IMAGE_F_COMPRESSED_LZMA2 0x00000400
#define IMAGE_F_COMPRESSED_ARM_THUMB_FLT 0x00000800
/*
* ECSDA224 is with NIST P-224
* ECSDA256 is with NIST P-256
*/
/*
* Image trailer TLV types.
*
* Signature is generated by computing signature over the image hash.
*
* Signature comes in the form of 2 TLVs.
* 1st on identifies the public key which should be used to verify it.
* 2nd one is the actual signature.
*/
#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */
#define IMAGE_TLV_PUBKEY 0x02 /* public key */
#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */
#define IMAGE_TLV_SHA384 0x11 /* SHA384 of image hdr and body */
#define IMAGE_TLV_SHA512 0x12 /* SHA512 of image hdr and body */
#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */
#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */
#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */
#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */
#define IMAGE_TLV_ED25519 0x24 /* ed25519 of hash output */
#define IMAGE_TLV_SIG_PURE 0x25 /* Indicator that attached signature has been prepared
* over image rather than its digest.
*/
#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */
#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/
#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */
#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */
#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */
#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */
#define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */
/* The following flags relate to compressed images and are for the decompressed image data */
#define IMAGE_TLV_DECOMP_SIZE 0x70 /* Decompressed image size excluding header/TLVs */
#define IMAGE_TLV_DECOMP_SHA 0x71 /*
* Decompressed image shaX hash, this field must match
* the format and size of the raw slot (compressed)
* shaX hash
*/
#define IMAGE_TLV_DECOMP_SIGNATURE 0x72 /*
* Decompressed image signature, this field must match
* the format and size of the raw slot (compressed)
* signature
*/
/*
* vendor reserved TLVs at xxA0-xxFF,
* where xx denotes the upper byte
* range. Examples:
* 0x00a0 - 0x00ff
* 0x01a0 - 0x01ff
* 0x02a0 - 0x02ff
* ...
* 0xffa0 - 0xfffe
*/
#define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */
struct image_version {
uint8_t iv_major;
uint8_t iv_minor;
uint16_t iv_revision;
uint32_t iv_build_num;
} __packed;
struct image_dependency {
uint8_t image_id; /* Image index (from 0) */
uint8_t _pad1;
uint16_t _pad2;
struct image_version image_min_version; /* Indicates at minimum which
* version of firmware must be
* available to satisfy compliance
*/
};
/** Image header. All fields are in little endian byte order. */
struct image_header {
uint32_t ih_magic;
uint32_t ih_load_addr;
uint16_t ih_hdr_size; /* Size of image header (bytes). */
uint16_t ih_protect_tlv_size; /* Size of protected TLV area (bytes). */
uint32_t ih_img_size; /* Does not include header. */
uint32_t ih_flags; /* IMAGE_F_[...]. */
struct image_version ih_ver;
uint32_t _pad1;
} __packed;
/** Image TLV header. All fields in little endian. */
struct image_tlv_info {
uint16_t it_magic;
uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */
} __packed;
/** Image trailer TLV format. All fields in little endian. */
struct image_tlv {
uint16_t it_type; /* IMAGE_TLV_[...]. */
uint16_t it_len; /* Data length (not including TLV header). */
} __packed;
#define ENCRYPTIONFLAGS (IMAGE_F_ENCRYPTED_AES128 | IMAGE_F_ENCRYPTED_AES256)
#define IS_ENCRYPTED(hdr) (((hdr)->ih_flags & IMAGE_F_ENCRYPTED_AES128) \
|| ((hdr)->ih_flags & IMAGE_F_ENCRYPTED_AES256))
#define MUST_DECRYPT(fap, idx, hdr) \
(flash_area_get_id(fap) == FLASH_AREA_IMAGE_SECONDARY(idx) && IS_ENCRYPTED(hdr))
#define COMPRESSIONFLAGS (IMAGE_F_COMPRESSED_LZMA1 | IMAGE_F_COMPRESSED_LZMA2 \
| IMAGE_F_COMPRESSED_ARM_THUMB_FLT)
#define IS_COMPRESSED(hdr) ((hdr)->ih_flags & COMPRESSIONFLAGS)
#define MUST_DECOMPRESS(fap, idx, hdr) \
(flash_area_get_id(fap) == FLASH_AREA_IMAGE_SECONDARY(idx) && IS_COMPRESSED(hdr))
_Static_assert(sizeof(struct image_header) == IMAGE_HEADER_SIZE,
"struct image_header not required size");
struct enc_key_data;
fih_ret bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
struct image_header *hdr,
const struct flash_area *fap,
uint8_t *tmp_buf, uint32_t tmp_buf_sz,
uint8_t *seed, int seed_len, uint8_t *out_hash);
struct image_tlv_iter {
const struct image_header *hdr;
const struct flash_area *fap;
uint16_t type;
bool prot;
uint32_t prot_end;
uint32_t tlv_off;
uint32_t tlv_end;
};
int bootutil_tlv_iter_begin(struct image_tlv_iter *it,
const struct image_header *hdr,
const struct flash_area *fap, uint16_t type,
bool prot);
int bootutil_tlv_iter_next(struct image_tlv_iter *it, uint32_t *off,
uint16_t *len, uint16_t *type);
int bootutil_tlv_iter_is_prot(struct image_tlv_iter *it, uint32_t off);
int32_t bootutil_get_img_security_cnt(struct image_header *hdr,
const struct flash_area *fap,
uint32_t *security_cnt);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2022, Laird Connectivity
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef H_MCUBOOT_STATUS_
#define H_MCUBOOT_STATUS_
/* Enumeration representing the states that MCUboot can be in */
typedef enum
{
MCUBOOT_STATUS_STARTUP = 0,
MCUBOOT_STATUS_UPGRADING,
MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND,
MCUBOOT_STATUS_NO_BOOTABLE_IMAGE_FOUND,
MCUBOOT_STATUS_BOOT_FAILED,
MCUBOOT_STATUS_USB_DFU_WAITING,
MCUBOOT_STATUS_USB_DFU_ENTERED,
MCUBOOT_STATUS_USB_DFU_TIMED_OUT,
MCUBOOT_STATUS_SERIAL_DFU_ENTERED,
} mcuboot_status_type_t;
#if defined(CONFIG_MCUBOOT_ACTION_HOOKS)
extern void mcuboot_status_change(mcuboot_status_type_t status);
#else
#define mcuboot_status_change(_status) do {} while (0)
#endif
#endif /* H_MCUBOOT_STATUS_ */

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __RAMLOAD_H__
#define __RAMLOAD_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef MULTIPLE_EXECUTABLE_RAM_REGIONS
/**
* Provides information about the Executable RAM for a given image ID.
*
* @param image_id Index of the image (from 0).
* @param exec_ram_start Pointer to store the start address of the exec RAM
* @param exec_ram_size Pointer to store the size of the exec RAM
*
* @return 0 on success; nonzero on failure.
*/
int boot_get_image_exec_ram_info(uint32_t image_id,
uint32_t *exec_ram_start,
uint32_t *exec_ram_size);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __RAMLOAD_H__ */

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __SECURITY_CNT_H__
#define __SECURITY_CNT_H__
/**
* @file security_cnt.h
*
* @note The interface must be implemented in a fail-safe way that is
* resistant to asynchronous power failures or it can use hardware
* counters that have this capability, if supported by the platform.
* When a counter incrementation was interrupted it must be able to
* continue the incrementation process or recover the previous consistent
* status of the counters. If the counters have reached a stable status
* (every counter incrementation operation has finished), from that point
* their value cannot decrease due to any kind of power failure.
*
* @note A security counter might be implemented using non-volatile OTP memory
* (i.e. fuses) in which case it is the responsibility of the platform
* code to map each possible security counter values onto the fuse bits
* as the direct usage of counter values can be costly / impractical.
*/
#include <stdint.h>
#include "bootutil/fault_injection_hardening.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Initialises the security counters.
*
* @return FIH_SUCCESS on success
*/
fih_ret boot_nv_security_counter_init(void);
/**
* Reads the stored value of a given image's security counter.
*
* @param image_id Index of the image (from 0).
* @param security_cnt Pointer to store the security counter value.
*
* @return FIH_SUCCESS on success
*/
fih_ret boot_nv_security_counter_get(uint32_t image_id, fih_int *security_cnt);
/**
* Updates the stored value of a given image's security counter with a new
* security counter value if the new one is greater.
*
* @param image_id Index of the image (from 0).
* @param img_security_cnt New security counter value. The new value must be
* between 0 and UINT32_MAX and it must be greater than
* or equal to the current security counter value.
*
* @return 0 on success; nonzero on failure.
*/
int32_t boot_nv_security_counter_update(uint32_t image_id,
uint32_t img_security_cnt);
#ifdef __cplusplus
}
#endif
#endif /* __SECURITY_CNT_H__ */

View File

@@ -0,0 +1,71 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 __BOOTUTIL_SIGN_KEY_H_
#define __BOOTUTIL_SIGN_KEY_H_
#include <stddef.h>
#include <stdint.h>
/* mcuboot_config.h is needed for MCUBOOT_HW_KEY to work */
#include "mcuboot_config/mcuboot_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MCUBOOT_HW_KEY
struct bootutil_key {
const uint8_t *key;
const unsigned int *len;
};
extern const struct bootutil_key bootutil_keys[];
#else
struct bootutil_key {
uint8_t *key;
unsigned int *len;
};
extern struct bootutil_key bootutil_keys[];
/**
* Retrieve the hash of the corresponding public key for image authentication.
*
* @param[in] image_index Index of the image to be authenticated.
* @param[out] public_key_hash Buffer to store the key-hash in.
* @param[in,out] key_hash_size As input the size of the buffer. As output
* the actual key-hash length.
*
* @return 0 on success; nonzero on failure.
*/
int boot_retrieve_public_key_hash(uint8_t image_index,
uint8_t *public_key_hash,
size_t *key_hash_size);
#endif /* !MCUBOOT_HW_KEY */
extern const int bootutil_key_cnt;
#ifdef __cplusplus
}
#endif
#endif /* __BOOTUTIL_SIGN_KEY_H_ */