Infineon: Add cyw20829 platform, shared slot feature, json memory map, psoc6 xip
Based in 1.8.0 release of MCUBoot library
This commit adds CYW20829 Infineon platform support with following capabilities:
1. Overwrite and swap upgrade mode support
2. Multi-image with up to 4 images
3. Hardware security counter is supported for CYW20829 platform
Add XIP support for PSOC6 platform - place BOOT slot in external memory and execute it in place using SMIF in XIP mode
and some new features for Infineon devices.
1. Shared upgrade slot feature - use one shared area for upgrade slots of multiple images
2. Memory map defined using JSON file - define memory regions for bootloader and user app in conventional way using JSON file
diff --git a/sim/Cargo.lock b/sim/Cargo.lock
deleted file mode 100644
index 11aaec7..0000000
--- a/sim/Cargo.lock
+++ /dev/null
@@ -1,667 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-[[package]]
-name = "aes-ctr"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92e60aeefd2a0243bd53a42e92444e039f67c3d7f0382c9813577696e7c10bf3"
-dependencies = [
- "aes-soft",
- "aesni",
- "ctr",
- "stream-cipher",
-]
-
-[[package]]
-name = "aes-soft"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4925647ee64e5056cf231608957ce7c81e12d6d6e316b9ce1404778cc1d35fa7"
-dependencies = [
- "block-cipher",
- "byteorder",
- "opaque-debug",
-]
-
-[[package]]
-name = "aesni"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d050d39b0b7688b3a3254394c3e30a9d66c41dcf9b05b0e2dbdc623f6505d264"
-dependencies = [
- "block-cipher",
- "opaque-debug",
- "stream-cipher",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "0.7.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "base64"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
-
-[[package]]
-name = "block-cipher"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa136449e765dc7faa244561ccae839c394048667929af599b5d931ebe7b7f10"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "bootsim"
-version = "0.1.0"
-dependencies = [
- "aes-ctr",
- "base64",
- "byteorder",
- "docopt",
- "env_logger",
- "libc",
- "log",
- "mcuboot-sys",
- "pem",
- "rand",
- "ring",
- "serde",
- "serde_derive",
- "simflash",
- "untrusted",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742"
-
-[[package]]
-name = "byteorder"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
-
-[[package]]
-name = "cc"
-version = "1.0.50"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
-[[package]]
-name = "ctr"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3592740fd55aaf61dd72df96756bd0d11e6037b89dcf30ae2e1895b267692be"
-dependencies = [
- "stream-cipher",
-]
-
-[[package]]
-name = "docopt"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969"
-dependencies = [
- "lazy_static",
- "regex",
- "serde",
- "strsim",
-]
-
-[[package]]
-name = "env_logger"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
-dependencies = [
- "atty",
- "humantime",
- "log",
- "regex",
- "termcolor",
-]
-
-[[package]]
-name = "generic-array"
-version = "0.14.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac746a5f3bbfdadd6106868134545e684693d54d9d44f6e9588a7d54af0bf980"
-dependencies = [
- "typenum",
- "version_check 0.9.2",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "heck"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "humantime"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
-dependencies = [
- "quick-error",
-]
-
-[[package]]
-name = "js-sys"
-version = "0.3.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
-name = "libc"
-version = "0.2.66"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
-
-[[package]]
-name = "log"
-version = "0.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "mcuboot-sys"
-version = "0.1.0"
-dependencies = [
- "cc",
- "libc",
- "log",
- "simflash",
-]
-
-[[package]]
-name = "memchr"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
-
-[[package]]
-name = "nom"
-version = "4.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
-dependencies = [
- "memchr",
- "version_check 0.1.5",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
-
-[[package]]
-name = "opaque-debug"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
-
-[[package]]
-name = "pem"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59698ea79df9bf77104aefd39cc3ec990cb9693fb59c3b0a70ddf2646fdffb4b"
-dependencies = [
- "base64",
- "once_cell",
- "regex",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "quick-error"
-version = "1.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
-
-[[package]]
-name = "quote"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
-dependencies = [
- "getrandom",
- "libc",
- "rand_chacha",
- "rand_core",
- "rand_hc",
- "rand_pcg",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "rand_pcg"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "regex"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
- "thread_local",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06"
-
-[[package]]
-name = "ring"
-version = "0.16.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "741ba1704ae21999c00942f9f5944f801e977f54302af346b596287599ad1862"
-dependencies = [
- "cc",
- "lazy_static",
- "libc",
- "spin",
- "untrusted",
- "web-sys",
- "winapi",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.104"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.104"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "simflash"
-version = "0.1.0"
-dependencies = [
- "log",
- "rand",
- "thiserror",
-]
-
-[[package]]
-name = "sourcefile"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3"
-
-[[package]]
-name = "spin"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
-
-[[package]]
-name = "stream-cipher"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09f8ed9974042b8c3672ff3030a69fcc03b74c47c3d1ecb7755e8a3626011e88"
-dependencies = [
- "block-cipher",
- "generic-array",
-]
-
-[[package]]
-name = "strsim"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
-
-[[package]]
-name = "syn"
-version = "1.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "thiserror"
-version = "1.0.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "thread_local"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
-dependencies = [
- "lazy_static",
-]
-
-[[package]]
-name = "typenum"
-version = "1.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
-
-[[package]]
-name = "untrusted"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece"
-
-[[package]]
-name = "version_check"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
-
-[[package]]
-name = "version_check"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
-
-[[package]]
-name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45"
-dependencies = [
- "bumpalo",
- "lazy_static",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601"
-
-[[package]]
-name = "wasm-bindgen-webidl"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d"
-dependencies = [
- "anyhow",
- "heck",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "weedle",
-]
-
-[[package]]
-name = "web-sys"
-version = "0.3.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b"
-dependencies = [
- "anyhow",
- "js-sys",
- "sourcefile",
- "wasm-bindgen",
- "wasm-bindgen-webidl",
-]
-
-[[package]]
-name = "weedle"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164"
-dependencies = [
- "nom",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/sim/Cargo.toml b/sim/Cargo.toml
index 02f0f73..b80dbb2 100644
--- a/sim/Cargo.toml
+++ b/sim/Cargo.toml
@@ -17,30 +17,39 @@
swap-status = ["mcuboot-sys/swap-status"]
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"]
large-write = []
downgrade-prevention = ["mcuboot-sys/downgrade-prevention"]
[dependencies]
byteorder = "1.3"
libc = "0.2"
-rand = { version = "0.7", features = ["small_rng"] }
+rand = { version = "0.8", features = ["small_rng"] }
docopt = "1.1.0"
serde = "1.0"
serde_derive = "1.0"
log = "0.4"
-env_logger = "0.7"
+env_logger = "0.9"
simflash = { path = "simflash" }
mcuboot-sys = { path = "mcuboot-sys" }
ring = "0.16.11"
-untrusted = "0.7"
+untrusted = "0.9"
pem = "0.8"
-aes-ctr = "0.4.0"
-base64 = "0.12.0"
+cipher = "0.3"
+aes = { version = "0.7.4", features = ["ctr"] }
+base64 = "0.13.0"
+typenum = "1.13.0"
# The simulator runs very slowly without optimization. A value of 1
# compiles in about half the time, but runs about 5-6 times slower. 2
@@ -48,6 +57,8 @@
# Use 2 in case that makes the code slightly more debuggable.
[profile.test]
opt-level = 2
+# debug = true
[profile.dev]
opt-level = 2
+# debug = true
diff --git a/sim/mcuboot-sys/Cargo.toml b/sim/mcuboot-sys/Cargo.toml
index ef09755..e3a00cb 100644
--- a/sim/mcuboot-sys/Cargo.toml
+++ b/sim/mcuboot-sys/Cargo.toml
@@ -30,34 +30,62 @@
# Overwrite only upgrade
overwrite-only = []
-swap-status = []
-
swap-move = []
+swap-status = []
+
# 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 = []
+# Large write. Not meaningful, but present here so that the
+# full-suite tests will work for this configuration.
+large-write = []
+
[build-dependencies]
cc = "1.0.25"
diff --git a/sim/mcuboot-sys/build.rs b/sim/mcuboot-sys/build.rs
index a2206c9..1a08741 100644
--- a/sim/mcuboot-sys/build.rs
+++ b/sim/mcuboot-sys/build.rs
@@ -2,10 +2,11 @@
extern crate cc;
+use std::collections::BTreeSet;
use std::env;
use std::fs;
use std::io;
-use std::path::Path;
+use std::path::{Path, PathBuf};
fn main() {
// Feature flags.
@@ -20,37 +21,51 @@
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 mut conf = cc::Build::new();
- conf.define("__BOOTSIM__", None);
- conf.define("MCUBOOT_HAVE_LOGGING", None);
- conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
- conf.define("MCUBOOT_HAVE_ASSERT_H", None);
- if !swap_status {
- conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("128"));
- }
- conf.define("MCUBOOT_IMAGE_NUMBER", Some(if multiimage { "2" } else { "1" }));
+ 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"));
+ 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.define("MCUBOOT_BOOTSTRAP", None);
+ conf.conf.define("MCUBOOT_BOOTSTRAP", None);
+ conf.conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
}
if validate_primary_slot {
- conf.define("MCUBOOT_VALIDATE_PRIMARY_SLOT", None);
+ conf.conf.define("MCUBOOT_VALIDATE_PRIMARY_SLOT", None);
}
if downgrade_prevention {
- conf.define("MCUBOOT_DOWNGRADE_PREVENTION", None);
+ 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);
}
// Currently no more than one sig type can be used simultaneously.
@@ -60,35 +75,35 @@
}
if sig_rsa || sig_rsa3072 {
- conf.define("MCUBOOT_SIGN_RSA", None);
+ 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.define("MCUBOOT_SIGN_RSA_LEN", "2048");
- conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "2048");
+ conf.conf.define("MCUBOOT_SIGN_RSA_LEN", "2048");
+ conf.conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "2048");
} else {
- conf.define("MCUBOOT_SIGN_RSA_LEN", "3072");
- conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "3072");
+ conf.conf.define("MCUBOOT_SIGN_RSA_LEN", "3072");
+ conf.conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "3072");
}
- conf.define("MCUBOOT_USE_MBED_TLS", None);
+ conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
- conf.include("../../ext/mbedtls/crypto/include");
- conf.file("../../ext/mbedtls/crypto/library/sha256.c");
+ conf.conf.include("../../ext/mbedtls/include");
+ conf.file("../../ext/mbedtls/library/sha256.c");
conf.file("csupport/keys.c");
- conf.file("../../ext/mbedtls/crypto/library/rsa.c");
- conf.file("../../ext/mbedtls/crypto/library/bignum.c");
- conf.file("../../ext/mbedtls/crypto/library/platform.c");
- conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
- conf.file("../../ext/mbedtls/crypto/library/asn1parse.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");
} else if sig_ecdsa {
- conf.define("MCUBOOT_SIGN_EC256", None);
- conf.define("MCUBOOT_USE_TINYCRYPT", None);
+ conf.conf.define("MCUBOOT_SIGN_EC256", None);
+ conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
if !enc_kw {
- conf.include("../../ext/mbedtls-asn1/include");
+ conf.conf.include("../../ext/mbedtls/include");
}
- conf.include("../../ext/tinycrypt/lib/include");
+ conf.conf.include("../../ext/tinycrypt/lib/include");
conf.file("csupport/keys.c");
@@ -97,115 +112,119 @@
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-asn1/src/platform_util.c");
- conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
+ conf.file("../../ext/mbedtls/library/platform_util.c");
+ conf.file("../../ext/mbedtls/library/asn1parse.c");
} else if sig_ecdsa_mbedtls {
- conf.define("MCUBOOT_SIGN_EC256", None);
- conf.define("MCUBOOT_USE_MBED_TLS", None);
+ conf.conf.define("MCUBOOT_SIGN_EC256", None);
+ conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
- conf.include("../../ext/mbedtls/crypto/include");
- conf.file("../../ext/mbedtls/crypto/library/sha256.c");
+ conf.conf.include("../../ext/mbedtls/include");
+ conf.file("../../ext/mbedtls/library/sha256.c");
conf.file("csupport/keys.c");
- conf.file("../../ext/mbedtls/crypto/library/asn1parse.c");
- conf.file("../../ext/mbedtls/crypto/library/bignum.c");
- conf.file("../../ext/mbedtls/crypto/library/ecdsa.c");
- conf.file("../../ext/mbedtls/crypto/library/ecp.c");
- conf.file("../../ext/mbedtls/crypto/library/ecp_curves.c");
- conf.file("../../ext/mbedtls/crypto/library/platform.c");
- conf.file("../../ext/mbedtls/crypto/library/platform_util.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_ed25519 {
- conf.define("MCUBOOT_SIGN_ED25519", None);
- conf.define("MCUBOOT_USE_TINYCRYPT", None);
+ conf.conf.define("MCUBOOT_SIGN_ED25519", None);
+ conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
- conf.include("../../ext/tinycrypt/lib/include");
- conf.include("../../ext/tinycrypt-sha512/lib/include");
- conf.include("../../ext/mbedtls-asn1/include");
+ 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-asn1/src/platform_util.c");
- conf.file("../../ext/mbedtls-asn1/src/asn1parse.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.define("MCUBOOT_USE_MBED_TLS", None);
- conf.include("../../ext/mbedtls/crypto/include");
- conf.file("../../ext/mbedtls/crypto/library/sha256.c");
+ 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.define("MCUBOOT_OVERWRITE_ONLY", None);
- conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
+ conf.conf.define("MCUBOOT_OVERWRITE_ONLY", None);
}
if swap_move {
- conf.define("MCUBOOT_SWAP_USING_MOVE", None);
- conf.file("../../boot/bootutil/src/swap_move.c");
+ conf.conf.define("MCUBOOT_SWAP_USING_MOVE", None);
+ } else if !overwrite_only {
+ conf.conf.define("CONFIG_BOOT_SWAP_USING_SCRATCH", None);
+ conf.conf.define("MCUBOOT_SWAP_USING_SCRATCH", None);
}
-
if swap_status {
- conf.define("MCUBOOT_SWAP_USING_STATUS", None);
- conf.define("MCUBOOT_LOG_LEVEL", "MCUBOOT_LOG_LEVEL_DEBUG");
- conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("2000"));
- conf.define("CY_FLASH_ALIGN", "512");
- conf.file("../../boot/bootutil/src/swap_status.c");
- conf.file("../../boot/bootutil/src/swap_status_part.c");
- conf.file("../../boot/bootutil/src/swap_status_misc.c");
- conf.file("../../boot/bootutil/src/crc32c.c");
-// conf.file("../../boot/cypress/cy_flash_pal/cy_my_support.c");
- conf.include("../../boot/cypress/cy_flash_pal");
+ conf.conf.define("MCUBOOT_SWAP_USING_STATUS", None);
+ conf.conf.define("CY_FLASH_ALIGN", "512");
+ conf.conf.file("../../boot/bootutil/src/swap_status.c");
+ conf.conf.file("../../boot/bootutil/src/swap_status_part.c");
+ conf.conf.file("../../boot/bootutil/src/swap_status_misc.c");
+ conf.conf.file("../../boot/bootutil/src/crc32c.c");
}
- if enc_rsa {
- conf.define("MCUBOOT_ENCRYPT_RSA", None);
- conf.define("MCUBOOT_ENC_IMAGES", None);
- conf.define("MCUBOOT_USE_MBED_TLS", 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.include("../../ext/mbedtls/crypto/include");
- conf.file("../../ext/mbedtls/crypto/library/sha256.c");
+ conf.conf.include("../../ext/mbedtls/include");
+ conf.conf.include("../../ext/mbedtls/library");
+ conf.file("../../ext/mbedtls/library/sha256.c");
- conf.file("../../ext/mbedtls/crypto/library/platform.c");
- conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
- conf.file("../../ext/mbedtls/crypto/library/rsa.c");
- conf.file("../../ext/mbedtls/crypto/library/rsa_internal.c");
- conf.file("../../ext/mbedtls/crypto/library/md.c");
- conf.file("../../ext/mbedtls/crypto/library/aes.c");
- conf.file("../../ext/mbedtls/crypto/library/bignum.c");
- conf.file("../../ext/mbedtls/crypto/library/asn1parse.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 {
- conf.define("MCUBOOT_ENCRYPT_KW", None);
- conf.define("MCUBOOT_ENC_IMAGES", None);
+ 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/crypto/library/sha256.c");
+ conf.file("../../ext/mbedtls/library/sha256.c");
}
/* Simulator uses Mbed-TLS to wrap keys */
- conf.include("../../ext/mbedtls/crypto/include");
- conf.file("../../ext/mbedtls/crypto/library/platform.c");
- conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
- conf.file("../../ext/mbedtls/crypto/library/nist_kw.c");
- conf.file("../../ext/mbedtls/crypto/library/cipher.c");
- conf.file("../../ext/mbedtls/crypto/library/cipher_wrap.c");
- conf.file("../../ext/mbedtls/crypto/library/aes.c");
+ 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.define("MCUBOOT_USE_TINYCRYPT", None);
+ conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
- conf.include("../../ext/tinycrypt/lib/include");
+ conf.conf.include("../../ext/tinycrypt/lib/include");
conf.file("../../ext/tinycrypt/lib/source/utils.c");
conf.file("../../ext/tinycrypt/lib/source/sha256.c");
@@ -220,16 +239,16 @@
}
if enc_ec256 {
- conf.define("MCUBOOT_ENCRYPT_EC256", None);
- conf.define("MCUBOOT_ENC_IMAGES", None);
- conf.define("MCUBOOT_USE_TINYCRYPT", None);
- conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
+ 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.include("../../ext/mbedtls-asn1/include");
- conf.include("../../ext/tinycrypt/lib/include");
+ conf.conf.include("../../ext/mbedtls/include");
+ conf.conf.include("../../ext/tinycrypt/lib/include");
/* FIXME: fail with other signature schemes ? */
@@ -239,36 +258,59 @@
conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");
- conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
- conf.file("../../ext/mbedtls-asn1/src/asn1parse.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.define("MCUBOOT_ENCRYPT_X25519", None);
- conf.define("MCUBOOT_ENC_IMAGES", None);
- conf.define("MCUBOOT_USE_TINYCRYPT", None);
- conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
+ 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.include("../../ext/mbedtls-asn1/include");
- conf.include("../../ext/tinycrypt/lib/include");
- conf.include("../../ext/tinycrypt-sha512/lib/include");
+ 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-asn1/src/platform_util.c");
- conf.file("../../ext/mbedtls-asn1/src/asn1parse.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");
@@ -276,24 +318,48 @@
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.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa-kw.h>"));
- } else if sig_rsa || sig_rsa3072 || enc_rsa {
- conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa.h>"));
- } else if sig_ecdsa_mbedtls {
- conf.define("MBEDTLS_CONFIG_FILE", Some("<config-ecdsa.h>"));
+ 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.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
+ conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
} else if sig_ed25519 || enc_x25519 {
- conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
- } else if enc_kw {
- conf.define("MBEDTLS_CONFIG_FILE", Some("<config-kw.h>"));
+ 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>"));
}
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 {
+ conf.conf.include("../../ext/mbedtls/include");
conf.file("../../boot/bootutil/src/image_ec256.c");
} else if sig_ed25519 {
conf.file("../../boot/bootutil/src/image_ed25519.c");
@@ -301,32 +367,33 @@
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.include("../../boot/bootutil/include");
- conf.include("csupport");
- conf.include("../../boot/zephyr/include");
- conf.debug(true);
- conf.flag("-Wall");
- conf.flag("-Werror");
+ conf.conf.include("../../boot/bootutil/include");
+ conf.conf.include("csupport");
+ conf.conf.include("../../boot/zephyr/include");
+ 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.flag("-std=c99");
+ conf.conf.flag("-std=c99");
- conf.compile("libbootutil.a");
+ 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/crypto/include").unwrap();
- walk_dir("../../ext/mbedtls/crypto/library").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.
@@ -347,3 +414,30 @@
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
+ }
+}
diff --git a/sim/mcuboot-sys/csupport/devicetree.h b/sim/mcuboot-sys/csupport/devicetree.h
index 73c7c83..22a7fe6 100644
--- a/sim/mcuboot-sys/csupport/devicetree.h
+++ b/sim/mcuboot-sys/csupport/devicetree.h
@@ -9,6 +9,8 @@
#ifndef __DEVICETREE_H__
#define __DEVICETREE_H__
+#define FLASH_AREA_ERROR 255u
+
#define FLASH_AREA_ID(x) FLASH_AREA_ID_##x
#define FLASH_AREA_ID_image_0 1
@@ -17,11 +19,16 @@
#define FLASH_AREA_ID_image_2 4
#define FLASH_AREA_ID_image_3 5
-#define FLASH_AREA_IMAGE_0 FLASH_AREA_ID(image_0)
-#define FLASH_AREA_IMAGE_1 FLASH_AREA_ID(image_1)
-#define FLASH_AREA_IMAGE_2 FLASH_AREA_ID(image_2)
-#define FLASH_AREA_IMAGE_3 FLASH_AREA_ID(image_3)
+/*
+ * PSoC6 area defines based on file:
+ * boot/cypress/MCUBootApp/sysflash/sysflash.h
+*/
+#define FLASH_AREA_IMAGE_0 1
+#define FLASH_AREA_IMAGE_1 2
+#define FLASH_AREA_IMAGE_2 4
+#define FLASH_AREA_IMAGE_3 5
+#define FLASH_AREA_IMAGE_SWAP_STATUS 7
-#define FLASH_AREA_IMAGE_SWAP_STATUS FLASH_AREA_ID(image_scratch)
+#define BOOT_MAX_SWAP_STATUS_SECTORS 64
#endif /*__DEVICETREE_H__*/
diff --git a/sim/mcuboot-sys/csupport/keys.c b/sim/mcuboot-sys/csupport/keys.c
index 8011629..f9325be 100644
--- a/sim/mcuboot-sys/csupport/keys.c
+++ b/sim/mcuboot-sys/csupport/keys.c
@@ -256,11 +256,20 @@
#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,
diff --git a/sim/mcuboot-sys/csupport/run.c b/sim/mcuboot-sys/csupport/run.c
index fd21bfd..fd6c3ca 100644
--- a/sim/mcuboot-sys/csupport/run.c
+++ b/sim/mcuboot-sys/csupport/run.c
@@ -22,7 +22,9 @@
#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]))
@@ -90,15 +92,15 @@
return -6;
}
- if (mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0) {
+ if (mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N)) != 0) {
return -7;
}
- if (mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0) {
+ if (mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E)) != 0) {
return -8;
}
- ctx->len = mbedtls_mpi_size(&ctx->N);
+ ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));
if (*p != end) {
return -9;
@@ -140,7 +142,12 @@
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;
@@ -150,8 +157,13 @@
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;
}
@@ -173,6 +185,15 @@
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;
@@ -181,13 +202,13 @@
mbedtls_nist_kw_init(&kw);
- rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES, kek, 128, 1);
+ 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, 16, encbuf,
- &olen, 24);
+ rc = mbedtls_nist_kw_wrap(&kw, MBEDTLS_KW_MODE_KW, seckey, in_len, encbuf,
+ &olen, out_size);
done:
mbedtls_nist_kw_free(&kw);
@@ -201,9 +222,9 @@
#endif
}
-uint16_t flash_area_align(const struct flash_area *area)
+size_t flash_area_align(const struct flash_area *area)
{
- return sim_flash_align(area->fa_device_id);
+ return (size_t)sim_flash_align(area->fa_device_id);
}
uint8_t flash_area_erased_val(const struct flash_area *area)
@@ -223,14 +244,16 @@
uint32_t num_slots;
};
-int invoke_boot_go(struct sim_context *ctx, struct area_desc *adesc)
+int invoke_boot_go(struct sim_context *ctx, struct area_desc *adesc,
+ struct boot_rsp *rsp)
{
int res;
- struct boot_rsp rsp;
struct boot_loader_state *state;
#if defined(MCUBOOT_SIGN_RSA) || \
- (defined(MCUBOOT_SIGN_EC256) && defined(MCUBOOT_USE_MBED_TLS))
+ (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
@@ -241,7 +264,7 @@
sim_set_context(ctx);
if (setjmp(ctx->boot_jmpbuf) == 0) {
- res = context_boot_go(state, &rsp);
+ res = context_boot_go(state, rsp);
sim_reset_flash_areas();
sim_reset_context();
free(state);
@@ -261,53 +284,30 @@
return malloc(size);
}
-void os_free(void *mem)
-{
- free(mem);
-}
-
-void *os_realloc(void *ptr, size_t size)
-{
- return realloc(ptr, 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;
-
- // case 7: return FLASH_AREA_IMAGE_SWAP_STATUS;
}
- printf("Image flash area ID not found, image=%d, slot=%d\n", image_index, slot);
+ printf("Image flash area ID not found\n");
return -1; /* flash_area_open will fail on that */
}
-int flash_area_id_from_image_slot(int slot)
-{
- return flash_area_id_from_multi_image_slot(0, slot);
-}
-
int flash_area_open(uint8_t id, const struct flash_area **area)
{
uint32_t i;
struct area_desc *flash_areas;
- // BOOT_LOG_SIM("%s: area id=%d, num_slots=%d", __func__, id, sim_get_flash_areas()->num_slots);
-
flash_areas = sim_get_flash_areas();
for (i = 0; i < flash_areas->num_slots; i++) {
- // BOOT_LOG_SIM(" * flash_areas->slots[%d].id=%d", i, flash_areas->slots[i].id);
if (flash_areas->slots[i].id == id)
- {
- // BOOT_LOG_SIM(" * found, i=%d, id=%d", i, id);
break;
- }
}
if (i == flash_areas->num_slots) {
- printf("Unsupported area id=%d\n", id);
+ printf("Unsupported area\n");
abort();
}
@@ -354,6 +354,15 @@
ctx->jumped++;
longjmp(ctx->boot_jmpbuf, 1);
}
+
+// Align offset and length to sector size
+#ifdef MCUBOOT_SWAP_USING_STATUS
+ uint32_t sect_off = off / CY_FLASH_ALIGN * CY_FLASH_ALIGN;
+ len = ((off + len - 1) / CY_FLASH_ALIGN + 1) * CY_FLASH_ALIGN - sect_off;
+ off = sect_off;
+ BOOT_LOG_SIM("%s: erase with aligment at area=%d, off=%x, len=%x", __func__, area->fa_id, off, len);
+#endif
+
return sim_flash_erase(area->fa_device_id, area->fa_off + off, len);
}
@@ -363,22 +372,20 @@
struct area *slot;
struct area_desc *flash_areas;
- // BOOT_LOG_SIM("%s: idx=%d", __func__, idx);
-
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("flash_area_to_sectors: Unsupported area = %d\n", idx);
+ printf("Unsupported area\n");
abort();
}
slot = &flash_areas->slots[i];
if (slot->num_areas > (uint32_t)*cnt) {
- printf("Too many areas in slot: %d > %d\n", slot->num_areas, *cnt);
+ printf("Too many areas in slot\n");
abort();
}
@@ -395,22 +402,20 @@
struct area *slot;
struct area_desc *flash_areas;
- // BOOT_LOG_SIM("%s: area id=%d", __func__, fa_id);
-
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("flash_area_get_sectors: Unsupported area = %d\n", fa_id);
+ printf("Unsupported area\n");
abort();
}
slot = &flash_areas->slots[i];
if (slot->num_areas > *count) {
- printf("Too many areas in slot: %d > %d\n", slot->num_areas, *count);
+ printf("Too many areas in slot\n");
abort();
}
@@ -433,10 +438,20 @@
return 1;
}
- printf("Unsupported image area ID=%d\n", area_id);
+ printf("Unsupported image area ID\n");
abort();
}
+uint8_t flash_area_get_device_id(const struct flash_area *fa)
+{
+ return fa->fa_device_id;
+}
+
+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);
+}
+
void sim_assert(int x, const char *assertion, const char *file, unsigned int line, const char *function)
{
if (!(x)) {
@@ -463,28 +478,3 @@
{
return BOOT_MAGIC_SZ;
}
-
-void mbedtls_platform_zeroize( void *buf, size_t len )
-{
- memset( buf, 0, len );
-}
-
-int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
- void *dst, uint32_t len)
-{
- uint8_t *mem_dest;
- int rc;
-
- mem_dest = (uint8_t *)dst;
- rc = flash_area_read(fa, off, dst, len);
- if (rc) {
- return -1;
- }
-
- for (uint8_t i = 0; i < len; i++) {
- if (mem_dest[i] != flash_area_erased_val(fa)) {
- return 0;
- }
- }
- return 1;
-}
diff --git a/sim/mcuboot-sys/csupport/storage/flash_map.h b/sim/mcuboot-sys/csupport/storage/flash_map.h
index 2a6fd56..7b20453 100644
--- a/sim/mcuboot-sys/csupport/storage/flash_map.h
+++ b/sim/mcuboot-sys/csupport/storage/flash_map.h
@@ -42,6 +42,7 @@
* and match the target offset specified in download script.
*/
#include <inttypes.h>
+#include <stddef.h>
/**
* @brief Structure describing an area on a flash device.
@@ -123,7 +124,7 @@
/*
* Alignment restriction for flash writes.
*/
-uint16_t flash_area_align(const struct flash_area *);
+size_t flash_area_align(const struct flash_area *);
/*
* What is value is read from erased flash bytes.
diff --git a/sim/mcuboot-sys/src/api.rs b/sim/mcuboot-sys/src/api.rs
index a6acd53..8d1140d 100644
--- a/sim/mcuboot-sys/src/api.rs
+++ b/sim/mcuboot-sys/src/api.rs
@@ -26,6 +26,38 @@
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,
}
@@ -89,9 +121,20 @@
}
}
+/// 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,
+}
+
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());
}
/// Set the flash device to be used by the simulation. The pointer is unsafely stashed away.
@@ -165,6 +208,32 @@
}
#[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 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| {
diff --git a/sim/mcuboot-sys/src/area.rs b/sim/mcuboot-sys/src/area.rs
index f151fe4..cfbebda 100644
--- a/sim/mcuboot-sys/src/area.rs
+++ b/sim/mcuboot-sys/src/area.rs
@@ -189,8 +189,8 @@
ImageScratch = 3,
Image2 = 4,
Image3 = 5,
- //ImageSwapStatus = 7,
- //ImageSwapStatus = 3,
+// Not_used = 6,
+ ImageSwapStatus = 7,
}
impl Default for FlashId {
diff --git a/sim/mcuboot-sys/src/c.rs b/sim/mcuboot-sys/src/c.rs
index 5f518f5..5c791b8 100644
--- a/sim/mcuboot-sys/src/c.rs
+++ b/sim/mcuboot-sys/src/c.rs
@@ -1,6 +1,6 @@
// Copyright (c) 2017-2019 Linaro LTD
// Copyright (c) 2017-2019 JUUL Labs
-// Copyright (c) 2019 Arm Limited
+// Copyright (c) 2019-2021 Arm Limited
//
// SPDX-License-Identifier: Apache-2.0
@@ -10,9 +10,61 @@
use simflash::SimMultiFlash;
use crate::api;
+/// 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>, catch_asserts: bool) -> (i32, u8) {
+ counter: Option<&mut i32>, catch_asserts: bool) -> BootGoResult {
for (&dev_id, flash) in multiflash.iter_mut() {
api::set_flash(dev_id, flash);
}
@@ -26,8 +78,14 @@
c_catch_asserts: if catch_asserts { 1 } else { 0 },
boot_jmpbuf: [0; 16],
};
+ let mut rsp = api::BootRsp {
+ br_hdr: std::ptr::null(),
+ flash_dev_id: 0,
+ image_off: 0,
+ };
let result = unsafe {
- raw::invoke_boot_go(&mut sim_ctx as *mut _, &areadesc.get_c() as *const _) as i32
+ raw::invoke_boot_go(&mut sim_ctx as *mut _, &areadesc.get_c() as *const _,
+ &mut rsp as *mut _) as i32
};
let asserts = sim_ctx.c_asserts;
if let Some(c) = counter {
@@ -36,7 +94,11 @@
for &dev_id in multiflash.keys() {
api::clear_flash(dev_id);
}
- (result, asserts)
+ if result == -0x13579 {
+ BootGoResult::Stopped
+ } else {
+ BootGoResult::Normal { result, asserts, resp: rsp }
+ }
}
pub fn boot_trailer_sz(align: u32) -> u32 {
@@ -67,9 +129,12 @@
}
}
-pub fn kw_encrypt(kek: &[u8], seckey: &[u8]) -> Result<[u8; 24], &'static str> {
+pub fn kw_encrypt(kek: &[u8], seckey: &[u8], keylen: u32) -> Result<Vec<u8>, &'static str> {
unsafe {
- let mut encbuf = [0u8; 24];
+ 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);
}
@@ -79,13 +144,14 @@
mod raw {
use crate::area::CAreaDesc;
- use crate::api::CSimContext;
+ 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) -> libc::c_int;
+ pub fn invoke_boot_go(sim_ctx: *mut CSimContext, areadesc: *const CAreaDesc,
+ rsp: *mut BootRsp) -> libc::c_int;
pub fn boot_trailer_sz(min_write_sz: u32) -> u32;
pub fn boot_status_sz(min_write_sz: u32) -> u32;
diff --git a/sim/mcuboot-sys/src/lib.rs b/sim/mcuboot-sys/src/lib.rs
index 8acb246..bc3fc49 100644
--- a/sim/mcuboot-sys/src/lib.rs
+++ b/sim/mcuboot-sys/src/lib.rs
@@ -10,3 +10,43 @@
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
+ }
+}
diff --git a/sim/simflash/src/lib.rs b/sim/simflash/src/lib.rs
index c52f53e..e5ccb96 100644
--- a/sim/simflash/src/lib.rs
+++ b/sim/simflash/src/lib.rs
@@ -66,8 +66,6 @@
fn align(&self) -> usize;
fn erased_val(&self) -> u8;
-
- fn set_erase_by_sector(&mut self, enable: bool);
}
fn ebounds<T: AsRef<str>>(message: T) -> FlashError {
@@ -96,7 +94,6 @@
align: usize,
verify_writes: bool,
erased_val: u8,
- erase_by_sector: bool,
}
impl SimFlash {
@@ -133,11 +130,11 @@
// 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, usize)> {
+ 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, size));
+ return Some((sector, offset));
}
offset -= size;
}
@@ -153,21 +150,8 @@
/// 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, mut slen, ssize) = self.get_sector(offset).ok_or_else(|| ebounds("start"))?;
- let (end, mut elen, _) = self.get_sector(offset + len - 1).ok_or_else(|| ebounds("end"))?;
-
- let mut offset = offset;
- let mut len = len;
-
- if self.erase_by_sector {
- // info!("erase_by_sector: {:#X}/{:#X} -> {:#X}/{:#X}", offset, len, offset - slen, ssize);
-
- offset = offset - slen;
- len = ssize;
-
- slen = 0;
- elen = self.sectors[end] - 1;
- }
+ 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"));
@@ -283,10 +267,6 @@
fn erased_val(&self) -> u8 {
self.erased_val
}
-
- fn set_erase_by_sector(&mut self, enable: bool) {
- self.erase_by_sector = enable;
- }
}
/// It is possible to iterate over the sectors in the device, each element returning this.
@@ -339,6 +319,10 @@
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);
+
+ // PSoC style, uniform sectors.
+ let mut f3 = SimFlash::new(vec![512usize; 1024], 512, erased_val);
+ test_device(&mut f3, erased_val);
}
}
diff --git a/sim/src/caps.rs b/sim/src/caps.rs
index c626ee6..3fbf4c3 100644
--- a/sim/src/caps.rs
+++ b/sim/src/caps.rs
@@ -1,6 +1,6 @@
// Copyright (c) 2017-2019 Linaro LTD
// Copyright (c) 2019 JUUL Labs
-// Copyright (c) 2019 Arm Limited
+// Copyright (c) 2019-2021 Arm Limited
//
// SPDX-License-Identifier: Apache-2.0
@@ -25,7 +25,10 @@
DowngradePrevention = (1 << 12),
EncX25519 = (1 << 13),
Bootstrap = (1 << 14),
- SwapUsingStatus = (1 << 15),
+ Aes256 = (1 << 15),
+ RamLoad = (1 << 16),
+ DirectXip = (1 << 17),
+ SwapUsingStatus = (1 << 18),
}
impl Caps {
@@ -39,6 +42,12 @@
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" {
diff --git a/sim/src/image.rs b/sim/src/image.rs
index 6bd14c5..29ddedd 100644
--- a/sim/src/image.rs
+++ b/sim/src/image.rs
@@ -1,6 +1,6 @@
// Copyright (c) 2019 Linaro LTD
// Copyright (c) 2019-2020 JUUL Labs
-// Copyright (c) 2019 Arm Limited
+// Copyright (c) 2019-2021 Arm Limited
//
// SPDX-License-Identifier: Apache-2.0
@@ -19,22 +19,26 @@
rngs::SmallRng,
};
use std::{
- collections::HashSet,
+ collections::{BTreeMap, HashSet},
io::{Cursor, Write},
mem,
slice,
};
-use aes_ctr::{
+use aes::{
+ Aes128,
Aes128Ctr,
- stream_cipher::{
- generic_array::GenericArray,
- NewStreamCipher,
- SyncStreamCipher,
- },
+ Aes256,
+ Aes256Ctr,
+ NewBlockCipher,
};
+use cipher::{
+ FromBlockCipher,
+ generic_array::GenericArray,
+ StreamCipher,
+ };
use simflash::{Flash, SimFlash, SimMultiFlash};
-use mcuboot_sys::{c, AreaDesc, FlashId};
+use mcuboot_sys::{c, AreaDesc, FlashId, RamBlock};
use crate::{
ALL_DEVICES,
DeviceName,
@@ -50,6 +54,11 @@
UpgradeInfo,
};
use crate::tlv::{ManifestGen, TlvGen, TlvFlags};
+use typenum::{U32, U16};
+
+/// For testing, use a non-zero offset for the ram-load, to make sure the offset is getting used
+/// properly, but the value is not really that important.
+const RAM_LOAD_ADDR: u32 = 1024;
/// A builder for Images. This describes a single run of the simulator,
/// capturing the configuration of a particular set of devices, including
@@ -59,6 +68,7 @@
flash: SimMultiFlash,
areadesc: AreaDesc,
slots: Vec<[SlotInfo; 2]>,
+ ram: RamData,
}
/// Images represents the state of a simulation for a given set of images.
@@ -69,6 +79,7 @@
areadesc: AreaDesc,
images: Vec<OneImage>,
total_count: Option<i32>,
+ ram: RamData,
}
/// When doing multi-image, there is an instance of this information for
@@ -83,10 +94,34 @@
/// is just the unencrypted payload. For encrypted images, we store both
/// the encrypted and the plaintext.
struct ImageData {
+ size: usize,
plain: Vec<u8>,
cipher: Option<Vec<u8>>,
}
+/// For the RamLoad test cases, we need a contiguous area of RAM to load these images into. For
+/// multi-image builds, these may not correspond with the offsets. This has to be computed early,
+/// before images are built, because each image contains the offset where the image is to be loaded
+/// in the header, which is contained within the signature.
+#[derive(Clone, Debug)]
+struct RamData {
+ places: BTreeMap<SlotKey, SlotPlace>,
+ total: u32,
+}
+
+/// Every slot is indexed by this key.
+#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+struct SlotKey {
+ dev_id: u8,
+ base_off: usize,
+}
+
+#[derive(Clone, Debug)]
+struct SlotPlace {
+ offset: u32,
+ size: u32,
+}
+
impl ImagesBuilder {
/// Construct a new image builder for the given device. Returns
/// Some(builder) if is possible to test this configuration, or None if
@@ -148,10 +183,13 @@
slots.push([primary, secondary]);
}
+ let ram = RamData::new(&slots);
+
Ok(ImagesBuilder {
flash,
areadesc,
slots,
+ ram,
})
}
@@ -174,16 +212,17 @@
pub fn make_no_upgrade_image(self, deps: &DepTest) -> Images {
let num_images = self.num_images();
let mut flash = self.flash;
+ let ram = self.ram.clone(); // TODO: This is wasteful.
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep: Box<dyn Depender> = if num_images > 1 {
Box::new(PairDep::new(num_images, image_num, deps))
} else {
Box::new(BoringDep::new(image_num, deps))
};
- let primaries = install_image(&mut flash, &slots[0], 42784, &*dep, false);
+ let primaries = install_image(&mut flash, &slots[0], 42784, &ram, &*dep, false);
let upgrades = match deps.depends[image_num] {
DepType::NoUpgrade => install_no_image(),
- _ => install_image(&mut flash, &slots[1], 46928, &*dep, false)
+ _ => install_image(&mut flash, &slots[1], 46928, &ram, &*dep, false)
};
OneImage {
slots,
@@ -196,6 +235,7 @@
areadesc: self.areadesc,
images,
total_count: None,
+ ram: self.ram,
}
}
@@ -205,6 +245,11 @@
mark_upgrade(&mut images.flash, &image.slots[1]);
}
+ // The count is meaningless if no flash operations are performed.
+ if !Caps::modifies_flash() {
+ return images;
+ }
+
// upgrades without fails, counts number of flash operations
let total_count = match images.run_basic_upgrade(permanent) {
Some(v) => v,
@@ -222,10 +267,11 @@
pub fn make_bad_secondary_slot_image(self) -> Images {
let mut bad_flash = self.flash;
+ let ram = self.ram.clone(); // TODO: Avoid this clone.
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
- let primaries = install_image(&mut bad_flash, &slots[0], 32784, &dep, false);
- let upgrades = install_image(&mut bad_flash, &slots[1], 41928, &dep, true);
+ let primaries = install_image(&mut bad_flash, &slots[0], 32784, &ram, &dep, false);
+ let upgrades = install_image(&mut bad_flash, &slots[1], 41928, &ram, &dep, true);
OneImage {
slots,
primaries,
@@ -236,14 +282,16 @@
areadesc: self.areadesc,
images,
total_count: None,
+ ram: self.ram,
}
}
pub fn make_erased_secondary_image(self) -> Images {
let mut flash = self.flash;
+ let ram = self.ram.clone(); // TODO: Avoid this clone.
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
- let primaries = install_image(&mut flash, &slots[0], 32784, &dep, false);
+ let primaries = install_image(&mut flash, &slots[0], 32784, &ram, &dep, false);
let upgrades = install_no_image();
OneImage {
slots,
@@ -255,15 +303,17 @@
areadesc: self.areadesc,
images,
total_count: None,
+ ram: self.ram,
}
}
pub fn make_bootstrap_image(self) -> Images {
let mut flash = self.flash;
+ let ram = self.ram.clone(); // TODO: Avoid this clone.
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_no_image();
- let upgrades = install_image(&mut flash, &slots[1], 32784, &dep, false);
+ let upgrades = install_image(&mut flash, &slots[1], 32784, &ram, &dep, false);
OneImage {
slots,
primaries,
@@ -274,15 +324,14 @@
areadesc: self.areadesc,
images,
total_count: None,
+ ram: self.ram,
}
}
/// Build the Flash and area descriptor for a given device.
pub fn make_device(device: DeviceName, align: usize, erased_val: u8) -> (SimMultiFlash, AreaDesc, &'static [Caps]) {
- info!(" +++ Make new device...");
match device {
DeviceName::Stm32f4 => {
- info!("DeviceName::Stm32f4");
// STM style flash. Large sectors, with a large scratch area.
let dev = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024,
64 * 1024,
@@ -300,7 +349,6 @@
(flash, areadesc, &[Caps::SwapUsingMove, Caps::SwapUsingStatus])
}
DeviceName::K64f => {
- info!("DeviceName::K64f");
// NXP style flash. Small sectors, one small sector for scratch.
let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
@@ -316,7 +364,6 @@
(flash, areadesc, &[Caps::SwapUsingStatus])
}
DeviceName::K64fBig => {
- info!("DeviceName::K64fBig");
// Simulating an STM style flash on top of an NXP style flash. Underlying flash device
// uses small sectors, but we tell the bootloader they are large.
let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
@@ -333,7 +380,6 @@
(flash, areadesc, &[Caps::SwapUsingMove, Caps::SwapUsingStatus])
}
DeviceName::Nrf52840 => {
- info!("DeviceName::Nrf52840");
// Simulating the flash on the nrf52840 with partitions set up so that the scratch size
// does not divide into the image size.
let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
@@ -350,7 +396,6 @@
(flash, areadesc, &[Caps::SwapUsingStatus])
}
DeviceName::Nrf52840UnequalSlots => {
- info!("DeviceName::Nrf52840UnequalSlots");
let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
let dev_id = 0;
@@ -364,7 +409,6 @@
(flash, areadesc, &[Caps::SwapUsingScratch, Caps::OverwriteUpgrade, Caps::SwapUsingStatus])
}
DeviceName::Nrf52840SpiFlash => {
- info!("DeviceName::Nrf52840SpiFlash");
// Simulate nrf52840 with external SPI flash. The external SPI flash
// has a larger sector size so for now store scratch on that flash.
let dev0 = SimFlash::new(vec![4096; 128], align as usize, erased_val);
@@ -384,7 +428,6 @@
(flash, areadesc, &[Caps::SwapUsingMove, Caps::SwapUsingStatus])
}
DeviceName::K64fMulti => {
- info!("DeviceName::K64fMulti");
// NXP style flash, but larger, to support multiple images.
let dev = SimFlash::new(vec![4096; 256], align as usize, erased_val);
@@ -401,32 +444,21 @@
flash.insert(dev_id, dev);
(flash, areadesc, &[Caps::SwapUsingStatus])
}
- DeviceName::PSoC6Multi => {
- info!("DeviceName::PSoC6Multi");
- // NXP style flash, but larger, to support multiple images.
+ DeviceName::PSoC6 => {
+ // PSoC style flash of 512K, single-image case
+ let dev = SimFlash::new(vec![512; 1024], align as usize, erased_val);
+ let dev_id = 0;
let mut areadesc = AreaDesc::new();
+ areadesc.add_flash_sectors(dev_id, &dev);
+ areadesc.add_image(0x018000, 0x010000, FlashId::Image0, dev_id);
+ areadesc.add_image(0x028000, 0x010000, FlashId::Image1, dev_id);
+ areadesc.add_image(0x039800, 0x001000, FlashId::ImageScratch, dev_id);
+ areadesc.add_image(0x038000, 0x001800, FlashId::ImageSwapStatus, dev_id);
+
let mut flash = SimMultiFlash::new();
-
- // let dev0 = SimFlash::new(vec![4096; 256], align as usize, 0);
- let mut dev0 = SimFlash::new(vec![512; 1024], align as usize, 0);
- dev0.set_verify_writes(false);
- dev0.set_erase_by_sector(true);
-
- areadesc.add_flash_sectors(0, &dev0);
- areadesc.add_image(0x020000, 0x020000, FlashId::Image0, 0);
- areadesc.add_image(0x040000, 0x020000, FlashId::Image1, 0);
- areadesc.add_image(0x060000, 0x008000, FlashId::ImageScratch, 0);
- flash.insert(0, dev0);
-
- // let dev1 = SimFlash::new(vec![4096; 256], align as usize, erased_val);
- // areadesc.add_flash_sectors(1, &dev1);
- // areadesc.add_image(0x080000, 0x020000, FlashId::Image2, 0);
- // areadesc.add_image(0x0a0000, 0x020000, FlashId::Image3, 1);
- // flash.insert(1, dev1);
-
- // (flash, areadesc, &[])
- (flash, areadesc, &[Caps::SwapUsingScratch, Caps::SwapUsingMove])
+ flash.insert(dev_id, dev);
+ (flash, areadesc, &[Caps::SwapUsingMove])
}
}
}
@@ -461,8 +493,7 @@
if Caps::Bootstrap.present() {
info!("Try bootstraping image in the primary");
- let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if result != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -490,17 +521,21 @@
/// Test a simple upgrade, with dependencies given, and verify that the
/// image does as is described in the test.
pub fn run_check_deps(&self, deps: &DepTest) -> bool {
+ if !Caps::modifies_flash() {
+ return false;
+ }
+
let (flash, _) = self.try_upgrade(None, true);
self.verify_dep_images(&flash, deps)
}
fn is_swap_upgrade(&self) -> bool {
- Caps::SwapUsingScratch.present() || Caps::SwapUsingMove.present() || Caps::SwapUsingStatus.present()
+ Caps::SwapUsingScratch.present() || Caps::SwapUsingMove.present()
}
pub fn run_basic_revert(&self) -> bool {
- if Caps::OverwriteUpgrade.present() {
+ if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
return false;
}
@@ -522,6 +557,10 @@
}
pub fn run_perm_with_fails(&self) -> bool {
+ if !Caps::modifies_flash() {
+ return false;
+ }
+
let mut fails = 0;
let total_flash_ops = self.total_count.unwrap();
@@ -563,6 +602,10 @@
}
pub fn run_perm_with_random_fails(&self, total_fails: usize) -> bool {
+ if !Caps::modifies_flash() {
+ return false;
+ }
+
let mut fails = 0;
let total_flash_ops = self.total_count.unwrap();
let (flash, total_counts) = self.try_random_fails(total_flash_ops, total_fails);
@@ -601,7 +644,7 @@
}
pub fn run_revert_with_fails(&self) -> bool {
- if Caps::OverwriteUpgrade.present() {
+ if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
return false;
}
@@ -621,7 +664,7 @@
}
pub fn run_norevert(&self) -> bool {
- if Caps::OverwriteUpgrade.present() {
+ if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
return false;
}
@@ -631,8 +674,7 @@
info!("Try norevert");
// First do a normal upgrade...
- let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if result != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -665,8 +707,7 @@
fails += 1;
}
- let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if result != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Failed second boot");
fails += 1;
}
@@ -701,8 +742,7 @@
info!("Try no downgrade");
// First, do a normal upgrade.
- let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if result != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -723,6 +763,11 @@
// image_ok set while there is no image on the secondary slot, so no revert
// should ever happen...
pub fn run_norevert_newimage(&self) -> bool {
+ if !Caps::modifies_flash() {
+ info!("Skipping run_norevert_newimage, as configuration doesn't modify flash");
+ return false;
+ }
+
let mut flash = self.flash.clone();
let mut fails = 0;
@@ -739,8 +784,7 @@
}
// Run the bootloader...
- let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if result != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -777,6 +821,12 @@
info!("Try upgrade image with bad signature");
+ // Only perform this test if an upgrade is expected to happen.
+ if !Caps::modifies_flash() {
+ info!("Skipping upgrade image with bad signature");
+ return false;
+ }
+
self.mark_upgrades(&mut flash, 0);
self.mark_permanent_upgrades(&mut flash, 0);
self.mark_upgrades(&mut flash, 1);
@@ -788,8 +838,7 @@
}
// Run the bootloader...
- let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if result != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -815,6 +864,10 @@
// Should detect there is a leftover trailer in an otherwise erased
// secondary slot and erase its trailer.
pub fn run_secondary_leftover_trailer(&self) -> bool {
+ if !Caps::modifies_flash() {
+ return false;
+ }
+
let mut flash = self.flash.clone();
let mut fails = 0;
@@ -825,8 +878,7 @@
self.mark_upgrades(&mut flash, 1);
// Run the bootloader...
- let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if result != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -861,7 +913,7 @@
/// allowing for fails in the status area. This should run to the end
/// and warn that write fails were detected...
pub fn run_with_status_fails_complete(&self) -> bool {
- if !Caps::ValidatePrimarySlot.present() {
+ if !Caps::ValidatePrimarySlot.present() || !Caps::modifies_flash() {
return false;
}
@@ -873,15 +925,15 @@
self.mark_permanent_upgrades(&mut flash, 1);
self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
- let (result, asserts) = c::boot_go(&mut flash, &self.areadesc, None, true);
- if result != 0 {
+ let result = c::boot_go(&mut flash, &self.areadesc, None, true);
+ if !result.success() {
warn!("Failed!");
fails += 1;
}
// Failed writes to the marked "bad" region don't assert anymore.
// Any detected assert() is happening in another part of the code.
- if asserts != 0 {
+ if result.asserts() != 0 {
warn!("At least one assert() was called");
fails += 1;
}
@@ -899,8 +951,7 @@
info!("validate primary slot enabled; \
re-run of boot_go should just work");
- let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if result != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Failed!");
fails += 1;
}
@@ -916,7 +967,7 @@
/// allowing for fails in the status area. This should run to the end
/// and warn that write fails were detected...
pub fn run_with_status_fails_with_reset(&self) -> bool {
- if Caps::OverwriteUpgrade.present() {
+ if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
false
} else if Caps::ValidatePrimarySlot.present() {
@@ -932,7 +983,7 @@
self.mark_bad_status_with_rate(&mut flash, 0, 0.5);
// Should not fail, writing to bad regions does not assert
- let (_, asserts) = c::boot_go(&mut flash, &self.areadesc, Some(&mut count), true);
+ let asserts = c::boot_go(&mut flash, &self.areadesc, Some(&mut count), true).asserts();
if asserts != 0 {
warn!("At least one assert() was called");
fails += 1;
@@ -941,7 +992,7 @@
self.reset_bad_status(&mut flash, 0);
info!("Resuming an interrupted swap operation");
- let (_, asserts) = c::boot_go(&mut flash, &self.areadesc, None, true);
+ let asserts = c::boot_go(&mut flash, &self.areadesc, None, true).asserts();
// This might throw no asserts, for large sector devices, where
// a single failure writing is indistinguishable from no failure,
@@ -968,7 +1019,7 @@
self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
// This is expected to fail while writing to bad regions...
- let (_, asserts) = c::boot_go(&mut flash, &self.areadesc, None, true);
+ let asserts = c::boot_go(&mut flash, &self.areadesc, None, true).asserts();
if asserts == 0 {
warn!("No assert() detected");
fails += 1;
@@ -978,6 +1029,78 @@
}
}
+ /// Test the direct XIP configuration. With this mode, flash images are never moved, and the
+ /// bootloader merely selects which partition is the proper one to boot.
+ pub fn run_direct_xip(&self) -> bool {
+ if !Caps::DirectXip.present() {
+ return false;
+ }
+
+ // Clone the flash so we can tell if unchanged.
+ let mut flash = self.flash.clone();
+
+ let result = c::boot_go(&mut flash, &self.areadesc, None, true);
+
+ // Ensure the boot was successful.
+ let resp = if let Some(resp) = result.resp() {
+ resp
+ } else {
+ panic!("Boot didn't return a valid result");
+ };
+
+ // This configuration should always try booting from the first upgrade slot.
+ if let Some((offset, _, dev_id)) = self.areadesc.find(FlashId::Image1) {
+ assert_eq!(offset, resp.image_off as usize);
+ assert_eq!(dev_id, resp.flash_dev_id);
+ } else {
+ panic!("Unable to find upgrade image");
+ }
+ false
+ }
+
+ /// Test the ram-loading.
+ pub fn run_ram_load(&self) -> bool {
+ if !Caps::RamLoad.present() {
+ return false;
+ }
+
+ // Clone the flash so we can tell if unchanged.
+ let mut flash = self.flash.clone();
+
+ // Setup ram based on the ram configuration we determined earlier for the images.
+ let ram = RamBlock::new(self.ram.total - RAM_LOAD_ADDR, RAM_LOAD_ADDR);
+
+ // println!("Ram: {:#?}", self.ram);
+
+ // Verify that the images area loaded into this.
+ let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc, None, true));
+ if !result.success() {
+ error!("Failed to execute ram-load");
+ return true;
+ }
+
+ // Verify each image.
+ for image in &self.images {
+ let place = self.ram.lookup(&image.slots[0]);
+ let ram_image = ram.borrow_part(place.offset as usize - RAM_LOAD_ADDR as usize,
+ place.size as usize);
+ let src_sz = image.upgrades.size();
+ if src_sz > ram_image.len() {
+ error!("Image ended up too large, nonsensical");
+ return true;
+ }
+ let src_image = &image.upgrades.plain[0..src_sz];
+ let ram_image = &ram_image[0..src_sz];
+ if ram_image != src_image {
+ error!("Image not loaded correctly");
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
/// Adds a new flash area that fails statistically
fn mark_bad_status_with_rate(&self, flash: &mut SimMultiFlash, slot: usize,
rate: f32) {
@@ -1028,18 +1151,18 @@
let mut counter = stop.unwrap_or(0);
let (first_interrupted, count) = match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
- (-0x13579, _) => (true, stop.unwrap()),
- (0, _) => (false, -counter),
- (x, _) => panic!("Unknown return: {}", x),
+ x if x.interrupted() => (true, stop.unwrap()),
+ x if x.success() => (false, -counter),
+ x => panic!("Unknown return: {:?}", x),
};
counter = 0;
if first_interrupted {
// fl.dump();
match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
- (-0x13579, _) => panic!("Shouldn't stop again"),
- (0, _) => (),
- (x, _) => panic!("Unknown return: {}", x),
+ x if x.interrupted() => panic!("Shouldn't stop again"),
+ x if x.success() => (),
+ x => panic!("Unknown return: {:?}", x),
}
}
@@ -1052,7 +1175,7 @@
// fl.write_file("image0.bin").unwrap();
for i in 0 .. count {
info!("Running boot pass {}", i + 1);
- assert_eq!(c::boot_go(&mut flash, &self.areadesc, None, false), (0, 0));
+ assert!(c::boot_go(&mut flash, &self.areadesc, None, false).success_no_asserts());
}
flash
}
@@ -1062,8 +1185,7 @@
let mut fails = 0;
let mut counter = stop;
- let (x, _) = c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false);
- if x != -0x13579 {
+ if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false).interrupted() {
warn!("Should have stopped test at interruption point");
fails += 1;
}
@@ -1075,8 +1197,7 @@
fails += 1;
}
- let (x, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if x != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Should have finished test upgrade");
fails += 1;
}
@@ -1104,14 +1225,12 @@
// Do Revert
let mut counter = stop;
- let (x, _) = c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false);
- if x != -0x13579 {
+ if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false).interrupted() {
warn!("Should have stopped revert at interruption point");
fails += 1;
}
- let (x, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if x != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Should have finished revert upgrade");
fails += 1;
}
@@ -1138,8 +1257,7 @@
fails += 1;
}
- let (x, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
- if x != 0 {
+ if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
warn!("Should have finished 3rd boot");
fails += 1;
}
@@ -1166,20 +1284,20 @@
let mut resets = vec![0i32; count];
let mut remaining_ops = total_ops;
for reset in &mut resets {
- let reset_counter = rng.gen_range(1, remaining_ops / 2);
+ let reset_counter = rng.gen_range(1 ..= remaining_ops / 2);
let mut counter = reset_counter;
match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
- (0, _) | (-0x13579, _) => (),
- (x, _) => panic!("Unknown return: {}", x),
+ x if x.interrupted() => (),
+ x => panic!("Unknown return: {:?}", x),
}
remaining_ops -= reset_counter;
*reset = reset_counter;
}
match c::boot_go(&mut flash, &self.areadesc, None, false) {
- (-0x13579, _) => panic!("Should not be have been interrupted!"),
- (0, _) => (),
- (x, _) => panic!("Unknown return: {}", x),
+ x if x.interrupted() => panic!("Should not be have been interrupted!"),
+ x if x.success() => (),
+ x => panic!("Unknown return: {:?}", x),
}
(flash, resets)
@@ -1266,6 +1384,40 @@
}
}
+impl RamData {
+ // TODO: This is not correct. The second slot of each image should be at the same address as
+ // the primary.
+ fn new(slots: &[[SlotInfo; 2]]) -> RamData {
+ let mut addr = RAM_LOAD_ADDR;
+ let mut places = BTreeMap::new();
+ // println!("Setup:-------------");
+ for imgs in slots {
+ for si in imgs {
+ // println!("Setup: si: {:?}", si);
+ let offset = addr;
+ let size = si.len as u32;
+ places.insert(SlotKey {
+ dev_id: si.dev_id,
+ base_off: si.base_off,
+ }, SlotPlace { offset, size });
+ // println!(" load: offset: {}, size: {}", offset, size);
+ }
+ addr += imgs[0].len as u32;
+ }
+ RamData {
+ places,
+ total: addr,
+ }
+ }
+
+ /// Lookup the ram data associated with a given flash partition. We just panic if not present,
+ /// because all slots used should be in the map.
+ fn lookup(&self, slot: &SlotInfo) -> &SlotPlace {
+ self.places.get(&SlotKey{dev_id: slot.dev_id, base_off: slot.base_off})
+ .expect("RamData should contain all slots")
+ }
+}
+
/// Show the flash layout.
#[allow(dead_code)]
fn show_flash(flash: &dyn Flash) {
@@ -1280,6 +1432,7 @@
/// Install a "program" into the given image. This fakes the image header, or at least all of the
/// fields used by the given code. Returns a copy of the image that was written.
fn install_image(flash: &mut SimMultiFlash, slot: &SlotInfo, len: usize,
+ ram: &RamData,
deps: &dyn Depender, bad_sig: bool) -> ImageData {
let offset = slot.base_off;
let slot_len = slot.len;
@@ -1294,10 +1447,17 @@
const HDR_SIZE: usize = 32;
+ let place = ram.lookup(&slot);
+ let load_addr = if Caps::RamLoad.present() {
+ place.offset
+ } else {
+ 0
+ };
+
// Generate a boot header. Note that the size doesn't include the header.
let header = ImageHeader {
magic: tlv.get_magic(),
- load_addr: 0,
+ load_addr,
hdr_size: HDR_SIZE as u16,
protect_tlv_size: tlv.protect_size(),
img_size: len as u32,
@@ -1329,17 +1489,27 @@
tlv.add_bytes(&b_img);
// Generate encrypted images
- let flag = TlvFlags::ENCRYPTED as u32;
- let is_encrypted = (tlv.get_flags() & flag) == flag;
+ let flag = TlvFlags::ENCRYPTED_AES128 as u32 | TlvFlags::ENCRYPTED_AES256 as u32;
+ let is_encrypted = (tlv.get_flags() & flag) != 0;
let mut b_encimg = vec![];
if is_encrypted {
+ let flag = TlvFlags::ENCRYPTED_AES256 as u32;
+ let aes256 = (tlv.get_flags() & flag) == flag;
tlv.generate_enc_key();
let enc_key = tlv.get_enc_key();
- let key = GenericArray::from_slice(enc_key.as_slice());
let nonce = GenericArray::from_slice(&[0; 16]);
- let mut cipher = Aes128Ctr::new(&key, &nonce);
b_encimg = b_img.clone();
- cipher.apply_keystream(&mut b_encimg);
+ if aes256 {
+ let key: &GenericArray<u8, U32> = GenericArray::from_slice(enc_key.as_slice());
+ let block = Aes256::new(&key);
+ let mut cipher = Aes256Ctr::from_block_cipher(block, &nonce);
+ cipher.apply_keystream(&mut b_encimg);
+ } else {
+ let key: &GenericArray<u8, U16> = GenericArray::from_slice(enc_key.as_slice());
+ let block = Aes128::new(&key);
+ let mut cipher = Aes128Ctr::from_block_cipher(block, &nonce);
+ cipher.apply_keystream(&mut b_encimg);
+ }
}
// Build the TLV itself.
@@ -1357,6 +1527,7 @@
// Pad the buffer to a multiple of the flash alignment.
let align = dev.align();
+ let image_sz = buf.len();
while buf.len() % align != 0 {
buf.push(dev.erased_val());
}
@@ -1399,6 +1570,7 @@
dev.read(offset, &mut copy).unwrap();
ImageData {
+ size: image_sz,
plain: copy,
cipher: enc_copy,
}
@@ -1425,6 +1597,7 @@
}
ImageData {
+ size: image_sz,
plain: copy,
cipher: enc_copy,
}
@@ -1434,6 +1607,7 @@
/// Install no image. This is used when no upgrade happens.
fn install_no_image() -> ImageData {
ImageData {
+ size: 0,
plain: vec![],
cipher: None,
}
@@ -1443,32 +1617,36 @@
if Caps::EcdsaP224.present() {
panic!("Ecdsa P224 not supported in Simulator");
}
+ let mut aes_key_size = 128;
+ if Caps::Aes256.present() {
+ aes_key_size = 256;
+ }
if Caps::EncKw.present() {
if Caps::RSA2048.present() {
- TlvGen::new_rsa_kw()
+ TlvGen::new_rsa_kw(aes_key_size)
} else if Caps::EcdsaP256.present() {
- TlvGen::new_ecdsa_kw()
+ TlvGen::new_ecdsa_kw(aes_key_size)
} else {
- TlvGen::new_enc_kw()
+ TlvGen::new_enc_kw(aes_key_size)
}
} else if Caps::EncRsa.present() {
if Caps::RSA2048.present() {
- TlvGen::new_sig_enc_rsa()
+ TlvGen::new_sig_enc_rsa(aes_key_size)
} else {
- TlvGen::new_enc_rsa()
+ TlvGen::new_enc_rsa(aes_key_size)
}
} else if Caps::EncEc256.present() {
if Caps::EcdsaP256.present() {
- TlvGen::new_ecdsa_ecies_p256()
+ TlvGen::new_ecdsa_ecies_p256(aes_key_size)
} else {
- TlvGen::new_ecies_p256()
+ TlvGen::new_ecies_p256(aes_key_size)
}
} else if Caps::EncX25519.present() {
if Caps::Ed25519.present() {
- TlvGen::new_ed25519_ecies_x25519()
+ TlvGen::new_ed25519_ecies_x25519(aes_key_size)
} else {
- TlvGen::new_ecies_x25519()
+ TlvGen::new_ecies_x25519(aes_key_size)
}
} else {
// The non-encrypted configuration.
@@ -1499,6 +1677,10 @@
_ => panic!("Invalid slot requested"),
}
}
+
+ fn size(&self) -> usize {
+ self.size
+ }
}
/// Verify that given image is present in the flash at the given offset.
@@ -1691,6 +1873,7 @@
const BOOT_FLAG_UNSET: Option<u8> = Some(3);
/// Write out the magic so that the loader tries doing an upgrade.
+#[cfg(not(feature = "swap-status"))]
pub fn mark_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
let dev = flash.get_mut(&slot.dev_id).unwrap();
let align = dev.align();
@@ -1707,8 +1890,24 @@
}
}
+/// Write out the magic so that the loader tries doing an upgrade.
+#[cfg(feature = "swap-status")]
+pub fn mark_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
+ let dev = flash.get_mut(&slot.dev_id).unwrap();
+ let align = dev.align();
+ let offset = slot.trailer_off + c::boot_max_align() * 4;
+ let mask = align - 1;
+ let sector_off = offset & !mask;
+ let mut buf = vec![dev.erased_val(); align];
+ dev.read(sector_off, &mut buf).unwrap();
+ buf[(offset & mask)..].copy_from_slice(MAGIC);
+ dev.erase(sector_off, align).unwrap();
+ dev.write(sector_off, &buf).unwrap();
+}
+
/// Writes the image_ok flag which, guess what, tells the bootloader
/// the this image is ok (not a test, and no revert is to be performed).
+#[cfg(not(feature = "swap-status"))]
fn mark_permanent_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
// Overwrite mode always is permanent, and only the magic is used in
// the trailer. To avoid problems with large write sizes, don't try to
@@ -1725,9 +1924,32 @@
dev.write(off, &ok[..align]).unwrap();
}
+/// Writes the image_ok flag which, guess what, tells the bootloader
+/// the this image is ok (not a test, and no revert is to be performed).
+#[cfg(feature = "swap-status")]
+fn mark_permanent_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
+ // Overwrite mode always is permanent, and only the magic is used in
+ // the trailer. To avoid problems with large write sizes, don't try to
+ // set anything in this case.
+ if Caps::OverwriteUpgrade.present() {
+ return;
+ }
+
+ let dev = flash.get_mut(&slot.dev_id).unwrap();
+ let align:usize = dev.align();
+ let mask:usize = align - 1;
+ let ok_off:usize = slot.trailer_off + c::boot_max_align() * 3;
+ let sector_off:usize = ok_off & !mask;
+ let mut buf = vec![dev.erased_val(); align];
+ dev.read(sector_off, &mut buf).unwrap();
+ buf[ok_off & mask] = 1u8;
+ dev.erase(sector_off, align).unwrap();
+ dev.write(sector_off, &buf[..align]).unwrap();
+}
+
// Drop some pseudo-random gibberish onto the data.
fn splat(data: &mut [u8], seed: usize) {
- let mut seed_block = [0u8; 16];
+ let mut seed_block = [0u8; 32];
let mut buf = Cursor::new(&mut seed_block[..]);
buf.write_u32::<LittleEndian>(0x135782ea).unwrap();
buf.write_u32::<LittleEndian>(0x92184728).unwrap();
@@ -1754,11 +1976,18 @@
}
#[cfg(not(feature = "large-write"))]
+#[cfg(not(feature = "swap-status"))]
fn test_alignments() -> &'static [usize] {
&[1, 2, 4, 8]
}
#[cfg(feature = "large-write")]
+#[cfg(not(feature = "swap-status"))]
fn test_alignments() -> &'static [usize] {
&[1, 2, 4, 8, 128, 512]
}
+
+#[cfg(feature = "swap-status")]
+fn test_alignments() -> &'static [usize] {
+ &[512]
+}
diff --git a/sim/src/lib.rs b/sim/src/lib.rs
index 4203c0e..69f13f1 100644
--- a/sim/src/lib.rs
+++ b/sim/src/lib.rs
@@ -63,8 +63,10 @@
#[derive(Copy, Clone, Debug, Deserialize)]
pub enum DeviceName {
- Stm32f4, K64f, K64fBig, K64fMulti, Nrf52840, Nrf52840SpiFlash,
- Nrf52840UnequalSlots, PSoC6Multi,
+ Stm32f4,
+ K64f, K64fBig, K64fMulti,
+ Nrf52840, Nrf52840SpiFlash, Nrf52840UnequalSlots,
+ PSoC6
}
pub static ALL_DEVICES: &[DeviceName] = &[
@@ -75,7 +77,7 @@
DeviceName::Nrf52840,
DeviceName::Nrf52840SpiFlash,
DeviceName::Nrf52840UnequalSlots,
- DeviceName::PSoC6Multi,
+ DeviceName::PSoC6
];
impl fmt::Display for DeviceName {
@@ -88,7 +90,7 @@
DeviceName::Nrf52840 => "nrf52840",
DeviceName::Nrf52840SpiFlash => "Nrf52840SpiFlash",
DeviceName::Nrf52840UnequalSlots => "Nrf52840UnequalSlots",
- DeviceName::PSoC6Multi => "psoc6multi",
+ DeviceName::PSoC6 => "PSoC6"
};
f.write_str(name)
}
diff --git a/sim/src/tlv.rs b/sim/src/tlv.rs
index b6c3c96..6680b4f 100644
--- a/sim/src/tlv.rs
+++ b/sim/src/tlv.rs
@@ -1,5 +1,6 @@
// Copyright (c) 2017-2020 Linaro LTD
// Copyright (c) 2017-2020 JUUL Labs
+// Copyright (c) 2021 Arm Limited
//
// SPDX-License-Identifier: Apache-2.0
@@ -16,6 +17,8 @@
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};
@@ -27,15 +30,19 @@
ECDSA_P256_SHA256_ASN1_SIGNING,
Ed25519KeyPair,
};
-use aes_ctr::{
+use aes::{
+ Aes128,
Aes128Ctr,
- stream_cipher::{
- generic_array::GenericArray,
- NewStreamCipher,
- SyncStreamCipher,
- },
+ 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)]
@@ -49,7 +56,7 @@
RSA3072 = 0x23,
ED25519 = 0x24,
ENCRSA2048 = 0x30,
- ENCKW128 = 0x31,
+ ENCKW = 0x31,
ENCEC256 = 0x32,
ENCX25519 = 0x33,
DEPENDENCY = 0x40,
@@ -59,8 +66,9 @@
pub enum TlvFlags {
PIC = 0x01,
NON_BOOTABLE = 0x02,
- ENCRYPTED = 0x04,
+ ENCRYPTED_AES128 = 0x04,
RAM_LOAD = 0x20,
+ ENCRYPTED_AES256 = 0x08,
}
/// A generator for manifests. The format of the manifest can be either a
@@ -115,8 +123,6 @@
version: ImageVersion,
}
-const AES_KEY_LEN: usize = 16;
-
impl TlvGen {
/// Construct a new tlv generator that will only contain a hash of the data.
#[allow(dead_code)]
@@ -160,81 +166,126 @@
}
#[allow(dead_code)]
- pub fn new_enc_rsa() -> TlvGen {
+ 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: TlvFlags::ENCRYPTED as u32,
+ flags: flag,
kinds: vec![TlvKinds::SHA256, TlvKinds::ENCRSA2048],
..Default::default()
}
}
#[allow(dead_code)]
- pub fn new_sig_enc_rsa() -> TlvGen {
+ 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: TlvFlags::ENCRYPTED as u32,
+ flags: flag,
kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCRSA2048],
..Default::default()
}
}
#[allow(dead_code)]
- pub fn new_enc_kw() -> TlvGen {
+ 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: TlvFlags::ENCRYPTED as u32,
- kinds: vec![TlvKinds::SHA256, TlvKinds::ENCKW128],
+ flags: flag,
+ kinds: vec![TlvKinds::SHA256, TlvKinds::ENCKW],
..Default::default()
}
}
#[allow(dead_code)]
- pub fn new_rsa_kw() -> TlvGen {
+ 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: TlvFlags::ENCRYPTED as u32,
- kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCKW128],
+ flags: flag,
+ kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCKW],
..Default::default()
}
}
#[allow(dead_code)]
- pub fn new_ecdsa_kw() -> TlvGen {
+ 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: TlvFlags::ENCRYPTED as u32,
- kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256, TlvKinds::ENCKW128],
+ flags: flag,
+ kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256, TlvKinds::ENCKW],
..Default::default()
}
}
#[allow(dead_code)]
- pub fn new_ecies_p256() -> TlvGen {
+ 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: TlvFlags::ENCRYPTED as u32,
+ flags: flag,
kinds: vec![TlvKinds::SHA256, TlvKinds::ENCEC256],
..Default::default()
}
}
#[allow(dead_code)]
- pub fn new_ecdsa_ecies_p256() -> TlvGen {
+ 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: TlvFlags::ENCRYPTED as u32,
+ flags: flag,
kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256, TlvKinds::ENCEC256],
..Default::default()
}
}
#[allow(dead_code)]
- pub fn new_ecies_x25519() -> TlvGen {
+ 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: TlvFlags::ENCRYPTED as u32,
+ flags: flag,
kinds: vec![TlvKinds::SHA256, TlvKinds::ENCX25519],
..Default::default()
}
}
#[allow(dead_code)]
- pub fn new_ed25519_ecies_x25519() -> TlvGen {
+ 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: TlvFlags::ENCRYPTED as u32,
+ flags: flag,
kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519, TlvKinds::ENCX25519],
..Default::default()
}
@@ -248,7 +299,12 @@
/// Retrieve the header flags for this configuration. This can be called at any time.
fn get_flags(&self) -> u32 {
- self.flags
+ // For the RamLoad case, add in the flag for this feature.
+ if Caps::RamLoad.present() {
+ self.flags | (TlvFlags::RAM_LOAD as u32)
+ } else {
+ self.flags
+ }
}
/// Add bytes to the covered hash.
@@ -479,20 +535,28 @@
result.extend_from_slice(&encbuf);
}
- if self.kinds.contains(&TlvKinds::ENCKW128) {
- let key_bytes = base64::decode(
- include_str!("../../enc-aes128kw.b64").trim()).unwrap();
-
+ 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 encbuf = match c::kw_encrypt(&key_bytes, cipherkey) {
+ 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"),
};
- assert!(encbuf.len() == 24);
- result.write_u16::<LittleEndian>(TlvKinds::ENCKW128 as u16).unwrap();
- result.write_u16::<LittleEndian>(24).unwrap();
+ 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);
}
@@ -503,7 +567,6 @@
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
@@ -535,15 +598,19 @@
}
}
+ 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 = match prk.expand(&[b"MCUBoot_ECIES_v1"], OkmLen(48)) {
+ 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 = [0u8; 48];
+ 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"),
@@ -554,13 +621,22 @@
Err(_) => panic!("Failed building HKDF"),
};
- let key = GenericArray::from_slice(&derived_key[..16]);
let nonce = GenericArray::from_slice(&[0; 16]);
- let mut cipher = Aes128Ctr::new(&key, &nonce);
let mut cipherkey = self.get_enc_key();
- cipher.apply_keystream(&mut cipherkey);
+ 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 key = hmac::Key::new(hmac::HMAC_SHA256, &derived_key[16..]);
+ 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![];
@@ -569,13 +645,15 @@
buf.append(&mut cipherkey);
if self.kinds.contains(&TlvKinds::ENCEC256) {
- assert!(buf.len() == 113);
+ let size = if aes256 { 129 } else { 113 };
+ assert!(buf.len() == size);
result.write_u16::<LittleEndian>(TlvKinds::ENCEC256 as u16).unwrap();
- result.write_u16::<LittleEndian>(113).unwrap();
+ result.write_u16::<LittleEndian>(size as u16).unwrap();
} else {
- assert!(buf.len() == 80);
+ let size = if aes256 { 96 } else { 80 };
+ assert!(buf.len() == size);
result.write_u16::<LittleEndian>(TlvKinds::ENCX25519 as u16).unwrap();
- result.write_u16::<LittleEndian>(80).unwrap();
+ result.write_u16::<LittleEndian>(size as u16).unwrap();
}
result.extend_from_slice(&buf);
}
@@ -590,7 +668,13 @@
fn generate_enc_key(&mut self) {
let rng = rand::SystemRandom::new();
- let mut buf = vec![0u8; AES_KEY_LEN];
+ 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");
}
@@ -599,7 +683,7 @@
}
fn get_enc_key(&self) -> Vec<u8> {
- if self.enc_key.len() != AES_KEY_LEN {
+ if self.enc_key.len() != 32 && self.enc_key.len() != 16 {
panic!("No random key was generated");
}
self.enc_key.clone()
diff --git a/sim/tests/core.rs b/sim/tests/core.rs
index 4e2d9c1..995c372 100644
--- a/sim/tests/core.rs
+++ b/sim/tests/core.rs
@@ -22,9 +22,11 @@
/// A single test, after setting up logging and such. Within the $body,
/// $arg will be bound to each device.
+/// The "$skip_feature" allows to set a feature for which this test will be skipped.
macro_rules! test_shell {
- ($name:ident, $arg: ident, $body:expr) => {
+ ($name:ident, $arg:ident, $body:expr, $skip_feature:expr) => {
#[test]
+ #[cfg_attr(feature = $skip_feature, ignore)]
fn $name() {
testlog::setup();
ImagesBuilder::each_device(|$arg| {
@@ -36,28 +38,34 @@
/// A typical test calls a particular constructor, and runs a given test on
/// that constructor.
+/// The "$skip_feature" allows to set a feature for which this test will be skipped.
macro_rules! sim_test {
- ($name:ident, $maker:ident($($margs:expr),*), $test:ident($($targs:expr),*)) => {
+ ($name:ident, $maker:ident($($margs:expr),*), $test:ident($($targs:expr),*), $skip_feature:expr) => {
test_shell!($name, r, {
let image = r.$maker($($margs),*);
dump_image(&image, stringify!($name));
assert!(!image.$test($($targs),*));
- });
+ }, $skip_feature);
};
}
-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!(norevert_newimage, make_no_upgrade_image(&NO_DEPS), 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());
-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!(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!(norevert_newimage, make_no_upgrade_image(&NO_DEPS), 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(), "");
+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(), "swap-status");
+sim_test!(downgrade_prevention, make_image(&REV_DEPS, true), run_nodowngrade(), "");
+
+sim_test!(direct_xip_first, make_no_upgrade_image(&NO_DEPS), run_direct_xip(), "");
+sim_test!(ram_load_first, make_no_upgrade_image(&NO_DEPS), run_ram_load(), "");
// Test various combinations of incorrect dependencies.
test_shell!(dependency_combos, r, {
@@ -71,7 +79,7 @@
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] = &[