Initial commit
Initial commit.
This commit is contained in:
2
bootloader/mcuboot/sim/.gitignore
vendored
Normal file
2
bootloader/mcuboot/sim/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
target
|
||||
.*.swp
|
||||
54
bootloader/mcuboot/sim/Cargo.toml
Normal file
54
bootloader/mcuboot/sim/Cargo.toml
Normal file
@@ -0,0 +1,54 @@
|
||||
[package]
|
||||
name = "bootsim"
|
||||
version = "0.1.0"
|
||||
authors = ["David Brown <davidb@davidb.org>"]
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
sig-rsa = ["mcuboot-sys/sig-rsa"]
|
||||
sig-rsa3072 = ["mcuboot-sys/sig-rsa3072"]
|
||||
sig-ecdsa = ["mcuboot-sys/sig-ecdsa"]
|
||||
sig-ecdsa-mbedtls = ["mcuboot-sys/sig-ecdsa-mbedtls"]
|
||||
sig-ecdsa-psa = ["mcuboot-sys/sig-ecdsa-psa", "mcuboot-sys/psa-crypto-api"]
|
||||
sig-p384 = ["mcuboot-sys/sig-p384"]
|
||||
sig-ed25519 = ["mcuboot-sys/sig-ed25519"]
|
||||
overwrite-only = ["mcuboot-sys/overwrite-only"]
|
||||
swap-move = ["mcuboot-sys/swap-move"]
|
||||
validate-primary-slot = ["mcuboot-sys/validate-primary-slot"]
|
||||
enc-rsa = ["mcuboot-sys/enc-rsa"]
|
||||
enc-aes256-rsa = ["mcuboot-sys/enc-aes256-rsa"]
|
||||
enc-kw = ["mcuboot-sys/enc-kw"]
|
||||
enc-aes256-kw = ["mcuboot-sys/enc-aes256-kw"]
|
||||
enc-ec256 = ["mcuboot-sys/enc-ec256"]
|
||||
enc-ec256-mbedtls = ["mcuboot-sys/enc-ec256-mbedtls"]
|
||||
enc-aes256-ec256 = ["mcuboot-sys/enc-aes256-ec256"]
|
||||
enc-x25519 = ["mcuboot-sys/enc-x25519"]
|
||||
enc-aes256-x25519 = ["mcuboot-sys/enc-aes256-x25519"]
|
||||
bootstrap = ["mcuboot-sys/bootstrap"]
|
||||
multiimage = ["mcuboot-sys/multiimage"]
|
||||
ram-load = ["mcuboot-sys/ram-load"]
|
||||
direct-xip = ["mcuboot-sys/direct-xip"]
|
||||
downgrade-prevention = ["mcuboot-sys/downgrade-prevention"]
|
||||
max-align-32 = ["mcuboot-sys/max-align-32"]
|
||||
hw-rollback-protection = ["mcuboot-sys/hw-rollback-protection"]
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1.4"
|
||||
libc = "0.2"
|
||||
rand = { version = "0.8", features = ["small_rng"] }
|
||||
docopt = "1.1.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
log = "0.4"
|
||||
env_logger = "0.9"
|
||||
simflash = { path = "simflash" }
|
||||
mcuboot-sys = { path = "mcuboot-sys" }
|
||||
ring = "0.16.11"
|
||||
untrusted = "0.9"
|
||||
pem = "1.0"
|
||||
cipher = "0.3"
|
||||
aes = { version = "0.7.4", features = ["ctr"] }
|
||||
base64 = "0.13.0"
|
||||
typenum = "1.13.0"
|
||||
61
bootloader/mcuboot/sim/README.rst
Normal file
61
bootloader/mcuboot/sim/README.rst
Normal file
@@ -0,0 +1,61 @@
|
||||
MCUboot simulator
|
||||
#################
|
||||
|
||||
This is a small simulator designed to exercise the mcuboot upgrade
|
||||
code, specifically testing untimely reset scenarios to make sure the
|
||||
code is robust.
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
|
||||
The simulator is written in Rust_, and you will need to install it to
|
||||
build it. The installation_ page describes this process. The
|
||||
simulator can be built with the stable release of Rust.
|
||||
|
||||
.. _Rust: https://www.rust-lang.org/
|
||||
|
||||
.. _installation: https://www.rust-lang.org/en-US/install.html
|
||||
|
||||
Dependent code
|
||||
--------------
|
||||
|
||||
The simulator depends on some external modules. These are stored as
|
||||
submodules within git. To fetch these dependencies the first time::
|
||||
|
||||
$ git submodule update --init --recursive
|
||||
|
||||
will clone and check out these trees in the appropriate place.
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
The tests are written as unit tests in Rust, and can be built and run
|
||||
automatically::
|
||||
|
||||
$ cargo test
|
||||
|
||||
this should download and compile the necessary dependencies, compile
|
||||
the relevant modules from mcuboot, build the simulator, and run the
|
||||
tests.
|
||||
|
||||
There are several different features you can test. For example,
|
||||
testing RSA signatures can be done with::
|
||||
|
||||
$ cargo test --features sig-rsa
|
||||
|
||||
For a complete list of features, see Cargo.toml.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
If the simulator indicates a failure, you can turn on additional
|
||||
logging by setting ``RUST_LOG=warn`` or ``RUST_LOG=error`` in the
|
||||
environment::
|
||||
|
||||
$ RUST_LOG=warn ./target/release/bootsim run ...
|
||||
|
||||
It is also possible to run specific tests, for example::
|
||||
|
||||
$ cargo test -- basic_revert
|
||||
|
||||
which will run only the `basic_revert` test.
|
||||
1
bootloader/mcuboot/sim/mcuboot-sys/.gitignore
vendored
Normal file
1
bootloader/mcuboot/sim/mcuboot-sys/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Cargo.lock
|
||||
104
bootloader/mcuboot/sim/mcuboot-sys/Cargo.toml
Normal file
104
bootloader/mcuboot/sim/mcuboot-sys/Cargo.toml
Normal file
@@ -0,0 +1,104 @@
|
||||
[package]
|
||||
name = "mcuboot-sys"
|
||||
version = "0.1.0"
|
||||
authors = ["David Brown <david.brown@linaro.org>"]
|
||||
description = "A simple wrapper around the mcuboot code."
|
||||
build = "build.rs"
|
||||
publish = false
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
# By default, build with simplistic signature verification.
|
||||
default = []
|
||||
|
||||
# Verify RSA signatures. Note that at this time, the C code will not
|
||||
# compile with both sig-rsa and sig-ecdsa enabled.
|
||||
sig-rsa = []
|
||||
|
||||
# Verify RSA-3072 signatures.
|
||||
sig-rsa3072 = []
|
||||
|
||||
# Verify ECDSA (secp256r1) signatures.
|
||||
sig-ecdsa = []
|
||||
|
||||
# Verify ECDSA (secp256r1) signatures using mbed TLS
|
||||
sig-ecdsa-mbedtls = []
|
||||
|
||||
# Verify ECDSA (p256 or p384) signatures using PSA Crypto API
|
||||
sig-ecdsa-psa = []
|
||||
|
||||
# Enable P384 Curve support (instead of P256) for PSA Crypto
|
||||
sig-p384 = []
|
||||
|
||||
# Verify ED25519 signatures.
|
||||
sig-ed25519 = []
|
||||
|
||||
# Overwrite only upgrade
|
||||
overwrite-only = []
|
||||
|
||||
swap-move = []
|
||||
|
||||
# Disable validation of the primary slot
|
||||
validate-primary-slot = []
|
||||
|
||||
# Encrypt image in the secondary slot using RSA-OAEP-2048
|
||||
enc-rsa = []
|
||||
|
||||
# Encrypt image in the secondary slot using AES-256-CTR and RSA-OAEP-2048
|
||||
enc-aes256-rsa = []
|
||||
|
||||
# Encrypt image in the secondary slot using AES-KW-128
|
||||
enc-kw = []
|
||||
|
||||
# Encrypt image in the secondary slot using AES-256-CTR and AES-KW-256
|
||||
enc-aes256-kw = []
|
||||
|
||||
# Encrypt image in the secondary slot using ECIES-P256
|
||||
enc-ec256 = []
|
||||
|
||||
# Encrypt image in the secondary slot using AES-256-CTR and ECIES-P256
|
||||
enc-aes256-ec256 = []
|
||||
|
||||
# Encrypt image in the secondary slot using ECIES-P256 using Mbed TLS
|
||||
enc-ec256-mbedtls = []
|
||||
|
||||
# Encrypt image in the secondary slot using ECIES-X25519
|
||||
enc-x25519 = []
|
||||
|
||||
# Encrypt image in the secondary slot using AES-256-CTR and ECIES-X25519
|
||||
enc-aes256-x25519 = []
|
||||
|
||||
# Allow bootstrapping an empty/invalid primary slot from a valid secondary slot
|
||||
bootstrap = []
|
||||
|
||||
# Support multiple images (currently 2 instead of 1).
|
||||
multiimage = []
|
||||
|
||||
# Support simulation of ram-loading. No swaps are performed, and the
|
||||
# image is copied to RAM before loading it.
|
||||
ram-load = []
|
||||
|
||||
# Support simulation of direct XIP. No swaps are performed, the image
|
||||
# is directly executed out of whichever partition contains the most
|
||||
# appropriate image.
|
||||
direct-xip = []
|
||||
|
||||
# Check (in software) against version downgrades.
|
||||
downgrade-prevention = []
|
||||
|
||||
# Support images with 32-byte maximum write alignment value.
|
||||
max-align-32 = []
|
||||
|
||||
# Enable hardware rollback protection
|
||||
hw-rollback-protection = []
|
||||
|
||||
# Enable the PSA Crypto APIs where supported for cryptography related operations.
|
||||
psa-crypto-api = []
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0.25"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
log = "0.4"
|
||||
simflash = { path = "../simflash" }
|
||||
532
bootloader/mcuboot/sim/mcuboot-sys/build.rs
Normal file
532
bootloader/mcuboot/sim/mcuboot-sys/build.rs
Normal file
@@ -0,0 +1,532 @@
|
||||
// Build mcuboot as a library, based on the requested features.
|
||||
|
||||
extern crate cc;
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn main() {
|
||||
// Feature flags.
|
||||
let psa_crypto_api = env::var("CARGO_FEATURE_PSA_CRYPTO_API").is_ok();
|
||||
let sig_rsa = env::var("CARGO_FEATURE_SIG_RSA").is_ok();
|
||||
let sig_rsa3072 = env::var("CARGO_FEATURE_SIG_RSA3072").is_ok();
|
||||
let sig_ecdsa = env::var("CARGO_FEATURE_SIG_ECDSA").is_ok();
|
||||
let sig_ecdsa_mbedtls = env::var("CARGO_FEATURE_SIG_ECDSA_MBEDTLS").is_ok();
|
||||
let sig_ecdsa_psa = env::var("CARGO_FEATURE_SIG_ECDSA_PSA").is_ok();
|
||||
let sig_p384 = env::var("CARGO_FEATURE_SIG_P384").is_ok();
|
||||
let sig_ed25519 = env::var("CARGO_FEATURE_SIG_ED25519").is_ok();
|
||||
let overwrite_only = env::var("CARGO_FEATURE_OVERWRITE_ONLY").is_ok();
|
||||
let swap_move = env::var("CARGO_FEATURE_SWAP_MOVE").is_ok();
|
||||
let validate_primary_slot =
|
||||
env::var("CARGO_FEATURE_VALIDATE_PRIMARY_SLOT").is_ok();
|
||||
let enc_rsa = env::var("CARGO_FEATURE_ENC_RSA").is_ok();
|
||||
let enc_aes256_rsa = env::var("CARGO_FEATURE_ENC_AES256_RSA").is_ok();
|
||||
let enc_kw = env::var("CARGO_FEATURE_ENC_KW").is_ok();
|
||||
let enc_aes256_kw = env::var("CARGO_FEATURE_ENC_AES256_KW").is_ok();
|
||||
let enc_ec256 = env::var("CARGO_FEATURE_ENC_EC256").is_ok();
|
||||
let enc_ec256_mbedtls = env::var("CARGO_FEATURE_ENC_EC256_MBEDTLS").is_ok();
|
||||
let enc_aes256_ec256 = env::var("CARGO_FEATURE_ENC_AES256_EC256").is_ok();
|
||||
let enc_x25519 = env::var("CARGO_FEATURE_ENC_X25519").is_ok();
|
||||
let enc_aes256_x25519 = env::var("CARGO_FEATURE_ENC_AES256_X25519").is_ok();
|
||||
let bootstrap = env::var("CARGO_FEATURE_BOOTSTRAP").is_ok();
|
||||
let multiimage = env::var("CARGO_FEATURE_MULTIIMAGE").is_ok();
|
||||
let downgrade_prevention = env::var("CARGO_FEATURE_DOWNGRADE_PREVENTION").is_ok();
|
||||
let ram_load = env::var("CARGO_FEATURE_RAM_LOAD").is_ok();
|
||||
let direct_xip = env::var("CARGO_FEATURE_DIRECT_XIP").is_ok();
|
||||
let max_align_32 = env::var("CARGO_FEATURE_MAX_ALIGN_32").is_ok();
|
||||
let hw_rollback_protection = env::var("CARGO_FEATURE_HW_ROLLBACK_PROTECTION").is_ok();
|
||||
|
||||
let mut conf = CachedBuild::new();
|
||||
conf.conf.define("__BOOTSIM__", None);
|
||||
conf.conf.define("MCUBOOT_HAVE_LOGGING", None);
|
||||
conf.conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
|
||||
conf.conf.define("MCUBOOT_HAVE_ASSERT_H", None);
|
||||
conf.conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("128"));
|
||||
|
||||
if max_align_32 {
|
||||
conf.conf.define("MCUBOOT_BOOT_MAX_ALIGN", Some("32"));
|
||||
} else {
|
||||
conf.conf.define("MCUBOOT_BOOT_MAX_ALIGN", Some("8"));
|
||||
}
|
||||
|
||||
conf.conf.define("MCUBOOT_IMAGE_NUMBER", Some(if multiimage { "2" } else { "1" }));
|
||||
|
||||
if downgrade_prevention && !overwrite_only {
|
||||
panic!("Downgrade prevention requires overwrite only");
|
||||
}
|
||||
|
||||
if bootstrap {
|
||||
conf.conf.define("MCUBOOT_BOOTSTRAP", None);
|
||||
conf.conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
|
||||
}
|
||||
|
||||
if validate_primary_slot {
|
||||
conf.conf.define("MCUBOOT_VALIDATE_PRIMARY_SLOT", None);
|
||||
}
|
||||
|
||||
if downgrade_prevention {
|
||||
conf.conf.define("MCUBOOT_DOWNGRADE_PREVENTION", None);
|
||||
}
|
||||
|
||||
if ram_load {
|
||||
conf.conf.define("MCUBOOT_RAM_LOAD", None);
|
||||
}
|
||||
|
||||
if direct_xip {
|
||||
conf.conf.define("MCUBOOT_DIRECT_XIP", None);
|
||||
}
|
||||
|
||||
if hw_rollback_protection {
|
||||
conf.conf.define("MCUBOOT_HW_ROLLBACK_PROT", None);
|
||||
conf.file("csupport/security_cnt.c");
|
||||
}
|
||||
|
||||
// Currently no more than one sig type can be used simultaneously.
|
||||
if vec![sig_rsa, sig_rsa3072, sig_ecdsa, sig_ed25519].iter()
|
||||
.fold(0, |sum, &v| sum + v as i32) > 1 {
|
||||
panic!("mcuboot does not support more than one sig type at the same time");
|
||||
}
|
||||
|
||||
if psa_crypto_api {
|
||||
if sig_ecdsa || enc_ec256 || enc_x25519 ||
|
||||
enc_aes256_ec256 || sig_ecdsa_mbedtls || enc_aes256_x25519 ||
|
||||
enc_kw || enc_aes256_kw {
|
||||
conf.file("csupport/psa_crypto_init_stub.c");
|
||||
} else {
|
||||
conf.conf.define("MCUBOOT_USE_PSA_CRYPTO", None);
|
||||
conf.file("../../ext/mbedtls/library/aes.c");
|
||||
conf.file("../../ext/mbedtls/library/aesni.c");
|
||||
conf.file("../../ext/mbedtls/library/aria.c");
|
||||
conf.file("../../ext/mbedtls/library/asn1write.c");
|
||||
conf.file("../../ext/mbedtls/library/base64.c");
|
||||
conf.file("../../ext/mbedtls/library/camellia.c");
|
||||
conf.file("../../ext/mbedtls/library/ccm.c");
|
||||
conf.file("../../ext/mbedtls/library/chacha20.c");
|
||||
conf.file("../../ext/mbedtls/library/chachapoly.c");
|
||||
conf.file("../../ext/mbedtls/library/cipher.c");
|
||||
conf.file("../../ext/mbedtls/library/cipher_wrap.c");
|
||||
conf.file("../../ext/mbedtls/library/ctr_drbg.c");
|
||||
conf.file("../../ext/mbedtls/library/des.c");
|
||||
conf.file("../../ext/mbedtls/library/ecdsa.c");
|
||||
conf.file("../../ext/mbedtls/library/ecp.c");
|
||||
conf.file("../../ext/mbedtls/library/ecp_curves.c");
|
||||
conf.file("../../ext/mbedtls/library/entropy.c");
|
||||
conf.file("../../ext/mbedtls/library/entropy_poll.c");
|
||||
conf.file("../../ext/mbedtls/library/gcm.c");
|
||||
conf.file("../../ext/mbedtls/library/md5.c");
|
||||
conf.file("../../ext/mbedtls/library/nist_kw.c");
|
||||
conf.file("../../ext/mbedtls/library/oid.c");
|
||||
conf.file("../../ext/mbedtls/library/pem.c");
|
||||
conf.file("../../ext/mbedtls/library/pk.c");
|
||||
conf.file("../../ext/mbedtls/library/pkcs5.c");
|
||||
conf.file("../../ext/mbedtls/library/pkcs12.c");
|
||||
conf.file("../../ext/mbedtls/library/pkparse.c");
|
||||
conf.file("../../ext/mbedtls/library/pk_wrap.c");
|
||||
conf.file("../../ext/mbedtls/library/pkwrite.c");
|
||||
conf.file("../../ext/mbedtls/library/poly1305.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_crypto.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_crypto_cipher.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_crypto_client.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_crypto_driver_wrappers.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_crypto_ecp.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_crypto_hash.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_crypto_mac.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_crypto_rsa.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_crypto_slot_management.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_crypto_storage.c");
|
||||
conf.file("../../ext/mbedtls/library/psa_its_file.c");
|
||||
conf.file("../../ext/mbedtls/library/ripemd160.c");
|
||||
conf.file("../../ext/mbedtls/library/rsa_alt_helpers.c");
|
||||
conf.file("../../ext/mbedtls/library/sha1.c");
|
||||
conf.file("../../ext/mbedtls/library/sha512.c");
|
||||
conf.file("../../ext/mbedtls/tests/src/random.c");
|
||||
conf.conf.include("../../ext/mbedtls/library");
|
||||
}
|
||||
|
||||
conf.conf.include("../../ext/mbedtls/tests/include/");
|
||||
conf.file("../../ext/mbedtls/tests/src/fake_external_rng_for_test.c");
|
||||
}
|
||||
|
||||
if sig_rsa || sig_rsa3072 {
|
||||
conf.conf.define("MCUBOOT_SIGN_RSA", None);
|
||||
// The Kconfig style defines must be added here as well because
|
||||
// they are used internally by "config-rsa.h"
|
||||
if sig_rsa {
|
||||
conf.conf.define("MCUBOOT_SIGN_RSA_LEN", "2048");
|
||||
conf.conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "2048");
|
||||
} else {
|
||||
conf.conf.define("MCUBOOT_SIGN_RSA_LEN", "3072");
|
||||
conf.conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "3072");
|
||||
}
|
||||
conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
|
||||
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
conf.file("../../ext/mbedtls/library/sha256.c");
|
||||
conf.file("csupport/keys.c");
|
||||
|
||||
conf.file("../../ext/mbedtls/library/rsa.c");
|
||||
conf.file("../../ext/mbedtls/library/bignum.c");
|
||||
conf.file("../../ext/mbedtls/library/platform.c");
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
conf.file("../../ext/mbedtls/library/asn1parse.c");
|
||||
conf.file("../../ext/mbedtls/library/md.c");
|
||||
|
||||
} else if sig_ecdsa {
|
||||
conf.conf.define("MCUBOOT_SIGN_EC256", None);
|
||||
conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
|
||||
|
||||
if !enc_kw {
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
}
|
||||
conf.conf.include("../../ext/tinycrypt/lib/include");
|
||||
|
||||
conf.file("csupport/keys.c");
|
||||
|
||||
conf.file("../../ext/tinycrypt/lib/source/utils.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/sha256.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/ecc.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
conf.file("../../ext/mbedtls/library/asn1parse.c");
|
||||
} else if sig_ecdsa_mbedtls {
|
||||
conf.conf.define("MCUBOOT_SIGN_EC256", None);
|
||||
conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
|
||||
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
conf.file("../../ext/mbedtls/library/sha256.c");
|
||||
conf.file("csupport/keys.c");
|
||||
|
||||
conf.file("../../ext/mbedtls/library/asn1parse.c");
|
||||
conf.file("../../ext/mbedtls/library/bignum.c");
|
||||
conf.file("../../ext/mbedtls/library/ecdsa.c");
|
||||
conf.file("../../ext/mbedtls/library/ecp.c");
|
||||
conf.file("../../ext/mbedtls/library/ecp_curves.c");
|
||||
conf.file("../../ext/mbedtls/library/platform.c");
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
} else if sig_ecdsa_psa {
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
|
||||
if sig_p384 {
|
||||
conf.conf.define("MCUBOOT_SIGN_EC384", None);
|
||||
conf.file("../../ext/mbedtls/library/sha512.c");
|
||||
} else {
|
||||
conf.conf.define("MCUBOOT_SIGN_EC256", None);
|
||||
conf.file("../../ext/mbedtls/library/sha256.c");
|
||||
}
|
||||
|
||||
conf.file("csupport/keys.c");
|
||||
conf.file("../../ext/mbedtls/library/asn1parse.c");
|
||||
conf.file("../../ext/mbedtls/library/bignum.c");
|
||||
conf.file("../../ext/mbedtls/library/ecp.c");
|
||||
conf.file("../../ext/mbedtls/library/ecp_curves.c");
|
||||
conf.file("../../ext/mbedtls/library/platform.c");
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
} else if sig_ed25519 {
|
||||
conf.conf.define("MCUBOOT_SIGN_ED25519", None);
|
||||
conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
|
||||
|
||||
conf.conf.include("../../ext/tinycrypt/lib/include");
|
||||
conf.conf.include("../../ext/tinycrypt-sha512/lib/include");
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
conf.file("../../ext/tinycrypt/lib/source/sha256.c");
|
||||
conf.file("../../ext/tinycrypt-sha512/lib/source/sha512.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/utils.c");
|
||||
conf.file("csupport/keys.c");
|
||||
conf.file("../../ext/fiat/src/curve25519.c");
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
conf.file("../../ext/mbedtls/library/asn1parse.c");
|
||||
} else if !enc_ec256 && !enc_x25519 {
|
||||
// No signature type, only sha256 validation. The default
|
||||
// configuration file bundled with mbedTLS is sufficient.
|
||||
// When using ECIES-P256 rely on Tinycrypt.
|
||||
conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
conf.file("../../ext/mbedtls/library/sha256.c");
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
}
|
||||
|
||||
if overwrite_only {
|
||||
conf.conf.define("MCUBOOT_OVERWRITE_ONLY", None);
|
||||
}
|
||||
|
||||
if swap_move {
|
||||
conf.conf.define("MCUBOOT_SWAP_USING_MOVE", None);
|
||||
} else if !overwrite_only && !direct_xip && !ram_load {
|
||||
conf.conf.define("CONFIG_BOOT_SWAP_USING_SCRATCH", None);
|
||||
conf.conf.define("MCUBOOT_SWAP_USING_SCRATCH", None);
|
||||
}
|
||||
|
||||
if enc_rsa || enc_aes256_rsa {
|
||||
if enc_aes256_rsa {
|
||||
conf.conf.define("MCUBOOT_AES_256", None);
|
||||
}
|
||||
conf.conf.define("MCUBOOT_ENCRYPT_RSA", None);
|
||||
conf.conf.define("MCUBOOT_ENC_IMAGES", None);
|
||||
conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
|
||||
|
||||
conf.file("../../boot/bootutil/src/encrypted.c");
|
||||
conf.file("csupport/keys.c");
|
||||
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
conf.conf.include("../../ext/mbedtls/library");
|
||||
conf.file("../../ext/mbedtls/library/sha256.c");
|
||||
|
||||
conf.file("../../ext/mbedtls/library/platform.c");
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
conf.file("../../ext/mbedtls/library/rsa.c");
|
||||
conf.file("../../ext/mbedtls/library/rsa_alt_helpers.c");
|
||||
conf.file("../../ext/mbedtls/library/md.c");
|
||||
conf.file("../../ext/mbedtls/library/aes.c");
|
||||
conf.file("../../ext/mbedtls/library/bignum.c");
|
||||
conf.file("../../ext/mbedtls/library/asn1parse.c");
|
||||
}
|
||||
|
||||
if enc_kw || enc_aes256_kw {
|
||||
if enc_aes256_kw {
|
||||
conf.conf.define("MCUBOOT_AES_256", None);
|
||||
}
|
||||
conf.conf.define("MCUBOOT_ENCRYPT_KW", None);
|
||||
conf.conf.define("MCUBOOT_ENC_IMAGES", None);
|
||||
|
||||
conf.file("../../boot/bootutil/src/encrypted.c");
|
||||
conf.file("csupport/keys.c");
|
||||
|
||||
if sig_rsa || sig_rsa3072 {
|
||||
conf.file("../../ext/mbedtls/library/sha256.c");
|
||||
}
|
||||
|
||||
/* Simulator uses Mbed-TLS to wrap keys */
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
conf.file("../../ext/mbedtls/library/platform.c");
|
||||
conf.conf.include("../../ext/mbedtls/library");
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
conf.file("../../ext/mbedtls/library/nist_kw.c");
|
||||
conf.file("../../ext/mbedtls/library/cipher.c");
|
||||
conf.file("../../ext/mbedtls/library/cipher_wrap.c");
|
||||
conf.file("../../ext/mbedtls/library/aes.c");
|
||||
|
||||
if sig_ecdsa {
|
||||
conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
|
||||
|
||||
conf.conf.include("../../ext/tinycrypt/lib/include");
|
||||
|
||||
conf.file("../../ext/tinycrypt/lib/source/utils.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/sha256.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
|
||||
}
|
||||
|
||||
if sig_ed25519 {
|
||||
panic!("ed25519 does not support image encryption with KW yet");
|
||||
}
|
||||
}
|
||||
|
||||
if enc_ec256 {
|
||||
conf.conf.define("MCUBOOT_ENCRYPT_EC256", None);
|
||||
conf.conf.define("MCUBOOT_ENC_IMAGES", None);
|
||||
conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
|
||||
conf.conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
|
||||
|
||||
conf.file("../../boot/bootutil/src/encrypted.c");
|
||||
conf.file("csupport/keys.c");
|
||||
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
conf.conf.include("../../ext/tinycrypt/lib/include");
|
||||
|
||||
/* FIXME: fail with other signature schemes ? */
|
||||
|
||||
conf.file("../../ext/tinycrypt/lib/source/utils.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/sha256.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/ecc.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");
|
||||
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
conf.file("../../ext/mbedtls/library/asn1parse.c");
|
||||
|
||||
conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/hmac.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/ecc_dh.c");
|
||||
} else if enc_ec256_mbedtls || enc_aes256_ec256 {
|
||||
if enc_aes256_ec256 {
|
||||
conf.conf.define("MCUBOOT_AES_256", None);
|
||||
}
|
||||
conf.conf.define("MCUBOOT_ENCRYPT_EC256", None);
|
||||
conf.conf.define("MCUBOOT_ENC_IMAGES", None);
|
||||
conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
|
||||
conf.conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
|
||||
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
|
||||
conf.file("../../boot/bootutil/src/encrypted.c");
|
||||
conf.file("../../ext/mbedtls/library/sha256.c");
|
||||
conf.file("../../ext/mbedtls/library/asn1parse.c");
|
||||
conf.file("../../ext/mbedtls/library/bignum.c");
|
||||
conf.file("../../ext/mbedtls/library/ecdh.c");
|
||||
conf.file("../../ext/mbedtls/library/md.c");
|
||||
conf.file("../../ext/mbedtls/library/aes.c");
|
||||
conf.file("../../ext/mbedtls/library/ecp.c");
|
||||
conf.file("../../ext/mbedtls/library/ecp_curves.c");
|
||||
conf.file("../../ext/mbedtls/library/platform.c");
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
conf.file("csupport/keys.c");
|
||||
}
|
||||
|
||||
if enc_x25519 {
|
||||
conf.conf.define("MCUBOOT_ENCRYPT_X25519", None);
|
||||
conf.conf.define("MCUBOOT_ENC_IMAGES", None);
|
||||
conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
|
||||
conf.conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
|
||||
|
||||
conf.file("../../boot/bootutil/src/encrypted.c");
|
||||
conf.file("csupport/keys.c");
|
||||
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
conf.conf.include("../../ext/tinycrypt/lib/include");
|
||||
conf.conf.include("../../ext/tinycrypt-sha512/lib/include");
|
||||
|
||||
conf.file("../../ext/fiat/src/curve25519.c");
|
||||
|
||||
conf.file("../../ext/tinycrypt/lib/source/utils.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/sha256.c");
|
||||
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
conf.file("../../ext/mbedtls/library/asn1parse.c");
|
||||
|
||||
conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
|
||||
conf.file("../../ext/tinycrypt/lib/source/hmac.c");
|
||||
}
|
||||
|
||||
else if enc_aes256_x25519 {
|
||||
conf.conf.define("MCUBOOT_AES_256", None);
|
||||
conf.conf.define("MCUBOOT_ENCRYPT_X25519", None);
|
||||
conf.conf.define("MCUBOOT_ENC_IMAGES", None);
|
||||
conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
|
||||
conf.conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
|
||||
|
||||
conf.file("../../boot/bootutil/src/encrypted.c");
|
||||
conf.file("csupport/keys.c");
|
||||
|
||||
conf.conf.include("../../ext/mbedtls/include");
|
||||
conf.file("../../ext/fiat/src/curve25519.c");
|
||||
conf.file("../../ext/mbedtls/library/asn1parse.c");
|
||||
conf.file("../../ext/mbedtls/library/platform.c");
|
||||
conf.file("../../ext/mbedtls/library/platform_util.c");
|
||||
conf.file("../../ext/mbedtls/library/aes.c");
|
||||
conf.file("../../ext/mbedtls/library/sha256.c");
|
||||
conf.file("../../ext/mbedtls/library/md.c");
|
||||
conf.file("../../ext/mbedtls/library/sha512.c");
|
||||
}
|
||||
|
||||
if sig_rsa && enc_kw {
|
||||
conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa-kw.h>"));
|
||||
} else if sig_rsa || sig_rsa3072 || enc_rsa || enc_aes256_rsa {
|
||||
conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa.h>"));
|
||||
} else if sig_ecdsa_mbedtls || enc_ec256_mbedtls || enc_aes256_ec256 {
|
||||
conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-ec.h>"));
|
||||
} else if (sig_ecdsa || enc_ec256) && !enc_kw {
|
||||
conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
|
||||
} else if sig_ed25519 || enc_x25519 {
|
||||
conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
|
||||
} else if enc_kw || enc_aes256_kw {
|
||||
conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-kw.h>"));
|
||||
} else if enc_aes256_x25519 {
|
||||
conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-ed25519.h>"));
|
||||
} else if sig_ecdsa_psa {
|
||||
conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-ec-psa.h>"));
|
||||
}
|
||||
|
||||
conf.file("../../boot/bootutil/src/image_validate.c");
|
||||
if sig_rsa || sig_rsa3072 {
|
||||
conf.file("../../boot/bootutil/src/image_rsa.c");
|
||||
} else if sig_ecdsa || sig_ecdsa_mbedtls || sig_ecdsa_psa {
|
||||
conf.file("../../boot/bootutil/src/image_ecdsa.c");
|
||||
} else if sig_ed25519 {
|
||||
conf.file("../../boot/bootutil/src/image_ed25519.c");
|
||||
}
|
||||
|
||||
conf.file("../../boot/bootutil/src/loader.c");
|
||||
conf.file("../../boot/bootutil/src/swap_misc.c");
|
||||
conf.file("../../boot/bootutil/src/swap_scratch.c");
|
||||
conf.file("../../boot/bootutil/src/swap_move.c");
|
||||
conf.file("../../boot/bootutil/src/caps.c");
|
||||
conf.file("../../boot/bootutil/src/bootutil_misc.c");
|
||||
conf.file("../../boot/bootutil/src/bootutil_public.c");
|
||||
conf.file("../../boot/bootutil/src/tlv.c");
|
||||
conf.file("../../boot/bootutil/src/fault_injection_hardening.c");
|
||||
conf.file("csupport/run.c");
|
||||
conf.conf.include("../../boot/bootutil/include");
|
||||
conf.conf.include("csupport");
|
||||
conf.conf.debug(true);
|
||||
conf.conf.flag("-Wall");
|
||||
conf.conf.flag("-Werror");
|
||||
|
||||
// FIXME: travis-ci still uses gcc 4.8.4 which defaults to std=gnu90.
|
||||
// It has incomplete std=c11 and std=c99 support but std=c99 was checked
|
||||
// to build correctly so leaving it here to updated in the future...
|
||||
conf.conf.flag("-std=c99");
|
||||
|
||||
conf.conf.compile("libbootutil.a");
|
||||
|
||||
walk_dir("../../boot").unwrap();
|
||||
walk_dir("../../ext/tinycrypt/lib/source").unwrap();
|
||||
walk_dir("../../ext/mbedtls-asn1").unwrap();
|
||||
walk_dir("csupport").unwrap();
|
||||
walk_dir("../../ext/mbedtls/include").unwrap();
|
||||
walk_dir("../../ext/mbedtls/library").unwrap();
|
||||
}
|
||||
|
||||
// Output the names of all files within a directory so that Cargo knows when to rebuild.
|
||||
fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||
for ent in fs::read_dir(path.as_ref())? {
|
||||
let ent = ent?;
|
||||
let p = ent.path();
|
||||
if p.is_dir() {
|
||||
walk_dir(p)?;
|
||||
} else {
|
||||
// Note that non-utf8 names will fail.
|
||||
let name = p.to_str().unwrap();
|
||||
if name.ends_with(".c") || name.ends_with(".h") {
|
||||
println!("cargo:rerun-if-changed={}", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Wrap the cc::Build type so that we can make sure that files are only added a single time.
|
||||
/// Other methods can be passed through as needed.
|
||||
struct CachedBuild {
|
||||
conf: cc::Build,
|
||||
seen: BTreeSet<PathBuf>,
|
||||
}
|
||||
|
||||
impl CachedBuild {
|
||||
fn new() -> CachedBuild {
|
||||
CachedBuild {
|
||||
conf: cc::Build::new(),
|
||||
seen: BTreeSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Works like `file` in the Build, but doesn't add a file if the same path has already been
|
||||
/// given.
|
||||
fn file<P: AsRef<Path>>(&mut self, p: P) -> &mut CachedBuild {
|
||||
let p = p.as_ref();
|
||||
if !self.seen.contains(p) {
|
||||
self.conf.file(p);
|
||||
self.seen.insert(p.to_owned());
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
26
bootloader/mcuboot/sim/mcuboot-sys/csupport/bootsim.h
Normal file
26
bootloader/mcuboot/sim/mcuboot-sys/csupport/bootsim.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BOOTSIM_
|
||||
#define H_BOOTSIM_
|
||||
|
||||
#include "mcuboot_config/mcuboot_assert.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2023 Arm Limited
|
||||
*/
|
||||
|
||||
#ifndef MCUBOOT_MBEDTLS_CONFIG_ADD_PSA_CRYPTO_H
|
||||
#define MCUBOOT_MBEDTLS_CONFIG_ADD_PSA_CRYPTO_H
|
||||
|
||||
#include "mbedtls/build_info.h"
|
||||
|
||||
/* Enable PSA Crypto Core without support for the permanent storage
|
||||
* Don't define MBEDTLS_PSA_CRYPTO_STORAGE_C to make sure that support
|
||||
* for permanent keys is not enabled, as it is not usually required during boot
|
||||
*/
|
||||
#define MBEDTLS_PSA_CRYPTO_C
|
||||
#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
|
||||
|
||||
#if defined(MCUBOOT_ENCRYPT_RSA) || defined(MCUBOOT_SIGN_RSA)
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_PK_WRITE_C
|
||||
#endif /* MCUBOOT_ENCRYPT_RSA || MCUBOOT_SIGN_RSA */
|
||||
|
||||
#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
|
||||
#define MBEDTLS_PLATFORM_FREE_MACRO free
|
||||
#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc
|
||||
#endif /* MCUBOOT_ENCRYPT_EC256 || MCUBOOT_ENCRYPT_X25519 */
|
||||
|
||||
#if !defined(MCUBOOT_ENCRYPT_X25519)
|
||||
#define MBEDTLS_PSA_BUILTIN_CIPHER 1
|
||||
#endif /* MCUBOOT_ENCRYPT_X25519 */
|
||||
|
||||
#if defined(MCUBOOT_ENCRYPT_KW)
|
||||
#define MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
#define MBEDTLS_POLY1305_C
|
||||
#endif /* MCUBOOT_ENCRYPT_KW */
|
||||
|
||||
#if MBEDTLS_VERSION_NUMBER == 0x03000000
|
||||
/* This PSA define is available only with more recent versions of 3.x */
|
||||
#define PSA_KEY_ID_NULL ((psa_key_id_t)0) // not overly happy with this being here
|
||||
#endif /* MBEDTLS_VERSION_NUMBER == 0x03000000 */
|
||||
|
||||
#endif /* MCUBOOT_MBEDTLS_CONFIG_ADD_PSA_CRYPTO_H */
|
||||
44
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-asn1.h
Normal file
44
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-asn1.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Configuration of mbedTLS containing only the ASN.1 parser.
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* Copyright (C) 2016, Linaro Ltd
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Minimal configuration for using TLS in the bootloader
|
||||
*
|
||||
* - RSA or ECDSA signature verification
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_CONFIG_ASN1_H
|
||||
#define MBEDTLS_CONFIG_ASN1_H
|
||||
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
// #define MBEDTLS_ASN1_WRITE_C
|
||||
// #define MBEDTLS_BIGNUM_C
|
||||
// #define MBEDTLS_MD_C
|
||||
// #define MBEDTLS_OID_C
|
||||
// #define MBEDTLS_SHA256_C
|
||||
|
||||
#endif /* MBEDTLS_CONFIG_ASN1_H */
|
||||
35
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-ec-psa.h
Normal file
35
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-ec-psa.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2023 Arm Limited
|
||||
*/
|
||||
|
||||
#ifndef MCUBOOT_PSA_CRYPTO_CONFIG_ECDSA
|
||||
#define MCUBOOT_PSA_CRYPTO_CONFIG_ECDSA
|
||||
|
||||
#if defined(MCUBOOT_USE_PSA_CRYPTO)
|
||||
#include "config-add-psa-crypto.h"
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECP_NIST_OPTIM
|
||||
#define MBEDTLS_ECDSA_C
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_OID_C
|
||||
#if defined(MCUBOOT_SIGN_EC384)
|
||||
#define MBEDTLS_SHA384_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#else
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#endif /* MCUBOOT_SIGN_EC384 */
|
||||
|
||||
#endif /* MCUBOOT_PSA_CRYPTO_CONFIG_ECDSA */
|
||||
95
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-ec.h
Normal file
95
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-ec.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Minimal configuration for using TLS in the bootloader
|
||||
*
|
||||
* Copyright (C) 2006-2021, ARM Limited, All Rights Reserved
|
||||
* Copyright (C) 2016, Linaro Ltd
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Minimal configuration for using TLS in the bootloader
|
||||
*
|
||||
* - RSA or ECDSA signature verification
|
||||
*/
|
||||
|
||||
#ifndef MCUBOOT_MBEDTLS_CONFIG_ECDSA
|
||||
#define MCUBOOT_MBEDTLS_CONFIG_ECDSA
|
||||
|
||||
#ifdef CONFIG_MCUBOOT_SERIAL
|
||||
/* Mcuboot uses mbedts-base64 for serial protocol encoding. */
|
||||
#define MBEDTLS_BASE64_C
|
||||
#endif
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
|
||||
|
||||
/* STD functions */
|
||||
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
|
||||
|
||||
#define MBEDTLS_PLATFORM_EXIT_ALT
|
||||
#define MBEDTLS_PLATFORM_PRINTF_ALT
|
||||
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
|
||||
|
||||
#if !defined(CONFIG_ARM)
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_ECDSA_C
|
||||
#define MBEDTLS_ECDH_C
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_NIST_OPTIM
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_AES_C
|
||||
|
||||
/* Bring in support for x509. */
|
||||
#define MBEDTLS_X509_USE_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
|
||||
/* Save RAM by adjusting to our exact needs */
|
||||
#define MBEDTLS_ECP_MAX_BITS 256
|
||||
|
||||
#define MBEDTLS_MPI_MAX_SIZE 32
|
||||
|
||||
#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024
|
||||
|
||||
/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
|
||||
#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
|
||||
|
||||
/* If encryption is being used, also enable the features needed for
|
||||
* that. */
|
||||
#if defined(MCUBOOT_ENC_IMAGES)
|
||||
#define MBEDTLS_CIPHER_MODE_CTR
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_NIST_KW_C
|
||||
#endif /* MCUBOOT_ENC_IMAGES */
|
||||
|
||||
#endif /* MCUBOOT_MBEDTLS_CONFIG_ECDSA */
|
||||
77
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-ed25519.h
Normal file
77
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-ed25519.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Configuration of mbedTLS containing only the ASN.1 parser.
|
||||
*
|
||||
* Copyright (C) 2006-2021, ARM Limited, All Rights Reserved
|
||||
* Copyright (C) 2016, Linaro Ltd
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Minimal configuration for using TLS in the bootloader
|
||||
*
|
||||
* - ed25519 signature verification
|
||||
*/
|
||||
|
||||
#ifndef MCUBOOT_MBEDTLS_CONFIG_ED25519
|
||||
#define MCUBOOT_MBEDTLS_CONFIG_ED25519
|
||||
|
||||
#ifdef CONFIG_MCUBOOT_SERIAL
|
||||
/* Mcuboot uses mbedts-base64 for serial protocol encoding. */
|
||||
#define MBEDTLS_BASE64_C
|
||||
#endif
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
|
||||
|
||||
/* STD functions */
|
||||
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
|
||||
|
||||
#define MBEDTLS_PLATFORM_EXIT_ALT
|
||||
#define MBEDTLS_PLATFORM_PRINTF_ALT
|
||||
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
|
||||
|
||||
#if !defined(CONFIG_ARM)
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_CIPHER_MODE_CTR
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_AES_C
|
||||
|
||||
/* Save RAM by adjusting to our exact needs */
|
||||
//#define MBEDTLS_ECP_MAX_BITS 2048
|
||||
|
||||
#define MBEDTLS_MPI_MAX_SIZE 64
|
||||
|
||||
//#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024
|
||||
|
||||
/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
|
||||
#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
|
||||
|
||||
#endif /* MCUBOOT_MBEDTLS_CONFIG_RSA */
|
||||
65
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-kw.h
Normal file
65
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-kw.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Minimal configuration for using TLS in the bootloader
|
||||
*
|
||||
* Copyright (C) 2006-2021, ARM Limited, All Rights Reserved
|
||||
* Copyright (C) 2016, Linaro Ltd
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Minimal configuration for using TLS in the bootloader
|
||||
*
|
||||
* - RSA or ECDSA signature verification
|
||||
*/
|
||||
|
||||
#ifndef MCUBOOT_MBEDTLS_CONFIG_KW
|
||||
#define MCUBOOT_MBEDTLS_CONFIG_KW
|
||||
|
||||
#ifdef CONFIG_MCUBOOT_SERIAL
|
||||
/* Mcuboot uses mbedts-base64 for serial protocol encoding. */
|
||||
#define MBEDTLS_BASE64_C
|
||||
#endif
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
|
||||
|
||||
/* STD functions */
|
||||
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
|
||||
|
||||
#define MBEDTLS_PLATFORM_EXIT_ALT
|
||||
#define MBEDTLS_PLATFORM_PRINTF_ALT
|
||||
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
|
||||
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
|
||||
#if !defined(CONFIG_ARM)
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_CIPHER_MODE_CTR
|
||||
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_NIST_KW_C
|
||||
|
||||
#endif /* MCUBOOT_MBEDTLS_CONFIG_KW */
|
||||
84
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-rsa-kw.h
Normal file
84
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-rsa-kw.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Minimal configuration for using TLS in the bootloader
|
||||
*
|
||||
* Copyright (C) 2006-2023, ARM Limited, All Rights Reserved
|
||||
* Copyright (C) 2016, Linaro Ltd
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Minimal configuration for using TLS in the bootloader
|
||||
*
|
||||
* - RSA signature verification + NIST Keywrapping support
|
||||
*/
|
||||
|
||||
#ifndef MCUBOOT_MBEDTLS_CONFIG_RSA_KW
|
||||
#define MCUBOOT_MBEDTLS_CONFIG_RSA_KW
|
||||
|
||||
#if defined(MCUBOOT_USE_PSA_CRYPTO)
|
||||
#include "config-add-psa-crypto.h"
|
||||
#endif /* defined(MCUBOOT_USE_PSA_CRYPTO) */
|
||||
|
||||
#ifdef CONFIG_MCUBOOT_SERIAL
|
||||
/* Mcuboot uses mbedts-base64 for serial protocol encoding. */
|
||||
#define MBEDTLS_BASE64_C
|
||||
#endif
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
|
||||
|
||||
/* STD functions */
|
||||
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
|
||||
|
||||
#define MBEDTLS_PLATFORM_EXIT_ALT
|
||||
#define MBEDTLS_PLATFORM_PRINTF_ALT
|
||||
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
|
||||
|
||||
#if !defined(CONFIG_ARM)
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_PKCS1_V21
|
||||
|
||||
#define MBEDTLS_CIPHER_MODE_CTR
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_NIST_KW_C
|
||||
|
||||
/* Save RAM by adjusting to our exact needs */
|
||||
#define MBEDTLS_ECP_MAX_BITS 2048
|
||||
#define MBEDTLS_MPI_MAX_SIZE 256
|
||||
|
||||
#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024
|
||||
|
||||
/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
|
||||
#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
|
||||
|
||||
#endif /* MCUBOOT_MBEDTLS_CONFIG_RSA_KW */
|
||||
85
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-rsa.h
Normal file
85
bootloader/mcuboot/sim/mcuboot-sys/csupport/config-rsa.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Minimal configuration for using TLS in the bootloader
|
||||
*
|
||||
* Copyright (C) 2006-2023, ARM Limited, All Rights Reserved
|
||||
* Copyright (C) 2016, Linaro Ltd
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Minimal configuration for using TLS in the bootloader
|
||||
*
|
||||
* - RSA or ECDSA signature verification
|
||||
*/
|
||||
|
||||
#ifndef MCUBOOT_MBEDTLS_CONFIG_RSA
|
||||
#define MCUBOOT_MBEDTLS_CONFIG_RSA
|
||||
|
||||
#if defined(MCUBOOT_USE_PSA_CRYPTO)
|
||||
#include "config-add-psa-crypto.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MCUBOOT_SERIAL
|
||||
/* Mcuboot uses mbedts-base64 for serial protocol encoding. */
|
||||
#define MBEDTLS_BASE64_C
|
||||
#endif
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
|
||||
|
||||
/* STD functions */
|
||||
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
|
||||
|
||||
#define MBEDTLS_PLATFORM_EXIT_ALT
|
||||
#define MBEDTLS_PLATFORM_PRINTF_ALT
|
||||
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
|
||||
|
||||
#if !defined(CONFIG_ARM)
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_PKCS1_V21
|
||||
|
||||
#define MBEDTLS_CIPHER_MODE_CTR
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_AES_C
|
||||
|
||||
#if (CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN == 3072)
|
||||
#define MBEDTLS_MPI_MAX_SIZE 384
|
||||
#else
|
||||
#define MBEDTLS_MPI_MAX_SIZE 256
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024
|
||||
|
||||
/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
|
||||
#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
|
||||
|
||||
#endif /* MCUBOOT_MBEDTLS_CONFIG_RSA */
|
||||
20
bootloader/mcuboot/sim/mcuboot-sys/csupport/devicetree.h
Normal file
20
bootloader/mcuboot/sim/mcuboot-sys/csupport/devicetree.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* This file mocks zephyr's flash map / DT macro */
|
||||
|
||||
#ifndef __DEVICETREE_H__
|
||||
#define __DEVICETREE_H__
|
||||
|
||||
#define FLASH_AREA_ID(x) FLASH_AREA_ID_##x
|
||||
|
||||
#define FLASH_AREA_ID_image_0 1
|
||||
#define FLASH_AREA_ID_image_1 2
|
||||
#define FLASH_AREA_ID_image_scratch 3
|
||||
#define FLASH_AREA_ID_image_2 4
|
||||
#define FLASH_AREA_ID_image_3 5
|
||||
|
||||
#endif /*__DEVICETREE_H__*/
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef __FLASH_MAP_BACKEND_H__
|
||||
#define __FLASH_MAP_BACKEND_H__
|
||||
|
||||
#include <storage/flash_map.h>
|
||||
|
||||
static inline uint32_t flash_area_get_off(const struct flash_area *fa)
|
||||
{
|
||||
return (uint32_t)fa->fa_off;
|
||||
}
|
||||
|
||||
static inline uint32_t flash_area_get_size(const struct flash_area *fa)
|
||||
{
|
||||
return (uint32_t)fa->fa_size;
|
||||
}
|
||||
|
||||
static inline uint32_t flash_sector_get_off(const struct flash_sector *fs)
|
||||
{
|
||||
return fs->fs_off;
|
||||
}
|
||||
|
||||
static inline uint32_t flash_sector_get_size(const struct flash_sector *fs)
|
||||
{
|
||||
return fs->fs_size;
|
||||
}
|
||||
|
||||
#define FLASH_DEVICE_ID 0
|
||||
|
||||
static inline uint8_t flash_area_get_device_id(const struct flash_area *fa)
|
||||
{
|
||||
return fa->fa_device_id;
|
||||
}
|
||||
|
||||
static inline uint8_t flash_area_get_id(const struct flash_area *fa)
|
||||
{
|
||||
return fa->fa_id;
|
||||
}
|
||||
|
||||
#endif /* __FLASH_MAP_BACKEND_H__*/
|
||||
330
bootloader/mcuboot/sim/mcuboot-sys/csupport/keys.c
Normal file
330
bootloader/mcuboot/sim/mcuboot-sys/csupport/keys.c
Normal file
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <bootutil/sign_key.h>
|
||||
|
||||
#include <mcuboot_config/mcuboot_config.h>
|
||||
|
||||
#if defined(MCUBOOT_SIGN_RSA)
|
||||
#if MCUBOOT_SIGN_RSA_LEN == 2048
|
||||
#define HAVE_KEYS
|
||||
const unsigned char root_pub_der[] = {
|
||||
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd1, 0x06, 0x08,
|
||||
0x1a, 0x18, 0x44, 0x2c, 0x18, 0xe8, 0xfb, 0xfd, 0xf7, 0x0d, 0xa3, 0x4f,
|
||||
0x1f, 0xbb, 0xee, 0x5e, 0xf9, 0xaa, 0xd2, 0x4b, 0x18, 0xd3, 0x5a, 0xe9,
|
||||
0x6d, 0x18, 0x80, 0x19, 0xf9, 0xf0, 0x9c, 0x34, 0x1b, 0xcb, 0xf3, 0xbc,
|
||||
0x74, 0xdb, 0x42, 0xe7, 0x8c, 0x7f, 0x10, 0x53, 0x7e, 0x43, 0x5e, 0x0d,
|
||||
0x57, 0x2c, 0x44, 0xd1, 0x67, 0x08, 0x0f, 0x0d, 0xbb, 0x5c, 0xee, 0xec,
|
||||
0xb3, 0x99, 0xdf, 0xe0, 0x4d, 0x84, 0x0b, 0xaa, 0x77, 0x41, 0x60, 0xed,
|
||||
0x15, 0x28, 0x49, 0xa7, 0x01, 0xb4, 0x3c, 0x10, 0xe6, 0x69, 0x8c, 0x2f,
|
||||
0x5f, 0xac, 0x41, 0x4d, 0x9e, 0x5c, 0x14, 0xdf, 0xf2, 0xf8, 0xcf, 0x3d,
|
||||
0x1e, 0x6f, 0xe7, 0x5b, 0xba, 0xb4, 0xa9, 0xc8, 0x88, 0x7e, 0x47, 0x3c,
|
||||
0x94, 0xc3, 0x77, 0x67, 0x54, 0x4b, 0xaa, 0x8d, 0x38, 0x35, 0xca, 0x62,
|
||||
0x61, 0x7e, 0xb7, 0xe1, 0x15, 0xdb, 0x77, 0x73, 0xd4, 0xbe, 0x7b, 0x72,
|
||||
0x21, 0x89, 0x69, 0x24, 0xfb, 0xf8, 0x65, 0x6e, 0x64, 0x3e, 0xc8, 0x0e,
|
||||
0xd7, 0x85, 0xd5, 0x5c, 0x4a, 0xe4, 0x53, 0x0d, 0x2f, 0xff, 0xb7, 0xfd,
|
||||
0xf3, 0x13, 0x39, 0x83, 0x3f, 0xa3, 0xae, 0xd2, 0x0f, 0xa7, 0x6a, 0x9d,
|
||||
0xf9, 0xfe, 0xb8, 0xce, 0xfa, 0x2a, 0xbe, 0xaf, 0xb8, 0xe0, 0xfa, 0x82,
|
||||
0x37, 0x54, 0xf4, 0x3e, 0xe1, 0x2b, 0xd0, 0xd3, 0x08, 0x58, 0x18, 0xf6,
|
||||
0x5e, 0x4c, 0xc8, 0x88, 0x81, 0x31, 0xad, 0x5f, 0xb0, 0x82, 0x17, 0xf2,
|
||||
0x8a, 0x69, 0x27, 0x23, 0xf3, 0xab, 0x87, 0x3e, 0x93, 0x1a, 0x1d, 0xfe,
|
||||
0xe8, 0xf8, 0x1a, 0x24, 0x66, 0x59, 0xf8, 0x1c, 0xab, 0xdc, 0xce, 0x68,
|
||||
0x1b, 0x66, 0x64, 0x35, 0xec, 0xfa, 0x0d, 0x11, 0x9d, 0xaf, 0x5c, 0x3a,
|
||||
0xa7, 0xd1, 0x67, 0xc6, 0x47, 0xef, 0xb1, 0x4b, 0x2c, 0x62, 0xe1, 0xd1,
|
||||
0xc9, 0x02, 0x03, 0x01, 0x00, 0x01
|
||||
};
|
||||
const unsigned int root_pub_der_len = 270;
|
||||
#elif MCUBOOT_SIGN_RSA_LEN == 3072
|
||||
#define HAVE_KEYS
|
||||
const unsigned char root_pub_der[] = {
|
||||
0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, 0x81,
|
||||
0x00, 0xb4, 0x2c, 0x0e, 0x98, 0x58, 0x10, 0xa4,
|
||||
0xa7, 0x58, 0x99, 0x7c, 0x01, 0xdd, 0x08, 0x2a,
|
||||
0x28, 0x34, 0x33, 0xf8, 0x96, 0x1a, 0x34, 0x20,
|
||||
0x5d, 0x45, 0xc8, 0x71, 0x26, 0x25, 0xe5, 0xd2,
|
||||
0x96, 0xea, 0x7b, 0xb1, 0x15, 0xaa, 0xa6, 0x8a,
|
||||
0x63, 0x22, 0x8b, 0x2d, 0x4e, 0x81, 0x73, 0xbf,
|
||||
0x6e, 0x15, 0x68, 0x8c, 0x1a, 0xf4, 0xef, 0x2a,
|
||||
0x8f, 0x8c, 0x22, 0x9e, 0x71, 0x57, 0x4b, 0xde,
|
||||
0x0f, 0x7e, 0x72, 0xd3, 0x7a, 0xb8, 0xa7, 0x1d,
|
||||
0x44, 0xad, 0x87, 0x00, 0x83, 0x5c, 0xfd, 0x73,
|
||||
0x05, 0x72, 0x46, 0x3f, 0x8b, 0xf9, 0x10, 0x00,
|
||||
0xd8, 0x6e, 0xcc, 0x85, 0xed, 0xf9, 0x49, 0xdb,
|
||||
0x78, 0x36, 0x80, 0x49, 0x38, 0x76, 0xdd, 0x5f,
|
||||
0x54, 0x04, 0xda, 0x8c, 0x34, 0xa7, 0x2b, 0x13,
|
||||
0x25, 0x6f, 0xd1, 0x15, 0x4f, 0xad, 0xc2, 0xe1,
|
||||
0xa5, 0xd2, 0x4e, 0x57, 0x0c, 0x7e, 0x9c, 0x9b,
|
||||
0xba, 0x4e, 0x68, 0xb2, 0xe0, 0x25, 0x02, 0xaa,
|
||||
0x00, 0xd3, 0xb4, 0xcc, 0x2f, 0x78, 0xe5, 0xbe,
|
||||
0x47, 0x67, 0x1f, 0xc8, 0x6e, 0x22, 0x6c, 0x5e,
|
||||
0x61, 0xb6, 0x9a, 0xcd, 0xe5, 0xa8, 0xba, 0x7a,
|
||||
0x80, 0x13, 0x1b, 0x17, 0x2e, 0x96, 0xed, 0xcf,
|
||||
0xb3, 0x9b, 0xe4, 0x1c, 0xe8, 0xad, 0xa7, 0xf6,
|
||||
0x3a, 0x51, 0x66, 0x5e, 0x99, 0x8e, 0x87, 0xee,
|
||||
0x60, 0x25, 0xf8, 0x8d, 0xbe, 0xce, 0xa4, 0xa8,
|
||||
0xca, 0x93, 0x6c, 0xd7, 0xbf, 0xd4, 0x73, 0x33,
|
||||
0x8d, 0x44, 0x85, 0xcc, 0x73, 0x30, 0x08, 0x9c,
|
||||
0x4d, 0xb2, 0xaa, 0x5a, 0x6c, 0x6f, 0x7b, 0xab,
|
||||
0xb7, 0xb3, 0x7c, 0xc3, 0xfb, 0xe7, 0xca, 0xc4,
|
||||
0xf8, 0x9a, 0x6f, 0xcb, 0xbb, 0x5b, 0x82, 0xe7,
|
||||
0x7a, 0xe8, 0x19, 0xfd, 0x2f, 0x11, 0x22, 0xfb,
|
||||
0x7f, 0x76, 0x8c, 0x6b, 0x94, 0xa4, 0x09, 0x4f,
|
||||
0xa5, 0x6a, 0x77, 0x51, 0xeb, 0xa7, 0x7e, 0xda,
|
||||
0x87, 0x06, 0xee, 0xdc, 0xbe, 0xd1, 0xea, 0x1a,
|
||||
0x40, 0x1d, 0x1b, 0xff, 0x1a, 0xb1, 0x51, 0x7c,
|
||||
0x12, 0xb0, 0xf3, 0xf6, 0x83, 0x01, 0x9c, 0xe7,
|
||||
0x0c, 0x99, 0xbf, 0xac, 0x68, 0x58, 0x72, 0xa4,
|
||||
0xb0, 0x59, 0x85, 0xee, 0x85, 0xac, 0x2a, 0x22,
|
||||
0xf4, 0xcf, 0x15, 0x08, 0x80, 0x1f, 0x0d, 0xd0,
|
||||
0x1e, 0xa0, 0xa0, 0x94, 0xc8, 0xf7, 0xfa, 0x65,
|
||||
0xdd, 0x52, 0xe8, 0x96, 0x37, 0x23, 0x30, 0x57,
|
||||
0x36, 0xe6, 0x9d, 0xf4, 0x0c, 0x4a, 0x05, 0x75,
|
||||
0x1f, 0xad, 0x01, 0xca, 0xb7, 0x6d, 0x8c, 0x43,
|
||||
0x74, 0x06, 0x0a, 0x81, 0xf3, 0x01, 0x62, 0xff,
|
||||
0xf7, 0xf5, 0x5f, 0xaf, 0xe7, 0x2b, 0x0e, 0xf8,
|
||||
0x81, 0xb5, 0x65, 0xdd, 0x01, 0xd9, 0x9f, 0x07,
|
||||
0x17, 0x8a, 0x18, 0xcf, 0x23, 0x6e, 0x88, 0x65,
|
||||
0x91, 0xb5, 0x7b, 0xd3, 0xb0, 0x2d, 0xaf, 0x93,
|
||||
0x66, 0x63, 0x74, 0xac, 0x5a, 0xe6, 0x73, 0xde,
|
||||
0x3b, 0x02, 0x03, 0x01, 0x00, 0x01,
|
||||
};
|
||||
const unsigned int root_pub_der_len = 398;
|
||||
#endif
|
||||
#elif defined(MCUBOOT_SIGN_EC256) || \
|
||||
defined(MCUBOOT_SIGN_EC384)
|
||||
#define HAVE_KEYS
|
||||
#ifndef MCUBOOT_SIGN_EC384
|
||||
const unsigned char root_pub_der[] = {
|
||||
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
|
||||
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
|
||||
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
|
||||
0x42, 0x00, 0x04, 0x2a, 0xcb, 0x40, 0x3c, 0xe8,
|
||||
0xfe, 0xed, 0x5b, 0xa4, 0x49, 0x95, 0xa1, 0xa9,
|
||||
0x1d, 0xae, 0xe8, 0xdb, 0xbe, 0x19, 0x37, 0xcd,
|
||||
0x14, 0xfb, 0x2f, 0x24, 0x57, 0x37, 0xe5, 0x95,
|
||||
0x39, 0x88, 0xd9, 0x94, 0xb9, 0xd6, 0x5a, 0xeb,
|
||||
0xd7, 0xcd, 0xd5, 0x30, 0x8a, 0xd6, 0xfe, 0x48,
|
||||
0xb2, 0x4a, 0x6a, 0x81, 0x0e, 0xe5, 0xf0, 0x7d,
|
||||
0x8b, 0x68, 0x34, 0xcc, 0x3a, 0x6a, 0xfc, 0x53,
|
||||
0x8e, 0xfa, 0xc1, };
|
||||
const unsigned int root_pub_der_len = 91;
|
||||
#else /* MCUBOOT_SIGN_EC384 */
|
||||
const unsigned char root_pub_der[] = {
|
||||
0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
|
||||
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b,
|
||||
0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04,
|
||||
0x0c, 0x76, 0xca, 0xae, 0x72, 0x3a, 0xa5, 0xe8,
|
||||
0xf0, 0xd4, 0xf1, 0x16, 0xb5, 0x02, 0xef, 0x77,
|
||||
0xa1, 0x1b, 0x93, 0x61, 0x78, 0xc0, 0x09, 0x26,
|
||||
0x7b, 0x3b, 0x40, 0x9c, 0xee, 0x49, 0x85, 0xe0,
|
||||
0xc9, 0x4f, 0xe7, 0xf2, 0xba, 0x97, 0x6c, 0xf3,
|
||||
0x82, 0x65, 0x14, 0x2c, 0xf5, 0x0c, 0x73, 0x33,
|
||||
0x4d, 0x32, 0xe7, 0x9b, 0xd3, 0x42, 0xcc, 0x95,
|
||||
0x5a, 0xe5, 0xe2, 0xf5, 0xf4, 0x6e, 0x45, 0xe0,
|
||||
0xed, 0x20, 0x35, 0x5c, 0xaf, 0x52, 0x35, 0x81,
|
||||
0xd4, 0xdc, 0x9c, 0xe3, 0x9e, 0x22, 0x3e, 0xfb,
|
||||
0x3f, 0x22, 0x10, 0xda, 0x70, 0x03, 0x37, 0xad,
|
||||
0xa8, 0xf2, 0x48, 0xfe, 0x3a, 0x60, 0x69, 0xa5,
|
||||
};
|
||||
const unsigned int root_pub_der_len = 120;
|
||||
#endif /* MCUBOOT_SIGN_EC384 */
|
||||
#elif defined(MCUBOOT_SIGN_ED25519)
|
||||
#define HAVE_KEYS
|
||||
const unsigned char root_pub_der[] = {
|
||||
0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
|
||||
0x70, 0x03, 0x21, 0x00, 0xd4, 0xb3, 0x1b, 0xa4,
|
||||
0x9a, 0x3a, 0xdd, 0x3f, 0x82, 0x5d, 0x10, 0xca,
|
||||
0x7f, 0x31, 0xb5, 0x0b, 0x0d, 0xe8, 0x7f, 0x37,
|
||||
0xcc, 0xc4, 0x9f, 0x1a, 0x40, 0x3a, 0x5c, 0x13,
|
||||
0x20, 0xff, 0xb4, 0xe0,
|
||||
};
|
||||
const unsigned int root_pub_der_len = 44;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_KEYS)
|
||||
const struct bootutil_key bootutil_keys[] = {
|
||||
{
|
||||
.key = root_pub_der,
|
||||
.len = &root_pub_der_len,
|
||||
},
|
||||
};
|
||||
const int bootutil_key_cnt = 1;
|
||||
#endif
|
||||
|
||||
#if defined(MCUBOOT_ENCRYPT_RSA)
|
||||
unsigned char enc_key[] = {
|
||||
0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
|
||||
0xb4, 0x26, 0x14, 0x49, 0x3d, 0x16, 0x13, 0x3a, 0x6d, 0x9c, 0x84, 0xa9,
|
||||
0x8b, 0x6a, 0x10, 0x20, 0x61, 0xef, 0x48, 0x04, 0xa4, 0x4b, 0x24, 0xf3,
|
||||
0x00, 0x32, 0xac, 0x22, 0xe0, 0x30, 0x27, 0x70, 0x18, 0xe5, 0x55, 0xc8,
|
||||
0xb8, 0x05, 0x34, 0x03, 0xb0, 0xf8, 0xa5, 0x96, 0xd2, 0x48, 0x58, 0xef,
|
||||
0x70, 0xb0, 0x09, 0xdb, 0xe3, 0x58, 0x62, 0xef, 0x99, 0x63, 0x01, 0xb2,
|
||||
0x89, 0xc4, 0xb3, 0xf6, 0x9e, 0x62, 0xbf, 0x4d, 0xc2, 0x8a, 0xd0, 0xc9,
|
||||
0x4d, 0x43, 0xa3, 0xd8, 0xe5, 0x1d, 0xec, 0x62, 0x63, 0x08, 0xe2, 0x20,
|
||||
0xa5, 0xfc, 0x78, 0xd0, 0x3e, 0x74, 0xc8, 0xa4, 0x1b, 0x36, 0xad, 0x7b,
|
||||
0xf5, 0x06, 0xae, 0x4d, 0x51, 0x9b, 0x40, 0xce, 0x30, 0x4f, 0x6c, 0xea,
|
||||
0xf9, 0xe9, 0x74, 0xea, 0x06, 0xee, 0x9c, 0xe4, 0x14, 0x68, 0x20, 0xb9,
|
||||
0x3d, 0xe7, 0x11, 0x14, 0x8b, 0x25, 0xa3, 0xff, 0x4c, 0x8a, 0xf3, 0x53,
|
||||
0xee, 0x6b, 0x3e, 0xef, 0x34, 0xcd, 0x6a, 0x3f, 0x62, 0x68, 0xc0, 0xff,
|
||||
0x78, 0x4c, 0xb0, 0xc3, 0xe6, 0x96, 0x61, 0xfc, 0x1f, 0x18, 0xf1, 0x7a,
|
||||
0x82, 0xe2, 0x8f, 0x35, 0xa8, 0x2b, 0x86, 0x16, 0xa4, 0x46, 0xfb, 0xac,
|
||||
0x7e, 0x41, 0xdb, 0x02, 0x05, 0x91, 0x6d, 0xdf, 0xc1, 0xde, 0x13, 0x95,
|
||||
0x9c, 0xf9, 0x9e, 0x5e, 0x72, 0xba, 0xa7, 0x25, 0x93, 0xfb, 0xdc, 0xe8,
|
||||
0xab, 0x86, 0x45, 0x88, 0x47, 0x2d, 0xed, 0xee, 0xee, 0x97, 0x9e, 0xce,
|
||||
0x5d, 0x9b, 0x04, 0x04, 0x40, 0x7c, 0xcb, 0x7c, 0x3d, 0x2c, 0x74, 0xab,
|
||||
0xa4, 0xcc, 0x64, 0xa3, 0x5c, 0x95, 0x3d, 0xd4, 0xa2, 0xdc, 0x92, 0xb2,
|
||||
0xc8, 0x18, 0xcb, 0xf9, 0x00, 0x39, 0x81, 0x8f, 0x8f, 0x40, 0xc2, 0xdf,
|
||||
0x99, 0x29, 0xac, 0x8a, 0xc2, 0x3b, 0xd8, 0xa4, 0xf2, 0xad, 0xaf, 0x74,
|
||||
0xc0, 0x11, 0xc7, 0x99, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01,
|
||||
0x00, 0x42, 0x47, 0x80, 0x4f, 0x31, 0xda, 0x5d, 0x58, 0xb1, 0xdb, 0x54,
|
||||
0x33, 0xcc, 0xc7, 0x49, 0x07, 0xa1, 0x00, 0x98, 0x4e, 0x9c, 0xe3, 0xc8,
|
||||
0xc4, 0x5e, 0xde, 0x45, 0xd6, 0xcf, 0x04, 0xe8, 0x7d, 0xa5, 0xab, 0x3a,
|
||||
0xd4, 0x8e, 0x5f, 0xdb, 0xb3, 0x3f, 0xf9, 0x3b, 0x73, 0x32, 0x0a, 0xcc,
|
||||
0x2d, 0xcc, 0x17, 0xf8, 0x88, 0x9e, 0x2c, 0x76, 0xba, 0x10, 0x85, 0x0c,
|
||||
0xaa, 0xd3, 0x65, 0x3b, 0x91, 0x10, 0xd4, 0xe3, 0xed, 0x88, 0x15, 0xea,
|
||||
0x9b, 0x25, 0x82, 0x2d, 0x56, 0x2f, 0x75, 0xc2, 0xf2, 0xaf, 0xdd, 0x24,
|
||||
0xd5, 0x3e, 0x3c, 0x95, 0x76, 0x88, 0x84, 0x0f, 0x0d, 0xd1, 0xb5, 0x5c,
|
||||
0x3e, 0xae, 0xf7, 0xb6, 0x49, 0x5c, 0x2c, 0xf2, 0xba, 0xe9, 0xab, 0x4f,
|
||||
0x37, 0x64, 0x9b, 0x30, 0x18, 0xaa, 0x54, 0x40, 0x04, 0xea, 0x3d, 0x25,
|
||||
0x4d, 0x02, 0x29, 0x71, 0x6f, 0x4d, 0x82, 0x9b, 0xc3, 0x44, 0x2a, 0x9d,
|
||||
0x0c, 0x98, 0xd3, 0xc8, 0x15, 0x0d, 0x04, 0x93, 0x60, 0x30, 0xc7, 0x5e,
|
||||
0x79, 0xea, 0x53, 0x9d, 0xc0, 0x0e, 0x81, 0xac, 0x90, 0xbc, 0x9e, 0x1e,
|
||||
0xd2, 0x28, 0x0f, 0x10, 0xf5, 0x1f, 0xdf, 0x38, 0x7f, 0x8a, 0x90, 0x8d,
|
||||
0x49, 0x07, 0x7d, 0x78, 0xcb, 0xa7, 0xef, 0x92, 0x6d, 0x3b, 0x13, 0x95,
|
||||
0x9b, 0xba, 0x83, 0xc6, 0xb3, 0x71, 0x25, 0x27, 0x07, 0x99, 0x54, 0x82,
|
||||
0x3d, 0xec, 0xc5, 0xf8, 0xb4, 0xa0, 0x38, 0x7a, 0x59, 0x6a, 0x0b, 0xca,
|
||||
0x69, 0x6c, 0x17, 0xa4, 0x18, 0xe0, 0xb4, 0xaa, 0x89, 0x99, 0x8f, 0xcb,
|
||||
0x71, 0x34, 0x09, 0x1b, 0x6e, 0xe6, 0x87, 0x00, 0xb5, 0xba, 0x70, 0x8a,
|
||||
0x29, 0x3d, 0x9a, 0x06, 0x18, 0x2d, 0x66, 0x5e, 0x61, 0x37, 0xeb, 0xdd,
|
||||
0x5e, 0xc8, 0x28, 0x92, 0x05, 0x30, 0xfd, 0xb8, 0x65, 0xb1, 0x7f, 0xbf,
|
||||
0x2d, 0x55, 0x12, 0x91, 0xc1, 0x02, 0x81, 0x81, 0x00, 0xda, 0x65, 0xda,
|
||||
0x38, 0x7c, 0x18, 0xfb, 0x00, 0x11, 0x60, 0xeb, 0x37, 0x65, 0xb8, 0x83,
|
||||
0x62, 0x88, 0xc4, 0x3a, 0x4e, 0x64, 0x6a, 0xf3, 0x3e, 0x4e, 0xc0, 0x34,
|
||||
0x19, 0x8a, 0xcb, 0x4a, 0xca, 0x2f, 0x5d, 0x50, 0x7a, 0xac, 0xf7, 0x9e,
|
||||
0x87, 0x5a, 0xfc, 0x4d, 0x49, 0xd7, 0xf9, 0x21, 0xf5, 0x0b, 0x6f, 0x57,
|
||||
0x41, 0x3d, 0x8f, 0xb8, 0xec, 0x7f, 0xcc, 0x92, 0x09, 0xbe, 0xd3, 0xa4,
|
||||
0xc3, 0x14, 0x85, 0x21, 0x5d, 0x05, 0xa3, 0xaa, 0x20, 0xf6, 0x62, 0x44,
|
||||
0x50, 0x03, 0x5e, 0x53, 0x4a, 0xcd, 0x6a, 0xb6, 0x65, 0x8e, 0x4e, 0x4b,
|
||||
0x3f, 0x25, 0xc6, 0x16, 0x31, 0xf5, 0x99, 0x13, 0x77, 0x42, 0xda, 0xdc,
|
||||
0x70, 0x4d, 0x65, 0xb0, 0x99, 0x0f, 0xdf, 0x5a, 0xb1, 0x45, 0xf0, 0xb9,
|
||||
0x8e, 0xa0, 0xae, 0x4f, 0x4d, 0x65, 0x09, 0x84, 0xb5, 0x38, 0x29, 0xbf,
|
||||
0x69, 0xe0, 0x88, 0x1f, 0x27, 0x02, 0x81, 0x81, 0x00, 0xd3, 0x2a, 0x59,
|
||||
0xec, 0x28, 0xc3, 0x0d, 0x4f, 0x92, 0x96, 0xca, 0x67, 0x94, 0xfc, 0x2e,
|
||||
0xa6, 0x86, 0x68, 0x45, 0x53, 0x92, 0xcc, 0x86, 0x7f, 0x8a, 0xe1, 0x5d,
|
||||
0xe8, 0x1d, 0x9e, 0xbb, 0x1e, 0x00, 0x26, 0x1d, 0x80, 0x12, 0xff, 0x9c,
|
||||
0x11, 0x0a, 0xbd, 0xa6, 0xc3, 0x8d, 0x48, 0xda, 0xfc, 0x10, 0xf7, 0x7a,
|
||||
0x16, 0x07, 0x15, 0xa0, 0x3a, 0xd3, 0x94, 0xfb, 0x52, 0x87, 0x39, 0xee,
|
||||
0xe7, 0xc4, 0x26, 0x49, 0x16, 0xc6, 0xc0, 0x83, 0x25, 0xbf, 0x6a, 0x4e,
|
||||
0x8c, 0x0b, 0x10, 0x85, 0x66, 0xab, 0x7e, 0xae, 0xac, 0x4c, 0x69, 0x3c,
|
||||
0x44, 0xeb, 0xcd, 0xe9, 0xf6, 0x64, 0x8b, 0x4a, 0xd8, 0x6a, 0x4d, 0x6d,
|
||||
0x47, 0xa9, 0xb8, 0x55, 0x72, 0xc1, 0xfd, 0xf4, 0x81, 0x4c, 0x66, 0xbe,
|
||||
0x49, 0xf2, 0x75, 0x4f, 0x80, 0xf1, 0x20, 0x38, 0xb8, 0x6a, 0x1b, 0x75,
|
||||
0x41, 0x30, 0x0f, 0x1b, 0x3f, 0x02, 0x81, 0x80, 0x09, 0x35, 0xfa, 0x7a,
|
||||
0x1f, 0x61, 0xbe, 0x54, 0x46, 0x67, 0x5c, 0x04, 0x3e, 0x1a, 0x06, 0x10,
|
||||
0x85, 0xcc, 0x20, 0xd9, 0x65, 0x8a, 0xcd, 0x2f, 0x77, 0x8a, 0xcb, 0xa7,
|
||||
0xb8, 0x1e, 0xd2, 0xcc, 0xac, 0x2a, 0xb7, 0x56, 0x35, 0x2d, 0x4c, 0x56,
|
||||
0x51, 0x14, 0x0a, 0xfe, 0x6e, 0x49, 0x67, 0x91, 0x3a, 0x26, 0x3b, 0xfb,
|
||||
0xd8, 0x68, 0xd3, 0x57, 0xc6, 0x1c, 0x0e, 0x9c, 0xb2, 0x9b, 0xa2, 0x7b,
|
||||
0x47, 0xc6, 0x45, 0x9d, 0xf2, 0xba, 0xf0, 0x55, 0xeb, 0x8e, 0x41, 0x6b,
|
||||
0x4e, 0x79, 0x0f, 0xf2, 0x3b, 0xaf, 0xa0, 0x79, 0xb0, 0x02, 0xc5, 0x51,
|
||||
0xa8, 0x7a, 0x2e, 0x3d, 0x75, 0x2a, 0x3b, 0x93, 0xf0, 0x11, 0xe2, 0xf2,
|
||||
0x29, 0x91, 0x7c, 0x5d, 0x38, 0x3a, 0x27, 0x4d, 0x0a, 0xb2, 0x18, 0x61,
|
||||
0x57, 0x8d, 0x82, 0x72, 0xb5, 0x2c, 0x2d, 0x98, 0xa7, 0x01, 0xbb, 0xbc,
|
||||
0xef, 0x67, 0x4e, 0x49, 0x02, 0x81, 0x81, 0x00, 0xb2, 0x70, 0x53, 0x54,
|
||||
0x70, 0x8d, 0x82, 0xad, 0xff, 0x1d, 0x55, 0x24, 0x7a, 0x8d, 0x2f, 0x8e,
|
||||
0xa0, 0x7d, 0x74, 0x37, 0xcf, 0x10, 0xed, 0x86, 0xd1, 0x80, 0xe7, 0xad,
|
||||
0xc1, 0x79, 0xe4, 0x7c, 0xd1, 0x7b, 0x63, 0xea, 0x5a, 0x23, 0x8d, 0x6a,
|
||||
0x09, 0x3d, 0x81, 0xb2, 0x35, 0xad, 0x9e, 0xfe, 0xea, 0x07, 0x76, 0x2f,
|
||||
0x2f, 0x05, 0x63, 0x44, 0xd2, 0x8e, 0x4e, 0x61, 0xca, 0xcb, 0x75, 0xca,
|
||||
0x7b, 0xc2, 0x2e, 0x79, 0x04, 0xb2, 0xa1, 0x20, 0x40, 0xc4, 0x40, 0x63,
|
||||
0xae, 0xe5, 0xe3, 0x14, 0x83, 0x4e, 0xa5, 0xa4, 0x0b, 0x5d, 0xd2, 0x04,
|
||||
0x1b, 0x8f, 0x01, 0x69, 0xa8, 0x44, 0xdc, 0x96, 0x4c, 0x1d, 0xe9, 0x7e,
|
||||
0x69, 0x38, 0xcf, 0x5c, 0x0d, 0xf9, 0xdf, 0xa7, 0x73, 0x3c, 0x4f, 0x08,
|
||||
0x85, 0xce, 0x03, 0xc4, 0xdd, 0xfd, 0x70, 0x70, 0xc5, 0x99, 0x36, 0x58,
|
||||
0x43, 0x98, 0x40, 0x59, 0x02, 0x81, 0x81, 0x00, 0xd5, 0xaa, 0xfb, 0xec,
|
||||
0x8d, 0xc6, 0xdd, 0xfa, 0x2b, 0x5a, 0x24, 0xd0, 0xda, 0x58, 0xbd, 0x87,
|
||||
0x92, 0x1a, 0x29, 0x62, 0x13, 0x1d, 0x4b, 0x79, 0x1b, 0xbe, 0x79, 0x7d,
|
||||
0xad, 0x79, 0xca, 0x17, 0x75, 0xda, 0xe8, 0x32, 0xe8, 0xa0, 0x9e, 0xa8,
|
||||
0x77, 0x53, 0xac, 0x38, 0xd6, 0xeb, 0xe6, 0x22, 0x65, 0xc4, 0xaa, 0x4c,
|
||||
0xc8, 0xd0, 0x33, 0x1a, 0x1e, 0xbe, 0xbd, 0x73, 0x09, 0x4a, 0xfa, 0x85,
|
||||
0x5c, 0xf3, 0x0c, 0x9c, 0x81, 0x56, 0x30, 0xa7, 0xf7, 0x9b, 0xf4, 0x92,
|
||||
0x9c, 0x6b, 0x93, 0x6a, 0x00, 0x33, 0xdc, 0x2f, 0x54, 0x1e, 0x78, 0xd4,
|
||||
0x97, 0xec, 0x24, 0xa2, 0xdb, 0x3d, 0x03, 0x33, 0x09, 0xb2, 0x2c, 0x03,
|
||||
0x05, 0x40, 0xde, 0x52, 0xf2, 0x9b, 0xfa, 0x00, 0x8d, 0x4b, 0xfe, 0x5b,
|
||||
0x9b, 0x9c, 0x73, 0xad, 0xfb, 0x7a, 0x00, 0x42, 0x62, 0x9e, 0xa0, 0x95,
|
||||
0x55, 0x50, 0x32, 0x87
|
||||
};
|
||||
static unsigned int enc_key_len = 1192;
|
||||
const struct bootutil_key bootutil_enc_key = {
|
||||
.key = enc_key,
|
||||
.len = &enc_key_len,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(MCUBOOT_ENCRYPT_KW)
|
||||
#if defined(MCUBOOT_AES_256)
|
||||
unsigned char enc_key[] = {
|
||||
0xE4, 0x5C, 0x51, 0x46, 0xD2, 0x1C, 0x82, 0x35, 0xCC, 0x1A, 0x19, 0xAF,
|
||||
0xA1, 0xF2, 0xAA, 0x20, 0xC8, 0x8C, 0x7F, 0x40, 0x6C, 0xDB, 0x22, 0xAA,
|
||||
0x6A, 0xB5, 0xCB, 0xAA, 0xF8, 0xB1, 0x5B, 0xB4
|
||||
};
|
||||
static unsigned int enc_key_len = 32;
|
||||
#else
|
||||
unsigned char enc_key[] = {
|
||||
0xd1, 0x5a, 0x04, 0x95, 0xc4, 0xc2, 0xa8, 0xff, 0x30, 0x78, 0xce, 0x49,
|
||||
0xb5, 0xfc, 0xb2, 0xdd
|
||||
};
|
||||
static unsigned int enc_key_len = 16;
|
||||
#endif
|
||||
const struct bootutil_key bootutil_enc_key = {
|
||||
.key = enc_key,
|
||||
.len = &enc_key_len,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(MCUBOOT_ENCRYPT_EC256)
|
||||
unsigned char enc_key[] = {
|
||||
0x30, 0x81, 0x43, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
|
||||
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
|
||||
0x03, 0x01, 0x07, 0x04, 0x29, 0x30, 0x27, 0x02, 0x01, 0x01, 0x04, 0x20,
|
||||
0xf6, 0x1e, 0x51, 0x9d, 0xf8, 0xfa, 0xdd, 0xa1, 0xb7, 0xd9, 0xa9, 0x64,
|
||||
0x64, 0x3b, 0x54, 0xd0, 0x3d, 0xd0, 0x1f, 0xe5, 0x78, 0xd9, 0x17, 0x98,
|
||||
0xa5, 0x28, 0xca, 0xcc, 0x6b, 0x67, 0x9e, 0x06, 0xa1, 0x44,
|
||||
|
||||
};
|
||||
static unsigned int enc_key_len = 70;
|
||||
const struct bootutil_key bootutil_enc_key = {
|
||||
.key = enc_key,
|
||||
.len = &enc_key_len,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(MCUBOOT_ENCRYPT_X25519)
|
||||
unsigned char enc_key[] = {
|
||||
0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e,
|
||||
0x04, 0x22, 0x04, 0x20, 0x28, 0x80, 0x2f, 0xef, 0xef, 0x82, 0x95, 0x50,
|
||||
0xf1, 0x41, 0x93, 0x03, 0x6c, 0x1b, 0xb9, 0x49, 0x6c, 0x51, 0xe5, 0x26,
|
||||
0x87, 0x8f, 0x77, 0x07, 0xf8, 0xb4, 0x1f, 0x04, 0x45, 0x6d, 0x84, 0x4f,
|
||||
};
|
||||
static unsigned int enc_key_len = 48;
|
||||
const struct bootutil_key bootutil_enc_key = {
|
||||
.key = enc_key,
|
||||
.len = &enc_key_len,
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef __MCUBOOT_ASSERT_H__
|
||||
#define __MCUBOOT_ASSERT_H__
|
||||
|
||||
#include <assert.h>
|
||||
void sim_assert(int, const char *test, const char *, unsigned int, const char *);
|
||||
#define ASSERT(x) sim_assert((x), #x, __FILE__, __LINE__, __func__)
|
||||
|
||||
#endif /* __MCUBOOT_ASSERT_H__ */
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __MCUBOOT_CONFIG_H__
|
||||
#define __MCUBOOT_CONFIG_H__
|
||||
|
||||
/*
|
||||
* This file is included by the simulator, but we don't want to
|
||||
* define almost anything here.
|
||||
*
|
||||
* Instead of using mcuboot_config.h, the simulator adds MCUBOOT_xxx
|
||||
* configuration flags to the compiler command lines based on the
|
||||
* values of environment variables. However, the file still must
|
||||
* exist, or bootutil won't build.
|
||||
*/
|
||||
|
||||
#define MCUBOOT_WATCHDOG_FEED() \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#define MCUBOOT_CPU_IDLE() \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#endif /* __MCUBOOT_CONFIG_H__ */
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef __MCUBOOT_LOGGING_H__
|
||||
#define __MCUBOOT_LOGGING_H__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define MCUBOOT_LOG_LEVEL_OFF 0
|
||||
#define MCUBOOT_LOG_LEVEL_ERROR 1
|
||||
#define MCUBOOT_LOG_LEVEL_WARNING 2
|
||||
#define MCUBOOT_LOG_LEVEL_INFO 3
|
||||
#define MCUBOOT_LOG_LEVEL_DEBUG 4
|
||||
#define MCUBOOT_LOG_LEVEL_SIM 5 /* RUST_LOG=trace */
|
||||
|
||||
/*
|
||||
* The compiled log level determines the maximum level that can be
|
||||
* printed. Messages at or below this level can be printed, provided
|
||||
* they are also enabled through the Rust logging system, such as by
|
||||
* setting RUST_LOG to bootsim::api=info.
|
||||
*/
|
||||
#ifndef MCUBOOT_LOG_LEVEL
|
||||
#define MCUBOOT_LOG_LEVEL MCUBOOT_LOG_LEVEL_DEBUG
|
||||
#endif
|
||||
|
||||
#define MCUBOOT_LOG_MODULE_DECLARE(domain) /* ignore */
|
||||
#define MCUBOOT_LOG_MODULE_REGISTER(domain) /* ignore */
|
||||
|
||||
int sim_log_enabled(int level);
|
||||
|
||||
#if MCUBOOT_LOG_LEVEL >= MCUBOOT_LOG_LEVEL_ERROR
|
||||
#define MCUBOOT_LOG_ERR(_fmt, ...) \
|
||||
do { \
|
||||
if (sim_log_enabled(MCUBOOT_LOG_LEVEL_ERROR)) { \
|
||||
fprintf(stderr, "[ERR] " _fmt "\n", ##__VA_ARGS__); \
|
||||
fflush(stderr); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define MCUBOOT_LOG_ERR(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if MCUBOOT_LOG_LEVEL >= MCUBOOT_LOG_LEVEL_WARNING
|
||||
#define MCUBOOT_LOG_WRN(_fmt, ...) \
|
||||
do { \
|
||||
if (sim_log_enabled(MCUBOOT_LOG_LEVEL_WARNING)) { \
|
||||
fprintf(stderr, "[WRN] " _fmt "\n", ##__VA_ARGS__); \
|
||||
fflush(stderr); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define MCUBOOT_LOG_WRN(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if MCUBOOT_LOG_LEVEL >= MCUBOOT_LOG_LEVEL_INFO
|
||||
#define MCUBOOT_LOG_INF(_fmt, ...) \
|
||||
do { \
|
||||
if (sim_log_enabled(MCUBOOT_LOG_LEVEL_INFO)) { \
|
||||
fprintf(stderr, "[INF] " _fmt "\n", ##__VA_ARGS__); \
|
||||
fflush(stderr); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define MCUBOOT_LOG_INF(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if MCUBOOT_LOG_LEVEL >= MCUBOOT_LOG_LEVEL_DEBUG
|
||||
#define MCUBOOT_LOG_DBG(_fmt, ...) \
|
||||
do { \
|
||||
if (sim_log_enabled(MCUBOOT_LOG_LEVEL_DEBUG)) { \
|
||||
fprintf(stderr, "[DBG] " _fmt "\n", ##__VA_ARGS__); \
|
||||
fflush(stderr); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define MCUBOOT_LOG_DBG(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if MCUBOOT_LOG_LEVEL >= MCUBOOT_LOG_LEVEL_SIM
|
||||
#define MCUBOOT_LOG_SIM(_fmt, ...) \
|
||||
do { \
|
||||
if (sim_log_enabled(MCUBOOT_LOG_LEVEL_SIM)) { \
|
||||
fprintf(stderr, "[SIM] " _fmt "\n", ##__VA_ARGS__); \
|
||||
fflush(stderr); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define MCUBOOT_LOG_SIM(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#endif /* __MCUBOOT_LOGGING_H__ */
|
||||
10
bootloader/mcuboot/sim/mcuboot-sys/csupport/os/os_heap.h
Normal file
10
bootloader/mcuboot/sim/mcuboot-sys/csupport/os/os_heap.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef H_OS_HEAP_
|
||||
#define H_OS_HEAP_
|
||||
|
||||
#endif
|
||||
10
bootloader/mcuboot/sim/mcuboot-sys/csupport/os/os_malloc.h
Normal file
10
bootloader/mcuboot/sim/mcuboot-sys/csupport/os/os_malloc.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef H_OS_MALLOC_
|
||||
#define H_OS_MALLOC_
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2023 Arm Limited
|
||||
*/
|
||||
|
||||
/* This file, and the methods within are required when PSA Crypto API is enabled
|
||||
* (--features psa-crypto-api), but the selected combination of features does
|
||||
* not rely on any PSA Crypto APIs, and will not be adding any of them to the build.
|
||||
*/
|
||||
|
||||
#include <bootutil/bootutil_log.h>
|
||||
|
||||
int psa_crypto_init()
|
||||
{
|
||||
BOOT_LOG_SIM("psa_crypto_init() is being stubbed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mbedtls_test_enable_insecure_external_rng(){
|
||||
BOOT_LOG_SIM("mbedtls_test_enable_insecure_external_rng() is being stubbed.\n");
|
||||
}
|
||||
543
bootloader/mcuboot/sim/mcuboot-sys/csupport/run.c
Normal file
543
bootloader/mcuboot/sim/mcuboot-sys/csupport/run.c
Normal file
@@ -0,0 +1,543 @@
|
||||
/* Run the boot image. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <bootutil/bootutil.h>
|
||||
#include <bootutil/image.h>
|
||||
|
||||
#include <flash_map_backend/flash_map_backend.h>
|
||||
|
||||
#include "../../../boot/bootutil/src/bootutil_priv.h"
|
||||
#include "bootsim.h"
|
||||
|
||||
#ifdef MCUBOOT_ENCRYPT_RSA
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/asn1.h"
|
||||
#endif
|
||||
|
||||
#ifdef MCUBOOT_ENCRYPT_KW
|
||||
#include "mbedtls/nist_kw.h"
|
||||
#endif
|
||||
|
||||
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR
|
||||
#include <bootutil/bootutil_log.h>
|
||||
#include "bootutil/crypto/common.h"
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
struct area_desc;
|
||||
extern struct area_desc *sim_get_flash_areas(void);
|
||||
extern void sim_set_flash_areas(struct area_desc *areas);
|
||||
extern void sim_reset_flash_areas(void);
|
||||
|
||||
struct sim_context;
|
||||
extern struct sim_context *sim_get_context(void);
|
||||
extern void sim_set_context(struct sim_context *ctx);
|
||||
extern void sim_reset_context(void);
|
||||
|
||||
extern int sim_flash_erase(uint8_t flash_id, uint32_t offset, uint32_t size);
|
||||
extern int sim_flash_read(uint8_t flash_id, uint32_t offset, uint8_t *dest,
|
||||
uint32_t size);
|
||||
extern int sim_flash_write(uint8_t flash_id, uint32_t offset, const uint8_t *src,
|
||||
uint32_t size);
|
||||
extern uint32_t sim_flash_align(uint8_t flash_id);
|
||||
extern uint8_t sim_flash_erased_val(uint8_t flash_id);
|
||||
|
||||
struct sim_context {
|
||||
int flash_counter;
|
||||
int jumped;
|
||||
uint8_t c_asserts;
|
||||
uint8_t c_catch_asserts;
|
||||
jmp_buf boot_jmpbuf;
|
||||
};
|
||||
|
||||
#ifdef MCUBOOT_ENCRYPT_RSA
|
||||
static int
|
||||
parse_pubkey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
|
||||
{
|
||||
int rc;
|
||||
size_t len;
|
||||
|
||||
if ((rc = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*p + len != end) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ((rc = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
*p += len;
|
||||
|
||||
if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
|
||||
return -4;
|
||||
}
|
||||
|
||||
if (**p != MBEDTLS_ASN1_PRIMITIVE) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
*p += 1;
|
||||
|
||||
if ((rc = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return -6;
|
||||
}
|
||||
|
||||
if (mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N)) != 0) {
|
||||
return -7;
|
||||
}
|
||||
|
||||
if (mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E)) != 0) {
|
||||
return -8;
|
||||
}
|
||||
|
||||
ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));
|
||||
|
||||
if (*p != end) {
|
||||
return -9;
|
||||
}
|
||||
|
||||
if (mbedtls_rsa_check_pubkey(ctx) != 0) {
|
||||
return -10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fake_rng(void *p_rng, unsigned char *output, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
(void)p_rng;
|
||||
for (i = 0; i < len; i++) {
|
||||
output[i] = (char)i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int mbedtls_platform_set_calloc_free(void * (*calloc_func)(size_t, size_t),
|
||||
void (*free_func)(void *));
|
||||
|
||||
int rsa_oaep_encrypt_(const uint8_t *pubkey, unsigned pubkey_len,
|
||||
const uint8_t *seckey, unsigned seckey_len,
|
||||
uint8_t *encbuf)
|
||||
{
|
||||
#ifdef MCUBOOT_ENCRYPT_RSA
|
||||
mbedtls_rsa_context ctx;
|
||||
uint8_t *cp;
|
||||
uint8_t *cpend;
|
||||
int rc;
|
||||
|
||||
mbedtls_platform_set_calloc_free(calloc, free);
|
||||
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
mbedtls_rsa_init(&ctx);
|
||||
mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
|
||||
#else
|
||||
mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
|
||||
#endif
|
||||
|
||||
cp = (uint8_t *)pubkey;
|
||||
cpend = cp + pubkey_len;
|
||||
|
||||
rc = parse_pubkey(&ctx, &cp, cpend);
|
||||
if (rc) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
rc = mbedtls_rsa_rsaes_oaep_encrypt(&ctx, fake_rng, NULL,
|
||||
NULL, 0, seckey_len, seckey, encbuf);
|
||||
#else
|
||||
rc = mbedtls_rsa_rsaes_oaep_encrypt(&ctx, fake_rng, NULL, MBEDTLS_RSA_PUBLIC,
|
||||
NULL, 0, seckey_len, seckey, encbuf);
|
||||
#endif
|
||||
if (rc) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
mbedtls_rsa_free(&ctx);
|
||||
return rc;
|
||||
|
||||
#else
|
||||
(void)pubkey;
|
||||
(void)pubkey_len;
|
||||
(void)seckey;
|
||||
(void)seckey_len;
|
||||
(void)encbuf;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int kw_encrypt_(const uint8_t *kek, const uint8_t *seckey, uint8_t *encbuf)
|
||||
{
|
||||
#ifdef MCUBOOT_ENCRYPT_KW
|
||||
#ifdef MCUBOOT_AES_256
|
||||
int key_len = 256;
|
||||
int out_size = 40;
|
||||
int in_len = 32;
|
||||
#else
|
||||
int key_len = 128;
|
||||
int out_size = 24;
|
||||
int in_len = 16;
|
||||
#endif
|
||||
mbedtls_nist_kw_context kw;
|
||||
size_t olen;
|
||||
int rc;
|
||||
|
||||
mbedtls_platform_set_calloc_free(calloc, free);
|
||||
|
||||
mbedtls_nist_kw_init(&kw);
|
||||
|
||||
rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES, kek, key_len, 1);
|
||||
if (rc) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = mbedtls_nist_kw_wrap(&kw, MBEDTLS_KW_MODE_KW, seckey, in_len, encbuf,
|
||||
&olen, out_size);
|
||||
|
||||
done:
|
||||
mbedtls_nist_kw_free(&kw);
|
||||
return rc;
|
||||
|
||||
#else
|
||||
(void)kek;
|
||||
(void)seckey;
|
||||
(void)encbuf;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t flash_area_align(const struct flash_area *area)
|
||||
{
|
||||
return sim_flash_align(area->fa_device_id);
|
||||
}
|
||||
|
||||
uint8_t flash_area_erased_val(const struct flash_area *area)
|
||||
{
|
||||
return sim_flash_erased_val(area->fa_device_id);
|
||||
}
|
||||
|
||||
struct area {
|
||||
struct flash_area whole;
|
||||
struct flash_area *areas;
|
||||
uint32_t num_areas;
|
||||
uint8_t id;
|
||||
};
|
||||
|
||||
struct area_desc {
|
||||
struct area slots[16];
|
||||
uint32_t num_slots;
|
||||
};
|
||||
|
||||
int invoke_boot_go(struct sim_context *ctx, struct area_desc *adesc,
|
||||
struct boot_rsp *rsp, int image_id)
|
||||
{
|
||||
int res;
|
||||
struct boot_loader_state *state;
|
||||
|
||||
#if defined(MCUBOOT_SIGN_RSA) || \
|
||||
(defined(MCUBOOT_SIGN_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ||\
|
||||
(defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ||\
|
||||
(defined(MCUBOOT_ENCRYPT_X25519) && defined(MCUBOOT_USE_MBED_TLS))
|
||||
mbedtls_platform_set_calloc_free(calloc, free);
|
||||
#endif
|
||||
|
||||
state = malloc(sizeof(struct boot_loader_state));
|
||||
|
||||
sim_set_flash_areas(adesc);
|
||||
sim_set_context(ctx);
|
||||
|
||||
if (setjmp(ctx->boot_jmpbuf) == 0) {
|
||||
boot_state_clear(state);
|
||||
|
||||
#if BOOT_IMAGE_NUMBER > 1
|
||||
if (image_id >= 0) {
|
||||
memset(state->img_mask, 1, sizeof(state->img_mask));
|
||||
state->img_mask[image_id] = 0;
|
||||
}
|
||||
#else
|
||||
(void) image_id;
|
||||
#endif /* BOOT_IMAGE_NUMBER > 1 */
|
||||
|
||||
res = context_boot_go(state, rsp);
|
||||
sim_reset_flash_areas();
|
||||
sim_reset_context();
|
||||
free(state);
|
||||
/* printf("boot_go off: %d (0x%08x)\n", res, rsp.br_image_off); */
|
||||
return res;
|
||||
} else {
|
||||
sim_reset_flash_areas();
|
||||
sim_reset_context();
|
||||
free(state);
|
||||
return -0x13579;
|
||||
}
|
||||
}
|
||||
|
||||
void *os_malloc(size_t size)
|
||||
{
|
||||
// printf("os_malloc 0x%x bytes\n", size);
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
int flash_area_id_from_multi_image_slot(int image_index, int slot)
|
||||
{
|
||||
switch (slot) {
|
||||
case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
|
||||
case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index);
|
||||
case 2: return FLASH_AREA_IMAGE_SCRATCH;
|
||||
}
|
||||
|
||||
printf("Image flash area ID not found\n");
|
||||
return -1; /* flash_area_open will fail on that */
|
||||
}
|
||||
|
||||
int flash_area_open(uint8_t id, const struct flash_area **area)
|
||||
{
|
||||
uint32_t i;
|
||||
struct area_desc *flash_areas;
|
||||
|
||||
flash_areas = sim_get_flash_areas();
|
||||
for (i = 0; i < flash_areas->num_slots; i++) {
|
||||
if (flash_areas->slots[i].id == id)
|
||||
break;
|
||||
}
|
||||
if (i == flash_areas->num_slots) {
|
||||
printf("Unsupported area\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Unsure if this is right, just returning the first area. */
|
||||
*area = &flash_areas->slots[i].whole;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void flash_area_close(const struct flash_area *area)
|
||||
{
|
||||
(void)area;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read/write/erase. Offset is relative from beginning of flash area.
|
||||
*/
|
||||
int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
|
||||
uint32_t len)
|
||||
{
|
||||
BOOT_LOG_SIM("%s: area=%d, off=%x, len=%x",
|
||||
__func__, area->fa_id, off, len);
|
||||
return sim_flash_read(area->fa_device_id, area->fa_off + off, dst, len);
|
||||
}
|
||||
|
||||
int flash_area_write(const struct flash_area *area, uint32_t off, const void *src,
|
||||
uint32_t len)
|
||||
{
|
||||
BOOT_LOG_SIM("%s: area=%d, off=%x, len=%x", __func__,
|
||||
area->fa_id, off, len);
|
||||
struct sim_context *ctx = sim_get_context();
|
||||
if (--(ctx->flash_counter) == 0) {
|
||||
ctx->jumped++;
|
||||
longjmp(ctx->boot_jmpbuf, 1);
|
||||
}
|
||||
return sim_flash_write(area->fa_device_id, area->fa_off + off, src, len);
|
||||
}
|
||||
|
||||
int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
|
||||
{
|
||||
BOOT_LOG_SIM("%s: area=%d, off=%x, len=%x", __func__,
|
||||
area->fa_id, off, len);
|
||||
struct sim_context *ctx = sim_get_context();
|
||||
if (--(ctx->flash_counter) == 0) {
|
||||
ctx->jumped++;
|
||||
longjmp(ctx->boot_jmpbuf, 1);
|
||||
}
|
||||
return sim_flash_erase(area->fa_device_id, area->fa_off + off, len);
|
||||
}
|
||||
|
||||
int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
|
||||
{
|
||||
uint32_t i;
|
||||
struct area *slot;
|
||||
struct area_desc *flash_areas;
|
||||
|
||||
flash_areas = sim_get_flash_areas();
|
||||
for (i = 0; i < flash_areas->num_slots; i++) {
|
||||
if (flash_areas->slots[i].id == idx)
|
||||
break;
|
||||
}
|
||||
if (i == flash_areas->num_slots) {
|
||||
printf("Unsupported area\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
slot = &flash_areas->slots[i];
|
||||
|
||||
if (slot->num_areas > (uint32_t)*cnt) {
|
||||
printf("Too many areas in slot\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
*cnt = slot->num_areas;
|
||||
memcpy(ret, slot->areas, slot->num_areas * sizeof(struct flash_area));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_area_get_sectors(int fa_id, uint32_t *count,
|
||||
struct flash_sector *sectors)
|
||||
{
|
||||
uint32_t i;
|
||||
struct area *slot;
|
||||
struct area_desc *flash_areas;
|
||||
|
||||
flash_areas = sim_get_flash_areas();
|
||||
for (i = 0; i < flash_areas->num_slots; i++) {
|
||||
if (flash_areas->slots[i].id == fa_id)
|
||||
break;
|
||||
}
|
||||
if (i == flash_areas->num_slots) {
|
||||
printf("Unsupported area\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
slot = &flash_areas->slots[i];
|
||||
|
||||
if (slot->num_areas > *count) {
|
||||
printf("Too many areas in slot\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
for (i = 0; i < slot->num_areas; i++) {
|
||||
sectors[i].fs_off = slot->areas[i].fa_off -
|
||||
slot->whole.fa_off;
|
||||
sectors[i].fs_size = slot->areas[i].fa_size;
|
||||
}
|
||||
*count = slot->num_areas;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_area_id_to_multi_image_slot(int image_index, int area_id)
|
||||
{
|
||||
if (area_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
|
||||
return 0;
|
||||
}
|
||||
if (area_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Unsupported image area ID\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
int flash_area_id_from_image_slot(int slot) {
|
||||
/* For single image cases, just use the first image. */
|
||||
return flash_area_id_from_multi_image_slot(0, slot);
|
||||
}
|
||||
|
||||
int flash_area_sector_from_off(uint32_t off, struct flash_sector *sector)
|
||||
{
|
||||
uint32_t i, sec_off, sec_size;
|
||||
struct area *slot;
|
||||
struct area_desc *flash_areas;
|
||||
|
||||
flash_areas = sim_get_flash_areas();
|
||||
for (i = 0; i < flash_areas->num_slots; i++) {
|
||||
if (flash_areas->slots[i].id == FLASH_AREA_ID(image_0))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == flash_areas->num_slots) {
|
||||
printf("Unsupported area\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
slot = &flash_areas->slots[i];
|
||||
|
||||
for (i = 0; i < slot->num_areas; i++) {
|
||||
sec_off = slot->areas[i].fa_off - slot->whole.fa_off;
|
||||
sec_size = slot->areas[i].fa_size;
|
||||
|
||||
if (off >= sec_off && off < (sec_off + sec_size)) {
|
||||
sector->fs_off = sec_off;
|
||||
sector->fs_size = sec_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (i < slot->num_areas) ? 0 : -1;
|
||||
}
|
||||
|
||||
int flash_area_get_sector(const struct flash_area *fa, uint32_t off,
|
||||
struct flash_sector *sector)
|
||||
{
|
||||
uint32_t i, sec_off, sec_size;
|
||||
struct area *slot;
|
||||
struct area_desc *flash_areas;
|
||||
|
||||
flash_areas = sim_get_flash_areas();
|
||||
for (i = 0; i < flash_areas->num_slots; i++) {
|
||||
if (&flash_areas->slots[i].whole == fa)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == flash_areas->num_slots) {
|
||||
printf("Unsupported area\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
slot = &flash_areas->slots[i];
|
||||
|
||||
for (i = 0; i < slot->num_areas; i++) {
|
||||
sec_off = slot->areas[i].fa_off - slot->whole.fa_off;
|
||||
sec_size = slot->areas[i].fa_size;
|
||||
|
||||
if (off >= sec_off && off < (sec_off + sec_size)) {
|
||||
sector->fs_off = sec_off;
|
||||
sector->fs_size = sec_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (i < slot->num_areas) ? 0 : -1;
|
||||
}
|
||||
|
||||
void sim_assert(int x, const char *assertion, const char *file, unsigned int line, const char *function)
|
||||
{
|
||||
if (!(x)) {
|
||||
struct sim_context *ctx = sim_get_context();
|
||||
if (ctx->c_catch_asserts) {
|
||||
ctx->c_asserts++;
|
||||
} else {
|
||||
BOOT_LOG_ERR("%s:%d: %s: Assertion `%s' failed.", file, line, function, assertion);
|
||||
|
||||
/* NOTE: if the assert below is triggered, the place where it was originally
|
||||
* asserted is printed by the message above...
|
||||
*/
|
||||
assert(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t boot_max_align(void)
|
||||
{
|
||||
return BOOT_MAX_ALIGN;
|
||||
}
|
||||
|
||||
uint32_t boot_magic_sz(void)
|
||||
{
|
||||
return BOOT_MAGIC_ALIGN_SIZE;
|
||||
}
|
||||
43
bootloader/mcuboot/sim/mcuboot-sys/csupport/security_cnt.c
Normal file
43
bootloader/mcuboot/sim/mcuboot-sys/csupport/security_cnt.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2023 Arm Limited
|
||||
*/
|
||||
|
||||
#include "bootutil/security_cnt.h"
|
||||
#include "mcuboot_config/mcuboot_logging.h"
|
||||
#include "bootutil/fault_injection_hardening.h"
|
||||
|
||||
/*
|
||||
* Since the simulator is executing unit tests in parallel,
|
||||
* the storage area where the security counter values reside
|
||||
* has to be managed per thread from Rust's side.
|
||||
*/
|
||||
#ifdef MCUBOOT_HW_ROLLBACK_PROT
|
||||
|
||||
int sim_set_nv_counter_for_image(uint32_t image_index, uint32_t security_counter_value);
|
||||
|
||||
int sim_get_nv_counter_for_image(uint32_t image_index, uint32_t* data);
|
||||
|
||||
fih_ret boot_nv_security_counter_init(void) {
|
||||
return FIH_SUCCESS;
|
||||
}
|
||||
|
||||
fih_ret boot_nv_security_counter_get(uint32_t image_id, fih_int *security_cnt) {
|
||||
uint32_t counter = 0;
|
||||
FIH_DECLARE(fih_rc, FIH_FAILURE);
|
||||
fih_rc = fih_ret_encode_zero_equality(sim_get_nv_counter_for_image(image_id, &counter));
|
||||
|
||||
MCUBOOT_LOG_INF("Read security counter value (%d) for image: %d\n", counter, image_id);
|
||||
*security_cnt = fih_int_encode(counter);
|
||||
|
||||
FIH_RET(fih_rc);
|
||||
}
|
||||
|
||||
int32_t boot_nv_security_counter_update(uint32_t image_id, uint32_t img_security_cnt) {
|
||||
MCUBOOT_LOG_INF("Writing security counter value (%d) for image: %d\n", img_security_cnt, image_id);
|
||||
|
||||
return sim_set_nv_counter_for_image(image_id, img_security_cnt);
|
||||
}
|
||||
|
||||
#endif /* MCUBOOT_HW_ROLLBACK_PROT */
|
||||
171
bootloader/mcuboot/sim/mcuboot-sys/csupport/storage/flash_map.h
Normal file
171
bootloader/mcuboot/sim/mcuboot-sys/csupport/storage/flash_map.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_UTIL_FLASH_MAP_
|
||||
#define H_UTIL_FLASH_MAP_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides abstraction of flash regions for type of use.
|
||||
* I.e. dude where's my image?
|
||||
*
|
||||
* System will contain a map which contains flash areas. Every
|
||||
* region will contain flash identifier, offset within flash and length.
|
||||
*
|
||||
* 1. This system map could be in a file within filesystem (Initializer
|
||||
* must know/figure out where the filesystem is at).
|
||||
* 2. Map could be at fixed location for project (compiled to code)
|
||||
* 3. Map could be at specific place in flash (put in place at mfg time).
|
||||
*
|
||||
* Note that the map you use must be valid for BSP it's for,
|
||||
* match the linker scripts when platform executes from flash,
|
||||
* and match the target offset specified in download script.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
|
||||
/**
|
||||
* @brief Structure describing an area on a flash device.
|
||||
*
|
||||
* Multiple flash devices may be available in the system, each of
|
||||
* which may have its own areas. For this reason, flash areas track
|
||||
* which flash device they are part of.
|
||||
*/
|
||||
struct flash_area {
|
||||
/**
|
||||
* This flash area's ID; unique in the system.
|
||||
*/
|
||||
uint8_t fa_id;
|
||||
|
||||
/**
|
||||
* ID of the flash device this area is a part of.
|
||||
*/
|
||||
uint8_t fa_device_id;
|
||||
|
||||
uint16_t pad16;
|
||||
|
||||
/**
|
||||
* This area's offset, relative to the beginning of its flash
|
||||
* device's storage.
|
||||
*/
|
||||
uint32_t fa_off;
|
||||
|
||||
/**
|
||||
* This area's size, in bytes.
|
||||
*/
|
||||
uint32_t fa_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure describing a sector within a flash area.
|
||||
*
|
||||
* Each sector has an offset relative to the start of its flash area
|
||||
* (NOT relative to the start of its flash device), and a size. A
|
||||
* flash area may contain sectors with different sizes.
|
||||
*/
|
||||
struct flash_sector {
|
||||
/**
|
||||
* Offset of this sector, from the start of its flash area (not device).
|
||||
*/
|
||||
uint32_t fs_off;
|
||||
|
||||
/**
|
||||
* Size of this sector, in bytes.
|
||||
*/
|
||||
uint32_t fs_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* Retrieve a memory-mapped flash device's base address.
|
||||
*
|
||||
* On success, the address will be stored in the value pointed to by
|
||||
* ret.
|
||||
*
|
||||
* Returns 0 on success, or an error code on failure.
|
||||
*/
|
||||
int flash_device_base(uint8_t fd_id, uintptr_t *ret);
|
||||
|
||||
/*
|
||||
* Start using flash area.
|
||||
*/
|
||||
int flash_area_open(uint8_t id, const struct flash_area **);
|
||||
|
||||
void flash_area_close(const struct flash_area *);
|
||||
|
||||
/*
|
||||
* Read/write/erase. Offset is relative from beginning of flash area.
|
||||
*/
|
||||
int flash_area_read(const struct flash_area *, uint32_t off, void *dst,
|
||||
uint32_t len);
|
||||
int flash_area_write(const struct flash_area *, uint32_t off, const void *src,
|
||||
uint32_t len);
|
||||
int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len);
|
||||
|
||||
/*
|
||||
* Alignment restriction for flash writes.
|
||||
*/
|
||||
uint32_t flash_area_align(const struct flash_area *);
|
||||
|
||||
/*
|
||||
* What is value is read from erased flash bytes.
|
||||
*/
|
||||
uint8_t flash_area_erased_val(const struct flash_area *);
|
||||
|
||||
/*
|
||||
* Given flash area ID, return info about sectors within the area.
|
||||
*/
|
||||
int flash_area_get_sectors(int fa_id, uint32_t *count,
|
||||
struct flash_sector *sectors);
|
||||
|
||||
|
||||
/* Retrieve the flash sector a given offset belongs to.
|
||||
*
|
||||
* Returns 0 on success, or an error code on failure.
|
||||
*/
|
||||
int flash_area_sector_from_off(uint32_t off, struct flash_sector *sector);
|
||||
|
||||
/* Retrieve the flash sector a given offset, within flash area.
|
||||
*
|
||||
* @param fa flash area.
|
||||
* @param off offset of sector.
|
||||
* @param sector pointer to structure for obtained information.
|
||||
* Returns 0 on success, or an error code on failure.
|
||||
*/
|
||||
int flash_area_get_sector(const struct flash_area *fa, uint32_t off,
|
||||
struct flash_sector *sector);
|
||||
|
||||
/*
|
||||
* Similar to flash_area_get_sectors(), but return the values in an
|
||||
* array of struct flash_area instead.
|
||||
*/
|
||||
__attribute__((deprecated))
|
||||
int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret);
|
||||
|
||||
int flash_area_id_from_image_slot(int slot);
|
||||
int flash_area_id_from_multi_image_slot(int image_index, int slot);
|
||||
int flash_area_id_to_multi_image_slot(int image_index, int area_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_UTIL_FLASH_MAP_ */
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __SYSFLASH_H__
|
||||
#define __SYSFLASH_H__
|
||||
|
||||
#include <devicetree.h>
|
||||
#include <mcuboot_config/mcuboot_config.h>
|
||||
|
||||
#if (MCUBOOT_IMAGE_NUMBER == 1)
|
||||
/*
|
||||
* NOTE: the definition below returns the same values for true/false on
|
||||
* purpose, to avoid having to mark x as non-used by all callers when
|
||||
* running in single image mode.
|
||||
*/
|
||||
#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? \
|
||||
FLASH_AREA_ID(image_0) : \
|
||||
FLASH_AREA_ID(image_0))
|
||||
#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? \
|
||||
FLASH_AREA_ID(image_1) : \
|
||||
FLASH_AREA_ID(image_1))
|
||||
#elif (MCUBOOT_IMAGE_NUMBER == 2)
|
||||
/* MCUBoot currently supports only up to 2 updateable firmware images.
|
||||
* If the number of the current image is greater than MCUBOOT_IMAGE_NUMBER - 1
|
||||
* then a dummy value will be assigned to the flash area macros.
|
||||
*/
|
||||
#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? \
|
||||
FLASH_AREA_ID(image_0) : \
|
||||
((x) == 1) ? \
|
||||
FLASH_AREA_ID(image_2) : \
|
||||
255)
|
||||
#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? \
|
||||
FLASH_AREA_ID(image_1) : \
|
||||
((x) == 1) ? \
|
||||
FLASH_AREA_ID(image_3) : \
|
||||
255)
|
||||
#else
|
||||
#error "Image slot and flash area mapping is not defined"
|
||||
#endif
|
||||
|
||||
#define FLASH_AREA_IMAGE_SCRATCH FLASH_AREA_ID(image_scratch)
|
||||
|
||||
#endif /* __SYSFLASH_H__ */
|
||||
390
bootloader/mcuboot/sim/mcuboot-sys/src/api.rs
Normal file
390
bootloader/mcuboot/sim/mcuboot-sys/src/api.rs
Normal file
@@ -0,0 +1,390 @@
|
||||
// Copyright (c) 2017-2021 Linaro LTD
|
||||
// Copyright (c) 2018-2019 JUUL Labs
|
||||
// Copyright (c) 2023 Arm Limited
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! HAL api for MyNewt applications
|
||||
|
||||
use crate::area::CAreaDesc;
|
||||
use log::{Level, log_enabled, warn};
|
||||
use simflash::{Result, Flash, FlashPtr};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::HashMap,
|
||||
mem,
|
||||
ptr,
|
||||
slice,
|
||||
};
|
||||
|
||||
/// A FlashMap maintain a table of [device_id -> Flash trait]
|
||||
pub type FlashMap = HashMap<u8, FlashPtr>;
|
||||
|
||||
pub struct FlashParamsStruct {
|
||||
align: u32,
|
||||
erased_val: u8,
|
||||
}
|
||||
|
||||
pub type FlashParams = HashMap<u8, FlashParamsStruct>;
|
||||
|
||||
/// The `boot_rsp` structure used by boot_go.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct BootRsp {
|
||||
pub br_hdr: *const ImageHeader,
|
||||
pub flash_dev_id: u8,
|
||||
pub image_off: u32,
|
||||
}
|
||||
|
||||
// TODO: Don't duplicate this image header declaration.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct ImageHeader {
|
||||
magic: u32,
|
||||
load_addr: u32,
|
||||
hdr_size: u16,
|
||||
protect_tlv_size: u16,
|
||||
img_size: u32,
|
||||
flags: u32,
|
||||
ver: ImageVersion,
|
||||
_pad2: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct ImageVersion {
|
||||
pub major: u8,
|
||||
pub minor: u8,
|
||||
pub revision: u16,
|
||||
pub build_num: u32,
|
||||
}
|
||||
|
||||
pub struct CAreaDescPtr {
|
||||
pub ptr: *const CAreaDesc,
|
||||
}
|
||||
|
||||
pub struct FlashContext {
|
||||
flash_map: FlashMap,
|
||||
flash_params: FlashParams,
|
||||
flash_areas: CAreaDescPtr,
|
||||
}
|
||||
|
||||
impl FlashContext {
|
||||
pub fn new() -> FlashContext {
|
||||
FlashContext {
|
||||
flash_map: HashMap::new(),
|
||||
flash_params: HashMap::new(),
|
||||
flash_areas: CAreaDescPtr{ptr: ptr::null()},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FlashContext {
|
||||
fn default() -> FlashContext {
|
||||
FlashContext {
|
||||
flash_map: HashMap::new(),
|
||||
flash_params: HashMap::new(),
|
||||
flash_areas: CAreaDescPtr{ptr: ptr::null()},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct CSimContext {
|
||||
pub flash_counter: libc::c_int,
|
||||
pub jumped: libc::c_int,
|
||||
pub c_asserts: u8,
|
||||
pub c_catch_asserts: u8,
|
||||
// NOTE: Always leave boot_jmpbuf declaration at the end; this should
|
||||
// store a "jmp_buf" which is arch specific and not defined by libc crate.
|
||||
// The size below is enough to store data on a x86_64 machine.
|
||||
pub boot_jmpbuf: [u64; 48],
|
||||
}
|
||||
|
||||
impl Default for CSimContext {
|
||||
fn default() -> Self {
|
||||
CSimContext {
|
||||
flash_counter: 0,
|
||||
jumped: 0,
|
||||
c_asserts: 0,
|
||||
c_catch_asserts: 0,
|
||||
boot_jmpbuf: [0; 48],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CSimContextPtr {
|
||||
pub ptr: *const CSimContext,
|
||||
}
|
||||
|
||||
impl CSimContextPtr {
|
||||
pub fn new() -> CSimContextPtr {
|
||||
CSimContextPtr {
|
||||
ptr: ptr::null(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CSimContextPtr {
|
||||
fn default() -> CSimContextPtr {
|
||||
CSimContextPtr {
|
||||
ptr: ptr::null(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This struct describes the RAM layout of the current device. It will be stashed, per test
|
||||
/// thread, and queried by the C code.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct BootsimRamInfo {
|
||||
pub start: u32,
|
||||
pub size: u32,
|
||||
pub base: usize,
|
||||
}
|
||||
|
||||
/// This struct stores the non-volatile security counter per image. It will be stored per test thread,
|
||||
/// and the C code will set / get the values here.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct NvCounterStorage {
|
||||
pub storage: Vec<u32>,
|
||||
}
|
||||
|
||||
impl NvCounterStorage {
|
||||
pub fn new() -> Self {
|
||||
let count = if cfg!(feature = "multiimage") {
|
||||
2
|
||||
} else {
|
||||
1
|
||||
};
|
||||
Self {
|
||||
storage: vec![0; count]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub static THREAD_CTX: RefCell<FlashContext> = RefCell::new(FlashContext::new());
|
||||
pub static SIM_CTX: RefCell<CSimContextPtr> = RefCell::new(CSimContextPtr::new());
|
||||
pub static RAM_CTX: RefCell<BootsimRamInfo> = RefCell::new(BootsimRamInfo::default());
|
||||
pub static NV_COUNTER_CTX: RefCell<NvCounterStorage> = RefCell::new(NvCounterStorage::new());
|
||||
}
|
||||
|
||||
/// Set the flash device to be used by the simulation. The pointer is unsafely stashed away.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This uses mem::transmute to stash a Rust pointer into a C value to
|
||||
/// retrieve later. It should be safe to use this.
|
||||
pub fn set_flash(dev_id: u8, dev: &mut dyn Flash) {
|
||||
THREAD_CTX.with(|ctx| {
|
||||
ctx.borrow_mut().flash_params.insert(dev_id, FlashParamsStruct {
|
||||
align: dev.align() as u32,
|
||||
erased_val: dev.erased_val(),
|
||||
});
|
||||
unsafe {
|
||||
let dev: &'static mut dyn Flash = mem::transmute(dev);
|
||||
ctx.borrow_mut().flash_map.insert(
|
||||
dev_id, FlashPtr{ptr: dev as *mut dyn Flash});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn clear_flash(dev_id: u8) {
|
||||
THREAD_CTX.with(|ctx| {
|
||||
ctx.borrow_mut().flash_map.remove(&dev_id);
|
||||
});
|
||||
}
|
||||
|
||||
// This isn't meant to call directly, but by a wrapper.
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_get_flash_areas() -> *const CAreaDesc {
|
||||
THREAD_CTX.with(|ctx| {
|
||||
ctx.borrow().flash_areas.ptr
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_set_flash_areas(areas: *const CAreaDesc) {
|
||||
THREAD_CTX.with(|ctx| {
|
||||
ctx.borrow_mut().flash_areas.ptr = areas;
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_reset_flash_areas() {
|
||||
THREAD_CTX.with(|ctx| {
|
||||
ctx.borrow_mut().flash_areas.ptr = ptr::null();
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_get_context() -> *const CSimContext {
|
||||
SIM_CTX.with(|ctx| {
|
||||
ctx.borrow().ptr
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_set_context(ptr: *const CSimContext) {
|
||||
SIM_CTX.with(|ctx| {
|
||||
ctx.borrow_mut().ptr = ptr;
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_reset_context() {
|
||||
SIM_CTX.with(|ctx| {
|
||||
ctx.borrow_mut().ptr = ptr::null();
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn bootsim_get_ram_info() -> *const BootsimRamInfo {
|
||||
RAM_CTX.with(|ctx| {
|
||||
if ctx.borrow().base == 0 {
|
||||
// Option is messier to get a pointer out of, so just check if the base has been set to
|
||||
// anything.
|
||||
panic!("ram info not set, but being used");
|
||||
}
|
||||
ctx.as_ptr()
|
||||
})
|
||||
}
|
||||
|
||||
/// Store a copy of this RAM info.
|
||||
pub fn set_ram_info(info: BootsimRamInfo) {
|
||||
RAM_CTX.with(|ctx| {
|
||||
ctx.replace(info);
|
||||
});
|
||||
}
|
||||
|
||||
/// Clear out the ram info.
|
||||
pub fn clear_ram_info() {
|
||||
RAM_CTX.with(|ctx| {
|
||||
ctx.borrow_mut().base = 0;
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_flash_erase(dev_id: u8, offset: u32, size: u32) -> libc::c_int {
|
||||
let mut rc: libc::c_int = -19;
|
||||
THREAD_CTX.with(|ctx| {
|
||||
if let Some(flash) = ctx.borrow().flash_map.get(&dev_id) {
|
||||
let dev = unsafe { &mut *(flash.ptr) };
|
||||
rc = map_err(dev.erase(offset as usize, size as usize));
|
||||
}
|
||||
});
|
||||
rc
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_flash_read(dev_id: u8, offset: u32, dest: *mut u8, size: u32) -> libc::c_int {
|
||||
let mut rc: libc::c_int = -19;
|
||||
THREAD_CTX.with(|ctx| {
|
||||
if let Some(flash) = ctx.borrow().flash_map.get(&dev_id) {
|
||||
let mut buf: &mut[u8] = unsafe { slice::from_raw_parts_mut(dest, size as usize) };
|
||||
let dev = unsafe { &mut *(flash.ptr) };
|
||||
rc = map_err(dev.read(offset as usize, &mut buf));
|
||||
}
|
||||
});
|
||||
rc
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_flash_write(dev_id: u8, offset: u32, src: *const u8, size: u32) -> libc::c_int {
|
||||
let mut rc: libc::c_int = -19;
|
||||
THREAD_CTX.with(|ctx| {
|
||||
if let Some(flash) = ctx.borrow().flash_map.get(&dev_id) {
|
||||
let buf: &[u8] = unsafe { slice::from_raw_parts(src, size as usize) };
|
||||
let dev = unsafe { &mut *(flash.ptr) };
|
||||
rc = map_err(dev.write(offset as usize, &buf));
|
||||
}
|
||||
});
|
||||
rc
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_flash_align(id: u8) -> u32 {
|
||||
THREAD_CTX.with(|ctx| {
|
||||
ctx.borrow().flash_params.get(&id).unwrap().align
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_flash_erased_val(id: u8) -> u8 {
|
||||
THREAD_CTX.with(|ctx| {
|
||||
ctx.borrow().flash_params.get(&id).unwrap().erased_val
|
||||
})
|
||||
}
|
||||
|
||||
fn map_err(err: Result<()>) -> libc::c_int {
|
||||
match err {
|
||||
Ok(()) => 0,
|
||||
Err(e) => {
|
||||
warn!("{}", e);
|
||||
-1
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Called by C code to determine if we should log at this level. Levels are defined in
|
||||
/// bootutil/bootutil_log.h. This makes the logging from the C code controlled by bootsim::api, so
|
||||
/// for example, it can be enabled with something like:
|
||||
/// RUST_LOG=bootsim::api=info cargo run --release runall
|
||||
/// or
|
||||
/// RUST_LOG=bootsim=info cargo run --release runall
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_log_enabled(level: libc::c_int) -> libc::c_int {
|
||||
let res = match level {
|
||||
1 => log_enabled!(Level::Error),
|
||||
2 => log_enabled!(Level::Warn),
|
||||
3 => log_enabled!(Level::Info),
|
||||
4 => log_enabled!(Level::Debug),
|
||||
5 => log_enabled!(Level::Trace), // log level == SIM
|
||||
_ => false,
|
||||
};
|
||||
if res {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_set_nv_counter_for_image(image_index: u32, security_counter_value: u32) -> libc::c_int {
|
||||
let mut rc = 0;
|
||||
NV_COUNTER_CTX.with(|ctx| {
|
||||
let mut counter_storage = ctx.borrow_mut();
|
||||
if image_index as usize >= counter_storage.storage.len() {
|
||||
rc = -1;
|
||||
return;
|
||||
}
|
||||
if counter_storage.storage[image_index as usize] > security_counter_value {
|
||||
rc = -2;
|
||||
warn!("Failed to set security counter value ({}) for image index {}", security_counter_value, image_index);
|
||||
return;
|
||||
}
|
||||
|
||||
counter_storage.storage[image_index as usize] = security_counter_value;
|
||||
});
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sim_get_nv_counter_for_image(image_index: u32, security_counter_value: *mut u32) -> libc::c_int {
|
||||
let mut rc = 0;
|
||||
NV_COUNTER_CTX.with(|ctx| {
|
||||
let counter_storage = ctx.borrow();
|
||||
if image_index as usize >= counter_storage.storage.len() {
|
||||
rc = -1;
|
||||
return;
|
||||
}
|
||||
unsafe { *security_counter_value = counter_storage.storage[image_index as usize] };
|
||||
|
||||
});
|
||||
return rc;
|
||||
}
|
||||
210
bootloader/mcuboot/sim/mcuboot-sys/src/area.rs
Normal file
210
bootloader/mcuboot/sim/mcuboot-sys/src/area.rs
Normal file
@@ -0,0 +1,210 @@
|
||||
// Copyright (c) 2017-2021 Linaro LTD
|
||||
// Copyright (c) 2018-2019 JUUL Labs
|
||||
// Copyright (c) 2019 Arm Limited
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Describe flash areas.
|
||||
|
||||
use simflash::{Flash, SimFlash, Sector};
|
||||
use std::ptr;
|
||||
use std::collections::HashMap;
|
||||
use std::borrow::BorrowMut;
|
||||
|
||||
/// Structure to build up the boot area table.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct AreaDesc {
|
||||
areas: Vec<Vec<FlashArea>>,
|
||||
whole: Vec<FlashArea>,
|
||||
sectors: HashMap<u8, Vec<Sector>>,
|
||||
}
|
||||
|
||||
impl AreaDesc {
|
||||
pub fn new() -> AreaDesc {
|
||||
AreaDesc {
|
||||
areas: vec![],
|
||||
whole: vec![],
|
||||
sectors: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_flash_sectors(&mut self, id: u8, flash: &SimFlash) {
|
||||
self.sectors.insert(id, flash.sector_iter().collect());
|
||||
}
|
||||
|
||||
/// Add a slot to the image. The slot must align with erasable units in the flash device.
|
||||
/// Panics if the description is not valid. There are also bootloader assumptions that the
|
||||
/// slots are PRIMARY_SLOT, SECONDARY_SLOT, and SCRATCH in that order.
|
||||
pub fn add_image(&mut self, base: usize, len: usize, id: FlashId, dev_id: u8) {
|
||||
let nid = id as usize;
|
||||
let orig_base = base;
|
||||
let orig_len = len;
|
||||
let mut base = base;
|
||||
let mut len = len;
|
||||
|
||||
while nid > self.areas.len() {
|
||||
self.areas.push(vec![]);
|
||||
self.whole.push(Default::default());
|
||||
}
|
||||
|
||||
if nid != self.areas.len() {
|
||||
panic!("Flash areas not added in order");
|
||||
}
|
||||
|
||||
let mut area = vec![];
|
||||
|
||||
for sector in &self.sectors[&dev_id] {
|
||||
if len == 0 {
|
||||
break;
|
||||
};
|
||||
if base > sector.base + sector.size - 1 {
|
||||
continue;
|
||||
}
|
||||
if sector.base != base {
|
||||
panic!("Image does not start on a sector boundary");
|
||||
}
|
||||
|
||||
area.push(FlashArea {
|
||||
flash_id: id,
|
||||
device_id: dev_id,
|
||||
pad16: 0,
|
||||
off: sector.base as u32,
|
||||
size: sector.size as u32,
|
||||
});
|
||||
|
||||
base += sector.size;
|
||||
len -= sector.size;
|
||||
}
|
||||
|
||||
if len != 0 {
|
||||
panic!("Image goes past end of device");
|
||||
}
|
||||
|
||||
self.areas.push(area);
|
||||
self.whole.push(FlashArea {
|
||||
flash_id: id,
|
||||
device_id: dev_id,
|
||||
pad16: 0,
|
||||
off: orig_base as u32,
|
||||
size: orig_len as u32,
|
||||
});
|
||||
}
|
||||
|
||||
// Add a simple slot to the image. This ignores the device layout, and just adds the area as a
|
||||
// single unit. It assumes that the image lines up with image boundaries. This tests
|
||||
// configurations where the partition table uses larger sectors than the underlying flash
|
||||
// device.
|
||||
pub fn add_simple_image(&mut self, base: usize, len: usize, id: FlashId, dev_id: u8) {
|
||||
let area = vec![FlashArea {
|
||||
flash_id: id,
|
||||
device_id: dev_id,
|
||||
pad16: 0,
|
||||
off: base as u32,
|
||||
size: len as u32,
|
||||
}];
|
||||
|
||||
self.areas.push(area);
|
||||
self.whole.push(FlashArea {
|
||||
flash_id: id,
|
||||
device_id: dev_id,
|
||||
pad16: 0,
|
||||
off: base as u32,
|
||||
size: len as u32,
|
||||
});
|
||||
}
|
||||
|
||||
// Look for the image with the given ID, and return its offset, size and
|
||||
// device id. Returns None if the area is not present.
|
||||
pub fn find(&self, id: FlashId) -> Option<(usize, usize, u8)> {
|
||||
for area in &self.whole {
|
||||
// FIXME: should we ensure id is not duplicated over multiple devices?
|
||||
if area.flash_id == id {
|
||||
return Some((area.off as usize, area.size as usize, area.device_id));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_c(&self) -> Box<CAreaDesc> {
|
||||
let mut areas_box: Box<CAreaDesc> = Box::new(Default::default());
|
||||
let areas: &mut CAreaDesc = areas_box.borrow_mut();
|
||||
|
||||
assert_eq!(self.areas.len(), self.whole.len());
|
||||
|
||||
for (i, area) in self.areas.iter().enumerate() {
|
||||
if !area.is_empty() {
|
||||
areas.slots[i].areas = &area[0];
|
||||
areas.slots[i].whole = self.whole[i].clone();
|
||||
areas.slots[i].num_areas = area.len() as u32;
|
||||
areas.slots[i].id = area[0].flash_id;
|
||||
}
|
||||
}
|
||||
|
||||
areas.num_slots = self.areas.len() as u32;
|
||||
|
||||
areas_box
|
||||
}
|
||||
|
||||
/// Return an iterator over all `FlashArea`s present.
|
||||
pub fn iter_areas(&self) -> impl Iterator<Item = &FlashArea> {
|
||||
self.whole.iter()
|
||||
}
|
||||
}
|
||||
|
||||
/// The area descriptor, C format.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CAreaDesc {
|
||||
slots: [CArea; 16],
|
||||
num_slots: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct CArea {
|
||||
whole: FlashArea,
|
||||
areas: *const FlashArea,
|
||||
num_areas: u32,
|
||||
// FIXME: is this not already available on whole/areas?
|
||||
id: FlashId,
|
||||
}
|
||||
|
||||
impl Default for CArea {
|
||||
fn default() -> CArea {
|
||||
CArea {
|
||||
areas: ptr::null(),
|
||||
whole: Default::default(),
|
||||
id: FlashId::BootLoader,
|
||||
num_areas: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Flash area map.
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[allow(dead_code)]
|
||||
pub enum FlashId {
|
||||
BootLoader = 0,
|
||||
Image0 = 1,
|
||||
Image1 = 2,
|
||||
ImageScratch = 3,
|
||||
Image2 = 4,
|
||||
Image3 = 5,
|
||||
}
|
||||
|
||||
impl Default for FlashId {
|
||||
fn default() -> FlashId {
|
||||
FlashId::BootLoader
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct FlashArea {
|
||||
pub flash_id: FlashId,
|
||||
pub device_id: u8,
|
||||
pad16: u16,
|
||||
pub off: u32,
|
||||
pub size: u32,
|
||||
}
|
||||
226
bootloader/mcuboot/sim/mcuboot-sys/src/c.rs
Normal file
226
bootloader/mcuboot/sim/mcuboot-sys/src/c.rs
Normal file
@@ -0,0 +1,226 @@
|
||||
// Copyright (c) 2017-2021 Linaro LTD
|
||||
// Copyright (c) 2017-2019 JUUL Labs
|
||||
// Copyright (c) 2019-2023 Arm Limited
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Interface wrappers to C API entering to the bootloader
|
||||
|
||||
use crate::area::AreaDesc;
|
||||
use simflash::SimMultiFlash;
|
||||
use crate::api;
|
||||
|
||||
#[allow(unused)]
|
||||
use std::sync::Once;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
|
||||
/// The result of an invocation of `boot_go`. This is intentionally opaque so that we can provide
|
||||
/// accessors for everything we need from this.
|
||||
#[derive(Debug)]
|
||||
pub enum BootGoResult {
|
||||
/// This run was stopped by the flash simulation mechanism.
|
||||
Stopped,
|
||||
/// The bootloader ran to completion with the following data.
|
||||
Normal {
|
||||
result: i32,
|
||||
asserts: u8,
|
||||
|
||||
resp: api::BootRsp,
|
||||
},
|
||||
}
|
||||
|
||||
impl BootGoResult {
|
||||
/// Was this run interrupted.
|
||||
pub fn interrupted(&self) -> bool {
|
||||
matches!(self, BootGoResult::Stopped)
|
||||
}
|
||||
|
||||
/// Was this boot run successful (returned 0)
|
||||
pub fn success(&self) -> bool {
|
||||
matches!(self, BootGoResult::Normal { result: 0, .. })
|
||||
}
|
||||
|
||||
/// Success, but also no asserts.
|
||||
pub fn success_no_asserts(&self) -> bool {
|
||||
matches!(self, BootGoResult::Normal {
|
||||
result: 0,
|
||||
asserts: 0,
|
||||
..
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the asserts count. An interrupted run will be considered to have no asserts.
|
||||
pub fn asserts(&self) -> u8 {
|
||||
match self {
|
||||
BootGoResult::Normal { asserts, .. } => *asserts,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the 'resp' field that is filled in.
|
||||
pub fn resp(&self) -> Option<&api::BootRsp> {
|
||||
match self {
|
||||
BootGoResult::Normal { resp, .. } => Some(resp),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Invoke the bootloader on this flash device.
|
||||
pub fn boot_go(multiflash: &mut SimMultiFlash, areadesc: &AreaDesc,
|
||||
counter: Option<&mut i32>, image_index: Option<i32>,
|
||||
catch_asserts: bool) -> BootGoResult {
|
||||
init_crypto();
|
||||
|
||||
for (&dev_id, flash) in multiflash.iter_mut() {
|
||||
api::set_flash(dev_id, flash);
|
||||
}
|
||||
let mut sim_ctx = api::CSimContext {
|
||||
flash_counter: match counter {
|
||||
None => 0,
|
||||
Some(ref c) => **c as libc::c_int
|
||||
},
|
||||
c_catch_asserts: if catch_asserts { 1 } else { 0 },
|
||||
.. Default::default()
|
||||
};
|
||||
let mut rsp = api::BootRsp {
|
||||
br_hdr: std::ptr::null(),
|
||||
flash_dev_id: 0,
|
||||
image_off: 0,
|
||||
};
|
||||
let result: i32 = unsafe {
|
||||
let adesc = areadesc.get_c();
|
||||
match image_index {
|
||||
None => raw::invoke_boot_go(&mut sim_ctx as *mut _,
|
||||
adesc.borrow() as *const _,
|
||||
&mut rsp as *mut _, -1) as i32,
|
||||
Some(i) => raw::invoke_boot_go(&mut sim_ctx as *mut _,
|
||||
adesc.borrow() as *const _,
|
||||
&mut rsp as *mut _,
|
||||
i as i32) as i32
|
||||
}
|
||||
};
|
||||
let asserts = sim_ctx.c_asserts;
|
||||
if let Some(c) = counter {
|
||||
*c = sim_ctx.flash_counter;
|
||||
}
|
||||
for &dev_id in multiflash.keys() {
|
||||
api::clear_flash(dev_id);
|
||||
}
|
||||
if result == -0x13579 {
|
||||
BootGoResult::Stopped
|
||||
} else {
|
||||
BootGoResult::Normal { result, asserts, resp: rsp }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn boot_trailer_sz(align: u32) -> u32 {
|
||||
unsafe { raw::boot_trailer_sz(align) }
|
||||
}
|
||||
|
||||
pub fn boot_status_sz(align: u32) -> u32 {
|
||||
unsafe { raw::boot_status_sz(align) }
|
||||
}
|
||||
|
||||
pub fn boot_magic_sz() -> usize {
|
||||
unsafe { raw::boot_magic_sz() as usize }
|
||||
}
|
||||
|
||||
pub fn boot_max_align() -> usize {
|
||||
unsafe { raw::boot_max_align() as usize }
|
||||
}
|
||||
|
||||
pub fn rsa_oaep_encrypt(pubkey: &[u8], seckey: &[u8]) -> Result<[u8; 256], &'static str> {
|
||||
unsafe {
|
||||
let mut encbuf: [u8; 256] = [0; 256];
|
||||
if raw::rsa_oaep_encrypt_(pubkey.as_ptr(), pubkey.len() as u32,
|
||||
seckey.as_ptr(), seckey.len() as u32,
|
||||
encbuf.as_mut_ptr()) == 0 {
|
||||
return Ok(encbuf);
|
||||
}
|
||||
Err("Failed to encrypt buffer")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kw_encrypt(kek: &[u8], seckey: &[u8], keylen: u32) -> Result<Vec<u8>, &'static str> {
|
||||
unsafe {
|
||||
let mut encbuf = vec![0u8; 24];
|
||||
if keylen == 32 {
|
||||
encbuf = vec![0u8; 40];
|
||||
}
|
||||
if raw::kw_encrypt_(kek.as_ptr(), seckey.as_ptr(), encbuf.as_mut_ptr()) == 0 {
|
||||
return Ok(encbuf);
|
||||
}
|
||||
Err("Failed to encrypt buffer")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_security_counter(image_index: u32, security_counter_value: u32) {
|
||||
api::sim_set_nv_counter_for_image(image_index, security_counter_value);
|
||||
}
|
||||
|
||||
pub fn get_security_counter(image_index: u32) -> u32 {
|
||||
let mut counter_val: u32 = 0;
|
||||
api::sim_get_nv_counter_for_image(image_index, &mut counter_val as *mut u32);
|
||||
return counter_val;
|
||||
}
|
||||
|
||||
mod raw {
|
||||
use crate::area::CAreaDesc;
|
||||
use crate::api::{BootRsp, CSimContext};
|
||||
|
||||
extern "C" {
|
||||
// This generates a warning about `CAreaDesc` not being foreign safe. There doesn't appear to
|
||||
// be any way to get rid of this warning. See https://github.com/rust-lang/rust/issues/34798
|
||||
// for information and tracking.
|
||||
pub fn invoke_boot_go(sim_ctx: *mut CSimContext, areadesc: *const CAreaDesc,
|
||||
rsp: *mut BootRsp, image_index: libc::c_int) -> libc::c_int;
|
||||
|
||||
pub fn boot_trailer_sz(min_write_sz: u32) -> u32;
|
||||
pub fn boot_status_sz(min_write_sz: u32) -> u32;
|
||||
|
||||
pub fn boot_magic_sz() -> u32;
|
||||
pub fn boot_max_align() -> u32;
|
||||
|
||||
pub fn rsa_oaep_encrypt_(pubkey: *const u8, pubkey_len: libc::c_uint,
|
||||
seckey: *const u8, seckey_len: libc::c_uint,
|
||||
encbuf: *mut u8) -> libc::c_int;
|
||||
|
||||
pub fn kw_encrypt_(kek: *const u8, seckey: *const u8,
|
||||
encbuf: *mut u8) -> libc::c_int;
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn psa_crypto_init() -> u32;
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn mbedtls_test_enable_insecure_external_rng();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
static PSA_INIT_SYNC: Once = Once::new();
|
||||
|
||||
#[allow(unused)]
|
||||
static MBEDTLS_EXTERNAL_RNG_ENABLE_SYNC: Once = Once::new();
|
||||
|
||||
#[cfg(feature = "psa-crypto-api")]
|
||||
fn init_crypto() {
|
||||
PSA_INIT_SYNC.call_once(|| {
|
||||
assert_eq!(unsafe { raw::psa_crypto_init() }, 0);
|
||||
});
|
||||
|
||||
/* The PSA APIs require properly initialisation of the entropy subsystem
|
||||
* The configuration adds the option MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG when the
|
||||
* psa-crypto-api feature is enabled. As a result the tests use the implementation
|
||||
* of the test external rng that needs to be initialised before being able to use it
|
||||
*/
|
||||
MBEDTLS_EXTERNAL_RNG_ENABLE_SYNC.call_once(|| {
|
||||
unsafe { raw::mbedtls_test_enable_insecure_external_rng() }
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "psa-crypto-api"))]
|
||||
fn init_crypto() {
|
||||
// When the feature is not enabled, the init is just empty
|
||||
}
|
||||
52
bootloader/mcuboot/sim/mcuboot-sys/src/lib.rs
Normal file
52
bootloader/mcuboot/sim/mcuboot-sys/src/lib.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2017-2019 Linaro LTD
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
mod area;
|
||||
pub mod c;
|
||||
|
||||
// The API needs to be public, even though it isn't intended to be called by Rust code, but the
|
||||
// functions are exported to C code.
|
||||
pub mod api;
|
||||
|
||||
pub use crate::area::{AreaDesc, FlashId};
|
||||
|
||||
/// For testing the ram load feature, we need to emulate a block of RAM and be able to pass that
|
||||
/// down to the C code. The call down to boot_go should go through this object so that the buffer
|
||||
/// itself is managed properly.
|
||||
pub struct RamBlock {
|
||||
ram: Vec<u8>,
|
||||
offset: u32, // 32-bit offset.
|
||||
}
|
||||
|
||||
impl RamBlock {
|
||||
pub fn new(size: u32, offset: u32) -> RamBlock {
|
||||
RamBlock {
|
||||
ram: vec![0; size as usize],
|
||||
offset: offset,
|
||||
}
|
||||
}
|
||||
|
||||
/// Borrow the RAM buffer, with 'offset' being the beginning of the buffer.
|
||||
pub fn borrow(&self) -> &[u8] {
|
||||
&self.ram
|
||||
}
|
||||
|
||||
/// Borrow a piece of the ram, with 'offset' being the beginning of the buffer.
|
||||
pub fn borrow_part(&self, base: usize, size: usize) -> &[u8] {
|
||||
&self.ram[base..base+size]
|
||||
}
|
||||
|
||||
pub fn invoke<F, R>(&self, act: F) -> R
|
||||
where F: FnOnce() -> R
|
||||
{
|
||||
api::set_ram_info(api::BootsimRamInfo {
|
||||
start: self.offset,
|
||||
size: self.ram.len() as u32,
|
||||
base: &self.ram[0] as *const u8 as usize - self.offset as usize,
|
||||
});
|
||||
let result = act();
|
||||
api::clear_ram_info();
|
||||
result
|
||||
}
|
||||
}
|
||||
1
bootloader/mcuboot/sim/simflash/.gitignore
vendored
Normal file
1
bootloader/mcuboot/sim/simflash/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Cargo.lock
|
||||
10
bootloader/mcuboot/sim/simflash/Cargo.toml
Normal file
10
bootloader/mcuboot/sim/simflash/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "simflash"
|
||||
version = "0.1.0"
|
||||
authors = ["David Brown <david.brown@linaro.org>"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8"
|
||||
log = "0.4"
|
||||
thiserror = "1.0"
|
||||
377
bootloader/mcuboot/sim/simflash/src/lib.rs
Normal file
377
bootloader/mcuboot/sim/simflash/src/lib.rs
Normal file
@@ -0,0 +1,377 @@
|
||||
// Copyright (c) 2017-2021 Linaro LTD
|
||||
// Copyright (c) 2017-2018 JUUL Labs
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! A flash simulator
|
||||
//!
|
||||
//! This module is capable of simulating the type of NOR flash commonly used in microcontrollers.
|
||||
//! These generally can be written as individual bytes, but must be erased in larger units.
|
||||
|
||||
mod pdump;
|
||||
|
||||
use crate::pdump::HexDump;
|
||||
use log::info;
|
||||
use rand::{
|
||||
self,
|
||||
distributions::Standard,
|
||||
Rng,
|
||||
};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fs::File,
|
||||
io::{self, Write},
|
||||
iter::Enumerate,
|
||||
path::Path,
|
||||
slice,
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, FlashError>;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum FlashError {
|
||||
#[error("Offset out of bounds: {0}")]
|
||||
OutOfBounds(String),
|
||||
#[error("Invalid write: {0}")]
|
||||
Write(String),
|
||||
#[error("Write failed by chance: {0}")]
|
||||
SimulatedFail(String),
|
||||
#[error("{0}")]
|
||||
Io(#[from] io::Error),
|
||||
}
|
||||
|
||||
// Transition from error-chain.
|
||||
macro_rules! bail {
|
||||
($item:expr) => (return Err($item.into());)
|
||||
}
|
||||
|
||||
pub struct FlashPtr {
|
||||
pub ptr: *mut dyn Flash,
|
||||
}
|
||||
unsafe impl Send for FlashPtr {}
|
||||
|
||||
pub trait Flash {
|
||||
fn erase(&mut self, offset: usize, len: usize) -> Result<()>;
|
||||
fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()>;
|
||||
fn read(&self, offset: usize, data: &mut [u8]) -> Result<()>;
|
||||
|
||||
fn add_bad_region(&mut self, offset: usize, len: usize, rate: f32) -> Result<()>;
|
||||
fn reset_bad_regions(&mut self);
|
||||
|
||||
fn set_verify_writes(&mut self, enable: bool);
|
||||
|
||||
fn sector_iter(&self) -> SectorIter<'_>;
|
||||
fn device_size(&self) -> usize;
|
||||
|
||||
fn align(&self) -> usize;
|
||||
fn erased_val(&self) -> u8;
|
||||
}
|
||||
|
||||
fn ebounds<T: AsRef<str>>(message: T) -> FlashError {
|
||||
FlashError::OutOfBounds(message.as_ref().to_owned())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn ewrite<T: AsRef<str>>(message: T) -> FlashError {
|
||||
FlashError::Write(message.as_ref().to_owned())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn esimulatedwrite<T: AsRef<str>>(message: T) -> FlashError {
|
||||
FlashError::SimulatedFail(message.as_ref().to_owned())
|
||||
}
|
||||
|
||||
/// An emulated flash device. It is represented as a block of bytes, and a list of the sector
|
||||
/// mappings.
|
||||
#[derive(Clone)]
|
||||
pub struct SimFlash {
|
||||
data: Vec<u8>,
|
||||
write_safe: Vec<bool>,
|
||||
sectors: Vec<usize>,
|
||||
bad_region: Vec<(usize, usize, f32)>,
|
||||
// Alignment required for writes.
|
||||
align: usize,
|
||||
verify_writes: bool,
|
||||
erased_val: u8,
|
||||
}
|
||||
|
||||
impl SimFlash {
|
||||
/// Given a sector size map, construct a flash device for that.
|
||||
pub fn new(sectors: Vec<usize>, align: usize, erased_val: u8) -> SimFlash {
|
||||
// Verify that the alignment is a positive power of two.
|
||||
assert!(align > 0);
|
||||
assert!(align & (align - 1) == 0);
|
||||
|
||||
let total = sectors.iter().sum();
|
||||
SimFlash {
|
||||
data: vec![erased_val; total],
|
||||
write_safe: vec![true; total],
|
||||
sectors,
|
||||
bad_region: Vec::new(),
|
||||
align,
|
||||
verify_writes: true,
|
||||
erased_val,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn dump(&self) {
|
||||
self.data.dump();
|
||||
}
|
||||
|
||||
/// Dump this image to the given file.
|
||||
#[allow(dead_code)]
|
||||
pub fn write_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
|
||||
let mut fd = File::create(path)?;
|
||||
fd.write_all(&self.data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Scan the sector map, and return the base and offset within a sector for this given byte.
|
||||
// Returns None if the value is outside of the device.
|
||||
fn get_sector(&self, offset: usize) -> Option<(usize, usize)> {
|
||||
let mut offset = offset;
|
||||
for (sector, &size) in self.sectors.iter().enumerate() {
|
||||
if offset < size {
|
||||
return Some((sector, offset));
|
||||
}
|
||||
offset -= size;
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub type SimMultiFlash = HashMap<u8, SimFlash>;
|
||||
|
||||
impl Flash for SimFlash {
|
||||
/// The flash drivers tend to erase beyond the bounds of the given range. Instead, we'll be
|
||||
/// strict, and make sure that the passed arguments are exactly at a sector boundary, otherwise
|
||||
/// return an error.
|
||||
fn erase(&mut self, offset: usize, len: usize) -> Result<()> {
|
||||
let (_start, slen) = self.get_sector(offset).ok_or_else(|| ebounds("start"))?;
|
||||
let (end, elen) = self.get_sector(offset + len - 1).ok_or_else(|| ebounds("end"))?;
|
||||
|
||||
if slen != 0 {
|
||||
bail!(ebounds("offset not at start of sector"));
|
||||
}
|
||||
if elen != self.sectors[end] - 1 {
|
||||
bail!(ebounds("end not at start of sector"));
|
||||
}
|
||||
|
||||
for x in &mut self.data[offset .. offset + len] {
|
||||
*x = self.erased_val;
|
||||
}
|
||||
|
||||
for x in &mut self.write_safe[offset .. offset + len] {
|
||||
*x = true;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// We restrict to only allowing writes of values that are:
|
||||
///
|
||||
/// 1. being written to for the first time
|
||||
/// 2. being written to after being erased
|
||||
///
|
||||
/// This emulates a flash device which starts out erased, with the
|
||||
/// added restriction that repeated writes to the same location
|
||||
/// are disallowed, even if they would be safe to do.
|
||||
fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()> {
|
||||
for &(off, len, rate) in &self.bad_region {
|
||||
if offset >= off && (offset + payload.len()) <= (off + len) {
|
||||
let mut rng = rand::thread_rng();
|
||||
let samp: f32 = rng.sample(Standard);
|
||||
if samp < rate {
|
||||
bail!(esimulatedwrite(
|
||||
format!("Ignoring write to {:#x}-{:#x}", off, off + len)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if offset + payload.len() > self.data.len() {
|
||||
panic!("Write outside of device");
|
||||
}
|
||||
|
||||
// Verify the alignment (which must be a power of two).
|
||||
if offset & (self.align - 1) != 0 {
|
||||
panic!("Misaligned write address");
|
||||
}
|
||||
|
||||
if payload.len() & (self.align - 1) != 0 {
|
||||
panic!("Write length not multiple of alignment");
|
||||
}
|
||||
|
||||
for (i, x) in &mut self.write_safe[offset .. offset + payload.len()].iter_mut().enumerate() {
|
||||
if self.verify_writes && !(*x) {
|
||||
panic!("Write to unerased location at 0x{:x}", offset + i);
|
||||
}
|
||||
*x = false;
|
||||
}
|
||||
|
||||
let sub = &mut self.data[offset .. offset + payload.len()];
|
||||
sub.copy_from_slice(payload);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Read is simple.
|
||||
fn read(&self, offset: usize, data: &mut [u8]) -> Result<()> {
|
||||
if offset + data.len() > self.data.len() {
|
||||
bail!(ebounds("Read outside of device"));
|
||||
}
|
||||
|
||||
let sub = &self.data[offset .. offset + data.len()];
|
||||
data.copy_from_slice(sub);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds a new flash bad region. Writes to this area fail with a chance
|
||||
/// given by `rate`.
|
||||
fn add_bad_region(&mut self, offset: usize, len: usize, rate: f32) -> Result<()> {
|
||||
if !(0.0..=1.0).contains(&rate) {
|
||||
bail!(ebounds("Invalid rate"));
|
||||
}
|
||||
|
||||
info!("Adding new bad region {:#x}-{:#x}", offset, offset + len);
|
||||
self.bad_region.push((offset, len, rate));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset_bad_regions(&mut self) {
|
||||
self.bad_region.clear();
|
||||
}
|
||||
|
||||
fn set_verify_writes(&mut self, enable: bool) {
|
||||
self.verify_writes = enable;
|
||||
}
|
||||
|
||||
/// An iterator over each sector in the device.
|
||||
fn sector_iter(&self) -> SectorIter<'_> {
|
||||
SectorIter {
|
||||
iter: self.sectors.iter().enumerate(),
|
||||
base: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn device_size(&self) -> usize {
|
||||
self.data.len()
|
||||
}
|
||||
|
||||
fn align(&self) -> usize {
|
||||
self.align
|
||||
}
|
||||
|
||||
fn erased_val(&self) -> u8 {
|
||||
self.erased_val
|
||||
}
|
||||
}
|
||||
|
||||
/// It is possible to iterate over the sectors in the device, each element returning this.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Sector {
|
||||
/// Which sector is this, starting from 0.
|
||||
pub num: usize,
|
||||
/// The offset, in bytes, of the start of this sector.
|
||||
pub base: usize,
|
||||
/// The length, in bytes, of this sector.
|
||||
pub size: usize,
|
||||
}
|
||||
|
||||
pub struct SectorIter<'a> {
|
||||
iter: Enumerate<slice::Iter<'a, usize>>,
|
||||
base: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for SectorIter<'a> {
|
||||
type Item = Sector;
|
||||
|
||||
fn next(&mut self) -> Option<Sector> {
|
||||
match self.iter.next() {
|
||||
None => None,
|
||||
Some((num, &size)) => {
|
||||
let base = self.base;
|
||||
self.base += size;
|
||||
Some(Sector {
|
||||
num,
|
||||
base,
|
||||
size,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Flash, FlashError, SimFlash, Result, Sector};
|
||||
|
||||
#[test]
|
||||
fn test_flash() {
|
||||
for &erased_val in &[0, 0xff] {
|
||||
// NXP-style, uniform sectors.
|
||||
let mut f1 = SimFlash::new(vec![4096usize; 256], 1, erased_val);
|
||||
test_device(&mut f1, erased_val);
|
||||
|
||||
// STM style, non-uniform sectors.
|
||||
let mut f2 = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
|
||||
128 * 1024, 128 * 1024, 128 * 1024], 1, erased_val);
|
||||
test_device(&mut f2, erased_val);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_device(flash: &mut dyn Flash, erased_val: u8) {
|
||||
let sectors: Vec<Sector> = flash.sector_iter().collect();
|
||||
|
||||
flash.erase(0, sectors[0].size).unwrap();
|
||||
let flash_size = flash.device_size();
|
||||
flash.erase(0, flash_size).unwrap();
|
||||
assert!(flash.erase(0, sectors[0].size - 1).is_bounds());
|
||||
|
||||
// Verify that write and erase do something.
|
||||
flash.write(0, &[0x55]).unwrap();
|
||||
let mut buf = [0xAA; 4];
|
||||
flash.read(0, &mut buf).unwrap();
|
||||
assert_eq!(buf, [0x55, erased_val, erased_val, erased_val]);
|
||||
|
||||
flash.erase(0, sectors[0].size).unwrap();
|
||||
flash.read(0, &mut buf).unwrap();
|
||||
assert_eq!(buf, [erased_val; 4]);
|
||||
|
||||
// Program the first and last byte of each sector, verify that has been done, and then
|
||||
// erase to verify the erase boundaries.
|
||||
for sector in §ors {
|
||||
let byte = [(sector.num & 127) as u8];
|
||||
flash.write(sector.base, &byte).unwrap();
|
||||
flash.write(sector.base + sector.size - 1, &byte).unwrap();
|
||||
}
|
||||
|
||||
// Verify the above
|
||||
let mut buf = Vec::new();
|
||||
for sector in §ors {
|
||||
let byte = (sector.num & 127) as u8;
|
||||
buf.resize(sector.size, 0);
|
||||
flash.read(sector.base, &mut buf).unwrap();
|
||||
assert_eq!(buf.first(), Some(&byte));
|
||||
assert_eq!(buf.last(), Some(&byte));
|
||||
assert!(buf[1..buf.len()-1].iter().all(|&x| x == erased_val));
|
||||
}
|
||||
}
|
||||
|
||||
// Helper checks for the result type.
|
||||
trait EChecker {
|
||||
fn is_bounds(&self) -> bool;
|
||||
}
|
||||
|
||||
impl<T> EChecker for Result<T> {
|
||||
|
||||
fn is_bounds(&self) -> bool {
|
||||
match *self {
|
||||
Err(FlashError::OutOfBounds(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
80
bootloader/mcuboot/sim/simflash/src/pdump.rs
Normal file
80
bootloader/mcuboot/sim/simflash/src/pdump.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2017,2021 Linaro LTD
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Printable hexdump.
|
||||
|
||||
pub trait HexDump {
|
||||
// Output the data value in hex.
|
||||
fn dump(&self);
|
||||
}
|
||||
|
||||
struct Dumper {
|
||||
hex: String,
|
||||
ascii: String,
|
||||
count: usize,
|
||||
total_count: usize,
|
||||
}
|
||||
|
||||
impl Dumper {
|
||||
fn new() -> Dumper {
|
||||
Dumper {
|
||||
hex: String::with_capacity(49),
|
||||
ascii: String::with_capacity(16),
|
||||
count: 0,
|
||||
total_count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_byte(&mut self, ch: u8) {
|
||||
if self.count == 16 {
|
||||
self.ship();
|
||||
}
|
||||
if self.count == 8 {
|
||||
self.hex.push(' ');
|
||||
}
|
||||
self.hex.push_str(&format!(" {:02x}", ch)[..]);
|
||||
self.ascii.push(if (b' '..=b'~').contains(&ch) {
|
||||
ch as char
|
||||
} else {
|
||||
'.'
|
||||
});
|
||||
self.count += 1;
|
||||
}
|
||||
|
||||
fn ship(&mut self) {
|
||||
if self.count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{:06x} {:-49} |{}|", self.total_count, self.hex, self.ascii);
|
||||
|
||||
self.hex.clear();
|
||||
self.ascii.clear();
|
||||
self.total_count += 16;
|
||||
self.count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> HexDump for &'a [u8] {
|
||||
fn dump(&self) {
|
||||
let mut dump = Dumper::new();
|
||||
for ch in self.iter() {
|
||||
dump.add_byte(*ch);
|
||||
}
|
||||
dump.ship();
|
||||
}
|
||||
}
|
||||
|
||||
impl HexDump for Vec<u8> {
|
||||
fn dump(&self) {
|
||||
(&self[..]).dump()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn samples() {
|
||||
"Hello".as_bytes().dump();
|
||||
"This is a much longer string".as_bytes().dump();
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f".as_bytes().dump();
|
||||
}
|
||||
62
bootloader/mcuboot/sim/src/caps.rs
Normal file
62
bootloader/mcuboot/sim/src/caps.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2017-2021 Linaro LTD
|
||||
// Copyright (c) 2019 JUUL Labs
|
||||
// Copyright (c) 2019-2023 Arm Limited
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Query the bootloader's capabilities.
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[allow(unused)]
|
||||
pub enum Caps {
|
||||
RSA2048 = (1 << 0),
|
||||
/* reserved (1 << 1) */
|
||||
EcdsaP256 = (1 << 2),
|
||||
SwapUsingScratch = (1 << 3),
|
||||
OverwriteUpgrade = (1 << 4),
|
||||
EncRsa = (1 << 5),
|
||||
EncKw = (1 << 6),
|
||||
ValidatePrimarySlot = (1 << 7),
|
||||
RSA3072 = (1 << 8),
|
||||
Ed25519 = (1 << 9),
|
||||
EncEc256 = (1 << 10),
|
||||
SwapUsingMove = (1 << 11),
|
||||
DowngradePrevention = (1 << 12),
|
||||
EncX25519 = (1 << 13),
|
||||
Bootstrap = (1 << 14),
|
||||
Aes256 = (1 << 15),
|
||||
RamLoad = (1 << 16),
|
||||
DirectXip = (1 << 17),
|
||||
HwRollbackProtection = (1 << 18),
|
||||
EcdsaP384 = (1 << 19),
|
||||
}
|
||||
|
||||
impl Caps {
|
||||
pub fn present(self) -> bool {
|
||||
let caps = unsafe { bootutil_get_caps() };
|
||||
(caps as u32) & (self as u32) != 0
|
||||
}
|
||||
|
||||
/// Does this build have ECDSA of some type enabled for signatures.
|
||||
pub fn has_ecdsa() -> bool {
|
||||
Caps::EcdsaP256.present() || Caps::EcdsaP384.present()
|
||||
}
|
||||
|
||||
/// Query for the number of images that have been configured into this
|
||||
/// MCUboot build.
|
||||
pub fn get_num_images() -> usize {
|
||||
(unsafe { bootutil_get_num_images() }) as usize
|
||||
}
|
||||
|
||||
/// Query if this configuration performs some kind of upgrade by writing to flash.
|
||||
pub fn modifies_flash() -> bool {
|
||||
// All other configurations perform upgrades by writing to flash.
|
||||
!(Self::RamLoad.present() || Self::DirectXip.present())
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn bootutil_get_caps() -> Caps;
|
||||
fn bootutil_get_num_images() -> u32;
|
||||
}
|
||||
187
bootloader/mcuboot/sim/src/depends.rs
Normal file
187
bootloader/mcuboot/sim/src/depends.rs
Normal file
@@ -0,0 +1,187 @@
|
||||
// Copyright (c) 2019-2021 Linaro LTD
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Support and tests related to the dependency management for multi-image
|
||||
//! support.
|
||||
|
||||
use crate::image::ImageVersion;
|
||||
|
||||
pub trait Depender {
|
||||
/// Generate a version for this particular image. The slot indicates
|
||||
/// which slot this is being put in.
|
||||
fn my_version(&self, offset: usize, slot: usize) -> ImageVersion;
|
||||
|
||||
/// Return dependencies for this image/slot combination.
|
||||
fn my_deps(&self, offset: usize, slot: usize) -> Vec<ImageVersion>;
|
||||
|
||||
/// Return the image ID of the other version.
|
||||
fn other_id(&self) -> u8;
|
||||
}
|
||||
|
||||
/// A boring image is used when we aren't testing dependencies. There will
|
||||
/// be meaningful version numbers. The size field is the image number we
|
||||
/// are.
|
||||
pub struct BoringDep {
|
||||
number: usize,
|
||||
test: DepTest,
|
||||
}
|
||||
|
||||
impl BoringDep {
|
||||
pub fn new(number: usize, test: &DepTest) -> BoringDep {
|
||||
BoringDep {
|
||||
number,
|
||||
test: test.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Depender for BoringDep {
|
||||
fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
|
||||
let slot = if self.test.downgrade {
|
||||
1 - slot
|
||||
} else {
|
||||
slot
|
||||
};
|
||||
ImageVersion::new_synthetic(self.number as u8, slot as u8, 0)
|
||||
}
|
||||
|
||||
fn my_deps(&self, _offset: usize, _slot: usize) -> Vec<ImageVersion> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn other_id(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// An individual test of the dependency mechanism describes one of the
|
||||
/// possibilities for the dependency information for each image, and what
|
||||
/// the expected outcome is.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DepTest {
|
||||
/// What kinds of dependency should be installed in the image.
|
||||
pub depends: [DepType; 2],
|
||||
|
||||
/// What is the expected outcome of the upgrade.
|
||||
pub upgrades: [UpgradeInfo; 2],
|
||||
|
||||
/// Should this be considered a downgrade (cause the version number to
|
||||
/// decrease).
|
||||
pub downgrade: bool,
|
||||
}
|
||||
|
||||
/// Describes the various types of dependency information that can be
|
||||
/// provided.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum DepType {
|
||||
/// Do not include dependency information
|
||||
Nothing,
|
||||
/// Provide dependency information that matches the other image.
|
||||
Correct,
|
||||
/// Provide a dependency that matches the old version of the other
|
||||
/// image.
|
||||
OldCorrect,
|
||||
/// Provide dependency information describing something newer than the
|
||||
/// other image.
|
||||
Newer,
|
||||
/// Don't provide an upgrade image at all for this image
|
||||
NoUpgrade,
|
||||
}
|
||||
|
||||
/// Describes what our expectation is for an upgrade.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum UpgradeInfo {
|
||||
/// The current version should be held.
|
||||
Held,
|
||||
/// The image should be upgraded
|
||||
Upgraded,
|
||||
}
|
||||
|
||||
/// A "test" that gives no dependency information.
|
||||
pub static NO_DEPS: DepTest = DepTest {
|
||||
depends: [DepType::Nothing, DepType::Nothing],
|
||||
upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Upgraded],
|
||||
downgrade: false,
|
||||
};
|
||||
|
||||
/// A "test" with no dependency information, and the images marked as a
|
||||
/// downgrade.
|
||||
pub static REV_DEPS: DepTest = DepTest {
|
||||
depends: [DepType::Nothing, DepType::Nothing],
|
||||
upgrades: [UpgradeInfo::Held, UpgradeInfo::Held],
|
||||
downgrade: true,
|
||||
};
|
||||
|
||||
/// A PairDep describes the dependencies between two pairs.
|
||||
pub struct PairDep {
|
||||
/// The image number of this image.
|
||||
number: usize,
|
||||
|
||||
test: DepTest,
|
||||
}
|
||||
|
||||
impl PairDep {
|
||||
pub fn new(total_image: usize, my_image: usize, deps: &DepTest) -> PairDep {
|
||||
if total_image != 2 {
|
||||
panic!("PairDep only works when there are two images");
|
||||
}
|
||||
|
||||
PairDep {
|
||||
number: my_image,
|
||||
test: deps.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Depender for PairDep {
|
||||
fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
|
||||
let slot = if self.test.downgrade {
|
||||
1 - slot
|
||||
} else {
|
||||
slot
|
||||
};
|
||||
ImageVersion::new_synthetic(self.number as u8, slot as u8, 0)
|
||||
}
|
||||
|
||||
fn my_deps(&self, _offset: usize, slot: usize) -> Vec<ImageVersion> {
|
||||
// For now, don't put any dependencies in slot zero. They could be
|
||||
// added here if we someday implement checking these.
|
||||
if slot == 0 {
|
||||
vec![]
|
||||
} else {
|
||||
match self.test.depends[self.number] {
|
||||
DepType::Nothing => vec![],
|
||||
DepType::NoUpgrade => panic!("Shouldn't get to this point"),
|
||||
DepType::Correct => vec![
|
||||
ImageVersion::new_synthetic(self.other_id(), slot as u8, 0)
|
||||
],
|
||||
DepType::OldCorrect => vec![
|
||||
ImageVersion::new_synthetic(self.other_id(), 0, 0)
|
||||
],
|
||||
DepType::Newer => vec![
|
||||
ImageVersion::new_synthetic(self.other_id(), slot as u8, 1)
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn other_id(&self) -> u8 {
|
||||
(1 - self.number) as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl ImageVersion {
|
||||
/// Generate an image version based on some key information. The image
|
||||
/// number influences the major version number (by an arbitrary factor),
|
||||
/// and the slot affects the major number on the build_number. The minor
|
||||
/// number can also be given to force numbers to be different.
|
||||
fn new_synthetic(image_id: u8, slot: u8, minor: u8) -> ImageVersion {
|
||||
ImageVersion {
|
||||
major: image_id * 20 + slot,
|
||||
minor,
|
||||
revision: 1,
|
||||
build_num: slot as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
32
bootloader/mcuboot/sim/src/ecdsa_pub_key-rs.txt
Normal file
32
bootloader/mcuboot/sim/src/ecdsa_pub_key-rs.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
static ECDSA256_PUB_KEY: &[u8] = &[
|
||||
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
|
||||
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
|
||||
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
|
||||
0x42, 0x00, 0x04, 0x2a, 0xcb, 0x40, 0x3c, 0xe8,
|
||||
0xfe, 0xed, 0x5b, 0xa4, 0x49, 0x95, 0xa1, 0xa9,
|
||||
0x1d, 0xae, 0xe8, 0xdb, 0xbe, 0x19, 0x37, 0xcd,
|
||||
0x14, 0xfb, 0x2f, 0x24, 0x57, 0x37, 0xe5, 0x95,
|
||||
0x39, 0x88, 0xd9, 0x94, 0xb9, 0xd6, 0x5a, 0xeb,
|
||||
0xd7, 0xcd, 0xd5, 0x30, 0x8a, 0xd6, 0xfe, 0x48,
|
||||
0xb2, 0x4a, 0x6a, 0x81, 0x0e, 0xe5, 0xf0, 0x7d,
|
||||
0x8b, 0x68, 0x34, 0xcc, 0x3a, 0x6a, 0xfc, 0x53,
|
||||
0x8e, 0xfa, 0xc1,
|
||||
];
|
||||
|
||||
static ECDSAP384_PUB_KEY: &[u8] = &[
|
||||
0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
|
||||
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b,
|
||||
0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04,
|
||||
0x0c, 0x76, 0xca, 0xae, 0x72, 0x3a, 0xa5, 0xe8,
|
||||
0xf0, 0xd4, 0xf1, 0x16, 0xb5, 0x02, 0xef, 0x77,
|
||||
0xa1, 0x1b, 0x93, 0x61, 0x78, 0xc0, 0x09, 0x26,
|
||||
0x7b, 0x3b, 0x40, 0x9c, 0xee, 0x49, 0x85, 0xe0,
|
||||
0xc9, 0x4f, 0xe7, 0xf2, 0xba, 0x97, 0x6c, 0xf3,
|
||||
0x82, 0x65, 0x14, 0x2c, 0xf5, 0x0c, 0x73, 0x33,
|
||||
0x4d, 0x32, 0xe7, 0x9b, 0xd3, 0x42, 0xcc, 0x95,
|
||||
0x5a, 0xe5, 0xe2, 0xf5, 0xf4, 0x6e, 0x45, 0xe0,
|
||||
0xed, 0x20, 0x35, 0x5c, 0xaf, 0x52, 0x35, 0x81,
|
||||
0xd4, 0xdc, 0x9c, 0xe3, 0x9e, 0x22, 0x3e, 0xfb,
|
||||
0x3f, 0x22, 0x10, 0xda, 0x70, 0x03, 0x37, 0xad,
|
||||
0xa8, 0xf2, 0x48, 0xfe, 0x3a, 0x60, 0x69, 0xa5,
|
||||
];
|
||||
8
bootloader/mcuboot/sim/src/ed25519_pub_key-rs.txt
Normal file
8
bootloader/mcuboot/sim/src/ed25519_pub_key-rs.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
static ED25519_PUB_KEY: &[u8] = &[
|
||||
0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
|
||||
0x70, 0x03, 0x21, 0x00, 0xd4, 0xb3, 0x1b, 0xa4,
|
||||
0x9a, 0x3a, 0xdd, 0x3f, 0x82, 0x5d, 0x10, 0xca,
|
||||
0x7f, 0x31, 0xb5, 0x0b, 0x0d, 0xe8, 0x7f, 0x37,
|
||||
0xcc, 0xc4, 0x9f, 0x1a, 0x40, 0x3a, 0x5c, 0x13,
|
||||
0x20, 0xff, 0xb4, 0xe0,
|
||||
];
|
||||
2332
bootloader/mcuboot/sim/src/image.rs
Normal file
2332
bootloader/mcuboot/sim/src/image.rs
Normal file
File diff suppressed because it is too large
Load Diff
231
bootloader/mcuboot/sim/src/lib.rs
Normal file
231
bootloader/mcuboot/sim/src/lib.rs
Normal file
@@ -0,0 +1,231 @@
|
||||
// Copyright (c) 2017-2019 Linaro LTD
|
||||
// Copyright (c) 2017-2019 JUUL Labs
|
||||
// Copyright (c) 2019-2023 Arm Limited
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use docopt::Docopt;
|
||||
use log::{warn, error};
|
||||
use std::{
|
||||
fmt,
|
||||
process,
|
||||
};
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
mod caps;
|
||||
mod depends;
|
||||
mod image;
|
||||
mod tlv;
|
||||
mod utils;
|
||||
pub mod testlog;
|
||||
|
||||
pub use crate::{
|
||||
depends::{
|
||||
DepTest,
|
||||
DepType,
|
||||
UpgradeInfo,
|
||||
NO_DEPS,
|
||||
REV_DEPS,
|
||||
},
|
||||
image::{
|
||||
ImagesBuilder,
|
||||
Images,
|
||||
ImageManipulation,
|
||||
show_sizes,
|
||||
},
|
||||
};
|
||||
|
||||
const USAGE: &str = "
|
||||
Mcuboot simulator
|
||||
|
||||
Usage:
|
||||
bootsim sizes
|
||||
bootsim run --device TYPE [--align SIZE]
|
||||
bootsim runall
|
||||
bootsim (--help | --version)
|
||||
|
||||
Options:
|
||||
-h, --help Show this message
|
||||
--version Version
|
||||
--device TYPE MCU to simulate
|
||||
Valid values: stm32f4, k64f
|
||||
--align SIZE Flash write alignment
|
||||
";
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Args {
|
||||
flag_device: Option<DeviceName>,
|
||||
flag_align: Option<AlignArg>,
|
||||
cmd_sizes: bool,
|
||||
cmd_run: bool,
|
||||
cmd_runall: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Deserialize)]
|
||||
pub enum DeviceName {
|
||||
Stm32f4, K64f, K64fBig, K64fMulti, Nrf52840, Nrf52840SpiFlash,
|
||||
Nrf52840UnequalSlots,
|
||||
}
|
||||
|
||||
pub static ALL_DEVICES: &[DeviceName] = &[
|
||||
DeviceName::Stm32f4,
|
||||
DeviceName::K64f,
|
||||
DeviceName::K64fBig,
|
||||
DeviceName::K64fMulti,
|
||||
DeviceName::Nrf52840,
|
||||
DeviceName::Nrf52840SpiFlash,
|
||||
DeviceName::Nrf52840UnequalSlots,
|
||||
];
|
||||
|
||||
impl fmt::Display for DeviceName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let name = match *self {
|
||||
DeviceName::Stm32f4 => "stm32f4",
|
||||
DeviceName::K64f => "k64f",
|
||||
DeviceName::K64fBig => "k64fbig",
|
||||
DeviceName::K64fMulti => "k64fmulti",
|
||||
DeviceName::Nrf52840 => "nrf52840",
|
||||
DeviceName::Nrf52840SpiFlash => "Nrf52840SpiFlash",
|
||||
DeviceName::Nrf52840UnequalSlots => "Nrf52840UnequalSlots",
|
||||
};
|
||||
f.write_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AlignArg(usize);
|
||||
|
||||
struct AlignArgVisitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for AlignArgVisitor {
|
||||
type Value = AlignArg;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("1, 2, 4 or 8")
|
||||
}
|
||||
|
||||
fn visit_u32<E>(self, n: u32) -> Result<Self::Value, E>
|
||||
where E: serde::de::Error
|
||||
{
|
||||
Ok(match n {
|
||||
1 | 2 | 4 | 8 => AlignArg(n as usize),
|
||||
n => {
|
||||
let err = format!("Could not deserialize '{}' as alignment", n);
|
||||
return Err(E::custom(err));
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::de::Deserialize<'de> for AlignArg {
|
||||
fn deserialize<D>(d: D) -> Result<AlignArg, D::Error>
|
||||
where D: serde::de::Deserializer<'de>
|
||||
{
|
||||
d.deserialize_u8(AlignArgVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let args: Args = Docopt::new(USAGE)
|
||||
.and_then(|d| d.deserialize())
|
||||
.unwrap_or_else(|e| e.exit());
|
||||
// println!("args: {:#?}", args);
|
||||
|
||||
if args.cmd_sizes {
|
||||
show_sizes();
|
||||
return;
|
||||
}
|
||||
|
||||
let mut status = RunStatus::new();
|
||||
if args.cmd_run {
|
||||
|
||||
let align = args.flag_align.map(|x| x.0).unwrap_or(1);
|
||||
|
||||
|
||||
let device = match args.flag_device {
|
||||
None => panic!("Missing mandatory device argument"),
|
||||
Some(dev) => dev,
|
||||
};
|
||||
|
||||
status.run_single(device, align, 0xff);
|
||||
}
|
||||
|
||||
if args.cmd_runall {
|
||||
for &dev in ALL_DEVICES {
|
||||
for &align in &[1, 2, 4, 8] {
|
||||
for &erased_val in &[0, 0xff] {
|
||||
status.run_single(dev, align, erased_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if status.failures > 0 {
|
||||
error!("{} Tests ran with {} failures", status.failures + status.passes, status.failures);
|
||||
process::exit(1);
|
||||
} else {
|
||||
error!("{} Tests ran successfully", status.passes);
|
||||
process::exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RunStatus {
|
||||
failures: usize,
|
||||
passes: usize,
|
||||
}
|
||||
|
||||
impl RunStatus {
|
||||
pub fn new() -> RunStatus {
|
||||
RunStatus {
|
||||
failures: 0,
|
||||
passes: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_single(&mut self, device: DeviceName, align: usize, erased_val: u8) {
|
||||
warn!("Running on device {} with alignment {}", device, align);
|
||||
|
||||
let run = match ImagesBuilder::new(device, align, erased_val) {
|
||||
Ok(builder) => builder,
|
||||
Err(msg) => {
|
||||
warn!("Skipping {}: {}", device, msg);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mut failed = false;
|
||||
|
||||
// Creates a badly signed image in the secondary slot to check that
|
||||
// it is not upgraded to
|
||||
let bad_secondary_slot_image = run.clone().make_bad_secondary_slot_image();
|
||||
|
||||
failed |= bad_secondary_slot_image.run_signfail_upgrade();
|
||||
|
||||
let images = run.clone().make_no_upgrade_image(&NO_DEPS, ImageManipulation::None);
|
||||
failed |= images.run_norevert_newimage();
|
||||
|
||||
let images = run.make_image(&NO_DEPS, true);
|
||||
|
||||
failed |= images.run_basic_revert();
|
||||
failed |= images.run_revert_with_fails();
|
||||
failed |= images.run_perm_with_fails();
|
||||
failed |= images.run_perm_with_random_fails(5);
|
||||
failed |= images.run_norevert();
|
||||
|
||||
failed |= images.run_with_status_fails_complete();
|
||||
failed |= images.run_with_status_fails_with_reset();
|
||||
|
||||
//show_flash(&flash);
|
||||
|
||||
if failed {
|
||||
self.failures += 1;
|
||||
} else {
|
||||
self.passes += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn failures(&self) -> usize {
|
||||
self.failures
|
||||
}
|
||||
}
|
||||
10
bootloader/mcuboot/sim/src/main.rs
Normal file
10
bootloader/mcuboot/sim/src/main.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) 2017-2019 Linaro LTD
|
||||
// Copyright (c) 2017-2019 JUUL Labs
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
bootsim::main();
|
||||
}
|
||||
53
bootloader/mcuboot/sim/src/rsa3072_pub_key-rs.txt
Normal file
53
bootloader/mcuboot/sim/src/rsa3072_pub_key-rs.txt
Normal file
@@ -0,0 +1,53 @@
|
||||
/* Autogenerated by imgtool.py, do not edit. */
|
||||
static RSA3072_PUB_KEY: &[u8] = &[
|
||||
0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, 0x81,
|
||||
0x00, 0xb4, 0x2c, 0x0e, 0x98, 0x58, 0x10, 0xa4,
|
||||
0xa7, 0x58, 0x99, 0x7c, 0x01, 0xdd, 0x08, 0x2a,
|
||||
0x28, 0x34, 0x33, 0xf8, 0x96, 0x1a, 0x34, 0x20,
|
||||
0x5d, 0x45, 0xc8, 0x71, 0x26, 0x25, 0xe5, 0xd2,
|
||||
0x96, 0xea, 0x7b, 0xb1, 0x15, 0xaa, 0xa6, 0x8a,
|
||||
0x63, 0x22, 0x8b, 0x2d, 0x4e, 0x81, 0x73, 0xbf,
|
||||
0x6e, 0x15, 0x68, 0x8c, 0x1a, 0xf4, 0xef, 0x2a,
|
||||
0x8f, 0x8c, 0x22, 0x9e, 0x71, 0x57, 0x4b, 0xde,
|
||||
0x0f, 0x7e, 0x72, 0xd3, 0x7a, 0xb8, 0xa7, 0x1d,
|
||||
0x44, 0xad, 0x87, 0x00, 0x83, 0x5c, 0xfd, 0x73,
|
||||
0x05, 0x72, 0x46, 0x3f, 0x8b, 0xf9, 0x10, 0x00,
|
||||
0xd8, 0x6e, 0xcc, 0x85, 0xed, 0xf9, 0x49, 0xdb,
|
||||
0x78, 0x36, 0x80, 0x49, 0x38, 0x76, 0xdd, 0x5f,
|
||||
0x54, 0x04, 0xda, 0x8c, 0x34, 0xa7, 0x2b, 0x13,
|
||||
0x25, 0x6f, 0xd1, 0x15, 0x4f, 0xad, 0xc2, 0xe1,
|
||||
0xa5, 0xd2, 0x4e, 0x57, 0x0c, 0x7e, 0x9c, 0x9b,
|
||||
0xba, 0x4e, 0x68, 0xb2, 0xe0, 0x25, 0x02, 0xaa,
|
||||
0x00, 0xd3, 0xb4, 0xcc, 0x2f, 0x78, 0xe5, 0xbe,
|
||||
0x47, 0x67, 0x1f, 0xc8, 0x6e, 0x22, 0x6c, 0x5e,
|
||||
0x61, 0xb6, 0x9a, 0xcd, 0xe5, 0xa8, 0xba, 0x7a,
|
||||
0x80, 0x13, 0x1b, 0x17, 0x2e, 0x96, 0xed, 0xcf,
|
||||
0xb3, 0x9b, 0xe4, 0x1c, 0xe8, 0xad, 0xa7, 0xf6,
|
||||
0x3a, 0x51, 0x66, 0x5e, 0x99, 0x8e, 0x87, 0xee,
|
||||
0x60, 0x25, 0xf8, 0x8d, 0xbe, 0xce, 0xa4, 0xa8,
|
||||
0xca, 0x93, 0x6c, 0xd7, 0xbf, 0xd4, 0x73, 0x33,
|
||||
0x8d, 0x44, 0x85, 0xcc, 0x73, 0x30, 0x08, 0x9c,
|
||||
0x4d, 0xb2, 0xaa, 0x5a, 0x6c, 0x6f, 0x7b, 0xab,
|
||||
0xb7, 0xb3, 0x7c, 0xc3, 0xfb, 0xe7, 0xca, 0xc4,
|
||||
0xf8, 0x9a, 0x6f, 0xcb, 0xbb, 0x5b, 0x82, 0xe7,
|
||||
0x7a, 0xe8, 0x19, 0xfd, 0x2f, 0x11, 0x22, 0xfb,
|
||||
0x7f, 0x76, 0x8c, 0x6b, 0x94, 0xa4, 0x09, 0x4f,
|
||||
0xa5, 0x6a, 0x77, 0x51, 0xeb, 0xa7, 0x7e, 0xda,
|
||||
0x87, 0x06, 0xee, 0xdc, 0xbe, 0xd1, 0xea, 0x1a,
|
||||
0x40, 0x1d, 0x1b, 0xff, 0x1a, 0xb1, 0x51, 0x7c,
|
||||
0x12, 0xb0, 0xf3, 0xf6, 0x83, 0x01, 0x9c, 0xe7,
|
||||
0x0c, 0x99, 0xbf, 0xac, 0x68, 0x58, 0x72, 0xa4,
|
||||
0xb0, 0x59, 0x85, 0xee, 0x85, 0xac, 0x2a, 0x22,
|
||||
0xf4, 0xcf, 0x15, 0x08, 0x80, 0x1f, 0x0d, 0xd0,
|
||||
0x1e, 0xa0, 0xa0, 0x94, 0xc8, 0xf7, 0xfa, 0x65,
|
||||
0xdd, 0x52, 0xe8, 0x96, 0x37, 0x23, 0x30, 0x57,
|
||||
0x36, 0xe6, 0x9d, 0xf4, 0x0c, 0x4a, 0x05, 0x75,
|
||||
0x1f, 0xad, 0x01, 0xca, 0xb7, 0x6d, 0x8c, 0x43,
|
||||
0x74, 0x06, 0x0a, 0x81, 0xf3, 0x01, 0x62, 0xff,
|
||||
0xf7, 0xf5, 0x5f, 0xaf, 0xe7, 0x2b, 0x0e, 0xf8,
|
||||
0x81, 0xb5, 0x65, 0xdd, 0x01, 0xd9, 0x9f, 0x07,
|
||||
0x17, 0x8a, 0x18, 0xcf, 0x23, 0x6e, 0x88, 0x65,
|
||||
0x91, 0xb5, 0x7b, 0xd3, 0xb0, 0x2d, 0xaf, 0x93,
|
||||
0x66, 0x63, 0x74, 0xac, 0x5a, 0xe6, 0x73, 0xde,
|
||||
0x3b, 0x02, 0x03, 0x01, 0x00, 0x01,
|
||||
];
|
||||
37
bootloader/mcuboot/sim/src/rsa_pub_key-rs.txt
Normal file
37
bootloader/mcuboot/sim/src/rsa_pub_key-rs.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
/* Autogenerated by imgtool.py, do not edit. */
|
||||
static RSA_PUB_KEY: &[u8] = &[
|
||||
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
|
||||
0x00, 0xd1, 0x06, 0x08, 0x1a, 0x18, 0x44, 0x2c,
|
||||
0x18, 0xe8, 0xfb, 0xfd, 0xf7, 0x0d, 0xa3, 0x4f,
|
||||
0x1f, 0xbb, 0xee, 0x5e, 0xf9, 0xaa, 0xd2, 0x4b,
|
||||
0x18, 0xd3, 0x5a, 0xe9, 0x6d, 0x18, 0x80, 0x19,
|
||||
0xf9, 0xf0, 0x9c, 0x34, 0x1b, 0xcb, 0xf3, 0xbc,
|
||||
0x74, 0xdb, 0x42, 0xe7, 0x8c, 0x7f, 0x10, 0x53,
|
||||
0x7e, 0x43, 0x5e, 0x0d, 0x57, 0x2c, 0x44, 0xd1,
|
||||
0x67, 0x08, 0x0f, 0x0d, 0xbb, 0x5c, 0xee, 0xec,
|
||||
0xb3, 0x99, 0xdf, 0xe0, 0x4d, 0x84, 0x0b, 0xaa,
|
||||
0x77, 0x41, 0x60, 0xed, 0x15, 0x28, 0x49, 0xa7,
|
||||
0x01, 0xb4, 0x3c, 0x10, 0xe6, 0x69, 0x8c, 0x2f,
|
||||
0x5f, 0xac, 0x41, 0x4d, 0x9e, 0x5c, 0x14, 0xdf,
|
||||
0xf2, 0xf8, 0xcf, 0x3d, 0x1e, 0x6f, 0xe7, 0x5b,
|
||||
0xba, 0xb4, 0xa9, 0xc8, 0x88, 0x7e, 0x47, 0x3c,
|
||||
0x94, 0xc3, 0x77, 0x67, 0x54, 0x4b, 0xaa, 0x8d,
|
||||
0x38, 0x35, 0xca, 0x62, 0x61, 0x7e, 0xb7, 0xe1,
|
||||
0x15, 0xdb, 0x77, 0x73, 0xd4, 0xbe, 0x7b, 0x72,
|
||||
0x21, 0x89, 0x69, 0x24, 0xfb, 0xf8, 0x65, 0x6e,
|
||||
0x64, 0x3e, 0xc8, 0x0e, 0xd7, 0x85, 0xd5, 0x5c,
|
||||
0x4a, 0xe4, 0x53, 0x0d, 0x2f, 0xff, 0xb7, 0xfd,
|
||||
0xf3, 0x13, 0x39, 0x83, 0x3f, 0xa3, 0xae, 0xd2,
|
||||
0x0f, 0xa7, 0x6a, 0x9d, 0xf9, 0xfe, 0xb8, 0xce,
|
||||
0xfa, 0x2a, 0xbe, 0xaf, 0xb8, 0xe0, 0xfa, 0x82,
|
||||
0x37, 0x54, 0xf4, 0x3e, 0xe1, 0x2b, 0xd0, 0xd3,
|
||||
0x08, 0x58, 0x18, 0xf6, 0x5e, 0x4c, 0xc8, 0x88,
|
||||
0x81, 0x31, 0xad, 0x5f, 0xb0, 0x82, 0x17, 0xf2,
|
||||
0x8a, 0x69, 0x27, 0x23, 0xf3, 0xab, 0x87, 0x3e,
|
||||
0x93, 0x1a, 0x1d, 0xfe, 0xe8, 0xf8, 0x1a, 0x24,
|
||||
0x66, 0x59, 0xf8, 0x1c, 0xab, 0xdc, 0xce, 0x68,
|
||||
0x1b, 0x66, 0x64, 0x35, 0xec, 0xfa, 0x0d, 0x11,
|
||||
0x9d, 0xaf, 0x5c, 0x3a, 0xa7, 0xd1, 0x67, 0xc6,
|
||||
0x47, 0xef, 0xb1, 0x4b, 0x2c, 0x62, 0xe1, 0xd1,
|
||||
0xc9, 0x02, 0x03, 0x01, 0x00, 0x01,
|
||||
];
|
||||
23
bootloader/mcuboot/sim/src/testlog.rs
Normal file
23
bootloader/mcuboot/sim/src/testlog.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2017 Linaro LTD
|
||||
// Copyright (c) 2019 JUUL Labs
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Logging support for the test framework.
|
||||
//!
|
||||
//! https://stackoverflow.com/questions/30177845/how-to-initialize-the-logger-for-integration-tests
|
||||
//!
|
||||
//! The test framework runs the tests, possibly simultaneously, and in various orders. This helper
|
||||
//! function, which should be called at the beginning of each test, will setup logging for all of
|
||||
//! the tests.
|
||||
|
||||
use std::sync::Once;
|
||||
|
||||
static INIT: Once = Once::new();
|
||||
|
||||
/// Setup the logging system. Intended to be called at the beginning of each test.
|
||||
pub fn setup() {
|
||||
INIT.call_once(|| {
|
||||
env_logger::init();
|
||||
});
|
||||
}
|
||||
841
bootloader/mcuboot/sim/src/tlv.rs
Normal file
841
bootloader/mcuboot/sim/src/tlv.rs
Normal file
@@ -0,0 +1,841 @@
|
||||
// Copyright (c) 2017-2021 Linaro LTD
|
||||
// Copyright (c) 2017-2020 JUUL Labs
|
||||
// Copyright (c) 2021-2023 Arm Limited
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! TLV Support
|
||||
//!
|
||||
//! mcuboot images are followed immediately by a list of TLV items that contain integrity
|
||||
//! information about the image. Their generation is made a little complicated because the size of
|
||||
//! the TLV block is in the image header, which is included in the hash. Since some signatures can
|
||||
//! vary in size, we just make them the largest size possible.
|
||||
//!
|
||||
//! Because of this header, we have to make two passes. The first pass will compute the size of
|
||||
//! the TLV, and the second pass will build the data for the TLV.
|
||||
|
||||
use byteorder::{
|
||||
LittleEndian, WriteBytesExt,
|
||||
};
|
||||
use cipher::FromBlockCipher;
|
||||
use crate::caps::Caps;
|
||||
use crate::image::ImageVersion;
|
||||
use log::info;
|
||||
use ring::{digest, rand, agreement, hkdf, hmac};
|
||||
use ring::rand::SecureRandom;
|
||||
use ring::signature::{
|
||||
RsaKeyPair,
|
||||
RSA_PSS_SHA256,
|
||||
EcdsaKeyPair,
|
||||
ECDSA_P256_SHA256_ASN1_SIGNING,
|
||||
Ed25519KeyPair,
|
||||
ECDSA_P384_SHA384_ASN1_SIGNING,
|
||||
};
|
||||
use aes::{
|
||||
Aes128,
|
||||
Aes128Ctr,
|
||||
Aes256,
|
||||
Aes256Ctr,
|
||||
NewBlockCipher
|
||||
};
|
||||
use cipher::{
|
||||
generic_array::GenericArray,
|
||||
StreamCipher,
|
||||
};
|
||||
use mcuboot_sys::c;
|
||||
use typenum::{U16, U32};
|
||||
|
||||
#[repr(u16)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[allow(dead_code)] // TODO: For now
|
||||
pub enum TlvKinds {
|
||||
KEYHASH = 0x01,
|
||||
SHA256 = 0x10,
|
||||
SHA384 = 0x11,
|
||||
RSA2048 = 0x20,
|
||||
ECDSASIG = 0x22,
|
||||
RSA3072 = 0x23,
|
||||
ED25519 = 0x24,
|
||||
ENCRSA2048 = 0x30,
|
||||
ENCKW = 0x31,
|
||||
ENCEC256 = 0x32,
|
||||
ENCX25519 = 0x33,
|
||||
DEPENDENCY = 0x40,
|
||||
SECCNT = 0x50,
|
||||
}
|
||||
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
pub enum TlvFlags {
|
||||
PIC = 0x01,
|
||||
NON_BOOTABLE = 0x02,
|
||||
ENCRYPTED_AES128 = 0x04,
|
||||
ENCRYPTED_AES256 = 0x08,
|
||||
RAM_LOAD = 0x20,
|
||||
}
|
||||
|
||||
/// A generator for manifests. The format of the manifest can be either a
|
||||
/// traditional "TLV" or a SUIT-style manifest.
|
||||
pub trait ManifestGen {
|
||||
/// Retrieve the header magic value for this manifest type.
|
||||
fn get_magic(&self) -> u32;
|
||||
|
||||
/// Retrieve the flags value for this particular manifest type.
|
||||
fn get_flags(&self) -> u32;
|
||||
|
||||
/// Retrieve the number of bytes of this manifest that is "protected".
|
||||
/// This field is stored in the outside image header instead of the
|
||||
/// manifest header.
|
||||
fn protect_size(&self) -> u16;
|
||||
|
||||
/// Add a dependency on another image.
|
||||
fn add_dependency(&mut self, id: u8, version: &ImageVersion);
|
||||
|
||||
/// Add a sequence of bytes to the payload that the manifest is
|
||||
/// protecting.
|
||||
fn add_bytes(&mut self, bytes: &[u8]);
|
||||
|
||||
/// Set an internal flag indicating that the next `make_tlv` should
|
||||
/// corrupt the signature.
|
||||
fn corrupt_sig(&mut self);
|
||||
|
||||
/// Estimate the size of the TLV. This can be called before the payload is added (but after
|
||||
/// other information is added). Some of the signature algorithms can generate variable sized
|
||||
/// data, and therefore, this can slightly overestimate the size.
|
||||
fn estimate_size(&self) -> usize;
|
||||
|
||||
/// Construct the manifest for this payload.
|
||||
fn make_tlv(self: Box<Self>) -> Vec<u8>;
|
||||
|
||||
/// Generate a new encryption random key
|
||||
fn generate_enc_key(&mut self);
|
||||
|
||||
/// Return the current encryption key
|
||||
fn get_enc_key(&self) -> Vec<u8>;
|
||||
|
||||
/// Set the security counter to the specified value.
|
||||
fn set_security_counter(&mut self, security_cnt: Option<u32>);
|
||||
|
||||
/// Sets the ignore_ram_load_flag so that can be validated when it is missing,
|
||||
/// it will not load successfully.
|
||||
fn set_ignore_ram_load_flag(&mut self);
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TlvGen {
|
||||
flags: u32,
|
||||
kinds: Vec<TlvKinds>,
|
||||
payload: Vec<u8>,
|
||||
dependencies: Vec<Dependency>,
|
||||
enc_key: Vec<u8>,
|
||||
/// Should this signature be corrupted.
|
||||
gen_corrupted: bool,
|
||||
security_cnt: Option<u32>,
|
||||
/// Ignore RAM_LOAD flag
|
||||
ignore_ram_load_flag: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Dependency {
|
||||
id: u8,
|
||||
version: ImageVersion,
|
||||
}
|
||||
|
||||
impl TlvGen {
|
||||
/// Construct a new tlv generator that will only contain a hash of the data.
|
||||
#[allow(dead_code)]
|
||||
pub fn new_hash_only() -> TlvGen {
|
||||
TlvGen {
|
||||
kinds: vec![TlvKinds::SHA256],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_rsa_pss() -> TlvGen {
|
||||
TlvGen {
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_rsa3072_pss() -> TlvGen {
|
||||
TlvGen {
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::RSA3072],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_ecdsa() -> TlvGen {
|
||||
let hash_kind = if cfg!(feature = "sig-p384") {
|
||||
TlvKinds::SHA384
|
||||
} else {
|
||||
TlvKinds::SHA256
|
||||
};
|
||||
TlvGen {
|
||||
kinds: vec![hash_kind, TlvKinds::ECDSASIG],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_ed25519() -> TlvGen {
|
||||
TlvGen {
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_enc_rsa(aes_key_size: u32) -> TlvGen {
|
||||
let flag = if aes_key_size == 256 {
|
||||
TlvFlags::ENCRYPTED_AES256 as u32
|
||||
} else {
|
||||
TlvFlags::ENCRYPTED_AES128 as u32
|
||||
};
|
||||
TlvGen {
|
||||
flags: flag,
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::ENCRSA2048],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_sig_enc_rsa(aes_key_size: u32) -> TlvGen {
|
||||
let flag = if aes_key_size == 256 {
|
||||
TlvFlags::ENCRYPTED_AES256 as u32
|
||||
} else {
|
||||
TlvFlags::ENCRYPTED_AES128 as u32
|
||||
};
|
||||
TlvGen {
|
||||
flags: flag,
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCRSA2048],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_enc_kw(aes_key_size: u32) -> TlvGen {
|
||||
let flag = if aes_key_size == 256 {
|
||||
TlvFlags::ENCRYPTED_AES256 as u32
|
||||
} else {
|
||||
TlvFlags::ENCRYPTED_AES128 as u32
|
||||
};
|
||||
TlvGen {
|
||||
flags: flag,
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::ENCKW],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_rsa_kw(aes_key_size: u32) -> TlvGen {
|
||||
let flag = if aes_key_size == 256 {
|
||||
TlvFlags::ENCRYPTED_AES256 as u32
|
||||
} else {
|
||||
TlvFlags::ENCRYPTED_AES128 as u32
|
||||
};
|
||||
TlvGen {
|
||||
flags: flag,
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCKW],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_ecdsa_kw(aes_key_size: u32) -> TlvGen {
|
||||
let flag = if aes_key_size == 256 {
|
||||
TlvFlags::ENCRYPTED_AES256 as u32
|
||||
} else {
|
||||
TlvFlags::ENCRYPTED_AES128 as u32
|
||||
};
|
||||
TlvGen {
|
||||
flags: flag,
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSASIG, TlvKinds::ENCKW],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_ecies_p256(aes_key_size: u32) -> TlvGen {
|
||||
let flag = if aes_key_size == 256 {
|
||||
TlvFlags::ENCRYPTED_AES256 as u32
|
||||
} else {
|
||||
TlvFlags::ENCRYPTED_AES128 as u32
|
||||
};
|
||||
TlvGen {
|
||||
flags: flag,
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::ENCEC256],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_ecdsa_ecies_p256(aes_key_size: u32) -> TlvGen {
|
||||
let flag = if aes_key_size == 256 {
|
||||
TlvFlags::ENCRYPTED_AES256 as u32
|
||||
} else {
|
||||
TlvFlags::ENCRYPTED_AES128 as u32
|
||||
};
|
||||
TlvGen {
|
||||
flags: flag,
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSASIG, TlvKinds::ENCEC256],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_ecies_x25519(aes_key_size: u32) -> TlvGen {
|
||||
let flag = if aes_key_size == 256 {
|
||||
TlvFlags::ENCRYPTED_AES256 as u32
|
||||
} else {
|
||||
TlvFlags::ENCRYPTED_AES128 as u32
|
||||
};
|
||||
TlvGen {
|
||||
flags: flag,
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::ENCX25519],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_ed25519_ecies_x25519(aes_key_size: u32) -> TlvGen {
|
||||
let flag = if aes_key_size == 256 {
|
||||
TlvFlags::ENCRYPTED_AES256 as u32
|
||||
} else {
|
||||
TlvFlags::ENCRYPTED_AES128 as u32
|
||||
};
|
||||
TlvGen {
|
||||
flags: flag,
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519, TlvKinds::ENCX25519],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_sec_cnt() -> TlvGen {
|
||||
TlvGen {
|
||||
kinds: vec![TlvKinds::SHA256, TlvKinds::SECCNT],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl ManifestGen for TlvGen {
|
||||
fn get_magic(&self) -> u32 {
|
||||
0x96f3b83d
|
||||
}
|
||||
|
||||
/// Retrieve the header flags for this configuration. This can be called at any time.
|
||||
fn get_flags(&self) -> u32 {
|
||||
// For the RamLoad case, add in the flag for this feature.
|
||||
if Caps::RamLoad.present() && !self.ignore_ram_load_flag {
|
||||
self.flags | (TlvFlags::RAM_LOAD as u32)
|
||||
} else {
|
||||
self.flags
|
||||
}
|
||||
}
|
||||
|
||||
/// Add bytes to the covered hash.
|
||||
fn add_bytes(&mut self, bytes: &[u8]) {
|
||||
self.payload.extend_from_slice(bytes);
|
||||
}
|
||||
|
||||
fn protect_size(&self) -> u16 {
|
||||
let mut size = 0;
|
||||
if !self.dependencies.is_empty() || (Caps::HwRollbackProtection.present() && self.security_cnt.is_some()) {
|
||||
// include the TLV area header.
|
||||
size += 4;
|
||||
// add space for each dependency.
|
||||
size += (self.dependencies.len() as u16) * (4 + std::mem::size_of::<Dependency>() as u16);
|
||||
if Caps::HwRollbackProtection.present() && self.security_cnt.is_some() {
|
||||
size += 4 + 4;
|
||||
}
|
||||
}
|
||||
size
|
||||
}
|
||||
|
||||
fn add_dependency(&mut self, id: u8, version: &ImageVersion) {
|
||||
self.dependencies.push(Dependency {
|
||||
id,
|
||||
version: version.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
fn corrupt_sig(&mut self) {
|
||||
self.gen_corrupted = true;
|
||||
}
|
||||
|
||||
fn estimate_size(&self) -> usize {
|
||||
// Begin the estimate with the 4 byte header.
|
||||
let mut estimate = 4;
|
||||
// A very poor estimate.
|
||||
|
||||
// Estimate the size of the image hash.
|
||||
if self.kinds.contains(&TlvKinds::SHA256) {
|
||||
estimate += 4 + 32;
|
||||
} else if self.kinds.contains(&TlvKinds::SHA384) {
|
||||
estimate += 4 + 48;
|
||||
}
|
||||
|
||||
// Add an estimate in for each of the signature algorithms.
|
||||
if self.kinds.contains(&TlvKinds::RSA2048) {
|
||||
estimate += 4 + 32; // keyhash
|
||||
estimate += 4 + 256; // RSA2048
|
||||
}
|
||||
if self.kinds.contains(&TlvKinds::RSA3072) {
|
||||
estimate += 4 + 32; // keyhash
|
||||
estimate += 4 + 384; // RSA3072
|
||||
}
|
||||
if self.kinds.contains(&TlvKinds::ED25519) {
|
||||
estimate += 4 + 32; // keyhash
|
||||
estimate += 4 + 64; // ED25519 signature.
|
||||
}
|
||||
if self.kinds.contains(&TlvKinds::ECDSASIG) {
|
||||
// ECDSA signatures are encoded as ASN.1 with the x and y values
|
||||
// stored as signed integers. As such, the size can vary by 2 bytes,
|
||||
// if for example the 256-bit value has the high bit, it takes an
|
||||
// extra 0 byte to avoid it being seen as a negative number.
|
||||
if self.kinds.contains(&TlvKinds::SHA384) {
|
||||
estimate += 4 + 48; // SHA384
|
||||
estimate += 4 + 104; // ECDSA384 (varies)
|
||||
} else {
|
||||
estimate += 4 + 32; // SHA256
|
||||
estimate += 4 + 72; // ECDSA256 (varies)
|
||||
}
|
||||
}
|
||||
|
||||
// Estimate encryption.
|
||||
let flag = TlvFlags::ENCRYPTED_AES256 as u32;
|
||||
let aes256 = (self.get_flags() & flag) == flag;
|
||||
|
||||
if self.kinds.contains(&TlvKinds::ENCRSA2048) {
|
||||
estimate += 4 + 256;
|
||||
}
|
||||
if self.kinds.contains(&TlvKinds::ENCKW) {
|
||||
estimate += 4 + if aes256 { 40 } else { 24 };
|
||||
}
|
||||
if self.kinds.contains(&TlvKinds::ENCEC256) {
|
||||
estimate += 4 + if aes256 { 129 } else { 113 };
|
||||
}
|
||||
if self.kinds.contains(&TlvKinds::ENCX25519) {
|
||||
estimate += 4 + if aes256 { 96 } else { 80 };
|
||||
}
|
||||
|
||||
// Gather the size of the protected TLV area.
|
||||
estimate += self.protect_size() as usize;
|
||||
|
||||
estimate
|
||||
}
|
||||
|
||||
/// Compute the TLV given the specified block of data.
|
||||
fn make_tlv(self: Box<Self>) -> Vec<u8> {
|
||||
let size_estimate = self.estimate_size();
|
||||
|
||||
let mut protected_tlv: Vec<u8> = vec![];
|
||||
|
||||
if self.protect_size() > 0 {
|
||||
protected_tlv.push(0x08);
|
||||
protected_tlv.push(0x69);
|
||||
let size = self.protect_size();
|
||||
protected_tlv.write_u16::<LittleEndian>(size).unwrap();
|
||||
for dep in &self.dependencies {
|
||||
protected_tlv.write_u16::<LittleEndian>(TlvKinds::DEPENDENCY as u16).unwrap();
|
||||
protected_tlv.write_u16::<LittleEndian>(12).unwrap();
|
||||
|
||||
// The dependency.
|
||||
protected_tlv.push(dep.id);
|
||||
protected_tlv.push(0);
|
||||
protected_tlv.write_u16::<LittleEndian>(0).unwrap();
|
||||
protected_tlv.push(dep.version.major);
|
||||
protected_tlv.push(dep.version.minor);
|
||||
protected_tlv.write_u16::<LittleEndian>(dep.version.revision).unwrap();
|
||||
protected_tlv.write_u32::<LittleEndian>(dep.version.build_num).unwrap();
|
||||
}
|
||||
|
||||
// Security counter has to be at the protected TLV area also
|
||||
if Caps::HwRollbackProtection.present() && self.security_cnt.is_some() {
|
||||
protected_tlv.write_u16::<LittleEndian>(TlvKinds::SECCNT as u16).unwrap();
|
||||
protected_tlv.write_u16::<LittleEndian>(std::mem::size_of::<u32>() as u16).unwrap();
|
||||
protected_tlv.write_u32::<LittleEndian>(self.security_cnt.unwrap() as u32).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(size, protected_tlv.len() as u16, "protected TLV length incorrect");
|
||||
}
|
||||
|
||||
// Ring does the signature itself, which means that it must be
|
||||
// given a full, contiguous payload. Although this does help from
|
||||
// a correct usage perspective, it is fairly stupid from an
|
||||
// efficiency view. If this is shown to be a performance issue
|
||||
// with the tests, the protected data could be appended to the
|
||||
// payload, and then removed after the signature is done. For now,
|
||||
// just make a signed payload.
|
||||
let mut sig_payload = self.payload.clone();
|
||||
sig_payload.extend_from_slice(&protected_tlv);
|
||||
|
||||
let mut result: Vec<u8> = vec![];
|
||||
|
||||
// add back signed payload
|
||||
result.extend_from_slice(&protected_tlv);
|
||||
|
||||
// add non-protected payload
|
||||
let npro_pos = result.len();
|
||||
result.push(0x07);
|
||||
result.push(0x69);
|
||||
// Placeholder for the size.
|
||||
result.write_u16::<LittleEndian>(0).unwrap();
|
||||
|
||||
if self.kinds.iter().any(|v| v == &TlvKinds::SHA256 || v == &TlvKinds::SHA384) {
|
||||
// If a signature is not requested, corrupt the hash we are
|
||||
// generating. But, if there is a signature, output the
|
||||
// correct hash. We want the hash test to pass so that the
|
||||
// signature verification can be validated.
|
||||
let mut corrupt_hash = self.gen_corrupted;
|
||||
for k in &[TlvKinds::RSA2048, TlvKinds::RSA3072,
|
||||
TlvKinds::ED25519, TlvKinds::ECDSASIG]
|
||||
{
|
||||
if self.kinds.contains(k) {
|
||||
corrupt_hash = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if corrupt_hash {
|
||||
sig_payload[0] ^= 1;
|
||||
}
|
||||
let (hash,hash_size,tlv_kind) = if self.kinds.contains(&TlvKinds::SHA256)
|
||||
{
|
||||
let hash = digest::digest(&digest::SHA256, &sig_payload);
|
||||
(hash,32,TlvKinds::SHA256)
|
||||
}
|
||||
else {
|
||||
let hash = digest::digest(&digest::SHA384, &sig_payload);
|
||||
(hash,48,TlvKinds::SHA384)
|
||||
};
|
||||
let hash = hash.as_ref();
|
||||
|
||||
assert!(hash.len() == hash_size);
|
||||
result.write_u16::<LittleEndian>(tlv_kind as u16).unwrap();
|
||||
result.write_u16::<LittleEndian>(hash_size as u16).unwrap();
|
||||
result.extend_from_slice(hash);
|
||||
|
||||
// Undo the corruption.
|
||||
if corrupt_hash {
|
||||
sig_payload[0] ^= 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if self.gen_corrupted {
|
||||
// Corrupt what is signed by modifying the input to the
|
||||
// signature code.
|
||||
sig_payload[0] ^= 1;
|
||||
}
|
||||
|
||||
if self.kinds.contains(&TlvKinds::RSA2048) ||
|
||||
self.kinds.contains(&TlvKinds::RSA3072) {
|
||||
|
||||
let is_rsa2048 = self.kinds.contains(&TlvKinds::RSA2048);
|
||||
|
||||
// Output the hash of the public key.
|
||||
let hash = if is_rsa2048 {
|
||||
digest::digest(&digest::SHA256, RSA_PUB_KEY)
|
||||
} else {
|
||||
digest::digest(&digest::SHA256, RSA3072_PUB_KEY)
|
||||
};
|
||||
let hash = hash.as_ref();
|
||||
|
||||
assert!(hash.len() == 32);
|
||||
result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
|
||||
result.write_u16::<LittleEndian>(32).unwrap();
|
||||
result.extend_from_slice(hash);
|
||||
|
||||
// For now assume PSS.
|
||||
let key_bytes = if is_rsa2048 {
|
||||
pem::parse(include_bytes!("../../root-rsa-2048.pem").as_ref()).unwrap()
|
||||
} else {
|
||||
pem::parse(include_bytes!("../../root-rsa-3072.pem").as_ref()).unwrap()
|
||||
};
|
||||
assert_eq!(key_bytes.tag, "RSA PRIVATE KEY");
|
||||
let key_pair = RsaKeyPair::from_der(&key_bytes.contents).unwrap();
|
||||
let rng = rand::SystemRandom::new();
|
||||
let mut signature = vec![0; key_pair.public_modulus_len()];
|
||||
if is_rsa2048 {
|
||||
assert_eq!(signature.len(), 256);
|
||||
} else {
|
||||
assert_eq!(signature.len(), 384);
|
||||
}
|
||||
key_pair.sign(&RSA_PSS_SHA256, &rng, &sig_payload, &mut signature).unwrap();
|
||||
|
||||
if is_rsa2048 {
|
||||
result.write_u16::<LittleEndian>(TlvKinds::RSA2048 as u16).unwrap();
|
||||
} else {
|
||||
result.write_u16::<LittleEndian>(TlvKinds::RSA3072 as u16).unwrap();
|
||||
}
|
||||
result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
|
||||
result.extend_from_slice(&signature);
|
||||
}
|
||||
|
||||
if self.kinds.contains(&TlvKinds::ECDSASIG) {
|
||||
let rng = rand::SystemRandom::new();
|
||||
let (signature, keyhash, keyhash_size) = if self.kinds.contains(&TlvKinds::SHA384) {
|
||||
let keyhash = digest::digest(&digest::SHA384, ECDSAP384_PUB_KEY);
|
||||
let key_bytes = pem::parse(include_bytes!("../../root-ec-p384-pkcs8.pem").as_ref()).unwrap();
|
||||
let sign_algo = &ECDSA_P384_SHA384_ASN1_SIGNING;
|
||||
let key_pair = EcdsaKeyPair::from_pkcs8(sign_algo, &key_bytes.contents).unwrap();
|
||||
(key_pair.sign(&rng, &sig_payload).unwrap(), keyhash, 48)
|
||||
} else {
|
||||
let keyhash = digest::digest(&digest::SHA256, ECDSA256_PUB_KEY);
|
||||
let key_bytes = pem::parse(include_bytes!("../../root-ec-p256-pkcs8.pem").as_ref()).unwrap();
|
||||
let sign_algo = &ECDSA_P256_SHA256_ASN1_SIGNING;
|
||||
let key_pair = EcdsaKeyPair::from_pkcs8(sign_algo, &key_bytes.contents).unwrap();
|
||||
(key_pair.sign(&rng, &sig_payload).unwrap(), keyhash, 32)
|
||||
};
|
||||
|
||||
// Write public key
|
||||
let keyhash_slice = keyhash.as_ref();
|
||||
assert!(keyhash_slice.len() == keyhash_size);
|
||||
result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
|
||||
result.write_u16::<LittleEndian>(keyhash_size as u16).unwrap();
|
||||
result.extend_from_slice(keyhash_slice);
|
||||
|
||||
// Write signature
|
||||
result.write_u16::<LittleEndian>(TlvKinds::ECDSASIG as u16).unwrap();
|
||||
let signature = signature.as_ref().to_vec();
|
||||
result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
|
||||
result.extend_from_slice(&signature);
|
||||
}
|
||||
|
||||
if self.kinds.contains(&TlvKinds::ED25519) {
|
||||
let keyhash = digest::digest(&digest::SHA256, ED25519_PUB_KEY);
|
||||
let keyhash = keyhash.as_ref();
|
||||
|
||||
assert!(keyhash.len() == 32);
|
||||
result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
|
||||
result.write_u16::<LittleEndian>(32).unwrap();
|
||||
result.extend_from_slice(keyhash);
|
||||
|
||||
let hash = digest::digest(&digest::SHA256, &sig_payload);
|
||||
let hash = hash.as_ref();
|
||||
assert!(hash.len() == 32);
|
||||
|
||||
let key_bytes = pem::parse(include_bytes!("../../root-ed25519.pem").as_ref()).unwrap();
|
||||
assert_eq!(key_bytes.tag, "PRIVATE KEY");
|
||||
|
||||
let key_pair = Ed25519KeyPair::from_seed_and_public_key(
|
||||
&key_bytes.contents[16..48], &ED25519_PUB_KEY[12..44]).unwrap();
|
||||
let signature = key_pair.sign(&hash);
|
||||
|
||||
result.write_u16::<LittleEndian>(TlvKinds::ED25519 as u16).unwrap();
|
||||
|
||||
let signature = signature.as_ref().to_vec();
|
||||
result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
|
||||
result.extend_from_slice(signature.as_ref());
|
||||
}
|
||||
|
||||
if self.kinds.contains(&TlvKinds::ENCRSA2048) {
|
||||
let key_bytes = pem::parse(include_bytes!("../../enc-rsa2048-pub.pem")
|
||||
.as_ref()).unwrap();
|
||||
assert_eq!(key_bytes.tag, "PUBLIC KEY");
|
||||
|
||||
let cipherkey = self.get_enc_key();
|
||||
let cipherkey = cipherkey.as_slice();
|
||||
let encbuf = match c::rsa_oaep_encrypt(&key_bytes.contents, cipherkey) {
|
||||
Ok(v) => v,
|
||||
Err(_) => panic!("Failed to encrypt secret key"),
|
||||
};
|
||||
|
||||
assert!(encbuf.len() == 256);
|
||||
result.write_u16::<LittleEndian>(TlvKinds::ENCRSA2048 as u16).unwrap();
|
||||
result.write_u16::<LittleEndian>(256).unwrap();
|
||||
result.extend_from_slice(&encbuf);
|
||||
}
|
||||
|
||||
if self.kinds.contains(&TlvKinds::ENCKW) {
|
||||
let flag = TlvFlags::ENCRYPTED_AES256 as u32;
|
||||
let aes256 = (self.get_flags() & flag) == flag;
|
||||
let key_bytes = if aes256 {
|
||||
base64::decode(
|
||||
include_str!("../../enc-aes256kw.b64").trim()).unwrap()
|
||||
} else {
|
||||
base64::decode(
|
||||
include_str!("../../enc-aes128kw.b64").trim()).unwrap()
|
||||
};
|
||||
let cipherkey = self.get_enc_key();
|
||||
let cipherkey = cipherkey.as_slice();
|
||||
let keylen = if aes256 { 32 } else { 16 };
|
||||
let encbuf = match c::kw_encrypt(&key_bytes, cipherkey, keylen) {
|
||||
Ok(v) => v,
|
||||
Err(_) => panic!("Failed to encrypt secret key"),
|
||||
};
|
||||
|
||||
let size = if aes256 { 40 } else { 24 };
|
||||
assert!(encbuf.len() == size);
|
||||
result.write_u16::<LittleEndian>(TlvKinds::ENCKW as u16).unwrap();
|
||||
result.write_u16::<LittleEndian>(size as u16).unwrap();
|
||||
result.extend_from_slice(&encbuf);
|
||||
}
|
||||
|
||||
if self.kinds.contains(&TlvKinds::ENCEC256) || self.kinds.contains(&TlvKinds::ENCX25519) {
|
||||
let key_bytes = if self.kinds.contains(&TlvKinds::ENCEC256) {
|
||||
pem::parse(include_bytes!("../../enc-ec256-pub.pem").as_ref()).unwrap()
|
||||
} else {
|
||||
pem::parse(include_bytes!("../../enc-x25519-pub.pem").as_ref()).unwrap()
|
||||
};
|
||||
assert_eq!(key_bytes.tag, "PUBLIC KEY");
|
||||
let rng = rand::SystemRandom::new();
|
||||
let alg = if self.kinds.contains(&TlvKinds::ENCEC256) {
|
||||
&agreement::ECDH_P256
|
||||
} else {
|
||||
&agreement::X25519
|
||||
};
|
||||
let pk = match agreement::EphemeralPrivateKey::generate(alg, &rng) {
|
||||
Ok(v) => v,
|
||||
Err(_) => panic!("Failed to generate ephemeral keypair"),
|
||||
};
|
||||
|
||||
let pubk = match pk.compute_public_key() {
|
||||
Ok(pubk) => pubk,
|
||||
Err(_) => panic!("Failed computing ephemeral public key"),
|
||||
};
|
||||
|
||||
let peer_pubk = if self.kinds.contains(&TlvKinds::ENCEC256) {
|
||||
agreement::UnparsedPublicKey::new(&agreement::ECDH_P256, &key_bytes.contents[26..])
|
||||
} else {
|
||||
agreement::UnparsedPublicKey::new(&agreement::X25519, &key_bytes.contents[12..])
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct OkmLen<T: core::fmt::Debug + PartialEq>(T);
|
||||
|
||||
impl hkdf::KeyType for OkmLen<usize> {
|
||||
fn len(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
let flag = TlvFlags::ENCRYPTED_AES256 as u32;
|
||||
let aes256 = (self.get_flags() & flag) == flag;
|
||||
|
||||
let derived_key = match agreement::agree_ephemeral(
|
||||
pk, &peer_pubk, ring::error::Unspecified, |shared| {
|
||||
let salt = hkdf::Salt::new(hkdf::HKDF_SHA256, &[]);
|
||||
let prk = salt.extract(&shared);
|
||||
let okm_len = if aes256 { 64 } else { 48 };
|
||||
let okm = match prk.expand(&[b"MCUBoot_ECIES_v1"], OkmLen(okm_len)) {
|
||||
Ok(okm) => okm,
|
||||
Err(_) => panic!("Failed building HKDF OKM"),
|
||||
};
|
||||
let mut buf = if aes256 { vec![0u8; 64] } else { vec![0u8; 48] };
|
||||
match okm.fill(&mut buf) {
|
||||
Ok(_) => Ok(buf),
|
||||
Err(_) => panic!("Failed generating HKDF output"),
|
||||
}
|
||||
},
|
||||
) {
|
||||
Ok(v) => v,
|
||||
Err(_) => panic!("Failed building HKDF"),
|
||||
};
|
||||
|
||||
let nonce = GenericArray::from_slice(&[0; 16]);
|
||||
let mut cipherkey = self.get_enc_key();
|
||||
if aes256 {
|
||||
let key: &GenericArray<u8, U32> = GenericArray::from_slice(&derived_key[..32]);
|
||||
let block = Aes256::new(&key);
|
||||
let mut cipher = Aes256Ctr::from_block_cipher(block, &nonce);
|
||||
cipher.apply_keystream(&mut cipherkey);
|
||||
} else {
|
||||
let key: &GenericArray<u8, U16> = GenericArray::from_slice(&derived_key[..16]);
|
||||
let block = Aes128::new(&key);
|
||||
let mut cipher = Aes128Ctr::from_block_cipher(block, &nonce);
|
||||
cipher.apply_keystream(&mut cipherkey);
|
||||
}
|
||||
|
||||
let size = if aes256 { 32 } else { 16 };
|
||||
let key = hmac::Key::new(hmac::HMAC_SHA256, &derived_key[size..]);
|
||||
let tag = hmac::sign(&key, &cipherkey);
|
||||
|
||||
let mut buf = vec![];
|
||||
buf.append(&mut pubk.as_ref().to_vec());
|
||||
buf.append(&mut tag.as_ref().to_vec());
|
||||
buf.append(&mut cipherkey);
|
||||
|
||||
if self.kinds.contains(&TlvKinds::ENCEC256) {
|
||||
let size = if aes256 { 129 } else { 113 };
|
||||
assert!(buf.len() == size);
|
||||
result.write_u16::<LittleEndian>(TlvKinds::ENCEC256 as u16).unwrap();
|
||||
result.write_u16::<LittleEndian>(size as u16).unwrap();
|
||||
} else {
|
||||
let size = if aes256 { 96 } else { 80 };
|
||||
assert!(buf.len() == size);
|
||||
result.write_u16::<LittleEndian>(TlvKinds::ENCX25519 as u16).unwrap();
|
||||
result.write_u16::<LittleEndian>(size as u16).unwrap();
|
||||
}
|
||||
result.extend_from_slice(&buf);
|
||||
}
|
||||
|
||||
// Patch the size back into the TLV header.
|
||||
let size = (result.len() - npro_pos) as u16;
|
||||
let mut size_buf = &mut result[npro_pos + 2 .. npro_pos + 4];
|
||||
size_buf.write_u16::<LittleEndian>(size).unwrap();
|
||||
|
||||
// ECDSA is stored as an ASN.1 integer. For a 128-bit value, this maximally results in 33
|
||||
// bytes of storage for each of the two values. If the high bit is zero, it will take 32
|
||||
// bytes, if the top 8 bits are zero, it will take 31 bits, and so on. The smaller size
|
||||
// will occur with decreasing likelihood. We'll allow this to get a bit smaller, hopefully
|
||||
// allowing the tests to pass with false failures rare. For this case, we'll handle up to
|
||||
// the top 16 bits of both numbers being all zeros (1 in 2^32).
|
||||
if !Caps::has_ecdsa() {
|
||||
if size_estimate != result.len() {
|
||||
panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
|
||||
}
|
||||
} else {
|
||||
if size_estimate < result.len() || size_estimate > result.len() + 6 {
|
||||
panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
|
||||
}
|
||||
}
|
||||
if size_estimate != result.len() {
|
||||
log::warn!("Size off: {} actual {}", size_estimate, result.len());
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn generate_enc_key(&mut self) {
|
||||
let rng = rand::SystemRandom::new();
|
||||
let flag = TlvFlags::ENCRYPTED_AES256 as u32;
|
||||
let aes256 = (self.get_flags() & flag) == flag;
|
||||
let mut buf = if aes256 {
|
||||
vec![0u8; 32]
|
||||
} else {
|
||||
vec![0u8; 16]
|
||||
};
|
||||
if rng.fill(&mut buf).is_err() {
|
||||
panic!("Error generating encrypted key");
|
||||
}
|
||||
info!("New encryption key: {:02x?}", buf);
|
||||
self.enc_key = buf;
|
||||
}
|
||||
|
||||
fn get_enc_key(&self) -> Vec<u8> {
|
||||
if self.enc_key.len() != 32 && self.enc_key.len() != 16 {
|
||||
panic!("No random key was generated");
|
||||
}
|
||||
self.enc_key.clone()
|
||||
}
|
||||
|
||||
fn set_security_counter(&mut self, security_cnt: Option<u32>) {
|
||||
self.security_cnt = security_cnt;
|
||||
}
|
||||
|
||||
fn set_ignore_ram_load_flag(&mut self) {
|
||||
self.ignore_ram_load_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
include!("rsa_pub_key-rs.txt");
|
||||
include!("rsa3072_pub_key-rs.txt");
|
||||
include!("ecdsa_pub_key-rs.txt");
|
||||
include!("ed25519_pub_key-rs.txt");
|
||||
11
bootloader/mcuboot/sim/src/utils.rs
Normal file
11
bootloader/mcuboot/sim/src/utils.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Utility functions used throughout MCUboot
|
||||
|
||||
pub fn align_up(num: u32, align: u32) -> u32 {
|
||||
assert!(align.is_power_of_two());
|
||||
|
||||
(num + (align - 1)) & !(align - 1)
|
||||
}
|
||||
201
bootloader/mcuboot/sim/tests/core.rs
Normal file
201
bootloader/mcuboot/sim/tests/core.rs
Normal file
@@ -0,0 +1,201 @@
|
||||
// Copyright (c) 2017-2021 Linaro LTD
|
||||
// Copyright (c) 2017-2019 JUUL Labs
|
||||
// Copyright (c) 2021-2023 Arm Limited
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Core tests
|
||||
//!
|
||||
//! Run the existing testsuite as a Rust unit test.
|
||||
|
||||
use bootsim::{
|
||||
DepTest, DepType, UpgradeInfo,
|
||||
ImagesBuilder,
|
||||
Images,
|
||||
NO_DEPS,
|
||||
REV_DEPS,
|
||||
testlog,
|
||||
ImageManipulation
|
||||
};
|
||||
use std::{
|
||||
env,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
/// A single test, after setting up logging and such. Within the $body,
|
||||
/// $arg will be bound to each device.
|
||||
macro_rules! test_shell {
|
||||
($name:ident, $arg: ident, $body:expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
testlog::setup();
|
||||
ImagesBuilder::each_device(|$arg| {
|
||||
$body;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A typical test calls a particular constructor, and runs a given test on
|
||||
/// that constructor.
|
||||
macro_rules! sim_test {
|
||||
($name:ident, $maker:ident($($margs:expr),*), $test:ident($($targs:expr),*)) => {
|
||||
test_shell!($name, r, {
|
||||
let image = r.$maker($($margs),*);
|
||||
dump_image(&image, stringify!($name));
|
||||
assert!(!image.$test($($targs),*));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
sim_test!(bad_secondary_slot, make_bad_secondary_slot_image(), run_signfail_upgrade());
|
||||
sim_test!(secondary_trailer_leftover, make_erased_secondary_image(), run_secondary_leftover_trailer());
|
||||
sim_test!(bootstrap, make_bootstrap_image(), run_bootstrap());
|
||||
sim_test!(oversized_bootstrap, make_oversized_bootstrap_image(), run_oversized_bootstrap());
|
||||
sim_test!(norevert_newimage, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_norevert_newimage());
|
||||
sim_test!(basic_revert, make_image(&NO_DEPS, true), run_basic_revert());
|
||||
sim_test!(revert_with_fails, make_image(&NO_DEPS, false), run_revert_with_fails());
|
||||
sim_test!(perm_with_fails, make_image(&NO_DEPS, true), run_perm_with_fails());
|
||||
sim_test!(perm_with_random_fails, make_image(&NO_DEPS, true), run_perm_with_random_fails(5));
|
||||
sim_test!(norevert, make_image(&NO_DEPS, true), run_norevert());
|
||||
|
||||
#[cfg(not(feature = "max-align-32"))]
|
||||
sim_test!(oversized_secondary_slot, make_oversized_secondary_slot_image(), run_oversizefail_upgrade());
|
||||
|
||||
sim_test!(status_write_fails_complete, make_image(&NO_DEPS, true), run_with_status_fails_complete());
|
||||
sim_test!(status_write_fails_with_reset, make_image(&NO_DEPS, true), run_with_status_fails_with_reset());
|
||||
sim_test!(downgrade_prevention, make_image(&REV_DEPS, true), run_nodowngrade());
|
||||
|
||||
sim_test!(direct_xip_first, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_direct_xip());
|
||||
sim_test!(ram_load_first, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_ram_load());
|
||||
sim_test!(ram_load_split, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_split_ram_load());
|
||||
sim_test!(hw_prot_failed_security_cnt_check, make_image_with_security_counter(Some(0)), run_hw_rollback_prot());
|
||||
sim_test!(hw_prot_missing_security_cnt, make_image_with_security_counter(None), run_hw_rollback_prot());
|
||||
sim_test!(ram_load_out_of_bounds, make_no_upgrade_image(&NO_DEPS, ImageManipulation::WrongOffset), run_ram_load_boot_with_result(false));
|
||||
sim_test!(ram_load_missing_header_flag, make_no_upgrade_image(&NO_DEPS, ImageManipulation::IgnoreRamLoadFlag), run_ram_load_boot_with_result(false));
|
||||
sim_test!(ram_load_failed_validation, make_no_upgrade_image(&NO_DEPS, ImageManipulation::BadSignature), run_ram_load_boot_with_result(false));
|
||||
sim_test!(ram_load_corrupt_higher_version_image, make_no_upgrade_image(&NO_DEPS, ImageManipulation::CorruptHigherVersionImage), run_ram_load_boot_with_result(true));
|
||||
|
||||
#[cfg(feature = "multiimage")]
|
||||
sim_test!(ram_load_overlapping_images_same_base, make_no_upgrade_image(&NO_DEPS, ImageManipulation::OverlapImages(true)), run_ram_load_boot_with_result(false));
|
||||
#[cfg(feature = "multiimage")]
|
||||
sim_test!(ram_load_overlapping_images_offset, make_no_upgrade_image(&NO_DEPS, ImageManipulation::OverlapImages(false)), run_ram_load_boot_with_result(false));
|
||||
|
||||
// Test various combinations of incorrect dependencies.
|
||||
test_shell!(dependency_combos, r, {
|
||||
// Only test setups with two images.
|
||||
if r.num_images() != 2 {
|
||||
return;
|
||||
}
|
||||
|
||||
for dep in TEST_DEPS {
|
||||
let image = r.clone().make_image(&dep, true);
|
||||
dump_image(&image, "dependency_combos");
|
||||
assert!(!image.run_check_deps(&dep));
|
||||
}
|
||||
});
|
||||
|
||||
/// These are the variants of dependencies we will test.
|
||||
pub static TEST_DEPS: &[DepTest] = &[
|
||||
// A sanity test, no dependencies should upgrade.
|
||||
DepTest {
|
||||
depends: [DepType::Nothing, DepType::Nothing],
|
||||
upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Upgraded],
|
||||
downgrade: false,
|
||||
},
|
||||
|
||||
// If all of the dependencies are met, we should also upgrade.
|
||||
DepTest {
|
||||
depends: [DepType::Correct, DepType::Correct],
|
||||
upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Upgraded],
|
||||
downgrade: false,
|
||||
},
|
||||
|
||||
// If none of the dependencies are met, the images should be held.
|
||||
DepTest {
|
||||
depends: [DepType::Newer, DepType::Newer],
|
||||
upgrades: [UpgradeInfo::Held, UpgradeInfo::Held],
|
||||
downgrade: false,
|
||||
},
|
||||
|
||||
// If the first image is not met, we should hold back on the
|
||||
// dependencies (it is not well defined what the correct behavior is
|
||||
// here, it could also be correct to upgrade only the second image).
|
||||
DepTest {
|
||||
depends: [DepType::Newer, DepType::Correct],
|
||||
upgrades: [UpgradeInfo::Held, UpgradeInfo::Held],
|
||||
downgrade: false,
|
||||
},
|
||||
|
||||
// Test the variant in the other direction.
|
||||
DepTest {
|
||||
depends: [DepType::Correct, DepType::Newer],
|
||||
upgrades: [UpgradeInfo::Held, UpgradeInfo::Held],
|
||||
downgrade: false,
|
||||
},
|
||||
|
||||
// Test where only the first image is upgraded, and there are no
|
||||
// dependencies.
|
||||
DepTest {
|
||||
depends: [DepType::Nothing, DepType::NoUpgrade],
|
||||
upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Held],
|
||||
downgrade: false,
|
||||
},
|
||||
|
||||
// Test one image with a valid dependency on the first image.
|
||||
DepTest {
|
||||
depends: [DepType::OldCorrect, DepType::NoUpgrade],
|
||||
upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Held],
|
||||
downgrade: false,
|
||||
},
|
||||
|
||||
// Test one image with an invalid dependency on the first image.
|
||||
DepTest {
|
||||
depends: [DepType::Newer, DepType::NoUpgrade],
|
||||
upgrades: [UpgradeInfo::Held, UpgradeInfo::Held],
|
||||
downgrade: false,
|
||||
},
|
||||
|
||||
// Test where only the second image is upgraded, and there are no
|
||||
// dependencies.
|
||||
DepTest {
|
||||
depends: [DepType::NoUpgrade, DepType::Nothing],
|
||||
upgrades: [UpgradeInfo::Held, UpgradeInfo::Upgraded],
|
||||
downgrade: false,
|
||||
},
|
||||
|
||||
// Test one image with a valid dependency on the second image.
|
||||
DepTest {
|
||||
depends: [DepType::NoUpgrade, DepType::OldCorrect],
|
||||
upgrades: [UpgradeInfo::Held, UpgradeInfo::Upgraded],
|
||||
downgrade: false,
|
||||
},
|
||||
|
||||
// Test one image with an invalid dependency on the second image.
|
||||
DepTest {
|
||||
depends: [DepType::NoUpgrade, DepType::Newer],
|
||||
upgrades: [UpgradeInfo::Held, UpgradeInfo::Held],
|
||||
downgrade: false,
|
||||
},
|
||||
];
|
||||
|
||||
/// Counter for the image number.
|
||||
static IMAGE_NUMBER: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
/// Dump an image if that makes sense. The name is the name of the test
|
||||
/// being run. If the MCUBOT_DEBUG_DUMP environment variable contains, in
|
||||
/// one of its comma separate strings a substring of this name, then this
|
||||
/// image will be dumped. As a special case, we will dump everything if
|
||||
/// this environment variable is set to all.
|
||||
fn dump_image(image: &Images, name: &str) {
|
||||
if let Ok(request) = env::var("MCUBOOT_DEBUG_DUMP") {
|
||||
if request.split(',').any(|req| {
|
||||
req == "all" || name.contains(req)
|
||||
}) {
|
||||
let count = IMAGE_NUMBER.fetch_add(1, Ordering::SeqCst);
|
||||
let full_name = format!("{}-{:04}", name, count);
|
||||
log::info!("Dump {:?}", full_name);
|
||||
image.debug_dump(&full_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user