use std::fs::{self, File};
use std::io::Write;
use std::process::Command;
use tempfile::tempdir;
extern crate hex;
use assert_cmd::prelude::*;
use predicates::prelude::*;
#[test]
fn factory_generates_correctly() {
let dir = tempdir().unwrap();
let cfgfile_path = dir.path().join("cfg.toml");
let mut cfgfile = File::create(cfgfile_path.clone()).unwrap();
let binfile_path = dir.path().join("factory.bin");
writeln!(
cfgfile,
r#"
[factory-settings]
usb-id = {{ vid = 0x1209, pid = 0xb000 }}
rot-fingerprint = "C7EE3124 DC87EAAE 5A6F7FCC B6C2E458 706835C9 9D5D7082 4EFFAC0F 12A5A875"
debug-access = "Disabled"
[factory-settings.boot-configuration]
failure-port = 1
failure-pin = 21
speed = "48MHz"
mode = "Usb"
[factory-settings.secure-boot-configuration]
secure-boot-enabled = true
puf-enrollment-disabled = false
puf-keycode-generation-disabled = false
trustzone-mode = "FromImageHeader"
use-rsa4096-keys = false
dice-computation-disabled = true
"#
)
.unwrap();
let mut cmd = Command::cargo_bin("lpc55").unwrap();
cmd.arg("configure")
.arg("factory-settings")
.arg("-o")
.arg(binfile_path.clone())
.arg(cfgfile_path);
cmd.assert().success();
let data = fs::read(binfile_path).expect("Unable to read output factory file");
assert_eq!(data.len(), 512);
assert_eq!(data[0..4], [0x10, 0x01, 0x00, 0xa9]);
assert_eq!(data[8..12], [0x09, 0x12, 0x00, 0xb0]);
assert_eq!(data[0x0c..0x10], [0x00u8; 4]);
assert_eq!(
data[0x10..0x18],
[0xff, 0x83, 0x00, 0x7c, 0x00, 0x00, 0xff, 0xff]
);
assert_eq!(data[0x18..0x1c], [0x00u8; 0x1c - 0x18]);
assert_eq!(data[0x1c..0x20], [0xc0, 0x00, 0x00, 0xc0]);
assert_eq!(data[0x20..0x50], [0x00u8; 0x50 - 0x20]);
assert_eq!(
data[0x50..0x70],
hex::decode("C7EE3124DC87EAAE5A6F7FCCB6C2E458706835C99D5D70824EFFAC0F12A5A875").unwrap()
);
assert_eq!(data[0x70..0x200], [0x00u8; 0x200 - 0x70]);
}
#[test]
fn customer_generates_correctly() {
let dir = tempdir().unwrap();
let cfgfile_path = dir.path().join("cfg.toml");
let mut cfgfile = File::create(cfgfile_path.clone()).unwrap();
let binfile_path = dir.path().join("customer.bin");
writeln!(
cfgfile,
r#"
[customer-settings]
customer-version = 0x030201
nonsecure-firmware-version = 0x060504
secure-firmware-version = 0x090807
rot-keys-status = ["Enabled", "Enabled", "Enabled", "Enabled"]
"#
)
.unwrap();
let mut cmd = Command::cargo_bin("lpc55").unwrap();
cmd.arg("configure")
.arg("customer-settings")
.arg("-o")
.arg(binfile_path.clone())
.arg(cfgfile_path);
cmd.assert().success();
let data = fs::read(binfile_path).expect("Unable to read output customer file");
assert_eq!(data.len(), 512);
assert_eq!(data[0..4], [0u8; 4]);
assert_eq!(data[4..16], [1, 2, 3, 0, 7, 8, 9, 0, 4, 5, 6, 0]);
assert_eq!(data[0x10..0x18], [0u8; 8]);
assert_eq!(data[0x18..0x1c], [0x55, 0, 0, 0]);
assert_eq!(data[0x1c..0x20], [0u8; 4]);
assert_eq!(data[0x20..0x28], [0u8; 8]);
assert_eq!(data[0x28..0x200], [0u8; 0x200 - 0x28]);
}
#[test]
fn custom_debug_policy() {
let dir = tempdir().unwrap();
let cfgfile_path = dir.path().join("cfg.toml");
let mut cfgfile = File::create(cfgfile_path.clone()).unwrap();
let binfile_path = dir.path().join("customer.bin");
writeln!(cfgfile, r#"
[factory-settings]
debug-access = {{ Custom = {{ nonsecure-noninvasive = "Disabled", secure-invasive = "Authenticate", jtag-tap = "Enabled" }} }}
"#).unwrap();
let mut cmd = Command::cargo_bin("lpc55").unwrap();
cmd.arg("configure")
.arg("factory-settings")
.arg("-o")
.arg(binfile_path.clone())
.arg(cfgfile_path);
cmd.assert().success();
let data = fs::read(binfile_path).expect("Unable to read output customer file");
assert_eq!(
data[0x10..0x18],
[0xf7, 0x03, 0x08, 0xfc, 0xf6, 0x03, 0x09, 0xfc]
);
}
#[test]
fn sha256_seal() {
let dir = tempdir().unwrap();
let cfgfile_path = dir.path().join("cfg.toml");
let mut cfgfile = File::create(cfgfile_path.clone()).unwrap();
let binfile_path = dir.path().join("factory.bin");
writeln!(
cfgfile,
r#"
[factory-settings]
usb-id = {{ vid = 0x1209, pid = 0xb000 }}
rot-fingerprint = "C7EE3124 DC87EAAE 5A6F7FCC B6C2E458 706835C9 9D5D7082 4EFFAC0F 12A5A875"
debug-access = "Disabled"
seal = true
"#
)
.unwrap();
let mut cmd = Command::cargo_bin("lpc55").unwrap();
cmd.arg("configure")
.arg("factory-settings")
.arg("-o")
.arg(binfile_path.clone())
.arg(cfgfile_path);
cmd.assert().success();
let data = fs::read(binfile_path).expect("Unable to read output factory file");
assert_eq!(
data[480..512],
hex::decode("11c38ce9fa006c6fda5f894c5ab679bd0a6dc01dfac2dc3e25a7670bd1e1752d").unwrap()
);
}
#[test]
fn rotkh() {
let mut cmd = Command::cargo_bin("lpc55").unwrap();
cmd.arg("fingerprint-certificates")
.arg("./example-cfgs/example-cfg.toml");
cmd.assert().success().stdout(predicate::str::contains(
"D826E2FD 44F5C254 BC58C62E BF96A938 95C19DC2 25810C95 C8B9E6FD 9F7CC9CB",
));
}