opentitanlib/chip/
boot_log.rs1use anyhow::Result;
6use byteorder::{LittleEndian, ReadBytesExt};
7use serde::Serialize;
8use serde_annotate::Annotate;
9use sha2::{Digest, Sha256};
10use std::convert::TryFrom;
11
12use super::ChipDataError;
13use super::boot_svc::BootSlot;
14use crate::with_unknown;
15
16with_unknown! {
17 pub enum OwnershipState: u32 [default = Self::Recovery] {
18 Recovery = 0,
19 LockedOwner = 0x444e574f,
20 UnlockedSelf = 0x464c5355,
21 UnlockedAny = 0x594e4155,
22 UnlockedEndorsed = 0x444e4555,
23 }
24
25}
26
27#[derive(Debug, Default, Serialize, Annotate)]
30pub struct BootLog {
31 #[annotate(format=hex)]
33 pub digest: [u32; 8],
34 #[annotate(format=hex)]
36 pub identifier: u32,
37 #[annotate(format=hex)]
39 pub chip_version: u64,
40 pub rom_ext_slot: BootSlot,
42 pub rom_ext_major: u32,
44 pub rom_ext_minor: u32,
46 #[annotate(format=hex)]
48 pub rom_ext_size: u32,
49 #[annotate(format=hex)]
51 pub rom_ext_nonce: u64,
52 pub bl0_slot: BootSlot,
54 pub ownership_state: OwnershipState,
56 #[annotate(format=hex)]
58 pub reserved: [u32; 13],
59}
60
61impl TryFrom<&[u8]> for BootLog {
62 type Error = ChipDataError;
63 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
64 if buf.len() < Self::SIZE {
65 return Err(ChipDataError::BadSize(Self::SIZE, buf.len()));
66 }
67 if !BootLog::valid_digest(buf) {
68 return Err(ChipDataError::InvalidDigest);
69 }
70 let mut reader = std::io::Cursor::new(buf);
71 let mut val = BootLog::default();
72 reader.read_u32_into::<LittleEndian>(&mut val.digest)?;
73 val.identifier = reader.read_u32::<LittleEndian>()?;
74 val.chip_version = reader.read_u64::<LittleEndian>()?;
75 val.rom_ext_slot = BootSlot(reader.read_u32::<LittleEndian>()?);
76 val.rom_ext_major = reader.read_u32::<LittleEndian>()?;
77 val.rom_ext_minor = reader.read_u32::<LittleEndian>()?;
78 val.rom_ext_size = reader.read_u32::<LittleEndian>()?;
79 val.rom_ext_nonce = reader.read_u64::<LittleEndian>()?;
80 val.bl0_slot = BootSlot(reader.read_u32::<LittleEndian>()?);
81 val.ownership_state = OwnershipState(reader.read_u32::<LittleEndian>()?);
82 reader.read_u32_into::<LittleEndian>(&mut val.reserved)?;
83 Ok(val)
84 }
85}
86
87impl BootLog {
88 pub const SIZE: usize = 128;
89 const HASH_LEN: usize = 32;
90
91 fn valid_digest(buf: &[u8]) -> bool {
92 let mut digest = Sha256::digest(&buf[Self::HASH_LEN..Self::SIZE]);
93 digest.reverse();
94 digest[..] == buf[..Self::HASH_LEN]
95 }
96}