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