#![no_main]
#![no_std]
use core::convert::TryInto;
extern crate panic_semihosting;
use cortex_m_rt::entry;
use cortex_m_semihosting::dbg;
use cortex_m_semihosting::heprint;
use cortex_m_semihosting::heprintln;
use hal::prelude::*;
use lpc55_hal as hal;
#[derive(Debug)]
pub enum State {
NotEnrolled,
Enrolled = 0x7533ff04,
}
macro_rules! dump_hex {
($array:expr, $length:expr ) => {
heprint!("{:?} = ", stringify!($array));
for i in 0..$length {
heprint!("{:02X}", $array[i]);
}
heprintln!("");
};
}
#[entry]
fn main() -> ! {
dbg!("Hello PUF");
const PUF_STATE_FLASH: usize = 0x0006_0000;
let dp = hal::raw::Peripherals::take().unwrap();
let mut syscon = hal::Syscon::from(dp.SYSCON);
let puf = hal::Puf::from(dp.PUF).enabled(&mut syscon).unwrap();
let flash = hal::Flash::from(dp.FLASH).enabled(&mut syscon);
let mut flash = hal::FlashGordon::new(flash);
dbg!(puf.version());
dbg!(&puf);
let mut buffer = [0u8; 16];
flash.read(PUF_STATE_FLASH, &mut buffer);
let state: u32 = u32::from_ne_bytes(buffer[0..4].try_into().unwrap());
let mut ac = [0u8; 1192];
let mut kc1 = [0u8; 52];
let mut kc2 = [0u8; 52];
let mut kc3 = [0u8; 52];
let mut kc4 = [0u8; 52];
let mut check_buf = [0u8; 1192 + 52 * 4];
if state != (State::Enrolled as u32) {
dbg!("The is not yet enrolled. ");
dbg!("enrolling...");
let mut write_buf = [0u8; 512];
let puf_enrolled = puf.enroll(&mut ac).unwrap();
dbg!(&puf_enrolled);
dump_hex!(ac[..16], 16);
dump_hex!(ac[1192 - 16..], 16);
dbg!("Generate 2 IP-direct keys, and 2 normal keys.");
puf_enrolled.generate_key(256, 0, &mut kc1).unwrap();
puf_enrolled.generate_key(256, 0, &mut kc2).unwrap();
puf_enrolled.generate_key(256, 1, &mut kc3).unwrap();
puf_enrolled.generate_key(256, 2, &mut kc4).unwrap();
dump_hex!(kc1[0..8], 8);
dump_hex!(kc2[0..8], 8);
dump_hex!(kc3[0..8], 8);
dump_hex!(kc4[0..8], 8);
for addr in (PUF_STATE_FLASH..PUF_STATE_FLASH + 512 * 3).step_by(512) {
flash.erase_page(addr >> 4).unwrap();
}
write_buf[0..4].copy_from_slice(&(State::Enrolled as u32).to_ne_bytes());
write_buf[16..].copy_from_slice(&ac[..496]);
flash.write(PUF_STATE_FLASH, &write_buf).unwrap();
write_buf.copy_from_slice(&ac[496..1008]);
flash.write(PUF_STATE_FLASH + 512, &write_buf).unwrap();
write_buf[0..184].copy_from_slice(&ac[1008..1192]);
write_buf[184..236].copy_from_slice(&kc1);
write_buf[236..288].copy_from_slice(&kc2);
write_buf[288..340].copy_from_slice(&kc3);
write_buf[340..392].copy_from_slice(&kc4);
flash.write(PUF_STATE_FLASH + 1024, &write_buf).unwrap();
dbg!("Reading back...");
flash.read(PUF_STATE_FLASH + 16, &mut check_buf);
dump_hex!(check_buf[..16], 16);
dump_hex!(check_buf[1192 - 16..], 16);
for i in 0..ac.len() {
assert!(ac[i] == check_buf[i])
}
for i in 0..kc1.len() {
assert!(kc1[i] == check_buf[1192 + i])
}
for i in 0..kc2.len() {
assert!(kc2[i] == check_buf[1192 + 52 + i])
}
for i in 0..kc3.len() {
assert!(kc3[i] == check_buf[1192 + 52 * 2 + i])
}
for i in 0..kc4.len() {
assert!(kc4[i] == check_buf[1192 + 52 * 3 + i])
}
dbg!("Now restart this program to derive the keys.");
} else {
dbg!("The device is already enrolled.");
flash.read(PUF_STATE_FLASH + 16, &mut check_buf);
ac.copy_from_slice(&check_buf[..1192]);
kc1.copy_from_slice(&check_buf[1192..][..52]);
kc2.copy_from_slice(&check_buf[1192 + 52..][..52]);
kc3.copy_from_slice(&check_buf[1192 + 52 * 2..][..52]);
kc4.copy_from_slice(&check_buf[1192 + 52 * 3..][..52]);
dump_hex!(ac[..16], 16);
dump_hex!(ac[1192 - 16..], 16);
let puf_started = puf.start(&ac).unwrap();
dbg!("Started.");
dbg!(&puf_started);
dbg!("Loading AES and Prince Keys..");
puf_started
.get_key(hal::raw::puf::keyenable::KEY_A::AES, &kc1, &mut [0u8; 0])
.unwrap();
puf_started
.get_key(
hal::raw::puf::keyenable::KEY_A::PRINCE0,
&kc2,
&mut [0u8; 0],
)
.unwrap();
puf_started
.get_key(
hal::raw::puf::keyenable::KEY_A::PRINCE1,
&kc2,
&mut [0u8; 0],
)
.unwrap();
puf_started
.get_key(
hal::raw::puf::keyenable::KEY_A::PRINCE2,
&kc2,
&mut [0u8; 0],
)
.unwrap();
dbg!("Loading SW Keys..");
let mut key1 = [0u8; 32];
let mut key2 = [0u8; 32];
puf_started
.get_key(hal::raw::puf::keyenable::KEY_A::NONE, &kc3, &mut key1)
.unwrap();
puf_started
.get_key(hal::raw::puf::keyenable::KEY_A::NONE, &kc4, &mut key2)
.unwrap();
dump_hex!(key1, 32);
dump_hex!(key2, 32);
dbg!(&puf_started);
dbg!("Done");
}
dbg!("Looping");
loop {
dbg!("Loop");
}
}