sim: Validate the SHA256 verification

Instead of stubbing out the image validation code, compile it, and add
the SHA256 TLV to the buffer.

Signed-off-by: David Brown <david.brown@linaro.org>
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..960139a
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "sim/mbedtls"]
+	path = sim/mbedtls
+	url = https://github.com/ARMmbed/mbedtls
diff --git a/sim/Cargo.lock b/sim/Cargo.lock
index 8974502..67d5c70 100644
--- a/sim/Cargo.lock
+++ b/sim/Cargo.lock
@@ -3,11 +3,14 @@
 version = "0.1.0"
 dependencies = [
  "docopt 0.6.86 (registry+https://github.com/rust-lang/crates.io-index)",
+ "enumflags 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "enumflags_derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "simflash 0.1.0",
 ]
@@ -69,6 +72,20 @@
 ]
 
 [[package]]
+name = "enumflags"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "enumflags_derive"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "env_logger"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -123,6 +140,11 @@
 ]
 
 [[package]]
+name = "quote"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "rand"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -131,6 +153,11 @@
 ]
 
 [[package]]
+name = "redox_syscall"
+version = "0.1.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "regex"
 version = "0.1.80"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -148,6 +175,18 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "rust-crypto"
+version = "0.2.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "rustc-demangle"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -170,6 +209,24 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "syn"
+version = "0.11.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "synom"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "thread-id"
 version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -187,6 +244,22 @@
 ]
 
 [[package]]
+name = "time"
+version = "0.1.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "utf8-ranges"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -208,6 +281,8 @@
 "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
 "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
 "checksum docopt 0.6.86 (registry+https://github.com/rust-lang/crates.io-index)" = "4a7ef30445607f6fc8720f0a0a2c7442284b629cf0d049286860fae23e71c4d9"
+"checksum enumflags 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b003f771fcd8df873645aa0142c86b50a9d5ce063ca0ce6057a4131f2b6ef3c2"
+"checksum enumflags_derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46ac5d2e0ce7696d1b0c9fb0a1d1c388bc1b04a23b99d54520c15d43ec832466"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
 "checksum error-chain 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cd681735364a04cd5d69f01a4f6768e70473941f8d86d8c224faf6955a75799"
 "checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a"
@@ -216,14 +291,21 @@
 "checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8"
 "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
 "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
+"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
+"checksum redox_syscall 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "9df6a71a1e67be2104410736b2389fb8e383c1d7e9e792d629ff13c02867147a"
 "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
 "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
+"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
 "checksum rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1430d286cadb237c17c885e25447c982c97113926bb579f4379c0eca8d9586dc"
 "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
 "checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c"
+"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
+"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
+"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520"
+"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
diff --git a/sim/Cargo.toml b/sim/Cargo.toml
index a0d6299..2e9af87 100644
--- a/sim/Cargo.toml
+++ b/sim/Cargo.toml
@@ -15,6 +15,9 @@
 log = "0.3"
 env_logger = "0.3"
 simflash = { path = "simflash" }
+enumflags = "0.1"
+enumflags_derive = "0.2"
+rust-crypto = "0.2"
 
 [profile.test]
 opt-level = 1
diff --git a/sim/build.rs b/sim/build.rs
index a7318f4..186cea9 100644
--- a/sim/build.rs
+++ b/sim/build.rs
@@ -12,6 +12,7 @@
     conf.file("../boot/bootutil/src/loader.c");
     conf.file("../boot/bootutil/src/caps.c");
     conf.file("../boot/bootutil/src/bootutil_misc.c");
+    conf.file("../boot/bootutil/src/image_validate.c");
     conf.file("csupport/run.c");
     conf.include("../boot/bootutil/include");
     conf.include("../boot/zephyr/include");
@@ -20,9 +21,21 @@
     conf.define("__BOOTSIM__", None);
     // conf.define("MCUBOOT_OVERWRITE_ONLY", None);
     conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
