Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AP_CheckFirmware/AP_CheckFirmware.cpp
Views: 1798
/*1support checking board ID and firmware CRC in the bootloader2*/3#include "AP_CheckFirmware.h"4#include <AP_HAL/HAL.h>5#include <AP_Math/crc.h>67#if AP_CHECK_FIRMWARE_ENABLED89#if defined(HAL_BOOTLOADER_BUILD)1011#if AP_SIGNED_FIRMWARE12#include "../../Tools/AP_Bootloader/support.h"13#include <string.h>14#include "monocypher.h"1516const struct ap_secure_data public_keys __attribute__((section(".apsec_data")));1718/*19return true if all public keys are zero. We allow boot of an20unsigned firmware in that case21*/22static bool all_zero_public_keys(void)23{24/*25look over all public keys, if one matches then we are OK26*/27const uint8_t zero_key[AP_PUBLIC_KEY_LEN] {};28for (const auto &public_key : public_keys.public_key) {29if (memcmp(public_key.key, zero_key, AP_PUBLIC_KEY_LEN) != 0) {30return false;31}32}33return true;34}3536/*37check a signature against bootloader keys38*/39static check_fw_result_t check_firmware_signature(const app_descriptor_signed *ad,40const uint8_t *flash1, uint32_t len1,41const uint8_t *flash2, uint32_t len2)42{43if (all_zero_public_keys()) {44return check_fw_result_t::CHECK_FW_OK;45}4647// 8 byte signature version48static const uint64_t sig_version = 30437LLU;49if (ad->signature_length != 72) {50return check_fw_result_t::FAIL_REASON_BAD_FIRMWARE_SIGNATURE;51}52if (memcmp((const uint8_t*)&sig_version, ad->signature, sizeof(sig_version)) != 0) {53return check_fw_result_t::FAIL_REASON_BAD_FIRMWARE_SIGNATURE;54}5556/*57look over all public keys, if one matches then we are OK58*/59for (const auto &public_key : public_keys.public_key) {60crypto_check_ctx ctx {};61crypto_check_ctx_abstract *actx = (crypto_check_ctx_abstract*)&ctx;62crypto_check_init(actx, &ad->signature[sizeof(sig_version)], public_key.key);6364crypto_check_update(actx, flash1, len1);65crypto_check_update(actx, flash2, len2);66if (crypto_check_final(actx) == 0) {67// good signature68return check_fw_result_t::CHECK_FW_OK;69}70}7172// none of the public keys matched73return check_fw_result_t::FAIL_REASON_VERIFICATION;74}75#endif // AP_SIGNED_FIRMWARE7677/*78check firmware CRC and board ID to see if it matches79*/80static check_fw_result_t check_good_firmware_signed(void)81{82const uint8_t sig[8] = AP_APP_DESCRIPTOR_SIGNATURE_SIGNED;83const uint8_t *flash1 = (const uint8_t *)(FLASH_LOAD_ADDRESS + (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB)*1024);84const uint32_t flash_size = (BOARD_FLASH_SIZE - (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB))*1024;85const app_descriptor_signed *ad = (const app_descriptor_signed *)memmem(flash1, flash_size-sizeof(app_descriptor_signed), sig, sizeof(sig));86if (ad == nullptr) {87// no application signature88return check_fw_result_t::FAIL_REASON_NO_APP_SIG;89}90// check length91if (ad->image_size > flash_size) {92return check_fw_result_t::FAIL_REASON_BAD_LENGTH_APP;93}9495bool id_ok = (ad->board_id == APJ_BOARD_ID);96#ifdef ALT_BOARD_ID97id_ok |= (ad->board_id == ALT_BOARD_ID);98#endif99100if (!id_ok) {101return check_fw_result_t::FAIL_REASON_BAD_BOARD_ID;102}103104const uint8_t *flash2 = (const uint8_t *)&ad->version_major;105const uint8_t desc_len = offsetof(app_descriptor_signed, version_major) - offsetof(app_descriptor_signed, image_crc1);106const uint32_t len1 = ((const uint8_t *)&ad->image_crc1) - flash1;107108if ((len1 + desc_len) > ad->image_size) {109return check_fw_result_t::FAIL_REASON_BAD_LENGTH_DESCRIPTOR;110}111112const uint32_t len2 = ad->image_size - (len1 + desc_len);113uint32_t crc1 = crc32_small(0, flash1, len1);114uint32_t crc2 = crc32_small(0, flash2, len2);115if (crc1 != ad->image_crc1 || crc2 != ad->image_crc2) {116return check_fw_result_t::FAIL_REASON_BAD_CRC;117}118119check_fw_result_t ret = check_fw_result_t::CHECK_FW_OK;120121#if AP_SIGNED_FIRMWARE122ret = check_firmware_signature(ad, flash1, len1, flash2, len2);123#endif124125return ret;126}127128/*129check firmware CRC and board ID to see if it matches, using unsigned130signature131*/132static check_fw_result_t check_good_firmware_unsigned(void)133{134const uint8_t sig[8] = AP_APP_DESCRIPTOR_SIGNATURE_UNSIGNED;135const uint8_t *flash1 = (const uint8_t *)(FLASH_LOAD_ADDRESS + (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB)*1024);136const uint32_t flash_size = (BOARD_FLASH_SIZE - (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB))*1024;137const app_descriptor_unsigned *ad = (const app_descriptor_unsigned *)memmem(flash1, flash_size-sizeof(app_descriptor_unsigned), sig, sizeof(sig));138if (ad == nullptr) {139// no application signature140return check_fw_result_t::FAIL_REASON_NO_APP_SIG;141}142// check length143if (ad->image_size > flash_size) {144return check_fw_result_t::FAIL_REASON_BAD_LENGTH_APP;145}146147bool id_ok = (ad->board_id == APJ_BOARD_ID);148#ifdef ALT_BOARD_ID149id_ok |= (ad->board_id == ALT_BOARD_ID);150#endif151152if (!id_ok) {153return check_fw_result_t::FAIL_REASON_BAD_BOARD_ID;154}155156const uint8_t *flash2 = (const uint8_t *)&ad->version_major;157const uint8_t desc_len = offsetof(app_descriptor_unsigned, version_major) - offsetof(app_descriptor_unsigned, image_crc1);158const uint32_t len1 = ((const uint8_t *)&ad->image_crc1) - flash1;159160if ((len1 + desc_len) > ad->image_size) {161return check_fw_result_t::FAIL_REASON_BAD_LENGTH_DESCRIPTOR;162}163164const uint32_t len2 = ad->image_size - (len1 + desc_len);165uint32_t crc1 = crc32_small(0, flash1, len1);166uint32_t crc2 = crc32_small(0, flash2, len2);167if (crc1 != ad->image_crc1 || crc2 != ad->image_crc2) {168return check_fw_result_t::FAIL_REASON_BAD_CRC;169}170171return check_fw_result_t::CHECK_FW_OK;172}173174check_fw_result_t check_good_firmware(void)175{176#if AP_SIGNED_FIRMWARE177// allow unsigned format if we have no public keys. This allows178// for use of SECURE_COMMAND to remove all public keys and then179// load of unsigned firmware180const auto ret = check_good_firmware_signed();181if (ret != check_fw_result_t::CHECK_FW_OK &&182all_zero_public_keys() &&183check_good_firmware_unsigned() == check_fw_result_t::CHECK_FW_OK) {184return check_fw_result_t::CHECK_FW_OK;185}186return ret;187#else188const auto ret = check_good_firmware_unsigned();189if (ret != check_fw_result_t::CHECK_FW_OK) {190// allow for signed format, not checking public keys. This191// allows for booting of a signed firmware with an unsigned192// bootloader, which allows for bootstrapping a system up from193// unsigned to signed194const auto ret2 = check_good_firmware_signed();195if (ret2 == check_fw_result_t::CHECK_FW_OK) {196return check_fw_result_t::CHECK_FW_OK;197}198}199return ret;200#endif201}202203const app_descriptor_t *get_app_descriptor(void)204{205#if AP_SIGNED_FIRMWARE206const uint8_t sig[8] = AP_APP_DESCRIPTOR_SIGNATURE_SIGNED;207#else208const uint8_t sig[8] = AP_APP_DESCRIPTOR_SIGNATURE_UNSIGNED;209#endif210const uint8_t *flash1 = (const uint8_t *)(FLASH_LOAD_ADDRESS + (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB)*1024);211const uint32_t flash_size = (BOARD_FLASH_SIZE - (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB))*1024;212const app_descriptor_t *ad = (const app_descriptor_t *)memmem(flash1, flash_size-sizeof(app_descriptor_t), sig, sizeof(sig));213return ad;214}215216#endif // HAL_BOOTLOADER_BUILD217218#if !defined(HAL_BOOTLOADER_BUILD)219extern const AP_HAL::HAL &hal;220extern const app_descriptor_t app_descriptor;221222/*223this is needed to ensure we don't elide the app_descriptor224*/225void check_firmware_print(void)226{227hal.console->printf("Booting %u/%u\n",228app_descriptor.version_major,229app_descriptor.version_minor);230}231#endif232233234#endif // AP_CHECK_FIRMWARE_ENABLED235236237