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