+
+    // Bring in some pieces of mbedtls we need.
+    conf.define("MCUBOOT_USE_MBED_TLS", None);
+    conf.define("MBEDTLS_CONFIG_FILE", Some("<config-boot.h>"));
+    conf.include("mbedtls/include");
+    conf.file("mbedtls/library/sha256.c");
+
+    // Test that signature/hashes are present.
+    conf.define("MCUBOOT_VALIDATE_SLOT0", None);
+
     conf.compile("libbootutil.a");
     walk_dir("../boot").unwrap();
     walk_dir("csupport").unwrap();
+    walk_dir("mbedtls/include").unwrap();
+    walk_dir("mbedtls/library").unwrap();
 }
 
 // Output the names of all files within a directory so that Cargo knows when to rebuild.
diff --git a/sim/csupport/run.c b/sim/csupport/run.c
index e1f0231..d52defd 100644
--- a/sim/csupport/run.c
+++ b/sim/csupport/run.c
@@ -219,16 +219,3 @@
 
     return 0;
 }
-
-int bootutil_img_validate(struct image_header *hdr,
-                          const struct flash_area *fap,
-                          uint8_t *tmp_buf, uint32_t tmp_buf_sz,
-                          uint8_t *seed, int seed_len, uint8_t *out_hash)
-{
-    if (hal_flash_read(fap->fa_id, fap->fa_off, tmp_buf, 4)) {
-        printf("Flash read error\n");
-        abort();
-    }
-
-    return (*((uint32_t *) tmp_buf) != 0x96f3b83c);
-}
diff --git a/sim/mbedtls b/sim/mbedtls
new file mode 160000
index 0000000..f2a597f
--- /dev/null
+++ b/sim/mbedtls
@@ -0,0 +1 @@
+Subproject commit f2a597fa3dd1c7b15e0fee62f6932b253295803d
diff --git a/sim/src/main.rs b/sim/src/main.rs
index dfebea7..aa7c75d 100644
--- a/sim/src/main.rs
+++ b/sim/src/main.rs
@@ -1,5 +1,8 @@
 #[macro_use] extern crate log;
+extern crate crypto;
 extern crate env_logger;
+extern crate enumflags;
+#[macro_use] extern crate enumflags_derive;
 extern crate docopt;
 extern crate libc;
 extern crate rand;
@@ -19,10 +22,12 @@
 mod c;
 pub mod api;
 mod caps;
+mod tlv;
 
 use simflash::{Flash, SimFlash};
 use area::{AreaDesc, FlashId};
 use caps::Caps;
+use tlv::TlvGen;
 
 const USAGE: &'static str = "
 Mcuboot simulator
