From 3d601f24c1deb3550314ab89cb419ca64d09fdd6 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Mon, 20 May 2024 08:47:02 +0200 Subject: [PATCH 001/287] [nrf fromtree] boot: SHA512 verification adds TLV and Kconfig to decouple verification from other options. Signed-off-by: Mateusz Michalek Signed-off-by: Dominik Ermel (cherry picked from commit 41df52e6906172ed3398b1478e4809abfc2bc3e2) (cherry picked from commit 756c5bf1bc19427e5c7901440c5a8f774e1decc8) (cherry picked from commit bf74f34f459f40f4a1ca614893494d4e9ba7ad6f) --- boot/bootutil/include/bootutil/crypto/sha.h | 15 +++-- boot/bootutil/include/bootutil/image.h | 1 + boot/bootutil/src/image_validate.c | 1 + boot/zephyr/Kconfig | 56 +++++++++++++++++++ .../include/mcuboot_config/mcuboot_config.h | 10 ++++ 5 files changed, 79 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index 704a123ea..34288ef02 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -34,13 +34,16 @@ #error "One crypto backend must be defined: either CC310/MBED_TLS/TINYCRYPT/PSA_CRYPTO" #endif -#if defined(MCUBOOT_SIGN_EC384) +#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_EC384 */ +#endif /* MCUBOOT_SIGN */ /* Universal defines for SHA-256 */ #define BOOTUTIL_CRYPTO_SHA256_BLOCK_SIZE (64) @@ -82,7 +85,9 @@ 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_SIGN_EC384) +#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); @@ -107,7 +112,9 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, { size_t hash_length = 0; /* Assumes the output buffer is at least the expected size of the hash */ -#if defined(MCUBOOT_SIGN_EC384) +#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); diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 3e03f80dd..9ede800a2 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -96,6 +96,7 @@ struct flash_area; #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 */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 5953658b0..b3f008989 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -362,6 +362,7 @@ static const uint16_t allowed_unprot_tlvs[] = { IMAGE_TLV_PUBKEY, IMAGE_TLV_SHA256, IMAGE_TLV_SHA384, + IMAGE_TLV_SHA512, IMAGE_TLV_RSA2048_PSS, IMAGE_TLV_ECDSA224, IMAGE_TLV_ECDSA_SIG, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 9ec442dfe..2dd084714 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -24,6 +24,12 @@ config BOOT_USE_MBEDTLS help Use mbedTLS for crypto primitives. +config BOOT_USE_PSA_CRYPTO + bool + # Hidden option + help + Hidden option set if using PSA crypt for cryptography functionality + config BOOT_USE_TINYCRYPT bool # Hidden option @@ -67,6 +73,52 @@ config SINGLE_APPLICATION_SLOT uploading a new application overwrites the one that previously occupied the area. +config BOOT_IMG_HASH_ALG_SHA256_ALLOW + bool + help + Hidden option set by configurations that allow SHA256 + +config BOOT_IMG_HASH_ALG_SHA384_ALLOW + bool + help + Hidden option set by configurations that allow SHA384 + +config BOOT_IMG_HASH_ALG_SHA512_ALLOW + bool + depends on BOOT_USE_PSA_CRYPTO + help + Hidden option set by configurations that allow SHA512 + +choice BOOT_IMG_HASH_ALG + prompt "Selected image hash algorithm" + default BOOT_IMG_HASH_ALG_SHA256 if BOOT_IMG_HASH_ALG_SHA256_ALLOW + default BOOT_IMG_HASH_ALG_SHA384 if BOOT_IMG_HASH_ALG_SHA384_ALLOW + default BOOT_IMG_HASH_ALG_SHA512 if BOOT_IMG_HASH_ALG_SHA512_ALLOW + help + Hash algorithm used for image verification. Selection + here may be limited by other configurations, like for + example selected cryptographic signature. + +config BOOT_IMG_HASH_ALG_SHA256 + bool "SHA256" + depends on BOOT_IMG_HASH_ALG_SHA256_ALLOW + help + SHA256 algorithm + +config BOOT_IMG_HASH_ALG_SHA384 + bool "SHA384" + depends on BOOT_IMG_HASH_ALG_SHA384_ALLOW + help + SHA384 algorithm + +config BOOT_IMG_HASH_ALG_SHA512 + bool "SHA512" + depends on BOOT_IMG_HASH_ALG_SHA512_ALLOW + help + SHA512 algorithm + +endchoice # BOOT_IMG_HASH_ALG + choice BOOT_SIGNATURE_TYPE prompt "Signature type" default BOOT_SIGNATURE_TYPE_RSA @@ -74,12 +126,14 @@ choice BOOT_SIGNATURE_TYPE config BOOT_SIGNATURE_TYPE_NONE bool "No signature; use only hash check" select BOOT_USE_TINYCRYPT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW config BOOT_SIGNATURE_TYPE_RSA bool "RSA signatures" select BOOT_USE_MBEDTLS select MBEDTLS select BOOT_ENCRYPTION_SUPPORT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_RSA_LEN @@ -91,6 +145,7 @@ endif config BOOT_SIGNATURE_TYPE_ECDSA_P256 bool "Elliptic curve digital signatures with curve P-256" select BOOT_ENCRYPTION_SUPPORT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if BOOT_SIGNATURE_TYPE_ECDSA_P256 choice BOOT_ECDSA_IMPLEMENTATION @@ -114,6 +169,7 @@ endif config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" select BOOT_ENCRYPTION_SUPPORT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 0891a4b11..56462fb76 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -43,6 +43,16 @@ #ifdef CONFIG_BOOT_USE_NRF_CC310_BL #define MCUBOOT_USE_NRF_CC310_BL #endif +#elif defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) +#define MCUBOOT_USE_PSA_CRYPTO +#endif + +#ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA512 +#define MCUBOOT_SHA512 +#endif + +#ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA256 +#define MCUBOOT_SHA256 #endif /* Zephyr, regardless of C library used, provides snprintf */ From 3c762c19adebdf07fa17f722558c8aae79cfc738 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 22 Aug 2024 14:58:15 +0000 Subject: [PATCH 002/287] [nrf fromlist] imgtool: Add support for calculating SHA512 The adds support for hashing image with SHA512, to allow SHA512-ED25519-SHA512 signature. To support above --sha parameter has been added that can take value: auto, 256, 384, 512 to select sha, where auto brings the default behaviour, or current, behaviour. The sha provided here is tested against key so not all combinations are supported. Upstream PR #: 2048 Signed-off-by: Dominik Ermel (cherry picked from commit 3a28585c5a5221b487dfd90604f613296172c8af) (cherry picked from commit 9cb8f933eee69fc501434c8639b2fa6770cdf783) --- scripts/imgtool/image.py | 111 ++++++++++++++++++++++++++++++++------- scripts/imgtool/main.py | 8 ++- 2 files changed, 97 insertions(+), 22 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 5c4732b53..53b19ef1d 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -40,6 +40,8 @@ from .boot_record import create_sw_component_data from .keys import rsa, ecdsa, x25519 +from collections import namedtuple + IMAGE_MAGIC = 0x96f3b83d IMAGE_HEADER_SIZE = 32 BIN_EXT = "bin" @@ -65,6 +67,7 @@ 'PUBKEY': 0x02, 'SHA256': 0x10, 'SHA384': 0x11, + 'SHA512': 0x12, 'RSA2048': 0x20, 'ECDSASIG': 0x22, 'RSA3072': 0x23, @@ -135,11 +138,73 @@ def get(self): return header + bytes(self.buf) +SHAAndAlgT = namedtuple('SHAAndAlgT', ['sha', 'alg']) + +TLV_SHA_TO_SHA_AND_ALG = { + TLV_VALUES['SHA256'] : SHAAndAlgT('256', hashlib.sha256), + TLV_VALUES['SHA384'] : SHAAndAlgT('384', hashlib.sha384), + TLV_VALUES['SHA512'] : SHAAndAlgT('512', hashlib.sha512), +} + + +USER_SHA_TO_ALG_AND_TLV = { + 'auto' : (hashlib.sha256, 'SHA256'), + '256' : (hashlib.sha256, 'SHA256'), + '384' : (hashlib.sha384, 'SHA384'), + '512' : (hashlib.sha512, 'SHA512') +} + + +def is_sha_tlv(tlv): + return tlv in TLV_SHA_TO_SHA_AND_ALG.keys() + + +def tlv_sha_to_sha(tlv): + return TLV_SHA_TO_SHA_AND_ALG[tlv].sha + + +# Auto selecting hash algorithm for type(key) +ALLOWED_KEY_SHA = { + keys.ECDSA384P1 : ['384'], + keys.ECDSA384P1Public : ['384'], + keys.ECDSA256P1 : ['256'], + keys.RSA : ['256'], + # This two are set to 256 for compatibility, the right would be 512 + keys.Ed25519 : ['256', '512'], + keys.X25519 : ['256', '512'] +} + +def key_and_user_sha_to_alg_and_tlv(key, user_sha): + """Matches key and user requested sha to sha alogrithm and TLV name. + + The returned tuple will contain hash functions and TVL name. + The function is designed to succeed or completely fail execution, + as providing incorrect pair here basically prevents doing + any more work. + """ + if key is None: + # If key is none, we allow whatever user has selected for sha + return USER_SHA_TO_ALG_AND_TLV[user_sha] + + # If key is not None, then we have to filter hash to only allowed + allowed = None + try: + allowed = ALLOWED_KEY_SHA[type(key)] + except KeyError: + raise click.UsageError("Colud not find allowed hash algorithms for {}" + .format(type(key))) + if user_sha == 'auto': + return USER_SHA_TO_ALG_AND_TLV[allowed[0]] + + if user_sha in allowed: + return USER_SHA_TO_ALG_AND_TLV[user_sha] + + raise click.UsageError("Key {} can not be used with --sha {}; allowed sha are one of {}" + .format(key.sig_type(), user_sha, allowed)) + + def get_digest(tlv_type, hash_region): - if tlv_type == TLV_VALUES["SHA384"]: - sha = hashlib.sha384() - elif tlv_type == TLV_VALUES["SHA256"]: - sha = hashlib.sha256() + sha = TLV_SHA_TO_SHA_AND_ALG[tlv_type].alg() sha.update(hash_region) return sha.digest() @@ -147,9 +212,16 @@ def get_digest(tlv_type, hash_region): def tlv_matches_key_type(tlv_type, key): """Check if provided key matches to TLV record in the image""" - return (key is None or - type(key) == keys.ECDSA384P1 and tlv_type == TLV_VALUES["SHA384"] or - type(key) != keys.ECDSA384P1 and tlv_type == TLV_VALUES["SHA256"]) + try: + # We do not need the result here, and the key_and_user_sha_to_alg_and_tlv + # will either succeed finding match or rise exception, so on success we + # return True, on exception we return False. + _, _ = key_and_user_sha_to_alg_and_tlv(key, tlv_sha_to_sha(tlv_type)) + return True + except: + pass + + return False class Image: @@ -336,17 +408,13 @@ def ecies_hkdf(self, enckey, plainkey): def create(self, key, public_key_format, enckey, dependencies=None, sw_type=None, custom_tlvs=None, encrypt_keylen=128, clear=False, - fixed_sig=None, pub_key=None, vector_to_sign=None): + fixed_sig=None, pub_key=None, vector_to_sign=None, user_sha='auto'): self.enckey = enckey - # Check what hashing algorithm should be used - if (key and isinstance(key, ecdsa.ECDSA384P1) - or pub_key and isinstance(pub_key, ecdsa.ECDSA384P1Public)): - hash_algorithm = hashlib.sha384 - hash_tlv = "SHA384" - else: - hash_algorithm = hashlib.sha256 - hash_tlv = "SHA256" + # key decides on sha, then pub_key; of both are none default is used + check_key = key if key is not None else pub_key + hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha) + # Calculate the hash of the public key if key is not None: pub = key.get_public_bytes() @@ -466,11 +534,14 @@ def create(self, key, public_key_format, enckey, dependencies=None, tlv = TLV(self.endian) - # Note that ecdsa wants to do the hashing itself, which means - # we get to hash it twice. + # These signature is done over sha of image. In case of + # EC signatures so called Pure algorithm, designated to be run + # over entire message is used with sha of image as message, + # so, for example, in case of ED25519 we have here SHAxxx-ED25519-SHA512. sha = hash_algorithm() sha.update(self.payload) digest = sha.digest() + message = digest; tlv.add(hash_tlv, digest) if vector_to_sign == 'payload': @@ -499,7 +570,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, sig = key.sign(bytes(self.payload)) else: print(os.path.basename(__file__) + ": sign the digest") - sig = key.sign_digest(digest) + sig = key.sign_digest(message) tlv.add(key.sig_tlv(), sig) self.signature = sig elif fixed_sig is not None and key is None: @@ -678,7 +749,7 @@ def verify(imgfile, key): while tlv_off < tlv_end: tlv = b[tlv_off:tlv_off + TLV_SIZE] tlv_type, _, tlv_len = struct.unpack('BBH', tlv) - if tlv_type == TLV_VALUES["SHA256"] or tlv_type == TLV_VALUES["SHA384"]: + if is_sha_tlv(tlv_type): if not tlv_matches_key_type(tlv_type, key): return VerifyResult.KEY_MISMATCH, None, None off = tlv_off + TLV_SIZE diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index cc2cf9c58..848fd3110 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -72,6 +72,7 @@ def gen_x25519(keyfile, passwd): 'x25519': gen_x25519, } valid_formats = ['openssl', 'pkcs8'] +valid_sha = [ 'auto', '256', '384', '512' ] def load_signature(sigfile): @@ -401,6 +402,9 @@ def convert(self, value, param, ctx): @click.option('--sig-out', metavar='filename', help='Path to the file to which signature will be written. ' 'The image signature will be encoded as base64 formatted string') +@click.option('--sha', 'user_sha', type=click.Choice(valid_sha), default='auto', + help='selected sha algorithm to use; defaults to "auto" which is 256 if ' + 'no cryptographic signature is used, or default for signature type') @click.option('--vector-to-sign', type=click.Choice(['payload', 'digest']), help='send to OUTFILE the payload or payload''s digest instead ' 'of complied image. These data can be used for external image ' @@ -413,7 +417,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, endian, encrypt_keylen, encrypt, infile, outfile, dependencies, load_addr, hex_addr, erased_val, save_enctlv, security_counter, boot_record, custom_tlv, rom_fixed, max_align, clear, fix_sig, - fix_sig_pubkey, sig_out, vector_to_sign, non_bootable): + fix_sig_pubkey, sig_out, user_sha, vector_to_sign, non_bootable): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -481,7 +485,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, int(encrypt_keylen), clear, baked_signature, - pub_key, vector_to_sign) + pub_key, vector_to_sign, user_sha) img.save(outfile, hex_addr) if sig_out is not None: From 6bf969fa1afb5ef41d0905edfc506c1264fa2cf2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 18 Jul 2024 17:47:43 +0000 Subject: [PATCH 003/287] [nrf fromlist] boot: Replace boot_encrypt by boot_enc_encrypt and boot_enc_decrypt To be able to implement encryption with API that requires different calls for encryption and encryption, the boot_encrypt needs to be replaced with encryption/decryption specific functions. Upstream PR #: 2017 Signed-off-by: Dominik Ermel (cherry picked from commit 18781c56da59566bcbf658c3dfc80a1365a009de) (cherry picked from commit a92ee3cd0cf7ad9096df4e13dc6a8f1b2b43663b) --- boot/boot_serial/src/boot_serial_encryption.c | 2 +- boot/bootutil/include/bootutil/enc_key.h | 4 ++- boot/bootutil/src/encrypted.c | 31 ++++++++++++++++--- boot/bootutil/src/image_validate.c | 4 +-- boot/bootutil/src/loader.c | 19 +++++++----- 5 files changed, 44 insertions(+), 16 deletions(-) diff --git a/boot/boot_serial/src/boot_serial_encryption.c b/boot/boot_serial/src/boot_serial_encryption.c index 7d3b47c72..c4bd7d87b 100644 --- a/boot/boot_serial/src/boot_serial_encryption.c +++ b/boot/boot_serial/src/boot_serial_encryption.c @@ -171,7 +171,7 @@ decrypt_region_inplace(struct boot_loader_state *state, blk_sz = tlv_off - (off + bytes_copied); } } - boot_encrypt(BOOT_CURR_ENC(state), slot, + boot_enc_decrypt(BOOT_CURR_ENC(state), slot, (off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz, blk_off, &buf[idx]); } diff --git a/boot/bootutil/include/bootutil/enc_key.h b/boot/bootutil/include/bootutil/enc_key.h index 84e05e72f..4ff2432cd 100644 --- a/boot/bootutil/include/bootutil/enc_key.h +++ b/boot/bootutil/include/bootutil/enc_key.h @@ -70,7 +70,9 @@ 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_encrypt(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); diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index d094ea77b..8449a28dd 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -688,14 +688,13 @@ boot_enc_valid(struct enc_key_data *enc_state, int slot) } void -boot_encrypt(struct enc_key_data *enc_state, int slot, uint32_t off, +boot_enc_encrypt(struct enc_key_data *enc_state, int slot, uint32_t off, uint32_t sz, uint32_t blk_off, uint8_t *buf) { - struct enc_key_data *enc; + struct enc_key_data *enc = &enc_state[slot]; uint8_t nonce[16]; - /* boot_copy_region will call boot_encrypt with sz = 0 when skipping over - the TLVs. */ + /* Nothing to do with size == 0 */ if (sz == 0) { return; } @@ -707,11 +706,33 @@ boot_encrypt(struct enc_key_data *enc_state, int slot, uint32_t off, nonce[14] = (uint8_t)(off >> 8); nonce[15] = (uint8_t)off; - enc = &enc_state[slot]; assert(enc->valid == 1); bootutil_aes_ctr_encrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, 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) +{ + struct enc_key_data *enc = &enc_state[slot]; + uint8_t nonce[16]; + + /* Nothing to do with size == 0 */ + if (sz == 0) { + return; + } + + memset(nonce, 0, 12); + off >>= 4; + nonce[12] = (uint8_t)(off >> 24); + nonce[13] = (uint8_t)(off >> 16); + nonce[14] = (uint8_t)(off >> 8); + nonce[15] = (uint8_t)off; + + assert(enc->valid == 1); + bootutil_aes_ctr_decrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, buf); +} + /** * Clears encrypted state after use. */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index b3f008989..ec5d986df 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -153,8 +153,8 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, if (off >= hdr_size && off < tlv_off) { blk_off = (off - hdr_size) & 0xf; - boot_encrypt(enc_state, slot, off - hdr_size, - blk_sz, blk_off, tmp_buf); + boot_enc_decrypt(enc_state, slot, off - hdr_size, + blk_sz, blk_off, tmp_buf); } } #endif diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 3f0793388..deea7dffa 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1359,9 +1359,15 @@ boot_copy_region(struct boot_loader_state *state, blk_sz = tlv_off - abs_off; } } - boot_encrypt(BOOT_CURR_ENC(state), source_slot, - (abs_off + idx) - hdr->ih_hdr_size, blk_sz, - blk_off, &buf[idx]); + if (source_slot == 0) { + boot_enc_encrypt(BOOT_CURR_ENC(state), source_slot, + (abs_off + idx) - hdr->ih_hdr_size, blk_sz, + blk_off, &buf[idx]); + } else { + boot_enc_decrypt(BOOT_CURR_ENC(state), source_slot, + (abs_off + idx) - hdr->ih_hdr_size, blk_sz, + blk_off, &buf[idx]); + } } } #endif @@ -2894,10 +2900,9 @@ boot_decrypt_and_copy_image_to_sram(struct boot_loader_state *state, * Part of the chunk is encrypted payload */ blk_sz = tlv_off - (bytes_copied); } - boot_encrypt(BOOT_CURR_ENC(state), slot, - (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz, - blk_off, cur_dst); - + boot_enc_decrypt(BOOT_CURR_ENC(state), slot, + (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz, + blk_off, cur_dst); bytes_copied += chunk_sz; } rc = 0; From 8d844dfbf40889a18025b45d709a33283e566bb4 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Fri, 9 Aug 2024 12:16:40 +0200 Subject: [PATCH 004/287] [nrf fromlist] scripts: imgtool: compression Adds LZMA2 compression to imgtool. Python lzma library is unable to compress with proper parameters while using "ALONE" container, therefore 2 header bytes are calculated and added to payload by imgtool. Upstream PR #: 2038 Signed-off-by: Mateusz Michalek (cherry picked from commit 237b8b98a97103dd27c51cb73fa60841bb9187d0) (cherry picked from commit 2b709522675eabd2dd57dc8c484b561bc0c61657) --- scripts/imgtool/image.py | 71 ++++++++++++++++++++++++++++++++---- scripts/imgtool/main.py | 79 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 135 insertions(+), 15 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 53b19ef1d..1f43ccf82 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -20,7 +20,15 @@ Image signing and management. """ +from . import version as versmod +from .boot_record import create_sw_component_data +import click +import copy +from enum import Enum +import array +from intelhex import IntelHex import hashlib +import array import os.path import struct from enum import Enum @@ -60,6 +68,8 @@ 'NON_BOOTABLE': 0x0000010, 'RAM_LOAD': 0x0000020, 'ROM_FIXED': 0x0000100, + 'COMPRESSED_LZMA1': 0x0000200, + 'COMPRESSED_LZMA2': 0x0000400, } TLV_VALUES = { @@ -79,6 +89,9 @@ 'DEPENDENCY': 0x40, 'SEC_CNT': 0x50, 'BOOT_RECORD': 0x60, + 'DECOMP_SIZE': 0x70, + 'DECOMP_SHA': 0x71, + 'DECOMP_SIGNATURE': 0x72, } TLV_SIZE = 4 @@ -237,6 +250,9 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, if load_addr and rom_fixed: raise click.UsageError("Can not set rom_fixed and load_addr at the same time") + self.image_hash = None + self.image_size = None + self.signature = None self.version = version or versmod.decode_version("0") self.header_size = header_size self.pad_header = pad_header @@ -252,6 +268,7 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, self.rom_fixed = rom_fixed self.erased_val = 0xff if erased_val is None else int(erased_val, 0) self.payload = [] + self.infile_data = [] self.enckey = None self.save_enctlv = save_enctlv self.enctlv_len = 0 @@ -300,19 +317,39 @@ def __repr__(self): self.__class__.__name__, len(self.payload)) - def load(self, path): + def load(self, path, compression_header=None): """Load an image from a given file""" ext = os.path.splitext(path)[1][1:].lower() try: if ext == INTEL_HEX_EXT: ih = IntelHex(path) - self.payload = ih.tobinarray() + self.infile_data = ih.tobinarray() + self.payload = copy.copy(self.infile_data) self.base_addr = ih.minaddr() else: with open(path, 'rb') as f: - self.payload = f.read() + self.infile_data = f.read() + self.payload = copy.copy(self.infile_data) + if compression_header is not None: + self.payload = compression_header + self.payload except FileNotFoundError: raise click.UsageError("Input file not found") + self.image_size = len(self.payload) + + # Add the image header if needed. + if self.pad_header and self.header_size > 0: + if self.base_addr: + # Adjust base_addr for new header + self.base_addr -= self.header_size + self.payload = bytes([self.erased_val] * self.header_size) + \ + self.payload + + self.check_header() + + def load_compressed(self, data, compression_header): + """Load an image from buffer""" + self.payload = compression_header + data + self.image_size = len(self.payload) # Add the image header if needed. if self.pad_header and self.header_size > 0: @@ -407,7 +444,8 @@ def ecies_hkdf(self, enckey, plainkey): return cipherkey, ciphermac, pubk def create(self, key, public_key_format, enckey, dependencies=None, - sw_type=None, custom_tlvs=None, encrypt_keylen=128, clear=False, + sw_type=None, custom_tlvs=None, compression_tlvs=None, + compression_type=None, encrypt_keylen=128, clear=False, fixed_sig=None, pub_key=None, vector_to_sign=None, user_sha='auto'): self.enckey = enckey @@ -470,6 +508,9 @@ def create(self, key, public_key_format, enckey, dependencies=None, dependencies_num = len(dependencies[DEP_IMAGES_KEY]) protected_tlv_size += (dependencies_num * 16) + if compression_tlvs is not None: + for value in compression_tlvs.values(): + protected_tlv_size += TLV_SIZE + len(value) if custom_tlvs is not None: for value in custom_tlvs.values(): protected_tlv_size += TLV_SIZE + len(value) @@ -491,11 +532,15 @@ def create(self, key, public_key_format, enckey, dependencies=None, else: self.payload.extend(pad) + compression_flags = 0x0 + if compression_tlvs is not None: + if compression_type == "lzma2": + compression_flags = IMAGE_F['COMPRESSED_LZMA2'] # This adds the header to the payload as well if encrypt_keylen == 256: - self.add_header(enckey, protected_tlv_size, 256) + self.add_header(enckey, protected_tlv_size, compression_flags, 256) else: - self.add_header(enckey, protected_tlv_size) + self.add_header(enckey, protected_tlv_size, compression_flags) prot_tlv = TLV(self.endian, TLV_PROT_INFO_MAGIC) @@ -525,6 +570,9 @@ def create(self, key, public_key_format, enckey, dependencies=None, ) prot_tlv.add('DEPENDENCY', payload) + if compression_tlvs is not None: + for tag, value in compression_tlvs.items(): + prot_tlv.add(tag, value) if custom_tlvs is not None: for tag, value in custom_tlvs.items(): prot_tlv.add(tag, value) @@ -543,6 +591,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, digest = sha.digest() message = digest; tlv.add(hash_tlv, digest) + self.image_hash = digest if vector_to_sign == 'payload': # Stop amending data to the image @@ -622,10 +671,16 @@ def create(self, key, public_key_format, enckey, dependencies=None, self.check_trailer() + def get_struct_endian(self): + return STRUCT_ENDIAN_DICT[self.endian] + def get_signature(self): return self.signature - def add_header(self, enckey, protected_tlv_size, aes_length=128): + def get_infile_data(self): + return self.infile_data + + def add_header(self, enckey, protected_tlv_size, compression_flags, aes_length=128): """Install the image header.""" flags = 0 @@ -663,7 +718,7 @@ def add_header(self, enckey, protected_tlv_size, aes_length=128): protected_tlv_size, # TLV Info header + # Protected TLVs len(self.payload) - self.header_size, # ImageSz - flags, + flags | compression_flags, self.version.major, self.version.minor or 0, self.version.revision or 0, diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 848fd3110..9e91582b9 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -22,6 +22,10 @@ import getpass import imgtool.keys as keys import sys +import struct +import os +import lzma +import hashlib import base64 from imgtool import image, imgtool_version from imgtool.version import decode_version @@ -29,6 +33,13 @@ from .keys import ( RSAUsageError, ECDSAUsageError, Ed25519UsageError, X25519UsageError) +comp_default_dictsize=131072 +comp_default_pb=2 +comp_default_lc=3 +comp_default_lp=1 +comp_default_preset=9 + + MIN_PYTHON_VERSION = (3, 6) if sys.version_info < MIN_PYTHON_VERSION: sys.exit("Python %s.%s or newer is required by imgtool." @@ -300,6 +311,14 @@ def get_dependencies(ctx, param, value): dependencies[image.DEP_VERSIONS_KEY] = versions return dependencies +def create_lzma2_header(dictsize, pb, lc, lp): + header = bytearray() + for i in range(0, 40): + if dictsize <= ((2 | ((i) & 1)) << int((i) / 2 + 11)): + header.append(i) + break + header.append( ( pb * 5 + lp) * 9 + lc) + return header class BasedIntParamType(click.ParamType): name = 'integer' @@ -343,6 +362,11 @@ def convert(self, value, param, ctx): type=click.Choice(['128', '256']), help='When encrypting the image using AES, select a 128 bit or ' '256 bit key len.') +@click.option('--compression', default='disabled', + type=click.Choice(['disabled', 'lzma2']), + help='Enable image compression using specified type. ' + 'Will fall back without image compression automatically ' + 'if the compression increases the image size.') @click.option('-c', '--clear', required=False, is_flag=True, default=False, help='Output a non-encrypted image with encryption capabilities,' 'so it can be installed in the primary slot, and encrypted ' @@ -414,10 +438,11 @@ def convert(self, value, param, ctx): .hex extension, otherwise binary format is used''') def sign(key, public_key_format, align, version, pad_sig, header_size, pad_header, slot_size, pad, confirm, max_sectors, overwrite_only, - endian, encrypt_keylen, encrypt, infile, outfile, dependencies, - load_addr, hex_addr, erased_val, save_enctlv, security_counter, - boot_record, custom_tlv, rom_fixed, max_align, clear, fix_sig, - fix_sig_pubkey, sig_out, user_sha, vector_to_sign, non_bootable): + endian, encrypt_keylen, encrypt, compression, infile, outfile, + dependencies, load_addr, hex_addr, erased_val, save_enctlv, + security_counter, boot_record, custom_tlv, rom_fixed, max_align, + clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, vector_to_sign, + non_bootable): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -431,6 +456,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, erased_val=erased_val, save_enctlv=save_enctlv, security_counter=security_counter, max_align=max_align, non_bootable=non_bootable) + compression_tlvs = {} img.load(infile) key = load_key(key) if key else None enckey = load_key(encrypt) if encrypt else None @@ -484,10 +510,49 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, } img.create(key, public_key_format, enckey, dependencies, boot_record, - custom_tlvs, int(encrypt_keylen), clear, baked_signature, - pub_key, vector_to_sign, user_sha) + custom_tlvs, compression_tlvs, int(encrypt_keylen), clear, + baked_signature, pub_key, vector_to_sign, user_sha) + + if compression == "lzma2" : + compressed_img = image.Image(version=decode_version(version), + header_size=header_size, pad_header=pad_header, + pad=pad, confirm=confirm, align=int(align), + slot_size=slot_size, max_sectors=max_sectors, + overwrite_only=overwrite_only, endian=endian, + load_addr=load_addr, rom_fixed=rom_fixed, + erased_val=erased_val, save_enctlv=save_enctlv, + security_counter=security_counter, max_align=max_align) + compression_filters = [ + {"id": lzma.FILTER_LZMA2, "preset": comp_default_preset, + "dict_size": comp_default_dictsize, "lp": comp_default_lp, + "lc": comp_default_lc} + ] + compressed_data = lzma.compress(img.get_infile_data(),filters=compression_filters, + format=lzma.FORMAT_RAW) + uncompressed_size = len(img.get_infile_data()) + compressed_size = len(compressed_data) + print("compressed image size:", compressed_size, + "bytes\noriginal image size:", uncompressed_size, "bytes") + compression_tlvs["DECOMP_SIZE"] = struct.pack( + img.get_struct_endian() + 'L', img.image_size) + compression_tlvs["DECOMP_SHA"] = img.image_hash + compression_tlvs_size = len(compression_tlvs["DECOMP_SIZE"]) + compression_tlvs_size += len(compression_tlvs["DECOMP_SHA"]) + if img.get_signature() is not None and img.get_signature() != "" : + compression_tlvs["DECOMP_SIGNATURE"] = img.get_signature() + compression_tlvs_size += len(compression_tlvs["DECOMP_SIGNATURE"]) + if (compressed_size + compression_tlvs_size) < uncompressed_size: + compression_header = create_lzma2_header( + dictsize = comp_default_dictsize, pb = comp_default_pb, + lc = comp_default_lc, lp = comp_default_lp) + compressed_img.load_compressed(compressed_data, compression_header) + compressed_img.base_addr = img.base_addr + compressed_img.create(key, public_key_format, enckey, + dependencies, boot_record, custom_tlvs, compression_tlvs, + compression, int(encrypt_keylen), clear, baked_signature, + pub_key, vector_to_sign) + img = compressed_img img.save(outfile, hex_addr) - if sig_out is not None: new_signature = img.get_signature() save_signature(sig_out, new_signature) From 1d7c7c1b0418519cc13fb0897ba6a52be80168b5 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 25 Sep 2024 07:47:08 +0100 Subject: [PATCH 005/287] [nrf fromtree] boot: bootutil: loader: Fix slot info for directXIP/RAM load Fixes an issue when either of these modes is used with serial recovery slot info enabled Signed-off-by: Jamie McCrae (cherry picked from commit 30109df32a65840d593e8aef2e2186d5337196f3) (cherry picked from commit d44d7bcc4b825a087b95422c725f774aa726d6ec) (cherry picked from commit 50402569ae9342350f9a93196fcf82a987964053) --- boot/bootutil/src/loader.c | 149 ++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 61 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index deea7dffa..0219220d0 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -301,6 +301,93 @@ boot_version_cmp(const struct image_version *ver1, } #endif +#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ +defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +#if !defined(__BOOTSIM__) +static void boot_get_sector_buffers(struct sector_buffer_t *buffers) +{ + /* The array of slot sectors are defined here (as opposed to file scope) so + * that they don't get allocated for non-boot-loader apps. This is + * necessary because the gcc option "-fdata-sections" doesn't seem to have + * any effect in older gcc versions (e.g., 4.8.4). + */ + static boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; + static boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; +#if MCUBOOT_SWAP_USING_SCRATCH + static boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS]; +#endif + + buffers->primary = (boot_sector_t *)&primary_slot_sectors; + buffers->secondary = (boot_sector_t *)&secondary_slot_sectors; +#if MCUBOOT_SWAP_USING_SCRATCH + buffers->scratch = (boot_sector_t *)&scratch_sectors; +#endif +} +#endif + +static int +boot_initialize_area(struct boot_loader_state *state, int flash_area) +{ + uint32_t num_sectors = BOOT_MAX_IMG_SECTORS; + boot_sector_t *out_sectors; + uint32_t *out_num_sectors; + int rc; + + num_sectors = BOOT_MAX_IMG_SECTORS; + + if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) { + out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors; + out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors; + } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { + out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors; + out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors; +#if MCUBOOT_SWAP_USING_SCRATCH + } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) { + out_sectors = state->scratch.sectors; + out_num_sectors = &state->scratch.num_sectors; +#endif + } else { + return BOOT_EFLASH; + } + +#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS + rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors); +#else + _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed"); + rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors); +#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */ + if (rc != 0) { + return rc; + } + *out_num_sectors = num_sectors; + return 0; +} +#endif + +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +static int +boot_read_sectors_recovery(struct boot_loader_state *state) +{ + uint8_t image_index; + int rc; + + image_index = BOOT_CURR_IMG(state); + + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index)); + if (rc != 0) { + return BOOT_EFLASH; + } + + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index)); + if (rc != 0) { + /* We need to differentiate from the primary image issue */ + return BOOT_EFLASH_SEC; + } + + return 0; +} +#endif + #if (BOOT_IMAGE_NUMBER > 1) @@ -617,44 +704,6 @@ boot_write_sz(struct boot_loader_state *state) return elem_sz; } -static int -boot_initialize_area(struct boot_loader_state *state, int flash_area) -{ - uint32_t num_sectors = BOOT_MAX_IMG_SECTORS; - boot_sector_t *out_sectors; - uint32_t *out_num_sectors; - int rc; - - num_sectors = BOOT_MAX_IMG_SECTORS; - - if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) { - out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors; - out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors; - } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { - out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors; - out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors; -#if MCUBOOT_SWAP_USING_SCRATCH - } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) { - out_sectors = state->scratch.sectors; - out_num_sectors = &state->scratch.num_sectors; -#endif - } else { - return BOOT_EFLASH; - } - -#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS - rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors); -#else - _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed"); - rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors); -#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */ - if (rc != 0) { - return rc; - } - *out_num_sectors = num_sectors; - return 0; -} - /** * Determines the sector layout of both image slots and the scratch area. * This information is necessary for calculating the number of bytes to erase @@ -2161,28 +2210,6 @@ check_downgrade_prevention(struct boot_loader_state *state) #endif } -#if !defined(__BOOTSIM__) -static void boot_get_sector_buffers(struct sector_buffer_t *buffers) -{ - /* The array of slot sectors are defined here (as opposed to file scope) so - * that they don't get allocated for non-boot-loader apps. This is - * necessary because the gcc option "-fdata-sections" doesn't seem to have - * any effect in older gcc versions (e.g., 4.8.4). - */ - static boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; - static boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; -#if MCUBOOT_SWAP_USING_SCRATCH - static boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS]; -#endif - - buffers->primary = (boot_sector_t *)&primary_slot_sectors; - buffers->secondary = (boot_sector_t *)&secondary_slot_sectors; -#if MCUBOOT_SWAP_USING_SCRATCH - buffers->scratch = (boot_sector_t *)&scratch_sectors; -#endif -} -#endif - fih_ret context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) { @@ -3491,7 +3518,7 @@ static void boot_fetch_slot_state_sizes(void) #endif /* Determine the sector layout of the image slots and scratch area. */ - rc = boot_read_sectors(&boot_data); + rc = boot_read_sectors_recovery(&boot_data); if (rc == 0) { max_size = app_max_size(&boot_data); From 55d5997b2edf0429f50dd32091de66f850d5ea95 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 27 Sep 2024 13:31:08 +0100 Subject: [PATCH 006/287] [nrf fromtree] boot: bootutil: loader: Fix issue with using pointers Fixes an issue whereby static buffers were changed into pointers, whereby they are then assumed to be the size of a pointer rather than the size of the actual buffers Signed-off-by: Jamie McCrae (cherry picked from commit 3a195f2207d5eadf45a5c989a870e91aff020d86) Signed-off-by: Dominik Ermel (cherry picked from commit 22adc04fc4b35a6ee477675c8a33e038a98258de) (cherry picked from commit 218c63da87e65743ad8f0a47ff0cd21ce8275c7e) --- boot/bootutil/src/loader.c | 55 ++++++++++---------------------------- 1 file changed, 14 insertions(+), 41 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 0219220d0..12d4abf40 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -67,17 +67,22 @@ static struct boot_loader_state boot_data; static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; #endif +#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ +defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) #if !defined(__BOOTSIM__) /* Used for holding static buffers in multiple functions to work around issues * in older versions of gcc (e.g. 4.8.4) */ struct sector_buffer_t { - boot_sector_t *primary; - boot_sector_t *secondary; + boot_sector_t primary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; + boot_sector_t secondary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; #if MCUBOOT_SWAP_USING_SCRATCH - boot_sector_t *scratch; + boot_sector_t scratch[BOOT_MAX_IMG_SECTORS]; #endif }; + +static struct sector_buffer_t sector_buffers; +#endif #endif #if (BOOT_IMAGE_NUMBER > 1) @@ -303,28 +308,6 @@ boot_version_cmp(const struct image_version *ver1, #if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) -#if !defined(__BOOTSIM__) -static void boot_get_sector_buffers(struct sector_buffer_t *buffers) -{ - /* The array of slot sectors are defined here (as opposed to file scope) so - * that they don't get allocated for non-boot-loader apps. This is - * necessary because the gcc option "-fdata-sections" doesn't seem to have - * any effect in older gcc versions (e.g., 4.8.4). - */ - static boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; - static boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; -#if MCUBOOT_SWAP_USING_SCRATCH - static boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS]; -#endif - - buffers->primary = (boot_sector_t *)&primary_slot_sectors; - buffers->secondary = (boot_sector_t *)&secondary_slot_sectors; -#if MCUBOOT_SWAP_USING_SCRATCH - buffers->scratch = (boot_sector_t *)&scratch_sectors; -#endif -} -#endif - static int boot_initialize_area(struct boot_loader_state *state, int flash_area) { @@ -2215,9 +2198,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) { size_t slot; struct boot_status bs; -#if !defined(__BOOTSIM__) - struct sector_buffer_t sector_buffers; -#endif int rc = -1; FIH_DECLARE(fih_rc, FIH_FAILURE); int fa_id; @@ -2244,10 +2224,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) (void)has_upgrade; #endif -#if !defined(__BOOTSIM__) - boot_get_sector_buffers(§or_buffers); -#endif - /* Iterate over all the images. By the end of the loop the swap type has * to be determined for each image and all aborted swaps have to be * completed. @@ -2270,9 +2246,9 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) #if !defined(__BOOTSIM__) BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors = - §or_buffers.primary[image_index]; + sector_buffers.primary[image_index]; BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors = - §or_buffers.secondary[image_index]; + sector_buffers.secondary[image_index]; #if MCUBOOT_SWAP_USING_SCRATCH state->scratch.sectors = sector_buffers.scratch; #endif @@ -3468,30 +3444,27 @@ void boot_state_clear(struct boot_loader_state *state) #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) /** * Reads image data to find out the maximum application sizes. Only needs to - * be called in serial recovery mode, as the state informatio is unpopulated + * be called in serial recovery mode, as the state information is unpopulated * at that time */ static void boot_fetch_slot_state_sizes(void) { - struct sector_buffer_t sector_buffers; size_t slot; int rc = -1; int fa_id; int image_index; - boot_get_sector_buffers(§or_buffers); - IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) { int max_size = 0; image_index = BOOT_CURR_IMG(&boot_data); BOOT_IMG(&boot_data, BOOT_PRIMARY_SLOT).sectors = - §or_buffers.primary[image_index]; + sector_buffers.primary[image_index]; BOOT_IMG(&boot_data, BOOT_SECONDARY_SLOT).sectors = - §or_buffers.secondary[image_index]; + sector_buffers.secondary[image_index]; #if MCUBOOT_SWAP_USING_SCRATCH - boot_data.scratch.sectors = sector_buffers.scratch;; + boot_data.scratch.sectors = sector_buffers.scratch; #endif /* Open primary and secondary image areas for the duration From c79d930185b5cbf1bca7b957ea3168943dfd46eb Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Fri, 9 Aug 2024 12:16:40 +0200 Subject: [PATCH 007/287] [nrf fromtree] scripts: imgtool: compression Adds LZMA2 compression to imgtool. Python lzma library is unable to compress with proper parameters while using "ALONE" container, therefore 2 header bytes are calculated and added to payload by imgtool. Signed-off-by: Mateusz Michalek (cherry picked from commit 35c9291fcafafe8608722e0ec3c801178884f0ef) (cherry picked from commit 10f3dbe511f9e480e9114de44819208bcc4237de) (cherry picked from commit 3d346f7cab8087121aacce2d840fc3f827bba28c) --- scripts/imgtool/image.py | 4 +--- scripts/imgtool/main.py | 10 +++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 1f43ccf82..10de2a33f 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -317,7 +317,7 @@ def __repr__(self): self.__class__.__name__, len(self.payload)) - def load(self, path, compression_header=None): + def load(self, path): """Load an image from a given file""" ext = os.path.splitext(path)[1][1:].lower() try: @@ -330,8 +330,6 @@ def load(self, path, compression_header=None): with open(path, 'rb') as f: self.infile_data = f.read() self.payload = copy.copy(self.infile_data) - if compression_header is not None: - self.payload = compression_header + self.payload except FileNotFoundError: raise click.UsageError("Input file not found") self.image_size = len(self.payload) diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 9e91582b9..03bb565c5 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -513,7 +513,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, custom_tlvs, compression_tlvs, int(encrypt_keylen), clear, baked_signature, pub_key, vector_to_sign, user_sha) - if compression == "lzma2" : + if compression == "lzma2": compressed_img = image.Image(version=decode_version(version), header_size=header_size, pad_header=pad_header, pad=pad, confirm=confirm, align=int(align), @@ -525,20 +525,20 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, compression_filters = [ {"id": lzma.FILTER_LZMA2, "preset": comp_default_preset, "dict_size": comp_default_dictsize, "lp": comp_default_lp, - "lc": comp_default_lc} + "lc": comp_default_lc} ] compressed_data = lzma.compress(img.get_infile_data(),filters=compression_filters, format=lzma.FORMAT_RAW) uncompressed_size = len(img.get_infile_data()) compressed_size = len(compressed_data) - print("compressed image size:", compressed_size, - "bytes\noriginal image size:", uncompressed_size, "bytes") + print(f"compressed image size: {compressed_size} bytes") + print(f"original image size: {uncompressed_size} bytes") compression_tlvs["DECOMP_SIZE"] = struct.pack( img.get_struct_endian() + 'L', img.image_size) compression_tlvs["DECOMP_SHA"] = img.image_hash compression_tlvs_size = len(compression_tlvs["DECOMP_SIZE"]) compression_tlvs_size += len(compression_tlvs["DECOMP_SHA"]) - if img.get_signature() is not None and img.get_signature() != "" : + if img.get_signature(): compression_tlvs["DECOMP_SIGNATURE"] = img.get_signature() compression_tlvs_size += len(compression_tlvs["DECOMP_SIGNATURE"]) if (compressed_size + compression_tlvs_size) < uncompressed_size: From 36a248f6857bea9630ab40c8230beb5945e9455e Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 7 Oct 2024 08:37:48 +0100 Subject: [PATCH 008/287] [nrf fromlist] boot: bootutil: swap_scratch: Fix compressed image sector size check Fixes an issue with compressed update support whereby it would wrong continue to check all sector sizes and error due to the sector sizes of the secondary slot being 0 until overflow Upstream PR #: 2085 Signed-off-by: Jamie McCrae (cherry picked from commit 8c814cbbae3036d7f5778f32abeade142ad8e30e) (cherry picked from commit a46eb1e6a9909d4ba2a728ed262ddd6ddbe9498b) --- boot/bootutil/src/swap_scratch.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index 24159d1db..f60109120 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -191,7 +191,17 @@ boot_slots_compatible(struct boot_loader_state *state) smaller = 1; i++; } else { - sz1 += boot_img_sector_size(state, BOOT_SECONDARY_SLOT, j); + size_t sector_size = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, j); + +#ifdef MCUBOOT_DECOMPRESS_IMAGES + if (sector_size == 0) { + /* Since this supports decompressed images, we can safely exit if slot1 is + * smaller than slot0. + */ + break; + } +#endif + sz1 += sector_size; /* Guarantee that multiple sectors of the primary slot * fit into the secondary slot. */ From 0f60b02be1384392975deabda08645fa1d5ae1a4 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Fri, 4 Oct 2024 13:36:52 +0200 Subject: [PATCH 009/287] [nrf fromlist] scripts: imgtool: compression ARM thumb filter Adds ARM thumb filter to imgtool's LZMA2 compression. Upstream PR #: 2084 Signed-off-by: Mateusz Michalek (cherry picked from commit 94212b4e3853b7b09acf0e2e1ec2b895bbbb2948) (cherry picked from commit 10df2a3ac9b495d1796d0e9fa9321d4c865dfd39) --- scripts/imgtool/image.py | 5 ++++- scripts/imgtool/main.py | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 10de2a33f..84811806d 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -70,6 +70,7 @@ 'ROM_FIXED': 0x0000100, 'COMPRESSED_LZMA1': 0x0000200, 'COMPRESSED_LZMA2': 0x0000400, + 'COMPRESSED_ARM_THUMB': 0x0000800, } TLV_VALUES = { @@ -532,8 +533,10 @@ def create(self, key, public_key_format, enckey, dependencies=None, compression_flags = 0x0 if compression_tlvs is not None: - if compression_type == "lzma2": + if compression_type in ["lzma2", "lzma2armthumb"]: compression_flags = IMAGE_F['COMPRESSED_LZMA2'] + if compression_type == "lzma2armthumb": + compression_flags |= IMAGE_F['COMPRESSED_ARM_THUMB'] # This adds the header to the payload as well if encrypt_keylen == 256: self.add_header(enckey, protected_tlv_size, compression_flags, 256) diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 03bb565c5..94952a838 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -363,7 +363,7 @@ def convert(self, value, param, ctx): help='When encrypting the image using AES, select a 128 bit or ' '256 bit key len.') @click.option('--compression', default='disabled', - type=click.Choice(['disabled', 'lzma2']), + type=click.Choice(['disabled', 'lzma2', 'lzma2armthumb']), help='Enable image compression using specified type. ' 'Will fall back without image compression automatically ' 'if the compression increases the image size.') @@ -513,7 +513,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, custom_tlvs, compression_tlvs, int(encrypt_keylen), clear, baked_signature, pub_key, vector_to_sign, user_sha) - if compression == "lzma2": + if compression in ["lzma2", "lzma2armthumb"]: compressed_img = image.Image(version=decode_version(version), header_size=header_size, pad_header=pad_header, pad=pad, confirm=confirm, align=int(align), @@ -527,6 +527,8 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, "dict_size": comp_default_dictsize, "lp": comp_default_lp, "lc": comp_default_lc} ] + if compression == "lzma2armthumb": + compression_filters.insert(0, {"id":lzma.FILTER_ARMTHUMB}) compressed_data = lzma.compress(img.get_infile_data(),filters=compression_filters, format=lzma.FORMAT_RAW) uncompressed_size = len(img.get_infile_data()) From 6376fe5db1ab5aad6aca88858ad95d09dc1d7acb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 8 Oct 2024 13:37:01 +0000 Subject: [PATCH 010/287] [nrf fromlist] zephyr: Fixing Kconfig dependency for SHA512 The SHA512_ALLOW Kconfig has been added to allow signature algorithms to select which SHA they support. Unfortunately it has been given dependency on PSA crypto, which now is problematic because if signature algorithm wants to indicate that it allows SHA512 it immediately becomes dependent on PSA crypto. The commit removes the dependency. Upstream PR #: 2088 Signed-off-by: Dominik Ermel (cherry picked from commit 7bfbd35cd6930ca78b24f3005c104cfe1fccd3da) (cherry picked from commit af4e468f950f57145127f0df497f94424acdaae3) --- boot/zephyr/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 2dd084714..931bccbbb 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -85,7 +85,6 @@ config BOOT_IMG_HASH_ALG_SHA384_ALLOW config BOOT_IMG_HASH_ALG_SHA512_ALLOW bool - depends on BOOT_USE_PSA_CRYPTO help Hidden option set by configurations that allow SHA512 From 9c2a359674e658866e96a1242bfac7730e37f259 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Tue, 15 Oct 2024 16:01:18 +0200 Subject: [PATCH 011/287] [nrf fromlist] scipts: imgtool: bugfix #2096 fixing broken encryption caused by shift in function parameters. Upstream PR #: 2098 Signed-off-by: Mateusz Michalek (cherry picked from commit 31f74eb6fcd304f185f716138d4bfcc8070bb316) (cherry picked from commit 2b568d8b28c507c322e5b0379b6cafe5d6a91cb2) --- scripts/imgtool/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 94952a838..009d9234c 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -510,7 +510,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, } img.create(key, public_key_format, enckey, dependencies, boot_record, - custom_tlvs, compression_tlvs, int(encrypt_keylen), clear, + custom_tlvs, compression_tlvs, None, int(encrypt_keylen), clear, baked_signature, pub_key, vector_to_sign, user_sha) if compression in ["lzma2", "lzma2armthumb"]: From fe61522a37e7c2cd26ad560fb1068e6c8875a216 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 12 Sep 2024 19:37:40 +0000 Subject: [PATCH 012/287] [nrf fromlist] imgtool: Add pure signature support Adds PureEdDSA signature support. The change includes implementation of SIG_PURE TLV that, when present, indicates the signature that is present is Pure type. Upstream PR #: 2063 Signed-off-by: Dominik Ermel Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 32a6e8cbfd5f042e4503d2789e755f3c89cfd3da) (cherry picked from commit a5786cdafcf6447c949a717f37bc5a2d3c536567) --- scripts/imgtool/image.py | 75 ++++++++++++++++++++++++++++++++-------- scripts/imgtool/main.py | 23 +++++++++--- 2 files changed, 78 insertions(+), 20 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 84811806d..5e10ab78a 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -188,7 +188,15 @@ def tlv_sha_to_sha(tlv): keys.X25519 : ['256', '512'] } -def key_and_user_sha_to_alg_and_tlv(key, user_sha): +ALLOWED_PURE_KEY_SHA = { + keys.Ed25519 : ['512'] +} + +ALLOWED_PURE_SIG_TLVS = [ + TLV_VALUES['ED25519'] +] + +def key_and_user_sha_to_alg_and_tlv(key, user_sha, is_pure = False): """Matches key and user requested sha to sha alogrithm and TLV name. The returned tuple will contain hash functions and TVL name. @@ -202,12 +210,16 @@ def key_and_user_sha_to_alg_and_tlv(key, user_sha): # If key is not None, then we have to filter hash to only allowed allowed = None + allowed_key_ssh = ALLOWED_PURE_KEY_SHA if is_pure else ALLOWED_KEY_SHA try: - allowed = ALLOWED_KEY_SHA[type(key)] + allowed = allowed_key_ssh[type(key)] + except KeyError: raise click.UsageError("Colud not find allowed hash algorithms for {}" .format(type(key))) - if user_sha == 'auto': + + # Pure enforces auto, and user selection is ignored + if user_sha == 'auto' or is_pure: return USER_SHA_TO_ALG_AND_TLV[allowed[0]] if user_sha in allowed: @@ -445,12 +457,13 @@ def ecies_hkdf(self, enckey, plainkey): def create(self, key, public_key_format, enckey, dependencies=None, sw_type=None, custom_tlvs=None, compression_tlvs=None, compression_type=None, encrypt_keylen=128, clear=False, - fixed_sig=None, pub_key=None, vector_to_sign=None, user_sha='auto'): + fixed_sig=None, pub_key=None, vector_to_sign=None, + user_sha='auto', is_pure=False): self.enckey = enckey # key decides on sha, then pub_key; of both are none default is used check_key = key if key is not None else pub_key - hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha) + hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha, is_pure) # Calculate the hash of the public key if key is not None: @@ -590,9 +603,16 @@ def create(self, key, public_key_format, enckey, dependencies=None, sha = hash_algorithm() sha.update(self.payload) digest = sha.digest() - message = digest; tlv.add(hash_tlv, digest) - self.image_hash = digest + # Unless pure, we are signing digest. + message = digest + + if is_pure: + # Note that when Pure signature is used, hash TLV is not present. + message = bytes(self.payload) + e = STRUCT_ENDIAN_DICT[self.endian] + sig_pure = struct.pack(e + '?', True) + tlv.add('SIG_PURE', sig_pure) if vector_to_sign == 'payload': # Stop amending data to the image @@ -784,7 +804,7 @@ def verify(imgfile, key): version = struct.unpack('BBHI', b[20:28]) if magic != IMAGE_MAGIC: - return VerifyResult.INVALID_MAGIC, None, None + return VerifyResult.INVALID_MAGIC, None, None, None tlv_off = header_size + img_size tlv_info = b[tlv_off:tlv_off + TLV_INFO_SIZE] @@ -795,11 +815,27 @@ def verify(imgfile, key): magic, tlv_tot = struct.unpack('HH', tlv_info) if magic != TLV_INFO_MAGIC: - return VerifyResult.INVALID_TLV_INFO_MAGIC, None, None + return VerifyResult.INVALID_TLV_INFO_MAGIC, None, None, None + + # This is set by existence of TLV SIG_PURE + is_pure = False prot_tlv_size = tlv_off hash_region = b[:prot_tlv_size] + tlv_end = tlv_off + tlv_tot + tlv_off += TLV_INFO_SIZE # skip tlv info + + # First scan all TLVs in search of SIG_PURE + while tlv_off < tlv_end: + tlv = b[tlv_off:tlv_off + TLV_SIZE] + tlv_type, _, tlv_len = struct.unpack('BBH', tlv) + if tlv_type == TLV_VALUES['SIG_PURE']: + is_pure = True + break + tlv_off += TLV_SIZE + tlv_len + digest = None + tlv_off = header_size + img_size tlv_end = tlv_off + tlv_tot tlv_off += TLV_INFO_SIZE # skip tlv info while tlv_off < tlv_end: @@ -807,15 +843,15 @@ def verify(imgfile, key): tlv_type, _, tlv_len = struct.unpack('BBH', tlv) if is_sha_tlv(tlv_type): if not tlv_matches_key_type(tlv_type, key): - return VerifyResult.KEY_MISMATCH, None, None + return VerifyResult.KEY_MISMATCH, None, None, None off = tlv_off + TLV_SIZE digest = get_digest(tlv_type, hash_region) if digest == b[off:off + tlv_len]: if key is None: - return VerifyResult.OK, version, digest + return VerifyResult.OK, version, digest, None else: - return VerifyResult.INVALID_HASH, None, None - elif key is not None and tlv_type == TLV_VALUES[key.sig_tlv()]: + return VerifyResult.INVALID_HASH, None, None, None + elif not is_pure and key is not None and tlv_type == TLV_VALUES[key.sig_tlv()]: off = tlv_off + TLV_SIZE tlv_sig = b[off:off + tlv_len] payload = b[:prot_tlv_size] @@ -824,9 +860,18 @@ def verify(imgfile, key): key.verify(tlv_sig, payload) else: key.verify_digest(tlv_sig, digest) - return VerifyResult.OK, version, digest + return VerifyResult.OK, version, digest, None + except InvalidSignature: + # continue to next TLV + pass + elif is_pure and key is not None and tlv_type in ALLOWED_PURE_SIG_TLVS: + off = tlv_off + TLV_SIZE + tlv_sig = b[off:off + tlv_len] + try: + key.verify_digest(tlv_sig, hash_region) + return VerifyResult.OK, version, None, tlv_sig except InvalidSignature: # continue to next TLV pass tlv_off += TLV_SIZE + tlv_len - return VerifyResult.INVALID_SIGNATURE, None, None + return VerifyResult.INVALID_SIGNATURE, None, None, None diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 009d9234c..03d46c907 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -226,11 +226,14 @@ def getpriv(key, minimal, format): @click.command(help="Check that signed image can be verified by given key") def verify(key, imgfile): key = load_key(key) if key else None - ret, version, digest = image.Image.verify(imgfile, key) + ret, version, digest, signature = image.Image.verify(imgfile, key) if ret == image.VerifyResult.OK: print("Image was correctly validated") print("Image version: {}.{}.{}+{}".format(*version)) - print("Image digest: {}".format(digest.hex())) + if digest: + print("Image digest: {}".format(digest.hex())) + if signature and digest is None: + print("Image signature over image: {}".format(signature.hex())) return elif ret == image.VerifyResult.INVALID_MAGIC: print("Invalid image magic; is this an MCUboot image?") @@ -423,6 +426,10 @@ def convert(self, value, param, ctx): 'the signature calculated using the public key') @click.option('--fix-sig-pubkey', metavar='filename', help='public key relevant to fixed signature') +@click.option('--pure', 'is_pure', is_flag=True, default=False, show_default=True, + help='Expected Pure variant of signature; the Pure variant is ' + 'expected to be signature done over an image rather than hash of ' + 'that image.') @click.option('--sig-out', metavar='filename', help='Path to the file to which signature will be written. ' 'The image signature will be encoded as base64 formatted string') @@ -441,8 +448,8 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, endian, encrypt_keylen, encrypt, compression, infile, outfile, dependencies, load_addr, hex_addr, erased_val, save_enctlv, security_counter, boot_record, custom_tlv, rom_fixed, max_align, - clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, vector_to_sign, - non_bootable): + clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, is_pure, + vector_to_sign, non_bootable): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -509,9 +516,15 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, 'value': raw_signature } + if is_pure and user_sha != 'auto': + raise click.UsageError( + 'Pure signatures, currently, enforces preferred hash algorithm, ' + 'and forbids sha selection by user.') + img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, compression_tlvs, None, int(encrypt_keylen), clear, - baked_signature, pub_key, vector_to_sign, user_sha) + baked_signature, pub_key, vector_to_sign, user_sha=user_sha, + is_pure=is_pure) if compression in ["lzma2", "lzma2armthumb"]: compressed_img = image.Image(version=decode_version(version), From 38c662b4b81b5ac92adf16eb1975888b6d68fb30 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Sat, 19 Oct 2024 15:21:23 +0200 Subject: [PATCH 013/287] [nrf noup] imgtool: create image obj with image_hash Kept creating the field for external usage. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 29646aceff168d3fce89042d7da76e27795e2f45) (cherry picked from commit 283fd06a5950d5cefcdfb9cb8460754d77bd30c8) --- scripts/imgtool/image.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 5e10ab78a..d05120548 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -604,6 +604,8 @@ def create(self, key, public_key_format, enckey, dependencies=None, sha.update(self.payload) digest = sha.digest() tlv.add(hash_tlv, digest) + # for external usage + self.image_hash = digest # Unless pure, we are signing digest. message = digest From 42a79a41ef7f9e9ecf70a39bbb81eb9dd6757fdd Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 2 Aug 2024 14:48:15 +0000 Subject: [PATCH 014/287] [nrf fromtree] bootutil: Add SIG_PURE TLV The commit adds SIG_PURE TLV that should be used as TLV indicating that the signature attached to image has been calculated over entire image, rather than digest of image. This is generic flag as the "pure" usage may be applied to, potentially, any signature algorithm. Signed-off-by: Dominik Ermel (cherry picked from commit 30bcd46855d34e3112f88c71a79e3f8a771fcebb) (cherry picked from commit 7e010864696446fc42e185161d1f73bff563ee29) (cherry picked from commit 3d2808d82e73b04cf112484a706d0817fb8b2464) --- scripts/imgtool/image.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index d05120548..9946a2595 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -83,6 +83,7 @@ 'ECDSASIG': 0x22, 'RSA3072': 0x23, 'ED25519': 0x24, + 'SIG_PURE': 0x25, 'ENCRSA2048': 0x30, 'ENCKW': 0x31, 'ENCEC256': 0x32, From 17f3f7f51a8d1b18444c0bcb6a6f01b66ee33ae6 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Tue, 10 Oct 2023 15:51:54 +0200 Subject: [PATCH 015/287] [nrf noup] github: Add a commit tags check workflow Use the generic commit-tags action to provide sauce tag checks. Signed-off-by: Carles Cufi (cherry picked from commit 00f58607a396fe4da36acadfbdd7586772d5aab5) (cherry picked from commit 6813bbbf94169196362f784313c26aa3aaefcbd4) --- .github/workflows/commit-tags.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/commit-tags.yml diff --git a/.github/workflows/commit-tags.yml b/.github/workflows/commit-tags.yml new file mode 100644 index 000000000..534ed5b58 --- /dev/null +++ b/.github/workflows/commit-tags.yml @@ -0,0 +1,28 @@ +name: Commit tags + +on: + pull_request: + types: [synchronize, opened, reopened, edited, labeled, unlabeled, + milestoned, demilestoned, assigned, unassigned, ready_for_review, + review_requested] + +jobs: + commit_tags: + runs-on: ubuntu-22.04 + name: Run commit tags checks on patch series (PR) + steps: + - name: Update PATH for west + run: | + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Checkout the code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Run the commit tags + uses: nrfconnect/action-commit-tags@main + with: + target: . + upstream: mcu-tools/mcuboot/main From b85273aabd958d332750fb936ee30e81db7bd670 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 26 Mar 2019 15:42:38 +0100 Subject: [PATCH 016/287] [nrf noup] zephyr: Remove duplication from cmake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes the `add_subdirectory` of nrfxlib it will still check that the nrfxlib is located outside the mcuboot directory. Signed-off-by: Sigvart Hovland Signed-off-by: Andrzej Puzdrowski Signed-off-by: Martí Bolívar Signed-off-by: Emil Obalski Signed-off-by: Andrzej Puzdrowski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 6bc65a9a5494e77a7d930d7ee7a9883d36207332) (cherry picked from commit 7f05233a948ed9dcabfede8585ba4fc2776f6d82) --- boot/zephyr/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index d02f93a40..89d76e991 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -42,8 +42,6 @@ if(NOT EXISTS ${NRFXLIB_DIR}) To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") endif() -# Don't include this if we are using west - add_subdirectory(${NRFXLIB_DIR} ${PROJECT_BINARY_DIR}/nrfxlib) endif() zephyr_library_include_directories( From 883a6ceac3537e90505c54f3fa4082f07b79f647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Bol=C3=ADvar?= Date: Fri, 3 Sep 2021 14:38:54 -0700 Subject: [PATCH 017/287] [nrf noup] zephyr: add 'minimal' configuration files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add prj_minimal.conf, a Kconfig fragment to be used for minimally sized image production. The minimal fragment has been simplified for only external crypto. Move partition sizing into Kconfig to be consistent with the method used by b0. Using this fragment with prj_minimal.conf makes MCUboot < 16kB for all nRF devices (9160 still needs 32kB partition). Ref: NCSDK-6704 Signed-off-by: Stephen Stauts Signed-off-by: Martí Bolívar Signed-off-by: Sebastian Bøe Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit bee94754baf89c4b81858ad2cdc5f171a1ea800c) (cherry picked from commit 60c998f13fa82877afa6657661fafaa64ebc3c1c) --- .../nrf5340dk_nrf5340_cpuapp_minimal.conf | 13 ++++++ boot/zephyr/prj_minimal.conf | 40 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf create mode 100644 boot/zephyr/prj_minimal.conf diff --git a/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf b/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf new file mode 100644 index 000000000..dd5468106 --- /dev/null +++ b/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf @@ -0,0 +1,13 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# CC3xx is currently not used for nrf53 +CONFIG_HW_CC3XX=n +CONFIG_NRF_CC3XX_PLATFORM=n + +# Required for kernel operation +CONFIG_CLOCK_CONTROL=y +CONFIG_SYS_CLOCK_EXISTS=y diff --git a/boot/zephyr/prj_minimal.conf b/boot/zephyr/prj_minimal.conf new file mode 100644 index 000000000..55d4c6167 --- /dev/null +++ b/boot/zephyr/prj_minimal.conf @@ -0,0 +1,40 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +CONFIG_FLASH=y +CONFIG_FPROTECT=y +CONFIG_PM=n + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_ENCRYPT_IMAGE=n + +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_BOOT_UPGRADE_ONLY=n + +### Minimal Configurations ### +CONFIG_BOOT_USE_MIN_PARTITION_SIZE=y +CONFIG_ASSERT=n +CONFIG_BOOT_BANNER=n +CONFIG_CLOCK_CONTROL=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_GPIO=n +CONFIG_KERNEL_MEM_POOL=n +CONFIG_LOG=n +CONFIG_MINIMAL_LIBC_CALLOC=n +CONFIG_MINIMAL_LIBC_MALLOC=n +CONFIG_MINIMAL_LIBC_REALLOCARRAY=n +CONFIG_NCS_SAMPLES_DEFAULTS=n +CONFIG_NO_RUNTIME_CHECKS=y +CONFIG_NRF_RTC_TIMER=n +CONFIG_PRINTK=n +CONFIG_SERIAL=n +CONFIG_SIZE_OPTIMIZATIONS=y +CONFIG_SYS_CLOCK_EXISTS=n +CONFIG_UART_CONSOLE=n From 1f7ca3dcfe94c8c929d0484ceec958bd7df2f4be Mon Sep 17 00:00:00 2001 From: Bernt Johan Damslora Date: Fri, 20 Sep 2019 18:25:41 +0200 Subject: [PATCH 018/287] [nrf noup] boards: add support for Thingy:91 Adds project configurations for the two systems on the Thingy:91 (PCA-20035) board. The bootloader that is factory-programmed on thing91 does not support ECDSA signature type. Hence this commit also sets the signature type to RSA for applications built for Thingy:91. Signed-off-by: Bernt Johan Damslora Signed-off-by: Sigvart Hovland Signed-off-by: Jon Helge Nistad Signed-off-by: Balaji Srinivasan Signed-off-by: Robert Lubos Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Marek Pieta Signed-off-by: Dominik Ermel (cherry picked from commit 49e2872fb37664823a4fd56ba0c03807bd5dc9ec) (cherry picked from commit 1e82a208f7d47c66e4975f1f237fadfcd22d9535) --- boot/zephyr/boards/thingy91_nrf52840.conf | 34 +++++++++++++++++++++++ boot/zephyr/boards/thingy91_nrf9160.conf | 13 +++++++++ 2 files changed, 47 insertions(+) create mode 100644 boot/zephyr/boards/thingy91_nrf52840.conf create mode 100644 boot/zephyr/boards/thingy91_nrf9160.conf diff --git a/boot/zephyr/boards/thingy91_nrf52840.conf b/boot/zephyr/boards/thingy91_nrf52840.conf new file mode 100644 index 000000000..c0d183401 --- /dev/null +++ b/boot/zephyr/boards/thingy91_nrf52840.conf @@ -0,0 +1,34 @@ +# Disable Zephyr console +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# The build won't fit on the partition allocated for it without size +# optimizations. +CONFIG_SIZE_OPTIMIZATIONS=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x12000 + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_NRFX=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y + +# MCUboot serial recovery +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by USB +CONFIG_MULTITHREADING=y + +# USB +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" +CONFIG_USB_CDC_ACM=y +CONFIG_USB_COMPOSITE_DEVICE=y +CONFIG_USB_MASS_STORAGE=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x520F diff --git a/boot/zephyr/boards/thingy91_nrf9160.conf b/boot/zephyr/boards/thingy91_nrf9160.conf new file mode 100644 index 000000000..1bf2e424d --- /dev/null +++ b/boot/zephyr/boards/thingy91_nrf9160.conf @@ -0,0 +1,13 @@ +# Disable Zephyr console +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# Disable Flash protection +CONFIG_FPROTECT=n + +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# MCUboot serial recovery +CONFIG_MCUBOOT_SERIAL=y From 48e0d079a0cfaef6c3622c24f804f4057701dc87 Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Mon, 21 Mar 2022 13:44:27 +0100 Subject: [PATCH 019/287] [nrf noup] zephyr: Restore default RTC user channel count The default value of CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT for nRF52 SOCs has been changed from 0 to 3, but it makes MCUBoot get stuck on erasing flash pages when swapping two images. Restore the previous value until the RTC issue is resolved (see NCSDK-14427) Signed-off-by: Damian Krolik Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 93bb567b8a3d8a708d5f09e09d0e251c3e43c235) (cherry picked from commit 4be7cf86a164bf84f9bccabd7403332f6dd7ff27) --- boot/zephyr/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 851c133ec..58cb2ae35 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -35,3 +35,4 @@ CONFIG_MCUBOOT_LOG_LEVEL_INF=y CONFIG_CBPRINTF_NANO=y ### Use the minimal C library to reduce flash usage CONFIG_MINIMAL_LIBC=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 From e541ae9e6e9125bc3ae7457b395397541b3feca3 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 8 Dec 2023 13:18:12 +0100 Subject: [PATCH 020/287] [nrf noup] boards: thingy91x: add board config This patch adds board configuration for the Thingy:91 X. Signed-off-by: Maximilian Deubel (cherry picked from commit c473f8ed1c5e258294fd3da20beb210292ecc9b8) (cherry picked from commit 932db78bbd76d64f3ff912f6f004e22b2d0a973e) --- .../boards/thingy91x_nrf5340_cpuapp.conf | 54 +++++++++++++++++++ boot/zephyr/boards/thingy91x_nrf9151.conf | 8 +++ 2 files changed, 62 insertions(+) create mode 100644 boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf create mode 100644 boot/zephyr/boards/thingy91x_nrf9151.conf diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf new file mode 100644 index 000000000..72dfa7fca --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -0,0 +1,54 @@ +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=110 + +# MCUboot serial recovery +CONFIG_MCUBOOT_SERIAL=y + +# Disable Zephyr console +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_NRFX=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y + +# MCUboot serial recovery +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by USB +CONFIG_MULTITHREADING=y + +# USB +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" +CONFIG_USB_CDC_ACM=y +CONFIG_USB_COMPOSITE_DEVICE=y +CONFIG_USB_MASS_STORAGE=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x520F + +CONFIG_BOOT_SERIAL_BOOT_MODE=y + +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x13E00 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 +CONFIG_BOOT_UPGRADE_ONLY=y +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y + +CONFIG_NRF53_RECOVERY_NETWORK_CORE=y diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf new file mode 100644 index 000000000..33cd3301c --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -0,0 +1,8 @@ +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=512 + +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_MULTITHREADING=y From 6a5dc04d20332548471564c0d88226c70f54f696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 12 Dec 2018 08:59:47 +0100 Subject: [PATCH 021/287] [nrf noup] treewide: add NCS partition manager support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partition Manager is an nRF Connect SDK component which uses yaml files to resolve flash partition placement with a holistic view of the device. This component's MCUboot portions began life as upstream mcuboot PR#430. This added support for being built as a sub image from the downstream Nordic patch set for a zephyr multi image build system (mcuboot 430 was combined with effor submitted to upstream zephyr as PR#13672, which was ultimately reworked after being rejected for mainline at the ELCE 2019 conference in Lyon). It has since evolved over time. This is the version that will go into NCS v1.3. It features: - page size aligned partitions for all partitions used by mcuboot. - image swaps without scratch partitions Add support for configurations where there exists two primary slots but only one secondary slot, which is shared. These two primary slots are the regular application and B1. B1 can be either S0 or S1 depending on the state of the device. Decide where an upgrade should be stored by looking at the vector table. Provide update candidates for both s0 and s1. These candidates must be signed with mcuboot after being signed by b0. Additional notes: - we make update.hex without trailer data This is needed for serial recovery to work using hex files. Prior to this the update.hex got TLV data at the end of the partition, which caused many blank pages to be included, which made it hard to use in a serial recovery scheme. Instead, make update.hex without TLV data at the end, and provide a new file test_update.hex which contains the TLV data, and can be directly flashed to test the upgrade procedure. - we use a function for signing the application as future-proofing for when other components must be signed as well - this includes an update to single image applications that enables support for partition manager; when single image DFU is used, a scratch partition is not needed. - In NCS, image 1 primary slot is the upgrade bank for mcuboot (IE S0 or S1 depending on the active slot). It is not required that this slot contains any valid data. - The nRF boards all have a single flash page size, and partition manager deals with the size of the update partitions and so on, so we must skip a boot_slots_compatible() check to avoid getting an error. - There is no need to verify the target when using partition manager. - We lock mcuboot using fprotect before jumping, to enable the secure boot property of the system. - Call fw_info_ext_api_provide() before booting if EXT_API_PROVIDE EXT_API is enabled. This is relevant only when the immutable bootloader has booted mcuboot. Signed-off-by: Håkon Øye Amundsen Signed-off-by: Øyvind Rønningstad Signed-off-by: Sebastian Bøe Signed-off-by: Sigvart Hovland Signed-off-by: Martí Bolívar Signed-off-by: Torsten Rasmussen Signed-off-by: Andrzej Głąbek Signed-off-by: Robert Lubos Signed-off-by: Andrzej Puzdrowski Signed-off-by: Emil Obalski Signed-off-by: Pawel Dunaj Signed-off-by: Ioannis Glaropoulos Signed-off-by: Johann Fischer Signed-off-by: Vidar Berg Signed-off-by: Draus, Sebastian Signed-off-by: Trond Einar Snekvik Signed-off-by: Jamie McCrae Signed-off-by: Joakim Andersson Signed-off-by: Georgios Vasilakis Signed-off-by: Dominik Ermel (cherry picked from commit 6facec9d2d89d853302c994c96d21134d4c23b66) (cherry picked from commit c13d7b3d6c14646214c52e3ddb6b9e9518055a54) --- boot/bootutil/src/loader.c | 95 ++++++++++++++++++++++--- boot/bootutil/src/swap_move.c | 13 ++++ boot/bootutil/src/swap_scratch.c | 13 ++++ boot/zephyr/CMakeLists.txt | 7 ++ boot/zephyr/Kconfig | 2 + boot/zephyr/include/sysflash/sysflash.h | 48 +++++++++++++ boot/zephyr/include/target.h | 4 ++ boot/zephyr/main.c | 45 ++++++++++++ boot/zephyr/pm.yml | 77 ++++++++++++++++++++ boot/zephyr/prj.conf | 1 + ext/nrf/cc310_glue.h | 2 +- zephyr/module.yml | 3 +- 12 files changed, 299 insertions(+), 11 deletions(-) create mode 100644 boot/zephyr/pm.yml diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 12d4abf40..a9bd131dd 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -133,6 +133,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. The primary slot of the second image + * (image 1) will not contain a valid image header until an upgrade + * of mcuboot has happened (filling S1 with the new version). + */ + if (BOOT_CURR_IMG(state) == 1 && i == 0) { + continue; + } +#endif /* PM_S1_ADDRESS */ if (i > 0 && !require_all) { return 0; } else { @@ -1140,7 +1149,24 @@ boot_validate_slot(struct boot_loader_state *state, int slot, goto out; } - if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) { + uint32_t min_addr, max_addr; + +#ifdef PM_CPUNET_APP_ADDRESS + /* The primary slot for the network core is emulated in RAM. + * Its flash_area hasn't got relevant boundaries. + * Therfore need to override its boundaries for the check. + */ + if (BOOT_CURR_IMG(state) == 1) { + min_addr = PM_CPUNET_APP_ADDRESS; + max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; + } else +#endif + { + min_addr = pri_fa->fa_off; + max_addr = pri_fa->fa_off + pri_fa->fa_size; + } + + if (reset_value < min_addr || reset_value> (max_addr)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1223,6 +1249,42 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other + * B1 slot S0 or S1) share the same secondary slot, we need to check + * whether the update candidate in the secondary slot is intended for + * image 0 or image 1 primary by looking at the address of the reset + * vector. Note that there are good reasons for not using img_num from + * the swap info. + */ + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = + (struct image_header *)secondary_fa->fa_off; + + if (hdr->ih_magic == IMAGE_MAGIC) { + const struct flash_area *primary_fa; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *vtable = (uint32_t *)(vtable_addr); + uint32_t reset_addr = vtable[1]; + int rc = flash_area_open( + flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ + return BOOT_SWAP_TYPE_NONE; + } + } +#endif swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2431,15 +2493,25 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT - FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL); - /* Check for all possible values is redundant in normal operation it - * is meant to prevent FI attack. +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. Image 1 primary is the currently + * executing MCUBoot image, and is therefore already validated by NSIB and + * does not need to also be validated by MCUBoot. */ - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || - FIH_EQ(fih_rc, FIH_FAILURE) || - FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; + if (!image_validated_by_nsib) +#endif + { + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL); + /* Check for all possible values is redundant in normal operation it + * is meant to prevent FI attack. + */ + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || + FIH_EQ(fih_rc, FIH_FAILURE) || + FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } } #else /* Even if we're not re-validating the primary slot, we could be booting @@ -2456,11 +2528,16 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ +#ifdef PM_S1_ADDRESS + if (!image_validated_by_nsib) +#endif + { rc = boot_update_hw_rollback_protection(state); if (rc != 0) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } + } rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT); if (rc != 0) { diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 8999403c5..20caa2b5c 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -259,6 +259,18 @@ static int app_max_sectors(struct boot_loader_state *state) int boot_slots_compatible(struct boot_loader_state *state) { +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. In this case, image 1 primary points to the other + * B1 slot (ie S0 or S1), and image 0 primary points to the app. + * With this configuration, image 0 and image 1 share the secondary slot. + * Hence, the primary slot of image 1 will be *smaller* than image 1's + * secondary slot. This is not allowed in upstream mcuboot, so we need + * this patch to allow it. Also, all of these checks are redundant when + * partition manager is in use, and since we have the same sector size + * in all of our flash. + */ + return 1; +#else size_t num_sectors_pri; size_t num_sectors_sec; size_t sector_sz_pri = 0; @@ -306,6 +318,7 @@ boot_slots_compatible(struct boot_loader_state *state) } return 1; +#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index f60109120..66dca83e9 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -141,6 +141,18 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. In this case, image 1 primary points to the other + * B1 slot (ie S0 or S1), and image 0 primary points to the app. + * With this configuration, image 0 and image 1 share the secondary slot. + * Hence, the primary slot of image 1 will be *smaller* than image 1's + * secondary slot. This is not allowed in upstream mcuboot, so we need + * this patch to allow it. Also, all of these checks are redundant when + * partition manager is in use, and since we have the same sector size + * in all of our flash. + */ + return 1; +#else size_t num_sectors_primary; size_t num_sectors_secondary; size_t sz0, sz1; @@ -238,6 +250,7 @@ boot_slots_compatible(struct boot_loader_state *state) #endif return 1; +#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 89d76e991..c3fe0bd74 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -295,6 +295,13 @@ if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") endif() message("MCUBoot bootloader key file: ${KEY_FILE}") + set_property( + GLOBAL + PROPERTY + KEY_FILE + ${KEY_FILE} + ) + set(GENERATED_PUBKEY ${ZEPHYR_BINARY_DIR}/autogen-pubkey.c) add_custom_command( OUTPUT ${GENERATED_PUBKEY} diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 931bccbbb..a641f3e6a 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -9,6 +9,8 @@ mainmenu "MCUboot configuration" comment "MCUboot-specific configuration options" +source "$(ZEPHYR_NRF_MODULE_DIR)/modules/mcuboot/boot/zephyr/Kconfig" + # Hidden option to mark a project as MCUboot config MCUBOOT default y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 1952950b9..4eaf0309e 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -7,6 +7,52 @@ #ifndef __SYSFLASH_H__ #define __SYSFLASH_H__ +#if USE_PARTITION_MANAGER +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + +extern uint32_t _image_1_primary_slot_id[]; + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) +#endif +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#else + +#include #include #include #include @@ -65,4 +111,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#endif /* USE_PARTITION_MANAGER */ + #endif /* __SYSFLASH_H__ */ diff --git a/boot/zephyr/include/target.h b/boot/zephyr/include/target.h index 9bbfd4b19..40287d515 100644 --- a/boot/zephyr/include/target.h +++ b/boot/zephyr/include/target.h @@ -8,6 +8,8 @@ #ifndef H_TARGETS_TARGET_ #define H_TARGETS_TARGET_ +#ifndef USE_PARTITION_MANAGER + #if defined(MCUBOOT_TARGET_CONFIG) /* * Target-specific definitions are permitted in legacy cases that @@ -45,4 +47,6 @@ #error "Target support is incomplete; cannot build mcuboot." #endif +#endif /* ifndef USE_PARTITION_MANAGER */ + #endif /* H_TARGETS_TARGET_ */ diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index fe0016c8c..abc57596a 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -69,6 +69,10 @@ #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */ +#ifdef CONFIG_FW_INFO +#include +#endif + #ifdef CONFIG_MCUBOOT_SERIAL #include "boot_serial/boot_serial.h" #include "serial_adapter/serial_adapter.h" @@ -129,6 +133,11 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); * !defined(ZEPHYR_LOG_MODE_MINIMAL) */ +#if USE_PARTITION_MANAGER && CONFIG_FPROTECT +#include +#include +#endif + BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -187,6 +196,19 @@ static void do_boot(struct boot_rsp *rsp) /* Disable the USB to prevent it from firing interrupts */ usb_disable(); #endif + +#if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) + bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); + +#ifdef PM_S0_ADDRESS + /* Only fail if the immutable bootloader is present. */ + if (!provided) { + BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); + return; + } +#endif +#endif + #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ @@ -560,7 +582,30 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND); +#if USE_PARTITION_MANAGER && CONFIG_FPROTECT + +#ifdef PM_S1_ADDRESS +/* MCUBoot is stored in either S0 or S1, protect both */ +#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_S0_ADDRESS) +#define PROTECT_ADDR PM_S0_ADDRESS +#else +/* There is only one instance of MCUBoot */ +#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_MCUBOOT_ADDRESS) +#define PROTECT_ADDR PM_MCUBOOT_ADDRESS +#endif + + rc = fprotect_area(PROTECT_ADDR, PROTECT_SIZE); + + if (rc != 0) { + BOOT_LOG_ERR("Protect mcuboot flash failed, cancel startup."); + while (1) + ; + } + +#endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ + ZEPHYR_BOOT_LOG_STOP(); + do_boot(&rsp); mcuboot_status_change(MCUBOOT_STATUS_BOOT_FAILED); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml new file mode 100644 index 000000000..5df9ae547 --- /dev/null +++ b/boot/zephyr/pm.yml @@ -0,0 +1,77 @@ +#include + +mcuboot: + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT + placement: + before: [mcuboot_primary] +#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) + align: {end: 0x1000} +#endif + +mcuboot_primary_app: + # All images to be placed in MCUboot's slot 0 should be placed in this + # partition + span: [app] + +mcuboot_primary: + span: [mcuboot_pad, mcuboot_primary_app] + +# Partition for secondary slot is not created if building in single application +# slot configuration. +#if !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) +mcuboot_secondary: + share_size: [mcuboot_primary] +#if defined(CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) + region: external_flash + placement: + align: {start: 4} +#else + placement: + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + align_next: CONFIG_FPROTECT_BLOCK_SIZE # Ensure that the next partition does not interfere with this image + after: mcuboot_primary +#endif /* CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY */ + +#endif /* !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) */ + +#if CONFIG_BOOT_DIRECT_XIP + +# Direct XIP is enabled, reserve area for metadata (padding) and name the +# partition so that its clear that it is not the secondary slot, but the direct +# XIP alternative. + +mcuboot_secondary_pad: + share_size: mcuboot_pad + placement: + after: mcuboot_primary + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + +mcuboot_secondary_app: + share_size: mcuboot_primary_app + placement: + after: mcuboot_secondary_pad + +mcuboot_secondary: + span: [mcuboot_secondary_pad, mcuboot_secondary_app] + +#endif /* CONFIG_BOOT_DIRECT_XIP */ + +#if CONFIG_BOOT_SWAP_USING_SCRATCH +mcuboot_scratch: + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_SCRATCH + placement: + after: app + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} +#endif /* CONFIG_BOOT_SWAP_USING_SCRATCH */ + +# Padding placed before image to boot. This reserves space for the MCUboot image header +# and it ensures that the boot image gets linked with the correct address offset in flash. +mcuboot_pad: + # MCUboot pad must be placed before the primary application partition. + # The primary application partition includes the secure firmware if present. + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_PAD + placement: + before: [mcuboot_primary_app] +#ifdef CONFIG_FPROTECT + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} +#endif diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 58cb2ae35..23b5f3b93 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -19,6 +19,7 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_TINYCRYPT_SHA256 is not set CONFIG_FLASH=y +CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/ext/nrf/cc310_glue.h b/ext/nrf/cc310_glue.h index ed3ed5c00..22eb94911 100644 --- a/ext/nrf/cc310_glue.h +++ b/ext/nrf/cc310_glue.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include /* diff --git a/zephyr/module.yml b/zephyr/module.yml index 014a21956..9360dbf70 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -1,5 +1,6 @@ samples: - boot/zephyr build: - cmake: ./boot/bootutil/zephyr + cmake-ext: True + kconfig-ext: True sysbuild-cmake: boot/zephyr/sysbuild From 9c26bb601e487ec60629ebcb6898f47ec3360100 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Thu, 27 Aug 2020 14:29:31 +0200 Subject: [PATCH 022/287] [nrf noup] boot: nrf53-specific customizations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add network core bootloader implementation Enables network core updates of nrf53 using MCUBoot by identifying images through their start addresses. Also implements the control and transfer using the PCD module. - Add support for multi image DFU using partition manager. - Add check for netcore addr if NSIB is enabled so netcore updates works - boot: zephyr: move thingy53_nrf5340_cpuapp.conf downstream Moved the board configuration for Thingy:53 Application Core to the nRF Connect SDK MCUboot downstream repository. The configuration file contains references to the Kconfig modules that are only available in the nRF Connect SDK. The current configuration is set up to work in the nRF Connect SDK environment and cannot be used upstream. - pm: enable ram flash partition using common flag This patch makes mcuboot_primary_1 ram-flash partition selectable using CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH property. This is needed since CONFIG_NRF53_MULTI_IMAGE_UPDATE become not only configuration which requires that partition. - MCUBoot configures USB CDC by its own. There is no need for BOARD_SERIAL_BACKEND_CDC_ACM option to configure anything which is later overwritten anyway. Jira: NCSDK-18596 Signed-off-by: Andrzej Puzdrowski Signed-off-by: Emil Obalski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Jamie McCrae Signed-off-by: Johann Fischer Signed-off-by: Kamil Piszczek Signed-off-by: Ole Sæther Signed-off-by: Sigvart Hovland Signed-off-by: Simon Iversen Signed-off-by: Torsten Rasmussen Signed-off-by: Trond Einar Snekvik Signed-off-by: Mateusz Kapala Signed-off-by: Dominik Ermel (cherry picked from commit 56934f9b475b51dbe20ef6e33621a57b7417c8ea) (cherry picked from commit 33cf05d8460d32b5298f1069a26d3eaece0657fb) --- boot/bootutil/src/loader.c | 96 ++++++++++++++----- .../boards/thingy53_nrf5340_cpuapp.conf | 74 +++++++++++++- boot/zephyr/include/sysflash/sysflash.h | 23 +++++ boot/zephyr/main.c | 7 ++ boot/zephyr/pm.yml | 13 +++ 5 files changed, 185 insertions(+), 28 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a9bd131dd..ea2e968a8 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,6 +49,10 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) +#include +#endif + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -1249,7 +1253,15 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); -#ifdef PM_S1_ADDRESS + bool upgrade_valid = false; + +#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = 0; + uint32_t *vtable = 0; + uint32_t reset_addr = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1257,34 +1269,36 @@ boot_validated_swap_type(struct boot_loader_state *state, * vector. Note that there are good reasons for not using img_num from * the swap info. */ - const struct flash_area *secondary_fa = - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = - (struct image_header *)secondary_fa->fa_off; if (hdr->ih_magic == IMAGE_MAGIC) { - const struct flash_area *primary_fa; - uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - uint32_t *vtable = (uint32_t *)(vtable_addr); - uint32_t reset_addr = vtable[1]; - int rc = flash_area_open( - flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ - return BOOT_SWAP_TYPE_NONE; - } - } + vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + vtable = (uint32_t *)(vtable_addr); + reset_addr = vtable[1]; +#ifdef PM_S1_ADDRESS +#ifdef PM_CPUNET_B0N_ADDRESS + if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif + { + const struct flash_area *primary_fa; + int rc = flash_area_open(flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ + return BOOT_SWAP_TYPE_NONE; + } + } +#endif /* PM_S1_ADDRESS */ + } +#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -1298,7 +1312,37 @@ boot_validated_swap_type(struct boot_loader_state *state, } else { swap_type = BOOT_SWAP_TYPE_FAIL; } + } else { + upgrade_valid = true; + } + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) + /* If the update is valid, and it targets the network core: perform the + * update and indicate to the caller of this function that no update is + * available + */ + if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + uint32_t fw_size = hdr->ih_img_size; + + BOOT_LOG_INF("Starting network core update"); + int rc = pcd_network_core_update(vtable, fw_size); + + if (rc != 0) { + swap_type = BOOT_SWAP_TYPE_FAIL; + } else { + BOOT_LOG_INF("Done updating network core"); +#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) + /* swap_erase_trailer_sectors is undefined if upgrade only + * method is used. There is no need to erase sectors, because + * the image cannot be reverted. + */ + rc = swap_erase_trailer_sectors(state, + secondary_fa); +#endif + swap_type = BOOT_SWAP_TYPE_NONE; + } } +#endif /* CONFIG_SOC_NRF5340_CPUAPP */ } return swap_type; diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index f2e42fd64..7d3bc0bec 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -1,3 +1,73 @@ -CONFIG_NORDIC_QSPI_NOR=n -CONFIG_SPI=n +CONFIG_SIZE_OPTIMIZATIONS=y + +CONFIG_SYSTEM_CLOCK_NO_WAIT=y +CONFIG_PM=n + +CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +CONFIG_BOOT_MAX_IMG_SECTORS=2048 +CONFIG_BOOT_SIGNATURE_TYPE_RSA=y + +# Flash +CONFIG_FLASH=y +CONFIG_BOOT_ERASE_PROGRESSIVELY=y +CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y +CONFIG_FPROTECT=y + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_LINE_CTRL=y + +# MCUBoot serial +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by QSPI +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# Required by USB and QSPI CONFIG_MULTITHREADING=y + +# USB +CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n +CONFIG_USB_DEVICE_REMOTE_WAKEUP=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor ASA" +CONFIG_USB_DEVICE_PRODUCT="Bootloader Thingy:53" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x5300 +CONFIG_USB_CDC_ACM=y + +# Decrease memory footprint +CONFIG_CBPRINTF_NANO=y +CONFIG_TIMESLICING=n +CONFIG_BOOT_BANNER=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_LOG=n +CONFIG_ERRNO=n +CONFIG_PRINTK=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_SPI=n +CONFIG_I2C=n +CONFIG_UART_NRFX=n + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 +CONFIG_BOOT_UPGRADE_ONLY=y +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +# Enable custom command to erase settings partition. +CONFIG_ENABLE_MGMT_PERUSER=y +CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE=y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 4eaf0309e..b98e48bce 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -20,6 +20,11 @@ #elif (MCUBOOT_IMAGE_NUMBER == 2) +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +#ifdef PM_B0_ADDRESS + extern uint32_t _image_1_primary_slot_id[]; #define FLASH_AREA_IMAGE_PRIMARY(x) \ @@ -35,6 +40,24 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) +#else + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) + +#endif /* PM_B0_ADDRESS */ + #endif #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index abc57596a..3e0b100ca 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -91,6 +91,10 @@ const struct boot_uart_funcs boot_funcs = { #include #endif +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) +#include +#endif + /* CONFIG_LOG_MINIMAL is the legacy Kconfig property, * replaced by CONFIG_LOG_MODE_MINIMAL. */ @@ -602,6 +606,9 @@ int main(void) ; } +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) + pcd_lock_ram(); +#endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ ZEPHYR_BOOT_LOG_STOP(); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index 5df9ae547..13ffc44aa 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -75,3 +75,16 @@ mcuboot_pad: #ifdef CONFIG_FPROTECT align: {start: CONFIG_FPROTECT_BLOCK_SIZE} #endif + +#if (CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH) +mcuboot_primary_1: + region: ram_flash + size: CONFIG_NRF53_RAM_FLASH_SIZE +#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ + +#if (CONFIG_NRF53_MULTI_IMAGE_UPDATE) +mcuboot_secondary_1: + region: external_flash + size: CONFIG_NRF53_RAM_FLASH_SIZE + +#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ From c82aef67eb4e2573f7d06aed3279019e3e6953b0 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 27 Feb 2020 12:48:56 +0100 Subject: [PATCH 023/287] [nrf noup] zephyr: clean peripherals state before boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do some cleanup of nRF peripherals. This is necessary since Zephyr doesn't have any driver deinitialization functionality, and we'd like to leave peripherals in a more predictable state before booting the Zephyr image. This should be re-worked when the zephyr driver model allows us to deinitialize devices cleanly before jumping to the chain-loaded image. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Robert Lubos Signed-off-by: Torsten Rasmussen Signed-off-by: Øyvind Rønningstad Signed-off-by: Martí Bolívar Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Johann Fischer Signed-off-by: Trond Einar Snekvik Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 50c5cdb7ef0dcbe29fc70ebe047c682f7b5b01c3) (cherry picked from commit 0a3f9c790fe27428d7e1100ee9d5e2aed2c8012e) --- boot/zephyr/CMakeLists.txt | 6 +++ boot/zephyr/include/nrf_cleanup.h | 19 +++++++ boot/zephyr/main.c | 8 ++- boot/zephyr/nrf_cleanup.c | 83 +++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 boot/zephyr/include/nrf_cleanup.h create mode 100644 boot/zephyr/nrf_cleanup.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index c3fe0bd74..b60b0c95d 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -574,3 +574,9 @@ if(SYSBUILD) set(mcuboot_image_footer_size ${required_size} CACHE INTERNAL "Estimated MCUboot image trailer size" FORCE) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() + +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) +zephyr_library_sources( + ${BOOT_DIR}/zephyr/nrf_cleanup.c +) +endif() diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h new file mode 100644 index 000000000..6b04cedfe --- /dev/null +++ b/boot/zephyr/include/nrf_cleanup.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_NRF_CLEANUP_ +#define H_NRF_CLEANUP_ + +/** + * Perform cleanup on some peripheral resources used by MCUBoot prior chainload + * the application. + * + * This function disables all RTC instances and UARTE instances. + * It Disables their interrupts signals as well. + */ +void nrf_cleanup_peripheral(void); + +#endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 3e0b100ca..c76ed18b3 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -142,6 +142,10 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL +#include +#endif + BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -212,7 +216,9 @@ static void do_boot(struct boot_rsp *rsp) } #endif #endif - +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL + nrf_cleanup_peripheral(); +#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c new file mode 100644 index 000000000..5bab26b24 --- /dev/null +++ b/boot/zephyr/nrf_cleanup.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#if defined(NRF_UARTE0) || defined(NRF_UARTE1) + #include +#endif +#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) + #include +#endif +#if defined(NRF_PPI) + #include +#endif +#if defined(NRF_DPPIC) + #include +#endif + +#include + +#define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) +#define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ + NRF_UARTE_SUBSCRIBE_CONF_OFFS) + +#define NRF_UARTE_PUBLISH_CONF_OFFS offsetof(NRF_UARTE_Type, PUBLISH_CTS) +#define NRF_UARTE_PUBLISH_CONF_SIZE (offsetof(NRF_UARTE_Type, SHORTS) -\ + NRF_UARTE_PUBLISH_CONF_OFFS) + +#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) +static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) +{ + nrf_rtc_task_trigger(rtc_reg, NRF_RTC_TASK_STOP); + nrf_rtc_event_disable(rtc_reg, 0xFFFFFFFF); + nrf_rtc_int_disable(rtc_reg, 0xFFFFFFFF); +} +#endif + +static void nrf_cleanup_clock(void) +{ + nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); +} + +void nrf_cleanup_peripheral(void) +{ +#if defined(NRF_RTC0) + nrf_cleanup_rtc(NRF_RTC0); +#endif +#if defined(NRF_RTC1) + nrf_cleanup_rtc(NRF_RTC1); +#endif +#if defined(NRF_RTC2) + nrf_cleanup_rtc(NRF_RTC2); +#endif +#if defined(NRF_UARTE0) + nrf_uarte_disable(NRF_UARTE0); + nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); +#if defined(NRF_DPPIC) + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); +#endif +#endif +#if defined(NRF_UARTE1) + nrf_uarte_disable(NRF_UARTE1); + nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); +#if defined(NRF_DPPIC) + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); +#endif +#endif +#if defined(NRF_PPI) + nrf_ppi_channels_disable_all(NRF_PPI); +#endif +#if defined(NRF_DPPIC) + nrf_dppi_channels_disable_all(NRF_DPPIC); +#endif + nrf_cleanup_clock(); +} From 75ab2de55cd557d4c19f5ed97bc508ddce07818a Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Fri, 6 Jan 2023 12:24:48 +0100 Subject: [PATCH 024/287] [nrf noup] zephyr: Clean up non-secure RAM if enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To ensure that MCUBoot does not leak keys or other material through memory to non-secure side we clear the memory before jumping to the next image. Signed-off-by: Sigvart Hovland Signed-off-by: Dominik Ermel Signed-off-by: Ole Sæther (cherry picked from commit d04dd27a2465abe302776a0fab654682a5f0d223) (cherry picked from commit 9aa2a2374c71647b0003a3bffb535a37164b4666) --- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/include/nrf_cleanup.h | 5 ++ boot/zephyr/main.c | 5 +- boot/zephyr/nrf_cleanup.c | 79 +++++++++++++++++++++++-------- 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index b60b0c95d..fde155833 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -575,7 +575,7 @@ if(SYSBUILD) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL OR CONFIG_MCUBOOT_CLEANUP_NONSECURE_RAM) zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h index 6b04cedfe..9e87e13f5 100644 --- a/boot/zephyr/include/nrf_cleanup.h +++ b/boot/zephyr/include/nrf_cleanup.h @@ -16,4 +16,9 @@ */ void nrf_cleanup_peripheral(void); +/** + * Perform cleanup of non-secure RAM that may have been used by MCUBoot. + */ +void nrf_cleanup_ns_ram(void); + #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index c76ed18b3..8aec9cf0d 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -142,7 +142,7 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL || CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM #include #endif @@ -219,6 +219,9 @@ static void do_boot(struct boot_rsp *rsp) #if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL nrf_cleanup_peripheral(); #endif +#if CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM && defined(PM_SRAM_NONSECURE_NAME) + nrf_cleanup_ns_ram(); +#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 5bab26b24..051705ec9 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -5,9 +5,8 @@ */ #include -#if defined(NRF_UARTE0) || defined(NRF_UARTE1) - #include -#endif +#include +#include #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif @@ -20,6 +19,15 @@ #include +#if USE_PARTITION_MANAGER +#include +#endif + +#if defined(NRF_UARTE0) || defined(NRF_UARTE1) || defined(NRF_UARTE20) || \ + defined(NRF_UARTE30) +#define NRF_UARTE_CLEANUP +#endif + #define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) #define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ NRF_UARTE_SUBSCRIBE_CONF_OFFS) @@ -37,6 +45,23 @@ static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) } #endif +#if defined(NRF_UARTE_CLEANUP) +static NRF_UARTE_Type *nrf_uarte_to_clean[] = { +#if defined(NRF_UARTE0) + NRF_UARTE0, +#endif +#if defined(NRF_UARTE1) + NRF_UARTE1, +#endif +#if defined(NRF_UARTE20) + NRF_UARTE20, +#endif +#if defined(NRF_UARTE30) + NRF_UARTE30, +#endif +}; +#endif + static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); @@ -53,26 +78,31 @@ void nrf_cleanup_peripheral(void) #if defined(NRF_RTC2) nrf_cleanup_rtc(NRF_RTC2); #endif -#if defined(NRF_UARTE0) - nrf_uarte_disable(NRF_UARTE0); - nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); -#if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); -#endif -#endif -#if defined(NRF_UARTE1) - nrf_uarte_disable(NRF_UARTE1); - nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); + +#if defined(NRF_UARTE_CLEANUP) + for (int i = 0; i < sizeof(nrf_uarte_to_clean) / sizeof(nrf_uarte_to_clean[0]); ++i) { + NRF_UARTE_Type *current = nrf_uarte_to_clean[i]; + + nrfy_uarte_int_disable(current, 0xFFFFFFFF); + nrfy_uarte_int_uninit(current); + nrfy_uarte_task_trigger(current, NRF_UARTE_TASK_STOPRX); + + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXSTARTED); + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_ENDRX); + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); + nrfy_uarte_disable(current); + #if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)current + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, + NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)current + NRF_UARTE_PUBLISH_CONF_OFFS, 0, + NRF_UARTE_PUBLISH_CONF_SIZE); #endif + } #endif + #if defined(NRF_PPI) nrf_ppi_channels_disable_all(NRF_PPI); #endif @@ -81,3 +111,12 @@ void nrf_cleanup_peripheral(void) #endif nrf_cleanup_clock(); } + +#if USE_PARTITION_MANAGER \ + && defined(CONFIG_ARM_TRUSTZONE_M) \ + && defined(PM_SRAM_NONSECURE_NAME) +void nrf_cleanup_ns_ram(void) +{ + memset((void *) PM_SRAM_NONSECURE_ADDRESS, 0, PM_SRAM_NONSECURE_SIZE); +} +#endif From f6bedc90762987f24cdc71a4b3014f85a3cb85e5 Mon Sep 17 00:00:00 2001 From: Christian Taedcke Date: Thu, 10 Feb 2022 15:37:49 +0100 Subject: [PATCH 025/287] [nrf noup] loader: Fix reading reset addr to support ext flash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When mcuboot_secondary is on external flash, the image header cannot dircetly be accessed via secondary_fa->fa_off. Instead the provided function boot_img_hdr() is used now. Additionally a similar issue is present when trying to read the address of the reset handler. For this flash_area_read() is used now. With this patch is possible to have the update partiton mcuboot_secondary on external flash and update a updatable bootloader (mcuboot) in s0 and/or s1. Signed-off-by: Christian Taedcke Signed-off-by: Ole Sæther Signed-off-by: Sigvart Hovland Signed-off-by: Dominik Ermel (cherry picked from commit a3a50e720af5c70dbc6ca52331b9e8e951fa43d7) (cherry picked from commit 4081b7960e4bc16093d7ca6473ade65330f5ac30) --- boot/bootutil/src/loader.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index ea2e968a8..9dfb6506c 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1258,10 +1258,9 @@ boot_validated_swap_type(struct boot_loader_state *state, #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; - uint32_t vtable_addr = 0; - uint32_t *vtable = 0; + struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); uint32_t reset_addr = 0; + int rc = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1271,16 +1270,19 @@ boot_validated_swap_type(struct boot_loader_state *state, */ if (hdr->ih_magic == IMAGE_MAGIC) { - vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - vtable = (uint32_t *)(vtable_addr); - reset_addr = vtable[1]; + rc = flash_area_read(secondary_fa, hdr->ih_hdr_size + + sizeof(uint32_t), &reset_addr, + sizeof(reset_addr)); + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif { const struct flash_area *primary_fa; - int rc = flash_area_open(flash_area_id_from_multi_image_slot( + rc = flash_area_open(flash_area_id_from_multi_image_slot( BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), &primary_fa); @@ -1316,16 +1318,19 @@ boot_validated_swap_type(struct boot_loader_state *state, upgrade_valid = true; } -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available */ if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); uint32_t fw_size = hdr->ih_img_size; - BOOT_LOG_INF("Starting network core update"); - int rc = pcd_network_core_update(vtable, fw_size); + rc = pcd_network_core_update(net_core_fw_addr, fw_size); if (rc != 0) { swap_type = BOOT_SWAP_TYPE_FAIL; From d978f7b4e9c000d554242c65800fdee51381a3d2 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jul 2023 08:42:49 +0100 Subject: [PATCH 026/287] [nrf noup] zephyr: Fix path variables Fixes path variables to use the proper Zephyr module variables Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 76d0d9a6b501d4cd51268c0dded8f76152c0452d) (cherry picked from commit a97a24cbe5fb5a83e8d7a1945ac5f4ea763e494c) --- boot/zephyr/CMakeLists.txt | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index fde155833..a288410bf 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -27,21 +27,20 @@ assert_exists(FIAT_DIR) # Path to mbed-tls' asn1 parser library. set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") assert_exists(MBEDTLS_ASN1_DIR) -set(NRF_DIR "${MCUBOOT_DIR}/ext/nrf") +set(MCUBOOT_NRF_EXT_DIR "${MCUBOOT_DIR}/ext/nrf") if(CONFIG_BOOT_USE_NRF_CC310_BL) -set(NRFXLIB_DIR ${ZEPHYR_BASE}/../nrfxlib) -if(NOT EXISTS ${NRFXLIB_DIR}) - message(FATAL_ERROR " + if(NOT EXISTS ${ZEPHYR_NRFXLIB_MODULE_DIR}) + message(FATAL_ERROR " ------------------------------------------------------------------------ - No such file or directory: ${NRFXLIB_DIR} + No such file or directory: ${ZEPHYR_NRFXLIB_MODULE_DIR} The current configuration enables nRF CC310 crypto accelerator hardware with the `CONFIG_BOOT_USE_NRF_CC310_BL` option. Please follow `ext/nrf/README.md` guide to fix your setup or use tinycrypt instead of the HW accelerator. To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") -endif() + endif() endif() zephyr_library_include_directories( @@ -169,8 +168,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) ${TINYCRYPT_DIR}/source/utils.c ) elseif(CONFIG_BOOT_USE_NRF_CC310_BL) - zephyr_library_sources(${NRF_DIR}/cc310_glue.c) - zephyr_library_include_directories(${NRF_DIR}) + zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) + zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) zephyr_link_libraries(nrfxlib_crypto) endif() From ec9999f7f812edea4679de01b72ae78e5438b1a1 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 22 Sep 2023 21:31:08 +0000 Subject: [PATCH 027/287] [nrf noup] loader: Do not check reset vector for XIP image The XIP image, 2, does not have reset vector. Signed-off-by: Dominik Ermel (cherry picked from commit 5a8e708be4ac381fccc74b45e2ce2fa4d2963723) (cherry picked from commit c2eb5fc16a00ac9803baf4c950a9d4d5062d68a6) --- boot/bootutil/src/loader.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 9dfb6506c..b71ff90b7 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1141,6 +1141,16 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * overwriting an application written to the incorrect slot. * This feature is only supported by ARM platforms. */ +#if MCUBOOT_IMAGE_NUMBER >= 3 + /* Currently the MCUboot can be configured for up to 3 image, where image number 2 is + * designated for XIP, where it is the second part of image stored in slots of image + * 0. This part of image is not bootable, as the XIP setup is done by the app in + * image 0 slot, and it does not carry the reset vector. + */ + if (area_id == FLASH_AREA_IMAGE_SECONDARY(2)) { + goto out; + } +#endif if (area_id == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); struct image_header *secondary_hdr = boot_img_hdr(state, slot); From 9d52cc5cd8e6b45bdb8becd92641d05acff03e22 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 18 Sep 2023 13:47:00 +0100 Subject: [PATCH 028/287] [nrf noup] zephyr: Add RAM flash configuration to cache for sysbuild Puts the flash simulation configurtion into cache variables that can be used by other applications and CMake code to know specifics on the simulated flash details Signed-off-by: Jamie McCrae (cherry picked from commit 9599724eace330fe16564ce6cc85e6ab65e6f2b0) (cherry picked from commit 002409bd8896e1d5d213bdf12a043525c5e34baa) --- boot/zephyr/CMakeLists.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index a288410bf..1d3009b22 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -579,3 +579,14 @@ zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) endif() + +if(SYSBUILD AND CONFIG_PCD_APP) + # Sysbuild requires details of the RAM flash device are stored to the cache of MCUboot so + # that they can be read when running partition manager + dt_nodelabel(ram_flash_dev NODELABEL flash_sim0) + dt_reg_addr(ram_flash_addr PATH ${ram_flash_dev}) + dt_reg_size(ram_flash_size PATH ${ram_flash_dev}) + + set(RAM_FLASH_ADDR "${ram_flash_addr}" CACHE STRING "" FORCE) + set(RAM_FLASH_SIZE "${ram_flash_size}" CACHE STRING "" FORCE) +endif() From 5e9aa4cb55cd88623976bb014c0a9c94425774be Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 17 Oct 2023 11:28:09 +0200 Subject: [PATCH 029/287] [nrf noup] zephyr: Boot even if EXT_ABI is not provided This removes the `return;` to ensure that the application is booted even if EXT_ABI is not provided to the application because it does not include `FW_INFO`. Added a bit more description to the error messages when FW_INFO is not found and EXT_ABI is not able to be provided to the next image. Ref. NCSDK-24132 Signed-off-by: Sigvart Hovland (cherry picked from commit 5b374005c2080103017c6f2f1df20cb7a158d5ef) (cherry picked from commit c6fe3b4309241bd8a6e42ab19d8efc6eb1b7b823) --- boot/zephyr/main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 8aec9cf0d..b5a65e460 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -206,13 +206,16 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); + const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); + bool provided = fw_info_ext_api_provide(firmware_info, true); #ifdef PM_S0_ADDRESS /* Only fail if the immutable bootloader is present. */ if (!provided) { - BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); - return; + if (firmware_info == NULL) { + BOOT_LOG_WRN("Unable to find firmware info structure in %p", vt); + } + BOOT_LOG_ERR("Failed to provide EXT_APIs to %p", vt); } #endif #endif From 186c927143ffac9ab1cd95bbf52ed459f1da127b Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Wed, 27 Sep 2023 15:18:04 +0200 Subject: [PATCH 030/287] =?UTF-8?q?[nrf=20noup]=C2=A0loader:=20Add=20firmw?= =?UTF-8?q?are=20version=20check=20downgrade=20prevention?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For nRF53, the only existing version number metadata is stored in the `firmware_info` structure in the network core. This utilizes PCD to read out the version number and compares it against the version number found in the secondary slot for the network core. Ref. NCSDK-21379 Signed-off-by: Sigvart Hovland (cherry picked from commit 20113950310c518f83e4c15f72bc6c4168e2fb8a) (cherry picked from commit fecd88c9910167129db07ca4e84848bd9847480d) --- boot/bootutil/src/loader.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index b71ff90b7..78e7faf2b 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -51,6 +51,10 @@ #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) #include +#ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION +#include +int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); +#endif #endif #ifdef MCUBOOT_ENC_IMAGES @@ -1097,9 +1101,21 @@ boot_validate_slot(struct boot_loader_state *state, int slot, #if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION) if (slot != BOOT_PRIMARY_SLOT) { /* Check if version of secondary slot is sufficient */ - rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ + && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) + if (BOOT_CURR_IMG(state) == 1) { + rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); + } else { + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + } +#else + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); +#endif if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); flash_area_erase(fap, 0, flash_area_get_size(fap)); From 0564022cdfa7d8a20c36a9c2d0bfb4b8be77c1da Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Mon, 9 Oct 2023 09:55:57 +0200 Subject: [PATCH 031/287] [nrf noup] boards: thingy53: disable GPIO ISR support Change disables GPIO interrupt support in Zephyr GPIO driver, which is not obligatory for MCUboot. This is needed to reduce memory footprint. Signed-off-by: Nikodem Kastelik (cherry picked from commit 39bbebf4de3fb0ec6ddb60176814500a8d93baea) (cherry picked from commit 2ce124eb1c3b59f89d410a3a94c6a3f7ec17a8f9) --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index 7d3bc0bec..e10656678 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -21,6 +21,7 @@ CONFIG_UART_LINE_CTRL=y # MCUBoot serial CONFIG_GPIO=y +CONFIG_GPIO_NRFX_INTERRUPT=n CONFIG_MCUBOOT_SERIAL=y CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_CDC_ACM=y From 513e91d505e178d4c4cbbe4fd5d3fa2230fc0ade Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 11 Apr 2024 17:26:50 +0200 Subject: [PATCH 032/287] [nrf noup] boot/zephyr/boards: nRF54l15pdk ext flash cfg Added configuration which allows to build MCUboot for nrf54l15pdk_nrf54l15_cpuapp with external flash used for the secondary slot. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 6f3eb6888f2351799e6896c854c7f977ef1b2fd3) (cherry picked from commit 38da586145f35cc5c270194f1307bbb11964b272) --- .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf | 8 ++++++++ .../nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 10 ++++++++++ 2 files changed, 18 insertions(+) create mode 100644 boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf create mode 100644 boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf new file mode 100644 index 000000000..841922dbd --- /dev/null +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf @@ -0,0 +1,8 @@ +CONFIG_MULTITHREADING=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_FLASH=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 +CONFIG_MAIN_STACK_SIZE=20480 +CONFIG_BOOT_MAX_IMG_SECTORS=512 +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay new file mode 100644 index 000000000..2341ffd26 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -0,0 +1,10 @@ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; + + +&mx25r64 { + status = "okay"; +}; From c85abeec4c1f0fbf1c4b563fb1219329c66a92f4 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 30 Mar 2021 22:45:17 +0200 Subject: [PATCH 033/287] [nrf noup] loader: work-around for multi-image builds Seems multi-image dependencies are not supported for multi-image in NCS yet. This is a workaround which reverts some lines to restore previous MCUboot behavior, so that Immutable bootloader + MCUBoot type builds will work. Ref. NCSDK-8681 Signed-off-by: Sigvart Hovland (cherry picked from commit 6f9c198e21bb817dc4cb92e2a82b815be2d71d0d) (cherry picked from commit 6b43e71b0a0f3a3ed119142ff38931452b2bd8c7) --- boot/bootutil/src/loader.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 78e7faf2b..72135088e 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -484,7 +484,7 @@ boot_verify_dependencies(struct boot_loader_state *state) if (rc == 0) { /* All dependencies've been satisfied, continue with next image. */ BOOT_CURR_IMG(state)++; - } else { + } else if (rc == BOOT_EBADIMAGE) { /* Cannot upgrade due to non-met dependencies, so disable all * image upgrades. */ @@ -493,7 +493,10 @@ boot_verify_dependencies(struct boot_loader_state *state) BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; } break; - } + } else { + /* Other error happened, images are inconsistent */ + return rc; + } } return rc; } @@ -1859,7 +1862,6 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) } #endif - /** * Performs a clean (not aborted) image update. * From 3213b0ca6ea88e264752d4ee71295ded7164c10a Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 31 Aug 2023 08:58:31 +0100 Subject: [PATCH 034/287] [nrf noup] loader: Fix missing PCD define check Fixes a missing PCD define check, an image might have the network core partition layout set but if PCD support is not enabled then it should not assume that PCD support is part of mcuboot. Signed-off-by: Jamie McCrae (cherry picked from commit dced8660b5dc8590d32d78950a70907e026dc5c5) (cherry picked from commit 333555503a2e6af868b99842dccc6888a6dff0af) --- boot/bootutil/src/loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 72135088e..666256778 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1348,7 +1348,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ - && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) && defined(CONFIG_PCD_APP) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available @@ -1376,7 +1376,8 @@ boot_validated_swap_type(struct boot_loader_state *state, swap_type = BOOT_SWAP_TYPE_NONE; } } -#endif /* CONFIG_SOC_NRF5340_CPUAPP */ +#endif /* CONFIG_SOC_NRF5340_CPUAPP && PM_CPUNET_B0N_ADDRESS && + !CONFIG_NRF53_MULTI_IMAGE_UPDATE && CONFIG_PCD_APP */ } return swap_type; From 0bf9af473ffd1e0750b1eb3d4b2a3d3918811955 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Wed, 31 May 2023 14:41:13 +0200 Subject: [PATCH 035/287] [nrf noup] boot: Add support for NSIB and multi-image This adds support for using both NSIB and the multi-image configuration in MCUboot. Before this was not possible due to upgradable bootloader support through NSIB was using the `UPDATEABLE_IMAGE_NUMBER` configuration to update the updateable bootloader. In this commit we change from using `FLASH_AREA_IMAGE_PRIMARY` to get the flash area ID to using the bootloader state where we set the flash area ID of the free updatable bootloader slot if the image is intended for this slot. Ref. NCSDK-19223 Ref. NCSDK-23305 Signed-off-by: Sigvart Hovland (cherry picked from commit a7cea4e88eae4925daf7b0ca7e74bb8d49f37858) (cherry picked from commit 73e8c3d240baaa3cf570fa84dbdf86cd61305093) --- boot/bootutil/src/loader.c | 44 +++++++++++++++++++------ boot/zephyr/include/sysflash/sysflash.h | 19 +++++++++-- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 666256778..19e8d801e 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1192,6 +1192,11 @@ boot_validate_slot(struct boot_loader_state *state, int slot, if (BOOT_CURR_IMG(state) == 1) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; +#ifdef PM_S1_ADDRESS + } else if (BOOT_CURR_IMG(state) == 0) { + min_addr = PM_S0_ADDRESS; + max_addr = pri_fa->fa_off + pri_fa->fa_size; +#endif } else #endif { @@ -1312,18 +1317,37 @@ boot_validated_swap_type(struct boot_loader_state *state, { const struct flash_area *primary_fa; rc = flash_area_open(flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - + BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), + &primary_fa); if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ + + /* Check start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off) { +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + const struct flash_area *nsib_fa; + + /* NSIB upgrade slot */ + rc = flash_area_open((uint32_t)_image_1_primary_slot_id, + &nsib_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + + /* Image is placed before Primary and within the NSIB slot */ + if (reset_addr > nsib_fa->fa_off + && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { + /* Set primary to be NSIB upgrade slot */ + BOOT_IMG_AREA(state, 0) = nsib_fa; + } +#else + return BOOT_SWAP_TYPE_NONE; +#endif + + } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } } @@ -1605,7 +1629,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs) BOOT_LOG_INF("Image %d upgrade secondary slot -> primary slot", image_index); BOOT_LOG_INF("Erasing the primary slot"); - rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), + rc = flash_area_open(flash_area_get_id(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)), &fap_primary_slot); assert (rc == 0); diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index b98e48bce..8b47a32b5 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -23,9 +23,24 @@ /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ -#ifdef PM_B0_ADDRESS - +#if defined(PM_B0_ADDRESS) extern uint32_t _image_1_primary_slot_id[]; +#endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ From e005bf866a3699eaba6a296988022af1a2074610 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 10 Aug 2023 17:32:48 +0000 Subject: [PATCH 036/287] [nrf noup] sysflash: Move partition manager definitions to pm_sysflash.h Making sysflash.h and pm_sysflash.h more readable. Signed-off-by: Dominik Ermel (cherry picked from commit fbe4075f6d08dc5e5dab52fa0d4b4bf512b1981e) (cherry picked from commit 628fcbd433167167bf22ed113750f01b9a554589) --- boot/zephyr/include/sysflash/pm_sysflash.h | 92 ++++++++++++++++++++++ boot/zephyr/include/sysflash/sysflash.h | 90 ++------------------- 2 files changed, 97 insertions(+), 85 deletions(-) create mode 100644 boot/zephyr/include/sysflash/pm_sysflash.h diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h new file mode 100644 index 000000000..377291e8b --- /dev/null +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef __PM_SYSFLASH_H__ +#define __PM_SYSFLASH_H__ +/* Blocking the __SYSFLASH_H__ */ +#define __SYSFLASH_H__ + +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +#if defined(PM_B0_ADDRESS) +extern uint32_t _image_1_primary_slot_id[]; +#endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) +#else + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) + +#endif /* PM_B0_ADDRESS */ + +#endif +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#endif /* __PM_SYSFLASH_H__ */ diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 8b47a32b5..f231c3d02 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -4,93 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __SYSFLASH_H__ -#define __SYSFLASH_H__ - #if USE_PARTITION_MANAGER -#include -#include - -#ifndef CONFIG_SINGLE_APPLICATION_SLOT - -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -#if defined(PM_B0_ADDRESS) -extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) -#else - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) - -#endif /* PM_B0_ADDRESS */ - +/* Blocking the rest of the file */ +#define __SYSFLASH_H__ +#include #endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID - -#else /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID -/* NOTE: Scratch parition is not used by single image DFU but some of - * functions in common files reference it, so the definitions has been - * provided to allow compilation of common units. - */ -#define FLASH_AREA_IMAGE_SCRATCH 0 -#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#else +#ifndef __SYSFLASH_H__ +#define __SYSFLASH_H__ -#include #include #include #include @@ -149,6 +71,4 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ -#endif /* USE_PARTITION_MANAGER */ - #endif /* __SYSFLASH_H__ */ From a251600dd2365d9da00f28e884770cfc43743fa7 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 11 Aug 2023 12:29:13 +0000 Subject: [PATCH 037/287] [nrf noup] sysflash: Add support for three images The commit modifies pm_sysflash.h to add support for three application images. Ref. NCSDK-19223 Signed-off-by: Dominik Ermel Signed-off-by: Sigvart Hovland (cherry picked from commit e80e79387a312046f24e9bc946c9fa5822687f0e) (cherry picked from commit dd4451ba547dd7b9e30701a694675b2fc81693c3) --- boot/zephyr/include/sysflash/pm_sysflash.h | 82 ++++++++++++---------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index 377291e8b..db60ddd03 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -11,37 +11,19 @@ #include #include +#include #ifndef CONFIG_SINGLE_APPLICATION_SLOT -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ -#if defined(PM_B0_ADDRESS) extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) +#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ @@ -56,26 +38,52 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) + +#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ + +/* Each pair of slots is separated by , and there is no terminating character */ +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID + +#if (MCUBOOT_IMAGE_NUMBER == 1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 2) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 3) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS, \ + FLASH_AREA_IMAGE_2_SLOTS #else +#error Unsupported number of images +#endif -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) +static inline uint32_t __flash_area_ids_for_slot(int img, int slot) +{ + static const int all_slots[] = { + ALL_AVAILABLE_SLOTS + }; + return all_slots[img * 2 + slot]; +}; -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) +#undef FLASH_AREA_IMAGE_0_SLOTS +#undef FLASH_AREA_IMAGE_1_SLOTS +#undef FLASH_AREA_IMAGE_2_SLOTS +#undef ALL_AVAILABLE_SLOTS -#endif /* PM_B0_ADDRESS */ +#define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) +#define FLASH_AREA_IMAGE_SECONDARY(x) __flash_area_ids_for_slot(x, 1) +#if !defined(CONFIG_BOOT_SWAP_USING_MOVE) +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ #else /* CONFIG_SINGLE_APPLICATION_SLOT */ From 6045ec967497abf777bf487db284c17f74bba0e0 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 15 Feb 2024 16:47:25 +0100 Subject: [PATCH 038/287] [nrf noup] loader: introduced cleanup of unusable secondary slot Added procedure which clean-up content of all the secondary slot which contains valid header but couldn't be assigned to any of supported primary images. This behavior is needed when configuration allows to use one secondary slot for collecting image for multiple primary slots. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 51e36d84b97b8de93f6b5b73dc81040616c2858a) (cherry picked from commit d002ffea70ed91640f71ea1f8bd45aee2428aaee) --- boot/bootutil/src/loader.c | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 19e8d801e..40c14ab51 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1272,6 +1272,87 @@ boot_update_security_counter(uint8_t image_index, int slot, } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ +#if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ +(defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) + +#define SEC_SLOT_VIRGIN 0 +#define SEC_SLOT_TOUCHED 1 +#define SEC_SLOT_ASSIGNED 2 + +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +/* This configuration is peculiar - the one physical secondary slot is + * mocking two logical secondary + */ +#define SEC_SLOT_PHYSICAL_CNT 1 +#else +#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER +#endif + +static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; + +static inline void sec_slot_touch(struct boot_loader_state *state) +{ + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); + + if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { + sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; + } +} + +static inline void sec_slot_mark_assigned(struct boot_loader_state *state) +{ + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); + + sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; +} + +/** + * Cleanu up all secondary slot which couldn't be assigned to any primary slot. + * + * This function erases content of each secondary slot which contains valid + * header but couldn't be assigned to any of supported primary images. + * + * This function is supposed to be called after boot_validated_swap_type() + * iterates over all the images in context_boot_go(). + */ +static void sec_slot_cleanup_if_unusable(void) +{ + uint8_t idx; + + for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { + if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { + const struct flash_area *secondary_fa; + int rc; + + rc = flash_area_open(flash_area_id_from_multi_image_slot(idx, BOOT_SECONDARY_SLOT), + &secondary_fa); + if (!rc) { + rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); + if (!rc) { + BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); + } + } + + if (rc) { + BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); + } + } + } +} +#else +static inline void sec_slot_touch(struct boot_loader_state *state) +{ +} +static inline void sec_slot_mark_assigned(struct boot_loader_state *state) +{ +} +static inline void sec_slot_cleanup_if_unusable(void) +{ +} +#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ + defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ + #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined @@ -1310,6 +1391,9 @@ boot_validated_swap_type(struct boot_loader_state *state, if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } + + sec_slot_touch(state); + #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) @@ -1344,6 +1428,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } #else return BOOT_SWAP_TYPE_NONE; + #endif } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { @@ -1352,7 +1437,9 @@ boot_validated_swap_type(struct boot_loader_state *state, } } #endif /* PM_S1_ADDRESS */ + sec_slot_mark_assigned(state); } + #endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); @@ -2459,6 +2546,9 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } + /* cleanup secondary slots which were recognized unusable*/ + sec_slot_cleanup_if_unusable(); + #if (BOOT_IMAGE_NUMBER > 1) if (has_upgrade) { /* Iterate over all the images and verify whether the image dependencies From 1bd0b62e4705f0a6d1a6ed4f723e4aa9fc7dfcc1 Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Tue, 16 Apr 2024 16:10:55 +0200 Subject: [PATCH 039/287] [nrf noup] boards: nrf54l15: Disable FPROTECT FPROTECT is not suppored yet for nrf54l15. Signed-off-by: Grzegorz Chwierut Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 592a0f140c5c9bc6ec3a436f03ab0249454cabf2) (cherry picked from commit da14b7071d91338c2e1f8fb35504204c0e18e95e) --- boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf index 43d8cebe3..8d8eb845f 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf @@ -7,4 +7,7 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + CONFIG_BOOT_WATCHDOG_FEED=n From dcef7e4813f5599cfe1302a6cc9b4b930ea85360 Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Fri, 17 May 2024 18:25:07 +0200 Subject: [PATCH 040/287] [nrf noup] loader: remove cleanup for direct xip mode Move ifdefs just to not add code for cleanup unusable slot when direct xip mode is enabled to avoid warnings. Signed-off-by: Grzegorz Chwierut (cherry picked from commit 948c3ad530822e58aae826984bae961626f4cca1) (cherry picked from commit 5f10ba072b7829587ae9fc91504cdb7f31fb11ab) --- boot/bootutil/src/loader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 40c14ab51..fe931fdef 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1272,6 +1272,8 @@ boot_update_security_counter(uint8_t image_index, int slot, } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) + #if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ (defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) @@ -1353,7 +1355,6 @@ static inline void sec_slot_cleanup_if_unusable(void) #endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined * that a swap operation is required, the image in the secondary slot is checked From 830ad12d077c584b2a99884e1129bba1a33dd72c Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Mon, 15 Apr 2024 18:54:45 +0200 Subject: [PATCH 041/287] [nrf noup] boot/zephyr/boards: nrf54l15pdk ext-flash partition Added DTS with partitioning which involves external flash as place for slo1_partition. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 1347dfbdc7b756eaac18d436f04f8755d57867a2) (cherry picked from commit 0cb3858db5eb3aefed01e2119fef9bb1a636108b) --- ...54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay index 2341ffd26..76b648903 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -4,7 +4,42 @@ }; }; +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; + +/delete-node/ &slot0_ns_partition; +/delete-node/ &slot1_ns_partition; + +/delete-node/ &storage_partition; + +&rram0 { + partitions { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x000000000 0x00014000>; + }; + slot0_partition: partition@14000 { + label = "image-0"; + reg = <0x000014000 0x0015A000>; + }; + storage_partition: partition@16E000 { + label = "storage"; + reg = < 0x16E000 0x9000 >; + }; + }; +}; &mx25r64 { status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot1_partition: partition@0 { + label = "image-1"; + reg = <0x000000000 0x0015A000>; + }; + }; }; From 494c935ae019a4be93d700ec49c65198aaa562ba Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Mon, 20 May 2024 15:48:33 +0200 Subject: [PATCH 042/287] [nrf noup] boot/zephyr/boards: nrf54l15pdk ext-flash update This patch supplements the configuration for external flash so MCUboot can be build with FILE_SUFFIX="ext_flash" for the nrf54l15pdk instead of explicitly configuration specification. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 8b7d37ff71b7306632186bfedc8fdd306f842fed) (cherry picked from commit a38a17e42cd01237eeca7eadfce2146a7f95535e) --- .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf | 7 +++++++ .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 1 + 2 files changed, 8 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf index 841922dbd..8fc12e074 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf @@ -6,3 +6,10 @@ CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 CONFIG_MAIN_STACK_SIZE=20480 CONFIG_BOOT_MAX_IMG_SECTORS=512 CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +# Ensure that the qspi driver is disabled by default +CONFIG_NORDIC_QSPI_NOR=n + +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + +CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay index 76b648903..ea024fcec 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -1,6 +1,7 @@ / { chosen { nordic,pm-ext-flash = &mx25r64; + zephyr,code-partition = &boot_partition; }; }; From 732083d3ec8b3bc76a6fd528ebc14a27df05d069 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Tue, 12 Mar 2024 12:30:52 +0100 Subject: [PATCH 043/287] [nrf noup] boards: thingy91x: enable serial recovery This patch disbales MCUBoot logging and enables serial recovery for the Thingy:91. Signed-off-by: Maximilian Deubel Signed-off-by: Bernt Johan Damslora (cherry picked from commit 6b95cd61058b116dcf9f186b5490b925230e3d3d) (cherry picked from commit b27bf533a51084055366271bac79fc3987ca660a) --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 10 ++++++++-- boot/zephyr/boards/thingy91x_nrf9151.conf | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index 72dfa7fca..37c7e95b1 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -32,7 +32,7 @@ CONFIG_USB_COMPOSITE_DEVICE=y CONFIG_USB_MASS_STORAGE=n CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x520F +CONFIG_USB_DEVICE_PID=0x910A CONFIG_BOOT_SERIAL_BOOT_MODE=y @@ -49,6 +49,12 @@ CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y CONFIG_FLASH_SIMULATOR_STATS=n CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +# Makes it possible to update the network core using the flash simulator CONFIG_NRF53_RECOVERY_NETWORK_CORE=y + +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y + +# Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 +CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 33cd3301c..2efe1e170 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -6,3 +6,12 @@ CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_SPI_NOR_SFDP_DEVICETREE=y CONFIG_MULTITHREADING=y + +# Disable Zephyr console and use UART for MCUboot serial recovery instead +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n +CONFIG_MCUBOOT_SERIAL=y + +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y From 4ae34b4e81382f2f7259472f0eddd21dbc471d99 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 17 May 2024 14:14:54 +0200 Subject: [PATCH 044/287] [nrf noup] boot: zephyr: Disable boot banner if NCS_BOOT_BANNER is used Mcuboot's boot banner should not be used if NCS boot banner is enabled. Signed-off-by: Robert Lubos (cherry picked from commit 220096b278e3c1ddb91249920d12688626e4a02e) (cherry picked from commit 6e473055d0898121dbda591763ca25afa060ddae) --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a641f3e6a..7cf16e816 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -778,6 +778,7 @@ config BOOT_DISABLE_CACHES config MCUBOOT_BOOT_BANNER bool "Use MCUboot boot banner" depends on BOOT_BANNER + depends on !NCS_BOOT_BANNER depends on "$(APP_VERSION_EXTENDED_STRING)" != "" default y help From efafb012f0a647a5e57a9438bc4b38a7cc5db1cf Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Mon, 27 May 2024 13:59:49 +0200 Subject: [PATCH 045/287] [nrf noup] boot/zephyr: fix fw_info search By the upstream patch the vt get now the pointer to the copy of the arm_vector instead of original. This patch fixes address of the firmware which is to be taken by the fw_info_find. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 592f636c54a3b4c702c8e90a0d791ab1f00c4082) (cherry picked from commit 362a9447b0196e12ec1fd03f2f1d1f864cb1a9ea) --- boot/zephyr/main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index b5a65e460..5042218b3 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -206,7 +206,14 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); + uintptr_t fw_start_addr; + + rc = flash_device_base(rsp->br_flash_dev_id, &fw_start_addr); + assert(rc == 0); + + fw_start_addr += rsp->br_image_off + rsp->br_hdr->ih_hdr_size; + + const struct fw_info *firmware_info = fw_info_find(fw_start_addr); bool provided = fw_info_ext_api_provide(firmware_info, true); #ifdef PM_S0_ADDRESS From ccffc83489330ec2dc4a57902b100d1b738641ec Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 28 May 2024 09:31:16 +0000 Subject: [PATCH 046/287] [nrf noup] Revert of zephyr: arm: Update reading the flash image reset vector This is revert of upstream commit 453096b17ddc3aac7bf6afb97c40591d5ea3aa9c which was supposed to allow picking interrupt vector table from flash area but the whole modification unfortunately misunderstood difference between flash device ID and flash area ID. The commit is not important for sdk-nrf and requires re-design and fixing upstream. Signed-off-by: Dominik Ermel (cherry picked from commit ad758099070ad3c3ff157e1dd9f7a7cd96abc8f4) (cherry picked from commit 861a34e32061423cfde36b66a0db64aff769774d) --- boot/zephyr/flash_map_extended.c | 8 ++------ boot/zephyr/main.c | 20 +++++--------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index 4631da75b..d0744afbd 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -141,12 +141,8 @@ int flash_area_sector_from_off(off_t off, struct flash_sector *sector) uint8_t flash_area_get_device_id(const struct flash_area *fa) { -#if defined(CONFIG_ARM) - return fa->fa_id; -#else - (void)fa; - return FLASH_DEVICE_ID; -#endif + (void)fa; + return FLASH_DEVICE_ID; } #define ERASED_VAL 0xff diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 5042218b3..5ae524feb 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -174,26 +174,16 @@ static void do_boot(struct boot_rsp *rsp) /* Get ram address for image */ vt = (struct arm_vector_table *)(rsp->br_hdr->ih_load_addr + rsp->br_hdr->ih_hdr_size); #else + uintptr_t flash_base; int rc; - const struct flash_area *fap; - static uint32_t dst[2]; /* Jump to flash image */ - rc = flash_area_open(rsp->br_flash_dev_id, &fap); - assert(rc == 0); - - rc = flash_area_read(fap, rsp->br_hdr->ih_hdr_size, dst, sizeof(dst)); + rc = flash_device_base(rsp->br_flash_dev_id, &flash_base); assert(rc == 0); -#ifndef CONFIG_ASSERT - /* Enter a lock up as asserts are disabled */ - if (rc != 0) { - while (1); - } -#endif - - flash_area_close(fap); - vt = (struct arm_vector_table *)dst; + vt = (struct arm_vector_table *)(flash_base + + rsp->br_image_off + + rsp->br_hdr->ih_hdr_size); #endif if (IS_ENABLED(CONFIG_SYSTEM_TIMER_HAS_DISABLE_SUPPORT)) { From f1393e6b8dde7f86513942271ad46c284fe22d3b Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Wed, 5 Jun 2024 15:46:13 +0200 Subject: [PATCH 047/287] [nrf noup] zephyr/boards: fix nrf54l15pdk ext flash dts overlay Align to changes in DTS: renamed: rram0 -> cpuapp_rram sized up cpauapp_rram region szie as part of it was reserved for cpuflpr_rram (which is not used by this config). Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 48e6e27175230a817fc47857696b006ddd15f6f3) (cherry picked from commit 4d86e379ebfd94c508735edf59de304d5ecae72d) --- .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay index ea024fcec..60ee6fe51 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -14,7 +14,8 @@ /delete-node/ &storage_partition; -&rram0 { +&cpuapp_rram { + reg = < 0x0 DT_SIZE_K(1524) >; partitions { boot_partition: partition@0 { label = "mcuboot"; From f754885576c2c1f19b53e6a41dc718286964ed40 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jun 2024 12:32:51 +0100 Subject: [PATCH 048/287] [nrf noup] boot: zephyr: Add NCS boot banner Adds a boot banner which shows as MCUboot Signed-off-by: Jamie McCrae (cherry picked from commit 0148f9641558629109d6e073740a2e7f2cd06e1d) (cherry picked from commit 8f7483332e1bca22fee415b582267ff0481fac6a) --- boot/zephyr/prj.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 23b5f3b93..e4f7d9030 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -37,3 +37,6 @@ CONFIG_CBPRINTF_NANO=y ### Use the minimal C library to reduce flash usage CONFIG_MINIMAL_LIBC=y CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 + +# NCS boot banner +CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" From de9d942b888ed8a2064fc36c44ef9cb93993d6db Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 13 Jun 2024 16:34:55 +0200 Subject: [PATCH 049/287] [nrf noup] boot/../loader: skip downgrade prevention for s1/s0 This patch introduces skip on checking downgrade for s1/s0 upgrade image (chain-loaded by NSIB). which is used for upgrade MCUboot instance itself. Reason is that sdk-mcuboot has not access to semantic version of its own image. I also shouldn't touch HW counter used for hardware downgrade prevention for the application image (which was the case). HW counters for s0/s1 image are owned by NSIB because its role is to prevnt dongrades of s0/s1 MCUboot. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit cc781180dd791b4ac7d9c875cf8ada38a2de0a12) (cherry picked from commit 1953d93aa4f09ac6f46af0bdfa1e830c65886796) --- boot/bootutil/src/loader.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index fe931fdef..37a435644 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -70,6 +70,9 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; +#ifdef PM_S1_ADDRESS +static bool owner_nsib[BOOT_IMAGE_NUMBER] = {false}; +#endif #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; @@ -1370,6 +1373,9 @@ boot_validated_swap_type(struct boot_loader_state *state, int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); bool upgrade_valid = false; +#if defined(PM_S1_ADDRESS) + owner_nsib[BOOT_CURR_IMG(state)] = false; +#endif #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = @@ -1426,6 +1432,7 @@ boot_validated_swap_type(struct boot_loader_state *state, && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { /* Set primary to be NSIB upgrade slot */ BOOT_IMG_AREA(state, 0) = nsib_fa; + owner_nsib[BOOT_CURR_IMG(state)] = true; } #else return BOOT_SWAP_TYPE_NONE; @@ -1436,6 +1443,10 @@ boot_validated_swap_type(struct boot_loader_state *state, /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } + + if ((primary_fa->fa_off == PM_S0_ADDRESS) || (primary_fa->fa_off == PM_S1_ADDRESS)) { + owner_nsib[BOOT_CURR_IMG(state)] = true; + } } #endif /* PM_S1_ADDRESS */ sec_slot_mark_assigned(state); @@ -2409,6 +2420,13 @@ check_downgrade_prevention(struct boot_loader_state *state) uint32_t security_counter[2]; int rc; +#if defined(PM_S1_ADDRESS) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + /* Downgrade prevention on S0/S1 image is managed by NSIB */ + return 0; + } +#endif + if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) { /* If there was security no counter in slot 0, allow swap */ rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 0).hdr), From f07918de07319dff91be492bf13f9a8320b73824 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 18 Jun 2024 17:35:41 +0200 Subject: [PATCH 050/287] [nrf noup] boot/../loader: reboot after updating s0/s1 As this is MCUboot updating itself, it should reboot the device so NSIB will chainload the update MCUboot Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 29fdb635a4fd7fab89281a1204383bc73c20c63f) (cherry picked from commit 5f52f93057adef29fcc9bb1f0cc74766af38e84c) --- boot/bootutil/src/loader.c | 10 ++++++++++ boot/zephyr/Kconfig | 1 + 2 files changed, 11 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 37a435644..63ba35ad6 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,6 +49,10 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#ifdef __ZEPHYR__ +#include +#endif + #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) #include #ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION @@ -2636,6 +2640,12 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); +#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + sys_reboot(SYS_REBOOT_COLD); + + } +#endif break; case BOOT_SWAP_TYPE_FAIL: diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 7cf16e816..f58eb1ba3 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -18,6 +18,7 @@ config MCUBOOT select MPU_ALLOW_FLASH_WRITE if ARM_MPU select USE_DT_CODE_PARTITION if HAS_FLASH_LOAD_OFFSET select MCUBOOT_BOOTUTIL_LIB + select REBOOT if SECURE_BOOT config BOOT_USE_MBEDTLS bool From e8705940ce0eebb48144854955d69465c69c5462 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 29 Aug 2024 12:41:37 +0100 Subject: [PATCH 051/287] [nrf noup] bootutil: loader: Fix netcore address checking Fixes an issues with wrongly checking the network core reset address Signed-off-by: Jamie McCrae (cherry picked from commit fcf0a3154845a17d90abd767b35716d1dee96df4) (cherry picked from commit b3d65d995a54cc99d44454a51f28098331eba6f4) --- boot/bootutil/src/loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 63ba35ad6..7ec789588 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1407,7 +1407,7 @@ boot_validated_swap_type(struct boot_loader_state *state, #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS - if(reset_addr < PM_CPUNET_B0N_ADDRESS) + if(!(reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS)) #endif { const struct flash_area *primary_fa; @@ -1480,7 +1480,8 @@ boot_validated_swap_type(struct boot_loader_state *state, * update and indicate to the caller of this function that no update is * available */ - if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS && + reset_addr < PM_CPUNET_APP_END_ADDRESS) { struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); From 9321e7f46a878d237209f4f596d5e88a8cf6aca3 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Wed, 18 Sep 2024 12:28:37 +0200 Subject: [PATCH 052/287] [nrf noup] boards: nrf54l15dk: Disable FPROTECT FPROTECT is not suppored for nrf54l15dk. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 123454f993b1dd08e9f158ee4df95247a1ea81d9) (cherry picked from commit 4786da41ce7079cc8c49bf0ba029c062e056f938) --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf index 43d8cebe3..8d8eb845f 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -7,4 +7,7 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + CONFIG_BOOT_WATCHDOG_FEED=n From 474a92290901ffb468978574087e98fc89fb3e80 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 22 Aug 2024 14:17:46 +0100 Subject: [PATCH 053/287] [nrf noup] zephyr: Add support for compressed image updates Adds support for LZMA-compressed firmware updates Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit a242e9124370dce206f7933a4f85a707e07c915f) (cherry picked from commit 880982096a88bdb8f5f11df06b40ec2f45ff9bad) (cherry picked from commit 16a77893d9c6c461f79178b2148159e32949d9ac) (cherry picked from commit 99fee8932912810517d2680d038b7d85fc144bab) (cherry picked from commit 0a70e4968d1f65118a2b5a17a27ed990c296bb5f) (cherry picked from commit e369d25711685470cbdbbbaef5c0c162f8c7d8d3) --- boot/bootutil/src/image_validate.c | 226 ++++ boot/bootutil/src/loader.c | 102 +- boot/zephyr/CMakeLists.txt | 6 + boot/zephyr/Kconfig | 10 +- boot/zephyr/decompression.c | 1115 +++++++++++++++++ .../include/compression/decompression.h | 104 ++ 6 files changed, 1540 insertions(+), 23 deletions(-) create mode 100644 boot/zephyr/decompression.c create mode 100644 boot/zephyr/include/compression/decompression.h diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ec5d986df..b1a50f126 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -40,6 +40,15 @@ #include "mcuboot_config/mcuboot_config.h" +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -416,6 +425,68 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, FIH_DECLARE(security_counter_valid, FIH_FAILURE); #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* If the image is compressed, the integrity of the image must also be validated */ + if (MUST_DECOMPRESS(fap, image_index, hdr)) { + bool found_decompressed_size = false; + bool found_decompressed_sha = false; + bool found_decompressed_signature = false; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + uint16_t expected_size = 0; + bool *found_flag = NULL; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + switch (type) { + case IMAGE_TLV_DECOMP_SIZE: + expected_size = sizeof(size_t); + found_flag = &found_decompressed_size; + break; + case IMAGE_TLV_DECOMP_SHA: + expected_size = IMAGE_HASH_SIZE; + found_flag = &found_decompressed_sha; + break; + case IMAGE_TLV_DECOMP_SIGNATURE: + found_flag = &found_decompressed_signature; + break; + default: + continue; + }; + + if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { + rc = -1; + goto out; + } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { + rc = -1; + goto out; + } + + *found_flag = true; + } + + rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); + if (rc) { + goto out; + } + } +#endif + rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); if (rc) { @@ -587,6 +658,161 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* Only after all previous verifications have passed, perform a dry-run of the decompression + * and ensure the image is valid + */ + if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { + image_hash_valid = 0; + FIH_SET(valid_signature, FIH_FAILURE); + + rc = bootutil_img_hash_decompress(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, + hash, seed, seed_len); + if (rc) { + goto out; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + /* Verify the image hash. This must always be present. */ + if (len != sizeof(hash)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); + if (rc) { + goto out; + } + + FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + image_hash_valid = 1; + } + } + + rc = !image_hash_valid; + if (rc) { + goto out; + } + +#ifdef EXPECTED_SIG_TLV +#ifdef EXPECTED_KEY_TLV + rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == EXPECTED_KEY_TLV) { + /* + * Determine which key we should be checking. + */ + if (len > KEY_BUF_SIZE) { + rc = -1; + goto out; + } +#ifndef MCUBOOT_HW_KEY + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(buf, len); +#else + rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(image_index, key_buf, len); +#endif /* !MCUBOOT_HW_KEY */ + /* + * The key may not be found, which is acceptable. There + * can be multiple signatures, each preceded by a key. + */ + } + } +#endif /* EXPECTED_KEY_TLV */ + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Ignore this signature if it is out of bounds. */ + if (key_id < 0 || key_id >= bootutil_key_cnt) { + key_id = -1; + continue; + } + + if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + + FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), + buf, len, key_id); + key_id = -1; + } + } +#endif /* EXPECTED_SIG_TLV */ + } +#endif + +#ifdef EXPECTED_SIG_TLV + FIH_SET(fih_rc, valid_signature); +#endif + out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 7ec789588..53f40c33a 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,6 +49,11 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + #ifdef __ZEPHYR__ #include #endif @@ -653,35 +658,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) goto done; } - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); +#ifdef MCUBOOT_DECOMPRESS_IMAGES + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { + uint32_t tmp_size = 0; - if (flash_area_read(fap, off, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } + rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); + + if (rc) { + rc = BOOT_EBADIMAGE; + goto done; + } + + off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { + rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); + + if (rc) { rc = BOOT_EBADIMAGE; goto done; } - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + off += tmp_size; + + if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + + boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, + sizeof(info))) { rc = BOOT_EFLASH; goto done; } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + info.it_tlv_tot; + } else { +#else + if (1) { +#endif + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); + + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + protect_tlv_size + info.it_tlv_tot; } - *size = off + protect_tlv_size + info.it_tlv_tot; rc = 0; done: @@ -970,10 +1016,10 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } #else - if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && - (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) - { - return false; + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { + if (!boot_is_compressed_header_valid(hdr, fap, state)) { + return false; + } } #endif @@ -1153,6 +1199,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * attempts to validate and boot it. */ } + #if !defined(__BOOTSIM__) BOOT_LOG_ERR("Image in the %s slot is not valid!", (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); @@ -1589,6 +1636,9 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + struct image_header *hdr; +#endif TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); @@ -1614,6 +1664,16 @@ boot_copy_region(struct boot_loader_state *state, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + + if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { + /* Use alternative function for compressed images */ + return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, + BUF_SZ); + } +#endif + bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 1d3009b22..253ab2537 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -249,6 +249,12 @@ if(CONFIG_BOOT_ENCRYPT_EC256) ) endif() +if(CONFIG_BOOT_DECOMPRESSION) + zephyr_library_sources( + decompression.c + ) +endif() + if(CONFIG_MCUBOOT_SERIAL) zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c) zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index f58eb1ba3..34c6be3a4 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -796,6 +796,10 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool + depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) + depends on !SINGLE_APPLICATION_SLOT && !BOOT_ENCRYPT_IMAGE && BOOT_UPGRADE_ONLY + depends on UPDATEABLE_IMAGE_NUMBER = 1 + default y help Hidden symbol which should be selected if a system provided decompression support. @@ -803,6 +807,8 @@ if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION bool "Decompression" + select NRF_COMPRESS_CLEANUP + select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to @@ -811,9 +817,9 @@ menuconfig BOOT_DECOMPRESSION if BOOT_DECOMPRESSION config BOOT_DECOMPRESSION_BUFFER_SIZE - int "Write buffer size" + int range 16 16384 - default 4096 + default NRF_COMPRESS_CHUNK_SIZE help The size of a secondary buffer used for writing decompressed data to the storage device. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c new file mode 100644 index 000000000..062cdbc61 --- /dev/null +++ b/boot/zephyr/decompression.c @@ -0,0 +1,1115 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include "compression/decompression.h" +#include "bootutil/crypto/sha.h" +#include "bootutil/bootutil_log.h" + +#if !defined(__BOOTSIM__) +#define TARGET_STATIC static +#else +#define TARGET_STATIC +#endif + +#if defined(MCUBOOT_SIGN_RSA) +#if MCUBOOT_SIGN_RSA_LEN == 2048 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS +#elif MCUBOOT_SIGN_RSA_LEN == 3072 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA3072_PSS +#endif +#elif defined(MCUBOOT_SIGN_EC256) || \ + defined(MCUBOOT_SIGN_EC384) || \ + defined(MCUBOOT_SIGN_EC) +#define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA_SIG +#elif defined(MCUBOOT_SIGN_ED25519) +#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 +#endif + +/* Number of times that consumed data by decompression system can be 0 in a row before aborting */ +#define OFFSET_ZERO_CHECK_TIMES 3 + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx); + +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state) +{ + /* Image is compressed in secondary slot, need to check if fits into the primary slot */ + bool opened_flash_area = false; + int primary_fa_id; + int rc; + int size_check; + int size; + uint32_t protected_tlvs_size; + uint32_t decompressed_size; + + if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { + opened_flash_area = true; + } + + primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); + rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + assert(rc == 0); + + size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + + if (opened_flash_area) { + (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + } + + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, decompressed_size, hdr->ih_hdr_size)) { + return false; + } + + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlvs_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, size, protected_tlvs_size)) { + return false; + } + + if (size >= size_check) { + BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", + size, size_check); + + return false; + } + + return true; +} + +int bootutil_img_hash_decompress(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 *hash_result, + uint8_t *seed, int seed_len) +{ + int rc; + uint32_t read_pos = 0; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t decompressed_image_size; + struct nrf_compress_implementation *compression = NULL; + TARGET_STATIC struct image_header modified_hdr; + bootutil_sha_context sha_ctx; + uint8_t flash_erased_value; + + bootutil_sha_init(&sha_ctx); + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + + goto finish_without_clean; + } + + compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish_without_clean; + } + + rc = compression->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish_without_clean; + } + + /* We need a modified header which has the updated sizes, start with the original header */ + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + /* Extract the decompressed image size from the protected TLV, set it and remove the + * compressed image flags + */ + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate the protected TLV size, these will not include the decompressed + * sha/size/signature entries + */ + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + bootutil_sha_update(&sha_ctx, &modified_hdr, sizeof(modified_hdr)); + read_pos = sizeof(modified_hdr); + flash_erased_value = flash_area_erased_val(fap); + memset(tmp_buf, flash_erased_value, tmp_buf_sz); + + while (read_pos < modified_hdr.ih_hdr_size) { + uint32_t copy_size = tmp_buf_sz; + + if ((read_pos + copy_size) > modified_hdr.ih_hdr_size) { + copy_size = modified_hdr.ih_hdr_size - read_pos; + } + + bootutil_sha_update(&sha_ctx, tmp_buf, copy_size); + read_pos += copy_size; + } + + /* Read in compressed data, decompress and add to hash calculation */ + read_pos = 0; + + while (read_pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - read_pos; + uint32_t tmp_off = 0; + uint8_t offset_zero_check = 0; + + if (copy_size > tmp_buf_sz) { + copy_size = tmp_buf_sz; + } + + rc = flash_area_read(fap, (hdr->ih_hdr_size + read_pos), tmp_buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint8_t *output = NULL; + uint32_t output_size = 0; + uint32_t chunk_size; + bool last_packet = false; + + chunk_size = compression->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + + if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { + last_packet = true; + } + + rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset, + &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + write_pos += output_size; + + if (write_pos > decompressed_image_size) { + BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", + write_pos); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + /* Additional dry-run validity checks */ + if (last_packet == true && write_pos == 0) { + /* Last packet and we still have no output, this is a faulty update */ + BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + if (offset == 0) { + /* If the decompression system continually consumes 0 bytes, then there is a + * problem with this update image, abort and mark image as bad + */ + if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { + BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + ++offset_zero_check; + + break; + } else { + offset_zero_check = 0; + } + + if (output_size > 0) { + bootutil_sha_update(&sha_ctx, output, output_size); + } + + tmp_off += offset; + } + + read_pos += copy_size; + } + + /* If there are any protected TLVs present, add them after the main decompressed image */ + if (modified_hdr.ih_protect_tlv_size > 0) { + rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, + tmp_buf_sz, &sha_ctx); + } + + bootutil_sha_finish(&sha_ctx, hash_result); + +finish: + /* Clean up decompression system */ + (void)compression->deinit(NULL); + +finish_without_clean: + bootutil_sha_drop(&sha_ctx); + + return rc; +} + +static int boot_copy_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t protected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t off; + uint32_t write_pos = 0; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Skip these TLVs as they are not needed */ + continue; + } else { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left = len; + + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - + header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + (len - data_size_left)), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + } + + *written = write_pos; + +out: + return rc; +} + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx) +{ + int rc; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + + bootutil_sha_update(sha_ctx, &tlv_info_header, sizeof(tlv_info_header)); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + while (true) { + uint32_t read_off = 0; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Skip these TLVs as they are not needed */ + continue; + } + + tlv_header.it_type = type; + tlv_header.it_len = len; + + bootutil_sha_update(sha_ctx, &tlv_header, sizeof(tlv_header)); + + while (read_off < len) { + uint32_t copy_size = buf_size; + + if (copy_size > (len - read_off)) { + copy_size = len - read_off; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + read_off), buf, copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + read_off), copy_size, fap_src->fa_id, rc); + + goto out; + } + + bootutil_sha_update(sha_ctx, buf, copy_size); + read_off += copy_size; + } + } + +out: + return rc; +} + +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = hdr->ih_protect_tlv_size; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Exclude these TLVs as they will be copied to the unprotected area */ + tlv_size -= len + sizeof(struct image_tlv); + } + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries then omit protected TLV section entirely */ + tlv_size = 0; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = sizeof(struct image_tlv_info); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off) && type != IMAGE_TLV_DECOMP_SHA && + type != IMAGE_TLV_DECOMP_SIGNATURE) { + /* Include size of protected hash and signature as these will be replacing the + * original ones + */ + continue; + } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + /* Exclude the original unprotected TLVs for signature and hash, the length of the + * signature of the compressed data might not be the same size as the signaute of the + * decompressed data, as is the case when using ECDSA-P256 + */ + continue; + } + + tlv_size += len + sizeof(struct image_tlv); + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries in the unprotected TLV section then there is something wrong + * with this image + */ + BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); + rc = BOOT_EBADIMAGE; + + goto out; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +static int boot_copy_unprotected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t unprotected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t write_pos = 0; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv_iter it_protected; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_INFO_MAGIC, + .it_tlv_tot = unprotected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, false); + if (rc) { + goto out; + } + + while (true) { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off)) { + /* Skip protected TLVs */ + continue; + } + + /* Change the values of these fields from having the data in the compressed image + * unprotected TLV (which is valid only for the compressed image data) to having the + * fields in the protected TLV section (which is valid for the decompressed image data). + * The compressed data is no longer needed + */ + if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + rc = bootutil_tlv_iter_begin(&it_protected, hdr, fap_src, (type == EXPECTED_HASH_TLV ? + IMAGE_TLV_DECOMP_SHA : + IMAGE_TLV_DECOMP_SIGNATURE), + true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it_protected, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + type = EXPECTED_HASH_TLV; + } else { + type = EXPECTED_SIG_TLV; + } + } + + data_size_left = len; + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + len - data_size_left), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + + *written = write_pos; + +out: + return rc; +} + +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size) +{ + int rc; + uint32_t pos = 0; + uint16_t decomp_buf_size = 0; + uint16_t write_alignment; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t unprotected_tlv_size = 0; + uint32_t tlv_write_size = 0; + uint32_t decompressed_image_size; + struct nrf_compress_implementation *compression = NULL; + struct image_header *hdr; + TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4))); + TARGET_STATIC struct image_header modified_hdr; + + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + rc = compression->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + write_alignment = flash_area_align(fap_dst); + + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + rc = bootutil_get_img_decomp_size(hdr, fap_src, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate protected TLV size for target image once items are removed */ + rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + + rc = boot_size_unprotected_tlvs(hdr, fap_src, &unprotected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + /* Write out the image header first, this should be a multiple of the write size */ + rc = flash_area_write(fap_dst, off_dst, &modified_hdr, sizeof(modified_hdr)); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + /* Read in, decompress and write out data */ + while (pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - pos; + uint32_t tmp_off = 0; + + if (copy_size > buf_size) { + copy_size = buf_size; + } + + rc = flash_area_read(fap_src, off_src + hdr->ih_hdr_size + pos, buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint32_t output_size = 0; + uint32_t chunk_size; + uint32_t compression_buffer_pos = 0; + uint8_t *output = NULL; + bool last_packet = false; + + chunk_size = compression->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + + if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { + last_packet = true; + } + + rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset, + &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + /* Copy data to secondary buffer for writing out */ + while (output_size > 0) { + uint32_t data_size = (sizeof(decomp_buf) - decomp_buf_size); + + if (data_size > output_size) { + data_size = output_size; + } + + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], data_size); + compression_buffer_pos += data_size; + + decomp_buf_size += data_size; + output_size -= data_size; + + /* Write data out from secondary buffer when it is full */ + if (decomp_buf_size == sizeof(decomp_buf)) { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, sizeof(decomp_buf)); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), sizeof(decomp_buf), + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + write_pos += sizeof(decomp_buf); + decomp_buf_size = 0; + } + } + + tmp_off += offset; + } + + pos += copy_size; + } + + /* Clean up decompression system */ + (void)compression->deinit(NULL); + + if (protected_tlv_size > 0) { + rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), protected_tlv_size, + decomp_buf, DECOMP_BUF_SIZE, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + + goto finish; + } + + write_pos += tlv_write_size; + } + + tlv_write_size = 0; + rc = boot_copy_unprotected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), unprotected_tlv_size, + decomp_buf, DECOMP_BUF_SIZE, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + + goto finish; + } + + write_pos += tlv_write_size; + + /* Check if we have unwritten data buffered up and, if so, write it out */ + if (decomp_buf_size > 0) { + uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); + + /* Check if additional write padding should be applied to meet the minimum write size */ + if (write_padding_size) { + uint8_t flash_erased_value; + + flash_erased_value = flash_area_erased_val(fap_dst); + memset(&decomp_buf[decomp_buf_size], flash_erased_value, write_padding_size); + decomp_buf_size += write_padding_size; + } + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf, + decomp_buf_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + write_pos += decomp_buf_size; + decomp_buf_size = 0; + } + +finish: + memset(decomp_buf, 0, sizeof(decomp_buf)); + + return rc; +} + +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size) +{ + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + if (hdr == NULL || fap == NULL || img_decomp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_decomp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_decomp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + + return BOOT_EFLASH; + } + + return 0; +} diff --git a/boot/zephyr/include/compression/decompression.h b/boot/zephyr/include/compression/decompression.h new file mode 100644 index 000000000..f8a676ac5 --- /dev/null +++ b/boot/zephyr/include/compression/decompression.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_DECOMPRESSION_ +#define H_DECOMPRESSION_ + +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil/bootutil_public.h" +#include "bootutil/image.h" +#include "../src/bootutil_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Checks if a compressed image header is valid. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param state Bootloader state object. + * + * @return true if valid; false if invalid. + */ +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state); + +/** + * Reads in compressed image data from a slot, decompresses it and writes it out to a destination + * slot, including corresponding image headers and TLVs. + * + * @param state Bootloader state object. + * @param fap_src Flash area of the source slot. + * @param fap_dst Flash area of the destination slot. + * @param off_src Offset of the source slot to read from (should be 0). + * @param off_dst Offset of the destination slot to write to (should be 0). + * @param sz Size of the source slot data. + * @param buf Temporary buffer for reading data from. + * @param buf_size Size of temporary buffer. + * + * @return 0 on success; nonzero on failure. + */ +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size); + +/** + * Gets the total data size (excluding headers and TLVs) of a compressed image when it is + * decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param img_decomp_size Pointer to variable that will be updated with the decompressed image + * size. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size); + +/** + * Calculate MCUboot-compatible image hash of compressed image slot. + * + * @param enc_state Not currently used, set to NULL. + * @param image_index Image number. + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param tmp_buf Temporary buffer for reading data from. + * @param tmp_buf_sz Size of temporary buffer. + * @param hash_result Pointer to a variable that will be updated with the image hash. + * @param seed Not currently used, set to NULL. + * @param seed_len Not currently used, set to 0. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_img_hash_decompress(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 *hash_result, + uint8_t *seed, int seed_len); + +/** + * Calculates the size that the compressed image protected TLV section will occupy once the image + * has been decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param sz Pointer to variable that will be updated with the protected TLV size. + * + * @return 0 on success; nonzero on failure. + */ +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap_src, + uint32_t *sz); + +#ifdef __cplusplus +} +#endif + +#endif /* H_DECOMPRESSION_ */ From 049e896648b012a036bda2f451fbd279e396102b Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Thu, 14 Feb 2019 13:20:34 +0100 Subject: [PATCH 054/287] [nrf noup] boot: Add shared crypto for ECDSA and SHA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add functions for ecdsa_verify_secp256r1 and sha256 to use the shared crypto API * Add Kconfig and CMake variables for selecting shared crypto when using ecdsa * Add custom section to project for placing the API section in the correct location in flash * Add kconfig fragment for using external crypto Signed-off-by: Sigvart Hovland Signed-off-by: Martí Bolívar Signed-off-by: Emil Obalski Signed-off-by: Andrzej Puzdrowski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Trond Einar Snekvik Signed-off-by: Georgios Vasilakis Signed-off-by: Johann Fischer Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 4e0dee6f1f656d682ee9e9f92d146e64cf8cce04) (cherry picked from commit 106ade3f4867bfb7f660fa1ec959c40f57a23bd2) --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 64 +++++++++++++++++-- boot/bootutil/include/bootutil/crypto/sha.h | 32 ++++++++++ boot/zephyr/CMakeLists.txt | 2 + boot/zephyr/external_crypto.conf | 20 ++++++ .../include/mcuboot_config/mcuboot_config.h | 5 +- 5 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 boot/zephyr/external_crypto.conf diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 3b0541072..85355f20c 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -34,6 +34,7 @@ #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 @@ -70,12 +71,18 @@ #include "bootutil/sign_key.h" #include "common.h" +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + #include + #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_PSA_CRYPTO) + defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO)) \ + && !defined(MCUBOOT_USE_PSA_CRYPTO) /* * Declaring these like this adds NULL termination. */ @@ -127,8 +134,6 @@ static int bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* (MCUBOOT_USE_TINYCRYPT || MCUBOOT_USE_MBED_TLS || MCUBOOT_USE_CC310) && !MCUBOOT_USE_PSA_CRYPTO */ -#if defined(MCUBOOT_USE_TINYCRYPT) -#ifndef MCUBOOT_ECDSA_NEED_ASN1_SIG /* * cp points to ASN1 string containing an integer. * Verify the tag, and that the length is 32 bytes. Helper function. @@ -178,8 +183,8 @@ static int bootutil_decode_sig(uint8_t signature[NUM_ECC_BYTES * 2], uint8_t *cp } return 0; } -#endif /* not MCUBOOT_ECDSA_NEED_ASN1_SIG */ +#if defined(MCUBOOT_USE_TINYCRYPT) typedef uintptr_t bootutil_ecdsa_context; static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx) { @@ -248,8 +253,12 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, { (void)ctx; (void)pk_len; - (void)sig_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) { @@ -257,7 +266,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, } pk++; - return cc310_ecdsa_verify_secp256r1(hash, pk, sig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE); + 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, @@ -613,6 +622,49 @@ static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, #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 diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index 34288ef02..88e94fbea 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -30,6 +30,7 @@ #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 @@ -211,6 +212,37 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, } #endif /* MCUBOOT_USE_CC310 */ +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + +#include + +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 diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 253ab2537..c0a0f0dbe 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -171,6 +171,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) zephyr_link_libraries(nrfxlib_crypto) + elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) + zephyr_include_directories(${BL_CRYPTO_DIR}/../include) endif() # Since here we are not using Zephyr's mbedTLS but rather our own, we need diff --git a/boot/zephyr/external_crypto.conf b/boot/zephyr/external_crypto.conf new file mode 100644 index 000000000..8181ad51c --- /dev/null +++ b/boot/zephyr/external_crypto.conf @@ -0,0 +1,20 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# These configurations should be used when using nrf/samples/bootloader +# as the immutable bootloader (B0), and MCUBoot as the second stage updateable +# bootloader. + +# Set ECDSA as signing mechanism +CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y + +# Use crypto backend from B0 +CONFIG_BOOT_NRF_EXTERNAL_CRYPTO=y +CONFIG_SECURE_BOOT_CRYPTO=y +CONFIG_SB_CRYPTO_CLIENT_ECDSA_SECP256R1=y +CONFIG_SB_CRYPTO_CLIENT_SHA256=y +CONFIG_BL_SHA256_EXT_API_REQUIRED=y +CONFIG_BL_SECP256R1_EXT_API_REQUIRED=y diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 56462fb76..f628f99c4 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -40,11 +40,10 @@ #define MCUBOOT_USE_TINYCRYPT #elif defined(CONFIG_BOOT_USE_CC310) #define MCUBOOT_USE_CC310 -#ifdef CONFIG_BOOT_USE_NRF_CC310_BL -#define MCUBOOT_USE_NRF_CC310_BL -#endif #elif defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) #define MCUBOOT_USE_PSA_CRYPTO +#elif defined(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) +#define MCUBOOT_USE_NRF_EXTERNAL_CRYPTO #endif #ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA512 From 2c3c181854448717dae6ad22c9bb813cfe14062f Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 29 May 2024 17:46:17 +0000 Subject: [PATCH 055/287] [nrf noup] PSA implementation of x25519 and ed25519 verification The commit provides implementation of image verification with ed25519 and encryption/decryption support where random key is encrypted using x25519. Signed-off-by: Dominik Ermel (cherry picked from commit e874cf8e2fc6d2f86ddfeeb09801d418b16957f1) (cherry picked from commit 9e1d883614a922a68544bbd47004e200b0e995bf) (cherry picked from commit 062d3e766c8eb9c9684323f4bb7e8638ee31bd57) --- .../include/bootutil/crypto/aes_ctr.h | 38 +- boot/bootutil/src/ed25519_psa.c | 71 +++ boot/bootutil/src/encrypted.c | 114 ++--- boot/bootutil/src/encrypted_psa.c | 454 ++++++++++++++++++ boot/bootutil/src/image_ed25519.c | 16 +- 5 files changed, 633 insertions(+), 60 deletions(-) create mode 100644 boot/bootutil/src/ed25519_psa.c create mode 100644 boot/bootutil/src/encrypted_psa.c diff --git a/boot/bootutil/include/bootutil/crypto/aes_ctr.h b/boot/bootutil/include/bootutil/crypto/aes_ctr.h index 50d36a4fc..44190361c 100644 --- a/boot/bootutil/include/bootutil/crypto/aes_ctr.h +++ b/boot/bootutil/include/bootutil/crypto/aes_ctr.h @@ -15,8 +15,8 @@ #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" + 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) @@ -38,12 +38,46 @@ #define BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE TC_AES_BLOCK_SIZE #endif /* MCUBOOT_USE_TINYCRYPT */ + +#if defined(MCUBOOT_USE_PSA_CRYPTO) + #include + #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 #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) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c new file mode 100644 index 000000000..3d7274307 --- /dev/null +++ b/boot/bootutil/src/ed25519_psa.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include +#include +#include + +#include +#include "bootutil/bootutil_log.h" + +#include +#include + +BOOT_LOG_MODULE_DECLARE(ed25519_psa); + +#define SHA512_DIGEST_LENGTH 64 +#define EDDSA_KEY_LENGTH 32 +#define EDDSA_SIGNAGURE_LENGTH 64 + +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], + const uint8_t public_key[EDDSA_KEY_LENGTH]) +{ + /* Set to any error */ + psa_status_t status = PSA_ERROR_BAD_STATE; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t kid; + int ret = 0; /* Fail by default */ + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d\n", status); + return 0; + } + + status = PSA_ERROR_BAD_STATE; + + psa_set_key_type(&key_attr, + PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS)); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE); + psa_set_key_algorithm(&key_attr, PSA_ALG_PURE_EDDSA); + + status = psa_import_key(&key_attr, public_key, EDDSA_KEY_LENGTH, &kid); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("ED25519 key import failed %d", status); + return 0; + } + + status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len, + signature, EDDSA_SIGNAGURE_LENGTH); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + ret = 0; + /* Pass through to destroy key */ + } else { + ret = 1; + /* Pass through to destroy key */ + } + + status = psa_destroy_key(kid); + + if (status != PSA_SUCCESS) { + /* Just for logging */ + BOOT_LOG_WRN("Failed to destroy key %d", status); + } + + return ret; +} diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index 8449a28dd..67fa819bb 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -25,6 +25,7 @@ #include "bootutil/crypto/ecdh_p256.h" #endif +#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_X25519) #include "bootutil/crypto/ecdh_x25519.h" #endif @@ -35,6 +36,7 @@ #include "mbedtls/oid.h" #include "mbedtls/asn1.h" #endif +#endif #include "bootutil/image.h" #include "bootutil/enc_key.h" @@ -43,6 +45,30 @@ #include "bootutil_priv.h" +#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE + +#if defined(MCUBOOT_ENCRYPT_RSA) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 +#elif defined(MCUBOOT_ENCRYPT_KW) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW +#elif defined(MCUBOOT_ENCRYPT_EC256) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (65) +# define EC_CIPHERKEY_INDEX (65 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-P256 component indexes"); +#elif defined(MCUBOOT_ENCRYPT_X25519) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (32) +# define EC_CIPHERKEY_INDEX (32 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-X25519 component indexes"); +#endif + +/* NOUP Fixme: */ +#if !defined(CONFIG_BOOT_ED25519_PSA) #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) #if defined(_compare) static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size) @@ -351,60 +377,6 @@ int boot_enc_retrieve_private_key(struct bootutil_key **private_key) } #endif /* !MCUBOOT_ENC_BUILTIN_KEY */ -int -boot_enc_init(struct enc_key_data *enc_state, uint8_t slot) -{ - bootutil_aes_ctr_init(&enc_state[slot].aes_ctr); - return 0; -} - -int -boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot) -{ - bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr); - enc_state[slot].valid = 0; - return 0; -} - -int -boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, - const struct boot_status *bs) -{ - int rc; - - rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]); - if (rc != 0) { - boot_enc_drop(enc_state, slot); - return -1; - } - - enc_state[slot].valid = 1; - - return 0; -} - -#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE - -#if defined(MCUBOOT_ENCRYPT_RSA) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 -#elif defined(MCUBOOT_ENCRYPT_KW) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW -#elif defined(MCUBOOT_ENCRYPT_EC256) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (65) -# define EC_CIPHERKEY_INDEX (65 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-P256 component indexes"); -#elif defined(MCUBOOT_ENCRYPT_X25519) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (32) -# define EC_CIPHERKEY_INDEX (32 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-X25519 component indexes"); -#endif - #if ( (defined(MCUBOOT_ENCRYPT_RSA) && defined(MCUBOOT_USE_MBED_TLS) && !defined(MCUBOOT_USE_PSA_CRYPTO)) || \ (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ) #if MBEDTLS_VERSION_NUMBER >= 0x03000000 @@ -627,6 +599,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return rc; } +#endif /* CONFIG_BOOT_ED25519_PSA */ /* * Load encryption key. @@ -681,6 +654,39 @@ boot_enc_load(struct enc_key_data *enc_state, int slot, return boot_decrypt_key(buf, bs->enckey[slot]); } +int +boot_enc_init(struct enc_key_data *enc_state, uint8_t slot) +{ + bootutil_aes_ctr_init(&enc_state[slot].aes_ctr); + return 0; +} + +int +boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot) +{ + bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr); + enc_state[slot].valid = 0; + return 0; +} + +int +boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, + const struct boot_status *bs) +{ + int rc; + + rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]); + if (rc != 0) { + boot_enc_drop(enc_state, slot); + return -1; + } + + enc_state[slot].valid = 1; + + return 0; +} + + bool boot_enc_valid(struct enc_key_data *enc_state, int slot) { diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c new file mode 100644 index 000000000..c3f72884d --- /dev/null +++ b/boot/bootutil/src/encrypted_psa.c @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "mcuboot_config/mcuboot_config.h" + +#include +#include +#include + +/* We are not really using the MBEDTLS but need the ASN.1 parsing functions */ +#define MBEDTLS_ASN1_PARSE_C + +#include "bootutil/crypto/sha.h" +#include "mbedtls/oid.h" +#include "mbedtls/asn1.h" + +#include "bootutil/image.h" +#include "bootutil/enc_key.h" +#include "bootutil/sign_key.h" +#include "bootutil/crypto/common.h" + +#include "bootutil_priv.h" +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); + +#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE +#define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 +#define EC_PUBK_INDEX (0) +#define EC_TAG_INDEX (32) +#define EC_CIPHERKEY_INDEX (32 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-X25519 component indexes"); + +#define X25519_OID "\x6e" +static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ + MBEDTLS_OID_ORG_GOV X25519_OID; + +#define SHARED_KEY_LEN 32 +#define PRIV_KEY_LEN 32 + +/* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ +static int +parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +{ + size_t len; + int version; + mbedtls_asn1_buf alg; + mbedtls_asn1_buf param; + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE) != 0) { + return -1; + } + + if (*p + len != end) { + return -2; + } + + version = 0; + if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { + return -3; + } + + if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { + return -4; + } + + 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 -5; + } + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -6; + } + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -7; + } + + if (len != PRIV_KEY_LEN) { + return -8; + } + + memcpy(private_key, *p, PRIV_KEY_LEN); + return 0; +} + +void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx) +{ + psa_status_t psa_ret = psa_crypto_init(); + + (void)ctx; + + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES init PSA crypto init failed %d", psa_ret); + assert(0); + } +} + +#if defined(MCUBOOT_ENC_IMAGES) +extern const struct bootutil_key bootutil_enc_key; +/* + * Decrypt an encryption key TLV. + * + * @param buf An encryption TLV read from flash (build time fixed length) + * @param enckey An AES-128 or AES-256 key sized buffer to store to plain key. + */ +int +boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) +{ + uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; + uint8_t *cp; + uint8_t *cpend; + uint8_t private_key[PRIV_KEY_LEN]; + size_t len; + psa_status_t psa_ret = PSA_ERROR_BAD_STATE; + psa_status_t psa_cleanup_ret = PSA_ERROR_BAD_STATE; + psa_key_id_t kid; + psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_derivation_operation_t key_do = PSA_KEY_DERIVATION_OPERATION_INIT; + psa_algorithm_t key_do_alg; + int rc = -1; + + cp = (uint8_t *)bootutil_enc_key.key; + cpend = cp + *bootutil_enc_key.len; + + /* The psa_cipher_decrypt needs initialization vector of proper length at + * the beginning of the input buffer. + */ + uint8_t iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR) + + BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE]; + + psa_ret = psa_crypto_init(); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES crypto init failed %d", psa_ret); + return -1; + } + + /* + * Load the stored X25519 decryption private key + */ + rc = parse_x25519_enckey(&cp, cpend, private_key); + if (rc) { + return rc; + } + + psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY)); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&kattr, PSA_ALG_ECDH); + + psa_ret = psa_import_key(&kattr, private_key, sizeof(private_key), &kid); + memset(private_key, 0, sizeof(private_key)); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("Built-in key import failed %d", psa_ret); + return -1; + } + + key_do_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)); + + psa_ret = psa_key_derivation_setup(&key_do, key_do_alg); + if (psa_ret != PSA_SUCCESS) { + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Built-in key destruction failed %d", psa_cleanup_ret); + } + BOOT_LOG_ERR("Key derivation setup failed %d", psa_ret); + return -1; + } + + /* Note: PSA 1.1.2 does not have psa_key_agreement that would be useful here + * as it could just add the derived key to the storage and return key id. + * Instead, we have to use the code below to generate derived key and put it + * into storage, to obtain the key id we can then use with psa_mac_* functions. + */ + psa_ret = psa_key_derivation_key_agreement(&key_do, PSA_KEY_DERIVATION_INPUT_SECRET, + kid, &buf[EC_PUBK_INDEX], + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Built-in key destruction failed %d", psa_cleanup_ret); + } + if (psa_ret != PSA_SUCCESS) { + psa_cleanup_ret = psa_key_derivation_abort(&key_do); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Key derivation abort failed %d", psa_ret); + } + + BOOT_LOG_ERR("Key derivation failed %d", psa_ret); + return -1; + } + + /* Only info, no salt */ + psa_ret = psa_key_derivation_input_bytes(&key_do, PSA_KEY_DERIVATION_INPUT_INFO, + "MCUBoot_ECIES_v1", 16); + if (psa_ret != PSA_SUCCESS) { + psa_cleanup_ret = psa_key_derivation_abort(&key_do); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Key derivation abort failed %d", psa_ret); + } + BOOT_LOG_ERR("Key derivation failed %d", psa_ret); + return -1; + } + + len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE; + psa_ret = psa_key_derivation_output_bytes(&key_do, derived_key, len); + psa_cleanup_ret = psa_key_derivation_abort(&key_do); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Key derivation cleanup failed %d", psa_ret); + } + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("Key derivation failed %d", psa_ret); + return -1; + } + + /* The derived key consists of BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE bytes + * followed by BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE bytes. Both parts will + * be imported at the point where needed and discarded immediately after. + */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_HMAC); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_VERIFY_MESSAGE); + psa_set_key_algorithm(&kattr, PSA_ALG_HMAC(PSA_ALG_SHA_256)); + + /* Import the MAC tag key part of derived key, that is the part that starts + * after BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE and has length of + * BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE bytes. + */ + psa_ret = psa_import_key(&kattr, + &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE], + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, &kid); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + memset(derived_key, 0, sizeof(derived_key)); + BOOT_LOG_ERR("MAC key import failed %d", psa_ret); + return -1; + } + + /* Verify the MAC tag of the random encryption key */ + psa_ret = psa_mac_verify(kid, PSA_ALG_HMAC(PSA_ALG_SHA_256), + &buf[EC_CIPHERKEY_INDEX], BOOT_ENC_KEY_SIZE, + &buf[EC_TAG_INDEX], + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("MAC key destruction failed %d", psa_cleanup_ret); + } + if (psa_ret != PSA_SUCCESS) { + memset(derived_key, 0, sizeof(derived_key)); + BOOT_LOG_ERR("MAC verification failed %d", psa_ret); + return -1; + } + + /* The derived key is used in AES decryption of random key */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&kattr, PSA_ALG_CTR); + + /* Import the AES partition of derived key, the first 16 bytes */ + psa_ret = psa_import_key(&kattr, &derived_key[0], + BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, &kid); + memset(derived_key, 0, sizeof(derived_key)); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES key import failed %d", psa_ret); + return -1; + } + + /* Decrypt the random AES encryption key with AES and the key obtained + * at derivation. */ + memset(&iv_and_key[0], 0, PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)); + memcpy(&iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)], + &buf[EC_CIPHERKEY_INDEX], + sizeof(iv_and_key) - PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)); + + len = 0; + psa_ret = psa_cipher_decrypt(kid, PSA_ALG_CTR, iv_and_key, sizeof(iv_and_key), + enckey, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, &len); + memset(iv_and_key, 0, sizeof(iv_and_key)); + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("AES key destruction failed %d", psa_cleanup_ret); + } + if (psa_ret != PSA_SUCCESS || len != BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE) { + memset(enckey, 0, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE); + BOOT_LOG_ERR("Random key decryption failed %d", psa_ret); + return -1; + } + + 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 ret = 0; + psa_status_t psa_ret = PSA_ERROR_BAD_STATE; + psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t kid; + psa_cipher_operation_t psa_op; + size_t elen = 0; /* Decrypted length */ + + /* Fixme: calling psa_crypto_init multiple times is not a problem, + * yet the code here is only present because there is not general + * crypto init. */ + psa_ret = psa_crypto_init(); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); + ret = -1; + goto gone; + } + + psa_op = psa_cipher_operation_init(); + + /* Fixme: Import should happen when key is decrypted, but due to lack + * of key destruction there is no way to destroy key stored by + * psa other way than here. */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&kattr, PSA_ALG_CTR); + + psa_ret = psa_import_key(&kattr, ctx->key, BOOT_ENC_KEY_SIZE, &kid); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc import key failed %d", psa_ret); + ret = -1; + goto gone; + } + + /* This could be done with psa_cipher_decrypt one-shot operation, but + * multi-part operation is used to avoid re-allocating input buffer + * to account for IV in front of data. + */ + psa_ret = psa_cipher_encrypt_setup(&psa_op, kid, PSA_ALG_CTR); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc setup failed %d", psa_ret); + ret = -1; + goto gone_with_key; + } + + /* Fixme: hardcoded counter size, but it is hardcoded everywhere */ + psa_ret = psa_cipher_set_iv(&psa_op, counter, 16); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc IV set failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + + psa_ret = psa_cipher_update(&psa_op, m, mlen, c, mlen, &elen); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc encryption failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + +gone_after_setup: + psa_ret = psa_cipher_abort(&psa_op); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("AES enc cipher abort failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone_with_key: + /* Fixme: Should be removed once key is shared by id */ + psa_ret = psa_destroy_key(kid); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("AES enc destroy key failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone: + return ret; +} + +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) +{ + int ret = 0; + psa_status_t psa_ret = PSA_ERROR_BAD_STATE; + psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t kid; + psa_cipher_operation_t psa_op; + size_t dlen = 0; /* Decrypted length */ + + /* Fixme: the init should already happen before calling the function, but + * somehow it does not, for example when recovering in swap. + */ + psa_ret = psa_crypto_init(); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); + ret = -1; + goto gone; + } + + psa_op = psa_cipher_operation_init(); + + /* Fixme: Import should happen when key is decrypted, but due to lack + * of key destruction there is no way to destroy key stored by + * psa other way than here. */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&kattr, PSA_ALG_CTR); + + psa_ret = psa_import_key(&kattr, ctx->key, BOOT_ENC_KEY_SIZE, &kid); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec import key failed %d", psa_ret); + ret = -1; + goto gone; + } + + /* This could be done with psa_cipher_decrypt one-shot operation, but + * multi-part operation is used to avoid re-allocating input buffer + * to account for IV in front of data. + */ + psa_ret = psa_cipher_decrypt_setup(&psa_op, kid, PSA_ALG_CTR); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec setup failed %d", psa_ret); + ret = -1; + goto gone_with_key; + } + + /* Fixme: hardcoded counter size, but it is hardcoded everywhere */ + psa_ret = psa_cipher_set_iv(&psa_op, counter, 16); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec IV set failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + + psa_ret = psa_cipher_update(&psa_op, c, clen, m, clen, &dlen); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec decryption failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + +gone_after_setup: + psa_ret = psa_cipher_abort(&psa_op); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("PSA dec abort failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone_with_key: + psa_ret = psa_destroy_key(kid); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("PSA dec key failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone: + return ret; +} +#endif /* defined(MCUBOOT_ENC_IMAGES) */ diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 7a597d4c0..447289253 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -9,6 +9,11 @@ #include "mcuboot_config/mcuboot_config.h" +#if defined(CONFIG_NRF_SECURITY) +/* We are not really using the MBEDTLS but need the ASN.1 parsing funcitons */ +#define MBEDTLS_ASN1_PARSE_C +#endif + #ifdef MCUBOOT_SIGN_ED25519 #include "bootutil/sign_key.h" @@ -17,13 +22,16 @@ #include "bootutil_priv.h" #include "bootutil/crypto/common.h" +#include "bootutil/crypto/sha.h" + +#define EDDSA_SIGNATURE_LENGTH 64 static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; #define NUM_ED25519_BYTES 32 extern int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[64], - const uint8_t public_key[32]); + const uint8_t signature[EDDSA_SIGNATURE_LENGTH], + const uint8_t public_key[NUM_ED25519_BYTES]); /* * Parse the public key used for signing. @@ -73,7 +81,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t *pubkey; uint8_t *end; - if (hlen != 32 || slen != 64) { + if (hlen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -87,7 +95,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, goto out; } - rc = ED25519_verify(hash, 32, sig, pubkey); + rc = ED25519_verify(hash, IMAGE_HASH_SIZE, sig, pubkey); if (rc == 0) { /* if verify returns 0, there was an error. */ From 390c468afcdc4f3039a00efece68073355320a97 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 2 Sep 2024 11:20:00 +0100 Subject: [PATCH 056/287] [nrf noup] zephyr: Add support for ARM thumb filter Adds support for ARM thumb filter usage for compressed firmware updates Signed-off-by: Jamie McCrae (cherry picked from commit 0ea935a76ad1b7bbcd58521b7ecbd5e07dd54283) (cherry picked from commit ded8242091a699e83a21e7fe2c3c9748c3481f3a) (cherry picked from commit 4fc8d2d7351b0b2e51be0c64ef5be7a521c7661f) --- boot/zephyr/decompression.c | 305 +++++++++++++++++++++++++++--------- 1 file changed, 234 insertions(+), 71 deletions(-) diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index 062cdbc61..35a1950b2 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -29,6 +29,14 @@ #define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 #endif +#define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) +#define DECOMP_BUF_EXTRA_SIZE 2 +#else +#define DECOMP_BUF_EXTRA_SIZE 0 +#endif +#define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE) + /* Number of times that consumed data by decompression system can be 0 in a row before aborting */ #define OFFSET_ZERO_CHECK_TIMES 3 @@ -87,13 +95,22 @@ bool boot_is_compressed_header_valid(const struct image_header *hdr, const struc if (size >= size_check) { BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", size, size_check); - return false; } return true; } +static bool is_compression_object_valid(struct nrf_compress_implementation *compression) +{ + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + return false; + } + + return true; +} + int bootutil_img_hash_decompress(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 *hash_result, @@ -104,7 +121,9 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index uint32_t write_pos = 0; uint32_t protected_tlv_size = 0; uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression = NULL; + uint32_t output_size_total = 0; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; TARGET_STATIC struct image_header modified_hdr; bootutil_sha_context sha_ctx; uint8_t flash_erased_value; @@ -122,27 +141,26 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; } - compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish_without_clean; } - rc = compression->init(NULL); + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); if (rc) { BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish_without_clean; } @@ -157,7 +175,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -172,7 +189,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (rc) { BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -211,7 +227,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } @@ -225,7 +240,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index uint32_t chunk_size; bool last_packet = false; - chunk_size = compression->decompress_bytes_needed(NULL); + chunk_size = compression_lzma->decompress_bytes_needed(NULL); if (chunk_size > (copy_size - tmp_off)) { chunk_size = (copy_size - tmp_off); @@ -235,13 +250,12 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index last_packet = true; } - rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset, - &output, &output_size); + rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); if (rc) { BOOT_LOG_ERR("Decompression error: %d", rc); rc = BOOT_EBADSTATUS; - goto finish; } @@ -251,7 +265,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", write_pos); rc = BOOT_EBADIMAGE; - goto finish; } @@ -260,7 +273,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index /* Last packet and we still have no output, this is a faulty update */ BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -271,7 +283,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -282,8 +293,48 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index offset_zero_check = 0; } + /* Copy data to secondary buffer for calculating hash */ if (output_size > 0) { - bootutil_sha_update(&sha_ctx, output, output_size); + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + /* Run this through the ARM thumb filter */ + uint32_t offset_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t processed_size = 0; + uint32_t output_size_arm_thumb = 0; + + while (processed_size < output_size) { + uint32_t current_size = output_size - processed_size; + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_packet && (processed_size + current_size) == + output_size) { + arm_thumb_last_packet = true; + } + + rc = compression_arm_thumb->decompress(NULL, &output[processed_size], + current_size, arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb); + output_size_total += output_size_arm_thumb; + processed_size += current_size; + } + } else { + bootutil_sha_update(&sha_ctx, output, output_size); + output_size_total += output_size; + } } tmp_off += offset; @@ -292,6 +343,13 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index read_pos += copy_size; } + if (modified_hdr.ih_img_size != output_size_total) { + BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d", + modified_hdr.ih_img_size, output_size_total); + rc = BOOT_EBADSTATUS; + goto finish; + } + /* If there are any protected TLVs present, add them after the main decompressed image */ if (modified_hdr.ih_protect_tlv_size > 0) { rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, @@ -302,7 +360,8 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index finish: /* Clean up decompression system */ - (void)compression->deinit(NULL); + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); finish_without_clean: bootutil_sha_drop(&sha_ctx); @@ -353,7 +412,6 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -422,7 +480,6 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - goto out; } @@ -438,7 +495,6 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -513,7 +569,6 @@ static int boot_sha_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + read_off), copy_size, fap_src->fa_id, rc); - goto out; } @@ -626,7 +681,6 @@ int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flas */ BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); rc = BOOT_EBADIMAGE; - goto out; } @@ -681,7 +735,6 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -778,7 +831,6 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - goto out; } @@ -794,7 +846,6 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -823,11 +874,17 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint32_t unprotected_tlv_size = 0; uint32_t tlv_write_size = 0; uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression = NULL; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; struct image_header *hdr; - TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4))); + TARGET_STATIC uint8_t decomp_buf[DECOMP_BUF_ALLOC_SIZE] __attribute__((aligned(4))); TARGET_STATIC struct image_header modified_hdr; +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + uint8_t excess_data_buffer[DECOMP_BUF_EXTRA_SIZE]; + bool excess_data_buffer_full = false; +#endif + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); /* Setup decompression system */ @@ -841,27 +898,26 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish; } - compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish; } - rc = compression->init(NULL); + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); if (rc) { BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish; } @@ -874,7 +930,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -887,7 +942,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -898,7 +952,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -909,7 +962,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } @@ -928,7 +980,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } @@ -943,7 +994,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint8_t *output = NULL; bool last_packet = false; - chunk_size = compression->decompress_bytes_needed(NULL); + chunk_size = compression_lzma->decompress_bytes_needed(NULL); if (chunk_size > (copy_size - tmp_off)) { chunk_size = (copy_size - tmp_off); @@ -953,47 +1004,142 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl last_packet = true; } - rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset, - &output, &output_size); + rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); if (rc) { BOOT_LOG_ERR("Decompression error: %d", rc); rc = BOOT_EBADSTATUS; - goto finish; } /* Copy data to secondary buffer for writing out */ while (output_size > 0) { - uint32_t data_size = (sizeof(decomp_buf) - decomp_buf_size); + uint32_t data_size = (DECOMP_BUF_SIZE - decomp_buf_size); if (data_size > output_size) { data_size = output_size; } - memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], data_size); +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + memcpy(&decomp_buf[decomp_buf_size + DECOMP_BUF_EXTRA_SIZE], + &output[compression_buffer_pos], data_size); + } else +#endif + { + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], + data_size); + } + compression_buffer_pos += data_size; decomp_buf_size += data_size; output_size -= data_size; /* Write data out from secondary buffer when it is full */ - if (decomp_buf_size == sizeof(decomp_buf)) { - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, sizeof(decomp_buf)); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), sizeof(decomp_buf), - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; + if (decomp_buf_size == DECOMP_BUF_SIZE) { +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + uint32_t filter_writeback_pos = 0; + uint32_t processed_size = 0; + + /* Run this through the ARM thumb filter */ + while (processed_size < DECOMP_BUF_SIZE) { + uint32_t offset_arm_thumb = 0; + uint32_t output_size_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t current_size = DECOMP_BUF_SIZE; + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_packet && (processed_size + current_size) == DECOMP_BUF_SIZE + && output_size == 0) { + arm_thumb_last_packet = true; + } + + rc = compression_arm_thumb->decompress(NULL, + &decomp_buf[processed_size + + DECOMP_BUF_EXTRA_SIZE], + current_size, + arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + memcpy(&decomp_buf[filter_writeback_pos], output_arm_thumb, + output_size_arm_thumb); + filter_writeback_pos += output_size_arm_thumb; + processed_size += current_size; + } + + if (excess_data_buffer_full == true) + { + /* Restore extra data removed from previous iteration to the write + * buffer + */ + memmove(&decomp_buf[DECOMP_BUF_EXTRA_SIZE], decomp_buf, + filter_writeback_pos); + memcpy(decomp_buf, excess_data_buffer, DECOMP_BUF_EXTRA_SIZE); + excess_data_buffer_full = false; + filter_writeback_pos += DECOMP_BUF_EXTRA_SIZE; + } + + if ((filter_writeback_pos % sizeof(uint32_t)) != 0) + { + /* Since there are an extra 2 bytes here, remove them and stash for + * later usage to prevent flash write issues with non-word boundary + * writes + */ + memcpy(excess_data_buffer, &decomp_buf[filter_writeback_pos - + DECOMP_BUF_EXTRA_SIZE], + DECOMP_BUF_EXTRA_SIZE); + excess_data_buffer_full = true; + filter_writeback_pos -= DECOMP_BUF_EXTRA_SIZE; + } + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, filter_writeback_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), DECOMP_BUF_SIZE, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += filter_writeback_pos; + decomp_buf_size = 0; + filter_writeback_pos = 0; + } else +#endif + { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, DECOMP_BUF_SIZE); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), DECOMP_BUF_SIZE, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += DECOMP_BUF_SIZE; + decomp_buf_size = 0; } - - write_pos += sizeof(decomp_buf); - decomp_buf_size = 0; } } @@ -1003,8 +1149,30 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl pos += copy_size; } +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0) { + /* Extra data that has not been written out that needs ARM thumb filter applied */ + uint32_t offset_arm_thumb = 0; + uint32_t output_size_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + + rc = compression_arm_thumb->decompress(NULL, &decomp_buf[DECOMP_BUF_EXTRA_SIZE], + decomp_buf_size, true, &offset_arm_thumb, + &output_arm_thumb, &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + memcpy(decomp_buf, output_arm_thumb, output_size_arm_thumb); + } +#endif + /* Clean up decompression system */ - (void)compression->deinit(NULL); + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); if (protected_tlv_size > 0) { rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + @@ -1014,7 +1182,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - goto finish; } @@ -1029,7 +1196,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - goto finish; } @@ -1040,7 +1206,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); /* Check if additional write padding should be applied to meet the minimum write size */ - if (write_padding_size) { + if (write_alignment > 1 && write_padding_size) { uint8_t flash_erased_value; flash_erased_value = flash_area_erased_val(fap_dst); @@ -1056,7 +1222,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } @@ -1098,7 +1263,6 @@ int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct fl if (len != sizeof(*img_decomp_size)) { BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); - return BOOT_EBADIMAGE; } @@ -1107,7 +1271,6 @@ int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct fl if (rc) { BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", off, len, fap->fa_id, rc); - return BOOT_EFLASH; } From ea00c047de0adbadc7162b945bfb139136f434cb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 17 Oct 2024 19:38:39 +0000 Subject: [PATCH 057/287] [nrf noup] Remove setting default MCUboot mbedTLS config This has been overriding logic that selects nrf-config.h when CONFIG_NRF_SECURITY=y. Signed-off-by: Dominik Ermel (cherry picked from commit 6ea6a72ab1a8ebde6d35f2445310581b28268127) (cherry picked from commit 2d5a490f3e4595ca26d4867014987166b0e1e79b) --- boot/zephyr/prj.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index e4f7d9030..9ff1ba274 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -1,7 +1,6 @@ CONFIG_PM=n CONFIG_MAIN_STACK_SIZE=10240 -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" CONFIG_BOOT_SWAP_SAVE_ENCTLV=n CONFIG_BOOT_ENCRYPT_IMAGE=n From ad56ff5183465af7f590d3ce8e1132fab2c5201a Mon Sep 17 00:00:00 2001 From: Markus Lassila Date: Fri, 30 Aug 2024 13:10:05 +0300 Subject: [PATCH 058/287] [nrf noup] boot: zephyr: Do not lock PCD region with TF-M Previously PCD memory was locked as read-only, non-secure in MCUboot. Given that TF-M also needs write to PCD to communicate with b0n, the memory is left unlocked and locked to read-only, non-secure in TF-M. Signed-off-by: Markus Lassila (cherry picked from commit 68b96b802cdeef77ce4200e776afa46f6d3cfb66) (cherry picked from commit b3c7d3ddddaa2101d4c8bb79795fd1698ce15c21) --- boot/zephyr/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 5ae524feb..351ca4c89 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -616,7 +616,11 @@ int main(void) } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) - pcd_lock_ram(); +#if defined(PM_TFM_SECURE_ADDRESS) + pcd_lock_ram(false); +#else + pcd_lock_ram(true); +#endif #endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ From 43d47399086a12c2d7f312fb30632655c5c23b3c Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 10 Sep 2024 13:41:30 +0100 Subject: [PATCH 059/287] [nrf noup] treewide: Add support for sysbuild assigned images Adds support for image IDs that are assigned by sysbuild, which allows for dynamically supporting different configurations without needing dummy images to support different modes. Also fixes multiple deficiencies with the previous code where things were not properly accounted for e.g. using the swap algorithm including all swap status parts when updating s0/s1 MCUboot image which could overwrite and corrupt the image data in the other slot Signed-off-by: Jamie McCrae (cherry picked from commit 5646583af3924eba4dd39f313fd51e88823d5123) (cherry picked from commit ba255be4e891ab95466e815d996d1ed86ec07619) --- boot/bootutil/src/loader.c | 161 +++++++++++++-------- boot/bootutil/src/swap_nsib.c | 70 +++++++++ boot/bootutil/src/swap_priv.h | 8 + boot/zephyr/CMakeLists.txt | 6 + boot/zephyr/include/sysflash/pm_sysflash.h | 69 ++++----- 5 files changed, 209 insertions(+), 105 deletions(-) create mode 100644 boot/bootutil/src/swap_nsib.c diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 53f40c33a..b0491b3ac 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -153,15 +153,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ -#ifdef PM_S1_ADDRESS +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 /* Patch needed for NCS. The primary slot of the second image * (image 1) will not contain a valid image header until an upgrade * of mcuboot has happened (filling S1 with the new version). */ - if (BOOT_CURR_IMG(state) == 1 && i == 0) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER && i == 0) { continue; } -#endif /* PM_S1_ADDRESS */ +#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */ if (i > 0 && !require_all) { return 0; } else { @@ -1160,7 +1160,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) - if (BOOT_CURR_IMG(state) == 1) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); } else { rc = boot_version_cmp( @@ -1229,6 +1229,8 @@ boot_validate_slot(struct boot_loader_state *state, int slot, struct image_header *secondary_hdr = boot_img_hdr(state, slot); uint32_t reset_value = 0; uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); + uint32_t min_addr, max_addr; + bool check_addresses = false; rc = flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)); if (rc != 0) { @@ -1236,29 +1238,46 @@ boot_validate_slot(struct boot_loader_state *state, int slot, goto out; } - uint32_t min_addr, max_addr; - #ifdef PM_CPUNET_APP_ADDRESS /* The primary slot for the network core is emulated in RAM. * Its flash_area hasn't got relevant boundaries. * Therfore need to override its boundaries for the check. */ - if (BOOT_CURR_IMG(state) == 1) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; -#ifdef PM_S1_ADDRESS - } else if (BOOT_CURR_IMG(state) == 0) { + check_addresses = true; + } else +#endif +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { +#if (CONFIG_NCS_IS_VARIANT_IMAGE) min_addr = PM_S0_ADDRESS; - max_addr = pri_fa->fa_off + pri_fa->fa_size; + max_addr = (PM_S0_ADDRESS + PM_S0_SIZE); +#else + min_addr = PM_S1_ADDRESS; + max_addr = (PM_S1_ADDRESS + PM_S1_SIZE); #endif + check_addresses = true; } else #endif - { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + min_addr = MIN(pri_fa->fa_off, PM_S0_ADDRESS); + max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S0_ADDRESS + PM_S0_SIZE)); +#else + min_addr = MIN(pri_fa->fa_off, PM_S1_ADDRESS); + max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S1_ADDRESS + PM_S1_SIZE)); +#endif +#else min_addr = pri_fa->fa_off; max_addr = pri_fa->fa_off + pri_fa->fa_size; +#endif + check_addresses = true; } - if (reset_value < min_addr || reset_value> (max_addr)) { + if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1335,36 +1354,42 @@ boot_update_security_counter(uint8_t image_index, int slot, #define SEC_SLOT_TOUCHED 1 #define SEC_SLOT_ASSIGNED 2 -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -/* This configuration is peculiar - the one physical secondary slot is - * mocking two logical secondary - */ -#define SEC_SLOT_PHYSICAL_CNT 1 -#else -#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER -#endif - -static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; +static uint8_t sec_slot_assignmnet[MCUBOOT_IMAGE_NUMBER] = {0}; static inline void sec_slot_touch(struct boot_loader_state *state) { - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + if (sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + } + } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + if (sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + } + } +#endif - if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { - sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; + if (sec_slot_assignmnet[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) { + sec_slot_assignmnet[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED; } } static inline void sec_slot_mark_assigned(struct boot_loader_state *state) { - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + } +#endif - sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; + sec_slot_assignmnet[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED; } /** - * Cleanu up all secondary slot which couldn't be assigned to any primary slot. + * Cleanup up all secondary slot which couldn't be assigned to any primary slot. * * This function erases content of each secondary slot which contains valid * header but couldn't be assigned to any of supported primary images. @@ -1376,7 +1401,7 @@ static void sec_slot_cleanup_if_unusable(void) { uint8_t idx; - for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { + for (idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) { if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { const struct flash_area *secondary_fa; int rc; @@ -1386,12 +1411,12 @@ static void sec_slot_cleanup_if_unusable(void) if (!rc) { rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); if (!rc) { - BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); + BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", idx); } } if (rc) { - BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); + BOOT_LOG_ERR("Failed to clean-up secondary slot of image %d: %d", idx, rc); } } } @@ -1428,7 +1453,7 @@ boot_validated_swap_type(struct boot_loader_state *state, owner_nsib[BOOT_CURR_IMG(state)] = false; #endif -#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) +#if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); @@ -1466,31 +1491,29 @@ boot_validated_swap_type(struct boot_loader_state *state, } /* Check start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off) { -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - const struct flash_area *nsib_fa; - - /* NSIB upgrade slot */ - rc = flash_area_open((uint32_t)_image_1_primary_slot_id, - &nsib_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - - /* Image is placed before Primary and within the NSIB slot */ - if (reset_addr > nsib_fa->fa_off - && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { - /* Set primary to be NSIB upgrade slot */ - BOOT_IMG_AREA(state, 0) = nsib_fa; - owner_nsib[BOOT_CURR_IMG(state)] = true; - } +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { #else - return BOOT_SWAP_TYPE_NONE; - + if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { #endif + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + /* This is not the s0/s1 upgrade image but the application image, pretend + * there is no image so the NSIB update can be loaded + */ + return BOOT_SWAP_TYPE_NONE; + } - } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + owner_nsib[BOOT_CURR_IMG(state)] = true; +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + } else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { +#else + } else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { +#endif + /* NSIB upgrade but for the wrong slot, must be erased */ + BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image"); + flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); + return BOOT_SWAP_TYPE_FAIL; + } else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } @@ -1503,7 +1526,7 @@ boot_validated_swap_type(struct boot_loader_state *state, sec_slot_mark_assigned(state); } -#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ +#endif /* PM_S1_ADDRESS || PM_CPUNET_B0N_ADDRESS */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2035,7 +2058,22 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) flash_area_close(fap); } - swap_run(state, bs, copy_size); +#if defined(PM_S1_ADDRESS) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (owner_nsib[BOOT_CURR_IMG(state)]) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* For NSIB, move the image instead of swapping it */ + nsib_swap_run(state, bs); + +#if defined(CONFIG_REBOOT) + /* Should also reboot at this point so the new S0/S1 update is applied */ + sys_reboot(SYS_REBOOT_COLD); +#endif + } + } else +#endif + { + swap_run(state, bs, copy_size); + } #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT extern int boot_status_fails; @@ -2701,12 +2739,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); -#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - sys_reboot(SYS_REBOOT_COLD); - - } -#endif break; case BOOT_SWAP_TYPE_FAIL: @@ -2780,7 +2812,8 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) * executing MCUBoot image, and is therefore already validated by NSIB and * does not need to also be validated by MCUBoot. */ - bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == + CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER; if (!image_validated_by_nsib) #endif { diff --git a/boot/bootutil/src/swap_nsib.c b/boot/bootutil/src/swap_nsib.c new file mode 100644 index 000000000..39ed4c652 --- /dev/null +++ b/boot/bootutil/src/swap_nsib.c @@ -0,0 +1,70 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil_priv.h" +#include "swap_priv.h" +#include "bootutil/bootutil_log.h" + +#include "mcuboot_config/mcuboot_config.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs) +{ + uint32_t sector_sz; + uint8_t image_index; + const struct flash_area *fap_pri; + const struct flash_area *fap_sec; + int rc; + + BOOT_LOG_INF("Starting swap using nsib algorithm."); + + sector_sz = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0); + +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + rc = flash_area_open(PM_S0_ID, &fap_pri); +#else + rc = flash_area_open(PM_S1_ID, &fap_pri); +#endif + assert (rc == 0); + image_index = BOOT_CURR_IMG(state); + + rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap_sec); + assert (rc == 0); + + rc = boot_erase_region(fap_pri, 0, fap_pri->fa_size); + assert(rc == 0); + + rc = boot_copy_region(state, fap_sec, fap_pri, 0, 0, fap_pri->fa_size); + assert(rc == 0); + + rc = swap_erase_trailer_sectors(state, fap_sec); + assert(rc == 0); + + rc = boot_erase_region(fap_sec, 0, MIN((fap_pri->fa_size + sector_sz), fap_sec->fa_size)); + assert(rc == 0); + + flash_area_close(fap_pri); + flash_area_close(fap_sec); +} diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index 960c72250..2734d6262 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -106,4 +106,12 @@ static inline size_t boot_scratch_area_size(const struct boot_loader_state *stat */ int app_max_size(struct boot_loader_state *state); +#if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ +(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) +/** + * Performs an NSIB update + */ +void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs); +#endif + #endif /* H_SWAP_PRIV_ */ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index c0a0f0dbe..839dd12b3 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -142,6 +142,12 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/swap_move.c ${BOOT_DIR}/bootutil/src/caps.c ) + + if(NOT CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER EQUAL "-1" AND NOT CONFIG_BOOT_UPGRADE_ONLY) + zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/swap_nsib.c + ) + endif() endif() if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index db60ddd03..42f25182e 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -15,48 +15,36 @@ #ifndef CONFIG_SINGLE_APPLICATION_SLOT -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -extern uint32_t _image_1_primary_slot_id[]; -#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ - -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) - -#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - /* Each pair of slots is separated by , and there is no terminating character */ -#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID -#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID -#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID, +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID, +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID, +#define FLASH_AREA_IMAGE_3_SLOTS PM_MCUBOOT_PRIMARY_3_ID, PM_MCUBOOT_SECONDARY_3_ID, + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +#ifdef CONFIG_NCS_IS_VARIANT_IMAGE +#define MCUBOOT_S0_S1_SLOTS PM_S0_ID, PM_MCUBOOT_SECONDARY_ID, +#else +#define MCUBOOT_S0_S1_SLOTS PM_S1_ID, PM_MCUBOOT_SECONDARY_ID, +#endif +#else +#define MCUBOOT_S0_S1_SLOTS +#endif -#if (MCUBOOT_IMAGE_NUMBER == 1) +#if (MCUBOOT_IMAGE_NUMBER == 1) || (MCUBOOT_IMAGE_NUMBER == 2 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) #define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 2) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ +#elif (MCUBOOT_IMAGE_NUMBER == 2) || (MCUBOOT_IMAGE_NUMBER == 3 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ FLASH_AREA_IMAGE_1_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 3) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ - FLASH_AREA_IMAGE_1_SLOTS, \ +#elif (MCUBOOT_IMAGE_NUMBER == 3) || (MCUBOOT_IMAGE_NUMBER == 4 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ + FLASH_AREA_IMAGE_1_SLOTS \ FLASH_AREA_IMAGE_2_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 4) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ + FLASH_AREA_IMAGE_1_SLOTS \ + FLASH_AREA_IMAGE_2_SLOTS \ + FLASH_AREA_IMAGE_3_SLOTS #else #error Unsupported number of images #endif @@ -65,6 +53,7 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) { static const int all_slots[] = { ALL_AVAILABLE_SLOTS + MCUBOOT_S0_S1_SLOTS }; return all_slots[img * 2 + slot]; }; @@ -72,6 +61,8 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #undef FLASH_AREA_IMAGE_0_SLOTS #undef FLASH_AREA_IMAGE_1_SLOTS #undef FLASH_AREA_IMAGE_2_SLOTS +#undef FLASH_AREA_IMAGE_3_SLOTS +#undef MCUBOOT_S0_S1_SLOTS #undef ALL_AVAILABLE_SLOTS #define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) @@ -81,10 +72,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif -#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - #else /* CONFIG_SINGLE_APPLICATION_SLOT */ #define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID From 63e53ed94680150350e813e74957c5673704aee4 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 15 Oct 2024 11:31:20 +0100 Subject: [PATCH 060/287] [nrf noup] boot: bootutil: loader: Add s0/s1 checking of MCUboot image Adds a check that will also check the s0/s1 package version of the currently running MCUboot against a MCUboot update image to ensure that an older version of MCUboot isn't loaded to the opposite slot Signed-off-by: Jamie McCrae (cherry picked from commit 04481ec1714c586171a3b54bdf9b5a4c3f7d1f83) (cherry picked from commit 4aaec13302922afc172bc62857cbfaf508530434) --- boot/bootutil/src/loader.c | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index b0491b3ac..f35ec7864 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -105,6 +105,17 @@ static struct sector_buffer_t sector_buffers; #endif #endif +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 && defined(MCUBOOT_OVERWRITE_ONLY) && \ + defined(MCUBOOT_DOWNGRADE_PREVENTION) +/* s0/s1 package version of the current MCUboot image */ +static const struct image_version mcuboot_s0_s1_image_version = { + .iv_major = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MAJOR, + .iv_minor = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MINOR, + .iv_revision = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_REVISION, + .iv_build_num = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_BUILD_NUMBER, +}; +#endif + #if (BOOT_IMAGE_NUMBER > 1) #define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x)) #else @@ -1166,11 +1177,45 @@ boot_validate_slot(struct boot_loader_state *state, int slot, rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot + * trailer version to prevent downgrades + */ + int version_check; + + version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &mcuboot_s0_s1_image_version); + + /* Only update rc if the currently running version is newer */ + if (version_check < rc) { + rc = version_check; + } + } +#endif } #else rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot + * trailer version to prevent downgrades + */ + int version_check; + + version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &mcuboot_s0_s1_image_version); + + /* Only update rc if the currently running version is newer */ + if (version_check < rc) { + rc = version_check; + } + } +#endif #endif if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); From 099f49f3e1d20984fa97922a0ea9312f58231737 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 17 Oct 2024 07:51:27 +0100 Subject: [PATCH 061/287] [nrf noup] treewide: Add child/parent image support back Adds support for child and parent images back, this commit will be reverted after the NCS 2.8 release when child/parent support is dropped Signed-off-by: Jamie McCrae (cherry picked from commit 20ee33769f45f6e94e761775bf235baf2723f384) (cherry picked from commit d5aa2152b31cff8b58c232989850451e55773739) --- .../bootutil/src/loader_legacy_child_parent.c | 3896 +++++++++++++++++ boot/zephyr/CMakeLists.txt | 12 +- .../pm_sysflash_legacy_child_parent.h | 100 + boot/zephyr/include/sysflash/sysflash.h | 6 + 4 files changed, 4013 insertions(+), 1 deletion(-) create mode 100644 boot/bootutil/src/loader_legacy_child_parent.c create mode 100644 boot/zephyr/include/sysflash/pm_sysflash_legacy_child_parent.h diff --git a/boot/bootutil/src/loader_legacy_child_parent.c b/boot/bootutil/src/loader_legacy_child_parent.c new file mode 100644 index 000000000..53f40c33a --- /dev/null +++ b/boot/bootutil/src/loader_legacy_child_parent.c @@ -0,0 +1,3896 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2016-2020 Linaro LTD + * Copyright (c) 2016-2019 JUUL Labs + * Copyright (c) 2019-2023 Arm Limited + * Copyright (c) 2024 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. + */ + +/** + * This file provides an interface to the boot loader. Functions defined in + * this file should only be called while the boot loader is running. + */ + +#include +#include +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil/bootutil_public.h" +#include "bootutil/image.h" +#include "bootutil_priv.h" +#include "swap_priv.h" +#include "bootutil/bootutil_log.h" +#include "bootutil/security_cnt.h" +#include "bootutil/boot_record.h" +#include "bootutil/fault_injection_hardening.h" +#include "bootutil/ramload.h" +#include "bootutil/boot_hooks.h" +#include "bootutil/mcuboot_status.h" + +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + +#ifdef __ZEPHYR__ +#include +#endif + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) +#include +#ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION +#include +int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); +#endif +#endif + +#ifdef MCUBOOT_ENC_IMAGES +#include "bootutil/enc_key.h" +#endif + +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) +#include +#endif + +#include "mcuboot_config/mcuboot_config.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +static struct boot_loader_state boot_data; +#ifdef PM_S1_ADDRESS +static bool owner_nsib[BOOT_IMAGE_NUMBER] = {false}; +#endif + +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) +static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; +#endif + +#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ +defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +#if !defined(__BOOTSIM__) +/* Used for holding static buffers in multiple functions to work around issues + * in older versions of gcc (e.g. 4.8.4) + */ +struct sector_buffer_t { + boot_sector_t primary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; + boot_sector_t secondary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; +#if MCUBOOT_SWAP_USING_SCRATCH + boot_sector_t scratch[BOOT_MAX_IMG_SECTORS]; +#endif +}; + +static struct sector_buffer_t sector_buffers; +#endif +#endif + +#if (BOOT_IMAGE_NUMBER > 1) +#define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x)) +#else +#define IMAGES_ITER(x) +#endif + +/* + * This macro allows some control on the allocation of local variables. + * When running natively on a target, we don't want to allocated huge + * variables on the stack, so make them global instead. For the simulator + * we want to run as many threads as there are tests, and it's safer + * to just make those variables stack allocated. + */ +#if !defined(__BOOTSIM__) +#define TARGET_STATIC static +#else +#define TARGET_STATIC +#endif + +#if BOOT_MAX_ALIGN > 1024 +#define BUF_SZ BOOT_MAX_ALIGN +#else +#define BUF_SZ 1024 +#endif + +#define NO_ACTIVE_SLOT UINT32_MAX + +static int +boot_read_image_headers(struct boot_loader_state *state, bool require_all, + struct boot_status *bs) +{ + int rc; + int i; + + for (i = 0; i < BOOT_NUM_SLOTS; i++) { + rc = BOOT_HOOK_CALL(boot_read_image_header_hook, BOOT_HOOK_REGULAR, + BOOT_CURR_IMG(state), i, boot_img_hdr(state, i)); + if (rc == BOOT_HOOK_REGULAR) + { + rc = boot_read_image_header(state, i, boot_img_hdr(state, i), bs); + } + if (rc != 0) { + /* If `require_all` is set, fail on any single fail, otherwise + * if at least the first slot's header was read successfully, + * then the boot loader can attempt a boot. + * + * Failure to read any headers is a fatal error. + */ +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. The primary slot of the second image + * (image 1) will not contain a valid image header until an upgrade + * of mcuboot has happened (filling S1 with the new version). + */ + if (BOOT_CURR_IMG(state) == 1 && i == 0) { + continue; + } +#endif /* PM_S1_ADDRESS */ + if (i > 0 && !require_all) { + return 0; + } else { + return rc; + } + } + } + + return 0; +} + +/** + * Saves boot status and shared data for current image. + * + * @param state Boot loader status information. + * @param active_slot Index of the slot will be loaded for current image. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_add_shared_data(struct boot_loader_state *state, + uint8_t active_slot) +{ +#if defined(MCUBOOT_MEASURED_BOOT) || defined(MCUBOOT_DATA_SHARING) + int rc; + +#ifdef MCUBOOT_MEASURED_BOOT + rc = boot_save_boot_status(BOOT_CURR_IMG(state), + boot_img_hdr(state, active_slot), + BOOT_IMG_AREA(state, active_slot)); + if (rc != 0) { + BOOT_LOG_ERR("Failed to add image data to shared area"); + return rc; + } +#endif /* MCUBOOT_MEASURED_BOOT */ + +#ifdef MCUBOOT_DATA_SHARING + rc = boot_save_shared_data(boot_img_hdr(state, active_slot), + BOOT_IMG_AREA(state, active_slot), + active_slot, image_max_sizes); + if (rc != 0) { + BOOT_LOG_ERR("Failed to add data to shared memory area."); + return rc; + } +#endif /* MCUBOOT_DATA_SHARING */ + + return 0; + +#else /* MCUBOOT_MEASURED_BOOT || MCUBOOT_DATA_SHARING */ + (void) (state); + (void) (active_slot); + + return 0; +#endif +} + +/** + * Fills rsp to indicate how booting should occur. + * + * @param state Boot loader status information. + * @param rsp boot_rsp struct to fill. + */ +static void +fill_rsp(struct boot_loader_state *state, struct boot_rsp *rsp) +{ + uint32_t active_slot; + +#if (BOOT_IMAGE_NUMBER > 1) + /* Always boot from the first enabled image. */ + BOOT_CURR_IMG(state) = 0; + IMAGES_ITER(BOOT_CURR_IMG(state)) { + if (!state->img_mask[BOOT_CURR_IMG(state)]) { + break; + } + } + /* At least one image must be active, otherwise skip the execution */ + if (BOOT_CURR_IMG(state) >= BOOT_IMAGE_NUMBER) { + return; + } +#endif + +#if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD) + active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; +#else + active_slot = BOOT_PRIMARY_SLOT; +#endif + + rsp->br_flash_dev_id = flash_area_get_device_id(BOOT_IMG_AREA(state, active_slot)); + rsp->br_image_off = boot_img_slot_off(state, active_slot); + rsp->br_hdr = boot_img_hdr(state, active_slot); +} + +/** + * Closes all flash areas. + * + * @param state Boot loader status information. + */ +static void +close_all_flash_areas(struct boot_loader_state *state) +{ + uint32_t slot; + + IMAGES_ITER(BOOT_CURR_IMG(state)) { +#if BOOT_IMAGE_NUMBER > 1 + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } +#endif +#if MCUBOOT_SWAP_USING_SCRATCH + flash_area_close(BOOT_SCRATCH_AREA(state)); +#endif + for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { + flash_area_close(BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot)); + } + } +} + +#if (BOOT_IMAGE_NUMBER > 1) || \ + defined(MCUBOOT_DIRECT_XIP) || \ + defined(MCUBOOT_RAM_LOAD) || \ + defined(MCUBOOT_DOWNGRADE_PREVENTION) +/** + * Compare image version numbers + * + * By default, the comparison does not take build number into account. + * Enable MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER to take the build number into account. + * + * @param ver1 Pointer to the first image version to compare. + * @param ver2 Pointer to the second image version to compare. + * + * @retval -1 If ver1 is less than ver2. + * @retval 0 If the image version numbers are equal. + * @retval 1 If ver1 is greater than ver2. + */ +static int +boot_version_cmp(const struct image_version *ver1, + const struct image_version *ver2) +{ + if (ver1->iv_major > ver2->iv_major) { + return 1; + } + if (ver1->iv_major < ver2->iv_major) { + return -1; + } + /* The major version numbers are equal, continue comparison. */ + if (ver1->iv_minor > ver2->iv_minor) { + return 1; + } + if (ver1->iv_minor < ver2->iv_minor) { + return -1; + } + /* The minor version numbers are equal, continue comparison. */ + if (ver1->iv_revision > ver2->iv_revision) { + return 1; + } + if (ver1->iv_revision < ver2->iv_revision) { + return -1; + } + +#if defined(MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER) + /* The revisions are equal, continue comparison. */ + if (ver1->iv_build_num > ver2->iv_build_num) { + return 1; + } + if (ver1->iv_build_num < ver2->iv_build_num) { + return -1; + } +#endif + + return 0; +} +#endif + +#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ +defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +static int +boot_initialize_area(struct boot_loader_state *state, int flash_area) +{ + uint32_t num_sectors = BOOT_MAX_IMG_SECTORS; + boot_sector_t *out_sectors; + uint32_t *out_num_sectors; + int rc; + + num_sectors = BOOT_MAX_IMG_SECTORS; + + if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) { + out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors; + out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors; + } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { + out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors; + out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors; +#if MCUBOOT_SWAP_USING_SCRATCH + } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) { + out_sectors = state->scratch.sectors; + out_num_sectors = &state->scratch.num_sectors; +#endif + } else { + return BOOT_EFLASH; + } + +#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS + rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors); +#else + _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed"); + rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors); +#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */ + if (rc != 0) { + return rc; + } + *out_num_sectors = num_sectors; + return 0; +} +#endif + +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +static int +boot_read_sectors_recovery(struct boot_loader_state *state) +{ + uint8_t image_index; + int rc; + + image_index = BOOT_CURR_IMG(state); + + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index)); + if (rc != 0) { + return BOOT_EFLASH; + } + + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index)); + if (rc != 0) { + /* We need to differentiate from the primary image issue */ + return BOOT_EFLASH_SEC; + } + + return 0; +} +#endif + + +#if (BOOT_IMAGE_NUMBER > 1) + +static int +boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot); + +/** + * Check the image dependency whether it is satisfied and modify + * the swap type if necessary. + * + * @param dep Image dependency which has to be verified. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_verify_slot_dependency(struct boot_loader_state *state, + struct image_dependency *dep) +{ + struct image_version *dep_version; + size_t dep_slot; + int rc; + + /* Determine the source of the image which is the subject of + * the dependency and get it's version. */ +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) + uint8_t swap_type = state->swap_type[dep->image_id]; + dep_slot = BOOT_IS_UPGRADE(swap_type) ? BOOT_SECONDARY_SLOT + : BOOT_PRIMARY_SLOT; +#else + dep_slot = state->slot_usage[dep->image_id].active_slot; +#endif + + dep_version = &state->imgs[dep->image_id][dep_slot].hdr.ih_ver; + + rc = boot_version_cmp(dep_version, &dep->image_min_version); +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) + if (rc < 0) { + /* Dependency not satisfied. + * Modify the swap type to decrease the version number of the image + * (which will be located in the primary slot after the boot process), + * consequently the number of unsatisfied dependencies will be + * decreased or remain the same. + */ + switch (BOOT_SWAP_TYPE(state)) { + case BOOT_SWAP_TYPE_TEST: + case BOOT_SWAP_TYPE_PERM: + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; + break; + case BOOT_SWAP_TYPE_NONE: + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT; + break; + default: + break; + } + } else { + /* Dependency satisfied. */ + rc = 0; + } +#else + if (rc >= 0) { + /* Dependency satisfied. */ + rc = 0; + } +#endif + + return rc; +} + +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) +/** + * Iterate over all the images and verify whether the image dependencies in the + * TLV area are all satisfied and update the related swap type if necessary. + */ +static int +boot_verify_dependencies(struct boot_loader_state *state) +{ + int rc = -1; + uint8_t slot; + + BOOT_CURR_IMG(state) = 0; + while (BOOT_CURR_IMG(state) < BOOT_IMAGE_NUMBER) { + if (state->img_mask[BOOT_CURR_IMG(state)]) { + BOOT_CURR_IMG(state)++; + continue; + } + if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE && + BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_FAIL) { + slot = BOOT_SECONDARY_SLOT; + } else { + slot = BOOT_PRIMARY_SLOT; + } + + rc = boot_verify_slot_dependencies(state, slot); + if (rc == 0) { + /* All dependencies've been satisfied, continue with next image. */ + BOOT_CURR_IMG(state)++; + } else if (rc == BOOT_EBADIMAGE) { + /* Cannot upgrade due to non-met dependencies, so disable all + * image upgrades. + */ + for (int idx = 0; idx < BOOT_IMAGE_NUMBER; idx++) { + BOOT_CURR_IMG(state) = idx; + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; + } + break; + } else { + /* Other error happened, images are inconsistent */ + return rc; + } + } + return rc; +} +#else + +#if defined MCUBOOT_RAM_LOAD +static inline int +boot_remove_image_from_sram(struct boot_loader_state *state); +#endif + +/** + * Checks the dependency of all the active slots. If an image found with + * invalid or not satisfied dependencies the image is removed from SRAM (in + * case of MCUBOOT_RAM_LOAD strategy) and its slot is set to unavailable. + * + * @param state Boot loader status information. + * + * @return 0 if dependencies are met; nonzero otherwise. + */ +static int +boot_verify_dependencies(struct boot_loader_state *state) +{ + int rc = -1; + uint32_t active_slot; + + IMAGES_ITER(BOOT_CURR_IMG(state)) { + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } + active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; + rc = boot_verify_slot_dependencies(state, active_slot); + if (rc != 0) { + /* Dependencies not met or invalid dependencies. */ + +#ifdef MCUBOOT_RAM_LOAD + boot_remove_image_from_sram(state); +#endif /* MCUBOOT_RAM_LOAD */ + + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false; + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + + return rc; + } + } + + return rc; +} +#endif + +/** + * Read all dependency TLVs of an image from the flash and verify + * one after another to see if they are all satisfied. + * + * @param slot Image slot number. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) +{ + const struct flash_area *fap; + struct image_tlv_iter it; + struct image_dependency dep; + uint32_t off; + uint16_t len; + int area_id; + int rc; + + area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); + rc = flash_area_open(area_id, &fap); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; + } + + rc = bootutil_tlv_iter_begin(&it, boot_img_hdr(state, slot), fap, + IMAGE_TLV_DEPENDENCY, true); + if (rc != 0) { + goto done; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + if (rc < 0) { + return -1; + } else if (rc > 0) { + rc = 0; + break; + } + + if (len != sizeof(dep)) { + rc = BOOT_EBADIMAGE; + goto done; + } + + rc = LOAD_IMAGE_DATA(boot_img_hdr(state, slot), + fap, off, &dep, len); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; + } + + if (dep.image_id >= BOOT_IMAGE_NUMBER) { + rc = BOOT_EBADARGS; + goto done; + } + + /* Verify dependency and modify the swap type if not satisfied. */ + rc = boot_verify_slot_dependency(state, &dep); + if (rc != 0) { + /* Dependency not satisfied */ + goto done; + } + } + +done: + flash_area_close(fap); + return rc; +} + +#endif /* (BOOT_IMAGE_NUMBER > 1) */ + +#if !defined(MCUBOOT_DIRECT_XIP) +/* + * Compute the total size of the given image. Includes the size of + * the TLVs. + */ +#if !defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_OVERWRITE_ONLY_FAST) +static int +boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) +{ + const struct flash_area *fap; + struct image_tlv_info info; + uint32_t off; + uint32_t protect_tlv_size; + int area_id; + int rc; + +#if (BOOT_IMAGE_NUMBER == 1) + (void)state; +#endif + + area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); + rc = flash_area_open(area_id, &fap); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; + } + +#ifdef MCUBOOT_DECOMPRESS_IMAGES + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { + uint32_t tmp_size = 0; + + rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); + + if (rc) { + rc = BOOT_EBADIMAGE; + goto done; + } + + off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; + + rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); + + if (rc) { + rc = BOOT_EBADIMAGE; + goto done; + } + + off += tmp_size; + + if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + + boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, + sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + info.it_tlv_tot; + } else { +#else + if (1) { +#endif + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); + + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + protect_tlv_size + info.it_tlv_tot; + } + + rc = 0; + +done: + flash_area_close(fap); + return rc; +} +#endif /* !MCUBOOT_OVERWRITE_ONLY */ + +#if !defined(MCUBOOT_RAM_LOAD) +static uint32_t +boot_write_sz(struct boot_loader_state *state) +{ + uint32_t elem_sz; +#if MCUBOOT_SWAP_USING_SCRATCH + uint32_t align; +#endif + + /* Figure out what size to write update status update as. The size depends + * on what the minimum write size is for scratch area, active image slot. + * We need to use the bigger of those 2 values. + */ + elem_sz = flash_area_align(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); +#if MCUBOOT_SWAP_USING_SCRATCH + align = flash_area_align(BOOT_SCRATCH_AREA(state)); + if (align > elem_sz) { + elem_sz = align; + } +#endif + + return elem_sz; +} + +/** + * Determines the sector layout of both image slots and the scratch area. + * This information is necessary for calculating the number of bytes to erase + * and copy during an image swap. The information collected during this + * function is used to populate the state. + */ +static int +boot_read_sectors(struct boot_loader_state *state) +{ + uint8_t image_index; + int rc; + + image_index = BOOT_CURR_IMG(state); + + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index)); + if (rc != 0) { + return BOOT_EFLASH; + } + + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index)); + if (rc != 0) { + /* We need to differentiate from the primary image issue */ + return BOOT_EFLASH_SEC; + } + +#if MCUBOOT_SWAP_USING_SCRATCH + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SCRATCH); + if (rc != 0) { + return BOOT_EFLASH; + } +#endif + + BOOT_WRITE_SZ(state) = boot_write_sz(state); + + return 0; +} + +void +boot_status_reset(struct boot_status *bs) +{ +#ifdef MCUBOOT_ENC_IMAGES + memset(&bs->enckey, 0xff, BOOT_NUM_SLOTS * BOOT_ENC_KEY_ALIGN_SIZE); +#if MCUBOOT_SWAP_SAVE_ENCTLV + memset(&bs->enctlv, 0xff, BOOT_NUM_SLOTS * BOOT_ENC_TLV_ALIGN_SIZE); +#endif +#endif /* MCUBOOT_ENC_IMAGES */ + + bs->use_scratch = 0; + bs->swap_size = 0; + bs->source = 0; + + bs->op = BOOT_STATUS_OP_MOVE; + bs->idx = BOOT_STATUS_IDX_0; + bs->state = BOOT_STATUS_STATE_0; + bs->swap_type = BOOT_SWAP_TYPE_NONE; +} + +bool +boot_status_is_reset(const struct boot_status *bs) +{ + return (bs->op == BOOT_STATUS_OP_MOVE && + bs->idx == BOOT_STATUS_IDX_0 && + bs->state == BOOT_STATUS_STATE_0); +} + +/** + * Writes the supplied boot status to the flash file system. The boot status + * contains the current state of an in-progress image copy operation. + * + * @param bs The boot status to write. + * + * @return 0 on success; nonzero on failure. + */ +int +boot_write_status(const struct boot_loader_state *state, struct boot_status *bs) +{ + const struct flash_area *fap; + uint32_t off; + int area_id; + int rc = 0; + uint8_t buf[BOOT_MAX_ALIGN]; + uint32_t align; + uint8_t erased_val; + + /* NOTE: The first sector copied (that is the last sector on slot) contains + * the trailer. Since in the last step the primary slot is erased, the + * first two status writes go to the scratch which will be copied to + * the primary slot! + */ + +#if MCUBOOT_SWAP_USING_SCRATCH + if (bs->use_scratch) { + /* Write to scratch. */ + area_id = FLASH_AREA_IMAGE_SCRATCH; + } else { +#endif + /* Write to the primary slot. */ + area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state)); +#if MCUBOOT_SWAP_USING_SCRATCH + } +#endif + + rc = flash_area_open(area_id, &fap); + if (rc != 0) { + return BOOT_EFLASH; + } + + off = boot_status_off(fap) + + boot_status_internal_off(bs, BOOT_WRITE_SZ(state)); + align = flash_area_align(fap); + erased_val = flash_area_erased_val(fap); + memset(buf, erased_val, BOOT_MAX_ALIGN); + buf[0] = bs->state; + + BOOT_LOG_DBG("writing swap status; fa_id=%d off=0x%lx (0x%lx)", + flash_area_get_id(fap), (unsigned long)off, + (unsigned long)flash_area_get_off(fap) + off); + + rc = flash_area_write(fap, off, buf, align); + if (rc != 0) { + rc = BOOT_EFLASH; + } + + flash_area_close(fap); + + return rc; +} +#endif /* !MCUBOOT_RAM_LOAD */ +#endif /* !MCUBOOT_DIRECT_XIP */ + +/* + * Validate image hash/signature and optionally the security counter in a slot. + */ +static fih_ret +boot_image_check(struct boot_loader_state *state, struct image_header *hdr, + const struct flash_area *fap, struct boot_status *bs) +{ + TARGET_STATIC uint8_t tmpbuf[BOOT_TMPBUF_SZ]; + int rc; + FIH_DECLARE(fih_rc, FIH_FAILURE); + +#if (BOOT_IMAGE_NUMBER == 1) + (void)state; +#endif + + (void)bs; + (void)rc; + +/* In the case of ram loading the image has already been decrypted as it is + * decrypted when copied in ram */ +#if defined(MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_RAM_LOAD) + if (MUST_DECRYPT(fap, BOOT_CURR_IMG(state), hdr)) { + rc = boot_enc_load(BOOT_CURR_ENC(state), 1, hdr, fap, bs); + if (rc < 0) { + FIH_RET(fih_rc); + } + if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) { + FIH_RET(fih_rc); + } + } +#endif + + FIH_CALL(bootutil_img_validate, fih_rc, BOOT_CURR_ENC(state), + BOOT_CURR_IMG(state), hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, + NULL, 0, NULL); + + FIH_RET(fih_rc); +} + +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) +static fih_ret +split_image_check(struct image_header *app_hdr, + const struct flash_area *app_fap, + struct image_header *loader_hdr, + const struct flash_area *loader_fap) +{ + static void *tmpbuf; + uint8_t loader_hash[32]; + FIH_DECLARE(fih_rc, FIH_FAILURE); + + if (!tmpbuf) { + tmpbuf = malloc(BOOT_TMPBUF_SZ); + if (!tmpbuf) { + goto out; + } + } + + FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, loader_hdr, loader_fap, + tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, loader_hash); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_RET(fih_rc); + } + + FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, app_hdr, app_fap, + tmpbuf, BOOT_TMPBUF_SZ, loader_hash, 32, NULL); + +out: + FIH_RET(fih_rc); +} +#endif /* !MCUBOOT_DIRECT_XIP && !MCUBOOT_RAM_LOAD */ + +/* + * Check that this is a valid header. Valid means that the magic is + * correct, and that the sizes/offsets are "sane". Sane means that + * there is no overflow on the arithmetic, and that the result fits + * within the flash area we are in. Also check the flags in the image + * and class the image as invalid if flags for encryption/compression + * are present but these features are not enabled. + */ +static bool +boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state) +{ + uint32_t size; + + (void)state; + + if (hdr->ih_magic != IMAGE_MAGIC) { + return false; + } + + if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size)) { + return false; + } + +#ifdef MCUBOOT_DECOMPRESS_IMAGES + if (!MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { +#else + if (1) { +#endif + if (!boot_u32_safe_add(&size, size, hdr->ih_protect_tlv_size)) { + return false; + } + } + + if (size >= flash_area_get_size(fap)) { + return false; + } + +#if !defined(MCUBOOT_ENC_IMAGES) + if (IS_ENCRYPTED(hdr)) { + return false; + } +#else + if ((hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) && + (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256)) + { + return false; + } +#endif + +#if !defined(MCUBOOT_DECOMPRESS_IMAGES) + if (IS_COMPRESSED(hdr)) { + return false; + } +#else + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { + if (!boot_is_compressed_header_valid(hdr, fap, state)) { + return false; + } + } +#endif + + return true; +} + +/* + * Check that a memory area consists of a given value. + */ +static inline bool +boot_data_is_set_to(uint8_t val, void *data, size_t len) +{ + uint8_t i; + uint8_t *p = (uint8_t *)data; + for (i = 0; i < len; i++) { + if (val != p[i]) { + return false; + } + } + return true; +} + +static int +boot_check_header_erased(struct boot_loader_state *state, int slot) +{ + const struct flash_area *fap; + struct image_header *hdr; + uint8_t erased_val; + int area_id; + int rc; + + area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); + rc = flash_area_open(area_id, &fap); + if (rc != 0) { + return -1; + } + + erased_val = flash_area_erased_val(fap); + flash_area_close(fap); + + hdr = boot_img_hdr(state, slot); + if (!boot_data_is_set_to(erased_val, &hdr->ih_magic, sizeof(hdr->ih_magic))) { + return -1; + } + + return 0; +} + +#if defined(MCUBOOT_DIRECT_XIP) +/** + * Check if image in slot has been set with specific ROM address to run from + * and whether the slot starts at that address. + * + * @returns 0 if IMAGE_F_ROM_FIXED flag is not set; + * 0 if IMAGE_F_ROM_FIXED flag is set and ROM address specified in + * header matches the slot address; + * 1 if IMF_F_ROM_FIXED flag is set but ROM address specified in header + * does not match the slot address. + */ +static bool +boot_rom_address_check(struct boot_loader_state *state) +{ + uint32_t active_slot; + const struct image_header *hdr; + uint32_t f_off; + + active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; + hdr = boot_img_hdr(state, active_slot); + f_off = boot_img_slot_off(state, active_slot); + + if (hdr->ih_flags & IMAGE_F_ROM_FIXED && hdr->ih_load_addr != f_off) { + BOOT_LOG_WRN("Image in %s slot at 0x%x has been built for offset 0x%x"\ + ", skipping", + active_slot == 0 ? "primary" : "secondary", f_off, + hdr->ih_load_addr); + + /* If there is address mismatch, the image is not bootable from this + * slot. + */ + return 1; + } + return 0; +} +#endif + +/* + * Check that there is a valid image in a slot + * + * @returns + * FIH_SUCCESS if image was successfully validated + * FIH_NO_BOOTABLE_IMAGE if no bootloable image was found + * FIH_FAILURE on any errors + */ +static fih_ret +boot_validate_slot(struct boot_loader_state *state, int slot, + struct boot_status *bs) +{ + const struct flash_area *fap; + struct image_header *hdr; + int area_id; + FIH_DECLARE(fih_rc, FIH_FAILURE); + int rc; + + area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); + rc = flash_area_open(area_id, &fap); + if (rc != 0) { + FIH_RET(fih_rc); + } + + hdr = boot_img_hdr(state, slot); + if (boot_check_header_erased(state, slot) == 0 || + (hdr->ih_flags & IMAGE_F_NON_BOOTABLE)) { + +#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) + /* + * This fixes an issue where an image might be erased, but a trailer + * be left behind. It can happen if the image is in the secondary slot + * and did not pass validation, in which case the whole slot is erased. + * If during the erase operation, a reset occurs, parts of the slot + * might have been erased while some did not. The concerning part is + * the trailer because it might disable a new image from being loaded + * through mcumgr; so we just get rid of the trailer here, if the header + * is erased. + */ + if (slot != BOOT_PRIMARY_SLOT) { + swap_erase_trailer_sectors(state, fap); + } +#endif + + /* No bootable image in slot; continue booting from the primary slot. */ + fih_rc = FIH_NO_BOOTABLE_IMAGE; + goto out; + } + +#if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION) + if (slot != BOOT_PRIMARY_SLOT) { + /* Check if version of secondary slot is sufficient */ + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ + && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) + if (BOOT_CURR_IMG(state) == 1) { + rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); + } else { + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + } +#else + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); +#endif + if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { + BOOT_LOG_ERR("insufficient version in secondary slot"); + flash_area_erase(fap, 0, flash_area_get_size(fap)); + /* Image in the secondary slot does not satisfy version requirement. + * Erase the image and continue booting from the primary slot. + */ + fih_rc = FIH_NO_BOOTABLE_IMAGE; + goto out; + } + } +#endif + if (!boot_is_header_valid(hdr, fap, state)) { + fih_rc = FIH_FAILURE; + } else { + BOOT_HOOK_CALL_FIH(boot_image_check_hook, FIH_BOOT_HOOK_REGULAR, + fih_rc, BOOT_CURR_IMG(state), slot); + if (FIH_EQ(fih_rc, FIH_BOOT_HOOK_REGULAR)) { + FIH_CALL(boot_image_check, fih_rc, state, hdr, fap, bs); + } + } + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + if ((slot != BOOT_PRIMARY_SLOT) || ARE_SLOTS_EQUIVALENT()) { + flash_area_erase(fap, 0, flash_area_get_size(fap)); + /* Image is invalid, erase it to prevent further unnecessary + * attempts to validate and boot it. + */ + } + +#if !defined(__BOOTSIM__) + BOOT_LOG_ERR("Image in the %s slot is not valid!", + (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); +#endif + fih_rc = FIH_NO_BOOTABLE_IMAGE; + goto out; + } + +#if MCUBOOT_IMAGE_NUMBER > 1 && !defined(MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_VERIFY_IMG_ADDRESS) + /* Verify that the image in the secondary slot has a reset address + * located in the primary slot. This is done to avoid users incorrectly + * overwriting an application written to the incorrect slot. + * This feature is only supported by ARM platforms. + */ +#if MCUBOOT_IMAGE_NUMBER >= 3 + /* Currently the MCUboot can be configured for up to 3 image, where image number 2 is + * designated for XIP, where it is the second part of image stored in slots of image + * 0. This part of image is not bootable, as the XIP setup is done by the app in + * image 0 slot, and it does not carry the reset vector. + */ + if (area_id == FLASH_AREA_IMAGE_SECONDARY(2)) { + goto out; + } +#endif + if (area_id == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { + const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); + struct image_header *secondary_hdr = boot_img_hdr(state, slot); + uint32_t reset_value = 0; + uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); + + rc = flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)); + if (rc != 0) { + fih_rc = FIH_NO_BOOTABLE_IMAGE; + goto out; + } + + uint32_t min_addr, max_addr; + +#ifdef PM_CPUNET_APP_ADDRESS + /* The primary slot for the network core is emulated in RAM. + * Its flash_area hasn't got relevant boundaries. + * Therfore need to override its boundaries for the check. + */ + if (BOOT_CURR_IMG(state) == 1) { + min_addr = PM_CPUNET_APP_ADDRESS; + max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; +#ifdef PM_S1_ADDRESS + } else if (BOOT_CURR_IMG(state) == 0) { + min_addr = PM_S0_ADDRESS; + max_addr = pri_fa->fa_off + pri_fa->fa_size; +#endif + } else +#endif + { + min_addr = pri_fa->fa_off; + max_addr = pri_fa->fa_off + pri_fa->fa_size; + } + + if (reset_value < min_addr || reset_value> (max_addr)) { + BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); + BOOT_LOG_ERR("Erasing image from secondary slot"); + + /* The vector table in the image located in the secondary + * slot does not target the primary slot. This might + * indicate that the image was loaded to the wrong slot. + * + * Erase the image and continue booting from the primary slot. + */ + flash_area_erase(fap, 0, fap->fa_size); + fih_rc = FIH_NO_BOOTABLE_IMAGE; + goto out; + } + } +#endif + +out: + flash_area_close(fap); + + FIH_RET(fih_rc); +} + +#ifdef MCUBOOT_HW_ROLLBACK_PROT +/** + * Updates the stored security counter value with the image's security counter + * value which resides in the given slot, only if it's greater than the stored + * value. + * + * @param image_index Index of the image to determine which security + * counter to update. + * @param slot Slot number of the image. + * @param hdr Pointer to the image header structure of the image + * that is currently stored in the given slot. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_update_security_counter(uint8_t image_index, int slot, + struct image_header *hdr) +{ + const struct flash_area *fap = NULL; + uint32_t img_security_cnt; + int rc; + + rc = flash_area_open(flash_area_id_from_multi_image_slot(image_index, slot), + &fap); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; + } + + rc = bootutil_get_img_security_cnt(hdr, fap, &img_security_cnt); + if (rc != 0) { + goto done; + } + + rc = boot_nv_security_counter_update(image_index, img_security_cnt); + if (rc != 0) { + goto done; + } + +done: + flash_area_close(fap); + return rc; +} +#endif /* MCUBOOT_HW_ROLLBACK_PROT */ + +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) + +#if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ +(defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) + +#define SEC_SLOT_VIRGIN 0 +#define SEC_SLOT_TOUCHED 1 +#define SEC_SLOT_ASSIGNED 2 + +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +/* This configuration is peculiar - the one physical secondary slot is + * mocking two logical secondary + */ +#define SEC_SLOT_PHYSICAL_CNT 1 +#else +#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER +#endif + +static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; + +static inline void sec_slot_touch(struct boot_loader_state *state) +{ + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); + + if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { + sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; + } +} + +static inline void sec_slot_mark_assigned(struct boot_loader_state *state) +{ + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); + + sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; +} + +/** + * Cleanu up all secondary slot which couldn't be assigned to any primary slot. + * + * This function erases content of each secondary slot which contains valid + * header but couldn't be assigned to any of supported primary images. + * + * This function is supposed to be called after boot_validated_swap_type() + * iterates over all the images in context_boot_go(). + */ +static void sec_slot_cleanup_if_unusable(void) +{ + uint8_t idx; + + for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { + if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { + const struct flash_area *secondary_fa; + int rc; + + rc = flash_area_open(flash_area_id_from_multi_image_slot(idx, BOOT_SECONDARY_SLOT), + &secondary_fa); + if (!rc) { + rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); + if (!rc) { + BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); + } + } + + if (rc) { + BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); + } + } + } +} +#else +static inline void sec_slot_touch(struct boot_loader_state *state) +{ +} +static inline void sec_slot_mark_assigned(struct boot_loader_state *state) +{ +} +static inline void sec_slot_cleanup_if_unusable(void) +{ +} +#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ + defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ + +/** + * Determines which swap operation to perform, if any. If it is determined + * that a swap operation is required, the image in the secondary slot is checked + * for validity. If the image in the secondary slot is invalid, it is erased, + * and a swap type of "none" is indicated. + * + * @return The type of swap to perform (BOOT_SWAP_TYPE...) + */ +static int +boot_validated_swap_type(struct boot_loader_state *state, + struct boot_status *bs) +{ + int swap_type; + FIH_DECLARE(fih_rc, FIH_FAILURE); + bool upgrade_valid = false; +#if defined(PM_S1_ADDRESS) + owner_nsib[BOOT_CURR_IMG(state)] = false; +#endif + +#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + uint32_t reset_addr = 0; + int rc = 0; + /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other + * B1 slot S0 or S1) share the same secondary slot, we need to check + * whether the update candidate in the secondary slot is intended for + * image 0 or image 1 primary by looking at the address of the reset + * vector. Note that there are good reasons for not using img_num from + * the swap info. + */ + + if (hdr->ih_magic == IMAGE_MAGIC) { + rc = flash_area_read(secondary_fa, hdr->ih_hdr_size + + sizeof(uint32_t), &reset_addr, + sizeof(reset_addr)); + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + + sec_slot_touch(state); + +#ifdef PM_S1_ADDRESS +#ifdef PM_CPUNET_B0N_ADDRESS + if(!(reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS)) +#endif + { + const struct flash_area *primary_fa; + rc = flash_area_open(flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), + &primary_fa); + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + + /* Check start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off) { +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + const struct flash_area *nsib_fa; + + /* NSIB upgrade slot */ + rc = flash_area_open((uint32_t)_image_1_primary_slot_id, + &nsib_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + + /* Image is placed before Primary and within the NSIB slot */ + if (reset_addr > nsib_fa->fa_off + && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { + /* Set primary to be NSIB upgrade slot */ + BOOT_IMG_AREA(state, 0) = nsib_fa; + owner_nsib[BOOT_CURR_IMG(state)] = true; + } +#else + return BOOT_SWAP_TYPE_NONE; + +#endif + + } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for any */ + return BOOT_SWAP_TYPE_NONE; + } + + if ((primary_fa->fa_off == PM_S0_ADDRESS) || (primary_fa->fa_off == PM_S1_ADDRESS)) { + owner_nsib[BOOT_CURR_IMG(state)] = true; + } + } +#endif /* PM_S1_ADDRESS */ + sec_slot_mark_assigned(state); + } + +#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ + + swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); + if (BOOT_IS_UPGRADE(swap_type)) { + /* Boot loader wants to switch to the secondary slot. + * Ensure image is valid. + */ + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_SECONDARY_SLOT, bs); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + if (FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { + swap_type = BOOT_SWAP_TYPE_NONE; + } else { + swap_type = BOOT_SWAP_TYPE_FAIL; + } + } else { + upgrade_valid = true; + } + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) && defined(CONFIG_PCD_APP) + /* If the update is valid, and it targets the network core: perform the + * update and indicate to the caller of this function that no update is + * available + */ + if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS && + reset_addr < PM_CPUNET_APP_END_ADDRESS) { + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); + uint32_t fw_size = hdr->ih_img_size; + BOOT_LOG_INF("Starting network core update"); + rc = pcd_network_core_update(net_core_fw_addr, fw_size); + + if (rc != 0) { + swap_type = BOOT_SWAP_TYPE_FAIL; + } else { + BOOT_LOG_INF("Done updating network core"); +#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) + /* swap_erase_trailer_sectors is undefined if upgrade only + * method is used. There is no need to erase sectors, because + * the image cannot be reverted. + */ + rc = swap_erase_trailer_sectors(state, + secondary_fa); +#endif + swap_type = BOOT_SWAP_TYPE_NONE; + } + } +#endif /* CONFIG_SOC_NRF5340_CPUAPP && PM_CPUNET_B0N_ADDRESS && + !CONFIG_NRF53_MULTI_IMAGE_UPDATE && CONFIG_PCD_APP */ + } + + return swap_type; +} +#endif + +/** + * Erases a region of flash. + * + * @param flash_area The flash_area containing the region to erase. + * @param off The offset within the flash area to start the + * erase. + * @param sz The number of bytes to erase. + * + * @return 0 on success; nonzero on failure. + */ +int +boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz) +{ + return flash_area_erase(fap, off, sz); +} + +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) + +#if defined(MCUBOOT_ENC_IMAGES) || defined(MCUBOOT_SWAP_SAVE_ENCTLV) +/* Replacement for memset(p, 0, sizeof(*p) that does not get + * optimized out. + */ +static void like_mbedtls_zeroize(void *p, size_t n) +{ + volatile unsigned char *v = (unsigned char *)p; + + for (size_t i = 0; i < n; i++) { + v[i] = 0; + } +} +#endif + +/** + * Copies the contents of one flash region to another. You must erase the + * destination region prior to calling this function. + * + * @param flash_area_id_src The ID of the source flash area. + * @param flash_area_id_dst The ID of the destination flash area. + * @param off_src The offset within the source flash area to + * copy from. + * @param off_dst The offset within the destination flash area to + * copy to. + * @param sz The number of bytes to copy. + * + * @return 0 on success; nonzero on failure. + */ +int +boot_copy_region(struct boot_loader_state *state, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, + uint32_t off_src, uint32_t off_dst, uint32_t sz) +{ + uint32_t bytes_copied; + int chunk_sz; + int rc; +#ifdef MCUBOOT_ENC_IMAGES + uint32_t off = off_dst; + uint32_t tlv_off; + size_t blk_off; + struct image_header *hdr; + uint16_t idx; + uint32_t blk_sz; + uint8_t image_index = BOOT_CURR_IMG(state); + bool encrypted_src; + bool encrypted_dst; + /* Assuming the secondary slot is source; note that 0 here not only + * means that primary slot is source, but also that there will be + * encryption happening, if it is 1 then there is decryption from + * secondary slot. + */ + int source_slot = 1; + /* In case of encryption enabled, we may have to do more work than + * just copy bytes */ + bool only_copy = false; +#else + (void)state; +#endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + struct image_header *hdr; +#endif + + TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); + +#ifdef MCUBOOT_ENC_IMAGES + encrypted_src = (flash_area_get_id(fap_src) != FLASH_AREA_IMAGE_PRIMARY(image_index)); + encrypted_dst = (flash_area_get_id(fap_dst) != FLASH_AREA_IMAGE_PRIMARY(image_index)); + + if (encrypted_src != encrypted_dst) { + if (encrypted_dst) { + /* Need encryption, metadata from the primary slot */ + hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT); + source_slot = 0; + } else { + /* Need decryption, metadata from the secondary slot */ + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + source_slot = 1; + } + } else { + /* In case when source and targe is the same area, this means that we + * only have to copy bytes, no encryption or decryption. + */ + only_copy = true; + } +#endif + +#ifdef MCUBOOT_DECOMPRESS_IMAGES + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + + if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { + /* Use alternative function for compressed images */ + return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, + BUF_SZ); + } +#endif + + bytes_copied = 0; + while (bytes_copied < sz) { + if (sz - bytes_copied > sizeof buf) { + chunk_sz = sizeof buf; + } else { + chunk_sz = sz - bytes_copied; + } + + rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz); + if (rc != 0) { + return BOOT_EFLASH; + } + +#ifdef MCUBOOT_ENC_IMAGES + /* If only copy, then does not matter if header indicates need for + * encryptio/decryptio, we just copy data. */ + if (!only_copy && IS_ENCRYPTED(hdr)) { + uint32_t abs_off = off + bytes_copied; + if (abs_off < hdr->ih_hdr_size) { + /* do not decrypt header */ + if (abs_off + chunk_sz > hdr->ih_hdr_size) { + /* The lower part of the chunk contains header data */ + blk_off = 0; + blk_sz = chunk_sz - (hdr->ih_hdr_size - abs_off); + idx = hdr->ih_hdr_size - abs_off; + } else { + /* The chunk contains exclusively header data */ + blk_sz = 0; /* nothing to decrypt */ + } + } else { + idx = 0; + blk_sz = chunk_sz; + blk_off = (abs_off - hdr->ih_hdr_size) & 0xf; + } + + if (blk_sz > 0) + { + tlv_off = BOOT_TLV_OFF(hdr); + if (abs_off + chunk_sz > tlv_off) { + /* do not decrypt TLVs */ + if (abs_off >= tlv_off) { + blk_sz = 0; + } else { + blk_sz = tlv_off - abs_off; + } + } + if (source_slot == 0) { + boot_enc_encrypt(BOOT_CURR_ENC(state), source_slot, + (abs_off + idx) - hdr->ih_hdr_size, blk_sz, + blk_off, &buf[idx]); + } else { + boot_enc_decrypt(BOOT_CURR_ENC(state), source_slot, + (abs_off + idx) - hdr->ih_hdr_size, blk_sz, + blk_off, &buf[idx]); + } + } + } +#endif + + rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz); + if (rc != 0) { + return BOOT_EFLASH; + } + + bytes_copied += chunk_sz; + + MCUBOOT_WATCHDOG_FEED(); + } + + return 0; +} + +/** + * Overwrite primary slot with the image contained in the secondary slot. + * If a prior copy operation was interrupted by a system reset, this function + * redos the copy. + * + * @param bs The current boot status. This function reads + * this struct to determine if it is resuming + * an interrupted swap operation. This + * function writes the updated status to this + * function on return. + * + * @return 0 on success; nonzero on failure. + */ +#if defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_BOOTSTRAP) +static int +boot_copy_image(struct boot_loader_state *state, struct boot_status *bs) +{ + size_t sect_count; + size_t sect; + int rc; + size_t size; + size_t this_size; + size_t last_sector; + const struct flash_area *fap_primary_slot; + const struct flash_area *fap_secondary_slot; + uint8_t image_index; + +#if defined(MCUBOOT_OVERWRITE_ONLY_FAST) + uint32_t sector; + uint32_t trailer_sz; + uint32_t off; + uint32_t sz; +#endif + + (void)bs; + +#if defined(MCUBOOT_OVERWRITE_ONLY_FAST) + uint32_t src_size = 0; + rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &src_size); + assert(rc == 0); +#endif + + image_index = BOOT_CURR_IMG(state); + + BOOT_LOG_INF("Image %d upgrade secondary slot -> primary slot", image_index); + BOOT_LOG_INF("Erasing the primary slot"); + + rc = flash_area_open(flash_area_get_id(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)), + &fap_primary_slot); + assert (rc == 0); + + rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), + &fap_secondary_slot); + assert (rc == 0); + + sect_count = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT); + for (sect = 0, size = 0; sect < sect_count; sect++) { + this_size = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sect); + rc = boot_erase_region(fap_primary_slot, size, this_size); + assert(rc == 0); + +#if defined(MCUBOOT_OVERWRITE_ONLY_FAST) + if ((size + this_size) >= src_size) { + size += src_size - size; + size += BOOT_WRITE_SZ(state) - (size % BOOT_WRITE_SZ(state)); + break; + } +#endif + + size += this_size; + } + +#if defined(MCUBOOT_OVERWRITE_ONLY_FAST) + trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + sector = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 1; + sz = 0; + do { + sz += boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sector); + off = boot_img_sector_off(state, BOOT_PRIMARY_SLOT, sector); + sector--; + } while (sz < trailer_sz); + + rc = boot_erase_region(fap_primary_slot, off, sz); + assert(rc == 0); +#endif + +#ifdef MCUBOOT_ENC_IMAGES + if (IS_ENCRYPTED(boot_img_hdr(state, BOOT_SECONDARY_SLOT))) { + rc = boot_enc_load(BOOT_CURR_ENC(state), BOOT_SECONDARY_SLOT, + boot_img_hdr(state, BOOT_SECONDARY_SLOT), + fap_secondary_slot, bs); + + if (rc < 0) { + return BOOT_EBADIMAGE; + } + if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) { + return BOOT_EBADIMAGE; + } + } +#endif + + BOOT_LOG_INF("Image %d copying the secondary slot to the primary slot: 0x%zx bytes", + image_index, size); + rc = boot_copy_region(state, fap_secondary_slot, fap_primary_slot, 0, 0, size); + if (rc != 0) { + return rc; + } + +#if defined(MCUBOOT_OVERWRITE_ONLY_FAST) + rc = boot_write_magic(fap_primary_slot); + if (rc != 0) { + return rc; + } +#endif + + rc = BOOT_HOOK_CALL(boot_copy_region_post_hook, 0, BOOT_CURR_IMG(state), + BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT), size); + if (rc != 0) { + return rc; + } + +#ifdef MCUBOOT_HW_ROLLBACK_PROT + /* Update the stored security counter with the new image's security counter + * value. Both slots hold the new image at this point, but the secondary + * slot's image header must be passed since the image headers in the + * boot_data structure have not been updated yet. + */ + rc = boot_update_security_counter(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT, + boot_img_hdr(state, BOOT_SECONDARY_SLOT)); + if (rc != 0) { + BOOT_LOG_ERR("Security counter update failed after image upgrade."); + return rc; + } +#endif /* MCUBOOT_HW_ROLLBACK_PROT */ + +#ifndef MCUBOOT_OVERWRITE_ONLY_KEEP_BACKUP + /* + * Erases header and trailer. The trailer is erased because when a new + * image is written without a trailer as is the case when using newt, the + * trailer that was left might trigger a new upgrade. + */ + BOOT_LOG_DBG("erasing secondary header"); + rc = boot_erase_region(fap_secondary_slot, + boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0), + boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0)); + assert(rc == 0); +#endif + + last_sector = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1; + BOOT_LOG_DBG("erasing secondary trailer"); + rc = boot_erase_region(fap_secondary_slot, + boot_img_sector_off(state, BOOT_SECONDARY_SLOT, + last_sector), + boot_img_sector_size(state, BOOT_SECONDARY_SLOT, + last_sector)); + assert(rc == 0); + + flash_area_close(fap_primary_slot); + flash_area_close(fap_secondary_slot); + + /* TODO: Perhaps verify the primary slot's signature again? */ + + return 0; +} +#endif + +#if !defined(MCUBOOT_OVERWRITE_ONLY) +/** + * Swaps the two images in flash. If a prior copy operation was interrupted + * by a system reset, this function completes that operation. + * + * @param bs The current boot status. This function reads + * this struct to determine if it is resuming + * an interrupted swap operation. This + * function writes the updated status to this + * function on return. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) +{ + struct image_header *hdr; + const struct flash_area *fap; +#ifdef MCUBOOT_ENC_IMAGES + uint8_t slot; + uint8_t i; +#endif + uint32_t size; + uint32_t copy_size; + uint8_t image_index; + int rc; + + /* FIXME: just do this if asked by user? */ + + size = copy_size = 0; + image_index = BOOT_CURR_IMG(state); + + if (boot_status_is_reset(bs)) { + /* + * No swap ever happened, so need to find the largest image which + * will be used to determine the amount of sectors to swap. + */ + hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT); + if (hdr->ih_magic == IMAGE_MAGIC) { + rc = boot_read_image_size(state, BOOT_PRIMARY_SLOT, ©_size); + assert(rc == 0); + } + +#ifdef MCUBOOT_ENC_IMAGES + if (IS_ENCRYPTED(hdr)) { + fap = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); + rc = boot_enc_load(BOOT_CURR_ENC(state), 0, hdr, fap, bs); + assert(rc >= 0); + + if (rc == 0) { + rc = boot_enc_set_key(BOOT_CURR_ENC(state), 0, bs); + assert(rc == 0); + } else { + rc = 0; + } + } else { + memset(bs->enckey[0], 0xff, BOOT_ENC_KEY_ALIGN_SIZE); + } +#endif + + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + if (hdr->ih_magic == IMAGE_MAGIC) { + rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &size); + assert(rc == 0); + } + +#ifdef MCUBOOT_ENC_IMAGES + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + if (IS_ENCRYPTED(hdr)) { + fap = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + rc = boot_enc_load(BOOT_CURR_ENC(state), 1, hdr, fap, bs); + assert(rc >= 0); + + if (rc == 0) { + rc = boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs); + assert(rc == 0); + } else { + rc = 0; + } + } else { + memset(bs->enckey[1], 0xff, BOOT_ENC_KEY_ALIGN_SIZE); + } +#endif + + if (size > copy_size) { + copy_size = size; + } + + bs->swap_size = copy_size; + } else { + /* + * If a swap was under way, the swap_size should already be present + * in the trailer... + */ + + rc = boot_find_status(image_index, &fap); + assert(fap != NULL); + rc = boot_read_swap_size(fap, &bs->swap_size); + assert(rc == 0); + + copy_size = bs->swap_size; + +#ifdef MCUBOOT_ENC_IMAGES + for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { + rc = boot_read_enc_key(fap, slot, bs); + assert(rc == 0); + + for (i = 0; i < BOOT_ENC_KEY_SIZE; i++) { + if (bs->enckey[slot][i] != 0xff) { + break; + } + } + + boot_enc_init(BOOT_CURR_ENC(state), slot); + + if (i != BOOT_ENC_KEY_SIZE) { + boot_enc_set_key(BOOT_CURR_ENC(state), slot, bs); + } + } +#endif + flash_area_close(fap); + } + + swap_run(state, bs, copy_size); + +#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT + extern int boot_status_fails; + if (boot_status_fails > 0) { + BOOT_LOG_WRN("%d status write fails performing the swap", + boot_status_fails); + } +#endif + rc = BOOT_HOOK_CALL(boot_copy_region_post_hook, 0, BOOT_CURR_IMG(state), + BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT), size); + + return 0; +} +#endif + +/** + * Performs a clean (not aborted) image update. + * + * @param bs The current boot status. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_perform_update(struct boot_loader_state *state, struct boot_status *bs) +{ + int rc; +#ifndef MCUBOOT_OVERWRITE_ONLY + uint8_t swap_type; +#endif + + /* At this point there are no aborted swaps. */ +#if defined(MCUBOOT_OVERWRITE_ONLY) + rc = boot_copy_image(state, bs); +#elif defined(MCUBOOT_BOOTSTRAP) + /* Check if the image update was triggered by a bad image in the + * primary slot (the validity of the image in the secondary slot had + * already been checked). + */ + FIH_DECLARE(fih_rc, FIH_FAILURE); + rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT); + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, bs); + if (rc == 0 || FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + rc = boot_copy_image(state, bs); + } else { + rc = boot_swap_image(state, bs); + } +#else + rc = boot_swap_image(state, bs); +#endif + assert(rc == 0); + +#ifndef MCUBOOT_OVERWRITE_ONLY + /* The following state needs image_ok be explicitly set after the + * swap was finished to avoid a new revert. + */ + swap_type = BOOT_SWAP_TYPE(state); + if (swap_type == BOOT_SWAP_TYPE_REVERT || + swap_type == BOOT_SWAP_TYPE_PERM) { + rc = swap_set_image_ok(BOOT_CURR_IMG(state)); + if (rc != 0) { + BOOT_SWAP_TYPE(state) = swap_type = BOOT_SWAP_TYPE_PANIC; + } + } + +#ifdef MCUBOOT_HW_ROLLBACK_PROT + if (swap_type == BOOT_SWAP_TYPE_PERM) { + /* Update the stored security counter with the new image's security + * counter value. The primary slot holds the new image at this point, + * but the secondary slot's image header must be passed since image + * headers in the boot_data structure have not been updated yet. + * + * In case of a permanent image swap mcuboot will never attempt to + * revert the images on the next reboot. Therefore, the security + * counter must be increased right after the image upgrade. + */ + rc = boot_update_security_counter( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT, + boot_img_hdr(state, BOOT_SECONDARY_SLOT)); + if (rc != 0) { + BOOT_LOG_ERR("Security counter update failed after " + "image upgrade."); + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; + } + } +#endif /* MCUBOOT_HW_ROLLBACK_PROT */ + + if (BOOT_IS_UPGRADE(swap_type)) { + rc = swap_set_copy_done(BOOT_CURR_IMG(state)); + if (rc != 0) { + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; + } + } +#endif /* !MCUBOOT_OVERWRITE_ONLY */ + + return rc; +} + +/** + * Completes a previously aborted image swap. + * + * @param bs The current boot status. + * + * @return 0 on success; nonzero on failure. + */ +#if !defined(MCUBOOT_OVERWRITE_ONLY) +static int +boot_complete_partial_swap(struct boot_loader_state *state, + struct boot_status *bs) +{ + int rc; + + /* Determine the type of swap operation being resumed from the + * `swap-type` trailer field. + */ + rc = boot_swap_image(state, bs); + assert(rc == 0); + + BOOT_SWAP_TYPE(state) = bs->swap_type; + + /* The following states need image_ok be explicitly set after the + * swap was finished to avoid a new revert. + */ + if (bs->swap_type == BOOT_SWAP_TYPE_REVERT || + bs->swap_type == BOOT_SWAP_TYPE_PERM) { + rc = swap_set_image_ok(BOOT_CURR_IMG(state)); + if (rc != 0) { + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; + } + } + + if (BOOT_IS_UPGRADE(bs->swap_type)) { + rc = swap_set_copy_done(BOOT_CURR_IMG(state)); + if (rc != 0) { + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; + } + } + + if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) { + BOOT_LOG_ERR("panic!"); + assert(0); + + /* Loop forever... */ + while (1) {} + } + + return rc; +} +#endif /* !MCUBOOT_OVERWRITE_ONLY */ + +#if (BOOT_IMAGE_NUMBER > 1) +/** + * Review the validity of previously determined swap types of other images. + * + * @param aborted_swap The current image upgrade is a + * partial/aborted swap. + */ +static void +boot_review_image_swap_types(struct boot_loader_state *state, + bool aborted_swap) +{ + /* In that case if we rebooted in the middle of an image upgrade process, we + * must review the validity of swap types, that were previously determined + * for other images. The image_ok flag had not been set before the reboot + * for any of the updated images (only the copy_done flag) and thus falsely + * the REVERT swap type has been determined for the previous images that had + * been updated before the reboot. + * + * There are two separate scenarios that we have to deal with: + * + * 1. The reboot has happened during swapping an image: + * The current image upgrade has been determined as a + * partial/aborted swap. + * 2. The reboot has happened between two separate image upgrades: + * In this scenario we must check the swap type of the current image. + * In those cases if it is NONE or REVERT we cannot certainly determine + * the fact of a reboot. In a consistent state images must move in the + * same direction or stay in place, e.g. in practice REVERT and TEST + * swap types cannot be present at the same time. If the swap type of + * the current image is either TEST, PERM or FAIL we must review the + * already determined swap types of other images and set each false + * REVERT swap types to NONE (these images had been successfully + * updated before the system rebooted between two separate image + * upgrades). + */ + + if (BOOT_CURR_IMG(state) == 0) { + /* Nothing to do */ + return; + } + + if (!aborted_swap) { + if ((BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) || + (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_REVERT)) { + /* Nothing to do */ + return; + } + } + + for (uint8_t i = 0; i < BOOT_CURR_IMG(state); i++) { + if (state->swap_type[i] == BOOT_SWAP_TYPE_REVERT) { + state->swap_type[i] = BOOT_SWAP_TYPE_NONE; + } + } +} +#endif + +/** + * Prepare image to be updated if required. + * + * Prepare image to be updated if required with completing an image swap + * operation if one was aborted and/or determining the type of the + * swap operation. In case of any error set the swap type to NONE. + * + * @param state TODO + * @param bs Pointer where the read and possibly updated + * boot status can be written to. + */ +static void +boot_prepare_image_for_update(struct boot_loader_state *state, + struct boot_status *bs) +{ + int rc; + FIH_DECLARE(fih_rc, FIH_FAILURE); + +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) + int max_size; +#endif + + /* Determine the sector layout of the image slots and scratch area. */ + rc = boot_read_sectors(state); + if (rc != 0) { + BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d" + " - too small?", BOOT_MAX_IMG_SECTORS); + /* Unable to determine sector layout, continue with next image + * if there is one. + */ + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; + if (rc == BOOT_EFLASH) + { + /* Only return on error from the primary image flash */ + return; + } + } + + /* Attempt to read an image header from each slot. */ + rc = boot_read_image_headers(state, false, NULL); + if (rc != 0) { + /* Continue with next image if there is one. */ + BOOT_LOG_WRN("Failed reading image headers; Image=%u", + BOOT_CURR_IMG(state)); + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; + return; + } + +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) + /* Fetch information on maximum sizes for later usage, if needed */ + max_size = app_max_size(state); + + if (max_size > 0) { + image_max_sizes[BOOT_CURR_IMG(state)].calculated = true; + image_max_sizes[BOOT_CURR_IMG(state)].max_size = max_size; + } +#endif + + /* If the current image's slots aren't compatible, no swap is possible. + * Just boot into primary slot. + */ + if (boot_slots_compatible(state)) { + boot_status_reset(bs); + +#ifndef MCUBOOT_OVERWRITE_ONLY + rc = swap_read_status(state, bs); + if (rc != 0) { + BOOT_LOG_WRN("Failed reading boot status; Image=%u", + BOOT_CURR_IMG(state)); + /* Continue with next image if there is one. */ + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; + return; + } +#endif + +#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) + /* + * Must re-read image headers because the boot status might + * have been updated in the previous function call. + */ + rc = boot_read_image_headers(state, !boot_status_is_reset(bs), bs); +#ifdef MCUBOOT_BOOTSTRAP + /* When bootstrapping it's OK to not have image magic in the primary slot */ + if (rc != 0 && (BOOT_CURR_IMG(state) != BOOT_PRIMARY_SLOT || + boot_check_header_erased(state, BOOT_PRIMARY_SLOT) != 0)) { +#else + if (rc != 0) { +#endif + + /* Continue with next image if there is one. */ + BOOT_LOG_WRN("Failed reading image headers; Image=%u", + BOOT_CURR_IMG(state)); + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; + return; + } +#endif + + /* Determine if we rebooted in the middle of an image swap + * operation. If a partial swap was detected, complete it. + */ + if (!boot_status_is_reset(bs)) { + +#if (BOOT_IMAGE_NUMBER > 1) + boot_review_image_swap_types(state, true); +#endif + +#ifdef MCUBOOT_OVERWRITE_ONLY + /* Should never arrive here, overwrite-only mode has + * no swap state. + */ + assert(0); +#else + /* Determine the type of swap operation being resumed from the + * `swap-type` trailer field. + */ + rc = boot_complete_partial_swap(state, bs); + assert(rc == 0); +#endif + /* Attempt to read an image header from each slot. Ensure that + * image headers in slots are aligned with headers in boot_data. + */ + rc = boot_read_image_headers(state, false, bs); + assert(rc == 0); + + /* Swap has finished set to NONE */ + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; + } else { + /* There was no partial swap, determine swap type. */ + if (bs->swap_type == BOOT_SWAP_TYPE_NONE) { + BOOT_SWAP_TYPE(state) = boot_validated_swap_type(state, bs); + } else { + FIH_CALL(boot_validate_slot, fih_rc, + state, BOOT_SECONDARY_SLOT, bs); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_FAIL; + } else { + BOOT_SWAP_TYPE(state) = bs->swap_type; + } + } + +#if (BOOT_IMAGE_NUMBER > 1) + boot_review_image_swap_types(state, false); +#endif + +#ifdef MCUBOOT_BOOTSTRAP + if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) { + /* Header checks are done first because they are + * inexpensive. Since overwrite-only copies starting from + * offset 0, if interrupted, it might leave a valid header + * magic, so also run validation on the primary slot to be + * sure it's not OK. + */ + rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT); + FIH_CALL(boot_validate_slot, fih_rc, + state, BOOT_PRIMARY_SLOT, bs); + + if (rc == 0 || FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + + rc = (boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_magic == IMAGE_MAGIC) ? 1: 0; + FIH_CALL(boot_validate_slot, fih_rc, + state, BOOT_SECONDARY_SLOT, bs); + + if (rc == 1 && FIH_EQ(fih_rc, FIH_SUCCESS)) { + /* Set swap type to REVERT to overwrite the primary + * slot with the image contained in secondary slot + * and to trigger the explicit setting of the + * image_ok flag. + */ + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT; + } + } + } +#endif + } + } else { + /* In that case if slots are not compatible. */ + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; + } +} + +/** + * Updates the security counter for the current image. + * + * @param state Boot loader status information. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_update_hw_rollback_protection(struct boot_loader_state *state) +{ +#ifdef MCUBOOT_HW_ROLLBACK_PROT + int rc; + + /* Update the stored security counter with the active image's security + * counter value. It will only be updated if the new security counter is + * greater than the stored value. + * + * In case of a successful image swapping when the swap type is TEST the + * security counter can be increased only after a reset, when the swap + * type is NONE and the image has marked itself "OK" (the image_ok flag + * has been set). This way a "revert" can be performed when it's + * necessary. + */ + if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) { + rc = boot_update_security_counter( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT, + boot_img_hdr(state, BOOT_PRIMARY_SLOT)); + if (rc != 0) { + BOOT_LOG_ERR("Security counter update failed after image " + "validation."); + return rc; + } + } + + return 0; + +#else /* MCUBOOT_HW_ROLLBACK_PROT */ + (void) (state); + + return 0; +#endif +} + +/** + * Checks test swap downgrade prevention conditions. + * + * Function called only for swap upgrades test run. It may prevent + * swap if slot 1 image has <= version number or < security counter + * + * @param state Boot loader status information. + * + * @return 0 - image can be swapped, -1 downgrade prevention + */ +static int +check_downgrade_prevention(struct boot_loader_state *state) +{ +#if defined(MCUBOOT_DOWNGRADE_PREVENTION) && \ + (defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_SCRATCH)) + uint32_t security_counter[2]; + int rc; + +#if defined(PM_S1_ADDRESS) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + /* Downgrade prevention on S0/S1 image is managed by NSIB */ + return 0; + } +#endif + + if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) { + /* If there was security no counter in slot 0, allow swap */ + rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 0).hdr), + BOOT_IMG(state, 0).area, + &security_counter[0]); + if (rc != 0) { + return 0; + } + /* If there is no security counter in slot 1, or it's lower than + * that of slot 0, prevent downgrade */ + rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 1).hdr), + BOOT_IMG(state, 1).area, + &security_counter[1]); + if (rc != 0 || security_counter[0] > security_counter[1]) { + rc = -1; + } + } + else { + rc = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + } + if (rc < 0) { + /* Image in slot 0 prevents downgrade, delete image in slot 1 */ + BOOT_LOG_INF("Image %d in slot 1 erased due to downgrade prevention", BOOT_CURR_IMG(state)); + flash_area_erase(BOOT_IMG(state, 1).area, 0, + flash_area_get_size(BOOT_IMG(state, 1).area)); + } else { + rc = 0; + } + return rc; +#else + (void)state; + return 0; +#endif +} + +fih_ret +context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) +{ + size_t slot; + struct boot_status bs; + int rc = -1; + FIH_DECLARE(fih_rc, FIH_FAILURE); + int fa_id; + int image_index; + bool has_upgrade; + volatile int fih_cnt; + +#if defined(__BOOTSIM__) + /* The array of slot sectors are defined here (as opposed to file scope) so + * that they don't get allocated for non-boot-loader apps. This is + * necessary because the gcc option "-fdata-sections" doesn't seem to have + * any effect in older gcc versions (e.g., 4.8.4). + */ + TARGET_STATIC boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; + TARGET_STATIC boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; +#if MCUBOOT_SWAP_USING_SCRATCH + TARGET_STATIC boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS]; +#endif +#endif + + has_upgrade = false; + +#if (BOOT_IMAGE_NUMBER == 1) + (void)has_upgrade; +#endif + + /* Iterate over all the images. By the end of the loop the swap type has + * to be determined for each image and all aborted swaps have to be + * completed. + */ + IMAGES_ITER(BOOT_CURR_IMG(state)) { +#if BOOT_IMAGE_NUMBER > 1 + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } +#endif +#if defined(MCUBOOT_ENC_IMAGES) && (BOOT_IMAGE_NUMBER > 1) + /* The keys used for encryption may no longer be valid (could belong to + * another images). Therefore, mark them as invalid to force their reload + * by boot_enc_load(). + */ + boot_enc_zeroize(BOOT_CURR_ENC(state)); +#endif + + image_index = BOOT_CURR_IMG(state); + +#if !defined(__BOOTSIM__) + BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors = + sector_buffers.primary[image_index]; + BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors = + sector_buffers.secondary[image_index]; +#if MCUBOOT_SWAP_USING_SCRATCH + state->scratch.sectors = sector_buffers.scratch; +#endif +#else + BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors = + primary_slot_sectors[image_index]; + BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors = + secondary_slot_sectors[image_index]; +#if MCUBOOT_SWAP_USING_SCRATCH + state->scratch.sectors = scratch_sectors; +#endif +#endif + + /* Open primary and secondary image areas for the duration + * of this call. + */ + for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { + fa_id = flash_area_id_from_multi_image_slot(image_index, slot); + rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot)); + assert(rc == 0); + + if (rc != 0) { + BOOT_LOG_ERR("Failed to open flash area ID %d (image %d slot %d): %d, " + "cannot continue", fa_id, image_index, (int8_t)slot, rc); + FIH_PANIC; + } + } +#if MCUBOOT_SWAP_USING_SCRATCH + rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, + &BOOT_SCRATCH_AREA(state)); + assert(rc == 0); + + if (rc != 0) { + BOOT_LOG_ERR("Failed to open scratch flash area: %d, cannot continue", rc); + FIH_PANIC; + } +#endif + + /* Determine swap type and complete swap if it has been aborted. */ + boot_prepare_image_for_update(state, &bs); + + if (BOOT_IS_UPGRADE(BOOT_SWAP_TYPE(state))) { + has_upgrade = true; + } + } + + /* cleanup secondary slots which were recognized unusable*/ + sec_slot_cleanup_if_unusable(); + +#if (BOOT_IMAGE_NUMBER > 1) + if (has_upgrade) { + /* Iterate over all the images and verify whether the image dependencies + * are all satisfied and update swap type if necessary. + */ + rc = boot_verify_dependencies(state); + if (rc != 0) { + /* + * It was impossible to upgrade because the expected dependency version + * was not available. Here we already changed the swap_type so that + * instead of asserting the bootloader, we continue and no upgrade is + * performed. + */ + rc = 0; + } + } +#endif + + /* Trigger status change callback with upgrading status */ + mcuboot_status_change(MCUBOOT_STATUS_UPGRADING); + + /* Iterate over all the images. At this point there are no aborted swaps + * and the swap types are determined for each image. By the end of the loop + * all required update operations will have been finished. + */ + IMAGES_ITER(BOOT_CURR_IMG(state)) { +#if (BOOT_IMAGE_NUMBER > 1) + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } + +#ifdef MCUBOOT_ENC_IMAGES + /* The keys used for encryption may no longer be valid (could belong to + * another images). Therefore, mark them as invalid to force their reload + * by boot_enc_load(). + */ + boot_enc_zeroize(BOOT_CURR_ENC(state)); +#endif /* MCUBOOT_ENC_IMAGES */ + + /* Indicate that swap is not aborted */ + boot_status_reset(&bs); +#endif /* (BOOT_IMAGE_NUMBER > 1) */ + + /* Set the previously determined swap type */ + bs.swap_type = BOOT_SWAP_TYPE(state); + + switch (BOOT_SWAP_TYPE(state)) { + case BOOT_SWAP_TYPE_NONE: + break; + + case BOOT_SWAP_TYPE_TEST: + /* fallthrough */ + case BOOT_SWAP_TYPE_PERM: + if (check_downgrade_prevention(state) != 0) { + /* Downgrade prevented */ + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; + break; + } + /* fallthrough */ + case BOOT_SWAP_TYPE_REVERT: + rc = BOOT_HOOK_CALL(boot_perform_update_hook, BOOT_HOOK_REGULAR, + BOOT_CURR_IMG(state), &(BOOT_IMG(state, 1).hdr), + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT)); + if (rc == BOOT_HOOK_REGULAR) + { + rc = boot_perform_update(state, &bs); + } + assert(rc == 0); +#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + sys_reboot(SYS_REBOOT_COLD); + + } +#endif + break; + + case BOOT_SWAP_TYPE_FAIL: + /* The image in secondary slot was invalid and is now erased. Ensure + * we don't try to boot into it again on the next reboot. Do this by + * pretending we just reverted back to primary slot. + */ +#ifndef MCUBOOT_OVERWRITE_ONLY + /* image_ok needs to be explicitly set to avoid a new revert. */ + rc = swap_set_image_ok(BOOT_CURR_IMG(state)); + if (rc != 0) { + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; + } +#endif /* !MCUBOOT_OVERWRITE_ONLY */ + break; + + default: + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; + } + + if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) { + BOOT_LOG_ERR("panic!"); + assert(0); + + /* Loop forever... */ + FIH_PANIC; + } + } + + /* Iterate over all the images. At this point all required update operations + * have finished. By the end of the loop each image in the primary slot will + * have been re-validated. + */ + FIH_SET(fih_cnt, 0); + IMAGES_ITER(BOOT_CURR_IMG(state)) { +#if BOOT_IMAGE_NUMBER > 1 + /* Hardenned to prevent from skipping check of a given image, + * tmp_img_mask is declared volatile + */ + volatile bool tmp_img_mask; + FIH_SET(tmp_img_mask, state->img_mask[BOOT_CURR_IMG(state)]); + if (FIH_EQ(tmp_img_mask, true)) { + ++fih_cnt; + continue; + } +#endif + if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE) { + /* Attempt to read an image header from each slot. Ensure that image + * headers in slots are aligned with headers in boot_data. + * Note: Quite complicated internal logic of boot_read_image_headers + * uses boot state, the last parm, to figure out in which slot which + * header is located; when boot state is not provided, then it + * is assumed that headers are at proper slots (we are not in + * the middle of moving images, etc). + */ + rc = boot_read_image_headers(state, false, NULL); + if (rc != 0) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + /* Since headers were reloaded, it can be assumed we just performed + * a swap or overwrite. Now the header info that should be used to + * provide the data for the bootstrap, which previously was at + * secondary slot, was updated to primary slot. + */ + } + +#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. Image 1 primary is the currently + * executing MCUBoot image, and is therefore already validated by NSIB and + * does not need to also be validated by MCUBoot. + */ + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; + if (!image_validated_by_nsib) +#endif + { + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL); + /* Check for all possible values is redundant in normal operation it + * is meant to prevent FI attack. + */ + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || + FIH_EQ(fih_rc, FIH_FAILURE) || + FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + } +#else + /* Even if we're not re-validating the primary slot, we could be booting + * onto an empty flash chip. At least do a basic sanity check that + * the magic number on the image is OK. + */ + if (BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic != IMAGE_MAGIC) { + BOOT_LOG_ERR("bad image magic 0x%lx; Image=%u", (unsigned long) + BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic, + BOOT_CURR_IMG(state)); + rc = BOOT_EBADIMAGE; + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } +#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ + +#ifdef PM_S1_ADDRESS + if (!image_validated_by_nsib) +#endif + { + rc = boot_update_hw_rollback_protection(state); + if (rc != 0) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + } + + rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT); + if (rc != 0) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + ++fih_cnt; + } + /* + * fih_cnt should be equal to BOOT_IMAGE_NUMBER now. + * If this is not the case, at least one iteration of the loop + * has been skipped. + */ + if(FIH_NOT_EQ(fih_cnt, BOOT_IMAGE_NUMBER)) { + FIH_PANIC; + } + + fill_rsp(state, rsp); + + fih_rc = FIH_SUCCESS; +out: + /* + * Since the boot_status struct stores plaintext encryption keys, reset + * them here to avoid the possibility of jumping into an image that could + * easily recover them. + */ +#if defined(MCUBOOT_ENC_IMAGES) || defined(MCUBOOT_SWAP_SAVE_ENCTLV) + like_mbedtls_zeroize(&bs, sizeof(bs)); +#else + memset(&bs, 0, sizeof(struct boot_status)); +#endif + + close_all_flash_areas(state); + FIH_RET(fih_rc); +} + +fih_ret +split_go(int loader_slot, int split_slot, void **entry) +{ + boot_sector_t *sectors; + uintptr_t entry_val; + int loader_flash_id; + int split_flash_id; + int rc; + FIH_DECLARE(fih_rc, FIH_FAILURE); + + sectors = malloc(BOOT_MAX_IMG_SECTORS * 2 * sizeof *sectors); + if (sectors == NULL) { + FIH_RET(FIH_FAILURE); + } + BOOT_IMG(&boot_data, loader_slot).sectors = sectors + 0; + BOOT_IMG(&boot_data, split_slot).sectors = sectors + BOOT_MAX_IMG_SECTORS; + + loader_flash_id = flash_area_id_from_image_slot(loader_slot); + rc = flash_area_open(loader_flash_id, + &BOOT_IMG_AREA(&boot_data, loader_slot)); + assert(rc == 0); + split_flash_id = flash_area_id_from_image_slot(split_slot); + rc = flash_area_open(split_flash_id, + &BOOT_IMG_AREA(&boot_data, split_slot)); + assert(rc == 0); + + /* Determine the sector layout of the image slots and scratch area. */ + rc = boot_read_sectors(&boot_data); + if (rc != 0) { + rc = SPLIT_GO_ERR; + goto done; + } + + rc = boot_read_image_headers(&boot_data, true, NULL); + if (rc != 0) { + goto done; + } + + /* Don't check the bootable image flag because we could really call a + * bootable or non-bootable image. Just validate that the image check + * passes which is distinct from the normal check. + */ + FIH_CALL(split_image_check, fih_rc, + boot_img_hdr(&boot_data, split_slot), + BOOT_IMG_AREA(&boot_data, split_slot), + boot_img_hdr(&boot_data, loader_slot), + BOOT_IMG_AREA(&boot_data, loader_slot)); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + goto done; + } + + entry_val = boot_img_slot_off(&boot_data, split_slot) + + boot_img_hdr(&boot_data, split_slot)->ih_hdr_size; + *entry = (void *) entry_val; + rc = SPLIT_GO_OK; + +done: + flash_area_close(BOOT_IMG_AREA(&boot_data, split_slot)); + flash_area_close(BOOT_IMG_AREA(&boot_data, loader_slot)); + free(sectors); + + if (rc) { + FIH_SET(fih_rc, FIH_FAILURE); + } + + FIH_RET(fih_rc); +} + +#else /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */ + +/** + * Opens all flash areas and checks which contain an image with a valid header. + * + * @param state Boot loader status information. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_get_slot_usage(struct boot_loader_state *state) +{ + uint32_t slot; + int fa_id; + int rc; + struct image_header *hdr = NULL; + + IMAGES_ITER(BOOT_CURR_IMG(state)) { +#if BOOT_IMAGE_NUMBER > 1 + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } +#endif + /* Open all the slots */ + for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { + fa_id = flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), slot); + rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot)); + assert(rc == 0); + } + + /* Attempt to read an image header from each slot. */ + rc = boot_read_image_headers(state, false, NULL); + if (rc != 0) { + BOOT_LOG_WRN("Failed reading image headers."); + return rc; + } + + /* Check headers in all slots */ + for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { + hdr = boot_img_hdr(state, slot); + + if (boot_is_header_valid(hdr, BOOT_IMG_AREA(state, slot), state)) { + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = true; + BOOT_LOG_IMAGE_INFO(slot, hdr); + } else { + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; + BOOT_LOG_INF("Image %d %s slot: Image not found", + BOOT_CURR_IMG(state), + (slot == BOOT_PRIMARY_SLOT) + ? "Primary" : "Secondary"); + } + } + + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + } + + return 0; +} + +/** + * Finds the slot containing the image with the highest version number for the + * current image. + * + * @param state Boot loader status information. + * + * @return NO_ACTIVE_SLOT if no available slot found, number of + * the found slot otherwise. + */ +static uint32_t +find_slot_with_highest_version(struct boot_loader_state *state) +{ + uint32_t slot; + uint32_t candidate_slot = NO_ACTIVE_SLOT; + int rc; + + for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { + if (state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot]) { + if (candidate_slot == NO_ACTIVE_SLOT) { + candidate_slot = slot; + } else { + rc = boot_version_cmp( + &boot_img_hdr(state, slot)->ih_ver, + &boot_img_hdr(state, candidate_slot)->ih_ver); + if (rc == 1) { + /* The version of the image being examined is greater than + * the version of the current candidate. + */ + candidate_slot = slot; + } + } + } + } + + return candidate_slot; +} + +#ifdef MCUBOOT_HAVE_LOGGING +/** + * Prints the state of the loaded images. + * + * @param state Boot loader status information. + */ +static void +print_loaded_images(struct boot_loader_state *state) +{ + uint32_t active_slot; + + (void)state; + + IMAGES_ITER(BOOT_CURR_IMG(state)) { +#if BOOT_IMAGE_NUMBER > 1 + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } +#endif + active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; + + BOOT_LOG_INF("Image %d loaded from the %s slot", + BOOT_CURR_IMG(state), + (active_slot == BOOT_PRIMARY_SLOT) ? + "primary" : "secondary"); + } +} +#endif + +#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT) +/** + * Checks whether the active slot of the current image was previously selected + * to run. Erases the image if it was selected but its execution failed, + * otherwise marks it as selected if it has not been before. + * + * @param state Boot loader status information. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_select_or_erase(struct boot_loader_state *state) +{ + const struct flash_area *fap; + int fa_id; + int rc; + uint32_t active_slot; + struct boot_swap_state* active_swap_state; + + active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; + + fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), active_slot); + rc = flash_area_open(fa_id, &fap); + assert(rc == 0); + + active_swap_state = &(state->slot_usage[BOOT_CURR_IMG(state)].swap_state); + + memset(active_swap_state, 0, sizeof(struct boot_swap_state)); + rc = boot_read_swap_state(fap, active_swap_state); + assert(rc == 0); + + if (active_swap_state->magic != BOOT_MAGIC_GOOD || + (active_swap_state->copy_done == BOOT_FLAG_SET && + active_swap_state->image_ok != BOOT_FLAG_SET)) { + /* + * A reboot happened without the image being confirmed at + * runtime or its trailer is corrupted/invalid. Erase the image + * to prevent it from being selected again on the next reboot. + */ + BOOT_LOG_DBG("Erasing faulty image in the %s slot.", + (active_slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); + rc = flash_area_erase(fap, 0, flash_area_get_size(fap)); + assert(rc == 0); + + flash_area_close(fap); + rc = -1; + } else { + if (active_swap_state->copy_done != BOOT_FLAG_SET) { + if (active_swap_state->copy_done == BOOT_FLAG_BAD) { + BOOT_LOG_DBG("The copy_done flag had an unexpected value. Its " + "value was neither 'set' nor 'unset', but 'bad'."); + } + /* + * Set the copy_done flag, indicating that the image has been + * selected to boot. It can be set in advance, before even + * validating the image, because in case the validation fails, the + * entire image slot will be erased (including the trailer). + */ + rc = boot_write_copy_done(fap); + if (rc != 0) { + BOOT_LOG_WRN("Failed to set copy_done flag of the image in " + "the %s slot.", (active_slot == BOOT_PRIMARY_SLOT) ? + "primary" : "secondary"); + rc = 0; + } + } + flash_area_close(fap); + } + + return rc; +} +#endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_DIRECT_XIP_REVERT */ + +#ifdef MCUBOOT_RAM_LOAD + +#ifndef MULTIPLE_EXECUTABLE_RAM_REGIONS +#if !defined(IMAGE_EXECUTABLE_RAM_START) || !defined(IMAGE_EXECUTABLE_RAM_SIZE) +#error "Platform MUST define executable RAM bounds in case of RAM_LOAD" +#endif +#endif + +/** + * Verifies that the active slot of the current image can be loaded within the + * predefined bounds that are allowed to be used by executable images. + * + * @param state Boot loader status information. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_verify_ram_load_address(struct boot_loader_state *state) +{ + uint32_t img_dst; + uint32_t img_sz; + uint32_t img_end_addr; + uint32_t exec_ram_start; + uint32_t exec_ram_size; + + (void)state; + +#ifdef MULTIPLE_EXECUTABLE_RAM_REGIONS + int rc; + + rc = boot_get_image_exec_ram_info(BOOT_CURR_IMG(state), &exec_ram_start, + &exec_ram_size); + if (rc != 0) { + return BOOT_EBADSTATUS; + } +#else + exec_ram_start = IMAGE_EXECUTABLE_RAM_START; + exec_ram_size = IMAGE_EXECUTABLE_RAM_SIZE; +#endif + + img_dst = state->slot_usage[BOOT_CURR_IMG(state)].img_dst; + img_sz = state->slot_usage[BOOT_CURR_IMG(state)].img_sz; + + if (img_dst < exec_ram_start) { + return BOOT_EBADIMAGE; + } + + if (!boot_u32_safe_add(&img_end_addr, img_dst, img_sz)) { + return BOOT_EBADIMAGE; + } + + if (img_end_addr > (exec_ram_start + exec_ram_size)) { + return BOOT_EBADIMAGE; + } + + return 0; +} + +#ifdef MCUBOOT_ENC_IMAGES + +/** + * Copies and decrypts an image from a slot in the flash to an SRAM address. + * + * @param state Boot loader status information. + * @param slot The flash slot of the image to be copied to SRAM. + * @param hdr The image header. + * @param src_sz Size of the image. + * @param img_dst Pointer to the address at which the image needs to be + * copied to SRAM. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_decrypt_and_copy_image_to_sram(struct boot_loader_state *state, + uint32_t slot, struct image_header *hdr, + uint32_t src_sz, uint32_t img_dst) +{ + /* The flow for the decryption and copy of the image is as follows : + * 1. The whole image is copied to the RAM (header + payload + TLV). + * 2. The encryption key is loaded from the TLV in flash. + * 3. The image is then decrypted chunk by chunk in RAM (1 chunk + * is 1024 bytes). Only the payload section is decrypted. + * 4. The image is authenticated in RAM. + */ + const struct flash_area *fap_src = NULL; + struct boot_status bs; + uint32_t blk_off; + uint32_t tlv_off; + uint32_t blk_sz; + uint32_t bytes_copied = hdr->ih_hdr_size; + uint32_t chunk_sz; + uint32_t max_sz = 1024; + uint16_t idx; + uint8_t * cur_dst; + int area_id; + int rc; + uint8_t * ram_dst = (void *)(IMAGE_RAM_BASE + img_dst); + + area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); + rc = flash_area_open(area_id, &fap_src); + if (rc != 0){ + return BOOT_EFLASH; + } + + tlv_off = BOOT_TLV_OFF(hdr); + + /* Copying the whole image in RAM */ + rc = flash_area_read(fap_src, 0, ram_dst, src_sz); + if (rc != 0) { + goto done; + } + + rc = boot_enc_load(BOOT_CURR_ENC(state), slot, hdr, fap_src, &bs); + if (rc < 0) { + goto done; + } + + /* if rc > 0 then the key has already been loaded */ + if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), slot, &bs)) { + goto done; + } + + /* Starting at the end of the header as the header section is not encrypted */ + while (bytes_copied < tlv_off) { /* TLV section copied previously */ + if (src_sz - bytes_copied > max_sz) { + chunk_sz = max_sz; + } else { + chunk_sz = src_sz - bytes_copied; + } + + cur_dst = ram_dst + bytes_copied; + blk_sz = chunk_sz; + idx = 0; + blk_off = ((bytes_copied) - hdr->ih_hdr_size) & 0xf; + if (bytes_copied + chunk_sz > tlv_off) { + /* Going over TLV section + * Part of the chunk is encrypted payload */ + blk_sz = tlv_off - (bytes_copied); + } + boot_enc_decrypt(BOOT_CURR_ENC(state), slot, + (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz, + blk_off, cur_dst); + bytes_copied += chunk_sz; + } + rc = 0; + +done: + flash_area_close(fap_src); + + return rc; +} + +#endif /* MCUBOOT_ENC_IMAGES */ +/** + * Copies a slot of the current image into SRAM. + * + * @param state Boot loader status information. + * @param slot The flash slot of the image to be copied to SRAM. + * @param img_dst The address at which the image needs to be copied to + * SRAM. + * @param img_sz The size of the image that needs to be copied to SRAM. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_copy_image_to_sram(struct boot_loader_state *state, int slot, + uint32_t img_dst, uint32_t img_sz) +{ + int rc; + const struct flash_area *fap_src = NULL; + int area_id; + +#if (BOOT_IMAGE_NUMBER == 1) + (void)state; +#endif + + area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); + + rc = flash_area_open(area_id, &fap_src); + if (rc != 0) { + return BOOT_EFLASH; + } + + /* Direct copy from flash to its new location in SRAM. */ + rc = flash_area_read(fap_src, 0, (void *)(IMAGE_RAM_BASE + img_dst), img_sz); + if (rc != 0) { + BOOT_LOG_INF("Error whilst copying image %d from Flash to SRAM: %d", + BOOT_CURR_IMG(state), rc); + } + + flash_area_close(fap_src); + + return rc; +} + +#if (BOOT_IMAGE_NUMBER > 1) +/** + * Checks if two memory regions (A and B) are overlap or not. + * + * @param start_a Start of the A region. + * @param end_a End of the A region. + * @param start_b Start of the B region. + * @param end_b End of the B region. + * + * @return true if there is overlap; false otherwise. + */ +static bool +do_regions_overlap(uint32_t start_a, uint32_t end_a, + uint32_t start_b, uint32_t end_b) +{ + if (start_b > end_a) { + return false; + } else if (start_b >= start_a) { + return true; + } else if (end_b > start_a) { + return true; + } + + return false; +} + +/** + * Checks if the image we want to load to memory overlap with an already + * ramloaded image. + * + * @param state Boot loader status information. + * + * @return 0 if there is no overlap; nonzero otherwise. + */ +static int +boot_check_ram_load_overlapping(struct boot_loader_state *state) +{ + uint32_t i; + + uint32_t start_a; + uint32_t end_a; + uint32_t start_b; + uint32_t end_b; + uint32_t image_id_to_check = BOOT_CURR_IMG(state); + + start_a = state->slot_usage[image_id_to_check].img_dst; + /* Safe to add here, values are already verified in + * boot_verify_ram_load_address() */ + end_a = start_a + state->slot_usage[image_id_to_check].img_sz; + + for (i = 0; i < BOOT_IMAGE_NUMBER; i++) { + if (state->slot_usage[i].active_slot == NO_ACTIVE_SLOT + || i == image_id_to_check) { + continue; + } + + start_b = state->slot_usage[i].img_dst; + /* Safe to add here, values are already verified in + * boot_verify_ram_load_address() */ + end_b = start_b + state->slot_usage[i].img_sz; + + if (do_regions_overlap(start_a, end_a, start_b, end_b)) { + return -1; + } + } + + return 0; +} +#endif + +/** + * Loads the active slot of the current image into SRAM. The load address and + * image size is extracted from the image header. + * + * @param state Boot loader status information. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_load_image_to_sram(struct boot_loader_state *state) +{ + uint32_t active_slot; + struct image_header *hdr = NULL; + uint32_t img_dst; + uint32_t img_sz; + int rc; + + active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; + hdr = boot_img_hdr(state, active_slot); + + if (hdr->ih_flags & IMAGE_F_RAM_LOAD) { + + img_dst = hdr->ih_load_addr; + + rc = boot_read_image_size(state, active_slot, &img_sz); + if (rc != 0) { + return rc; + } + + state->slot_usage[BOOT_CURR_IMG(state)].img_dst = img_dst; + state->slot_usage[BOOT_CURR_IMG(state)].img_sz = img_sz; + + rc = boot_verify_ram_load_address(state); + if (rc != 0) { + BOOT_LOG_INF("Image %d RAM load address 0x%x is invalid.", BOOT_CURR_IMG(state), img_dst); + return rc; + } + +#if (BOOT_IMAGE_NUMBER > 1) + rc = boot_check_ram_load_overlapping(state); + if (rc != 0) { + BOOT_LOG_INF("Image %d RAM loading to address 0x%x would overlap with\ + another image.", BOOT_CURR_IMG(state), img_dst); + return rc; + } +#endif +#ifdef MCUBOOT_ENC_IMAGES + /* decrypt image if encrypted and copy it to RAM */ + if (IS_ENCRYPTED(hdr)) { + rc = boot_decrypt_and_copy_image_to_sram(state, active_slot, hdr, img_sz, img_dst); + } else { + rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz); + } +#else + /* Copy image to the load address from where it currently resides in + * flash. + */ + rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz); +#endif + if (rc != 0) { + BOOT_LOG_INF("Image %d RAM loading to 0x%x is failed.", BOOT_CURR_IMG(state), img_dst); + } else { + BOOT_LOG_INF("Image %d RAM loading to 0x%x is succeeded.", BOOT_CURR_IMG(state), img_dst); + } + } else { + /* Only images that support IMAGE_F_RAM_LOAD are allowed if + * MCUBOOT_RAM_LOAD is set. + */ + rc = BOOT_EBADIMAGE; + } + + if (rc != 0) { + state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0; + state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0; + } + + return rc; +} + +/** + * Removes an image from SRAM, by overwriting it with zeros. + * + * @param state Boot loader status information. + * + * @return 0 on success; nonzero on failure. + */ +static inline int +boot_remove_image_from_sram(struct boot_loader_state *state) +{ + (void)state; + + BOOT_LOG_INF("Removing image %d from SRAM at address 0x%x", + BOOT_CURR_IMG(state), + state->slot_usage[BOOT_CURR_IMG(state)].img_dst); + + memset((void*)(IMAGE_RAM_BASE + state->slot_usage[BOOT_CURR_IMG(state)].img_dst), + 0, state->slot_usage[BOOT_CURR_IMG(state)].img_sz); + + state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0; + state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0; + + return 0; +} + +/** + * Removes an image from flash by erasing the corresponding flash area + * + * @param state Boot loader status information. + * @param slot The flash slot of the image to be erased. + * + * @return 0 on success; nonzero on failure. + */ +static inline int +boot_remove_image_from_flash(struct boot_loader_state *state, uint32_t slot) +{ + int area_id; + int rc; + const struct flash_area *fap; + + (void)state; + + BOOT_LOG_INF("Removing image %d slot %d from flash", BOOT_CURR_IMG(state), + slot); + area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); + rc = flash_area_open(area_id, &fap); + if (rc == 0) { + flash_area_erase(fap, 0, flash_area_get_size(fap)); + flash_area_close(fap); + } + + return rc; +} +#endif /* MCUBOOT_RAM_LOAD */ + + +/** + * Tries to load a slot for all the images with validation. + * + * @param state Boot loader status information. + * + * @return 0 on success; nonzero on failure. + */ +fih_ret +boot_load_and_validate_images(struct boot_loader_state *state) +{ + uint32_t active_slot; + int rc; + fih_ret fih_rc; + + /* Go over all the images and try to load one */ + IMAGES_ITER(BOOT_CURR_IMG(state)) { + /* All slots tried until a valid image found. Breaking from this loop + * means that a valid image found or already loaded. If no slot is + * found the function returns with error code. */ + while (true) { + /* Go over all the slots and try to load one */ + active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; + if (active_slot != NO_ACTIVE_SLOT){ + /* A slot is already active, go to next image. */ + break; + } + + active_slot = find_slot_with_highest_version(state); + if (active_slot == NO_ACTIVE_SLOT) { + BOOT_LOG_INF("No slot to load for image %d", + BOOT_CURR_IMG(state)); + FIH_RET(FIH_FAILURE); + } + + /* Save the number of the active slot. */ + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = active_slot; + +#if BOOT_IMAGE_NUMBER > 1 + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } +#endif + +#ifdef MCUBOOT_DIRECT_XIP + rc = boot_rom_address_check(state); + if (rc != 0) { + /* The image is placed in an unsuitable slot. */ + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false; + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + continue; + } + +#ifdef MCUBOOT_DIRECT_XIP_REVERT + rc = boot_select_or_erase(state); + if (rc != 0) { + /* The selected image slot has been erased. */ + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false; + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + continue; + } +#endif /* MCUBOOT_DIRECT_XIP_REVERT */ +#endif /* MCUBOOT_DIRECT_XIP */ + +#ifdef MCUBOOT_RAM_LOAD + /* Image is first loaded to RAM and authenticated there in order to + * prevent TOCTOU attack during image copy. This could be applied + * when loading images from external (untrusted) flash to internal + * (trusted) RAM and image is authenticated before copying. + */ + rc = boot_load_image_to_sram(state); + if (rc != 0 ) { + /* Image cannot be ramloaded. */ + boot_remove_image_from_flash(state, active_slot); + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false; + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + continue; + } +#endif /* MCUBOOT_RAM_LOAD */ + + FIH_CALL(boot_validate_slot, fih_rc, state, active_slot, NULL); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + /* Image is invalid. */ +#ifdef MCUBOOT_RAM_LOAD + boot_remove_image_from_sram(state); +#endif /* MCUBOOT_RAM_LOAD */ + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false; + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + continue; + } + + /* Valid image loaded from a slot, go to next image. */ + break; + } + } + + FIH_RET(FIH_SUCCESS); +} + +/** + * Updates the security counter for the current image. + * + * @param state Boot loader status information. + * + * @return 0 on success; nonzero on failure. + */ +static int +boot_update_hw_rollback_protection(struct boot_loader_state *state) +{ +#ifdef MCUBOOT_HW_ROLLBACK_PROT + int rc; + + /* Update the stored security counter with the newer (active) image's + * security counter value. + */ +#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT) + /* When the 'revert' mechanism is enabled in direct-xip mode, the + * security counter can be increased only after reboot, if the image + * has been confirmed at runtime (the image_ok flag has been set). + * This way a 'revert' can be performed when it's necessary. + */ + if (state->slot_usage[BOOT_CURR_IMG(state)].swap_state.image_ok == BOOT_FLAG_SET) { +#endif + rc = boot_update_security_counter(BOOT_CURR_IMG(state), + state->slot_usage[BOOT_CURR_IMG(state)].active_slot, + boot_img_hdr(state, state->slot_usage[BOOT_CURR_IMG(state)].active_slot)); + if (rc != 0) { + BOOT_LOG_ERR("Security counter update failed after image %d validation.", BOOT_CURR_IMG(state)); + return rc; + } +#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT) + } +#endif + + return 0; + +#else /* MCUBOOT_HW_ROLLBACK_PROT */ + (void) (state); + return 0; +#endif +} + +fih_ret +context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) +{ + int rc; + FIH_DECLARE(fih_rc, FIH_FAILURE); + + rc = boot_get_slot_usage(state); + if (rc != 0) { + goto out; + } + +#if (BOOT_IMAGE_NUMBER > 1) + while (true) { +#endif + FIH_CALL(boot_load_and_validate_images, fih_rc, state); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + +#if (BOOT_IMAGE_NUMBER > 1) + rc = boot_verify_dependencies(state); + if (rc != 0) { + /* Dependency check failed for an image, it has been removed from + * SRAM in case of MCUBOOT_RAM_LOAD strategy, and set to + * unavailable. Try to load an image from another slot. + */ + continue; + } + /* Dependency check was successful. */ + break; + } +#endif + + IMAGES_ITER(BOOT_CURR_IMG(state)) { +#if BOOT_IMAGE_NUMBER > 1 + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } +#endif + rc = boot_update_hw_rollback_protection(state); + if (rc != 0) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + rc = boot_add_shared_data(state, (uint8_t)state->slot_usage[BOOT_CURR_IMG(state)].active_slot); + if (rc != 0) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + } + + /* All image loaded successfully. */ +#ifdef MCUBOOT_HAVE_LOGGING + print_loaded_images(state); +#endif + + fill_rsp(state, rsp); + +out: + close_all_flash_areas(state); + + if (rc != 0) { + FIH_SET(fih_rc, FIH_FAILURE); + } + + FIH_RET(fih_rc); +} +#endif /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */ + +/** + * Prepares the booting process. This function moves images around in flash as + * appropriate, and tells you what address to boot from. + * + * @param rsp On success, indicates how booting should occur. + * + * @return FIH_SUCCESS on success; nonzero on failure. + */ +fih_ret +boot_go(struct boot_rsp *rsp) +{ + FIH_DECLARE(fih_rc, FIH_FAILURE); + + boot_state_clear(NULL); + + FIH_CALL(context_boot_go, fih_rc, &boot_data, rsp); + FIH_RET(fih_rc); +} + +/** + * Prepares the booting process, considering only a single image. This function + * moves images around in flash as appropriate, and tells you what address to + * boot from. + * + * @param rsp On success, indicates how booting should occur. + * + * @param image_id The image ID to prepare the boot process for. + * + * @return FIH_SUCCESS on success; nonzero on failure. + */ +fih_ret +boot_go_for_image_id(struct boot_rsp *rsp, uint32_t image_id) +{ + FIH_DECLARE(fih_rc, FIH_FAILURE); + + if (image_id >= BOOT_IMAGE_NUMBER) { + FIH_RET(FIH_FAILURE); + } + +#if BOOT_IMAGE_NUMBER > 1 + memset(&boot_data.img_mask, 1, BOOT_IMAGE_NUMBER); + boot_data.img_mask[image_id] = 0; +#endif + + FIH_CALL(context_boot_go, fih_rc, &boot_data, rsp); + FIH_RET(fih_rc); +} + +/** + * Clears the boot state, so that previous operations have no effect on new + * ones. + * + * @param state The state that should be cleared. If the value + * is NULL, the default bootloader state will be + * cleared. + */ +void boot_state_clear(struct boot_loader_state *state) +{ + if (state != NULL) { + memset(state, 0, sizeof(struct boot_loader_state)); + } else { + memset(&boot_data, 0, sizeof(struct boot_loader_state)); + } +} + +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +/** + * Reads image data to find out the maximum application sizes. Only needs to + * be called in serial recovery mode, as the state information is unpopulated + * at that time + */ +static void boot_fetch_slot_state_sizes(void) +{ + size_t slot; + int rc = -1; + int fa_id; + int image_index; + + IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) { + int max_size = 0; + + image_index = BOOT_CURR_IMG(&boot_data); + + BOOT_IMG(&boot_data, BOOT_PRIMARY_SLOT).sectors = + sector_buffers.primary[image_index]; + BOOT_IMG(&boot_data, BOOT_SECONDARY_SLOT).sectors = + sector_buffers.secondary[image_index]; +#if MCUBOOT_SWAP_USING_SCRATCH + boot_data.scratch.sectors = sector_buffers.scratch; +#endif + + /* Open primary and secondary image areas for the duration + * of this call. + */ + for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { + fa_id = flash_area_id_from_multi_image_slot(image_index, slot); + rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, slot)); + assert(rc == 0); + + if (rc != 0) { + goto finish; + } + } + +#if MCUBOOT_SWAP_USING_SCRATCH + rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, + &BOOT_SCRATCH_AREA(&boot_data)); + assert(rc == 0); + + if (rc != 0) { + goto finish; + } +#endif + + /* Determine the sector layout of the image slots and scratch area. */ + rc = boot_read_sectors_recovery(&boot_data); + + if (rc == 0) { + max_size = app_max_size(&boot_data); + + if (max_size > 0) { + image_max_sizes[image_index].calculated = true; + image_max_sizes[image_index].max_size = max_size; + } + } + } + +finish: + close_all_flash_areas(&boot_data); + memset(&boot_data, 0x00, sizeof(boot_data)); +} +#endif + +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) +/** + * Fetches the maximum allowed size of the image + */ +const struct image_max_size *boot_get_max_app_size(void) +{ +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) + uint8_t i = 0; + + while (i < BOOT_IMAGE_NUMBER) { + if (image_max_sizes[i].calculated == true) { + break; + } + + ++i; + } + + if (i == BOOT_IMAGE_NUMBER) { + /* Information not available, need to fetch it */ + boot_fetch_slot_state_sizes(); + } +#endif + + return image_max_sizes; +} +#endif diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 839dd12b3..293f6bd76 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -135,8 +135,18 @@ zephyr_library_sources( ) zephyr_library_include_directories(${BOOT_DIR}/bootutil/src) else() + if(NOT CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER EQUAL "-1") + # Sysbuild + zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/loader.c + ) + else() + # Legacy child/parent image + zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/loader_legacy_child_parent.c + ) + endif() zephyr_library_sources( - ${BOOT_DIR}/bootutil/src/loader.c ${BOOT_DIR}/bootutil/src/swap_misc.c ${BOOT_DIR}/bootutil/src/swap_scratch.c ${BOOT_DIR}/bootutil/src/swap_move.c diff --git a/boot/zephyr/include/sysflash/pm_sysflash_legacy_child_parent.h b/boot/zephyr/include/sysflash/pm_sysflash_legacy_child_parent.h new file mode 100644 index 000000000..db60ddd03 --- /dev/null +++ b/boot/zephyr/include/sysflash/pm_sysflash_legacy_child_parent.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef __PM_SYSFLASH_H__ +#define __PM_SYSFLASH_H__ +/* Blocking the __SYSFLASH_H__ */ +#define __SYSFLASH_H__ + +#include +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +extern uint32_t _image_1_primary_slot_id[]; +#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ + +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) + +#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ + +/* Each pair of slots is separated by , and there is no terminating character */ +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID + +#if (MCUBOOT_IMAGE_NUMBER == 1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 2) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 3) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS, \ + FLASH_AREA_IMAGE_2_SLOTS +#else +#error Unsupported number of images +#endif + +static inline uint32_t __flash_area_ids_for_slot(int img, int slot) +{ + static const int all_slots[] = { + ALL_AVAILABLE_SLOTS + }; + return all_slots[img * 2 + slot]; +}; + +#undef FLASH_AREA_IMAGE_0_SLOTS +#undef FLASH_AREA_IMAGE_1_SLOTS +#undef FLASH_AREA_IMAGE_2_SLOTS +#undef ALL_AVAILABLE_SLOTS + +#define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) +#define FLASH_AREA_IMAGE_SECONDARY(x) __flash_area_ids_for_slot(x, 1) + +#if !defined(CONFIG_BOOT_SWAP_USING_MOVE) +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID +#endif + +#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#endif /* __PM_SYSFLASH_H__ */ diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index f231c3d02..bee101b2e 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -7,7 +7,13 @@ #if USE_PARTITION_MANAGER /* Blocking the rest of the file */ #define __SYSFLASH_H__ +#if CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER != -1 +/* Sysbuild */ #include +#else +/* Legacy child/parent */ +#include +#endif #endif #ifndef __SYSFLASH_H__ From 78211ab58eb6b003416dc85effd2fe515ec5b53a Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Wed, 23 Oct 2024 16:48:13 +0200 Subject: [PATCH 062/287] [nrf noup] boards: Thingy:91 X release config Update the configuration files for the Thingy:91 X targets to the ones used in production. Signed-off-by: Maximilian Deubel (cherry picked from commit ae07a335ffb581a4d4dc43324bb0261e12728deb) (cherry picked from commit 0ab75e06ed7ce5ffc7b2790dfa2756180cb04abf) --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 3 +++ boot/zephyr/boards/thingy91x_nrf9151.conf | 6 +++++- boot/zephyr/boards/thingy91x_nrf9151.overlay | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 boot/zephyr/boards/thingy91x_nrf9151.overlay diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index 37c7e95b1..d3e253b65 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -58,3 +58,6 @@ CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y # Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n + +CONFIG_BOOT_SERIAL_NO_APPLICATION=y +CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 2efe1e170..7c2042de6 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -12,6 +12,10 @@ CONFIG_CONSOLE=n CONFIG_CONSOLE_HANDLER=n CONFIG_UART_CONSOLE=n CONFIG_MCUBOOT_SERIAL=y - CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y + +CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.overlay b/boot/zephyr/boards/thingy91x_nrf9151.overlay new file mode 100644 index 000000000..7f2818c0d --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf9151.overlay @@ -0,0 +1,4 @@ +&uart0 { + status = "okay"; + current-speed = < 1000000 >; +}; From 7058149cf30a37beb7b0a85bcad9a3cd00b14d1b Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Fri, 25 Oct 2024 09:37:44 +0200 Subject: [PATCH 063/287] [nrf noup] workflows: Add a backport workflow Enable backporting of PRs. Signed-off-by: Carles Cufi (cherry picked from commit 93f46457ec0dff360279e81a2840ee9dad8c8358) --- .github/workflows/backport.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 000000000..e986738ff --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,31 @@ +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + branches: + - main + +jobs: + backport: + name: Backport + runs-on: ubuntu-22.04 + # Only react to merged PRs for security reasons. + # See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target. + if: > + github.event.pull_request.merged && + ( + github.event.action == 'closed' || + ( + github.event.action == 'labeled' && + contains(github.event.label.name, 'backport') + ) + ) + steps: + - name: Backport + uses: zephyrproject-rtos/action-backport@v2.0.3-3 + with: + github_token: ${{ secrets.NCS_GITHUB_TOKEN }} + issue_labels: Backport + labels_template: '["Backport"]' From bd64752dfd68275f2927e46471f2ef0315ffe53a Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Thu, 7 Nov 2024 11:09:18 +0100 Subject: [PATCH 064/287] [nrf noup] boot/zephyr: add nrf54l15dk ext flash configs Moved configs from nrf54l15pdk. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 6b030d76a4575ebcc7e69eb15f6f967d1518a299) --- .../nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 15 ++++++ ...f54l15dk_nrf54l15_cpuapp_ext_flash.overlay | 47 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf new file mode 100644 index 000000000..8fc12e074 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -0,0 +1,15 @@ +CONFIG_MULTITHREADING=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_FLASH=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 +CONFIG_MAIN_STACK_SIZE=20480 +CONFIG_BOOT_MAX_IMG_SECTORS=512 +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +# Ensure that the qspi driver is disabled by default +CONFIG_NORDIC_QSPI_NOR=n + +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + +CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay new file mode 100644 index 000000000..60ee6fe51 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay @@ -0,0 +1,47 @@ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + zephyr,code-partition = &boot_partition; + }; +}; + +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; + +/delete-node/ &slot0_ns_partition; +/delete-node/ &slot1_ns_partition; + +/delete-node/ &storage_partition; + +&cpuapp_rram { + reg = < 0x0 DT_SIZE_K(1524) >; + partitions { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x000000000 0x00014000>; + }; + slot0_partition: partition@14000 { + label = "image-0"; + reg = <0x000014000 0x0015A000>; + }; + storage_partition: partition@16E000 { + label = "storage"; + reg = < 0x16E000 0x9000 >; + }; + }; +}; + +&mx25r64 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot1_partition: partition@0 { + label = "image-1"; + reg = <0x000000000 0x0015A000>; + }; + }; +}; From b8c46d575cd1ce57ba72c5b13c3e9f668fb76f6b Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 12 Nov 2024 14:49:28 +0000 Subject: [PATCH 065/287] [nrf fromlist] boot_serial: Support sha256, sha384 and sha512 Add support for reporting various sha in image list. There is always only one sha compiled in, but serial recovery has been previously hardcoded to support sha256 only. Upstream PR #: 2116 Signed-off-by: Dominik Ermel (cherry picked from commit bcdf6e24493a0c3de7c5f3a126a6b4075b2ad088) --- boot/boot_serial/src/boot_serial.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c index c324d7340..3891793e0 100644 --- a/boot/boot_serial/src/boot_serial.c +++ b/boot/boot_serial/src/boot_serial.c @@ -81,6 +81,17 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #define ARRAY_SIZE ZCBOR_ARRAY_SIZE #endif +#if defined(MCUBOOT_SHA512) + #define IMAGE_HASH_SIZE (64) + #define IMAGE_SHA_TLV IMAGE_TLV_SHA512 +#elif defined(MCUBOOT_SIGN_EC384) + #define IMAGE_HASH_SIZE (48) + #define IMAGE_SHA_TLV IMAGE_TLV_SHA384 +#else + #define IMAGE_HASH_SIZE (32) + #define IMAGE_SHA_TLV IMAGE_TLV_SHA256 +#endif + #ifndef MCUBOOT_SERIAL_MAX_RECEIVE_SIZE #define MCUBOOT_SERIAL_MAX_RECEIVE_SIZE 512 #endif @@ -91,7 +102,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #define BOOT_SERIAL_IMAGE_STATE_SIZE_MAX 0 #endif #ifdef MCUBOOT_SERIAL_IMG_GRP_HASH -#define BOOT_SERIAL_HASH_SIZE_MAX 36 +#define BOOT_SERIAL_HASH_SIZE_MAX (IMAGE_HASH_SIZE + 4) #else #define BOOT_SERIAL_HASH_SIZE_MAX 0 #endif @@ -263,7 +274,7 @@ bs_list(char *buf, int len) const struct flash_area *fap; uint8_t image_index; #ifdef MCUBOOT_SERIAL_IMG_GRP_HASH - uint8_t hash[32]; + uint8_t hash[IMAGE_HASH_SIZE]; #endif zcbor_map_start_encode(cbor_state, 1); @@ -336,7 +347,7 @@ bs_list(char *buf, int len) } #ifdef MCUBOOT_SERIAL_IMG_GRP_HASH - /* Retrieve SHA256 hash of image for identification */ + /* Retrieve hash of image for identification */ rc = boot_serial_get_hash(&hdr, fap, hash); #endif @@ -440,7 +451,7 @@ bs_set(char *buf, int len) */ uint8_t image_index = 0; size_t decoded = 0; - uint8_t hash[32]; + uint8_t hash[IMAGE_HASH_SIZE]; bool confirm; struct zcbor_string img_hash; bool ok; @@ -523,7 +534,7 @@ bs_set(char *buf, int len) } } - /* Retrieve SHA256 hash of image for identification */ + /* Retrieve hash of image for identification */ rc = boot_serial_get_hash(&hdr, fap, hash); flash_area_close(fap); @@ -1467,9 +1478,9 @@ static int boot_serial_get_hash(const struct image_header *hdr, break; } - if (type == IMAGE_TLV_SHA256) { + if (type == IMAGE_SHA_TLV) { /* Get the image's hash value from the manifest section. */ - if (len != 32) { + if (len != IMAGE_HASH_SIZE) { return -1; } From c8829648a3617e988a52a56b1d56b83c67438c38 Mon Sep 17 00:00:00 2001 From: Maciej Baczmanski Date: Thu, 28 Nov 2024 11:13:23 +0100 Subject: [PATCH 066/287] [nrf noup] Fix logging for ED25519_psa Log module has been declared but never registered. This commit fixes that by just registering the module. Signed-off-by: Maciej Baczmanski Co-authored-by: Marek Pieta (cherry picked from commit c6b9d8385481692bc435b3c2c130abe921cf6807) --- boot/bootutil/src/ed25519_psa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 3d7274307..e84b71d2a 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -13,7 +13,7 @@ #include #include -BOOT_LOG_MODULE_DECLARE(ed25519_psa); +BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define SHA512_DIGEST_LENGTH 64 #define EDDSA_KEY_LENGTH 32 From 534580bc1b170ef54658151c5e102ddaa7ff2922 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 20 Nov 2024 17:53:23 +0000 Subject: [PATCH 067/287] [nrf fromtree] zephyr: Add CONFIG_MCUBOOT_CLEANUP_RAM Add Kconfig option to cleanup RAM in MCUboot before passing control to an application. Signed-off-by: Dominik Ermel (cherry picked from commit 39aab3d87eed9073639d27c7dd30b7dc13495433) (cherry picked from commit 1c2a423f14c1bd7f57444c60fba400e008e56fea) --- boot/zephyr/Kconfig | 6 ++++++ boot/zephyr/main.c | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 34c6be3a4..7f36a45dc 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -222,6 +222,12 @@ config MCUBOOT_CLEANUP_ARM_CORE start-up code which can cause a module fault and potentially make the module irrecoverable. +config MCUBOOT_CLEANUP_RAM + bool "Perform RAM cleanup" + depends on CPU_CORTEX_M4 || CPU_CORTEX_M33 + help + Sets contents of memory to 0 before jumping to application. + config MBEDTLS_CFG_FILE default "mcuboot-mbedtls-cfg.h" diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 351ca4c89..fcc2606e2 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -271,7 +271,34 @@ static void do_boot(struct boot_rsp *rsp) __set_CONTROL(0x00); /* application will configures core on its own */ __ISB(); #endif +#if CONFIG_MCUBOOT_CLEANUP_RAM + __asm__ volatile ( + /* vt->reset -> r0 */ + " mov r0, %0\n" + /* base to write -> r1 */ + " mov r1, %1\n" + /* size to write -> r2 */ + " mov r2, %2\n" + /* value to write -> r3 */ + " mov r3, %3\n" + "clear:\n" + " str r3, [r1]\n" + " add r1, r1, #4\n" + " sub r2, r2, #4\n" + " cbz r2, out\n" + " b clear\n" + "out:\n" + " dsb\n" + /* jump to reset vector of an app */ + " bx r0\n" + : + : "r" (vt->reset), "i" (CONFIG_SRAM_BASE_ADDRESS), + "i" (CONFIG_SRAM_SIZE * 1024), "i" (0) + : "r0", "r1", "r2", "r3", "memory" + ); +#else ((void (*)(void))vt->reset)(); +#endif } #elif defined(CONFIG_XTENSA) || defined(CONFIG_RISCV) From 00f35bb1a4e0dd9f29cf9056674c28f72202fa4a Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 24 Jul 2024 17:00:04 +0000 Subject: [PATCH 068/287] [nrf noup] PSA configuration required changes Set of changes to Kconfig, CMakeLists.txt and some of headers that are required for the PSA support to compile. Signed-off-by: Dominik Ermel (cherry picked from commit 6400cc8188d3a4c03d9c4ac120bc4a46b1610d12) (cherry picked from commit 3cdcdb32f254248e6d2cd87dce09597723782562) (cherry picked from commit a47fccf72a1108707131126b8416d9daca41c046) --- boot/bootutil/zephyr/CMakeLists.txt | 14 +++-- boot/zephyr/CMakeLists.txt | 39 ++++++++---- boot/zephyr/Kconfig | 73 ++++++++++++++++++++++- boot/zephyr/include/mcuboot-mbedtls-cfg.h | 2 +- 4 files changed, 112 insertions(+), 16 deletions(-) diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index 72a6a8638..d5364d025 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -29,12 +29,18 @@ zephyr_library_link_libraries(MCUBOOT_BOOTUTIL) target_link_libraries(MCUBOOT_BOOTUTIL INTERFACE zephyr_interface) if(CONFIG_BOOT_USE_TINYCRYPT) -target_include_directories(MCUBOOT_BOOTUTIL INTERFACE - ../../../ext/tinycrypt/lib/include -) + target_include_directories(MCUBOOT_BOOTUTIL INTERFACE + ../../../ext/tinycrypt/lib/include + ) +endif() + +if(CONFIG_BOOT_USE_PSA_CRYPTO) + target_include_directories(MCUBOOT_BOOTUTIL INTERFACE + ${ZEPHYR_MBEDTLS_MODULE_DIR}/include + ) endif() -if(CONFIG_BOOT_USE_MBEDTLS) +if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO AND NOT CONFIG_PSA_CORE_OBERON) zephyr_link_libraries(mbedTLS) endif() endif() diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 293f6bd76..e01524221 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -51,6 +51,12 @@ if(EXISTS targets/${BOARD}.h) zephyr_library_compile_definitions(MCUBOOT_TARGET_CONFIG="${BOARD}.h") endif() +if(DEFINED CONFIG_MBEDTLS) + zephyr_library_include_directories( + ${ZEPHYR_MBEDTLS_MODULE_DIR}/include + ) +endif() + # Zephyr port-specific sources. zephyr_library_sources( main.c @@ -102,6 +108,10 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/fault_injection_hardening.c ) +if(DEFINED CONFIG_BOOT_ENCRYPT_X25519 AND DEFINED CONFIG_BOOT_ED25519_PSA) + zephyr_library_sources(${BOOT_DIR}/bootutil/src/encrypted_psa.c) +endif() + if(DEFINED CONFIG_MEASURED_BOOT OR DEFINED CONFIG_BOOT_SHARE_DATA) zephyr_library_sources( ${BOOT_DIR}/bootutil/src/boot_record.c @@ -246,19 +256,28 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) ${FIAT_DIR}/include/ ) - zephyr_library_sources( - ${FIAT_DIR}/src/curve25519.c - ) + if(NOT CONFIG_BOOT_ED25519_PSA) + zephyr_library_sources( + ${FIAT_DIR}/src/curve25519.c + ) + else() + zephyr_library_sources( + ${MBEDTLS_ASN1_DIR}/src/asn1parse.c + ${BOOT_DIR}/bootutil/src/ed25519_psa.c + ) + endif() endif() -if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) - zephyr_library_sources( - ${TINYCRYPT_DIR}/source/aes_encrypt.c - ${TINYCRYPT_DIR}/source/aes_decrypt.c - ${TINYCRYPT_DIR}/source/ctr_mode.c - ${TINYCRYPT_DIR}/source/hmac.c - ${TINYCRYPT_DIR}/source/ecc_dh.c +if(NOT CONFIG_BOOT_ED25519_PSA) + if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) + zephyr_library_sources( + ${TINYCRYPT_DIR}/source/aes_encrypt.c + ${TINYCRYPT_DIR}/source/aes_decrypt.c + ${TINYCRYPT_DIR}/source/ctr_mode.c + ${TINYCRYPT_DIR}/source/hmac.c + ${TINYCRYPT_DIR}/source/ecc_dh.c ) + endif() endif() if(CONFIG_BOOT_ENCRYPT_EC256) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 7f36a45dc..cb64488a5 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -29,7 +29,10 @@ config BOOT_USE_MBEDTLS config BOOT_USE_PSA_CRYPTO bool - # Hidden option + default y if NRF_SECURITY + # This is counter intuitive but that is how PSA heap is enabled. + select MBEDTLS_ENABLE_HEAP + select MBEDTLS_PSA_CRYPTO_C help Hidden option set if using PSA crypt for cryptography functionality @@ -66,6 +69,58 @@ config NRF_CC310_BL bool default n +if BOOT_USE_PSA_CRYPTO + +config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES + bool + default y if BOOT_IMG_HASH_ALG_SHA256 + select PSA_WANT_ALG_SHA_256 + help + Dependencies for hashing with SHA256 + +config BOOT_ED25519_PSA_DEPENDENCIES + bool + select PSA_WANT_ALG_SHA_256 + select PSA_WANT_ALG_SHA_512 + select PSA_WANT_ALG_PURE_EDDSA + select PSA_WANT_ECC_TWISTED_EDWARDS_255 + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + help + Dependencies for ed25519 signature + +if BOOT_ENCRYPT_IMAGE + +config BOOT_X25519_PSA_DEPENDENCIES + bool + select PSA_WANT_ALG_ECDH + select PSA_WANT_ALG_HMAC + select PSA_WANT_ALG_HKDF + select PSA_WANT_ALG_CTR + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + select PSA_WANT_KEY_TYPE_DERIVE + select PSA_WANT_KEY_TYPE_AES + select PSA_WANT_ECC_MONTGOMERY_255 + help + Dependencies for x25519 shared-random key encryption and AES + encryption. The PSA_WANT_ALG_CTR and PSA_WANT_KEY_TYPE_AES + enable Counter based block cipher and AES key, and algorithm support, + to use with it; the others are used for shared key decryption + and derivation. + +endif # BOOT_ENCRYPT_IMAGE + +if MBEDTLS_ENABLE_HEAP + +config MBEDTLS_HEAP_SIZE + default 2048 if BOOT_USE_PSA_CRYPTO + help + The PSA internals need to be able to allocate memory for operation + and it uses mbedTLS heap for that. + +endif # MBEDTLS_ENABLE_HEAP + +endif # BOOT_USE_PSA_CRYPTO + menu "MCUBoot settings" config SINGLE_APPLICATION_SLOT @@ -123,6 +178,7 @@ endchoice # BOOT_IMG_HASH_ALG choice BOOT_SIGNATURE_TYPE prompt "Signature type" + default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP default BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_NONE @@ -177,13 +233,24 @@ if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" default BOOT_ED25519_TINYCRYPT + config BOOT_ED25519_TINYCRYPT bool "Use tinycrypt" select BOOT_USE_TINYCRYPT + depends on !NRF_SECURITY + config BOOT_ED25519_MBEDTLS bool "Use mbedTLS" select BOOT_USE_MBEDTLS select MBEDTLS + depends on !NRF_SECURITY + +config BOOT_ED25519_PSA + bool "Use PSA crypto" + select BOOT_USE_PSA_CRYPTO + select BOOT_ED25519_PSA_DEPENDENCIES + select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE + endchoice endif @@ -228,9 +295,13 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +if MBEDTLS + config MBEDTLS_CFG_FILE default "mcuboot-mbedtls-cfg.h" +endif + config BOOT_HW_KEY bool "Use HW key for image verification" default n diff --git a/boot/zephyr/include/mcuboot-mbedtls-cfg.h b/boot/zephyr/include/mcuboot-mbedtls-cfg.h index 2bab537d7..a46fbb09f 100644 --- a/boot/zephyr/include/mcuboot-mbedtls-cfg.h +++ b/boot/zephyr/include/mcuboot-mbedtls-cfg.h @@ -23,7 +23,7 @@ #if defined(CONFIG_BOOT_SIGNATURE_TYPE_RSA) || defined(CONFIG_BOOT_ENCRYPT_RSA) #include "config-rsa.h" -#elif defined(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256) || \ +#elif defined(CONFIG_BOOT_USE_PSA_CRYPTO) || defined(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256) || \ defined(CONFIG_BOOT_ENCRYPT_EC256) || \ (defined(CONFIG_BOOT_ENCRYPT_X25519) && !defined(CONFIG_BOOT_SIGNATURE_TYPE_ED25519)) #include "config-asn1.h" From 5a6676cf392232b671cabb7dbf242d01f2ec5d6b Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 2 Aug 2024 15:55:13 +0000 Subject: [PATCH 069/287] [nrf noup] bootutil: Provide support for SHA512 with ED25519 Use SHA512 directly calculated over image with the ED25519 signature. Signed-off-by: Dominik Ermel (cherry picked from commit ccb95529b3b4fa2ba3c6a0f8d4ffe9b685cc0673) (cherry picked from commit 10211d4a68351be1a733248e8bee7be000ea41f1) (cherry picked from commit bb17cf717f2e63a2d1dc3c58ddaf743ccdbd0516) --- boot/zephyr/Kconfig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index cb64488a5..abb7bc2ae 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -80,7 +80,7 @@ config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES config BOOT_ED25519_PSA_DEPENDENCIES bool - select PSA_WANT_ALG_SHA_256 + select PSA_WANT_ALG_SHA_256 if BOOT_IMG_HASH_ALG_SHA256 select PSA_WANT_ALG_SHA_512 select PSA_WANT_ALG_PURE_EDDSA select PSA_WANT_ECC_TWISTED_EDWARDS_255 @@ -228,6 +228,11 @@ config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" select BOOT_ENCRYPTION_SUPPORT select BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_IMG_HASH_ALG_SHA512_ALLOW if BOOT_USE_PSA_CRYPTO + help + This is ed25519 signature calculated over SHA512 of SHA256 of application + image; that is not completely correct approach as the SHA512 should be + rather directly calculated over an image. if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION From b2ad117bd7cb645731625bf5ca574abf788110e2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 5 Sep 2024 10:53:17 +0000 Subject: [PATCH 070/287] [nrf noup] bootutil: Enable hash calculation directly on storage The commit add support for passing storage device address space to hash calculation functions, which allows to use hardware accelerated hash calculation on storage. This feature only works when image encryption is not enabled and all slots are defined within internal storage of device. The feature is enabled using Kconfig option CONFIG_BOOT_IMG_HASH_DIRECTLY_ON_STORAGE Signed-off-by: Dominik Ermel (cherry picked from commit 258b36998f7a400ae3b38d6d1b01f57722e2004b) (cherry picked from commit b4e5a3b2248d35605cf3b3cf9b51898738d443ae) (cherry picked from commit c7f14784e5b5465f116ab25254e4e8dd242d2d01) --- boot/bootutil/src/image_validate.c | 15 ++++++++++++--- boot/zephyr/Kconfig | 16 ++++++++++++++++ .../include/mcuboot_config/mcuboot_config.h | 7 +++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index b1a50f126..fa1d373d7 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -77,13 +77,15 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, uint8_t *seed, int seed_len) { bootutil_sha_context sha_ctx; - uint32_t blk_sz; uint32_t size; uint16_t hdr_size; - uint32_t off; - int rc; uint32_t blk_off; uint32_t tlv_off; +#if !defined(MCUBOOT_HASH_STORAGE_DIRECTLY) + int rc; + uint32_t off; + uint32_t blk_sz; +#endif #if (BOOT_IMAGE_NUMBER == 1) || !defined(MCUBOOT_ENC_IMAGES) || \ defined(MCUBOOT_RAM_LOAD) @@ -126,6 +128,12 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, /* If protected TLVs are present they are also hashed. */ size += hdr->ih_protect_tlv_size; +#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY + /* No chunk loading, storage is mapped to address space and can + * be directly given to hashing function. + */ + bootutil_sha_update(&sha_ctx, (void *)flash_area_get_off(fap), size); +#else /* MCUBOOT_HASH_STORAGE_DIRECTLY */ #ifdef MCUBOOT_RAM_LOAD bootutil_sha_update(&sha_ctx, (void*)(IMAGE_RAM_BASE + hdr->ih_load_addr), @@ -170,6 +178,7 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, bootutil_sha_update(&sha_ctx, tmp_buf, blk_sz); } #endif /* MCUBOOT_RAM_LOAD */ +#endif /* MCUBOOT_HASH_STORAGE_DIRECTLY */ bootutil_sha_finish(&sha_ctx, hash_result); bootutil_sha_drop(&sha_ctx); diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index abb7bc2ae..bb73e32f2 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -146,6 +146,22 @@ config BOOT_IMG_HASH_ALG_SHA512_ALLOW help Hidden option set by configurations that allow SHA512 +config BOOT_IMG_HASH_DIRECTLY_ON_STORAGE + bool "Hash calculation functions access storage through address space" + depends on !BOOT_ENCRYPT_IMAGE + help + When possible to map storage device, at least for read operations, + to address space or RAM area, enabling this option allows hash + calculation functions to directly access the storage through that address + space or using its own DMA. This reduces flash read overhead done + by the MCUboot. + Notes: + - not supported when encrypted images are in use, because calculating + SHA requires image to be decrypted first, which is done to RAM. + - currently only supported on internal storage of devices; this + option will not work with devices that use external storage for + either of image slots. + choice BOOT_IMG_HASH_ALG prompt "Selected image hash algorithm" default BOOT_IMG_HASH_ALG_SHA256 if BOOT_IMG_HASH_ALG_SHA256_ALLOW diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index f628f99c4..fbd64b5e7 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -140,6 +140,13 @@ #define MCUBOOT_DECOMPRESS_IMAGES #endif +/* Invoke hashing functions directly on storage. This requires for device + * to be able to map storage to address space or RAM. + */ +#ifdef CONFIG_BOOT_IMG_HASH_DIRECTLY_ON_STORAGE +#define MCUBOOT_HASH_STORAGE_DIRECTLY +#endif + #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From 1a2f5f68aad108cb79d91779e82c8f9ea1d1f594 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 6 Sep 2024 16:16:28 +0000 Subject: [PATCH 071/287] [nrf noup] bootutil: PureEdDSA using ED25519 The commit adds support for PureEdDSA, which validates signature of image rather than hash. This is most secure, available, ED25519 usage in MCUboot, but due to requirement of PureEdDSA to be able to calculate signature at whole message at once, here image, it only works on setups where entire image can be mapped to device address space, so that PSA functions calculating the signature can see the whole image at once. This option is enabled with Kconfig option: CONFIG_BOOT_SIGNATURE_TYPE_PURE when the ED25519 signature type is already selected. Note that the option will enable SHA512 for calculating public key hash. Signed-off-by: Dominik Ermel (cherry picked from commit d1b85af4e5a65a0e98b637c20f230d4bedda8808) (cherry picked from commit 81988f9d5f9b36f63067d7bd3ddb29e136175836) (cherry picked from commit 347b49e4a429d64aecdba9e43ad4647ad7abda6b) --- boot/bootutil/include/bootutil/image.h | 3 + boot/bootutil/src/bootutil_priv.h | 3 + boot/bootutil/src/image_ed25519.c | 37 ++++++++ boot/bootutil/src/image_validate.c | 95 +++++++++++++++++-- boot/zephyr/Kconfig | 29 +++++- .../include/mcuboot_config/mcuboot_config.h | 4 + 6 files changed, 163 insertions(+), 8 deletions(-) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 9ede800a2..05e04438b 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -102,6 +102,9 @@ struct flash_area; #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 */ diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index 208d189b9..c23f61689 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -268,6 +268,9 @@ struct boot_loader_state { fih_ret bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t key_id); +fih_ret bootutil_verify_img(const uint8_t *img, uint32_t size, + uint8_t *sig, size_t slen, uint8_t key_id); + fih_ret boot_fih_memequal(const void *s1, const void *s2, size_t n); int boot_find_status(int image_index, const struct flash_area **fap); diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 447289253..40d494bcf 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -109,4 +109,41 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, FIH_RET(fih_rc); } +fih_ret +bootutil_verify_img(const uint8_t *img, uint32_t size, + uint8_t *sig, size_t slen, uint8_t key_id) +{ + int rc; + FIH_DECLARE(fih_rc, FIH_FAILURE); + uint8_t *pubkey; + uint8_t *end; + + if (slen != EDDSA_SIGNATURE_LENGTH) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + pubkey = (uint8_t *)bootutil_keys[key_id].key; + end = pubkey + *bootutil_keys[key_id].len; + + rc = bootutil_import_key(&pubkey, end); + if (rc) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + rc = ED25519_verify(img, size, sig, pubkey); + + if (rc == 0) { + /* if verify returns 0, there was an error. */ + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + FIH_SET(fih_rc, FIH_SUCCESS); +out: + + FIH_RET(fih_rc); +} + #endif /* MCUBOOT_SIGN_ED25519 */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index fa1d373d7..c419b9497 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -65,6 +65,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil_priv.h" +#ifndef MCUBOOT_SIGN_PURE /* * Compute SHA hash over the image. * (SHA384 if ECDSA-P384 is being used, @@ -184,6 +185,7 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, return 0; } +#endif /* * Currently, we only support being able to verify one type of @@ -370,6 +372,43 @@ bootutil_get_img_security_cnt(struct image_header *hdr, return 0; } +#if defined(MCUBOOT_SIGN_PURE) +/* Returns: + * 0 -- found + * 1 -- not found or found but not true + * -1 -- failed for some reason + * + * Value of TLV does not matter, presence decides. + */ +static int bootutil_check_for_pure(const struct image_header *hdr, + const struct flash_area *fap) +{ + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_SIG_PURE, false); + if (rc) { + return rc; + } + + /* Search for the TLV */ + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + if (rc == 0 && len == 1) { + bool val; + + rc = LOAD_IMAGE_DATA(hdr, fap, off, &val, 1); + if (rc == 0) { + rc = !val; + } + } + + return rc; +} +#endif + + #ifndef ALLOW_ROGUE_TLVS /* * The following list of TLVs are the only entries allowed in the unprotected @@ -386,6 +425,9 @@ static const uint16_t allowed_unprot_tlvs[] = { IMAGE_TLV_ECDSA_SIG, IMAGE_TLV_RSA3072_PSS, IMAGE_TLV_ED25519, +#if defined(MCUBOOT_SIGN_PURE) + IMAGE_TLV_SIG_PURE, +#endif IMAGE_TLV_ENC_RSA2048, IMAGE_TLV_ENC_KW, IMAGE_TLV_ENC_EC256, @@ -408,7 +450,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, uint32_t off; uint16_t len; uint16_t type; - int image_hash_valid = 0; #ifdef EXPECTED_SIG_TLV FIH_DECLARE(valid_signature, FIH_FAILURE); #ifndef MCUBOOT_BUILTIN_KEY @@ -425,7 +466,10 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, #endif /* EXPECTED_SIG_TLV */ struct image_tlv_iter it; uint8_t buf[SIG_BUF_SIZE]; +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) + int image_hash_valid = 0; uint8_t hash[IMAGE_HASH_SIZE]; +#endif int rc = 0; FIH_DECLARE(fih_rc, FIH_FAILURE); #ifdef MCUBOOT_HW_ROLLBACK_PROT @@ -496,6 +540,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #endif +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); if (rc) { @@ -505,6 +550,15 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (out_hash) { memcpy(out_hash, hash, IMAGE_HASH_SIZE); } +#endif + +#if defined(MCUBOOT_SIGN_PURE) + /* If Pure type signature is expected then it has to be there */ + rc = bootutil_check_for_pure(hdr, fap); + if (rc != 0) { + goto out; + } +#endif rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); if (rc) { @@ -548,8 +602,10 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } } #endif - - if (type == EXPECTED_HASH_TLV) { + switch(type) { +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) + case EXPECTED_HASH_TLV: + { /* Verify the image hash. This must always be present. */ if (len != sizeof(hash)) { rc = -1; @@ -567,8 +623,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } image_hash_valid = 1; + break; + } +#endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ #ifdef EXPECTED_KEY_TLV - } else if (type == EXPECTED_KEY_TLV) { + case EXPECTED_KEY_TLV: + { /* * Determine which key we should be checking. */ @@ -593,9 +653,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, * The key may not be found, which is acceptable. There * can be multiple signatures, each preceded by a key. */ + break; + } #endif /* EXPECTED_KEY_TLV */ #ifdef EXPECTED_SIG_TLV - } else if (type == EXPECTED_SIG_TLV) { + case EXPECTED_SIG_TLV: + { /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; @@ -609,12 +672,25 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (rc) { goto out; } +#ifndef MCUBOOT_SIGN_PURE FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), buf, len, key_id); +#else + /* Directly check signature on the image, by using the mapping of + * a device to memory. The pointer is beginning of image in flash, + * so offset of area, the range is header + image + protected tlvs. + */ + FIH_CALL(bootutil_verify_img, valid_signature, (void *)flash_area_get_off(fap), + hdr->ih_hdr_size + hdr->ih_img_size + hdr->ih_protect_tlv_size, + buf, len, key_id); +#endif key_id = -1; + break; + } #endif /* EXPECTED_SIG_TLV */ #ifdef MCUBOOT_HW_ROLLBACK_PROT - } else if (type == IMAGE_TLV_SEC_CNT) { + case IMAGE_TLV_SEC_CNT: + { /* * Verify the image's security counter. * This must always be present. @@ -649,14 +725,21 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, /* The image's security counter has been successfully verified. */ security_counter_valid = fih_rc; + break; + } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ } } +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = !image_hash_valid; if (rc) { goto out; } +#elif defined(MCUBOOT_SIGN_PURE) + /* This returns true on EQ, rc is err on non-0 */ + rc = FIH_NOT_EQ(valid_signature, FIH_SUCCESS); +#endif #ifdef EXPECTED_SIG_TLV FIH_SET(fih_rc, valid_signature); #endif diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index bb73e32f2..6c5b88a87 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -192,6 +192,14 @@ config BOOT_IMG_HASH_ALG_SHA512 endchoice # BOOT_IMG_HASH_ALG +config BOOT_SIGNATURE_TYPE_PURE_ALLOW + bool + help + Hidden option set by configurations that allow Pure variant, + for example ed25519. The pure variant means that image + signature is calculated over entire image instead of hash + of an image. + choice BOOT_SIGNATURE_TYPE prompt "Signature type" default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP @@ -242,15 +250,32 @@ endif config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" - select BOOT_ENCRYPTION_SUPPORT - select BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_ENCRYPTION_SUPPORT if !BOOT_SIGNATURE_TYPE_PURE + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !BOOT_SIGNATURE_TYPE_PURE + # The SHA is used only for key hashing, not for images. select BOOT_IMG_HASH_ALG_SHA512_ALLOW if BOOT_USE_PSA_CRYPTO + select BOOT_SIGNATURE_TYPE_PURE_ALLOW help This is ed25519 signature calculated over SHA512 of SHA256 of application image; that is not completely correct approach as the SHA512 should be rather directly calculated over an image. + Select BOOT_SIGNATURE_TYPE_PURE to have a PureEdDSA calculating image + signature directly on image, rather than hash of the image. if BOOT_SIGNATURE_TYPE_ED25519 + +config BOOT_SIGNATURE_TYPE_PURE + bool "Use Pure signature of image" + depends on BOOT_SIGNATURE_TYPE_PURE_ALLOW + help + The Pure signature is calculated directly over image rather than + hash of an image. + This is more secure signature, specifically if hardware can do the + verification without need to share key. + Note that this requires that all slots for which signature is to be + verified need to be accessible through memory address space that + cryptography can access. + choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" default BOOT_ED25519_TINYCRYPT diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index fbd64b5e7..7896e0939 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -147,6 +147,10 @@ #define MCUBOOT_HASH_STORAGE_DIRECTLY #endif +#ifdef CONFIG_BOOT_SIGNATURE_TYPE_PURE +#define MCUBOOT_SIGN_PURE +#endif + #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From d09c5a0cdcc4e4a115d1a77f961a031598a93b5c Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 19 Sep 2024 14:32:37 +0200 Subject: [PATCH 072/287] [nrf noup] boot/zephyr/Kconfig: conditionally disable BOOT_MAX_IMG_SECTORS_AUTO Automatic calculation are based on DTS data which are no the right source on partition layout in case Partition manager does the partitioning. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Dominik Ermel (cherry picked from commit 12e9928b48a081a74a8b0688e6c310315de12f88) (cherry picked from commit a023c2e50989983cb7ffc1c822e44486d0722efe) (cherry picked from commit 7432f4aae9e9dcf082f4a82c82b198a639b6c065) --- boot/zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 6c5b88a87..29e4f0bb7 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -563,7 +563,7 @@ config BOOT_ENCRYPTION_KEY_FILE config BOOT_MAX_IMG_SECTORS_AUTO bool "Calculate maximum sectors automatically" - default y + default y if !PARTITION_MANAGER_ENABLED help If this option is enabled then the maximum number of supported sectors per image will be calculated automatically from the flash erase sizes and size of each partition for From 6e0c2b8794daa33d7688b35fc4af04c4d8052d41 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 20 Sep 2024 16:34:00 +0000 Subject: [PATCH 073/287] [nrf noup] bootutil: Add support for KMU stored ED25519 signature key The commit adds verification of image using keys stored in KMU. Signed-off-by: Dominik Ermel (cherry picked from commit 1dbca8ff9cd211b72d96ebda410ba83bea650c6f) (cherry picked from commit 40543f121d919566e580970c918aa6ae0aba615b) (cherry picked from commit 896a16e117f374a4622810b894b6cd34b1aa3eba) --- boot/bootutil/src/ed25519_psa.c | 51 ++++++++++++++++++++++++++++++ boot/bootutil/src/image_ed25519.c | 19 ++++++++--- boot/bootutil/src/image_validate.c | 6 ++++ boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 29 ++++++++++++++++- 5 files changed, 101 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index e84b71d2a..83fc692a1 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,6 +12,9 @@ #include #include +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#include +#endif BOOT_LOG_MODULE_REGISTER(ed25519_psa); @@ -19,6 +22,18 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define EDDSA_KEY_LENGTH 32 #define EDDSA_SIGNAGURE_LENGTH 64 +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +/* List of KMU stored key ids available for MCUboot */ +#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) +static psa_key_id_t kmu_key_ids[3] = { + MAKE_PSA_KMU_KEY_ID(226), + MAKE_PSA_KMU_KEY_ID(228), + MAKE_PSA_KMU_KEY_ID(230) +}; +#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) +#endif + +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -69,3 +84,39 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } +#else +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], + const uint8_t public_key[EDDSA_KEY_LENGTH]) +{ + ARG_UNUSED(public_key); + /* Set to any error */ + psa_status_t status = PSA_ERROR_BAD_STATE; + int ret = 0; /* Fail by default */ + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", status); + return 0; + } + + status = PSA_ERROR_BAD_STATE; + + for (int i = 0; i < KMU_KEY_COUNT; ++i) { + psa_key_id_t kid = kmu_key_ids[i]; + + status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, + message_len, signature, + EDDSA_SIGNAGURE_LENGTH); + if (status == PSA_SUCCESS) { + ret = 1; + break; + } + + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + } + + return ret; +} +#endif diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 40d494bcf..e6c792a99 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -25,14 +25,16 @@ #include "bootutil/crypto/sha.h" #define EDDSA_SIGNATURE_LENGTH 64 - -static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; #define NUM_ED25519_BYTES 32 extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) + +static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; + /* * Parse the public key used for signing. */ @@ -71,6 +73,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } +#endif fih_ret bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, @@ -78,14 +81,17 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey; + uint8_t *pubkey = NULL; +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) uint8_t *end; +#endif if (hlen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -94,6 +100,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, FIH_SET(fih_rc, FIH_FAILURE); goto out; } +#endif rc = ED25519_verify(hash, IMAGE_HASH_SIZE, sig, pubkey); @@ -115,14 +122,17 @@ bootutil_verify_img(const uint8_t *img, uint32_t size, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey; + uint8_t *pubkey = NULL; +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) uint8_t *end; +#endif if (slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -131,6 +141,7 @@ bootutil_verify_img(const uint8_t *img, uint32_t size, FIH_SET(fih_rc, FIH_FAILURE); goto out; } +#endif rc = ED25519_verify(img, size, sig, pubkey); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index c419b9497..f71d1d9a6 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -245,6 +245,7 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_HW_KEY) static int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) @@ -310,6 +311,7 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) } #endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ /** @@ -626,6 +628,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, break; } #endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { @@ -656,14 +659,17 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, break; } #endif /* EXPECTED_KEY_TLV */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index e01524221..3a3406465 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -313,7 +313,7 @@ if(CONFIG_MCUBOOT_SERIAL) endif() endif() -if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") +if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU AND NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") # CONF_FILE points to the KConfig configuration files of the bootloader. foreach (filepath ${CONF_FILE}) file(READ ${filepath} temp_text) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 29e4f0bb7..6b47e8240 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -293,6 +293,7 @@ config BOOT_ED25519_MBEDTLS config BOOT_ED25519_PSA bool "Use PSA crypto" + depends on NRF_SECURITY select BOOT_USE_PSA_CRYPTO select BOOT_ED25519_PSA_DEPENDENCIES select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE @@ -302,6 +303,22 @@ endif endchoice +config BOOT_SIGNATURE_USING_KMU + bool "Use KMU stored keys for signature verification" + depends on NRF_SECURITY + depends on CRACEN_LIB_KMU + select PSA_WANT_ALG_GCM + select PSA_WANT_KEY_TYPE_AES + select PSA_WANT_AES_KEY_SIZE_256 + select PSA_WANT_ALG_SP800_108_COUNTER_CMAC + select PSA_WANT_ALG_CMAC + select PSA_WANT_ALG_ECB_NO_PADDING + help + MCUboot will use keys provisioned to the device key management unit for signature + verification instead of compiling in key data from a file. + +if !BOOT_SIGNATURE_USING_KMU + config BOOT_SIGNATURE_KEY_FILE string "PEM key file" default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 @@ -319,6 +336,8 @@ config BOOT_SIGNATURE_KEY_FILE with the public key information will be written in a format expected by MCUboot. +endif + config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" depends on CPU_CORTEX_M @@ -341,10 +360,18 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +# Disable MBEDTLS from being selected if NRF_SECURITY is enabled, and use default NRF_SECURITY +# configuration file for MBEDTLS +config MBEDTLS + depends on !NRF_SECURITY + +config NRF_SECURITY + select MBEDTLS_PROMPTLESS + if MBEDTLS config MBEDTLS_CFG_FILE - default "mcuboot-mbedtls-cfg.h" + default "mcuboot-mbedtls-cfg.h" if !NRF_SECURITY endif From ff3c31fba7e8eb659d8505e9c635057a2ca53987 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Nov 2024 10:53:06 +0000 Subject: [PATCH 074/287] [nrf noup] boot: zephyr: Add experimental selection to compression Adds selecting the experimental Kconfig when compession is in use Signed-off-by: Jamie McCrae (cherry picked from commit b836582c3f7dccb16af500023644e38224fdddd8) Signed-off-by: Dominik Ermel (cherry picked from commit 36788a6584c0815976f5463efef2c796ebf80c2c) --- boot/zephyr/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 6b47e8240..fd089a661 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -956,9 +956,10 @@ config BOOT_DECOMPRESSION_SUPPORT if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION - bool "Decompression" + bool "Decompression [EXPERIMENTAL]" select NRF_COMPRESS_CLEANUP select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP + select EXPERIMENTAL help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to From eebb8abc831093d07978608a5ecd4e6fa18df920 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Mon, 2 Dec 2024 10:34:03 +0100 Subject: [PATCH 075/287] [nrf fromtree] boot: zephyr: boards: nrf54l10 and nrf54l05 configs adds default configs. Upstream PR #: 2133 Signed-off-by: Mateusz Michalek (cherry picked from commit 7cc60059845d4252773f538aa50e0906c34f7bd5) (cherry picked from commit be3292309d73d81eb88682fef12570a3d914eaff) --- boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf | 12 ++++++++++++ boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf | 12 ++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf new file mode 100644 index 000000000..1b7a3616d --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +CONFIG_FPROTECT=y + +CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf new file mode 100644 index 000000000..1b7a3616d --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +CONFIG_FPROTECT=y + +CONFIG_BOOT_WATCHDOG_FEED=n From 12e5ee106034972b0f1074d6f2261b2b39d1501b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 2 Dec 2024 10:51:41 +0000 Subject: [PATCH 076/287] [nrf noup] boot: bootutil: Allow configuring number of KMU keys Adds a new Kconfig CONFIG_BOOT_SIGNATURE_KMU_SLOTS which allows specifying how many KMU key IDs are supported, the default is set to 1 instead of 3 which was set before NCSDK-30743 Signed-off-by: Jamie McCrae (cherry picked from commit ed0fc24030f3765cfb04a8fdd8771bd5078107a7) --- boot/bootutil/src/ed25519_psa.c | 9 ++++++--- boot/zephyr/Kconfig | 12 ++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 83fc692a1..3042eeabf 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Nordic Semiconductor ASA + * Copyright (c) 2020-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ @@ -12,6 +12,7 @@ #include #include +#include #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #include #endif @@ -30,7 +31,9 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; -#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) + +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), + "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) @@ -103,7 +106,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < KMU_KEY_COUNT; ++i) { + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index fd089a661..77d57e15f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -317,6 +317,18 @@ config BOOT_SIGNATURE_USING_KMU MCUboot will use keys provisioned to the device key management unit for signature verification instead of compiling in key data from a file. +if BOOT_SIGNATURE_USING_KMU + +config BOOT_SIGNATURE_KMU_SLOTS + int "KMU key slots" + range 1 3 + default 1 + help + Selects the number of KMU key slots (also known as generations) to use when verifying + an image. + +endif + if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 03434241388ea62363ffcb6cf332b4fa7b88626b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 10 Dec 2024 08:16:22 +0000 Subject: [PATCH 077/287] [nrf noup] boot: bootutil: image_validate: Add KMU support to compression fixup! [nrf noup] bootutil: Add support for KMU stored ED25519 signature key This adds the additional code required so that the compression feature can be used with keys that reside in the KMU Signed-off-by: Jamie McCrae --- boot/bootutil/src/image_validate.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index f71d1d9a6..64983b318 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -815,7 +815,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #ifdef EXPECTED_SIG_TLV -#ifdef EXPECTED_KEY_TLV +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && defined(EXPECTED_KEY_TLV) rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); if (rc) { goto out; @@ -861,7 +861,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, */ } } -#endif /* EXPECTED_KEY_TLV */ +#endif /* !CONFIG_BOOT_SIGNATURE_USING_KMU && EXPECTED_KEY_TLV */ rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); if (rc) { @@ -884,10 +884,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; From b82206c15fff357c151c24bf97c99c4348d14a46 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 9 Dec 2024 12:27:38 +0000 Subject: [PATCH 078/287] [nrf noup] boot: zephyr: serial_recovery: Add nRF5340 Kconfig override Adds additional conditions that lets the direct upload option to be selected on nRF5340 to allow for uploading network core updates directly to the network core with the flash simulator Signed-off-by: Jamie McCrae --- boot/zephyr/Kconfig.serial_recovery | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index 7ed9a7d9c..3119edddc 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -47,9 +47,14 @@ config BOOT_SERIAL_CDC_ACM endchoice +DT_COMPAT_SIM_FLASH:= zephyr,sim-flash +DT_SIM_FLASH_PATH := $(dt_nodelabel_path,flash_sim0) + config MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD bool "Allow to select image number for DFU" - depends on !SINGLE_APPLICATION_SLOT + # Allow this option to be selected in cases where support for direct uploading to nRF5340 + # network core should be supported + depends on !SINGLE_APPLICATION_SLOT || (SINGLE_APPLICATION_SLOT && SOC_NRF5340_CPUAPP && BOOT_IMAGE_ACCESS_HOOK_NRF5340 && FLASH_SIMULATOR && $(dt_compat_enabled,$(DT_COMPAT_SIM_FLASH))) help With the option enabled, the mcuboot serial recovery will respect the "image" field in mcumgr image update frame From 0a910b600a3ddeffd941fa59359e373a29d63bf3 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 17 Dec 2024 15:54:01 +0100 Subject: [PATCH 079/287] [nrf noup] boot/zephyr/boards: configure fastest RRAM operations Configured CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 Which ensure the fastest bulk RRAM write operations. Signed-off-by: Andrzej Puzdrowski --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf index 8fc12e074..12650a9ed 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -13,3 +13,6 @@ CONFIG_NORDIC_QSPI_NOR=n CONFIG_FPROTECT=n CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 From 032d1921d6cec90cd127d0ae53822bb2a7a990af Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 17 Dec 2024 15:06:32 +0100 Subject: [PATCH 080/287] [nrf fromtree] boot/zephyr/boards: configure fastest RRAM operations Configured CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 Which ensure the fastest bulk RRAM write operations. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 3a33d4faceb86abb2229d4dd09486514df4fac43) --- boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf | 3 +++ boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf | 3 +++ boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf | 3 +++ 3 files changed, 9 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf index 1b7a3616d..f911aa248 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf @@ -10,3 +10,6 @@ CONFIG_SPI_NOR=n CONFIG_FPROTECT=y CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf index 1b7a3616d..f911aa248 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf @@ -10,3 +10,6 @@ CONFIG_SPI_NOR=n CONFIG_FPROTECT=y CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf index 8d8eb845f..1dbd7c1ab 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -11,3 +11,6 @@ CONFIG_SPI_NOR=n CONFIG_FPROTECT=n CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 From 1ddaca24bc79344580e97886256f6e1c8e1d12fa Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 5 Dec 2024 10:19:17 +0000 Subject: [PATCH 081/287] Revert "[nrf noup] treewide: Add child/parent image support back" fixup! [nrf noup] treewide: Add child/parent image support back This reverts commit d5aa2152b31cff8b58c232989850451e55773739. Signed-off-by: Jamie McCrae --- .../bootutil/src/loader_legacy_child_parent.c | 3896 ----------------- boot/zephyr/CMakeLists.txt | 12 +- .../pm_sysflash_legacy_child_parent.h | 100 - boot/zephyr/include/sysflash/sysflash.h | 6 - 4 files changed, 1 insertion(+), 4013 deletions(-) delete mode 100644 boot/bootutil/src/loader_legacy_child_parent.c delete mode 100644 boot/zephyr/include/sysflash/pm_sysflash_legacy_child_parent.h diff --git a/boot/bootutil/src/loader_legacy_child_parent.c b/boot/bootutil/src/loader_legacy_child_parent.c deleted file mode 100644 index 53f40c33a..000000000 --- a/boot/bootutil/src/loader_legacy_child_parent.c +++ /dev/null @@ -1,3896 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Copyright (c) 2016-2020 Linaro LTD - * Copyright (c) 2016-2019 JUUL Labs - * Copyright (c) 2019-2023 Arm Limited - * Copyright (c) 2024 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. - */ - -/** - * This file provides an interface to the boot loader. Functions defined in - * this file should only be called while the boot loader is running. - */ - -#include -#include -#include -#include -#include -#include "bootutil/bootutil.h" -#include "bootutil/bootutil_public.h" -#include "bootutil/image.h" -#include "bootutil_priv.h" -#include "swap_priv.h" -#include "bootutil/bootutil_log.h" -#include "bootutil/security_cnt.h" -#include "bootutil/boot_record.h" -#include "bootutil/fault_injection_hardening.h" -#include "bootutil/ramload.h" -#include "bootutil/boot_hooks.h" -#include "bootutil/mcuboot_status.h" - -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - -#ifdef __ZEPHYR__ -#include -#endif - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) -#include -#ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION -#include -int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); -#endif -#endif - -#ifdef MCUBOOT_ENC_IMAGES -#include "bootutil/enc_key.h" -#endif - -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) -#include -#endif - -#include "mcuboot_config/mcuboot_config.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot); - -static struct boot_loader_state boot_data; -#ifdef PM_S1_ADDRESS -static bool owner_nsib[BOOT_IMAGE_NUMBER] = {false}; -#endif - -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) -static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; -#endif - -#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ -defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) -#if !defined(__BOOTSIM__) -/* Used for holding static buffers in multiple functions to work around issues - * in older versions of gcc (e.g. 4.8.4) - */ -struct sector_buffer_t { - boot_sector_t primary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; - boot_sector_t secondary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; -#if MCUBOOT_SWAP_USING_SCRATCH - boot_sector_t scratch[BOOT_MAX_IMG_SECTORS]; -#endif -}; - -static struct sector_buffer_t sector_buffers; -#endif -#endif - -#if (BOOT_IMAGE_NUMBER > 1) -#define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x)) -#else -#define IMAGES_ITER(x) -#endif - -/* - * This macro allows some control on the allocation of local variables. - * When running natively on a target, we don't want to allocated huge - * variables on the stack, so make them global instead. For the simulator - * we want to run as many threads as there are tests, and it's safer - * to just make those variables stack allocated. - */ -#if !defined(__BOOTSIM__) -#define TARGET_STATIC static -#else -#define TARGET_STATIC -#endif - -#if BOOT_MAX_ALIGN > 1024 -#define BUF_SZ BOOT_MAX_ALIGN -#else -#define BUF_SZ 1024 -#endif - -#define NO_ACTIVE_SLOT UINT32_MAX - -static int -boot_read_image_headers(struct boot_loader_state *state, bool require_all, - struct boot_status *bs) -{ - int rc; - int i; - - for (i = 0; i < BOOT_NUM_SLOTS; i++) { - rc = BOOT_HOOK_CALL(boot_read_image_header_hook, BOOT_HOOK_REGULAR, - BOOT_CURR_IMG(state), i, boot_img_hdr(state, i)); - if (rc == BOOT_HOOK_REGULAR) - { - rc = boot_read_image_header(state, i, boot_img_hdr(state, i), bs); - } - if (rc != 0) { - /* If `require_all` is set, fail on any single fail, otherwise - * if at least the first slot's header was read successfully, - * then the boot loader can attempt a boot. - * - * Failure to read any headers is a fatal error. - */ -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. The primary slot of the second image - * (image 1) will not contain a valid image header until an upgrade - * of mcuboot has happened (filling S1 with the new version). - */ - if (BOOT_CURR_IMG(state) == 1 && i == 0) { - continue; - } -#endif /* PM_S1_ADDRESS */ - if (i > 0 && !require_all) { - return 0; - } else { - return rc; - } - } - } - - return 0; -} - -/** - * Saves boot status and shared data for current image. - * - * @param state Boot loader status information. - * @param active_slot Index of the slot will be loaded for current image. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_add_shared_data(struct boot_loader_state *state, - uint8_t active_slot) -{ -#if defined(MCUBOOT_MEASURED_BOOT) || defined(MCUBOOT_DATA_SHARING) - int rc; - -#ifdef MCUBOOT_MEASURED_BOOT - rc = boot_save_boot_status(BOOT_CURR_IMG(state), - boot_img_hdr(state, active_slot), - BOOT_IMG_AREA(state, active_slot)); - if (rc != 0) { - BOOT_LOG_ERR("Failed to add image data to shared area"); - return rc; - } -#endif /* MCUBOOT_MEASURED_BOOT */ - -#ifdef MCUBOOT_DATA_SHARING - rc = boot_save_shared_data(boot_img_hdr(state, active_slot), - BOOT_IMG_AREA(state, active_slot), - active_slot, image_max_sizes); - if (rc != 0) { - BOOT_LOG_ERR("Failed to add data to shared memory area."); - return rc; - } -#endif /* MCUBOOT_DATA_SHARING */ - - return 0; - -#else /* MCUBOOT_MEASURED_BOOT || MCUBOOT_DATA_SHARING */ - (void) (state); - (void) (active_slot); - - return 0; -#endif -} - -/** - * Fills rsp to indicate how booting should occur. - * - * @param state Boot loader status information. - * @param rsp boot_rsp struct to fill. - */ -static void -fill_rsp(struct boot_loader_state *state, struct boot_rsp *rsp) -{ - uint32_t active_slot; - -#if (BOOT_IMAGE_NUMBER > 1) - /* Always boot from the first enabled image. */ - BOOT_CURR_IMG(state) = 0; - IMAGES_ITER(BOOT_CURR_IMG(state)) { - if (!state->img_mask[BOOT_CURR_IMG(state)]) { - break; - } - } - /* At least one image must be active, otherwise skip the execution */ - if (BOOT_CURR_IMG(state) >= BOOT_IMAGE_NUMBER) { - return; - } -#endif - -#if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD) - active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; -#else - active_slot = BOOT_PRIMARY_SLOT; -#endif - - rsp->br_flash_dev_id = flash_area_get_device_id(BOOT_IMG_AREA(state, active_slot)); - rsp->br_image_off = boot_img_slot_off(state, active_slot); - rsp->br_hdr = boot_img_hdr(state, active_slot); -} - -/** - * Closes all flash areas. - * - * @param state Boot loader status information. - */ -static void -close_all_flash_areas(struct boot_loader_state *state) -{ - uint32_t slot; - - IMAGES_ITER(BOOT_CURR_IMG(state)) { -#if BOOT_IMAGE_NUMBER > 1 - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } -#endif -#if MCUBOOT_SWAP_USING_SCRATCH - flash_area_close(BOOT_SCRATCH_AREA(state)); -#endif - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { - flash_area_close(BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot)); - } - } -} - -#if (BOOT_IMAGE_NUMBER > 1) || \ - defined(MCUBOOT_DIRECT_XIP) || \ - defined(MCUBOOT_RAM_LOAD) || \ - defined(MCUBOOT_DOWNGRADE_PREVENTION) -/** - * Compare image version numbers - * - * By default, the comparison does not take build number into account. - * Enable MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER to take the build number into account. - * - * @param ver1 Pointer to the first image version to compare. - * @param ver2 Pointer to the second image version to compare. - * - * @retval -1 If ver1 is less than ver2. - * @retval 0 If the image version numbers are equal. - * @retval 1 If ver1 is greater than ver2. - */ -static int -boot_version_cmp(const struct image_version *ver1, - const struct image_version *ver2) -{ - if (ver1->iv_major > ver2->iv_major) { - return 1; - } - if (ver1->iv_major < ver2->iv_major) { - return -1; - } - /* The major version numbers are equal, continue comparison. */ - if (ver1->iv_minor > ver2->iv_minor) { - return 1; - } - if (ver1->iv_minor < ver2->iv_minor) { - return -1; - } - /* The minor version numbers are equal, continue comparison. */ - if (ver1->iv_revision > ver2->iv_revision) { - return 1; - } - if (ver1->iv_revision < ver2->iv_revision) { - return -1; - } - -#if defined(MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER) - /* The revisions are equal, continue comparison. */ - if (ver1->iv_build_num > ver2->iv_build_num) { - return 1; - } - if (ver1->iv_build_num < ver2->iv_build_num) { - return -1; - } -#endif - - return 0; -} -#endif - -#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ -defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) -static int -boot_initialize_area(struct boot_loader_state *state, int flash_area) -{ - uint32_t num_sectors = BOOT_MAX_IMG_SECTORS; - boot_sector_t *out_sectors; - uint32_t *out_num_sectors; - int rc; - - num_sectors = BOOT_MAX_IMG_SECTORS; - - if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) { - out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors; - out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors; - } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { - out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors; - out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors; -#if MCUBOOT_SWAP_USING_SCRATCH - } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) { - out_sectors = state->scratch.sectors; - out_num_sectors = &state->scratch.num_sectors; -#endif - } else { - return BOOT_EFLASH; - } - -#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS - rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors); -#else - _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed"); - rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors); -#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */ - if (rc != 0) { - return rc; - } - *out_num_sectors = num_sectors; - return 0; -} -#endif - -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) -static int -boot_read_sectors_recovery(struct boot_loader_state *state) -{ - uint8_t image_index; - int rc; - - image_index = BOOT_CURR_IMG(state); - - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index)); - if (rc != 0) { - return BOOT_EFLASH; - } - - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index)); - if (rc != 0) { - /* We need to differentiate from the primary image issue */ - return BOOT_EFLASH_SEC; - } - - return 0; -} -#endif - - -#if (BOOT_IMAGE_NUMBER > 1) - -static int -boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot); - -/** - * Check the image dependency whether it is satisfied and modify - * the swap type if necessary. - * - * @param dep Image dependency which has to be verified. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_verify_slot_dependency(struct boot_loader_state *state, - struct image_dependency *dep) -{ - struct image_version *dep_version; - size_t dep_slot; - int rc; - - /* Determine the source of the image which is the subject of - * the dependency and get it's version. */ -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) - uint8_t swap_type = state->swap_type[dep->image_id]; - dep_slot = BOOT_IS_UPGRADE(swap_type) ? BOOT_SECONDARY_SLOT - : BOOT_PRIMARY_SLOT; -#else - dep_slot = state->slot_usage[dep->image_id].active_slot; -#endif - - dep_version = &state->imgs[dep->image_id][dep_slot].hdr.ih_ver; - - rc = boot_version_cmp(dep_version, &dep->image_min_version); -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) - if (rc < 0) { - /* Dependency not satisfied. - * Modify the swap type to decrease the version number of the image - * (which will be located in the primary slot after the boot process), - * consequently the number of unsatisfied dependencies will be - * decreased or remain the same. - */ - switch (BOOT_SWAP_TYPE(state)) { - case BOOT_SWAP_TYPE_TEST: - case BOOT_SWAP_TYPE_PERM: - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; - break; - case BOOT_SWAP_TYPE_NONE: - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT; - break; - default: - break; - } - } else { - /* Dependency satisfied. */ - rc = 0; - } -#else - if (rc >= 0) { - /* Dependency satisfied. */ - rc = 0; - } -#endif - - return rc; -} - -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) -/** - * Iterate over all the images and verify whether the image dependencies in the - * TLV area are all satisfied and update the related swap type if necessary. - */ -static int -boot_verify_dependencies(struct boot_loader_state *state) -{ - int rc = -1; - uint8_t slot; - - BOOT_CURR_IMG(state) = 0; - while (BOOT_CURR_IMG(state) < BOOT_IMAGE_NUMBER) { - if (state->img_mask[BOOT_CURR_IMG(state)]) { - BOOT_CURR_IMG(state)++; - continue; - } - if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE && - BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_FAIL) { - slot = BOOT_SECONDARY_SLOT; - } else { - slot = BOOT_PRIMARY_SLOT; - } - - rc = boot_verify_slot_dependencies(state, slot); - if (rc == 0) { - /* All dependencies've been satisfied, continue with next image. */ - BOOT_CURR_IMG(state)++; - } else if (rc == BOOT_EBADIMAGE) { - /* Cannot upgrade due to non-met dependencies, so disable all - * image upgrades. - */ - for (int idx = 0; idx < BOOT_IMAGE_NUMBER; idx++) { - BOOT_CURR_IMG(state) = idx; - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; - } - break; - } else { - /* Other error happened, images are inconsistent */ - return rc; - } - } - return rc; -} -#else - -#if defined MCUBOOT_RAM_LOAD -static inline int -boot_remove_image_from_sram(struct boot_loader_state *state); -#endif - -/** - * Checks the dependency of all the active slots. If an image found with - * invalid or not satisfied dependencies the image is removed from SRAM (in - * case of MCUBOOT_RAM_LOAD strategy) and its slot is set to unavailable. - * - * @param state Boot loader status information. - * - * @return 0 if dependencies are met; nonzero otherwise. - */ -static int -boot_verify_dependencies(struct boot_loader_state *state) -{ - int rc = -1; - uint32_t active_slot; - - IMAGES_ITER(BOOT_CURR_IMG(state)) { - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } - active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; - rc = boot_verify_slot_dependencies(state, active_slot); - if (rc != 0) { - /* Dependencies not met or invalid dependencies. */ - -#ifdef MCUBOOT_RAM_LOAD - boot_remove_image_from_sram(state); -#endif /* MCUBOOT_RAM_LOAD */ - - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - - return rc; - } - } - - return rc; -} -#endif - -/** - * Read all dependency TLVs of an image from the flash and verify - * one after another to see if they are all satisfied. - * - * @param slot Image slot number. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) -{ - const struct flash_area *fap; - struct image_tlv_iter it; - struct image_dependency dep; - uint32_t off; - uint16_t len; - int area_id; - int rc; - - area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); - rc = flash_area_open(area_id, &fap); - if (rc != 0) { - rc = BOOT_EFLASH; - goto done; - } - - rc = bootutil_tlv_iter_begin(&it, boot_img_hdr(state, slot), fap, - IMAGE_TLV_DEPENDENCY, true); - if (rc != 0) { - goto done; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - if (rc < 0) { - return -1; - } else if (rc > 0) { - rc = 0; - break; - } - - if (len != sizeof(dep)) { - rc = BOOT_EBADIMAGE; - goto done; - } - - rc = LOAD_IMAGE_DATA(boot_img_hdr(state, slot), - fap, off, &dep, len); - if (rc != 0) { - rc = BOOT_EFLASH; - goto done; - } - - if (dep.image_id >= BOOT_IMAGE_NUMBER) { - rc = BOOT_EBADARGS; - goto done; - } - - /* Verify dependency and modify the swap type if not satisfied. */ - rc = boot_verify_slot_dependency(state, &dep); - if (rc != 0) { - /* Dependency not satisfied */ - goto done; - } - } - -done: - flash_area_close(fap); - return rc; -} - -#endif /* (BOOT_IMAGE_NUMBER > 1) */ - -#if !defined(MCUBOOT_DIRECT_XIP) -/* - * Compute the total size of the given image. Includes the size of - * the TLVs. - */ -#if !defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_OVERWRITE_ONLY_FAST) -static int -boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) -{ - const struct flash_area *fap; - struct image_tlv_info info; - uint32_t off; - uint32_t protect_tlv_size; - int area_id; - int rc; - -#if (BOOT_IMAGE_NUMBER == 1) - (void)state; -#endif - - area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); - rc = flash_area_open(area_id, &fap); - if (rc != 0) { - rc = BOOT_EFLASH; - goto done; - } - -#ifdef MCUBOOT_DECOMPRESS_IMAGES - if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { - uint32_t tmp_size = 0; - - rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); - - if (rc) { - rc = BOOT_EBADIMAGE; - goto done; - } - - off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; - - rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); - - if (rc) { - rc = BOOT_EBADIMAGE; - goto done; - } - - off += tmp_size; - - if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + - boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, - sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } - - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; - } - - *size = off + info.it_tlv_tot; - } else { -#else - if (1) { -#endif - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); - - if (flash_area_read(fap, off, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } - - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { - rc = BOOT_EBADIMAGE; - goto done; - } - - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; - } - - *size = off + protect_tlv_size + info.it_tlv_tot; - } - - rc = 0; - -done: - flash_area_close(fap); - return rc; -} -#endif /* !MCUBOOT_OVERWRITE_ONLY */ - -#if !defined(MCUBOOT_RAM_LOAD) -static uint32_t -boot_write_sz(struct boot_loader_state *state) -{ - uint32_t elem_sz; -#if MCUBOOT_SWAP_USING_SCRATCH - uint32_t align; -#endif - - /* Figure out what size to write update status update as. The size depends - * on what the minimum write size is for scratch area, active image slot. - * We need to use the bigger of those 2 values. - */ - elem_sz = flash_area_align(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); -#if MCUBOOT_SWAP_USING_SCRATCH - align = flash_area_align(BOOT_SCRATCH_AREA(state)); - if (align > elem_sz) { - elem_sz = align; - } -#endif - - return elem_sz; -} - -/** - * Determines the sector layout of both image slots and the scratch area. - * This information is necessary for calculating the number of bytes to erase - * and copy during an image swap. The information collected during this - * function is used to populate the state. - */ -static int -boot_read_sectors(struct boot_loader_state *state) -{ - uint8_t image_index; - int rc; - - image_index = BOOT_CURR_IMG(state); - - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index)); - if (rc != 0) { - return BOOT_EFLASH; - } - - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index)); - if (rc != 0) { - /* We need to differentiate from the primary image issue */ - return BOOT_EFLASH_SEC; - } - -#if MCUBOOT_SWAP_USING_SCRATCH - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SCRATCH); - if (rc != 0) { - return BOOT_EFLASH; - } -#endif - - BOOT_WRITE_SZ(state) = boot_write_sz(state); - - return 0; -} - -void -boot_status_reset(struct boot_status *bs) -{ -#ifdef MCUBOOT_ENC_IMAGES - memset(&bs->enckey, 0xff, BOOT_NUM_SLOTS * BOOT_ENC_KEY_ALIGN_SIZE); -#if MCUBOOT_SWAP_SAVE_ENCTLV - memset(&bs->enctlv, 0xff, BOOT_NUM_SLOTS * BOOT_ENC_TLV_ALIGN_SIZE); -#endif -#endif /* MCUBOOT_ENC_IMAGES */ - - bs->use_scratch = 0; - bs->swap_size = 0; - bs->source = 0; - - bs->op = BOOT_STATUS_OP_MOVE; - bs->idx = BOOT_STATUS_IDX_0; - bs->state = BOOT_STATUS_STATE_0; - bs->swap_type = BOOT_SWAP_TYPE_NONE; -} - -bool -boot_status_is_reset(const struct boot_status *bs) -{ - return (bs->op == BOOT_STATUS_OP_MOVE && - bs->idx == BOOT_STATUS_IDX_0 && - bs->state == BOOT_STATUS_STATE_0); -} - -/** - * Writes the supplied boot status to the flash file system. The boot status - * contains the current state of an in-progress image copy operation. - * - * @param bs The boot status to write. - * - * @return 0 on success; nonzero on failure. - */ -int -boot_write_status(const struct boot_loader_state *state, struct boot_status *bs) -{ - const struct flash_area *fap; - uint32_t off; - int area_id; - int rc = 0; - uint8_t buf[BOOT_MAX_ALIGN]; - uint32_t align; - uint8_t erased_val; - - /* NOTE: The first sector copied (that is the last sector on slot) contains - * the trailer. Since in the last step the primary slot is erased, the - * first two status writes go to the scratch which will be copied to - * the primary slot! - */ - -#if MCUBOOT_SWAP_USING_SCRATCH - if (bs->use_scratch) { - /* Write to scratch. */ - area_id = FLASH_AREA_IMAGE_SCRATCH; - } else { -#endif - /* Write to the primary slot. */ - area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state)); -#if MCUBOOT_SWAP_USING_SCRATCH - } -#endif - - rc = flash_area_open(area_id, &fap); - if (rc != 0) { - return BOOT_EFLASH; - } - - off = boot_status_off(fap) + - boot_status_internal_off(bs, BOOT_WRITE_SZ(state)); - align = flash_area_align(fap); - erased_val = flash_area_erased_val(fap); - memset(buf, erased_val, BOOT_MAX_ALIGN); - buf[0] = bs->state; - - BOOT_LOG_DBG("writing swap status; fa_id=%d off=0x%lx (0x%lx)", - flash_area_get_id(fap), (unsigned long)off, - (unsigned long)flash_area_get_off(fap) + off); - - rc = flash_area_write(fap, off, buf, align); - if (rc != 0) { - rc = BOOT_EFLASH; - } - - flash_area_close(fap); - - return rc; -} -#endif /* !MCUBOOT_RAM_LOAD */ -#endif /* !MCUBOOT_DIRECT_XIP */ - -/* - * Validate image hash/signature and optionally the security counter in a slot. - */ -static fih_ret -boot_image_check(struct boot_loader_state *state, struct image_header *hdr, - const struct flash_area *fap, struct boot_status *bs) -{ - TARGET_STATIC uint8_t tmpbuf[BOOT_TMPBUF_SZ]; - int rc; - FIH_DECLARE(fih_rc, FIH_FAILURE); - -#if (BOOT_IMAGE_NUMBER == 1) - (void)state; -#endif - - (void)bs; - (void)rc; - -/* In the case of ram loading the image has already been decrypted as it is - * decrypted when copied in ram */ -#if defined(MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_RAM_LOAD) - if (MUST_DECRYPT(fap, BOOT_CURR_IMG(state), hdr)) { - rc = boot_enc_load(BOOT_CURR_ENC(state), 1, hdr, fap, bs); - if (rc < 0) { - FIH_RET(fih_rc); - } - if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) { - FIH_RET(fih_rc); - } - } -#endif - - FIH_CALL(bootutil_img_validate, fih_rc, BOOT_CURR_ENC(state), - BOOT_CURR_IMG(state), hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, - NULL, 0, NULL); - - FIH_RET(fih_rc); -} - -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) -static fih_ret -split_image_check(struct image_header *app_hdr, - const struct flash_area *app_fap, - struct image_header *loader_hdr, - const struct flash_area *loader_fap) -{ - static void *tmpbuf; - uint8_t loader_hash[32]; - FIH_DECLARE(fih_rc, FIH_FAILURE); - - if (!tmpbuf) { - tmpbuf = malloc(BOOT_TMPBUF_SZ); - if (!tmpbuf) { - goto out; - } - } - - FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, loader_hdr, loader_fap, - tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, loader_hash); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - FIH_RET(fih_rc); - } - - FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, app_hdr, app_fap, - tmpbuf, BOOT_TMPBUF_SZ, loader_hash, 32, NULL); - -out: - FIH_RET(fih_rc); -} -#endif /* !MCUBOOT_DIRECT_XIP && !MCUBOOT_RAM_LOAD */ - -/* - * Check that this is a valid header. Valid means that the magic is - * correct, and that the sizes/offsets are "sane". Sane means that - * there is no overflow on the arithmetic, and that the result fits - * within the flash area we are in. Also check the flags in the image - * and class the image as invalid if flags for encryption/compression - * are present but these features are not enabled. - */ -static bool -boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fap, - struct boot_loader_state *state) -{ - uint32_t size; - - (void)state; - - if (hdr->ih_magic != IMAGE_MAGIC) { - return false; - } - - if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size)) { - return false; - } - -#ifdef MCUBOOT_DECOMPRESS_IMAGES - if (!MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { -#else - if (1) { -#endif - if (!boot_u32_safe_add(&size, size, hdr->ih_protect_tlv_size)) { - return false; - } - } - - if (size >= flash_area_get_size(fap)) { - return false; - } - -#if !defined(MCUBOOT_ENC_IMAGES) - if (IS_ENCRYPTED(hdr)) { - return false; - } -#else - if ((hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) && - (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256)) - { - return false; - } -#endif - -#if !defined(MCUBOOT_DECOMPRESS_IMAGES) - if (IS_COMPRESSED(hdr)) { - return false; - } -#else - if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { - if (!boot_is_compressed_header_valid(hdr, fap, state)) { - return false; - } - } -#endif - - return true; -} - -/* - * Check that a memory area consists of a given value. - */ -static inline bool -boot_data_is_set_to(uint8_t val, void *data, size_t len) -{ - uint8_t i; - uint8_t *p = (uint8_t *)data; - for (i = 0; i < len; i++) { - if (val != p[i]) { - return false; - } - } - return true; -} - -static int -boot_check_header_erased(struct boot_loader_state *state, int slot) -{ - const struct flash_area *fap; - struct image_header *hdr; - uint8_t erased_val; - int area_id; - int rc; - - area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); - rc = flash_area_open(area_id, &fap); - if (rc != 0) { - return -1; - } - - erased_val = flash_area_erased_val(fap); - flash_area_close(fap); - - hdr = boot_img_hdr(state, slot); - if (!boot_data_is_set_to(erased_val, &hdr->ih_magic, sizeof(hdr->ih_magic))) { - return -1; - } - - return 0; -} - -#if defined(MCUBOOT_DIRECT_XIP) -/** - * Check if image in slot has been set with specific ROM address to run from - * and whether the slot starts at that address. - * - * @returns 0 if IMAGE_F_ROM_FIXED flag is not set; - * 0 if IMAGE_F_ROM_FIXED flag is set and ROM address specified in - * header matches the slot address; - * 1 if IMF_F_ROM_FIXED flag is set but ROM address specified in header - * does not match the slot address. - */ -static bool -boot_rom_address_check(struct boot_loader_state *state) -{ - uint32_t active_slot; - const struct image_header *hdr; - uint32_t f_off; - - active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; - hdr = boot_img_hdr(state, active_slot); - f_off = boot_img_slot_off(state, active_slot); - - if (hdr->ih_flags & IMAGE_F_ROM_FIXED && hdr->ih_load_addr != f_off) { - BOOT_LOG_WRN("Image in %s slot at 0x%x has been built for offset 0x%x"\ - ", skipping", - active_slot == 0 ? "primary" : "secondary", f_off, - hdr->ih_load_addr); - - /* If there is address mismatch, the image is not bootable from this - * slot. - */ - return 1; - } - return 0; -} -#endif - -/* - * Check that there is a valid image in a slot - * - * @returns - * FIH_SUCCESS if image was successfully validated - * FIH_NO_BOOTABLE_IMAGE if no bootloable image was found - * FIH_FAILURE on any errors - */ -static fih_ret -boot_validate_slot(struct boot_loader_state *state, int slot, - struct boot_status *bs) -{ - const struct flash_area *fap; - struct image_header *hdr; - int area_id; - FIH_DECLARE(fih_rc, FIH_FAILURE); - int rc; - - area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); - rc = flash_area_open(area_id, &fap); - if (rc != 0) { - FIH_RET(fih_rc); - } - - hdr = boot_img_hdr(state, slot); - if (boot_check_header_erased(state, slot) == 0 || - (hdr->ih_flags & IMAGE_F_NON_BOOTABLE)) { - -#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) - /* - * This fixes an issue where an image might be erased, but a trailer - * be left behind. It can happen if the image is in the secondary slot - * and did not pass validation, in which case the whole slot is erased. - * If during the erase operation, a reset occurs, parts of the slot - * might have been erased while some did not. The concerning part is - * the trailer because it might disable a new image from being loaded - * through mcumgr; so we just get rid of the trailer here, if the header - * is erased. - */ - if (slot != BOOT_PRIMARY_SLOT) { - swap_erase_trailer_sectors(state, fap); - } -#endif - - /* No bootable image in slot; continue booting from the primary slot. */ - fih_rc = FIH_NO_BOOTABLE_IMAGE; - goto out; - } - -#if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION) - if (slot != BOOT_PRIMARY_SLOT) { - /* Check if version of secondary slot is sufficient */ - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ - && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) - if (BOOT_CURR_IMG(state) == 1) { - rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); - } else { - rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); - } -#else - rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); -#endif - if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { - BOOT_LOG_ERR("insufficient version in secondary slot"); - flash_area_erase(fap, 0, flash_area_get_size(fap)); - /* Image in the secondary slot does not satisfy version requirement. - * Erase the image and continue booting from the primary slot. - */ - fih_rc = FIH_NO_BOOTABLE_IMAGE; - goto out; - } - } -#endif - if (!boot_is_header_valid(hdr, fap, state)) { - fih_rc = FIH_FAILURE; - } else { - BOOT_HOOK_CALL_FIH(boot_image_check_hook, FIH_BOOT_HOOK_REGULAR, - fih_rc, BOOT_CURR_IMG(state), slot); - if (FIH_EQ(fih_rc, FIH_BOOT_HOOK_REGULAR)) { - FIH_CALL(boot_image_check, fih_rc, state, hdr, fap, bs); - } - } - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - if ((slot != BOOT_PRIMARY_SLOT) || ARE_SLOTS_EQUIVALENT()) { - flash_area_erase(fap, 0, flash_area_get_size(fap)); - /* Image is invalid, erase it to prevent further unnecessary - * attempts to validate and boot it. - */ - } - -#if !defined(__BOOTSIM__) - BOOT_LOG_ERR("Image in the %s slot is not valid!", - (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); -#endif - fih_rc = FIH_NO_BOOTABLE_IMAGE; - goto out; - } - -#if MCUBOOT_IMAGE_NUMBER > 1 && !defined(MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_VERIFY_IMG_ADDRESS) - /* Verify that the image in the secondary slot has a reset address - * located in the primary slot. This is done to avoid users incorrectly - * overwriting an application written to the incorrect slot. - * This feature is only supported by ARM platforms. - */ -#if MCUBOOT_IMAGE_NUMBER >= 3 - /* Currently the MCUboot can be configured for up to 3 image, where image number 2 is - * designated for XIP, where it is the second part of image stored in slots of image - * 0. This part of image is not bootable, as the XIP setup is done by the app in - * image 0 slot, and it does not carry the reset vector. - */ - if (area_id == FLASH_AREA_IMAGE_SECONDARY(2)) { - goto out; - } -#endif - if (area_id == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { - const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); - struct image_header *secondary_hdr = boot_img_hdr(state, slot); - uint32_t reset_value = 0; - uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); - - rc = flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)); - if (rc != 0) { - fih_rc = FIH_NO_BOOTABLE_IMAGE; - goto out; - } - - uint32_t min_addr, max_addr; - -#ifdef PM_CPUNET_APP_ADDRESS - /* The primary slot for the network core is emulated in RAM. - * Its flash_area hasn't got relevant boundaries. - * Therfore need to override its boundaries for the check. - */ - if (BOOT_CURR_IMG(state) == 1) { - min_addr = PM_CPUNET_APP_ADDRESS; - max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; -#ifdef PM_S1_ADDRESS - } else if (BOOT_CURR_IMG(state) == 0) { - min_addr = PM_S0_ADDRESS; - max_addr = pri_fa->fa_off + pri_fa->fa_size; -#endif - } else -#endif - { - min_addr = pri_fa->fa_off; - max_addr = pri_fa->fa_off + pri_fa->fa_size; - } - - if (reset_value < min_addr || reset_value> (max_addr)) { - BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); - BOOT_LOG_ERR("Erasing image from secondary slot"); - - /* The vector table in the image located in the secondary - * slot does not target the primary slot. This might - * indicate that the image was loaded to the wrong slot. - * - * Erase the image and continue booting from the primary slot. - */ - flash_area_erase(fap, 0, fap->fa_size); - fih_rc = FIH_NO_BOOTABLE_IMAGE; - goto out; - } - } -#endif - -out: - flash_area_close(fap); - - FIH_RET(fih_rc); -} - -#ifdef MCUBOOT_HW_ROLLBACK_PROT -/** - * Updates the stored security counter value with the image's security counter - * value which resides in the given slot, only if it's greater than the stored - * value. - * - * @param image_index Index of the image to determine which security - * counter to update. - * @param slot Slot number of the image. - * @param hdr Pointer to the image header structure of the image - * that is currently stored in the given slot. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_update_security_counter(uint8_t image_index, int slot, - struct image_header *hdr) -{ - const struct flash_area *fap = NULL; - uint32_t img_security_cnt; - int rc; - - rc = flash_area_open(flash_area_id_from_multi_image_slot(image_index, slot), - &fap); - if (rc != 0) { - rc = BOOT_EFLASH; - goto done; - } - - rc = bootutil_get_img_security_cnt(hdr, fap, &img_security_cnt); - if (rc != 0) { - goto done; - } - - rc = boot_nv_security_counter_update(image_index, img_security_cnt); - if (rc != 0) { - goto done; - } - -done: - flash_area_close(fap); - return rc; -} -#endif /* MCUBOOT_HW_ROLLBACK_PROT */ - -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) - -#if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ -(defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) - -#define SEC_SLOT_VIRGIN 0 -#define SEC_SLOT_TOUCHED 1 -#define SEC_SLOT_ASSIGNED 2 - -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -/* This configuration is peculiar - the one physical secondary slot is - * mocking two logical secondary - */ -#define SEC_SLOT_PHYSICAL_CNT 1 -#else -#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER -#endif - -static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; - -static inline void sec_slot_touch(struct boot_loader_state *state) -{ - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); - - if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { - sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; - } -} - -static inline void sec_slot_mark_assigned(struct boot_loader_state *state) -{ - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); - - sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; -} - -/** - * Cleanu up all secondary slot which couldn't be assigned to any primary slot. - * - * This function erases content of each secondary slot which contains valid - * header but couldn't be assigned to any of supported primary images. - * - * This function is supposed to be called after boot_validated_swap_type() - * iterates over all the images in context_boot_go(). - */ -static void sec_slot_cleanup_if_unusable(void) -{ - uint8_t idx; - - for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { - if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { - const struct flash_area *secondary_fa; - int rc; - - rc = flash_area_open(flash_area_id_from_multi_image_slot(idx, BOOT_SECONDARY_SLOT), - &secondary_fa); - if (!rc) { - rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); - if (!rc) { - BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); - } - } - - if (rc) { - BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); - } - } - } -} -#else -static inline void sec_slot_touch(struct boot_loader_state *state) -{ -} -static inline void sec_slot_mark_assigned(struct boot_loader_state *state) -{ -} -static inline void sec_slot_cleanup_if_unusable(void) -{ -} -#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ - defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ - -/** - * Determines which swap operation to perform, if any. If it is determined - * that a swap operation is required, the image in the secondary slot is checked - * for validity. If the image in the secondary slot is invalid, it is erased, - * and a swap type of "none" is indicated. - * - * @return The type of swap to perform (BOOT_SWAP_TYPE...) - */ -static int -boot_validated_swap_type(struct boot_loader_state *state, - struct boot_status *bs) -{ - int swap_type; - FIH_DECLARE(fih_rc, FIH_FAILURE); - bool upgrade_valid = false; -#if defined(PM_S1_ADDRESS) - owner_nsib[BOOT_CURR_IMG(state)] = false; -#endif - -#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) - const struct flash_area *secondary_fa = - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - uint32_t reset_addr = 0; - int rc = 0; - /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other - * B1 slot S0 or S1) share the same secondary slot, we need to check - * whether the update candidate in the secondary slot is intended for - * image 0 or image 1 primary by looking at the address of the reset - * vector. Note that there are good reasons for not using img_num from - * the swap info. - */ - - if (hdr->ih_magic == IMAGE_MAGIC) { - rc = flash_area_read(secondary_fa, hdr->ih_hdr_size + - sizeof(uint32_t), &reset_addr, - sizeof(reset_addr)); - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - - sec_slot_touch(state); - -#ifdef PM_S1_ADDRESS -#ifdef PM_CPUNET_B0N_ADDRESS - if(!(reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS)) -#endif - { - const struct flash_area *primary_fa; - rc = flash_area_open(flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), - &primary_fa); - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - - /* Check start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off) { -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - const struct flash_area *nsib_fa; - - /* NSIB upgrade slot */ - rc = flash_area_open((uint32_t)_image_1_primary_slot_id, - &nsib_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - - /* Image is placed before Primary and within the NSIB slot */ - if (reset_addr > nsib_fa->fa_off - && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { - /* Set primary to be NSIB upgrade slot */ - BOOT_IMG_AREA(state, 0) = nsib_fa; - owner_nsib[BOOT_CURR_IMG(state)] = true; - } -#else - return BOOT_SWAP_TYPE_NONE; - -#endif - - } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for any */ - return BOOT_SWAP_TYPE_NONE; - } - - if ((primary_fa->fa_off == PM_S0_ADDRESS) || (primary_fa->fa_off == PM_S1_ADDRESS)) { - owner_nsib[BOOT_CURR_IMG(state)] = true; - } - } -#endif /* PM_S1_ADDRESS */ - sec_slot_mark_assigned(state); - } - -#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ - - swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); - if (BOOT_IS_UPGRADE(swap_type)) { - /* Boot loader wants to switch to the secondary slot. - * Ensure image is valid. - */ - FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_SECONDARY_SLOT, bs); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - if (FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { - swap_type = BOOT_SWAP_TYPE_NONE; - } else { - swap_type = BOOT_SWAP_TYPE_FAIL; - } - } else { - upgrade_valid = true; - } - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ - && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) && defined(CONFIG_PCD_APP) - /* If the update is valid, and it targets the network core: perform the - * update and indicate to the caller of this function that no update is - * available - */ - if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS && - reset_addr < PM_CPUNET_APP_END_ADDRESS) { - struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; - uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); - uint32_t fw_size = hdr->ih_img_size; - BOOT_LOG_INF("Starting network core update"); - rc = pcd_network_core_update(net_core_fw_addr, fw_size); - - if (rc != 0) { - swap_type = BOOT_SWAP_TYPE_FAIL; - } else { - BOOT_LOG_INF("Done updating network core"); -#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) - /* swap_erase_trailer_sectors is undefined if upgrade only - * method is used. There is no need to erase sectors, because - * the image cannot be reverted. - */ - rc = swap_erase_trailer_sectors(state, - secondary_fa); -#endif - swap_type = BOOT_SWAP_TYPE_NONE; - } - } -#endif /* CONFIG_SOC_NRF5340_CPUAPP && PM_CPUNET_B0N_ADDRESS && - !CONFIG_NRF53_MULTI_IMAGE_UPDATE && CONFIG_PCD_APP */ - } - - return swap_type; -} -#endif - -/** - * Erases a region of flash. - * - * @param flash_area The flash_area containing the region to erase. - * @param off The offset within the flash area to start the - * erase. - * @param sz The number of bytes to erase. - * - * @return 0 on success; nonzero on failure. - */ -int -boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz) -{ - return flash_area_erase(fap, off, sz); -} - -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) - -#if defined(MCUBOOT_ENC_IMAGES) || defined(MCUBOOT_SWAP_SAVE_ENCTLV) -/* Replacement for memset(p, 0, sizeof(*p) that does not get - * optimized out. - */ -static void like_mbedtls_zeroize(void *p, size_t n) -{ - volatile unsigned char *v = (unsigned char *)p; - - for (size_t i = 0; i < n; i++) { - v[i] = 0; - } -} -#endif - -/** - * Copies the contents of one flash region to another. You must erase the - * destination region prior to calling this function. - * - * @param flash_area_id_src The ID of the source flash area. - * @param flash_area_id_dst The ID of the destination flash area. - * @param off_src The offset within the source flash area to - * copy from. - * @param off_dst The offset within the destination flash area to - * copy to. - * @param sz The number of bytes to copy. - * - * @return 0 on success; nonzero on failure. - */ -int -boot_copy_region(struct boot_loader_state *state, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, - uint32_t off_src, uint32_t off_dst, uint32_t sz) -{ - uint32_t bytes_copied; - int chunk_sz; - int rc; -#ifdef MCUBOOT_ENC_IMAGES - uint32_t off = off_dst; - uint32_t tlv_off; - size_t blk_off; - struct image_header *hdr; - uint16_t idx; - uint32_t blk_sz; - uint8_t image_index = BOOT_CURR_IMG(state); - bool encrypted_src; - bool encrypted_dst; - /* Assuming the secondary slot is source; note that 0 here not only - * means that primary slot is source, but also that there will be - * encryption happening, if it is 1 then there is decryption from - * secondary slot. - */ - int source_slot = 1; - /* In case of encryption enabled, we may have to do more work than - * just copy bytes */ - bool only_copy = false; -#else - (void)state; -#endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - struct image_header *hdr; -#endif - - TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); - -#ifdef MCUBOOT_ENC_IMAGES - encrypted_src = (flash_area_get_id(fap_src) != FLASH_AREA_IMAGE_PRIMARY(image_index)); - encrypted_dst = (flash_area_get_id(fap_dst) != FLASH_AREA_IMAGE_PRIMARY(image_index)); - - if (encrypted_src != encrypted_dst) { - if (encrypted_dst) { - /* Need encryption, metadata from the primary slot */ - hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT); - source_slot = 0; - } else { - /* Need decryption, metadata from the secondary slot */ - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - source_slot = 1; - } - } else { - /* In case when source and targe is the same area, this means that we - * only have to copy bytes, no encryption or decryption. - */ - only_copy = true; - } -#endif - -#ifdef MCUBOOT_DECOMPRESS_IMAGES - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - - if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { - /* Use alternative function for compressed images */ - return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, - BUF_SZ); - } -#endif - - bytes_copied = 0; - while (bytes_copied < sz) { - if (sz - bytes_copied > sizeof buf) { - chunk_sz = sizeof buf; - } else { - chunk_sz = sz - bytes_copied; - } - - rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz); - if (rc != 0) { - return BOOT_EFLASH; - } - -#ifdef MCUBOOT_ENC_IMAGES - /* If only copy, then does not matter if header indicates need for - * encryptio/decryptio, we just copy data. */ - if (!only_copy && IS_ENCRYPTED(hdr)) { - uint32_t abs_off = off + bytes_copied; - if (abs_off < hdr->ih_hdr_size) { - /* do not decrypt header */ - if (abs_off + chunk_sz > hdr->ih_hdr_size) { - /* The lower part of the chunk contains header data */ - blk_off = 0; - blk_sz = chunk_sz - (hdr->ih_hdr_size - abs_off); - idx = hdr->ih_hdr_size - abs_off; - } else { - /* The chunk contains exclusively header data */ - blk_sz = 0; /* nothing to decrypt */ - } - } else { - idx = 0; - blk_sz = chunk_sz; - blk_off = (abs_off - hdr->ih_hdr_size) & 0xf; - } - - if (blk_sz > 0) - { - tlv_off = BOOT_TLV_OFF(hdr); - if (abs_off + chunk_sz > tlv_off) { - /* do not decrypt TLVs */ - if (abs_off >= tlv_off) { - blk_sz = 0; - } else { - blk_sz = tlv_off - abs_off; - } - } - if (source_slot == 0) { - boot_enc_encrypt(BOOT_CURR_ENC(state), source_slot, - (abs_off + idx) - hdr->ih_hdr_size, blk_sz, - blk_off, &buf[idx]); - } else { - boot_enc_decrypt(BOOT_CURR_ENC(state), source_slot, - (abs_off + idx) - hdr->ih_hdr_size, blk_sz, - blk_off, &buf[idx]); - } - } - } -#endif - - rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz); - if (rc != 0) { - return BOOT_EFLASH; - } - - bytes_copied += chunk_sz; - - MCUBOOT_WATCHDOG_FEED(); - } - - return 0; -} - -/** - * Overwrite primary slot with the image contained in the secondary slot. - * If a prior copy operation was interrupted by a system reset, this function - * redos the copy. - * - * @param bs The current boot status. This function reads - * this struct to determine if it is resuming - * an interrupted swap operation. This - * function writes the updated status to this - * function on return. - * - * @return 0 on success; nonzero on failure. - */ -#if defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_BOOTSTRAP) -static int -boot_copy_image(struct boot_loader_state *state, struct boot_status *bs) -{ - size_t sect_count; - size_t sect; - int rc; - size_t size; - size_t this_size; - size_t last_sector; - const struct flash_area *fap_primary_slot; - const struct flash_area *fap_secondary_slot; - uint8_t image_index; - -#if defined(MCUBOOT_OVERWRITE_ONLY_FAST) - uint32_t sector; - uint32_t trailer_sz; - uint32_t off; - uint32_t sz; -#endif - - (void)bs; - -#if defined(MCUBOOT_OVERWRITE_ONLY_FAST) - uint32_t src_size = 0; - rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &src_size); - assert(rc == 0); -#endif - - image_index = BOOT_CURR_IMG(state); - - BOOT_LOG_INF("Image %d upgrade secondary slot -> primary slot", image_index); - BOOT_LOG_INF("Erasing the primary slot"); - - rc = flash_area_open(flash_area_get_id(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)), - &fap_primary_slot); - assert (rc == 0); - - rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), - &fap_secondary_slot); - assert (rc == 0); - - sect_count = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT); - for (sect = 0, size = 0; sect < sect_count; sect++) { - this_size = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sect); - rc = boot_erase_region(fap_primary_slot, size, this_size); - assert(rc == 0); - -#if defined(MCUBOOT_OVERWRITE_ONLY_FAST) - if ((size + this_size) >= src_size) { - size += src_size - size; - size += BOOT_WRITE_SZ(state) - (size % BOOT_WRITE_SZ(state)); - break; - } -#endif - - size += this_size; - } - -#if defined(MCUBOOT_OVERWRITE_ONLY_FAST) - trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - sector = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 1; - sz = 0; - do { - sz += boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sector); - off = boot_img_sector_off(state, BOOT_PRIMARY_SLOT, sector); - sector--; - } while (sz < trailer_sz); - - rc = boot_erase_region(fap_primary_slot, off, sz); - assert(rc == 0); -#endif - -#ifdef MCUBOOT_ENC_IMAGES - if (IS_ENCRYPTED(boot_img_hdr(state, BOOT_SECONDARY_SLOT))) { - rc = boot_enc_load(BOOT_CURR_ENC(state), BOOT_SECONDARY_SLOT, - boot_img_hdr(state, BOOT_SECONDARY_SLOT), - fap_secondary_slot, bs); - - if (rc < 0) { - return BOOT_EBADIMAGE; - } - if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) { - return BOOT_EBADIMAGE; - } - } -#endif - - BOOT_LOG_INF("Image %d copying the secondary slot to the primary slot: 0x%zx bytes", - image_index, size); - rc = boot_copy_region(state, fap_secondary_slot, fap_primary_slot, 0, 0, size); - if (rc != 0) { - return rc; - } - -#if defined(MCUBOOT_OVERWRITE_ONLY_FAST) - rc = boot_write_magic(fap_primary_slot); - if (rc != 0) { - return rc; - } -#endif - - rc = BOOT_HOOK_CALL(boot_copy_region_post_hook, 0, BOOT_CURR_IMG(state), - BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT), size); - if (rc != 0) { - return rc; - } - -#ifdef MCUBOOT_HW_ROLLBACK_PROT - /* Update the stored security counter with the new image's security counter - * value. Both slots hold the new image at this point, but the secondary - * slot's image header must be passed since the image headers in the - * boot_data structure have not been updated yet. - */ - rc = boot_update_security_counter(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT, - boot_img_hdr(state, BOOT_SECONDARY_SLOT)); - if (rc != 0) { - BOOT_LOG_ERR("Security counter update failed after image upgrade."); - return rc; - } -#endif /* MCUBOOT_HW_ROLLBACK_PROT */ - -#ifndef MCUBOOT_OVERWRITE_ONLY_KEEP_BACKUP - /* - * Erases header and trailer. The trailer is erased because when a new - * image is written without a trailer as is the case when using newt, the - * trailer that was left might trigger a new upgrade. - */ - BOOT_LOG_DBG("erasing secondary header"); - rc = boot_erase_region(fap_secondary_slot, - boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0), - boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0)); - assert(rc == 0); -#endif - - last_sector = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1; - BOOT_LOG_DBG("erasing secondary trailer"); - rc = boot_erase_region(fap_secondary_slot, - boot_img_sector_off(state, BOOT_SECONDARY_SLOT, - last_sector), - boot_img_sector_size(state, BOOT_SECONDARY_SLOT, - last_sector)); - assert(rc == 0); - - flash_area_close(fap_primary_slot); - flash_area_close(fap_secondary_slot); - - /* TODO: Perhaps verify the primary slot's signature again? */ - - return 0; -} -#endif - -#if !defined(MCUBOOT_OVERWRITE_ONLY) -/** - * Swaps the two images in flash. If a prior copy operation was interrupted - * by a system reset, this function completes that operation. - * - * @param bs The current boot status. This function reads - * this struct to determine if it is resuming - * an interrupted swap operation. This - * function writes the updated status to this - * function on return. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) -{ - struct image_header *hdr; - const struct flash_area *fap; -#ifdef MCUBOOT_ENC_IMAGES - uint8_t slot; - uint8_t i; -#endif - uint32_t size; - uint32_t copy_size; - uint8_t image_index; - int rc; - - /* FIXME: just do this if asked by user? */ - - size = copy_size = 0; - image_index = BOOT_CURR_IMG(state); - - if (boot_status_is_reset(bs)) { - /* - * No swap ever happened, so need to find the largest image which - * will be used to determine the amount of sectors to swap. - */ - hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT); - if (hdr->ih_magic == IMAGE_MAGIC) { - rc = boot_read_image_size(state, BOOT_PRIMARY_SLOT, ©_size); - assert(rc == 0); - } - -#ifdef MCUBOOT_ENC_IMAGES - if (IS_ENCRYPTED(hdr)) { - fap = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); - rc = boot_enc_load(BOOT_CURR_ENC(state), 0, hdr, fap, bs); - assert(rc >= 0); - - if (rc == 0) { - rc = boot_enc_set_key(BOOT_CURR_ENC(state), 0, bs); - assert(rc == 0); - } else { - rc = 0; - } - } else { - memset(bs->enckey[0], 0xff, BOOT_ENC_KEY_ALIGN_SIZE); - } -#endif - - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - if (hdr->ih_magic == IMAGE_MAGIC) { - rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &size); - assert(rc == 0); - } - -#ifdef MCUBOOT_ENC_IMAGES - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - if (IS_ENCRYPTED(hdr)) { - fap = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - rc = boot_enc_load(BOOT_CURR_ENC(state), 1, hdr, fap, bs); - assert(rc >= 0); - - if (rc == 0) { - rc = boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs); - assert(rc == 0); - } else { - rc = 0; - } - } else { - memset(bs->enckey[1], 0xff, BOOT_ENC_KEY_ALIGN_SIZE); - } -#endif - - if (size > copy_size) { - copy_size = size; - } - - bs->swap_size = copy_size; - } else { - /* - * If a swap was under way, the swap_size should already be present - * in the trailer... - */ - - rc = boot_find_status(image_index, &fap); - assert(fap != NULL); - rc = boot_read_swap_size(fap, &bs->swap_size); - assert(rc == 0); - - copy_size = bs->swap_size; - -#ifdef MCUBOOT_ENC_IMAGES - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { - rc = boot_read_enc_key(fap, slot, bs); - assert(rc == 0); - - for (i = 0; i < BOOT_ENC_KEY_SIZE; i++) { - if (bs->enckey[slot][i] != 0xff) { - break; - } - } - - boot_enc_init(BOOT_CURR_ENC(state), slot); - - if (i != BOOT_ENC_KEY_SIZE) { - boot_enc_set_key(BOOT_CURR_ENC(state), slot, bs); - } - } -#endif - flash_area_close(fap); - } - - swap_run(state, bs, copy_size); - -#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT - extern int boot_status_fails; - if (boot_status_fails > 0) { - BOOT_LOG_WRN("%d status write fails performing the swap", - boot_status_fails); - } -#endif - rc = BOOT_HOOK_CALL(boot_copy_region_post_hook, 0, BOOT_CURR_IMG(state), - BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT), size); - - return 0; -} -#endif - -/** - * Performs a clean (not aborted) image update. - * - * @param bs The current boot status. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_perform_update(struct boot_loader_state *state, struct boot_status *bs) -{ - int rc; -#ifndef MCUBOOT_OVERWRITE_ONLY - uint8_t swap_type; -#endif - - /* At this point there are no aborted swaps. */ -#if defined(MCUBOOT_OVERWRITE_ONLY) - rc = boot_copy_image(state, bs); -#elif defined(MCUBOOT_BOOTSTRAP) - /* Check if the image update was triggered by a bad image in the - * primary slot (the validity of the image in the secondary slot had - * already been checked). - */ - FIH_DECLARE(fih_rc, FIH_FAILURE); - rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT); - FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, bs); - if (rc == 0 || FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - rc = boot_copy_image(state, bs); - } else { - rc = boot_swap_image(state, bs); - } -#else - rc = boot_swap_image(state, bs); -#endif - assert(rc == 0); - -#ifndef MCUBOOT_OVERWRITE_ONLY - /* The following state needs image_ok be explicitly set after the - * swap was finished to avoid a new revert. - */ - swap_type = BOOT_SWAP_TYPE(state); - if (swap_type == BOOT_SWAP_TYPE_REVERT || - swap_type == BOOT_SWAP_TYPE_PERM) { - rc = swap_set_image_ok(BOOT_CURR_IMG(state)); - if (rc != 0) { - BOOT_SWAP_TYPE(state) = swap_type = BOOT_SWAP_TYPE_PANIC; - } - } - -#ifdef MCUBOOT_HW_ROLLBACK_PROT - if (swap_type == BOOT_SWAP_TYPE_PERM) { - /* Update the stored security counter with the new image's security - * counter value. The primary slot holds the new image at this point, - * but the secondary slot's image header must be passed since image - * headers in the boot_data structure have not been updated yet. - * - * In case of a permanent image swap mcuboot will never attempt to - * revert the images on the next reboot. Therefore, the security - * counter must be increased right after the image upgrade. - */ - rc = boot_update_security_counter( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT, - boot_img_hdr(state, BOOT_SECONDARY_SLOT)); - if (rc != 0) { - BOOT_LOG_ERR("Security counter update failed after " - "image upgrade."); - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; - } - } -#endif /* MCUBOOT_HW_ROLLBACK_PROT */ - - if (BOOT_IS_UPGRADE(swap_type)) { - rc = swap_set_copy_done(BOOT_CURR_IMG(state)); - if (rc != 0) { - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; - } - } -#endif /* !MCUBOOT_OVERWRITE_ONLY */ - - return rc; -} - -/** - * Completes a previously aborted image swap. - * - * @param bs The current boot status. - * - * @return 0 on success; nonzero on failure. - */ -#if !defined(MCUBOOT_OVERWRITE_ONLY) -static int -boot_complete_partial_swap(struct boot_loader_state *state, - struct boot_status *bs) -{ - int rc; - - /* Determine the type of swap operation being resumed from the - * `swap-type` trailer field. - */ - rc = boot_swap_image(state, bs); - assert(rc == 0); - - BOOT_SWAP_TYPE(state) = bs->swap_type; - - /* The following states need image_ok be explicitly set after the - * swap was finished to avoid a new revert. - */ - if (bs->swap_type == BOOT_SWAP_TYPE_REVERT || - bs->swap_type == BOOT_SWAP_TYPE_PERM) { - rc = swap_set_image_ok(BOOT_CURR_IMG(state)); - if (rc != 0) { - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; - } - } - - if (BOOT_IS_UPGRADE(bs->swap_type)) { - rc = swap_set_copy_done(BOOT_CURR_IMG(state)); - if (rc != 0) { - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; - } - } - - if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) { - BOOT_LOG_ERR("panic!"); - assert(0); - - /* Loop forever... */ - while (1) {} - } - - return rc; -} -#endif /* !MCUBOOT_OVERWRITE_ONLY */ - -#if (BOOT_IMAGE_NUMBER > 1) -/** - * Review the validity of previously determined swap types of other images. - * - * @param aborted_swap The current image upgrade is a - * partial/aborted swap. - */ -static void -boot_review_image_swap_types(struct boot_loader_state *state, - bool aborted_swap) -{ - /* In that case if we rebooted in the middle of an image upgrade process, we - * must review the validity of swap types, that were previously determined - * for other images. The image_ok flag had not been set before the reboot - * for any of the updated images (only the copy_done flag) and thus falsely - * the REVERT swap type has been determined for the previous images that had - * been updated before the reboot. - * - * There are two separate scenarios that we have to deal with: - * - * 1. The reboot has happened during swapping an image: - * The current image upgrade has been determined as a - * partial/aborted swap. - * 2. The reboot has happened between two separate image upgrades: - * In this scenario we must check the swap type of the current image. - * In those cases if it is NONE or REVERT we cannot certainly determine - * the fact of a reboot. In a consistent state images must move in the - * same direction or stay in place, e.g. in practice REVERT and TEST - * swap types cannot be present at the same time. If the swap type of - * the current image is either TEST, PERM or FAIL we must review the - * already determined swap types of other images and set each false - * REVERT swap types to NONE (these images had been successfully - * updated before the system rebooted between two separate image - * upgrades). - */ - - if (BOOT_CURR_IMG(state) == 0) { - /* Nothing to do */ - return; - } - - if (!aborted_swap) { - if ((BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) || - (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_REVERT)) { - /* Nothing to do */ - return; - } - } - - for (uint8_t i = 0; i < BOOT_CURR_IMG(state); i++) { - if (state->swap_type[i] == BOOT_SWAP_TYPE_REVERT) { - state->swap_type[i] = BOOT_SWAP_TYPE_NONE; - } - } -} -#endif - -/** - * Prepare image to be updated if required. - * - * Prepare image to be updated if required with completing an image swap - * operation if one was aborted and/or determining the type of the - * swap operation. In case of any error set the swap type to NONE. - * - * @param state TODO - * @param bs Pointer where the read and possibly updated - * boot status can be written to. - */ -static void -boot_prepare_image_for_update(struct boot_loader_state *state, - struct boot_status *bs) -{ - int rc; - FIH_DECLARE(fih_rc, FIH_FAILURE); - -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) - int max_size; -#endif - - /* Determine the sector layout of the image slots and scratch area. */ - rc = boot_read_sectors(state); - if (rc != 0) { - BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d" - " - too small?", BOOT_MAX_IMG_SECTORS); - /* Unable to determine sector layout, continue with next image - * if there is one. - */ - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; - if (rc == BOOT_EFLASH) - { - /* Only return on error from the primary image flash */ - return; - } - } - - /* Attempt to read an image header from each slot. */ - rc = boot_read_image_headers(state, false, NULL); - if (rc != 0) { - /* Continue with next image if there is one. */ - BOOT_LOG_WRN("Failed reading image headers; Image=%u", - BOOT_CURR_IMG(state)); - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; - return; - } - -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) - /* Fetch information on maximum sizes for later usage, if needed */ - max_size = app_max_size(state); - - if (max_size > 0) { - image_max_sizes[BOOT_CURR_IMG(state)].calculated = true; - image_max_sizes[BOOT_CURR_IMG(state)].max_size = max_size; - } -#endif - - /* If the current image's slots aren't compatible, no swap is possible. - * Just boot into primary slot. - */ - if (boot_slots_compatible(state)) { - boot_status_reset(bs); - -#ifndef MCUBOOT_OVERWRITE_ONLY - rc = swap_read_status(state, bs); - if (rc != 0) { - BOOT_LOG_WRN("Failed reading boot status; Image=%u", - BOOT_CURR_IMG(state)); - /* Continue with next image if there is one. */ - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; - return; - } -#endif - -#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) - /* - * Must re-read image headers because the boot status might - * have been updated in the previous function call. - */ - rc = boot_read_image_headers(state, !boot_status_is_reset(bs), bs); -#ifdef MCUBOOT_BOOTSTRAP - /* When bootstrapping it's OK to not have image magic in the primary slot */ - if (rc != 0 && (BOOT_CURR_IMG(state) != BOOT_PRIMARY_SLOT || - boot_check_header_erased(state, BOOT_PRIMARY_SLOT) != 0)) { -#else - if (rc != 0) { -#endif - - /* Continue with next image if there is one. */ - BOOT_LOG_WRN("Failed reading image headers; Image=%u", - BOOT_CURR_IMG(state)); - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; - return; - } -#endif - - /* Determine if we rebooted in the middle of an image swap - * operation. If a partial swap was detected, complete it. - */ - if (!boot_status_is_reset(bs)) { - -#if (BOOT_IMAGE_NUMBER > 1) - boot_review_image_swap_types(state, true); -#endif - -#ifdef MCUBOOT_OVERWRITE_ONLY - /* Should never arrive here, overwrite-only mode has - * no swap state. - */ - assert(0); -#else - /* Determine the type of swap operation being resumed from the - * `swap-type` trailer field. - */ - rc = boot_complete_partial_swap(state, bs); - assert(rc == 0); -#endif - /* Attempt to read an image header from each slot. Ensure that - * image headers in slots are aligned with headers in boot_data. - */ - rc = boot_read_image_headers(state, false, bs); - assert(rc == 0); - - /* Swap has finished set to NONE */ - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; - } else { - /* There was no partial swap, determine swap type. */ - if (bs->swap_type == BOOT_SWAP_TYPE_NONE) { - BOOT_SWAP_TYPE(state) = boot_validated_swap_type(state, bs); - } else { - FIH_CALL(boot_validate_slot, fih_rc, - state, BOOT_SECONDARY_SLOT, bs); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_FAIL; - } else { - BOOT_SWAP_TYPE(state) = bs->swap_type; - } - } - -#if (BOOT_IMAGE_NUMBER > 1) - boot_review_image_swap_types(state, false); -#endif - -#ifdef MCUBOOT_BOOTSTRAP - if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) { - /* Header checks are done first because they are - * inexpensive. Since overwrite-only copies starting from - * offset 0, if interrupted, it might leave a valid header - * magic, so also run validation on the primary slot to be - * sure it's not OK. - */ - rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT); - FIH_CALL(boot_validate_slot, fih_rc, - state, BOOT_PRIMARY_SLOT, bs); - - if (rc == 0 || FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - - rc = (boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_magic == IMAGE_MAGIC) ? 1: 0; - FIH_CALL(boot_validate_slot, fih_rc, - state, BOOT_SECONDARY_SLOT, bs); - - if (rc == 1 && FIH_EQ(fih_rc, FIH_SUCCESS)) { - /* Set swap type to REVERT to overwrite the primary - * slot with the image contained in secondary slot - * and to trigger the explicit setting of the - * image_ok flag. - */ - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT; - } - } - } -#endif - } - } else { - /* In that case if slots are not compatible. */ - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; - } -} - -/** - * Updates the security counter for the current image. - * - * @param state Boot loader status information. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_update_hw_rollback_protection(struct boot_loader_state *state) -{ -#ifdef MCUBOOT_HW_ROLLBACK_PROT - int rc; - - /* Update the stored security counter with the active image's security - * counter value. It will only be updated if the new security counter is - * greater than the stored value. - * - * In case of a successful image swapping when the swap type is TEST the - * security counter can be increased only after a reset, when the swap - * type is NONE and the image has marked itself "OK" (the image_ok flag - * has been set). This way a "revert" can be performed when it's - * necessary. - */ - if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) { - rc = boot_update_security_counter( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT, - boot_img_hdr(state, BOOT_PRIMARY_SLOT)); - if (rc != 0) { - BOOT_LOG_ERR("Security counter update failed after image " - "validation."); - return rc; - } - } - - return 0; - -#else /* MCUBOOT_HW_ROLLBACK_PROT */ - (void) (state); - - return 0; -#endif -} - -/** - * Checks test swap downgrade prevention conditions. - * - * Function called only for swap upgrades test run. It may prevent - * swap if slot 1 image has <= version number or < security counter - * - * @param state Boot loader status information. - * - * @return 0 - image can be swapped, -1 downgrade prevention - */ -static int -check_downgrade_prevention(struct boot_loader_state *state) -{ -#if defined(MCUBOOT_DOWNGRADE_PREVENTION) && \ - (defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_SCRATCH)) - uint32_t security_counter[2]; - int rc; - -#if defined(PM_S1_ADDRESS) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - /* Downgrade prevention on S0/S1 image is managed by NSIB */ - return 0; - } -#endif - - if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) { - /* If there was security no counter in slot 0, allow swap */ - rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 0).hdr), - BOOT_IMG(state, 0).area, - &security_counter[0]); - if (rc != 0) { - return 0; - } - /* If there is no security counter in slot 1, or it's lower than - * that of slot 0, prevent downgrade */ - rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 1).hdr), - BOOT_IMG(state, 1).area, - &security_counter[1]); - if (rc != 0 || security_counter[0] > security_counter[1]) { - rc = -1; - } - } - else { - rc = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); - } - if (rc < 0) { - /* Image in slot 0 prevents downgrade, delete image in slot 1 */ - BOOT_LOG_INF("Image %d in slot 1 erased due to downgrade prevention", BOOT_CURR_IMG(state)); - flash_area_erase(BOOT_IMG(state, 1).area, 0, - flash_area_get_size(BOOT_IMG(state, 1).area)); - } else { - rc = 0; - } - return rc; -#else - (void)state; - return 0; -#endif -} - -fih_ret -context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) -{ - size_t slot; - struct boot_status bs; - int rc = -1; - FIH_DECLARE(fih_rc, FIH_FAILURE); - int fa_id; - int image_index; - bool has_upgrade; - volatile int fih_cnt; - -#if defined(__BOOTSIM__) - /* The array of slot sectors are defined here (as opposed to file scope) so - * that they don't get allocated for non-boot-loader apps. This is - * necessary because the gcc option "-fdata-sections" doesn't seem to have - * any effect in older gcc versions (e.g., 4.8.4). - */ - TARGET_STATIC boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; - TARGET_STATIC boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; -#if MCUBOOT_SWAP_USING_SCRATCH - TARGET_STATIC boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS]; -#endif -#endif - - has_upgrade = false; - -#if (BOOT_IMAGE_NUMBER == 1) - (void)has_upgrade; -#endif - - /* Iterate over all the images. By the end of the loop the swap type has - * to be determined for each image and all aborted swaps have to be - * completed. - */ - IMAGES_ITER(BOOT_CURR_IMG(state)) { -#if BOOT_IMAGE_NUMBER > 1 - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } -#endif -#if defined(MCUBOOT_ENC_IMAGES) && (BOOT_IMAGE_NUMBER > 1) - /* The keys used for encryption may no longer be valid (could belong to - * another images). Therefore, mark them as invalid to force their reload - * by boot_enc_load(). - */ - boot_enc_zeroize(BOOT_CURR_ENC(state)); -#endif - - image_index = BOOT_CURR_IMG(state); - -#if !defined(__BOOTSIM__) - BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors = - sector_buffers.primary[image_index]; - BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors = - sector_buffers.secondary[image_index]; -#if MCUBOOT_SWAP_USING_SCRATCH - state->scratch.sectors = sector_buffers.scratch; -#endif -#else - BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors = - primary_slot_sectors[image_index]; - BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors = - secondary_slot_sectors[image_index]; -#if MCUBOOT_SWAP_USING_SCRATCH - state->scratch.sectors = scratch_sectors; -#endif -#endif - - /* Open primary and secondary image areas for the duration - * of this call. - */ - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { - fa_id = flash_area_id_from_multi_image_slot(image_index, slot); - rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot)); - assert(rc == 0); - - if (rc != 0) { - BOOT_LOG_ERR("Failed to open flash area ID %d (image %d slot %d): %d, " - "cannot continue", fa_id, image_index, (int8_t)slot, rc); - FIH_PANIC; - } - } -#if MCUBOOT_SWAP_USING_SCRATCH - rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, - &BOOT_SCRATCH_AREA(state)); - assert(rc == 0); - - if (rc != 0) { - BOOT_LOG_ERR("Failed to open scratch flash area: %d, cannot continue", rc); - FIH_PANIC; - } -#endif - - /* Determine swap type and complete swap if it has been aborted. */ - boot_prepare_image_for_update(state, &bs); - - if (BOOT_IS_UPGRADE(BOOT_SWAP_TYPE(state))) { - has_upgrade = true; - } - } - - /* cleanup secondary slots which were recognized unusable*/ - sec_slot_cleanup_if_unusable(); - -#if (BOOT_IMAGE_NUMBER > 1) - if (has_upgrade) { - /* Iterate over all the images and verify whether the image dependencies - * are all satisfied and update swap type if necessary. - */ - rc = boot_verify_dependencies(state); - if (rc != 0) { - /* - * It was impossible to upgrade because the expected dependency version - * was not available. Here we already changed the swap_type so that - * instead of asserting the bootloader, we continue and no upgrade is - * performed. - */ - rc = 0; - } - } -#endif - - /* Trigger status change callback with upgrading status */ - mcuboot_status_change(MCUBOOT_STATUS_UPGRADING); - - /* Iterate over all the images. At this point there are no aborted swaps - * and the swap types are determined for each image. By the end of the loop - * all required update operations will have been finished. - */ - IMAGES_ITER(BOOT_CURR_IMG(state)) { -#if (BOOT_IMAGE_NUMBER > 1) - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } - -#ifdef MCUBOOT_ENC_IMAGES - /* The keys used for encryption may no longer be valid (could belong to - * another images). Therefore, mark them as invalid to force their reload - * by boot_enc_load(). - */ - boot_enc_zeroize(BOOT_CURR_ENC(state)); -#endif /* MCUBOOT_ENC_IMAGES */ - - /* Indicate that swap is not aborted */ - boot_status_reset(&bs); -#endif /* (BOOT_IMAGE_NUMBER > 1) */ - - /* Set the previously determined swap type */ - bs.swap_type = BOOT_SWAP_TYPE(state); - - switch (BOOT_SWAP_TYPE(state)) { - case BOOT_SWAP_TYPE_NONE: - break; - - case BOOT_SWAP_TYPE_TEST: - /* fallthrough */ - case BOOT_SWAP_TYPE_PERM: - if (check_downgrade_prevention(state) != 0) { - /* Downgrade prevented */ - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; - break; - } - /* fallthrough */ - case BOOT_SWAP_TYPE_REVERT: - rc = BOOT_HOOK_CALL(boot_perform_update_hook, BOOT_HOOK_REGULAR, - BOOT_CURR_IMG(state), &(BOOT_IMG(state, 1).hdr), - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT)); - if (rc == BOOT_HOOK_REGULAR) - { - rc = boot_perform_update(state, &bs); - } - assert(rc == 0); -#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - sys_reboot(SYS_REBOOT_COLD); - - } -#endif - break; - - case BOOT_SWAP_TYPE_FAIL: - /* The image in secondary slot was invalid and is now erased. Ensure - * we don't try to boot into it again on the next reboot. Do this by - * pretending we just reverted back to primary slot. - */ -#ifndef MCUBOOT_OVERWRITE_ONLY - /* image_ok needs to be explicitly set to avoid a new revert. */ - rc = swap_set_image_ok(BOOT_CURR_IMG(state)); - if (rc != 0) { - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; - } -#endif /* !MCUBOOT_OVERWRITE_ONLY */ - break; - - default: - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC; - } - - if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) { - BOOT_LOG_ERR("panic!"); - assert(0); - - /* Loop forever... */ - FIH_PANIC; - } - } - - /* Iterate over all the images. At this point all required update operations - * have finished. By the end of the loop each image in the primary slot will - * have been re-validated. - */ - FIH_SET(fih_cnt, 0); - IMAGES_ITER(BOOT_CURR_IMG(state)) { -#if BOOT_IMAGE_NUMBER > 1 - /* Hardenned to prevent from skipping check of a given image, - * tmp_img_mask is declared volatile - */ - volatile bool tmp_img_mask; - FIH_SET(tmp_img_mask, state->img_mask[BOOT_CURR_IMG(state)]); - if (FIH_EQ(tmp_img_mask, true)) { - ++fih_cnt; - continue; - } -#endif - if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE) { - /* Attempt to read an image header from each slot. Ensure that image - * headers in slots are aligned with headers in boot_data. - * Note: Quite complicated internal logic of boot_read_image_headers - * uses boot state, the last parm, to figure out in which slot which - * header is located; when boot state is not provided, then it - * is assumed that headers are at proper slots (we are not in - * the middle of moving images, etc). - */ - rc = boot_read_image_headers(state, false, NULL); - if (rc != 0) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - /* Since headers were reloaded, it can be assumed we just performed - * a swap or overwrite. Now the header info that should be used to - * provide the data for the bootstrap, which previously was at - * secondary slot, was updated to primary slot. - */ - } - -#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. Image 1 primary is the currently - * executing MCUBoot image, and is therefore already validated by NSIB and - * does not need to also be validated by MCUBoot. - */ - bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; - if (!image_validated_by_nsib) -#endif - { - FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL); - /* Check for all possible values is redundant in normal operation it - * is meant to prevent FI attack. - */ - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || - FIH_EQ(fih_rc, FIH_FAILURE) || - FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - } -#else - /* Even if we're not re-validating the primary slot, we could be booting - * onto an empty flash chip. At least do a basic sanity check that - * the magic number on the image is OK. - */ - if (BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic != IMAGE_MAGIC) { - BOOT_LOG_ERR("bad image magic 0x%lx; Image=%u", (unsigned long) - BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic, - BOOT_CURR_IMG(state)); - rc = BOOT_EBADIMAGE; - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } -#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ - -#ifdef PM_S1_ADDRESS - if (!image_validated_by_nsib) -#endif - { - rc = boot_update_hw_rollback_protection(state); - if (rc != 0) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - } - - rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT); - if (rc != 0) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - ++fih_cnt; - } - /* - * fih_cnt should be equal to BOOT_IMAGE_NUMBER now. - * If this is not the case, at least one iteration of the loop - * has been skipped. - */ - if(FIH_NOT_EQ(fih_cnt, BOOT_IMAGE_NUMBER)) { - FIH_PANIC; - } - - fill_rsp(state, rsp); - - fih_rc = FIH_SUCCESS; -out: - /* - * Since the boot_status struct stores plaintext encryption keys, reset - * them here to avoid the possibility of jumping into an image that could - * easily recover them. - */ -#if defined(MCUBOOT_ENC_IMAGES) || defined(MCUBOOT_SWAP_SAVE_ENCTLV) - like_mbedtls_zeroize(&bs, sizeof(bs)); -#else - memset(&bs, 0, sizeof(struct boot_status)); -#endif - - close_all_flash_areas(state); - FIH_RET(fih_rc); -} - -fih_ret -split_go(int loader_slot, int split_slot, void **entry) -{ - boot_sector_t *sectors; - uintptr_t entry_val; - int loader_flash_id; - int split_flash_id; - int rc; - FIH_DECLARE(fih_rc, FIH_FAILURE); - - sectors = malloc(BOOT_MAX_IMG_SECTORS * 2 * sizeof *sectors); - if (sectors == NULL) { - FIH_RET(FIH_FAILURE); - } - BOOT_IMG(&boot_data, loader_slot).sectors = sectors + 0; - BOOT_IMG(&boot_data, split_slot).sectors = sectors + BOOT_MAX_IMG_SECTORS; - - loader_flash_id = flash_area_id_from_image_slot(loader_slot); - rc = flash_area_open(loader_flash_id, - &BOOT_IMG_AREA(&boot_data, loader_slot)); - assert(rc == 0); - split_flash_id = flash_area_id_from_image_slot(split_slot); - rc = flash_area_open(split_flash_id, - &BOOT_IMG_AREA(&boot_data, split_slot)); - assert(rc == 0); - - /* Determine the sector layout of the image slots and scratch area. */ - rc = boot_read_sectors(&boot_data); - if (rc != 0) { - rc = SPLIT_GO_ERR; - goto done; - } - - rc = boot_read_image_headers(&boot_data, true, NULL); - if (rc != 0) { - goto done; - } - - /* Don't check the bootable image flag because we could really call a - * bootable or non-bootable image. Just validate that the image check - * passes which is distinct from the normal check. - */ - FIH_CALL(split_image_check, fih_rc, - boot_img_hdr(&boot_data, split_slot), - BOOT_IMG_AREA(&boot_data, split_slot), - boot_img_hdr(&boot_data, loader_slot), - BOOT_IMG_AREA(&boot_data, loader_slot)); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - goto done; - } - - entry_val = boot_img_slot_off(&boot_data, split_slot) + - boot_img_hdr(&boot_data, split_slot)->ih_hdr_size; - *entry = (void *) entry_val; - rc = SPLIT_GO_OK; - -done: - flash_area_close(BOOT_IMG_AREA(&boot_data, split_slot)); - flash_area_close(BOOT_IMG_AREA(&boot_data, loader_slot)); - free(sectors); - - if (rc) { - FIH_SET(fih_rc, FIH_FAILURE); - } - - FIH_RET(fih_rc); -} - -#else /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */ - -/** - * Opens all flash areas and checks which contain an image with a valid header. - * - * @param state Boot loader status information. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_get_slot_usage(struct boot_loader_state *state) -{ - uint32_t slot; - int fa_id; - int rc; - struct image_header *hdr = NULL; - - IMAGES_ITER(BOOT_CURR_IMG(state)) { -#if BOOT_IMAGE_NUMBER > 1 - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } -#endif - /* Open all the slots */ - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { - fa_id = flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), slot); - rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot)); - assert(rc == 0); - } - - /* Attempt to read an image header from each slot. */ - rc = boot_read_image_headers(state, false, NULL); - if (rc != 0) { - BOOT_LOG_WRN("Failed reading image headers."); - return rc; - } - - /* Check headers in all slots */ - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { - hdr = boot_img_hdr(state, slot); - - if (boot_is_header_valid(hdr, BOOT_IMG_AREA(state, slot), state)) { - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = true; - BOOT_LOG_IMAGE_INFO(slot, hdr); - } else { - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; - BOOT_LOG_INF("Image %d %s slot: Image not found", - BOOT_CURR_IMG(state), - (slot == BOOT_PRIMARY_SLOT) - ? "Primary" : "Secondary"); - } - } - - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - } - - return 0; -} - -/** - * Finds the slot containing the image with the highest version number for the - * current image. - * - * @param state Boot loader status information. - * - * @return NO_ACTIVE_SLOT if no available slot found, number of - * the found slot otherwise. - */ -static uint32_t -find_slot_with_highest_version(struct boot_loader_state *state) -{ - uint32_t slot; - uint32_t candidate_slot = NO_ACTIVE_SLOT; - int rc; - - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { - if (state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot]) { - if (candidate_slot == NO_ACTIVE_SLOT) { - candidate_slot = slot; - } else { - rc = boot_version_cmp( - &boot_img_hdr(state, slot)->ih_ver, - &boot_img_hdr(state, candidate_slot)->ih_ver); - if (rc == 1) { - /* The version of the image being examined is greater than - * the version of the current candidate. - */ - candidate_slot = slot; - } - } - } - } - - return candidate_slot; -} - -#ifdef MCUBOOT_HAVE_LOGGING -/** - * Prints the state of the loaded images. - * - * @param state Boot loader status information. - */ -static void -print_loaded_images(struct boot_loader_state *state) -{ - uint32_t active_slot; - - (void)state; - - IMAGES_ITER(BOOT_CURR_IMG(state)) { -#if BOOT_IMAGE_NUMBER > 1 - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } -#endif - active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; - - BOOT_LOG_INF("Image %d loaded from the %s slot", - BOOT_CURR_IMG(state), - (active_slot == BOOT_PRIMARY_SLOT) ? - "primary" : "secondary"); - } -} -#endif - -#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT) -/** - * Checks whether the active slot of the current image was previously selected - * to run. Erases the image if it was selected but its execution failed, - * otherwise marks it as selected if it has not been before. - * - * @param state Boot loader status information. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_select_or_erase(struct boot_loader_state *state) -{ - const struct flash_area *fap; - int fa_id; - int rc; - uint32_t active_slot; - struct boot_swap_state* active_swap_state; - - active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; - - fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), active_slot); - rc = flash_area_open(fa_id, &fap); - assert(rc == 0); - - active_swap_state = &(state->slot_usage[BOOT_CURR_IMG(state)].swap_state); - - memset(active_swap_state, 0, sizeof(struct boot_swap_state)); - rc = boot_read_swap_state(fap, active_swap_state); - assert(rc == 0); - - if (active_swap_state->magic != BOOT_MAGIC_GOOD || - (active_swap_state->copy_done == BOOT_FLAG_SET && - active_swap_state->image_ok != BOOT_FLAG_SET)) { - /* - * A reboot happened without the image being confirmed at - * runtime or its trailer is corrupted/invalid. Erase the image - * to prevent it from being selected again on the next reboot. - */ - BOOT_LOG_DBG("Erasing faulty image in the %s slot.", - (active_slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); - rc = flash_area_erase(fap, 0, flash_area_get_size(fap)); - assert(rc == 0); - - flash_area_close(fap); - rc = -1; - } else { - if (active_swap_state->copy_done != BOOT_FLAG_SET) { - if (active_swap_state->copy_done == BOOT_FLAG_BAD) { - BOOT_LOG_DBG("The copy_done flag had an unexpected value. Its " - "value was neither 'set' nor 'unset', but 'bad'."); - } - /* - * Set the copy_done flag, indicating that the image has been - * selected to boot. It can be set in advance, before even - * validating the image, because in case the validation fails, the - * entire image slot will be erased (including the trailer). - */ - rc = boot_write_copy_done(fap); - if (rc != 0) { - BOOT_LOG_WRN("Failed to set copy_done flag of the image in " - "the %s slot.", (active_slot == BOOT_PRIMARY_SLOT) ? - "primary" : "secondary"); - rc = 0; - } - } - flash_area_close(fap); - } - - return rc; -} -#endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_DIRECT_XIP_REVERT */ - -#ifdef MCUBOOT_RAM_LOAD - -#ifndef MULTIPLE_EXECUTABLE_RAM_REGIONS -#if !defined(IMAGE_EXECUTABLE_RAM_START) || !defined(IMAGE_EXECUTABLE_RAM_SIZE) -#error "Platform MUST define executable RAM bounds in case of RAM_LOAD" -#endif -#endif - -/** - * Verifies that the active slot of the current image can be loaded within the - * predefined bounds that are allowed to be used by executable images. - * - * @param state Boot loader status information. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_verify_ram_load_address(struct boot_loader_state *state) -{ - uint32_t img_dst; - uint32_t img_sz; - uint32_t img_end_addr; - uint32_t exec_ram_start; - uint32_t exec_ram_size; - - (void)state; - -#ifdef MULTIPLE_EXECUTABLE_RAM_REGIONS - int rc; - - rc = boot_get_image_exec_ram_info(BOOT_CURR_IMG(state), &exec_ram_start, - &exec_ram_size); - if (rc != 0) { - return BOOT_EBADSTATUS; - } -#else - exec_ram_start = IMAGE_EXECUTABLE_RAM_START; - exec_ram_size = IMAGE_EXECUTABLE_RAM_SIZE; -#endif - - img_dst = state->slot_usage[BOOT_CURR_IMG(state)].img_dst; - img_sz = state->slot_usage[BOOT_CURR_IMG(state)].img_sz; - - if (img_dst < exec_ram_start) { - return BOOT_EBADIMAGE; - } - - if (!boot_u32_safe_add(&img_end_addr, img_dst, img_sz)) { - return BOOT_EBADIMAGE; - } - - if (img_end_addr > (exec_ram_start + exec_ram_size)) { - return BOOT_EBADIMAGE; - } - - return 0; -} - -#ifdef MCUBOOT_ENC_IMAGES - -/** - * Copies and decrypts an image from a slot in the flash to an SRAM address. - * - * @param state Boot loader status information. - * @param slot The flash slot of the image to be copied to SRAM. - * @param hdr The image header. - * @param src_sz Size of the image. - * @param img_dst Pointer to the address at which the image needs to be - * copied to SRAM. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_decrypt_and_copy_image_to_sram(struct boot_loader_state *state, - uint32_t slot, struct image_header *hdr, - uint32_t src_sz, uint32_t img_dst) -{ - /* The flow for the decryption and copy of the image is as follows : - * 1. The whole image is copied to the RAM (header + payload + TLV). - * 2. The encryption key is loaded from the TLV in flash. - * 3. The image is then decrypted chunk by chunk in RAM (1 chunk - * is 1024 bytes). Only the payload section is decrypted. - * 4. The image is authenticated in RAM. - */ - const struct flash_area *fap_src = NULL; - struct boot_status bs; - uint32_t blk_off; - uint32_t tlv_off; - uint32_t blk_sz; - uint32_t bytes_copied = hdr->ih_hdr_size; - uint32_t chunk_sz; - uint32_t max_sz = 1024; - uint16_t idx; - uint8_t * cur_dst; - int area_id; - int rc; - uint8_t * ram_dst = (void *)(IMAGE_RAM_BASE + img_dst); - - area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); - rc = flash_area_open(area_id, &fap_src); - if (rc != 0){ - return BOOT_EFLASH; - } - - tlv_off = BOOT_TLV_OFF(hdr); - - /* Copying the whole image in RAM */ - rc = flash_area_read(fap_src, 0, ram_dst, src_sz); - if (rc != 0) { - goto done; - } - - rc = boot_enc_load(BOOT_CURR_ENC(state), slot, hdr, fap_src, &bs); - if (rc < 0) { - goto done; - } - - /* if rc > 0 then the key has already been loaded */ - if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), slot, &bs)) { - goto done; - } - - /* Starting at the end of the header as the header section is not encrypted */ - while (bytes_copied < tlv_off) { /* TLV section copied previously */ - if (src_sz - bytes_copied > max_sz) { - chunk_sz = max_sz; - } else { - chunk_sz = src_sz - bytes_copied; - } - - cur_dst = ram_dst + bytes_copied; - blk_sz = chunk_sz; - idx = 0; - blk_off = ((bytes_copied) - hdr->ih_hdr_size) & 0xf; - if (bytes_copied + chunk_sz > tlv_off) { - /* Going over TLV section - * Part of the chunk is encrypted payload */ - blk_sz = tlv_off - (bytes_copied); - } - boot_enc_decrypt(BOOT_CURR_ENC(state), slot, - (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz, - blk_off, cur_dst); - bytes_copied += chunk_sz; - } - rc = 0; - -done: - flash_area_close(fap_src); - - return rc; -} - -#endif /* MCUBOOT_ENC_IMAGES */ -/** - * Copies a slot of the current image into SRAM. - * - * @param state Boot loader status information. - * @param slot The flash slot of the image to be copied to SRAM. - * @param img_dst The address at which the image needs to be copied to - * SRAM. - * @param img_sz The size of the image that needs to be copied to SRAM. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_copy_image_to_sram(struct boot_loader_state *state, int slot, - uint32_t img_dst, uint32_t img_sz) -{ - int rc; - const struct flash_area *fap_src = NULL; - int area_id; - -#if (BOOT_IMAGE_NUMBER == 1) - (void)state; -#endif - - area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); - - rc = flash_area_open(area_id, &fap_src); - if (rc != 0) { - return BOOT_EFLASH; - } - - /* Direct copy from flash to its new location in SRAM. */ - rc = flash_area_read(fap_src, 0, (void *)(IMAGE_RAM_BASE + img_dst), img_sz); - if (rc != 0) { - BOOT_LOG_INF("Error whilst copying image %d from Flash to SRAM: %d", - BOOT_CURR_IMG(state), rc); - } - - flash_area_close(fap_src); - - return rc; -} - -#if (BOOT_IMAGE_NUMBER > 1) -/** - * Checks if two memory regions (A and B) are overlap or not. - * - * @param start_a Start of the A region. - * @param end_a End of the A region. - * @param start_b Start of the B region. - * @param end_b End of the B region. - * - * @return true if there is overlap; false otherwise. - */ -static bool -do_regions_overlap(uint32_t start_a, uint32_t end_a, - uint32_t start_b, uint32_t end_b) -{ - if (start_b > end_a) { - return false; - } else if (start_b >= start_a) { - return true; - } else if (end_b > start_a) { - return true; - } - - return false; -} - -/** - * Checks if the image we want to load to memory overlap with an already - * ramloaded image. - * - * @param state Boot loader status information. - * - * @return 0 if there is no overlap; nonzero otherwise. - */ -static int -boot_check_ram_load_overlapping(struct boot_loader_state *state) -{ - uint32_t i; - - uint32_t start_a; - uint32_t end_a; - uint32_t start_b; - uint32_t end_b; - uint32_t image_id_to_check = BOOT_CURR_IMG(state); - - start_a = state->slot_usage[image_id_to_check].img_dst; - /* Safe to add here, values are already verified in - * boot_verify_ram_load_address() */ - end_a = start_a + state->slot_usage[image_id_to_check].img_sz; - - for (i = 0; i < BOOT_IMAGE_NUMBER; i++) { - if (state->slot_usage[i].active_slot == NO_ACTIVE_SLOT - || i == image_id_to_check) { - continue; - } - - start_b = state->slot_usage[i].img_dst; - /* Safe to add here, values are already verified in - * boot_verify_ram_load_address() */ - end_b = start_b + state->slot_usage[i].img_sz; - - if (do_regions_overlap(start_a, end_a, start_b, end_b)) { - return -1; - } - } - - return 0; -} -#endif - -/** - * Loads the active slot of the current image into SRAM. The load address and - * image size is extracted from the image header. - * - * @param state Boot loader status information. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_load_image_to_sram(struct boot_loader_state *state) -{ - uint32_t active_slot; - struct image_header *hdr = NULL; - uint32_t img_dst; - uint32_t img_sz; - int rc; - - active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; - hdr = boot_img_hdr(state, active_slot); - - if (hdr->ih_flags & IMAGE_F_RAM_LOAD) { - - img_dst = hdr->ih_load_addr; - - rc = boot_read_image_size(state, active_slot, &img_sz); - if (rc != 0) { - return rc; - } - - state->slot_usage[BOOT_CURR_IMG(state)].img_dst = img_dst; - state->slot_usage[BOOT_CURR_IMG(state)].img_sz = img_sz; - - rc = boot_verify_ram_load_address(state); - if (rc != 0) { - BOOT_LOG_INF("Image %d RAM load address 0x%x is invalid.", BOOT_CURR_IMG(state), img_dst); - return rc; - } - -#if (BOOT_IMAGE_NUMBER > 1) - rc = boot_check_ram_load_overlapping(state); - if (rc != 0) { - BOOT_LOG_INF("Image %d RAM loading to address 0x%x would overlap with\ - another image.", BOOT_CURR_IMG(state), img_dst); - return rc; - } -#endif -#ifdef MCUBOOT_ENC_IMAGES - /* decrypt image if encrypted and copy it to RAM */ - if (IS_ENCRYPTED(hdr)) { - rc = boot_decrypt_and_copy_image_to_sram(state, active_slot, hdr, img_sz, img_dst); - } else { - rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz); - } -#else - /* Copy image to the load address from where it currently resides in - * flash. - */ - rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz); -#endif - if (rc != 0) { - BOOT_LOG_INF("Image %d RAM loading to 0x%x is failed.", BOOT_CURR_IMG(state), img_dst); - } else { - BOOT_LOG_INF("Image %d RAM loading to 0x%x is succeeded.", BOOT_CURR_IMG(state), img_dst); - } - } else { - /* Only images that support IMAGE_F_RAM_LOAD are allowed if - * MCUBOOT_RAM_LOAD is set. - */ - rc = BOOT_EBADIMAGE; - } - - if (rc != 0) { - state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0; - state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0; - } - - return rc; -} - -/** - * Removes an image from SRAM, by overwriting it with zeros. - * - * @param state Boot loader status information. - * - * @return 0 on success; nonzero on failure. - */ -static inline int -boot_remove_image_from_sram(struct boot_loader_state *state) -{ - (void)state; - - BOOT_LOG_INF("Removing image %d from SRAM at address 0x%x", - BOOT_CURR_IMG(state), - state->slot_usage[BOOT_CURR_IMG(state)].img_dst); - - memset((void*)(IMAGE_RAM_BASE + state->slot_usage[BOOT_CURR_IMG(state)].img_dst), - 0, state->slot_usage[BOOT_CURR_IMG(state)].img_sz); - - state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0; - state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0; - - return 0; -} - -/** - * Removes an image from flash by erasing the corresponding flash area - * - * @param state Boot loader status information. - * @param slot The flash slot of the image to be erased. - * - * @return 0 on success; nonzero on failure. - */ -static inline int -boot_remove_image_from_flash(struct boot_loader_state *state, uint32_t slot) -{ - int area_id; - int rc; - const struct flash_area *fap; - - (void)state; - - BOOT_LOG_INF("Removing image %d slot %d from flash", BOOT_CURR_IMG(state), - slot); - area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot); - rc = flash_area_open(area_id, &fap); - if (rc == 0) { - flash_area_erase(fap, 0, flash_area_get_size(fap)); - flash_area_close(fap); - } - - return rc; -} -#endif /* MCUBOOT_RAM_LOAD */ - - -/** - * Tries to load a slot for all the images with validation. - * - * @param state Boot loader status information. - * - * @return 0 on success; nonzero on failure. - */ -fih_ret -boot_load_and_validate_images(struct boot_loader_state *state) -{ - uint32_t active_slot; - int rc; - fih_ret fih_rc; - - /* Go over all the images and try to load one */ - IMAGES_ITER(BOOT_CURR_IMG(state)) { - /* All slots tried until a valid image found. Breaking from this loop - * means that a valid image found or already loaded. If no slot is - * found the function returns with error code. */ - while (true) { - /* Go over all the slots and try to load one */ - active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; - if (active_slot != NO_ACTIVE_SLOT){ - /* A slot is already active, go to next image. */ - break; - } - - active_slot = find_slot_with_highest_version(state); - if (active_slot == NO_ACTIVE_SLOT) { - BOOT_LOG_INF("No slot to load for image %d", - BOOT_CURR_IMG(state)); - FIH_RET(FIH_FAILURE); - } - - /* Save the number of the active slot. */ - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = active_slot; - -#if BOOT_IMAGE_NUMBER > 1 - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } -#endif - -#ifdef MCUBOOT_DIRECT_XIP - rc = boot_rom_address_check(state); - if (rc != 0) { - /* The image is placed in an unsuitable slot. */ - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - continue; - } - -#ifdef MCUBOOT_DIRECT_XIP_REVERT - rc = boot_select_or_erase(state); - if (rc != 0) { - /* The selected image slot has been erased. */ - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - continue; - } -#endif /* MCUBOOT_DIRECT_XIP_REVERT */ -#endif /* MCUBOOT_DIRECT_XIP */ - -#ifdef MCUBOOT_RAM_LOAD - /* Image is first loaded to RAM and authenticated there in order to - * prevent TOCTOU attack during image copy. This could be applied - * when loading images from external (untrusted) flash to internal - * (trusted) RAM and image is authenticated before copying. - */ - rc = boot_load_image_to_sram(state); - if (rc != 0 ) { - /* Image cannot be ramloaded. */ - boot_remove_image_from_flash(state, active_slot); - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - continue; - } -#endif /* MCUBOOT_RAM_LOAD */ - - FIH_CALL(boot_validate_slot, fih_rc, state, active_slot, NULL); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - /* Image is invalid. */ -#ifdef MCUBOOT_RAM_LOAD - boot_remove_image_from_sram(state); -#endif /* MCUBOOT_RAM_LOAD */ - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - continue; - } - - /* Valid image loaded from a slot, go to next image. */ - break; - } - } - - FIH_RET(FIH_SUCCESS); -} - -/** - * Updates the security counter for the current image. - * - * @param state Boot loader status information. - * - * @return 0 on success; nonzero on failure. - */ -static int -boot_update_hw_rollback_protection(struct boot_loader_state *state) -{ -#ifdef MCUBOOT_HW_ROLLBACK_PROT - int rc; - - /* Update the stored security counter with the newer (active) image's - * security counter value. - */ -#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT) - /* When the 'revert' mechanism is enabled in direct-xip mode, the - * security counter can be increased only after reboot, if the image - * has been confirmed at runtime (the image_ok flag has been set). - * This way a 'revert' can be performed when it's necessary. - */ - if (state->slot_usage[BOOT_CURR_IMG(state)].swap_state.image_ok == BOOT_FLAG_SET) { -#endif - rc = boot_update_security_counter(BOOT_CURR_IMG(state), - state->slot_usage[BOOT_CURR_IMG(state)].active_slot, - boot_img_hdr(state, state->slot_usage[BOOT_CURR_IMG(state)].active_slot)); - if (rc != 0) { - BOOT_LOG_ERR("Security counter update failed after image %d validation.", BOOT_CURR_IMG(state)); - return rc; - } -#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT) - } -#endif - - return 0; - -#else /* MCUBOOT_HW_ROLLBACK_PROT */ - (void) (state); - return 0; -#endif -} - -fih_ret -context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) -{ - int rc; - FIH_DECLARE(fih_rc, FIH_FAILURE); - - rc = boot_get_slot_usage(state); - if (rc != 0) { - goto out; - } - -#if (BOOT_IMAGE_NUMBER > 1) - while (true) { -#endif - FIH_CALL(boot_load_and_validate_images, fih_rc, state); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - -#if (BOOT_IMAGE_NUMBER > 1) - rc = boot_verify_dependencies(state); - if (rc != 0) { - /* Dependency check failed for an image, it has been removed from - * SRAM in case of MCUBOOT_RAM_LOAD strategy, and set to - * unavailable. Try to load an image from another slot. - */ - continue; - } - /* Dependency check was successful. */ - break; - } -#endif - - IMAGES_ITER(BOOT_CURR_IMG(state)) { -#if BOOT_IMAGE_NUMBER > 1 - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } -#endif - rc = boot_update_hw_rollback_protection(state); - if (rc != 0) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - rc = boot_add_shared_data(state, (uint8_t)state->slot_usage[BOOT_CURR_IMG(state)].active_slot); - if (rc != 0) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - } - - /* All image loaded successfully. */ -#ifdef MCUBOOT_HAVE_LOGGING - print_loaded_images(state); -#endif - - fill_rsp(state, rsp); - -out: - close_all_flash_areas(state); - - if (rc != 0) { - FIH_SET(fih_rc, FIH_FAILURE); - } - - FIH_RET(fih_rc); -} -#endif /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */ - -/** - * Prepares the booting process. This function moves images around in flash as - * appropriate, and tells you what address to boot from. - * - * @param rsp On success, indicates how booting should occur. - * - * @return FIH_SUCCESS on success; nonzero on failure. - */ -fih_ret -boot_go(struct boot_rsp *rsp) -{ - FIH_DECLARE(fih_rc, FIH_FAILURE); - - boot_state_clear(NULL); - - FIH_CALL(context_boot_go, fih_rc, &boot_data, rsp); - FIH_RET(fih_rc); -} - -/** - * Prepares the booting process, considering only a single image. This function - * moves images around in flash as appropriate, and tells you what address to - * boot from. - * - * @param rsp On success, indicates how booting should occur. - * - * @param image_id The image ID to prepare the boot process for. - * - * @return FIH_SUCCESS on success; nonzero on failure. - */ -fih_ret -boot_go_for_image_id(struct boot_rsp *rsp, uint32_t image_id) -{ - FIH_DECLARE(fih_rc, FIH_FAILURE); - - if (image_id >= BOOT_IMAGE_NUMBER) { - FIH_RET(FIH_FAILURE); - } - -#if BOOT_IMAGE_NUMBER > 1 - memset(&boot_data.img_mask, 1, BOOT_IMAGE_NUMBER); - boot_data.img_mask[image_id] = 0; -#endif - - FIH_CALL(context_boot_go, fih_rc, &boot_data, rsp); - FIH_RET(fih_rc); -} - -/** - * Clears the boot state, so that previous operations have no effect on new - * ones. - * - * @param state The state that should be cleared. If the value - * is NULL, the default bootloader state will be - * cleared. - */ -void boot_state_clear(struct boot_loader_state *state) -{ - if (state != NULL) { - memset(state, 0, sizeof(struct boot_loader_state)); - } else { - memset(&boot_data, 0, sizeof(struct boot_loader_state)); - } -} - -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) -/** - * Reads image data to find out the maximum application sizes. Only needs to - * be called in serial recovery mode, as the state information is unpopulated - * at that time - */ -static void boot_fetch_slot_state_sizes(void) -{ - size_t slot; - int rc = -1; - int fa_id; - int image_index; - - IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) { - int max_size = 0; - - image_index = BOOT_CURR_IMG(&boot_data); - - BOOT_IMG(&boot_data, BOOT_PRIMARY_SLOT).sectors = - sector_buffers.primary[image_index]; - BOOT_IMG(&boot_data, BOOT_SECONDARY_SLOT).sectors = - sector_buffers.secondary[image_index]; -#if MCUBOOT_SWAP_USING_SCRATCH - boot_data.scratch.sectors = sector_buffers.scratch; -#endif - - /* Open primary and secondary image areas for the duration - * of this call. - */ - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { - fa_id = flash_area_id_from_multi_image_slot(image_index, slot); - rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, slot)); - assert(rc == 0); - - if (rc != 0) { - goto finish; - } - } - -#if MCUBOOT_SWAP_USING_SCRATCH - rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, - &BOOT_SCRATCH_AREA(&boot_data)); - assert(rc == 0); - - if (rc != 0) { - goto finish; - } -#endif - - /* Determine the sector layout of the image slots and scratch area. */ - rc = boot_read_sectors_recovery(&boot_data); - - if (rc == 0) { - max_size = app_max_size(&boot_data); - - if (max_size > 0) { - image_max_sizes[image_index].calculated = true; - image_max_sizes[image_index].max_size = max_size; - } - } - } - -finish: - close_all_flash_areas(&boot_data); - memset(&boot_data, 0x00, sizeof(boot_data)); -} -#endif - -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) -/** - * Fetches the maximum allowed size of the image - */ -const struct image_max_size *boot_get_max_app_size(void) -{ -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) - uint8_t i = 0; - - while (i < BOOT_IMAGE_NUMBER) { - if (image_max_sizes[i].calculated == true) { - break; - } - - ++i; - } - - if (i == BOOT_IMAGE_NUMBER) { - /* Information not available, need to fetch it */ - boot_fetch_slot_state_sizes(); - } -#endif - - return image_max_sizes; -} -#endif diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 3a3406465..528e90404 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -145,18 +145,8 @@ zephyr_library_sources( ) zephyr_library_include_directories(${BOOT_DIR}/bootutil/src) else() - if(NOT CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER EQUAL "-1") - # Sysbuild - zephyr_library_sources( - ${BOOT_DIR}/bootutil/src/loader.c - ) - else() - # Legacy child/parent image - zephyr_library_sources( - ${BOOT_DIR}/bootutil/src/loader_legacy_child_parent.c - ) - endif() zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/loader.c ${BOOT_DIR}/bootutil/src/swap_misc.c ${BOOT_DIR}/bootutil/src/swap_scratch.c ${BOOT_DIR}/bootutil/src/swap_move.c diff --git a/boot/zephyr/include/sysflash/pm_sysflash_legacy_child_parent.h b/boot/zephyr/include/sysflash/pm_sysflash_legacy_child_parent.h deleted file mode 100644 index db60ddd03..000000000 --- a/boot/zephyr/include/sysflash/pm_sysflash_legacy_child_parent.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef __PM_SYSFLASH_H__ -#define __PM_SYSFLASH_H__ -/* Blocking the __SYSFLASH_H__ */ -#define __SYSFLASH_H__ - -#include -#include -#include - -#ifndef CONFIG_SINGLE_APPLICATION_SLOT - -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -extern uint32_t _image_1_primary_slot_id[]; -#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ - -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) - -#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - -/* Each pair of slots is separated by , and there is no terminating character */ -#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID -#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID -#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID - -#if (MCUBOOT_IMAGE_NUMBER == 1) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 2) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ - FLASH_AREA_IMAGE_1_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 3) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ - FLASH_AREA_IMAGE_1_SLOTS, \ - FLASH_AREA_IMAGE_2_SLOTS -#else -#error Unsupported number of images -#endif - -static inline uint32_t __flash_area_ids_for_slot(int img, int slot) -{ - static const int all_slots[] = { - ALL_AVAILABLE_SLOTS - }; - return all_slots[img * 2 + slot]; -}; - -#undef FLASH_AREA_IMAGE_0_SLOTS -#undef FLASH_AREA_IMAGE_1_SLOTS -#undef FLASH_AREA_IMAGE_2_SLOTS -#undef ALL_AVAILABLE_SLOTS - -#define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) -#define FLASH_AREA_IMAGE_SECONDARY(x) __flash_area_ids_for_slot(x, 1) - -#if !defined(CONFIG_BOOT_SWAP_USING_MOVE) -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID -#endif - -#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - -#else /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID -/* NOTE: Scratch parition is not used by single image DFU but some of - * functions in common files reference it, so the definitions has been - * provided to allow compilation of common units. - */ -#define FLASH_AREA_IMAGE_SCRATCH 0 - -#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#endif /* __PM_SYSFLASH_H__ */ diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index bee101b2e..f231c3d02 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -7,13 +7,7 @@ #if USE_PARTITION_MANAGER /* Blocking the rest of the file */ #define __SYSFLASH_H__ -#if CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER != -1 -/* Sysbuild */ #include -#else -/* Legacy child/parent */ -#include -#endif #endif #ifndef __SYSFLASH_H__ From 99d4ae97314c413208746f1fb272eb4ecf85b3ea Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 5 Dec 2024 10:20:19 +0000 Subject: [PATCH 082/287] [nrf noup] boot: Remove child/parent references Removes stray child/parent references Signed-off-by: Jamie McCrae --- boot/bootutil/src/swap_priv.h | 2 +- boot/zephyr/pm.yml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index 2734d6262..719960f21 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -107,7 +107,7 @@ static inline size_t boot_scratch_area_size(const struct boot_loader_state *stat int app_max_size(struct boot_loader_state *state); #if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ -(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) +CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 /** * Performs an NSIB update */ diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index 13ffc44aa..ab8f6d1c3 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -4,9 +4,7 @@ mcuboot: size: CONFIG_PM_PARTITION_SIZE_MCUBOOT placement: before: [mcuboot_primary] -#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) align: {end: 0x1000} -#endif mcuboot_primary_app: # All images to be placed in MCUboot's slot 0 should be placed in this From c09c22a1b1c84a41dd0a1817c1c2802b8c6c4097 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 30 Dec 2024 11:46:19 +0000 Subject: [PATCH 083/287] [nrf noup] boot: bootutil: loader: Fix assignment typo nrf-squash! [nrf noup] treewide: Add support for sysbuild assigned images Fixes a typo with assignment variable name Signed-off-by: Jamie McCrae --- boot/bootutil/src/loader.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index f35ec7864..17623d268 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1399,24 +1399,24 @@ boot_update_security_counter(uint8_t image_index, int slot, #define SEC_SLOT_TOUCHED 1 #define SEC_SLOT_ASSIGNED 2 -static uint8_t sec_slot_assignmnet[MCUBOOT_IMAGE_NUMBER] = {0}; +static uint8_t sec_slot_assignment[MCUBOOT_IMAGE_NUMBER] = {0}; static inline void sec_slot_touch(struct boot_loader_state *state) { #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - if (sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { - sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + if (sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; } } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { - if (sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { - sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + if (sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; } } #endif - if (sec_slot_assignmnet[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) { - sec_slot_assignmnet[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED; + if (sec_slot_assignment[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED; } } @@ -1424,13 +1424,13 @@ static inline void sec_slot_mark_assigned(struct boot_loader_state *state) { #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { - sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; } #endif - sec_slot_assignmnet[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED; + sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED; } /** @@ -1447,7 +1447,7 @@ static void sec_slot_cleanup_if_unusable(void) uint8_t idx; for (idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) { - if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { + if (SEC_SLOT_TOUCHED == sec_slot_assignment[idx]) { const struct flash_area *secondary_fa; int rc; From 3a25855215a2cfc64c3f0e2dba3ada3f11df7816 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 30 Dec 2024 11:47:15 +0000 Subject: [PATCH 084/287] [nrf noup] boot: bootutil: loader: Fix triple erasing s0/s1 update nrf-squash! [nrf noup] treewide: Add support for sysbuild assigned images Fixes an issue whereby if an invalid s0/s1 slot update was loaded, then the slot would be erased 3 times instead of just once Signed-off-by: Jamie McCrae --- boot/bootutil/src/loader.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 17623d268..5fde7fa89 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1401,6 +1401,18 @@ boot_update_security_counter(uint8_t image_index, int slot, static uint8_t sec_slot_assignment[MCUBOOT_IMAGE_NUMBER] = {0}; +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; +} +#else +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ +} +#endif + static inline void sec_slot_touch(struct boot_loader_state *state) { #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 @@ -1467,6 +1479,9 @@ static void sec_slot_cleanup_if_unusable(void) } } #else +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ +} static inline void sec_slot_touch(struct boot_loader_state *state) { } @@ -1557,6 +1572,8 @@ boot_validated_swap_type(struct boot_loader_state *state, /* NSIB upgrade but for the wrong slot, must be erased */ BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image"); flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); + sec_slot_untouch(state); + BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", BOOT_CURR_IMG(state)); return BOOT_SWAP_TYPE_FAIL; } else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { /* The image in the secondary slot is not intended for any */ From a77e9f621e616d3373f9f3ad651df5776ba26507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 085/287] Revert "[nrf noup] boot: bootutil: loader: Fix triple erasing s0/s1 update" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 3a25855215a2cfc64c3f0e2dba3ada3f11df7816. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 5fde7fa89..17623d268 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1401,18 +1401,6 @@ boot_update_security_counter(uint8_t image_index, int slot, static uint8_t sec_slot_assignment[MCUBOOT_IMAGE_NUMBER] = {0}; -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 -static inline void sec_slot_untouch(struct boot_loader_state *state) -{ - sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; - sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; -} -#else -static inline void sec_slot_untouch(struct boot_loader_state *state) -{ -} -#endif - static inline void sec_slot_touch(struct boot_loader_state *state) { #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 @@ -1479,9 +1467,6 @@ static void sec_slot_cleanup_if_unusable(void) } } #else -static inline void sec_slot_untouch(struct boot_loader_state *state) -{ -} static inline void sec_slot_touch(struct boot_loader_state *state) { } @@ -1572,8 +1557,6 @@ boot_validated_swap_type(struct boot_loader_state *state, /* NSIB upgrade but for the wrong slot, must be erased */ BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image"); flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); - sec_slot_untouch(state); - BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", BOOT_CURR_IMG(state)); return BOOT_SWAP_TYPE_FAIL; } else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { /* The image in the secondary slot is not intended for any */ From e12b195fe6b397fd8accd8e7b6d922d0a5ea7758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 086/287] Revert "[nrf noup] boot: bootutil: loader: Fix assignment typo" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c09c22a1b1c84a41dd0a1817c1c2802b8c6c4097. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 17623d268..f35ec7864 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1399,24 +1399,24 @@ boot_update_security_counter(uint8_t image_index, int slot, #define SEC_SLOT_TOUCHED 1 #define SEC_SLOT_ASSIGNED 2 -static uint8_t sec_slot_assignment[MCUBOOT_IMAGE_NUMBER] = {0}; +static uint8_t sec_slot_assignmnet[MCUBOOT_IMAGE_NUMBER] = {0}; static inline void sec_slot_touch(struct boot_loader_state *state) { #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - if (sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { - sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + if (sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; } } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { - if (sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { - sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + if (sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; } } #endif - if (sec_slot_assignment[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) { - sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED; + if (sec_slot_assignmnet[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) { + sec_slot_assignmnet[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED; } } @@ -1424,13 +1424,13 @@ static inline void sec_slot_mark_assigned(struct boot_loader_state *state) { #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { - sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; } #endif - sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED; + sec_slot_assignmnet[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED; } /** @@ -1447,7 +1447,7 @@ static void sec_slot_cleanup_if_unusable(void) uint8_t idx; for (idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) { - if (SEC_SLOT_TOUCHED == sec_slot_assignment[idx]) { + if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { const struct flash_area *secondary_fa; int rc; From 4b683d47402c5b6499f082b5d6c37b7b90826945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 087/287] Revert "[nrf noup] boot: Remove child/parent references" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 99d4ae97314c413208746f1fb272eb4ecf85b3ea. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/swap_priv.h | 2 +- boot/zephyr/pm.yml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index 719960f21..2734d6262 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -107,7 +107,7 @@ static inline size_t boot_scratch_area_size(const struct boot_loader_state *stat int app_max_size(struct boot_loader_state *state); #if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ -CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) /** * Performs an NSIB update */ diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index ab8f6d1c3..13ffc44aa 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -4,7 +4,9 @@ mcuboot: size: CONFIG_PM_PARTITION_SIZE_MCUBOOT placement: before: [mcuboot_primary] +#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) align: {end: 0x1000} +#endif mcuboot_primary_app: # All images to be placed in MCUboot's slot 0 should be placed in this From 8a9e392f7990c022677ab734b31108eeefab2482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 088/287] Revert "[nrf fromtree] boot/zephyr/boards: configure fastest RRAM operations" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 032d1921d6cec90cd127d0ae53822bb2a7a990af. Signed-off-by: Andrzej Głąbek --- boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf | 3 --- boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf | 3 --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf | 3 --- 3 files changed, 9 deletions(-) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf index f911aa248..1b7a3616d 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf @@ -10,6 +10,3 @@ CONFIG_SPI_NOR=n CONFIG_FPROTECT=y CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf index f911aa248..1b7a3616d 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf @@ -10,6 +10,3 @@ CONFIG_SPI_NOR=n CONFIG_FPROTECT=y CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf index 1dbd7c1ab..8d8eb845f 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -11,6 +11,3 @@ CONFIG_SPI_NOR=n CONFIG_FPROTECT=n CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 From c47377e548256e124c30fdb6bf151a349051d032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 089/287] Revert "[nrf noup] boot/zephyr/boards: configure fastest RRAM operations" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 0a910b600a3ddeffd941fa59359e373a29d63bf3. Signed-off-by: Andrzej Głąbek --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf index 12650a9ed..8fc12e074 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -13,6 +13,3 @@ CONFIG_NORDIC_QSPI_NOR=n CONFIG_FPROTECT=n CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 From 41e6cfcf14af1c2c8da6752c68cb12452f9c63a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 090/287] Revert "[nrf noup] boot: zephyr: serial_recovery: Add nRF5340 Kconfig override" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b82206c15fff357c151c24bf97c99c4348d14a46. Signed-off-by: Andrzej Głąbek --- boot/zephyr/Kconfig.serial_recovery | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index 3119edddc..7ed9a7d9c 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -47,14 +47,9 @@ config BOOT_SERIAL_CDC_ACM endchoice -DT_COMPAT_SIM_FLASH:= zephyr,sim-flash -DT_SIM_FLASH_PATH := $(dt_nodelabel_path,flash_sim0) - config MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD bool "Allow to select image number for DFU" - # Allow this option to be selected in cases where support for direct uploading to nRF5340 - # network core should be supported - depends on !SINGLE_APPLICATION_SLOT || (SINGLE_APPLICATION_SLOT && SOC_NRF5340_CPUAPP && BOOT_IMAGE_ACCESS_HOOK_NRF5340 && FLASH_SIMULATOR && $(dt_compat_enabled,$(DT_COMPAT_SIM_FLASH))) + depends on !SINGLE_APPLICATION_SLOT help With the option enabled, the mcuboot serial recovery will respect the "image" field in mcumgr image update frame From 8b0afef678d5f5a427587408351a493fd5637b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 091/287] Revert "[nrf noup] boot: bootutil: image_validate: Add KMU support to compression" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 03434241388ea62363ffcb6cf332b4fa7b88626b. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/image_validate.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 64983b318..f71d1d9a6 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -815,7 +815,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #ifdef EXPECTED_SIG_TLV -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && defined(EXPECTED_KEY_TLV) +#ifdef EXPECTED_KEY_TLV rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); if (rc) { goto out; @@ -861,7 +861,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, */ } } -#endif /* !CONFIG_BOOT_SIGNATURE_USING_KMU && EXPECTED_KEY_TLV */ +#endif /* EXPECTED_KEY_TLV */ rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); if (rc) { @@ -884,12 +884,10 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; From 4a885d4fba0e20139244a10fad5d8b4fca034e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 092/287] Revert "[nrf noup] boot: bootutil: Allow configuring number of KMU keys" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 12e5ee106034972b0f1074d6f2261b2b39d1501b. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/ed25519_psa.c | 9 +++------ boot/zephyr/Kconfig | 12 ------------ 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 3042eeabf..83fc692a1 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2024 Nordic Semiconductor ASA + * Copyright (c) 2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ @@ -12,7 +12,6 @@ #include #include -#include #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #include #endif @@ -31,9 +30,7 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; - -BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), - "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); +#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) #endif #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) @@ -106,7 +103,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { + for (int i = 0; i < KMU_KEY_COUNT; ++i) { psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 77d57e15f..fd089a661 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -317,18 +317,6 @@ config BOOT_SIGNATURE_USING_KMU MCUboot will use keys provisioned to the device key management unit for signature verification instead of compiling in key data from a file. -if BOOT_SIGNATURE_USING_KMU - -config BOOT_SIGNATURE_KMU_SLOTS - int "KMU key slots" - range 1 3 - default 1 - help - Selects the number of KMU key slots (also known as generations) to use when verifying - an image. - -endif - if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 6ab18fd2dd16f0f006b5ff695fbd743e033bdbff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 093/287] Revert "[nrf fromtree] boot: zephyr: boards: nrf54l10 and nrf54l05 configs" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit eebb8abc831093d07978608a5ecd4e6fa18df920. Signed-off-by: Andrzej Głąbek --- boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf | 12 ------------ boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf | 12 ------------ 2 files changed, 24 deletions(-) delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf deleted file mode 100644 index 1b7a3616d..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -CONFIG_FPROTECT=y - -CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf deleted file mode 100644 index 1b7a3616d..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -CONFIG_FPROTECT=y - -CONFIG_BOOT_WATCHDOG_FEED=n From 3bc9ca275c328fb692cf734837a540962bab3744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 094/287] Revert "[nrf noup] boot: zephyr: Add experimental selection to compression" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ff3c31fba7e8eb659d8505e9c635057a2ca53987. Signed-off-by: Andrzej Głąbek --- boot/zephyr/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index fd089a661..6b47e8240 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -956,10 +956,9 @@ config BOOT_DECOMPRESSION_SUPPORT if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION - bool "Decompression [EXPERIMENTAL]" + bool "Decompression" select NRF_COMPRESS_CLEANUP select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP - select EXPERIMENTAL help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to From e0ca99af85ad49e1ef00b0a8da79ea12bc6d106b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 095/287] Revert "[nrf noup] bootutil: Add support for KMU stored ED25519 signature key" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 6e0c2b8794daa33d7688b35fc4af04c4d8052d41. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/ed25519_psa.c | 51 ------------------------------ boot/bootutil/src/image_ed25519.c | 19 +++-------- boot/bootutil/src/image_validate.c | 6 ---- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 29 +---------------- 5 files changed, 6 insertions(+), 101 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 83fc692a1..e84b71d2a 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,9 +12,6 @@ #include #include -#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) -#include -#endif BOOT_LOG_MODULE_REGISTER(ed25519_psa); @@ -22,18 +19,6 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define EDDSA_KEY_LENGTH 32 #define EDDSA_SIGNAGURE_LENGTH 64 -#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) -/* List of KMU stored key ids available for MCUboot */ -#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) -static psa_key_id_t kmu_key_ids[3] = { - MAKE_PSA_KMU_KEY_ID(226), - MAKE_PSA_KMU_KEY_ID(228), - MAKE_PSA_KMU_KEY_ID(230) -}; -#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) -#endif - -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -84,39 +69,3 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } -#else -int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], - const uint8_t public_key[EDDSA_KEY_LENGTH]) -{ - ARG_UNUSED(public_key); - /* Set to any error */ - psa_status_t status = PSA_ERROR_BAD_STATE; - int ret = 0; /* Fail by default */ - - /* Initialize PSA Crypto */ - status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", status); - return 0; - } - - status = PSA_ERROR_BAD_STATE; - - for (int i = 0; i < KMU_KEY_COUNT; ++i) { - psa_key_id_t kid = kmu_key_ids[i]; - - status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, - message_len, signature, - EDDSA_SIGNAGURE_LENGTH); - if (status == PSA_SUCCESS) { - ret = 1; - break; - } - - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); - } - - return ret; -} -#endif diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index e6c792a99..40d494bcf 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -25,16 +25,14 @@ #include "bootutil/crypto/sha.h" #define EDDSA_SIGNATURE_LENGTH 64 + +static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; #define NUM_ED25519_BYTES 32 extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) - -static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; - /* * Parse the public key used for signing. */ @@ -73,7 +71,6 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } -#endif fih_ret bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, @@ -81,17 +78,14 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) + uint8_t *pubkey; uint8_t *end; -#endif if (hlen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -100,7 +94,6 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, FIH_SET(fih_rc, FIH_FAILURE); goto out; } -#endif rc = ED25519_verify(hash, IMAGE_HASH_SIZE, sig, pubkey); @@ -122,17 +115,14 @@ bootutil_verify_img(const uint8_t *img, uint32_t size, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) + uint8_t *pubkey; uint8_t *end; -#endif if (slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -141,7 +131,6 @@ bootutil_verify_img(const uint8_t *img, uint32_t size, FIH_SET(fih_rc, FIH_FAILURE); goto out; } -#endif rc = ED25519_verify(img, size, sig, pubkey); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index f71d1d9a6..c419b9497 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -245,7 +245,6 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_HW_KEY) static int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) @@ -311,7 +310,6 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) } #endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ /** @@ -628,7 +626,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, break; } #endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { @@ -659,17 +656,14 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, break; } #endif /* EXPECTED_KEY_TLV */ -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 528e90404..4587681e5 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -303,7 +303,7 @@ if(CONFIG_MCUBOOT_SERIAL) endif() endif() -if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU AND NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") +if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") # CONF_FILE points to the KConfig configuration files of the bootloader. foreach (filepath ${CONF_FILE}) file(READ ${filepath} temp_text) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 6b47e8240..29e4f0bb7 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -293,7 +293,6 @@ config BOOT_ED25519_MBEDTLS config BOOT_ED25519_PSA bool "Use PSA crypto" - depends on NRF_SECURITY select BOOT_USE_PSA_CRYPTO select BOOT_ED25519_PSA_DEPENDENCIES select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE @@ -303,22 +302,6 @@ endif endchoice -config BOOT_SIGNATURE_USING_KMU - bool "Use KMU stored keys for signature verification" - depends on NRF_SECURITY - depends on CRACEN_LIB_KMU - select PSA_WANT_ALG_GCM - select PSA_WANT_KEY_TYPE_AES - select PSA_WANT_AES_KEY_SIZE_256 - select PSA_WANT_ALG_SP800_108_COUNTER_CMAC - select PSA_WANT_ALG_CMAC - select PSA_WANT_ALG_ECB_NO_PADDING - help - MCUboot will use keys provisioned to the device key management unit for signature - verification instead of compiling in key data from a file. - -if !BOOT_SIGNATURE_USING_KMU - config BOOT_SIGNATURE_KEY_FILE string "PEM key file" default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 @@ -336,8 +319,6 @@ config BOOT_SIGNATURE_KEY_FILE with the public key information will be written in a format expected by MCUboot. -endif - config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" depends on CPU_CORTEX_M @@ -360,18 +341,10 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. -# Disable MBEDTLS from being selected if NRF_SECURITY is enabled, and use default NRF_SECURITY -# configuration file for MBEDTLS -config MBEDTLS - depends on !NRF_SECURITY - -config NRF_SECURITY - select MBEDTLS_PROMPTLESS - if MBEDTLS config MBEDTLS_CFG_FILE - default "mcuboot-mbedtls-cfg.h" if !NRF_SECURITY + default "mcuboot-mbedtls-cfg.h" endif From e603ce07e6d515ed1a73778db818bd10cd6ad76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 096/287] Revert "[nrf noup] boot/zephyr/Kconfig: conditionally disable BOOT_MAX_IMG_SECTORS_AUTO" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit d09c5a0cdcc4e4a115d1a77f961a031598a93b5c. Signed-off-by: Andrzej Głąbek --- boot/zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 29e4f0bb7..6c5b88a87 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -563,7 +563,7 @@ config BOOT_ENCRYPTION_KEY_FILE config BOOT_MAX_IMG_SECTORS_AUTO bool "Calculate maximum sectors automatically" - default y if !PARTITION_MANAGER_ENABLED + default y help If this option is enabled then the maximum number of supported sectors per image will be calculated automatically from the flash erase sizes and size of each partition for From 42ba2a505b323722de9d6024944f994b78287bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 097/287] Revert "[nrf noup] bootutil: PureEdDSA using ED25519" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 1a2f5f68aad108cb79d91779e82c8f9ea1d1f594. Signed-off-by: Andrzej Głąbek --- boot/bootutil/include/bootutil/image.h | 3 - boot/bootutil/src/bootutil_priv.h | 3 - boot/bootutil/src/image_ed25519.c | 37 -------- boot/bootutil/src/image_validate.c | 95 ++----------------- boot/zephyr/Kconfig | 29 +----- .../include/mcuboot_config/mcuboot_config.h | 4 - 6 files changed, 8 insertions(+), 163 deletions(-) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 05e04438b..9ede800a2 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -102,9 +102,6 @@ struct flash_area; #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 */ diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index c23f61689..208d189b9 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -268,9 +268,6 @@ struct boot_loader_state { fih_ret bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t key_id); -fih_ret bootutil_verify_img(const uint8_t *img, uint32_t size, - uint8_t *sig, size_t slen, uint8_t key_id); - fih_ret boot_fih_memequal(const void *s1, const void *s2, size_t n); int boot_find_status(int image_index, const struct flash_area **fap); diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 40d494bcf..447289253 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -109,41 +109,4 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, FIH_RET(fih_rc); } -fih_ret -bootutil_verify_img(const uint8_t *img, uint32_t size, - uint8_t *sig, size_t slen, uint8_t key_id) -{ - int rc; - FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey; - uint8_t *end; - - if (slen != EDDSA_SIGNATURE_LENGTH) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - pubkey = (uint8_t *)bootutil_keys[key_id].key; - end = pubkey + *bootutil_keys[key_id].len; - - rc = bootutil_import_key(&pubkey, end); - if (rc) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - rc = ED25519_verify(img, size, sig, pubkey); - - if (rc == 0) { - /* if verify returns 0, there was an error. */ - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - FIH_SET(fih_rc, FIH_SUCCESS); -out: - - FIH_RET(fih_rc); -} - #endif /* MCUBOOT_SIGN_ED25519 */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index c419b9497..fa1d373d7 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -65,7 +65,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil_priv.h" -#ifndef MCUBOOT_SIGN_PURE /* * Compute SHA hash over the image. * (SHA384 if ECDSA-P384 is being used, @@ -185,7 +184,6 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, return 0; } -#endif /* * Currently, we only support being able to verify one type of @@ -372,43 +370,6 @@ bootutil_get_img_security_cnt(struct image_header *hdr, return 0; } -#if defined(MCUBOOT_SIGN_PURE) -/* Returns: - * 0 -- found - * 1 -- not found or found but not true - * -1 -- failed for some reason - * - * Value of TLV does not matter, presence decides. - */ -static int bootutil_check_for_pure(const struct image_header *hdr, - const struct flash_area *fap) -{ - struct image_tlv_iter it; - uint32_t off; - uint16_t len; - int32_t rc; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_SIG_PURE, false); - if (rc) { - return rc; - } - - /* Search for the TLV */ - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - if (rc == 0 && len == 1) { - bool val; - - rc = LOAD_IMAGE_DATA(hdr, fap, off, &val, 1); - if (rc == 0) { - rc = !val; - } - } - - return rc; -} -#endif - - #ifndef ALLOW_ROGUE_TLVS /* * The following list of TLVs are the only entries allowed in the unprotected @@ -425,9 +386,6 @@ static const uint16_t allowed_unprot_tlvs[] = { IMAGE_TLV_ECDSA_SIG, IMAGE_TLV_RSA3072_PSS, IMAGE_TLV_ED25519, -#if defined(MCUBOOT_SIGN_PURE) - IMAGE_TLV_SIG_PURE, -#endif IMAGE_TLV_ENC_RSA2048, IMAGE_TLV_ENC_KW, IMAGE_TLV_ENC_EC256, @@ -450,6 +408,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, uint32_t off; uint16_t len; uint16_t type; + int image_hash_valid = 0; #ifdef EXPECTED_SIG_TLV FIH_DECLARE(valid_signature, FIH_FAILURE); #ifndef MCUBOOT_BUILTIN_KEY @@ -466,10 +425,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, #endif /* EXPECTED_SIG_TLV */ struct image_tlv_iter it; uint8_t buf[SIG_BUF_SIZE]; -#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) - int image_hash_valid = 0; uint8_t hash[IMAGE_HASH_SIZE]; -#endif int rc = 0; FIH_DECLARE(fih_rc, FIH_FAILURE); #ifdef MCUBOOT_HW_ROLLBACK_PROT @@ -540,7 +496,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #endif -#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); if (rc) { @@ -550,15 +505,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (out_hash) { memcpy(out_hash, hash, IMAGE_HASH_SIZE); } -#endif - -#if defined(MCUBOOT_SIGN_PURE) - /* If Pure type signature is expected then it has to be there */ - rc = bootutil_check_for_pure(hdr, fap); - if (rc != 0) { - goto out; - } -#endif rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); if (rc) { @@ -602,10 +548,8 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } } #endif - switch(type) { -#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) - case EXPECTED_HASH_TLV: - { + + if (type == EXPECTED_HASH_TLV) { /* Verify the image hash. This must always be present. */ if (len != sizeof(hash)) { rc = -1; @@ -623,12 +567,8 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } image_hash_valid = 1; - break; - } -#endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ #ifdef EXPECTED_KEY_TLV - case EXPECTED_KEY_TLV: - { + } else if (type == EXPECTED_KEY_TLV) { /* * Determine which key we should be checking. */ @@ -653,12 +593,9 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, * The key may not be found, which is acceptable. There * can be multiple signatures, each preceded by a key. */ - break; - } #endif /* EXPECTED_KEY_TLV */ #ifdef EXPECTED_SIG_TLV - case EXPECTED_SIG_TLV: - { + } else if (type == EXPECTED_SIG_TLV) { /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; @@ -672,25 +609,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (rc) { goto out; } -#ifndef MCUBOOT_SIGN_PURE FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), buf, len, key_id); -#else - /* Directly check signature on the image, by using the mapping of - * a device to memory. The pointer is beginning of image in flash, - * so offset of area, the range is header + image + protected tlvs. - */ - FIH_CALL(bootutil_verify_img, valid_signature, (void *)flash_area_get_off(fap), - hdr->ih_hdr_size + hdr->ih_img_size + hdr->ih_protect_tlv_size, - buf, len, key_id); -#endif key_id = -1; - break; - } #endif /* EXPECTED_SIG_TLV */ #ifdef MCUBOOT_HW_ROLLBACK_PROT - case IMAGE_TLV_SEC_CNT: - { + } else if (type == IMAGE_TLV_SEC_CNT) { /* * Verify the image's security counter. * This must always be present. @@ -725,21 +649,14 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, /* The image's security counter has been successfully verified. */ security_counter_valid = fih_rc; - break; - } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ } } -#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = !image_hash_valid; if (rc) { goto out; } -#elif defined(MCUBOOT_SIGN_PURE) - /* This returns true on EQ, rc is err on non-0 */ - rc = FIH_NOT_EQ(valid_signature, FIH_SUCCESS); -#endif #ifdef EXPECTED_SIG_TLV FIH_SET(fih_rc, valid_signature); #endif diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 6c5b88a87..bb73e32f2 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -192,14 +192,6 @@ config BOOT_IMG_HASH_ALG_SHA512 endchoice # BOOT_IMG_HASH_ALG -config BOOT_SIGNATURE_TYPE_PURE_ALLOW - bool - help - Hidden option set by configurations that allow Pure variant, - for example ed25519. The pure variant means that image - signature is calculated over entire image instead of hash - of an image. - choice BOOT_SIGNATURE_TYPE prompt "Signature type" default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP @@ -250,32 +242,15 @@ endif config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" - select BOOT_ENCRYPTION_SUPPORT if !BOOT_SIGNATURE_TYPE_PURE - select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !BOOT_SIGNATURE_TYPE_PURE - # The SHA is used only for key hashing, not for images. + select BOOT_ENCRYPTION_SUPPORT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW select BOOT_IMG_HASH_ALG_SHA512_ALLOW if BOOT_USE_PSA_CRYPTO - select BOOT_SIGNATURE_TYPE_PURE_ALLOW help This is ed25519 signature calculated over SHA512 of SHA256 of application image; that is not completely correct approach as the SHA512 should be rather directly calculated over an image. - Select BOOT_SIGNATURE_TYPE_PURE to have a PureEdDSA calculating image - signature directly on image, rather than hash of the image. if BOOT_SIGNATURE_TYPE_ED25519 - -config BOOT_SIGNATURE_TYPE_PURE - bool "Use Pure signature of image" - depends on BOOT_SIGNATURE_TYPE_PURE_ALLOW - help - The Pure signature is calculated directly over image rather than - hash of an image. - This is more secure signature, specifically if hardware can do the - verification without need to share key. - Note that this requires that all slots for which signature is to be - verified need to be accessible through memory address space that - cryptography can access. - choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" default BOOT_ED25519_TINYCRYPT diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 7896e0939..fbd64b5e7 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -147,10 +147,6 @@ #define MCUBOOT_HASH_STORAGE_DIRECTLY #endif -#ifdef CONFIG_BOOT_SIGNATURE_TYPE_PURE -#define MCUBOOT_SIGN_PURE -#endif - #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From f1ef3cb7a63ca9c02912d450760e33e32e4822a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 098/287] Revert "[nrf noup] bootutil: Enable hash calculation directly on storage" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b2ad117bd7cb645731625bf5ca574abf788110e2. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/image_validate.c | 15 +++------------ boot/zephyr/Kconfig | 16 ---------------- .../include/mcuboot_config/mcuboot_config.h | 7 ------- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index fa1d373d7..b1a50f126 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -77,15 +77,13 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, uint8_t *seed, int seed_len) { bootutil_sha_context sha_ctx; + uint32_t blk_sz; uint32_t size; uint16_t hdr_size; + uint32_t off; + int rc; uint32_t blk_off; uint32_t tlv_off; -#if !defined(MCUBOOT_HASH_STORAGE_DIRECTLY) - int rc; - uint32_t off; - uint32_t blk_sz; -#endif #if (BOOT_IMAGE_NUMBER == 1) || !defined(MCUBOOT_ENC_IMAGES) || \ defined(MCUBOOT_RAM_LOAD) @@ -128,12 +126,6 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, /* If protected TLVs are present they are also hashed. */ size += hdr->ih_protect_tlv_size; -#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY - /* No chunk loading, storage is mapped to address space and can - * be directly given to hashing function. - */ - bootutil_sha_update(&sha_ctx, (void *)flash_area_get_off(fap), size); -#else /* MCUBOOT_HASH_STORAGE_DIRECTLY */ #ifdef MCUBOOT_RAM_LOAD bootutil_sha_update(&sha_ctx, (void*)(IMAGE_RAM_BASE + hdr->ih_load_addr), @@ -178,7 +170,6 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, bootutil_sha_update(&sha_ctx, tmp_buf, blk_sz); } #endif /* MCUBOOT_RAM_LOAD */ -#endif /* MCUBOOT_HASH_STORAGE_DIRECTLY */ bootutil_sha_finish(&sha_ctx, hash_result); bootutil_sha_drop(&sha_ctx); diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index bb73e32f2..abb7bc2ae 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -146,22 +146,6 @@ config BOOT_IMG_HASH_ALG_SHA512_ALLOW help Hidden option set by configurations that allow SHA512 -config BOOT_IMG_HASH_DIRECTLY_ON_STORAGE - bool "Hash calculation functions access storage through address space" - depends on !BOOT_ENCRYPT_IMAGE - help - When possible to map storage device, at least for read operations, - to address space or RAM area, enabling this option allows hash - calculation functions to directly access the storage through that address - space or using its own DMA. This reduces flash read overhead done - by the MCUboot. - Notes: - - not supported when encrypted images are in use, because calculating - SHA requires image to be decrypted first, which is done to RAM. - - currently only supported on internal storage of devices; this - option will not work with devices that use external storage for - either of image slots. - choice BOOT_IMG_HASH_ALG prompt "Selected image hash algorithm" default BOOT_IMG_HASH_ALG_SHA256 if BOOT_IMG_HASH_ALG_SHA256_ALLOW diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index fbd64b5e7..f628f99c4 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -140,13 +140,6 @@ #define MCUBOOT_DECOMPRESS_IMAGES #endif -/* Invoke hashing functions directly on storage. This requires for device - * to be able to map storage to address space or RAM. - */ -#ifdef CONFIG_BOOT_IMG_HASH_DIRECTLY_ON_STORAGE -#define MCUBOOT_HASH_STORAGE_DIRECTLY -#endif - #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From ed414694ca7775851305632d3dcc89f42242f203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 099/287] Revert "[nrf noup] bootutil: Provide support for SHA512 with ED25519" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 5a6676cf392232b671cabb7dbf242d01f2ec5d6b. Signed-off-by: Andrzej Głąbek --- boot/zephyr/Kconfig | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index abb7bc2ae..cb64488a5 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -80,7 +80,7 @@ config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES config BOOT_ED25519_PSA_DEPENDENCIES bool - select PSA_WANT_ALG_SHA_256 if BOOT_IMG_HASH_ALG_SHA256 + select PSA_WANT_ALG_SHA_256 select PSA_WANT_ALG_SHA_512 select PSA_WANT_ALG_PURE_EDDSA select PSA_WANT_ECC_TWISTED_EDWARDS_255 @@ -228,11 +228,6 @@ config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" select BOOT_ENCRYPTION_SUPPORT select BOOT_IMG_HASH_ALG_SHA256_ALLOW - select BOOT_IMG_HASH_ALG_SHA512_ALLOW if BOOT_USE_PSA_CRYPTO - help - This is ed25519 signature calculated over SHA512 of SHA256 of application - image; that is not completely correct approach as the SHA512 should be - rather directly calculated over an image. if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION From 5a8d7a270e296c009af050396994a7f13851c915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 100/287] Revert "[nrf noup] PSA configuration required changes" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 00f35bb1a4e0dd9f29cf9056674c28f72202fa4a. Signed-off-by: Andrzej Głąbek --- boot/bootutil/zephyr/CMakeLists.txt | 14 ++--- boot/zephyr/CMakeLists.txt | 39 ++++-------- boot/zephyr/Kconfig | 73 +---------------------- boot/zephyr/include/mcuboot-mbedtls-cfg.h | 2 +- 4 files changed, 16 insertions(+), 112 deletions(-) diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index d5364d025..72a6a8638 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -29,18 +29,12 @@ zephyr_library_link_libraries(MCUBOOT_BOOTUTIL) target_link_libraries(MCUBOOT_BOOTUTIL INTERFACE zephyr_interface) if(CONFIG_BOOT_USE_TINYCRYPT) - target_include_directories(MCUBOOT_BOOTUTIL INTERFACE - ../../../ext/tinycrypt/lib/include - ) -endif() - -if(CONFIG_BOOT_USE_PSA_CRYPTO) - target_include_directories(MCUBOOT_BOOTUTIL INTERFACE - ${ZEPHYR_MBEDTLS_MODULE_DIR}/include - ) +target_include_directories(MCUBOOT_BOOTUTIL INTERFACE + ../../../ext/tinycrypt/lib/include +) endif() -if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO AND NOT CONFIG_PSA_CORE_OBERON) +if(CONFIG_BOOT_USE_MBEDTLS) zephyr_link_libraries(mbedTLS) endif() endif() diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 4587681e5..839dd12b3 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -51,12 +51,6 @@ if(EXISTS targets/${BOARD}.h) zephyr_library_compile_definitions(MCUBOOT_TARGET_CONFIG="${BOARD}.h") endif() -if(DEFINED CONFIG_MBEDTLS) - zephyr_library_include_directories( - ${ZEPHYR_MBEDTLS_MODULE_DIR}/include - ) -endif() - # Zephyr port-specific sources. zephyr_library_sources( main.c @@ -108,10 +102,6 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/fault_injection_hardening.c ) -if(DEFINED CONFIG_BOOT_ENCRYPT_X25519 AND DEFINED CONFIG_BOOT_ED25519_PSA) - zephyr_library_sources(${BOOT_DIR}/bootutil/src/encrypted_psa.c) -endif() - if(DEFINED CONFIG_MEASURED_BOOT OR DEFINED CONFIG_BOOT_SHARE_DATA) zephyr_library_sources( ${BOOT_DIR}/bootutil/src/boot_record.c @@ -246,28 +236,19 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) ${FIAT_DIR}/include/ ) - if(NOT CONFIG_BOOT_ED25519_PSA) - zephyr_library_sources( - ${FIAT_DIR}/src/curve25519.c - ) - else() - zephyr_library_sources( - ${MBEDTLS_ASN1_DIR}/src/asn1parse.c - ${BOOT_DIR}/bootutil/src/ed25519_psa.c - ) - endif() + zephyr_library_sources( + ${FIAT_DIR}/src/curve25519.c + ) endif() -if(NOT CONFIG_BOOT_ED25519_PSA) - if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) - zephyr_library_sources( - ${TINYCRYPT_DIR}/source/aes_encrypt.c - ${TINYCRYPT_DIR}/source/aes_decrypt.c - ${TINYCRYPT_DIR}/source/ctr_mode.c - ${TINYCRYPT_DIR}/source/hmac.c - ${TINYCRYPT_DIR}/source/ecc_dh.c +if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) + zephyr_library_sources( + ${TINYCRYPT_DIR}/source/aes_encrypt.c + ${TINYCRYPT_DIR}/source/aes_decrypt.c + ${TINYCRYPT_DIR}/source/ctr_mode.c + ${TINYCRYPT_DIR}/source/hmac.c + ${TINYCRYPT_DIR}/source/ecc_dh.c ) - endif() endif() if(CONFIG_BOOT_ENCRYPT_EC256) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index cb64488a5..7f36a45dc 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -29,10 +29,7 @@ config BOOT_USE_MBEDTLS config BOOT_USE_PSA_CRYPTO bool - default y if NRF_SECURITY - # This is counter intuitive but that is how PSA heap is enabled. - select MBEDTLS_ENABLE_HEAP - select MBEDTLS_PSA_CRYPTO_C + # Hidden option help Hidden option set if using PSA crypt for cryptography functionality @@ -69,58 +66,6 @@ config NRF_CC310_BL bool default n -if BOOT_USE_PSA_CRYPTO - -config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES - bool - default y if BOOT_IMG_HASH_ALG_SHA256 - select PSA_WANT_ALG_SHA_256 - help - Dependencies for hashing with SHA256 - -config BOOT_ED25519_PSA_DEPENDENCIES - bool - select PSA_WANT_ALG_SHA_256 - select PSA_WANT_ALG_SHA_512 - select PSA_WANT_ALG_PURE_EDDSA - select PSA_WANT_ECC_TWISTED_EDWARDS_255 - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT - help - Dependencies for ed25519 signature - -if BOOT_ENCRYPT_IMAGE - -config BOOT_X25519_PSA_DEPENDENCIES - bool - select PSA_WANT_ALG_ECDH - select PSA_WANT_ALG_HMAC - select PSA_WANT_ALG_HKDF - select PSA_WANT_ALG_CTR - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT - select PSA_WANT_KEY_TYPE_DERIVE - select PSA_WANT_KEY_TYPE_AES - select PSA_WANT_ECC_MONTGOMERY_255 - help - Dependencies for x25519 shared-random key encryption and AES - encryption. The PSA_WANT_ALG_CTR and PSA_WANT_KEY_TYPE_AES - enable Counter based block cipher and AES key, and algorithm support, - to use with it; the others are used for shared key decryption - and derivation. - -endif # BOOT_ENCRYPT_IMAGE - -if MBEDTLS_ENABLE_HEAP - -config MBEDTLS_HEAP_SIZE - default 2048 if BOOT_USE_PSA_CRYPTO - help - The PSA internals need to be able to allocate memory for operation - and it uses mbedTLS heap for that. - -endif # MBEDTLS_ENABLE_HEAP - -endif # BOOT_USE_PSA_CRYPTO - menu "MCUBoot settings" config SINGLE_APPLICATION_SLOT @@ -178,7 +123,6 @@ endchoice # BOOT_IMG_HASH_ALG choice BOOT_SIGNATURE_TYPE prompt "Signature type" - default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP default BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_NONE @@ -233,24 +177,13 @@ if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" default BOOT_ED25519_TINYCRYPT - config BOOT_ED25519_TINYCRYPT bool "Use tinycrypt" select BOOT_USE_TINYCRYPT - depends on !NRF_SECURITY - config BOOT_ED25519_MBEDTLS bool "Use mbedTLS" select BOOT_USE_MBEDTLS select MBEDTLS - depends on !NRF_SECURITY - -config BOOT_ED25519_PSA - bool "Use PSA crypto" - select BOOT_USE_PSA_CRYPTO - select BOOT_ED25519_PSA_DEPENDENCIES - select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE - endchoice endif @@ -295,13 +228,9 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. -if MBEDTLS - config MBEDTLS_CFG_FILE default "mcuboot-mbedtls-cfg.h" -endif - config BOOT_HW_KEY bool "Use HW key for image verification" default n diff --git a/boot/zephyr/include/mcuboot-mbedtls-cfg.h b/boot/zephyr/include/mcuboot-mbedtls-cfg.h index a46fbb09f..2bab537d7 100644 --- a/boot/zephyr/include/mcuboot-mbedtls-cfg.h +++ b/boot/zephyr/include/mcuboot-mbedtls-cfg.h @@ -23,7 +23,7 @@ #if defined(CONFIG_BOOT_SIGNATURE_TYPE_RSA) || defined(CONFIG_BOOT_ENCRYPT_RSA) #include "config-rsa.h" -#elif defined(CONFIG_BOOT_USE_PSA_CRYPTO) || defined(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256) || \ +#elif defined(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256) || \ defined(CONFIG_BOOT_ENCRYPT_EC256) || \ (defined(CONFIG_BOOT_ENCRYPT_X25519) && !defined(CONFIG_BOOT_SIGNATURE_TYPE_ED25519)) #include "config-asn1.h" From 1f20f287501a2380beb9601ba7f240b50515ca3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 101/287] Revert "[nrf fromtree] zephyr: Add CONFIG_MCUBOOT_CLEANUP_RAM" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 534580bc1b170ef54658151c5e102ddaa7ff2922. Signed-off-by: Andrzej Głąbek --- boot/zephyr/Kconfig | 6 ------ boot/zephyr/main.c | 27 --------------------------- 2 files changed, 33 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 7f36a45dc..34c6be3a4 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -222,12 +222,6 @@ config MCUBOOT_CLEANUP_ARM_CORE start-up code which can cause a module fault and potentially make the module irrecoverable. -config MCUBOOT_CLEANUP_RAM - bool "Perform RAM cleanup" - depends on CPU_CORTEX_M4 || CPU_CORTEX_M33 - help - Sets contents of memory to 0 before jumping to application. - config MBEDTLS_CFG_FILE default "mcuboot-mbedtls-cfg.h" diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index fcc2606e2..351ca4c89 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -271,34 +271,7 @@ static void do_boot(struct boot_rsp *rsp) __set_CONTROL(0x00); /* application will configures core on its own */ __ISB(); #endif -#if CONFIG_MCUBOOT_CLEANUP_RAM - __asm__ volatile ( - /* vt->reset -> r0 */ - " mov r0, %0\n" - /* base to write -> r1 */ - " mov r1, %1\n" - /* size to write -> r2 */ - " mov r2, %2\n" - /* value to write -> r3 */ - " mov r3, %3\n" - "clear:\n" - " str r3, [r1]\n" - " add r1, r1, #4\n" - " sub r2, r2, #4\n" - " cbz r2, out\n" - " b clear\n" - "out:\n" - " dsb\n" - /* jump to reset vector of an app */ - " bx r0\n" - : - : "r" (vt->reset), "i" (CONFIG_SRAM_BASE_ADDRESS), - "i" (CONFIG_SRAM_SIZE * 1024), "i" (0) - : "r0", "r1", "r2", "r3", "memory" - ); -#else ((void (*)(void))vt->reset)(); -#endif } #elif defined(CONFIG_XTENSA) || defined(CONFIG_RISCV) From 5555a242e6ae0256639b2e0cdf5e010e5235d563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 102/287] Revert "[nrf noup] Fix logging for ED25519_psa" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c8829648a3617e988a52a56b1d56b83c67438c38. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/ed25519_psa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index e84b71d2a..3d7274307 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -13,7 +13,7 @@ #include #include -BOOT_LOG_MODULE_REGISTER(ed25519_psa); +BOOT_LOG_MODULE_DECLARE(ed25519_psa); #define SHA512_DIGEST_LENGTH 64 #define EDDSA_KEY_LENGTH 32 From 77dd719828efd3a94e82d3e08bee7d68a5f9a58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 103/287] Revert "[nrf fromlist] boot_serial: Support sha256, sha384 and sha512" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b8c46d575cd1ce57ba72c5b13c3e9f668fb76f6b. Signed-off-by: Andrzej Głąbek --- boot/boot_serial/src/boot_serial.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c index 3891793e0..c324d7340 100644 --- a/boot/boot_serial/src/boot_serial.c +++ b/boot/boot_serial/src/boot_serial.c @@ -81,17 +81,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #define ARRAY_SIZE ZCBOR_ARRAY_SIZE #endif -#if defined(MCUBOOT_SHA512) - #define IMAGE_HASH_SIZE (64) - #define IMAGE_SHA_TLV IMAGE_TLV_SHA512 -#elif defined(MCUBOOT_SIGN_EC384) - #define IMAGE_HASH_SIZE (48) - #define IMAGE_SHA_TLV IMAGE_TLV_SHA384 -#else - #define IMAGE_HASH_SIZE (32) - #define IMAGE_SHA_TLV IMAGE_TLV_SHA256 -#endif - #ifndef MCUBOOT_SERIAL_MAX_RECEIVE_SIZE #define MCUBOOT_SERIAL_MAX_RECEIVE_SIZE 512 #endif @@ -102,7 +91,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #define BOOT_SERIAL_IMAGE_STATE_SIZE_MAX 0 #endif #ifdef MCUBOOT_SERIAL_IMG_GRP_HASH -#define BOOT_SERIAL_HASH_SIZE_MAX (IMAGE_HASH_SIZE + 4) +#define BOOT_SERIAL_HASH_SIZE_MAX 36 #else #define BOOT_SERIAL_HASH_SIZE_MAX 0 #endif @@ -274,7 +263,7 @@ bs_list(char *buf, int len) const struct flash_area *fap; uint8_t image_index; #ifdef MCUBOOT_SERIAL_IMG_GRP_HASH - uint8_t hash[IMAGE_HASH_SIZE]; + uint8_t hash[32]; #endif zcbor_map_start_encode(cbor_state, 1); @@ -347,7 +336,7 @@ bs_list(char *buf, int len) } #ifdef MCUBOOT_SERIAL_IMG_GRP_HASH - /* Retrieve hash of image for identification */ + /* Retrieve SHA256 hash of image for identification */ rc = boot_serial_get_hash(&hdr, fap, hash); #endif @@ -451,7 +440,7 @@ bs_set(char *buf, int len) */ uint8_t image_index = 0; size_t decoded = 0; - uint8_t hash[IMAGE_HASH_SIZE]; + uint8_t hash[32]; bool confirm; struct zcbor_string img_hash; bool ok; @@ -534,7 +523,7 @@ bs_set(char *buf, int len) } } - /* Retrieve hash of image for identification */ + /* Retrieve SHA256 hash of image for identification */ rc = boot_serial_get_hash(&hdr, fap, hash); flash_area_close(fap); @@ -1478,9 +1467,9 @@ static int boot_serial_get_hash(const struct image_header *hdr, break; } - if (type == IMAGE_SHA_TLV) { + if (type == IMAGE_TLV_SHA256) { /* Get the image's hash value from the manifest section. */ - if (len != IMAGE_HASH_SIZE) { + if (len != 32) { return -1; } From f104e9b8843c38f44a8197461e79b860834b87dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 104/287] Revert "[nrf noup] boot/zephyr: add nrf54l15dk ext flash configs" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit bd64752dfd68275f2927e46471f2ef0315ffe53a. Signed-off-by: Andrzej Głąbek --- .../nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 15 ------ ...f54l15dk_nrf54l15_cpuapp_ext_flash.overlay | 47 ------------------- 2 files changed, 62 deletions(-) delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf deleted file mode 100644 index 8fc12e074..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf +++ /dev/null @@ -1,15 +0,0 @@ -CONFIG_MULTITHREADING=y -CONFIG_SPI=y -CONFIG_SPI_NOR=y -CONFIG_FLASH=y -CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 -CONFIG_MAIN_STACK_SIZE=20480 -CONFIG_BOOT_MAX_IMG_SECTORS=512 -CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 -# Ensure that the qspi driver is disabled by default -CONFIG_NORDIC_QSPI_NOR=n - -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - -CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay deleted file mode 100644 index 60ee6fe51..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay +++ /dev/null @@ -1,47 +0,0 @@ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - zephyr,code-partition = &boot_partition; - }; -}; - -/delete-node/ &boot_partition; -/delete-node/ &slot0_partition; -/delete-node/ &slot1_partition; - -/delete-node/ &slot0_ns_partition; -/delete-node/ &slot1_ns_partition; - -/delete-node/ &storage_partition; - -&cpuapp_rram { - reg = < 0x0 DT_SIZE_K(1524) >; - partitions { - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x000000000 0x00014000>; - }; - slot0_partition: partition@14000 { - label = "image-0"; - reg = <0x000014000 0x0015A000>; - }; - storage_partition: partition@16E000 { - label = "storage"; - reg = < 0x16E000 0x9000 >; - }; - }; -}; - -&mx25r64 { - status = "okay"; - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - slot1_partition: partition@0 { - label = "image-1"; - reg = <0x000000000 0x0015A000>; - }; - }; -}; From 99e36bfb9a327d56d7cca27e35a2b68de955096a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 105/287] Revert "[nrf noup] workflows: Add a backport workflow" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7058149cf30a37beb7b0a85bcad9a3cd00b14d1b. Signed-off-by: Andrzej Głąbek --- .github/workflows/backport.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml deleted file mode 100644 index e986738ff..000000000 --- a/.github/workflows/backport.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Backport -on: - pull_request_target: - types: - - closed - - labeled - branches: - - main - -jobs: - backport: - name: Backport - runs-on: ubuntu-22.04 - # Only react to merged PRs for security reasons. - # See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target. - if: > - github.event.pull_request.merged && - ( - github.event.action == 'closed' || - ( - github.event.action == 'labeled' && - contains(github.event.label.name, 'backport') - ) - ) - steps: - - name: Backport - uses: zephyrproject-rtos/action-backport@v2.0.3-3 - with: - github_token: ${{ secrets.NCS_GITHUB_TOKEN }} - issue_labels: Backport - labels_template: '["Backport"]' From 7f65da13f254208814f9be4dc8d6c83352349dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 106/287] Revert "[nrf noup] boards: Thingy:91 X release config" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 78211ab58eb6b003416dc85effd2fe515ec5b53a. Signed-off-by: Andrzej Głąbek --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 3 --- boot/zephyr/boards/thingy91x_nrf9151.conf | 6 +----- boot/zephyr/boards/thingy91x_nrf9151.overlay | 4 ---- 3 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 boot/zephyr/boards/thingy91x_nrf9151.overlay diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index d3e253b65..37c7e95b1 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -58,6 +58,3 @@ CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y # Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n - -CONFIG_BOOT_SERIAL_NO_APPLICATION=y -CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 7c2042de6..2efe1e170 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -12,10 +12,6 @@ CONFIG_CONSOLE=n CONFIG_CONSOLE_HANDLER=n CONFIG_UART_CONSOLE=n CONFIG_MCUBOOT_SERIAL=y + CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y - -CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y -CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y - -CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.overlay b/boot/zephyr/boards/thingy91x_nrf9151.overlay deleted file mode 100644 index 7f2818c0d..000000000 --- a/boot/zephyr/boards/thingy91x_nrf9151.overlay +++ /dev/null @@ -1,4 +0,0 @@ -&uart0 { - status = "okay"; - current-speed = < 1000000 >; -}; From ebdd66482d842bb76c34ebf7e21d697f821ea1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:00 +0100 Subject: [PATCH 107/287] Revert "[nrf noup] boot: bootutil: loader: Add s0/s1 checking of MCUboot image" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 63e53ed94680150350e813e74957c5673704aee4. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 45 -------------------------------------- 1 file changed, 45 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index f35ec7864..b0491b3ac 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -105,17 +105,6 @@ static struct sector_buffer_t sector_buffers; #endif #endif -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 && defined(MCUBOOT_OVERWRITE_ONLY) && \ - defined(MCUBOOT_DOWNGRADE_PREVENTION) -/* s0/s1 package version of the current MCUboot image */ -static const struct image_version mcuboot_s0_s1_image_version = { - .iv_major = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MAJOR, - .iv_minor = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MINOR, - .iv_revision = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_REVISION, - .iv_build_num = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_BUILD_NUMBER, -}; -#endif - #if (BOOT_IMAGE_NUMBER > 1) #define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x)) #else @@ -1177,45 +1166,11 @@ boot_validate_slot(struct boot_loader_state *state, int slot, rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); - -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot - * trailer version to prevent downgrades - */ - int version_check; - - version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &mcuboot_s0_s1_image_version); - - /* Only update rc if the currently running version is newer */ - if (version_check < rc) { - rc = version_check; - } - } -#endif } #else rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); - -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot - * trailer version to prevent downgrades - */ - int version_check; - - version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &mcuboot_s0_s1_image_version); - - /* Only update rc if the currently running version is newer */ - if (version_check < rc) { - rc = version_check; - } - } -#endif #endif if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); From 4fe78aa9430f75c75e5609b81bca3677f73b93c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 108/287] Revert "[nrf noup] treewide: Add support for sysbuild assigned images" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 43d47399086a12c2d7f312fb30632655c5c23b3c. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 161 ++++++++------------- boot/bootutil/src/swap_nsib.c | 70 --------- boot/bootutil/src/swap_priv.h | 8 - boot/zephyr/CMakeLists.txt | 6 - boot/zephyr/include/sysflash/pm_sysflash.h | 69 +++++---- 5 files changed, 105 insertions(+), 209 deletions(-) delete mode 100644 boot/bootutil/src/swap_nsib.c diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index b0491b3ac..53f40c33a 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -153,15 +153,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +#ifdef PM_S1_ADDRESS /* Patch needed for NCS. The primary slot of the second image * (image 1) will not contain a valid image header until an upgrade * of mcuboot has happened (filling S1 with the new version). */ - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER && i == 0) { + if (BOOT_CURR_IMG(state) == 1 && i == 0) { continue; } -#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */ +#endif /* PM_S1_ADDRESS */ if (i > 0 && !require_all) { return 0; } else { @@ -1160,7 +1160,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + if (BOOT_CURR_IMG(state) == 1) { rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); } else { rc = boot_version_cmp( @@ -1229,8 +1229,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, struct image_header *secondary_hdr = boot_img_hdr(state, slot); uint32_t reset_value = 0; uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); - uint32_t min_addr, max_addr; - bool check_addresses = false; rc = flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)); if (rc != 0) { @@ -1238,46 +1236,29 @@ boot_validate_slot(struct boot_loader_state *state, int slot, goto out; } + uint32_t min_addr, max_addr; + #ifdef PM_CPUNET_APP_ADDRESS /* The primary slot for the network core is emulated in RAM. * Its flash_area hasn't got relevant boundaries. * Therfore need to override its boundaries for the check. */ - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + if (BOOT_CURR_IMG(state) == 1) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; - check_addresses = true; - } else -#endif -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { -#if (CONFIG_NCS_IS_VARIANT_IMAGE) +#ifdef PM_S1_ADDRESS + } else if (BOOT_CURR_IMG(state) == 0) { min_addr = PM_S0_ADDRESS; - max_addr = (PM_S0_ADDRESS + PM_S0_SIZE); -#else - min_addr = PM_S1_ADDRESS; - max_addr = (PM_S1_ADDRESS + PM_S1_SIZE); + max_addr = pri_fa->fa_off + pri_fa->fa_size; #endif - check_addresses = true; } else #endif - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 -#if (CONFIG_NCS_IS_VARIANT_IMAGE) - min_addr = MIN(pri_fa->fa_off, PM_S0_ADDRESS); - max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S0_ADDRESS + PM_S0_SIZE)); -#else - min_addr = MIN(pri_fa->fa_off, PM_S1_ADDRESS); - max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S1_ADDRESS + PM_S1_SIZE)); -#endif -#else + { min_addr = pri_fa->fa_off; max_addr = pri_fa->fa_off + pri_fa->fa_size; -#endif - check_addresses = true; } - if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr)) { + if (reset_value < min_addr || reset_value> (max_addr)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1354,42 +1335,36 @@ boot_update_security_counter(uint8_t image_index, int slot, #define SEC_SLOT_TOUCHED 1 #define SEC_SLOT_ASSIGNED 2 -static uint8_t sec_slot_assignmnet[MCUBOOT_IMAGE_NUMBER] = {0}; +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +/* This configuration is peculiar - the one physical secondary slot is + * mocking two logical secondary + */ +#define SEC_SLOT_PHYSICAL_CNT 1 +#else +#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER +#endif + +static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; static inline void sec_slot_touch(struct boot_loader_state *state) { -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - if (sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { - sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; - } - } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { - if (sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { - sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; - } - } -#endif + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); - if (sec_slot_assignmnet[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) { - sec_slot_assignmnet[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED; + if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { + sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; } } static inline void sec_slot_mark_assigned(struct boot_loader_state *state) { -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - sec_slot_assignmnet[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; - } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { - sec_slot_assignmnet[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; - } -#endif + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); - sec_slot_assignmnet[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED; + sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; } /** - * Cleanup up all secondary slot which couldn't be assigned to any primary slot. + * Cleanu up all secondary slot which couldn't be assigned to any primary slot. * * This function erases content of each secondary slot which contains valid * header but couldn't be assigned to any of supported primary images. @@ -1401,7 +1376,7 @@ static void sec_slot_cleanup_if_unusable(void) { uint8_t idx; - for (idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) { + for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { const struct flash_area *secondary_fa; int rc; @@ -1411,12 +1386,12 @@ static void sec_slot_cleanup_if_unusable(void) if (!rc) { rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); if (!rc) { - BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", idx); + BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); } } if (rc) { - BOOT_LOG_ERR("Failed to clean-up secondary slot of image %d: %d", idx, rc); + BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); } } } @@ -1453,7 +1428,7 @@ boot_validated_swap_type(struct boot_loader_state *state, owner_nsib[BOOT_CURR_IMG(state)] = false; #endif -#if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS) +#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); @@ -1491,29 +1466,31 @@ boot_validated_swap_type(struct boot_loader_state *state, } /* Check start and end of primary slot for current image */ -#if (CONFIG_NCS_IS_VARIANT_IMAGE) - if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { -#else - if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { -#endif - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { - /* This is not the s0/s1 upgrade image but the application image, pretend - * there is no image so the NSIB update can be loaded - */ - return BOOT_SWAP_TYPE_NONE; - } + if (reset_addr < primary_fa->fa_off) { +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + const struct flash_area *nsib_fa; - owner_nsib[BOOT_CURR_IMG(state)] = true; -#if (CONFIG_NCS_IS_VARIANT_IMAGE) - } else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { + /* NSIB upgrade slot */ + rc = flash_area_open((uint32_t)_image_1_primary_slot_id, + &nsib_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + + /* Image is placed before Primary and within the NSIB slot */ + if (reset_addr > nsib_fa->fa_off + && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { + /* Set primary to be NSIB upgrade slot */ + BOOT_IMG_AREA(state, 0) = nsib_fa; + owner_nsib[BOOT_CURR_IMG(state)] = true; + } #else - } else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { + return BOOT_SWAP_TYPE_NONE; + #endif - /* NSIB upgrade but for the wrong slot, must be erased */ - BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image"); - flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); - return BOOT_SWAP_TYPE_FAIL; - } else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + + } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } @@ -1526,7 +1503,7 @@ boot_validated_swap_type(struct boot_loader_state *state, sec_slot_mark_assigned(state); } -#endif /* PM_S1_ADDRESS || PM_CPUNET_B0N_ADDRESS */ +#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2058,22 +2035,7 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) flash_area_close(fap); } -#if defined(PM_S1_ADDRESS) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (owner_nsib[BOOT_CURR_IMG(state)]) { - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - /* For NSIB, move the image instead of swapping it */ - nsib_swap_run(state, bs); - -#if defined(CONFIG_REBOOT) - /* Should also reboot at this point so the new S0/S1 update is applied */ - sys_reboot(SYS_REBOOT_COLD); -#endif - } - } else -#endif - { - swap_run(state, bs, copy_size); - } + swap_run(state, bs, copy_size); #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT extern int boot_status_fails; @@ -2739,6 +2701,12 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); +#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + sys_reboot(SYS_REBOOT_COLD); + + } +#endif break; case BOOT_SWAP_TYPE_FAIL: @@ -2812,8 +2780,7 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) * executing MCUBoot image, and is therefore already validated by NSIB and * does not need to also be validated by MCUBoot. */ - bool image_validated_by_nsib = BOOT_CURR_IMG(state) == - CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER; + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; if (!image_validated_by_nsib) #endif { diff --git a/boot/bootutil/src/swap_nsib.c b/boot/bootutil/src/swap_nsib.c deleted file mode 100644 index 39ed4c652..000000000 --- a/boot/bootutil/src/swap_nsib.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include "bootutil/bootutil.h" -#include "bootutil_priv.h" -#include "swap_priv.h" -#include "bootutil/bootutil_log.h" - -#include "mcuboot_config/mcuboot_config.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot); - -void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs) -{ - uint32_t sector_sz; - uint8_t image_index; - const struct flash_area *fap_pri; - const struct flash_area *fap_sec; - int rc; - - BOOT_LOG_INF("Starting swap using nsib algorithm."); - - sector_sz = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0); - -#if (CONFIG_NCS_IS_VARIANT_IMAGE) - rc = flash_area_open(PM_S0_ID, &fap_pri); -#else - rc = flash_area_open(PM_S1_ID, &fap_pri); -#endif - assert (rc == 0); - image_index = BOOT_CURR_IMG(state); - - rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap_sec); - assert (rc == 0); - - rc = boot_erase_region(fap_pri, 0, fap_pri->fa_size); - assert(rc == 0); - - rc = boot_copy_region(state, fap_sec, fap_pri, 0, 0, fap_pri->fa_size); - assert(rc == 0); - - rc = swap_erase_trailer_sectors(state, fap_sec); - assert(rc == 0); - - rc = boot_erase_region(fap_sec, 0, MIN((fap_pri->fa_size + sector_sz), fap_sec->fa_size)); - assert(rc == 0); - - flash_area_close(fap_pri); - flash_area_close(fap_sec); -} diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index 2734d6262..960c72250 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -106,12 +106,4 @@ static inline size_t boot_scratch_area_size(const struct boot_loader_state *stat */ int app_max_size(struct boot_loader_state *state); -#if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ -(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) -/** - * Performs an NSIB update - */ -void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs); -#endif - #endif /* H_SWAP_PRIV_ */ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 839dd12b3..c0a0f0dbe 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -142,12 +142,6 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/swap_move.c ${BOOT_DIR}/bootutil/src/caps.c ) - - if(NOT CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER EQUAL "-1" AND NOT CONFIG_BOOT_UPGRADE_ONLY) - zephyr_library_sources( - ${BOOT_DIR}/bootutil/src/swap_nsib.c - ) - endif() endif() if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index 42f25182e..db60ddd03 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -15,36 +15,48 @@ #ifndef CONFIG_SINGLE_APPLICATION_SLOT +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +extern uint32_t _image_1_primary_slot_id[]; +#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ + +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) + +#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ + /* Each pair of slots is separated by , and there is no terminating character */ -#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID, -#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID, -#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID, -#define FLASH_AREA_IMAGE_3_SLOTS PM_MCUBOOT_PRIMARY_3_ID, PM_MCUBOOT_SECONDARY_3_ID, - -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 -#ifdef CONFIG_NCS_IS_VARIANT_IMAGE -#define MCUBOOT_S0_S1_SLOTS PM_S0_ID, PM_MCUBOOT_SECONDARY_ID, -#else -#define MCUBOOT_S0_S1_SLOTS PM_S1_ID, PM_MCUBOOT_SECONDARY_ID, -#endif -#else -#define MCUBOOT_S0_S1_SLOTS -#endif +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID -#if (MCUBOOT_IMAGE_NUMBER == 1) || (MCUBOOT_IMAGE_NUMBER == 2 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) +#if (MCUBOOT_IMAGE_NUMBER == 1) #define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 2) || (MCUBOOT_IMAGE_NUMBER == 3 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ +#elif (MCUBOOT_IMAGE_NUMBER == 2) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ FLASH_AREA_IMAGE_1_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 3) || (MCUBOOT_IMAGE_NUMBER == 4 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ - FLASH_AREA_IMAGE_1_SLOTS \ +#elif (MCUBOOT_IMAGE_NUMBER == 3) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS, \ FLASH_AREA_IMAGE_2_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 4) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ - FLASH_AREA_IMAGE_1_SLOTS \ - FLASH_AREA_IMAGE_2_SLOTS \ - FLASH_AREA_IMAGE_3_SLOTS #else #error Unsupported number of images #endif @@ -53,7 +65,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) { static const int all_slots[] = { ALL_AVAILABLE_SLOTS - MCUBOOT_S0_S1_SLOTS }; return all_slots[img * 2 + slot]; }; @@ -61,8 +72,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #undef FLASH_AREA_IMAGE_0_SLOTS #undef FLASH_AREA_IMAGE_1_SLOTS #undef FLASH_AREA_IMAGE_2_SLOTS -#undef FLASH_AREA_IMAGE_3_SLOTS -#undef MCUBOOT_S0_S1_SLOTS #undef ALL_AVAILABLE_SLOTS #define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) @@ -72,6 +81,10 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif +#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ + #else /* CONFIG_SINGLE_APPLICATION_SLOT */ #define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID From e4b6326d68560dda0e05dde73977fea6106c9971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 109/287] Revert "[nrf noup] boot: zephyr: Do not lock PCD region with TF-M" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ad56ff5183465af7f590d3ce8e1132fab2c5201a. Signed-off-by: Andrzej Głąbek --- boot/zephyr/main.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 351ca4c89..5ae524feb 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -616,11 +616,7 @@ int main(void) } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) -#if defined(PM_TFM_SECURE_ADDRESS) - pcd_lock_ram(false); -#else - pcd_lock_ram(true); -#endif + pcd_lock_ram(); #endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ From 885a2e607049ffa009c618d6a5913a1362e929f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 110/287] Revert "[nrf noup] Remove setting default MCUboot mbedTLS config" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ea00c047de0adbadc7162b945bfb139136f434cb. Signed-off-by: Andrzej Głąbek --- boot/zephyr/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 9ff1ba274..e4f7d9030 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -1,6 +1,7 @@ CONFIG_PM=n CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" CONFIG_BOOT_SWAP_SAVE_ENCTLV=n CONFIG_BOOT_ENCRYPT_IMAGE=n From 925ab74cd745f2384d0ca75330aebd6ace10990b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 111/287] Revert "[nrf noup] zephyr: Add support for ARM thumb filter" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 390c468afcdc4f3039a00efece68073355320a97. Signed-off-by: Andrzej Głąbek --- boot/zephyr/decompression.c | 305 +++++++++--------------------------- 1 file changed, 71 insertions(+), 234 deletions(-) diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index 35a1950b2..062cdbc61 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -29,14 +29,6 @@ #define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 #endif -#define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) -#define DECOMP_BUF_EXTRA_SIZE 2 -#else -#define DECOMP_BUF_EXTRA_SIZE 0 -#endif -#define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE) - /* Number of times that consumed data by decompression system can be 0 in a row before aborting */ #define OFFSET_ZERO_CHECK_TIMES 3 @@ -95,22 +87,13 @@ bool boot_is_compressed_header_valid(const struct image_header *hdr, const struc if (size >= size_check) { BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", size, size_check); + return false; } return true; } -static bool is_compression_object_valid(struct nrf_compress_implementation *compression) -{ - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { - return false; - } - - return true; -} - int bootutil_img_hash_decompress(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 *hash_result, @@ -121,9 +104,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index uint32_t write_pos = 0; uint32_t protected_tlv_size = 0; uint32_t decompressed_image_size; - uint32_t output_size_total = 0; - struct nrf_compress_implementation *compression_lzma = NULL; - struct nrf_compress_implementation *compression_arm_thumb = NULL; + struct nrf_compress_implementation *compression = NULL; TARGET_STATIC struct image_header modified_hdr; bootutil_sha_context sha_ctx; uint8_t flash_erased_value; @@ -141,26 +122,27 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; + goto finish_without_clean; } - compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); + compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - if (!is_compression_object_valid(compression_lzma) || - !is_compression_object_valid(compression_arm_thumb)) { + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; + goto finish_without_clean; } - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); + rc = compression->init(NULL); if (rc) { BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; + goto finish_without_clean; } @@ -175,6 +157,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -189,6 +172,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (rc) { BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -227,6 +211,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); rc = BOOT_EFLASH; + goto finish; } @@ -240,7 +225,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index uint32_t chunk_size; bool last_packet = false; - chunk_size = compression_lzma->decompress_bytes_needed(NULL); + chunk_size = compression->decompress_bytes_needed(NULL); if (chunk_size > (copy_size - tmp_off)) { chunk_size = (copy_size - tmp_off); @@ -250,12 +235,13 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index last_packet = true; } - rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, - &offset, &output, &output_size); + rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset, + &output, &output_size); if (rc) { BOOT_LOG_ERR("Decompression error: %d", rc); rc = BOOT_EBADSTATUS; + goto finish; } @@ -265,6 +251,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", write_pos); rc = BOOT_EBADIMAGE; + goto finish; } @@ -273,6 +260,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index /* Last packet and we still have no output, this is a faulty update */ BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -283,6 +271,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -293,48 +282,8 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index offset_zero_check = 0; } - /* Copy data to secondary buffer for calculating hash */ if (output_size > 0) { - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - /* Run this through the ARM thumb filter */ - uint32_t offset_arm_thumb = 0; - uint8_t *output_arm_thumb = NULL; - uint32_t processed_size = 0; - uint32_t output_size_arm_thumb = 0; - - while (processed_size < output_size) { - uint32_t current_size = output_size - processed_size; - bool arm_thumb_last_packet = false; - - if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { - current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; - } - - if (last_packet && (processed_size + current_size) == - output_size) { - arm_thumb_last_packet = true; - } - - rc = compression_arm_thumb->decompress(NULL, &output[processed_size], - current_size, arm_thumb_last_packet, - &offset_arm_thumb, - &output_arm_thumb, - &output_size_arm_thumb); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb); - output_size_total += output_size_arm_thumb; - processed_size += current_size; - } - } else { - bootutil_sha_update(&sha_ctx, output, output_size); - output_size_total += output_size; - } + bootutil_sha_update(&sha_ctx, output, output_size); } tmp_off += offset; @@ -343,13 +292,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index read_pos += copy_size; } - if (modified_hdr.ih_img_size != output_size_total) { - BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d", - modified_hdr.ih_img_size, output_size_total); - rc = BOOT_EBADSTATUS; - goto finish; - } - /* If there are any protected TLVs present, add them after the main decompressed image */ if (modified_hdr.ih_protect_tlv_size > 0) { rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, @@ -360,8 +302,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index finish: /* Clean up decompression system */ - (void)compression_lzma->deinit(NULL); - (void)compression_arm_thumb->deinit(NULL); + (void)compression->deinit(NULL); finish_without_clean: bootutil_sha_drop(&sha_ctx); @@ -412,6 +353,7 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto out; } @@ -480,6 +422,7 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + goto out; } @@ -495,6 +438,7 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto out; } @@ -569,6 +513,7 @@ static int boot_sha_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + read_off), copy_size, fap_src->fa_id, rc); + goto out; } @@ -681,6 +626,7 @@ int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flas */ BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); rc = BOOT_EBADIMAGE; + goto out; } @@ -735,6 +681,7 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto out; } @@ -831,6 +778,7 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + goto out; } @@ -846,6 +794,7 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto out; } @@ -874,17 +823,11 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint32_t unprotected_tlv_size = 0; uint32_t tlv_write_size = 0; uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression_lzma = NULL; - struct nrf_compress_implementation *compression_arm_thumb = NULL; + struct nrf_compress_implementation *compression = NULL; struct image_header *hdr; - TARGET_STATIC uint8_t decomp_buf[DECOMP_BUF_ALLOC_SIZE] __attribute__((aligned(4))); + TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4))); TARGET_STATIC struct image_header modified_hdr; -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - uint8_t excess_data_buffer[DECOMP_BUF_EXTRA_SIZE]; - bool excess_data_buffer_full = false; -#endif - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); /* Setup decompression system */ @@ -898,26 +841,27 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; + goto finish; } - compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); + compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - if (!is_compression_object_valid(compression_lzma) || - !is_compression_object_valid(compression_arm_thumb)) { + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; + goto finish; } - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); + rc = compression->init(NULL); if (rc) { BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; + goto finish; } @@ -930,6 +874,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -942,6 +887,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -952,6 +898,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -962,6 +909,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto finish; } @@ -980,6 +928,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); rc = BOOT_EFLASH; + goto finish; } @@ -994,7 +943,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint8_t *output = NULL; bool last_packet = false; - chunk_size = compression_lzma->decompress_bytes_needed(NULL); + chunk_size = compression->decompress_bytes_needed(NULL); if (chunk_size > (copy_size - tmp_off)) { chunk_size = (copy_size - tmp_off); @@ -1004,142 +953,47 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl last_packet = true; } - rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, - &offset, &output, &output_size); + rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset, + &output, &output_size); if (rc) { BOOT_LOG_ERR("Decompression error: %d", rc); rc = BOOT_EBADSTATUS; + goto finish; } /* Copy data to secondary buffer for writing out */ while (output_size > 0) { - uint32_t data_size = (DECOMP_BUF_SIZE - decomp_buf_size); + uint32_t data_size = (sizeof(decomp_buf) - decomp_buf_size); if (data_size > output_size) { data_size = output_size; } -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - memcpy(&decomp_buf[decomp_buf_size + DECOMP_BUF_EXTRA_SIZE], - &output[compression_buffer_pos], data_size); - } else -#endif - { - memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], - data_size); - } - + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], data_size); compression_buffer_pos += data_size; decomp_buf_size += data_size; output_size -= data_size; /* Write data out from secondary buffer when it is full */ - if (decomp_buf_size == DECOMP_BUF_SIZE) { -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - uint32_t filter_writeback_pos = 0; - uint32_t processed_size = 0; - - /* Run this through the ARM thumb filter */ - while (processed_size < DECOMP_BUF_SIZE) { - uint32_t offset_arm_thumb = 0; - uint32_t output_size_arm_thumb = 0; - uint8_t *output_arm_thumb = NULL; - uint32_t current_size = DECOMP_BUF_SIZE; - bool arm_thumb_last_packet = false; - - if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { - current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; - } - - if (last_packet && (processed_size + current_size) == DECOMP_BUF_SIZE - && output_size == 0) { - arm_thumb_last_packet = true; - } - - rc = compression_arm_thumb->decompress(NULL, - &decomp_buf[processed_size + - DECOMP_BUF_EXTRA_SIZE], - current_size, - arm_thumb_last_packet, - &offset_arm_thumb, - &output_arm_thumb, - &output_size_arm_thumb); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - memcpy(&decomp_buf[filter_writeback_pos], output_arm_thumb, - output_size_arm_thumb); - filter_writeback_pos += output_size_arm_thumb; - processed_size += current_size; - } - - if (excess_data_buffer_full == true) - { - /* Restore extra data removed from previous iteration to the write - * buffer - */ - memmove(&decomp_buf[DECOMP_BUF_EXTRA_SIZE], decomp_buf, - filter_writeback_pos); - memcpy(decomp_buf, excess_data_buffer, DECOMP_BUF_EXTRA_SIZE); - excess_data_buffer_full = false; - filter_writeback_pos += DECOMP_BUF_EXTRA_SIZE; - } - - if ((filter_writeback_pos % sizeof(uint32_t)) != 0) - { - /* Since there are an extra 2 bytes here, remove them and stash for - * later usage to prevent flash write issues with non-word boundary - * writes - */ - memcpy(excess_data_buffer, &decomp_buf[filter_writeback_pos - - DECOMP_BUF_EXTRA_SIZE], - DECOMP_BUF_EXTRA_SIZE); - excess_data_buffer_full = true; - filter_writeback_pos -= DECOMP_BUF_EXTRA_SIZE; - } - - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, filter_writeback_pos); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), DECOMP_BUF_SIZE, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - write_pos += filter_writeback_pos; - decomp_buf_size = 0; - filter_writeback_pos = 0; - } else -#endif - { - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, DECOMP_BUF_SIZE); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), DECOMP_BUF_SIZE, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - write_pos += DECOMP_BUF_SIZE; - decomp_buf_size = 0; + if (decomp_buf_size == sizeof(decomp_buf)) { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, sizeof(decomp_buf)); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), sizeof(decomp_buf), + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; } + + write_pos += sizeof(decomp_buf); + decomp_buf_size = 0; } } @@ -1149,30 +1003,8 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl pos += copy_size; } -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0) { - /* Extra data that has not been written out that needs ARM thumb filter applied */ - uint32_t offset_arm_thumb = 0; - uint32_t output_size_arm_thumb = 0; - uint8_t *output_arm_thumb = NULL; - - rc = compression_arm_thumb->decompress(NULL, &decomp_buf[DECOMP_BUF_EXTRA_SIZE], - decomp_buf_size, true, &offset_arm_thumb, - &output_arm_thumb, &output_size_arm_thumb); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - memcpy(decomp_buf, output_arm_thumb, output_size_arm_thumb); - } -#endif - /* Clean up decompression system */ - (void)compression_lzma->deinit(NULL); - (void)compression_arm_thumb->deinit(NULL); + (void)compression->deinit(NULL); if (protected_tlv_size > 0) { rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + @@ -1182,6 +1014,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + goto finish; } @@ -1196,6 +1029,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + goto finish; } @@ -1206,7 +1040,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); /* Check if additional write padding should be applied to meet the minimum write size */ - if (write_alignment > 1 && write_padding_size) { + if (write_padding_size) { uint8_t flash_erased_value; flash_erased_value = flash_area_erased_val(fap_dst); @@ -1222,6 +1056,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto finish; } @@ -1263,6 +1098,7 @@ int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct fl if (len != sizeof(*img_decomp_size)) { BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + return BOOT_EBADIMAGE; } @@ -1271,6 +1107,7 @@ int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct fl if (rc) { BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", off, len, fap->fa_id, rc); + return BOOT_EFLASH; } From 331c5104de6a401380545a68a54cd80e2682c2ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 112/287] Revert "[nrf noup] PSA implementation of x25519 and ed25519 verification" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 2c3c181854448717dae6ad22c9bb813cfe14062f. Signed-off-by: Andrzej Głąbek --- .../include/bootutil/crypto/aes_ctr.h | 38 +- boot/bootutil/src/ed25519_psa.c | 71 --- boot/bootutil/src/encrypted.c | 114 +++-- boot/bootutil/src/encrypted_psa.c | 454 ------------------ boot/bootutil/src/image_ed25519.c | 16 +- 5 files changed, 60 insertions(+), 633 deletions(-) delete mode 100644 boot/bootutil/src/ed25519_psa.c delete mode 100644 boot/bootutil/src/encrypted_psa.c diff --git a/boot/bootutil/include/bootutil/crypto/aes_ctr.h b/boot/bootutil/include/bootutil/crypto/aes_ctr.h index 44190361c..50d36a4fc 100644 --- a/boot/bootutil/include/bootutil/crypto/aes_ctr.h +++ b/boot/bootutil/include/bootutil/crypto/aes_ctr.h @@ -15,8 +15,8 @@ #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" + defined(MCUBOOT_USE_TINYCRYPT)) != 1 + #error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT" #endif #if defined(MCUBOOT_USE_MBED_TLS) @@ -38,46 +38,12 @@ #define BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE TC_AES_BLOCK_SIZE #endif /* MCUBOOT_USE_TINYCRYPT */ - -#if defined(MCUBOOT_USE_PSA_CRYPTO) - #include - #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 #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) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c deleted file mode 100644 index 3d7274307..000000000 --- a/boot/bootutil/src/ed25519_psa.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -#include -#include -#include - -#include -#include "bootutil/bootutil_log.h" - -#include -#include - -BOOT_LOG_MODULE_DECLARE(ed25519_psa); - -#define SHA512_DIGEST_LENGTH 64 -#define EDDSA_KEY_LENGTH 32 -#define EDDSA_SIGNAGURE_LENGTH 64 - -int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], - const uint8_t public_key[EDDSA_KEY_LENGTH]) -{ - /* Set to any error */ - psa_status_t status = PSA_ERROR_BAD_STATE; - psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t kid; - int ret = 0; /* Fail by default */ - - /* Initialize PSA Crypto */ - status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d\n", status); - return 0; - } - - status = PSA_ERROR_BAD_STATE; - - psa_set_key_type(&key_attr, - PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS)); - psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE); - psa_set_key_algorithm(&key_attr, PSA_ALG_PURE_EDDSA); - - status = psa_import_key(&key_attr, public_key, EDDSA_KEY_LENGTH, &kid); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("ED25519 key import failed %d", status); - return 0; - } - - status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len, - signature, EDDSA_SIGNAGURE_LENGTH); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); - ret = 0; - /* Pass through to destroy key */ - } else { - ret = 1; - /* Pass through to destroy key */ - } - - status = psa_destroy_key(kid); - - if (status != PSA_SUCCESS) { - /* Just for logging */ - BOOT_LOG_WRN("Failed to destroy key %d", status); - } - - return ret; -} diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index 67fa819bb..8449a28dd 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -25,7 +25,6 @@ #include "bootutil/crypto/ecdh_p256.h" #endif -#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_X25519) #include "bootutil/crypto/ecdh_x25519.h" #endif @@ -36,7 +35,6 @@ #include "mbedtls/oid.h" #include "mbedtls/asn1.h" #endif -#endif #include "bootutil/image.h" #include "bootutil/enc_key.h" @@ -45,30 +43,6 @@ #include "bootutil_priv.h" -#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE - -#if defined(MCUBOOT_ENCRYPT_RSA) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 -#elif defined(MCUBOOT_ENCRYPT_KW) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW -#elif defined(MCUBOOT_ENCRYPT_EC256) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (65) -# define EC_CIPHERKEY_INDEX (65 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-P256 component indexes"); -#elif defined(MCUBOOT_ENCRYPT_X25519) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (32) -# define EC_CIPHERKEY_INDEX (32 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-X25519 component indexes"); -#endif - -/* NOUP Fixme: */ -#if !defined(CONFIG_BOOT_ED25519_PSA) #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) #if defined(_compare) static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size) @@ -377,6 +351,60 @@ int boot_enc_retrieve_private_key(struct bootutil_key **private_key) } #endif /* !MCUBOOT_ENC_BUILTIN_KEY */ +int +boot_enc_init(struct enc_key_data *enc_state, uint8_t slot) +{ + bootutil_aes_ctr_init(&enc_state[slot].aes_ctr); + return 0; +} + +int +boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot) +{ + bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr); + enc_state[slot].valid = 0; + return 0; +} + +int +boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, + const struct boot_status *bs) +{ + int rc; + + rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]); + if (rc != 0) { + boot_enc_drop(enc_state, slot); + return -1; + } + + enc_state[slot].valid = 1; + + return 0; +} + +#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE + +#if defined(MCUBOOT_ENCRYPT_RSA) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 +#elif defined(MCUBOOT_ENCRYPT_KW) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW +#elif defined(MCUBOOT_ENCRYPT_EC256) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (65) +# define EC_CIPHERKEY_INDEX (65 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-P256 component indexes"); +#elif defined(MCUBOOT_ENCRYPT_X25519) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (32) +# define EC_CIPHERKEY_INDEX (32 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-X25519 component indexes"); +#endif + #if ( (defined(MCUBOOT_ENCRYPT_RSA) && defined(MCUBOOT_USE_MBED_TLS) && !defined(MCUBOOT_USE_PSA_CRYPTO)) || \ (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ) #if MBEDTLS_VERSION_NUMBER >= 0x03000000 @@ -599,7 +627,6 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return rc; } -#endif /* CONFIG_BOOT_ED25519_PSA */ /* * Load encryption key. @@ -654,39 +681,6 @@ boot_enc_load(struct enc_key_data *enc_state, int slot, return boot_decrypt_key(buf, bs->enckey[slot]); } -int -boot_enc_init(struct enc_key_data *enc_state, uint8_t slot) -{ - bootutil_aes_ctr_init(&enc_state[slot].aes_ctr); - return 0; -} - -int -boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot) -{ - bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr); - enc_state[slot].valid = 0; - return 0; -} - -int -boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, - const struct boot_status *bs) -{ - int rc; - - rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]); - if (rc != 0) { - boot_enc_drop(enc_state, slot); - return -1; - } - - enc_state[slot].valid = 1; - - return 0; -} - - bool boot_enc_valid(struct enc_key_data *enc_state, int slot) { diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c deleted file mode 100644 index c3f72884d..000000000 --- a/boot/bootutil/src/encrypted_psa.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include "mcuboot_config/mcuboot_config.h" - -#include -#include -#include - -/* We are not really using the MBEDTLS but need the ASN.1 parsing functions */ -#define MBEDTLS_ASN1_PARSE_C - -#include "bootutil/crypto/sha.h" -#include "mbedtls/oid.h" -#include "mbedtls/asn1.h" - -#include "bootutil/image.h" -#include "bootutil/enc_key.h" -#include "bootutil/sign_key.h" -#include "bootutil/crypto/common.h" - -#include "bootutil_priv.h" -#include "bootutil/bootutil_log.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); - -#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE -#define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 -#define EC_PUBK_INDEX (0) -#define EC_TAG_INDEX (32) -#define EC_CIPHERKEY_INDEX (32 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-X25519 component indexes"); - -#define X25519_OID "\x6e" -static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ - MBEDTLS_OID_ORG_GOV X25519_OID; - -#define SHARED_KEY_LEN 32 -#define PRIV_KEY_LEN 32 - -/* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ -static int -parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) -{ - size_t len; - int version; - mbedtls_asn1_buf alg; - mbedtls_asn1_buf param; - - if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE) != 0) { - return -1; - } - - if (*p + len != end) { - return -2; - } - - version = 0; - if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { - return -3; - } - - if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { - return -4; - } - - 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 -5; - } - - if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -6; - } - - if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -7; - } - - if (len != PRIV_KEY_LEN) { - return -8; - } - - memcpy(private_key, *p, PRIV_KEY_LEN); - return 0; -} - -void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx) -{ - psa_status_t psa_ret = psa_crypto_init(); - - (void)ctx; - - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES init PSA crypto init failed %d", psa_ret); - assert(0); - } -} - -#if defined(MCUBOOT_ENC_IMAGES) -extern const struct bootutil_key bootutil_enc_key; -/* - * Decrypt an encryption key TLV. - * - * @param buf An encryption TLV read from flash (build time fixed length) - * @param enckey An AES-128 or AES-256 key sized buffer to store to plain key. - */ -int -boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) -{ - uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; - uint8_t *cp; - uint8_t *cpend; - uint8_t private_key[PRIV_KEY_LEN]; - size_t len; - psa_status_t psa_ret = PSA_ERROR_BAD_STATE; - psa_status_t psa_cleanup_ret = PSA_ERROR_BAD_STATE; - psa_key_id_t kid; - psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; - psa_key_derivation_operation_t key_do = PSA_KEY_DERIVATION_OPERATION_INIT; - psa_algorithm_t key_do_alg; - int rc = -1; - - cp = (uint8_t *)bootutil_enc_key.key; - cpend = cp + *bootutil_enc_key.len; - - /* The psa_cipher_decrypt needs initialization vector of proper length at - * the beginning of the input buffer. - */ - uint8_t iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR) + - BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE]; - - psa_ret = psa_crypto_init(); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES crypto init failed %d", psa_ret); - return -1; - } - - /* - * Load the stored X25519 decryption private key - */ - rc = parse_x25519_enckey(&cp, cpend, private_key); - if (rc) { - return rc; - } - - psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY)); - psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DERIVE); - psa_set_key_algorithm(&kattr, PSA_ALG_ECDH); - - psa_ret = psa_import_key(&kattr, private_key, sizeof(private_key), &kid); - memset(private_key, 0, sizeof(private_key)); - psa_reset_key_attributes(&kattr); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("Built-in key import failed %d", psa_ret); - return -1; - } - - key_do_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)); - - psa_ret = psa_key_derivation_setup(&key_do, key_do_alg); - if (psa_ret != PSA_SUCCESS) { - psa_cleanup_ret = psa_destroy_key(kid); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("Built-in key destruction failed %d", psa_cleanup_ret); - } - BOOT_LOG_ERR("Key derivation setup failed %d", psa_ret); - return -1; - } - - /* Note: PSA 1.1.2 does not have psa_key_agreement that would be useful here - * as it could just add the derived key to the storage and return key id. - * Instead, we have to use the code below to generate derived key and put it - * into storage, to obtain the key id we can then use with psa_mac_* functions. - */ - psa_ret = psa_key_derivation_key_agreement(&key_do, PSA_KEY_DERIVATION_INPUT_SECRET, - kid, &buf[EC_PUBK_INDEX], - BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); - psa_cleanup_ret = psa_destroy_key(kid); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("Built-in key destruction failed %d", psa_cleanup_ret); - } - if (psa_ret != PSA_SUCCESS) { - psa_cleanup_ret = psa_key_derivation_abort(&key_do); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("Key derivation abort failed %d", psa_ret); - } - - BOOT_LOG_ERR("Key derivation failed %d", psa_ret); - return -1; - } - - /* Only info, no salt */ - psa_ret = psa_key_derivation_input_bytes(&key_do, PSA_KEY_DERIVATION_INPUT_INFO, - "MCUBoot_ECIES_v1", 16); - if (psa_ret != PSA_SUCCESS) { - psa_cleanup_ret = psa_key_derivation_abort(&key_do); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("Key derivation abort failed %d", psa_ret); - } - BOOT_LOG_ERR("Key derivation failed %d", psa_ret); - return -1; - } - - len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE; - psa_ret = psa_key_derivation_output_bytes(&key_do, derived_key, len); - psa_cleanup_ret = psa_key_derivation_abort(&key_do); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("Key derivation cleanup failed %d", psa_ret); - } - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("Key derivation failed %d", psa_ret); - return -1; - } - - /* The derived key consists of BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE bytes - * followed by BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE bytes. Both parts will - * be imported at the point where needed and discarded immediately after. - */ - psa_set_key_type(&kattr, PSA_KEY_TYPE_HMAC); - psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_VERIFY_MESSAGE); - psa_set_key_algorithm(&kattr, PSA_ALG_HMAC(PSA_ALG_SHA_256)); - - /* Import the MAC tag key part of derived key, that is the part that starts - * after BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE and has length of - * BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE bytes. - */ - psa_ret = psa_import_key(&kattr, - &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE], - BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, &kid); - psa_reset_key_attributes(&kattr); - if (psa_ret != PSA_SUCCESS) { - memset(derived_key, 0, sizeof(derived_key)); - BOOT_LOG_ERR("MAC key import failed %d", psa_ret); - return -1; - } - - /* Verify the MAC tag of the random encryption key */ - psa_ret = psa_mac_verify(kid, PSA_ALG_HMAC(PSA_ALG_SHA_256), - &buf[EC_CIPHERKEY_INDEX], BOOT_ENC_KEY_SIZE, - &buf[EC_TAG_INDEX], - BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); - psa_cleanup_ret = psa_destroy_key(kid); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("MAC key destruction failed %d", psa_cleanup_ret); - } - if (psa_ret != PSA_SUCCESS) { - memset(derived_key, 0, sizeof(derived_key)); - BOOT_LOG_ERR("MAC verification failed %d", psa_ret); - return -1; - } - - /* The derived key is used in AES decryption of random key */ - psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); - psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DECRYPT); - psa_set_key_algorithm(&kattr, PSA_ALG_CTR); - - /* Import the AES partition of derived key, the first 16 bytes */ - psa_ret = psa_import_key(&kattr, &derived_key[0], - BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, &kid); - memset(derived_key, 0, sizeof(derived_key)); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES key import failed %d", psa_ret); - return -1; - } - - /* Decrypt the random AES encryption key with AES and the key obtained - * at derivation. */ - memset(&iv_and_key[0], 0, PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)); - memcpy(&iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)], - &buf[EC_CIPHERKEY_INDEX], - sizeof(iv_and_key) - PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)); - - len = 0; - psa_ret = psa_cipher_decrypt(kid, PSA_ALG_CTR, iv_and_key, sizeof(iv_and_key), - enckey, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, &len); - memset(iv_and_key, 0, sizeof(iv_and_key)); - psa_cleanup_ret = psa_destroy_key(kid); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("AES key destruction failed %d", psa_cleanup_ret); - } - if (psa_ret != PSA_SUCCESS || len != BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE) { - memset(enckey, 0, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE); - BOOT_LOG_ERR("Random key decryption failed %d", psa_ret); - return -1; - } - - 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 ret = 0; - psa_status_t psa_ret = PSA_ERROR_BAD_STATE; - psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t kid; - psa_cipher_operation_t psa_op; - size_t elen = 0; /* Decrypted length */ - - /* Fixme: calling psa_crypto_init multiple times is not a problem, - * yet the code here is only present because there is not general - * crypto init. */ - psa_ret = psa_crypto_init(); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); - ret = -1; - goto gone; - } - - psa_op = psa_cipher_operation_init(); - - /* Fixme: Import should happen when key is decrypted, but due to lack - * of key destruction there is no way to destroy key stored by - * psa other way than here. */ - psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); - psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_ENCRYPT); - psa_set_key_algorithm(&kattr, PSA_ALG_CTR); - - psa_ret = psa_import_key(&kattr, ctx->key, BOOT_ENC_KEY_SIZE, &kid); - psa_reset_key_attributes(&kattr); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES enc import key failed %d", psa_ret); - ret = -1; - goto gone; - } - - /* This could be done with psa_cipher_decrypt one-shot operation, but - * multi-part operation is used to avoid re-allocating input buffer - * to account for IV in front of data. - */ - psa_ret = psa_cipher_encrypt_setup(&psa_op, kid, PSA_ALG_CTR); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES enc setup failed %d", psa_ret); - ret = -1; - goto gone_with_key; - } - - /* Fixme: hardcoded counter size, but it is hardcoded everywhere */ - psa_ret = psa_cipher_set_iv(&psa_op, counter, 16); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES enc IV set failed %d", psa_ret); - ret = -1; - goto gone_after_setup; - } - - psa_ret = psa_cipher_update(&psa_op, m, mlen, c, mlen, &elen); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES enc encryption failed %d", psa_ret); - ret = -1; - goto gone_after_setup; - } - -gone_after_setup: - psa_ret = psa_cipher_abort(&psa_op); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("AES enc cipher abort failed %d", psa_ret); - /* Intentionally not changing the ret */ - } -gone_with_key: - /* Fixme: Should be removed once key is shared by id */ - psa_ret = psa_destroy_key(kid); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("AES enc destroy key failed %d", psa_ret); - /* Intentionally not changing the ret */ - } -gone: - return ret; -} - -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) -{ - int ret = 0; - psa_status_t psa_ret = PSA_ERROR_BAD_STATE; - psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t kid; - psa_cipher_operation_t psa_op; - size_t dlen = 0; /* Decrypted length */ - - /* Fixme: the init should already happen before calling the function, but - * somehow it does not, for example when recovering in swap. - */ - psa_ret = psa_crypto_init(); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); - ret = -1; - goto gone; - } - - psa_op = psa_cipher_operation_init(); - - /* Fixme: Import should happen when key is decrypted, but due to lack - * of key destruction there is no way to destroy key stored by - * psa other way than here. */ - psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); - psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DECRYPT); - psa_set_key_algorithm(&kattr, PSA_ALG_CTR); - - psa_ret = psa_import_key(&kattr, ctx->key, BOOT_ENC_KEY_SIZE, &kid); - psa_reset_key_attributes(&kattr); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES dec import key failed %d", psa_ret); - ret = -1; - goto gone; - } - - /* This could be done with psa_cipher_decrypt one-shot operation, but - * multi-part operation is used to avoid re-allocating input buffer - * to account for IV in front of data. - */ - psa_ret = psa_cipher_decrypt_setup(&psa_op, kid, PSA_ALG_CTR); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES dec setup failed %d", psa_ret); - ret = -1; - goto gone_with_key; - } - - /* Fixme: hardcoded counter size, but it is hardcoded everywhere */ - psa_ret = psa_cipher_set_iv(&psa_op, counter, 16); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES dec IV set failed %d", psa_ret); - ret = -1; - goto gone_after_setup; - } - - psa_ret = psa_cipher_update(&psa_op, c, clen, m, clen, &dlen); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES dec decryption failed %d", psa_ret); - ret = -1; - goto gone_after_setup; - } - -gone_after_setup: - psa_ret = psa_cipher_abort(&psa_op); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("PSA dec abort failed %d", psa_ret); - /* Intentionally not changing the ret */ - } -gone_with_key: - psa_ret = psa_destroy_key(kid); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("PSA dec key failed %d", psa_ret); - /* Intentionally not changing the ret */ - } -gone: - return ret; -} -#endif /* defined(MCUBOOT_ENC_IMAGES) */ diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 447289253..7a597d4c0 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -9,11 +9,6 @@ #include "mcuboot_config/mcuboot_config.h" -#if defined(CONFIG_NRF_SECURITY) -/* We are not really using the MBEDTLS but need the ASN.1 parsing funcitons */ -#define MBEDTLS_ASN1_PARSE_C -#endif - #ifdef MCUBOOT_SIGN_ED25519 #include "bootutil/sign_key.h" @@ -22,16 +17,13 @@ #include "bootutil_priv.h" #include "bootutil/crypto/common.h" -#include "bootutil/crypto/sha.h" - -#define EDDSA_SIGNATURE_LENGTH 64 static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; #define NUM_ED25519_BYTES 32 extern int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[EDDSA_SIGNATURE_LENGTH], - const uint8_t public_key[NUM_ED25519_BYTES]); + const uint8_t signature[64], + const uint8_t public_key[32]); /* * Parse the public key used for signing. @@ -81,7 +73,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t *pubkey; uint8_t *end; - if (hlen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) { + if (hlen != 32 || slen != 64) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -95,7 +87,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, goto out; } - rc = ED25519_verify(hash, IMAGE_HASH_SIZE, sig, pubkey); + rc = ED25519_verify(hash, 32, sig, pubkey); if (rc == 0) { /* if verify returns 0, there was an error. */ From 6b0723bbc16176dc9ef6f3b5bc4ca9ecb4e2903d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 113/287] Revert "[nrf noup] boot: Add shared crypto for ECDSA and SHA" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 049e896648b012a036bda2f451fbd279e396102b. Signed-off-by: Andrzej Głąbek --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 64 ++----------------- boot/bootutil/include/bootutil/crypto/sha.h | 32 ---------- boot/zephyr/CMakeLists.txt | 2 - boot/zephyr/external_crypto.conf | 20 ------ .../include/mcuboot_config/mcuboot_config.h | 5 +- 5 files changed, 9 insertions(+), 114 deletions(-) delete mode 100644 boot/zephyr/external_crypto.conf diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 85355f20c..3b0541072 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -34,7 +34,6 @@ #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 @@ -71,18 +70,12 @@ #include "bootutil/sign_key.h" #include "common.h" -#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) - #include - #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) + defined(MCUBOOT_USE_CC310)) && !defined(MCUBOOT_USE_PSA_CRYPTO) /* * Declaring these like this adds NULL termination. */ @@ -134,6 +127,8 @@ static int bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* (MCUBOOT_USE_TINYCRYPT || MCUBOOT_USE_MBED_TLS || MCUBOOT_USE_CC310) && !MCUBOOT_USE_PSA_CRYPTO */ +#if defined(MCUBOOT_USE_TINYCRYPT) +#ifndef MCUBOOT_ECDSA_NEED_ASN1_SIG /* * cp points to ASN1 string containing an integer. * Verify the tag, and that the length is 32 bytes. Helper function. @@ -183,8 +178,8 @@ static int bootutil_decode_sig(uint8_t signature[NUM_ECC_BYTES * 2], uint8_t *cp } return 0; } +#endif /* not MCUBOOT_ECDSA_NEED_ASN1_SIG */ -#if defined(MCUBOOT_USE_TINYCRYPT) typedef uintptr_t bootutil_ecdsa_context; static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx) { @@ -253,12 +248,8 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, { (void)ctx; (void)pk_len; + (void)sig_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) { @@ -266,7 +257,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, } pk++; - return cc310_ecdsa_verify_secp256r1(hash, pk, dsig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE); + return cc310_ecdsa_verify_secp256r1(hash, pk, sig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE); } static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, @@ -622,49 +613,6 @@ static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, #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 diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index 88e94fbea..34288ef02 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -30,7 +30,6 @@ #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 @@ -212,37 +211,6 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, } #endif /* MCUBOOT_USE_CC310 */ -#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) - -#include - -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 diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index c0a0f0dbe..253ab2537 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -171,8 +171,6 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) zephyr_link_libraries(nrfxlib_crypto) - elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) - zephyr_include_directories(${BL_CRYPTO_DIR}/../include) endif() # Since here we are not using Zephyr's mbedTLS but rather our own, we need diff --git a/boot/zephyr/external_crypto.conf b/boot/zephyr/external_crypto.conf deleted file mode 100644 index 8181ad51c..000000000 --- a/boot/zephyr/external_crypto.conf +++ /dev/null @@ -1,20 +0,0 @@ -# -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# These configurations should be used when using nrf/samples/bootloader -# as the immutable bootloader (B0), and MCUBoot as the second stage updateable -# bootloader. - -# Set ECDSA as signing mechanism -CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y - -# Use crypto backend from B0 -CONFIG_BOOT_NRF_EXTERNAL_CRYPTO=y -CONFIG_SECURE_BOOT_CRYPTO=y -CONFIG_SB_CRYPTO_CLIENT_ECDSA_SECP256R1=y -CONFIG_SB_CRYPTO_CLIENT_SHA256=y -CONFIG_BL_SHA256_EXT_API_REQUIRED=y -CONFIG_BL_SECP256R1_EXT_API_REQUIRED=y diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index f628f99c4..56462fb76 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -40,10 +40,11 @@ #define MCUBOOT_USE_TINYCRYPT #elif defined(CONFIG_BOOT_USE_CC310) #define MCUBOOT_USE_CC310 +#ifdef CONFIG_BOOT_USE_NRF_CC310_BL +#define MCUBOOT_USE_NRF_CC310_BL +#endif #elif defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) #define MCUBOOT_USE_PSA_CRYPTO -#elif defined(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) -#define MCUBOOT_USE_NRF_EXTERNAL_CRYPTO #endif #ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA512 From 6aae4ebcff41a9a515ad6088795dc9980b02104f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 114/287] Revert "[nrf noup] zephyr: Add support for compressed image updates" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 474a92290901ffb468978574087e98fc89fb3e80. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/image_validate.c | 226 ---- boot/bootutil/src/loader.c | 102 +- boot/zephyr/CMakeLists.txt | 6 - boot/zephyr/Kconfig | 10 +- boot/zephyr/decompression.c | 1115 ----------------- .../include/compression/decompression.h | 104 -- 6 files changed, 23 insertions(+), 1540 deletions(-) delete mode 100644 boot/zephyr/decompression.c delete mode 100644 boot/zephyr/include/compression/decompression.h diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index b1a50f126..ec5d986df 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -40,15 +40,6 @@ #include "mcuboot_config/mcuboot_config.h" -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - -#include "bootutil/bootutil_log.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot); - #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -425,68 +416,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, FIH_DECLARE(security_counter_valid, FIH_FAILURE); #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - /* If the image is compressed, the integrity of the image must also be validated */ - if (MUST_DECOMPRESS(fap, image_index, hdr)) { - bool found_decompressed_size = false; - bool found_decompressed_sha = false; - bool found_decompressed_signature = false; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(fap)) { - rc = -1; - goto out; - } - - while (true) { - uint16_t expected_size = 0; - bool *found_flag = NULL; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - switch (type) { - case IMAGE_TLV_DECOMP_SIZE: - expected_size = sizeof(size_t); - found_flag = &found_decompressed_size; - break; - case IMAGE_TLV_DECOMP_SHA: - expected_size = IMAGE_HASH_SIZE; - found_flag = &found_decompressed_sha; - break; - case IMAGE_TLV_DECOMP_SIGNATURE: - found_flag = &found_decompressed_signature; - break; - default: - continue; - }; - - if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { - rc = -1; - goto out; - } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { - rc = -1; - goto out; - } - - *found_flag = true; - } - - rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); - if (rc) { - goto out; - } - } -#endif - rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); if (rc) { @@ -658,161 +587,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - /* Only after all previous verifications have passed, perform a dry-run of the decompression - * and ensure the image is valid - */ - if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { - image_hash_valid = 0; - FIH_SET(valid_signature, FIH_FAILURE); - - rc = bootutil_img_hash_decompress(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, - hash, seed, seed_len); - if (rc) { - goto out; - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - if (type == IMAGE_TLV_DECOMP_SHA) { - /* Verify the image hash. This must always be present. */ - if (len != sizeof(hash)) { - rc = -1; - goto out; - } - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); - if (rc) { - goto out; - } - - FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - image_hash_valid = 1; - } - } - - rc = !image_hash_valid; - if (rc) { - goto out; - } - -#ifdef EXPECTED_SIG_TLV -#ifdef EXPECTED_KEY_TLV - rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - if (type == EXPECTED_KEY_TLV) { - /* - * Determine which key we should be checking. - */ - if (len > KEY_BUF_SIZE) { - rc = -1; - goto out; - } -#ifndef MCUBOOT_HW_KEY - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); - if (rc) { - goto out; - } - key_id = bootutil_find_key(buf, len); -#else - rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); - if (rc) { - goto out; - } - key_id = bootutil_find_key(image_index, key_buf, len); -#endif /* !MCUBOOT_HW_KEY */ - /* - * The key may not be found, which is acceptable. There - * can be multiple signatures, each preceded by a key. - */ - } - } -#endif /* EXPECTED_KEY_TLV */ - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIGNATURE) { - /* Ignore this signature if it is out of bounds. */ - if (key_id < 0 || key_id >= bootutil_key_cnt) { - key_id = -1; - continue; - } - - if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { - rc = -1; - goto out; - } - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); - if (rc) { - goto out; - } - - FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), - buf, len, key_id); - key_id = -1; - } - } -#endif /* EXPECTED_SIG_TLV */ - } -#endif - -#ifdef EXPECTED_SIG_TLV - FIH_SET(fih_rc, valid_signature); -#endif - out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 53f40c33a..7ec789588 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,11 +49,6 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - #ifdef __ZEPHYR__ #include #endif @@ -658,76 +653,35 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) goto done; } -#ifdef MCUBOOT_DECOMPRESS_IMAGES - if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { - uint32_t tmp_size = 0; - - rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); - - if (rc) { - rc = BOOT_EBADIMAGE; - goto done; - } - - off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; - - rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); - - if (rc) { - rc = BOOT_EBADIMAGE; - goto done; - } - - off += tmp_size; + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); - if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + - boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, - sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { rc = BOOT_EBADIMAGE; goto done; } - *size = off + info.it_tlv_tot; - } else { -#else - if (1) { -#endif - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); - - if (flash_area_read(fap, off, &info, sizeof(info))) { + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { rc = BOOT_EFLASH; goto done; } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { - rc = BOOT_EBADIMAGE; - goto done; - } - - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; - } - - *size = off + protect_tlv_size + info.it_tlv_tot; + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; } + *size = off + protect_tlv_size + info.it_tlv_tot; rc = 0; done: @@ -1016,10 +970,10 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } #else - if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { - if (!boot_is_compressed_header_valid(hdr, fap, state)) { - return false; - } + if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && + (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) + { + return false; } #endif @@ -1199,7 +1153,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * attempts to validate and boot it. */ } - #if !defined(__BOOTSIM__) BOOT_LOG_ERR("Image in the %s slot is not valid!", (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); @@ -1636,9 +1589,6 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - struct image_header *hdr; -#endif TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); @@ -1664,16 +1614,6 @@ boot_copy_region(struct boot_loader_state *state, } #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - - if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { - /* Use alternative function for compressed images */ - return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, - BUF_SZ); - } -#endif - bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 253ab2537..1d3009b22 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -249,12 +249,6 @@ if(CONFIG_BOOT_ENCRYPT_EC256) ) endif() -if(CONFIG_BOOT_DECOMPRESSION) - zephyr_library_sources( - decompression.c - ) -endif() - if(CONFIG_MCUBOOT_SERIAL) zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c) zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 34c6be3a4..f58eb1ba3 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -796,10 +796,6 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool - depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) - depends on !SINGLE_APPLICATION_SLOT && !BOOT_ENCRYPT_IMAGE && BOOT_UPGRADE_ONLY - depends on UPDATEABLE_IMAGE_NUMBER = 1 - default y help Hidden symbol which should be selected if a system provided decompression support. @@ -807,8 +803,6 @@ if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION bool "Decompression" - select NRF_COMPRESS_CLEANUP - select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to @@ -817,9 +811,9 @@ menuconfig BOOT_DECOMPRESSION if BOOT_DECOMPRESSION config BOOT_DECOMPRESSION_BUFFER_SIZE - int + int "Write buffer size" range 16 16384 - default NRF_COMPRESS_CHUNK_SIZE + default 4096 help The size of a secondary buffer used for writing decompressed data to the storage device. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c deleted file mode 100644 index 062cdbc61..000000000 --- a/boot/zephyr/decompression.c +++ /dev/null @@ -1,1115 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include "compression/decompression.h" -#include "bootutil/crypto/sha.h" -#include "bootutil/bootutil_log.h" - -#if !defined(__BOOTSIM__) -#define TARGET_STATIC static -#else -#define TARGET_STATIC -#endif - -#if defined(MCUBOOT_SIGN_RSA) -#if MCUBOOT_SIGN_RSA_LEN == 2048 -#define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS -#elif MCUBOOT_SIGN_RSA_LEN == 3072 -#define EXPECTED_SIG_TLV IMAGE_TLV_RSA3072_PSS -#endif -#elif defined(MCUBOOT_SIGN_EC256) || \ - defined(MCUBOOT_SIGN_EC384) || \ - defined(MCUBOOT_SIGN_EC) -#define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA_SIG -#elif defined(MCUBOOT_SIGN_ED25519) -#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 -#endif - -/* Number of times that consumed data by decompression system can be 0 in a row before aborting */ -#define OFFSET_ZERO_CHECK_TIMES 3 - -BOOT_LOG_MODULE_DECLARE(mcuboot); - -static int boot_sha_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, uint32_t protected_size, - uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx); - -bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, - struct boot_loader_state *state) -{ - /* Image is compressed in secondary slot, need to check if fits into the primary slot */ - bool opened_flash_area = false; - int primary_fa_id; - int rc; - int size_check; - int size; - uint32_t protected_tlvs_size; - uint32_t decompressed_size; - - if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { - opened_flash_area = true; - } - - primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); - rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - assert(rc == 0); - - size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - - if (opened_flash_area) { - (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - } - - rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); - - if (rc) { - return false; - } - - if (!boot_u32_safe_add(&size, decompressed_size, hdr->ih_hdr_size)) { - return false; - } - - rc = boot_size_protected_tlvs(hdr, fap, &protected_tlvs_size); - - if (rc) { - return false; - } - - if (!boot_u32_safe_add(&size, size, protected_tlvs_size)) { - return false; - } - - if (size >= size_check) { - BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", - size, size_check); - - return false; - } - - return true; -} - -int bootutil_img_hash_decompress(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 *hash_result, - uint8_t *seed, int seed_len) -{ - int rc; - uint32_t read_pos = 0; - uint32_t write_pos = 0; - uint32_t protected_tlv_size = 0; - uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression = NULL; - TARGET_STATIC struct image_header modified_hdr; - bootutil_sha_context sha_ctx; - uint8_t flash_erased_value; - - bootutil_sha_init(&sha_ctx); - - /* Setup decompression system */ -#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { -#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { -#endif - /* Compressed image does not use the correct compression type which is supported by this - * build - */ - BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); - rc = BOOT_EBADIMAGE; - - goto finish_without_clean; - } - - compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { - /* Compression library missing or missing required function pointer */ - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - - goto finish_without_clean; - } - - rc = compression->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - - goto finish_without_clean; - } - - /* We need a modified header which has the updated sizes, start with the original header */ - memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); - - /* Extract the decompressed image size from the protected TLV, set it and remove the - * compressed image flags - */ - rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; - modified_hdr.ih_img_size = decompressed_image_size; - - /* Calculate the protected TLV size, these will not include the decompressed - * sha/size/signature entries - */ - rc = boot_size_protected_tlvs(hdr, fap, &protected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - modified_hdr.ih_protect_tlv_size = protected_tlv_size; - bootutil_sha_update(&sha_ctx, &modified_hdr, sizeof(modified_hdr)); - read_pos = sizeof(modified_hdr); - flash_erased_value = flash_area_erased_val(fap); - memset(tmp_buf, flash_erased_value, tmp_buf_sz); - - while (read_pos < modified_hdr.ih_hdr_size) { - uint32_t copy_size = tmp_buf_sz; - - if ((read_pos + copy_size) > modified_hdr.ih_hdr_size) { - copy_size = modified_hdr.ih_hdr_size - read_pos; - } - - bootutil_sha_update(&sha_ctx, tmp_buf, copy_size); - read_pos += copy_size; - } - - /* Read in compressed data, decompress and add to hash calculation */ - read_pos = 0; - - while (read_pos < hdr->ih_img_size) { - uint32_t copy_size = hdr->ih_img_size - read_pos; - uint32_t tmp_off = 0; - uint8_t offset_zero_check = 0; - - if (copy_size > tmp_buf_sz) { - copy_size = tmp_buf_sz; - } - - rc = flash_area_read(fap, (hdr->ih_hdr_size + read_pos), tmp_buf, copy_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; - } - - /* Decompress data in chunks, writing it back with a larger write offset of the primary - * slot than read size of the secondary slot - */ - while (tmp_off < copy_size) { - uint32_t offset = 0; - uint8_t *output = NULL; - uint32_t output_size = 0; - uint32_t chunk_size; - bool last_packet = false; - - chunk_size = compression->decompress_bytes_needed(NULL); - - if (chunk_size > (copy_size - tmp_off)) { - chunk_size = (copy_size - tmp_off); - } - - if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { - last_packet = true; - } - - rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset, - &output, &output_size); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - - goto finish; - } - - write_pos += output_size; - - if (write_pos > decompressed_image_size) { - BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", - write_pos); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - /* Additional dry-run validity checks */ - if (last_packet == true && write_pos == 0) { - /* Last packet and we still have no output, this is a faulty update */ - BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - if (offset == 0) { - /* If the decompression system continually consumes 0 bytes, then there is a - * problem with this update image, abort and mark image as bad - */ - if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { - BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - ++offset_zero_check; - - break; - } else { - offset_zero_check = 0; - } - - if (output_size > 0) { - bootutil_sha_update(&sha_ctx, output, output_size); - } - - tmp_off += offset; - } - - read_pos += copy_size; - } - - /* If there are any protected TLVs present, add them after the main decompressed image */ - if (modified_hdr.ih_protect_tlv_size > 0) { - rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, - tmp_buf_sz, &sha_ctx); - } - - bootutil_sha_finish(&sha_ctx, hash_result); - -finish: - /* Clean up decompression system */ - (void)compression->deinit(NULL); - -finish_without_clean: - bootutil_sha_drop(&sha_ctx); - - return rc; -} - -static int boot_copy_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_dst, - uint32_t protected_size, uint8_t *buf, size_t buf_size, - uint16_t *buf_pos, uint32_t *written) -{ - int rc; - uint32_t off; - uint32_t write_pos = 0; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, - .it_tlv_tot = protected_size, - }; - uint16_t info_size_left = sizeof(tlv_info_header); - - while (info_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (info_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; - - if (single_copy_size > info_size_left) { - single_copy_size = info_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - - info_size_left], single_copy_size); - *buf_pos += single_copy_size; - info_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { - /* Skip these TLVs as they are not needed */ - continue; - } else { - uint16_t header_size_left = sizeof(tlv_header); - uint16_t data_size_left = len; - - tlv_header.it_type = type; - tlv_header.it_len = len; - - while (header_size_left > 0 || data_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - uint8_t *tlv_header_address = (uint8_t *)&tlv_header; - - if (header_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > header_size_left) { - single_copy_size = header_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - - header_size_left], - single_copy_size); - *buf_pos += single_copy_size; - copy_size -= single_copy_size; - header_size_left -= single_copy_size; - } - - if (data_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > data_size_left) { - single_copy_size = data_size_left; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + (len - data_size_left)), - &buf[*buf_pos], single_copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - - goto out; - } - - *buf_pos += single_copy_size; - data_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - } - } - - *written = write_pos; - -out: - return rc; -} - -static int boot_sha_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, uint32_t protected_size, - uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx) -{ - int rc; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, - .it_tlv_tot = protected_size, - }; - - bootutil_sha_update(sha_ctx, &tlv_info_header, sizeof(tlv_info_header)); - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); - if (rc) { - goto out; - } - - while (true) { - uint32_t read_off = 0; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { - /* Skip these TLVs as they are not needed */ - continue; - } - - tlv_header.it_type = type; - tlv_header.it_len = len; - - bootutil_sha_update(sha_ctx, &tlv_header, sizeof(tlv_header)); - - while (read_off < len) { - uint32_t copy_size = buf_size; - - if (copy_size > (len - read_off)) { - copy_size = len - read_off; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + read_off), buf, copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + read_off), copy_size, fap_src->fa_id, rc); - - goto out; - } - - bootutil_sha_update(sha_ctx, buf, copy_size); - read_off += copy_size; - } - } - -out: - return rc; -} - -int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *sz) -{ - int rc = 0; - uint32_t tlv_size; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - - *sz = 0; - tlv_size = hdr->ih_protect_tlv_size; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { - /* Exclude these TLVs as they will be copied to the unprotected area */ - tlv_size -= len + sizeof(struct image_tlv); - } - } - - if (!rc) { - if (tlv_size == sizeof(struct image_tlv_info)) { - /* If there are no entries then omit protected TLV section entirely */ - tlv_size = 0; - } - - *sz = tlv_size; - } - -out: - return rc; -} - -int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *sz) -{ - int rc = 0; - uint32_t tlv_size; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - - *sz = 0; - tlv_size = sizeof(struct image_tlv_info); - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } else if (bootutil_tlv_iter_is_prot(&it, off) && type != IMAGE_TLV_DECOMP_SHA && - type != IMAGE_TLV_DECOMP_SIGNATURE) { - /* Include size of protected hash and signature as these will be replacing the - * original ones - */ - continue; - } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { - /* Exclude the original unprotected TLVs for signature and hash, the length of the - * signature of the compressed data might not be the same size as the signaute of the - * decompressed data, as is the case when using ECDSA-P256 - */ - continue; - } - - tlv_size += len + sizeof(struct image_tlv); - } - - if (!rc) { - if (tlv_size == sizeof(struct image_tlv_info)) { - /* If there are no entries in the unprotected TLV section then there is something wrong - * with this image - */ - BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); - rc = BOOT_EBADIMAGE; - - goto out; - } - - *sz = tlv_size; - } - -out: - return rc; -} - -static int boot_copy_unprotected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_dst, - uint32_t unprotected_size, uint8_t *buf, size_t buf_size, - uint16_t *buf_pos, uint32_t *written) -{ - int rc; - uint32_t write_pos = 0; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv_iter it_protected; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_INFO_MAGIC, - .it_tlv_tot = unprotected_size, - }; - uint16_t info_size_left = sizeof(tlv_info_header); - - while (info_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (info_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; - - if (single_copy_size > info_size_left) { - single_copy_size = info_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - - info_size_left], single_copy_size); - *buf_pos += single_copy_size; - info_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, false); - if (rc) { - goto out; - } - - while (true) { - uint16_t header_size_left = sizeof(tlv_header); - uint16_t data_size_left; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } else if (bootutil_tlv_iter_is_prot(&it, off)) { - /* Skip protected TLVs */ - continue; - } - - /* Change the values of these fields from having the data in the compressed image - * unprotected TLV (which is valid only for the compressed image data) to having the - * fields in the protected TLV section (which is valid for the decompressed image data). - * The compressed data is no longer needed - */ - if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { - rc = bootutil_tlv_iter_begin(&it_protected, hdr, fap_src, (type == EXPECTED_HASH_TLV ? - IMAGE_TLV_DECOMP_SHA : - IMAGE_TLV_DECOMP_SIGNATURE), - true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it_protected, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - } - - if (type == IMAGE_TLV_DECOMP_SHA) { - type = EXPECTED_HASH_TLV; - } else { - type = EXPECTED_SIG_TLV; - } - } - - data_size_left = len; - tlv_header.it_type = type; - tlv_header.it_len = len; - - while (header_size_left > 0 || data_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (header_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_header_address = (uint8_t *)&tlv_header; - - if (single_copy_size > header_size_left) { - single_copy_size = header_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - header_size_left], - single_copy_size); - *buf_pos += single_copy_size; - copy_size -= single_copy_size; - header_size_left -= single_copy_size; - } - - if (data_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > data_size_left) { - single_copy_size = data_size_left; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + len - data_size_left), - &buf[*buf_pos], single_copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - - goto out; - } - - *buf_pos += single_copy_size; - data_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - } - - *written = write_pos; - -out: - return rc; -} - -int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_src, - uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size) -{ - int rc; - uint32_t pos = 0; - uint16_t decomp_buf_size = 0; - uint16_t write_alignment; - uint32_t write_pos = 0; - uint32_t protected_tlv_size = 0; - uint32_t unprotected_tlv_size = 0; - uint32_t tlv_write_size = 0; - uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression = NULL; - struct image_header *hdr; - TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4))); - TARGET_STATIC struct image_header modified_hdr; - - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - - /* Setup decompression system */ -#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { -#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { -#endif - /* Compressed image does not use the correct compression type which is supported by this - * build - */ - BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { - /* Compression library missing or missing required function pointer */ - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - - goto finish; - } - - rc = compression->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - - goto finish; - } - - write_alignment = flash_area_align(fap_dst); - - memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); - - rc = bootutil_get_img_decomp_size(hdr, fap_src, &decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; - modified_hdr.ih_img_size = decompressed_image_size; - - /* Calculate protected TLV size for target image once items are removed */ - rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - modified_hdr.ih_protect_tlv_size = protected_tlv_size; - - rc = boot_size_unprotected_tlvs(hdr, fap_src, &unprotected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - /* Write out the image header first, this should be a multiple of the write size */ - rc = flash_area_write(fap_dst, off_dst, &modified_hdr, sizeof(modified_hdr)); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; - } - - /* Read in, decompress and write out data */ - while (pos < hdr->ih_img_size) { - uint32_t copy_size = hdr->ih_img_size - pos; - uint32_t tmp_off = 0; - - if (copy_size > buf_size) { - copy_size = buf_size; - } - - rc = flash_area_read(fap_src, off_src + hdr->ih_hdr_size + pos, buf, copy_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; - } - - /* Decompress data in chunks, writing it back with a larger write offset of the primary - * slot than read size of the secondary slot - */ - while (tmp_off < copy_size) { - uint32_t offset = 0; - uint32_t output_size = 0; - uint32_t chunk_size; - uint32_t compression_buffer_pos = 0; - uint8_t *output = NULL; - bool last_packet = false; - - chunk_size = compression->decompress_bytes_needed(NULL); - - if (chunk_size > (copy_size - tmp_off)) { - chunk_size = (copy_size - tmp_off); - } - - if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { - last_packet = true; - } - - rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset, - &output, &output_size); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - - goto finish; - } - - /* Copy data to secondary buffer for writing out */ - while (output_size > 0) { - uint32_t data_size = (sizeof(decomp_buf) - decomp_buf_size); - - if (data_size > output_size) { - data_size = output_size; - } - - memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], data_size); - compression_buffer_pos += data_size; - - decomp_buf_size += data_size; - output_size -= data_size; - - /* Write data out from secondary buffer when it is full */ - if (decomp_buf_size == sizeof(decomp_buf)) { - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, sizeof(decomp_buf)); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), sizeof(decomp_buf), - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; - } - - write_pos += sizeof(decomp_buf); - decomp_buf_size = 0; - } - } - - tmp_off += offset; - } - - pos += copy_size; - } - - /* Clean up decompression system */ - (void)compression->deinit(NULL); - - if (protected_tlv_size > 0) { - rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + - write_pos), protected_tlv_size, - decomp_buf, DECOMP_BUF_SIZE, &decomp_buf_size, - &tlv_write_size); - - if (rc) { - BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - - goto finish; - } - - write_pos += tlv_write_size; - } - - tlv_write_size = 0; - rc = boot_copy_unprotected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + - write_pos), unprotected_tlv_size, - decomp_buf, DECOMP_BUF_SIZE, &decomp_buf_size, - &tlv_write_size); - - if (rc) { - BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - - goto finish; - } - - write_pos += tlv_write_size; - - /* Check if we have unwritten data buffered up and, if so, write it out */ - if (decomp_buf_size > 0) { - uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); - - /* Check if additional write padding should be applied to meet the minimum write size */ - if (write_padding_size) { - uint8_t flash_erased_value; - - flash_erased_value = flash_area_erased_val(fap_dst); - memset(&decomp_buf[decomp_buf_size], flash_erased_value, write_padding_size); - decomp_buf_size += write_padding_size; - } - - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf, - decomp_buf_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; - } - - write_pos += decomp_buf_size; - decomp_buf_size = 0; - } - -finish: - memset(decomp_buf, 0, sizeof(decomp_buf)); - - return rc; -} - -int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *img_decomp_size) -{ - struct image_tlv_iter it; - uint32_t off; - uint16_t len; - int32_t rc; - - if (hdr == NULL || fap == NULL || img_decomp_size == NULL) { - return BOOT_EBADARGS; - } else if (hdr->ih_protect_tlv_size == 0) { - return BOOT_EBADIMAGE; - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIZE, true); - - if (rc) { - return rc; - } - - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - - if (rc != 0) { - return -1; - } - - if (len != sizeof(*img_decomp_size)) { - BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); - - return BOOT_EBADIMAGE; - } - - rc = LOAD_IMAGE_DATA(hdr, fap, off, img_decomp_size, len); - - if (rc) { - BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off, len, fap->fa_id, rc); - - return BOOT_EFLASH; - } - - return 0; -} diff --git a/boot/zephyr/include/compression/decompression.h b/boot/zephyr/include/compression/decompression.h deleted file mode 100644 index f8a676ac5..000000000 --- a/boot/zephyr/include/compression/decompression.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef H_DECOMPRESSION_ -#define H_DECOMPRESSION_ - -#include -#include -#include -#include "bootutil/bootutil.h" -#include "bootutil/bootutil_public.h" -#include "bootutil/image.h" -#include "../src/bootutil_priv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Checks if a compressed image header is valid. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param state Bootloader state object. - * - * @return true if valid; false if invalid. - */ -bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, - struct boot_loader_state *state); - -/** - * Reads in compressed image data from a slot, decompresses it and writes it out to a destination - * slot, including corresponding image headers and TLVs. - * - * @param state Bootloader state object. - * @param fap_src Flash area of the source slot. - * @param fap_dst Flash area of the destination slot. - * @param off_src Offset of the source slot to read from (should be 0). - * @param off_dst Offset of the destination slot to write to (should be 0). - * @param sz Size of the source slot data. - * @param buf Temporary buffer for reading data from. - * @param buf_size Size of temporary buffer. - * - * @return 0 on success; nonzero on failure. - */ -int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_src, - uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size); - -/** - * Gets the total data size (excluding headers and TLVs) of a compressed image when it is - * decompressed. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param img_decomp_size Pointer to variable that will be updated with the decompressed image - * size. - * - * @return 0 on success; nonzero on failure. - */ -int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *img_decomp_size); - -/** - * Calculate MCUboot-compatible image hash of compressed image slot. - * - * @param enc_state Not currently used, set to NULL. - * @param image_index Image number. - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param tmp_buf Temporary buffer for reading data from. - * @param tmp_buf_sz Size of temporary buffer. - * @param hash_result Pointer to a variable that will be updated with the image hash. - * @param seed Not currently used, set to NULL. - * @param seed_len Not currently used, set to 0. - * - * @return 0 on success; nonzero on failure. - */ -int bootutil_img_hash_decompress(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 *hash_result, - uint8_t *seed, int seed_len); - -/** - * Calculates the size that the compressed image protected TLV section will occupy once the image - * has been decompressed. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param sz Pointer to variable that will be updated with the protected TLV size. - * - * @return 0 on success; nonzero on failure. - */ -int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap_src, - uint32_t *sz); - -#ifdef __cplusplus -} -#endif - -#endif /* H_DECOMPRESSION_ */ From 878691e497cc0393dba799cfda26f33db5b3f22e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 115/287] Revert "[nrf noup] boards: nrf54l15dk: Disable FPROTECT" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9321e7f46a878d237209f4f596d5e88a8cf6aca3. Signed-off-by: Andrzej Głąbek --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf index 8d8eb845f..43d8cebe3 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -7,7 +7,4 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - CONFIG_BOOT_WATCHDOG_FEED=n From 2d9721140baa6b250b12014455adb8da1309b915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 116/287] Revert "[nrf noup] bootutil: loader: Fix netcore address checking" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e8705940ce0eebb48144854955d69465c69c5462. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 7ec789588..63ba35ad6 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1407,7 +1407,7 @@ boot_validated_swap_type(struct boot_loader_state *state, #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS - if(!(reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS)) + if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif { const struct flash_area *primary_fa; @@ -1480,8 +1480,7 @@ boot_validated_swap_type(struct boot_loader_state *state, * update and indicate to the caller of this function that no update is * available */ - if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS && - reset_addr < PM_CPUNET_APP_END_ADDRESS) { + if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); From 40f28e394067cea835cc6ef735569b2a5b538b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 117/287] Revert "[nrf noup] boot/../loader: reboot after updating s0/s1" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f07918de07319dff91be492bf13f9a8320b73824. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 10 ---------- boot/zephyr/Kconfig | 1 - 2 files changed, 11 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 63ba35ad6..37a435644 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,10 +49,6 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" -#ifdef __ZEPHYR__ -#include -#endif - #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) #include #ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION @@ -2640,12 +2636,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); -#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - sys_reboot(SYS_REBOOT_COLD); - - } -#endif break; case BOOT_SWAP_TYPE_FAIL: diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index f58eb1ba3..7cf16e816 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -18,7 +18,6 @@ config MCUBOOT select MPU_ALLOW_FLASH_WRITE if ARM_MPU select USE_DT_CODE_PARTITION if HAS_FLASH_LOAD_OFFSET select MCUBOOT_BOOTUTIL_LIB - select REBOOT if SECURE_BOOT config BOOT_USE_MBEDTLS bool From cf2647c299011d33c6684cbf7dffc863e2e956a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 118/287] Revert "[nrf noup] boot/../loader: skip downgrade prevention for s1/s0" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit de9d942b888ed8a2064fc36c44ef9cb93993d6db. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 37a435644..fe931fdef 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -70,9 +70,6 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; -#ifdef PM_S1_ADDRESS -static bool owner_nsib[BOOT_IMAGE_NUMBER] = {false}; -#endif #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; @@ -1373,9 +1370,6 @@ boot_validated_swap_type(struct boot_loader_state *state, int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); bool upgrade_valid = false; -#if defined(PM_S1_ADDRESS) - owner_nsib[BOOT_CURR_IMG(state)] = false; -#endif #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = @@ -1432,7 +1426,6 @@ boot_validated_swap_type(struct boot_loader_state *state, && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { /* Set primary to be NSIB upgrade slot */ BOOT_IMG_AREA(state, 0) = nsib_fa; - owner_nsib[BOOT_CURR_IMG(state)] = true; } #else return BOOT_SWAP_TYPE_NONE; @@ -1443,10 +1436,6 @@ boot_validated_swap_type(struct boot_loader_state *state, /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } - - if ((primary_fa->fa_off == PM_S0_ADDRESS) || (primary_fa->fa_off == PM_S1_ADDRESS)) { - owner_nsib[BOOT_CURR_IMG(state)] = true; - } } #endif /* PM_S1_ADDRESS */ sec_slot_mark_assigned(state); @@ -2420,13 +2409,6 @@ check_downgrade_prevention(struct boot_loader_state *state) uint32_t security_counter[2]; int rc; -#if defined(PM_S1_ADDRESS) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - /* Downgrade prevention on S0/S1 image is managed by NSIB */ - return 0; - } -#endif - if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) { /* If there was security no counter in slot 0, allow swap */ rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 0).hdr), From bb9fcf23cf91f711fcf7c69057bc56b8ebe5a8fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 119/287] Revert "[nrf noup] boot: zephyr: Add NCS boot banner" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f754885576c2c1f19b53e6a41dc718286964ed40. Signed-off-by: Andrzej Głąbek --- boot/zephyr/prj.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index e4f7d9030..23b5f3b93 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -37,6 +37,3 @@ CONFIG_CBPRINTF_NANO=y ### Use the minimal C library to reduce flash usage CONFIG_MINIMAL_LIBC=y CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 - -# NCS boot banner -CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" From 4e648e2ef9c6004be53b8da43dd5786c75cbfa0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 120/287] Revert "[nrf noup] zephyr/boards: fix nrf54l15pdk ext flash dts overlay" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f1393e6b8dde7f86513942271ad46c284fe22d3b. Signed-off-by: Andrzej Głąbek --- .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay index 60ee6fe51..ea024fcec 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -14,8 +14,7 @@ /delete-node/ &storage_partition; -&cpuapp_rram { - reg = < 0x0 DT_SIZE_K(1524) >; +&rram0 { partitions { boot_partition: partition@0 { label = "mcuboot"; From 1e4bb026c33f23ca1c70c66e2558597237177eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 121/287] Revert "[nrf noup] Revert of zephyr: arm: Update reading the flash image reset vector" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ccffc83489330ec2dc4a57902b100d1b738641ec. Signed-off-by: Andrzej Głąbek --- boot/zephyr/flash_map_extended.c | 8 ++++++-- boot/zephyr/main.c | 20 +++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index d0744afbd..4631da75b 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -141,8 +141,12 @@ int flash_area_sector_from_off(off_t off, struct flash_sector *sector) uint8_t flash_area_get_device_id(const struct flash_area *fa) { - (void)fa; - return FLASH_DEVICE_ID; +#if defined(CONFIG_ARM) + return fa->fa_id; +#else + (void)fa; + return FLASH_DEVICE_ID; +#endif } #define ERASED_VAL 0xff diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 5ae524feb..5042218b3 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -174,16 +174,26 @@ static void do_boot(struct boot_rsp *rsp) /* Get ram address for image */ vt = (struct arm_vector_table *)(rsp->br_hdr->ih_load_addr + rsp->br_hdr->ih_hdr_size); #else - uintptr_t flash_base; int rc; + const struct flash_area *fap; + static uint32_t dst[2]; /* Jump to flash image */ - rc = flash_device_base(rsp->br_flash_dev_id, &flash_base); + rc = flash_area_open(rsp->br_flash_dev_id, &fap); + assert(rc == 0); + + rc = flash_area_read(fap, rsp->br_hdr->ih_hdr_size, dst, sizeof(dst)); assert(rc == 0); +#ifndef CONFIG_ASSERT + /* Enter a lock up as asserts are disabled */ + if (rc != 0) { + while (1); + } +#endif + + flash_area_close(fap); - vt = (struct arm_vector_table *)(flash_base + - rsp->br_image_off + - rsp->br_hdr->ih_hdr_size); + vt = (struct arm_vector_table *)dst; #endif if (IS_ENABLED(CONFIG_SYSTEM_TIMER_HAS_DISABLE_SUPPORT)) { From d99b5fe2237f000684ef9b2343de96c7a57d9029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 122/287] Revert "[nrf noup] boot/zephyr: fix fw_info search" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit efafb012f0a647a5e57a9438bc4b38a7cc5db1cf. Signed-off-by: Andrzej Głąbek --- boot/zephyr/main.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 5042218b3..b5a65e460 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -206,14 +206,7 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - uintptr_t fw_start_addr; - - rc = flash_device_base(rsp->br_flash_dev_id, &fw_start_addr); - assert(rc == 0); - - fw_start_addr += rsp->br_image_off + rsp->br_hdr->ih_hdr_size; - - const struct fw_info *firmware_info = fw_info_find(fw_start_addr); + const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); bool provided = fw_info_ext_api_provide(firmware_info, true); #ifdef PM_S0_ADDRESS From 4b1aadc948b1ab824756904bdee5be31a0a6af11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 123/287] Revert "[nrf noup] boot: zephyr: Disable boot banner if NCS_BOOT_BANNER is used" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 4ae34b4e81382f2f7259472f0eddd21dbc471d99. Signed-off-by: Andrzej Głąbek --- boot/zephyr/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 7cf16e816..a641f3e6a 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -778,7 +778,6 @@ config BOOT_DISABLE_CACHES config MCUBOOT_BOOT_BANNER bool "Use MCUboot boot banner" depends on BOOT_BANNER - depends on !NCS_BOOT_BANNER depends on "$(APP_VERSION_EXTENDED_STRING)" != "" default y help From 663c1c77f008ec46ae1966a961ceafd9a7fadcf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 124/287] Revert "[nrf noup] boards: thingy91x: enable serial recovery" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 732083d3ec8b3bc76a6fd528ebc14a27df05d069. Signed-off-by: Andrzej Głąbek --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 10 ++-------- boot/zephyr/boards/thingy91x_nrf9151.conf | 9 --------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index 37c7e95b1..72dfa7fca 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -32,7 +32,7 @@ CONFIG_USB_COMPOSITE_DEVICE=y CONFIG_USB_MASS_STORAGE=n CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x910A +CONFIG_USB_DEVICE_PID=0x520F CONFIG_BOOT_SERIAL_BOOT_MODE=y @@ -49,12 +49,6 @@ CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y CONFIG_FLASH_SIMULATOR_STATS=n CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y - -# Makes it possible to update the network core using the flash simulator -CONFIG_NRF53_RECOVERY_NETWORK_CORE=y - CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y -CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y -# Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 -CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n +CONFIG_NRF53_RECOVERY_NETWORK_CORE=y diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 2efe1e170..33cd3301c 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -6,12 +6,3 @@ CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_SPI_NOR_SFDP_DEVICETREE=y CONFIG_MULTITHREADING=y - -# Disable Zephyr console and use UART for MCUboot serial recovery instead -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_UART_CONSOLE=n -CONFIG_MCUBOOT_SERIAL=y - -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y -CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y From e61f3fa67c61629fad13b9168e30a22eae987779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 125/287] Revert "[nrf noup] boot/zephyr/boards: nrf54l15pdk ext-flash update" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 494c935ae019a4be93d700ec49c65198aaa562ba. Signed-off-by: Andrzej Głąbek --- .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf | 7 ------- .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 1 - 2 files changed, 8 deletions(-) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf index 8fc12e074..841922dbd 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf @@ -6,10 +6,3 @@ CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 CONFIG_MAIN_STACK_SIZE=20480 CONFIG_BOOT_MAX_IMG_SECTORS=512 CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 -# Ensure that the qspi driver is disabled by default -CONFIG_NORDIC_QSPI_NOR=n - -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - -CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay index ea024fcec..76b648903 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -1,7 +1,6 @@ / { chosen { nordic,pm-ext-flash = &mx25r64; - zephyr,code-partition = &boot_partition; }; }; From 944b60de4067e3026b460bfd235d80cd086f145a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 126/287] Revert "[nrf noup] boot/zephyr/boards: nrf54l15pdk ext-flash partition" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 830ad12d077c584b2a99884e1129bba1a33dd72c. Signed-off-by: Andrzej Głąbek --- ...54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay index 76b648903..2341ffd26 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -4,42 +4,7 @@ }; }; -/delete-node/ &boot_partition; -/delete-node/ &slot0_partition; -/delete-node/ &slot1_partition; - -/delete-node/ &slot0_ns_partition; -/delete-node/ &slot1_ns_partition; - -/delete-node/ &storage_partition; - -&rram0 { - partitions { - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x000000000 0x00014000>; - }; - slot0_partition: partition@14000 { - label = "image-0"; - reg = <0x000014000 0x0015A000>; - }; - storage_partition: partition@16E000 { - label = "storage"; - reg = < 0x16E000 0x9000 >; - }; - }; -}; &mx25r64 { status = "okay"; - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - slot1_partition: partition@0 { - label = "image-1"; - reg = <0x000000000 0x0015A000>; - }; - }; }; From 0d6fedb6b35b951292e79bfc0d5aa48207e368e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 127/287] Revert "[nrf noup] loader: remove cleanup for direct xip mode" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit dcef7e4813f5599cfe1302a6cc9b4b930ea85360. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index fe931fdef..40c14ab51 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1272,8 +1272,6 @@ boot_update_security_counter(uint8_t image_index, int slot, } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) - #if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ (defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) @@ -1355,6 +1353,7 @@ static inline void sec_slot_cleanup_if_unusable(void) #endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined * that a swap operation is required, the image in the secondary slot is checked From 0d80c0f6152349c4eec89b08eefab0d07589c9c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 128/287] Revert "[nrf noup] boards: nrf54l15: Disable FPROTECT" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 1bd0b62e4705f0a6d1a6ed4f723e4aa9fc7dfcc1. Signed-off-by: Andrzej Głąbek --- boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf index 8d8eb845f..43d8cebe3 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf @@ -7,7 +7,4 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - CONFIG_BOOT_WATCHDOG_FEED=n From 8fcce98778328c4abcef3f796afa0fa7989c6ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 129/287] Revert "[nrf noup] loader: introduced cleanup of unusable secondary slot" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 6045ec967497abf777bf487db284c17f74bba0e0. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 90 -------------------------------------- 1 file changed, 90 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 40c14ab51..19e8d801e 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1272,87 +1272,6 @@ boot_update_security_counter(uint8_t image_index, int slot, } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ -#if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ -(defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) - -#define SEC_SLOT_VIRGIN 0 -#define SEC_SLOT_TOUCHED 1 -#define SEC_SLOT_ASSIGNED 2 - -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -/* This configuration is peculiar - the one physical secondary slot is - * mocking two logical secondary - */ -#define SEC_SLOT_PHYSICAL_CNT 1 -#else -#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER -#endif - -static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; - -static inline void sec_slot_touch(struct boot_loader_state *state) -{ - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); - - if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { - sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; - } -} - -static inline void sec_slot_mark_assigned(struct boot_loader_state *state) -{ - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); - - sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; -} - -/** - * Cleanu up all secondary slot which couldn't be assigned to any primary slot. - * - * This function erases content of each secondary slot which contains valid - * header but couldn't be assigned to any of supported primary images. - * - * This function is supposed to be called after boot_validated_swap_type() - * iterates over all the images in context_boot_go(). - */ -static void sec_slot_cleanup_if_unusable(void) -{ - uint8_t idx; - - for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { - if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { - const struct flash_area *secondary_fa; - int rc; - - rc = flash_area_open(flash_area_id_from_multi_image_slot(idx, BOOT_SECONDARY_SLOT), - &secondary_fa); - if (!rc) { - rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); - if (!rc) { - BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); - } - } - - if (rc) { - BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); - } - } - } -} -#else -static inline void sec_slot_touch(struct boot_loader_state *state) -{ -} -static inline void sec_slot_mark_assigned(struct boot_loader_state *state) -{ -} -static inline void sec_slot_cleanup_if_unusable(void) -{ -} -#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ - defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ - #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined @@ -1391,9 +1310,6 @@ boot_validated_swap_type(struct boot_loader_state *state, if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } - - sec_slot_touch(state); - #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) @@ -1428,7 +1344,6 @@ boot_validated_swap_type(struct boot_loader_state *state, } #else return BOOT_SWAP_TYPE_NONE; - #endif } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { @@ -1437,9 +1352,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } } #endif /* PM_S1_ADDRESS */ - sec_slot_mark_assigned(state); } - #endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); @@ -2546,9 +2459,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } - /* cleanup secondary slots which were recognized unusable*/ - sec_slot_cleanup_if_unusable(); - #if (BOOT_IMAGE_NUMBER > 1) if (has_upgrade) { /* Iterate over all the images and verify whether the image dependencies From 685cd06bcd5cdbf8d688c4fa3a2869c69922a052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 130/287] Revert "[nrf noup] sysflash: Add support for three images" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit a251600dd2365d9da00f28e884770cfc43743fa7. Signed-off-by: Andrzej Głąbek --- boot/zephyr/include/sysflash/pm_sysflash.h | 82 ++++++++++------------ 1 file changed, 37 insertions(+), 45 deletions(-) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index db60ddd03..377291e8b 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -11,19 +11,37 @@ #include #include -#include #ifndef CONFIG_SINGLE_APPLICATION_SLOT -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ +#if defined(PM_B0_ADDRESS) extern uint32_t _image_1_primary_slot_id[]; -#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ +#endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ @@ -38,52 +56,26 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) - -#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - -/* Each pair of slots is separated by , and there is no terminating character */ -#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID -#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID -#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID - -#if (MCUBOOT_IMAGE_NUMBER == 1) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 2) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ - FLASH_AREA_IMAGE_1_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 3) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ - FLASH_AREA_IMAGE_1_SLOTS, \ - FLASH_AREA_IMAGE_2_SLOTS #else -#error Unsupported number of images -#endif -static inline uint32_t __flash_area_ids_for_slot(int img, int slot) -{ - static const int all_slots[] = { - ALL_AVAILABLE_SLOTS - }; - return all_slots[img * 2 + slot]; -}; +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) -#undef FLASH_AREA_IMAGE_0_SLOTS -#undef FLASH_AREA_IMAGE_1_SLOTS -#undef FLASH_AREA_IMAGE_2_SLOTS -#undef ALL_AVAILABLE_SLOTS +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) -#define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) -#define FLASH_AREA_IMAGE_SECONDARY(x) __flash_area_ids_for_slot(x, 1) +#endif /* PM_B0_ADDRESS */ -#if !defined(CONFIG_BOOT_SWAP_USING_MOVE) -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif - -#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #else /* CONFIG_SINGLE_APPLICATION_SLOT */ From 07b5e655c04589038df47f66eee0ad02a5e4d035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 131/287] Revert "[nrf noup] sysflash: Move partition manager definitions to pm_sysflash.h" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e005bf866a3699eaba6a296988022af1a2074610. Signed-off-by: Andrzej Głąbek --- boot/zephyr/include/sysflash/pm_sysflash.h | 92 ---------------------- boot/zephyr/include/sysflash/sysflash.h | 90 +++++++++++++++++++-- 2 files changed, 85 insertions(+), 97 deletions(-) delete mode 100644 boot/zephyr/include/sysflash/pm_sysflash.h diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h deleted file mode 100644 index 377291e8b..000000000 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef __PM_SYSFLASH_H__ -#define __PM_SYSFLASH_H__ -/* Blocking the __SYSFLASH_H__ */ -#define __SYSFLASH_H__ - -#include -#include - -#ifndef CONFIG_SINGLE_APPLICATION_SLOT - -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -#if defined(PM_B0_ADDRESS) -extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) -#else - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) - -#endif /* PM_B0_ADDRESS */ - -#endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID - -#else /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID -/* NOTE: Scratch parition is not used by single image DFU but some of - * functions in common files reference it, so the definitions has been - * provided to allow compilation of common units. - */ -#define FLASH_AREA_IMAGE_SCRATCH 0 - -#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#endif /* __PM_SYSFLASH_H__ */ diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index f231c3d02..8b47a32b5 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -4,15 +4,93 @@ * SPDX-License-Identifier: Apache-2.0 */ -#if USE_PARTITION_MANAGER -/* Blocking the rest of the file */ +#ifndef __SYSFLASH_H__ #define __SYSFLASH_H__ -#include + +#if USE_PARTITION_MANAGER +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +#if defined(PM_B0_ADDRESS) +extern uint32_t _image_1_primary_slot_id[]; #endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) +#else + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) + +#endif /* PM_B0_ADDRESS */ -#ifndef __SYSFLASH_H__ -#define __SYSFLASH_H__ +#endif +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#else + +#include #include #include #include @@ -71,4 +149,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#endif /* USE_PARTITION_MANAGER */ + #endif /* __SYSFLASH_H__ */ From 9b135b027a3b4dd2de7fd237be8697a058190269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 132/287] Revert "[nrf noup] boot: Add support for NSIB and multi-image" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 0bf9af473ffd1e0750b1eb3d4b2a3d3918811955. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 44 ++++++------------------- boot/zephyr/include/sysflash/sysflash.h | 19 ++--------- 2 files changed, 12 insertions(+), 51 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 19e8d801e..666256778 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1192,11 +1192,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, if (BOOT_CURR_IMG(state) == 1) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; -#ifdef PM_S1_ADDRESS - } else if (BOOT_CURR_IMG(state) == 0) { - min_addr = PM_S0_ADDRESS; - max_addr = pri_fa->fa_off + pri_fa->fa_size; -#endif } else #endif { @@ -1317,37 +1312,18 @@ boot_validated_swap_type(struct boot_loader_state *state, { const struct flash_area *primary_fa; rc = flash_area_open(flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), - &primary_fa); + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } - - /* Check start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off) { -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - const struct flash_area *nsib_fa; - - /* NSIB upgrade slot */ - rc = flash_area_open((uint32_t)_image_1_primary_slot_id, - &nsib_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - - /* Image is placed before Primary and within the NSIB slot */ - if (reset_addr > nsib_fa->fa_off - && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { - /* Set primary to be NSIB upgrade slot */ - BOOT_IMG_AREA(state, 0) = nsib_fa; - } -#else - return BOOT_SWAP_TYPE_NONE; -#endif - - } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for any */ + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ return BOOT_SWAP_TYPE_NONE; } } @@ -1629,7 +1605,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs) BOOT_LOG_INF("Image %d upgrade secondary slot -> primary slot", image_index); BOOT_LOG_INF("Erasing the primary slot"); - rc = flash_area_open(flash_area_get_id(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)), + rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap_primary_slot); assert (rc == 0); diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 8b47a32b5..b98e48bce 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -23,24 +23,9 @@ /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ -#if defined(PM_B0_ADDRESS) -extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) +#ifdef PM_B0_ADDRESS -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) +extern uint32_t _image_1_primary_slot_id[]; #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ From 7bf424554eb386d4e96c7e0d4c2f89fbeeb5629c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 133/287] Revert "[nrf noup] loader: Fix missing PCD define check" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 3213b0ca6ea88e264752d4ee71295ded7164c10a. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 666256778..72135088e 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1348,7 +1348,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ - && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) && defined(CONFIG_PCD_APP) + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available @@ -1376,8 +1376,7 @@ boot_validated_swap_type(struct boot_loader_state *state, swap_type = BOOT_SWAP_TYPE_NONE; } } -#endif /* CONFIG_SOC_NRF5340_CPUAPP && PM_CPUNET_B0N_ADDRESS && - !CONFIG_NRF53_MULTI_IMAGE_UPDATE && CONFIG_PCD_APP */ +#endif /* CONFIG_SOC_NRF5340_CPUAPP */ } return swap_type; From c99f1dc80d2b4542bbd6bf4dac140d37d98bf4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 134/287] Revert "[nrf noup] loader: work-around for multi-image builds" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c85abeec4c1f0fbf1c4b563fb1219329c66a92f4. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 72135088e..78e7faf2b 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -484,7 +484,7 @@ boot_verify_dependencies(struct boot_loader_state *state) if (rc == 0) { /* All dependencies've been satisfied, continue with next image. */ BOOT_CURR_IMG(state)++; - } else if (rc == BOOT_EBADIMAGE) { + } else { /* Cannot upgrade due to non-met dependencies, so disable all * image upgrades. */ @@ -493,10 +493,7 @@ boot_verify_dependencies(struct boot_loader_state *state) BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; } break; - } else { - /* Other error happened, images are inconsistent */ - return rc; - } + } } return rc; } @@ -1862,6 +1859,7 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) } #endif + /** * Performs a clean (not aborted) image update. * From 2ee7e90f2cf1e1ec6ab78f0f4d9ed431fdffabf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 135/287] Revert "[nrf noup] boot/zephyr/boards: nRF54l15pdk ext flash cfg" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 513e91d505e178d4c4cbbe4fd5d3fa2230fc0ade. Signed-off-by: Andrzej Głąbek --- .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf | 8 -------- .../nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 10 ---------- 2 files changed, 18 deletions(-) delete mode 100644 boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf delete mode 100644 boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf deleted file mode 100644 index 841922dbd..000000000 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_MULTITHREADING=y -CONFIG_SPI=y -CONFIG_SPI_NOR=y -CONFIG_FLASH=y -CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 -CONFIG_MAIN_STACK_SIZE=20480 -CONFIG_BOOT_MAX_IMG_SECTORS=512 -CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay deleted file mode 100644 index 2341ffd26..000000000 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay +++ /dev/null @@ -1,10 +0,0 @@ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; - - -&mx25r64 { - status = "okay"; -}; From 5fe2f59b6fe206ce5081cf765eb8b72ec5e4ee99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 136/287] Revert "[nrf noup] boards: thingy53: disable GPIO ISR support" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 0564022cdfa7d8a20c36a9c2d0bfb4b8be77c1da. Signed-off-by: Andrzej Głąbek --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index e10656678..7d3bc0bec 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -21,7 +21,6 @@ CONFIG_UART_LINE_CTRL=y # MCUBoot serial CONFIG_GPIO=y -CONFIG_GPIO_NRFX_INTERRUPT=n CONFIG_MCUBOOT_SERIAL=y CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_CDC_ACM=y From 6abe5011a8667991556854d92450a9aea74633e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 137/287] =?UTF-8?q?Revert=20"[nrf=20noup]=C2=A0loader:=20A?= =?UTF-8?q?dd=20firmware=20version=20check=20downgrade=20prevention"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 186c927143ffac9ab1cd95bbf52ed459f1da127b. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 78e7faf2b..b71ff90b7 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -51,10 +51,6 @@ #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) #include -#ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION -#include -int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); -#endif #endif #ifdef MCUBOOT_ENC_IMAGES @@ -1101,21 +1097,9 @@ boot_validate_slot(struct boot_loader_state *state, int slot, #if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION) if (slot != BOOT_PRIMARY_SLOT) { /* Check if version of secondary slot is sufficient */ - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ - && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) - if (BOOT_CURR_IMG(state) == 1) { - rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); - } else { - rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); - } -#else - rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); -#endif + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); flash_area_erase(fap, 0, flash_area_get_size(fap)); From aced3e3066dc6900dd2486db2e2189ab120765d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 138/287] Revert "[nrf noup] zephyr: Boot even if EXT_ABI is not provided" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 5e9aa4cb55cd88623976bb014c0a9c94425774be. Signed-off-by: Andrzej Głąbek --- boot/zephyr/main.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index b5a65e460..8aec9cf0d 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -206,16 +206,13 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); - bool provided = fw_info_ext_api_provide(firmware_info, true); + bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); #ifdef PM_S0_ADDRESS /* Only fail if the immutable bootloader is present. */ if (!provided) { - if (firmware_info == NULL) { - BOOT_LOG_WRN("Unable to find firmware info structure in %p", vt); - } - BOOT_LOG_ERR("Failed to provide EXT_APIs to %p", vt); + BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); + return; } #endif #endif From 27eb775b719d37081192c32bc42c64e20e9e2f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 139/287] Revert "[nrf noup] zephyr: Add RAM flash configuration to cache for sysbuild" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9d52cc5cd8e6b45bdb8becd92641d05acff03e22. Signed-off-by: Andrzej Głąbek --- boot/zephyr/CMakeLists.txt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 1d3009b22..a288410bf 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -579,14 +579,3 @@ zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) endif() - -if(SYSBUILD AND CONFIG_PCD_APP) - # Sysbuild requires details of the RAM flash device are stored to the cache of MCUboot so - # that they can be read when running partition manager - dt_nodelabel(ram_flash_dev NODELABEL flash_sim0) - dt_reg_addr(ram_flash_addr PATH ${ram_flash_dev}) - dt_reg_size(ram_flash_size PATH ${ram_flash_dev}) - - set(RAM_FLASH_ADDR "${ram_flash_addr}" CACHE STRING "" FORCE) - set(RAM_FLASH_SIZE "${ram_flash_size}" CACHE STRING "" FORCE) -endif() From bfd303433dcfb13aa3e820df4793d1697c565634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 140/287] Revert "[nrf noup] loader: Do not check reset vector for XIP image" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ec9999f7f812edea4679de01b72ae78e5438b1a1. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index b71ff90b7..9dfb6506c 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1141,16 +1141,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * overwriting an application written to the incorrect slot. * This feature is only supported by ARM platforms. */ -#if MCUBOOT_IMAGE_NUMBER >= 3 - /* Currently the MCUboot can be configured for up to 3 image, where image number 2 is - * designated for XIP, where it is the second part of image stored in slots of image - * 0. This part of image is not bootable, as the XIP setup is done by the app in - * image 0 slot, and it does not carry the reset vector. - */ - if (area_id == FLASH_AREA_IMAGE_SECONDARY(2)) { - goto out; - } -#endif if (area_id == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); struct image_header *secondary_hdr = boot_img_hdr(state, slot); From 1746c575c9869249b1d649625086f19f2e14c8b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 141/287] Revert "[nrf noup] zephyr: Fix path variables" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit d978f7b4e9c000d554242c65800fdee51381a3d2. Signed-off-by: Andrzej Głąbek --- boot/zephyr/CMakeLists.txt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index a288410bf..fde155833 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -27,20 +27,21 @@ assert_exists(FIAT_DIR) # Path to mbed-tls' asn1 parser library. set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") assert_exists(MBEDTLS_ASN1_DIR) -set(MCUBOOT_NRF_EXT_DIR "${MCUBOOT_DIR}/ext/nrf") +set(NRF_DIR "${MCUBOOT_DIR}/ext/nrf") if(CONFIG_BOOT_USE_NRF_CC310_BL) - if(NOT EXISTS ${ZEPHYR_NRFXLIB_MODULE_DIR}) - message(FATAL_ERROR " +set(NRFXLIB_DIR ${ZEPHYR_BASE}/../nrfxlib) +if(NOT EXISTS ${NRFXLIB_DIR}) + message(FATAL_ERROR " ------------------------------------------------------------------------ - No such file or directory: ${ZEPHYR_NRFXLIB_MODULE_DIR} + No such file or directory: ${NRFXLIB_DIR} The current configuration enables nRF CC310 crypto accelerator hardware with the `CONFIG_BOOT_USE_NRF_CC310_BL` option. Please follow `ext/nrf/README.md` guide to fix your setup or use tinycrypt instead of the HW accelerator. To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") - endif() +endif() endif() zephyr_library_include_directories( @@ -168,8 +169,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) ${TINYCRYPT_DIR}/source/utils.c ) elseif(CONFIG_BOOT_USE_NRF_CC310_BL) - zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) - zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) + zephyr_library_sources(${NRF_DIR}/cc310_glue.c) + zephyr_library_include_directories(${NRF_DIR}) zephyr_link_libraries(nrfxlib_crypto) endif() From d47f6bcf962ef2ff606ab06c62b2413e6c3e3d77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 142/287] Revert "[nrf noup] loader: Fix reading reset addr to support ext flash" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f6bedc90762987f24cdc71a4b3014f85a3cb85e5. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 9dfb6506c..ea2e968a8 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1258,9 +1258,10 @@ boot_validated_swap_type(struct boot_loader_state *state, #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = 0; + uint32_t *vtable = 0; uint32_t reset_addr = 0; - int rc = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1270,19 +1271,16 @@ boot_validated_swap_type(struct boot_loader_state *state, */ if (hdr->ih_magic == IMAGE_MAGIC) { - rc = flash_area_read(secondary_fa, hdr->ih_hdr_size + - sizeof(uint32_t), &reset_addr, - sizeof(reset_addr)); - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } + vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + vtable = (uint32_t *)(vtable_addr); + reset_addr = vtable[1]; #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif { const struct flash_area *primary_fa; - rc = flash_area_open(flash_area_id_from_multi_image_slot( + int rc = flash_area_open(flash_area_id_from_multi_image_slot( BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), &primary_fa); @@ -1318,19 +1316,16 @@ boot_validated_swap_type(struct boot_loader_state *state, upgrade_valid = true; } -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ - && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available */ if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { - struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; - uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); uint32_t fw_size = hdr->ih_img_size; + BOOT_LOG_INF("Starting network core update"); - rc = pcd_network_core_update(net_core_fw_addr, fw_size); + int rc = pcd_network_core_update(vtable, fw_size); if (rc != 0) { swap_type = BOOT_SWAP_TYPE_FAIL; From 83b9d544fcd90cd0f890475af3cdda719513a088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 143/287] Revert "[nrf noup] zephyr: Clean up non-secure RAM if enabled" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 75ab2de55cd557d4c19f5ed97bc508ddce07818a. Signed-off-by: Andrzej Głąbek --- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/include/nrf_cleanup.h | 5 -- boot/zephyr/main.c | 5 +- boot/zephyr/nrf_cleanup.c | 79 ++++++++----------------------- 4 files changed, 22 insertions(+), 69 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index fde155833..b60b0c95d 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -575,7 +575,7 @@ if(SYSBUILD) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL OR CONFIG_MCUBOOT_CLEANUP_NONSECURE_RAM) +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h index 9e87e13f5..6b04cedfe 100644 --- a/boot/zephyr/include/nrf_cleanup.h +++ b/boot/zephyr/include/nrf_cleanup.h @@ -16,9 +16,4 @@ */ void nrf_cleanup_peripheral(void); -/** - * Perform cleanup of non-secure RAM that may have been used by MCUBoot. - */ -void nrf_cleanup_ns_ram(void); - #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 8aec9cf0d..c76ed18b3 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -142,7 +142,7 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL || CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL #include #endif @@ -219,9 +219,6 @@ static void do_boot(struct boot_rsp *rsp) #if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL nrf_cleanup_peripheral(); #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM && defined(PM_SRAM_NONSECURE_NAME) - nrf_cleanup_ns_ram(); -#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 051705ec9..5bab26b24 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -5,8 +5,9 @@ */ #include -#include -#include +#if defined(NRF_UARTE0) || defined(NRF_UARTE1) + #include +#endif #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif @@ -19,15 +20,6 @@ #include -#if USE_PARTITION_MANAGER -#include -#endif - -#if defined(NRF_UARTE0) || defined(NRF_UARTE1) || defined(NRF_UARTE20) || \ - defined(NRF_UARTE30) -#define NRF_UARTE_CLEANUP -#endif - #define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) #define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ NRF_UARTE_SUBSCRIBE_CONF_OFFS) @@ -45,23 +37,6 @@ static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) } #endif -#if defined(NRF_UARTE_CLEANUP) -static NRF_UARTE_Type *nrf_uarte_to_clean[] = { -#if defined(NRF_UARTE0) - NRF_UARTE0, -#endif -#if defined(NRF_UARTE1) - NRF_UARTE1, -#endif -#if defined(NRF_UARTE20) - NRF_UARTE20, -#endif -#if defined(NRF_UARTE30) - NRF_UARTE30, -#endif -}; -#endif - static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); @@ -78,31 +53,26 @@ void nrf_cleanup_peripheral(void) #if defined(NRF_RTC2) nrf_cleanup_rtc(NRF_RTC2); #endif - -#if defined(NRF_UARTE_CLEANUP) - for (int i = 0; i < sizeof(nrf_uarte_to_clean) / sizeof(nrf_uarte_to_clean[0]); ++i) { - NRF_UARTE_Type *current = nrf_uarte_to_clean[i]; - - nrfy_uarte_int_disable(current, 0xFFFFFFFF); - nrfy_uarte_int_uninit(current); - nrfy_uarte_task_trigger(current, NRF_UARTE_TASK_STOPRX); - - nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXSTARTED); - nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_ENDRX); - nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); - nrfy_uarte_disable(current); - +#if defined(NRF_UARTE0) + nrf_uarte_disable(NRF_UARTE0); + nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); #if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)current + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, - NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)current + NRF_UARTE_PUBLISH_CONF_OFFS, 0, - NRF_UARTE_PUBLISH_CONF_SIZE); + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); +#endif +#endif +#if defined(NRF_UARTE1) + nrf_uarte_disable(NRF_UARTE1); + nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); +#if defined(NRF_DPPIC) + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); #endif - } #endif - #if defined(NRF_PPI) nrf_ppi_channels_disable_all(NRF_PPI); #endif @@ -111,12 +81,3 @@ void nrf_cleanup_peripheral(void) #endif nrf_cleanup_clock(); } - -#if USE_PARTITION_MANAGER \ - && defined(CONFIG_ARM_TRUSTZONE_M) \ - && defined(PM_SRAM_NONSECURE_NAME) -void nrf_cleanup_ns_ram(void) -{ - memset((void *) PM_SRAM_NONSECURE_ADDRESS, 0, PM_SRAM_NONSECURE_SIZE); -} -#endif From 287bc5f8a0d67f5982d90d0ed7138059ff980f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 144/287] Revert "[nrf noup] zephyr: clean peripherals state before boot" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c82aef67eb4e2573f7d06aed3279019e3e6953b0. Signed-off-by: Andrzej Głąbek --- boot/zephyr/CMakeLists.txt | 6 --- boot/zephyr/include/nrf_cleanup.h | 19 ------- boot/zephyr/main.c | 8 +-- boot/zephyr/nrf_cleanup.c | 83 ------------------------------- 4 files changed, 1 insertion(+), 115 deletions(-) delete mode 100644 boot/zephyr/include/nrf_cleanup.h delete mode 100644 boot/zephyr/nrf_cleanup.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index b60b0c95d..c3fe0bd74 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -574,9 +574,3 @@ if(SYSBUILD) set(mcuboot_image_footer_size ${required_size} CACHE INTERNAL "Estimated MCUboot image trailer size" FORCE) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() - -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) -zephyr_library_sources( - ${BOOT_DIR}/zephyr/nrf_cleanup.c -) -endif() diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h deleted file mode 100644 index 6b04cedfe..000000000 --- a/boot/zephyr/include/nrf_cleanup.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef H_NRF_CLEANUP_ -#define H_NRF_CLEANUP_ - -/** - * Perform cleanup on some peripheral resources used by MCUBoot prior chainload - * the application. - * - * This function disables all RTC instances and UARTE instances. - * It Disables their interrupts signals as well. - */ -void nrf_cleanup_peripheral(void); - -#endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index c76ed18b3..3e0b100ca 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -142,10 +142,6 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL -#include -#endif - BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -216,9 +212,7 @@ static void do_boot(struct boot_rsp *rsp) } #endif #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL - nrf_cleanup_peripheral(); -#endif + #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c deleted file mode 100644 index 5bab26b24..000000000 --- a/boot/zephyr/nrf_cleanup.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#if defined(NRF_UARTE0) || defined(NRF_UARTE1) - #include -#endif -#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) - #include -#endif -#if defined(NRF_PPI) - #include -#endif -#if defined(NRF_DPPIC) - #include -#endif - -#include - -#define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) -#define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ - NRF_UARTE_SUBSCRIBE_CONF_OFFS) - -#define NRF_UARTE_PUBLISH_CONF_OFFS offsetof(NRF_UARTE_Type, PUBLISH_CTS) -#define NRF_UARTE_PUBLISH_CONF_SIZE (offsetof(NRF_UARTE_Type, SHORTS) -\ - NRF_UARTE_PUBLISH_CONF_OFFS) - -#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) -static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) -{ - nrf_rtc_task_trigger(rtc_reg, NRF_RTC_TASK_STOP); - nrf_rtc_event_disable(rtc_reg, 0xFFFFFFFF); - nrf_rtc_int_disable(rtc_reg, 0xFFFFFFFF); -} -#endif - -static void nrf_cleanup_clock(void) -{ - nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); -} - -void nrf_cleanup_peripheral(void) -{ -#if defined(NRF_RTC0) - nrf_cleanup_rtc(NRF_RTC0); -#endif -#if defined(NRF_RTC1) - nrf_cleanup_rtc(NRF_RTC1); -#endif -#if defined(NRF_RTC2) - nrf_cleanup_rtc(NRF_RTC2); -#endif -#if defined(NRF_UARTE0) - nrf_uarte_disable(NRF_UARTE0); - nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); -#if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); -#endif -#endif -#if defined(NRF_UARTE1) - nrf_uarte_disable(NRF_UARTE1); - nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); -#if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); -#endif -#endif -#if defined(NRF_PPI) - nrf_ppi_channels_disable_all(NRF_PPI); -#endif -#if defined(NRF_DPPIC) - nrf_dppi_channels_disable_all(NRF_DPPIC); -#endif - nrf_cleanup_clock(); -} From 33b8200189e1cda247899cbe351585eec5d58d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 145/287] Revert "[nrf noup] boot: nrf53-specific customizations" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9c26bb601e487ec60629ebcb6898f47ec3360100. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 96 +++++-------------- .../boards/thingy53_nrf5340_cpuapp.conf | 74 +------------- boot/zephyr/include/sysflash/sysflash.h | 23 ----- boot/zephyr/main.c | 7 -- boot/zephyr/pm.yml | 13 --- 5 files changed, 28 insertions(+), 185 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index ea2e968a8..a9bd131dd 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,10 +49,6 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) -#include -#endif - #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -1253,15 +1249,7 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); - bool upgrade_valid = false; - -#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) - const struct flash_area *secondary_fa = - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; - uint32_t vtable_addr = 0; - uint32_t *vtable = 0; - uint32_t reset_addr = 0; +#ifdef PM_S1_ADDRESS /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1269,36 +1257,34 @@ boot_validated_swap_type(struct boot_loader_state *state, * vector. Note that there are good reasons for not using img_num from * the swap info. */ + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = + (struct image_header *)secondary_fa->fa_off; if (hdr->ih_magic == IMAGE_MAGIC) { - vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - vtable = (uint32_t *)(vtable_addr); - reset_addr = vtable[1]; -#ifdef PM_S1_ADDRESS -#ifdef PM_CPUNET_B0N_ADDRESS - if(reset_addr < PM_CPUNET_B0N_ADDRESS) -#endif - { - const struct flash_area *primary_fa; - int rc = flash_area_open(flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ - return BOOT_SWAP_TYPE_NONE; - } - } -#endif /* PM_S1_ADDRESS */ + const struct flash_area *primary_fa; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *vtable = (uint32_t *)(vtable_addr); + uint32_t reset_addr = vtable[1]; + int rc = flash_area_open( + flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ + return BOOT_SWAP_TYPE_NONE; + } } -#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ +#endif swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -1312,37 +1298,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } else { swap_type = BOOT_SWAP_TYPE_FAIL; } - } else { - upgrade_valid = true; - } - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) - /* If the update is valid, and it targets the network core: perform the - * update and indicate to the caller of this function that no update is - * available - */ - if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { - uint32_t fw_size = hdr->ih_img_size; - - BOOT_LOG_INF("Starting network core update"); - int rc = pcd_network_core_update(vtable, fw_size); - - if (rc != 0) { - swap_type = BOOT_SWAP_TYPE_FAIL; - } else { - BOOT_LOG_INF("Done updating network core"); -#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) - /* swap_erase_trailer_sectors is undefined if upgrade only - * method is used. There is no need to erase sectors, because - * the image cannot be reverted. - */ - rc = swap_erase_trailer_sectors(state, - secondary_fa); -#endif - swap_type = BOOT_SWAP_TYPE_NONE; - } } -#endif /* CONFIG_SOC_NRF5340_CPUAPP */ } return swap_type; diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index 7d3bc0bec..f2e42fd64 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -1,73 +1,3 @@ -CONFIG_SIZE_OPTIMIZATIONS=y - -CONFIG_SYSTEM_CLOCK_NO_WAIT=y -CONFIG_PM=n - -CONFIG_MAIN_STACK_SIZE=10240 -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -CONFIG_BOOT_MAX_IMG_SECTORS=2048 -CONFIG_BOOT_SIGNATURE_TYPE_RSA=y - -# Flash -CONFIG_FLASH=y -CONFIG_BOOT_ERASE_PROGRESSIVELY=y -CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y -CONFIG_FPROTECT=y - -# Serial -CONFIG_SERIAL=y -CONFIG_UART_LINE_CTRL=y - -# MCUBoot serial -CONFIG_GPIO=y -CONFIG_MCUBOOT_SERIAL=y -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y -CONFIG_BOOT_SERIAL_CDC_ACM=y - -# Required by QSPI -CONFIG_NORDIC_QSPI_NOR=y -CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 -CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 - -# Required by USB and QSPI -CONFIG_MULTITHREADING=y - -# USB -CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n -CONFIG_USB_DEVICE_REMOTE_WAKEUP=n -CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor ASA" -CONFIG_USB_DEVICE_PRODUCT="Bootloader Thingy:53" -CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x5300 -CONFIG_USB_CDC_ACM=y - -# Decrease memory footprint -CONFIG_CBPRINTF_NANO=y -CONFIG_TIMESLICING=n -CONFIG_BOOT_BANNER=n -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n -CONFIG_LOG=n -CONFIG_ERRNO=n -CONFIG_PRINTK=n -CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_NORDIC_QSPI_NOR=n CONFIG_SPI=n -CONFIG_I2C=n -CONFIG_UART_NRFX=n - -# The following configurations are required to support simultaneous multi image update -CONFIG_PCD_APP=y -CONFIG_UPDATEABLE_IMAGE_NUMBER=2 -CONFIG_BOOT_UPGRADE_ONLY=y -# The network core cannot access external flash directly. The flash simulator must be used to -# provide a memory region that is used to forward the new firmware to the network core. -CONFIG_FLASH_SIMULATOR=y -CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y -CONFIG_FLASH_SIMULATOR_STATS=n - -# Enable custom command to erase settings partition. -CONFIG_ENABLE_MGMT_PERUSER=y -CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE=y +CONFIG_MULTITHREADING=y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index b98e48bce..4eaf0309e 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -20,11 +20,6 @@ #elif (MCUBOOT_IMAGE_NUMBER == 2) -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -#ifdef PM_B0_ADDRESS - extern uint32_t _image_1_primary_slot_id[]; #define FLASH_AREA_IMAGE_PRIMARY(x) \ @@ -40,24 +35,6 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) -#else - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) - -#endif /* PM_B0_ADDRESS */ - #endif #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 3e0b100ca..abc57596a 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -91,10 +91,6 @@ const struct boot_uart_funcs boot_funcs = { #include #endif -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) -#include -#endif - /* CONFIG_LOG_MINIMAL is the legacy Kconfig property, * replaced by CONFIG_LOG_MODE_MINIMAL. */ @@ -606,9 +602,6 @@ int main(void) ; } -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) - pcd_lock_ram(); -#endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ ZEPHYR_BOOT_LOG_STOP(); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index 13ffc44aa..5df9ae547 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -75,16 +75,3 @@ mcuboot_pad: #ifdef CONFIG_FPROTECT align: {start: CONFIG_FPROTECT_BLOCK_SIZE} #endif - -#if (CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH) -mcuboot_primary_1: - region: ram_flash - size: CONFIG_NRF53_RAM_FLASH_SIZE -#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ - -#if (CONFIG_NRF53_MULTI_IMAGE_UPDATE) -mcuboot_secondary_1: - region: external_flash - size: CONFIG_NRF53_RAM_FLASH_SIZE - -#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ From 86e391d7f0a5086266aa9213018ee30919e12835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 146/287] Revert "[nrf noup] treewide: add NCS partition manager support" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 6a5dc04d20332548471564c0d88226c70f54f696. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 95 +++---------------------- boot/bootutil/src/swap_move.c | 13 ---- boot/bootutil/src/swap_scratch.c | 13 ---- boot/zephyr/CMakeLists.txt | 7 -- boot/zephyr/Kconfig | 2 - boot/zephyr/include/sysflash/sysflash.h | 48 ------------- boot/zephyr/include/target.h | 4 -- boot/zephyr/main.c | 45 ------------ boot/zephyr/pm.yml | 77 -------------------- boot/zephyr/prj.conf | 1 - ext/nrf/cc310_glue.h | 2 +- zephyr/module.yml | 3 +- 12 files changed, 11 insertions(+), 299 deletions(-) delete mode 100644 boot/zephyr/pm.yml diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a9bd131dd..12d4abf40 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -133,15 +133,6 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. The primary slot of the second image - * (image 1) will not contain a valid image header until an upgrade - * of mcuboot has happened (filling S1 with the new version). - */ - if (BOOT_CURR_IMG(state) == 1 && i == 0) { - continue; - } -#endif /* PM_S1_ADDRESS */ if (i > 0 && !require_all) { return 0; } else { @@ -1149,24 +1140,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, goto out; } - uint32_t min_addr, max_addr; - -#ifdef PM_CPUNET_APP_ADDRESS - /* The primary slot for the network core is emulated in RAM. - * Its flash_area hasn't got relevant boundaries. - * Therfore need to override its boundaries for the check. - */ - if (BOOT_CURR_IMG(state) == 1) { - min_addr = PM_CPUNET_APP_ADDRESS; - max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; - } else -#endif - { - min_addr = pri_fa->fa_off; - max_addr = pri_fa->fa_off + pri_fa->fa_size; - } - - if (reset_value < min_addr || reset_value> (max_addr)) { + if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1249,42 +1223,6 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other - * B1 slot S0 or S1) share the same secondary slot, we need to check - * whether the update candidate in the secondary slot is intended for - * image 0 or image 1 primary by looking at the address of the reset - * vector. Note that there are good reasons for not using img_num from - * the swap info. - */ - const struct flash_area *secondary_fa = - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = - (struct image_header *)secondary_fa->fa_off; - - if (hdr->ih_magic == IMAGE_MAGIC) { - const struct flash_area *primary_fa; - uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - uint32_t *vtable = (uint32_t *)(vtable_addr); - uint32_t reset_addr = vtable[1]; - int rc = flash_area_open( - flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ - return BOOT_SWAP_TYPE_NONE; - } - } -#endif swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2493,25 +2431,15 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. Image 1 primary is the currently - * executing MCUBoot image, and is therefore already validated by NSIB and - * does not need to also be validated by MCUBoot. + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL); + /* Check for all possible values is redundant in normal operation it + * is meant to prevent FI attack. */ - bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; - if (!image_validated_by_nsib) -#endif - { - FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL); - /* Check for all possible values is redundant in normal operation it - * is meant to prevent FI attack. - */ - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || - FIH_EQ(fih_rc, FIH_FAILURE) || - FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || + FIH_EQ(fih_rc, FIH_FAILURE) || + FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; } #else /* Even if we're not re-validating the primary slot, we could be booting @@ -2528,16 +2456,11 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ -#ifdef PM_S1_ADDRESS - if (!image_validated_by_nsib) -#endif - { rc = boot_update_hw_rollback_protection(state); if (rc != 0) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } - } rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT); if (rc != 0) { diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 20caa2b5c..8999403c5 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -259,18 +259,6 @@ static int app_max_sectors(struct boot_loader_state *state) int boot_slots_compatible(struct boot_loader_state *state) { -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. In this case, image 1 primary points to the other - * B1 slot (ie S0 or S1), and image 0 primary points to the app. - * With this configuration, image 0 and image 1 share the secondary slot. - * Hence, the primary slot of image 1 will be *smaller* than image 1's - * secondary slot. This is not allowed in upstream mcuboot, so we need - * this patch to allow it. Also, all of these checks are redundant when - * partition manager is in use, and since we have the same sector size - * in all of our flash. - */ - return 1; -#else size_t num_sectors_pri; size_t num_sectors_sec; size_t sector_sz_pri = 0; @@ -318,7 +306,6 @@ boot_slots_compatible(struct boot_loader_state *state) } return 1; -#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index 66dca83e9..f60109120 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -141,18 +141,6 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. In this case, image 1 primary points to the other - * B1 slot (ie S0 or S1), and image 0 primary points to the app. - * With this configuration, image 0 and image 1 share the secondary slot. - * Hence, the primary slot of image 1 will be *smaller* than image 1's - * secondary slot. This is not allowed in upstream mcuboot, so we need - * this patch to allow it. Also, all of these checks are redundant when - * partition manager is in use, and since we have the same sector size - * in all of our flash. - */ - return 1; -#else size_t num_sectors_primary; size_t num_sectors_secondary; size_t sz0, sz1; @@ -250,7 +238,6 @@ boot_slots_compatible(struct boot_loader_state *state) #endif return 1; -#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index c3fe0bd74..89d76e991 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -295,13 +295,6 @@ if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") endif() message("MCUBoot bootloader key file: ${KEY_FILE}") - set_property( - GLOBAL - PROPERTY - KEY_FILE - ${KEY_FILE} - ) - set(GENERATED_PUBKEY ${ZEPHYR_BINARY_DIR}/autogen-pubkey.c) add_custom_command( OUTPUT ${GENERATED_PUBKEY} diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a641f3e6a..931bccbbb 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -9,8 +9,6 @@ mainmenu "MCUboot configuration" comment "MCUboot-specific configuration options" -source "$(ZEPHYR_NRF_MODULE_DIR)/modules/mcuboot/boot/zephyr/Kconfig" - # Hidden option to mark a project as MCUboot config MCUBOOT default y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 4eaf0309e..1952950b9 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -7,52 +7,6 @@ #ifndef __SYSFLASH_H__ #define __SYSFLASH_H__ -#if USE_PARTITION_MANAGER -#include -#include - -#ifndef CONFIG_SINGLE_APPLICATION_SLOT - -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - -extern uint32_t _image_1_primary_slot_id[]; - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) -#endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID - -#else /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID -/* NOTE: Scratch parition is not used by single image DFU but some of - * functions in common files reference it, so the definitions has been - * provided to allow compilation of common units. - */ -#define FLASH_AREA_IMAGE_SCRATCH 0 - -#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#else - -#include #include #include #include @@ -111,6 +65,4 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ -#endif /* USE_PARTITION_MANAGER */ - #endif /* __SYSFLASH_H__ */ diff --git a/boot/zephyr/include/target.h b/boot/zephyr/include/target.h index 40287d515..9bbfd4b19 100644 --- a/boot/zephyr/include/target.h +++ b/boot/zephyr/include/target.h @@ -8,8 +8,6 @@ #ifndef H_TARGETS_TARGET_ #define H_TARGETS_TARGET_ -#ifndef USE_PARTITION_MANAGER - #if defined(MCUBOOT_TARGET_CONFIG) /* * Target-specific definitions are permitted in legacy cases that @@ -47,6 +45,4 @@ #error "Target support is incomplete; cannot build mcuboot." #endif -#endif /* ifndef USE_PARTITION_MANAGER */ - #endif /* H_TARGETS_TARGET_ */ diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index abc57596a..fe0016c8c 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -69,10 +69,6 @@ #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */ -#ifdef CONFIG_FW_INFO -#include -#endif - #ifdef CONFIG_MCUBOOT_SERIAL #include "boot_serial/boot_serial.h" #include "serial_adapter/serial_adapter.h" @@ -133,11 +129,6 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); * !defined(ZEPHYR_LOG_MODE_MINIMAL) */ -#if USE_PARTITION_MANAGER && CONFIG_FPROTECT -#include -#include -#endif - BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -196,19 +187,6 @@ static void do_boot(struct boot_rsp *rsp) /* Disable the USB to prevent it from firing interrupts */ usb_disable(); #endif - -#if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); - -#ifdef PM_S0_ADDRESS - /* Only fail if the immutable bootloader is present. */ - if (!provided) { - BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); - return; - } -#endif -#endif - #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ @@ -582,30 +560,7 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND); -#if USE_PARTITION_MANAGER && CONFIG_FPROTECT - -#ifdef PM_S1_ADDRESS -/* MCUBoot is stored in either S0 or S1, protect both */ -#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_S0_ADDRESS) -#define PROTECT_ADDR PM_S0_ADDRESS -#else -/* There is only one instance of MCUBoot */ -#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_MCUBOOT_ADDRESS) -#define PROTECT_ADDR PM_MCUBOOT_ADDRESS -#endif - - rc = fprotect_area(PROTECT_ADDR, PROTECT_SIZE); - - if (rc != 0) { - BOOT_LOG_ERR("Protect mcuboot flash failed, cancel startup."); - while (1) - ; - } - -#endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ - ZEPHYR_BOOT_LOG_STOP(); - do_boot(&rsp); mcuboot_status_change(MCUBOOT_STATUS_BOOT_FAILED); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml deleted file mode 100644 index 5df9ae547..000000000 --- a/boot/zephyr/pm.yml +++ /dev/null @@ -1,77 +0,0 @@ -#include - -mcuboot: - size: CONFIG_PM_PARTITION_SIZE_MCUBOOT - placement: - before: [mcuboot_primary] -#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) - align: {end: 0x1000} -#endif - -mcuboot_primary_app: - # All images to be placed in MCUboot's slot 0 should be placed in this - # partition - span: [app] - -mcuboot_primary: - span: [mcuboot_pad, mcuboot_primary_app] - -# Partition for secondary slot is not created if building in single application -# slot configuration. -#if !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) -mcuboot_secondary: - share_size: [mcuboot_primary] -#if defined(CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) - region: external_flash - placement: - align: {start: 4} -#else - placement: - align: {start: CONFIG_FPROTECT_BLOCK_SIZE} - align_next: CONFIG_FPROTECT_BLOCK_SIZE # Ensure that the next partition does not interfere with this image - after: mcuboot_primary -#endif /* CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY */ - -#endif /* !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) */ - -#if CONFIG_BOOT_DIRECT_XIP - -# Direct XIP is enabled, reserve area for metadata (padding) and name the -# partition so that its clear that it is not the secondary slot, but the direct -# XIP alternative. - -mcuboot_secondary_pad: - share_size: mcuboot_pad - placement: - after: mcuboot_primary - align: {start: CONFIG_FPROTECT_BLOCK_SIZE} - -mcuboot_secondary_app: - share_size: mcuboot_primary_app - placement: - after: mcuboot_secondary_pad - -mcuboot_secondary: - span: [mcuboot_secondary_pad, mcuboot_secondary_app] - -#endif /* CONFIG_BOOT_DIRECT_XIP */ - -#if CONFIG_BOOT_SWAP_USING_SCRATCH -mcuboot_scratch: - size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_SCRATCH - placement: - after: app - align: {start: CONFIG_FPROTECT_BLOCK_SIZE} -#endif /* CONFIG_BOOT_SWAP_USING_SCRATCH */ - -# Padding placed before image to boot. This reserves space for the MCUboot image header -# and it ensures that the boot image gets linked with the correct address offset in flash. -mcuboot_pad: - # MCUboot pad must be placed before the primary application partition. - # The primary application partition includes the secure firmware if present. - size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_PAD - placement: - before: [mcuboot_primary_app] -#ifdef CONFIG_FPROTECT - align: {start: CONFIG_FPROTECT_BLOCK_SIZE} -#endif diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 23b5f3b93..58cb2ae35 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -19,7 +19,6 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_TINYCRYPT_SHA256 is not set CONFIG_FLASH=y -CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/ext/nrf/cc310_glue.h b/ext/nrf/cc310_glue.h index 22eb94911..ed3ed5c00 100644 --- a/ext/nrf/cc310_glue.h +++ b/ext/nrf/cc310_glue.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include /* diff --git a/zephyr/module.yml b/zephyr/module.yml index 9360dbf70..014a21956 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -1,6 +1,5 @@ samples: - boot/zephyr build: - cmake-ext: True - kconfig-ext: True + cmake: ./boot/bootutil/zephyr sysbuild-cmake: boot/zephyr/sysbuild From 61be87f4812628ee695f87de33e24d6ef7f22e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 147/287] Revert "[nrf noup] boards: thingy91x: add board config" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e541ae9e6e9125bc3ae7457b395397541b3feca3. Signed-off-by: Andrzej Głąbek --- .../boards/thingy91x_nrf5340_cpuapp.conf | 54 ------------------- boot/zephyr/boards/thingy91x_nrf9151.conf | 8 --- 2 files changed, 62 deletions(-) delete mode 100644 boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf delete mode 100644 boot/zephyr/boards/thingy91x_nrf9151.conf diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf deleted file mode 100644 index 72dfa7fca..000000000 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ /dev/null @@ -1,54 +0,0 @@ -# MCUBoot settings -CONFIG_BOOT_MAX_IMG_SECTORS=110 - -# MCUboot serial recovery -CONFIG_MCUBOOT_SERIAL=y - -# Disable Zephyr console -CONFIG_LOG=n -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_UART_CONSOLE=n - -# Serial -CONFIG_SERIAL=y -CONFIG_UART_NRFX=y -CONFIG_UART_INTERRUPT_DRIVEN=y -CONFIG_UART_LINE_CTRL=y - -# MCUboot serial recovery -CONFIG_GPIO=y -CONFIG_MCUBOOT_SERIAL=y -CONFIG_BOOT_SERIAL_CDC_ACM=y - -# Required by USB -CONFIG_MULTITHREADING=y - -# USB -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" -CONFIG_USB_CDC_ACM=y -CONFIG_USB_COMPOSITE_DEVICE=y -CONFIG_USB_MASS_STORAGE=n -CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" -CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x520F - -CONFIG_BOOT_SERIAL_BOOT_MODE=y - -CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x13E00 - -# The following configurations are required to support simultaneous multi image update -CONFIG_PCD_APP=y -CONFIG_UPDATEABLE_IMAGE_NUMBER=2 -CONFIG_BOOT_UPGRADE_ONLY=y -# The network core cannot access external flash directly. The flash simulator must be used to -# provide a memory region that is used to forward the new firmware to the network core. -CONFIG_FLASH_SIMULATOR=y -CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y -CONFIG_FLASH_SIMULATOR_STATS=n - -CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y - -CONFIG_NRF53_RECOVERY_NETWORK_CORE=y diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf deleted file mode 100644 index 33cd3301c..000000000 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ /dev/null @@ -1,8 +0,0 @@ -# MCUBoot settings -CONFIG_BOOT_MAX_IMG_SECTORS=512 - -CONFIG_SPI=y -CONFIG_SPI_NOR=y -CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 -CONFIG_SPI_NOR_SFDP_DEVICETREE=y -CONFIG_MULTITHREADING=y From 51df21eb078d1ecc67ff3434a8874fc55f2cc609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 148/287] Revert "[nrf noup] zephyr: Restore default RTC user channel count" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 48e0d079a0cfaef6c3622c24f804f4057701dc87. Signed-off-by: Andrzej Głąbek --- boot/zephyr/prj.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 58cb2ae35..851c133ec 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -35,4 +35,3 @@ CONFIG_MCUBOOT_LOG_LEVEL_INF=y CONFIG_CBPRINTF_NANO=y ### Use the minimal C library to reduce flash usage CONFIG_MINIMAL_LIBC=y -CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 From a4b1583718e48136822cb1d0601c30ce4c339f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 149/287] Revert "[nrf noup] boards: add support for Thingy:91" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 1f7ca3dcfe94c8c929d0484ceec958bd7df2f4be. Signed-off-by: Andrzej Głąbek --- boot/zephyr/boards/thingy91_nrf52840.conf | 34 ----------------------- boot/zephyr/boards/thingy91_nrf9160.conf | 13 --------- 2 files changed, 47 deletions(-) delete mode 100644 boot/zephyr/boards/thingy91_nrf52840.conf delete mode 100644 boot/zephyr/boards/thingy91_nrf9160.conf diff --git a/boot/zephyr/boards/thingy91_nrf52840.conf b/boot/zephyr/boards/thingy91_nrf52840.conf deleted file mode 100644 index c0d183401..000000000 --- a/boot/zephyr/boards/thingy91_nrf52840.conf +++ /dev/null @@ -1,34 +0,0 @@ -# Disable Zephyr console -CONFIG_LOG=n -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_UART_CONSOLE=n - -# The build won't fit on the partition allocated for it without size -# optimizations. -CONFIG_SIZE_OPTIMIZATIONS=y -CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x12000 - -# Serial -CONFIG_SERIAL=y -CONFIG_UART_NRFX=y -CONFIG_UART_INTERRUPT_DRIVEN=y -CONFIG_UART_LINE_CTRL=y - -# MCUboot serial recovery -CONFIG_GPIO=y -CONFIG_MCUBOOT_SERIAL=y -CONFIG_BOOT_SERIAL_CDC_ACM=y - -# Required by USB -CONFIG_MULTITHREADING=y - -# USB -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" -CONFIG_USB_CDC_ACM=y -CONFIG_USB_COMPOSITE_DEVICE=y -CONFIG_USB_MASS_STORAGE=n -CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" -CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x520F diff --git a/boot/zephyr/boards/thingy91_nrf9160.conf b/boot/zephyr/boards/thingy91_nrf9160.conf deleted file mode 100644 index 1bf2e424d..000000000 --- a/boot/zephyr/boards/thingy91_nrf9160.conf +++ /dev/null @@ -1,13 +0,0 @@ -# Disable Zephyr console -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_UART_CONSOLE=n - -# Disable Flash protection -CONFIG_FPROTECT=n - -# MCUBoot settings -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# MCUboot serial recovery -CONFIG_MCUBOOT_SERIAL=y From b7f903e6f9251a246d1127ba5cf0713c8aeff6ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 150/287] Revert "[nrf noup] zephyr: add 'minimal' configuration files" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 883a6ceac3537e90505c54f3fa4082f07b79f647. Signed-off-by: Andrzej Głąbek --- .../nrf5340dk_nrf5340_cpuapp_minimal.conf | 13 ------ boot/zephyr/prj_minimal.conf | 40 ------------------- 2 files changed, 53 deletions(-) delete mode 100644 boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf delete mode 100644 boot/zephyr/prj_minimal.conf diff --git a/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf b/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf deleted file mode 100644 index dd5468106..000000000 --- a/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf +++ /dev/null @@ -1,13 +0,0 @@ -# -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# CC3xx is currently not used for nrf53 -CONFIG_HW_CC3XX=n -CONFIG_NRF_CC3XX_PLATFORM=n - -# Required for kernel operation -CONFIG_CLOCK_CONTROL=y -CONFIG_SYS_CLOCK_EXISTS=y diff --git a/boot/zephyr/prj_minimal.conf b/boot/zephyr/prj_minimal.conf deleted file mode 100644 index 55d4c6167..000000000 --- a/boot/zephyr/prj_minimal.conf +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -CONFIG_MAIN_STACK_SIZE=10240 -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -CONFIG_FLASH=y -CONFIG_FPROTECT=y -CONFIG_PM=n - -CONFIG_BOOT_SWAP_SAVE_ENCTLV=n -CONFIG_BOOT_ENCRYPT_IMAGE=n - -CONFIG_BOOT_BOOTSTRAP=n -CONFIG_BOOT_UPGRADE_ONLY=n - -### Minimal Configurations ### -CONFIG_BOOT_USE_MIN_PARTITION_SIZE=y -CONFIG_ASSERT=n -CONFIG_BOOT_BANNER=n -CONFIG_CLOCK_CONTROL=n -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_GPIO=n -CONFIG_KERNEL_MEM_POOL=n -CONFIG_LOG=n -CONFIG_MINIMAL_LIBC_CALLOC=n -CONFIG_MINIMAL_LIBC_MALLOC=n -CONFIG_MINIMAL_LIBC_REALLOCARRAY=n -CONFIG_NCS_SAMPLES_DEFAULTS=n -CONFIG_NO_RUNTIME_CHECKS=y -CONFIG_NRF_RTC_TIMER=n -CONFIG_PRINTK=n -CONFIG_SERIAL=n -CONFIG_SIZE_OPTIMIZATIONS=y -CONFIG_SYS_CLOCK_EXISTS=n -CONFIG_UART_CONSOLE=n From 3025955b4ea36f0ae21923247781469b61c1d8d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 151/287] Revert "[nrf noup] zephyr: Remove duplication from cmake" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b85273aabd958d332750fb936ee30e81db7bd670. Signed-off-by: Andrzej Głąbek --- boot/zephyr/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 89d76e991..d02f93a40 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -42,6 +42,8 @@ if(NOT EXISTS ${NRFXLIB_DIR}) To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") endif() +# Don't include this if we are using west + add_subdirectory(${NRFXLIB_DIR} ${PROJECT_BINARY_DIR}/nrfxlib) endif() zephyr_library_include_directories( From 122dd3deb87c7aeac4e7a169b92053dea21974b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 152/287] Revert "[nrf noup] github: Add a commit tags check workflow" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 17f3f7f51a8d1b18444c0bcb6a6f01b66ee33ae6. Signed-off-by: Andrzej Głąbek --- .github/workflows/commit-tags.yml | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 .github/workflows/commit-tags.yml diff --git a/.github/workflows/commit-tags.yml b/.github/workflows/commit-tags.yml deleted file mode 100644 index 534ed5b58..000000000 --- a/.github/workflows/commit-tags.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Commit tags - -on: - pull_request: - types: [synchronize, opened, reopened, edited, labeled, unlabeled, - milestoned, demilestoned, assigned, unassigned, ready_for_review, - review_requested] - -jobs: - commit_tags: - runs-on: ubuntu-22.04 - name: Run commit tags checks on patch series (PR) - steps: - - name: Update PATH for west - run: | - echo "$HOME/.local/bin" >> $GITHUB_PATH - - - name: Checkout the code - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - - name: Run the commit tags - uses: nrfconnect/action-commit-tags@main - with: - target: . - upstream: mcu-tools/mcuboot/main From 2317bc77802bd96ecf004310c41c094a14b38f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 153/287] Revert "[nrf fromtree] bootutil: Add SIG_PURE TLV" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 42a79a41ef7f9e9ecf70a39bbb81eb9dd6757fdd. Signed-off-by: Andrzej Głąbek --- scripts/imgtool/image.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 9946a2595..d05120548 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -83,7 +83,6 @@ 'ECDSASIG': 0x22, 'RSA3072': 0x23, 'ED25519': 0x24, - 'SIG_PURE': 0x25, 'ENCRSA2048': 0x30, 'ENCKW': 0x31, 'ENCEC256': 0x32, From 4c986a69d37acc4e838f8fcda2737261038214d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 154/287] Revert "[nrf noup] imgtool: create image obj with image_hash" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 38c662b4b81b5ac92adf16eb1975888b6d68fb30. Signed-off-by: Andrzej Głąbek --- scripts/imgtool/image.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index d05120548..5e10ab78a 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -604,8 +604,6 @@ def create(self, key, public_key_format, enckey, dependencies=None, sha.update(self.payload) digest = sha.digest() tlv.add(hash_tlv, digest) - # for external usage - self.image_hash = digest # Unless pure, we are signing digest. message = digest From f7b2f388c3550fd2d1d933ceb9a3e0a660de35b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 155/287] Revert "[nrf fromlist] imgtool: Add pure signature support" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit fe61522a37e7c2cd26ad560fb1068e6c8875a216. Signed-off-by: Andrzej Głąbek --- scripts/imgtool/image.py | 75 ++++++++-------------------------------- scripts/imgtool/main.py | 23 +++--------- 2 files changed, 20 insertions(+), 78 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 5e10ab78a..84811806d 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -188,15 +188,7 @@ def tlv_sha_to_sha(tlv): keys.X25519 : ['256', '512'] } -ALLOWED_PURE_KEY_SHA = { - keys.Ed25519 : ['512'] -} - -ALLOWED_PURE_SIG_TLVS = [ - TLV_VALUES['ED25519'] -] - -def key_and_user_sha_to_alg_and_tlv(key, user_sha, is_pure = False): +def key_and_user_sha_to_alg_and_tlv(key, user_sha): """Matches key and user requested sha to sha alogrithm and TLV name. The returned tuple will contain hash functions and TVL name. @@ -210,16 +202,12 @@ def key_and_user_sha_to_alg_and_tlv(key, user_sha, is_pure = False): # If key is not None, then we have to filter hash to only allowed allowed = None - allowed_key_ssh = ALLOWED_PURE_KEY_SHA if is_pure else ALLOWED_KEY_SHA try: - allowed = allowed_key_ssh[type(key)] - + allowed = ALLOWED_KEY_SHA[type(key)] except KeyError: raise click.UsageError("Colud not find allowed hash algorithms for {}" .format(type(key))) - - # Pure enforces auto, and user selection is ignored - if user_sha == 'auto' or is_pure: + if user_sha == 'auto': return USER_SHA_TO_ALG_AND_TLV[allowed[0]] if user_sha in allowed: @@ -457,13 +445,12 @@ def ecies_hkdf(self, enckey, plainkey): def create(self, key, public_key_format, enckey, dependencies=None, sw_type=None, custom_tlvs=None, compression_tlvs=None, compression_type=None, encrypt_keylen=128, clear=False, - fixed_sig=None, pub_key=None, vector_to_sign=None, - user_sha='auto', is_pure=False): + fixed_sig=None, pub_key=None, vector_to_sign=None, user_sha='auto'): self.enckey = enckey # key decides on sha, then pub_key; of both are none default is used check_key = key if key is not None else pub_key - hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha, is_pure) + hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha) # Calculate the hash of the public key if key is not None: @@ -603,16 +590,9 @@ def create(self, key, public_key_format, enckey, dependencies=None, sha = hash_algorithm() sha.update(self.payload) digest = sha.digest() + message = digest; tlv.add(hash_tlv, digest) - # Unless pure, we are signing digest. - message = digest - - if is_pure: - # Note that when Pure signature is used, hash TLV is not present. - message = bytes(self.payload) - e = STRUCT_ENDIAN_DICT[self.endian] - sig_pure = struct.pack(e + '?', True) - tlv.add('SIG_PURE', sig_pure) + self.image_hash = digest if vector_to_sign == 'payload': # Stop amending data to the image @@ -804,7 +784,7 @@ def verify(imgfile, key): version = struct.unpack('BBHI', b[20:28]) if magic != IMAGE_MAGIC: - return VerifyResult.INVALID_MAGIC, None, None, None + return VerifyResult.INVALID_MAGIC, None, None tlv_off = header_size + img_size tlv_info = b[tlv_off:tlv_off + TLV_INFO_SIZE] @@ -815,27 +795,11 @@ def verify(imgfile, key): magic, tlv_tot = struct.unpack('HH', tlv_info) if magic != TLV_INFO_MAGIC: - return VerifyResult.INVALID_TLV_INFO_MAGIC, None, None, None - - # This is set by existence of TLV SIG_PURE - is_pure = False + return VerifyResult.INVALID_TLV_INFO_MAGIC, None, None prot_tlv_size = tlv_off hash_region = b[:prot_tlv_size] - tlv_end = tlv_off + tlv_tot - tlv_off += TLV_INFO_SIZE # skip tlv info - - # First scan all TLVs in search of SIG_PURE - while tlv_off < tlv_end: - tlv = b[tlv_off:tlv_off + TLV_SIZE] - tlv_type, _, tlv_len = struct.unpack('BBH', tlv) - if tlv_type == TLV_VALUES['SIG_PURE']: - is_pure = True - break - tlv_off += TLV_SIZE + tlv_len - digest = None - tlv_off = header_size + img_size tlv_end = tlv_off + tlv_tot tlv_off += TLV_INFO_SIZE # skip tlv info while tlv_off < tlv_end: @@ -843,15 +807,15 @@ def verify(imgfile, key): tlv_type, _, tlv_len = struct.unpack('BBH', tlv) if is_sha_tlv(tlv_type): if not tlv_matches_key_type(tlv_type, key): - return VerifyResult.KEY_MISMATCH, None, None, None + return VerifyResult.KEY_MISMATCH, None, None off = tlv_off + TLV_SIZE digest = get_digest(tlv_type, hash_region) if digest == b[off:off + tlv_len]: if key is None: - return VerifyResult.OK, version, digest, None + return VerifyResult.OK, version, digest else: - return VerifyResult.INVALID_HASH, None, None, None - elif not is_pure and key is not None and tlv_type == TLV_VALUES[key.sig_tlv()]: + return VerifyResult.INVALID_HASH, None, None + elif key is not None and tlv_type == TLV_VALUES[key.sig_tlv()]: off = tlv_off + TLV_SIZE tlv_sig = b[off:off + tlv_len] payload = b[:prot_tlv_size] @@ -860,18 +824,9 @@ def verify(imgfile, key): key.verify(tlv_sig, payload) else: key.verify_digest(tlv_sig, digest) - return VerifyResult.OK, version, digest, None - except InvalidSignature: - # continue to next TLV - pass - elif is_pure and key is not None and tlv_type in ALLOWED_PURE_SIG_TLVS: - off = tlv_off + TLV_SIZE - tlv_sig = b[off:off + tlv_len] - try: - key.verify_digest(tlv_sig, hash_region) - return VerifyResult.OK, version, None, tlv_sig + return VerifyResult.OK, version, digest except InvalidSignature: # continue to next TLV pass tlv_off += TLV_SIZE + tlv_len - return VerifyResult.INVALID_SIGNATURE, None, None, None + return VerifyResult.INVALID_SIGNATURE, None, None diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 03d46c907..009d9234c 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -226,14 +226,11 @@ def getpriv(key, minimal, format): @click.command(help="Check that signed image can be verified by given key") def verify(key, imgfile): key = load_key(key) if key else None - ret, version, digest, signature = image.Image.verify(imgfile, key) + ret, version, digest = image.Image.verify(imgfile, key) if ret == image.VerifyResult.OK: print("Image was correctly validated") print("Image version: {}.{}.{}+{}".format(*version)) - if digest: - print("Image digest: {}".format(digest.hex())) - if signature and digest is None: - print("Image signature over image: {}".format(signature.hex())) + print("Image digest: {}".format(digest.hex())) return elif ret == image.VerifyResult.INVALID_MAGIC: print("Invalid image magic; is this an MCUboot image?") @@ -426,10 +423,6 @@ def convert(self, value, param, ctx): 'the signature calculated using the public key') @click.option('--fix-sig-pubkey', metavar='filename', help='public key relevant to fixed signature') -@click.option('--pure', 'is_pure', is_flag=True, default=False, show_default=True, - help='Expected Pure variant of signature; the Pure variant is ' - 'expected to be signature done over an image rather than hash of ' - 'that image.') @click.option('--sig-out', metavar='filename', help='Path to the file to which signature will be written. ' 'The image signature will be encoded as base64 formatted string') @@ -448,8 +441,8 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, endian, encrypt_keylen, encrypt, compression, infile, outfile, dependencies, load_addr, hex_addr, erased_val, save_enctlv, security_counter, boot_record, custom_tlv, rom_fixed, max_align, - clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, is_pure, - vector_to_sign, non_bootable): + clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, vector_to_sign, + non_bootable): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -516,15 +509,9 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, 'value': raw_signature } - if is_pure and user_sha != 'auto': - raise click.UsageError( - 'Pure signatures, currently, enforces preferred hash algorithm, ' - 'and forbids sha selection by user.') - img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, compression_tlvs, None, int(encrypt_keylen), clear, - baked_signature, pub_key, vector_to_sign, user_sha=user_sha, - is_pure=is_pure) + baked_signature, pub_key, vector_to_sign, user_sha) if compression in ["lzma2", "lzma2armthumb"]: compressed_img = image.Image(version=decode_version(version), From 4a6a0651ba65a6d832105aff157e75762837c531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 156/287] Revert "[nrf fromlist] scipts: imgtool: bugfix #2096" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9c2a359674e658866e96a1242bfac7730e37f259. Signed-off-by: Andrzej Głąbek --- scripts/imgtool/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 009d9234c..94952a838 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -510,7 +510,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, } img.create(key, public_key_format, enckey, dependencies, boot_record, - custom_tlvs, compression_tlvs, None, int(encrypt_keylen), clear, + custom_tlvs, compression_tlvs, int(encrypt_keylen), clear, baked_signature, pub_key, vector_to_sign, user_sha) if compression in ["lzma2", "lzma2armthumb"]: From 0979687461cce788f5444090b5c87feb504d9564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 157/287] Revert "[nrf fromlist] zephyr: Fixing Kconfig dependency for SHA512" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 6376fe5db1ab5aad6aca88858ad95d09dc1d7acb. Signed-off-by: Andrzej Głąbek --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 931bccbbb..2dd084714 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -85,6 +85,7 @@ config BOOT_IMG_HASH_ALG_SHA384_ALLOW config BOOT_IMG_HASH_ALG_SHA512_ALLOW bool + depends on BOOT_USE_PSA_CRYPTO help Hidden option set by configurations that allow SHA512 From 133bf39374543daf249e5a0e68541829ffa7e4c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 158/287] Revert "[nrf fromlist] scripts: imgtool: compression ARM thumb filter" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 0f60b02be1384392975deabda08645fa1d5ae1a4. Signed-off-by: Andrzej Głąbek --- scripts/imgtool/image.py | 5 +---- scripts/imgtool/main.py | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 84811806d..10de2a33f 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -70,7 +70,6 @@ 'ROM_FIXED': 0x0000100, 'COMPRESSED_LZMA1': 0x0000200, 'COMPRESSED_LZMA2': 0x0000400, - 'COMPRESSED_ARM_THUMB': 0x0000800, } TLV_VALUES = { @@ -533,10 +532,8 @@ def create(self, key, public_key_format, enckey, dependencies=None, compression_flags = 0x0 if compression_tlvs is not None: - if compression_type in ["lzma2", "lzma2armthumb"]: + if compression_type == "lzma2": compression_flags = IMAGE_F['COMPRESSED_LZMA2'] - if compression_type == "lzma2armthumb": - compression_flags |= IMAGE_F['COMPRESSED_ARM_THUMB'] # This adds the header to the payload as well if encrypt_keylen == 256: self.add_header(enckey, protected_tlv_size, compression_flags, 256) diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 94952a838..03bb565c5 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -363,7 +363,7 @@ def convert(self, value, param, ctx): help='When encrypting the image using AES, select a 128 bit or ' '256 bit key len.') @click.option('--compression', default='disabled', - type=click.Choice(['disabled', 'lzma2', 'lzma2armthumb']), + type=click.Choice(['disabled', 'lzma2']), help='Enable image compression using specified type. ' 'Will fall back without image compression automatically ' 'if the compression increases the image size.') @@ -513,7 +513,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, custom_tlvs, compression_tlvs, int(encrypt_keylen), clear, baked_signature, pub_key, vector_to_sign, user_sha) - if compression in ["lzma2", "lzma2armthumb"]: + if compression == "lzma2": compressed_img = image.Image(version=decode_version(version), header_size=header_size, pad_header=pad_header, pad=pad, confirm=confirm, align=int(align), @@ -527,8 +527,6 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, "dict_size": comp_default_dictsize, "lp": comp_default_lp, "lc": comp_default_lc} ] - if compression == "lzma2armthumb": - compression_filters.insert(0, {"id":lzma.FILTER_ARMTHUMB}) compressed_data = lzma.compress(img.get_infile_data(),filters=compression_filters, format=lzma.FORMAT_RAW) uncompressed_size = len(img.get_infile_data()) From 3ad918f504f48a9db3a18f66c1453f2387e7bac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 159/287] Revert "[nrf fromlist] boot: bootutil: swap_scratch: Fix compressed image sector size check" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 36a248f6857bea9630ab40c8230beb5945e9455e. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/swap_scratch.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index f60109120..24159d1db 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -191,17 +191,7 @@ boot_slots_compatible(struct boot_loader_state *state) smaller = 1; i++; } else { - size_t sector_size = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, j); - -#ifdef MCUBOOT_DECOMPRESS_IMAGES - if (sector_size == 0) { - /* Since this supports decompressed images, we can safely exit if slot1 is - * smaller than slot0. - */ - break; - } -#endif - sz1 += sector_size; + sz1 += boot_img_sector_size(state, BOOT_SECONDARY_SLOT, j); /* Guarantee that multiple sectors of the primary slot * fit into the secondary slot. */ From de45d45e4143a3b2f3ee8861d9cab0cf8663cc8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 160/287] Revert "[nrf fromtree] scripts: imgtool: compression" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c79d930185b5cbf1bca7b957ea3168943dfd46eb. Signed-off-by: Andrzej Głąbek --- scripts/imgtool/image.py | 4 +++- scripts/imgtool/main.py | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 10de2a33f..1f43ccf82 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -317,7 +317,7 @@ def __repr__(self): self.__class__.__name__, len(self.payload)) - def load(self, path): + def load(self, path, compression_header=None): """Load an image from a given file""" ext = os.path.splitext(path)[1][1:].lower() try: @@ -330,6 +330,8 @@ def load(self, path): with open(path, 'rb') as f: self.infile_data = f.read() self.payload = copy.copy(self.infile_data) + if compression_header is not None: + self.payload = compression_header + self.payload except FileNotFoundError: raise click.UsageError("Input file not found") self.image_size = len(self.payload) diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 03bb565c5..9e91582b9 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -513,7 +513,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, custom_tlvs, compression_tlvs, int(encrypt_keylen), clear, baked_signature, pub_key, vector_to_sign, user_sha) - if compression == "lzma2": + if compression == "lzma2" : compressed_img = image.Image(version=decode_version(version), header_size=header_size, pad_header=pad_header, pad=pad, confirm=confirm, align=int(align), @@ -525,20 +525,20 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, compression_filters = [ {"id": lzma.FILTER_LZMA2, "preset": comp_default_preset, "dict_size": comp_default_dictsize, "lp": comp_default_lp, - "lc": comp_default_lc} + "lc": comp_default_lc} ] compressed_data = lzma.compress(img.get_infile_data(),filters=compression_filters, format=lzma.FORMAT_RAW) uncompressed_size = len(img.get_infile_data()) compressed_size = len(compressed_data) - print(f"compressed image size: {compressed_size} bytes") - print(f"original image size: {uncompressed_size} bytes") + print("compressed image size:", compressed_size, + "bytes\noriginal image size:", uncompressed_size, "bytes") compression_tlvs["DECOMP_SIZE"] = struct.pack( img.get_struct_endian() + 'L', img.image_size) compression_tlvs["DECOMP_SHA"] = img.image_hash compression_tlvs_size = len(compression_tlvs["DECOMP_SIZE"]) compression_tlvs_size += len(compression_tlvs["DECOMP_SHA"]) - if img.get_signature(): + if img.get_signature() is not None and img.get_signature() != "" : compression_tlvs["DECOMP_SIGNATURE"] = img.get_signature() compression_tlvs_size += len(compression_tlvs["DECOMP_SIGNATURE"]) if (compressed_size + compression_tlvs_size) < uncompressed_size: From e795ecf13ac14637f5bf0b9a47ce688e5bb03b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 161/287] Revert "[nrf fromtree] boot: bootutil: loader: Fix issue with using pointers" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 55d5997b2edf0429f50dd32091de66f850d5ea95. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 55 ++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 12d4abf40..0219220d0 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -67,22 +67,17 @@ static struct boot_loader_state boot_data; static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; #endif -#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ -defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) #if !defined(__BOOTSIM__) /* Used for holding static buffers in multiple functions to work around issues * in older versions of gcc (e.g. 4.8.4) */ struct sector_buffer_t { - boot_sector_t primary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; - boot_sector_t secondary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; + boot_sector_t *primary; + boot_sector_t *secondary; #if MCUBOOT_SWAP_USING_SCRATCH - boot_sector_t scratch[BOOT_MAX_IMG_SECTORS]; + boot_sector_t *scratch; #endif }; - -static struct sector_buffer_t sector_buffers; -#endif #endif #if (BOOT_IMAGE_NUMBER > 1) @@ -308,6 +303,28 @@ boot_version_cmp(const struct image_version *ver1, #if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +#if !defined(__BOOTSIM__) +static void boot_get_sector_buffers(struct sector_buffer_t *buffers) +{ + /* The array of slot sectors are defined here (as opposed to file scope) so + * that they don't get allocated for non-boot-loader apps. This is + * necessary because the gcc option "-fdata-sections" doesn't seem to have + * any effect in older gcc versions (e.g., 4.8.4). + */ + static boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; + static boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; +#if MCUBOOT_SWAP_USING_SCRATCH + static boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS]; +#endif + + buffers->primary = (boot_sector_t *)&primary_slot_sectors; + buffers->secondary = (boot_sector_t *)&secondary_slot_sectors; +#if MCUBOOT_SWAP_USING_SCRATCH + buffers->scratch = (boot_sector_t *)&scratch_sectors; +#endif +} +#endif + static int boot_initialize_area(struct boot_loader_state *state, int flash_area) { @@ -2198,6 +2215,9 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) { size_t slot; struct boot_status bs; +#if !defined(__BOOTSIM__) + struct sector_buffer_t sector_buffers; +#endif int rc = -1; FIH_DECLARE(fih_rc, FIH_FAILURE); int fa_id; @@ -2224,6 +2244,10 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) (void)has_upgrade; #endif +#if !defined(__BOOTSIM__) + boot_get_sector_buffers(§or_buffers); +#endif + /* Iterate over all the images. By the end of the loop the swap type has * to be determined for each image and all aborted swaps have to be * completed. @@ -2246,9 +2270,9 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) #if !defined(__BOOTSIM__) BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors = - sector_buffers.primary[image_index]; + §or_buffers.primary[image_index]; BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors = - sector_buffers.secondary[image_index]; + §or_buffers.secondary[image_index]; #if MCUBOOT_SWAP_USING_SCRATCH state->scratch.sectors = sector_buffers.scratch; #endif @@ -3444,27 +3468,30 @@ void boot_state_clear(struct boot_loader_state *state) #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) /** * Reads image data to find out the maximum application sizes. Only needs to - * be called in serial recovery mode, as the state information is unpopulated + * be called in serial recovery mode, as the state informatio is unpopulated * at that time */ static void boot_fetch_slot_state_sizes(void) { + struct sector_buffer_t sector_buffers; size_t slot; int rc = -1; int fa_id; int image_index; + boot_get_sector_buffers(§or_buffers); + IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) { int max_size = 0; image_index = BOOT_CURR_IMG(&boot_data); BOOT_IMG(&boot_data, BOOT_PRIMARY_SLOT).sectors = - sector_buffers.primary[image_index]; + §or_buffers.primary[image_index]; BOOT_IMG(&boot_data, BOOT_SECONDARY_SLOT).sectors = - sector_buffers.secondary[image_index]; + §or_buffers.secondary[image_index]; #if MCUBOOT_SWAP_USING_SCRATCH - boot_data.scratch.sectors = sector_buffers.scratch; + boot_data.scratch.sectors = sector_buffers.scratch;; #endif /* Open primary and secondary image areas for the duration From 4472738ca62456caf91fbb1c6db27eca2cbb3b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 162/287] Revert "[nrf fromtree] boot: bootutil: loader: Fix slot info for directXIP/RAM load" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 1d7c7c1b0418519cc13fb0897ba6a52be80168b5. Signed-off-by: Andrzej Głąbek --- boot/bootutil/src/loader.c | 149 +++++++++++++++---------------------- 1 file changed, 61 insertions(+), 88 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 0219220d0..deea7dffa 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -301,93 +301,6 @@ boot_version_cmp(const struct image_version *ver1, } #endif -#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ -defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) -#if !defined(__BOOTSIM__) -static void boot_get_sector_buffers(struct sector_buffer_t *buffers) -{ - /* The array of slot sectors are defined here (as opposed to file scope) so - * that they don't get allocated for non-boot-loader apps. This is - * necessary because the gcc option "-fdata-sections" doesn't seem to have - * any effect in older gcc versions (e.g., 4.8.4). - */ - static boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; - static boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; -#if MCUBOOT_SWAP_USING_SCRATCH - static boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS]; -#endif - - buffers->primary = (boot_sector_t *)&primary_slot_sectors; - buffers->secondary = (boot_sector_t *)&secondary_slot_sectors; -#if MCUBOOT_SWAP_USING_SCRATCH - buffers->scratch = (boot_sector_t *)&scratch_sectors; -#endif -} -#endif - -static int -boot_initialize_area(struct boot_loader_state *state, int flash_area) -{ - uint32_t num_sectors = BOOT_MAX_IMG_SECTORS; - boot_sector_t *out_sectors; - uint32_t *out_num_sectors; - int rc; - - num_sectors = BOOT_MAX_IMG_SECTORS; - - if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) { - out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors; - out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors; - } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { - out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors; - out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors; -#if MCUBOOT_SWAP_USING_SCRATCH - } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) { - out_sectors = state->scratch.sectors; - out_num_sectors = &state->scratch.num_sectors; -#endif - } else { - return BOOT_EFLASH; - } - -#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS - rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors); -#else - _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed"); - rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors); -#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */ - if (rc != 0) { - return rc; - } - *out_num_sectors = num_sectors; - return 0; -} -#endif - -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) -static int -boot_read_sectors_recovery(struct boot_loader_state *state) -{ - uint8_t image_index; - int rc; - - image_index = BOOT_CURR_IMG(state); - - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index)); - if (rc != 0) { - return BOOT_EFLASH; - } - - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index)); - if (rc != 0) { - /* We need to differentiate from the primary image issue */ - return BOOT_EFLASH_SEC; - } - - return 0; -} -#endif - #if (BOOT_IMAGE_NUMBER > 1) @@ -704,6 +617,44 @@ boot_write_sz(struct boot_loader_state *state) return elem_sz; } +static int +boot_initialize_area(struct boot_loader_state *state, int flash_area) +{ + uint32_t num_sectors = BOOT_MAX_IMG_SECTORS; + boot_sector_t *out_sectors; + uint32_t *out_num_sectors; + int rc; + + num_sectors = BOOT_MAX_IMG_SECTORS; + + if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) { + out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors; + out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors; + } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { + out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors; + out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors; +#if MCUBOOT_SWAP_USING_SCRATCH + } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) { + out_sectors = state->scratch.sectors; + out_num_sectors = &state->scratch.num_sectors; +#endif + } else { + return BOOT_EFLASH; + } + +#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS + rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors); +#else + _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed"); + rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors); +#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */ + if (rc != 0) { + return rc; + } + *out_num_sectors = num_sectors; + return 0; +} + /** * Determines the sector layout of both image slots and the scratch area. * This information is necessary for calculating the number of bytes to erase @@ -2210,6 +2161,28 @@ check_downgrade_prevention(struct boot_loader_state *state) #endif } +#if !defined(__BOOTSIM__) +static void boot_get_sector_buffers(struct sector_buffer_t *buffers) +{ + /* The array of slot sectors are defined here (as opposed to file scope) so + * that they don't get allocated for non-boot-loader apps. This is + * necessary because the gcc option "-fdata-sections" doesn't seem to have + * any effect in older gcc versions (e.g., 4.8.4). + */ + static boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; + static boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; +#if MCUBOOT_SWAP_USING_SCRATCH + static boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS]; +#endif + + buffers->primary = (boot_sector_t *)&primary_slot_sectors; + buffers->secondary = (boot_sector_t *)&secondary_slot_sectors; +#if MCUBOOT_SWAP_USING_SCRATCH + buffers->scratch = (boot_sector_t *)&scratch_sectors; +#endif +} +#endif + fih_ret context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) { @@ -3518,7 +3491,7 @@ static void boot_fetch_slot_state_sizes(void) #endif /* Determine the sector layout of the image slots and scratch area. */ - rc = boot_read_sectors_recovery(&boot_data); + rc = boot_read_sectors(&boot_data); if (rc == 0) { max_size = app_max_size(&boot_data); From 906a40caa896c9f1519e8fa6b2e9446395b91545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 163/287] Revert "[nrf fromlist] scripts: imgtool: compression" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8d844dfbf40889a18025b45d709a33283e566bb4. Signed-off-by: Andrzej Głąbek --- scripts/imgtool/image.py | 71 ++++-------------------------------- scripts/imgtool/main.py | 79 ++++------------------------------------ 2 files changed, 15 insertions(+), 135 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 1f43ccf82..53b19ef1d 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -20,15 +20,7 @@ Image signing and management. """ -from . import version as versmod -from .boot_record import create_sw_component_data -import click -import copy -from enum import Enum -import array -from intelhex import IntelHex import hashlib -import array import os.path import struct from enum import Enum @@ -68,8 +60,6 @@ 'NON_BOOTABLE': 0x0000010, 'RAM_LOAD': 0x0000020, 'ROM_FIXED': 0x0000100, - 'COMPRESSED_LZMA1': 0x0000200, - 'COMPRESSED_LZMA2': 0x0000400, } TLV_VALUES = { @@ -89,9 +79,6 @@ 'DEPENDENCY': 0x40, 'SEC_CNT': 0x50, 'BOOT_RECORD': 0x60, - 'DECOMP_SIZE': 0x70, - 'DECOMP_SHA': 0x71, - 'DECOMP_SIGNATURE': 0x72, } TLV_SIZE = 4 @@ -250,9 +237,6 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, if load_addr and rom_fixed: raise click.UsageError("Can not set rom_fixed and load_addr at the same time") - self.image_hash = None - self.image_size = None - self.signature = None self.version = version or versmod.decode_version("0") self.header_size = header_size self.pad_header = pad_header @@ -268,7 +252,6 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, self.rom_fixed = rom_fixed self.erased_val = 0xff if erased_val is None else int(erased_val, 0) self.payload = [] - self.infile_data = [] self.enckey = None self.save_enctlv = save_enctlv self.enctlv_len = 0 @@ -317,39 +300,19 @@ def __repr__(self): self.__class__.__name__, len(self.payload)) - def load(self, path, compression_header=None): + def load(self, path): """Load an image from a given file""" ext = os.path.splitext(path)[1][1:].lower() try: if ext == INTEL_HEX_EXT: ih = IntelHex(path) - self.infile_data = ih.tobinarray() - self.payload = copy.copy(self.infile_data) + self.payload = ih.tobinarray() self.base_addr = ih.minaddr() else: with open(path, 'rb') as f: - self.infile_data = f.read() - self.payload = copy.copy(self.infile_data) - if compression_header is not None: - self.payload = compression_header + self.payload + self.payload = f.read() except FileNotFoundError: raise click.UsageError("Input file not found") - self.image_size = len(self.payload) - - # Add the image header if needed. - if self.pad_header and self.header_size > 0: - if self.base_addr: - # Adjust base_addr for new header - self.base_addr -= self.header_size - self.payload = bytes([self.erased_val] * self.header_size) + \ - self.payload - - self.check_header() - - def load_compressed(self, data, compression_header): - """Load an image from buffer""" - self.payload = compression_header + data - self.image_size = len(self.payload) # Add the image header if needed. if self.pad_header and self.header_size > 0: @@ -444,8 +407,7 @@ def ecies_hkdf(self, enckey, plainkey): return cipherkey, ciphermac, pubk def create(self, key, public_key_format, enckey, dependencies=None, - sw_type=None, custom_tlvs=None, compression_tlvs=None, - compression_type=None, encrypt_keylen=128, clear=False, + sw_type=None, custom_tlvs=None, encrypt_keylen=128, clear=False, fixed_sig=None, pub_key=None, vector_to_sign=None, user_sha='auto'): self.enckey = enckey @@ -508,9 +470,6 @@ def create(self, key, public_key_format, enckey, dependencies=None, dependencies_num = len(dependencies[DEP_IMAGES_KEY]) protected_tlv_size += (dependencies_num * 16) - if compression_tlvs is not None: - for value in compression_tlvs.values(): - protected_tlv_size += TLV_SIZE + len(value) if custom_tlvs is not None: for value in custom_tlvs.values(): protected_tlv_size += TLV_SIZE + len(value) @@ -532,15 +491,11 @@ def create(self, key, public_key_format, enckey, dependencies=None, else: self.payload.extend(pad) - compression_flags = 0x0 - if compression_tlvs is not None: - if compression_type == "lzma2": - compression_flags = IMAGE_F['COMPRESSED_LZMA2'] # This adds the header to the payload as well if encrypt_keylen == 256: - self.add_header(enckey, protected_tlv_size, compression_flags, 256) + self.add_header(enckey, protected_tlv_size, 256) else: - self.add_header(enckey, protected_tlv_size, compression_flags) + self.add_header(enckey, protected_tlv_size) prot_tlv = TLV(self.endian, TLV_PROT_INFO_MAGIC) @@ -570,9 +525,6 @@ def create(self, key, public_key_format, enckey, dependencies=None, ) prot_tlv.add('DEPENDENCY', payload) - if compression_tlvs is not None: - for tag, value in compression_tlvs.items(): - prot_tlv.add(tag, value) if custom_tlvs is not None: for tag, value in custom_tlvs.items(): prot_tlv.add(tag, value) @@ -591,7 +543,6 @@ def create(self, key, public_key_format, enckey, dependencies=None, digest = sha.digest() message = digest; tlv.add(hash_tlv, digest) - self.image_hash = digest if vector_to_sign == 'payload': # Stop amending data to the image @@ -671,16 +622,10 @@ def create(self, key, public_key_format, enckey, dependencies=None, self.check_trailer() - def get_struct_endian(self): - return STRUCT_ENDIAN_DICT[self.endian] - def get_signature(self): return self.signature - def get_infile_data(self): - return self.infile_data - - def add_header(self, enckey, protected_tlv_size, compression_flags, aes_length=128): + def add_header(self, enckey, protected_tlv_size, aes_length=128): """Install the image header.""" flags = 0 @@ -718,7 +663,7 @@ def add_header(self, enckey, protected_tlv_size, compression_flags, aes_length=1 protected_tlv_size, # TLV Info header + # Protected TLVs len(self.payload) - self.header_size, # ImageSz - flags | compression_flags, + flags, self.version.major, self.version.minor or 0, self.version.revision or 0, diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 9e91582b9..848fd3110 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -22,10 +22,6 @@ import getpass import imgtool.keys as keys import sys -import struct -import os -import lzma -import hashlib import base64 from imgtool import image, imgtool_version from imgtool.version import decode_version @@ -33,13 +29,6 @@ from .keys import ( RSAUsageError, ECDSAUsageError, Ed25519UsageError, X25519UsageError) -comp_default_dictsize=131072 -comp_default_pb=2 -comp_default_lc=3 -comp_default_lp=1 -comp_default_preset=9 - - MIN_PYTHON_VERSION = (3, 6) if sys.version_info < MIN_PYTHON_VERSION: sys.exit("Python %s.%s or newer is required by imgtool." @@ -311,14 +300,6 @@ def get_dependencies(ctx, param, value): dependencies[image.DEP_VERSIONS_KEY] = versions return dependencies -def create_lzma2_header(dictsize, pb, lc, lp): - header = bytearray() - for i in range(0, 40): - if dictsize <= ((2 | ((i) & 1)) << int((i) / 2 + 11)): - header.append(i) - break - header.append( ( pb * 5 + lp) * 9 + lc) - return header class BasedIntParamType(click.ParamType): name = 'integer' @@ -362,11 +343,6 @@ def convert(self, value, param, ctx): type=click.Choice(['128', '256']), help='When encrypting the image using AES, select a 128 bit or ' '256 bit key len.') -@click.option('--compression', default='disabled', - type=click.Choice(['disabled', 'lzma2']), - help='Enable image compression using specified type. ' - 'Will fall back without image compression automatically ' - 'if the compression increases the image size.') @click.option('-c', '--clear', required=False, is_flag=True, default=False, help='Output a non-encrypted image with encryption capabilities,' 'so it can be installed in the primary slot, and encrypted ' @@ -438,11 +414,10 @@ def convert(self, value, param, ctx): .hex extension, otherwise binary format is used''') def sign(key, public_key_format, align, version, pad_sig, header_size, pad_header, slot_size, pad, confirm, max_sectors, overwrite_only, - endian, encrypt_keylen, encrypt, compression, infile, outfile, - dependencies, load_addr, hex_addr, erased_val, save_enctlv, - security_counter, boot_record, custom_tlv, rom_fixed, max_align, - clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, vector_to_sign, - non_bootable): + endian, encrypt_keylen, encrypt, infile, outfile, dependencies, + load_addr, hex_addr, erased_val, save_enctlv, security_counter, + boot_record, custom_tlv, rom_fixed, max_align, clear, fix_sig, + fix_sig_pubkey, sig_out, user_sha, vector_to_sign, non_bootable): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -456,7 +431,6 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, erased_val=erased_val, save_enctlv=save_enctlv, security_counter=security_counter, max_align=max_align, non_bootable=non_bootable) - compression_tlvs = {} img.load(infile) key = load_key(key) if key else None enckey = load_key(encrypt) if encrypt else None @@ -510,49 +484,10 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, } img.create(key, public_key_format, enckey, dependencies, boot_record, - custom_tlvs, compression_tlvs, int(encrypt_keylen), clear, - baked_signature, pub_key, vector_to_sign, user_sha) - - if compression == "lzma2" : - compressed_img = image.Image(version=decode_version(version), - header_size=header_size, pad_header=pad_header, - pad=pad, confirm=confirm, align=int(align), - slot_size=slot_size, max_sectors=max_sectors, - overwrite_only=overwrite_only, endian=endian, - load_addr=load_addr, rom_fixed=rom_fixed, - erased_val=erased_val, save_enctlv=save_enctlv, - security_counter=security_counter, max_align=max_align) - compression_filters = [ - {"id": lzma.FILTER_LZMA2, "preset": comp_default_preset, - "dict_size": comp_default_dictsize, "lp": comp_default_lp, - "lc": comp_default_lc} - ] - compressed_data = lzma.compress(img.get_infile_data(),filters=compression_filters, - format=lzma.FORMAT_RAW) - uncompressed_size = len(img.get_infile_data()) - compressed_size = len(compressed_data) - print("compressed image size:", compressed_size, - "bytes\noriginal image size:", uncompressed_size, "bytes") - compression_tlvs["DECOMP_SIZE"] = struct.pack( - img.get_struct_endian() + 'L', img.image_size) - compression_tlvs["DECOMP_SHA"] = img.image_hash - compression_tlvs_size = len(compression_tlvs["DECOMP_SIZE"]) - compression_tlvs_size += len(compression_tlvs["DECOMP_SHA"]) - if img.get_signature() is not None and img.get_signature() != "" : - compression_tlvs["DECOMP_SIGNATURE"] = img.get_signature() - compression_tlvs_size += len(compression_tlvs["DECOMP_SIGNATURE"]) - if (compressed_size + compression_tlvs_size) < uncompressed_size: - compression_header = create_lzma2_header( - dictsize = comp_default_dictsize, pb = comp_default_pb, - lc = comp_default_lc, lp = comp_default_lp) - compressed_img.load_compressed(compressed_data, compression_header) - compressed_img.base_addr = img.base_addr - compressed_img.create(key, public_key_format, enckey, - dependencies, boot_record, custom_tlvs, compression_tlvs, - compression, int(encrypt_keylen), clear, baked_signature, - pub_key, vector_to_sign) - img = compressed_img + custom_tlvs, int(encrypt_keylen), clear, baked_signature, + pub_key, vector_to_sign, user_sha) img.save(outfile, hex_addr) + if sig_out is not None: new_signature = img.get_signature() save_signature(sig_out, new_signature) From d07b6fa1b2457ab384a08aabc842283847d2d62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 164/287] Revert "[nrf fromlist] boot: Replace boot_encrypt by boot_enc_encrypt and boot_enc_decrypt" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 6bf969fa1afb5ef41d0905edfc506c1264fa2cf2. Signed-off-by: Andrzej Głąbek --- boot/boot_serial/src/boot_serial_encryption.c | 2 +- boot/bootutil/include/bootutil/enc_key.h | 4 +-- boot/bootutil/src/encrypted.c | 31 +++---------------- boot/bootutil/src/image_validate.c | 4 +-- boot/bootutil/src/loader.c | 19 +++++------- 5 files changed, 16 insertions(+), 44 deletions(-) diff --git a/boot/boot_serial/src/boot_serial_encryption.c b/boot/boot_serial/src/boot_serial_encryption.c index c4bd7d87b..7d3b47c72 100644 --- a/boot/boot_serial/src/boot_serial_encryption.c +++ b/boot/boot_serial/src/boot_serial_encryption.c @@ -171,7 +171,7 @@ decrypt_region_inplace(struct boot_loader_state *state, blk_sz = tlv_off - (off + bytes_copied); } } - boot_enc_decrypt(BOOT_CURR_ENC(state), slot, + boot_encrypt(BOOT_CURR_ENC(state), slot, (off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz, blk_off, &buf[idx]); } diff --git a/boot/bootutil/include/bootutil/enc_key.h b/boot/bootutil/include/bootutil/enc_key.h index 4ff2432cd..84e05e72f 100644 --- a/boot/bootutil/include/bootutil/enc_key.h +++ b/boot/bootutil/include/bootutil/enc_key.h @@ -70,9 +70,7 @@ 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, +void boot_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_zeroize(struct enc_key_data *enc_state); diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index 8449a28dd..d094ea77b 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -688,13 +688,14 @@ 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, +boot_encrypt(struct enc_key_data *enc_state, int slot, uint32_t off, uint32_t sz, uint32_t blk_off, uint8_t *buf) { - struct enc_key_data *enc = &enc_state[slot]; + struct enc_key_data *enc; uint8_t nonce[16]; - /* Nothing to do with size == 0 */ + /* boot_copy_region will call boot_encrypt with sz = 0 when skipping over + the TLVs. */ if (sz == 0) { return; } @@ -706,33 +707,11 @@ boot_enc_encrypt(struct enc_key_data *enc_state, int slot, uint32_t off, nonce[14] = (uint8_t)(off >> 8); nonce[15] = (uint8_t)off; + enc = &enc_state[slot]; assert(enc->valid == 1); bootutil_aes_ctr_encrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, 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) -{ - struct enc_key_data *enc = &enc_state[slot]; - uint8_t nonce[16]; - - /* Nothing to do with size == 0 */ - if (sz == 0) { - return; - } - - memset(nonce, 0, 12); - off >>= 4; - nonce[12] = (uint8_t)(off >> 24); - nonce[13] = (uint8_t)(off >> 16); - nonce[14] = (uint8_t)(off >> 8); - nonce[15] = (uint8_t)off; - - assert(enc->valid == 1); - bootutil_aes_ctr_decrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, buf); -} - /** * Clears encrypted state after use. */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ec5d986df..b3f008989 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -153,8 +153,8 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, if (off >= hdr_size && off < tlv_off) { blk_off = (off - hdr_size) & 0xf; - boot_enc_decrypt(enc_state, slot, off - hdr_size, - blk_sz, blk_off, tmp_buf); + boot_encrypt(enc_state, slot, off - hdr_size, + blk_sz, blk_off, tmp_buf); } } #endif diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index deea7dffa..3f0793388 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1359,15 +1359,9 @@ boot_copy_region(struct boot_loader_state *state, blk_sz = tlv_off - abs_off; } } - if (source_slot == 0) { - boot_enc_encrypt(BOOT_CURR_ENC(state), source_slot, - (abs_off + idx) - hdr->ih_hdr_size, blk_sz, - blk_off, &buf[idx]); - } else { - boot_enc_decrypt(BOOT_CURR_ENC(state), source_slot, - (abs_off + idx) - hdr->ih_hdr_size, blk_sz, - blk_off, &buf[idx]); - } + boot_encrypt(BOOT_CURR_ENC(state), source_slot, + (abs_off + idx) - hdr->ih_hdr_size, blk_sz, + blk_off, &buf[idx]); } } #endif @@ -2900,9 +2894,10 @@ boot_decrypt_and_copy_image_to_sram(struct boot_loader_state *state, * Part of the chunk is encrypted payload */ blk_sz = tlv_off - (bytes_copied); } - boot_enc_decrypt(BOOT_CURR_ENC(state), slot, - (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz, - blk_off, cur_dst); + boot_encrypt(BOOT_CURR_ENC(state), slot, + (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz, + blk_off, cur_dst); + bytes_copied += chunk_sz; } rc = 0; From e739cdd0a325cb04c885dbb1fcc37a36ddf309e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 165/287] Revert "[nrf fromlist] imgtool: Add support for calculating SHA512" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 3c762c19adebdf07fa17f722558c8aae79cfc738. Signed-off-by: Andrzej Głąbek --- scripts/imgtool/image.py | 111 +++++++-------------------------------- scripts/imgtool/main.py | 8 +-- 2 files changed, 22 insertions(+), 97 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 53b19ef1d..5c4732b53 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -40,8 +40,6 @@ from .boot_record import create_sw_component_data from .keys import rsa, ecdsa, x25519 -from collections import namedtuple - IMAGE_MAGIC = 0x96f3b83d IMAGE_HEADER_SIZE = 32 BIN_EXT = "bin" @@ -67,7 +65,6 @@ 'PUBKEY': 0x02, 'SHA256': 0x10, 'SHA384': 0x11, - 'SHA512': 0x12, 'RSA2048': 0x20, 'ECDSASIG': 0x22, 'RSA3072': 0x23, @@ -138,73 +135,11 @@ def get(self): return header + bytes(self.buf) -SHAAndAlgT = namedtuple('SHAAndAlgT', ['sha', 'alg']) - -TLV_SHA_TO_SHA_AND_ALG = { - TLV_VALUES['SHA256'] : SHAAndAlgT('256', hashlib.sha256), - TLV_VALUES['SHA384'] : SHAAndAlgT('384', hashlib.sha384), - TLV_VALUES['SHA512'] : SHAAndAlgT('512', hashlib.sha512), -} - - -USER_SHA_TO_ALG_AND_TLV = { - 'auto' : (hashlib.sha256, 'SHA256'), - '256' : (hashlib.sha256, 'SHA256'), - '384' : (hashlib.sha384, 'SHA384'), - '512' : (hashlib.sha512, 'SHA512') -} - - -def is_sha_tlv(tlv): - return tlv in TLV_SHA_TO_SHA_AND_ALG.keys() - - -def tlv_sha_to_sha(tlv): - return TLV_SHA_TO_SHA_AND_ALG[tlv].sha - - -# Auto selecting hash algorithm for type(key) -ALLOWED_KEY_SHA = { - keys.ECDSA384P1 : ['384'], - keys.ECDSA384P1Public : ['384'], - keys.ECDSA256P1 : ['256'], - keys.RSA : ['256'], - # This two are set to 256 for compatibility, the right would be 512 - keys.Ed25519 : ['256', '512'], - keys.X25519 : ['256', '512'] -} - -def key_and_user_sha_to_alg_and_tlv(key, user_sha): - """Matches key and user requested sha to sha alogrithm and TLV name. - - The returned tuple will contain hash functions and TVL name. - The function is designed to succeed or completely fail execution, - as providing incorrect pair here basically prevents doing - any more work. - """ - if key is None: - # If key is none, we allow whatever user has selected for sha - return USER_SHA_TO_ALG_AND_TLV[user_sha] - - # If key is not None, then we have to filter hash to only allowed - allowed = None - try: - allowed = ALLOWED_KEY_SHA[type(key)] - except KeyError: - raise click.UsageError("Colud not find allowed hash algorithms for {}" - .format(type(key))) - if user_sha == 'auto': - return USER_SHA_TO_ALG_AND_TLV[allowed[0]] - - if user_sha in allowed: - return USER_SHA_TO_ALG_AND_TLV[user_sha] - - raise click.UsageError("Key {} can not be used with --sha {}; allowed sha are one of {}" - .format(key.sig_type(), user_sha, allowed)) - - def get_digest(tlv_type, hash_region): - sha = TLV_SHA_TO_SHA_AND_ALG[tlv_type].alg() + if tlv_type == TLV_VALUES["SHA384"]: + sha = hashlib.sha384() + elif tlv_type == TLV_VALUES["SHA256"]: + sha = hashlib.sha256() sha.update(hash_region) return sha.digest() @@ -212,16 +147,9 @@ def get_digest(tlv_type, hash_region): def tlv_matches_key_type(tlv_type, key): """Check if provided key matches to TLV record in the image""" - try: - # We do not need the result here, and the key_and_user_sha_to_alg_and_tlv - # will either succeed finding match or rise exception, so on success we - # return True, on exception we return False. - _, _ = key_and_user_sha_to_alg_and_tlv(key, tlv_sha_to_sha(tlv_type)) - return True - except: - pass - - return False + return (key is None or + type(key) == keys.ECDSA384P1 and tlv_type == TLV_VALUES["SHA384"] or + type(key) != keys.ECDSA384P1 and tlv_type == TLV_VALUES["SHA256"]) class Image: @@ -408,13 +336,17 @@ def ecies_hkdf(self, enckey, plainkey): def create(self, key, public_key_format, enckey, dependencies=None, sw_type=None, custom_tlvs=None, encrypt_keylen=128, clear=False, - fixed_sig=None, pub_key=None, vector_to_sign=None, user_sha='auto'): + fixed_sig=None, pub_key=None, vector_to_sign=None): self.enckey = enckey - # key decides on sha, then pub_key; of both are none default is used - check_key = key if key is not None else pub_key - hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha) - + # Check what hashing algorithm should be used + if (key and isinstance(key, ecdsa.ECDSA384P1) + or pub_key and isinstance(pub_key, ecdsa.ECDSA384P1Public)): + hash_algorithm = hashlib.sha384 + hash_tlv = "SHA384" + else: + hash_algorithm = hashlib.sha256 + hash_tlv = "SHA256" # Calculate the hash of the public key if key is not None: pub = key.get_public_bytes() @@ -534,14 +466,11 @@ def create(self, key, public_key_format, enckey, dependencies=None, tlv = TLV(self.endian) - # These signature is done over sha of image. In case of - # EC signatures so called Pure algorithm, designated to be run - # over entire message is used with sha of image as message, - # so, for example, in case of ED25519 we have here SHAxxx-ED25519-SHA512. + # Note that ecdsa wants to do the hashing itself, which means + # we get to hash it twice. sha = hash_algorithm() sha.update(self.payload) digest = sha.digest() - message = digest; tlv.add(hash_tlv, digest) if vector_to_sign == 'payload': @@ -570,7 +499,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, sig = key.sign(bytes(self.payload)) else: print(os.path.basename(__file__) + ": sign the digest") - sig = key.sign_digest(message) + sig = key.sign_digest(digest) tlv.add(key.sig_tlv(), sig) self.signature = sig elif fixed_sig is not None and key is None: @@ -749,7 +678,7 @@ def verify(imgfile, key): while tlv_off < tlv_end: tlv = b[tlv_off:tlv_off + TLV_SIZE] tlv_type, _, tlv_len = struct.unpack('BBH', tlv) - if is_sha_tlv(tlv_type): + if tlv_type == TLV_VALUES["SHA256"] or tlv_type == TLV_VALUES["SHA384"]: if not tlv_matches_key_type(tlv_type, key): return VerifyResult.KEY_MISMATCH, None, None off = tlv_off + TLV_SIZE diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 848fd3110..cc2cf9c58 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -72,7 +72,6 @@ def gen_x25519(keyfile, passwd): 'x25519': gen_x25519, } valid_formats = ['openssl', 'pkcs8'] -valid_sha = [ 'auto', '256', '384', '512' ] def load_signature(sigfile): @@ -402,9 +401,6 @@ def convert(self, value, param, ctx): @click.option('--sig-out', metavar='filename', help='Path to the file to which signature will be written. ' 'The image signature will be encoded as base64 formatted string') -@click.option('--sha', 'user_sha', type=click.Choice(valid_sha), default='auto', - help='selected sha algorithm to use; defaults to "auto" which is 256 if ' - 'no cryptographic signature is used, or default for signature type') @click.option('--vector-to-sign', type=click.Choice(['payload', 'digest']), help='send to OUTFILE the payload or payload''s digest instead ' 'of complied image. These data can be used for external image ' @@ -417,7 +413,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, endian, encrypt_keylen, encrypt, infile, outfile, dependencies, load_addr, hex_addr, erased_val, save_enctlv, security_counter, boot_record, custom_tlv, rom_fixed, max_align, clear, fix_sig, - fix_sig_pubkey, sig_out, user_sha, vector_to_sign, non_bootable): + fix_sig_pubkey, sig_out, vector_to_sign, non_bootable): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -485,7 +481,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, int(encrypt_keylen), clear, baked_signature, - pub_key, vector_to_sign, user_sha) + pub_key, vector_to_sign) img.save(outfile, hex_addr) if sig_out is not None: From a4793c7d0d01cc35781950cb13982ca027727c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 29 Jan 2025 10:35:01 +0100 Subject: [PATCH 166/287] Revert "[nrf fromtree] boot: SHA512 verification" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 3d601f24c1deb3550314ab89cb419ca64d09fdd6. Signed-off-by: Andrzej Głąbek --- boot/bootutil/include/bootutil/crypto/sha.h | 15 ++--- boot/bootutil/include/bootutil/image.h | 1 - boot/bootutil/src/image_validate.c | 1 - boot/zephyr/Kconfig | 56 ------------------- .../include/mcuboot_config/mcuboot_config.h | 10 ---- 5 files changed, 4 insertions(+), 79 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index 34288ef02..704a123ea 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -34,16 +34,13 @@ #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) +#if 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 */ +#endif /* MCUBOOT_SIGN_EC384 */ /* Universal defines for SHA-256 */ #define BOOTUTIL_CRYPTO_SHA256_BLOCK_SIZE (64) @@ -85,9 +82,7 @@ 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) +#if 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); @@ -112,9 +107,7 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, { 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) +#if 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); diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 9ede800a2..3e03f80dd 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -96,7 +96,6 @@ struct flash_area; #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 */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index b3f008989..5953658b0 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -362,7 +362,6 @@ static const uint16_t allowed_unprot_tlvs[] = { IMAGE_TLV_PUBKEY, IMAGE_TLV_SHA256, IMAGE_TLV_SHA384, - IMAGE_TLV_SHA512, IMAGE_TLV_RSA2048_PSS, IMAGE_TLV_ECDSA224, IMAGE_TLV_ECDSA_SIG, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 2dd084714..9ec442dfe 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -24,12 +24,6 @@ config BOOT_USE_MBEDTLS help Use mbedTLS for crypto primitives. -config BOOT_USE_PSA_CRYPTO - bool - # Hidden option - help - Hidden option set if using PSA crypt for cryptography functionality - config BOOT_USE_TINYCRYPT bool # Hidden option @@ -73,52 +67,6 @@ config SINGLE_APPLICATION_SLOT uploading a new application overwrites the one that previously occupied the area. -config BOOT_IMG_HASH_ALG_SHA256_ALLOW - bool - help - Hidden option set by configurations that allow SHA256 - -config BOOT_IMG_HASH_ALG_SHA384_ALLOW - bool - help - Hidden option set by configurations that allow SHA384 - -config BOOT_IMG_HASH_ALG_SHA512_ALLOW - bool - depends on BOOT_USE_PSA_CRYPTO - help - Hidden option set by configurations that allow SHA512 - -choice BOOT_IMG_HASH_ALG - prompt "Selected image hash algorithm" - default BOOT_IMG_HASH_ALG_SHA256 if BOOT_IMG_HASH_ALG_SHA256_ALLOW - default BOOT_IMG_HASH_ALG_SHA384 if BOOT_IMG_HASH_ALG_SHA384_ALLOW - default BOOT_IMG_HASH_ALG_SHA512 if BOOT_IMG_HASH_ALG_SHA512_ALLOW - help - Hash algorithm used for image verification. Selection - here may be limited by other configurations, like for - example selected cryptographic signature. - -config BOOT_IMG_HASH_ALG_SHA256 - bool "SHA256" - depends on BOOT_IMG_HASH_ALG_SHA256_ALLOW - help - SHA256 algorithm - -config BOOT_IMG_HASH_ALG_SHA384 - bool "SHA384" - depends on BOOT_IMG_HASH_ALG_SHA384_ALLOW - help - SHA384 algorithm - -config BOOT_IMG_HASH_ALG_SHA512 - bool "SHA512" - depends on BOOT_IMG_HASH_ALG_SHA512_ALLOW - help - SHA512 algorithm - -endchoice # BOOT_IMG_HASH_ALG - choice BOOT_SIGNATURE_TYPE prompt "Signature type" default BOOT_SIGNATURE_TYPE_RSA @@ -126,14 +74,12 @@ choice BOOT_SIGNATURE_TYPE config BOOT_SIGNATURE_TYPE_NONE bool "No signature; use only hash check" select BOOT_USE_TINYCRYPT - select BOOT_IMG_HASH_ALG_SHA256_ALLOW config BOOT_SIGNATURE_TYPE_RSA bool "RSA signatures" select BOOT_USE_MBEDTLS select MBEDTLS select BOOT_ENCRYPTION_SUPPORT - select BOOT_IMG_HASH_ALG_SHA256_ALLOW if BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_RSA_LEN @@ -145,7 +91,6 @@ endif config BOOT_SIGNATURE_TYPE_ECDSA_P256 bool "Elliptic curve digital signatures with curve P-256" select BOOT_ENCRYPTION_SUPPORT - select BOOT_IMG_HASH_ALG_SHA256_ALLOW if BOOT_SIGNATURE_TYPE_ECDSA_P256 choice BOOT_ECDSA_IMPLEMENTATION @@ -169,7 +114,6 @@ endif config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" select BOOT_ENCRYPTION_SUPPORT - select BOOT_IMG_HASH_ALG_SHA256_ALLOW if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 56462fb76..0891a4b11 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -43,16 +43,6 @@ #ifdef CONFIG_BOOT_USE_NRF_CC310_BL #define MCUBOOT_USE_NRF_CC310_BL #endif -#elif defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) -#define MCUBOOT_USE_PSA_CRYPTO -#endif - -#ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA512 -#define MCUBOOT_SHA512 -#endif - -#ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA256 -#define MCUBOOT_SHA256 #endif /* Zephyr, regardless of C library used, provides snprintf */ From 1deca3037607ab784a52e499bfefeedbb04f907c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 12 Sep 2024 19:37:40 +0000 Subject: [PATCH 167/287] [nrf fromtree] imgtool: Add pure signature support Adds PureEdDSA signature support. The change includes implementation of SIG_PURE TLV that, when present, indicates the signature that is present is Pure type. Signed-off-by: Dominik Ermel Signed-off-by: Mateusz Michalek (cherry picked from commit 1c04eac60b3bc2552023d9276850d19d5f343ea1) --- scripts/imgtool/image.py | 74 ++++++++++++++++++++++++++++++++-------- scripts/imgtool/main.py | 26 ++++++++++---- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 5fec3c1b7..88ef7b90c 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -190,7 +190,15 @@ def tlv_sha_to_sha(tlv): keys.X25519 : ['256', '512'] } -def key_and_user_sha_to_alg_and_tlv(key, user_sha): +ALLOWED_PURE_KEY_SHA = { + keys.Ed25519 : ['512'] +} + +ALLOWED_PURE_SIG_TLVS = [ + TLV_VALUES['ED25519'] +] + +def key_and_user_sha_to_alg_and_tlv(key, user_sha, is_pure = False): """Matches key and user requested sha to sha alogrithm and TLV name. The returned tuple will contain hash functions and TVL name. @@ -204,12 +212,16 @@ def key_and_user_sha_to_alg_and_tlv(key, user_sha): # If key is not None, then we have to filter hash to only allowed allowed = None + allowed_key_ssh = ALLOWED_PURE_KEY_SHA if is_pure else ALLOWED_KEY_SHA try: - allowed = ALLOWED_KEY_SHA[type(key)] + allowed = allowed_key_ssh[type(key)] + except KeyError: raise click.UsageError("Colud not find allowed hash algorithms for {}" .format(type(key))) - if user_sha == 'auto': + + # Pure enforces auto, and user selection is ignored + if user_sha == 'auto' or is_pure: return USER_SHA_TO_ALG_AND_TLV[allowed[0]] if user_sha in allowed: @@ -447,12 +459,13 @@ def ecies_hkdf(self, enckey, plainkey): def create(self, key, public_key_format, enckey, dependencies=None, sw_type=None, custom_tlvs=None, compression_tlvs=None, compression_type=None, encrypt_keylen=128, clear=False, - fixed_sig=None, pub_key=None, vector_to_sign=None, user_sha='auto'): + fixed_sig=None, pub_key=None, vector_to_sign=None, + user_sha='auto', is_pure=False): self.enckey = enckey # key decides on sha, then pub_key; of both are none default is used check_key = key if key is not None else pub_key - hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha) + hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha, is_pure) # Calculate the hash of the public key if key is not None: @@ -592,9 +605,17 @@ def create(self, key, public_key_format, enckey, dependencies=None, sha = hash_algorithm() sha.update(self.payload) digest = sha.digest() - message = digest; tlv.add(hash_tlv, digest) self.image_hash = digest + # Unless pure, we are signing digest. + message = digest + + if is_pure: + # Note that when Pure signature is used, hash TLV is not present. + message = bytes(self.payload) + e = STRUCT_ENDIAN_DICT[self.endian] + sig_pure = struct.pack(e + '?', True) + tlv.add('SIG_PURE', sig_pure) if vector_to_sign == 'payload': # Stop amending data to the image @@ -786,7 +807,7 @@ def verify(imgfile, key): version = struct.unpack('BBHI', b[20:28]) if magic != IMAGE_MAGIC: - return VerifyResult.INVALID_MAGIC, None, None + return VerifyResult.INVALID_MAGIC, None, None, None tlv_off = header_size + img_size tlv_info = b[tlv_off:tlv_off + TLV_INFO_SIZE] @@ -797,11 +818,27 @@ def verify(imgfile, key): magic, tlv_tot = struct.unpack('HH', tlv_info) if magic != TLV_INFO_MAGIC: - return VerifyResult.INVALID_TLV_INFO_MAGIC, None, None + return VerifyResult.INVALID_TLV_INFO_MAGIC, None, None, None + + # This is set by existence of TLV SIG_PURE + is_pure = False prot_tlv_size = tlv_off hash_region = b[:prot_tlv_size] + tlv_end = tlv_off + tlv_tot + tlv_off += TLV_INFO_SIZE # skip tlv info + + # First scan all TLVs in search of SIG_PURE + while tlv_off < tlv_end: + tlv = b[tlv_off:tlv_off + TLV_SIZE] + tlv_type, _, tlv_len = struct.unpack('BBH', tlv) + if tlv_type == TLV_VALUES['SIG_PURE']: + is_pure = True + break + tlv_off += TLV_SIZE + tlv_len + digest = None + tlv_off = header_size + img_size tlv_end = tlv_off + tlv_tot tlv_off += TLV_INFO_SIZE # skip tlv info while tlv_off < tlv_end: @@ -809,15 +846,15 @@ def verify(imgfile, key): tlv_type, _, tlv_len = struct.unpack('BBH', tlv) if is_sha_tlv(tlv_type): if not tlv_matches_key_type(tlv_type, key): - return VerifyResult.KEY_MISMATCH, None, None + return VerifyResult.KEY_MISMATCH, None, None, None off = tlv_off + TLV_SIZE digest = get_digest(tlv_type, hash_region) if digest == b[off:off + tlv_len]: if key is None: - return VerifyResult.OK, version, digest + return VerifyResult.OK, version, digest, None else: - return VerifyResult.INVALID_HASH, None, None - elif key is not None and tlv_type == TLV_VALUES[key.sig_tlv()]: + return VerifyResult.INVALID_HASH, None, None, None + elif not is_pure and key is not None and tlv_type == TLV_VALUES[key.sig_tlv()]: off = tlv_off + TLV_SIZE tlv_sig = b[off:off + tlv_len] payload = b[:prot_tlv_size] @@ -826,9 +863,18 @@ def verify(imgfile, key): key.verify(tlv_sig, payload) else: key.verify_digest(tlv_sig, digest) - return VerifyResult.OK, version, digest + return VerifyResult.OK, version, digest, None + except InvalidSignature: + # continue to next TLV + pass + elif is_pure and key is not None and tlv_type in ALLOWED_PURE_SIG_TLVS: + off = tlv_off + TLV_SIZE + tlv_sig = b[off:off + tlv_len] + try: + key.verify_digest(tlv_sig, hash_region) + return VerifyResult.OK, version, None, tlv_sig except InvalidSignature: # continue to next TLV pass tlv_off += TLV_SIZE + tlv_len - return VerifyResult.INVALID_SIGNATURE, None, None + return VerifyResult.INVALID_SIGNATURE, None, None, None diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index e0f70945c..434530c7a 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -226,11 +226,14 @@ def getpriv(key, minimal, format): @click.command(help="Check that signed image can be verified by given key") def verify(key, imgfile): key = load_key(key) if key else None - ret, version, digest = image.Image.verify(imgfile, key) + ret, version, digest, signature = image.Image.verify(imgfile, key) if ret == image.VerifyResult.OK: print("Image was correctly validated") print("Image version: {}.{}.{}+{}".format(*version)) - print("Image digest: {}".format(digest.hex())) + if digest: + print("Image digest: {}".format(digest.hex())) + if signature and digest is None: + print("Image signature over image: {}".format(signature.hex())) return elif ret == image.VerifyResult.INVALID_MAGIC: print("Invalid image magic; is this an MCUboot image?") @@ -423,6 +426,10 @@ def convert(self, value, param, ctx): 'the signature calculated using the public key') @click.option('--fix-sig-pubkey', metavar='filename', help='public key relevant to fixed signature') +@click.option('--pure', 'is_pure', is_flag=True, default=False, show_default=True, + help='Expected Pure variant of signature; the Pure variant is ' + 'expected to be signature done over an image rather than hash of ' + 'that image.') @click.option('--sig-out', metavar='filename', help='Path to the file to which signature will be written. ' 'The image signature will be encoded as base64 formatted string') @@ -441,8 +448,8 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, endian, encrypt_keylen, encrypt, compression, infile, outfile, dependencies, load_addr, hex_addr, erased_val, save_enctlv, security_counter, boot_record, custom_tlv, rom_fixed, max_align, - clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, vector_to_sign, - non_bootable): + clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, is_pure, + vector_to_sign, non_bootable): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -509,9 +516,15 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, 'value': raw_signature } + if is_pure and user_sha != 'auto': + raise click.UsageError( + 'Pure signatures, currently, enforces preferred hash algorithm, ' + 'and forbids sha selection by user.') + img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, compression_tlvs, None, int(encrypt_keylen), clear, - baked_signature, pub_key, vector_to_sign, user_sha) + baked_signature, pub_key, vector_to_sign, user_sha=user_sha, + is_pure=is_pure) if compression in ["lzma2", "lzma2armthumb"]: compressed_img = image.Image(version=decode_version(version), @@ -552,7 +565,8 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, compressed_img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, compression_tlvs, compression, int(encrypt_keylen), clear, baked_signature, - pub_key, vector_to_sign, user_sha=user_sha) + pub_key, vector_to_sign, user_sha=user_sha, + is_pure=is_pure) img = compressed_img img.save(outfile, hex_addr) if sig_out is not None: From 4e424909e949c056e7f11d0192958a80fd9a6085 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Tue, 10 Oct 2023 15:51:54 +0200 Subject: [PATCH 168/287] [nrf noup] github: Add a commit tags check workflow Use the generic commit-tags action to provide sauce tag checks. Signed-off-by: Carles Cufi (cherry picked from commit 17f3f7f51a8d1b18444c0bcb6a6f01b66ee33ae6) --- .github/workflows/commit-tags.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/commit-tags.yml diff --git a/.github/workflows/commit-tags.yml b/.github/workflows/commit-tags.yml new file mode 100644 index 000000000..534ed5b58 --- /dev/null +++ b/.github/workflows/commit-tags.yml @@ -0,0 +1,28 @@ +name: Commit tags + +on: + pull_request: + types: [synchronize, opened, reopened, edited, labeled, unlabeled, + milestoned, demilestoned, assigned, unassigned, ready_for_review, + review_requested] + +jobs: + commit_tags: + runs-on: ubuntu-22.04 + name: Run commit tags checks on patch series (PR) + steps: + - name: Update PATH for west + run: | + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Checkout the code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Run the commit tags + uses: nrfconnect/action-commit-tags@main + with: + target: . + upstream: mcu-tools/mcuboot/main From 068908da503969ee6cb2678055ccbbbc0274a504 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 26 Mar 2019 15:42:38 +0100 Subject: [PATCH 169/287] [nrf noup] zephyr: Remove duplication from cmake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes the `add_subdirectory` of nrfxlib it will still check that the nrfxlib is located outside the mcuboot directory. Signed-off-by: Sigvart Hovland Signed-off-by: Andrzej Puzdrowski Signed-off-by: Martí Bolívar Signed-off-by: Emil Obalski Signed-off-by: Andrzej Puzdrowski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit b85273aabd958d332750fb936ee30e81db7bd670) --- boot/zephyr/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index ed490e6ee..68e4c38bb 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -42,8 +42,6 @@ if(NOT EXISTS ${NRFXLIB_DIR}) To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") endif() -# Don't include this if we are using west - add_subdirectory(${NRFXLIB_DIR} ${PROJECT_BINARY_DIR}/nrfxlib) endif() zephyr_library_include_directories( From f973fc6cee6313c39041bd81810832b3dc96f0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Bol=C3=ADvar?= Date: Fri, 3 Sep 2021 14:38:54 -0700 Subject: [PATCH 170/287] [nrf noup] zephyr: add 'minimal' configuration files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add prj_minimal.conf, a Kconfig fragment to be used for minimally sized image production. The minimal fragment has been simplified for only external crypto. Move partition sizing into Kconfig to be consistent with the method used by b0. Using this fragment with prj_minimal.conf makes MCUboot < 16kB for all nRF devices (9160 still needs 32kB partition). Ref: NCSDK-6704 Signed-off-by: Stephen Stauts Signed-off-by: Martí Bolívar Signed-off-by: Sebastian Bøe Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 883a6ceac3537e90505c54f3fa4082f07b79f647) --- .../nrf5340dk_nrf5340_cpuapp_minimal.conf | 13 ++++++ boot/zephyr/prj_minimal.conf | 40 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf create mode 100644 boot/zephyr/prj_minimal.conf diff --git a/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf b/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf new file mode 100644 index 000000000..dd5468106 --- /dev/null +++ b/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf @@ -0,0 +1,13 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# CC3xx is currently not used for nrf53 +CONFIG_HW_CC3XX=n +CONFIG_NRF_CC3XX_PLATFORM=n + +# Required for kernel operation +CONFIG_CLOCK_CONTROL=y +CONFIG_SYS_CLOCK_EXISTS=y diff --git a/boot/zephyr/prj_minimal.conf b/boot/zephyr/prj_minimal.conf new file mode 100644 index 000000000..55d4c6167 --- /dev/null +++ b/boot/zephyr/prj_minimal.conf @@ -0,0 +1,40 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +CONFIG_FLASH=y +CONFIG_FPROTECT=y +CONFIG_PM=n + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_ENCRYPT_IMAGE=n + +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_BOOT_UPGRADE_ONLY=n + +### Minimal Configurations ### +CONFIG_BOOT_USE_MIN_PARTITION_SIZE=y +CONFIG_ASSERT=n +CONFIG_BOOT_BANNER=n +CONFIG_CLOCK_CONTROL=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_GPIO=n +CONFIG_KERNEL_MEM_POOL=n +CONFIG_LOG=n +CONFIG_MINIMAL_LIBC_CALLOC=n +CONFIG_MINIMAL_LIBC_MALLOC=n +CONFIG_MINIMAL_LIBC_REALLOCARRAY=n +CONFIG_NCS_SAMPLES_DEFAULTS=n +CONFIG_NO_RUNTIME_CHECKS=y +CONFIG_NRF_RTC_TIMER=n +CONFIG_PRINTK=n +CONFIG_SERIAL=n +CONFIG_SIZE_OPTIMIZATIONS=y +CONFIG_SYS_CLOCK_EXISTS=n +CONFIG_UART_CONSOLE=n From 3f63c19769a852f6cf9cb1e52605a4907fd0f93c Mon Sep 17 00:00:00 2001 From: Bernt Johan Damslora Date: Fri, 20 Sep 2019 18:25:41 +0200 Subject: [PATCH 171/287] [nrf noup] boards: add support for Thingy:91 Adds project configurations for the two systems on the Thingy:91 (PCA-20035) board. The bootloader that is factory-programmed on thing91 does not support ECDSA signature type. Hence this commit also sets the signature type to RSA for applications built for Thingy:91. Signed-off-by: Bernt Johan Damslora Signed-off-by: Sigvart Hovland Signed-off-by: Jon Helge Nistad Signed-off-by: Balaji Srinivasan Signed-off-by: Robert Lubos Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Marek Pieta Signed-off-by: Dominik Ermel (cherry picked from commit 1f7ca3dcfe94c8c929d0484ceec958bd7df2f4be) --- boot/zephyr/boards/thingy91_nrf52840.conf | 34 +++++++++++++++++++++++ boot/zephyr/boards/thingy91_nrf9160.conf | 13 +++++++++ 2 files changed, 47 insertions(+) create mode 100644 boot/zephyr/boards/thingy91_nrf52840.conf create mode 100644 boot/zephyr/boards/thingy91_nrf9160.conf diff --git a/boot/zephyr/boards/thingy91_nrf52840.conf b/boot/zephyr/boards/thingy91_nrf52840.conf new file mode 100644 index 000000000..c0d183401 --- /dev/null +++ b/boot/zephyr/boards/thingy91_nrf52840.conf @@ -0,0 +1,34 @@ +# Disable Zephyr console +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# The build won't fit on the partition allocated for it without size +# optimizations. +CONFIG_SIZE_OPTIMIZATIONS=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x12000 + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_NRFX=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y + +# MCUboot serial recovery +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by USB +CONFIG_MULTITHREADING=y + +# USB +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" +CONFIG_USB_CDC_ACM=y +CONFIG_USB_COMPOSITE_DEVICE=y +CONFIG_USB_MASS_STORAGE=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x520F diff --git a/boot/zephyr/boards/thingy91_nrf9160.conf b/boot/zephyr/boards/thingy91_nrf9160.conf new file mode 100644 index 000000000..1bf2e424d --- /dev/null +++ b/boot/zephyr/boards/thingy91_nrf9160.conf @@ -0,0 +1,13 @@ +# Disable Zephyr console +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# Disable Flash protection +CONFIG_FPROTECT=n + +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# MCUboot serial recovery +CONFIG_MCUBOOT_SERIAL=y From 782c4a1d400b215c2c659271431401a23ca2c22a Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Mon, 21 Mar 2022 13:44:27 +0100 Subject: [PATCH 172/287] [nrf noup] zephyr: Restore default RTC user channel count The default value of CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT for nRF52 SOCs has been changed from 0 to 3, but it makes MCUBoot get stuck on erasing flash pages when swapping two images. Restore the previous value until the RTC issue is resolved (see NCSDK-14427) Signed-off-by: Damian Krolik Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 48e0d079a0cfaef6c3622c24f804f4057701dc87) --- boot/zephyr/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 851c133ec..58cb2ae35 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -35,3 +35,4 @@ CONFIG_MCUBOOT_LOG_LEVEL_INF=y CONFIG_CBPRINTF_NANO=y ### Use the minimal C library to reduce flash usage CONFIG_MINIMAL_LIBC=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 From 7a4b0a8d7c3eafa7cf04aa02b9d590f2dd56fd23 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 8 Dec 2023 13:18:12 +0100 Subject: [PATCH 173/287] [nrf noup] boards: thingy91x: add board config This patch adds board configuration for the Thingy:91 X. Signed-off-by: Maximilian Deubel (cherry picked from commit e541ae9e6e9125bc3ae7457b395397541b3feca3) --- .../boards/thingy91x_nrf5340_cpuapp.conf | 54 +++++++++++++++++++ boot/zephyr/boards/thingy91x_nrf9151.conf | 8 +++ 2 files changed, 62 insertions(+) create mode 100644 boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf create mode 100644 boot/zephyr/boards/thingy91x_nrf9151.conf diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf new file mode 100644 index 000000000..72dfa7fca --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -0,0 +1,54 @@ +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=110 + +# MCUboot serial recovery +CONFIG_MCUBOOT_SERIAL=y + +# Disable Zephyr console +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_NRFX=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y + +# MCUboot serial recovery +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by USB +CONFIG_MULTITHREADING=y + +# USB +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" +CONFIG_USB_CDC_ACM=y +CONFIG_USB_COMPOSITE_DEVICE=y +CONFIG_USB_MASS_STORAGE=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x520F + +CONFIG_BOOT_SERIAL_BOOT_MODE=y + +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x13E00 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 +CONFIG_BOOT_UPGRADE_ONLY=y +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y + +CONFIG_NRF53_RECOVERY_NETWORK_CORE=y diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf new file mode 100644 index 000000000..33cd3301c --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -0,0 +1,8 @@ +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=512 + +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_MULTITHREADING=y From 7d603f8e56c63fea7c1fe54054daf70c8f0faac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 12 Dec 2018 08:59:47 +0100 Subject: [PATCH 174/287] [nrf noup] treewide: add NCS partition manager support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partition Manager is an nRF Connect SDK component which uses yaml files to resolve flash partition placement with a holistic view of the device. This component's MCUboot portions began life as upstream mcuboot PR#430. This added support for being built as a sub image from the downstream Nordic patch set for a zephyr multi image build system (mcuboot 430 was combined with effor submitted to upstream zephyr as PR#13672, which was ultimately reworked after being rejected for mainline at the ELCE 2019 conference in Lyon). It has since evolved over time. This is the version that will go into NCS v1.3. It features: - page size aligned partitions for all partitions used by mcuboot. - image swaps without scratch partitions Add support for configurations where there exists two primary slots but only one secondary slot, which is shared. These two primary slots are the regular application and B1. B1 can be either S0 or S1 depending on the state of the device. Decide where an upgrade should be stored by looking at the vector table. Provide update candidates for both s0 and s1. These candidates must be signed with mcuboot after being signed by b0. Additional notes: - we make update.hex without trailer data This is needed for serial recovery to work using hex files. Prior to this the update.hex got TLV data at the end of the partition, which caused many blank pages to be included, which made it hard to use in a serial recovery scheme. Instead, make update.hex without TLV data at the end, and provide a new file test_update.hex which contains the TLV data, and can be directly flashed to test the upgrade procedure. - we use a function for signing the application as future-proofing for when other components must be signed as well - this includes an update to single image applications that enables support for partition manager; when single image DFU is used, a scratch partition is not needed. - In NCS, image 1 primary slot is the upgrade bank for mcuboot (IE S0 or S1 depending on the active slot). It is not required that this slot contains any valid data. - The nRF boards all have a single flash page size, and partition manager deals with the size of the update partitions and so on, so we must skip a boot_slots_compatible() check to avoid getting an error. - There is no need to verify the target when using partition manager. - We lock mcuboot using fprotect before jumping, to enable the secure boot property of the system. - Call fw_info_ext_api_provide() before booting if EXT_API_PROVIDE EXT_API is enabled. This is relevant only when the immutable bootloader has booted mcuboot. Signed-off-by: Håkon Øye Amundsen Signed-off-by: Øyvind Rønningstad Signed-off-by: Sebastian Bøe Signed-off-by: Sigvart Hovland Signed-off-by: Martí Bolívar Signed-off-by: Torsten Rasmussen Signed-off-by: Andrzej Głąbek Signed-off-by: Robert Lubos Signed-off-by: Andrzej Puzdrowski Signed-off-by: Emil Obalski Signed-off-by: Pawel Dunaj Signed-off-by: Ioannis Glaropoulos Signed-off-by: Johann Fischer Signed-off-by: Vidar Berg Signed-off-by: Draus, Sebastian Signed-off-by: Trond Einar Snekvik Signed-off-by: Jamie McCrae Signed-off-by: Joakim Andersson Signed-off-by: Georgios Vasilakis Signed-off-by: Dominik Ermel (cherry picked from commit 6a5dc04d20332548471564c0d88226c70f54f696) --- boot/bootutil/src/loader.c | 95 ++++++++++++++++++++++--- boot/bootutil/src/swap_move.c | 13 ++++ boot/bootutil/src/swap_scratch.c | 13 ++++ boot/zephyr/CMakeLists.txt | 7 ++ boot/zephyr/Kconfig | 2 + boot/zephyr/include/sysflash/sysflash.h | 48 +++++++++++++ boot/zephyr/include/target.h | 4 ++ boot/zephyr/main.c | 45 ++++++++++++ boot/zephyr/pm.yml | 77 ++++++++++++++++++++ boot/zephyr/prj.conf | 1 + ext/nrf/cc310_glue.h | 2 +- zephyr/module.yml | 3 +- 12 files changed, 299 insertions(+), 11 deletions(-) create mode 100644 boot/zephyr/pm.yml diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 94ec0bfc6..86da6db6c 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -131,6 +131,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. The primary slot of the second image + * (image 1) will not contain a valid image header until an upgrade + * of mcuboot has happened (filling S1 with the new version). + */ + if (BOOT_CURR_IMG(state) == 1 && i == 0) { + continue; + } +#endif /* PM_S1_ADDRESS */ if (i > 0 && !require_all) { return 0; } else { @@ -1071,7 +1080,24 @@ boot_validate_slot(struct boot_loader_state *state, int slot, goto out; } - if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) { + uint32_t min_addr, max_addr; + +#ifdef PM_CPUNET_APP_ADDRESS + /* The primary slot for the network core is emulated in RAM. + * Its flash_area hasn't got relevant boundaries. + * Therfore need to override its boundaries for the check. + */ + if (BOOT_CURR_IMG(state) == 1) { + min_addr = PM_CPUNET_APP_ADDRESS; + max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; + } else +#endif + { + min_addr = pri_fa->fa_off; + max_addr = pri_fa->fa_off + pri_fa->fa_size; + } + + if (reset_value < min_addr || reset_value> (max_addr)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1154,6 +1180,42 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other + * B1 slot S0 or S1) share the same secondary slot, we need to check + * whether the update candidate in the secondary slot is intended for + * image 0 or image 1 primary by looking at the address of the reset + * vector. Note that there are good reasons for not using img_num from + * the swap info. + */ + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = + (struct image_header *)secondary_fa->fa_off; + + if (hdr->ih_magic == IMAGE_MAGIC) { + const struct flash_area *primary_fa; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *vtable = (uint32_t *)(vtable_addr); + uint32_t reset_addr = vtable[1]; + int rc = flash_area_open( + flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ + return BOOT_SWAP_TYPE_NONE; + } + } +#endif swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2374,15 +2436,25 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT - FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL); - /* Check for all possible values is redundant in normal operation it - * is meant to prevent FI attack. +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. Image 1 primary is the currently + * executing MCUBoot image, and is therefore already validated by NSIB and + * does not need to also be validated by MCUBoot. */ - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || - FIH_EQ(fih_rc, FIH_FAILURE) || - FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; + if (!image_validated_by_nsib) +#endif + { + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL); + /* Check for all possible values is redundant in normal operation it + * is meant to prevent FI attack. + */ + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || + FIH_EQ(fih_rc, FIH_FAILURE) || + FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } } #else /* Even if we're not re-validating the primary slot, we could be booting @@ -2399,11 +2471,16 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ +#ifdef PM_S1_ADDRESS + if (!image_validated_by_nsib) +#endif + { rc = boot_update_hw_rollback_protection(state); if (rc != 0) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } + } rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT); if (rc != 0) { diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index b124ff894..67bab1439 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -259,6 +259,18 @@ static int app_max_sectors(struct boot_loader_state *state) int boot_slots_compatible(struct boot_loader_state *state) { +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. In this case, image 1 primary points to the other + * B1 slot (ie S0 or S1), and image 0 primary points to the app. + * With this configuration, image 0 and image 1 share the secondary slot. + * Hence, the primary slot of image 1 will be *smaller* than image 1's + * secondary slot. This is not allowed in upstream mcuboot, so we need + * this patch to allow it. Also, all of these checks are redundant when + * partition manager is in use, and since we have the same sector size + * in all of our flash. + */ + return 1; +#else size_t num_sectors_pri; size_t num_sectors_sec; size_t sector_sz_pri = 0; @@ -326,6 +338,7 @@ boot_slots_compatible(struct boot_loader_state *state) } return 1; +#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index f60109120..66dca83e9 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -141,6 +141,18 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. In this case, image 1 primary points to the other + * B1 slot (ie S0 or S1), and image 0 primary points to the app. + * With this configuration, image 0 and image 1 share the secondary slot. + * Hence, the primary slot of image 1 will be *smaller* than image 1's + * secondary slot. This is not allowed in upstream mcuboot, so we need + * this patch to allow it. Also, all of these checks are redundant when + * partition manager is in use, and since we have the same sector size + * in all of our flash. + */ + return 1; +#else size_t num_sectors_primary; size_t num_sectors_secondary; size_t sz0, sz1; @@ -238,6 +250,7 @@ boot_slots_compatible(struct boot_loader_state *state) #endif return 1; +#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 68e4c38bb..3571d22d5 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -297,6 +297,13 @@ if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") endif() message("MCUBoot bootloader key file: ${KEY_FILE}") + set_property( + GLOBAL + PROPERTY + KEY_FILE + ${KEY_FILE} + ) + set(mcuboot_default_signature_files ${MCUBOOT_DIR}/root-ec-p256-pkcs8.pem ${MCUBOOT_DIR}/root-ec-p384.pem diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index d93014192..77e1e9c37 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -9,6 +9,8 @@ mainmenu "MCUboot configuration" comment "MCUboot-specific configuration options" +source "$(ZEPHYR_NRF_MODULE_DIR)/modules/mcuboot/boot/zephyr/Kconfig" + # Hidden option to mark a project as MCUboot config MCUBOOT default y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 1952950b9..4eaf0309e 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -7,6 +7,52 @@ #ifndef __SYSFLASH_H__ #define __SYSFLASH_H__ +#if USE_PARTITION_MANAGER +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + +extern uint32_t _image_1_primary_slot_id[]; + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) +#endif +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#else + +#include #include #include #include @@ -65,4 +111,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#endif /* USE_PARTITION_MANAGER */ + #endif /* __SYSFLASH_H__ */ diff --git a/boot/zephyr/include/target.h b/boot/zephyr/include/target.h index 9bbfd4b19..40287d515 100644 --- a/boot/zephyr/include/target.h +++ b/boot/zephyr/include/target.h @@ -8,6 +8,8 @@ #ifndef H_TARGETS_TARGET_ #define H_TARGETS_TARGET_ +#ifndef USE_PARTITION_MANAGER + #if defined(MCUBOOT_TARGET_CONFIG) /* * Target-specific definitions are permitted in legacy cases that @@ -45,4 +47,6 @@ #error "Target support is incomplete; cannot build mcuboot." #endif +#endif /* ifndef USE_PARTITION_MANAGER */ + #endif /* H_TARGETS_TARGET_ */ diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index c84f18a1d..978992fa6 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -69,6 +69,10 @@ #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */ +#ifdef CONFIG_FW_INFO +#include +#endif + #ifdef CONFIG_MCUBOOT_SERIAL #include "boot_serial/boot_serial.h" #include "serial_adapter/serial_adapter.h" @@ -129,6 +133,11 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); * !defined(ZEPHYR_LOG_MODE_MINIMAL) */ +#if USE_PARTITION_MANAGER && CONFIG_FPROTECT +#include +#include +#endif + BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -187,6 +196,19 @@ static void do_boot(struct boot_rsp *rsp) /* Disable the USB to prevent it from firing interrupts */ usb_disable(); #endif + +#if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) + bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); + +#ifdef PM_S0_ADDRESS + /* Only fail if the immutable bootloader is present. */ + if (!provided) { + BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); + return; + } +#endif +#endif + #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ @@ -592,7 +614,30 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND); +#if USE_PARTITION_MANAGER && CONFIG_FPROTECT + +#ifdef PM_S1_ADDRESS +/* MCUBoot is stored in either S0 or S1, protect both */ +#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_S0_ADDRESS) +#define PROTECT_ADDR PM_S0_ADDRESS +#else +/* There is only one instance of MCUBoot */ +#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_MCUBOOT_ADDRESS) +#define PROTECT_ADDR PM_MCUBOOT_ADDRESS +#endif + + rc = fprotect_area(PROTECT_ADDR, PROTECT_SIZE); + + if (rc != 0) { + BOOT_LOG_ERR("Protect mcuboot flash failed, cancel startup."); + while (1) + ; + } + +#endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ + ZEPHYR_BOOT_LOG_STOP(); + do_boot(&rsp); mcuboot_status_change(MCUBOOT_STATUS_BOOT_FAILED); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml new file mode 100644 index 000000000..5df9ae547 --- /dev/null +++ b/boot/zephyr/pm.yml @@ -0,0 +1,77 @@ +#include + +mcuboot: + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT + placement: + before: [mcuboot_primary] +#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) + align: {end: 0x1000} +#endif + +mcuboot_primary_app: + # All images to be placed in MCUboot's slot 0 should be placed in this + # partition + span: [app] + +mcuboot_primary: + span: [mcuboot_pad, mcuboot_primary_app] + +# Partition for secondary slot is not created if building in single application +# slot configuration. +#if !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) +mcuboot_secondary: + share_size: [mcuboot_primary] +#if defined(CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) + region: external_flash + placement: + align: {start: 4} +#else + placement: + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + align_next: CONFIG_FPROTECT_BLOCK_SIZE # Ensure that the next partition does not interfere with this image + after: mcuboot_primary +#endif /* CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY */ + +#endif /* !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) */ + +#if CONFIG_BOOT_DIRECT_XIP + +# Direct XIP is enabled, reserve area for metadata (padding) and name the +# partition so that its clear that it is not the secondary slot, but the direct +# XIP alternative. + +mcuboot_secondary_pad: + share_size: mcuboot_pad + placement: + after: mcuboot_primary + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + +mcuboot_secondary_app: + share_size: mcuboot_primary_app + placement: + after: mcuboot_secondary_pad + +mcuboot_secondary: + span: [mcuboot_secondary_pad, mcuboot_secondary_app] + +#endif /* CONFIG_BOOT_DIRECT_XIP */ + +#if CONFIG_BOOT_SWAP_USING_SCRATCH +mcuboot_scratch: + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_SCRATCH + placement: + after: app + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} +#endif /* CONFIG_BOOT_SWAP_USING_SCRATCH */ + +# Padding placed before image to boot. This reserves space for the MCUboot image header +# and it ensures that the boot image gets linked with the correct address offset in flash. +mcuboot_pad: + # MCUboot pad must be placed before the primary application partition. + # The primary application partition includes the secure firmware if present. + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_PAD + placement: + before: [mcuboot_primary_app] +#ifdef CONFIG_FPROTECT + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} +#endif diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 58cb2ae35..23b5f3b93 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -19,6 +19,7 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_TINYCRYPT_SHA256 is not set CONFIG_FLASH=y +CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/ext/nrf/cc310_glue.h b/ext/nrf/cc310_glue.h index ed3ed5c00..22eb94911 100644 --- a/ext/nrf/cc310_glue.h +++ b/ext/nrf/cc310_glue.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include /* diff --git a/zephyr/module.yml b/zephyr/module.yml index 014a21956..9360dbf70 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -1,5 +1,6 @@ samples: - boot/zephyr build: - cmake: ./boot/bootutil/zephyr + cmake-ext: True + kconfig-ext: True sysbuild-cmake: boot/zephyr/sysbuild From 9b3b8d293289d188c75a3303ea23dc666be47052 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Thu, 27 Aug 2020 14:29:31 +0200 Subject: [PATCH 175/287] [nrf noup] boot: nrf53-specific customizations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add network core bootloader implementation Enables network core updates of nrf53 using MCUBoot by identifying images through their start addresses. Also implements the control and transfer using the PCD module. - Add support for multi image DFU using partition manager. - Add check for netcore addr if NSIB is enabled so netcore updates works - boot: zephyr: move thingy53_nrf5340_cpuapp.conf downstream Moved the board configuration for Thingy:53 Application Core to the nRF Connect SDK MCUboot downstream repository. The configuration file contains references to the Kconfig modules that are only available in the nRF Connect SDK. The current configuration is set up to work in the nRF Connect SDK environment and cannot be used upstream. - pm: enable ram flash partition using common flag This patch makes mcuboot_primary_1 ram-flash partition selectable using CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH property. This is needed since CONFIG_NRF53_MULTI_IMAGE_UPDATE become not only configuration which requires that partition. - MCUBoot configures USB CDC by its own. There is no need for BOARD_SERIAL_BACKEND_CDC_ACM option to configure anything which is later overwritten anyway. Jira: NCSDK-18596 Signed-off-by: Andrzej Puzdrowski Signed-off-by: Emil Obalski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Jamie McCrae Signed-off-by: Johann Fischer Signed-off-by: Kamil Piszczek Signed-off-by: Ole Sæther Signed-off-by: Sigvart Hovland Signed-off-by: Simon Iversen Signed-off-by: Torsten Rasmussen Signed-off-by: Trond Einar Snekvik Signed-off-by: Mateusz Kapala Signed-off-by: Dominik Ermel (cherry picked from commit 9c26bb601e487ec60629ebcb6898f47ec3360100) --- boot/bootutil/src/loader.c | 96 ++++++++++++++----- .../boards/thingy53_nrf5340_cpuapp.conf | 74 +++++++++++++- boot/zephyr/include/sysflash/sysflash.h | 23 +++++ boot/zephyr/main.c | 7 ++ boot/zephyr/pm.yml | 13 +++ 5 files changed, 185 insertions(+), 28 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 86da6db6c..e332dc729 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,6 +49,10 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) +#include +#endif + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -1180,7 +1184,15 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); -#ifdef PM_S1_ADDRESS + bool upgrade_valid = false; + +#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = 0; + uint32_t *vtable = 0; + uint32_t reset_addr = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1188,34 +1200,36 @@ boot_validated_swap_type(struct boot_loader_state *state, * vector. Note that there are good reasons for not using img_num from * the swap info. */ - const struct flash_area *secondary_fa = - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = - (struct image_header *)secondary_fa->fa_off; if (hdr->ih_magic == IMAGE_MAGIC) { - const struct flash_area *primary_fa; - uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - uint32_t *vtable = (uint32_t *)(vtable_addr); - uint32_t reset_addr = vtable[1]; - int rc = flash_area_open( - flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ - return BOOT_SWAP_TYPE_NONE; - } - } + vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + vtable = (uint32_t *)(vtable_addr); + reset_addr = vtable[1]; +#ifdef PM_S1_ADDRESS +#ifdef PM_CPUNET_B0N_ADDRESS + if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif + { + const struct flash_area *primary_fa; + int rc = flash_area_open(flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ + return BOOT_SWAP_TYPE_NONE; + } + } +#endif /* PM_S1_ADDRESS */ + } +#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -1229,7 +1243,37 @@ boot_validated_swap_type(struct boot_loader_state *state, } else { swap_type = BOOT_SWAP_TYPE_FAIL; } + } else { + upgrade_valid = true; + } + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) + /* If the update is valid, and it targets the network core: perform the + * update and indicate to the caller of this function that no update is + * available + */ + if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + uint32_t fw_size = hdr->ih_img_size; + + BOOT_LOG_INF("Starting network core update"); + int rc = pcd_network_core_update(vtable, fw_size); + + if (rc != 0) { + swap_type = BOOT_SWAP_TYPE_FAIL; + } else { + BOOT_LOG_INF("Done updating network core"); +#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) + /* swap_erase_trailer_sectors is undefined if upgrade only + * method is used. There is no need to erase sectors, because + * the image cannot be reverted. + */ + rc = swap_erase_trailer_sectors(state, + secondary_fa); +#endif + swap_type = BOOT_SWAP_TYPE_NONE; + } } +#endif /* CONFIG_SOC_NRF5340_CPUAPP */ } return swap_type; diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index f2e42fd64..7d3bc0bec 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -1,3 +1,73 @@ -CONFIG_NORDIC_QSPI_NOR=n -CONFIG_SPI=n +CONFIG_SIZE_OPTIMIZATIONS=y + +CONFIG_SYSTEM_CLOCK_NO_WAIT=y +CONFIG_PM=n + +CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +CONFIG_BOOT_MAX_IMG_SECTORS=2048 +CONFIG_BOOT_SIGNATURE_TYPE_RSA=y + +# Flash +CONFIG_FLASH=y +CONFIG_BOOT_ERASE_PROGRESSIVELY=y +CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y +CONFIG_FPROTECT=y + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_LINE_CTRL=y + +# MCUBoot serial +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by QSPI +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# Required by USB and QSPI CONFIG_MULTITHREADING=y + +# USB +CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n +CONFIG_USB_DEVICE_REMOTE_WAKEUP=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor ASA" +CONFIG_USB_DEVICE_PRODUCT="Bootloader Thingy:53" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x5300 +CONFIG_USB_CDC_ACM=y + +# Decrease memory footprint +CONFIG_CBPRINTF_NANO=y +CONFIG_TIMESLICING=n +CONFIG_BOOT_BANNER=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_LOG=n +CONFIG_ERRNO=n +CONFIG_PRINTK=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_SPI=n +CONFIG_I2C=n +CONFIG_UART_NRFX=n + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 +CONFIG_BOOT_UPGRADE_ONLY=y +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +# Enable custom command to erase settings partition. +CONFIG_ENABLE_MGMT_PERUSER=y +CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE=y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 4eaf0309e..b98e48bce 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -20,6 +20,11 @@ #elif (MCUBOOT_IMAGE_NUMBER == 2) +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +#ifdef PM_B0_ADDRESS + extern uint32_t _image_1_primary_slot_id[]; #define FLASH_AREA_IMAGE_PRIMARY(x) \ @@ -35,6 +40,24 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) +#else + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) + +#endif /* PM_B0_ADDRESS */ + #endif #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 978992fa6..fc8e8c40a 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -91,6 +91,10 @@ const struct boot_uart_funcs boot_funcs = { #include #endif +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) +#include +#endif + /* CONFIG_LOG_MINIMAL is the legacy Kconfig property, * replaced by CONFIG_LOG_MODE_MINIMAL. */ @@ -634,6 +638,9 @@ int main(void) ; } +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) + pcd_lock_ram(); +#endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ ZEPHYR_BOOT_LOG_STOP(); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index 5df9ae547..13ffc44aa 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -75,3 +75,16 @@ mcuboot_pad: #ifdef CONFIG_FPROTECT align: {start: CONFIG_FPROTECT_BLOCK_SIZE} #endif + +#if (CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH) +mcuboot_primary_1: + region: ram_flash + size: CONFIG_NRF53_RAM_FLASH_SIZE +#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ + +#if (CONFIG_NRF53_MULTI_IMAGE_UPDATE) +mcuboot_secondary_1: + region: external_flash + size: CONFIG_NRF53_RAM_FLASH_SIZE + +#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ From 62d5f7b7057ffa148934f6b79f562ae733001507 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 27 Feb 2020 12:48:56 +0100 Subject: [PATCH 176/287] [nrf noup] zephyr: clean peripherals state before boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do some cleanup of nRF peripherals. This is necessary since Zephyr doesn't have any driver deinitialization functionality, and we'd like to leave peripherals in a more predictable state before booting the Zephyr image. This should be re-worked when the zephyr driver model allows us to deinitialize devices cleanly before jumping to the chain-loaded image. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Robert Lubos Signed-off-by: Torsten Rasmussen Signed-off-by: Øyvind Rønningstad Signed-off-by: Martí Bolívar Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Johann Fischer Signed-off-by: Trond Einar Snekvik Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit c82aef67eb4e2573f7d06aed3279019e3e6953b0) --- boot/zephyr/CMakeLists.txt | 6 +++ boot/zephyr/include/nrf_cleanup.h | 19 +++++++ boot/zephyr/main.c | 8 ++- boot/zephyr/nrf_cleanup.c | 83 +++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 boot/zephyr/include/nrf_cleanup.h create mode 100644 boot/zephyr/nrf_cleanup.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 3571d22d5..abc13171b 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -638,3 +638,9 @@ if(SYSBUILD) set(mcuboot_image_footer_size ${required_size} CACHE INTERNAL "Estimated MCUboot image trailer size" FORCE) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() + +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) +zephyr_library_sources( + ${BOOT_DIR}/zephyr/nrf_cleanup.c +) +endif() diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h new file mode 100644 index 000000000..6b04cedfe --- /dev/null +++ b/boot/zephyr/include/nrf_cleanup.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_NRF_CLEANUP_ +#define H_NRF_CLEANUP_ + +/** + * Perform cleanup on some peripheral resources used by MCUBoot prior chainload + * the application. + * + * This function disables all RTC instances and UARTE instances. + * It Disables their interrupts signals as well. + */ +void nrf_cleanup_peripheral(void); + +#endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index fc8e8c40a..7ab35ce47 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -142,6 +142,10 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL +#include +#endif + BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -212,7 +216,9 @@ static void do_boot(struct boot_rsp *rsp) } #endif #endif - +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL + nrf_cleanup_peripheral(); +#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c new file mode 100644 index 000000000..5bab26b24 --- /dev/null +++ b/boot/zephyr/nrf_cleanup.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#if defined(NRF_UARTE0) || defined(NRF_UARTE1) + #include +#endif +#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) + #include +#endif +#if defined(NRF_PPI) + #include +#endif +#if defined(NRF_DPPIC) + #include +#endif + +#include + +#define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) +#define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ + NRF_UARTE_SUBSCRIBE_CONF_OFFS) + +#define NRF_UARTE_PUBLISH_CONF_OFFS offsetof(NRF_UARTE_Type, PUBLISH_CTS) +#define NRF_UARTE_PUBLISH_CONF_SIZE (offsetof(NRF_UARTE_Type, SHORTS) -\ + NRF_UARTE_PUBLISH_CONF_OFFS) + +#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) +static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) +{ + nrf_rtc_task_trigger(rtc_reg, NRF_RTC_TASK_STOP); + nrf_rtc_event_disable(rtc_reg, 0xFFFFFFFF); + nrf_rtc_int_disable(rtc_reg, 0xFFFFFFFF); +} +#endif + +static void nrf_cleanup_clock(void) +{ + nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); +} + +void nrf_cleanup_peripheral(void) +{ +#if defined(NRF_RTC0) + nrf_cleanup_rtc(NRF_RTC0); +#endif +#if defined(NRF_RTC1) + nrf_cleanup_rtc(NRF_RTC1); +#endif +#if defined(NRF_RTC2) + nrf_cleanup_rtc(NRF_RTC2); +#endif +#if defined(NRF_UARTE0) + nrf_uarte_disable(NRF_UARTE0); + nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); +#if defined(NRF_DPPIC) + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); +#endif +#endif +#if defined(NRF_UARTE1) + nrf_uarte_disable(NRF_UARTE1); + nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); +#if defined(NRF_DPPIC) + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); +#endif +#endif +#if defined(NRF_PPI) + nrf_ppi_channels_disable_all(NRF_PPI); +#endif +#if defined(NRF_DPPIC) + nrf_dppi_channels_disable_all(NRF_DPPIC); +#endif + nrf_cleanup_clock(); +} From a5c6d2e418c621d6e008265ed6c950caa7ac7f0a Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Fri, 6 Jan 2023 12:24:48 +0100 Subject: [PATCH 177/287] [nrf noup] zephyr: Clean up non-secure RAM if enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To ensure that MCUBoot does not leak keys or other material through memory to non-secure side we clear the memory before jumping to the next image. Signed-off-by: Sigvart Hovland Signed-off-by: Dominik Ermel Signed-off-by: Ole Sæther (cherry picked from commit 75ab2de55cd557d4c19f5ed97bc508ddce07818a) --- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/include/nrf_cleanup.h | 5 ++ boot/zephyr/main.c | 5 +- boot/zephyr/nrf_cleanup.c | 79 +++++++++++++++++++++++-------- 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index abc13171b..ec84a445c 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -639,7 +639,7 @@ if(SYSBUILD) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL OR CONFIG_MCUBOOT_CLEANUP_NONSECURE_RAM) zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h index 6b04cedfe..9e87e13f5 100644 --- a/boot/zephyr/include/nrf_cleanup.h +++ b/boot/zephyr/include/nrf_cleanup.h @@ -16,4 +16,9 @@ */ void nrf_cleanup_peripheral(void); +/** + * Perform cleanup of non-secure RAM that may have been used by MCUBoot. + */ +void nrf_cleanup_ns_ram(void); + #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 7ab35ce47..82763843d 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -142,7 +142,7 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL || CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM #include #endif @@ -219,6 +219,9 @@ static void do_boot(struct boot_rsp *rsp) #if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL nrf_cleanup_peripheral(); #endif +#if CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM && defined(PM_SRAM_NONSECURE_NAME) + nrf_cleanup_ns_ram(); +#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 5bab26b24..051705ec9 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -5,9 +5,8 @@ */ #include -#if defined(NRF_UARTE0) || defined(NRF_UARTE1) - #include -#endif +#include +#include #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif @@ -20,6 +19,15 @@ #include +#if USE_PARTITION_MANAGER +#include +#endif + +#if defined(NRF_UARTE0) || defined(NRF_UARTE1) || defined(NRF_UARTE20) || \ + defined(NRF_UARTE30) +#define NRF_UARTE_CLEANUP +#endif + #define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) #define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ NRF_UARTE_SUBSCRIBE_CONF_OFFS) @@ -37,6 +45,23 @@ static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) } #endif +#if defined(NRF_UARTE_CLEANUP) +static NRF_UARTE_Type *nrf_uarte_to_clean[] = { +#if defined(NRF_UARTE0) + NRF_UARTE0, +#endif +#if defined(NRF_UARTE1) + NRF_UARTE1, +#endif +#if defined(NRF_UARTE20) + NRF_UARTE20, +#endif +#if defined(NRF_UARTE30) + NRF_UARTE30, +#endif +}; +#endif + static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); @@ -53,26 +78,31 @@ void nrf_cleanup_peripheral(void) #if defined(NRF_RTC2) nrf_cleanup_rtc(NRF_RTC2); #endif -#if defined(NRF_UARTE0) - nrf_uarte_disable(NRF_UARTE0); - nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); -#if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); -#endif -#endif -#if defined(NRF_UARTE1) - nrf_uarte_disable(NRF_UARTE1); - nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); + +#if defined(NRF_UARTE_CLEANUP) + for (int i = 0; i < sizeof(nrf_uarte_to_clean) / sizeof(nrf_uarte_to_clean[0]); ++i) { + NRF_UARTE_Type *current = nrf_uarte_to_clean[i]; + + nrfy_uarte_int_disable(current, 0xFFFFFFFF); + nrfy_uarte_int_uninit(current); + nrfy_uarte_task_trigger(current, NRF_UARTE_TASK_STOPRX); + + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXSTARTED); + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_ENDRX); + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); + nrfy_uarte_disable(current); + #if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)current + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, + NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)current + NRF_UARTE_PUBLISH_CONF_OFFS, 0, + NRF_UARTE_PUBLISH_CONF_SIZE); #endif + } #endif + #if defined(NRF_PPI) nrf_ppi_channels_disable_all(NRF_PPI); #endif @@ -81,3 +111,12 @@ void nrf_cleanup_peripheral(void) #endif nrf_cleanup_clock(); } + +#if USE_PARTITION_MANAGER \ + && defined(CONFIG_ARM_TRUSTZONE_M) \ + && defined(PM_SRAM_NONSECURE_NAME) +void nrf_cleanup_ns_ram(void) +{ + memset((void *) PM_SRAM_NONSECURE_ADDRESS, 0, PM_SRAM_NONSECURE_SIZE); +} +#endif From 85b9daefc0bdbf883ad82f97bc8959135dafd82b Mon Sep 17 00:00:00 2001 From: Christian Taedcke Date: Thu, 10 Feb 2022 15:37:49 +0100 Subject: [PATCH 178/287] [nrf noup] loader: Fix reading reset addr to support ext flash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When mcuboot_secondary is on external flash, the image header cannot dircetly be accessed via secondary_fa->fa_off. Instead the provided function boot_img_hdr() is used now. Additionally a similar issue is present when trying to read the address of the reset handler. For this flash_area_read() is used now. With this patch is possible to have the update partiton mcuboot_secondary on external flash and update a updatable bootloader (mcuboot) in s0 and/or s1. Signed-off-by: Christian Taedcke Signed-off-by: Ole Sæther Signed-off-by: Sigvart Hovland Signed-off-by: Dominik Ermel (cherry picked from commit f6bedc90762987f24cdc71a4b3014f85a3cb85e5) --- boot/bootutil/src/loader.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index e332dc729..ef16c5f6b 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1189,10 +1189,9 @@ boot_validated_swap_type(struct boot_loader_state *state, #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; - uint32_t vtable_addr = 0; - uint32_t *vtable = 0; + struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); uint32_t reset_addr = 0; + int rc = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1202,16 +1201,19 @@ boot_validated_swap_type(struct boot_loader_state *state, */ if (hdr->ih_magic == IMAGE_MAGIC) { - vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - vtable = (uint32_t *)(vtable_addr); - reset_addr = vtable[1]; + rc = flash_area_read(secondary_fa, hdr->ih_hdr_size + + sizeof(uint32_t), &reset_addr, + sizeof(reset_addr)); + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif { const struct flash_area *primary_fa; - int rc = flash_area_open(flash_area_id_from_multi_image_slot( + rc = flash_area_open(flash_area_id_from_multi_image_slot( BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), &primary_fa); @@ -1247,16 +1249,19 @@ boot_validated_swap_type(struct boot_loader_state *state, upgrade_valid = true; } -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available */ if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); uint32_t fw_size = hdr->ih_img_size; - BOOT_LOG_INF("Starting network core update"); - int rc = pcd_network_core_update(vtable, fw_size); + rc = pcd_network_core_update(net_core_fw_addr, fw_size); if (rc != 0) { swap_type = BOOT_SWAP_TYPE_FAIL; From 4943e2f425738025e48efc74d323884c4effdf4d Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jul 2023 08:42:49 +0100 Subject: [PATCH 179/287] [nrf noup] zephyr: Fix path variables Fixes path variables to use the proper Zephyr module variables Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit d978f7b4e9c000d554242c65800fdee51381a3d2) --- boot/zephyr/CMakeLists.txt | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index ec84a445c..36e0a5bb5 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -27,21 +27,20 @@ assert_exists(FIAT_DIR) # Path to mbed-tls' asn1 parser library. set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") assert_exists(MBEDTLS_ASN1_DIR) -set(NRF_DIR "${MCUBOOT_DIR}/ext/nrf") +set(MCUBOOT_NRF_EXT_DIR "${MCUBOOT_DIR}/ext/nrf") if(CONFIG_BOOT_USE_NRF_CC310_BL) -set(NRFXLIB_DIR ${ZEPHYR_BASE}/../nrfxlib) -if(NOT EXISTS ${NRFXLIB_DIR}) - message(FATAL_ERROR " + if(NOT EXISTS ${ZEPHYR_NRFXLIB_MODULE_DIR}) + message(FATAL_ERROR " ------------------------------------------------------------------------ - No such file or directory: ${NRFXLIB_DIR} + No such file or directory: ${ZEPHYR_NRFXLIB_MODULE_DIR} The current configuration enables nRF CC310 crypto accelerator hardware with the `CONFIG_BOOT_USE_NRF_CC310_BL` option. Please follow `ext/nrf/README.md` guide to fix your setup or use tinycrypt instead of the HW accelerator. To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") -endif() + endif() endif() zephyr_library_include_directories( @@ -171,8 +170,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) ${TINYCRYPT_DIR}/source/utils.c ) elseif(CONFIG_BOOT_USE_NRF_CC310_BL) - zephyr_library_sources(${NRF_DIR}/cc310_glue.c) - zephyr_library_include_directories(${NRF_DIR}) + zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) + zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) zephyr_link_libraries(nrfxlib_crypto) endif() From 4ff3af115647a1187ae8a52d433865eb5b8779ec Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 22 Sep 2023 21:31:08 +0000 Subject: [PATCH 180/287] [nrf noup] loader: Do not check reset vector for XIP image The XIP image, 2, does not have reset vector. Signed-off-by: Dominik Ermel (cherry picked from commit ec9999f7f812edea4679de01b72ae78e5438b1a1) --- boot/bootutil/src/loader.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index ef16c5f6b..511165f37 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1072,6 +1072,16 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * overwriting an application written to the incorrect slot. * This feature is only supported by ARM platforms. */ +#if MCUBOOT_IMAGE_NUMBER >= 3 + /* Currently the MCUboot can be configured for up to 3 image, where image number 2 is + * designated for XIP, where it is the second part of image stored in slots of image + * 0. This part of image is not bootable, as the XIP setup is done by the app in + * image 0 slot, and it does not carry the reset vector. + */ + if (area_id == FLASH_AREA_IMAGE_SECONDARY(2)) { + goto out; + } +#endif if (area_id == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); struct image_header *secondary_hdr = boot_img_hdr(state, slot); From 9b2bbcc98515992702f1bdd54bf8a113352ff5c3 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 18 Sep 2023 13:47:00 +0100 Subject: [PATCH 181/287] [nrf noup] zephyr: Add RAM flash configuration to cache for sysbuild Puts the flash simulation configurtion into cache variables that can be used by other applications and CMake code to know specifics on the simulated flash details Signed-off-by: Jamie McCrae (cherry picked from commit 9d52cc5cd8e6b45bdb8becd92641d05acff03e22) --- boot/zephyr/CMakeLists.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 36e0a5bb5..776328d71 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -643,3 +643,14 @@ zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) endif() + +if(SYSBUILD AND CONFIG_PCD_APP) + # Sysbuild requires details of the RAM flash device are stored to the cache of MCUboot so + # that they can be read when running partition manager + dt_nodelabel(ram_flash_dev NODELABEL flash_sim0) + dt_reg_addr(ram_flash_addr PATH ${ram_flash_dev}) + dt_reg_size(ram_flash_size PATH ${ram_flash_dev}) + + set(RAM_FLASH_ADDR "${ram_flash_addr}" CACHE STRING "" FORCE) + set(RAM_FLASH_SIZE "${ram_flash_size}" CACHE STRING "" FORCE) +endif() From 72947ce77e53f17238594012c57ca7d2cb24934c Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 17 Oct 2023 11:28:09 +0200 Subject: [PATCH 182/287] [nrf noup] zephyr: Boot even if EXT_ABI is not provided This removes the `return;` to ensure that the application is booted even if EXT_ABI is not provided to the application because it does not include `FW_INFO`. Added a bit more description to the error messages when FW_INFO is not found and EXT_ABI is not able to be provided to the next image. Ref. NCSDK-24132 Signed-off-by: Sigvart Hovland (cherry picked from commit 5e9aa4cb55cd88623976bb014c0a9c94425774be) --- boot/zephyr/main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 82763843d..7330a164b 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -206,13 +206,16 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); + const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); + bool provided = fw_info_ext_api_provide(firmware_info, true); #ifdef PM_S0_ADDRESS /* Only fail if the immutable bootloader is present. */ if (!provided) { - BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); - return; + if (firmware_info == NULL) { + BOOT_LOG_WRN("Unable to find firmware info structure in %p", vt); + } + BOOT_LOG_ERR("Failed to provide EXT_APIs to %p", vt); } #endif #endif From 45f9b8e1f1c738f21b3b5909a6d1a159d5243143 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Wed, 27 Sep 2023 15:18:04 +0200 Subject: [PATCH 183/287] =?UTF-8?q?[nrf=20noup]=C2=A0loader:=20Add=20firmw?= =?UTF-8?q?are=20version=20check=20downgrade=20prevention?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For nRF53, the only existing version number metadata is stored in the `firmware_info` structure in the network core. This utilizes PCD to read out the version number and compares it against the version number found in the secondary slot for the network core. Ref. NCSDK-21379 Signed-off-by: Sigvart Hovland (cherry picked from commit 186c927143ffac9ab1cd95bbf52ed459f1da127b) --- boot/bootutil/src/loader.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 511165f37..d4d3ab298 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -51,6 +51,10 @@ #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) #include +#ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION +#include +int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); +#endif #endif #ifdef MCUBOOT_ENC_IMAGES @@ -1028,9 +1032,21 @@ boot_validate_slot(struct boot_loader_state *state, int slot, #if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION) if (slot != BOOT_PRIMARY_SLOT) { /* Check if version of secondary slot is sufficient */ - rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ + && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) + if (BOOT_CURR_IMG(state) == 1) { + rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); + } else { + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + } +#else + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); +#endif if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); flash_area_erase(fap, 0, flash_area_get_size(fap)); From 6c636e4394da40223340de4b87d117c2a64f97d0 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Mon, 9 Oct 2023 09:55:57 +0200 Subject: [PATCH 184/287] [nrf noup] boards: thingy53: disable GPIO ISR support Change disables GPIO interrupt support in Zephyr GPIO driver, which is not obligatory for MCUboot. This is needed to reduce memory footprint. Signed-off-by: Nikodem Kastelik (cherry picked from commit 0564022cdfa7d8a20c36a9c2d0bfb4b8be77c1da) --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index 7d3bc0bec..e10656678 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -21,6 +21,7 @@ CONFIG_UART_LINE_CTRL=y # MCUBoot serial CONFIG_GPIO=y +CONFIG_GPIO_NRFX_INTERRUPT=n CONFIG_MCUBOOT_SERIAL=y CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_CDC_ACM=y From cc3462a3cbae39770c5c74e69ac2349539c7c9d3 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 11 Apr 2024 17:26:50 +0200 Subject: [PATCH 185/287] [nrf noup] boot/zephyr/boards: nRF54l15pdk ext flash cfg Added configuration which allows to build MCUboot for nrf54l15pdk_nrf54l15_cpuapp with external flash used for the secondary slot. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 513e91d505e178d4c4cbbe4fd5d3fa2230fc0ade) --- .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf | 8 ++++++++ .../nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 10 ++++++++++ 2 files changed, 18 insertions(+) create mode 100644 boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf create mode 100644 boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf new file mode 100644 index 000000000..841922dbd --- /dev/null +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf @@ -0,0 +1,8 @@ +CONFIG_MULTITHREADING=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_FLASH=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 +CONFIG_MAIN_STACK_SIZE=20480 +CONFIG_BOOT_MAX_IMG_SECTORS=512 +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay new file mode 100644 index 000000000..2341ffd26 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -0,0 +1,10 @@ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; + + +&mx25r64 { + status = "okay"; +}; From 366116a1e3381bec6d39951b5b4a1eebccbcbcdf Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 30 Mar 2021 22:45:17 +0200 Subject: [PATCH 186/287] [nrf noup] loader: work-around for multi-image builds Seems multi-image dependencies are not supported for multi-image in NCS yet. This is a workaround which reverts some lines to restore previous MCUboot behavior, so that Immutable bootloader + MCUBoot type builds will work. Ref. NCSDK-8681 Signed-off-by: Sigvart Hovland (cherry picked from commit c85abeec4c1f0fbf1c4b563fb1219329c66a92f4) --- boot/bootutil/src/loader.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index d4d3ab298..de536855d 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -482,7 +482,7 @@ boot_verify_dependencies(struct boot_loader_state *state) if (rc == 0) { /* All dependencies've been satisfied, continue with next image. */ BOOT_CURR_IMG(state)++; - } else { + } else if (rc == BOOT_EBADIMAGE) { /* Cannot upgrade due to non-met dependencies, so disable all * image upgrades. */ @@ -491,7 +491,10 @@ boot_verify_dependencies(struct boot_loader_state *state) BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; } break; - } + } else { + /* Other error happened, images are inconsistent */ + return rc; + } } return rc; } @@ -1790,7 +1793,6 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) } #endif - /** * Performs a clean (not aborted) image update. * From 444a78defaa3bec84f38f1b5a46bdefadd49a435 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 31 Aug 2023 08:58:31 +0100 Subject: [PATCH 187/287] [nrf noup] loader: Fix missing PCD define check Fixes a missing PCD define check, an image might have the network core partition layout set but if PCD support is not enabled then it should not assume that PCD support is part of mcuboot. Signed-off-by: Jamie McCrae (cherry picked from commit 3213b0ca6ea88e264752d4ee71295ded7164c10a) --- boot/bootutil/src/loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index de536855d..2db4d2101 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1279,7 +1279,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ - && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) && defined(CONFIG_PCD_APP) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available @@ -1307,7 +1307,8 @@ boot_validated_swap_type(struct boot_loader_state *state, swap_type = BOOT_SWAP_TYPE_NONE; } } -#endif /* CONFIG_SOC_NRF5340_CPUAPP */ +#endif /* CONFIG_SOC_NRF5340_CPUAPP && PM_CPUNET_B0N_ADDRESS && + !CONFIG_NRF53_MULTI_IMAGE_UPDATE && CONFIG_PCD_APP */ } return swap_type; From f90af57904232422bbd8f16444c1b49b44834587 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Wed, 31 May 2023 14:41:13 +0200 Subject: [PATCH 188/287] [nrf noup] boot: Add support for NSIB and multi-image This adds support for using both NSIB and the multi-image configuration in MCUboot. Before this was not possible due to upgradable bootloader support through NSIB was using the `UPDATEABLE_IMAGE_NUMBER` configuration to update the updateable bootloader. In this commit we change from using `FLASH_AREA_IMAGE_PRIMARY` to get the flash area ID to using the bootloader state where we set the flash area ID of the free updatable bootloader slot if the image is intended for this slot. Ref. NCSDK-19223 Ref. NCSDK-23305 Signed-off-by: Sigvart Hovland (cherry picked from commit 0bf9af473ffd1e0750b1eb3d4b2a3d3918811955) --- boot/bootutil/src/loader.c | 44 +++++++++++++++++++------ boot/zephyr/include/sysflash/sysflash.h | 19 +++++++++-- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 2db4d2101..c5b0c1002 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1123,6 +1123,11 @@ boot_validate_slot(struct boot_loader_state *state, int slot, if (BOOT_CURR_IMG(state) == 1) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; +#ifdef PM_S1_ADDRESS + } else if (BOOT_CURR_IMG(state) == 0) { + min_addr = PM_S0_ADDRESS; + max_addr = pri_fa->fa_off + pri_fa->fa_size; +#endif } else #endif { @@ -1243,18 +1248,37 @@ boot_validated_swap_type(struct boot_loader_state *state, { const struct flash_area *primary_fa; rc = flash_area_open(flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - + BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), + &primary_fa); if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ + + /* Check start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off) { +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + const struct flash_area *nsib_fa; + + /* NSIB upgrade slot */ + rc = flash_area_open((uint32_t)_image_1_primary_slot_id, + &nsib_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + + /* Image is placed before Primary and within the NSIB slot */ + if (reset_addr > nsib_fa->fa_off + && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { + /* Set primary to be NSIB upgrade slot */ + BOOT_IMG_AREA(state, 0) = nsib_fa; + } +#else + return BOOT_SWAP_TYPE_NONE; +#endif + + } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } } @@ -1536,7 +1560,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs) BOOT_LOG_INF("Image %d upgrade secondary slot -> primary slot", image_index); BOOT_LOG_INF("Erasing the primary slot"); - rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), + rc = flash_area_open(flash_area_get_id(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)), &fap_primary_slot); assert (rc == 0); diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index b98e48bce..8b47a32b5 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -23,9 +23,24 @@ /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ -#ifdef PM_B0_ADDRESS - +#if defined(PM_B0_ADDRESS) extern uint32_t _image_1_primary_slot_id[]; +#endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ From 277c5c401ff2f9288ed774ca84c18ba83cc967f0 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 10 Aug 2023 17:32:48 +0000 Subject: [PATCH 189/287] [nrf noup] sysflash: Move partition manager definitions to pm_sysflash.h Making sysflash.h and pm_sysflash.h more readable. Signed-off-by: Dominik Ermel (cherry picked from commit e005bf866a3699eaba6a296988022af1a2074610) --- boot/zephyr/include/sysflash/pm_sysflash.h | 92 ++++++++++++++++++++++ boot/zephyr/include/sysflash/sysflash.h | 90 ++------------------- 2 files changed, 97 insertions(+), 85 deletions(-) create mode 100644 boot/zephyr/include/sysflash/pm_sysflash.h diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h new file mode 100644 index 000000000..377291e8b --- /dev/null +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef __PM_SYSFLASH_H__ +#define __PM_SYSFLASH_H__ +/* Blocking the __SYSFLASH_H__ */ +#define __SYSFLASH_H__ + +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +#if defined(PM_B0_ADDRESS) +extern uint32_t _image_1_primary_slot_id[]; +#endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) +#else + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) + +#endif /* PM_B0_ADDRESS */ + +#endif +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#endif /* __PM_SYSFLASH_H__ */ diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 8b47a32b5..f231c3d02 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -4,93 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __SYSFLASH_H__ -#define __SYSFLASH_H__ - #if USE_PARTITION_MANAGER -#include -#include - -#ifndef CONFIG_SINGLE_APPLICATION_SLOT - -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -#if defined(PM_B0_ADDRESS) -extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) -#else - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) - -#endif /* PM_B0_ADDRESS */ - +/* Blocking the rest of the file */ +#define __SYSFLASH_H__ +#include #endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID - -#else /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID -/* NOTE: Scratch parition is not used by single image DFU but some of - * functions in common files reference it, so the definitions has been - * provided to allow compilation of common units. - */ -#define FLASH_AREA_IMAGE_SCRATCH 0 -#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#else +#ifndef __SYSFLASH_H__ +#define __SYSFLASH_H__ -#include #include #include #include @@ -149,6 +71,4 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ -#endif /* USE_PARTITION_MANAGER */ - #endif /* __SYSFLASH_H__ */ From 0952fb36679a6bc43de0325dbde9a3fc4c0fef46 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 11 Aug 2023 12:29:13 +0000 Subject: [PATCH 190/287] [nrf noup] sysflash: Add support for three images The commit modifies pm_sysflash.h to add support for three application images. Ref. NCSDK-19223 Signed-off-by: Dominik Ermel Signed-off-by: Sigvart Hovland (cherry picked from commit a251600dd2365d9da00f28e884770cfc43743fa7) --- boot/zephyr/include/sysflash/pm_sysflash.h | 82 ++++++++++++---------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index 377291e8b..db60ddd03 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -11,37 +11,19 @@ #include #include +#include #ifndef CONFIG_SINGLE_APPLICATION_SLOT -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ -#if defined(PM_B0_ADDRESS) extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) +#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ @@ -56,26 +38,52 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) + +#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ + +/* Each pair of slots is separated by , and there is no terminating character */ +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID + +#if (MCUBOOT_IMAGE_NUMBER == 1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 2) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 3) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS, \ + FLASH_AREA_IMAGE_2_SLOTS #else +#error Unsupported number of images +#endif -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) +static inline uint32_t __flash_area_ids_for_slot(int img, int slot) +{ + static const int all_slots[] = { + ALL_AVAILABLE_SLOTS + }; + return all_slots[img * 2 + slot]; +}; -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) +#undef FLASH_AREA_IMAGE_0_SLOTS +#undef FLASH_AREA_IMAGE_1_SLOTS +#undef FLASH_AREA_IMAGE_2_SLOTS +#undef ALL_AVAILABLE_SLOTS -#endif /* PM_B0_ADDRESS */ +#define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) +#define FLASH_AREA_IMAGE_SECONDARY(x) __flash_area_ids_for_slot(x, 1) +#if !defined(CONFIG_BOOT_SWAP_USING_MOVE) +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ #else /* CONFIG_SINGLE_APPLICATION_SLOT */ From 36ac0266fae1fb057d8b3230599d4942635bc81c Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 15 Feb 2024 16:47:25 +0100 Subject: [PATCH 191/287] [nrf noup] loader: introduced cleanup of unusable secondary slot Added procedure which clean-up content of all the secondary slot which contains valid header but couldn't be assigned to any of supported primary images. This behavior is needed when configuration allows to use one secondary slot for collecting image for multiple primary slots. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 6045ec967497abf777bf487db284c17f74bba0e0) --- boot/bootutil/src/loader.c | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index c5b0c1002..5a5a3c2c0 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1203,6 +1203,87 @@ boot_update_security_counter(uint8_t image_index, int slot, } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ +#if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ +(defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) + +#define SEC_SLOT_VIRGIN 0 +#define SEC_SLOT_TOUCHED 1 +#define SEC_SLOT_ASSIGNED 2 + +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +/* This configuration is peculiar - the one physical secondary slot is + * mocking two logical secondary + */ +#define SEC_SLOT_PHYSICAL_CNT 1 +#else +#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER +#endif + +static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; + +static inline void sec_slot_touch(struct boot_loader_state *state) +{ + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); + + if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { + sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; + } +} + +static inline void sec_slot_mark_assigned(struct boot_loader_state *state) +{ + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); + + sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; +} + +/** + * Cleanu up all secondary slot which couldn't be assigned to any primary slot. + * + * This function erases content of each secondary slot which contains valid + * header but couldn't be assigned to any of supported primary images. + * + * This function is supposed to be called after boot_validated_swap_type() + * iterates over all the images in context_boot_go(). + */ +static void sec_slot_cleanup_if_unusable(void) +{ + uint8_t idx; + + for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { + if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { + const struct flash_area *secondary_fa; + int rc; + + rc = flash_area_open(flash_area_id_from_multi_image_slot(idx, BOOT_SECONDARY_SLOT), + &secondary_fa); + if (!rc) { + rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); + if (!rc) { + BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); + } + } + + if (rc) { + BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); + } + } + } +} +#else +static inline void sec_slot_touch(struct boot_loader_state *state) +{ +} +static inline void sec_slot_mark_assigned(struct boot_loader_state *state) +{ +} +static inline void sec_slot_cleanup_if_unusable(void) +{ +} +#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ + defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ + #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined @@ -1241,6 +1322,9 @@ boot_validated_swap_type(struct boot_loader_state *state, if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } + + sec_slot_touch(state); + #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) @@ -1275,6 +1359,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } #else return BOOT_SWAP_TYPE_NONE; + #endif } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { @@ -1283,7 +1368,9 @@ boot_validated_swap_type(struct boot_loader_state *state, } } #endif /* PM_S1_ADDRESS */ + sec_slot_mark_assigned(state); } + #endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); @@ -2400,6 +2487,9 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } + /* cleanup secondary slots which were recognized unusable*/ + sec_slot_cleanup_if_unusable(); + #if (BOOT_IMAGE_NUMBER > 1) if (has_upgrade) { /* Iterate over all the images and verify whether the image dependencies From 43623ffcfd53396c1a8410e335a6c4faf0128ea0 Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Tue, 16 Apr 2024 16:10:55 +0200 Subject: [PATCH 192/287] [nrf noup] boards: nrf54l15: Disable FPROTECT FPROTECT is not suppored yet for nrf54l15. Signed-off-by: Grzegorz Chwierut Signed-off-by: Gerard Marull-Paretas (cherry picked from commit 1bd0b62e4705f0a6d1a6ed4f723e4aa9fc7dfcc1) --- boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf index 43d8cebe3..8d8eb845f 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf @@ -7,4 +7,7 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + CONFIG_BOOT_WATCHDOG_FEED=n From 2cb3c76754d6cef2b26edf823da0d4586be862a2 Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Fri, 17 May 2024 18:25:07 +0200 Subject: [PATCH 193/287] [nrf noup] loader: remove cleanup for direct xip mode Move ifdefs just to not add code for cleanup unusable slot when direct xip mode is enabled to avoid warnings. Signed-off-by: Grzegorz Chwierut (cherry picked from commit dcef7e4813f5599cfe1302a6cc9b4b930ea85360) --- boot/bootutil/src/loader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 5a5a3c2c0..a98d6ba79 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1203,6 +1203,8 @@ boot_update_security_counter(uint8_t image_index, int slot, } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) + #if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ (defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) @@ -1284,7 +1286,6 @@ static inline void sec_slot_cleanup_if_unusable(void) #endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined * that a swap operation is required, the image in the secondary slot is checked From 8929c5ffb322cdfb75f583a7103ef41f59349cf8 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Mon, 15 Apr 2024 18:54:45 +0200 Subject: [PATCH 194/287] [nrf noup] boot/zephyr/boards: nrf54l15pdk ext-flash partition Added DTS with partitioning which involves external flash as place for slo1_partition. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 830ad12d077c584b2a99884e1129bba1a33dd72c) --- ...54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay index 2341ffd26..76b648903 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -4,7 +4,42 @@ }; }; +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; + +/delete-node/ &slot0_ns_partition; +/delete-node/ &slot1_ns_partition; + +/delete-node/ &storage_partition; + +&rram0 { + partitions { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x000000000 0x00014000>; + }; + slot0_partition: partition@14000 { + label = "image-0"; + reg = <0x000014000 0x0015A000>; + }; + storage_partition: partition@16E000 { + label = "storage"; + reg = < 0x16E000 0x9000 >; + }; + }; +}; &mx25r64 { status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot1_partition: partition@0 { + label = "image-1"; + reg = <0x000000000 0x0015A000>; + }; + }; }; From 6b35b59e16ecfa58c889956e1e91dc4f353204d5 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Mon, 20 May 2024 15:48:33 +0200 Subject: [PATCH 195/287] [nrf noup] boot/zephyr/boards: nrf54l15pdk ext-flash update This patch supplements the configuration for external flash so MCUboot can be build with FILE_SUFFIX="ext_flash" for the nrf54l15pdk instead of explicitly configuration specification. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 494c935ae019a4be93d700ec49c65198aaa562ba) --- .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf | 7 +++++++ .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 1 + 2 files changed, 8 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf index 841922dbd..8fc12e074 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.conf @@ -6,3 +6,10 @@ CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 CONFIG_MAIN_STACK_SIZE=20480 CONFIG_BOOT_MAX_IMG_SECTORS=512 CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +# Ensure that the qspi driver is disabled by default +CONFIG_NORDIC_QSPI_NOR=n + +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + +CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay index 76b648903..ea024fcec 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -1,6 +1,7 @@ / { chosen { nordic,pm-ext-flash = &mx25r64; + zephyr,code-partition = &boot_partition; }; }; From d8729897a98f78cc5d99664fc5b7d93e31477210 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Tue, 12 Mar 2024 12:30:52 +0100 Subject: [PATCH 196/287] [nrf noup] boards: thingy91x: enable serial recovery This patch disbales MCUBoot logging and enables serial recovery for the Thingy:91. Signed-off-by: Maximilian Deubel Signed-off-by: Bernt Johan Damslora (cherry picked from commit 732083d3ec8b3bc76a6fd528ebc14a27df05d069) --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 10 ++++++++-- boot/zephyr/boards/thingy91x_nrf9151.conf | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index 72dfa7fca..37c7e95b1 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -32,7 +32,7 @@ CONFIG_USB_COMPOSITE_DEVICE=y CONFIG_USB_MASS_STORAGE=n CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x520F +CONFIG_USB_DEVICE_PID=0x910A CONFIG_BOOT_SERIAL_BOOT_MODE=y @@ -49,6 +49,12 @@ CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y CONFIG_FLASH_SIMULATOR_STATS=n CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +# Makes it possible to update the network core using the flash simulator CONFIG_NRF53_RECOVERY_NETWORK_CORE=y + +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y + +# Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 +CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 33cd3301c..2efe1e170 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -6,3 +6,12 @@ CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_SPI_NOR_SFDP_DEVICETREE=y CONFIG_MULTITHREADING=y + +# Disable Zephyr console and use UART for MCUboot serial recovery instead +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n +CONFIG_MCUBOOT_SERIAL=y + +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y From fb3cc4c5863822d190135640989110d2257dcbd2 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 17 May 2024 14:14:54 +0200 Subject: [PATCH 197/287] [nrf noup] boot: zephyr: Disable boot banner if NCS_BOOT_BANNER is used Mcuboot's boot banner should not be used if NCS boot banner is enabled. Signed-off-by: Robert Lubos (cherry picked from commit 4ae34b4e81382f2f7259472f0eddd21dbc471d99) --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 77e1e9c37..af3134694 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -797,6 +797,7 @@ config BOOT_DISABLE_CACHES config MCUBOOT_BOOT_BANNER bool "Use MCUboot boot banner" depends on BOOT_BANNER + depends on !NCS_BOOT_BANNER depends on "$(APP_VERSION_EXTENDED_STRING)" != "" default y help From b1851b65f49448e74aeac4ad0c5fd7cc46bafa93 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Mon, 27 May 2024 13:59:49 +0200 Subject: [PATCH 198/287] [nrf noup] boot/zephyr: fix fw_info search By the upstream patch the vt get now the pointer to the copy of the arm_vector instead of original. This patch fixes address of the firmware which is to be taken by the fw_info_find. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit efafb012f0a647a5e57a9438bc4b38a7cc5db1cf) --- boot/zephyr/main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 7330a164b..397d88cf4 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -206,7 +206,14 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); + uintptr_t fw_start_addr; + + rc = flash_device_base(rsp->br_flash_dev_id, &fw_start_addr); + assert(rc == 0); + + fw_start_addr += rsp->br_image_off + rsp->br_hdr->ih_hdr_size; + + const struct fw_info *firmware_info = fw_info_find(fw_start_addr); bool provided = fw_info_ext_api_provide(firmware_info, true); #ifdef PM_S0_ADDRESS From e48c56f63dc33b0d40d54d84397e0617998a2212 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 28 May 2024 09:31:16 +0000 Subject: [PATCH 199/287] [nrf noup] Revert of zephyr: arm: Update reading the flash image reset vector This is revert of upstream commit 453096b17ddc3aac7bf6afb97c40591d5ea3aa9c which was supposed to allow picking interrupt vector table from flash area but the whole modification unfortunately misunderstood difference between flash device ID and flash area ID. The commit is not important for sdk-nrf and requires re-design and fixing upstream. Signed-off-by: Dominik Ermel (cherry picked from commit ccffc83489330ec2dc4a57902b100d1b738641ec) --- boot/zephyr/flash_map_extended.c | 8 ++------ boot/zephyr/main.c | 20 +++++--------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index 4631da75b..d0744afbd 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -141,12 +141,8 @@ int flash_area_sector_from_off(off_t off, struct flash_sector *sector) uint8_t flash_area_get_device_id(const struct flash_area *fa) { -#if defined(CONFIG_ARM) - return fa->fa_id; -#else - (void)fa; - return FLASH_DEVICE_ID; -#endif + (void)fa; + return FLASH_DEVICE_ID; } #define ERASED_VAL 0xff diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 397d88cf4..b8bb6ec14 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -174,26 +174,16 @@ static void do_boot(struct boot_rsp *rsp) /* Get ram address for image */ vt = (struct arm_vector_table *)(rsp->br_hdr->ih_load_addr + rsp->br_hdr->ih_hdr_size); #else + uintptr_t flash_base; int rc; - const struct flash_area *fap; - static uint32_t dst[2]; /* Jump to flash image */ - rc = flash_area_open(rsp->br_flash_dev_id, &fap); - assert(rc == 0); - - rc = flash_area_read(fap, rsp->br_hdr->ih_hdr_size, dst, sizeof(dst)); + rc = flash_device_base(rsp->br_flash_dev_id, &flash_base); assert(rc == 0); -#ifndef CONFIG_ASSERT - /* Enter a lock up as asserts are disabled */ - if (rc != 0) { - while (1); - } -#endif - - flash_area_close(fap); - vt = (struct arm_vector_table *)dst; + vt = (struct arm_vector_table *)(flash_base + + rsp->br_image_off + + rsp->br_hdr->ih_hdr_size); #endif if (IS_ENABLED(CONFIG_SYSTEM_TIMER_HAS_DISABLE_SUPPORT)) { From b062f946ad0f971d34a81df36a5c8ee2db79e5b1 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Wed, 5 Jun 2024 15:46:13 +0200 Subject: [PATCH 200/287] [nrf noup] zephyr/boards: fix nrf54l15pdk ext flash dts overlay Align to changes in DTS: renamed: rram0 -> cpuapp_rram sized up cpauapp_rram region szie as part of it was reserved for cpuflpr_rram (which is not used by this config). Signed-off-by: Andrzej Puzdrowski (cherry picked from commit f1393e6b8dde7f86513942271ad46c284fe22d3b) --- .../boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay index ea024fcec..60ee6fe51 100644 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp_ext_flash.overlay @@ -14,7 +14,8 @@ /delete-node/ &storage_partition; -&rram0 { +&cpuapp_rram { + reg = < 0x0 DT_SIZE_K(1524) >; partitions { boot_partition: partition@0 { label = "mcuboot"; From 053d2f231d01e9833fabf647aaedbabef9ca6cbd Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jun 2024 12:32:51 +0100 Subject: [PATCH 201/287] [nrf noup] boot: zephyr: Add NCS boot banner Adds a boot banner which shows as MCUboot Signed-off-by: Jamie McCrae (cherry picked from commit f754885576c2c1f19b53e6a41dc718286964ed40) --- boot/zephyr/prj.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 23b5f3b93..e4f7d9030 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -37,3 +37,6 @@ CONFIG_CBPRINTF_NANO=y ### Use the minimal C library to reduce flash usage CONFIG_MINIMAL_LIBC=y CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 + +# NCS boot banner +CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" From 21024f623e6b4197b8b26f2f95da8f10ade5507f Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 13 Jun 2024 16:34:55 +0200 Subject: [PATCH 202/287] [nrf noup] boot/../loader: skip downgrade prevention for s1/s0 This patch introduces skip on checking downgrade for s1/s0 upgrade image (chain-loaded by NSIB). which is used for upgrade MCUboot instance itself. Reason is that sdk-mcuboot has not access to semantic version of its own image. I also shouldn't touch HW counter used for hardware downgrade prevention for the application image (which was the case). HW counters for s0/s1 image are owned by NSIB because its role is to prevnt dongrades of s0/s1 MCUboot. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit de9d942b888ed8a2064fc36c44ef9cb93993d6db) --- boot/bootutil/src/loader.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a98d6ba79..1f9ce5bb6 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -70,6 +70,9 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; +#ifdef PM_S1_ADDRESS +static bool owner_nsib[BOOT_IMAGE_NUMBER] = {false}; +#endif #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; @@ -1301,6 +1304,9 @@ boot_validated_swap_type(struct boot_loader_state *state, int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); bool upgrade_valid = false; +#if defined(PM_S1_ADDRESS) + owner_nsib[BOOT_CURR_IMG(state)] = false; +#endif #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = @@ -1357,6 +1363,7 @@ boot_validated_swap_type(struct boot_loader_state *state, && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { /* Set primary to be NSIB upgrade slot */ BOOT_IMG_AREA(state, 0) = nsib_fa; + owner_nsib[BOOT_CURR_IMG(state)] = true; } #else return BOOT_SWAP_TYPE_NONE; @@ -1367,6 +1374,10 @@ boot_validated_swap_type(struct boot_loader_state *state, /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } + + if ((primary_fa->fa_off == PM_S0_ADDRESS) || (primary_fa->fa_off == PM_S1_ADDRESS)) { + owner_nsib[BOOT_CURR_IMG(state)] = true; + } } #endif /* PM_S1_ADDRESS */ sec_slot_mark_assigned(state); @@ -2350,6 +2361,13 @@ check_downgrade_prevention(struct boot_loader_state *state) uint32_t security_counter[2]; int rc; +#if defined(PM_S1_ADDRESS) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + /* Downgrade prevention on S0/S1 image is managed by NSIB */ + return 0; + } +#endif + if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) { /* If there was security no counter in slot 0, allow swap */ rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 0).hdr), From 0e1a28868543d824058ebba69479a0f0b31af106 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 18 Jun 2024 17:35:41 +0200 Subject: [PATCH 203/287] [nrf noup] boot/../loader: reboot after updating s0/s1 As this is MCUboot updating itself, it should reboot the device so NSIB will chainload the update MCUboot Signed-off-by: Andrzej Puzdrowski (cherry picked from commit f07918de07319dff91be492bf13f9a8320b73824) --- boot/bootutil/src/loader.c | 10 ++++++++++ boot/zephyr/Kconfig | 1 + 2 files changed, 11 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 1f9ce5bb6..6a26de3dc 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,6 +49,10 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#ifdef __ZEPHYR__ +#include +#endif + #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) #include #ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION @@ -2579,6 +2583,12 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); +#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + sys_reboot(SYS_REBOOT_COLD); + + } +#endif break; case BOOT_SWAP_TYPE_FAIL: diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index af3134694..848b6ca83 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -18,6 +18,7 @@ config MCUBOOT select MPU_ALLOW_FLASH_WRITE if ARM_MPU select USE_DT_CODE_PARTITION if HAS_FLASH_LOAD_OFFSET select MCUBOOT_BOOTUTIL_LIB + select REBOOT if SECURE_BOOT config BOOT_USE_MBEDTLS bool From b5a4c74a5a1a52111d391ec58497f416ccbba2f3 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 29 Aug 2024 12:41:37 +0100 Subject: [PATCH 204/287] [nrf noup] bootutil: loader: Fix netcore address checking Fixes an issues with wrongly checking the network core reset address Signed-off-by: Jamie McCrae (cherry picked from commit e8705940ce0eebb48144854955d69465c69c5462) --- boot/bootutil/src/loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 6a26de3dc..7b718758d 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1338,7 +1338,7 @@ boot_validated_swap_type(struct boot_loader_state *state, #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS - if(reset_addr < PM_CPUNET_B0N_ADDRESS) + if(!(reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS)) #endif { const struct flash_area *primary_fa; @@ -1411,7 +1411,8 @@ boot_validated_swap_type(struct boot_loader_state *state, * update and indicate to the caller of this function that no update is * available */ - if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS && + reset_addr < PM_CPUNET_APP_END_ADDRESS) { struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); From 3952b4d304a53c9cf7664f786110faa131247c44 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Wed, 18 Sep 2024 12:28:37 +0200 Subject: [PATCH 205/287] [nrf noup] boards: nrf54l15dk: Disable FPROTECT FPROTECT is not suppored for nrf54l15dk. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 9321e7f46a878d237209f4f596d5e88a8cf6aca3) --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf index c8fcd32c3..1dbd7c1ab 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -7,6 +7,9 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + CONFIG_BOOT_WATCHDOG_FEED=n # Ensure the fastest RRAM write operations From 655eeacf16cfd090bb309ef06f940a943790e671 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 22 Aug 2024 14:17:46 +0100 Subject: [PATCH 206/287] [nrf noup] zephyr: Add support for compressed image updates Adds support for LZMA-compressed firmware updates Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 474a92290901ffb468978574087e98fc89fb3e80) --- boot/bootutil/src/bootutil_misc.c | 80 +- boot/bootutil/src/image_validate.c | 226 ++++ boot/bootutil/src/loader.c | 27 +- boot/zephyr/CMakeLists.txt | 6 + boot/zephyr/Kconfig | 10 +- boot/zephyr/decompression.c | 1115 +++++++++++++++++ .../include/compression/decompression.h | 104 ++ 7 files changed, 1545 insertions(+), 23 deletions(-) create mode 100644 boot/zephyr/decompression.c create mode 100644 boot/zephyr/include/compression/decompression.h diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 56859d515..ac50eaa52 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -42,6 +42,11 @@ #include "bootutil/enc_key.h" #endif +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + BOOT_LOG_MODULE_DECLARE(mcuboot); /* Currently only used by imgmgr */ @@ -384,35 +389,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) goto done; } - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); +#ifdef MCUBOOT_DECOMPRESS_IMAGES + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { + uint32_t tmp_size = 0; - if (flash_area_read(fap, off, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } + rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { + if (rc) { rc = BOOT_EBADIMAGE; goto done; } - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; + + rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); + + if (rc) { + rc = BOOT_EBADIMAGE; + goto done; + } + + off += tmp_size; + + if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + + boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, + sizeof(info))) { rc = BOOT_EFLASH; goto done; } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + info.it_tlv_tot; + } else { +#else + if (1) { +#endif + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); + + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + protect_tlv_size + info.it_tlv_tot; } - *size = off + protect_tlv_size + info.it_tlv_tot; rc = 0; done: diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ec5d986df..b1a50f126 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -40,6 +40,15 @@ #include "mcuboot_config/mcuboot_config.h" +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -416,6 +425,68 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, FIH_DECLARE(security_counter_valid, FIH_FAILURE); #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* If the image is compressed, the integrity of the image must also be validated */ + if (MUST_DECOMPRESS(fap, image_index, hdr)) { + bool found_decompressed_size = false; + bool found_decompressed_sha = false; + bool found_decompressed_signature = false; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + uint16_t expected_size = 0; + bool *found_flag = NULL; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + switch (type) { + case IMAGE_TLV_DECOMP_SIZE: + expected_size = sizeof(size_t); + found_flag = &found_decompressed_size; + break; + case IMAGE_TLV_DECOMP_SHA: + expected_size = IMAGE_HASH_SIZE; + found_flag = &found_decompressed_sha; + break; + case IMAGE_TLV_DECOMP_SIGNATURE: + found_flag = &found_decompressed_signature; + break; + default: + continue; + }; + + if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { + rc = -1; + goto out; + } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { + rc = -1; + goto out; + } + + *found_flag = true; + } + + rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); + if (rc) { + goto out; + } + } +#endif + rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); if (rc) { @@ -587,6 +658,161 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* Only after all previous verifications have passed, perform a dry-run of the decompression + * and ensure the image is valid + */ + if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { + image_hash_valid = 0; + FIH_SET(valid_signature, FIH_FAILURE); + + rc = bootutil_img_hash_decompress(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, + hash, seed, seed_len); + if (rc) { + goto out; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + /* Verify the image hash. This must always be present. */ + if (len != sizeof(hash)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); + if (rc) { + goto out; + } + + FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + image_hash_valid = 1; + } + } + + rc = !image_hash_valid; + if (rc) { + goto out; + } + +#ifdef EXPECTED_SIG_TLV +#ifdef EXPECTED_KEY_TLV + rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == EXPECTED_KEY_TLV) { + /* + * Determine which key we should be checking. + */ + if (len > KEY_BUF_SIZE) { + rc = -1; + goto out; + } +#ifndef MCUBOOT_HW_KEY + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(buf, len); +#else + rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(image_index, key_buf, len); +#endif /* !MCUBOOT_HW_KEY */ + /* + * The key may not be found, which is acceptable. There + * can be multiple signatures, each preceded by a key. + */ + } + } +#endif /* EXPECTED_KEY_TLV */ + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Ignore this signature if it is out of bounds. */ + if (key_id < 0 || key_id >= bootutil_key_cnt) { + key_id = -1; + continue; + } + + if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + + FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), + buf, len, key_id); + key_id = -1; + } + } +#endif /* EXPECTED_SIG_TLV */ + } +#endif + +#ifdef EXPECTED_SIG_TLV + FIH_SET(fih_rc, valid_signature); +#endif + out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 7b718758d..99837a300 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,6 +49,11 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + #ifdef __ZEPHYR__ #include #endif @@ -901,10 +906,10 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } #else - if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && - (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) - { - return false; + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { + if (!boot_is_compressed_header_valid(hdr, fap, state)) { + return false; + } } #endif @@ -1084,6 +1089,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * attempts to validate and boot it. */ } + #if !defined(__BOOTSIM__) BOOT_LOG_ERR("Image in the %s slot is not valid!", (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); @@ -1520,6 +1526,9 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + struct image_header *hdr; +#endif TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); @@ -1545,6 +1554,16 @@ boot_copy_region(struct boot_loader_state *state, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + + if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { + /* Use alternative function for compressed images */ + return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, + BUF_SZ); + } +#endif + bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 776328d71..7d150d7ea 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -251,6 +251,12 @@ if(CONFIG_BOOT_ENCRYPT_EC256) ) endif() +if(CONFIG_BOOT_DECOMPRESSION) + zephyr_library_sources( + decompression.c + ) +endif() + if(CONFIG_MCUBOOT_SERIAL) zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c) zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 848b6ca83..f7d1eb77e 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -815,6 +815,10 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool + depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) + depends on !SINGLE_APPLICATION_SLOT && !BOOT_ENCRYPT_IMAGE && BOOT_UPGRADE_ONLY + depends on UPDATEABLE_IMAGE_NUMBER = 1 + default y help Hidden symbol which should be selected if a system provided decompression support. @@ -822,6 +826,8 @@ if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION bool "Decompression" + select NRF_COMPRESS_CLEANUP + select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to @@ -830,9 +836,9 @@ menuconfig BOOT_DECOMPRESSION if BOOT_DECOMPRESSION config BOOT_DECOMPRESSION_BUFFER_SIZE - int "Write buffer size" + int range 16 16384 - default 4096 + default NRF_COMPRESS_CHUNK_SIZE help The size of a secondary buffer used for writing decompressed data to the storage device. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c new file mode 100644 index 000000000..062cdbc61 --- /dev/null +++ b/boot/zephyr/decompression.c @@ -0,0 +1,1115 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include "compression/decompression.h" +#include "bootutil/crypto/sha.h" +#include "bootutil/bootutil_log.h" + +#if !defined(__BOOTSIM__) +#define TARGET_STATIC static +#else +#define TARGET_STATIC +#endif + +#if defined(MCUBOOT_SIGN_RSA) +#if MCUBOOT_SIGN_RSA_LEN == 2048 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS +#elif MCUBOOT_SIGN_RSA_LEN == 3072 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA3072_PSS +#endif +#elif defined(MCUBOOT_SIGN_EC256) || \ + defined(MCUBOOT_SIGN_EC384) || \ + defined(MCUBOOT_SIGN_EC) +#define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA_SIG +#elif defined(MCUBOOT_SIGN_ED25519) +#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 +#endif + +/* Number of times that consumed data by decompression system can be 0 in a row before aborting */ +#define OFFSET_ZERO_CHECK_TIMES 3 + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx); + +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state) +{ + /* Image is compressed in secondary slot, need to check if fits into the primary slot */ + bool opened_flash_area = false; + int primary_fa_id; + int rc; + int size_check; + int size; + uint32_t protected_tlvs_size; + uint32_t decompressed_size; + + if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { + opened_flash_area = true; + } + + primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); + rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + assert(rc == 0); + + size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + + if (opened_flash_area) { + (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + } + + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, decompressed_size, hdr->ih_hdr_size)) { + return false; + } + + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlvs_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, size, protected_tlvs_size)) { + return false; + } + + if (size >= size_check) { + BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", + size, size_check); + + return false; + } + + return true; +} + +int bootutil_img_hash_decompress(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 *hash_result, + uint8_t *seed, int seed_len) +{ + int rc; + uint32_t read_pos = 0; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t decompressed_image_size; + struct nrf_compress_implementation *compression = NULL; + TARGET_STATIC struct image_header modified_hdr; + bootutil_sha_context sha_ctx; + uint8_t flash_erased_value; + + bootutil_sha_init(&sha_ctx); + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + + goto finish_without_clean; + } + + compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish_without_clean; + } + + rc = compression->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish_without_clean; + } + + /* We need a modified header which has the updated sizes, start with the original header */ + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + /* Extract the decompressed image size from the protected TLV, set it and remove the + * compressed image flags + */ + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate the protected TLV size, these will not include the decompressed + * sha/size/signature entries + */ + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + bootutil_sha_update(&sha_ctx, &modified_hdr, sizeof(modified_hdr)); + read_pos = sizeof(modified_hdr); + flash_erased_value = flash_area_erased_val(fap); + memset(tmp_buf, flash_erased_value, tmp_buf_sz); + + while (read_pos < modified_hdr.ih_hdr_size) { + uint32_t copy_size = tmp_buf_sz; + + if ((read_pos + copy_size) > modified_hdr.ih_hdr_size) { + copy_size = modified_hdr.ih_hdr_size - read_pos; + } + + bootutil_sha_update(&sha_ctx, tmp_buf, copy_size); + read_pos += copy_size; + } + + /* Read in compressed data, decompress and add to hash calculation */ + read_pos = 0; + + while (read_pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - read_pos; + uint32_t tmp_off = 0; + uint8_t offset_zero_check = 0; + + if (copy_size > tmp_buf_sz) { + copy_size = tmp_buf_sz; + } + + rc = flash_area_read(fap, (hdr->ih_hdr_size + read_pos), tmp_buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint8_t *output = NULL; + uint32_t output_size = 0; + uint32_t chunk_size; + bool last_packet = false; + + chunk_size = compression->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + + if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { + last_packet = true; + } + + rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset, + &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + write_pos += output_size; + + if (write_pos > decompressed_image_size) { + BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", + write_pos); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + /* Additional dry-run validity checks */ + if (last_packet == true && write_pos == 0) { + /* Last packet and we still have no output, this is a faulty update */ + BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + if (offset == 0) { + /* If the decompression system continually consumes 0 bytes, then there is a + * problem with this update image, abort and mark image as bad + */ + if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { + BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + ++offset_zero_check; + + break; + } else { + offset_zero_check = 0; + } + + if (output_size > 0) { + bootutil_sha_update(&sha_ctx, output, output_size); + } + + tmp_off += offset; + } + + read_pos += copy_size; + } + + /* If there are any protected TLVs present, add them after the main decompressed image */ + if (modified_hdr.ih_protect_tlv_size > 0) { + rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, + tmp_buf_sz, &sha_ctx); + } + + bootutil_sha_finish(&sha_ctx, hash_result); + +finish: + /* Clean up decompression system */ + (void)compression->deinit(NULL); + +finish_without_clean: + bootutil_sha_drop(&sha_ctx); + + return rc; +} + +static int boot_copy_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t protected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t off; + uint32_t write_pos = 0; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Skip these TLVs as they are not needed */ + continue; + } else { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left = len; + + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - + header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + (len - data_size_left)), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + } + + *written = write_pos; + +out: + return rc; +} + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx) +{ + int rc; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + + bootutil_sha_update(sha_ctx, &tlv_info_header, sizeof(tlv_info_header)); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + while (true) { + uint32_t read_off = 0; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Skip these TLVs as they are not needed */ + continue; + } + + tlv_header.it_type = type; + tlv_header.it_len = len; + + bootutil_sha_update(sha_ctx, &tlv_header, sizeof(tlv_header)); + + while (read_off < len) { + uint32_t copy_size = buf_size; + + if (copy_size > (len - read_off)) { + copy_size = len - read_off; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + read_off), buf, copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + read_off), copy_size, fap_src->fa_id, rc); + + goto out; + } + + bootutil_sha_update(sha_ctx, buf, copy_size); + read_off += copy_size; + } + } + +out: + return rc; +} + +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = hdr->ih_protect_tlv_size; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Exclude these TLVs as they will be copied to the unprotected area */ + tlv_size -= len + sizeof(struct image_tlv); + } + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries then omit protected TLV section entirely */ + tlv_size = 0; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = sizeof(struct image_tlv_info); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off) && type != IMAGE_TLV_DECOMP_SHA && + type != IMAGE_TLV_DECOMP_SIGNATURE) { + /* Include size of protected hash and signature as these will be replacing the + * original ones + */ + continue; + } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + /* Exclude the original unprotected TLVs for signature and hash, the length of the + * signature of the compressed data might not be the same size as the signaute of the + * decompressed data, as is the case when using ECDSA-P256 + */ + continue; + } + + tlv_size += len + sizeof(struct image_tlv); + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries in the unprotected TLV section then there is something wrong + * with this image + */ + BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); + rc = BOOT_EBADIMAGE; + + goto out; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +static int boot_copy_unprotected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t unprotected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t write_pos = 0; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv_iter it_protected; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_INFO_MAGIC, + .it_tlv_tot = unprotected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, false); + if (rc) { + goto out; + } + + while (true) { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off)) { + /* Skip protected TLVs */ + continue; + } + + /* Change the values of these fields from having the data in the compressed image + * unprotected TLV (which is valid only for the compressed image data) to having the + * fields in the protected TLV section (which is valid for the decompressed image data). + * The compressed data is no longer needed + */ + if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + rc = bootutil_tlv_iter_begin(&it_protected, hdr, fap_src, (type == EXPECTED_HASH_TLV ? + IMAGE_TLV_DECOMP_SHA : + IMAGE_TLV_DECOMP_SIGNATURE), + true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it_protected, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + type = EXPECTED_HASH_TLV; + } else { + type = EXPECTED_SIG_TLV; + } + } + + data_size_left = len; + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + len - data_size_left), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + + *written = write_pos; + +out: + return rc; +} + +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size) +{ + int rc; + uint32_t pos = 0; + uint16_t decomp_buf_size = 0; + uint16_t write_alignment; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t unprotected_tlv_size = 0; + uint32_t tlv_write_size = 0; + uint32_t decompressed_image_size; + struct nrf_compress_implementation *compression = NULL; + struct image_header *hdr; + TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4))); + TARGET_STATIC struct image_header modified_hdr; + + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + rc = compression->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + write_alignment = flash_area_align(fap_dst); + + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + rc = bootutil_get_img_decomp_size(hdr, fap_src, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate protected TLV size for target image once items are removed */ + rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + + rc = boot_size_unprotected_tlvs(hdr, fap_src, &unprotected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + /* Write out the image header first, this should be a multiple of the write size */ + rc = flash_area_write(fap_dst, off_dst, &modified_hdr, sizeof(modified_hdr)); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + /* Read in, decompress and write out data */ + while (pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - pos; + uint32_t tmp_off = 0; + + if (copy_size > buf_size) { + copy_size = buf_size; + } + + rc = flash_area_read(fap_src, off_src + hdr->ih_hdr_size + pos, buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint32_t output_size = 0; + uint32_t chunk_size; + uint32_t compression_buffer_pos = 0; + uint8_t *output = NULL; + bool last_packet = false; + + chunk_size = compression->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + + if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { + last_packet = true; + } + + rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset, + &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + /* Copy data to secondary buffer for writing out */ + while (output_size > 0) { + uint32_t data_size = (sizeof(decomp_buf) - decomp_buf_size); + + if (data_size > output_size) { + data_size = output_size; + } + + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], data_size); + compression_buffer_pos += data_size; + + decomp_buf_size += data_size; + output_size -= data_size; + + /* Write data out from secondary buffer when it is full */ + if (decomp_buf_size == sizeof(decomp_buf)) { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, sizeof(decomp_buf)); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), sizeof(decomp_buf), + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + write_pos += sizeof(decomp_buf); + decomp_buf_size = 0; + } + } + + tmp_off += offset; + } + + pos += copy_size; + } + + /* Clean up decompression system */ + (void)compression->deinit(NULL); + + if (protected_tlv_size > 0) { + rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), protected_tlv_size, + decomp_buf, DECOMP_BUF_SIZE, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + + goto finish; + } + + write_pos += tlv_write_size; + } + + tlv_write_size = 0; + rc = boot_copy_unprotected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), unprotected_tlv_size, + decomp_buf, DECOMP_BUF_SIZE, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + + goto finish; + } + + write_pos += tlv_write_size; + + /* Check if we have unwritten data buffered up and, if so, write it out */ + if (decomp_buf_size > 0) { + uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); + + /* Check if additional write padding should be applied to meet the minimum write size */ + if (write_padding_size) { + uint8_t flash_erased_value; + + flash_erased_value = flash_area_erased_val(fap_dst); + memset(&decomp_buf[decomp_buf_size], flash_erased_value, write_padding_size); + decomp_buf_size += write_padding_size; + } + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf, + decomp_buf_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + write_pos += decomp_buf_size; + decomp_buf_size = 0; + } + +finish: + memset(decomp_buf, 0, sizeof(decomp_buf)); + + return rc; +} + +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size) +{ + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + if (hdr == NULL || fap == NULL || img_decomp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_decomp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_decomp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + + return BOOT_EFLASH; + } + + return 0; +} diff --git a/boot/zephyr/include/compression/decompression.h b/boot/zephyr/include/compression/decompression.h new file mode 100644 index 000000000..f8a676ac5 --- /dev/null +++ b/boot/zephyr/include/compression/decompression.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_DECOMPRESSION_ +#define H_DECOMPRESSION_ + +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil/bootutil_public.h" +#include "bootutil/image.h" +#include "../src/bootutil_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Checks if a compressed image header is valid. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param state Bootloader state object. + * + * @return true if valid; false if invalid. + */ +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state); + +/** + * Reads in compressed image data from a slot, decompresses it and writes it out to a destination + * slot, including corresponding image headers and TLVs. + * + * @param state Bootloader state object. + * @param fap_src Flash area of the source slot. + * @param fap_dst Flash area of the destination slot. + * @param off_src Offset of the source slot to read from (should be 0). + * @param off_dst Offset of the destination slot to write to (should be 0). + * @param sz Size of the source slot data. + * @param buf Temporary buffer for reading data from. + * @param buf_size Size of temporary buffer. + * + * @return 0 on success; nonzero on failure. + */ +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size); + +/** + * Gets the total data size (excluding headers and TLVs) of a compressed image when it is + * decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param img_decomp_size Pointer to variable that will be updated with the decompressed image + * size. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size); + +/** + * Calculate MCUboot-compatible image hash of compressed image slot. + * + * @param enc_state Not currently used, set to NULL. + * @param image_index Image number. + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param tmp_buf Temporary buffer for reading data from. + * @param tmp_buf_sz Size of temporary buffer. + * @param hash_result Pointer to a variable that will be updated with the image hash. + * @param seed Not currently used, set to NULL. + * @param seed_len Not currently used, set to 0. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_img_hash_decompress(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 *hash_result, + uint8_t *seed, int seed_len); + +/** + * Calculates the size that the compressed image protected TLV section will occupy once the image + * has been decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param sz Pointer to variable that will be updated with the protected TLV size. + * + * @return 0 on success; nonzero on failure. + */ +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap_src, + uint32_t *sz); + +#ifdef __cplusplus +} +#endif + +#endif /* H_DECOMPRESSION_ */ From 7ff8c8fa0c1689026566c8cb2ed9121d6831809f Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Thu, 14 Feb 2019 13:20:34 +0100 Subject: [PATCH 207/287] [nrf noup] boot: Add shared crypto for ECDSA and SHA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add functions for ecdsa_verify_secp256r1 and sha256 to use the shared crypto API * Add Kconfig and CMake variables for selecting shared crypto when using ecdsa * Add custom section to project for placing the API section in the correct location in flash * Add kconfig fragment for using external crypto Signed-off-by: Sigvart Hovland Signed-off-by: Martí Bolívar Signed-off-by: Emil Obalski Signed-off-by: Andrzej Puzdrowski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Trond Einar Snekvik Signed-off-by: Georgios Vasilakis Signed-off-by: Johann Fischer Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 049e896648b012a036bda2f451fbd279e396102b) --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 64 +++++++++++++++++-- boot/bootutil/include/bootutil/crypto/sha.h | 32 ++++++++++ boot/zephyr/CMakeLists.txt | 2 + boot/zephyr/external_crypto.conf | 20 ++++++ .../include/mcuboot_config/mcuboot_config.h | 5 +- 5 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 boot/zephyr/external_crypto.conf diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 3b0541072..85355f20c 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -34,6 +34,7 @@ #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 @@ -70,12 +71,18 @@ #include "bootutil/sign_key.h" #include "common.h" +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + #include + #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_PSA_CRYPTO) + defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO)) \ + && !defined(MCUBOOT_USE_PSA_CRYPTO) /* * Declaring these like this adds NULL termination. */ @@ -127,8 +134,6 @@ static int bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* (MCUBOOT_USE_TINYCRYPT || MCUBOOT_USE_MBED_TLS || MCUBOOT_USE_CC310) && !MCUBOOT_USE_PSA_CRYPTO */ -#if defined(MCUBOOT_USE_TINYCRYPT) -#ifndef MCUBOOT_ECDSA_NEED_ASN1_SIG /* * cp points to ASN1 string containing an integer. * Verify the tag, and that the length is 32 bytes. Helper function. @@ -178,8 +183,8 @@ static int bootutil_decode_sig(uint8_t signature[NUM_ECC_BYTES * 2], uint8_t *cp } return 0; } -#endif /* not MCUBOOT_ECDSA_NEED_ASN1_SIG */ +#if defined(MCUBOOT_USE_TINYCRYPT) typedef uintptr_t bootutil_ecdsa_context; static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx) { @@ -248,8 +253,12 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, { (void)ctx; (void)pk_len; - (void)sig_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) { @@ -257,7 +266,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, } pk++; - return cc310_ecdsa_verify_secp256r1(hash, pk, sig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE); + 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, @@ -613,6 +622,49 @@ static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, #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 diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index d136a7f53..6ba8d946d 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -30,6 +30,7 @@ #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 @@ -250,6 +251,37 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, } #endif /* MCUBOOT_USE_CC310 */ +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + +#include + +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 diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 7d150d7ea..51333a73d 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -173,6 +173,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) zephyr_link_libraries(nrfxlib_crypto) + elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) + zephyr_include_directories(${BL_CRYPTO_DIR}/../include) endif() # Since here we are not using Zephyr's mbedTLS but rather our own, we need diff --git a/boot/zephyr/external_crypto.conf b/boot/zephyr/external_crypto.conf new file mode 100644 index 000000000..8181ad51c --- /dev/null +++ b/boot/zephyr/external_crypto.conf @@ -0,0 +1,20 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# These configurations should be used when using nrf/samples/bootloader +# as the immutable bootloader (B0), and MCUBoot as the second stage updateable +# bootloader. + +# Set ECDSA as signing mechanism +CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y + +# Use crypto backend from B0 +CONFIG_BOOT_NRF_EXTERNAL_CRYPTO=y +CONFIG_SECURE_BOOT_CRYPTO=y +CONFIG_SB_CRYPTO_CLIENT_ECDSA_SECP256R1=y +CONFIG_SB_CRYPTO_CLIENT_SHA256=y +CONFIG_BL_SHA256_EXT_API_REQUIRED=y +CONFIG_BL_SECP256R1_EXT_API_REQUIRED=y diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 573155b39..ae17f85ff 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -40,11 +40,10 @@ #define MCUBOOT_USE_TINYCRYPT #elif defined(CONFIG_BOOT_USE_CC310) #define MCUBOOT_USE_CC310 -#ifdef CONFIG_BOOT_USE_NRF_CC310_BL -#define MCUBOOT_USE_NRF_CC310_BL -#endif #elif defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) #define MCUBOOT_USE_PSA_CRYPTO +#elif defined(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) +#define MCUBOOT_USE_NRF_EXTERNAL_CRYPTO #endif #ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA512 From 1107145b8496acf8682d5ae223f942f861771405 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 29 May 2024 17:46:17 +0000 Subject: [PATCH 208/287] [nrf noup] PSA implementation of x25519 and ed25519 verification The commit provides implementation of image verification with ed25519 and encryption/decryption support where random key is encrypted using x25519. Signed-off-by: Dominik Ermel (cherry picked from commit 2c3c181854448717dae6ad22c9bb813cfe14062f) --- .../include/bootutil/crypto/aes_ctr.h | 38 +- boot/bootutil/src/ed25519_psa.c | 71 +++ boot/bootutil/src/encrypted.c | 114 ++--- boot/bootutil/src/encrypted_psa.c | 454 ++++++++++++++++++ boot/bootutil/src/image_ed25519.c | 13 +- 5 files changed, 631 insertions(+), 59 deletions(-) create mode 100644 boot/bootutil/src/ed25519_psa.c create mode 100644 boot/bootutil/src/encrypted_psa.c diff --git a/boot/bootutil/include/bootutil/crypto/aes_ctr.h b/boot/bootutil/include/bootutil/crypto/aes_ctr.h index 50d36a4fc..44190361c 100644 --- a/boot/bootutil/include/bootutil/crypto/aes_ctr.h +++ b/boot/bootutil/include/bootutil/crypto/aes_ctr.h @@ -15,8 +15,8 @@ #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" + 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) @@ -38,12 +38,46 @@ #define BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE TC_AES_BLOCK_SIZE #endif /* MCUBOOT_USE_TINYCRYPT */ + +#if defined(MCUBOOT_USE_PSA_CRYPTO) + #include + #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 #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) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c new file mode 100644 index 000000000..3d7274307 --- /dev/null +++ b/boot/bootutil/src/ed25519_psa.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include +#include +#include + +#include +#include "bootutil/bootutil_log.h" + +#include +#include + +BOOT_LOG_MODULE_DECLARE(ed25519_psa); + +#define SHA512_DIGEST_LENGTH 64 +#define EDDSA_KEY_LENGTH 32 +#define EDDSA_SIGNAGURE_LENGTH 64 + +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], + const uint8_t public_key[EDDSA_KEY_LENGTH]) +{ + /* Set to any error */ + psa_status_t status = PSA_ERROR_BAD_STATE; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t kid; + int ret = 0; /* Fail by default */ + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d\n", status); + return 0; + } + + status = PSA_ERROR_BAD_STATE; + + psa_set_key_type(&key_attr, + PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS)); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE); + psa_set_key_algorithm(&key_attr, PSA_ALG_PURE_EDDSA); + + status = psa_import_key(&key_attr, public_key, EDDSA_KEY_LENGTH, &kid); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("ED25519 key import failed %d", status); + return 0; + } + + status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len, + signature, EDDSA_SIGNAGURE_LENGTH); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + ret = 0; + /* Pass through to destroy key */ + } else { + ret = 1; + /* Pass through to destroy key */ + } + + status = psa_destroy_key(kid); + + if (status != PSA_SUCCESS) { + /* Just for logging */ + BOOT_LOG_WRN("Failed to destroy key %d", status); + } + + return ret; +} diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index 8449a28dd..67fa819bb 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -25,6 +25,7 @@ #include "bootutil/crypto/ecdh_p256.h" #endif +#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_X25519) #include "bootutil/crypto/ecdh_x25519.h" #endif @@ -35,6 +36,7 @@ #include "mbedtls/oid.h" #include "mbedtls/asn1.h" #endif +#endif #include "bootutil/image.h" #include "bootutil/enc_key.h" @@ -43,6 +45,30 @@ #include "bootutil_priv.h" +#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE + +#if defined(MCUBOOT_ENCRYPT_RSA) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 +#elif defined(MCUBOOT_ENCRYPT_KW) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW +#elif defined(MCUBOOT_ENCRYPT_EC256) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (65) +# define EC_CIPHERKEY_INDEX (65 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-P256 component indexes"); +#elif defined(MCUBOOT_ENCRYPT_X25519) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (32) +# define EC_CIPHERKEY_INDEX (32 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-X25519 component indexes"); +#endif + +/* NOUP Fixme: */ +#if !defined(CONFIG_BOOT_ED25519_PSA) #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) #if defined(_compare) static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size) @@ -351,60 +377,6 @@ int boot_enc_retrieve_private_key(struct bootutil_key **private_key) } #endif /* !MCUBOOT_ENC_BUILTIN_KEY */ -int -boot_enc_init(struct enc_key_data *enc_state, uint8_t slot) -{ - bootutil_aes_ctr_init(&enc_state[slot].aes_ctr); - return 0; -} - -int -boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot) -{ - bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr); - enc_state[slot].valid = 0; - return 0; -} - -int -boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, - const struct boot_status *bs) -{ - int rc; - - rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]); - if (rc != 0) { - boot_enc_drop(enc_state, slot); - return -1; - } - - enc_state[slot].valid = 1; - - return 0; -} - -#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE - -#if defined(MCUBOOT_ENCRYPT_RSA) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 -#elif defined(MCUBOOT_ENCRYPT_KW) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW -#elif defined(MCUBOOT_ENCRYPT_EC256) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (65) -# define EC_CIPHERKEY_INDEX (65 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-P256 component indexes"); -#elif defined(MCUBOOT_ENCRYPT_X25519) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (32) -# define EC_CIPHERKEY_INDEX (32 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-X25519 component indexes"); -#endif - #if ( (defined(MCUBOOT_ENCRYPT_RSA) && defined(MCUBOOT_USE_MBED_TLS) && !defined(MCUBOOT_USE_PSA_CRYPTO)) || \ (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ) #if MBEDTLS_VERSION_NUMBER >= 0x03000000 @@ -627,6 +599,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return rc; } +#endif /* CONFIG_BOOT_ED25519_PSA */ /* * Load encryption key. @@ -681,6 +654,39 @@ boot_enc_load(struct enc_key_data *enc_state, int slot, return boot_decrypt_key(buf, bs->enckey[slot]); } +int +boot_enc_init(struct enc_key_data *enc_state, uint8_t slot) +{ + bootutil_aes_ctr_init(&enc_state[slot].aes_ctr); + return 0; +} + +int +boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot) +{ + bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr); + enc_state[slot].valid = 0; + return 0; +} + +int +boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, + const struct boot_status *bs) +{ + int rc; + + rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]); + if (rc != 0) { + boot_enc_drop(enc_state, slot); + return -1; + } + + enc_state[slot].valid = 1; + + return 0; +} + + bool boot_enc_valid(struct enc_key_data *enc_state, int slot) { diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c new file mode 100644 index 000000000..c3f72884d --- /dev/null +++ b/boot/bootutil/src/encrypted_psa.c @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "mcuboot_config/mcuboot_config.h" + +#include +#include +#include + +/* We are not really using the MBEDTLS but need the ASN.1 parsing functions */ +#define MBEDTLS_ASN1_PARSE_C + +#include "bootutil/crypto/sha.h" +#include "mbedtls/oid.h" +#include "mbedtls/asn1.h" + +#include "bootutil/image.h" +#include "bootutil/enc_key.h" +#include "bootutil/sign_key.h" +#include "bootutil/crypto/common.h" + +#include "bootutil_priv.h" +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); + +#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE +#define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 +#define EC_PUBK_INDEX (0) +#define EC_TAG_INDEX (32) +#define EC_CIPHERKEY_INDEX (32 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-X25519 component indexes"); + +#define X25519_OID "\x6e" +static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ + MBEDTLS_OID_ORG_GOV X25519_OID; + +#define SHARED_KEY_LEN 32 +#define PRIV_KEY_LEN 32 + +/* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ +static int +parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +{ + size_t len; + int version; + mbedtls_asn1_buf alg; + mbedtls_asn1_buf param; + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE) != 0) { + return -1; + } + + if (*p + len != end) { + return -2; + } + + version = 0; + if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { + return -3; + } + + if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { + return -4; + } + + 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 -5; + } + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -6; + } + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -7; + } + + if (len != PRIV_KEY_LEN) { + return -8; + } + + memcpy(private_key, *p, PRIV_KEY_LEN); + return 0; +} + +void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx) +{ + psa_status_t psa_ret = psa_crypto_init(); + + (void)ctx; + + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES init PSA crypto init failed %d", psa_ret); + assert(0); + } +} + +#if defined(MCUBOOT_ENC_IMAGES) +extern const struct bootutil_key bootutil_enc_key; +/* + * Decrypt an encryption key TLV. + * + * @param buf An encryption TLV read from flash (build time fixed length) + * @param enckey An AES-128 or AES-256 key sized buffer to store to plain key. + */ +int +boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) +{ + uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; + uint8_t *cp; + uint8_t *cpend; + uint8_t private_key[PRIV_KEY_LEN]; + size_t len; + psa_status_t psa_ret = PSA_ERROR_BAD_STATE; + psa_status_t psa_cleanup_ret = PSA_ERROR_BAD_STATE; + psa_key_id_t kid; + psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_derivation_operation_t key_do = PSA_KEY_DERIVATION_OPERATION_INIT; + psa_algorithm_t key_do_alg; + int rc = -1; + + cp = (uint8_t *)bootutil_enc_key.key; + cpend = cp + *bootutil_enc_key.len; + + /* The psa_cipher_decrypt needs initialization vector of proper length at + * the beginning of the input buffer. + */ + uint8_t iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR) + + BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE]; + + psa_ret = psa_crypto_init(); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES crypto init failed %d", psa_ret); + return -1; + } + + /* + * Load the stored X25519 decryption private key + */ + rc = parse_x25519_enckey(&cp, cpend, private_key); + if (rc) { + return rc; + } + + psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY)); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&kattr, PSA_ALG_ECDH); + + psa_ret = psa_import_key(&kattr, private_key, sizeof(private_key), &kid); + memset(private_key, 0, sizeof(private_key)); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("Built-in key import failed %d", psa_ret); + return -1; + } + + key_do_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)); + + psa_ret = psa_key_derivation_setup(&key_do, key_do_alg); + if (psa_ret != PSA_SUCCESS) { + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Built-in key destruction failed %d", psa_cleanup_ret); + } + BOOT_LOG_ERR("Key derivation setup failed %d", psa_ret); + return -1; + } + + /* Note: PSA 1.1.2 does not have psa_key_agreement that would be useful here + * as it could just add the derived key to the storage and return key id. + * Instead, we have to use the code below to generate derived key and put it + * into storage, to obtain the key id we can then use with psa_mac_* functions. + */ + psa_ret = psa_key_derivation_key_agreement(&key_do, PSA_KEY_DERIVATION_INPUT_SECRET, + kid, &buf[EC_PUBK_INDEX], + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Built-in key destruction failed %d", psa_cleanup_ret); + } + if (psa_ret != PSA_SUCCESS) { + psa_cleanup_ret = psa_key_derivation_abort(&key_do); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Key derivation abort failed %d", psa_ret); + } + + BOOT_LOG_ERR("Key derivation failed %d", psa_ret); + return -1; + } + + /* Only info, no salt */ + psa_ret = psa_key_derivation_input_bytes(&key_do, PSA_KEY_DERIVATION_INPUT_INFO, + "MCUBoot_ECIES_v1", 16); + if (psa_ret != PSA_SUCCESS) { + psa_cleanup_ret = psa_key_derivation_abort(&key_do); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Key derivation abort failed %d", psa_ret); + } + BOOT_LOG_ERR("Key derivation failed %d", psa_ret); + return -1; + } + + len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE; + psa_ret = psa_key_derivation_output_bytes(&key_do, derived_key, len); + psa_cleanup_ret = psa_key_derivation_abort(&key_do); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Key derivation cleanup failed %d", psa_ret); + } + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("Key derivation failed %d", psa_ret); + return -1; + } + + /* The derived key consists of BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE bytes + * followed by BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE bytes. Both parts will + * be imported at the point where needed and discarded immediately after. + */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_HMAC); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_VERIFY_MESSAGE); + psa_set_key_algorithm(&kattr, PSA_ALG_HMAC(PSA_ALG_SHA_256)); + + /* Import the MAC tag key part of derived key, that is the part that starts + * after BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE and has length of + * BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE bytes. + */ + psa_ret = psa_import_key(&kattr, + &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE], + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, &kid); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + memset(derived_key, 0, sizeof(derived_key)); + BOOT_LOG_ERR("MAC key import failed %d", psa_ret); + return -1; + } + + /* Verify the MAC tag of the random encryption key */ + psa_ret = psa_mac_verify(kid, PSA_ALG_HMAC(PSA_ALG_SHA_256), + &buf[EC_CIPHERKEY_INDEX], BOOT_ENC_KEY_SIZE, + &buf[EC_TAG_INDEX], + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("MAC key destruction failed %d", psa_cleanup_ret); + } + if (psa_ret != PSA_SUCCESS) { + memset(derived_key, 0, sizeof(derived_key)); + BOOT_LOG_ERR("MAC verification failed %d", psa_ret); + return -1; + } + + /* The derived key is used in AES decryption of random key */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&kattr, PSA_ALG_CTR); + + /* Import the AES partition of derived key, the first 16 bytes */ + psa_ret = psa_import_key(&kattr, &derived_key[0], + BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, &kid); + memset(derived_key, 0, sizeof(derived_key)); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES key import failed %d", psa_ret); + return -1; + } + + /* Decrypt the random AES encryption key with AES and the key obtained + * at derivation. */ + memset(&iv_and_key[0], 0, PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)); + memcpy(&iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)], + &buf[EC_CIPHERKEY_INDEX], + sizeof(iv_and_key) - PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)); + + len = 0; + psa_ret = psa_cipher_decrypt(kid, PSA_ALG_CTR, iv_and_key, sizeof(iv_and_key), + enckey, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, &len); + memset(iv_and_key, 0, sizeof(iv_and_key)); + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("AES key destruction failed %d", psa_cleanup_ret); + } + if (psa_ret != PSA_SUCCESS || len != BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE) { + memset(enckey, 0, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE); + BOOT_LOG_ERR("Random key decryption failed %d", psa_ret); + return -1; + } + + 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 ret = 0; + psa_status_t psa_ret = PSA_ERROR_BAD_STATE; + psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t kid; + psa_cipher_operation_t psa_op; + size_t elen = 0; /* Decrypted length */ + + /* Fixme: calling psa_crypto_init multiple times is not a problem, + * yet the code here is only present because there is not general + * crypto init. */ + psa_ret = psa_crypto_init(); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); + ret = -1; + goto gone; + } + + psa_op = psa_cipher_operation_init(); + + /* Fixme: Import should happen when key is decrypted, but due to lack + * of key destruction there is no way to destroy key stored by + * psa other way than here. */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&kattr, PSA_ALG_CTR); + + psa_ret = psa_import_key(&kattr, ctx->key, BOOT_ENC_KEY_SIZE, &kid); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc import key failed %d", psa_ret); + ret = -1; + goto gone; + } + + /* This could be done with psa_cipher_decrypt one-shot operation, but + * multi-part operation is used to avoid re-allocating input buffer + * to account for IV in front of data. + */ + psa_ret = psa_cipher_encrypt_setup(&psa_op, kid, PSA_ALG_CTR); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc setup failed %d", psa_ret); + ret = -1; + goto gone_with_key; + } + + /* Fixme: hardcoded counter size, but it is hardcoded everywhere */ + psa_ret = psa_cipher_set_iv(&psa_op, counter, 16); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc IV set failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + + psa_ret = psa_cipher_update(&psa_op, m, mlen, c, mlen, &elen); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc encryption failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + +gone_after_setup: + psa_ret = psa_cipher_abort(&psa_op); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("AES enc cipher abort failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone_with_key: + /* Fixme: Should be removed once key is shared by id */ + psa_ret = psa_destroy_key(kid); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("AES enc destroy key failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone: + return ret; +} + +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) +{ + int ret = 0; + psa_status_t psa_ret = PSA_ERROR_BAD_STATE; + psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t kid; + psa_cipher_operation_t psa_op; + size_t dlen = 0; /* Decrypted length */ + + /* Fixme: the init should already happen before calling the function, but + * somehow it does not, for example when recovering in swap. + */ + psa_ret = psa_crypto_init(); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); + ret = -1; + goto gone; + } + + psa_op = psa_cipher_operation_init(); + + /* Fixme: Import should happen when key is decrypted, but due to lack + * of key destruction there is no way to destroy key stored by + * psa other way than here. */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&kattr, PSA_ALG_CTR); + + psa_ret = psa_import_key(&kattr, ctx->key, BOOT_ENC_KEY_SIZE, &kid); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec import key failed %d", psa_ret); + ret = -1; + goto gone; + } + + /* This could be done with psa_cipher_decrypt one-shot operation, but + * multi-part operation is used to avoid re-allocating input buffer + * to account for IV in front of data. + */ + psa_ret = psa_cipher_decrypt_setup(&psa_op, kid, PSA_ALG_CTR); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec setup failed %d", psa_ret); + ret = -1; + goto gone_with_key; + } + + /* Fixme: hardcoded counter size, but it is hardcoded everywhere */ + psa_ret = psa_cipher_set_iv(&psa_op, counter, 16); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec IV set failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + + psa_ret = psa_cipher_update(&psa_op, c, clen, m, clen, &dlen); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec decryption failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + +gone_after_setup: + psa_ret = psa_cipher_abort(&psa_op); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("PSA dec abort failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone_with_key: + psa_ret = psa_destroy_key(kid); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("PSA dec key failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone: + return ret; +} +#endif /* defined(MCUBOOT_ENC_IMAGES) */ diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 0d5e66df0..447289253 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -9,6 +9,11 @@ #include "mcuboot_config/mcuboot_config.h" +#if defined(CONFIG_NRF_SECURITY) +/* We are not really using the MBEDTLS but need the ASN.1 parsing funcitons */ +#define MBEDTLS_ASN1_PARSE_C +#endif + #ifdef MCUBOOT_SIGN_ED25519 #include "bootutil/sign_key.h" @@ -19,12 +24,14 @@ #include "bootutil/crypto/common.h" #include "bootutil/crypto/sha.h" +#define EDDSA_SIGNATURE_LENGTH 64 + static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; #define NUM_ED25519_BYTES 32 extern int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[64], - const uint8_t public_key[32]); + const uint8_t signature[EDDSA_SIGNATURE_LENGTH], + const uint8_t public_key[NUM_ED25519_BYTES]); /* * Parse the public key used for signing. @@ -74,7 +81,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t *pubkey; uint8_t *end; - if (hlen != IMAGE_HASH_SIZE || slen != 64) { + if (hlen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } From cbb7da0a51f469b775bcbf9662ae3a905917563b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 2 Sep 2024 11:20:00 +0100 Subject: [PATCH 209/287] [nrf noup] zephyr: Add support for ARM thumb filter Adds support for ARM thumb filter usage for compressed firmware updates Signed-off-by: Jamie McCrae (cherry picked from commit 390c468afcdc4f3039a00efece68073355320a97) --- boot/zephyr/decompression.c | 305 +++++++++++++++++++++++++++--------- 1 file changed, 234 insertions(+), 71 deletions(-) diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index 062cdbc61..35a1950b2 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -29,6 +29,14 @@ #define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 #endif +#define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) +#define DECOMP_BUF_EXTRA_SIZE 2 +#else +#define DECOMP_BUF_EXTRA_SIZE 0 +#endif +#define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE) + /* Number of times that consumed data by decompression system can be 0 in a row before aborting */ #define OFFSET_ZERO_CHECK_TIMES 3 @@ -87,13 +95,22 @@ bool boot_is_compressed_header_valid(const struct image_header *hdr, const struc if (size >= size_check) { BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", size, size_check); - return false; } return true; } +static bool is_compression_object_valid(struct nrf_compress_implementation *compression) +{ + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + return false; + } + + return true; +} + int bootutil_img_hash_decompress(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 *hash_result, @@ -104,7 +121,9 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index uint32_t write_pos = 0; uint32_t protected_tlv_size = 0; uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression = NULL; + uint32_t output_size_total = 0; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; TARGET_STATIC struct image_header modified_hdr; bootutil_sha_context sha_ctx; uint8_t flash_erased_value; @@ -122,27 +141,26 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; } - compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish_without_clean; } - rc = compression->init(NULL); + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); if (rc) { BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish_without_clean; } @@ -157,7 +175,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -172,7 +189,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (rc) { BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -211,7 +227,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } @@ -225,7 +240,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index uint32_t chunk_size; bool last_packet = false; - chunk_size = compression->decompress_bytes_needed(NULL); + chunk_size = compression_lzma->decompress_bytes_needed(NULL); if (chunk_size > (copy_size - tmp_off)) { chunk_size = (copy_size - tmp_off); @@ -235,13 +250,12 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index last_packet = true; } - rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset, - &output, &output_size); + rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); if (rc) { BOOT_LOG_ERR("Decompression error: %d", rc); rc = BOOT_EBADSTATUS; - goto finish; } @@ -251,7 +265,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", write_pos); rc = BOOT_EBADIMAGE; - goto finish; } @@ -260,7 +273,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index /* Last packet and we still have no output, this is a faulty update */ BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -271,7 +283,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -282,8 +293,48 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index offset_zero_check = 0; } + /* Copy data to secondary buffer for calculating hash */ if (output_size > 0) { - bootutil_sha_update(&sha_ctx, output, output_size); + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + /* Run this through the ARM thumb filter */ + uint32_t offset_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t processed_size = 0; + uint32_t output_size_arm_thumb = 0; + + while (processed_size < output_size) { + uint32_t current_size = output_size - processed_size; + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_packet && (processed_size + current_size) == + output_size) { + arm_thumb_last_packet = true; + } + + rc = compression_arm_thumb->decompress(NULL, &output[processed_size], + current_size, arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb); + output_size_total += output_size_arm_thumb; + processed_size += current_size; + } + } else { + bootutil_sha_update(&sha_ctx, output, output_size); + output_size_total += output_size; + } } tmp_off += offset; @@ -292,6 +343,13 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index read_pos += copy_size; } + if (modified_hdr.ih_img_size != output_size_total) { + BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d", + modified_hdr.ih_img_size, output_size_total); + rc = BOOT_EBADSTATUS; + goto finish; + } + /* If there are any protected TLVs present, add them after the main decompressed image */ if (modified_hdr.ih_protect_tlv_size > 0) { rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, @@ -302,7 +360,8 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index finish: /* Clean up decompression system */ - (void)compression->deinit(NULL); + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); finish_without_clean: bootutil_sha_drop(&sha_ctx); @@ -353,7 +412,6 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -422,7 +480,6 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - goto out; } @@ -438,7 +495,6 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -513,7 +569,6 @@ static int boot_sha_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + read_off), copy_size, fap_src->fa_id, rc); - goto out; } @@ -626,7 +681,6 @@ int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flas */ BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); rc = BOOT_EBADIMAGE; - goto out; } @@ -681,7 +735,6 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -778,7 +831,6 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - goto out; } @@ -794,7 +846,6 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -823,11 +874,17 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint32_t unprotected_tlv_size = 0; uint32_t tlv_write_size = 0; uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression = NULL; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; struct image_header *hdr; - TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4))); + TARGET_STATIC uint8_t decomp_buf[DECOMP_BUF_ALLOC_SIZE] __attribute__((aligned(4))); TARGET_STATIC struct image_header modified_hdr; +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + uint8_t excess_data_buffer[DECOMP_BUF_EXTRA_SIZE]; + bool excess_data_buffer_full = false; +#endif + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); /* Setup decompression system */ @@ -841,27 +898,26 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish; } - compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish; } - rc = compression->init(NULL); + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); if (rc) { BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish; } @@ -874,7 +930,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -887,7 +942,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -898,7 +952,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -909,7 +962,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } @@ -928,7 +980,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } @@ -943,7 +994,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint8_t *output = NULL; bool last_packet = false; - chunk_size = compression->decompress_bytes_needed(NULL); + chunk_size = compression_lzma->decompress_bytes_needed(NULL); if (chunk_size > (copy_size - tmp_off)) { chunk_size = (copy_size - tmp_off); @@ -953,47 +1004,142 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl last_packet = true; } - rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset, - &output, &output_size); + rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); if (rc) { BOOT_LOG_ERR("Decompression error: %d", rc); rc = BOOT_EBADSTATUS; - goto finish; } /* Copy data to secondary buffer for writing out */ while (output_size > 0) { - uint32_t data_size = (sizeof(decomp_buf) - decomp_buf_size); + uint32_t data_size = (DECOMP_BUF_SIZE - decomp_buf_size); if (data_size > output_size) { data_size = output_size; } - memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], data_size); +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + memcpy(&decomp_buf[decomp_buf_size + DECOMP_BUF_EXTRA_SIZE], + &output[compression_buffer_pos], data_size); + } else +#endif + { + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], + data_size); + } + compression_buffer_pos += data_size; decomp_buf_size += data_size; output_size -= data_size; /* Write data out from secondary buffer when it is full */ - if (decomp_buf_size == sizeof(decomp_buf)) { - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, sizeof(decomp_buf)); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), sizeof(decomp_buf), - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; + if (decomp_buf_size == DECOMP_BUF_SIZE) { +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + uint32_t filter_writeback_pos = 0; + uint32_t processed_size = 0; + + /* Run this through the ARM thumb filter */ + while (processed_size < DECOMP_BUF_SIZE) { + uint32_t offset_arm_thumb = 0; + uint32_t output_size_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t current_size = DECOMP_BUF_SIZE; + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_packet && (processed_size + current_size) == DECOMP_BUF_SIZE + && output_size == 0) { + arm_thumb_last_packet = true; + } + + rc = compression_arm_thumb->decompress(NULL, + &decomp_buf[processed_size + + DECOMP_BUF_EXTRA_SIZE], + current_size, + arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + memcpy(&decomp_buf[filter_writeback_pos], output_arm_thumb, + output_size_arm_thumb); + filter_writeback_pos += output_size_arm_thumb; + processed_size += current_size; + } + + if (excess_data_buffer_full == true) + { + /* Restore extra data removed from previous iteration to the write + * buffer + */ + memmove(&decomp_buf[DECOMP_BUF_EXTRA_SIZE], decomp_buf, + filter_writeback_pos); + memcpy(decomp_buf, excess_data_buffer, DECOMP_BUF_EXTRA_SIZE); + excess_data_buffer_full = false; + filter_writeback_pos += DECOMP_BUF_EXTRA_SIZE; + } + + if ((filter_writeback_pos % sizeof(uint32_t)) != 0) + { + /* Since there are an extra 2 bytes here, remove them and stash for + * later usage to prevent flash write issues with non-word boundary + * writes + */ + memcpy(excess_data_buffer, &decomp_buf[filter_writeback_pos - + DECOMP_BUF_EXTRA_SIZE], + DECOMP_BUF_EXTRA_SIZE); + excess_data_buffer_full = true; + filter_writeback_pos -= DECOMP_BUF_EXTRA_SIZE; + } + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, filter_writeback_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), DECOMP_BUF_SIZE, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += filter_writeback_pos; + decomp_buf_size = 0; + filter_writeback_pos = 0; + } else +#endif + { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, DECOMP_BUF_SIZE); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), DECOMP_BUF_SIZE, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += DECOMP_BUF_SIZE; + decomp_buf_size = 0; } - - write_pos += sizeof(decomp_buf); - decomp_buf_size = 0; } } @@ -1003,8 +1149,30 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl pos += copy_size; } +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0) { + /* Extra data that has not been written out that needs ARM thumb filter applied */ + uint32_t offset_arm_thumb = 0; + uint32_t output_size_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + + rc = compression_arm_thumb->decompress(NULL, &decomp_buf[DECOMP_BUF_EXTRA_SIZE], + decomp_buf_size, true, &offset_arm_thumb, + &output_arm_thumb, &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + memcpy(decomp_buf, output_arm_thumb, output_size_arm_thumb); + } +#endif + /* Clean up decompression system */ - (void)compression->deinit(NULL); + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); if (protected_tlv_size > 0) { rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + @@ -1014,7 +1182,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - goto finish; } @@ -1029,7 +1196,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - goto finish; } @@ -1040,7 +1206,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); /* Check if additional write padding should be applied to meet the minimum write size */ - if (write_padding_size) { + if (write_alignment > 1 && write_padding_size) { uint8_t flash_erased_value; flash_erased_value = flash_area_erased_val(fap_dst); @@ -1056,7 +1222,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } @@ -1098,7 +1263,6 @@ int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct fl if (len != sizeof(*img_decomp_size)) { BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); - return BOOT_EBADIMAGE; } @@ -1107,7 +1271,6 @@ int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct fl if (rc) { BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", off, len, fap->fa_id, rc); - return BOOT_EFLASH; } From 62929e493c6feb75fc83378d7235280e14a745cc Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 17 Oct 2024 19:38:39 +0000 Subject: [PATCH 210/287] [nrf noup] Remove setting default MCUboot mbedTLS config This has been overriding logic that selects nrf-config.h when CONFIG_NRF_SECURITY=y. Signed-off-by: Dominik Ermel (cherry picked from commit ea00c047de0adbadc7162b945bfb139136f434cb) --- boot/zephyr/prj.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index e4f7d9030..9ff1ba274 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -1,7 +1,6 @@ CONFIG_PM=n CONFIG_MAIN_STACK_SIZE=10240 -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" CONFIG_BOOT_SWAP_SAVE_ENCTLV=n CONFIG_BOOT_ENCRYPT_IMAGE=n From 09035f0f04709d5d29d61532bbedd433a569d506 Mon Sep 17 00:00:00 2001 From: Markus Lassila Date: Fri, 30 Aug 2024 13:10:05 +0300 Subject: [PATCH 211/287] [nrf noup] boot: zephyr: Do not lock PCD region with TF-M Previously PCD memory was locked as read-only, non-secure in MCUboot. Given that TF-M also needs write to PCD to communicate with b0n, the memory is left unlocked and locked to read-only, non-secure in TF-M. Signed-off-by: Markus Lassila (cherry picked from commit ad56ff5183465af7f590d3ce8e1132fab2c5201a) --- boot/zephyr/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index b8bb6ec14..62a9c2c57 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -648,7 +648,11 @@ int main(void) } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) - pcd_lock_ram(); +#if defined(PM_TFM_SECURE_ADDRESS) + pcd_lock_ram(false); +#else + pcd_lock_ram(true); +#endif #endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ From 8041ad6935fce96c37e873ef6ca5a1d42e98a04c Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 10 Sep 2024 13:41:30 +0100 Subject: [PATCH 212/287] [nrf noup] treewide: Add support for sysbuild assigned images Adds support for image IDs that are assigned by sysbuild, which allows for dynamically supporting different configurations without needing dummy images to support different modes. Also fixes multiple deficiencies with the previous code where things were not properly accounted for e.g. using the swap algorithm including all swap status parts when updating s0/s1 MCUboot image which could overwrite and corrupt the image data in the other slot Signed-off-by: Jamie McCrae (cherry picked from commit 43d47399086a12c2d7f312fb30632655c5c23b3c) (cherry picked from commit c09c22a1b1c84a41dd0a1817c1c2802b8c6c4097) (cherry picked from commit 3a25855215a2cfc64c3f0e2dba3ada3f11df7816) --- boot/bootutil/src/loader.c | 176 +++++++++++++-------- boot/bootutil/src/swap_nsib.c | 70 ++++++++ boot/bootutil/src/swap_priv.h | 8 + boot/zephyr/CMakeLists.txt | 6 + boot/zephyr/include/sysflash/pm_sysflash.h | 69 ++++---- 5 files changed, 225 insertions(+), 104 deletions(-) create mode 100644 boot/bootutil/src/swap_nsib.c diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 99837a300..84dbd625a 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -151,15 +151,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ -#ifdef PM_S1_ADDRESS +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 /* Patch needed for NCS. The primary slot of the second image * (image 1) will not contain a valid image header until an upgrade * of mcuboot has happened (filling S1 with the new version). */ - if (BOOT_CURR_IMG(state) == 1 && i == 0) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER && i == 0) { continue; } -#endif /* PM_S1_ADDRESS */ +#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */ if (i > 0 && !require_all) { return 0; } else { @@ -1050,7 +1050,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) - if (BOOT_CURR_IMG(state) == 1) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); } else { rc = boot_version_cmp( @@ -1119,6 +1119,8 @@ boot_validate_slot(struct boot_loader_state *state, int slot, struct image_header *secondary_hdr = boot_img_hdr(state, slot); uint32_t reset_value = 0; uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); + uint32_t min_addr, max_addr; + bool check_addresses = false; rc = flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)); if (rc != 0) { @@ -1126,29 +1128,46 @@ boot_validate_slot(struct boot_loader_state *state, int slot, goto out; } - uint32_t min_addr, max_addr; - #ifdef PM_CPUNET_APP_ADDRESS /* The primary slot for the network core is emulated in RAM. * Its flash_area hasn't got relevant boundaries. * Therfore need to override its boundaries for the check. */ - if (BOOT_CURR_IMG(state) == 1) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; -#ifdef PM_S1_ADDRESS - } else if (BOOT_CURR_IMG(state) == 0) { + check_addresses = true; + } else +#endif +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { +#if (CONFIG_NCS_IS_VARIANT_IMAGE) min_addr = PM_S0_ADDRESS; - max_addr = pri_fa->fa_off + pri_fa->fa_size; + max_addr = (PM_S0_ADDRESS + PM_S0_SIZE); +#else + min_addr = PM_S1_ADDRESS; + max_addr = (PM_S1_ADDRESS + PM_S1_SIZE); #endif + check_addresses = true; } else #endif - { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + min_addr = MIN(pri_fa->fa_off, PM_S0_ADDRESS); + max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S0_ADDRESS + PM_S0_SIZE)); +#else + min_addr = MIN(pri_fa->fa_off, PM_S1_ADDRESS); + max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S1_ADDRESS + PM_S1_SIZE)); +#endif +#else min_addr = pri_fa->fa_off; max_addr = pri_fa->fa_off + pri_fa->fa_size; +#endif + check_addresses = true; } - if (reset_value < min_addr || reset_value> (max_addr)) { + if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1225,36 +1244,54 @@ boot_update_security_counter(uint8_t image_index, int slot, #define SEC_SLOT_TOUCHED 1 #define SEC_SLOT_ASSIGNED 2 -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -/* This configuration is peculiar - the one physical secondary slot is - * mocking two logical secondary - */ -#define SEC_SLOT_PHYSICAL_CNT 1 +static uint8_t sec_slot_assignment[MCUBOOT_IMAGE_NUMBER] = {0}; + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; +} #else -#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ +} #endif -static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; - static inline void sec_slot_touch(struct boot_loader_state *state) { - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + if (sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + } + } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + if (sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + } + } +#endif - if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { - sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; + if (sec_slot_assignment[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED; } } static inline void sec_slot_mark_assigned(struct boot_loader_state *state) { - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + } +#endif - sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; + sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED; } /** - * Cleanu up all secondary slot which couldn't be assigned to any primary slot. + * Cleanup up all secondary slot which couldn't be assigned to any primary slot. * * This function erases content of each secondary slot which contains valid * header but couldn't be assigned to any of supported primary images. @@ -1266,8 +1303,8 @@ static void sec_slot_cleanup_if_unusable(void) { uint8_t idx; - for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { - if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { + for (idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) { + if (SEC_SLOT_TOUCHED == sec_slot_assignment[idx]) { const struct flash_area *secondary_fa; int rc; @@ -1276,17 +1313,20 @@ static void sec_slot_cleanup_if_unusable(void) if (!rc) { rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); if (!rc) { - BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); + BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", idx); } } if (rc) { - BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); + BOOT_LOG_ERR("Failed to clean-up secondary slot of image %d: %d", idx, rc); } } } } #else +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ +} static inline void sec_slot_touch(struct boot_loader_state *state) { } @@ -1318,7 +1358,7 @@ boot_validated_swap_type(struct boot_loader_state *state, owner_nsib[BOOT_CURR_IMG(state)] = false; #endif -#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) +#if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); @@ -1356,31 +1396,31 @@ boot_validated_swap_type(struct boot_loader_state *state, } /* Check start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off) { -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - const struct flash_area *nsib_fa; - - /* NSIB upgrade slot */ - rc = flash_area_open((uint32_t)_image_1_primary_slot_id, - &nsib_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - - /* Image is placed before Primary and within the NSIB slot */ - if (reset_addr > nsib_fa->fa_off - && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { - /* Set primary to be NSIB upgrade slot */ - BOOT_IMG_AREA(state, 0) = nsib_fa; - owner_nsib[BOOT_CURR_IMG(state)] = true; - } +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { #else - return BOOT_SWAP_TYPE_NONE; - + if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { #endif + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + /* This is not the s0/s1 upgrade image but the application image, pretend + * there is no image so the NSIB update can be loaded + */ + return BOOT_SWAP_TYPE_NONE; + } - } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + owner_nsib[BOOT_CURR_IMG(state)] = true; +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + } else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { +#else + } else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { +#endif + /* NSIB upgrade but for the wrong slot, must be erased */ + BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image"); + flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); + sec_slot_untouch(state); + BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", BOOT_CURR_IMG(state)); + return BOOT_SWAP_TYPE_FAIL; + } else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } @@ -1393,7 +1433,7 @@ boot_validated_swap_type(struct boot_loader_state *state, sec_slot_mark_assigned(state); } -#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ +#endif /* PM_S1_ADDRESS || PM_CPUNET_B0N_ADDRESS */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -1925,7 +1965,22 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) flash_area_close(fap); } - swap_run(state, bs, copy_size); +#if defined(PM_S1_ADDRESS) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (owner_nsib[BOOT_CURR_IMG(state)]) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* For NSIB, move the image instead of swapping it */ + nsib_swap_run(state, bs); + +#if defined(CONFIG_REBOOT) + /* Should also reboot at this point so the new S0/S1 update is applied */ + sys_reboot(SYS_REBOOT_COLD); +#endif + } + } else +#endif + { + swap_run(state, bs, copy_size); + } #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT extern int boot_status_fails; @@ -2603,12 +2658,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); -#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - sys_reboot(SYS_REBOOT_COLD); - - } -#endif break; case BOOT_SWAP_TYPE_FAIL: @@ -2682,7 +2731,8 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) * executing MCUBoot image, and is therefore already validated by NSIB and * does not need to also be validated by MCUBoot. */ - bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == + CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER; if (!image_validated_by_nsib) #endif { diff --git a/boot/bootutil/src/swap_nsib.c b/boot/bootutil/src/swap_nsib.c new file mode 100644 index 000000000..39ed4c652 --- /dev/null +++ b/boot/bootutil/src/swap_nsib.c @@ -0,0 +1,70 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil_priv.h" +#include "swap_priv.h" +#include "bootutil/bootutil_log.h" + +#include "mcuboot_config/mcuboot_config.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs) +{ + uint32_t sector_sz; + uint8_t image_index; + const struct flash_area *fap_pri; + const struct flash_area *fap_sec; + int rc; + + BOOT_LOG_INF("Starting swap using nsib algorithm."); + + sector_sz = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0); + +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + rc = flash_area_open(PM_S0_ID, &fap_pri); +#else + rc = flash_area_open(PM_S1_ID, &fap_pri); +#endif + assert (rc == 0); + image_index = BOOT_CURR_IMG(state); + + rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap_sec); + assert (rc == 0); + + rc = boot_erase_region(fap_pri, 0, fap_pri->fa_size); + assert(rc == 0); + + rc = boot_copy_region(state, fap_sec, fap_pri, 0, 0, fap_pri->fa_size); + assert(rc == 0); + + rc = swap_erase_trailer_sectors(state, fap_sec); + assert(rc == 0); + + rc = boot_erase_region(fap_sec, 0, MIN((fap_pri->fa_size + sector_sz), fap_sec->fa_size)); + assert(rc == 0); + + flash_area_close(fap_pri); + flash_area_close(fap_sec); +} diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index 255e74736..f64e8fcf6 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -119,4 +119,12 @@ bool swap_write_block_size_check(struct boot_loader_state *state); */ int app_max_size(struct boot_loader_state *state); +#if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ +(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) +/** + * Performs an NSIB update + */ +void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs); +#endif + #endif /* H_SWAP_PRIV_ */ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 51333a73d..fa9f4c68c 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -138,6 +138,12 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/swap_move.c ${BOOT_DIR}/bootutil/src/caps.c ) + + if(NOT CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER EQUAL "-1" AND NOT CONFIG_BOOT_UPGRADE_ONLY) + zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/swap_nsib.c + ) + endif() endif() if(CONFIG_BOOT_RAM_LOAD OR CONFIG_SINGLE_APPLICATION_SLOT_RAM_LOAD) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index db60ddd03..42f25182e 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -15,48 +15,36 @@ #ifndef CONFIG_SINGLE_APPLICATION_SLOT -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -extern uint32_t _image_1_primary_slot_id[]; -#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ - -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) - -#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - /* Each pair of slots is separated by , and there is no terminating character */ -#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID -#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID -#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID, +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID, +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID, +#define FLASH_AREA_IMAGE_3_SLOTS PM_MCUBOOT_PRIMARY_3_ID, PM_MCUBOOT_SECONDARY_3_ID, + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +#ifdef CONFIG_NCS_IS_VARIANT_IMAGE +#define MCUBOOT_S0_S1_SLOTS PM_S0_ID, PM_MCUBOOT_SECONDARY_ID, +#else +#define MCUBOOT_S0_S1_SLOTS PM_S1_ID, PM_MCUBOOT_SECONDARY_ID, +#endif +#else +#define MCUBOOT_S0_S1_SLOTS +#endif -#if (MCUBOOT_IMAGE_NUMBER == 1) +#if (MCUBOOT_IMAGE_NUMBER == 1) || (MCUBOOT_IMAGE_NUMBER == 2 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) #define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 2) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ +#elif (MCUBOOT_IMAGE_NUMBER == 2) || (MCUBOOT_IMAGE_NUMBER == 3 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ FLASH_AREA_IMAGE_1_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 3) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ - FLASH_AREA_IMAGE_1_SLOTS, \ +#elif (MCUBOOT_IMAGE_NUMBER == 3) || (MCUBOOT_IMAGE_NUMBER == 4 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ + FLASH_AREA_IMAGE_1_SLOTS \ FLASH_AREA_IMAGE_2_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 4) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ + FLASH_AREA_IMAGE_1_SLOTS \ + FLASH_AREA_IMAGE_2_SLOTS \ + FLASH_AREA_IMAGE_3_SLOTS #else #error Unsupported number of images #endif @@ -65,6 +53,7 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) { static const int all_slots[] = { ALL_AVAILABLE_SLOTS + MCUBOOT_S0_S1_SLOTS }; return all_slots[img * 2 + slot]; }; @@ -72,6 +61,8 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #undef FLASH_AREA_IMAGE_0_SLOTS #undef FLASH_AREA_IMAGE_1_SLOTS #undef FLASH_AREA_IMAGE_2_SLOTS +#undef FLASH_AREA_IMAGE_3_SLOTS +#undef MCUBOOT_S0_S1_SLOTS #undef ALL_AVAILABLE_SLOTS #define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) @@ -81,10 +72,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif -#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - #else /* CONFIG_SINGLE_APPLICATION_SLOT */ #define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID From b481eb0b9e27ae2712b1831b7172758b5eb1b628 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 15 Oct 2024 11:31:20 +0100 Subject: [PATCH 213/287] [nrf noup] boot: bootutil: loader: Add s0/s1 checking of MCUboot image Adds a check that will also check the s0/s1 package version of the currently running MCUboot against a MCUboot update image to ensure that an older version of MCUboot isn't loaded to the opposite slot Signed-off-by: Jamie McCrae (cherry picked from commit 63e53ed94680150350e813e74957c5673704aee4) --- boot/bootutil/src/loader.c | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 84dbd625a..6ea929f8d 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -105,6 +105,17 @@ static struct sector_buffer_t sector_buffers; #endif #endif +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 && defined(MCUBOOT_OVERWRITE_ONLY) && \ + defined(MCUBOOT_DOWNGRADE_PREVENTION) +/* s0/s1 package version of the current MCUboot image */ +static const struct image_version mcuboot_s0_s1_image_version = { + .iv_major = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MAJOR, + .iv_minor = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MINOR, + .iv_revision = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_REVISION, + .iv_build_num = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_BUILD_NUMBER, +}; +#endif + #if (BOOT_IMAGE_NUMBER > 1) #define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x)) #else @@ -1056,11 +1067,45 @@ boot_validate_slot(struct boot_loader_state *state, int slot, rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot + * trailer version to prevent downgrades + */ + int version_check; + + version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &mcuboot_s0_s1_image_version); + + /* Only update rc if the currently running version is newer */ + if (version_check < rc) { + rc = version_check; + } + } +#endif } #else rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot + * trailer version to prevent downgrades + */ + int version_check; + + version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &mcuboot_s0_s1_image_version); + + /* Only update rc if the currently running version is newer */ + if (version_check < rc) { + rc = version_check; + } + } +#endif #endif if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); From dd40ff344529fa8d8430523fb0553d9549170a98 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Wed, 23 Oct 2024 16:48:13 +0200 Subject: [PATCH 214/287] [nrf noup] boards: Thingy:91 X release config Update the configuration files for the Thingy:91 X targets to the ones used in production. Signed-off-by: Maximilian Deubel (cherry picked from commit 78211ab58eb6b003416dc85effd2fe515ec5b53a) --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 3 +++ boot/zephyr/boards/thingy91x_nrf9151.conf | 6 +++++- boot/zephyr/boards/thingy91x_nrf9151.overlay | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 boot/zephyr/boards/thingy91x_nrf9151.overlay diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index 37c7e95b1..d3e253b65 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -58,3 +58,6 @@ CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y # Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n + +CONFIG_BOOT_SERIAL_NO_APPLICATION=y +CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 2efe1e170..7c2042de6 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -12,6 +12,10 @@ CONFIG_CONSOLE=n CONFIG_CONSOLE_HANDLER=n CONFIG_UART_CONSOLE=n CONFIG_MCUBOOT_SERIAL=y - CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y + +CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.overlay b/boot/zephyr/boards/thingy91x_nrf9151.overlay new file mode 100644 index 000000000..7f2818c0d --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf9151.overlay @@ -0,0 +1,4 @@ +&uart0 { + status = "okay"; + current-speed = < 1000000 >; +}; From dc0e95d910100e3584a0e733da8757744793e1a4 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Fri, 25 Oct 2024 09:37:44 +0200 Subject: [PATCH 215/287] [nrf noup] workflows: Add a backport workflow Enable backporting of PRs. Signed-off-by: Carles Cufi (cherry picked from commit 7058149cf30a37beb7b0a85bcad9a3cd00b14d1b) --- .github/workflows/backport.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 000000000..e986738ff --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,31 @@ +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + branches: + - main + +jobs: + backport: + name: Backport + runs-on: ubuntu-22.04 + # Only react to merged PRs for security reasons. + # See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target. + if: > + github.event.pull_request.merged && + ( + github.event.action == 'closed' || + ( + github.event.action == 'labeled' && + contains(github.event.label.name, 'backport') + ) + ) + steps: + - name: Backport + uses: zephyrproject-rtos/action-backport@v2.0.3-3 + with: + github_token: ${{ secrets.NCS_GITHUB_TOKEN }} + issue_labels: Backport + labels_template: '["Backport"]' From ba988088164972b78c86e0af0e28b4a027bf74d3 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Thu, 7 Nov 2024 11:09:18 +0100 Subject: [PATCH 216/287] [nrf noup] boot/zephyr: add nrf54l15dk ext flash configs Moved configs from nrf54l15pdk. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit bd64752dfd68275f2927e46471f2ef0315ffe53a) --- .../nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 15 ++++++ ...f54l15dk_nrf54l15_cpuapp_ext_flash.overlay | 47 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf new file mode 100644 index 000000000..8fc12e074 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -0,0 +1,15 @@ +CONFIG_MULTITHREADING=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_FLASH=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 +CONFIG_MAIN_STACK_SIZE=20480 +CONFIG_BOOT_MAX_IMG_SECTORS=512 +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +# Ensure that the qspi driver is disabled by default +CONFIG_NORDIC_QSPI_NOR=n + +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + +CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay new file mode 100644 index 000000000..60ee6fe51 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay @@ -0,0 +1,47 @@ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + zephyr,code-partition = &boot_partition; + }; +}; + +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; + +/delete-node/ &slot0_ns_partition; +/delete-node/ &slot1_ns_partition; + +/delete-node/ &storage_partition; + +&cpuapp_rram { + reg = < 0x0 DT_SIZE_K(1524) >; + partitions { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x000000000 0x00014000>; + }; + slot0_partition: partition@14000 { + label = "image-0"; + reg = <0x000014000 0x0015A000>; + }; + storage_partition: partition@16E000 { + label = "storage"; + reg = < 0x16E000 0x9000 >; + }; + }; +}; + +&mx25r64 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot1_partition: partition@0 { + label = "image-1"; + reg = <0x000000000 0x0015A000>; + }; + }; +}; From f3c2fbc9234ab08f9f5fdd2f075397a4b3e1d00c Mon Sep 17 00:00:00 2001 From: Maciej Baczmanski Date: Thu, 28 Nov 2024 11:13:23 +0100 Subject: [PATCH 217/287] [nrf noup] Fix logging for ED25519_psa Log module has been declared but never registered. This commit fixes that by just registering the module. Signed-off-by: Maciej Baczmanski Co-authored-by: Marek Pieta (cherry picked from commit c8829648a3617e988a52a56b1d56b83c67438c38) --- boot/bootutil/src/ed25519_psa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 3d7274307..e84b71d2a 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -13,7 +13,7 @@ #include #include -BOOT_LOG_MODULE_DECLARE(ed25519_psa); +BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define SHA512_DIGEST_LENGTH 64 #define EDDSA_KEY_LENGTH 32 From 9644dc258228d71e7eff85025e9d67dbc56df789 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 24 Jul 2024 17:00:04 +0000 Subject: [PATCH 218/287] [nrf noup] PSA configuration required changes Set of changes to Kconfig, CMakeLists.txt and some of headers that are required for the PSA support to compile. Signed-off-by: Dominik Ermel (cherry picked from commit 00f35bb1a4e0dd9f29cf9056674c28f72202fa4a) --- boot/bootutil/zephyr/CMakeLists.txt | 14 +++-- boot/zephyr/CMakeLists.txt | 39 ++++++++---- boot/zephyr/Kconfig | 73 ++++++++++++++++++++++- boot/zephyr/include/mcuboot-mbedtls-cfg.h | 2 +- 4 files changed, 112 insertions(+), 16 deletions(-) diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index 72a6a8638..d5364d025 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -29,12 +29,18 @@ zephyr_library_link_libraries(MCUBOOT_BOOTUTIL) target_link_libraries(MCUBOOT_BOOTUTIL INTERFACE zephyr_interface) if(CONFIG_BOOT_USE_TINYCRYPT) -target_include_directories(MCUBOOT_BOOTUTIL INTERFACE - ../../../ext/tinycrypt/lib/include -) + target_include_directories(MCUBOOT_BOOTUTIL INTERFACE + ../../../ext/tinycrypt/lib/include + ) +endif() + +if(CONFIG_BOOT_USE_PSA_CRYPTO) + target_include_directories(MCUBOOT_BOOTUTIL INTERFACE + ${ZEPHYR_MBEDTLS_MODULE_DIR}/include + ) endif() -if(CONFIG_BOOT_USE_MBEDTLS) +if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO AND NOT CONFIG_PSA_CORE_OBERON) zephyr_link_libraries(mbedTLS) endif() endif() diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index fa9f4c68c..c5d712e74 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -47,6 +47,12 @@ zephyr_library_include_directories( include ) +if(DEFINED CONFIG_MBEDTLS) + zephyr_library_include_directories( + ${ZEPHYR_MBEDTLS_MODULE_DIR}/include + ) +endif() + # Zephyr port-specific sources. zephyr_library_sources( main.c @@ -98,6 +104,10 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/fault_injection_hardening.c ) +if(DEFINED CONFIG_BOOT_ENCRYPT_X25519 AND DEFINED CONFIG_BOOT_ED25519_PSA) + zephyr_library_sources(${BOOT_DIR}/bootutil/src/encrypted_psa.c) +endif() + if(DEFINED CONFIG_MEASURED_BOOT OR DEFINED CONFIG_BOOT_SHARE_DATA) zephyr_library_sources( ${BOOT_DIR}/bootutil/src/boot_record.c @@ -238,19 +248,28 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) ${FIAT_DIR}/include/ ) - zephyr_library_sources( - ${FIAT_DIR}/src/curve25519.c - ) + if(NOT CONFIG_BOOT_ED25519_PSA) + zephyr_library_sources( + ${FIAT_DIR}/src/curve25519.c + ) + else() + zephyr_library_sources( + ${MBEDTLS_ASN1_DIR}/src/asn1parse.c + ${BOOT_DIR}/bootutil/src/ed25519_psa.c + ) + endif() endif() -if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) - zephyr_library_sources( - ${TINYCRYPT_DIR}/source/aes_encrypt.c - ${TINYCRYPT_DIR}/source/aes_decrypt.c - ${TINYCRYPT_DIR}/source/ctr_mode.c - ${TINYCRYPT_DIR}/source/hmac.c - ${TINYCRYPT_DIR}/source/ecc_dh.c +if(NOT CONFIG_BOOT_ED25519_PSA) + if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) + zephyr_library_sources( + ${TINYCRYPT_DIR}/source/aes_encrypt.c + ${TINYCRYPT_DIR}/source/aes_decrypt.c + ${TINYCRYPT_DIR}/source/ctr_mode.c + ${TINYCRYPT_DIR}/source/hmac.c + ${TINYCRYPT_DIR}/source/ecc_dh.c ) + endif() endif() if(CONFIG_BOOT_ENCRYPT_EC256) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index f7d1eb77e..66aec4c8a 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -29,7 +29,10 @@ config BOOT_USE_MBEDTLS config BOOT_USE_PSA_CRYPTO bool - # Hidden option + default y if NRF_SECURITY + # This is counter intuitive but that is how PSA heap is enabled. + select MBEDTLS_ENABLE_HEAP + select MBEDTLS_PSA_CRYPTO_C help Hidden option set if using PSA crypt for cryptography functionality @@ -66,6 +69,58 @@ config NRF_CC310_BL bool default n +if BOOT_USE_PSA_CRYPTO + +config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES + bool + default y if BOOT_IMG_HASH_ALG_SHA256 + select PSA_WANT_ALG_SHA_256 + help + Dependencies for hashing with SHA256 + +config BOOT_ED25519_PSA_DEPENDENCIES + bool + select PSA_WANT_ALG_SHA_256 + select PSA_WANT_ALG_SHA_512 + select PSA_WANT_ALG_PURE_EDDSA + select PSA_WANT_ECC_TWISTED_EDWARDS_255 + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + help + Dependencies for ed25519 signature + +if BOOT_ENCRYPT_IMAGE + +config BOOT_X25519_PSA_DEPENDENCIES + bool + select PSA_WANT_ALG_ECDH + select PSA_WANT_ALG_HMAC + select PSA_WANT_ALG_HKDF + select PSA_WANT_ALG_CTR + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + select PSA_WANT_KEY_TYPE_DERIVE + select PSA_WANT_KEY_TYPE_AES + select PSA_WANT_ECC_MONTGOMERY_255 + help + Dependencies for x25519 shared-random key encryption and AES + encryption. The PSA_WANT_ALG_CTR and PSA_WANT_KEY_TYPE_AES + enable Counter based block cipher and AES key, and algorithm support, + to use with it; the others are used for shared key decryption + and derivation. + +endif # BOOT_ENCRYPT_IMAGE + +if MBEDTLS_ENABLE_HEAP + +config MBEDTLS_HEAP_SIZE + default 2048 if BOOT_USE_PSA_CRYPTO + help + The PSA internals need to be able to allocate memory for operation + and it uses mbedTLS heap for that. + +endif # MBEDTLS_ENABLE_HEAP + +endif # BOOT_USE_PSA_CRYPTO + menu "MCUBoot settings" config SINGLE_APPLICATION_SLOT @@ -123,6 +178,7 @@ endchoice # BOOT_IMG_HASH_ALG choice BOOT_SIGNATURE_TYPE prompt "Signature type" + default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP default BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_NONE @@ -177,13 +233,24 @@ if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" default BOOT_ED25519_TINYCRYPT + config BOOT_ED25519_TINYCRYPT bool "Use tinycrypt" select BOOT_USE_TINYCRYPT + depends on !NRF_SECURITY + config BOOT_ED25519_MBEDTLS bool "Use mbedTLS" select BOOT_USE_MBEDTLS select MBEDTLS + depends on !NRF_SECURITY + +config BOOT_ED25519_PSA + bool "Use PSA crypto" + select BOOT_USE_PSA_CRYPTO + select BOOT_ED25519_PSA_DEPENDENCIES + select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE + endchoice endif @@ -228,9 +295,13 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +if MBEDTLS + config MBEDTLS_CFG_FILE default "mcuboot-mbedtls-cfg.h" +endif + config BOOT_HW_KEY bool "Use HW key for image verification" default n diff --git a/boot/zephyr/include/mcuboot-mbedtls-cfg.h b/boot/zephyr/include/mcuboot-mbedtls-cfg.h index 2bab537d7..a46fbb09f 100644 --- a/boot/zephyr/include/mcuboot-mbedtls-cfg.h +++ b/boot/zephyr/include/mcuboot-mbedtls-cfg.h @@ -23,7 +23,7 @@ #if defined(CONFIG_BOOT_SIGNATURE_TYPE_RSA) || defined(CONFIG_BOOT_ENCRYPT_RSA) #include "config-rsa.h" -#elif defined(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256) || \ +#elif defined(CONFIG_BOOT_USE_PSA_CRYPTO) || defined(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256) || \ defined(CONFIG_BOOT_ENCRYPT_EC256) || \ (defined(CONFIG_BOOT_ENCRYPT_X25519) && !defined(CONFIG_BOOT_SIGNATURE_TYPE_ED25519)) #include "config-asn1.h" From 4e2273f992401997fc9a08868a0f4c4e3fac682e Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 2 Aug 2024 15:55:13 +0000 Subject: [PATCH 219/287] [nrf noup] bootutil: Provide support for SHA512 with ED25519 Use SHA512 directly calculated over image with the ED25519 signature. Signed-off-by: Dominik Ermel (cherry picked from commit 5a6676cf392232b671cabb7dbf242d01f2ec5d6b) --- boot/zephyr/Kconfig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 66aec4c8a..5715c7ea5 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -80,7 +80,7 @@ config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES config BOOT_ED25519_PSA_DEPENDENCIES bool - select PSA_WANT_ALG_SHA_256 + select PSA_WANT_ALG_SHA_256 if BOOT_IMG_HASH_ALG_SHA256 select PSA_WANT_ALG_SHA_512 select PSA_WANT_ALG_PURE_EDDSA select PSA_WANT_ECC_TWISTED_EDWARDS_255 @@ -228,6 +228,11 @@ config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" select BOOT_ENCRYPTION_SUPPORT select BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_IMG_HASH_ALG_SHA512_ALLOW if BOOT_USE_PSA_CRYPTO + help + This is ed25519 signature calculated over SHA512 of SHA256 of application + image; that is not completely correct approach as the SHA512 should be + rather directly calculated over an image. if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION From 32a7c77d13f25c2832b4b3ebaf774c2299be5818 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 5 Sep 2024 10:53:17 +0000 Subject: [PATCH 220/287] [nrf noup] bootutil: Enable hash calculation directly on storage The commit add support for passing storage device address space to hash calculation functions, which allows to use hardware accelerated hash calculation on storage. This feature only works when image encryption is not enabled and all slots are defined within internal storage of device. The feature is enabled using Kconfig option CONFIG_BOOT_IMG_HASH_DIRECTLY_ON_STORAGE Signed-off-by: Dominik Ermel (cherry picked from commit b2ad117bd7cb645731625bf5ca574abf788110e2) --- boot/bootutil/src/image_validate.c | 15 ++++++++++++--- boot/zephyr/Kconfig | 16 ++++++++++++++++ .../include/mcuboot_config/mcuboot_config.h | 7 +++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index b1a50f126..fa1d373d7 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -77,13 +77,15 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, uint8_t *seed, int seed_len) { bootutil_sha_context sha_ctx; - uint32_t blk_sz; uint32_t size; uint16_t hdr_size; - uint32_t off; - int rc; uint32_t blk_off; uint32_t tlv_off; +#if !defined(MCUBOOT_HASH_STORAGE_DIRECTLY) + int rc; + uint32_t off; + uint32_t blk_sz; +#endif #if (BOOT_IMAGE_NUMBER == 1) || !defined(MCUBOOT_ENC_IMAGES) || \ defined(MCUBOOT_RAM_LOAD) @@ -126,6 +128,12 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, /* If protected TLVs are present they are also hashed. */ size += hdr->ih_protect_tlv_size; +#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY + /* No chunk loading, storage is mapped to address space and can + * be directly given to hashing function. + */ + bootutil_sha_update(&sha_ctx, (void *)flash_area_get_off(fap), size); +#else /* MCUBOOT_HASH_STORAGE_DIRECTLY */ #ifdef MCUBOOT_RAM_LOAD bootutil_sha_update(&sha_ctx, (void*)(IMAGE_RAM_BASE + hdr->ih_load_addr), @@ -170,6 +178,7 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, bootutil_sha_update(&sha_ctx, tmp_buf, blk_sz); } #endif /* MCUBOOT_RAM_LOAD */ +#endif /* MCUBOOT_HASH_STORAGE_DIRECTLY */ bootutil_sha_finish(&sha_ctx, hash_result); bootutil_sha_drop(&sha_ctx); diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 5715c7ea5..e4943edc1 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -146,6 +146,22 @@ config BOOT_IMG_HASH_ALG_SHA512_ALLOW help Hidden option set by configurations that allow SHA512 +config BOOT_IMG_HASH_DIRECTLY_ON_STORAGE + bool "Hash calculation functions access storage through address space" + depends on !BOOT_ENCRYPT_IMAGE + help + When possible to map storage device, at least for read operations, + to address space or RAM area, enabling this option allows hash + calculation functions to directly access the storage through that address + space or using its own DMA. This reduces flash read overhead done + by the MCUboot. + Notes: + - not supported when encrypted images are in use, because calculating + SHA requires image to be decrypted first, which is done to RAM. + - currently only supported on internal storage of devices; this + option will not work with devices that use external storage for + either of image slots. + choice BOOT_IMG_HASH_ALG prompt "Selected image hash algorithm" default BOOT_IMG_HASH_ALG_SHA256 if BOOT_IMG_HASH_ALG_SHA256_ALLOW diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index ae17f85ff..d72770d99 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -148,6 +148,13 @@ #define MCUBOOT_DECOMPRESS_IMAGES #endif +/* Invoke hashing functions directly on storage. This requires for device + * to be able to map storage to address space or RAM. + */ +#ifdef CONFIG_BOOT_IMG_HASH_DIRECTLY_ON_STORAGE +#define MCUBOOT_HASH_STORAGE_DIRECTLY +#endif + #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From a43e5f460b230ae696454eb4b189d1c1139c73a6 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 6 Sep 2024 16:16:28 +0000 Subject: [PATCH 221/287] [nrf noup] bootutil: PureEdDSA using ED25519 The commit adds support for PureEdDSA, which validates signature of image rather than hash. This is most secure, available, ED25519 usage in MCUboot, but due to requirement of PureEdDSA to be able to calculate signature at whole message at once, here image, it only works on setups where entire image can be mapped to device address space, so that PSA functions calculating the signature can see the whole image at once. This option is enabled with Kconfig option: CONFIG_BOOT_SIGNATURE_TYPE_PURE when the ED25519 signature type is already selected. Note that the option will enable SHA512 for calculating public key hash. Signed-off-by: Dominik Ermel (cherry picked from commit 1a2f5f68aad108cb79d91779e82c8f9ea1d1f594) --- boot/bootutil/src/bootutil_priv.h | 3 + boot/bootutil/src/image_ed25519.c | 37 ++++++++ boot/bootutil/src/image_validate.c | 95 +++++++++++++++++-- boot/zephyr/Kconfig | 29 +++++- .../include/mcuboot_config/mcuboot_config.h | 4 + 5 files changed, 160 insertions(+), 8 deletions(-) diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index 345933a5f..5592f1a87 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -270,6 +270,9 @@ struct boot_loader_state { fih_ret bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t key_id); +fih_ret bootutil_verify_img(const uint8_t *img, uint32_t size, + uint8_t *sig, size_t slen, uint8_t key_id); + fih_ret boot_fih_memequal(const void *s1, const void *s2, size_t n); int boot_find_status(int image_index, const struct flash_area **fap); diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 447289253..40d494bcf 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -109,4 +109,41 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, FIH_RET(fih_rc); } +fih_ret +bootutil_verify_img(const uint8_t *img, uint32_t size, + uint8_t *sig, size_t slen, uint8_t key_id) +{ + int rc; + FIH_DECLARE(fih_rc, FIH_FAILURE); + uint8_t *pubkey; + uint8_t *end; + + if (slen != EDDSA_SIGNATURE_LENGTH) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + pubkey = (uint8_t *)bootutil_keys[key_id].key; + end = pubkey + *bootutil_keys[key_id].len; + + rc = bootutil_import_key(&pubkey, end); + if (rc) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + rc = ED25519_verify(img, size, sig, pubkey); + + if (rc == 0) { + /* if verify returns 0, there was an error. */ + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + FIH_SET(fih_rc, FIH_SUCCESS); +out: + + FIH_RET(fih_rc); +} + #endif /* MCUBOOT_SIGN_ED25519 */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index fa1d373d7..c419b9497 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -65,6 +65,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil_priv.h" +#ifndef MCUBOOT_SIGN_PURE /* * Compute SHA hash over the image. * (SHA384 if ECDSA-P384 is being used, @@ -184,6 +185,7 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, return 0; } +#endif /* * Currently, we only support being able to verify one type of @@ -370,6 +372,43 @@ bootutil_get_img_security_cnt(struct image_header *hdr, return 0; } +#if defined(MCUBOOT_SIGN_PURE) +/* Returns: + * 0 -- found + * 1 -- not found or found but not true + * -1 -- failed for some reason + * + * Value of TLV does not matter, presence decides. + */ +static int bootutil_check_for_pure(const struct image_header *hdr, + const struct flash_area *fap) +{ + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_SIG_PURE, false); + if (rc) { + return rc; + } + + /* Search for the TLV */ + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + if (rc == 0 && len == 1) { + bool val; + + rc = LOAD_IMAGE_DATA(hdr, fap, off, &val, 1); + if (rc == 0) { + rc = !val; + } + } + + return rc; +} +#endif + + #ifndef ALLOW_ROGUE_TLVS /* * The following list of TLVs are the only entries allowed in the unprotected @@ -386,6 +425,9 @@ static const uint16_t allowed_unprot_tlvs[] = { IMAGE_TLV_ECDSA_SIG, IMAGE_TLV_RSA3072_PSS, IMAGE_TLV_ED25519, +#if defined(MCUBOOT_SIGN_PURE) + IMAGE_TLV_SIG_PURE, +#endif IMAGE_TLV_ENC_RSA2048, IMAGE_TLV_ENC_KW, IMAGE_TLV_ENC_EC256, @@ -408,7 +450,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, uint32_t off; uint16_t len; uint16_t type; - int image_hash_valid = 0; #ifdef EXPECTED_SIG_TLV FIH_DECLARE(valid_signature, FIH_FAILURE); #ifndef MCUBOOT_BUILTIN_KEY @@ -425,7 +466,10 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, #endif /* EXPECTED_SIG_TLV */ struct image_tlv_iter it; uint8_t buf[SIG_BUF_SIZE]; +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) + int image_hash_valid = 0; uint8_t hash[IMAGE_HASH_SIZE]; +#endif int rc = 0; FIH_DECLARE(fih_rc, FIH_FAILURE); #ifdef MCUBOOT_HW_ROLLBACK_PROT @@ -496,6 +540,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #endif +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); if (rc) { @@ -505,6 +550,15 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (out_hash) { memcpy(out_hash, hash, IMAGE_HASH_SIZE); } +#endif + +#if defined(MCUBOOT_SIGN_PURE) + /* If Pure type signature is expected then it has to be there */ + rc = bootutil_check_for_pure(hdr, fap); + if (rc != 0) { + goto out; + } +#endif rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); if (rc) { @@ -548,8 +602,10 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } } #endif - - if (type == EXPECTED_HASH_TLV) { + switch(type) { +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) + case EXPECTED_HASH_TLV: + { /* Verify the image hash. This must always be present. */ if (len != sizeof(hash)) { rc = -1; @@ -567,8 +623,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } image_hash_valid = 1; + break; + } +#endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ #ifdef EXPECTED_KEY_TLV - } else if (type == EXPECTED_KEY_TLV) { + case EXPECTED_KEY_TLV: + { /* * Determine which key we should be checking. */ @@ -593,9 +653,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, * The key may not be found, which is acceptable. There * can be multiple signatures, each preceded by a key. */ + break; + } #endif /* EXPECTED_KEY_TLV */ #ifdef EXPECTED_SIG_TLV - } else if (type == EXPECTED_SIG_TLV) { + case EXPECTED_SIG_TLV: + { /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; @@ -609,12 +672,25 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (rc) { goto out; } +#ifndef MCUBOOT_SIGN_PURE FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), buf, len, key_id); +#else + /* Directly check signature on the image, by using the mapping of + * a device to memory. The pointer is beginning of image in flash, + * so offset of area, the range is header + image + protected tlvs. + */ + FIH_CALL(bootutil_verify_img, valid_signature, (void *)flash_area_get_off(fap), + hdr->ih_hdr_size + hdr->ih_img_size + hdr->ih_protect_tlv_size, + buf, len, key_id); +#endif key_id = -1; + break; + } #endif /* EXPECTED_SIG_TLV */ #ifdef MCUBOOT_HW_ROLLBACK_PROT - } else if (type == IMAGE_TLV_SEC_CNT) { + case IMAGE_TLV_SEC_CNT: + { /* * Verify the image's security counter. * This must always be present. @@ -649,14 +725,21 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, /* The image's security counter has been successfully verified. */ security_counter_valid = fih_rc; + break; + } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ } } +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = !image_hash_valid; if (rc) { goto out; } +#elif defined(MCUBOOT_SIGN_PURE) + /* This returns true on EQ, rc is err on non-0 */ + rc = FIH_NOT_EQ(valid_signature, FIH_SUCCESS); +#endif #ifdef EXPECTED_SIG_TLV FIH_SET(fih_rc, valid_signature); #endif diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index e4943edc1..8d0f0ff0f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -192,6 +192,14 @@ config BOOT_IMG_HASH_ALG_SHA512 endchoice # BOOT_IMG_HASH_ALG +config BOOT_SIGNATURE_TYPE_PURE_ALLOW + bool + help + Hidden option set by configurations that allow Pure variant, + for example ed25519. The pure variant means that image + signature is calculated over entire image instead of hash + of an image. + choice BOOT_SIGNATURE_TYPE prompt "Signature type" default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP @@ -242,15 +250,32 @@ endif config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" - select BOOT_ENCRYPTION_SUPPORT - select BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_ENCRYPTION_SUPPORT if !BOOT_SIGNATURE_TYPE_PURE + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !BOOT_SIGNATURE_TYPE_PURE + # The SHA is used only for key hashing, not for images. select BOOT_IMG_HASH_ALG_SHA512_ALLOW if BOOT_USE_PSA_CRYPTO + select BOOT_SIGNATURE_TYPE_PURE_ALLOW help This is ed25519 signature calculated over SHA512 of SHA256 of application image; that is not completely correct approach as the SHA512 should be rather directly calculated over an image. + Select BOOT_SIGNATURE_TYPE_PURE to have a PureEdDSA calculating image + signature directly on image, rather than hash of the image. if BOOT_SIGNATURE_TYPE_ED25519 + +config BOOT_SIGNATURE_TYPE_PURE + bool "Use Pure signature of image" + depends on BOOT_SIGNATURE_TYPE_PURE_ALLOW + help + The Pure signature is calculated directly over image rather than + hash of an image. + This is more secure signature, specifically if hardware can do the + verification without need to share key. + Note that this requires that all slots for which signature is to be + verified need to be accessible through memory address space that + cryptography can access. + choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" default BOOT_ED25519_TINYCRYPT diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index d72770d99..9485f7d96 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -155,6 +155,10 @@ #define MCUBOOT_HASH_STORAGE_DIRECTLY #endif +#ifdef CONFIG_BOOT_SIGNATURE_TYPE_PURE +#define MCUBOOT_SIGN_PURE +#endif + #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From d6a16f86aa8b344ccc8ba25820338f7ebb0517a3 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 19 Sep 2024 14:32:37 +0200 Subject: [PATCH 222/287] [nrf noup] boot/zephyr/Kconfig: conditionally disable BOOT_MAX_IMG_SECTORS_AUTO Automatic calculation are based on DTS data which are no the right source on partition layout in case Partition manager does the partitioning. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Dominik Ermel (cherry picked from commit d09c5a0cdcc4e4a115d1a77f961a031598a93b5c) --- boot/zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 8d0f0ff0f..327edbbe0 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -571,7 +571,7 @@ config BOOT_ENCRYPTION_KEY_FILE config BOOT_MAX_IMG_SECTORS_AUTO bool "Calculate maximum sectors automatically" - default y + default y if !PARTITION_MANAGER_ENABLED help If this option is enabled then the maximum number of supported sectors per image will be calculated automatically from the flash erase sizes and size of each partition for From b647a94a24b1a20b3cbbde41ff9a4a92be67a232 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 20 Sep 2024 16:34:00 +0000 Subject: [PATCH 223/287] [nrf noup] bootutil: Add support for KMU stored ED25519 signature key The commit adds verification of image using keys stored in KMU. Signed-off-by: Dominik Ermel (cherry picked from commit 6e0c2b8794daa33d7688b35fc4af04c4d8052d41) --- boot/bootutil/src/ed25519_psa.c | 51 ++++++++++++++++++++++++++++++ boot/bootutil/src/image_ed25519.c | 19 ++++++++--- boot/bootutil/src/image_validate.c | 6 ++++ boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 29 ++++++++++++++++- 5 files changed, 101 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index e84b71d2a..83fc692a1 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,6 +12,9 @@ #include #include +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#include +#endif BOOT_LOG_MODULE_REGISTER(ed25519_psa); @@ -19,6 +22,18 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define EDDSA_KEY_LENGTH 32 #define EDDSA_SIGNAGURE_LENGTH 64 +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +/* List of KMU stored key ids available for MCUboot */ +#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) +static psa_key_id_t kmu_key_ids[3] = { + MAKE_PSA_KMU_KEY_ID(226), + MAKE_PSA_KMU_KEY_ID(228), + MAKE_PSA_KMU_KEY_ID(230) +}; +#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) +#endif + +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -69,3 +84,39 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } +#else +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], + const uint8_t public_key[EDDSA_KEY_LENGTH]) +{ + ARG_UNUSED(public_key); + /* Set to any error */ + psa_status_t status = PSA_ERROR_BAD_STATE; + int ret = 0; /* Fail by default */ + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", status); + return 0; + } + + status = PSA_ERROR_BAD_STATE; + + for (int i = 0; i < KMU_KEY_COUNT; ++i) { + psa_key_id_t kid = kmu_key_ids[i]; + + status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, + message_len, signature, + EDDSA_SIGNAGURE_LENGTH); + if (status == PSA_SUCCESS) { + ret = 1; + break; + } + + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + } + + return ret; +} +#endif diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 40d494bcf..e6c792a99 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -25,14 +25,16 @@ #include "bootutil/crypto/sha.h" #define EDDSA_SIGNATURE_LENGTH 64 - -static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; #define NUM_ED25519_BYTES 32 extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) + +static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; + /* * Parse the public key used for signing. */ @@ -71,6 +73,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } +#endif fih_ret bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, @@ -78,14 +81,17 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey; + uint8_t *pubkey = NULL; +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) uint8_t *end; +#endif if (hlen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -94,6 +100,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, FIH_SET(fih_rc, FIH_FAILURE); goto out; } +#endif rc = ED25519_verify(hash, IMAGE_HASH_SIZE, sig, pubkey); @@ -115,14 +122,17 @@ bootutil_verify_img(const uint8_t *img, uint32_t size, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey; + uint8_t *pubkey = NULL; +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) uint8_t *end; +#endif if (slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -131,6 +141,7 @@ bootutil_verify_img(const uint8_t *img, uint32_t size, FIH_SET(fih_rc, FIH_FAILURE); goto out; } +#endif rc = ED25519_verify(img, size, sig, pubkey); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index c419b9497..f71d1d9a6 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -245,6 +245,7 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_HW_KEY) static int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) @@ -310,6 +311,7 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) } #endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ /** @@ -626,6 +628,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, break; } #endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { @@ -656,14 +659,17 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, break; } #endif /* EXPECTED_KEY_TLV */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index c5d712e74..596e698b3 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -305,7 +305,7 @@ if(CONFIG_MCUBOOT_SERIAL) endif() endif() -if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") +if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU AND NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") # CONF_FILE points to the KConfig configuration files of the bootloader. foreach (filepath ${CONF_FILE}) file(READ ${filepath} temp_text) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 327edbbe0..7891b54a3 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -293,6 +293,7 @@ config BOOT_ED25519_MBEDTLS config BOOT_ED25519_PSA bool "Use PSA crypto" + depends on NRF_SECURITY select BOOT_USE_PSA_CRYPTO select BOOT_ED25519_PSA_DEPENDENCIES select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE @@ -302,6 +303,22 @@ endif endchoice +config BOOT_SIGNATURE_USING_KMU + bool "Use KMU stored keys for signature verification" + depends on NRF_SECURITY + depends on CRACEN_LIB_KMU + select PSA_WANT_ALG_GCM + select PSA_WANT_KEY_TYPE_AES + select PSA_WANT_AES_KEY_SIZE_256 + select PSA_WANT_ALG_SP800_108_COUNTER_CMAC + select PSA_WANT_ALG_CMAC + select PSA_WANT_ALG_ECB_NO_PADDING + help + MCUboot will use keys provisioned to the device key management unit for signature + verification instead of compiling in key data from a file. + +if !BOOT_SIGNATURE_USING_KMU + config BOOT_SIGNATURE_KEY_FILE string "PEM key file" default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 @@ -319,6 +336,8 @@ config BOOT_SIGNATURE_KEY_FILE with the public key information will be written in a format expected by MCUboot. +endif + config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" depends on CPU_CORTEX_M @@ -341,10 +360,18 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +# Disable MBEDTLS from being selected if NRF_SECURITY is enabled, and use default NRF_SECURITY +# configuration file for MBEDTLS +config MBEDTLS + depends on !NRF_SECURITY + +config NRF_SECURITY + select MBEDTLS_PROMPTLESS + if MBEDTLS config MBEDTLS_CFG_FILE - default "mcuboot-mbedtls-cfg.h" + default "mcuboot-mbedtls-cfg.h" if !NRF_SECURITY endif From 4ceb4773b31dd8d56dfcb6e0461a70bb161ca95f Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Nov 2024 10:53:06 +0000 Subject: [PATCH 224/287] [nrf noup] boot: zephyr: Add experimental selection to compression Adds selecting the experimental Kconfig when compession is in use Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit ff3c31fba7e8eb659d8505e9c635057a2ca53987) --- boot/zephyr/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 7891b54a3..8c5de8f42 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -969,9 +969,10 @@ config BOOT_DECOMPRESSION_SUPPORT if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION - bool "Decompression" + bool "Decompression [EXPERIMENTAL]" select NRF_COMPRESS_CLEANUP select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP + select EXPERIMENTAL help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to From 2ca0efedf8d331028455f05d77f1c3c5064b773b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 2 Dec 2024 10:51:41 +0000 Subject: [PATCH 225/287] [nrf noup] boot: bootutil: Allow configuring number of KMU keys Adds a new Kconfig CONFIG_BOOT_SIGNATURE_KMU_SLOTS which allows specifying how many KMU key IDs are supported, the default is set to 1 instead of 3 which was set before NCSDK-30743 Signed-off-by: Jamie McCrae (cherry picked from commit 12e5ee106034972b0f1074d6f2261b2b39d1501b) --- boot/bootutil/src/ed25519_psa.c | 9 ++++++--- boot/zephyr/Kconfig | 12 ++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 83fc692a1..3042eeabf 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Nordic Semiconductor ASA + * Copyright (c) 2020-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ @@ -12,6 +12,7 @@ #include #include +#include #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #include #endif @@ -30,7 +31,9 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; -#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) + +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), + "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) @@ -103,7 +106,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < KMU_KEY_COUNT; ++i) { + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 8c5de8f42..7b2576b9f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -317,6 +317,18 @@ config BOOT_SIGNATURE_USING_KMU MCUboot will use keys provisioned to the device key management unit for signature verification instead of compiling in key data from a file. +if BOOT_SIGNATURE_USING_KMU + +config BOOT_SIGNATURE_KMU_SLOTS + int "KMU key slots" + range 1 3 + default 1 + help + Selects the number of KMU key slots (also known as generations) to use when verifying + an image. + +endif + if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 97e8acfb8db54b23de41130732ab6f95c3053d15 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 10 Dec 2024 08:16:22 +0000 Subject: [PATCH 226/287] [nrf noup] boot: bootutil: image_validate: Add KMU support to compression fixup! [nrf noup] bootutil: Add support for KMU stored ED25519 signature key This adds the additional code required so that the compression feature can be used with keys that reside in the KMU Signed-off-by: Jamie McCrae (cherry picked from commit 03434241388ea62363ffcb6cf332b4fa7b88626b) --- boot/bootutil/src/image_validate.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index f71d1d9a6..64983b318 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -815,7 +815,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #ifdef EXPECTED_SIG_TLV -#ifdef EXPECTED_KEY_TLV +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && defined(EXPECTED_KEY_TLV) rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); if (rc) { goto out; @@ -861,7 +861,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, */ } } -#endif /* EXPECTED_KEY_TLV */ +#endif /* !CONFIG_BOOT_SIGNATURE_USING_KMU && EXPECTED_KEY_TLV */ rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); if (rc) { @@ -884,10 +884,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; From 2341b2977b2fbf78c94a01cd0e2b8c4760b60697 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 9 Dec 2024 12:27:38 +0000 Subject: [PATCH 227/287] [nrf noup] boot: zephyr: serial_recovery: Add nRF5340 Kconfig override Adds additional conditions that lets the direct upload option to be selected on nRF5340 to allow for uploading network core updates directly to the network core with the flash simulator Signed-off-by: Jamie McCrae (cherry picked from commit b82206c15fff357c151c24bf97c99c4348d14a46) --- boot/zephyr/Kconfig.serial_recovery | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index 72be5ccfb..f5ee8945b 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -47,9 +47,14 @@ config BOOT_SERIAL_CDC_ACM endchoice +DT_COMPAT_SIM_FLASH:= zephyr,sim-flash +DT_SIM_FLASH_PATH := $(dt_nodelabel_path,flash_sim0) + config MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD bool "Allow to select image number for DFU" - depends on !SINGLE_APPLICATION_SLOT + # Allow this option to be selected in cases where support for direct uploading to nRF5340 + # network core should be supported + depends on !SINGLE_APPLICATION_SLOT || (SINGLE_APPLICATION_SLOT && SOC_NRF5340_CPUAPP && BOOT_IMAGE_ACCESS_HOOK_NRF5340 && FLASH_SIMULATOR && $(dt_compat_enabled,$(DT_COMPAT_SIM_FLASH))) help With the option enabled, the mcuboot serial recovery will respect the "image" field in mcumgr image update frame From 1068cb1b4fb46014baf4fa9b3aeb288294bb5984 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 17 Dec 2024 15:54:01 +0100 Subject: [PATCH 228/287] [nrf noup] boot/zephyr/boards: configure fastest RRAM operations Configured CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 Which ensure the fastest bulk RRAM write operations. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 0a910b600a3ddeffd941fa59359e373a29d63bf3) --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf index 8fc12e074..12650a9ed 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -13,3 +13,6 @@ CONFIG_NORDIC_QSPI_NOR=n CONFIG_FPROTECT=n CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 From 81be16e08923ce2adc72a53f6cf749d3bfca3ebf Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 5 Dec 2024 10:20:19 +0000 Subject: [PATCH 229/287] [nrf noup] boot: Remove child/parent references Removes stray child/parent references Signed-off-by: Jamie McCrae (cherry picked from commit 99d4ae97314c413208746f1fb272eb4ecf85b3ea) --- boot/bootutil/src/swap_priv.h | 2 +- boot/zephyr/pm.yml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index f64e8fcf6..cc72b7653 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -120,7 +120,7 @@ bool swap_write_block_size_check(struct boot_loader_state *state); int app_max_size(struct boot_loader_state *state); #if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ -(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) +CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 /** * Performs an NSIB update */ diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index 13ffc44aa..ab8f6d1c3 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -4,9 +4,7 @@ mcuboot: size: CONFIG_PM_PARTITION_SIZE_MCUBOOT placement: before: [mcuboot_primary] -#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) align: {end: 0x1000} -#endif mcuboot_primary_app: # All images to be placed in MCUboot's slot 0 should be placed in this From 2a8f5b43cb99cecdecd6fdc1cb59dda286d8929c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 15 Jan 2025 15:09:55 +0000 Subject: [PATCH 230/287] [nrf noup] sysflash: Add missing _FLASH_0_ID definitions MCUboot uses SOC_FLASH_0_ID and SPI_FLASH_0_ID to distinguish between internal and external boot device. These IDs are provided by sysflash.h, but the pm_sysflash.h overrides entire file, and was lacking that definitions. Signed-off-by: Dominik Ermel --- boot/zephyr/include/sysflash/pm_sysflash.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index 42f25182e..0cb16292f 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -84,4 +84,12 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#ifndef SOC_FLASH_0_ID +#define SOC_FLASH_0_ID 0 +#endif + +#ifndef SPI_FLASH_0_ID +#define SPI_FLASH_0_ID 1 +#endif + #endif /* __PM_SYSFLASH_H__ */ From 3897a7b0f645f3c79829bd6840fc3502ea1bdacb Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Fri, 24 Jan 2025 08:59:31 +0100 Subject: [PATCH 231/287] [nrf noup] boot: zephyr: boards: Disabled NCS boot banner for thingy 53 Disabled NCS BOOT BANNER to save some flash, as Thingy:53 stopped to fit in the mcuboot partition. The boot banner is not used anyway, as logs are disabled. Signed-off-by: Kamil Kasperczyk --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index e10656678..c584aa911 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -47,6 +47,7 @@ CONFIG_USB_CDC_ACM=y CONFIG_CBPRINTF_NANO=y CONFIG_TIMESLICING=n CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n CONFIG_CONSOLE=n CONFIG_CONSOLE_HANDLER=n CONFIG_UART_CONSOLE=n From bc8d277df74908cd52f24fd9a3744f225f21169e Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 9 Jan 2025 11:09:49 +0000 Subject: [PATCH 232/287] [nrf fromtree] boot: bootutil: Add TLV for size of compressed but decrypted image This TLV is needed in order to know what the data length provided to the decompression system is to remove the padding that is a resultant of the encryption block size Signed-off-by: Jamie McCrae (cherry picked from commit 4bda587549c0fccd5cd9b59d76c8edf061ee84c3) --- boot/bootutil/include/bootutil/image.h | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 05e04438b..92adc605b 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -124,6 +124,7 @@ struct flash_area; * the format and size of the raw slot (compressed) * signature */ +#define IMAGE_TLV_COMP_DEC_SIZE 0x73 /* Compressed decrypted image size */ /* * vendor reserved TLVs at xxA0-xxFF, * where xx denotes the upper byte From 9fa43565f0fbcf09f55619307f6a818e3c83c83e Mon Sep 17 00:00:00 2001 From: Michael Konieczny Date: Sat, 11 Jan 2025 15:54:45 +0100 Subject: [PATCH 233/287] [nrf fromtree] added missing MCUBOOT_VERSION_TWEAK in Zephyr port Signed-off-by: Michael Konieczny (cherry picked from commit 256a02c3a5dd244f765c697a125b34ed1a52e576) --- boot/zephyr/include/mcuboot_config/mcuboot_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 9485f7d96..36b5faa42 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -333,6 +333,7 @@ #define MCUBOOT_VERSION_MAJOR APP_VERSION_MAJOR #define MCUBOOT_VERSION_MINOR APP_VERSION_MINOR #define MCUBOOT_VERSION_PATCHLEVEL APP_PATCHLEVEL +#define MCUBOOT_VERSION_TWEAK APP_TWEAK #endif /* Support 32-byte aligned flash sizes */ From 56c26be7ed723b5aec894e875a06d06f23bd9cc7 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Thu, 2 Jan 2025 14:48:28 +0100 Subject: [PATCH 234/287] [nrf fromtree] scripts: imgtool: fix compression with encryption adds TLV which stores compressed image size in case encryption is on. This is to avoid wrong streaam size due to encryption padding. Signed-off-by: Mateusz Michalek (cherry picked from commit 1da18e9060d7af0df9b1e85e07c75ef717ad4723) --- scripts/imgtool/image.py | 11 ++++++++--- scripts/imgtool/main.py | 17 ++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 88ef7b90c..3e2c11073 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -94,6 +94,7 @@ 'DECOMP_SIZE': 0x70, 'DECOMP_SHA': 0x71, 'DECOMP_SIGNATURE': 0x72, + 'COMP_DEC_SIZE' : 0x73, } TLV_SIZE = 4 @@ -460,7 +461,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, sw_type=None, custom_tlvs=None, compression_tlvs=None, compression_type=None, encrypt_keylen=128, clear=False, fixed_sig=None, pub_key=None, vector_to_sign=None, - user_sha='auto', is_pure=False): + user_sha='auto', is_pure=False, keep_comp_size=False, dont_encrypt=False): self.enckey = enckey # key decides on sha, then pub_key; of both are none default is used @@ -522,6 +523,9 @@ def create(self, key, public_key_format, enckey, dependencies=None, dependencies_num = len(dependencies[DEP_IMAGES_KEY]) protected_tlv_size += (dependencies_num * 16) + if keep_comp_size: + compression_tlvs["COMP_DEC_SIZE"] = struct.pack( + self.get_struct_endian() + 'L', self.image_size) if compression_tlvs is not None: for value in compression_tlvs.values(): protected_tlv_size += TLV_SIZE + len(value) @@ -537,7 +541,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, # # This adds the padding if image is not aligned to the 16 Bytes # in encrypted mode - if self.enckey is not None: + if self.enckey is not None and dont_encrypt is False: pad_len = len(self.payload) % 16 if pad_len > 0: pad = bytes(16 - pad_len) @@ -594,6 +598,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, prot_tlv.add(tag, value) protected_tlv_off = len(self.payload) + self.payload += prot_tlv.get() tlv = TLV(self.endian) @@ -657,7 +662,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, if protected_tlv_off is not None: self.payload = self.payload[:protected_tlv_off] - if enckey is not None: + if enckey is not None and dont_encrypt is False: if encrypt_keylen == 256: plainkey = os.urandom(32) else: diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 434530c7a..28caa8947 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -521,12 +521,11 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, 'Pure signatures, currently, enforces preferred hash algorithm, ' 'and forbids sha selection by user.') - img.create(key, public_key_format, enckey, dependencies, boot_record, + if compression in ["lzma2", "lzma2armthumb"]: + img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, compression_tlvs, None, int(encrypt_keylen), clear, baked_signature, pub_key, vector_to_sign, user_sha=user_sha, - is_pure=is_pure) - - if compression in ["lzma2", "lzma2armthumb"]: + is_pure=is_pure, keep_comp_size=False, dont_encrypt=True) compressed_img = image.Image(version=decode_version(version), header_size=header_size, pad_header=pad_header, pad=pad, confirm=confirm, align=int(align), @@ -562,12 +561,20 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, lc = comp_default_lc, lp = comp_default_lp) compressed_img.load_compressed(compressed_data, compression_header) compressed_img.base_addr = img.base_addr + keep_comp_size = False; + if enckey: + keep_comp_size = True compressed_img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, compression_tlvs, compression, int(encrypt_keylen), clear, baked_signature, pub_key, vector_to_sign, user_sha=user_sha, - is_pure=is_pure) + is_pure=is_pure, keep_comp_size=keep_comp_size) img = compressed_img + else: + img.create(key, public_key_format, enckey, dependencies, boot_record, + custom_tlvs, compression_tlvs, None, int(encrypt_keylen), clear, + baked_signature, pub_key, vector_to_sign, user_sha=user_sha, + is_pure=is_pure) img.save(outfile, hex_addr) if sig_out is not None: new_signature = img.get_signature() From a7db1f9c61d9917a7014c500038b0fc1cde138a8 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 15 Jan 2025 13:35:35 +0000 Subject: [PATCH 235/287] [nrf fromtree] boot: boot_serial: Fix uninitialised variables for upload Fixes some issues whereby some variables were not initialised, and undefined values were wrongly used instead Signed-off-by: Jamie McCrae (cherry picked from commit b18b91c2b1fed39887e534631dea1a2a95f5b1d2) --- boot/boot_serial/src/boot_serial.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c index 137cb5633..8b256c623 100644 --- a/boot/boot_serial/src/boot_serial.c +++ b/boot/boot_serial/src/boot_serial.c @@ -452,8 +452,8 @@ bs_set(char *buf, int len) uint8_t image_index = 0; size_t decoded = 0; uint8_t hash[IMAGE_HASH_SIZE]; - bool confirm; - struct zcbor_string img_hash; + bool confirm = false; + struct zcbor_string img_hash = { 0 }; bool ok; int rc; @@ -798,7 +798,7 @@ bs_upload(char *buf, int len) size_t img_size_tmp = SIZE_MAX; /* Temp variable for image size */ const struct flash_area *fap = NULL; int rc; - struct zcbor_string img_chunk_data; + struct zcbor_string img_chunk_data = { 0 }; size_t decoded = 0; bool ok; #ifdef MCUBOOT_ERASE_PROGRESSIVELY @@ -1021,7 +1021,7 @@ bs_upload(char *buf, int len) } } } else { - out_invalid_data: +out_invalid_data: rc = MGMT_ERR_EINVAL; } From 9278beed6e1fb5345817d03298b38e09cdb33a01 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 3 Jan 2025 16:08:43 +0000 Subject: [PATCH 236/287] [nrf fromtree] zephyr: Remove scratch from flash_area_id_from_multi_image_slot The mapping does not seem to be needed as scratch is opened directly, and there is only one for all images anyway. Simulator seems to error out when asked to identify scratch with this function. Signed-off-by: Dominik Ermel (cherry picked from commit 06747985eee7c27d891f2529c58e18f4a84ea6a3) --- boot/zephyr/flash_map_extended.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index d0744afbd..46f4c5a3c 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -62,9 +62,6 @@ int flash_area_id_from_multi_image_slot(int image_index, int slot) case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index); #if !defined(CONFIG_SINGLE_APPLICATION_SLOT) case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index); -#endif -#if defined(CONFIG_BOOT_SWAP_USING_SCRATCH) - case 2: return FLASH_AREA_IMAGE_SCRATCH; #endif } From 61d971b8de92a76793783e021d5ccc9afc2390dc Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 22 Jan 2025 15:58:21 +0000 Subject: [PATCH 237/287] [nrf fromtree] bootutil: Add missing MBEDTLS_ASN1_PARSE_C Need to define MBEDTLS_ASN1_PARSE_C to be able to see ASN1 functions declarations from mbedTLS. Signed-off-by: Dominik Ermel (cherry picked from commit c6f5db297c2f4a67e22517c98d6cd1d52fdc96cb) --- boot/bootutil/src/image_ed25519.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index e6c792a99..07131d1ae 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -17,6 +17,8 @@ #ifdef MCUBOOT_SIGN_ED25519 #include "bootutil/sign_key.h" +/* We are not really using the MBEDTLS but need the ASN.1 parsing functions */ +#define MBEDTLS_ASN1_PARSE_C #include "mbedtls/oid.h" #include "mbedtls/asn1.h" From b5d6e6cb4cf17169903cae9123eaddcf378403ca Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 10 Jan 2025 11:42:38 +0000 Subject: [PATCH 238/287] [nrf fromtree] boot: bootutil: loader: Fix some comments Fixes some comments which had typos or were not formatted correctly Signed-off-by: Jamie McCrae (cherry picked from commit fecf7e87ffee74a9a056929f72d67e0221de6da3) --- boot/bootutil/src/loader.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 6ea929f8d..a561d5cb7 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -809,8 +809,9 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, (void)bs; (void)rc; -/* In the case of ram loading the image has already been decrypted as it is - * decrypted when copied in ram */ + /* In the case of ram loading the image has already been decrypted as it is + * decrypted when copied in ram + */ #if defined(MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_RAM_LOAD) if (MUST_DECRYPT(fap, BOOT_CURR_IMG(state), hdr)) { rc = boot_enc_load(BOOT_CURR_ENC(state), 1, hdr, fap, bs); @@ -1664,7 +1665,7 @@ boot_copy_region(struct boot_loader_state *state, #ifdef MCUBOOT_ENC_IMAGES /* If only copy, then does not matter if header indicates need for - * encryptio/decryptio, we just copy data. */ + * encryption/decryption, we just copy data. */ if (!only_copy && IS_ENCRYPTED(hdr)) { uint32_t abs_off = off + bytes_copied; if (abs_off < hdr->ih_hdr_size) { From 7fd6163e6ca5d069b9cc26f2d6746bad3f8bc9e7 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Tue, 11 Feb 2025 13:55:18 +0100 Subject: [PATCH 239/287] [nrf fromtree] doc: imgtool: importance of clear flag factory-programming procedure. Signed-off-by: Mateusz Michalek Signed-off-by: Anna Wojdylo (cherry picked from commit 9e72eb393bb1cef5a33d20cd462e2028c6541dd2) --- docs/encrypted_images.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/encrypted_images.md b/docs/encrypted_images.md index 85d26d8e1..ebc4f46ed 100644 --- a/docs/encrypted_images.md +++ b/docs/encrypted_images.md @@ -147,6 +147,14 @@ the status area just before starting the upgrade process, because it would be very hard to determine this information when an interruption occurs and the information is spread across multiple areas. +## [Factory-programing requirement](#factory-programing-requirement) + +It is important to have updates without any voids in encryption. +Therefore, from the very beginning, flags and TLV's must be set accordingly. +Perform the first flashing with an image signed by imgtool with encryption settings +intended for DFU. +Append it with the `--clear` flag to keep the image unencrypted and ready for use. + ## [Creating your keys with imgtool](#creating-your-keys-with-imgtool) `imgtool` can generate keys by using `imgtool keygen -k -t `, From 47faf767ec38947bd317dee906d44bdaaeb59368 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 17 Feb 2025 08:53:41 +0000 Subject: [PATCH 240/287] [nrf fromlist] boot: zephyr: kconfig: Add new defaults option for FIH Adds a new menu with options which can be used by e.g. sysbuild to select which default options are set in a build, adds options for fault injection hardening modes Upstream PR #: 2207 Signed-off-by: Jamie McCrae --- boot/zephyr/Kconfig | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 7b2576b9f..0ee9e20c7 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -717,6 +717,9 @@ config MEASURED_BOOT_MAX_CBOR_SIZE choice BOOT_FAULT_INJECTION_HARDENING_PROFILE prompt "Fault injection hardening profile" + default BOOT_FIH_PROFILE_HIGH if BOOT_FIH_PROFILE_DEFAULT_HIGH + default BOOT_FIH_PROFILE_MEDIUM if BOOT_FIH_PROFILE_DEFAULT_MEDIUM + default BOOT_FIH_PROFILE_LOW if BOOT_FIH_PROFILE_DEFAULT_LOW default BOOT_FIH_PROFILE_OFF config BOOT_FIH_PROFILE_OFF @@ -1003,6 +1006,22 @@ endif # BOOT_DECOMPRESSION endif # BOOT_DECOMPRESSION_SUPPORT +menu "Defaults" + # Items in this menu should not be manually set. These options are for modules/sysbuild to + # set as defaults to allow MCUboot's default configuration to be set, but still allow it + # to be overridden by users. + +config BOOT_FIH_PROFILE_DEFAULT_LOW + bool "Default to low fault inject hardening level" + +config BOOT_FIH_PROFILE_DEFAULT_MEDIUM + bool "Default to medium fault inject hardening level" + +config BOOT_FIH_PROFILE_DEFAULT_HIGH + bool "Default to high fault inject hardening level" + +endmenu + endmenu config MCUBOOT_DEVICE_SETTINGS From e8cc9b61368957621fb89a9b2fc30f41a64b4873 Mon Sep 17 00:00:00 2001 From: Sigurd Hellesvik Date: Thu, 6 Feb 2025 08:47:39 +0100 Subject: [PATCH 241/287] [nrf noup] partition_manager: Add support for internal flash netcore DFU Adds check to region of mcuboot_secondary_1 to put it in external flash only if CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY is set. This should allow for DFU from internal flash on the nRF5340 with dynamic partitioning. Also fixing a typo. Signed-off-by: Sigurd Hellesvik --- boot/zephyr/pm.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index ab8f6d1c3..eec62473c 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -78,11 +78,17 @@ mcuboot_pad: mcuboot_primary_1: region: ram_flash size: CONFIG_NRF53_RAM_FLASH_SIZE -#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ +#endif /* CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH */ #if (CONFIG_NRF53_MULTI_IMAGE_UPDATE) mcuboot_secondary_1: +#if defined(CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) region: external_flash +#else + placement: + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + after: mcuboot_secondary +#endif size: CONFIG_NRF53_RAM_FLASH_SIZE #endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ From 148712e7b4618aadbedd04e8d3ce5c3847d3be4f Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 27 Dec 2024 11:45:43 +0000 Subject: [PATCH 242/287] [nrf noup] zephyr: Add support for encrypted compressed updates nrf-squash! [nrf noup] zephyr: Add support for ARM thumb filter Adds support to the compressed image update for allowing encrypted images. Also removes the limit of having 1 updateable image Signed-off-by: Jamie McCrae --- boot/bootutil/src/loader.c | 2 +- boot/zephyr/Kconfig | 3 +- boot/zephyr/decompression.c | 134 ++++++++++++++++++++++++++++++++++-- 3 files changed, 131 insertions(+), 8 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a561d5cb7..f9a9de71d 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1612,7 +1612,7 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES +#if defined(MCUBOOT_DECOMPRESS_IMAGES) && !defined(MCUBOOT_ENC_IMAGES) struct image_header *hdr; #endif diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 0ee9e20c7..1632e6a34 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -975,8 +975,7 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) - depends on !SINGLE_APPLICATION_SLOT && !BOOT_ENCRYPT_IMAGE && BOOT_UPGRADE_ONLY - depends on UPDATEABLE_IMAGE_NUMBER = 1 + depends on !SINGLE_APPLICATION_SLOT && BOOT_UPGRADE_ONLY default y help Hidden symbol which should be selected if a system provided decompression support. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index 35a1950b2..7a9507de6 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -58,11 +58,17 @@ bool boot_is_compressed_header_valid(const struct image_header *hdr, const struc uint32_t protected_tlvs_size; uint32_t decompressed_size; + primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); + + if (primary_fa_id == fap->fa_id) { + BOOT_LOG_ERR("Primary slots cannot be compressed, image: %d", BOOT_CURR_IMG(state)); + return false; + } + if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { opened_flash_area = true; } - primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); assert(rc == 0); @@ -111,6 +117,55 @@ static bool is_compression_object_valid(struct nrf_compress_implementation *comp return true; } +#ifdef MCUBOOT_ENC_IMAGES +int bootutil_get_img_decrypted_comp_size(const struct image_header *hdr, + const struct flash_area *fap, uint32_t *img_comp_size) +{ + if (hdr == NULL || fap == NULL || img_comp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + if (!IS_ENCRYPTED(hdr)) { + /* Update is not encrypted so use size from header */ + *img_comp_size = hdr->ih_img_size; + } else { + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_COMP_DEC_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_comp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_comp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + return BOOT_EFLASH; + } + } + + return 0; +} +#endif + int bootutil_img_hash_decompress(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 *hash_result, @@ -128,8 +183,28 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index bootutil_sha_context sha_ctx; uint8_t flash_erased_value; +#ifdef MCUBOOT_ENC_IMAGES + uint32_t comp_size = 0; + + rc = bootutil_get_img_decrypted_comp_size(hdr, fap, &comp_size); + + if (rc) { + BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); + rc = BOOT_EBADIMAGE; + goto finish_end; + } +#endif + bootutil_sha_init(&sha_ctx); +#ifdef MCUBOOT_ENC_IMAGES + /* Encrypted images only exist in the secondary slot */ + if (MUST_DECRYPT(fap, image_index, hdr) && + !boot_enc_valid(enc_state, 1)) { + return -1; + } +#endif + /* Setup decompression system */ #if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { @@ -212,8 +287,13 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index /* Read in compressed data, decompress and add to hash calculation */ read_pos = 0; +#ifdef MCUBOOT_ENC_IMAGES + while (read_pos < comp_size) { + uint32_t copy_size = comp_size - read_pos; +#else while (read_pos < hdr->ih_img_size) { uint32_t copy_size = hdr->ih_img_size - read_pos; +#endif uint32_t tmp_off = 0; uint8_t offset_zero_check = 0; @@ -230,6 +310,14 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index goto finish; } +#ifdef MCUBOOT_ENC_IMAGES + if (MUST_DECRYPT(fap, image_index, hdr)) { + boot_enc_decrypt(enc_state, 1, read_pos, + copy_size, (read_pos & 0xf), + tmp_buf); + } +#endif + /* Decompress data in chunks, writing it back with a larger write offset of the primary * slot than read size of the secondary slot */ @@ -246,7 +334,11 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index chunk_size = (copy_size - tmp_off); } +#ifdef MCUBOOT_ENC_IMAGES + if ((read_pos + tmp_off + chunk_size) >= comp_size) { +#else if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { +#endif last_packet = true; } @@ -366,6 +458,9 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index finish_without_clean: bootutil_sha_drop(&sha_ctx); +#ifdef MCUBOOT_ENC_IMAGES +finish_end: +#endif return rc; } @@ -437,7 +532,7 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, } if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { /* Skip these TLVs as they are not needed */ continue; } else { @@ -546,7 +641,7 @@ static int boot_sha_protected_tlvs(const struct image_header *hdr, } if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { /* Skip these TLVs as they are not needed */ continue; } @@ -611,7 +706,7 @@ int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_ } if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { /* Exclude these TLVs as they will be copied to the unprotected area */ tlv_size -= len + sizeof(struct image_tlv); } @@ -663,7 +758,7 @@ int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flas * original ones */ continue; - } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV || type == IMAGE_TLV_COMP_DEC_SIZE) { /* Exclude the original unprotected TLVs for signature and hash, the length of the * signature of the compressed data might not be the same size as the signaute of the * decompressed data, as is the case when using ECDSA-P256 @@ -885,8 +980,22 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl bool excess_data_buffer_full = false; #endif +#ifdef MCUBOOT_ENC_IMAGES + uint32_t comp_size = 0; +#endif + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); +#ifdef MCUBOOT_ENC_IMAGES + rc = bootutil_get_img_decrypted_comp_size(hdr, fap_src, &comp_size); + + if (rc) { + BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); + rc = BOOT_EBADIMAGE; + goto finish; + } +#endif + /* Setup decompression system */ #if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { @@ -966,8 +1075,13 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl } /* Read in, decompress and write out data */ +#ifdef MCUBOOT_ENC_IMAGES + while (pos < comp_size) { + uint32_t copy_size = comp_size - pos; +#else while (pos < hdr->ih_img_size) { uint32_t copy_size = hdr->ih_img_size - pos; +#endif uint32_t tmp_off = 0; if (copy_size > buf_size) { @@ -983,6 +1097,12 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl goto finish; } +#ifdef MCUBOOT_ENC_IMAGES + if (IS_ENCRYPTED(hdr)) { + boot_enc_decrypt(BOOT_CURR_ENC(state), 1, pos, copy_size, (pos & 0xf), buf); + } +#endif + /* Decompress data in chunks, writing it back with a larger write offset of the primary * slot than read size of the secondary slot */ @@ -1000,7 +1120,11 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl chunk_size = (copy_size - tmp_off); } +#ifdef MCUBOOT_ENC_IMAGES + if ((pos + tmp_off + chunk_size) >= comp_size) { +#else if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { +#endif last_packet = true; } From 3fff8fd4bb2f321e298c0d4d095c41ede3e5e2a5 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 243/287] Revert "[nrf noup] zephyr: Add support for encrypted compressed updates" This reverts commit 148712e7b4618aadbedd04e8d3ce5c3847d3be4f. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 2 +- boot/zephyr/Kconfig | 3 +- boot/zephyr/decompression.c | 134 ++---------------------------------- 3 files changed, 8 insertions(+), 131 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index f9a9de71d..a561d5cb7 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1612,7 +1612,7 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif -#if defined(MCUBOOT_DECOMPRESS_IMAGES) && !defined(MCUBOOT_ENC_IMAGES) +#ifdef MCUBOOT_DECOMPRESS_IMAGES struct image_header *hdr; #endif diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 1632e6a34..0ee9e20c7 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -975,7 +975,8 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) - depends on !SINGLE_APPLICATION_SLOT && BOOT_UPGRADE_ONLY + depends on !SINGLE_APPLICATION_SLOT && !BOOT_ENCRYPT_IMAGE && BOOT_UPGRADE_ONLY + depends on UPDATEABLE_IMAGE_NUMBER = 1 default y help Hidden symbol which should be selected if a system provided decompression support. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index 7a9507de6..35a1950b2 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -58,17 +58,11 @@ bool boot_is_compressed_header_valid(const struct image_header *hdr, const struc uint32_t protected_tlvs_size; uint32_t decompressed_size; - primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); - - if (primary_fa_id == fap->fa_id) { - BOOT_LOG_ERR("Primary slots cannot be compressed, image: %d", BOOT_CURR_IMG(state)); - return false; - } - if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { opened_flash_area = true; } + primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); assert(rc == 0); @@ -117,55 +111,6 @@ static bool is_compression_object_valid(struct nrf_compress_implementation *comp return true; } -#ifdef MCUBOOT_ENC_IMAGES -int bootutil_get_img_decrypted_comp_size(const struct image_header *hdr, - const struct flash_area *fap, uint32_t *img_comp_size) -{ - if (hdr == NULL || fap == NULL || img_comp_size == NULL) { - return BOOT_EBADARGS; - } else if (hdr->ih_protect_tlv_size == 0) { - return BOOT_EBADIMAGE; - } - - if (!IS_ENCRYPTED(hdr)) { - /* Update is not encrypted so use size from header */ - *img_comp_size = hdr->ih_img_size; - } else { - struct image_tlv_iter it; - uint32_t off; - uint16_t len; - int32_t rc; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_COMP_DEC_SIZE, true); - - if (rc) { - return rc; - } - - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - - if (rc != 0) { - return -1; - } - - if (len != sizeof(*img_comp_size)) { - BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); - return BOOT_EBADIMAGE; - } - - rc = LOAD_IMAGE_DATA(hdr, fap, off, img_comp_size, len); - - if (rc) { - BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off, len, fap->fa_id, rc); - return BOOT_EFLASH; - } - } - - return 0; -} -#endif - int bootutil_img_hash_decompress(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 *hash_result, @@ -183,28 +128,8 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index bootutil_sha_context sha_ctx; uint8_t flash_erased_value; -#ifdef MCUBOOT_ENC_IMAGES - uint32_t comp_size = 0; - - rc = bootutil_get_img_decrypted_comp_size(hdr, fap, &comp_size); - - if (rc) { - BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); - rc = BOOT_EBADIMAGE; - goto finish_end; - } -#endif - bootutil_sha_init(&sha_ctx); -#ifdef MCUBOOT_ENC_IMAGES - /* Encrypted images only exist in the secondary slot */ - if (MUST_DECRYPT(fap, image_index, hdr) && - !boot_enc_valid(enc_state, 1)) { - return -1; - } -#endif - /* Setup decompression system */ #if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { @@ -287,13 +212,8 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index /* Read in compressed data, decompress and add to hash calculation */ read_pos = 0; -#ifdef MCUBOOT_ENC_IMAGES - while (read_pos < comp_size) { - uint32_t copy_size = comp_size - read_pos; -#else while (read_pos < hdr->ih_img_size) { uint32_t copy_size = hdr->ih_img_size - read_pos; -#endif uint32_t tmp_off = 0; uint8_t offset_zero_check = 0; @@ -310,14 +230,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index goto finish; } -#ifdef MCUBOOT_ENC_IMAGES - if (MUST_DECRYPT(fap, image_index, hdr)) { - boot_enc_decrypt(enc_state, 1, read_pos, - copy_size, (read_pos & 0xf), - tmp_buf); - } -#endif - /* Decompress data in chunks, writing it back with a larger write offset of the primary * slot than read size of the secondary slot */ @@ -334,11 +246,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index chunk_size = (copy_size - tmp_off); } -#ifdef MCUBOOT_ENC_IMAGES - if ((read_pos + tmp_off + chunk_size) >= comp_size) { -#else if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { -#endif last_packet = true; } @@ -458,9 +366,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index finish_without_clean: bootutil_sha_drop(&sha_ctx); -#ifdef MCUBOOT_ENC_IMAGES -finish_end: -#endif return rc; } @@ -532,7 +437,7 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, } if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Skip these TLVs as they are not needed */ continue; } else { @@ -641,7 +546,7 @@ static int boot_sha_protected_tlvs(const struct image_header *hdr, } if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Skip these TLVs as they are not needed */ continue; } @@ -706,7 +611,7 @@ int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_ } if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Exclude these TLVs as they will be copied to the unprotected area */ tlv_size -= len + sizeof(struct image_tlv); } @@ -758,7 +663,7 @@ int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flas * original ones */ continue; - } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV || type == IMAGE_TLV_COMP_DEC_SIZE) { + } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { /* Exclude the original unprotected TLVs for signature and hash, the length of the * signature of the compressed data might not be the same size as the signaute of the * decompressed data, as is the case when using ECDSA-P256 @@ -980,22 +885,8 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl bool excess_data_buffer_full = false; #endif -#ifdef MCUBOOT_ENC_IMAGES - uint32_t comp_size = 0; -#endif - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); -#ifdef MCUBOOT_ENC_IMAGES - rc = bootutil_get_img_decrypted_comp_size(hdr, fap_src, &comp_size); - - if (rc) { - BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); - rc = BOOT_EBADIMAGE; - goto finish; - } -#endif - /* Setup decompression system */ #if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { @@ -1075,13 +966,8 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl } /* Read in, decompress and write out data */ -#ifdef MCUBOOT_ENC_IMAGES - while (pos < comp_size) { - uint32_t copy_size = comp_size - pos; -#else while (pos < hdr->ih_img_size) { uint32_t copy_size = hdr->ih_img_size - pos; -#endif uint32_t tmp_off = 0; if (copy_size > buf_size) { @@ -1097,12 +983,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl goto finish; } -#ifdef MCUBOOT_ENC_IMAGES - if (IS_ENCRYPTED(hdr)) { - boot_enc_decrypt(BOOT_CURR_ENC(state), 1, pos, copy_size, (pos & 0xf), buf); - } -#endif - /* Decompress data in chunks, writing it back with a larger write offset of the primary * slot than read size of the secondary slot */ @@ -1120,11 +1000,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl chunk_size = (copy_size - tmp_off); } -#ifdef MCUBOOT_ENC_IMAGES - if ((pos + tmp_off + chunk_size) >= comp_size) { -#else if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { -#endif last_packet = true; } From 007bdadff21e8ae120a8153afaf31bde1588ccbb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 244/287] Revert "[nrf fromtree] boot: bootutil: Add TLV for size of compressed but decrypted image" This reverts commit bc8d277df74908cd52f24fd9a3744f225f21169e. Signed-off-by: Dominik Ermel --- boot/bootutil/include/bootutil/image.h | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 92adc605b..05e04438b 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -124,7 +124,6 @@ struct flash_area; * the format and size of the raw slot (compressed) * signature */ -#define IMAGE_TLV_COMP_DEC_SIZE 0x73 /* Compressed decrypted image size */ /* * vendor reserved TLVs at xxA0-xxFF, * where xx denotes the upper byte From b10316b378916e1a087619ca92929c5613bdfc41 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 245/287] Revert "[nrf noup] boot: bootutil: image_validate: Add KMU support to compression" This reverts commit 97e8acfb8db54b23de41130732ab6f95c3053d15. Signed-off-by: Dominik Ermel --- boot/bootutil/src/image_validate.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 64983b318..f71d1d9a6 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -815,7 +815,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #ifdef EXPECTED_SIG_TLV -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && defined(EXPECTED_KEY_TLV) +#ifdef EXPECTED_KEY_TLV rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); if (rc) { goto out; @@ -861,7 +861,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, */ } } -#endif /* !CONFIG_BOOT_SIGNATURE_USING_KMU && EXPECTED_KEY_TLV */ +#endif /* EXPECTED_KEY_TLV */ rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); if (rc) { @@ -884,12 +884,10 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; From 24e3cfa01d94ceea5e3a60210b4560a0a90276f5 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 246/287] Revert "[nrf noup] boot: bootutil: Allow configuring number of KMU keys" This reverts commit 2ca0efedf8d331028455f05d77f1c3c5064b773b. Signed-off-by: Dominik Ermel --- boot/bootutil/src/ed25519_psa.c | 9 +++------ boot/zephyr/Kconfig | 12 ------------ 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 3042eeabf..83fc692a1 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2024 Nordic Semiconductor ASA + * Copyright (c) 2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ @@ -12,7 +12,6 @@ #include #include -#include #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #include #endif @@ -31,9 +30,7 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; - -BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), - "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); +#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) #endif #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) @@ -106,7 +103,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { + for (int i = 0; i < KMU_KEY_COUNT; ++i) { psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 0ee9e20c7..f39daaa18 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -317,18 +317,6 @@ config BOOT_SIGNATURE_USING_KMU MCUboot will use keys provisioned to the device key management unit for signature verification instead of compiling in key data from a file. -if BOOT_SIGNATURE_USING_KMU - -config BOOT_SIGNATURE_KMU_SLOTS - int "KMU key slots" - range 1 3 - default 1 - help - Selects the number of KMU key slots (also known as generations) to use when verifying - an image. - -endif - if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 5afc6353897536a8e39e5812e7b3dff040f6aa6c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 247/287] Revert "[nrf noup] boot: zephyr: Add experimental selection to compression" This reverts commit 4ceb4773b31dd8d56dfcb6e0461a70bb161ca95f. Signed-off-by: Dominik Ermel --- boot/zephyr/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index f39daaa18..ba3888e74 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -972,10 +972,9 @@ config BOOT_DECOMPRESSION_SUPPORT if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION - bool "Decompression [EXPERIMENTAL]" + bool "Decompression" select NRF_COMPRESS_CLEANUP select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP - select EXPERIMENTAL help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to From fd12c26be5f4559beb5e7482b567e7a848018dd5 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 248/287] Revert "[nrf noup] bootutil: Add support for KMU stored ED25519 signature key" This reverts commit b647a94a24b1a20b3cbbde41ff9a4a92be67a232. Signed-off-by: Dominik Ermel --- boot/bootutil/src/ed25519_psa.c | 51 ------------------------------ boot/bootutil/src/image_ed25519.c | 19 +++-------- boot/bootutil/src/image_validate.c | 6 ---- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 29 +---------------- 5 files changed, 6 insertions(+), 101 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 83fc692a1..e84b71d2a 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,9 +12,6 @@ #include #include -#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) -#include -#endif BOOT_LOG_MODULE_REGISTER(ed25519_psa); @@ -22,18 +19,6 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define EDDSA_KEY_LENGTH 32 #define EDDSA_SIGNAGURE_LENGTH 64 -#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) -/* List of KMU stored key ids available for MCUboot */ -#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) -static psa_key_id_t kmu_key_ids[3] = { - MAKE_PSA_KMU_KEY_ID(226), - MAKE_PSA_KMU_KEY_ID(228), - MAKE_PSA_KMU_KEY_ID(230) -}; -#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) -#endif - -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -84,39 +69,3 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } -#else -int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], - const uint8_t public_key[EDDSA_KEY_LENGTH]) -{ - ARG_UNUSED(public_key); - /* Set to any error */ - psa_status_t status = PSA_ERROR_BAD_STATE; - int ret = 0; /* Fail by default */ - - /* Initialize PSA Crypto */ - status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", status); - return 0; - } - - status = PSA_ERROR_BAD_STATE; - - for (int i = 0; i < KMU_KEY_COUNT; ++i) { - psa_key_id_t kid = kmu_key_ids[i]; - - status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, - message_len, signature, - EDDSA_SIGNAGURE_LENGTH); - if (status == PSA_SUCCESS) { - ret = 1; - break; - } - - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); - } - - return ret; -} -#endif diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 07131d1ae..8e74f48f0 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -27,16 +27,14 @@ #include "bootutil/crypto/sha.h" #define EDDSA_SIGNATURE_LENGTH 64 + +static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; #define NUM_ED25519_BYTES 32 extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) - -static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; - /* * Parse the public key used for signing. */ @@ -75,7 +73,6 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } -#endif fih_ret bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, @@ -83,17 +80,14 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) + uint8_t *pubkey; uint8_t *end; -#endif if (hlen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -102,7 +96,6 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, FIH_SET(fih_rc, FIH_FAILURE); goto out; } -#endif rc = ED25519_verify(hash, IMAGE_HASH_SIZE, sig, pubkey); @@ -124,17 +117,14 @@ bootutil_verify_img(const uint8_t *img, uint32_t size, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) + uint8_t *pubkey; uint8_t *end; -#endif if (slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -143,7 +133,6 @@ bootutil_verify_img(const uint8_t *img, uint32_t size, FIH_SET(fih_rc, FIH_FAILURE); goto out; } -#endif rc = ED25519_verify(img, size, sig, pubkey); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index f71d1d9a6..c419b9497 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -245,7 +245,6 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_HW_KEY) static int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) @@ -311,7 +310,6 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) } #endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ /** @@ -628,7 +626,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, break; } #endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { @@ -659,17 +656,14 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, break; } #endif /* EXPECTED_KEY_TLV */ -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 596e698b3..c5d712e74 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -305,7 +305,7 @@ if(CONFIG_MCUBOOT_SERIAL) endif() endif() -if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU AND NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") +if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") # CONF_FILE points to the KConfig configuration files of the bootloader. foreach (filepath ${CONF_FILE}) file(READ ${filepath} temp_text) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index ba3888e74..2eb1bac7d 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -293,7 +293,6 @@ config BOOT_ED25519_MBEDTLS config BOOT_ED25519_PSA bool "Use PSA crypto" - depends on NRF_SECURITY select BOOT_USE_PSA_CRYPTO select BOOT_ED25519_PSA_DEPENDENCIES select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE @@ -303,22 +302,6 @@ endif endchoice -config BOOT_SIGNATURE_USING_KMU - bool "Use KMU stored keys for signature verification" - depends on NRF_SECURITY - depends on CRACEN_LIB_KMU - select PSA_WANT_ALG_GCM - select PSA_WANT_KEY_TYPE_AES - select PSA_WANT_AES_KEY_SIZE_256 - select PSA_WANT_ALG_SP800_108_COUNTER_CMAC - select PSA_WANT_ALG_CMAC - select PSA_WANT_ALG_ECB_NO_PADDING - help - MCUboot will use keys provisioned to the device key management unit for signature - verification instead of compiling in key data from a file. - -if !BOOT_SIGNATURE_USING_KMU - config BOOT_SIGNATURE_KEY_FILE string "PEM key file" default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 @@ -336,8 +319,6 @@ config BOOT_SIGNATURE_KEY_FILE with the public key information will be written in a format expected by MCUboot. -endif - config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" depends on CPU_CORTEX_M @@ -360,18 +341,10 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. -# Disable MBEDTLS from being selected if NRF_SECURITY is enabled, and use default NRF_SECURITY -# configuration file for MBEDTLS -config MBEDTLS - depends on !NRF_SECURITY - -config NRF_SECURITY - select MBEDTLS_PROMPTLESS - if MBEDTLS config MBEDTLS_CFG_FILE - default "mcuboot-mbedtls-cfg.h" if !NRF_SECURITY + default "mcuboot-mbedtls-cfg.h" endif From c30fbf15c5ee787ec12f4e1b9e53657e1e26355c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 249/287] Revert "[nrf noup] bootutil: PureEdDSA using ED25519" This reverts commit a43e5f460b230ae696454eb4b189d1c1139c73a6. Signed-off-by: Dominik Ermel --- boot/bootutil/src/bootutil_priv.h | 3 - boot/bootutil/src/image_ed25519.c | 37 -------- boot/bootutil/src/image_validate.c | 95 ++----------------- boot/zephyr/Kconfig | 29 +----- .../include/mcuboot_config/mcuboot_config.h | 4 - 5 files changed, 8 insertions(+), 160 deletions(-) diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index 5592f1a87..345933a5f 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -270,9 +270,6 @@ struct boot_loader_state { fih_ret bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t key_id); -fih_ret bootutil_verify_img(const uint8_t *img, uint32_t size, - uint8_t *sig, size_t slen, uint8_t key_id); - fih_ret boot_fih_memequal(const void *s1, const void *s2, size_t n); int boot_find_status(int image_index, const struct flash_area **fap); diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 8e74f48f0..897edcad1 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -111,41 +111,4 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, FIH_RET(fih_rc); } -fih_ret -bootutil_verify_img(const uint8_t *img, uint32_t size, - uint8_t *sig, size_t slen, uint8_t key_id) -{ - int rc; - FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey; - uint8_t *end; - - if (slen != EDDSA_SIGNATURE_LENGTH) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - pubkey = (uint8_t *)bootutil_keys[key_id].key; - end = pubkey + *bootutil_keys[key_id].len; - - rc = bootutil_import_key(&pubkey, end); - if (rc) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - rc = ED25519_verify(img, size, sig, pubkey); - - if (rc == 0) { - /* if verify returns 0, there was an error. */ - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - FIH_SET(fih_rc, FIH_SUCCESS); -out: - - FIH_RET(fih_rc); -} - #endif /* MCUBOOT_SIGN_ED25519 */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index c419b9497..fa1d373d7 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -65,7 +65,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil_priv.h" -#ifndef MCUBOOT_SIGN_PURE /* * Compute SHA hash over the image. * (SHA384 if ECDSA-P384 is being used, @@ -185,7 +184,6 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, return 0; } -#endif /* * Currently, we only support being able to verify one type of @@ -372,43 +370,6 @@ bootutil_get_img_security_cnt(struct image_header *hdr, return 0; } -#if defined(MCUBOOT_SIGN_PURE) -/* Returns: - * 0 -- found - * 1 -- not found or found but not true - * -1 -- failed for some reason - * - * Value of TLV does not matter, presence decides. - */ -static int bootutil_check_for_pure(const struct image_header *hdr, - const struct flash_area *fap) -{ - struct image_tlv_iter it; - uint32_t off; - uint16_t len; - int32_t rc; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_SIG_PURE, false); - if (rc) { - return rc; - } - - /* Search for the TLV */ - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - if (rc == 0 && len == 1) { - bool val; - - rc = LOAD_IMAGE_DATA(hdr, fap, off, &val, 1); - if (rc == 0) { - rc = !val; - } - } - - return rc; -} -#endif - - #ifndef ALLOW_ROGUE_TLVS /* * The following list of TLVs are the only entries allowed in the unprotected @@ -425,9 +386,6 @@ static const uint16_t allowed_unprot_tlvs[] = { IMAGE_TLV_ECDSA_SIG, IMAGE_TLV_RSA3072_PSS, IMAGE_TLV_ED25519, -#if defined(MCUBOOT_SIGN_PURE) - IMAGE_TLV_SIG_PURE, -#endif IMAGE_TLV_ENC_RSA2048, IMAGE_TLV_ENC_KW, IMAGE_TLV_ENC_EC256, @@ -450,6 +408,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, uint32_t off; uint16_t len; uint16_t type; + int image_hash_valid = 0; #ifdef EXPECTED_SIG_TLV FIH_DECLARE(valid_signature, FIH_FAILURE); #ifndef MCUBOOT_BUILTIN_KEY @@ -466,10 +425,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, #endif /* EXPECTED_SIG_TLV */ struct image_tlv_iter it; uint8_t buf[SIG_BUF_SIZE]; -#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) - int image_hash_valid = 0; uint8_t hash[IMAGE_HASH_SIZE]; -#endif int rc = 0; FIH_DECLARE(fih_rc, FIH_FAILURE); #ifdef MCUBOOT_HW_ROLLBACK_PROT @@ -540,7 +496,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #endif -#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); if (rc) { @@ -550,15 +505,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (out_hash) { memcpy(out_hash, hash, IMAGE_HASH_SIZE); } -#endif - -#if defined(MCUBOOT_SIGN_PURE) - /* If Pure type signature is expected then it has to be there */ - rc = bootutil_check_for_pure(hdr, fap); - if (rc != 0) { - goto out; - } -#endif rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); if (rc) { @@ -602,10 +548,8 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } } #endif - switch(type) { -#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) - case EXPECTED_HASH_TLV: - { + + if (type == EXPECTED_HASH_TLV) { /* Verify the image hash. This must always be present. */ if (len != sizeof(hash)) { rc = -1; @@ -623,12 +567,8 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } image_hash_valid = 1; - break; - } -#endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ #ifdef EXPECTED_KEY_TLV - case EXPECTED_KEY_TLV: - { + } else if (type == EXPECTED_KEY_TLV) { /* * Determine which key we should be checking. */ @@ -653,12 +593,9 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, * The key may not be found, which is acceptable. There * can be multiple signatures, each preceded by a key. */ - break; - } #endif /* EXPECTED_KEY_TLV */ #ifdef EXPECTED_SIG_TLV - case EXPECTED_SIG_TLV: - { + } else if (type == EXPECTED_SIG_TLV) { /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; @@ -672,25 +609,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (rc) { goto out; } -#ifndef MCUBOOT_SIGN_PURE FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), buf, len, key_id); -#else - /* Directly check signature on the image, by using the mapping of - * a device to memory. The pointer is beginning of image in flash, - * so offset of area, the range is header + image + protected tlvs. - */ - FIH_CALL(bootutil_verify_img, valid_signature, (void *)flash_area_get_off(fap), - hdr->ih_hdr_size + hdr->ih_img_size + hdr->ih_protect_tlv_size, - buf, len, key_id); -#endif key_id = -1; - break; - } #endif /* EXPECTED_SIG_TLV */ #ifdef MCUBOOT_HW_ROLLBACK_PROT - case IMAGE_TLV_SEC_CNT: - { + } else if (type == IMAGE_TLV_SEC_CNT) { /* * Verify the image's security counter. * This must always be present. @@ -725,21 +649,14 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, /* The image's security counter has been successfully verified. */ security_counter_valid = fih_rc; - break; - } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ } } -#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = !image_hash_valid; if (rc) { goto out; } -#elif defined(MCUBOOT_SIGN_PURE) - /* This returns true on EQ, rc is err on non-0 */ - rc = FIH_NOT_EQ(valid_signature, FIH_SUCCESS); -#endif #ifdef EXPECTED_SIG_TLV FIH_SET(fih_rc, valid_signature); #endif diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 2eb1bac7d..a8aef35d9 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -192,14 +192,6 @@ config BOOT_IMG_HASH_ALG_SHA512 endchoice # BOOT_IMG_HASH_ALG -config BOOT_SIGNATURE_TYPE_PURE_ALLOW - bool - help - Hidden option set by configurations that allow Pure variant, - for example ed25519. The pure variant means that image - signature is calculated over entire image instead of hash - of an image. - choice BOOT_SIGNATURE_TYPE prompt "Signature type" default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP @@ -250,32 +242,15 @@ endif config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" - select BOOT_ENCRYPTION_SUPPORT if !BOOT_SIGNATURE_TYPE_PURE - select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !BOOT_SIGNATURE_TYPE_PURE - # The SHA is used only for key hashing, not for images. + select BOOT_ENCRYPTION_SUPPORT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW select BOOT_IMG_HASH_ALG_SHA512_ALLOW if BOOT_USE_PSA_CRYPTO - select BOOT_SIGNATURE_TYPE_PURE_ALLOW help This is ed25519 signature calculated over SHA512 of SHA256 of application image; that is not completely correct approach as the SHA512 should be rather directly calculated over an image. - Select BOOT_SIGNATURE_TYPE_PURE to have a PureEdDSA calculating image - signature directly on image, rather than hash of the image. if BOOT_SIGNATURE_TYPE_ED25519 - -config BOOT_SIGNATURE_TYPE_PURE - bool "Use Pure signature of image" - depends on BOOT_SIGNATURE_TYPE_PURE_ALLOW - help - The Pure signature is calculated directly over image rather than - hash of an image. - This is more secure signature, specifically if hardware can do the - verification without need to share key. - Note that this requires that all slots for which signature is to be - verified need to be accessible through memory address space that - cryptography can access. - choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" default BOOT_ED25519_TINYCRYPT diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 36b5faa42..40f771911 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -155,10 +155,6 @@ #define MCUBOOT_HASH_STORAGE_DIRECTLY #endif -#ifdef CONFIG_BOOT_SIGNATURE_TYPE_PURE -#define MCUBOOT_SIGN_PURE -#endif - #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From 5176c10b5414519093caa19034b57b5bc8ccfb2e Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 250/287] Revert "[nrf noup] bootutil: Enable hash calculation directly on storage" This reverts commit 32a7c77d13f25c2832b4b3ebaf774c2299be5818. Signed-off-by: Dominik Ermel --- boot/bootutil/src/image_validate.c | 15 +++------------ boot/zephyr/Kconfig | 16 ---------------- .../include/mcuboot_config/mcuboot_config.h | 7 ------- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index fa1d373d7..b1a50f126 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -77,15 +77,13 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, uint8_t *seed, int seed_len) { bootutil_sha_context sha_ctx; + uint32_t blk_sz; uint32_t size; uint16_t hdr_size; + uint32_t off; + int rc; uint32_t blk_off; uint32_t tlv_off; -#if !defined(MCUBOOT_HASH_STORAGE_DIRECTLY) - int rc; - uint32_t off; - uint32_t blk_sz; -#endif #if (BOOT_IMAGE_NUMBER == 1) || !defined(MCUBOOT_ENC_IMAGES) || \ defined(MCUBOOT_RAM_LOAD) @@ -128,12 +126,6 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, /* If protected TLVs are present they are also hashed. */ size += hdr->ih_protect_tlv_size; -#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY - /* No chunk loading, storage is mapped to address space and can - * be directly given to hashing function. - */ - bootutil_sha_update(&sha_ctx, (void *)flash_area_get_off(fap), size); -#else /* MCUBOOT_HASH_STORAGE_DIRECTLY */ #ifdef MCUBOOT_RAM_LOAD bootutil_sha_update(&sha_ctx, (void*)(IMAGE_RAM_BASE + hdr->ih_load_addr), @@ -178,7 +170,6 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, bootutil_sha_update(&sha_ctx, tmp_buf, blk_sz); } #endif /* MCUBOOT_RAM_LOAD */ -#endif /* MCUBOOT_HASH_STORAGE_DIRECTLY */ bootutil_sha_finish(&sha_ctx, hash_result); bootutil_sha_drop(&sha_ctx); diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a8aef35d9..7942bbd19 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -146,22 +146,6 @@ config BOOT_IMG_HASH_ALG_SHA512_ALLOW help Hidden option set by configurations that allow SHA512 -config BOOT_IMG_HASH_DIRECTLY_ON_STORAGE - bool "Hash calculation functions access storage through address space" - depends on !BOOT_ENCRYPT_IMAGE - help - When possible to map storage device, at least for read operations, - to address space or RAM area, enabling this option allows hash - calculation functions to directly access the storage through that address - space or using its own DMA. This reduces flash read overhead done - by the MCUboot. - Notes: - - not supported when encrypted images are in use, because calculating - SHA requires image to be decrypted first, which is done to RAM. - - currently only supported on internal storage of devices; this - option will not work with devices that use external storage for - either of image slots. - choice BOOT_IMG_HASH_ALG prompt "Selected image hash algorithm" default BOOT_IMG_HASH_ALG_SHA256 if BOOT_IMG_HASH_ALG_SHA256_ALLOW diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 40f771911..4743539f1 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -148,13 +148,6 @@ #define MCUBOOT_DECOMPRESS_IMAGES #endif -/* Invoke hashing functions directly on storage. This requires for device - * to be able to map storage to address space or RAM. - */ -#ifdef CONFIG_BOOT_IMG_HASH_DIRECTLY_ON_STORAGE -#define MCUBOOT_HASH_STORAGE_DIRECTLY -#endif - #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From e2b2c08be0710dc34952bbdee1d0e254daf11c8d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 251/287] Revert "[nrf noup] bootutil: Provide support for SHA512 with ED25519" This reverts commit 4e2273f992401997fc9a08868a0f4c4e3fac682e. Signed-off-by: Dominik Ermel --- boot/zephyr/Kconfig | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 7942bbd19..778ffca52 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -80,7 +80,7 @@ config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES config BOOT_ED25519_PSA_DEPENDENCIES bool - select PSA_WANT_ALG_SHA_256 if BOOT_IMG_HASH_ALG_SHA256 + select PSA_WANT_ALG_SHA_256 select PSA_WANT_ALG_SHA_512 select PSA_WANT_ALG_PURE_EDDSA select PSA_WANT_ECC_TWISTED_EDWARDS_255 @@ -228,11 +228,6 @@ config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" select BOOT_ENCRYPTION_SUPPORT select BOOT_IMG_HASH_ALG_SHA256_ALLOW - select BOOT_IMG_HASH_ALG_SHA512_ALLOW if BOOT_USE_PSA_CRYPTO - help - This is ed25519 signature calculated over SHA512 of SHA256 of application - image; that is not completely correct approach as the SHA512 should be - rather directly calculated over an image. if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION From a547fd70d99fc639ead410d1b10e1674cf590cd2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 252/287] Revert "[nrf noup] PSA configuration required changes" This reverts commit 9644dc258228d71e7eff85025e9d67dbc56df789. Signed-off-by: Dominik Ermel --- boot/bootutil/zephyr/CMakeLists.txt | 14 ++--- boot/zephyr/CMakeLists.txt | 39 ++++-------- boot/zephyr/Kconfig | 73 +---------------------- boot/zephyr/include/mcuboot-mbedtls-cfg.h | 2 +- 4 files changed, 16 insertions(+), 112 deletions(-) diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index d5364d025..72a6a8638 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -29,18 +29,12 @@ zephyr_library_link_libraries(MCUBOOT_BOOTUTIL) target_link_libraries(MCUBOOT_BOOTUTIL INTERFACE zephyr_interface) if(CONFIG_BOOT_USE_TINYCRYPT) - target_include_directories(MCUBOOT_BOOTUTIL INTERFACE - ../../../ext/tinycrypt/lib/include - ) -endif() - -if(CONFIG_BOOT_USE_PSA_CRYPTO) - target_include_directories(MCUBOOT_BOOTUTIL INTERFACE - ${ZEPHYR_MBEDTLS_MODULE_DIR}/include - ) +target_include_directories(MCUBOOT_BOOTUTIL INTERFACE + ../../../ext/tinycrypt/lib/include +) endif() -if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO AND NOT CONFIG_PSA_CORE_OBERON) +if(CONFIG_BOOT_USE_MBEDTLS) zephyr_link_libraries(mbedTLS) endif() endif() diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index c5d712e74..fa9f4c68c 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -47,12 +47,6 @@ zephyr_library_include_directories( include ) -if(DEFINED CONFIG_MBEDTLS) - zephyr_library_include_directories( - ${ZEPHYR_MBEDTLS_MODULE_DIR}/include - ) -endif() - # Zephyr port-specific sources. zephyr_library_sources( main.c @@ -104,10 +98,6 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/fault_injection_hardening.c ) -if(DEFINED CONFIG_BOOT_ENCRYPT_X25519 AND DEFINED CONFIG_BOOT_ED25519_PSA) - zephyr_library_sources(${BOOT_DIR}/bootutil/src/encrypted_psa.c) -endif() - if(DEFINED CONFIG_MEASURED_BOOT OR DEFINED CONFIG_BOOT_SHARE_DATA) zephyr_library_sources( ${BOOT_DIR}/bootutil/src/boot_record.c @@ -248,28 +238,19 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) ${FIAT_DIR}/include/ ) - if(NOT CONFIG_BOOT_ED25519_PSA) - zephyr_library_sources( - ${FIAT_DIR}/src/curve25519.c - ) - else() - zephyr_library_sources( - ${MBEDTLS_ASN1_DIR}/src/asn1parse.c - ${BOOT_DIR}/bootutil/src/ed25519_psa.c - ) - endif() + zephyr_library_sources( + ${FIAT_DIR}/src/curve25519.c + ) endif() -if(NOT CONFIG_BOOT_ED25519_PSA) - if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) - zephyr_library_sources( - ${TINYCRYPT_DIR}/source/aes_encrypt.c - ${TINYCRYPT_DIR}/source/aes_decrypt.c - ${TINYCRYPT_DIR}/source/ctr_mode.c - ${TINYCRYPT_DIR}/source/hmac.c - ${TINYCRYPT_DIR}/source/ecc_dh.c +if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) + zephyr_library_sources( + ${TINYCRYPT_DIR}/source/aes_encrypt.c + ${TINYCRYPT_DIR}/source/aes_decrypt.c + ${TINYCRYPT_DIR}/source/ctr_mode.c + ${TINYCRYPT_DIR}/source/hmac.c + ${TINYCRYPT_DIR}/source/ecc_dh.c ) - endif() endif() if(CONFIG_BOOT_ENCRYPT_EC256) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 778ffca52..8f84e9275 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -29,10 +29,7 @@ config BOOT_USE_MBEDTLS config BOOT_USE_PSA_CRYPTO bool - default y if NRF_SECURITY - # This is counter intuitive but that is how PSA heap is enabled. - select MBEDTLS_ENABLE_HEAP - select MBEDTLS_PSA_CRYPTO_C + # Hidden option help Hidden option set if using PSA crypt for cryptography functionality @@ -69,58 +66,6 @@ config NRF_CC310_BL bool default n -if BOOT_USE_PSA_CRYPTO - -config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES - bool - default y if BOOT_IMG_HASH_ALG_SHA256 - select PSA_WANT_ALG_SHA_256 - help - Dependencies for hashing with SHA256 - -config BOOT_ED25519_PSA_DEPENDENCIES - bool - select PSA_WANT_ALG_SHA_256 - select PSA_WANT_ALG_SHA_512 - select PSA_WANT_ALG_PURE_EDDSA - select PSA_WANT_ECC_TWISTED_EDWARDS_255 - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT - help - Dependencies for ed25519 signature - -if BOOT_ENCRYPT_IMAGE - -config BOOT_X25519_PSA_DEPENDENCIES - bool - select PSA_WANT_ALG_ECDH - select PSA_WANT_ALG_HMAC - select PSA_WANT_ALG_HKDF - select PSA_WANT_ALG_CTR - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT - select PSA_WANT_KEY_TYPE_DERIVE - select PSA_WANT_KEY_TYPE_AES - select PSA_WANT_ECC_MONTGOMERY_255 - help - Dependencies for x25519 shared-random key encryption and AES - encryption. The PSA_WANT_ALG_CTR and PSA_WANT_KEY_TYPE_AES - enable Counter based block cipher and AES key, and algorithm support, - to use with it; the others are used for shared key decryption - and derivation. - -endif # BOOT_ENCRYPT_IMAGE - -if MBEDTLS_ENABLE_HEAP - -config MBEDTLS_HEAP_SIZE - default 2048 if BOOT_USE_PSA_CRYPTO - help - The PSA internals need to be able to allocate memory for operation - and it uses mbedTLS heap for that. - -endif # MBEDTLS_ENABLE_HEAP - -endif # BOOT_USE_PSA_CRYPTO - menu "MCUBoot settings" config SINGLE_APPLICATION_SLOT @@ -178,7 +123,6 @@ endchoice # BOOT_IMG_HASH_ALG choice BOOT_SIGNATURE_TYPE prompt "Signature type" - default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP default BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_NONE @@ -233,24 +177,13 @@ if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" default BOOT_ED25519_TINYCRYPT - config BOOT_ED25519_TINYCRYPT bool "Use tinycrypt" select BOOT_USE_TINYCRYPT - depends on !NRF_SECURITY - config BOOT_ED25519_MBEDTLS bool "Use mbedTLS" select BOOT_USE_MBEDTLS select MBEDTLS - depends on !NRF_SECURITY - -config BOOT_ED25519_PSA - bool "Use PSA crypto" - select BOOT_USE_PSA_CRYPTO - select BOOT_ED25519_PSA_DEPENDENCIES - select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE - endchoice endif @@ -295,13 +228,9 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. -if MBEDTLS - config MBEDTLS_CFG_FILE default "mcuboot-mbedtls-cfg.h" -endif - config BOOT_HW_KEY bool "Use HW key for image verification" default n diff --git a/boot/zephyr/include/mcuboot-mbedtls-cfg.h b/boot/zephyr/include/mcuboot-mbedtls-cfg.h index a46fbb09f..2bab537d7 100644 --- a/boot/zephyr/include/mcuboot-mbedtls-cfg.h +++ b/boot/zephyr/include/mcuboot-mbedtls-cfg.h @@ -23,7 +23,7 @@ #if defined(CONFIG_BOOT_SIGNATURE_TYPE_RSA) || defined(CONFIG_BOOT_ENCRYPT_RSA) #include "config-rsa.h" -#elif defined(CONFIG_BOOT_USE_PSA_CRYPTO) || defined(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256) || \ +#elif defined(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256) || \ defined(CONFIG_BOOT_ENCRYPT_EC256) || \ (defined(CONFIG_BOOT_ENCRYPT_X25519) && !defined(CONFIG_BOOT_SIGNATURE_TYPE_ED25519)) #include "config-asn1.h" From 883b397bc8641bf10da0a43a12f3ed77d2c20c96 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 253/287] Revert "[nrf noup] Fix logging for ED25519_psa" This reverts commit f3c2fbc9234ab08f9f5fdd2f075397a4b3e1d00c. Signed-off-by: Dominik Ermel --- boot/bootutil/src/ed25519_psa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index e84b71d2a..3d7274307 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -13,7 +13,7 @@ #include #include -BOOT_LOG_MODULE_REGISTER(ed25519_psa); +BOOT_LOG_MODULE_DECLARE(ed25519_psa); #define SHA512_DIGEST_LENGTH 64 #define EDDSA_KEY_LENGTH 32 From 9bd9ae25611d83d6bbbf76352a4f62c117c622e1 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 254/287] Revert "[nrf noup] Remove setting default MCUboot mbedTLS config" This reverts commit 62929e493c6feb75fc83378d7235280e14a745cc. Signed-off-by: Dominik Ermel --- boot/zephyr/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 9ff1ba274..e4f7d9030 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -1,6 +1,7 @@ CONFIG_PM=n CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" CONFIG_BOOT_SWAP_SAVE_ENCTLV=n CONFIG_BOOT_ENCRYPT_IMAGE=n From 4b8ed01f40b7fae1864be530722904dc2e623d96 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 255/287] Revert "[nrf noup] zephyr: Add support for ARM thumb filter" This reverts commit cbb7da0a51f469b775bcbf9662ae3a905917563b. Signed-off-by: Dominik Ermel --- boot/zephyr/decompression.c | 305 +++++++++--------------------------- 1 file changed, 71 insertions(+), 234 deletions(-) diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index 35a1950b2..062cdbc61 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -29,14 +29,6 @@ #define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 #endif -#define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) -#define DECOMP_BUF_EXTRA_SIZE 2 -#else -#define DECOMP_BUF_EXTRA_SIZE 0 -#endif -#define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE) - /* Number of times that consumed data by decompression system can be 0 in a row before aborting */ #define OFFSET_ZERO_CHECK_TIMES 3 @@ -95,22 +87,13 @@ bool boot_is_compressed_header_valid(const struct image_header *hdr, const struc if (size >= size_check) { BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", size, size_check); + return false; } return true; } -static bool is_compression_object_valid(struct nrf_compress_implementation *compression) -{ - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { - return false; - } - - return true; -} - int bootutil_img_hash_decompress(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 *hash_result, @@ -121,9 +104,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index uint32_t write_pos = 0; uint32_t protected_tlv_size = 0; uint32_t decompressed_image_size; - uint32_t output_size_total = 0; - struct nrf_compress_implementation *compression_lzma = NULL; - struct nrf_compress_implementation *compression_arm_thumb = NULL; + struct nrf_compress_implementation *compression = NULL; TARGET_STATIC struct image_header modified_hdr; bootutil_sha_context sha_ctx; uint8_t flash_erased_value; @@ -141,26 +122,27 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; + goto finish_without_clean; } - compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); + compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - if (!is_compression_object_valid(compression_lzma) || - !is_compression_object_valid(compression_arm_thumb)) { + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; + goto finish_without_clean; } - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); + rc = compression->init(NULL); if (rc) { BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; + goto finish_without_clean; } @@ -175,6 +157,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -189,6 +172,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (rc) { BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -227,6 +211,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); rc = BOOT_EFLASH; + goto finish; } @@ -240,7 +225,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index uint32_t chunk_size; bool last_packet = false; - chunk_size = compression_lzma->decompress_bytes_needed(NULL); + chunk_size = compression->decompress_bytes_needed(NULL); if (chunk_size > (copy_size - tmp_off)) { chunk_size = (copy_size - tmp_off); @@ -250,12 +235,13 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index last_packet = true; } - rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, - &offset, &output, &output_size); + rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset, + &output, &output_size); if (rc) { BOOT_LOG_ERR("Decompression error: %d", rc); rc = BOOT_EBADSTATUS; + goto finish; } @@ -265,6 +251,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", write_pos); rc = BOOT_EBADIMAGE; + goto finish; } @@ -273,6 +260,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index /* Last packet and we still have no output, this is a faulty update */ BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -283,6 +271,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -293,48 +282,8 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index offset_zero_check = 0; } - /* Copy data to secondary buffer for calculating hash */ if (output_size > 0) { - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - /* Run this through the ARM thumb filter */ - uint32_t offset_arm_thumb = 0; - uint8_t *output_arm_thumb = NULL; - uint32_t processed_size = 0; - uint32_t output_size_arm_thumb = 0; - - while (processed_size < output_size) { - uint32_t current_size = output_size - processed_size; - bool arm_thumb_last_packet = false; - - if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { - current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; - } - - if (last_packet && (processed_size + current_size) == - output_size) { - arm_thumb_last_packet = true; - } - - rc = compression_arm_thumb->decompress(NULL, &output[processed_size], - current_size, arm_thumb_last_packet, - &offset_arm_thumb, - &output_arm_thumb, - &output_size_arm_thumb); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb); - output_size_total += output_size_arm_thumb; - processed_size += current_size; - } - } else { - bootutil_sha_update(&sha_ctx, output, output_size); - output_size_total += output_size; - } + bootutil_sha_update(&sha_ctx, output, output_size); } tmp_off += offset; @@ -343,13 +292,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index read_pos += copy_size; } - if (modified_hdr.ih_img_size != output_size_total) { - BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d", - modified_hdr.ih_img_size, output_size_total); - rc = BOOT_EBADSTATUS; - goto finish; - } - /* If there are any protected TLVs present, add them after the main decompressed image */ if (modified_hdr.ih_protect_tlv_size > 0) { rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, @@ -360,8 +302,7 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index finish: /* Clean up decompression system */ - (void)compression_lzma->deinit(NULL); - (void)compression_arm_thumb->deinit(NULL); + (void)compression->deinit(NULL); finish_without_clean: bootutil_sha_drop(&sha_ctx); @@ -412,6 +353,7 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto out; } @@ -480,6 +422,7 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + goto out; } @@ -495,6 +438,7 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto out; } @@ -569,6 +513,7 @@ static int boot_sha_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + read_off), copy_size, fap_src->fa_id, rc); + goto out; } @@ -681,6 +626,7 @@ int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flas */ BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); rc = BOOT_EBADIMAGE; + goto out; } @@ -735,6 +681,7 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto out; } @@ -831,6 +778,7 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + goto out; } @@ -846,6 +794,7 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto out; } @@ -874,17 +823,11 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint32_t unprotected_tlv_size = 0; uint32_t tlv_write_size = 0; uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression_lzma = NULL; - struct nrf_compress_implementation *compression_arm_thumb = NULL; + struct nrf_compress_implementation *compression = NULL; struct image_header *hdr; - TARGET_STATIC uint8_t decomp_buf[DECOMP_BUF_ALLOC_SIZE] __attribute__((aligned(4))); + TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4))); TARGET_STATIC struct image_header modified_hdr; -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - uint8_t excess_data_buffer[DECOMP_BUF_EXTRA_SIZE]; - bool excess_data_buffer_full = false; -#endif - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); /* Setup decompression system */ @@ -898,26 +841,27 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; + goto finish; } - compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); + compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - if (!is_compression_object_valid(compression_lzma) || - !is_compression_object_valid(compression_arm_thumb)) { + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; + goto finish; } - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); + rc = compression->init(NULL); if (rc) { BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; + goto finish; } @@ -930,6 +874,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -942,6 +887,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -952,6 +898,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); rc = BOOT_EBADIMAGE; + goto finish; } @@ -962,6 +909,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto finish; } @@ -980,6 +928,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); rc = BOOT_EFLASH; + goto finish; } @@ -994,7 +943,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint8_t *output = NULL; bool last_packet = false; - chunk_size = compression_lzma->decompress_bytes_needed(NULL); + chunk_size = compression->decompress_bytes_needed(NULL); if (chunk_size > (copy_size - tmp_off)) { chunk_size = (copy_size - tmp_off); @@ -1004,142 +953,47 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl last_packet = true; } - rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, - &offset, &output, &output_size); + rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset, + &output, &output_size); if (rc) { BOOT_LOG_ERR("Decompression error: %d", rc); rc = BOOT_EBADSTATUS; + goto finish; } /* Copy data to secondary buffer for writing out */ while (output_size > 0) { - uint32_t data_size = (DECOMP_BUF_SIZE - decomp_buf_size); + uint32_t data_size = (sizeof(decomp_buf) - decomp_buf_size); if (data_size > output_size) { data_size = output_size; } -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - memcpy(&decomp_buf[decomp_buf_size + DECOMP_BUF_EXTRA_SIZE], - &output[compression_buffer_pos], data_size); - } else -#endif - { - memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], - data_size); - } - + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], data_size); compression_buffer_pos += data_size; decomp_buf_size += data_size; output_size -= data_size; /* Write data out from secondary buffer when it is full */ - if (decomp_buf_size == DECOMP_BUF_SIZE) { -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - uint32_t filter_writeback_pos = 0; - uint32_t processed_size = 0; - - /* Run this through the ARM thumb filter */ - while (processed_size < DECOMP_BUF_SIZE) { - uint32_t offset_arm_thumb = 0; - uint32_t output_size_arm_thumb = 0; - uint8_t *output_arm_thumb = NULL; - uint32_t current_size = DECOMP_BUF_SIZE; - bool arm_thumb_last_packet = false; - - if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { - current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; - } - - if (last_packet && (processed_size + current_size) == DECOMP_BUF_SIZE - && output_size == 0) { - arm_thumb_last_packet = true; - } - - rc = compression_arm_thumb->decompress(NULL, - &decomp_buf[processed_size + - DECOMP_BUF_EXTRA_SIZE], - current_size, - arm_thumb_last_packet, - &offset_arm_thumb, - &output_arm_thumb, - &output_size_arm_thumb); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - memcpy(&decomp_buf[filter_writeback_pos], output_arm_thumb, - output_size_arm_thumb); - filter_writeback_pos += output_size_arm_thumb; - processed_size += current_size; - } - - if (excess_data_buffer_full == true) - { - /* Restore extra data removed from previous iteration to the write - * buffer - */ - memmove(&decomp_buf[DECOMP_BUF_EXTRA_SIZE], decomp_buf, - filter_writeback_pos); - memcpy(decomp_buf, excess_data_buffer, DECOMP_BUF_EXTRA_SIZE); - excess_data_buffer_full = false; - filter_writeback_pos += DECOMP_BUF_EXTRA_SIZE; - } - - if ((filter_writeback_pos % sizeof(uint32_t)) != 0) - { - /* Since there are an extra 2 bytes here, remove them and stash for - * later usage to prevent flash write issues with non-word boundary - * writes - */ - memcpy(excess_data_buffer, &decomp_buf[filter_writeback_pos - - DECOMP_BUF_EXTRA_SIZE], - DECOMP_BUF_EXTRA_SIZE); - excess_data_buffer_full = true; - filter_writeback_pos -= DECOMP_BUF_EXTRA_SIZE; - } - - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, filter_writeback_pos); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), DECOMP_BUF_SIZE, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - write_pos += filter_writeback_pos; - decomp_buf_size = 0; - filter_writeback_pos = 0; - } else -#endif - { - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, DECOMP_BUF_SIZE); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), DECOMP_BUF_SIZE, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - write_pos += DECOMP_BUF_SIZE; - decomp_buf_size = 0; + if (decomp_buf_size == sizeof(decomp_buf)) { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, sizeof(decomp_buf)); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), sizeof(decomp_buf), + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; } + + write_pos += sizeof(decomp_buf); + decomp_buf_size = 0; } } @@ -1149,30 +1003,8 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl pos += copy_size; } -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0) { - /* Extra data that has not been written out that needs ARM thumb filter applied */ - uint32_t offset_arm_thumb = 0; - uint32_t output_size_arm_thumb = 0; - uint8_t *output_arm_thumb = NULL; - - rc = compression_arm_thumb->decompress(NULL, &decomp_buf[DECOMP_BUF_EXTRA_SIZE], - decomp_buf_size, true, &offset_arm_thumb, - &output_arm_thumb, &output_size_arm_thumb); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - memcpy(decomp_buf, output_arm_thumb, output_size_arm_thumb); - } -#endif - /* Clean up decompression system */ - (void)compression_lzma->deinit(NULL); - (void)compression_arm_thumb->deinit(NULL); + (void)compression->deinit(NULL); if (protected_tlv_size > 0) { rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + @@ -1182,6 +1014,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + goto finish; } @@ -1196,6 +1029,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + goto finish; } @@ -1206,7 +1040,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); /* Check if additional write padding should be applied to meet the minimum write size */ - if (write_alignment > 1 && write_padding_size) { + if (write_padding_size) { uint8_t flash_erased_value; flash_erased_value = flash_area_erased_val(fap_dst); @@ -1222,6 +1056,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, fap_dst->fa_id, rc); rc = BOOT_EFLASH; + goto finish; } @@ -1263,6 +1098,7 @@ int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct fl if (len != sizeof(*img_decomp_size)) { BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + return BOOT_EBADIMAGE; } @@ -1271,6 +1107,7 @@ int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct fl if (rc) { BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", off, len, fap->fa_id, rc); + return BOOT_EFLASH; } From 9b791650189250ede2d02cc38d160062012a9d91 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 256/287] Revert "[nrf noup] PSA implementation of x25519 and ed25519 verification" This reverts commit 1107145b8496acf8682d5ae223f942f861771405. Signed-off-by: Dominik Ermel --- .../include/bootutil/crypto/aes_ctr.h | 38 +- boot/bootutil/src/ed25519_psa.c | 71 --- boot/bootutil/src/encrypted.c | 114 +++-- boot/bootutil/src/encrypted_psa.c | 454 ------------------ boot/bootutil/src/image_ed25519.c | 13 +- 5 files changed, 59 insertions(+), 631 deletions(-) delete mode 100644 boot/bootutil/src/ed25519_psa.c delete mode 100644 boot/bootutil/src/encrypted_psa.c diff --git a/boot/bootutil/include/bootutil/crypto/aes_ctr.h b/boot/bootutil/include/bootutil/crypto/aes_ctr.h index 44190361c..50d36a4fc 100644 --- a/boot/bootutil/include/bootutil/crypto/aes_ctr.h +++ b/boot/bootutil/include/bootutil/crypto/aes_ctr.h @@ -15,8 +15,8 @@ #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" + defined(MCUBOOT_USE_TINYCRYPT)) != 1 + #error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT" #endif #if defined(MCUBOOT_USE_MBED_TLS) @@ -38,46 +38,12 @@ #define BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE TC_AES_BLOCK_SIZE #endif /* MCUBOOT_USE_TINYCRYPT */ - -#if defined(MCUBOOT_USE_PSA_CRYPTO) - #include - #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 #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) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c deleted file mode 100644 index 3d7274307..000000000 --- a/boot/bootutil/src/ed25519_psa.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -#include -#include -#include - -#include -#include "bootutil/bootutil_log.h" - -#include -#include - -BOOT_LOG_MODULE_DECLARE(ed25519_psa); - -#define SHA512_DIGEST_LENGTH 64 -#define EDDSA_KEY_LENGTH 32 -#define EDDSA_SIGNAGURE_LENGTH 64 - -int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], - const uint8_t public_key[EDDSA_KEY_LENGTH]) -{ - /* Set to any error */ - psa_status_t status = PSA_ERROR_BAD_STATE; - psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t kid; - int ret = 0; /* Fail by default */ - - /* Initialize PSA Crypto */ - status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d\n", status); - return 0; - } - - status = PSA_ERROR_BAD_STATE; - - psa_set_key_type(&key_attr, - PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS)); - psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE); - psa_set_key_algorithm(&key_attr, PSA_ALG_PURE_EDDSA); - - status = psa_import_key(&key_attr, public_key, EDDSA_KEY_LENGTH, &kid); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("ED25519 key import failed %d", status); - return 0; - } - - status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len, - signature, EDDSA_SIGNAGURE_LENGTH); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); - ret = 0; - /* Pass through to destroy key */ - } else { - ret = 1; - /* Pass through to destroy key */ - } - - status = psa_destroy_key(kid); - - if (status != PSA_SUCCESS) { - /* Just for logging */ - BOOT_LOG_WRN("Failed to destroy key %d", status); - } - - return ret; -} diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index 67fa819bb..8449a28dd 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -25,7 +25,6 @@ #include "bootutil/crypto/ecdh_p256.h" #endif -#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_X25519) #include "bootutil/crypto/ecdh_x25519.h" #endif @@ -36,7 +35,6 @@ #include "mbedtls/oid.h" #include "mbedtls/asn1.h" #endif -#endif #include "bootutil/image.h" #include "bootutil/enc_key.h" @@ -45,30 +43,6 @@ #include "bootutil_priv.h" -#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE - -#if defined(MCUBOOT_ENCRYPT_RSA) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 -#elif defined(MCUBOOT_ENCRYPT_KW) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW -#elif defined(MCUBOOT_ENCRYPT_EC256) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (65) -# define EC_CIPHERKEY_INDEX (65 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-P256 component indexes"); -#elif defined(MCUBOOT_ENCRYPT_X25519) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (32) -# define EC_CIPHERKEY_INDEX (32 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-X25519 component indexes"); -#endif - -/* NOUP Fixme: */ -#if !defined(CONFIG_BOOT_ED25519_PSA) #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) #if defined(_compare) static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size) @@ -377,6 +351,60 @@ int boot_enc_retrieve_private_key(struct bootutil_key **private_key) } #endif /* !MCUBOOT_ENC_BUILTIN_KEY */ +int +boot_enc_init(struct enc_key_data *enc_state, uint8_t slot) +{ + bootutil_aes_ctr_init(&enc_state[slot].aes_ctr); + return 0; +} + +int +boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot) +{ + bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr); + enc_state[slot].valid = 0; + return 0; +} + +int +boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, + const struct boot_status *bs) +{ + int rc; + + rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]); + if (rc != 0) { + boot_enc_drop(enc_state, slot); + return -1; + } + + enc_state[slot].valid = 1; + + return 0; +} + +#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE + +#if defined(MCUBOOT_ENCRYPT_RSA) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 +#elif defined(MCUBOOT_ENCRYPT_KW) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW +#elif defined(MCUBOOT_ENCRYPT_EC256) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (65) +# define EC_CIPHERKEY_INDEX (65 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-P256 component indexes"); +#elif defined(MCUBOOT_ENCRYPT_X25519) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (32) +# define EC_CIPHERKEY_INDEX (32 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-X25519 component indexes"); +#endif + #if ( (defined(MCUBOOT_ENCRYPT_RSA) && defined(MCUBOOT_USE_MBED_TLS) && !defined(MCUBOOT_USE_PSA_CRYPTO)) || \ (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ) #if MBEDTLS_VERSION_NUMBER >= 0x03000000 @@ -599,7 +627,6 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return rc; } -#endif /* CONFIG_BOOT_ED25519_PSA */ /* * Load encryption key. @@ -654,39 +681,6 @@ boot_enc_load(struct enc_key_data *enc_state, int slot, return boot_decrypt_key(buf, bs->enckey[slot]); } -int -boot_enc_init(struct enc_key_data *enc_state, uint8_t slot) -{ - bootutil_aes_ctr_init(&enc_state[slot].aes_ctr); - return 0; -} - -int -boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot) -{ - bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr); - enc_state[slot].valid = 0; - return 0; -} - -int -boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, - const struct boot_status *bs) -{ - int rc; - - rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]); - if (rc != 0) { - boot_enc_drop(enc_state, slot); - return -1; - } - - enc_state[slot].valid = 1; - - return 0; -} - - bool boot_enc_valid(struct enc_key_data *enc_state, int slot) { diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c deleted file mode 100644 index c3f72884d..000000000 --- a/boot/bootutil/src/encrypted_psa.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include "mcuboot_config/mcuboot_config.h" - -#include -#include -#include - -/* We are not really using the MBEDTLS but need the ASN.1 parsing functions */ -#define MBEDTLS_ASN1_PARSE_C - -#include "bootutil/crypto/sha.h" -#include "mbedtls/oid.h" -#include "mbedtls/asn1.h" - -#include "bootutil/image.h" -#include "bootutil/enc_key.h" -#include "bootutil/sign_key.h" -#include "bootutil/crypto/common.h" - -#include "bootutil_priv.h" -#include "bootutil/bootutil_log.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); - -#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE -#define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 -#define EC_PUBK_INDEX (0) -#define EC_TAG_INDEX (32) -#define EC_CIPHERKEY_INDEX (32 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-X25519 component indexes"); - -#define X25519_OID "\x6e" -static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ - MBEDTLS_OID_ORG_GOV X25519_OID; - -#define SHARED_KEY_LEN 32 -#define PRIV_KEY_LEN 32 - -/* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ -static int -parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) -{ - size_t len; - int version; - mbedtls_asn1_buf alg; - mbedtls_asn1_buf param; - - if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE) != 0) { - return -1; - } - - if (*p + len != end) { - return -2; - } - - version = 0; - if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { - return -3; - } - - if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { - return -4; - } - - 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 -5; - } - - if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -6; - } - - if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -7; - } - - if (len != PRIV_KEY_LEN) { - return -8; - } - - memcpy(private_key, *p, PRIV_KEY_LEN); - return 0; -} - -void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx) -{ - psa_status_t psa_ret = psa_crypto_init(); - - (void)ctx; - - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES init PSA crypto init failed %d", psa_ret); - assert(0); - } -} - -#if defined(MCUBOOT_ENC_IMAGES) -extern const struct bootutil_key bootutil_enc_key; -/* - * Decrypt an encryption key TLV. - * - * @param buf An encryption TLV read from flash (build time fixed length) - * @param enckey An AES-128 or AES-256 key sized buffer to store to plain key. - */ -int -boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) -{ - uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; - uint8_t *cp; - uint8_t *cpend; - uint8_t private_key[PRIV_KEY_LEN]; - size_t len; - psa_status_t psa_ret = PSA_ERROR_BAD_STATE; - psa_status_t psa_cleanup_ret = PSA_ERROR_BAD_STATE; - psa_key_id_t kid; - psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; - psa_key_derivation_operation_t key_do = PSA_KEY_DERIVATION_OPERATION_INIT; - psa_algorithm_t key_do_alg; - int rc = -1; - - cp = (uint8_t *)bootutil_enc_key.key; - cpend = cp + *bootutil_enc_key.len; - - /* The psa_cipher_decrypt needs initialization vector of proper length at - * the beginning of the input buffer. - */ - uint8_t iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR) + - BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE]; - - psa_ret = psa_crypto_init(); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES crypto init failed %d", psa_ret); - return -1; - } - - /* - * Load the stored X25519 decryption private key - */ - rc = parse_x25519_enckey(&cp, cpend, private_key); - if (rc) { - return rc; - } - - psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY)); - psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DERIVE); - psa_set_key_algorithm(&kattr, PSA_ALG_ECDH); - - psa_ret = psa_import_key(&kattr, private_key, sizeof(private_key), &kid); - memset(private_key, 0, sizeof(private_key)); - psa_reset_key_attributes(&kattr); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("Built-in key import failed %d", psa_ret); - return -1; - } - - key_do_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)); - - psa_ret = psa_key_derivation_setup(&key_do, key_do_alg); - if (psa_ret != PSA_SUCCESS) { - psa_cleanup_ret = psa_destroy_key(kid); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("Built-in key destruction failed %d", psa_cleanup_ret); - } - BOOT_LOG_ERR("Key derivation setup failed %d", psa_ret); - return -1; - } - - /* Note: PSA 1.1.2 does not have psa_key_agreement that would be useful here - * as it could just add the derived key to the storage and return key id. - * Instead, we have to use the code below to generate derived key and put it - * into storage, to obtain the key id we can then use with psa_mac_* functions. - */ - psa_ret = psa_key_derivation_key_agreement(&key_do, PSA_KEY_DERIVATION_INPUT_SECRET, - kid, &buf[EC_PUBK_INDEX], - BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); - psa_cleanup_ret = psa_destroy_key(kid); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("Built-in key destruction failed %d", psa_cleanup_ret); - } - if (psa_ret != PSA_SUCCESS) { - psa_cleanup_ret = psa_key_derivation_abort(&key_do); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("Key derivation abort failed %d", psa_ret); - } - - BOOT_LOG_ERR("Key derivation failed %d", psa_ret); - return -1; - } - - /* Only info, no salt */ - psa_ret = psa_key_derivation_input_bytes(&key_do, PSA_KEY_DERIVATION_INPUT_INFO, - "MCUBoot_ECIES_v1", 16); - if (psa_ret != PSA_SUCCESS) { - psa_cleanup_ret = psa_key_derivation_abort(&key_do); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("Key derivation abort failed %d", psa_ret); - } - BOOT_LOG_ERR("Key derivation failed %d", psa_ret); - return -1; - } - - len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE; - psa_ret = psa_key_derivation_output_bytes(&key_do, derived_key, len); - psa_cleanup_ret = psa_key_derivation_abort(&key_do); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("Key derivation cleanup failed %d", psa_ret); - } - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("Key derivation failed %d", psa_ret); - return -1; - } - - /* The derived key consists of BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE bytes - * followed by BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE bytes. Both parts will - * be imported at the point where needed and discarded immediately after. - */ - psa_set_key_type(&kattr, PSA_KEY_TYPE_HMAC); - psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_VERIFY_MESSAGE); - psa_set_key_algorithm(&kattr, PSA_ALG_HMAC(PSA_ALG_SHA_256)); - - /* Import the MAC tag key part of derived key, that is the part that starts - * after BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE and has length of - * BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE bytes. - */ - psa_ret = psa_import_key(&kattr, - &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE], - BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, &kid); - psa_reset_key_attributes(&kattr); - if (psa_ret != PSA_SUCCESS) { - memset(derived_key, 0, sizeof(derived_key)); - BOOT_LOG_ERR("MAC key import failed %d", psa_ret); - return -1; - } - - /* Verify the MAC tag of the random encryption key */ - psa_ret = psa_mac_verify(kid, PSA_ALG_HMAC(PSA_ALG_SHA_256), - &buf[EC_CIPHERKEY_INDEX], BOOT_ENC_KEY_SIZE, - &buf[EC_TAG_INDEX], - BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); - psa_cleanup_ret = psa_destroy_key(kid); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("MAC key destruction failed %d", psa_cleanup_ret); - } - if (psa_ret != PSA_SUCCESS) { - memset(derived_key, 0, sizeof(derived_key)); - BOOT_LOG_ERR("MAC verification failed %d", psa_ret); - return -1; - } - - /* The derived key is used in AES decryption of random key */ - psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); - psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DECRYPT); - psa_set_key_algorithm(&kattr, PSA_ALG_CTR); - - /* Import the AES partition of derived key, the first 16 bytes */ - psa_ret = psa_import_key(&kattr, &derived_key[0], - BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, &kid); - memset(derived_key, 0, sizeof(derived_key)); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES key import failed %d", psa_ret); - return -1; - } - - /* Decrypt the random AES encryption key with AES and the key obtained - * at derivation. */ - memset(&iv_and_key[0], 0, PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)); - memcpy(&iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)], - &buf[EC_CIPHERKEY_INDEX], - sizeof(iv_and_key) - PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)); - - len = 0; - psa_ret = psa_cipher_decrypt(kid, PSA_ALG_CTR, iv_and_key, sizeof(iv_and_key), - enckey, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, &len); - memset(iv_and_key, 0, sizeof(iv_and_key)); - psa_cleanup_ret = psa_destroy_key(kid); - if (psa_cleanup_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("AES key destruction failed %d", psa_cleanup_ret); - } - if (psa_ret != PSA_SUCCESS || len != BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE) { - memset(enckey, 0, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE); - BOOT_LOG_ERR("Random key decryption failed %d", psa_ret); - return -1; - } - - 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 ret = 0; - psa_status_t psa_ret = PSA_ERROR_BAD_STATE; - psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t kid; - psa_cipher_operation_t psa_op; - size_t elen = 0; /* Decrypted length */ - - /* Fixme: calling psa_crypto_init multiple times is not a problem, - * yet the code here is only present because there is not general - * crypto init. */ - psa_ret = psa_crypto_init(); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); - ret = -1; - goto gone; - } - - psa_op = psa_cipher_operation_init(); - - /* Fixme: Import should happen when key is decrypted, but due to lack - * of key destruction there is no way to destroy key stored by - * psa other way than here. */ - psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); - psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_ENCRYPT); - psa_set_key_algorithm(&kattr, PSA_ALG_CTR); - - psa_ret = psa_import_key(&kattr, ctx->key, BOOT_ENC_KEY_SIZE, &kid); - psa_reset_key_attributes(&kattr); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES enc import key failed %d", psa_ret); - ret = -1; - goto gone; - } - - /* This could be done with psa_cipher_decrypt one-shot operation, but - * multi-part operation is used to avoid re-allocating input buffer - * to account for IV in front of data. - */ - psa_ret = psa_cipher_encrypt_setup(&psa_op, kid, PSA_ALG_CTR); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES enc setup failed %d", psa_ret); - ret = -1; - goto gone_with_key; - } - - /* Fixme: hardcoded counter size, but it is hardcoded everywhere */ - psa_ret = psa_cipher_set_iv(&psa_op, counter, 16); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES enc IV set failed %d", psa_ret); - ret = -1; - goto gone_after_setup; - } - - psa_ret = psa_cipher_update(&psa_op, m, mlen, c, mlen, &elen); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES enc encryption failed %d", psa_ret); - ret = -1; - goto gone_after_setup; - } - -gone_after_setup: - psa_ret = psa_cipher_abort(&psa_op); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("AES enc cipher abort failed %d", psa_ret); - /* Intentionally not changing the ret */ - } -gone_with_key: - /* Fixme: Should be removed once key is shared by id */ - psa_ret = psa_destroy_key(kid); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("AES enc destroy key failed %d", psa_ret); - /* Intentionally not changing the ret */ - } -gone: - return ret; -} - -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) -{ - int ret = 0; - psa_status_t psa_ret = PSA_ERROR_BAD_STATE; - psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t kid; - psa_cipher_operation_t psa_op; - size_t dlen = 0; /* Decrypted length */ - - /* Fixme: the init should already happen before calling the function, but - * somehow it does not, for example when recovering in swap. - */ - psa_ret = psa_crypto_init(); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); - ret = -1; - goto gone; - } - - psa_op = psa_cipher_operation_init(); - - /* Fixme: Import should happen when key is decrypted, but due to lack - * of key destruction there is no way to destroy key stored by - * psa other way than here. */ - psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); - psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DECRYPT); - psa_set_key_algorithm(&kattr, PSA_ALG_CTR); - - psa_ret = psa_import_key(&kattr, ctx->key, BOOT_ENC_KEY_SIZE, &kid); - psa_reset_key_attributes(&kattr); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES dec import key failed %d", psa_ret); - ret = -1; - goto gone; - } - - /* This could be done with psa_cipher_decrypt one-shot operation, but - * multi-part operation is used to avoid re-allocating input buffer - * to account for IV in front of data. - */ - psa_ret = psa_cipher_decrypt_setup(&psa_op, kid, PSA_ALG_CTR); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES dec setup failed %d", psa_ret); - ret = -1; - goto gone_with_key; - } - - /* Fixme: hardcoded counter size, but it is hardcoded everywhere */ - psa_ret = psa_cipher_set_iv(&psa_op, counter, 16); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES dec IV set failed %d", psa_ret); - ret = -1; - goto gone_after_setup; - } - - psa_ret = psa_cipher_update(&psa_op, c, clen, m, clen, &dlen); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES dec decryption failed %d", psa_ret); - ret = -1; - goto gone_after_setup; - } - -gone_after_setup: - psa_ret = psa_cipher_abort(&psa_op); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("PSA dec abort failed %d", psa_ret); - /* Intentionally not changing the ret */ - } -gone_with_key: - psa_ret = psa_destroy_key(kid); - if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_WRN("PSA dec key failed %d", psa_ret); - /* Intentionally not changing the ret */ - } -gone: - return ret; -} -#endif /* defined(MCUBOOT_ENC_IMAGES) */ diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 897edcad1..4e2423a08 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -9,11 +9,6 @@ #include "mcuboot_config/mcuboot_config.h" -#if defined(CONFIG_NRF_SECURITY) -/* We are not really using the MBEDTLS but need the ASN.1 parsing funcitons */ -#define MBEDTLS_ASN1_PARSE_C -#endif - #ifdef MCUBOOT_SIGN_ED25519 #include "bootutil/sign_key.h" @@ -26,14 +21,12 @@ #include "bootutil/crypto/common.h" #include "bootutil/crypto/sha.h" -#define EDDSA_SIGNATURE_LENGTH 64 - static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; #define NUM_ED25519_BYTES 32 extern int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[EDDSA_SIGNATURE_LENGTH], - const uint8_t public_key[NUM_ED25519_BYTES]); + const uint8_t signature[64], + const uint8_t public_key[32]); /* * Parse the public key used for signing. @@ -83,7 +76,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t *pubkey; uint8_t *end; - if (hlen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) { + if (hlen != IMAGE_HASH_SIZE || slen != 64) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } From d2f9af82a0b02c67adbf4e7c6f40eaceda3ba9cf Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 257/287] Revert "[nrf noup] zephyr: Add support for compressed image updates" This reverts commit 655eeacf16cfd090bb309ef06f940a943790e671. Signed-off-by: Dominik Ermel --- boot/bootutil/src/bootutil_misc.c | 80 +- boot/bootutil/src/image_validate.c | 226 ---- boot/bootutil/src/loader.c | 27 +- boot/zephyr/CMakeLists.txt | 6 - boot/zephyr/Kconfig | 10 +- boot/zephyr/decompression.c | 1115 ----------------- .../include/compression/decompression.h | 104 -- 7 files changed, 23 insertions(+), 1545 deletions(-) delete mode 100644 boot/zephyr/decompression.c delete mode 100644 boot/zephyr/include/compression/decompression.h diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index ac50eaa52..56859d515 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -42,11 +42,6 @@ #include "bootutil/enc_key.h" #endif -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - BOOT_LOG_MODULE_DECLARE(mcuboot); /* Currently only used by imgmgr */ @@ -389,76 +384,35 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) goto done; } -#ifdef MCUBOOT_DECOMPRESS_IMAGES - if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { - uint32_t tmp_size = 0; - - rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); - - if (rc) { - rc = BOOT_EBADIMAGE; - goto done; - } - - off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); - rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); - - if (rc) { - rc = BOOT_EBADIMAGE; - goto done; - } - - off += tmp_size; - - if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + - boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, - sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { rc = BOOT_EBADIMAGE; goto done; } - *size = off + info.it_tlv_tot; - } else { -#else - if (1) { -#endif - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); - - if (flash_area_read(fap, off, &info, sizeof(info))) { + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { rc = BOOT_EFLASH; goto done; } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { - rc = BOOT_EBADIMAGE; - goto done; - } - - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; - } - - *size = off + protect_tlv_size + info.it_tlv_tot; + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; } + *size = off + protect_tlv_size + info.it_tlv_tot; rc = 0; done: diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index b1a50f126..ec5d986df 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -40,15 +40,6 @@ #include "mcuboot_config/mcuboot_config.h" -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - -#include "bootutil/bootutil_log.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot); - #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -425,68 +416,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, FIH_DECLARE(security_counter_valid, FIH_FAILURE); #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - /* If the image is compressed, the integrity of the image must also be validated */ - if (MUST_DECOMPRESS(fap, image_index, hdr)) { - bool found_decompressed_size = false; - bool found_decompressed_sha = false; - bool found_decompressed_signature = false; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(fap)) { - rc = -1; - goto out; - } - - while (true) { - uint16_t expected_size = 0; - bool *found_flag = NULL; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - switch (type) { - case IMAGE_TLV_DECOMP_SIZE: - expected_size = sizeof(size_t); - found_flag = &found_decompressed_size; - break; - case IMAGE_TLV_DECOMP_SHA: - expected_size = IMAGE_HASH_SIZE; - found_flag = &found_decompressed_sha; - break; - case IMAGE_TLV_DECOMP_SIGNATURE: - found_flag = &found_decompressed_signature; - break; - default: - continue; - }; - - if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { - rc = -1; - goto out; - } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { - rc = -1; - goto out; - } - - *found_flag = true; - } - - rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); - if (rc) { - goto out; - } - } -#endif - rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); if (rc) { @@ -658,161 +587,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - /* Only after all previous verifications have passed, perform a dry-run of the decompression - * and ensure the image is valid - */ - if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { - image_hash_valid = 0; - FIH_SET(valid_signature, FIH_FAILURE); - - rc = bootutil_img_hash_decompress(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, - hash, seed, seed_len); - if (rc) { - goto out; - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - if (type == IMAGE_TLV_DECOMP_SHA) { - /* Verify the image hash. This must always be present. */ - if (len != sizeof(hash)) { - rc = -1; - goto out; - } - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); - if (rc) { - goto out; - } - - FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - image_hash_valid = 1; - } - } - - rc = !image_hash_valid; - if (rc) { - goto out; - } - -#ifdef EXPECTED_SIG_TLV -#ifdef EXPECTED_KEY_TLV - rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - if (type == EXPECTED_KEY_TLV) { - /* - * Determine which key we should be checking. - */ - if (len > KEY_BUF_SIZE) { - rc = -1; - goto out; - } -#ifndef MCUBOOT_HW_KEY - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); - if (rc) { - goto out; - } - key_id = bootutil_find_key(buf, len); -#else - rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); - if (rc) { - goto out; - } - key_id = bootutil_find_key(image_index, key_buf, len); -#endif /* !MCUBOOT_HW_KEY */ - /* - * The key may not be found, which is acceptable. There - * can be multiple signatures, each preceded by a key. - */ - } - } -#endif /* EXPECTED_KEY_TLV */ - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIGNATURE) { - /* Ignore this signature if it is out of bounds. */ - if (key_id < 0 || key_id >= bootutil_key_cnt) { - key_id = -1; - continue; - } - - if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { - rc = -1; - goto out; - } - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); - if (rc) { - goto out; - } - - FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), - buf, len, key_id); - key_id = -1; - } - } -#endif /* EXPECTED_SIG_TLV */ - } -#endif - -#ifdef EXPECTED_SIG_TLV - FIH_SET(fih_rc, valid_signature); -#endif - out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a561d5cb7..4c61c4217 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,11 +49,6 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - #ifdef __ZEPHYR__ #include #endif @@ -918,10 +913,10 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } #else - if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { - if (!boot_is_compressed_header_valid(hdr, fap, state)) { - return false; - } + if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && + (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) + { + return false; } #endif @@ -1135,7 +1130,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * attempts to validate and boot it. */ } - #if !defined(__BOOTSIM__) BOOT_LOG_ERR("Image in the %s slot is not valid!", (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); @@ -1612,9 +1606,6 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - struct image_header *hdr; -#endif TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); @@ -1640,16 +1631,6 @@ boot_copy_region(struct boot_loader_state *state, } #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - - if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { - /* Use alternative function for compressed images */ - return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, - BUF_SZ); - } -#endif - bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index fa9f4c68c..cdc32e346 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -259,12 +259,6 @@ if(CONFIG_BOOT_ENCRYPT_EC256) ) endif() -if(CONFIG_BOOT_DECOMPRESSION) - zephyr_library_sources( - decompression.c - ) -endif() - if(CONFIG_MCUBOOT_SERIAL) zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c) zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 8f84e9275..a13201969 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -818,10 +818,6 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool - depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) - depends on !SINGLE_APPLICATION_SLOT && !BOOT_ENCRYPT_IMAGE && BOOT_UPGRADE_ONLY - depends on UPDATEABLE_IMAGE_NUMBER = 1 - default y help Hidden symbol which should be selected if a system provided decompression support. @@ -829,8 +825,6 @@ if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION bool "Decompression" - select NRF_COMPRESS_CLEANUP - select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to @@ -839,9 +833,9 @@ menuconfig BOOT_DECOMPRESSION if BOOT_DECOMPRESSION config BOOT_DECOMPRESSION_BUFFER_SIZE - int + int "Write buffer size" range 16 16384 - default NRF_COMPRESS_CHUNK_SIZE + default 4096 help The size of a secondary buffer used for writing decompressed data to the storage device. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c deleted file mode 100644 index 062cdbc61..000000000 --- a/boot/zephyr/decompression.c +++ /dev/null @@ -1,1115 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include "compression/decompression.h" -#include "bootutil/crypto/sha.h" -#include "bootutil/bootutil_log.h" - -#if !defined(__BOOTSIM__) -#define TARGET_STATIC static -#else -#define TARGET_STATIC -#endif - -#if defined(MCUBOOT_SIGN_RSA) -#if MCUBOOT_SIGN_RSA_LEN == 2048 -#define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS -#elif MCUBOOT_SIGN_RSA_LEN == 3072 -#define EXPECTED_SIG_TLV IMAGE_TLV_RSA3072_PSS -#endif -#elif defined(MCUBOOT_SIGN_EC256) || \ - defined(MCUBOOT_SIGN_EC384) || \ - defined(MCUBOOT_SIGN_EC) -#define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA_SIG -#elif defined(MCUBOOT_SIGN_ED25519) -#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 -#endif - -/* Number of times that consumed data by decompression system can be 0 in a row before aborting */ -#define OFFSET_ZERO_CHECK_TIMES 3 - -BOOT_LOG_MODULE_DECLARE(mcuboot); - -static int boot_sha_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, uint32_t protected_size, - uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx); - -bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, - struct boot_loader_state *state) -{ - /* Image is compressed in secondary slot, need to check if fits into the primary slot */ - bool opened_flash_area = false; - int primary_fa_id; - int rc; - int size_check; - int size; - uint32_t protected_tlvs_size; - uint32_t decompressed_size; - - if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { - opened_flash_area = true; - } - - primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); - rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - assert(rc == 0); - - size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - - if (opened_flash_area) { - (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - } - - rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); - - if (rc) { - return false; - } - - if (!boot_u32_safe_add(&size, decompressed_size, hdr->ih_hdr_size)) { - return false; - } - - rc = boot_size_protected_tlvs(hdr, fap, &protected_tlvs_size); - - if (rc) { - return false; - } - - if (!boot_u32_safe_add(&size, size, protected_tlvs_size)) { - return false; - } - - if (size >= size_check) { - BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", - size, size_check); - - return false; - } - - return true; -} - -int bootutil_img_hash_decompress(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 *hash_result, - uint8_t *seed, int seed_len) -{ - int rc; - uint32_t read_pos = 0; - uint32_t write_pos = 0; - uint32_t protected_tlv_size = 0; - uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression = NULL; - TARGET_STATIC struct image_header modified_hdr; - bootutil_sha_context sha_ctx; - uint8_t flash_erased_value; - - bootutil_sha_init(&sha_ctx); - - /* Setup decompression system */ -#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { -#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { -#endif - /* Compressed image does not use the correct compression type which is supported by this - * build - */ - BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); - rc = BOOT_EBADIMAGE; - - goto finish_without_clean; - } - - compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { - /* Compression library missing or missing required function pointer */ - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - - goto finish_without_clean; - } - - rc = compression->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - - goto finish_without_clean; - } - - /* We need a modified header which has the updated sizes, start with the original header */ - memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); - - /* Extract the decompressed image size from the protected TLV, set it and remove the - * compressed image flags - */ - rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; - modified_hdr.ih_img_size = decompressed_image_size; - - /* Calculate the protected TLV size, these will not include the decompressed - * sha/size/signature entries - */ - rc = boot_size_protected_tlvs(hdr, fap, &protected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - modified_hdr.ih_protect_tlv_size = protected_tlv_size; - bootutil_sha_update(&sha_ctx, &modified_hdr, sizeof(modified_hdr)); - read_pos = sizeof(modified_hdr); - flash_erased_value = flash_area_erased_val(fap); - memset(tmp_buf, flash_erased_value, tmp_buf_sz); - - while (read_pos < modified_hdr.ih_hdr_size) { - uint32_t copy_size = tmp_buf_sz; - - if ((read_pos + copy_size) > modified_hdr.ih_hdr_size) { - copy_size = modified_hdr.ih_hdr_size - read_pos; - } - - bootutil_sha_update(&sha_ctx, tmp_buf, copy_size); - read_pos += copy_size; - } - - /* Read in compressed data, decompress and add to hash calculation */ - read_pos = 0; - - while (read_pos < hdr->ih_img_size) { - uint32_t copy_size = hdr->ih_img_size - read_pos; - uint32_t tmp_off = 0; - uint8_t offset_zero_check = 0; - - if (copy_size > tmp_buf_sz) { - copy_size = tmp_buf_sz; - } - - rc = flash_area_read(fap, (hdr->ih_hdr_size + read_pos), tmp_buf, copy_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; - } - - /* Decompress data in chunks, writing it back with a larger write offset of the primary - * slot than read size of the secondary slot - */ - while (tmp_off < copy_size) { - uint32_t offset = 0; - uint8_t *output = NULL; - uint32_t output_size = 0; - uint32_t chunk_size; - bool last_packet = false; - - chunk_size = compression->decompress_bytes_needed(NULL); - - if (chunk_size > (copy_size - tmp_off)) { - chunk_size = (copy_size - tmp_off); - } - - if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { - last_packet = true; - } - - rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset, - &output, &output_size); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - - goto finish; - } - - write_pos += output_size; - - if (write_pos > decompressed_image_size) { - BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", - write_pos); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - /* Additional dry-run validity checks */ - if (last_packet == true && write_pos == 0) { - /* Last packet and we still have no output, this is a faulty update */ - BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - if (offset == 0) { - /* If the decompression system continually consumes 0 bytes, then there is a - * problem with this update image, abort and mark image as bad - */ - if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { - BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - ++offset_zero_check; - - break; - } else { - offset_zero_check = 0; - } - - if (output_size > 0) { - bootutil_sha_update(&sha_ctx, output, output_size); - } - - tmp_off += offset; - } - - read_pos += copy_size; - } - - /* If there are any protected TLVs present, add them after the main decompressed image */ - if (modified_hdr.ih_protect_tlv_size > 0) { - rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, - tmp_buf_sz, &sha_ctx); - } - - bootutil_sha_finish(&sha_ctx, hash_result); - -finish: - /* Clean up decompression system */ - (void)compression->deinit(NULL); - -finish_without_clean: - bootutil_sha_drop(&sha_ctx); - - return rc; -} - -static int boot_copy_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_dst, - uint32_t protected_size, uint8_t *buf, size_t buf_size, - uint16_t *buf_pos, uint32_t *written) -{ - int rc; - uint32_t off; - uint32_t write_pos = 0; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, - .it_tlv_tot = protected_size, - }; - uint16_t info_size_left = sizeof(tlv_info_header); - - while (info_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (info_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; - - if (single_copy_size > info_size_left) { - single_copy_size = info_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - - info_size_left], single_copy_size); - *buf_pos += single_copy_size; - info_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { - /* Skip these TLVs as they are not needed */ - continue; - } else { - uint16_t header_size_left = sizeof(tlv_header); - uint16_t data_size_left = len; - - tlv_header.it_type = type; - tlv_header.it_len = len; - - while (header_size_left > 0 || data_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - uint8_t *tlv_header_address = (uint8_t *)&tlv_header; - - if (header_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > header_size_left) { - single_copy_size = header_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - - header_size_left], - single_copy_size); - *buf_pos += single_copy_size; - copy_size -= single_copy_size; - header_size_left -= single_copy_size; - } - - if (data_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > data_size_left) { - single_copy_size = data_size_left; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + (len - data_size_left)), - &buf[*buf_pos], single_copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - - goto out; - } - - *buf_pos += single_copy_size; - data_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - } - } - - *written = write_pos; - -out: - return rc; -} - -static int boot_sha_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, uint32_t protected_size, - uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx) -{ - int rc; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, - .it_tlv_tot = protected_size, - }; - - bootutil_sha_update(sha_ctx, &tlv_info_header, sizeof(tlv_info_header)); - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); - if (rc) { - goto out; - } - - while (true) { - uint32_t read_off = 0; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { - /* Skip these TLVs as they are not needed */ - continue; - } - - tlv_header.it_type = type; - tlv_header.it_len = len; - - bootutil_sha_update(sha_ctx, &tlv_header, sizeof(tlv_header)); - - while (read_off < len) { - uint32_t copy_size = buf_size; - - if (copy_size > (len - read_off)) { - copy_size = len - read_off; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + read_off), buf, copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + read_off), copy_size, fap_src->fa_id, rc); - - goto out; - } - - bootutil_sha_update(sha_ctx, buf, copy_size); - read_off += copy_size; - } - } - -out: - return rc; -} - -int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *sz) -{ - int rc = 0; - uint32_t tlv_size; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - - *sz = 0; - tlv_size = hdr->ih_protect_tlv_size; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { - /* Exclude these TLVs as they will be copied to the unprotected area */ - tlv_size -= len + sizeof(struct image_tlv); - } - } - - if (!rc) { - if (tlv_size == sizeof(struct image_tlv_info)) { - /* If there are no entries then omit protected TLV section entirely */ - tlv_size = 0; - } - - *sz = tlv_size; - } - -out: - return rc; -} - -int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *sz) -{ - int rc = 0; - uint32_t tlv_size; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - - *sz = 0; - tlv_size = sizeof(struct image_tlv_info); - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } else if (bootutil_tlv_iter_is_prot(&it, off) && type != IMAGE_TLV_DECOMP_SHA && - type != IMAGE_TLV_DECOMP_SIGNATURE) { - /* Include size of protected hash and signature as these will be replacing the - * original ones - */ - continue; - } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { - /* Exclude the original unprotected TLVs for signature and hash, the length of the - * signature of the compressed data might not be the same size as the signaute of the - * decompressed data, as is the case when using ECDSA-P256 - */ - continue; - } - - tlv_size += len + sizeof(struct image_tlv); - } - - if (!rc) { - if (tlv_size == sizeof(struct image_tlv_info)) { - /* If there are no entries in the unprotected TLV section then there is something wrong - * with this image - */ - BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); - rc = BOOT_EBADIMAGE; - - goto out; - } - - *sz = tlv_size; - } - -out: - return rc; -} - -static int boot_copy_unprotected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_dst, - uint32_t unprotected_size, uint8_t *buf, size_t buf_size, - uint16_t *buf_pos, uint32_t *written) -{ - int rc; - uint32_t write_pos = 0; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv_iter it_protected; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_INFO_MAGIC, - .it_tlv_tot = unprotected_size, - }; - uint16_t info_size_left = sizeof(tlv_info_header); - - while (info_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (info_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; - - if (single_copy_size > info_size_left) { - single_copy_size = info_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - - info_size_left], single_copy_size); - *buf_pos += single_copy_size; - info_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, false); - if (rc) { - goto out; - } - - while (true) { - uint16_t header_size_left = sizeof(tlv_header); - uint16_t data_size_left; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } else if (bootutil_tlv_iter_is_prot(&it, off)) { - /* Skip protected TLVs */ - continue; - } - - /* Change the values of these fields from having the data in the compressed image - * unprotected TLV (which is valid only for the compressed image data) to having the - * fields in the protected TLV section (which is valid for the decompressed image data). - * The compressed data is no longer needed - */ - if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { - rc = bootutil_tlv_iter_begin(&it_protected, hdr, fap_src, (type == EXPECTED_HASH_TLV ? - IMAGE_TLV_DECOMP_SHA : - IMAGE_TLV_DECOMP_SIGNATURE), - true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it_protected, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - } - - if (type == IMAGE_TLV_DECOMP_SHA) { - type = EXPECTED_HASH_TLV; - } else { - type = EXPECTED_SIG_TLV; - } - } - - data_size_left = len; - tlv_header.it_type = type; - tlv_header.it_len = len; - - while (header_size_left > 0 || data_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (header_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_header_address = (uint8_t *)&tlv_header; - - if (single_copy_size > header_size_left) { - single_copy_size = header_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - header_size_left], - single_copy_size); - *buf_pos += single_copy_size; - copy_size -= single_copy_size; - header_size_left -= single_copy_size; - } - - if (data_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > data_size_left) { - single_copy_size = data_size_left; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + len - data_size_left), - &buf[*buf_pos], single_copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - - goto out; - } - - *buf_pos += single_copy_size; - data_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - } - - *written = write_pos; - -out: - return rc; -} - -int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_src, - uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size) -{ - int rc; - uint32_t pos = 0; - uint16_t decomp_buf_size = 0; - uint16_t write_alignment; - uint32_t write_pos = 0; - uint32_t protected_tlv_size = 0; - uint32_t unprotected_tlv_size = 0; - uint32_t tlv_write_size = 0; - uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression = NULL; - struct image_header *hdr; - TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4))); - TARGET_STATIC struct image_header modified_hdr; - - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - - /* Setup decompression system */ -#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { -#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { -#endif - /* Compressed image does not use the correct compression type which is supported by this - * build - */ - BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { - /* Compression library missing or missing required function pointer */ - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - - goto finish; - } - - rc = compression->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - - goto finish; - } - - write_alignment = flash_area_align(fap_dst); - - memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); - - rc = bootutil_get_img_decomp_size(hdr, fap_src, &decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; - modified_hdr.ih_img_size = decompressed_image_size; - - /* Calculate protected TLV size for target image once items are removed */ - rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - modified_hdr.ih_protect_tlv_size = protected_tlv_size; - - rc = boot_size_unprotected_tlvs(hdr, fap_src, &unprotected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - - goto finish; - } - - /* Write out the image header first, this should be a multiple of the write size */ - rc = flash_area_write(fap_dst, off_dst, &modified_hdr, sizeof(modified_hdr)); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; - } - - /* Read in, decompress and write out data */ - while (pos < hdr->ih_img_size) { - uint32_t copy_size = hdr->ih_img_size - pos; - uint32_t tmp_off = 0; - - if (copy_size > buf_size) { - copy_size = buf_size; - } - - rc = flash_area_read(fap_src, off_src + hdr->ih_hdr_size + pos, buf, copy_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; - } - - /* Decompress data in chunks, writing it back with a larger write offset of the primary - * slot than read size of the secondary slot - */ - while (tmp_off < copy_size) { - uint32_t offset = 0; - uint32_t output_size = 0; - uint32_t chunk_size; - uint32_t compression_buffer_pos = 0; - uint8_t *output = NULL; - bool last_packet = false; - - chunk_size = compression->decompress_bytes_needed(NULL); - - if (chunk_size > (copy_size - tmp_off)) { - chunk_size = (copy_size - tmp_off); - } - - if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { - last_packet = true; - } - - rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset, - &output, &output_size); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - - goto finish; - } - - /* Copy data to secondary buffer for writing out */ - while (output_size > 0) { - uint32_t data_size = (sizeof(decomp_buf) - decomp_buf_size); - - if (data_size > output_size) { - data_size = output_size; - } - - memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], data_size); - compression_buffer_pos += data_size; - - decomp_buf_size += data_size; - output_size -= data_size; - - /* Write data out from secondary buffer when it is full */ - if (decomp_buf_size == sizeof(decomp_buf)) { - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, sizeof(decomp_buf)); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), sizeof(decomp_buf), - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; - } - - write_pos += sizeof(decomp_buf); - decomp_buf_size = 0; - } - } - - tmp_off += offset; - } - - pos += copy_size; - } - - /* Clean up decompression system */ - (void)compression->deinit(NULL); - - if (protected_tlv_size > 0) { - rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + - write_pos), protected_tlv_size, - decomp_buf, DECOMP_BUF_SIZE, &decomp_buf_size, - &tlv_write_size); - - if (rc) { - BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - - goto finish; - } - - write_pos += tlv_write_size; - } - - tlv_write_size = 0; - rc = boot_copy_unprotected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + - write_pos), unprotected_tlv_size, - decomp_buf, DECOMP_BUF_SIZE, &decomp_buf_size, - &tlv_write_size); - - if (rc) { - BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - - goto finish; - } - - write_pos += tlv_write_size; - - /* Check if we have unwritten data buffered up and, if so, write it out */ - if (decomp_buf_size > 0) { - uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); - - /* Check if additional write padding should be applied to meet the minimum write size */ - if (write_padding_size) { - uint8_t flash_erased_value; - - flash_erased_value = flash_area_erased_val(fap_dst); - memset(&decomp_buf[decomp_buf_size], flash_erased_value, write_padding_size); - decomp_buf_size += write_padding_size; - } - - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf, - decomp_buf_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; - } - - write_pos += decomp_buf_size; - decomp_buf_size = 0; - } - -finish: - memset(decomp_buf, 0, sizeof(decomp_buf)); - - return rc; -} - -int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *img_decomp_size) -{ - struct image_tlv_iter it; - uint32_t off; - uint16_t len; - int32_t rc; - - if (hdr == NULL || fap == NULL || img_decomp_size == NULL) { - return BOOT_EBADARGS; - } else if (hdr->ih_protect_tlv_size == 0) { - return BOOT_EBADIMAGE; - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIZE, true); - - if (rc) { - return rc; - } - - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - - if (rc != 0) { - return -1; - } - - if (len != sizeof(*img_decomp_size)) { - BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); - - return BOOT_EBADIMAGE; - } - - rc = LOAD_IMAGE_DATA(hdr, fap, off, img_decomp_size, len); - - if (rc) { - BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off, len, fap->fa_id, rc); - - return BOOT_EFLASH; - } - - return 0; -} diff --git a/boot/zephyr/include/compression/decompression.h b/boot/zephyr/include/compression/decompression.h deleted file mode 100644 index f8a676ac5..000000000 --- a/boot/zephyr/include/compression/decompression.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef H_DECOMPRESSION_ -#define H_DECOMPRESSION_ - -#include -#include -#include -#include "bootutil/bootutil.h" -#include "bootutil/bootutil_public.h" -#include "bootutil/image.h" -#include "../src/bootutil_priv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Checks if a compressed image header is valid. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param state Bootloader state object. - * - * @return true if valid; false if invalid. - */ -bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, - struct boot_loader_state *state); - -/** - * Reads in compressed image data from a slot, decompresses it and writes it out to a destination - * slot, including corresponding image headers and TLVs. - * - * @param state Bootloader state object. - * @param fap_src Flash area of the source slot. - * @param fap_dst Flash area of the destination slot. - * @param off_src Offset of the source slot to read from (should be 0). - * @param off_dst Offset of the destination slot to write to (should be 0). - * @param sz Size of the source slot data. - * @param buf Temporary buffer for reading data from. - * @param buf_size Size of temporary buffer. - * - * @return 0 on success; nonzero on failure. - */ -int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_src, - uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size); - -/** - * Gets the total data size (excluding headers and TLVs) of a compressed image when it is - * decompressed. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param img_decomp_size Pointer to variable that will be updated with the decompressed image - * size. - * - * @return 0 on success; nonzero on failure. - */ -int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *img_decomp_size); - -/** - * Calculate MCUboot-compatible image hash of compressed image slot. - * - * @param enc_state Not currently used, set to NULL. - * @param image_index Image number. - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param tmp_buf Temporary buffer for reading data from. - * @param tmp_buf_sz Size of temporary buffer. - * @param hash_result Pointer to a variable that will be updated with the image hash. - * @param seed Not currently used, set to NULL. - * @param seed_len Not currently used, set to 0. - * - * @return 0 on success; nonzero on failure. - */ -int bootutil_img_hash_decompress(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 *hash_result, - uint8_t *seed, int seed_len); - -/** - * Calculates the size that the compressed image protected TLV section will occupy once the image - * has been decompressed. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param sz Pointer to variable that will be updated with the protected TLV size. - * - * @return 0 on success; nonzero on failure. - */ -int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap_src, - uint32_t *sz); - -#ifdef __cplusplus -} -#endif - -#endif /* H_DECOMPRESSION_ */ From 67faef4bb4dfdf8b1aa8d35d322b87b39f54e4c7 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 14:44:12 +0000 Subject: [PATCH 258/287] Revert "[nrf noup] zephyr: Fix path variables" This reverts commit 4943e2f425738025e48efc74d323884c4effdf4d. Signed-off-by: Dominik Ermel --- boot/zephyr/CMakeLists.txt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index cdc32e346..6522f8572 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -27,20 +27,21 @@ assert_exists(FIAT_DIR) # Path to mbed-tls' asn1 parser library. set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") assert_exists(MBEDTLS_ASN1_DIR) -set(MCUBOOT_NRF_EXT_DIR "${MCUBOOT_DIR}/ext/nrf") +set(NRF_DIR "${MCUBOOT_DIR}/ext/nrf") if(CONFIG_BOOT_USE_NRF_CC310_BL) - if(NOT EXISTS ${ZEPHYR_NRFXLIB_MODULE_DIR}) - message(FATAL_ERROR " +set(NRFXLIB_DIR ${ZEPHYR_BASE}/../nrfxlib) +if(NOT EXISTS ${NRFXLIB_DIR}) + message(FATAL_ERROR " ------------------------------------------------------------------------ - No such file or directory: ${ZEPHYR_NRFXLIB_MODULE_DIR} + No such file or directory: ${NRFXLIB_DIR} The current configuration enables nRF CC310 crypto accelerator hardware with the `CONFIG_BOOT_USE_NRF_CC310_BL` option. Please follow `ext/nrf/README.md` guide to fix your setup or use tinycrypt instead of the HW accelerator. To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") - endif() +endif() endif() zephyr_library_include_directories( @@ -176,8 +177,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) ${TINYCRYPT_DIR}/source/utils.c ) elseif(CONFIG_BOOT_USE_NRF_CC310_BL) - zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) - zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) + zephyr_library_sources(${NRF_DIR}/cc310_glue.c) + zephyr_library_include_directories(${NRF_DIR}) zephyr_link_libraries(nrfxlib_crypto) elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) zephyr_include_directories(${BL_CRYPTO_DIR}/../include) From 7ab23b4518c9a91747e3abb19d9d7cf23fe197f5 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 22 Jan 2025 16:03:53 +0000 Subject: [PATCH 259/287] [nrf fromtree] zephyr: Fix usage of CONFIG_MBEDTLS_BUILTIN and ASN1 This commit fixes issue where even if Zephyr provided mbedTLS module was used, ASN1 decoding procedures have been taken from MCUboot own version of mbedTLS extracted sources for these functions. To be able to do that this commit changes config file used with mbedTLS with the one provided from Zephyr (the generic one), which allows to select required mbedTLS features via Kconfig options exposed by Zephyr. Signed-off-by: Dominik Ermel (cherry picked from commit 3f6721346f050edf69ce001da2f38be7060f96d9) --- boot/zephyr/CMakeLists.txt | 34 ++++++++++++++++++++++------------ boot/zephyr/Kconfig | 11 ++++++++++- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 6522f8572..b0c119da4 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -25,8 +25,10 @@ assert_exists(TINYCRYPT_SHA512_DIR) set(FIAT_DIR "${MCUBOOT_DIR}/ext/fiat") assert_exists(FIAT_DIR) # Path to mbed-tls' asn1 parser library. -set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") -assert_exists(MBEDTLS_ASN1_DIR) +if(NOT CONFIG_MBEDTLS_BUILTIN) + set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") + assert_exists(MBEDTLS_ASN1_DIR) +endif() set(NRF_DIR "${MCUBOOT_DIR}/ext/nrf") if(CONFIG_BOOT_USE_NRF_CC310_BL) @@ -154,14 +156,16 @@ if(CONFIG_BOOT_RAM_LOAD OR CONFIG_SINGLE_APPLICATION_SLOT_RAM_LOAD) endif() if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) - zephyr_library_include_directories( - ${MBEDTLS_ASN1_DIR}/include + if(MBEDTLS_ASN1_DIR) + zephyr_library_include_directories( + ${MBEDTLS_ASN1_DIR}/include ) - zephyr_library_sources( - # Additionally pull in just the ASN.1 parser from mbedTLS. - ${MBEDTLS_ASN1_DIR}/src/asn1parse.c - ${MBEDTLS_ASN1_DIR}/src/platform_util.c + zephyr_library_sources( + # Additionally pull in just the ASN.1 parser from mbedTLS. + ${MBEDTLS_ASN1_DIR}/src/asn1parse.c + ${MBEDTLS_ASN1_DIR}/src/platform_util.c ) + endif() if(CONFIG_BOOT_USE_TINYCRYPT) # When using ECDSA signatures, pull in our copy of the tinycrypt library. zephyr_library_include_directories( @@ -213,8 +217,17 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_RSA) endif() elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) if(CONFIG_BOOT_USE_TINYCRYPT) + if(MBEDTLS_ASN1_DIR) + zephyr_library_include_directories( + ${MBEDTLS_ASN1_DIR}/include + ) + zephyr_library_sources( + # Additionally pull in just the ASN.1 parser from mbedTLS. + ${MBEDTLS_ASN1_DIR}/src/asn1parse.c + ${MBEDTLS_ASN1_DIR}/src/platform_util.c + ) + endif() zephyr_library_include_directories( - ${MBEDTLS_ASN1_DIR}/include ${BOOT_DIR}/zephyr/include ${TINYCRYPT_DIR}/include ${TINYCRYPT_SHA512_DIR}/include @@ -223,9 +236,6 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) ${TINYCRYPT_DIR}/source/sha256.c ${TINYCRYPT_DIR}/source/utils.c ${TINYCRYPT_SHA512_DIR}/source/sha512.c - # Additionally pull in just the ASN.1 parser from mbedTLS. - ${MBEDTLS_ASN1_DIR}/src/asn1parse.c - ${MBEDTLS_ASN1_DIR}/src/platform_util.c ) zephyr_library_compile_definitions( MBEDTLS_CONFIG_FILE="${CMAKE_CURRENT_LIST_DIR}/include/mcuboot-mbedtls-cfg.h" diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a13201969..512f485f6 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -134,6 +134,8 @@ config BOOT_SIGNATURE_TYPE_RSA bool "RSA signatures" select BOOT_USE_MBEDTLS select MBEDTLS + select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN + select MBEDTLS_KEY_EXCHANGE_RSA_ENABLED if MBEDTLS_BUILTIN select BOOT_ENCRYPTION_SUPPORT select BOOT_IMG_HASH_ALG_SHA256_ALLOW @@ -184,6 +186,8 @@ config BOOT_ED25519_MBEDTLS bool "Use mbedTLS" select BOOT_USE_MBEDTLS select MBEDTLS + select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN + endchoice endif @@ -228,8 +232,13 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +if MBEDTLS + config MBEDTLS_CFG_FILE - default "mcuboot-mbedtls-cfg.h" + default "config-tls-generic.h" if MBEDTLS_BUILTIN + default "mcuboot-mbedtls-cfg.h" if BOOT_USE_MBEDTLS + +endif config BOOT_HW_KEY bool "Use HW key for image verification" From e3ce7c39563926e12c3e1ff79df3dae63350aa1a Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 2 Oct 2024 11:05:20 +0000 Subject: [PATCH 260/287] [nrf fromtree] bootutil: Allow SHA512 with TinyCrypt The commit enables SHA512 support, for image hashing, with TinyCrypt. Although on 32bit machines the SHA256 will be faster than SHA512, benefit of enabling the SHA512 is that you have only one algorithm compiled in which reduces size of code. Signed-off-by: Dominik Ermel (cherry picked from commit f72158ff313ac771c3b510adf64685cabf34f8c0) --- boot/bootutil/include/bootutil/crypto/sha.h | 20 ++++++++++++++++++++ boot/bootutil/src/image_ed25519.c | 9 ++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index 6ba8d946d..b83a3ec40 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -70,7 +70,11 @@ #endif /* MCUBOOT_USE_MBED_TLS */ #if defined(MCUBOOT_USE_TINYCRYPT) +#if defined(MCUBOOT_SHA512) + #include +#else #include +#endif #include #endif /* MCUBOOT_USE_TINYCRYPT */ @@ -193,11 +197,19 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, #endif /* MCUBOOT_USE_MBED_TLS */ #if defined(MCUBOOT_USE_TINYCRYPT) +#if defined(MCUBOOT_SHA512) +typedef struct tc_sha512_state_struct bootutil_sha_context; +#else typedef struct tc_sha256_state_struct bootutil_sha_context; +#endif static inline int bootutil_sha_init(bootutil_sha_context *ctx) { +#if defined(MCUBOOT_SHA512) + tc_sha512_init(ctx); +#else tc_sha256_init(ctx); +#endif return 0; } @@ -211,13 +223,21 @@ static inline int bootutil_sha_update(bootutil_sha_context *ctx, const void *data, uint32_t data_len) { +#if defined(MCUBOOT_SHA512) + return tc_sha512_update(ctx, data, data_len); +#else return tc_sha256_update(ctx, data, data_len); +#endif } static inline int bootutil_sha_finish(bootutil_sha_context *ctx, uint8_t *output) { +#if defined(MCUBOOT_SHA512) + return tc_sha512_final(output, ctx); +#else return tc_sha256_final(output, ctx); +#endif } #endif /* MCUBOOT_USE_TINYCRYPT */ diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 4e2423a08..4a5755b66 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -21,12 +21,14 @@ #include "bootutil/crypto/common.h" #include "bootutil/crypto/sha.h" +#define EDDSA_SIGNATURE_LENGTH 64 + static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; #define NUM_ED25519_BYTES 32 extern int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[64], - const uint8_t public_key[32]); + const uint8_t signature[EDDSA_SIGNATURE_LENGTH], + const uint8_t public_key[NUM_ED25519_BYTES]); /* * Parse the public key used for signing. @@ -76,7 +78,8 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t *pubkey; uint8_t *end; - if (hlen != IMAGE_HASH_SIZE || slen != 64) { + if (hlen != IMAGE_HASH_SIZE || + slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } From 411c06e61f2be24251c15042f69f77108f49b29a Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 5 Sep 2024 10:53:17 +0000 Subject: [PATCH 261/287] [nrf fromtree] bootutil: Enable hash calculation directly on storage The commit add support for passing storage device address space to hash calculation functions, which allows to use hardware accelerated hash calculation on storage. This feature only works when image encryption is not enabled and all slots are defined within internal storage of device. The feature is enabled with MCUboot configuration option MCUBOOT_HASH_STORAGE_DIRECTLY. Signed-off-by: Dominik Ermel (cherry picked from commit b43b8c80b87b9cf7a8efe35b7cdaea49ed0b457f) --- boot/bootutil/src/image_validate.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ec5d986df..ae22e27ed 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -68,13 +68,15 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, uint8_t *seed, int seed_len) { bootutil_sha_context sha_ctx; - uint32_t blk_sz; uint32_t size; uint16_t hdr_size; - uint32_t off; - int rc; uint32_t blk_off; uint32_t tlv_off; +#if !defined(MCUBOOT_HASH_STORAGE_DIRECTLY) + int rc; + uint32_t off; + uint32_t blk_sz; +#endif #if (BOOT_IMAGE_NUMBER == 1) || !defined(MCUBOOT_ENC_IMAGES) || \ defined(MCUBOOT_RAM_LOAD) @@ -117,6 +119,12 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, /* If protected TLVs are present they are also hashed. */ size += hdr->ih_protect_tlv_size; +#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY + /* No chunk loading, storage is mapped to address space and can + * be directly given to hashing function. + */ + bootutil_sha_update(&sha_ctx, (void *)flash_area_get_off(fap), size); +#else /* MCUBOOT_HASH_STORAGE_DIRECTLY */ #ifdef MCUBOOT_RAM_LOAD bootutil_sha_update(&sha_ctx, (void*)(IMAGE_RAM_BASE + hdr->ih_load_addr), @@ -161,6 +169,7 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, bootutil_sha_update(&sha_ctx, tmp_buf, blk_sz); } #endif /* MCUBOOT_RAM_LOAD */ +#endif /* MCUBOOT_HASH_STORAGE_DIRECTLY */ bootutil_sha_finish(&sha_ctx, hash_result); bootutil_sha_drop(&sha_ctx); From 16750b3086de90301aadaead72235706747ef9d2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 6 Sep 2024 16:16:28 +0000 Subject: [PATCH 262/287] [nrf fromtree] bootutil: PureEdDSA using ED25519 The commit adds support for PureEdDSA, which validates signature of image rather than hash. This is most secure, available, ED25519 usage in MCUboot, but due to requirement of PureEdDSA to be able to calculate signature at whole message at once, here image, it only works on setups where entire image can be mapped to device address space, so that PSA functions calculating the signature can see the whole image at once. The feature is enabled with MCUBOOT_SIGN_PURE MCUboot configuration option. Signed-off-by: Dominik Ermel (cherry picked from commit de9bc3d006b2ac44f056bb66ef1b2f60d15df11d) --- boot/bootutil/src/bootutil_priv.h | 9 +++ boot/bootutil/src/image_ed25519.c | 59 ++++++++++++++++-- boot/bootutil/src/image_validate.c | 96 ++++++++++++++++++++++++++++-- docs/design.md | 2 + 4 files changed, 154 insertions(+), 12 deletions(-) diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index 345933a5f..5703f627a 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -267,9 +267,18 @@ struct boot_loader_state { #endif /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */ }; +/* The function is intended for verification of image hash against + * provided signature. + */ fih_ret bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t key_id); +/* The function is intended for direct verification of image + * against provided signature. + */ +fih_ret bootutil_verify_img(uint8_t *img, uint32_t size, + uint8_t *sig, size_t slen, uint8_t key_id); + fih_ret boot_fih_memequal(const void *s1, const void *s2, size_t n); int boot_find_status(int image_index, const struct flash_area **fap); diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 4a5755b66..238c9d671 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -69,17 +69,23 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } -fih_ret -bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, - uint8_t key_id) +/* Signature verification base function. + * The function takes buffer of specified length and tries to verify + * it against provided signature. + * The function does key import and checks whether signature is + * of expected length. + */ +static fih_ret +bootutil_verify(uint8_t *buf, uint32_t blen, + uint8_t *sig, size_t slen, + uint8_t key_id) { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); uint8_t *pubkey; uint8_t *end; - if (hlen != IMAGE_HASH_SIZE || - slen != EDDSA_SIGNATURE_LENGTH) { + if (slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -93,7 +99,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, goto out; } - rc = ED25519_verify(hash, IMAGE_HASH_SIZE, sig, pubkey); + rc = ED25519_verify(buf, blen, sig, pubkey); if (rc == 0) { /* if verify returns 0, there was an error. */ @@ -107,4 +113,45 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, FIH_RET(fih_rc); } +/* Hash signature verification function. + * Verifies hash against provided signature. + * The function verifies that hash is of expected size and then + * calls bootutil_verify to do the signature verification. + */ +fih_ret +bootutil_verify_sig(uint8_t *hash, uint32_t hlen, + uint8_t *sig, size_t slen, + uint8_t key_id) +{ + FIH_DECLARE(fih_rc, FIH_FAILURE); + + if (hlen != IMAGE_HASH_SIZE) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + FIH_CALL(bootutil_verify, fih_rc, hash, IMAGE_HASH_SIZE, sig, + slen, key_id); + +out: + FIH_RET(fih_rc); +} + +/* Image verification function. + * The function directly calls bootutil_verify to verify signature + * of image. + */ +fih_ret +bootutil_verify_img(uint8_t *img, uint32_t size, + uint8_t *sig, size_t slen, + uint8_t key_id) +{ + FIH_DECLARE(fih_rc, FIH_FAILURE); + + FIH_CALL(bootutil_verify, fih_rc, img, size, sig, + slen, key_id); + + FIH_RET(fih_rc); +} + #endif /* MCUBOOT_SIGN_ED25519 */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ae22e27ed..e038f22fe 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -56,6 +56,7 @@ #include "bootutil_priv.h" +#ifndef MCUBOOT_SIGN_PURE /* * Compute SHA hash over the image. * (SHA384 if ECDSA-P384 is being used, @@ -175,6 +176,7 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, return 0; } +#endif /* * Currently, we only support being able to verify one type of @@ -361,6 +363,44 @@ bootutil_get_img_security_cnt(struct image_header *hdr, return 0; } +#if defined(MCUBOOT_SIGN_PURE) +/* Returns: + * 0 -- found + * 1 -- not found or found but not true + * -1 -- failed for some reason + * + * Value of TLV does not matter, presence decides. + */ +static int bootutil_check_for_pure(const struct image_header *hdr, + const struct flash_area *fap) +{ + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_SIG_PURE, false); + if (rc) { + return -1; + } + + /* Search for the TLV */ + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + if (rc == 0 && len == 1) { + uint8_t val; + + rc = LOAD_IMAGE_DATA(hdr, fap, off, &val, sizeof(val)); + if (rc == 0) { + return (val == 1) ? 0 : 1; + } else { + return -1; + } + } + + return 1; +} +#endif + #ifndef ALLOW_ROGUE_TLVS /* * The following list of TLVs are the only entries allowed in the unprotected @@ -377,6 +417,9 @@ static const uint16_t allowed_unprot_tlvs[] = { IMAGE_TLV_ECDSA_SIG, IMAGE_TLV_RSA3072_PSS, IMAGE_TLV_ED25519, +#if defined(MCUBOOT_SIGN_PURE) + IMAGE_TLV_SIG_PURE, +#endif IMAGE_TLV_ENC_RSA2048, IMAGE_TLV_ENC_KW, IMAGE_TLV_ENC_EC256, @@ -399,7 +442,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, uint32_t off; uint16_t len; uint16_t type; - int image_hash_valid = 0; #ifdef EXPECTED_SIG_TLV FIH_DECLARE(valid_signature, FIH_FAILURE); #ifndef MCUBOOT_BUILTIN_KEY @@ -416,7 +458,10 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, #endif /* EXPECTED_SIG_TLV */ struct image_tlv_iter it; uint8_t buf[SIG_BUF_SIZE]; +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) + int image_hash_valid = 0; uint8_t hash[IMAGE_HASH_SIZE]; +#endif int rc = 0; FIH_DECLARE(fih_rc, FIH_FAILURE); #ifdef MCUBOOT_HW_ROLLBACK_PROT @@ -425,6 +470,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, FIH_DECLARE(security_counter_valid, FIH_FAILURE); #endif +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); if (rc) { @@ -434,6 +480,15 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (out_hash) { memcpy(out_hash, hash, IMAGE_HASH_SIZE); } +#endif + +#if defined(MCUBOOT_SIGN_PURE) + /* If Pure type signature is expected then it has to be there */ + rc = bootutil_check_for_pure(hdr, fap); + if (rc != 0) { + goto out; + } +#endif rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); if (rc) { @@ -477,8 +532,10 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } } #endif - - if (type == EXPECTED_HASH_TLV) { + switch(type) { +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) + case EXPECTED_HASH_TLV: + { /* Verify the image hash. This must always be present. */ if (len != sizeof(hash)) { rc = -1; @@ -496,8 +553,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } image_hash_valid = 1; + break; + } +#endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ #ifdef EXPECTED_KEY_TLV - } else if (type == EXPECTED_KEY_TLV) { + case EXPECTED_KEY_TLV: + { /* * Determine which key we should be checking. */ @@ -522,9 +583,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, * The key may not be found, which is acceptable. There * can be multiple signatures, each preceded by a key. */ + break; + } #endif /* EXPECTED_KEY_TLV */ #ifdef EXPECTED_SIG_TLV - } else if (type == EXPECTED_SIG_TLV) { + case EXPECTED_SIG_TLV: + { /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; @@ -538,12 +602,25 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (rc) { goto out; } +#ifndef MCUBOOT_SIGN_PURE FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), buf, len, key_id); +#else + /* Directly check signature on the image, by using the mapping of + * a device to memory. The pointer is beginning of image in flash, + * so offset of area, the range is header + image + protected tlvs. + */ + FIH_CALL(bootutil_verify_img, valid_signature, (void *)flash_area_get_off(fap), + hdr->ih_hdr_size + hdr->ih_img_size + hdr->ih_protect_tlv_size, + buf, len, key_id); +#endif key_id = -1; + break; + } #endif /* EXPECTED_SIG_TLV */ #ifdef MCUBOOT_HW_ROLLBACK_PROT - } else if (type == IMAGE_TLV_SEC_CNT) { + case IMAGE_TLV_SEC_CNT: + { /* * Verify the image's security counter. * This must always be present. @@ -578,14 +655,21 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, /* The image's security counter has been successfully verified. */ security_counter_valid = fih_rc; + break; + } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ } } +#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = !image_hash_valid; if (rc) { goto out; } +#elif defined(MCUBOOT_SIGN_PURE) + /* This returns true on EQ, rc is err on non-0 */ + rc = FIH_NOT_EQ(valid_signature, FIH_SUCCESS); +#endif #ifdef EXPECTED_SIG_TLV FIH_SET(fih_rc, valid_signature); #endif diff --git a/docs/design.md b/docs/design.md index 7fa06fe6b..b1979a7c2 100755 --- a/docs/design.md +++ b/docs/design.md @@ -111,6 +111,8 @@ struct image_tlv { #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 /* If true then any signature found has been + calculated over image directly. */ #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 */ From 29818ad3bbfcc38df973aa365d65f083039b885e Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 2 Oct 2024 11:05:20 +0000 Subject: [PATCH 263/287] [nrf fromtree] zephyr: Allow SHA512 with TinyCrypt Select BOOT_IMG_HASH_ALG_SHA512_ALLOW via BOOT_ED25519_TINYCRYPT. Signed-off-by: Dominik Ermel (cherry picked from commit 30e6adfe43bb0786d6c32426fdd11cb750f01ac6) --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 512f485f6..915075819 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -182,6 +182,7 @@ choice BOOT_ED25519_IMPLEMENTATION config BOOT_ED25519_TINYCRYPT bool "Use tinycrypt" select BOOT_USE_TINYCRYPT + select BOOT_IMG_HASH_ALG_SHA512_ALLOW config BOOT_ED25519_MBEDTLS bool "Use mbedTLS" select BOOT_USE_MBEDTLS From e8142682fecd3dfdfa1fa246b6bdaed90a4aa76d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 5 Sep 2024 10:53:17 +0000 Subject: [PATCH 264/287] [nrf fromtree] zephyr: Add Kconfig and configuration for SHA on storage Adds CONFIG_BOOT_IMG_HASH_DIRECTLY_ON_STORAGE, which enables MCUBOOT_HASH_STORAGE_DIRECTLY for Zephyr. Signed-off-by: Dominik Ermel (cherry picked from commit 96f01aad668929cbcebc5c1395aa4af110e53a51) --- boot/zephyr/Kconfig | 16 ++++++++++++++++ .../include/mcuboot_config/mcuboot_config.h | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 915075819..33708b8a2 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -91,6 +91,22 @@ config BOOT_IMG_HASH_ALG_SHA512_ALLOW help Hidden option set by configurations that allow SHA512 +config BOOT_IMG_HASH_DIRECTLY_ON_STORAGE + bool "Hash calculation functions access storage through address space" + depends on !BOOT_ENCRYPT_IMAGE + help + When possible to map storage device, at least for read operations, + to address space or RAM area, enabling this option allows hash + calculation functions to directly access the storage through that address + space or using its own DMA. This reduces flash read overhead done + by MCUboot. + Notes: + - not supported when encrypted images are in use, because calculating + SHA requires image to be decrypted first, which is done in RAM. + - currently only supported on internal storage of devices; this + option will not work with devices that use external storage for + either of the image slots. + choice BOOT_IMG_HASH_ALG prompt "Selected image hash algorithm" default BOOT_IMG_HASH_ALG_SHA256 if BOOT_IMG_HASH_ALG_SHA256_ALLOW diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 4743539f1..cb3d26535 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -148,6 +148,13 @@ #define MCUBOOT_DECOMPRESS_IMAGES #endif +/* Invoke hashing functions directly on storage device. This requires the device + * be able to map storage to address space or RAM. + */ +#ifdef CONFIG_BOOT_IMG_HASH_DIRECTLY_ON_STORAGE +#define MCUBOOT_HASH_STORAGE_DIRECTLY +#endif + #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From 0bb59a7277454bc2ca56e695c7877f622fd6f4aa Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 6 Sep 2024 16:16:28 +0000 Subject: [PATCH 265/287] [nrf fromtree] zephyr: Add Kconfig option to select PureEdDS Commit adds CONFIG_BOOT_SIGNATURE_TYPE_PURE Kconfig option, which enables MCUBOOT_SIGN_PURE in MCUboot configuration. Signed-off-by: Dominik Ermel (cherry picked from commit 9668469f00a70d43e6b1fcaf8287833d102870b7) --- boot/zephyr/Kconfig | 30 +++++++++++++++++-- .../include/mcuboot_config/mcuboot_config.h | 4 +++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 33708b8a2..2b335498c 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -137,6 +137,14 @@ config BOOT_IMG_HASH_ALG_SHA512 endchoice # BOOT_IMG_HASH_ALG +config BOOT_SIGNATURE_TYPE_PURE_ALLOW + bool + help + Hidden option set by configurations that allow Pure variant, + for example ed25519. The pure variant means that image + signature is calculated over entire image instead of hash + of an image. + choice BOOT_SIGNATURE_TYPE prompt "Signature type" default BOOT_SIGNATURE_TYPE_RSA @@ -188,10 +196,28 @@ endif config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" - select BOOT_ENCRYPTION_SUPPORT - select BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_ENCRYPTION_SUPPORT if !BOOT_SIGNATURE_TYPE_PURE + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !BOOT_SIGNATURE_TYPE_PURE + # The SHA is used only for key hashing, not for images. + select BOOT_SIGNATURE_TYPE_PURE_ALLOW + help + This is ed25519 signature calculated over SHA512 of SHA256 of application + image. + To check signature over entire image directly, rather than hash, + select BOOT_SIGNATURE_TYPE_PURE. if BOOT_SIGNATURE_TYPE_ED25519 + +config BOOT_SIGNATURE_TYPE_PURE + bool "Use Pure signature of image" + depends on BOOT_SIGNATURE_TYPE_PURE_ALLOW + help + The Pure signature is calculated directly over image rather than + hash of an image, as the BOOT_SIGNATURE_TYPE_ED25519 does by + default. + Image to be verified needs to be accessible through memory address + space that cryptography functions can access via pointers. + choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" default BOOT_ED25519_TINYCRYPT diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index cb3d26535..db80f1882 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -155,6 +155,10 @@ #define MCUBOOT_HASH_STORAGE_DIRECTLY #endif +#ifdef CONFIG_BOOT_SIGNATURE_TYPE_PURE +#define MCUBOOT_SIGN_PURE +#endif + #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From 96d10de4a42f4cccd540c7b5ecfbaf663c51eac2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 24 Jan 2025 17:05:18 +0000 Subject: [PATCH 266/287] [nrf fromtree] zephyr: Fix image encryption configuration for mbedTLS. Add a few missing Kconfig options. Signed-off-by: Dominik Ermel (cherry picked from commit 96b70086c8e3104564c72f718f5191aa18952f96) --- boot/zephyr/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 2b335498c..5de63a2e3 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -66,6 +66,15 @@ config NRF_CC310_BL bool default n +if BOOT_USE_MBEDTLS && MBEDTLS_BUILTIN + +config BOOT_AES_MBEDTLS_DEPENDENCIES + bool + select MBEDTLS_CIPHER_AES_ENABLED + select MBEDTLS_CIPHER_MODE_CTR_ENABLED + +endif + menu "MCUBoot settings" config SINGLE_APPLICATION_SLOT @@ -162,6 +171,7 @@ config BOOT_SIGNATURE_TYPE_RSA select MBEDTLS_KEY_EXCHANGE_RSA_ENABLED if MBEDTLS_BUILTIN select BOOT_ENCRYPTION_SUPPORT select BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_AES_MBEDTLS_DEPENDENCIES if MBEDTLS_BUILTIN && BOOT_ENCRYPT_IMAGE if BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_RSA_LEN @@ -230,6 +240,7 @@ config BOOT_ED25519_MBEDTLS select BOOT_USE_MBEDTLS select MBEDTLS select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN + select BOOT_AES_MBEDTLS_DEPENDENCIES if MBEDTLS_BUILTIN && BOOT_ENCRYPT_IMAGE endchoice endif From 6938931d4cafe2223e640ceeb85d55d2d6ee2958 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 29 May 2024 17:46:17 +0000 Subject: [PATCH 267/287] [nrf fromtree] bootutil: PSA implementation of x25519 and ed25519 verification The commit provides implementation of image verification with ed25519 and encryption/decryption support where random key is encrypted using x25519. Signed-off-by: Dominik Ermel (cherry picked from commit 615a9dffd03e6ebcdd1bcc58a67cc92e5eafea7b) --- .../include/bootutil/crypto/aes_ctr.h | 37 +- boot/bootutil/pkg.yml | 2 + boot/bootutil/src/ed25519_psa.c | 71 +++ boot/bootutil/src/encrypted.c | 114 ++--- boot/bootutil/src/encrypted_psa.c | 454 ++++++++++++++++++ boot/bootutil/src/image_ed25519.c | 3 +- 6 files changed, 624 insertions(+), 57 deletions(-) create mode 100644 boot/bootutil/src/ed25519_psa.c create mode 100644 boot/bootutil/src/encrypted_psa.c diff --git a/boot/bootutil/include/bootutil/crypto/aes_ctr.h b/boot/bootutil/include/bootutil/crypto/aes_ctr.h index 50d36a4fc..23862825c 100644 --- a/boot/bootutil/include/bootutil/crypto/aes_ctr.h +++ b/boot/bootutil/include/bootutil/crypto/aes_ctr.h @@ -15,8 +15,8 @@ #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" + 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) @@ -38,12 +38,45 @@ #define BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE TC_AES_BLOCK_SIZE #endif /* MCUBOOT_USE_TINYCRYPT */ +#if defined(MCUBOOT_USE_PSA_CRYPTO) + #include + #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 #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) diff --git a/boot/bootutil/pkg.yml b/boot/bootutil/pkg.yml index ed6f35810..4a7fabc1c 100644 --- a/boot/bootutil/pkg.yml +++ b/boot/bootutil/pkg.yml @@ -47,6 +47,8 @@ pkg.ign_files.BOOTUTIL_SINGLE_APPLICATION_SLOT: pkg.ign_files: - "ram_load.c" + - "ed25519_psa.c" # Currently no PSA for mynewet + - "encrypted_psa.c" pkg.deps.BOOTUTIL_USE_MBED_TLS: - "@apache-mynewt-core/crypto/mbedtls" diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c new file mode 100644 index 000000000..12ba20ac1 --- /dev/null +++ b/boot/bootutil/src/ed25519_psa.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +#include +#include "bootutil/bootutil_log.h" + +#include +#include + +BOOT_LOG_MODULE_REGISTER(ed25519_psa); + +#define SHA512_DIGEST_LENGTH 64 +#define EDDSA_KEY_LENGTH 32 +#define EDDSA_SIGNAGURE_LENGTH 64 + +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], + const uint8_t public_key[EDDSA_KEY_LENGTH]) +{ + /* Set to any error */ + psa_status_t status = PSA_ERROR_BAD_STATE; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t kid; + int ret = 0; /* Fail by default */ + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d\n", status); + return 0; + } + + status = PSA_ERROR_BAD_STATE; + + psa_set_key_type(&key_attr, + PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS)); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE); + psa_set_key_algorithm(&key_attr, PSA_ALG_PURE_EDDSA); + + status = psa_import_key(&key_attr, public_key, EDDSA_KEY_LENGTH, &kid); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("ED25519 key import failed %d", status); + return 0; + } + + status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len, + signature, EDDSA_SIGNAGURE_LENGTH); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + ret = 0; + /* Pass through to destroy key */ + } else { + ret = 1; + /* Pass through to destroy key */ + } + + status = psa_destroy_key(kid); + + if (status != PSA_SUCCESS) { + /* Just for logging */ + BOOT_LOG_WRN("Failed to destroy key %d", status); + } + + return ret; +} diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index 8449a28dd..8c631d731 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -3,6 +3,7 @@ * * Copyright (c) 2018-2019 JUUL Labs * Copyright (c) 2019-2024 Arm Limited + * Copyright (c) 2025 Nordic Semiconductor ASA */ #include "mcuboot_config/mcuboot_config.h" @@ -25,6 +26,7 @@ #include "bootutil/crypto/ecdh_p256.h" #endif +#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_X25519) #include "bootutil/crypto/ecdh_x25519.h" #endif @@ -35,6 +37,7 @@ #include "mbedtls/oid.h" #include "mbedtls/asn1.h" #endif +#endif #include "bootutil/image.h" #include "bootutil/enc_key.h" @@ -43,6 +46,30 @@ #include "bootutil_priv.h" +#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE + +#if defined(MCUBOOT_ENCRYPT_RSA) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 +#elif defined(MCUBOOT_ENCRYPT_KW) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW +#elif defined(MCUBOOT_ENCRYPT_EC256) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (65) +# define EC_CIPHERKEY_INDEX (65 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-P256 component indexes"); +#elif defined(MCUBOOT_ENCRYPT_X25519) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (32) +# define EC_CIPHERKEY_INDEX (32 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-X25519 component indexes"); +#endif + +/* NOUP Fixme: */ +#if !defined(CONFIG_BOOT_ED25519_PSA) #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) #if defined(_compare) static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size) @@ -351,60 +378,6 @@ int boot_enc_retrieve_private_key(struct bootutil_key **private_key) } #endif /* !MCUBOOT_ENC_BUILTIN_KEY */ -int -boot_enc_init(struct enc_key_data *enc_state, uint8_t slot) -{ - bootutil_aes_ctr_init(&enc_state[slot].aes_ctr); - return 0; -} - -int -boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot) -{ - bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr); - enc_state[slot].valid = 0; - return 0; -} - -int -boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, - const struct boot_status *bs) -{ - int rc; - - rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]); - if (rc != 0) { - boot_enc_drop(enc_state, slot); - return -1; - } - - enc_state[slot].valid = 1; - - return 0; -} - -#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE - -#if defined(MCUBOOT_ENCRYPT_RSA) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 -#elif defined(MCUBOOT_ENCRYPT_KW) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW -#elif defined(MCUBOOT_ENCRYPT_EC256) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (65) -# define EC_CIPHERKEY_INDEX (65 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-P256 component indexes"); -#elif defined(MCUBOOT_ENCRYPT_X25519) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (32) -# define EC_CIPHERKEY_INDEX (32 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-X25519 component indexes"); -#endif - #if ( (defined(MCUBOOT_ENCRYPT_RSA) && defined(MCUBOOT_USE_MBED_TLS) && !defined(MCUBOOT_USE_PSA_CRYPTO)) || \ (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ) #if MBEDTLS_VERSION_NUMBER >= 0x03000000 @@ -627,6 +600,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return rc; } +#endif /* CONFIG_BOOT_ED25519_PSA */ /* * Load encryption key. @@ -681,6 +655,38 @@ boot_enc_load(struct enc_key_data *enc_state, int slot, return boot_decrypt_key(buf, bs->enckey[slot]); } +int +boot_enc_init(struct enc_key_data *enc_state, uint8_t slot) +{ + bootutil_aes_ctr_init(&enc_state[slot].aes_ctr); + return 0; +} + +int +boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot) +{ + bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr); + enc_state[slot].valid = 0; + return 0; +} + +int +boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, + const struct boot_status *bs) +{ + int rc; + + rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]); + if (rc != 0) { + boot_enc_drop(enc_state, slot); + return -1; + } + + enc_state[slot].valid = 1; + + return 0; +} + bool boot_enc_valid(struct enc_key_data *enc_state, int slot) { diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c new file mode 100644 index 000000000..441ce94df --- /dev/null +++ b/boot/bootutil/src/encrypted_psa.c @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mcuboot_config/mcuboot_config.h" + +#include +#include +#include + +/* We are not really using the MBEDTLS but need the ASN.1 parsing functions */ +#define MBEDTLS_ASN1_PARSE_C + +#include "bootutil/crypto/sha.h" +#include "mbedtls/oid.h" +#include "mbedtls/asn1.h" + +#include "bootutil/image.h" +#include "bootutil/enc_key.h" +#include "bootutil/sign_key.h" +#include "bootutil/crypto/common.h" + +#include "bootutil_priv.h" +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); + +#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE +#define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 +#define EC_PUBK_INDEX (0) +#define EC_TAG_INDEX (32) +#define EC_CIPHERKEY_INDEX (32 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-X25519 component indexes"); + +#define X25519_OID "\x6e" +static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ + MBEDTLS_OID_ORG_GOV X25519_OID; + +#define SHARED_KEY_LEN 32 +#define PRIV_KEY_LEN 32 + +/* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ +static int +parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +{ + size_t len; + int version; + mbedtls_asn1_buf alg; + mbedtls_asn1_buf param; + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE) != 0) { + return -1; + } + + if (*p + len != end) { + return -2; + } + + version = 0; + if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { + return -3; + } + + if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { + return -4; + } + + 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 -5; + } + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -6; + } + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -7; + } + + if (len != PRIV_KEY_LEN) { + return -8; + } + + memcpy(private_key, *p, PRIV_KEY_LEN); + return 0; +} + +void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx) +{ + psa_status_t psa_ret = psa_crypto_init(); + + (void)ctx; + + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES init PSA crypto init failed %d", psa_ret); + assert(0); + } +} + +#if defined(MCUBOOT_ENC_IMAGES) +extern const struct bootutil_key bootutil_enc_key; +/* + * Decrypt an encryption key TLV. + * + * @param buf An encryption TLV read from flash (build time fixed length) + * @param enckey An AES-128 or AES-256 key sized buffer to store to plain key. + */ +int +boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) +{ + uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; + uint8_t *cp; + uint8_t *cpend; + uint8_t private_key[PRIV_KEY_LEN]; + size_t len; + psa_status_t psa_ret = PSA_ERROR_BAD_STATE; + psa_status_t psa_cleanup_ret = PSA_ERROR_BAD_STATE; + psa_key_id_t kid; + psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_derivation_operation_t key_do = PSA_KEY_DERIVATION_OPERATION_INIT; + psa_algorithm_t key_do_alg; + int rc = -1; + + cp = (uint8_t *)bootutil_enc_key.key; + cpend = cp + *bootutil_enc_key.len; + + /* The psa_cipher_decrypt needs initialization vector of proper length at + * the beginning of the input buffer. + */ + uint8_t iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR) + + BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE]; + + psa_ret = psa_crypto_init(); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES crypto init failed %d", psa_ret); + return -1; + } + + /* + * Load the stored X25519 decryption private key + */ + rc = parse_x25519_enckey(&cp, cpend, private_key); + if (rc) { + return rc; + } + + psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY)); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&kattr, PSA_ALG_ECDH); + + psa_ret = psa_import_key(&kattr, private_key, sizeof(private_key), &kid); + memset(private_key, 0, sizeof(private_key)); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("Built-in key import failed %d", psa_ret); + return -1; + } + + key_do_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)); + + psa_ret = psa_key_derivation_setup(&key_do, key_do_alg); + if (psa_ret != PSA_SUCCESS) { + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Built-in key destruction failed %d", psa_cleanup_ret); + } + BOOT_LOG_ERR("Key derivation setup failed %d", psa_ret); + return -1; + } + + /* Note: PSA 1.1.2 does not have psa_key_agreement that would be useful here + * as it could just add the derived key to the storage and return key id. + * Instead, we have to use the code below to generate derived key and put it + * into storage, to obtain the key id we can then use with psa_mac_* functions. + */ + psa_ret = psa_key_derivation_key_agreement(&key_do, PSA_KEY_DERIVATION_INPUT_SECRET, + kid, &buf[EC_PUBK_INDEX], + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Built-in key destruction failed %d", psa_cleanup_ret); + } + if (psa_ret != PSA_SUCCESS) { + psa_cleanup_ret = psa_key_derivation_abort(&key_do); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Key derivation abort failed %d", psa_ret); + } + + BOOT_LOG_ERR("Key derivation failed %d", psa_ret); + return -1; + } + + /* Only info, no salt */ + psa_ret = psa_key_derivation_input_bytes(&key_do, PSA_KEY_DERIVATION_INPUT_INFO, + "MCUBoot_ECIES_v1", 16); + if (psa_ret != PSA_SUCCESS) { + psa_cleanup_ret = psa_key_derivation_abort(&key_do); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Key derivation abort failed %d", psa_ret); + } + BOOT_LOG_ERR("Key derivation failed %d", psa_ret); + return -1; + } + + len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE; + psa_ret = psa_key_derivation_output_bytes(&key_do, derived_key, len); + psa_cleanup_ret = psa_key_derivation_abort(&key_do); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("Key derivation cleanup failed %d", psa_ret); + } + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("Key derivation failed %d", psa_ret); + return -1; + } + + /* The derived key consists of BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE bytes + * followed by BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE bytes. Both parts will + * be imported at the point where needed and discarded immediately after. + */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_HMAC); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_VERIFY_MESSAGE); + psa_set_key_algorithm(&kattr, PSA_ALG_HMAC(PSA_ALG_SHA_256)); + + /* Import the MAC tag key part of derived key, that is the part that starts + * after BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE and has length of + * BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE bytes. + */ + psa_ret = psa_import_key(&kattr, + &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE], + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, &kid); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + memset(derived_key, 0, sizeof(derived_key)); + BOOT_LOG_ERR("MAC key import failed %d", psa_ret); + return -1; + } + + /* Verify the MAC tag of the random encryption key */ + psa_ret = psa_mac_verify(kid, PSA_ALG_HMAC(PSA_ALG_SHA_256), + &buf[EC_CIPHERKEY_INDEX], BOOT_ENC_KEY_SIZE, + &buf[EC_TAG_INDEX], + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("MAC key destruction failed %d", psa_cleanup_ret); + } + if (psa_ret != PSA_SUCCESS) { + memset(derived_key, 0, sizeof(derived_key)); + BOOT_LOG_ERR("MAC verification failed %d", psa_ret); + return -1; + } + + /* The derived key is used in AES decryption of random key */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&kattr, PSA_ALG_CTR); + + /* Import the AES partition of derived key, the first 16 bytes */ + psa_ret = psa_import_key(&kattr, &derived_key[0], + BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, &kid); + memset(derived_key, 0, sizeof(derived_key)); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES key import failed %d", psa_ret); + return -1; + } + + /* Decrypt the random AES encryption key with AES and the key obtained + * at derivation. */ + memset(&iv_and_key[0], 0, PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)); + memcpy(&iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)], + &buf[EC_CIPHERKEY_INDEX], + sizeof(iv_and_key) - PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR)); + + len = 0; + psa_ret = psa_cipher_decrypt(kid, PSA_ALG_CTR, iv_and_key, sizeof(iv_and_key), + enckey, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, &len); + memset(iv_and_key, 0, sizeof(iv_and_key)); + psa_cleanup_ret = psa_destroy_key(kid); + if (psa_cleanup_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("AES key destruction failed %d", psa_cleanup_ret); + } + if (psa_ret != PSA_SUCCESS || len != BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE) { + memset(enckey, 0, BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE); + BOOT_LOG_ERR("Random key decryption failed %d", psa_ret); + return -1; + } + + 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 ret = 0; + psa_status_t psa_ret = PSA_ERROR_BAD_STATE; + psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t kid; + psa_cipher_operation_t psa_op; + size_t elen = 0; /* Decrypted length */ + + /* Fixme: calling psa_crypto_init multiple times is not a problem, + * yet the code here is only present because there is not general + * crypto init. */ + psa_ret = psa_crypto_init(); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); + ret = -1; + goto gone; + } + + psa_op = psa_cipher_operation_init(); + + /* Fixme: Import should happen when key is decrypted, but due to lack + * of key destruction there is no way to destroy key stored by + * psa other way than here. */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&kattr, PSA_ALG_CTR); + + psa_ret = psa_import_key(&kattr, ctx->key, BOOT_ENC_KEY_SIZE, &kid); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc import key failed %d", psa_ret); + ret = -1; + goto gone; + } + + /* This could be done with psa_cipher_decrypt one-shot operation, but + * multi-part operation is used to avoid re-allocating input buffer + * to account for IV in front of data. + */ + psa_ret = psa_cipher_encrypt_setup(&psa_op, kid, PSA_ALG_CTR); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc setup failed %d", psa_ret); + ret = -1; + goto gone_with_key; + } + + /* Fixme: hardcoded counter size, but it is hardcoded everywhere */ + psa_ret = psa_cipher_set_iv(&psa_op, counter, 16); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc IV set failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + + psa_ret = psa_cipher_update(&psa_op, m, mlen, c, mlen, &elen); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES enc encryption failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + +gone_after_setup: + psa_ret = psa_cipher_abort(&psa_op); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("AES enc cipher abort failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone_with_key: + /* Fixme: Should be removed once key is shared by id */ + psa_ret = psa_destroy_key(kid); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("AES enc destroy key failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone: + return ret; +} + +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) +{ + int ret = 0; + psa_status_t psa_ret = PSA_ERROR_BAD_STATE; + psa_key_attributes_t kattr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t kid; + psa_cipher_operation_t psa_op; + size_t dlen = 0; /* Decrypted length */ + + /* Fixme: the init should already happen before calling the function, but + * somehow it does not, for example when recovering in swap. + */ + psa_ret = psa_crypto_init(); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); + ret = -1; + goto gone; + } + + psa_op = psa_cipher_operation_init(); + + /* Fixme: Import should happen when key is decrypted, but due to lack + * of key destruction there is no way to destroy key stored by + * psa other way than here. */ + psa_set_key_type(&kattr, PSA_KEY_TYPE_AES); + psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&kattr, PSA_ALG_CTR); + + psa_ret = psa_import_key(&kattr, ctx->key, BOOT_ENC_KEY_SIZE, &kid); + psa_reset_key_attributes(&kattr); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec import key failed %d", psa_ret); + ret = -1; + goto gone; + } + + /* This could be done with psa_cipher_decrypt one-shot operation, but + * multi-part operation is used to avoid re-allocating input buffer + * to account for IV in front of data. + */ + psa_ret = psa_cipher_decrypt_setup(&psa_op, kid, PSA_ALG_CTR); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec setup failed %d", psa_ret); + ret = -1; + goto gone_with_key; + } + + /* Fixme: hardcoded counter size, but it is hardcoded everywhere */ + psa_ret = psa_cipher_set_iv(&psa_op, counter, 16); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec IV set failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + + psa_ret = psa_cipher_update(&psa_op, c, clen, m, clen, &dlen); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_ERR("AES dec decryption failed %d", psa_ret); + ret = -1; + goto gone_after_setup; + } + +gone_after_setup: + psa_ret = psa_cipher_abort(&psa_op); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("PSA dec abort failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone_with_key: + psa_ret = psa_destroy_key(kid); + if (psa_ret != PSA_SUCCESS) { + BOOT_LOG_WRN("PSA dec key failed %d", psa_ret); + /* Intentionally not changing the ret */ + } +gone: + return ret; +} +#endif /* defined(MCUBOOT_ENC_IMAGES) */ diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 238c9d671..0c5810666 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -3,6 +3,7 @@ * * Copyright (c) 2019 JUUL Labs * Copyright (c) 2021-2023 Arm Limited + * Copyright (c) 2025 Nordic Semiconductor ASA */ #include @@ -85,7 +86,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, uint8_t *pubkey; uint8_t *end; - if (slen != EDDSA_SIGNATURE_LENGTH) { + if (blen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } From 2ff8e8e4cc14804cbcbf042b619c384d3ba7607d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 24 Jan 2025 17:12:05 +0000 Subject: [PATCH 268/287] [nrf fromtree] zephyr: Enable building ed25519 PSA variant with Zephyr Adds Kconfig option CONFIG_BOOT_ED25519_PSA that allows to switch ed25519 to PSA backend. Signed-off-by: Dominik Ermel (cherry picked from commit f2b6def94041820ddb9f5c384d0406a3a8f91b4a) --- boot/bootutil/zephyr/CMakeLists.txt | 16 ++++--- boot/zephyr/CMakeLists.txt | 41 ++++++++++++----- boot/zephyr/Kconfig | 70 ++++++++++++++++++++++++++++- 3 files changed, 110 insertions(+), 17 deletions(-) diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index 72a6a8638..f6d37441c 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Nordic Semiconductor ASA +# Copyright (c) 2020-2025 Nordic Semiconductor ASA # # SPDX-License-Identifier: Apache-2.0 @@ -29,12 +29,18 @@ zephyr_library_link_libraries(MCUBOOT_BOOTUTIL) target_link_libraries(MCUBOOT_BOOTUTIL INTERFACE zephyr_interface) if(CONFIG_BOOT_USE_TINYCRYPT) -target_include_directories(MCUBOOT_BOOTUTIL INTERFACE - ../../../ext/tinycrypt/lib/include -) + target_include_directories(MCUBOOT_BOOTUTIL INTERFACE + ../../../ext/tinycrypt/lib/include + ) +endif() + +if(CONFIG_BOOT_USE_PSA_CRYPTO) + target_include_directories(MCUBOOT_BOOTUTIL INTERFACE + ${ZEPHYR_MBEDTLS_MODULE_DIR}/include + ) endif() -if(CONFIG_BOOT_USE_MBEDTLS) +if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO) zephyr_link_libraries(mbedTLS) endif() endif() diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index b0c119da4..cc74de180 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists.txt for building mcuboot as a Zephyr project # # Copyright (c) 2017 Open Source Foundries Limited -# Copyright (c) 2023 Nordic Semiconductor ASA +# Copyright (c) 2023-2025 Nordic Semiconductor ASA # # SPDX-License-Identifier: Apache-2.0 @@ -50,6 +50,12 @@ zephyr_library_include_directories( include ) +if(DEFINED CONFIG_MBEDTLS) + zephyr_library_include_directories( + ${ZEPHYR_MBEDTLS_MODULE_DIR}/include + ) +endif() + # Zephyr port-specific sources. zephyr_library_sources( main.c @@ -101,6 +107,10 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/fault_injection_hardening.c ) +if(DEFINED CONFIG_BOOT_ENCRYPT_X25519 AND DEFINED CONFIG_BOOT_ED25519_PSA) + zephyr_library_sources(${BOOT_DIR}/bootutil/src/encrypted_psa.c) +endif() + if(DEFINED CONFIG_MEASURED_BOOT OR DEFINED CONFIG_BOOT_SHARE_DATA) zephyr_library_sources( ${BOOT_DIR}/bootutil/src/boot_record.c @@ -249,19 +259,28 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) ${FIAT_DIR}/include/ ) - zephyr_library_sources( - ${FIAT_DIR}/src/curve25519.c - ) + if(NOT CONFIG_BOOT_ED25519_PSA) + zephyr_library_sources( + ${FIAT_DIR}/src/curve25519.c + ) + else() + zephyr_library_sources( + ${MBEDTLS_ASN1_DIR}/src/asn1parse.c + ${BOOT_DIR}/bootutil/src/ed25519_psa.c + ) + endif() endif() -if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) - zephyr_library_sources( - ${TINYCRYPT_DIR}/source/aes_encrypt.c - ${TINYCRYPT_DIR}/source/aes_decrypt.c - ${TINYCRYPT_DIR}/source/ctr_mode.c - ${TINYCRYPT_DIR}/source/hmac.c - ${TINYCRYPT_DIR}/source/ecc_dh.c +if(NOT CONFIG_BOOT_ED25519_PSA) + if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) + zephyr_library_sources( + ${TINYCRYPT_DIR}/source/aes_encrypt.c + ${TINYCRYPT_DIR}/source/aes_decrypt.c + ${TINYCRYPT_DIR}/source/ctr_mode.c + ${TINYCRYPT_DIR}/source/hmac.c + ${TINYCRYPT_DIR}/source/ecc_dh.c ) + endif() endif() if(CONFIG_BOOT_ENCRYPT_EC256) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 5de63a2e3..f9870248c 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -75,6 +75,60 @@ config BOOT_AES_MBEDTLS_DEPENDENCIES endif +if BOOT_USE_PSA_CRYPTO + +config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES + bool + default y if BOOT_IMG_HASH_ALG_SHA256 + select PSA_WANT_ALG_SHA_256 + help + Dependencies for hashing with SHA256 + +config BOOT_ED25519_PSA_DEPENDENCIES + bool + select PSA_WANT_ALG_SHA_256 + select PSA_WANT_ALG_SHA_512 + select PSA_WANT_ALG_PURE_EDDSA + # Seems that upstream mbedTLS does not have TE + #select PSA_WANT_ECC_TWISTED_EDWARDS_255 + select PSA_WANT_ECC_MONTGOMERY_255 + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + help + Dependencies for ed25519 signature + +if BOOT_ENCRYPT_IMAGE + +config BOOT_X25519_PSA_DEPENDENCIES + bool + select PSA_WANT_ALG_ECDH + select PSA_WANT_ALG_HMAC + select PSA_WANT_ALG_HKDF + select PSA_WANT_ALG_CTR + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + select PSA_WANT_KEY_TYPE_DERIVE + select PSA_WANT_KEY_TYPE_AES + select PSA_WANT_ECC_MONTGOMERY_255 + help + Dependencies for x25519 shared-random key encryption and AES + encryption. The PSA_WANT_ALG_CTR and PSA_WANT_KEY_TYPE_AES + enable Counter based block cipher and AES key, and algorithm support, + to use with it; the others are used for shared key decryption + and derivation. + +endif # BOOT_ENCRYPT_IMAGE + +if MBEDTLS_ENABLE_HEAP + +config MBEDTLS_HEAP_SIZE + default 2048 if BOOT_USE_PSA_CRYPTO + help + The PSA internals need to be able to allocate memory for operation + and it uses mbedTLS heap for that. + +endif # MBEDTLS_ENABLE_HEAP + +endif # BOOT_USE_PSA_CRYPTO + menu "MCUBoot settings" config SINGLE_APPLICATION_SLOT @@ -156,6 +210,7 @@ config BOOT_SIGNATURE_TYPE_PURE_ALLOW choice BOOT_SIGNATURE_TYPE prompt "Signature type" + default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP default BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_NONE @@ -231,10 +286,12 @@ config BOOT_SIGNATURE_TYPE_PURE choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" default BOOT_ED25519_TINYCRYPT + config BOOT_ED25519_TINYCRYPT bool "Use tinycrypt" select BOOT_USE_TINYCRYPT select BOOT_IMG_HASH_ALG_SHA512_ALLOW + config BOOT_ED25519_MBEDTLS bool "Use mbedTLS" select BOOT_USE_MBEDTLS @@ -242,6 +299,17 @@ config BOOT_ED25519_MBEDTLS select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN select BOOT_AES_MBEDTLS_DEPENDENCIES if MBEDTLS_BUILTIN && BOOT_ENCRYPT_IMAGE +config BOOT_ED25519_PSA + bool "Use PSA crypto" + select MBEDTLS + select BOOT_USE_PSA_CRYPTO + select MBEDTLS_PSA_CRYPTO_C + select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN + select PSA_CRYPTO_CLIENT + select PSA_CRYPTO_C + select BOOT_ED25519_PSA_DEPENDENCIES + select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE + endchoice endif @@ -289,7 +357,7 @@ config MCUBOOT_CLEANUP_RAM if MBEDTLS config MBEDTLS_CFG_FILE - default "config-tls-generic.h" if MBEDTLS_BUILTIN + default "config-tls-generic.h" if MBEDTLS_BUILTIN || BOOT_USE_PSA_CRYPTO default "mcuboot-mbedtls-cfg.h" if BOOT_USE_MBEDTLS endif From 421c664eb542157d536da0047836dc0cd530cc22 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 8 Oct 2024 16:31:48 +0000 Subject: [PATCH 269/287] [nrf fromtree] bootutil: Allow bypassing ASN.1 encoding for ED25519 key import The commit adds MCUBOOT_KEY_IMPORT_BYPASS_ASN configuration option that allows bypassing ASN.1 decoding of ED25519 public key, compiled into MCUboot. When the option is enabled the key will be accessed directly and ASN.1 processing is not compiled in, resulting in smaller footprint of MCUboot, at a cost of reduced detection of invalid key, i.e. public key designated for different method than compiled in. Signed-off-by: Dominik Ermel (cherry picked from commit 1dcfbdacc41762a89aeba9a5eb334b73563e3b43) --- boot/bootutil/src/image_ed25519.c | 22 +++++++++++++++++-- .../include/mcuboot_config/mcuboot_config.h | 4 ++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 0c5810666..01bef149d 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -13,27 +13,30 @@ #ifdef MCUBOOT_SIGN_ED25519 #include "bootutil/sign_key.h" +#if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) /* We are not really using the MBEDTLS but need the ASN.1 parsing functions */ #define MBEDTLS_ASN1_PARSE_C #include "mbedtls/oid.h" #include "mbedtls/asn1.h" +#endif #include "bootutil_priv.h" #include "bootutil/crypto/common.h" #include "bootutil/crypto/sha.h" #define EDDSA_SIGNATURE_LENGTH 64 - -static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; #define NUM_ED25519_BYTES 32 extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); +#if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) /* * Parse the public key used for signing. */ +static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70"; + static int bootutil_import_key(uint8_t **cp, uint8_t *end) { @@ -69,6 +72,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } +#endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -94,11 +98,25 @@ bootutil_verify(uint8_t *buf, uint32_t blen, pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; +#if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) rc = bootutil_import_key(&pubkey, end); if (rc) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } +#else + /* Directly use the key contents from the ASN stream, + * these are the last NUM_ED25519_BYTES. + * There is no check whether this is the correct key, + * here, by the algorithm selected. + */ + if (*bootutil_keys[key_id].len < NUM_ED25519_BYTES) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + pubkey = end - NUM_ED25519_BYTES; +#endif rc = ED25519_verify(buf, blen, sig, pubkey); diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index db80f1882..01a9439aa 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -34,6 +34,10 @@ # error "One crypto library implementation allowed at a time." #endif +#if defined(CONFIG_BOOT_KEY_IMPORT_BYPASS_ASN) +#define MCUBOOT_KEY_IMPORT_BYPASS_ASN +#endif + #ifdef CONFIG_BOOT_USE_MBEDTLS #define MCUBOOT_USE_MBED_TLS #elif defined(CONFIG_BOOT_USE_TINYCRYPT) From 5f21ef3ce33ce4fb852ea6a30950c57e5ec1e971 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 8 Oct 2024 16:36:15 +0000 Subject: [PATCH 270/287] [nrf fromtree] zephyr: Add Kconfig option CONFIG_BOOT_KEY_IMPORT_BYPASS_ASN The option enables MCUboot configuration option MCUBOOT_KEY_IMPORT_BYPASS_ASN. Signed-off-by: Dominik Ermel (cherry picked from commit 3ff75490e4a42096e07d38f8325953da334b367c) --- boot/zephyr/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index f9870248c..18bbcb134 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -311,6 +311,15 @@ config BOOT_ED25519_PSA select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE endchoice + +config BOOT_KEY_IMPORT_BYPASS_ASN + bool "Directly access key value without ASN.1 parsing" + help + Originally, public keys compiled into MCUboot were + stored in ASN.1 encoded format. Enabling this option + bypasses the ASN.1 decoding and directly accesses the key + in ASN.1 bitstream; this reduces MCUboot code by removing + the ASN.1 processing. endif endchoice From da2ae88950991d463f10852a49f9db07408a6d7c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 12 Mar 2025 16:06:32 +0000 Subject: [PATCH 271/287] [nrf fromtree] bootutil: Fix ASN1 bypass not building One of includes is not available when bypassing ASN1 encoding as mbedTLS is no longer enabled for compilation. Discovered with zephyr, but common for other platforms, after recent changes in CMakeLists.txt. Signed-off-by: Dominik Ermel (cherry picked from commit a01ca4cf946badfc409c490850c335f7152bc391) --- boot/bootutil/src/image_ed25519.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 01bef149d..90e8300de 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -18,10 +18,10 @@ #define MBEDTLS_ASN1_PARSE_C #include "mbedtls/oid.h" #include "mbedtls/asn1.h" +#include "bootutil/crypto/common.h" #endif #include "bootutil_priv.h" -#include "bootutil/crypto/common.h" #include "bootutil/crypto/sha.h" #define EDDSA_SIGNATURE_LENGTH 64 From afa5789069349e3836c062b46fd854d0aa3e8e6d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 12 Mar 2025 16:09:12 +0000 Subject: [PATCH 272/287] [nrf fromtree] zephyr: Do not compile ASN1 code when bypassed Commit removes files needed for ASN1 parsing from compilation, when ASN1 bypass is enabled. Signed-off-by: Dominik Ermel (cherry picked from commit ec86244ac150d87b46e41d948ce7b655be672f88) --- boot/zephyr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index cc74de180..2849e31fe 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -25,7 +25,7 @@ assert_exists(TINYCRYPT_SHA512_DIR) set(FIAT_DIR "${MCUBOOT_DIR}/ext/fiat") assert_exists(FIAT_DIR) # Path to mbed-tls' asn1 parser library. -if(NOT CONFIG_MBEDTLS_BUILTIN) +if(NOT CONFIG_MBEDTLS_BUILTIN AND NOT CONFIG_BOOT_KEY_IMPORT_BYPASS_ASN) set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") assert_exists(MBEDTLS_ASN1_DIR) endif() From 721b3f681b192ff1835c4e837ad72feeebf5c169 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 12 Mar 2025 16:44:21 +0000 Subject: [PATCH 273/287] [nrf fromtree] zephyr: Prevent selecting MBEDTLS_ASN1_PARSE_C when not needed Make selection of MBEDTLS_ASN1_PARSE_C, in BOOT_ED25519_MBEDTLS, depending on ASN1 parsing being enabled. Signed-off-by: Dominik Ermel (cherry picked from commit 0ba80ffb1a0a2514385de47da67ac19c17ff23de) --- boot/zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 18bbcb134..17a7007c1 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -296,7 +296,7 @@ config BOOT_ED25519_MBEDTLS bool "Use mbedTLS" select BOOT_USE_MBEDTLS select MBEDTLS - select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN + select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN && !BOOT_KEY_IMPORT_BYPASS_ASN select BOOT_AES_MBEDTLS_DEPENDENCIES if MBEDTLS_BUILTIN && BOOT_ENCRYPT_IMAGE config BOOT_ED25519_PSA From de7aeef3a18c85aa7feb7900e77f904510bacb3c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 12 Mar 2025 16:13:28 +0000 Subject: [PATCH 274/287] [nrf fromtree] zephyr: Fix ED25519 compilation with mbedTLS ED25519 with mbedTLS has not been linking due to missing SHA512, which is internally required by ED25519 implementation. Signed-off-by: Dominik Ermel (cherry picked from commit f523c60dbd60677557d192dcabd20af28a8470c3) --- boot/zephyr/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 17a7007c1..8ee906621 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -295,7 +295,9 @@ config BOOT_ED25519_TINYCRYPT config BOOT_ED25519_MBEDTLS bool "Use mbedTLS" select BOOT_USE_MBEDTLS + select BOOT_IMG_HASH_ALG_SHA512_ALLOW select MBEDTLS + select MBEDTLS_SHA512 select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN && !BOOT_KEY_IMPORT_BYPASS_ASN select BOOT_AES_MBEDTLS_DEPENDENCIES if MBEDTLS_BUILTIN && BOOT_ENCRYPT_IMAGE From 04c71e3e74a2ed316492db20492080d7517787ea Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 13 Mar 2025 15:07:09 +0000 Subject: [PATCH 275/287] [nrf fromtree] zephyr: Add missing selection for allowed SHA algorithms All of ED25519 backends allow SHA512, together with SHA512. The ED25519 internally requires SHA512 for calculations, but image may be hashed with any SHA algorithm. The PSA has also been missing selecting of any SHA as allowed. Signed-off-by: Dominik Ermel (cherry picked from commit e5d8640cd49829a1d5916fbae04cb2c817fb6116) --- boot/zephyr/Kconfig | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 8ee906621..5d8c66570 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -290,11 +290,13 @@ choice BOOT_ED25519_IMPLEMENTATION config BOOT_ED25519_TINYCRYPT bool "Use tinycrypt" select BOOT_USE_TINYCRYPT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW select BOOT_IMG_HASH_ALG_SHA512_ALLOW config BOOT_ED25519_MBEDTLS bool "Use mbedTLS" select BOOT_USE_MBEDTLS + select BOOT_IMG_HASH_ALG_SHA256_ALLOW select BOOT_IMG_HASH_ALG_SHA512_ALLOW select MBEDTLS select MBEDTLS_SHA512 @@ -305,10 +307,13 @@ config BOOT_ED25519_PSA bool "Use PSA crypto" select MBEDTLS select BOOT_USE_PSA_CRYPTO - select MBEDTLS_PSA_CRYPTO_C - select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN select PSA_CRYPTO_CLIENT select PSA_CRYPTO_C + select MBEDTLS_PSA_CRYPTO_C + select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN + select MBEDTLS_ENABLE_HEAP + select BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_IMG_HASH_ALG_SHA512_ALLOW select BOOT_ED25519_PSA_DEPENDENCIES select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE From f203bf1269e5de19c5e4e543fb174fbfa5844913 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 18 Mar 2025 12:40:06 +0000 Subject: [PATCH 276/287] [nrf fromlist] bootutil: Fix ed25519 pure signature verification Accidentally added check for size of blen against hash length, in bootutil_verify, was doubling check done in bootutli_verify_sig and prevented pure signature from working. Upstream PR #: 2237 Signed-off-by: Dominik Ermel --- boot/bootutil/src/image_ed25519.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 90e8300de..ffb8cec3b 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -90,7 +90,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, uint8_t *pubkey; uint8_t *end; - if (blen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) { + if (slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } From 72a8bdc50ac77adc40b94649bf1bd57952d0bc92 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 17:31:33 +0000 Subject: [PATCH 277/287] [nrf noup] zephyr: sdk-nrf specific overrides on PSA Kconfigs Select proper configuration and disable mbedTLS selection, as we are using NRF Security enabled Oberon. Signed-off-by: Dominik Ermel --- boot/bootutil/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index f6d37441c..44f78f395 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -40,7 +40,7 @@ if(CONFIG_BOOT_USE_PSA_CRYPTO) ) endif() -if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO) +if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO AND NOT CONFIG_NRF_SECURITY) zephyr_link_libraries(mbedTLS) endif() endif() diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 5d8c66570..a3bb0aab0 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -89,8 +89,7 @@ config BOOT_ED25519_PSA_DEPENDENCIES select PSA_WANT_ALG_SHA_256 select PSA_WANT_ALG_SHA_512 select PSA_WANT_ALG_PURE_EDDSA - # Seems that upstream mbedTLS does not have TE - #select PSA_WANT_ECC_TWISTED_EDWARDS_255 + select PSA_WANT_ECC_TWISTED_EDWARDS_255 select PSA_WANT_ECC_MONTGOMERY_255 select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT help @@ -285,6 +284,7 @@ config BOOT_SIGNATURE_TYPE_PURE choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" + default BOOT_ED25519_PSA if NRF_SECURITY default BOOT_ED25519_TINYCRYPT config BOOT_ED25519_TINYCRYPT @@ -305,7 +305,7 @@ config BOOT_ED25519_MBEDTLS config BOOT_ED25519_PSA bool "Use PSA crypto" - select MBEDTLS + depends on NRF_SECURITY select BOOT_USE_PSA_CRYPTO select PSA_CRYPTO_CLIENT select PSA_CRYPTO_C @@ -370,11 +370,11 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. -if MBEDTLS +if MBEDTLS || NRF_SECURITY config MBEDTLS_CFG_FILE default "config-tls-generic.h" if MBEDTLS_BUILTIN || BOOT_USE_PSA_CRYPTO - default "mcuboot-mbedtls-cfg.h" if BOOT_USE_MBEDTLS + default "mcuboot-mbedtls-cfg.h" if BOOT_USE_MBEDTLS && !NRF_SECURITY endif From a1a093a728f4a1aeec87c98de5372e1af305fc28 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jul 2023 08:42:49 +0100 Subject: [PATCH 278/287] [nrf noup] zephyr: Fix path variables Fixes path variables to use the proper Zephyr module variables Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit d978f7b4e9c000d554242c65800fdee51381a3d2) (cherry picked from commit 4943e2f425738025e48efc74d323884c4effdf4d) --- boot/zephyr/CMakeLists.txt | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 2849e31fe..7c60125bf 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -29,21 +29,20 @@ if(NOT CONFIG_MBEDTLS_BUILTIN AND NOT CONFIG_BOOT_KEY_IMPORT_BYPASS_ASN) set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") assert_exists(MBEDTLS_ASN1_DIR) endif() -set(NRF_DIR "${MCUBOOT_DIR}/ext/nrf") +set(MCUBOOT_NRF_EXT_DIR "${MCUBOOT_DIR}/ext/nrf") if(CONFIG_BOOT_USE_NRF_CC310_BL) -set(NRFXLIB_DIR ${ZEPHYR_BASE}/../nrfxlib) -if(NOT EXISTS ${NRFXLIB_DIR}) - message(FATAL_ERROR " + if(NOT EXISTS ${ZEPHYR_NRFXLIB_MODULE_DIR}) + message(FATAL_ERROR " ------------------------------------------------------------------------ - No such file or directory: ${NRFXLIB_DIR} + No such file or directory: ${ZEPHYR_NRFXLIB_MODULE_DIR} The current configuration enables nRF CC310 crypto accelerator hardware with the `CONFIG_BOOT_USE_NRF_CC310_BL` option. Please follow `ext/nrf/README.md` guide to fix your setup or use tinycrypt instead of the HW accelerator. To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") -endif() + endif() endif() zephyr_library_include_directories( @@ -191,8 +190,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) ${TINYCRYPT_DIR}/source/utils.c ) elseif(CONFIG_BOOT_USE_NRF_CC310_BL) - zephyr_library_sources(${NRF_DIR}/cc310_glue.c) - zephyr_library_include_directories(${NRF_DIR}) + zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) + zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) zephyr_link_libraries(nrfxlib_crypto) elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) zephyr_include_directories(${BL_CRYPTO_DIR}/../include) From 4399de2a69ff425a0a06c5955b042055e4c2fe49 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 22 Aug 2024 14:17:46 +0100 Subject: [PATCH 279/287] [nrf noup] zephyr: Add support for compressed image updates Adds support for LZMA-compressed firmware updates Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 474a92290901ffb468978574087e98fc89fb3e80) (cherry picked from commit 655eeacf16cfd090bb309ef06f940a943790e671) --- boot/bootutil/src/bootutil_misc.c | 80 +- boot/bootutil/src/image_validate.c | 226 ++++ boot/bootutil/src/loader.c | 27 +- boot/zephyr/CMakeLists.txt | 6 + boot/zephyr/Kconfig | 10 +- boot/zephyr/decompression.c | 1115 +++++++++++++++++ .../include/compression/decompression.h | 104 ++ 7 files changed, 1545 insertions(+), 23 deletions(-) create mode 100644 boot/zephyr/decompression.c create mode 100644 boot/zephyr/include/compression/decompression.h diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 56859d515..ac50eaa52 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -42,6 +42,11 @@ #include "bootutil/enc_key.h" #endif +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + BOOT_LOG_MODULE_DECLARE(mcuboot); /* Currently only used by imgmgr */ @@ -384,35 +389,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) goto done; } - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); +#ifdef MCUBOOT_DECOMPRESS_IMAGES + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { + uint32_t tmp_size = 0; - if (flash_area_read(fap, off, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } + rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { + if (rc) { rc = BOOT_EBADIMAGE; goto done; } - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; + + rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); + + if (rc) { + rc = BOOT_EBADIMAGE; + goto done; + } + + off += tmp_size; + + if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + + boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, + sizeof(info))) { rc = BOOT_EFLASH; goto done; } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + info.it_tlv_tot; + } else { +#else + if (1) { +#endif + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); + + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + protect_tlv_size + info.it_tlv_tot; } - *size = off + protect_tlv_size + info.it_tlv_tot; rc = 0; done: diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index e038f22fe..08f354be8 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -40,6 +40,15 @@ #include "mcuboot_config/mcuboot_config.h" +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -470,6 +479,68 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, FIH_DECLARE(security_counter_valid, FIH_FAILURE); #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* If the image is compressed, the integrity of the image must also be validated */ + if (MUST_DECOMPRESS(fap, image_index, hdr)) { + bool found_decompressed_size = false; + bool found_decompressed_sha = false; + bool found_decompressed_signature = false; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + uint16_t expected_size = 0; + bool *found_flag = NULL; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + switch (type) { + case IMAGE_TLV_DECOMP_SIZE: + expected_size = sizeof(size_t); + found_flag = &found_decompressed_size; + break; + case IMAGE_TLV_DECOMP_SHA: + expected_size = IMAGE_HASH_SIZE; + found_flag = &found_decompressed_sha; + break; + case IMAGE_TLV_DECOMP_SIGNATURE: + found_flag = &found_decompressed_signature; + break; + default: + continue; + }; + + if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { + rc = -1; + goto out; + } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { + rc = -1; + goto out; + } + + *found_flag = true; + } + + rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); + if (rc) { + goto out; + } + } +#endif + #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); @@ -680,6 +751,161 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* Only after all previous verifications have passed, perform a dry-run of the decompression + * and ensure the image is valid + */ + if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { + image_hash_valid = 0; + FIH_SET(valid_signature, FIH_FAILURE); + + rc = bootutil_img_hash_decompress(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz, + hash, seed, seed_len); + if (rc) { + goto out; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + /* Verify the image hash. This must always be present. */ + if (len != sizeof(hash)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); + if (rc) { + goto out; + } + + FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + image_hash_valid = 1; + } + } + + rc = !image_hash_valid; + if (rc) { + goto out; + } + +#ifdef EXPECTED_SIG_TLV +#ifdef EXPECTED_KEY_TLV + rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == EXPECTED_KEY_TLV) { + /* + * Determine which key we should be checking. + */ + if (len > KEY_BUF_SIZE) { + rc = -1; + goto out; + } +#ifndef MCUBOOT_HW_KEY + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(buf, len); +#else + rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(image_index, key_buf, len); +#endif /* !MCUBOOT_HW_KEY */ + /* + * The key may not be found, which is acceptable. There + * can be multiple signatures, each preceded by a key. + */ + } + } +#endif /* EXPECTED_KEY_TLV */ + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Ignore this signature if it is out of bounds. */ + if (key_id < 0 || key_id >= bootutil_key_cnt) { + key_id = -1; + continue; + } + + if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + + FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), + buf, len, key_id); + key_id = -1; + } + } +#endif /* EXPECTED_SIG_TLV */ + } +#endif + +#ifdef EXPECTED_SIG_TLV + FIH_SET(fih_rc, valid_signature); +#endif + out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 4c61c4217..a561d5cb7 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -49,6 +49,11 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + #ifdef __ZEPHYR__ #include #endif @@ -913,10 +918,10 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } #else - if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && - (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) - { - return false; + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { + if (!boot_is_compressed_header_valid(hdr, fap, state)) { + return false; + } } #endif @@ -1130,6 +1135,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * attempts to validate and boot it. */ } + #if !defined(__BOOTSIM__) BOOT_LOG_ERR("Image in the %s slot is not valid!", (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); @@ -1606,6 +1612,9 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + struct image_header *hdr; +#endif TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); @@ -1631,6 +1640,16 @@ boot_copy_region(struct boot_loader_state *state, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + + if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { + /* Use alternative function for compressed images */ + return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, + BUF_SZ); + } +#endif + bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 7c60125bf..a9a761a4d 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -288,6 +288,12 @@ if(CONFIG_BOOT_ENCRYPT_EC256) ) endif() +if(CONFIG_BOOT_DECOMPRESSION) + zephyr_library_sources( + decompression.c + ) +endif() + if(CONFIG_MCUBOOT_SERIAL) zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c) zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a3bb0aab0..d68ac4f6e 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -965,6 +965,10 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool + depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) + depends on !SINGLE_APPLICATION_SLOT && !BOOT_ENCRYPT_IMAGE && BOOT_UPGRADE_ONLY + depends on UPDATEABLE_IMAGE_NUMBER = 1 + default y help Hidden symbol which should be selected if a system provided decompression support. @@ -972,6 +976,8 @@ if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION bool "Decompression" + select NRF_COMPRESS_CLEANUP + select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to @@ -980,9 +986,9 @@ menuconfig BOOT_DECOMPRESSION if BOOT_DECOMPRESSION config BOOT_DECOMPRESSION_BUFFER_SIZE - int "Write buffer size" + int range 16 16384 - default 4096 + default NRF_COMPRESS_CHUNK_SIZE help The size of a secondary buffer used for writing decompressed data to the storage device. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c new file mode 100644 index 000000000..062cdbc61 --- /dev/null +++ b/boot/zephyr/decompression.c @@ -0,0 +1,1115 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include "compression/decompression.h" +#include "bootutil/crypto/sha.h" +#include "bootutil/bootutil_log.h" + +#if !defined(__BOOTSIM__) +#define TARGET_STATIC static +#else +#define TARGET_STATIC +#endif + +#if defined(MCUBOOT_SIGN_RSA) +#if MCUBOOT_SIGN_RSA_LEN == 2048 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS +#elif MCUBOOT_SIGN_RSA_LEN == 3072 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA3072_PSS +#endif +#elif defined(MCUBOOT_SIGN_EC256) || \ + defined(MCUBOOT_SIGN_EC384) || \ + defined(MCUBOOT_SIGN_EC) +#define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA_SIG +#elif defined(MCUBOOT_SIGN_ED25519) +#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 +#endif + +/* Number of times that consumed data by decompression system can be 0 in a row before aborting */ +#define OFFSET_ZERO_CHECK_TIMES 3 + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx); + +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state) +{ + /* Image is compressed in secondary slot, need to check if fits into the primary slot */ + bool opened_flash_area = false; + int primary_fa_id; + int rc; + int size_check; + int size; + uint32_t protected_tlvs_size; + uint32_t decompressed_size; + + if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { + opened_flash_area = true; + } + + primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); + rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + assert(rc == 0); + + size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + + if (opened_flash_area) { + (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + } + + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, decompressed_size, hdr->ih_hdr_size)) { + return false; + } + + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlvs_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, size, protected_tlvs_size)) { + return false; + } + + if (size >= size_check) { + BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", + size, size_check); + + return false; + } + + return true; +} + +int bootutil_img_hash_decompress(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 *hash_result, + uint8_t *seed, int seed_len) +{ + int rc; + uint32_t read_pos = 0; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t decompressed_image_size; + struct nrf_compress_implementation *compression = NULL; + TARGET_STATIC struct image_header modified_hdr; + bootutil_sha_context sha_ctx; + uint8_t flash_erased_value; + + bootutil_sha_init(&sha_ctx); + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + + goto finish_without_clean; + } + + compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish_without_clean; + } + + rc = compression->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish_without_clean; + } + + /* We need a modified header which has the updated sizes, start with the original header */ + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + /* Extract the decompressed image size from the protected TLV, set it and remove the + * compressed image flags + */ + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate the protected TLV size, these will not include the decompressed + * sha/size/signature entries + */ + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + bootutil_sha_update(&sha_ctx, &modified_hdr, sizeof(modified_hdr)); + read_pos = sizeof(modified_hdr); + flash_erased_value = flash_area_erased_val(fap); + memset(tmp_buf, flash_erased_value, tmp_buf_sz); + + while (read_pos < modified_hdr.ih_hdr_size) { + uint32_t copy_size = tmp_buf_sz; + + if ((read_pos + copy_size) > modified_hdr.ih_hdr_size) { + copy_size = modified_hdr.ih_hdr_size - read_pos; + } + + bootutil_sha_update(&sha_ctx, tmp_buf, copy_size); + read_pos += copy_size; + } + + /* Read in compressed data, decompress and add to hash calculation */ + read_pos = 0; + + while (read_pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - read_pos; + uint32_t tmp_off = 0; + uint8_t offset_zero_check = 0; + + if (copy_size > tmp_buf_sz) { + copy_size = tmp_buf_sz; + } + + rc = flash_area_read(fap, (hdr->ih_hdr_size + read_pos), tmp_buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint8_t *output = NULL; + uint32_t output_size = 0; + uint32_t chunk_size; + bool last_packet = false; + + chunk_size = compression->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + + if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { + last_packet = true; + } + + rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset, + &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + write_pos += output_size; + + if (write_pos > decompressed_image_size) { + BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", + write_pos); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + /* Additional dry-run validity checks */ + if (last_packet == true && write_pos == 0) { + /* Last packet and we still have no output, this is a faulty update */ + BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + if (offset == 0) { + /* If the decompression system continually consumes 0 bytes, then there is a + * problem with this update image, abort and mark image as bad + */ + if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { + BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + ++offset_zero_check; + + break; + } else { + offset_zero_check = 0; + } + + if (output_size > 0) { + bootutil_sha_update(&sha_ctx, output, output_size); + } + + tmp_off += offset; + } + + read_pos += copy_size; + } + + /* If there are any protected TLVs present, add them after the main decompressed image */ + if (modified_hdr.ih_protect_tlv_size > 0) { + rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, + tmp_buf_sz, &sha_ctx); + } + + bootutil_sha_finish(&sha_ctx, hash_result); + +finish: + /* Clean up decompression system */ + (void)compression->deinit(NULL); + +finish_without_clean: + bootutil_sha_drop(&sha_ctx); + + return rc; +} + +static int boot_copy_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t protected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t off; + uint32_t write_pos = 0; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Skip these TLVs as they are not needed */ + continue; + } else { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left = len; + + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - + header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + (len - data_size_left)), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + } + + *written = write_pos; + +out: + return rc; +} + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx) +{ + int rc; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + + bootutil_sha_update(sha_ctx, &tlv_info_header, sizeof(tlv_info_header)); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + while (true) { + uint32_t read_off = 0; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Skip these TLVs as they are not needed */ + continue; + } + + tlv_header.it_type = type; + tlv_header.it_len = len; + + bootutil_sha_update(sha_ctx, &tlv_header, sizeof(tlv_header)); + + while (read_off < len) { + uint32_t copy_size = buf_size; + + if (copy_size > (len - read_off)) { + copy_size = len - read_off; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + read_off), buf, copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + read_off), copy_size, fap_src->fa_id, rc); + + goto out; + } + + bootutil_sha_update(sha_ctx, buf, copy_size); + read_off += copy_size; + } + } + +out: + return rc; +} + +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = hdr->ih_protect_tlv_size; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Exclude these TLVs as they will be copied to the unprotected area */ + tlv_size -= len + sizeof(struct image_tlv); + } + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries then omit protected TLV section entirely */ + tlv_size = 0; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = sizeof(struct image_tlv_info); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off) && type != IMAGE_TLV_DECOMP_SHA && + type != IMAGE_TLV_DECOMP_SIGNATURE) { + /* Include size of protected hash and signature as these will be replacing the + * original ones + */ + continue; + } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + /* Exclude the original unprotected TLVs for signature and hash, the length of the + * signature of the compressed data might not be the same size as the signaute of the + * decompressed data, as is the case when using ECDSA-P256 + */ + continue; + } + + tlv_size += len + sizeof(struct image_tlv); + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries in the unprotected TLV section then there is something wrong + * with this image + */ + BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); + rc = BOOT_EBADIMAGE; + + goto out; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +static int boot_copy_unprotected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t unprotected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t write_pos = 0; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv_iter it_protected; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_INFO_MAGIC, + .it_tlv_tot = unprotected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, false); + if (rc) { + goto out; + } + + while (true) { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off)) { + /* Skip protected TLVs */ + continue; + } + + /* Change the values of these fields from having the data in the compressed image + * unprotected TLV (which is valid only for the compressed image data) to having the + * fields in the protected TLV section (which is valid for the decompressed image data). + * The compressed data is no longer needed + */ + if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + rc = bootutil_tlv_iter_begin(&it_protected, hdr, fap_src, (type == EXPECTED_HASH_TLV ? + IMAGE_TLV_DECOMP_SHA : + IMAGE_TLV_DECOMP_SIGNATURE), + true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it_protected, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + type = EXPECTED_HASH_TLV; + } else { + type = EXPECTED_SIG_TLV; + } + } + + data_size_left = len; + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + len - data_size_left), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + + *written = write_pos; + +out: + return rc; +} + +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size) +{ + int rc; + uint32_t pos = 0; + uint16_t decomp_buf_size = 0; + uint16_t write_alignment; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t unprotected_tlv_size = 0; + uint32_t tlv_write_size = 0; + uint32_t decompressed_image_size; + struct nrf_compress_implementation *compression = NULL; + struct image_header *hdr; + TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4))); + TARGET_STATIC struct image_header modified_hdr; + + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + rc = compression->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + write_alignment = flash_area_align(fap_dst); + + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + rc = bootutil_get_img_decomp_size(hdr, fap_src, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate protected TLV size for target image once items are removed */ + rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + + rc = boot_size_unprotected_tlvs(hdr, fap_src, &unprotected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + + goto finish; + } + + /* Write out the image header first, this should be a multiple of the write size */ + rc = flash_area_write(fap_dst, off_dst, &modified_hdr, sizeof(modified_hdr)); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + /* Read in, decompress and write out data */ + while (pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - pos; + uint32_t tmp_off = 0; + + if (copy_size > buf_size) { + copy_size = buf_size; + } + + rc = flash_area_read(fap_src, off_src + hdr->ih_hdr_size + pos, buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint32_t output_size = 0; + uint32_t chunk_size; + uint32_t compression_buffer_pos = 0; + uint8_t *output = NULL; + bool last_packet = false; + + chunk_size = compression->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + + if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { + last_packet = true; + } + + rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset, + &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + + goto finish; + } + + /* Copy data to secondary buffer for writing out */ + while (output_size > 0) { + uint32_t data_size = (sizeof(decomp_buf) - decomp_buf_size); + + if (data_size > output_size) { + data_size = output_size; + } + + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], data_size); + compression_buffer_pos += data_size; + + decomp_buf_size += data_size; + output_size -= data_size; + + /* Write data out from secondary buffer when it is full */ + if (decomp_buf_size == sizeof(decomp_buf)) { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, sizeof(decomp_buf)); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), sizeof(decomp_buf), + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + write_pos += sizeof(decomp_buf); + decomp_buf_size = 0; + } + } + + tmp_off += offset; + } + + pos += copy_size; + } + + /* Clean up decompression system */ + (void)compression->deinit(NULL); + + if (protected_tlv_size > 0) { + rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), protected_tlv_size, + decomp_buf, DECOMP_BUF_SIZE, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + + goto finish; + } + + write_pos += tlv_write_size; + } + + tlv_write_size = 0; + rc = boot_copy_unprotected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), unprotected_tlv_size, + decomp_buf, DECOMP_BUF_SIZE, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + + goto finish; + } + + write_pos += tlv_write_size; + + /* Check if we have unwritten data buffered up and, if so, write it out */ + if (decomp_buf_size > 0) { + uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); + + /* Check if additional write padding should be applied to meet the minimum write size */ + if (write_padding_size) { + uint8_t flash_erased_value; + + flash_erased_value = flash_area_erased_val(fap_dst); + memset(&decomp_buf[decomp_buf_size], flash_erased_value, write_padding_size); + decomp_buf_size += write_padding_size; + } + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf, + decomp_buf_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + + goto finish; + } + + write_pos += decomp_buf_size; + decomp_buf_size = 0; + } + +finish: + memset(decomp_buf, 0, sizeof(decomp_buf)); + + return rc; +} + +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size) +{ + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + if (hdr == NULL || fap == NULL || img_decomp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_decomp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_decomp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + + return BOOT_EFLASH; + } + + return 0; +} diff --git a/boot/zephyr/include/compression/decompression.h b/boot/zephyr/include/compression/decompression.h new file mode 100644 index 000000000..f8a676ac5 --- /dev/null +++ b/boot/zephyr/include/compression/decompression.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_DECOMPRESSION_ +#define H_DECOMPRESSION_ + +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil/bootutil_public.h" +#include "bootutil/image.h" +#include "../src/bootutil_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Checks if a compressed image header is valid. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param state Bootloader state object. + * + * @return true if valid; false if invalid. + */ +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state); + +/** + * Reads in compressed image data from a slot, decompresses it and writes it out to a destination + * slot, including corresponding image headers and TLVs. + * + * @param state Bootloader state object. + * @param fap_src Flash area of the source slot. + * @param fap_dst Flash area of the destination slot. + * @param off_src Offset of the source slot to read from (should be 0). + * @param off_dst Offset of the destination slot to write to (should be 0). + * @param sz Size of the source slot data. + * @param buf Temporary buffer for reading data from. + * @param buf_size Size of temporary buffer. + * + * @return 0 on success; nonzero on failure. + */ +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size); + +/** + * Gets the total data size (excluding headers and TLVs) of a compressed image when it is + * decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param img_decomp_size Pointer to variable that will be updated with the decompressed image + * size. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size); + +/** + * Calculate MCUboot-compatible image hash of compressed image slot. + * + * @param enc_state Not currently used, set to NULL. + * @param image_index Image number. + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param tmp_buf Temporary buffer for reading data from. + * @param tmp_buf_sz Size of temporary buffer. + * @param hash_result Pointer to a variable that will be updated with the image hash. + * @param seed Not currently used, set to NULL. + * @param seed_len Not currently used, set to 0. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_img_hash_decompress(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 *hash_result, + uint8_t *seed, int seed_len); + +/** + * Calculates the size that the compressed image protected TLV section will occupy once the image + * has been decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param sz Pointer to variable that will be updated with the protected TLV size. + * + * @return 0 on success; nonzero on failure. + */ +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap_src, + uint32_t *sz); + +#ifdef __cplusplus +} +#endif + +#endif /* H_DECOMPRESSION_ */ From b94c842a720f84bc5e63205b2db33d9ba6941612 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 2 Sep 2024 11:20:00 +0100 Subject: [PATCH 280/287] [nrf noup] zephyr: Add support for ARM thumb filter Adds support to the compressed image update for allowing encrypted images. Also removes the limit of having 1 updateable image Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 390c468afcdc4f3039a00efece68073355320a97) (cherry picked from commit cbb7da0a51f469b775bcbf9662ae3a905917563b) (cherry picked from commit 148712e7b4618aadbedd04e8d3ce5c3847d3be4f) --- boot/bootutil/src/loader.c | 2 +- boot/zephyr/Kconfig | 3 +- boot/zephyr/decompression.c | 439 +++++++++++++++++++++++++++++------- 3 files changed, 365 insertions(+), 79 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a561d5cb7..f9a9de71d 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1612,7 +1612,7 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES +#if defined(MCUBOOT_DECOMPRESS_IMAGES) && !defined(MCUBOOT_ENC_IMAGES) struct image_header *hdr; #endif diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index d68ac4f6e..72eb8031b 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -966,8 +966,7 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) - depends on !SINGLE_APPLICATION_SLOT && !BOOT_ENCRYPT_IMAGE && BOOT_UPGRADE_ONLY - depends on UPDATEABLE_IMAGE_NUMBER = 1 + depends on !SINGLE_APPLICATION_SLOT && BOOT_UPGRADE_ONLY default y help Hidden symbol which should be selected if a system provided decompression support. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index 062cdbc61..7a9507de6 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -29,6 +29,14 @@ #define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 #endif +#define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) +#define DECOMP_BUF_EXTRA_SIZE 2 +#else +#define DECOMP_BUF_EXTRA_SIZE 0 +#endif +#define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE) + /* Number of times that consumed data by decompression system can be 0 in a row before aborting */ #define OFFSET_ZERO_CHECK_TIMES 3 @@ -50,11 +58,17 @@ bool boot_is_compressed_header_valid(const struct image_header *hdr, const struc uint32_t protected_tlvs_size; uint32_t decompressed_size; + primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); + + if (primary_fa_id == fap->fa_id) { + BOOT_LOG_ERR("Primary slots cannot be compressed, image: %d", BOOT_CURR_IMG(state)); + return false; + } + if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { opened_flash_area = true; } - primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); assert(rc == 0); @@ -87,13 +101,71 @@ bool boot_is_compressed_header_valid(const struct image_header *hdr, const struc if (size >= size_check) { BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", size, size_check); - return false; } return true; } +static bool is_compression_object_valid(struct nrf_compress_implementation *compression) +{ + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + return false; + } + + return true; +} + +#ifdef MCUBOOT_ENC_IMAGES +int bootutil_get_img_decrypted_comp_size(const struct image_header *hdr, + const struct flash_area *fap, uint32_t *img_comp_size) +{ + if (hdr == NULL || fap == NULL || img_comp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + if (!IS_ENCRYPTED(hdr)) { + /* Update is not encrypted so use size from header */ + *img_comp_size = hdr->ih_img_size; + } else { + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_COMP_DEC_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_comp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_comp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + return BOOT_EFLASH; + } + } + + return 0; +} +#endif + int bootutil_img_hash_decompress(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 *hash_result, @@ -104,13 +176,35 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index uint32_t write_pos = 0; uint32_t protected_tlv_size = 0; uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression = NULL; + uint32_t output_size_total = 0; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; TARGET_STATIC struct image_header modified_hdr; bootutil_sha_context sha_ctx; uint8_t flash_erased_value; +#ifdef MCUBOOT_ENC_IMAGES + uint32_t comp_size = 0; + + rc = bootutil_get_img_decrypted_comp_size(hdr, fap, &comp_size); + + if (rc) { + BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); + rc = BOOT_EBADIMAGE; + goto finish_end; + } +#endif + bootutil_sha_init(&sha_ctx); +#ifdef MCUBOOT_ENC_IMAGES + /* Encrypted images only exist in the secondary slot */ + if (MUST_DECRYPT(fap, image_index, hdr) && + !boot_enc_valid(enc_state, 1)) { + return -1; + } +#endif + /* Setup decompression system */ #if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { @@ -122,27 +216,26 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; } - compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish_without_clean; } - rc = compression->init(NULL); + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); if (rc) { BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish_without_clean; } @@ -157,7 +250,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -172,7 +264,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (rc) { BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -196,8 +287,13 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index /* Read in compressed data, decompress and add to hash calculation */ read_pos = 0; +#ifdef MCUBOOT_ENC_IMAGES + while (read_pos < comp_size) { + uint32_t copy_size = comp_size - read_pos; +#else while (read_pos < hdr->ih_img_size) { uint32_t copy_size = hdr->ih_img_size - read_pos; +#endif uint32_t tmp_off = 0; uint8_t offset_zero_check = 0; @@ -211,10 +307,17 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } +#ifdef MCUBOOT_ENC_IMAGES + if (MUST_DECRYPT(fap, image_index, hdr)) { + boot_enc_decrypt(enc_state, 1, read_pos, + copy_size, (read_pos & 0xf), + tmp_buf); + } +#endif + /* Decompress data in chunks, writing it back with a larger write offset of the primary * slot than read size of the secondary slot */ @@ -225,23 +328,26 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index uint32_t chunk_size; bool last_packet = false; - chunk_size = compression->decompress_bytes_needed(NULL); + chunk_size = compression_lzma->decompress_bytes_needed(NULL); if (chunk_size > (copy_size - tmp_off)) { chunk_size = (copy_size - tmp_off); } +#ifdef MCUBOOT_ENC_IMAGES + if ((read_pos + tmp_off + chunk_size) >= comp_size) { +#else if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { +#endif last_packet = true; } - rc = compression->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, &offset, - &output, &output_size); + rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); if (rc) { BOOT_LOG_ERR("Decompression error: %d", rc); rc = BOOT_EBADSTATUS; - goto finish; } @@ -251,7 +357,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", write_pos); rc = BOOT_EBADIMAGE; - goto finish; } @@ -260,7 +365,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index /* Last packet and we still have no output, this is a faulty update */ BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -271,7 +375,6 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -282,8 +385,48 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index offset_zero_check = 0; } + /* Copy data to secondary buffer for calculating hash */ if (output_size > 0) { - bootutil_sha_update(&sha_ctx, output, output_size); + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + /* Run this through the ARM thumb filter */ + uint32_t offset_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t processed_size = 0; + uint32_t output_size_arm_thumb = 0; + + while (processed_size < output_size) { + uint32_t current_size = output_size - processed_size; + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_packet && (processed_size + current_size) == + output_size) { + arm_thumb_last_packet = true; + } + + rc = compression_arm_thumb->decompress(NULL, &output[processed_size], + current_size, arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb); + output_size_total += output_size_arm_thumb; + processed_size += current_size; + } + } else { + bootutil_sha_update(&sha_ctx, output, output_size); + output_size_total += output_size; + } } tmp_off += offset; @@ -292,6 +435,13 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index read_pos += copy_size; } + if (modified_hdr.ih_img_size != output_size_total) { + BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d", + modified_hdr.ih_img_size, output_size_total); + rc = BOOT_EBADSTATUS; + goto finish; + } + /* If there are any protected TLVs present, add them after the main decompressed image */ if (modified_hdr.ih_protect_tlv_size > 0) { rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, @@ -302,11 +452,15 @@ int bootutil_img_hash_decompress(struct enc_key_data *enc_state, int image_index finish: /* Clean up decompression system */ - (void)compression->deinit(NULL); + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); finish_without_clean: bootutil_sha_drop(&sha_ctx); +#ifdef MCUBOOT_ENC_IMAGES +finish_end: +#endif return rc; } @@ -353,7 +507,6 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -379,7 +532,7 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, } if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { /* Skip these TLVs as they are not needed */ continue; } else { @@ -422,7 +575,6 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - goto out; } @@ -438,7 +590,6 @@ static int boot_copy_protected_tlvs(const struct image_header *hdr, "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -490,7 +641,7 @@ static int boot_sha_protected_tlvs(const struct image_header *hdr, } if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { /* Skip these TLVs as they are not needed */ continue; } @@ -513,7 +664,6 @@ static int boot_sha_protected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + read_off), copy_size, fap_src->fa_id, rc); - goto out; } @@ -556,7 +706,7 @@ int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_ } if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE) { + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { /* Exclude these TLVs as they will be copied to the unprotected area */ tlv_size -= len + sizeof(struct image_tlv); } @@ -608,7 +758,7 @@ int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flas * original ones */ continue; - } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV || type == IMAGE_TLV_COMP_DEC_SIZE) { /* Exclude the original unprotected TLVs for signature and hash, the length of the * signature of the compressed data might not be the same size as the signaute of the * decompressed data, as is the case when using ECDSA-P256 @@ -626,7 +776,6 @@ int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flas */ BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); rc = BOOT_EBADIMAGE; - goto out; } @@ -681,7 +830,6 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -778,7 +926,6 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, BOOT_LOG_ERR( "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - goto out; } @@ -794,7 +941,6 @@ static int boot_copy_unprotected_tlvs(const struct image_header *hdr, "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto out; } @@ -823,13 +969,33 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint32_t unprotected_tlv_size = 0; uint32_t tlv_write_size = 0; uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression = NULL; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; struct image_header *hdr; - TARGET_STATIC uint8_t decomp_buf[CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE] __attribute__((aligned(4))); + TARGET_STATIC uint8_t decomp_buf[DECOMP_BUF_ALLOC_SIZE] __attribute__((aligned(4))); TARGET_STATIC struct image_header modified_hdr; +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + uint8_t excess_data_buffer[DECOMP_BUF_EXTRA_SIZE]; + bool excess_data_buffer_full = false; +#endif + +#ifdef MCUBOOT_ENC_IMAGES + uint32_t comp_size = 0; +#endif + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); +#ifdef MCUBOOT_ENC_IMAGES + rc = bootutil_get_img_decrypted_comp_size(hdr, fap_src, &comp_size); + + if (rc) { + BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); + rc = BOOT_EBADIMAGE; + goto finish; + } +#endif + /* Setup decompression system */ #if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { @@ -841,27 +1007,26 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish; } - compression = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish; } - rc = compression->init(NULL); + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); if (rc) { BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish; } @@ -874,7 +1039,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -887,7 +1051,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -898,7 +1061,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; } @@ -909,13 +1071,17 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } /* Read in, decompress and write out data */ +#ifdef MCUBOOT_ENC_IMAGES + while (pos < comp_size) { + uint32_t copy_size = comp_size - pos; +#else while (pos < hdr->ih_img_size) { uint32_t copy_size = hdr->ih_img_size - pos; +#endif uint32_t tmp_off = 0; if (copy_size > buf_size) { @@ -928,10 +1094,15 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } +#ifdef MCUBOOT_ENC_IMAGES + if (IS_ENCRYPTED(hdr)) { + boot_enc_decrypt(BOOT_CURR_ENC(state), 1, pos, copy_size, (pos & 0xf), buf); + } +#endif + /* Decompress data in chunks, writing it back with a larger write offset of the primary * slot than read size of the secondary slot */ @@ -943,57 +1114,156 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint8_t *output = NULL; bool last_packet = false; - chunk_size = compression->decompress_bytes_needed(NULL); + chunk_size = compression_lzma->decompress_bytes_needed(NULL); if (chunk_size > (copy_size - tmp_off)) { chunk_size = (copy_size - tmp_off); } +#ifdef MCUBOOT_ENC_IMAGES + if ((pos + tmp_off + chunk_size) >= comp_size) { +#else if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { +#endif last_packet = true; } - rc = compression->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, &offset, - &output, &output_size); + rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); if (rc) { BOOT_LOG_ERR("Decompression error: %d", rc); rc = BOOT_EBADSTATUS; - goto finish; } /* Copy data to secondary buffer for writing out */ while (output_size > 0) { - uint32_t data_size = (sizeof(decomp_buf) - decomp_buf_size); + uint32_t data_size = (DECOMP_BUF_SIZE - decomp_buf_size); if (data_size > output_size) { data_size = output_size; } - memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], data_size); +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + memcpy(&decomp_buf[decomp_buf_size + DECOMP_BUF_EXTRA_SIZE], + &output[compression_buffer_pos], data_size); + } else +#endif + { + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], + data_size); + } + compression_buffer_pos += data_size; decomp_buf_size += data_size; output_size -= data_size; /* Write data out from secondary buffer when it is full */ - if (decomp_buf_size == sizeof(decomp_buf)) { - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, sizeof(decomp_buf)); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), sizeof(decomp_buf), - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - - goto finish; + if (decomp_buf_size == DECOMP_BUF_SIZE) { +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + uint32_t filter_writeback_pos = 0; + uint32_t processed_size = 0; + + /* Run this through the ARM thumb filter */ + while (processed_size < DECOMP_BUF_SIZE) { + uint32_t offset_arm_thumb = 0; + uint32_t output_size_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t current_size = DECOMP_BUF_SIZE; + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_packet && (processed_size + current_size) == DECOMP_BUF_SIZE + && output_size == 0) { + arm_thumb_last_packet = true; + } + + rc = compression_arm_thumb->decompress(NULL, + &decomp_buf[processed_size + + DECOMP_BUF_EXTRA_SIZE], + current_size, + arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + memcpy(&decomp_buf[filter_writeback_pos], output_arm_thumb, + output_size_arm_thumb); + filter_writeback_pos += output_size_arm_thumb; + processed_size += current_size; + } + + if (excess_data_buffer_full == true) + { + /* Restore extra data removed from previous iteration to the write + * buffer + */ + memmove(&decomp_buf[DECOMP_BUF_EXTRA_SIZE], decomp_buf, + filter_writeback_pos); + memcpy(decomp_buf, excess_data_buffer, DECOMP_BUF_EXTRA_SIZE); + excess_data_buffer_full = false; + filter_writeback_pos += DECOMP_BUF_EXTRA_SIZE; + } + + if ((filter_writeback_pos % sizeof(uint32_t)) != 0) + { + /* Since there are an extra 2 bytes here, remove them and stash for + * later usage to prevent flash write issues with non-word boundary + * writes + */ + memcpy(excess_data_buffer, &decomp_buf[filter_writeback_pos - + DECOMP_BUF_EXTRA_SIZE], + DECOMP_BUF_EXTRA_SIZE); + excess_data_buffer_full = true; + filter_writeback_pos -= DECOMP_BUF_EXTRA_SIZE; + } + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, filter_writeback_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), DECOMP_BUF_SIZE, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += filter_writeback_pos; + decomp_buf_size = 0; + filter_writeback_pos = 0; + } else +#endif + { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, DECOMP_BUF_SIZE); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), DECOMP_BUF_SIZE, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += DECOMP_BUF_SIZE; + decomp_buf_size = 0; } - - write_pos += sizeof(decomp_buf); - decomp_buf_size = 0; } } @@ -1003,8 +1273,30 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl pos += copy_size; } +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0) { + /* Extra data that has not been written out that needs ARM thumb filter applied */ + uint32_t offset_arm_thumb = 0; + uint32_t output_size_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + + rc = compression_arm_thumb->decompress(NULL, &decomp_buf[DECOMP_BUF_EXTRA_SIZE], + decomp_buf_size, true, &offset_arm_thumb, + &output_arm_thumb, &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + memcpy(decomp_buf, output_arm_thumb, output_size_arm_thumb); + } +#endif + /* Clean up decompression system */ - (void)compression->deinit(NULL); + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); if (protected_tlv_size > 0) { rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + @@ -1014,7 +1306,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - goto finish; } @@ -1029,7 +1320,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - goto finish; } @@ -1040,7 +1330,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); /* Check if additional write padding should be applied to meet the minimum write size */ - if (write_padding_size) { + if (write_alignment > 1 && write_padding_size) { uint8_t flash_erased_value; flash_erased_value = flash_area_erased_val(fap_dst); @@ -1056,7 +1346,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, fap_dst->fa_id, rc); rc = BOOT_EFLASH; - goto finish; } @@ -1098,7 +1387,6 @@ int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct fl if (len != sizeof(*img_decomp_size)) { BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); - return BOOT_EBADIMAGE; } @@ -1107,7 +1395,6 @@ int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct fl if (rc) { BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", off, len, fap->fa_id, rc); - return BOOT_EFLASH; } From d88f72af380e60371d21f7e58e32ff8b38493829 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 17 Oct 2024 19:38:39 +0000 Subject: [PATCH 281/287] [nrf noup] Remove setting default MCUboot mbedTLS config This has been overriding logic that selects nrf-config.h when CONFIG_NRF_SECURITY=y. Signed-off-by: Dominik Ermel (cherry picked from commit ea00c047de0adbadc7162b945bfb139136f434cb) (cherry picked from commit 62929e493c6feb75fc83378d7235280e14a745cc) --- boot/zephyr/prj.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index e4f7d9030..9ff1ba274 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -1,7 +1,6 @@ CONFIG_PM=n CONFIG_MAIN_STACK_SIZE=10240 -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" CONFIG_BOOT_SWAP_SAVE_ENCTLV=n CONFIG_BOOT_ENCRYPT_IMAGE=n From 1d1508349c93896750da1c0a2271ac0ec22dc5b0 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 20 Sep 2024 16:34:00 +0000 Subject: [PATCH 282/287] [nrf noup] bootutil: Add support for KMU stored ED25519 signature key The commit adds verification of image using keys stored in KMU. Signed-off-by: Dominik Ermel (cherry picked from commit 6e0c2b8794daa33d7688b35fc4af04c4d8052d41) (cherry picked from commit b647a94a24b1a20b3cbbde41ff9a4a92be67a232) --- boot/bootutil/src/ed25519_psa.c | 51 ++++++++++++++++++++++++++++++ boot/bootutil/src/image_ed25519.c | 9 +++++- boot/bootutil/src/image_validate.c | 12 +++++-- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 26 +++++++++++++++ 5 files changed, 96 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 12ba20ac1..b6153f9a4 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,6 +12,9 @@ #include #include +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#include +#endif BOOT_LOG_MODULE_REGISTER(ed25519_psa); @@ -19,6 +22,18 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define EDDSA_KEY_LENGTH 32 #define EDDSA_SIGNAGURE_LENGTH 64 +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +/* List of KMU stored key ids available for MCUboot */ +#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) +static psa_key_id_t kmu_key_ids[3] = { + MAKE_PSA_KMU_KEY_ID(226), + MAKE_PSA_KMU_KEY_ID(228), + MAKE_PSA_KMU_KEY_ID(230) +}; +#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) +#endif + +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -69,3 +84,39 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } +#else +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], + const uint8_t public_key[EDDSA_KEY_LENGTH]) +{ + ARG_UNUSED(public_key); + /* Set to any error */ + psa_status_t status = PSA_ERROR_BAD_STATE; + int ret = 0; /* Fail by default */ + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", status); + return 0; + } + + status = PSA_ERROR_BAD_STATE; + + for (int i = 0; i < KMU_KEY_COUNT; ++i) { + psa_key_id_t kid = kmu_key_ids[i]; + + status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, + message_len, signature, + EDDSA_SIGNAGURE_LENGTH); + if (status == PSA_SUCCESS) { + ret = 1; + break; + } + + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + } + + return ret; +} +#endif diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index ffb8cec3b..d5aee65bc 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -31,6 +31,7 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) /* * Parse the public key used for signing. @@ -73,6 +74,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ +#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -87,14 +89,17 @@ bootutil_verify(uint8_t *buf, uint32_t blen, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey; + uint8_t *pubkey = NULL; +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) uint8_t *end; +#endif if (slen != EDDSA_SIGNATURE_LENGTH) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -116,6 +121,8 @@ bootutil_verify(uint8_t *buf, uint32_t blen, } pubkey = end - NUM_ED25519_BYTES; +#endif + #endif rc = ED25519_verify(buf, blen, sig, pubkey); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 08f354be8..6f1cbc568 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -245,6 +245,7 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index, # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_HW_KEY) static int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) @@ -310,6 +311,7 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) } #endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ /** @@ -627,6 +629,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, break; } #endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { @@ -657,14 +660,17 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, break; } #endif /* EXPECTED_KEY_TLV */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -810,7 +816,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, } #ifdef EXPECTED_SIG_TLV -#ifdef EXPECTED_KEY_TLV +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && defined(EXPECTED_KEY_TLV) rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); if (rc) { goto out; @@ -856,7 +862,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, */ } } -#endif /* EXPECTED_KEY_TLV */ +#endif /* !CONFIG_BOOT_SIGNATURE_USING_KMU && EXPECTED_KEY_TLV */ rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); if (rc) { @@ -879,10 +885,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index a9a761a4d..537a7580c 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -315,7 +315,7 @@ if(CONFIG_MCUBOOT_SERIAL) endif() endif() -if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") +if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU AND NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") # CONF_FILE points to the KConfig configuration files of the bootloader. foreach (filepath ${CONF_FILE}) file(READ ${filepath} temp_text) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 72eb8031b..a9289ccbd 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -331,6 +331,22 @@ endif endchoice +config BOOT_SIGNATURE_USING_KMU + bool "Use KMU stored keys for signature verification" + depends on NRF_SECURITY + depends on CRACEN_LIB_KMU + select PSA_WANT_ALG_GCM + select PSA_WANT_KEY_TYPE_AES + select PSA_WANT_AES_KEY_SIZE_256 + select PSA_WANT_ALG_SP800_108_COUNTER_CMAC + select PSA_WANT_ALG_CMAC + select PSA_WANT_ALG_ECB_NO_PADDING + help + MCUboot will use keys provisioned to the device key management unit for signature + verification instead of compiling in key data from a file. + +if !BOOT_SIGNATURE_USING_KMU + config BOOT_SIGNATURE_KEY_FILE string "PEM key file" default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 @@ -348,6 +364,8 @@ config BOOT_SIGNATURE_KEY_FILE with the public key information will be written in a format expected by MCUboot. +endif + config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" depends on CPU_CORTEX_M @@ -370,6 +388,14 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +# Disable MBEDTLS from being selected if NRF_SECURITY is enabled, and use default NRF_SECURITY +# configuration file for MBEDTLS +config MBEDTLS + depends on !NRF_SECURITY + +config NRF_SECURITY + select MBEDTLS_PROMPTLESS + if MBEDTLS || NRF_SECURITY config MBEDTLS_CFG_FILE From 2ffbf8aa3ee9e7b8d9788dcf140623e4bdc297a0 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Nov 2024 10:53:06 +0000 Subject: [PATCH 283/287] [nrf noup] boot: zephyr: Add experimental selection to compression Adds selecting the experimental Kconfig when compession is in use Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit ff3c31fba7e8eb659d8505e9c635057a2ca53987) (cherry picked from commit 4ceb4773b31dd8d56dfcb6e0461a70bb161ca95f) --- boot/zephyr/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a9289ccbd..6af784f9a 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1000,9 +1000,10 @@ config BOOT_DECOMPRESSION_SUPPORT if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION - bool "Decompression" + bool "Decompression [EXPERIMENTAL]" select NRF_COMPRESS_CLEANUP select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP + select EXPERIMENTAL help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to From 519e62ae6b11e7cb82a1773e125ea761a7999f43 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 2 Dec 2024 10:51:41 +0000 Subject: [PATCH 284/287] [nrf noup] boot: bootutil: Allow configuring number of KMU keys Adds a new Kconfig CONFIG_BOOT_SIGNATURE_KMU_SLOTS which allows specifying how many KMU key IDs are supported, the default is set to 1 instead of 3 which was set before NCSDK-30743 Signed-off-by: Jamie McCrae (cherry picked from commit 12e5ee106034972b0f1074d6f2261b2b39d1501b) (cherry picked from commit 2ca0efedf8d331028455f05d77f1c3c5064b773b) --- boot/bootutil/src/ed25519_psa.c | 7 +++++-- boot/zephyr/Kconfig | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index b6153f9a4..3e9cf2cbd 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,6 +12,7 @@ #include #include +#include #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #include #endif @@ -30,7 +31,9 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; -#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) + +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), + "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) @@ -103,7 +106,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < KMU_KEY_COUNT; ++i) { + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 6af784f9a..99b946926 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -345,6 +345,18 @@ config BOOT_SIGNATURE_USING_KMU MCUboot will use keys provisioned to the device key management unit for signature verification instead of compiling in key data from a file. +if BOOT_SIGNATURE_USING_KMU + +config BOOT_SIGNATURE_KMU_SLOTS + int "KMU key slots" + range 1 3 + default 1 + help + Selects the number of KMU key slots (also known as generations) to use when verifying + an image. + +endif + if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 0535f4c35a6ac59b5146aaaadea3b9c57881640f Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 9 Jan 2025 11:09:49 +0000 Subject: [PATCH 285/287] [nrf fromtree] boot: bootutil: Add TLV for size of compressed but decrypted image This TLV is needed in order to know what the data length provided to the decompression system is to remove the padding that is a resultant of the encryption block size Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 4bda587549c0fccd5cd9b59d76c8edf061ee84c3) (cherry picked from commit bc8d277df74908cd52f24fd9a3744f225f21169e) --- boot/bootutil/include/bootutil/image.h | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 05e04438b..92adc605b 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -124,6 +124,7 @@ struct flash_area; * the format and size of the raw slot (compressed) * signature */ +#define IMAGE_TLV_COMP_DEC_SIZE 0x73 /* Compressed decrypted image size */ /* * vendor reserved TLVs at xxA0-xxFF, * where xx denotes the upper byte From 91c282e7afc83c666ad478fbe70ff3e48ac56a05 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 14 Mar 2025 17:51:23 +0000 Subject: [PATCH 286/287] [nrf noup] zephyr: Use mbedTLS specific C functions with RSA Use snprinf, alloc, calloc and free from mbedTLS rather than from Zephyr. Signed-off-by: Dominik Ermel --- boot/zephyr/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 99b946926..a2614917b 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -223,6 +223,8 @@ config BOOT_SIGNATURE_TYPE_RSA select MBEDTLS select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN select MBEDTLS_KEY_EXCHANGE_RSA_ENABLED if MBEDTLS_BUILTIN + select MBEDTLS_PLATFORM_NO_STD_FUNCTIONS if MBEDTLS_BUILTIN + select MBEDTLS_PLATFORM_SNPRINTF_ALT if MBEDTLS_BUILTIN select BOOT_ENCRYPTION_SUPPORT select BOOT_IMG_HASH_ALG_SHA256_ALLOW select BOOT_AES_MBEDTLS_DEPENDENCIES if MBEDTLS_BUILTIN && BOOT_ENCRYPT_IMAGE From 2513d4b8c433e3460ce5c9cbfee4371b91d02ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ga=C5=82da?= Date: Tue, 25 Mar 2025 15:53:03 +0100 Subject: [PATCH 287/287] [nrf noup] ci: Pin GH actions to SHAs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Jira: NCSDK-32440 Signed-off-by: Jan Gałda --- .github/workflows/backport.yml | 2 +- .github/workflows/commit-tags.yml | 2 +- .github/workflows/espressif.yaml | 2 +- .github/workflows/fih_tests.yaml | 2 +- .github/workflows/imgtool.yaml | 10 +++++----- .github/workflows/issue.yml | 2 +- .github/workflows/issue_closed.yml | 2 +- .github/workflows/mynewt.yaml | 4 ++-- .github/workflows/sim.yaml | 4 ++-- .github/workflows/stale_issue.yml | 2 +- .github/workflows/zephyr_build.yaml | 6 +++--- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index e986738ff..af2f0ac90 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -24,7 +24,7 @@ jobs: ) steps: - name: Backport - uses: zephyrproject-rtos/action-backport@v2.0.3-3 + uses: zephyrproject-rtos/action-backport@6b0bae5b575d289305a22ab11a273941b518994c # v2.0.3-3 with: github_token: ${{ secrets.NCS_GITHUB_TOKEN }} issue_labels: Backport diff --git a/.github/workflows/commit-tags.yml b/.github/workflows/commit-tags.yml index 534ed5b58..2f3b8a25b 100644 --- a/.github/workflows/commit-tags.yml +++ b/.github/workflows/commit-tags.yml @@ -16,7 +16,7 @@ jobs: echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Checkout the code - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 diff --git a/.github/workflows/espressif.yaml b/.github/workflows/espressif.yaml index a5c3a75c7..b672abec0 100644 --- a/.github/workflows/espressif.yaml +++ b/.github/workflows/espressif.yaml @@ -35,7 +35,7 @@ jobs: MCUBOOT_FEATURES: ${{ matrix.features }} MCUBOOT_IMG_NUM: ${{ matrix.img }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2 with: fetch-depth: 0 submodules: recursive diff --git a/.github/workflows/fih_tests.yaml b/.github/workflows/fih_tests.yaml index 8fcef2332..33f3e13e5 100644 --- a/.github/workflows/fih_tests.yaml +++ b/.github/workflows/fih_tests.yaml @@ -32,7 +32,7 @@ jobs: - "MINSIZEREL 8,10 SIGNATURE MEDIUM" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2 with: fetch-depth: 0 # Uses Mbed TLS from TFM, and nothing else from here. diff --git a/.github/workflows/imgtool.yaml b/.github/workflows/imgtool.yaml index e3dc80457..85e81cd10 100644 --- a/.github/workflows/imgtool.yaml +++ b/.github/workflows/imgtool.yaml @@ -18,9 +18,9 @@ jobs: matrix: python-version: ["3.x", "pypy3.9"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4 with: python-version: ${{ matrix.python-version }} cache: 'pipenv' @@ -35,7 +35,7 @@ jobs: pipenv run pip install pytest -e . pipenv run pytest --junitxml=../junit/pytest-results-${{ matrix.python-version }}.xml - name: Upload test results - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4 if: always() with: name: pytest-results-${{ matrix.python-version }} @@ -47,11 +47,11 @@ jobs: if: ${{ github.event_name == 'push' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2 with: fetch-depth: 0 - name: Cache pip - uses: actions/cache@v4 + uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip diff --git a/.github/workflows/issue.yml b/.github/workflows/issue.yml index 6f05889c7..c51f9320f 100644 --- a/.github/workflows/issue.yml +++ b/.github/workflows/issue.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'mcu-tools/mcuboot' steps: - - uses: fojia/action-move-issues-to-column@master + - uses: fojia/action-move-issues-to-column@e56b9b3dc1a153cf4c9fd6f20064a431dd3e0b62 # master with: project: 'Issue Tracking' column: 'No Status' diff --git a/.github/workflows/issue_closed.yml b/.github/workflows/issue_closed.yml index 4477a087f..341c72256 100644 --- a/.github/workflows/issue_closed.yml +++ b/.github/workflows/issue_closed.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'mcu-tools/mcuboot' steps: - - uses: fojia/action-move-issues-to-column@master + - uses: fojia/action-move-issues-to-column@e56b9b3dc1a153cf4c9fd6f20064a431dd3e0b62 # master with: project: 'MCUboot releases' column: 'Done' diff --git a/.github/workflows/mynewt.yaml b/.github/workflows/mynewt.yaml index 1fe66fe23..08f736b29 100644 --- a/.github/workflows/mynewt.yaml +++ b/.github/workflows/mynewt.yaml @@ -15,10 +15,10 @@ jobs: environment: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2 with: fetch-depth: 0 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3 with: go-version: 'stable' - name: Print the environment diff --git a/.github/workflows/sim.yaml b/.github/workflows/sim.yaml index c1d91a673..3d5fa4d79 100644 --- a/.github/workflows/sim.yaml +++ b/.github/workflows/sim.yaml @@ -51,7 +51,7 @@ jobs: env: MULTI_FEATURES: ${{ matrix.features }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2 with: fetch-depth: 0 submodules: recursive @@ -66,7 +66,7 @@ jobs: run: | ./ci/check-signed-off-by.sh - name: Install stable Rust - uses: actions-rs/toolchain@v1 + uses: actions-rs/toolchain@63eb9591781c46a70274cb3ebdf190fce92702e8 # v1 with: toolchain: stable - name: Sim install diff --git a/.github/workflows/stale_issue.yml b/.github/workflows/stale_issue.yml index 6dec8b169..5446f6e9c 100644 --- a/.github/workflows/stale_issue.yml +++ b/.github/workflows/stale_issue.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'mcu-tools/mcuboot' steps: - - uses: actions/stale@v3 + - uses: actions/stale@98ed4cb500039dbcccf4bd9bedada4d0187f2757 # v3 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: 'This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.' diff --git a/.github/workflows/zephyr_build.yaml b/.github/workflows/zephyr_build.yaml index e1ef4631d..993f178a4 100644 --- a/.github/workflows/zephyr_build.yaml +++ b/.github/workflows/zephyr_build.yaml @@ -60,7 +60,7 @@ jobs: echo "MCUBOOT_VERSION=${{ github.event.pull_request.head.sha }}" >> $GITHUB_ENV - name: Checkout Zephyr - uses: actions/checkout@v2 + uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2 with: repository: 'zephyrproject-rtos/zephyr' ref: ${{ env.ZEPHYR_VERSION }} @@ -74,7 +74,7 @@ jobs: west update - name: Checkout MCUBoot - uses: actions/checkout@v2 + uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2 with: repository: 'mcu-tools/mcuboot' ref: ${{ env.MCUBOOT_VERSION }} @@ -95,7 +95,7 @@ jobs: ./scripts/twister --inline-logs -v -N -M --integration --overflow-as-errors --retry-failed 2 ${test_paths} - name: Upload Tests Results - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4 if: always() with: name: Tests Results