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;
6use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
7use serde::{Deserialize, Serialize};
8use serde_annotate::Annotate;
9use std::convert::TryFrom;
10use std::io::{Read, Write};
11
12use super::GlobalFlags;
13use super::misc::{KeyMaterial, OwnershipKeyAlg, TlvHeader, TlvTag};
14use super::{OwnerApplicationKey, OwnerFlashConfig, OwnerFlashInfoConfig, OwnerRescueConfig};
15use crate::crypto::ecdsa::{EcdsaPrivateKey, EcdsaRawSignature};
16use crate::with_unknown;
17
18with_unknown! {
19    pub enum SramExecMode: u32 [default = Self::DisabledLocked] {
20        DisabledLocked = u32::from_le_bytes(*b"LNEX"),
21        Disabled = u32::from_le_bytes(*b"NOEX"),
22        Enabled = u32::from_le_bytes(*b"EXEC"),
23    }
24
25    pub enum MinSecurityVersion: u32 [default = Self::NoChange] {
26        NoChange = 0xFFFFFFFFu32,
27    }
28
29    pub enum OwnershipUpdateMode: u32 [default = Self::Open] {
30        Open = u32::from_le_bytes(*b"OPEN"),
31        UnlockSelf = u32::from_le_bytes(*b"SELF"),
32        SelfVersion = u32::from_le_bytes(*b"SELV"),
33        NewVersion = u32::from_le_bytes(*b"NEWV"),
34    }
35}
36
37/// Describes the owner configuration and key material.
38#[derive(Debug, Serialize, Deserialize, Annotate)]
39pub struct OwnerBlock {
40    /// Header identifying this struct.
41    #[serde(
42        skip_serializing_if = "GlobalFlags::not_debug",
43        default = "OwnerBlock::default_header"
44    )]
45    pub header: TlvHeader,
46    /// Configuraion version (monotonically increasing per owner).
47    #[serde(default)]
48    pub config_version: u32,
49    /// Whether the owner wants to permit code execution in SRAM.
50    #[serde(default)]
51    pub sram_exec: SramExecMode,
52    /// The key algorithm of the ownership keys.
53    pub ownership_key_alg: OwnershipKeyAlg,
54    /// Ownership update mode.
55    #[serde(default)]
56    pub update_mode: OwnershipUpdateMode,
57    /// Set the minimum security version to this value.
58    #[serde(default)]
59    pub min_security_version_bl0: MinSecurityVersion,
60    /// The device ID locking constraint.
61    #[serde(default)]
62    pub lock_constraint: u32,
63    /// The device ID to which this config applies.
64    #[serde(
65        default = "OwnerBlock::default_constraint",
66        skip_serializing_if = "OwnerBlock::is_default_constraint"
67    )]
68    #[annotate(format=hex)]
69    pub device_id: [u32; 8],
70    #[serde(default, skip_serializing_if = "GlobalFlags::not_debug")]
71    #[annotate(format=hex)]
72    pub reserved: [u32; 16],
73    /// The owner identity key.
74    pub owner_key: KeyMaterial,
75    /// The owner activation key.
76    pub activate_key: KeyMaterial,
77    /// The owner unlock key.
78    pub unlock_key: KeyMaterial,
79    /// A list of other configuration items (application keys, flash configuration, etc).
80    #[serde(default)]
81    pub data: Vec<OwnerConfigItem>,
82    #[serde(default, skip_serializing_if = "EcdsaRawSignature::is_empty")]
83    #[annotate(format=hex)]
84    /// A signature over this block with the owner key.
85    pub signature: EcdsaRawSignature,
86    /// A sealing value that locks a configuration to a particular device.
87    #[serde(default, skip_serializing_if = "Vec::is_empty", with = "serde_bytes")]
88    #[annotate(format = hexstr)]
89    pub seal: Vec<u8>,
90}
91
92impl Default for OwnerBlock {
93    fn default() -> Self {
94        Self {
95            header: Self::default_header(),
96            config_version: 0,
97            sram_exec: SramExecMode::default(),
98            ownership_key_alg: OwnershipKeyAlg::default(),
99            update_mode: OwnershipUpdateMode::default(),
100            min_security_version_bl0: MinSecurityVersion::default(),
101            lock_constraint: 0,
102            device_id: Self::default_constraint(),
103            reserved: [0u32; 16],
104            owner_key: KeyMaterial::default(),
105            activate_key: KeyMaterial::default(),
106            unlock_key: KeyMaterial::default(),
107            data: Vec::new(),
108            signature: EcdsaRawSignature::default(),
109            seal: Vec::new(),
110        }
111    }
112}
113
114impl OwnerBlock {
115    pub const SIZE: usize = 2048;
116    pub const DATA_SIZE: usize = 1536;
117    pub const SIGNATURE_OFFSET: usize = 1952;
118    // The not present value must be reflected in the TlvTag::NotPresent value.
119    const NOT_PRESENT: u8 = 0x5a;
120    const NO_CONSTRAINT: u32 = 0x7e7e7e7e;
121
122    pub fn default_header() -> TlvHeader {
123        TlvHeader::new(TlvTag::Owner, 0, "0.0")
124    }
125    pub fn basic() -> Self {
126        Self {
127            data: vec![
128                OwnerConfigItem::ApplicationKey(OwnerApplicationKey::default()),
129                OwnerConfigItem::FlashConfig(OwnerFlashConfig::basic()),
130                OwnerConfigItem::FlashInfoConfig(OwnerFlashInfoConfig::basic()),
131                OwnerConfigItem::RescueConfig(OwnerRescueConfig::all()),
132            ],
133            ..Default::default()
134        }
135    }
136
137    pub fn write(&self, dest: &mut impl Write) -> Result<()> {
138        let header = TlvHeader::new(TlvTag::Owner, Self::SIZE, "0.0");
139        header.write(dest)?;
140        dest.write_u32::<LittleEndian>(self.config_version)?;
141        dest.write_u32::<LittleEndian>(u32::from(self.sram_exec))?;
142        dest.write_u32::<LittleEndian>(u32::from(self.ownership_key_alg))?;
143        dest.write_u32::<LittleEndian>(u32::from(self.update_mode))?;
144        dest.write_u32::<LittleEndian>(u32::from(self.min_security_version_bl0))?;
145        dest.write_u32::<LittleEndian>(self.lock_constraint)?;
146
147        for (i, x) in self.device_id.iter().enumerate() {
148            if self.lock_constraint & (1u32 << i) == 0 {
149                dest.write_u32::<LittleEndian>(Self::NO_CONSTRAINT)?;
150            } else {
151                dest.write_u32::<LittleEndian>(*x)?;
152            }
153        }
154        for x in &self.reserved {
155            dest.write_u32::<LittleEndian>(*x)?;
156        }
157        self.owner_key.write_length(dest, 96)?;
158        self.activate_key.write_length(dest, 96)?;
159        self.unlock_key.write_length(dest, 96)?;
160        let mut data = Vec::new();
161        for item in &self.data {
162            item.write(&mut data)?;
163        }
164        data.resize(Self::DATA_SIZE, Self::NOT_PRESENT);
165        dest.write_all(&data)?;
166        self.signature.write(dest)?;
167        if self.seal.is_empty() {
168            dest.write_all(&[0u8; 32])?;
169        } else {
170            dest.write_all(&self.seal)?;
171        }
172        Ok(())
173    }
174
175    pub fn read(src: &mut impl Read, header: TlvHeader) -> Result<Self> {
176        let config_version = src.read_u32::<LittleEndian>()?;
177        let sram_exec = SramExecMode(src.read_u32::<LittleEndian>()?);
178        let ownership_key_alg = OwnershipKeyAlg(src.read_u32::<LittleEndian>()?);
179        let update_mode = OwnershipUpdateMode(src.read_u32::<LittleEndian>()?);
180        let min_security_version_bl0 = MinSecurityVersion(src.read_u32::<LittleEndian>()?);
181        let lock_constraint = src.read_u32::<LittleEndian>()?;
182
183        let mut device_id = [0u32; 8];
184        src.read_u32_into::<LittleEndian>(&mut device_id)?;
185        let mut reserved = [0u32; 16];
186        src.read_u32_into::<LittleEndian>(&mut reserved)?;
187        let owner_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?;
188        let activate_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?;
189        let unlock_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?;
190        let mut bytes = vec![0u8; Self::DATA_SIZE];
191        src.read_exact(&mut bytes)?;
192        let mut cursor = std::io::Cursor::new(&bytes);
193        let mut data = Vec::new();
194        while cursor.position() as usize != Self::DATA_SIZE {
195            match OwnerConfigItem::read(&mut cursor)? {
196                Some(item) => data.push(item),
197                None => break,
198            }
199        }
200        let signature = EcdsaRawSignature::read(src)?;
201        let mut seal = vec![0u8; 32];
202        src.read_exact(&mut seal)?;
203        Ok(Self {
204            header,
205            config_version,
206            sram_exec,
207            ownership_key_alg,
208            update_mode,
209            min_security_version_bl0,
210            lock_constraint,
211            device_id,
212            reserved,
213            owner_key,
214            activate_key,
215            unlock_key,
216            data,
217            signature,
218            seal,
219        })
220    }
221    pub fn sign(&mut self, key: &EcdsaPrivateKey) -> Result<()> {
222        let mut data = Vec::new();
223        self.write(&mut data)?;
224        self.signature = key.digest_and_sign(&data[..Self::SIGNATURE_OFFSET])?;
225        Ok(())
226    }
227
228    pub fn is_default_constraint(d: &[u32; 8]) -> bool {
229        *d == [Self::NO_CONSTRAINT; 8]
230    }
231
232    pub fn default_constraint() -> [u32; 8] {
233        [Self::NO_CONSTRAINT; 8]
234    }
235}
236
237#[derive(Debug, Serialize, Deserialize, Annotate)]
238pub enum OwnerConfigItem {
239    #[serde(alias = "application_key")]
240    ApplicationKey(OwnerApplicationKey),
241    #[serde(alias = "flash_info_config")]
242    FlashInfoConfig(OwnerFlashInfoConfig),
243    #[serde(alias = "flash_config")]
244    FlashConfig(OwnerFlashConfig),
245    #[serde(alias = "rescue_config")]
246    RescueConfig(OwnerRescueConfig),
247    #[serde(alias = "raw")]
248    Raw(
249        #[serde(with = "serde_bytes")]
250        #[annotate(format = hexdump)]
251        Vec<u8>,
252    ),
253}
254
255impl OwnerConfigItem {
256    pub fn write(&self, dest: &mut impl Write) -> Result<()> {
257        match self {
258            Self::ApplicationKey(x) => x.write(dest)?,
259            Self::FlashInfoConfig(x) => x.write(dest)?,
260            Self::FlashConfig(x) => x.write(dest)?,
261            Self::RescueConfig(x) => x.write(dest)?,
262            Self::Raw(x) => dest.write_all(x)?,
263        }
264        Ok(())
265    }
266
267    pub fn read(src: &mut impl Read) -> Result<Option<Self>> {
268        let header = TlvHeader::read(src)?;
269        let item = match header.identifier {
270            TlvTag::ApplicationKey => Self::ApplicationKey(OwnerApplicationKey::read(src, header)?),
271            TlvTag::FlashConfig => Self::FlashConfig(OwnerFlashConfig::read(src, header)?),
272            TlvTag::FlashInfoConfig => {
273                Self::FlashInfoConfig(OwnerFlashInfoConfig::read(src, header)?)
274            }
275            TlvTag::Rescue => Self::RescueConfig(OwnerRescueConfig::read(src, header)?),
276            TlvTag::NotPresent => return Ok(None),
277            _ => {
278                let mut data = Vec::new();
279                header.write(&mut data)?;
280                if header.length >= TlvHeader::SIZE && header.length < OwnerBlock::DATA_SIZE {
281                    data.resize(header.length, 0);
282                    let len = src.read(&mut data)?;
283                    data.resize(len, 0);
284                } else {
285                    src.read_to_end(&mut data)?;
286                }
287                Self::Raw(data)
288            }
289        };
290        Ok(Some(item))
291    }
292}
293
294#[cfg(test)]
295mod test {
296    use super::*;
297    use crate::crypto::ecdsa::EcdsaRawPublicKey;
298    use crate::ownership::{
299        ApplicationKeyDomain, FlashFlags, OwnerFlashInfoConfig, OwnerFlashRegion, OwnerInfoPage,
300        OwnerRescueConfig,
301    };
302    use crate::util::hexdump::{hexdump_parse, hexdump_string};
303
304    #[rustfmt::skip]
305    const OWNER_BIN: &str =
306r#"00000000: 4f 57 4e 52 00 08 00 00 00 00 00 00 4c 4e 45 58  OWNR........LNEX
30700000010: 50 32 35 36 4f 50 45 4e ff ff ff ff 00 00 00 00  P256OPEN........
30800000020: 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e  ~~~~~~~~~~~~~~~~
30900000030: 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e  ~~~~~~~~~~~~~~~~
31000000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
31100000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
31200000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
31300000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
31400000080: 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11  ................
31500000090: 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11  ................
316000000a0: 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21  !!!!!!!!!!!!!!!!
317000000b0: 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21  !!!!!!!!!!!!!!!!
318000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
319000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
320000000e0: 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33  3333333333333333
321000000f0: 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33  3333333333333333
32200000100: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
32300000110: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
32400000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
32500000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
32600000140: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55  UUUUUUUUUUUUUUUU
32700000150: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55  UUUUUUUUUUUUUUUU
32800000160: 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66  ffffffffffffffff
32900000170: 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66  ffffffffffffffff
33000000180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
33100000190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
332000001a0: 41 50 50 4b 70 00 00 00 50 32 35 36 70 72 6f 64  APPKp...P256prod
333000001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
334000001c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
335000001d0: aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa  ................
336000001e0: aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa  ................
337000001f0: bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb  ................
33800000200: bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb  ................
33900000210: 46 4c 53 48 20 00 00 00 00 00 00 01 66 06 00 99  FLSH .......f...
34000000220: 66 06 00 00 00 01 00 02 77 17 11 88 77 17 11 11  f.......w...w...
34100000230: 49 4e 46 4f 20 00 00 00 00 01 00 00 66 06 00 99  INFO .......f...
34200000240: 66 06 00 00 01 05 00 00 77 17 11 88 77 17 11 11  f.......w...w...
34300000250: 52 45 53 51 50 00 00 00 58 4d 44 4d 20 00 e0 00  RESQP...XMDM ...
34400000260: 45 4d 50 54 4d 53 45 43 4e 45 58 54 55 4e 4c 4b  EMPTMSECNEXTUNLK
34500000270: 41 43 54 56 51 53 45 52 42 53 45 52 4f 42 45 52  ACTVQSERBSEROBER
34600000280: 47 4f 4c 42 51 45 52 42 50 53 52 42 52 4e 57 4f  GOLBQERBPSRBRNWO
34700000290: 30 47 50 4f 31 47 50 4f 44 49 54 4f 54 49 41 57  0GPO1GPODITOTIAW
348000002a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
349000002b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
350000002c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
351000002d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
352000002e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
353000002f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
35400000300: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
35500000310: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
35600000320: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
35700000330: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
35800000340: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
35900000350: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
36000000360: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
36100000370: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
36200000380: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
36300000390: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
364000003a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
365000003b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
366000003c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
367000003d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
368000003e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
369000003f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
37000000400: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
37100000410: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
37200000420: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
37300000430: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
37400000440: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
37500000450: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
37600000460: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
37700000470: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
37800000480: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
37900000490: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
380000004a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
381000004b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
382000004c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
383000004d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
384000004e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
385000004f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
38600000500: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
38700000510: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
38800000520: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
38900000530: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39000000540: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39100000550: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39200000560: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39300000570: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39400000580: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39500000590: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
396000005a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
397000005b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
398000005c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
399000005d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
400000005e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
401000005f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40200000600: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40300000610: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40400000620: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40500000630: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40600000640: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40700000650: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40800000660: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40900000670: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41000000680: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41100000690: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
412000006a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
413000006b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
414000006c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
415000006d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
416000006e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
417000006f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41800000700: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41900000710: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42000000720: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42100000730: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42200000740: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42300000750: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42400000760: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42500000770: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42600000780: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42700000790: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
428000007a0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77  wwwwwwwwwwwwwwww
429000007b0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77  wwwwwwwwwwwwwwww
430000007c0: 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88  ................
431000007d0: 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88  ................
432000007e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
433000007f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
434"#;
435
436    const OWNER_JSON: &str = r#"{
437  config_version: 0,
438  sram_exec: "DisabledLocked",
439  ownership_key_alg: "EcdsaP256",
440  update_mode: "Open",
441  min_security_version_bl0: "NoChange",
442  lock_constraint: 0,
443  owner_key: {
444    Ecdsa: {
445      x: "1111111111111111111111111111111111111111111111111111111111111111",
446      y: "2121212121212121212121212121212121212121212121212121212121212121"
447    }
448  },
449  activate_key: {
450    Ecdsa: {
451      x: "3333333333333333333333333333333333333333333333333333333333333333",
452      y: "4444444444444444444444444444444444444444444444444444444444444444"
453    }
454  },
455  unlock_key: {
456    Ecdsa: {
457      x: "5555555555555555555555555555555555555555555555555555555555555555",
458      y: "6666666666666666666666666666666666666666666666666666666666666666"
459    }
460  },
461  data: [
462    {
463      ApplicationKey: {
464        key_alg: "EcdsaP256",
465        key_domain: "Prod",
466        key_diversifier: [
467          0x0,
468          0x0,
469          0x0,
470          0x0,
471          0x0,
472          0x0,
473          0x0
474        ],
475        usage_constraint: 0x0,
476        key: {
477          Ecdsa: {
478            x: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
479            y: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
480          }
481        }
482      }
483    },
484    {
485      FlashConfig: {
486        config: [
487          {
488            start: 0,
489            size: 256,
490            read: true,
491            program: true,
492            erase: true,
493            scramble: true,
494            ecc: true,
495            high_endurance: true,
496            protect_when_active: false,
497            lock: false
498          },
499          {
500            start: 256,
501            size: 512,
502            read: true,
503            program: true,
504            erase: true,
505            scramble: true,
506            ecc: true,
507            high_endurance: true,
508            protect_when_active: false,
509            lock: false
510          }
511        ]
512      }
513    },
514    {
515      FlashInfoConfig: {
516        config: [
517          {
518            bank: 0,
519            page: 1,
520            pad: 0,
521            read: true,
522            program: true,
523            erase: true,
524            scramble: true,
525            ecc: true,
526            high_endurance: true,
527            protect_when_active: false,
528            lock: false
529          },
530          {
531            bank: 1,
532            page: 5,
533            pad: 0,
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      }
545    },
546    {
547      RescueConfig: {
548        rescue_type: "Xmodem",
549        start: 32,
550        size: 224,
551        command_allow: [
552          "Empty",
553          "MinBl0SecVerRequest",
554          "NextBl0SlotRequest",
555          "OwnershipUnlockRequest",
556          "OwnershipActivateRequest",
557          "Rescue",
558          "RescueB",
559          "Reboot",
560          "GetBootLog",
561          "BootSvcReq",
562          "BootSvcRsp",
563          "OwnerBlock",
564          "GetOwnerPage0",
565          "GetOwnerPage1",
566          "GetDeviceId",
567          "Wait"
568        ]
569      }
570    }
571  ],
572  signature: {
573    r: "7777777777777777777777777777777777777777777777777777777777777777",
574    s: "8888888888888888888888888888888888888888888888888888888888888888"
575  },
576  seal: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
577}"#;
578
579    #[test]
580    fn test_owner_write() -> Result<()> {
581        let own = OwnerBlock {
582            config_version: 0,
583            sram_exec: SramExecMode::default(),
584            ownership_key_alg: OwnershipKeyAlg::EcdsaP256,
585            owner_key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
586                x: hex::decode("1111111111111111111111111111111111111111111111111111111111111111")?,
587                y: hex::decode("2121212121212121212121212121212121212121212121212121212121212121")?,
588            }),
589            activate_key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
590                x: hex::decode("3333333333333333333333333333333333333333333333333333333333333333")?,
591                y: hex::decode("4444444444444444444444444444444444444444444444444444444444444444")?,
592            }),
593            unlock_key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
594                x: hex::decode("5555555555555555555555555555555555555555555555555555555555555555")?,
595                y: hex::decode("6666666666666666666666666666666666666666666666666666666666666666")?,
596            }),
597            data: vec![
598                OwnerConfigItem::ApplicationKey(OwnerApplicationKey {
599                    key_alg: OwnershipKeyAlg::EcdsaP256,
600                    key_domain: ApplicationKeyDomain::Prod,
601                    key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
602                        x: hex::decode(
603                            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
604                        )?,
605                        y: hex::decode(
606                            "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
607                        )?,
608                    }),
609                    ..Default::default()
610                }),
611                OwnerConfigItem::FlashConfig(OwnerFlashConfig {
612                    config: vec![
613                        OwnerFlashRegion {
614                            start: 0x000,
615                            size: 0x100,
616                            flags: FlashFlags::basic(),
617                        },
618                        OwnerFlashRegion {
619                            start: 0x100,
620                            size: 0x200,
621                            flags: FlashFlags::basic(),
622                        },
623                    ],
624                    ..Default::default()
625                }),
626                OwnerConfigItem::FlashInfoConfig(OwnerFlashInfoConfig {
627                    config: vec![
628                        OwnerInfoPage::new(0, 1, FlashFlags::basic()),
629                        OwnerInfoPage::new(1, 5, FlashFlags::basic()),
630                    ],
631                    ..Default::default()
632                }),
633                OwnerConfigItem::RescueConfig(OwnerRescueConfig::all()),
634            ],
635            signature: EcdsaRawSignature {
636                r: hex::decode("7777777777777777777777777777777777777777777777777777777777777777")?,
637                s: hex::decode("8888888888888888888888888888888888888888888888888888888888888888")?,
638            },
639            seal: hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")?,
640            ..Default::default()
641        };
642        let mut bin = Vec::new();
643        own.write(&mut bin)?;
644        eprintln!("{}", hexdump_string(&bin)?);
645        assert_eq!(hexdump_string(&bin)?, OWNER_BIN);
646        Ok(())
647    }
648
649    #[test]
650    fn test_owner_read() -> Result<()> {
651        let buf = hexdump_parse(OWNER_BIN)?;
652        let mut cur = std::io::Cursor::new(&buf);
653        let header = TlvHeader::read(&mut cur)?;
654        let own = OwnerBlock::read(&mut cur, header)?;
655        let doc = serde_annotate::serialize(&own)?.to_json5().to_string();
656        eprintln!("{}", doc);
657        assert_eq!(doc, OWNER_JSON);
658        Ok(())
659    }
660}