@@ -124,7 +129,7 @@
     }
 
     if status.failures > 0 {
-        warn!("{} Tests ran with {} failures", status.failures + status.passes, status.failures);
+        error!("{} Tests ran with {} failures", status.failures + status.passes, status.failures);
         process::exit(1);
     } else {
         warn!("{} Tests ran successfully", status.passes);
@@ -597,16 +602,18 @@
 fn install_image(flash: &mut Flash, offset: usize, len: usize) -> Vec<u8> {
     let offset0 = offset;
 
+    let mut tlv = TlvGen::new_hash_only();
+
     // Generate a boot header.  Note that the size doesn't include the header.
     let header = ImageHeader {
         magic: 0x96f3b83c,
-        tlv_size: 0,
+        tlv_size: tlv.get_size(),
         _pad1: 0,
         hdr_size: 32,
         key_id: 0,
         _pad2: 0,
         img_size: len as u32,
-        flags: 0,
+        flags: tlv.get_flags(),
         ver: ImageVersion {
             major: (offset / (128 * 1024)) as u8,
             minor: 0,
@@ -617,6 +624,7 @@
     };
 
     let b_header = header.as_raw();
+    tlv.add_bytes(&b_header);
     /*
     let b_header = unsafe { slice::from_raw_parts(&header as *const _ as *const u8,
                                                   mem::size_of::<ImageHeader>()) };
@@ -628,6 +636,16 @@
     // The core of the image itself is just pseudorandom data.
     let mut buf = vec![0; len];
     splat(&mut buf, offset);
+    tlv.add_bytes(&buf);
+
+    // Get and append the TLV itself.
+    buf.append(&mut tlv.make_tlv());
+
+    // Pad the block to a flash alignment (8 bytes).
+    while buf.len() % 8 != 0 {
+        buf.push(0xFF);
+    }
+
     flash.write(offset, &buf).unwrap();
     let offset = offset + buf.len();
 
diff --git a/sim/src/tlv.rs b/sim/src/tlv.rs
new file mode 100644
index 0000000..071af0c
--- /dev/null
+++ b/sim/src/tlv.rs
@@ -0,0 +1,91 @@
+//! TLV Support
+//!
+//! mcuboot images are followed immediately by a list of TLV items that contain integrity
+//! information about the image.  Their generation is made a little complicated because the size of
+//! the TLV block is in the image header, which is included in the hash.  Since some signatures can
+//! vary in size, we just make them the largest size possible.
+//!
+//! Because of this header, we have to make two passes.  The first pass will compute the size of
+//! the TLV, and the second pass will build the data for the TLV.
+
+use crypto::digest::Digest;
+use crypto::sha2::Sha256;
+
+#[derive(EnumFlags, Copy, Clone, Debug)]
+#[repr(u32)]
+#[allow(non_camel_case_types)]
+pub enum Flags {
+    PIC = 0x000001,
+    SHA256 = 0x000002,
+    PKCS15_RSA2048_SHA256 = 0x000004,
+    ECDSA224_SHA256 = 0x000008,
+    NON_BOOTABLE = 0x000010,
+    ECDSA256_SHA256 = 0x000020,
+    PKCS1_PSS_RSA2048_SHA256 = 0x000040,
+}
+
+#[repr(u8)]
+#[derive(Copy, Clone, PartialEq, Eq)]
+#[allow(dead_code)] // TODO: For now
+pub enum TlvKinds {
+    SHA256 = 1,
+    RSA2048 = 2,
+    ECDSA224 = 3,
+    ECDSA256 = 4,
+}
+
+pub struct TlvGen {
+    flags: Flags,
+    kinds: Vec<TlvKinds>,
+    size: u16,
+    hasher: Sha256,
+}
+
+impl TlvGen {
+    /// Construct a new tlv generator that will only contain a hash of the data.
+    pub fn new_hash_only() -> TlvGen {
+        TlvGen {
+            flags: Flags::SHA256,
+            kinds: vec![TlvKinds::SHA256],
+            size: 4 + 32,
+            hasher: Sha256::new(),
+        }
+    }
+
+    /// Retrieve the header flags for this configuration.  This can be called at any time.
+    pub fn get_flags(&self) -> u32 {
+        self.flags as u32
+    }
+
+    /// Retrieve the size that the TLV will occupy.  This can be called at any time.
+    pub fn get_size(&self) -> u16 {
+        self.size
+    }
+
+    /// Add bytes to the covered hash.
+    pub fn add_bytes(&mut self, bytes: &[u8]) {
+        self.hasher.input(bytes);
+    }
+
+    /// Compute the TLV given the specified block of data.
+    pub fn make_tlv(mut self) -> Vec<u8> {
+        let mut result: Vec<u8> = vec![];
+
+        if self.kinds.contains(&TlvKinds::SHA256) {
+            let hash_size = self.hasher.output_bytes();
+            assert!(hash_size == 32); // Assumption made.
+
+            let mut hash = vec![0; hash_size];
+
+            self.hasher.result(&mut hash);
+
+            result.push(TlvKinds::SHA256 as u8);
+            result.push(0);
+            result.push(32);
+            result.push(0);
+            result.append(&mut hash);
+        }
+
+        result
+    }
+}