opentitanlib/ownership/
owner.rs

1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5use anyhow::{Result, anyhow, ensure};
6use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
7use serde::Deserialize;
8use serde_annotate::Annotate;
9use sphincsplus::SpxSecretKey;
10use std::convert::TryFrom;
11use std::io::{Read, Write};
12
13use super::GlobalFlags;
14use super::misc::{KeyMaterial, OwnershipKeyAlg, TlvHeader, TlvTag};
15use super::{
16    DetachedSignature, OwnerApplicationKey, OwnerFlashConfig, OwnerFlashInfoConfig,
17    OwnerIsfbConfig, OwnerRescueConfig,
18};
19use crate::chip::boolean::HardenedBool;
20use crate::crypto::Error as CryptoError;
21use crate::crypto::ecdsa::{EcdsaPrivateKey, EcdsaRawSignature};
22use crate::with_unknown;
23
24with_unknown! {
25    pub enum SramExecMode: u32 [default = Self::DisabledLocked] {
26        DisabledLocked = u32::from_le_bytes(*b"LNEX"),
27        Disabled = u32::from_le_bytes(*b"NOEX"),
28        Enabled = u32::from_le_bytes(*b"EXEC"),
29    }
30
31    pub enum MinSecurityVersion: u32 [default = Self::NoChange] {
32        NoChange = 0xFFFFFFFFu32,
33    }
34
35    pub enum OwnershipUpdateMode: u32 [default = Self::Open] {
36        Open = bindgen::ownership_datatypes::ownership_update_mode::kOwnershipUpdateModeOpen as u32,
37        UnlockSelf = bindgen::ownership_datatypes::ownership_update_mode::kOwnershipUpdateModeSelf as u32,
38        SelfVersion = bindgen::ownership_datatypes::ownership_update_mode::kOwnershipUpdateModeSelfVersion as u32,
39        NewVersion = bindgen::ownership_datatypes::ownership_update_mode::kOwnershipUpdateModeNewVersion as u32,
40        AnyVersion = bindgen::ownership_datatypes::ownership_update_mode::kOwnershipUpdateModeAnyVersion as u32,
41    }
42}
43
44/// Describes the owner configuration and key material.
45#[derive(Debug, Deserialize, Annotate, PartialEq)]
46pub struct OwnerBlock {
47    /// Header identifying this struct.
48    #[serde(
49        skip_serializing_if = "GlobalFlags::not_debug",
50        default = "OwnerBlock::default_header"
51    )]
52    pub header: TlvHeader,
53    /// Configuraion version (monotonically increasing per owner).
54    #[serde(default)]
55    pub config_version: u32,
56    /// Whether the owner wants to permit code execution in SRAM.
57    #[serde(default)]
58    pub sram_exec: SramExecMode,
59    /// The key algorithm of the ownership keys.
60    pub ownership_key_alg: OwnershipKeyAlg,
61    /// Ownership update mode.
62    #[serde(default)]
63    pub update_mode: OwnershipUpdateMode,
64    /// Set the minimum security version to this value.
65    #[serde(default)]
66    pub min_security_version_bl0: MinSecurityVersion,
67    /// The device ID locking constraint.
68    #[serde(default)]
69    pub lock_constraint: u32,
70    /// The device ID to which this config applies.
71    #[serde(
72        default = "OwnerBlock::default_constraint",
73        skip_serializing_if = "OwnerBlock::is_default_constraint"
74    )]
75    #[annotate(format=hex)]
76    pub device_id: [u32; 8],
77    #[serde(default)]
78    pub boot_svc_after_wakeup: HardenedBool,
79    #[serde(default, skip_serializing_if = "GlobalFlags::not_debug")]
80    #[annotate(format=hex)]
81    pub reserved: [u32; 15],
82    /// The owner identity key.
83    pub owner_key: KeyMaterial,
84    /// The owner activation key.
85    pub activate_key: KeyMaterial,
86    /// The owner unlock key.
87    pub unlock_key: KeyMaterial,
88    /// A list of other configuration items (application keys, flash configuration, etc).
89    #[serde(default)]
90    pub data: Vec<OwnerConfigItem>,
91    #[serde(default, skip_serializing_if = "EcdsaRawSignature::is_empty")]
92    #[annotate(format=hex)]
93    /// A signature over this block with the owner key.
94    pub signature: EcdsaRawSignature,
95    /// A sealing value that locks a configuration to a particular device.
96    #[serde(default, skip_serializing_if = "Vec::is_empty", with = "serde_bytes")]
97    #[annotate(format = hexstr)]
98    pub seal: Vec<u8>,
99}
100
101impl Default for OwnerBlock {
102    fn default() -> Self {
103        Self {
104            header: Self::default_header(),
105            config_version: 0,
106            sram_exec: SramExecMode::default(),
107            ownership_key_alg: OwnershipKeyAlg::default(),
108            update_mode: OwnershipUpdateMode::default(),
109            min_security_version_bl0: MinSecurityVersion::default(),
110            lock_constraint: 0,
111            device_id: Self::default_constraint(),
112            boot_svc_after_wakeup: HardenedBool::default(),
113            reserved: [0u32; 15],
114            owner_key: KeyMaterial::default(),
115            activate_key: KeyMaterial::default(),
116            unlock_key: KeyMaterial::default(),
117            data: Vec::new(),
118            signature: EcdsaRawSignature::default(),
119            seal: Vec::new(),
120        }
121    }
122}
123
124impl OwnerBlock {
125    pub const SIZE: usize = 2048;
126    pub const DATA_SIZE: usize = 1536;
127    pub const SIGNATURE_OFFSET: usize = 1952;
128    // The not present value must be reflected in the TlvTag::NotPresent value.
129    const NOT_PRESENT: u8 = 0x5a;
130    const NO_CONSTRAINT: u32 = 0x7e7e7e7e;
131
132    pub fn default_header() -> TlvHeader {
133        TlvHeader::new(TlvTag::Owner, Self::SIZE, "0.0")
134    }
135    pub fn basic() -> Self {
136        Self {
137            data: vec![
138                OwnerConfigItem::ApplicationKey(OwnerApplicationKey::default()),
139                OwnerConfigItem::FlashConfig(OwnerFlashConfig::basic()),
140                OwnerConfigItem::FlashInfoConfig(OwnerFlashInfoConfig::basic()),
141                OwnerConfigItem::RescueConfig(OwnerRescueConfig::all()),
142            ],
143            ..Default::default()
144        }
145    }
146
147    pub fn write(&self, dest: &mut impl Write) -> Result<()> {
148        self.header.write(dest)?;
149        dest.write_u32::<LittleEndian>(self.config_version)?;
150        dest.write_u32::<LittleEndian>(u32::from(self.sram_exec))?;
151        dest.write_u32::<LittleEndian>(u32::from(self.ownership_key_alg))?;
152        dest.write_u32::<LittleEndian>(u32::from(self.update_mode))?;
153        dest.write_u32::<LittleEndian>(u32::from(self.min_security_version_bl0))?;
154        dest.write_u32::<LittleEndian>(self.lock_constraint)?;
155
156        for (i, x) in self.device_id.iter().enumerate() {
157            if self.lock_constraint & (1u32 << i) == 0 {
158                dest.write_u32::<LittleEndian>(Self::NO_CONSTRAINT)?;
159            } else {
160                dest.write_u32::<LittleEndian>(*x)?;
161            }
162        }
163        dest.write_u32::<LittleEndian>(u32::from(self.boot_svc_after_wakeup))?;
164        for x in &self.reserved {
165            dest.write_u32::<LittleEndian>(*x)?;
166        }
167        self.owner_key.write_length(dest, 96)?;
168        self.activate_key.write_length(dest, 96)?;
169        self.unlock_key.write_length(dest, 96)?;
170        let mut data = Vec::new();
171        for item in &self.data {
172            item.write(&mut data)?;
173        }
174        data.resize(Self::DATA_SIZE, Self::NOT_PRESENT);
175        dest.write_all(&data)?;
176        self.signature.write(dest)?;
177        if self.seal.is_empty() {
178            dest.write_all(&[0u8; 32])?;
179        } else {
180            dest.write_all(&self.seal)?;
181        }
182        Ok(())
183    }
184
185    pub fn read(src: &mut impl Read, header: TlvHeader) -> Result<Self> {
186        let config_version = src.read_u32::<LittleEndian>()?;
187        let sram_exec = SramExecMode(src.read_u32::<LittleEndian>()?);
188        let ownership_key_alg = OwnershipKeyAlg(src.read_u32::<LittleEndian>()?);
189        let update_mode = OwnershipUpdateMode(src.read_u32::<LittleEndian>()?);
190        let min_security_version_bl0 = MinSecurityVersion(src.read_u32::<LittleEndian>()?);
191        let lock_constraint = src.read_u32::<LittleEndian>()?;
192
193        let mut device_id = [0u32; 8];
194        src.read_u32_into::<LittleEndian>(&mut device_id)?;
195        let boot_svc_after_wakeup = HardenedBool(src.read_u32::<LittleEndian>()?);
196        let mut reserved = [0u32; 15];
197        src.read_u32_into::<LittleEndian>(&mut reserved)?;
198        let owner_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?;
199        let activate_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?;
200        let unlock_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?;
201        let mut bytes = vec![0u8; Self::DATA_SIZE];
202        src.read_exact(&mut bytes)?;
203        let mut cursor = std::io::Cursor::new(&bytes);
204        let mut data = Vec::new();
205        while cursor.position() as usize != Self::DATA_SIZE {
206            match OwnerConfigItem::read(&mut cursor)? {
207                Some(item) => data.push(item),
208                None => break,
209            }
210        }
211        let signature = EcdsaRawSignature::read(src)?;
212        let mut seal = vec![0u8; 32];
213        src.read_exact(&mut seal)?;
214        Ok(Self {
215            header,
216            config_version,
217            sram_exec,
218            ownership_key_alg,
219            update_mode,
220            min_security_version_bl0,
221            lock_constraint,
222            device_id,
223            boot_svc_after_wakeup,
224            reserved,
225            owner_key,
226            activate_key,
227            unlock_key,
228            data,
229            signature,
230            seal,
231        })
232    }
233    pub fn sign(&mut self, key: &EcdsaPrivateKey) -> Result<()> {
234        ensure!(
235            self.ownership_key_alg == OwnershipKeyAlg::EcdsaP256,
236            CryptoError::SignFailed(anyhow!(
237                "Algorithm {} requires a detached signature",
238                self.ownership_key_alg
239            ))
240        );
241        let mut data = Vec::new();
242        self.write(&mut data)?;
243        self.signature = key.digest_and_sign(&data[..Self::SIGNATURE_OFFSET])?;
244        Ok(())
245    }
246
247    pub fn detached_sign(
248        &mut self,
249        nonce: u64,
250        ecdsa_key: Option<&EcdsaPrivateKey>,
251        spx_key: Option<&SpxSecretKey>,
252    ) -> Result<DetachedSignature> {
253        self.signature = Default::default();
254        let mut data = Vec::new();
255        self.write(&mut data)?;
256        DetachedSignature::new(
257            &data[..Self::SIGNATURE_OFFSET],
258            TlvTag::Owner.into(),
259            self.ownership_key_alg,
260            nonce,
261            ecdsa_key,
262            spx_key,
263        )
264    }
265
266    pub fn is_default_constraint(d: &[u32; 8]) -> bool {
267        *d == [Self::NO_CONSTRAINT; 8]
268    }
269
270    pub fn default_constraint() -> [u32; 8] {
271        [Self::NO_CONSTRAINT; 8]
272    }
273}
274
275#[derive(Debug, Deserialize, Annotate, PartialEq)]
276pub enum OwnerConfigItem {
277    #[serde(alias = "application_key")]
278    ApplicationKey(OwnerApplicationKey),
279    #[serde(alias = "flash_info_config")]
280    FlashInfoConfig(OwnerFlashInfoConfig),
281    #[serde(alias = "flash_config")]
282    FlashConfig(OwnerFlashConfig),
283    #[serde(alias = "rescue_config")]
284    RescueConfig(OwnerRescueConfig),
285    #[serde(alias = "isfb_config")]
286    IsfbConfig(OwnerIsfbConfig),
287    #[serde(alias = "raw")]
288    Raw(
289        #[serde(with = "serde_bytes")]
290        #[annotate(format = hexdump)]
291        Vec<u8>,
292    ),
293}
294
295impl OwnerConfigItem {
296    pub fn write(&self, dest: &mut impl Write) -> Result<()> {
297        match self {
298            Self::ApplicationKey(x) => x.write(dest)?,
299            Self::FlashInfoConfig(x) => x.write(dest)?,
300            Self::FlashConfig(x) => x.write(dest)?,
301            Self::RescueConfig(x) => x.write(dest)?,
302            Self::IsfbConfig(x) => x.write(dest)?,
303            Self::Raw(x) => dest.write_all(x)?,
304        }
305        Ok(())
306    }
307
308    pub fn read(src: &mut impl Read) -> Result<Option<Self>> {
309        let header = TlvHeader::read(src)?;
310        let item = match header.identifier {
311            TlvTag::ApplicationKey => Self::ApplicationKey(OwnerApplicationKey::read(src, header)?),
312            TlvTag::FlashConfig => Self::FlashConfig(OwnerFlashConfig::read(src, header)?),
313            TlvTag::FlashInfoConfig => {
314                Self::FlashInfoConfig(OwnerFlashInfoConfig::read(src, header)?)
315            }
316            TlvTag::Rescue => Self::RescueConfig(OwnerRescueConfig::read(src, header)?),
317            TlvTag::IntegratorSpecificFirmwareBinding => {
318                Self::IsfbConfig(OwnerIsfbConfig::read(src, header)?)
319            }
320            TlvTag::NotPresent => return Ok(None),
321            _ => {
322                let mut data = Vec::new();
323                header.write(&mut data)?;
324                if header.length >= TlvHeader::SIZE && header.length < OwnerBlock::DATA_SIZE {
325                    data.resize(header.length, 0);
326                    let len = src.read(&mut data)?;
327                    data.resize(len, 0);
328                } else {
329                    src.read_to_end(&mut data)?;
330                }
331                Self::Raw(data)
332            }
333        };
334        Ok(Some(item))
335    }
336}
337
338#[cfg(test)]
339mod test {
340    use super::*;
341    use crate::crypto::ecdsa::EcdsaRawPublicKey;
342    use crate::ownership::{
343        ApplicationKeyDomain, FlashFlags, OwnerFlashInfoConfig, OwnerFlashRegion, OwnerInfoPage,
344        OwnerRescueConfig,
345    };
346    use crate::util::hexdump::{hexdump_parse, hexdump_string};
347
348    #[rustfmt::skip]
349    const OWNER_BIN: &str =
350r#"00000000: 4f 57 4e 52 00 08 00 00 00 00 00 00 4c 4e 45 58  OWNR........LNEX
35100000010: 50 32 35 36 4f 50 45 4e ff ff ff ff 00 00 00 00  P256OPEN........
35200000020: 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e  ~~~~~~~~~~~~~~~~
35300000030: 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e  ~~~~~~~~~~~~~~~~
35400000040: d4 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
35500000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
35600000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
35700000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
35800000080: 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11  ................
35900000090: 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11  ................
360000000a0: 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21  !!!!!!!!!!!!!!!!
361000000b0: 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21  !!!!!!!!!!!!!!!!
362000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
363000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
364000000e0: 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33  3333333333333333
365000000f0: 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33  3333333333333333
36600000100: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
36700000110: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
36800000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
36900000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
37000000140: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55  UUUUUUUUUUUUUUUU
37100000150: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55  UUUUUUUUUUUUUUUU
37200000160: 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66  ffffffffffffffff
37300000170: 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66  ffffffffffffffff
37400000180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
37500000190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
376000001a0: 41 50 50 4b 70 00 00 00 50 32 35 36 70 72 6f 64  APPKp...P256prod
377000001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
378000001c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
379000001d0: aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa  ................
380000001e0: aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa  ................
381000001f0: bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb  ................
38200000200: bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb  ................
38300000210: 46 4c 53 48 20 00 00 00 00 00 00 01 66 06 00 99  FLSH .......f...
38400000220: 66 06 00 00 00 01 00 02 77 17 11 88 77 17 11 11  f.......w...w...
38500000230: 49 4e 46 4f 20 00 00 00 00 01 00 00 66 06 00 99  INFO .......f...
38600000240: 66 06 00 00 01 05 00 00 77 17 11 88 77 17 11 11  f.......w...w...
38700000250: 52 45 53 51 50 00 00 00 58 00 00 40 20 00 e0 00  RESQP...X..@ ...
38800000260: 45 4d 50 54 4d 53 45 43 4e 45 58 54 55 4e 4c 4b  EMPTMSECNEXTUNLK
38900000270: 41 43 54 56 51 53 45 52 42 53 45 52 4f 42 45 52  ACTVQSERBSEROBER
39000000280: 47 4f 4c 42 51 45 52 42 50 53 52 42 52 4e 57 4f  GOLBQERBPSRBRNWO
39100000290: 30 47 50 4f 31 47 50 4f 44 49 54 4f 54 49 41 57  0GPO1GPODITOTIAW
392000002a0: 49 53 46 42 2c 00 00 00 01 08 00 00 66 06 00 00  ISFB,.......f...
393000002b0: 70 72 6f 64 00 00 00 00 00 00 00 00 00 00 00 00  prod............
394000002c0: 00 00 00 00 00 00 00 00 80 00 00 00 5a 5a 5a 5a  ............ZZZZ
395000002d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
396000002e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
397000002f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39800000300: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39900000310: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40000000320: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40100000330: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40200000340: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40300000350: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40400000360: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40500000370: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40600000380: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40700000390: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
408000003a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
409000003b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
410000003c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
411000003d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
412000003e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
413000003f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41400000400: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41500000410: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41600000420: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41700000430: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41800000440: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41900000450: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42000000460: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42100000470: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42200000480: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42300000490: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
424000004a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
425000004b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
426000004c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
427000004d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
428000004e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
429000004f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43000000500: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43100000510: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43200000520: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43300000530: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43400000540: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43500000550: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43600000560: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43700000570: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43800000580: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43900000590: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
440000005a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
441000005b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
442000005c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
443000005d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
444000005e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
445000005f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44600000600: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44700000610: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44800000620: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44900000630: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45000000640: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45100000650: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45200000660: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45300000670: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45400000680: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45500000690: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
456000006a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
457000006b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
458000006c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
459000006d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
460000006e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
461000006f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46200000700: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46300000710: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46400000720: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46500000730: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46600000740: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46700000750: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46800000760: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46900000770: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
47000000780: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
47100000790: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
472000007a0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77  wwwwwwwwwwwwwwww
473000007b0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77  wwwwwwwwwwwwwwww
474000007c0: 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88  ................
475000007d0: 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88  ................
476000007e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
477000007f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
478"#;
479
480    const OWNER_JSON: &str = r#"{
481  config_version: 0,
482  sram_exec: "DisabledLocked",
483  ownership_key_alg: "EcdsaP256",
484  update_mode: "Open",
485  min_security_version_bl0: "NoChange",
486  lock_constraint: 0,
487  boot_svc_after_wakeup: "False",
488  owner_key: {
489    Ecdsa: {
490      x: "1111111111111111111111111111111111111111111111111111111111111111",
491      y: "2121212121212121212121212121212121212121212121212121212121212121"
492    }
493  },
494  activate_key: {
495    Ecdsa: {
496      x: "3333333333333333333333333333333333333333333333333333333333333333",
497      y: "4444444444444444444444444444444444444444444444444444444444444444"
498    }
499  },
500  unlock_key: {
501    Ecdsa: {
502      x: "5555555555555555555555555555555555555555555555555555555555555555",
503      y: "6666666666666666666666666666666666666666666666666666666666666666"
504    }
505  },
506  data: [
507    {
508      ApplicationKey: {
509        key_alg: "EcdsaP256",
510        key_domain: "Prod",
511        key_diversifier: [
512          0x0,
513          0x0,
514          0x0,
515          0x0,
516          0x0,
517          0x0,
518          0x0
519        ],
520        usage_constraint: 0x0,
521        key: {
522          Ecdsa: {
523            x: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
524            y: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
525          }
526        }
527      }
528    },
529    {
530      FlashConfig: {
531        config: [
532          {
533            start: 0,
534            size: 256,
535            read: true,
536            program: true,
537            erase: true,
538            scramble: true,
539            ecc: true,
540            high_endurance: true,
541            protect_when_active: false,
542            lock: false
543          },
544          {
545            start: 256,
546            size: 512,
547            read: true,
548            program: true,
549            erase: true,
550            scramble: true,
551            ecc: true,
552            high_endurance: true,
553            protect_when_active: false,
554            lock: false
555          }
556        ]
557      }
558    },
559    {
560      FlashInfoConfig: {
561        config: [
562          {
563            bank: 0,
564            page: 1,
565            pad: 0,
566            read: true,
567            program: true,
568            erase: true,
569            scramble: true,
570            ecc: true,
571            high_endurance: true,
572            protect_when_active: false,
573            lock: false
574          },
575          {
576            bank: 1,
577            page: 5,
578            pad: 0,
579            read: true,
580            program: true,
581            erase: true,
582            scramble: true,
583            ecc: true,
584            high_endurance: true,
585            protect_when_active: false,
586            lock: false
587          }
588        ]
589      }
590    },
591    {
592      RescueConfig: {
593        protocol: "Xmodem",
594        trigger: "UartBreak",
595        trigger_index: 0,
596        gpio_pull_en: false,
597        gpio_value: false,
598        enter_on_watchdog: false,
599        enter_on_failure: false,
600        timeout: 0,
601        start: 32,
602        size: 224,
603        command_allow: [
604          "Empty",
605          "MinBl0SecVerRequest",
606          "NextBl0SlotRequest",
607          "OwnershipUnlockRequest",
608          "OwnershipActivateRequest",
609          "Rescue",
610          "RescueB",
611          "Reboot",
612          "GetBootLog",
613          "BootSvcReq",
614          "BootSvcRsp",
615          "OwnerBlock",
616          "GetOwnerPage0",
617          "GetOwnerPage1",
618          "GetDeviceId",
619          "Wait"
620        ]
621      }
622    },
623    {
624      IsfbConfig: {
625        bank: 1,
626        page: 8,
627        erase_conditions: 0x666,
628        key_domain: "Prod",
629        product_words: 128
630      }
631    }
632  ],
633  signature: {
634    r: "7777777777777777777777777777777777777777777777777777777777777777",
635    s: "8888888888888888888888888888888888888888888888888888888888888888"
636  },
637  seal: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
638}"#;
639
640    #[test]
641    fn test_owner_write() -> Result<()> {
642        let own = OwnerBlock {
643            config_version: 0,
644            sram_exec: SramExecMode::default(),
645            ownership_key_alg: OwnershipKeyAlg::EcdsaP256,
646            owner_key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
647                x: hex::decode("1111111111111111111111111111111111111111111111111111111111111111")?,
648                y: hex::decode("2121212121212121212121212121212121212121212121212121212121212121")?,
649            }),
650            activate_key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
651                x: hex::decode("3333333333333333333333333333333333333333333333333333333333333333")?,
652                y: hex::decode("4444444444444444444444444444444444444444444444444444444444444444")?,
653            }),
654            unlock_key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
655                x: hex::decode("5555555555555555555555555555555555555555555555555555555555555555")?,
656                y: hex::decode("6666666666666666666666666666666666666666666666666666666666666666")?,
657            }),
658            data: vec![
659                OwnerConfigItem::ApplicationKey(OwnerApplicationKey {
660                    key_alg: OwnershipKeyAlg::EcdsaP256,
661                    key_domain: ApplicationKeyDomain::Prod,
662                    key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
663                        x: hex::decode(
664                            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
665                        )?,
666                        y: hex::decode(
667                            "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
668                        )?,
669                    }),
670                    ..Default::default()
671                }),
672                OwnerConfigItem::FlashConfig(OwnerFlashConfig {
673                    config: vec![
674                        OwnerFlashRegion {
675                            start: 0x000,
676                            size: 0x100,
677                            flags: FlashFlags::basic(),
678                        },
679                        OwnerFlashRegion {
680                            start: 0x100,
681                            size: 0x200,
682                            flags: FlashFlags::basic(),
683                        },
684                    ],
685                    ..Default::default()
686                }),
687                OwnerConfigItem::FlashInfoConfig(OwnerFlashInfoConfig {
688                    config: vec![
689                        OwnerInfoPage::new(0, 1, FlashFlags::basic()),
690                        OwnerInfoPage::new(1, 5, FlashFlags::basic()),
691                    ],
692                    ..Default::default()
693                }),
694                OwnerConfigItem::RescueConfig(OwnerRescueConfig::all()),
695                OwnerConfigItem::IsfbConfig(OwnerIsfbConfig {
696                    bank: 1,
697                    page: 8,
698                    pad: 0,
699                    erase_conditions: 0x0000_0666,
700                    key_domain: ApplicationKeyDomain::Prod,
701                    product_words: 128,
702                    ..Default::default()
703                }),
704            ],
705            signature: EcdsaRawSignature {
706                r: hex::decode("7777777777777777777777777777777777777777777777777777777777777777")?,
707                s: hex::decode("8888888888888888888888888888888888888888888888888888888888888888")?,
708            },
709            seal: hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")?,
710            ..Default::default()
711        };
712        let mut bin = Vec::new();
713        own.write(&mut bin)?;
714        eprintln!("{}", hexdump_string(&bin)?);
715        assert_eq!(hexdump_string(&bin)?, OWNER_BIN);
716        Ok(())
717    }
718
719    #[test]
720    fn test_owner_read() -> Result<()> {
721        let buf = hexdump_parse(OWNER_BIN)?;
722        let mut cur = std::io::Cursor::new(&buf);
723        let header = TlvHeader::read(&mut cur)?;
724        let own = OwnerBlock::read(&mut cur, header)?;
725        let doc = serde_annotate::serialize(&own)?.to_json5().to_string();
726        eprintln!("{}", doc);
727        assert_eq!(doc, OWNER_JSON);
728        Ok(())
729    }
730}