From ccadb50d8c6d4850d37719dd3d07c2e84154ceb7 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Mon, 26 Jun 2023 18:47:45 -0700 Subject: [PATCH] dice-mfg: allow querying secure boot key slot status --- Cargo.toml | 2 +- app/oxide-rot-1/app.toml | 2 +- lib/dice/src/mfg.rs | 74 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 73e06faa3e..a097c98f93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,7 +111,7 @@ zeroize = { version = "1.5.7", default-features = false, features = ["zeroize_de zip = { version = "0.6", default-features = false, features = ["bzip2"] } # Oxide forks and repos -dice-mfg-msgs = { git = "https://github.com/oxidecomputer/dice-util", default-features = false } +dice-mfg-msgs = { git = "https://github.com/oxidecomputer/dice-util", default-features = false, version = "0.2.1" } gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", default-features = false, features = ["smoltcp"] } hif = { git = "https://github.com/oxidecomputer/hif", default-features = false } humpty = { git = "https://github.com/oxidecomputer/humpty", default-features = false, version = "0.1.3" } diff --git a/app/oxide-rot-1/app.toml b/app/oxide-rot-1/app.toml index 74101edafb..0bc47e61c1 100644 --- a/app/oxide-rot-1/app.toml +++ b/app/oxide-rot-1/app.toml @@ -9,7 +9,7 @@ version = 0 [kernel] name = "oxide-rot-1" -requires = {flash = 59840, ram = 2696} +requires = {flash = 60544, ram = 2696} features = ["dice-mfg"] [caboose] diff --git a/lib/dice/src/mfg.rs b/lib/dice/src/mfg.rs index 78babca7db..824b3c5109 100644 --- a/lib/dice/src/mfg.rs +++ b/lib/dice/src/mfg.rs @@ -6,12 +6,16 @@ use crate::{ cert::PersistIdSelfCertBuilder, csr::PersistIdCsrBuilder, CertSerialNumber, IntermediateCert, PersistIdCert, SeedBuf, }; -use dice_mfg_msgs::{MessageHash, MfgMessage, PlatformId, SizedBlob}; +use core::mem::size_of; +use dice_mfg_msgs::{ + KeySlotStatus, MessageHash, MfgMessage, PlatformId, SizedBlob, +}; use lib_lpc55_usart::{Read, Usart, Write}; use lpc55_pac::SYSCON; use salty::{constants::SECRETKEY_SEED_LENGTH, signature::Keypair}; use sha3::{digest::FixedOutputReset, Digest, Sha3_256}; use unwrap_lite::UnwrapLite; +use zerocopy::FromBytes; use zeroize::{Zeroize, ZeroizeOnDrop}; pub enum Error { @@ -299,6 +303,74 @@ impl DiceMfg for SerialMfg<'_> { syscon_locked, }) } + MfgMessage::GetKeySlotStatus => { + /// Layout of the Customer Field Programmble Area structure in Flash. + /// + /// This struct should be exactly 512 bytes. If you change it such that its size + /// is no longer 512 bytes, it will not compromise security, but bootleby will + /// panic while checking the persistent settings (and with any luck the static + /// assertion below will fire before you hit the panic). + #[derive(FromBytes)] + #[repr(C)] + struct CfpaPage { + // Fields defined by NXP: + header: u32, + monotonic_version: u32, + _fields_we_do_not_use: [u32; 4], + rotkh_revoke: u32, + _more_fields_we_do_not_use: [u32; 5], + _prince_ivs: [[u32; 14]; 3], + _nxp_reserved: [u32; 10], + _customer_area: [u8; 224], + _digest: [u8; 32], + } + + // It's really quite important that the CFPA data structure be exactly the size + // of a flash page, 512 bytes. + static_assertions::const_assert_eq!( + size_of::(), + 512 + ); + + let cfpa_ping: &[u8] = unsafe { + core::slice::from_raw_parts(0x9_e000 as *const u8, 512) + }; + let Some(cfpa_ping) = CfpaPage::read_from(cfpa_ping) else { + let _ = self.send_nak(); + continue; + }; + + let cfpa_pong: &[u8] = unsafe { + core::slice::from_raw_parts(0x9_e200 as *const u8, 512) + }; + let Some(cfpa_pong) = CfpaPage::read_from(cfpa_pong) else { + let _ = self.send_nak(); + continue; + }; + + let cfpa = if cfpa_ping.monotonic_version + > cfpa_pong.monotonic_version + { + &cfpa_ping + } else { + &cfpa_pong + }; + + let key_status_from_slot_value = |value| match value & 0x3 { + 0b00 => KeySlotStatus::Invalid, + 0b01 => KeySlotStatus::Enabled, + _ => KeySlotStatus::Revoked, + }; + + self.send_msg(MfgMessage::KeySlotStatus { + slots: [ + key_status_from_slot_value(cfpa.rotkh_revoke), + key_status_from_slot_value(cfpa.rotkh_revoke >> 2), + key_status_from_slot_value(cfpa.rotkh_revoke >> 4), + key_status_from_slot_value(cfpa.rotkh_revoke >> 6), + ], + }) + } _ => continue, }; }