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::crypto::Error as CryptoError;
20use crate::crypto::ecdsa::{EcdsaPrivateKey, EcdsaRawSignature};
21use crate::with_unknown;
22
23with_unknown! {
24    pub enum SramExecMode: u32 [default = Self::DisabledLocked] {
25        DisabledLocked = u32::from_le_bytes(*b"LNEX"),
26        Disabled = u32::from_le_bytes(*b"NOEX"),
27        Enabled = u32::from_le_bytes(*b"EXEC"),
28    }
29
30    pub enum MinSecurityVersion: u32 [default = Self::NoChange] {
31        NoChange = 0xFFFFFFFFu32,
32    }
33
34    pub enum OwnershipUpdateMode: u32 [default = Self::Open] {
35        Open = u32::from_le_bytes(*b"OPEN"),
36        UnlockSelf = u32::from_le_bytes(*b"SELF"),
37        SelfVersion = u32::from_le_bytes(*b"SELV"),
38        NewVersion = u32::from_le_bytes(*b"NEWV"),
39    }
40}
41
42/// Describes the owner configuration and key material.
43#[derive(Debug, Deserialize, Annotate)]
44pub struct OwnerBlock {
45    /// Header identifying this struct.
46    #[serde(
47        skip_serializing_if = "GlobalFlags::not_debug",
48        default = "OwnerBlock::default_header"
49    )]
50    pub header: TlvHeader,
51    /// Configuraion version (monotonically increasing per owner).
52    #[serde(default)]
53    pub config_version: u32,
54    /// Whether the owner wants to permit code execution in SRAM.
55    #[serde(default)]
56    pub sram_exec: SramExecMode,
57    /// The key algorithm of the ownership keys.
58    pub ownership_key_alg: OwnershipKeyAlg,
59    /// Ownership update mode.
60    #[serde(default)]
61    pub update_mode: OwnershipUpdateMode,
62    /// Set the minimum security version to this value.
63    #[serde(default)]
64    pub min_security_version_bl0: MinSecurityVersion,
65    /// The device ID locking constraint.
66    #[serde(default)]
67    pub lock_constraint: u32,
68    /// The device ID to which this config applies.
69    #[serde(
70        default = "OwnerBlock::default_constraint",
71        skip_serializing_if = "OwnerBlock::is_default_constraint"
72    )]
73    #[annotate(format=hex)]
74    pub device_id: [u32; 8],
75    #[serde(default, skip_serializing_if = "GlobalFlags::not_debug")]
76    #[annotate(format=hex)]
77    pub reserved: [u32; 16],
78    /// The owner identity key.
79    pub owner_key: KeyMaterial,
80    /// The owner activation key.
81    pub activate_key: KeyMaterial,
82    /// The owner unlock key.
83    pub unlock_key: KeyMaterial,
84    /// A list of other configuration items (application keys, flash configuration, etc).
85    #[serde(default)]
86    pub data: Vec<OwnerConfigItem>,
87    #[serde(default, skip_serializing_if = "EcdsaRawSignature::is_empty")]
88    #[annotate(format=hex)]
89    /// A signature over this block with the owner key.
90    pub signature: EcdsaRawSignature,
91    /// A sealing value that locks a configuration to a particular device.
92    #[serde(default, skip_serializing_if = "Vec::is_empty", with = "serde_bytes")]
93    #[annotate(format = hexstr)]
94    pub seal: Vec<u8>,
95}
96
97impl Default for OwnerBlock {
98    fn default() -> Self {
99        Self {
100            header: Self::default_header(),
101            config_version: 0,
102            sram_exec: SramExecMode::default(),
103            ownership_key_alg: OwnershipKeyAlg::default(),
104            update_mode: OwnershipUpdateMode::default(),
105            min_security_version_bl0: MinSecurityVersion::default(),
106            lock_constraint: 0,
107            device_id: Self::default_constraint(),
108            reserved: [0u32; 16],
109            owner_key: KeyMaterial::default(),
110            activate_key: KeyMaterial::default(),
111            unlock_key: KeyMaterial::default(),
112            data: Vec::new(),
113            signature: EcdsaRawSignature::default(),
114            seal: Vec::new(),
115        }
116    }
117}
118
119impl OwnerBlock {
120    pub const SIZE: usize = 2048;
121    pub const DATA_SIZE: usize = 1536;
122    pub const SIGNATURE_OFFSET: usize = 1952;
123    // The not present value must be reflected in the TlvTag::NotPresent value.
124    const NOT_PRESENT: u8 = 0x5a;
125    const NO_CONSTRAINT: u32 = 0x7e7e7e7e;
126
127    pub fn default_header() -> TlvHeader {
128        TlvHeader::new(TlvTag::Owner, 0, "0.0")
129    }
130    pub fn basic() -> Self {
131        Self {
132            data: vec![
133                OwnerConfigItem::ApplicationKey(OwnerApplicationKey::default()),
134                OwnerConfigItem::FlashConfig(OwnerFlashConfig::basic()),
135                OwnerConfigItem::FlashInfoConfig(OwnerFlashInfoConfig::basic()),
136                OwnerConfigItem::RescueConfig(OwnerRescueConfig::all()),
137            ],
138            ..Default::default()
139        }
140    }
141
142    pub fn write(&self, dest: &mut impl Write) -> Result<()> {
143        let header = TlvHeader::new(TlvTag::Owner, Self::SIZE, "0.0");
144        header.write(dest)?;
145        dest.write_u32::<LittleEndian>(self.config_version)?;
146        dest.write_u32::<LittleEndian>(u32::from(self.sram_exec))?;
147        dest.write_u32::<LittleEndian>(u32::from(self.ownership_key_alg))?;
148        dest.write_u32::<LittleEndian>(u32::from(self.update_mode))?;
149        dest.write_u32::<LittleEndian>(u32::from(self.min_security_version_bl0))?;
150        dest.write_u32::<LittleEndian>(self.lock_constraint)?;
151
152        for (i, x) in self.device_id.iter().enumerate() {
153            if self.lock_constraint & (1u32 << i) == 0 {
154                dest.write_u32::<LittleEndian>(Self::NO_CONSTRAINT)?;
155            } else {
156                dest.write_u32::<LittleEndian>(*x)?;
157            }
158        }
159        for x in &self.reserved {
160            dest.write_u32::<LittleEndian>(*x)?;
161        }
162        self.owner_key.write_length(dest, 96)?;
163        self.activate_key.write_length(dest, 96)?;
164        self.unlock_key.write_length(dest, 96)?;
165        let mut data = Vec::new();
166        for item in &self.data {
167            item.write(&mut data)?;
168        }
169        data.resize(Self::DATA_SIZE, Self::NOT_PRESENT);
170        dest.write_all(&data)?;
171        self.signature.write(dest)?;
172        if self.seal.is_empty() {
173            dest.write_all(&[0u8; 32])?;
174        } else {
175            dest.write_all(&self.seal)?;
176        }
177        Ok(())
178    }
179
180    pub fn read(src: &mut impl Read, header: TlvHeader) -> Result<Self> {
181        let config_version = src.read_u32::<LittleEndian>()?;
182        let sram_exec = SramExecMode(src.read_u32::<LittleEndian>()?);
183        let ownership_key_alg = OwnershipKeyAlg(src.read_u32::<LittleEndian>()?);
184        let update_mode = OwnershipUpdateMode(src.read_u32::<LittleEndian>()?);
185        let min_security_version_bl0 = MinSecurityVersion(src.read_u32::<LittleEndian>()?);
186        let lock_constraint = src.read_u32::<LittleEndian>()?;
187
188        let mut device_id = [0u32; 8];
189        src.read_u32_into::<LittleEndian>(&mut device_id)?;
190        let mut reserved = [0u32; 16];
191        src.read_u32_into::<LittleEndian>(&mut reserved)?;
192        let owner_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?;
193        let activate_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?;
194        let unlock_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?;
195        let mut bytes = vec![0u8; Self::DATA_SIZE];
196        src.read_exact(&mut bytes)?;
197        let mut cursor = std::io::Cursor::new(&bytes);
198        let mut data = Vec::new();
199        while cursor.position() as usize != Self::DATA_SIZE {
200            match OwnerConfigItem::read(&mut cursor)? {
201                Some(item) => data.push(item),
202                None => break,
203            }
204        }
205        let signature = EcdsaRawSignature::read(src)?;
206        let mut seal = vec![0u8; 32];
207        src.read_exact(&mut seal)?;
208        Ok(Self {
209            header,
210            config_version,
211            sram_exec,
212            ownership_key_alg,
213            update_mode,
214            min_security_version_bl0,
215            lock_constraint,
216            device_id,
217            reserved,
218            owner_key,
219            activate_key,
220            unlock_key,
221            data,
222            signature,
223            seal,
224        })
225    }
226    pub fn sign(&mut self, key: &EcdsaPrivateKey) -> Result<()> {
227        ensure!(
228            self.ownership_key_alg == OwnershipKeyAlg::EcdsaP256,
229            CryptoError::SignFailed(anyhow!(
230                "Algorithm {} requires a detached signature",
231                self.ownership_key_alg
232            ))
233        );
234        let mut data = Vec::new();
235        self.write(&mut data)?;
236        self.signature = key.digest_and_sign(&data[..Self::SIGNATURE_OFFSET])?;
237        Ok(())
238    }
239
240    pub fn detached_sign(
241        &mut self,
242        nonce: u64,
243        ecdsa_key: Option<&EcdsaPrivateKey>,
244        spx_key: Option<&SpxSecretKey>,
245    ) -> Result<DetachedSignature> {
246        self.signature = Default::default();
247        let mut data = Vec::new();
248        self.write(&mut data)?;
249        DetachedSignature::new(
250            &data[..Self::SIGNATURE_OFFSET],
251            TlvTag::Owner.into(),
252            self.ownership_key_alg,
253            nonce,
254            ecdsa_key,
255            spx_key,
256        )
257    }
258
259    pub fn is_default_constraint(d: &[u32; 8]) -> bool {
260        *d == [Self::NO_CONSTRAINT; 8]
261    }
262
263    pub fn default_constraint() -> [u32; 8] {
264        [Self::NO_CONSTRAINT; 8]
265    }
266}
267
268#[derive(Debug, Deserialize, Annotate)]
269pub enum OwnerConfigItem {
270    #[serde(alias = "application_key")]
271    ApplicationKey(OwnerApplicationKey),
272    #[serde(alias = "flash_info_config")]
273    FlashInfoConfig(OwnerFlashInfoConfig),
274    #[serde(alias = "flash_config")]
275    FlashConfig(OwnerFlashConfig),
276    #[serde(alias = "rescue_config")]
277    RescueConfig(OwnerRescueConfig),
278    #[serde(alias = "isfb_config")]
279    IsfbConfig(OwnerIsfbConfig),
280    #[serde(alias = "raw")]
281    Raw(
282        #[serde(with = "serde_bytes")]
283        #[annotate(format = hexdump)]
284        Vec<u8>,
285    ),
286}
287
288impl OwnerConfigItem {
289    pub fn write(&self, dest: &mut impl Write) -> Result<()> {
290        match self {
291            Self::ApplicationKey(x) => x.write(dest)?,
292            Self::FlashInfoConfig(x) => x.write(dest)?,
293            Self::FlashConfig(x) => x.write(dest)?,
294            Self::RescueConfig(x) => x.write(dest)?,
295            Self::IsfbConfig(x) => x.write(dest)?,
296            Self::Raw(x) => dest.write_all(x)?,
297        }
298        Ok(())
299    }
300
301    pub fn read(src: &mut impl Read) -> Result<Option<Self>> {
302        let header = TlvHeader::read(src)?;
303        let item = match header.identifier {
304            TlvTag::ApplicationKey => Self::ApplicationKey(OwnerApplicationKey::read(src, header)?),
305            TlvTag::FlashConfig => Self::FlashConfig(OwnerFlashConfig::read(src, header)?),
306            TlvTag::FlashInfoConfig => {
307                Self::FlashInfoConfig(OwnerFlashInfoConfig::read(src, header)?)
308            }
309            TlvTag::Rescue => Self::RescueConfig(OwnerRescueConfig::read(src, header)?),
310            TlvTag::IntegratorSpecificFirmwareBinding => {
311                Self::IsfbConfig(OwnerIsfbConfig::read(src, header)?)
312            }
313            TlvTag::NotPresent => return Ok(None),
314            _ => {
315                let mut data = Vec::new();
316                header.write(&mut data)?;
317                if header.length >= TlvHeader::SIZE && header.length < OwnerBlock::DATA_SIZE {
318                    data.resize(header.length, 0);
319                    let len = src.read(&mut data)?;
320                    data.resize(len, 0);
321                } else {
322                    src.read_to_end(&mut data)?;
323                }
324                Self::Raw(data)
325            }
326        };
327        Ok(Some(item))
328    }
329}
330
331#[cfg(test)]
332mod test {
333    use super::*;
334    use crate::crypto::ecdsa::EcdsaRawPublicKey;
335    use crate::ownership::{
336        ApplicationKeyDomain, FlashFlags, OwnerFlashInfoConfig, OwnerFlashRegion, OwnerInfoPage,
337        OwnerRescueConfig,
338    };
339    use crate::util::hexdump::{hexdump_parse, hexdump_string};
340
341    #[rustfmt::skip]
342    const OWNER_BIN: &str =
343r#"00000000: 4f 57 4e 52 00 08 00 00 00 00 00 00 4c 4e 45 58  OWNR........LNEX
34400000010: 50 32 35 36 4f 50 45 4e ff ff ff ff 00 00 00 00  P256OPEN........
34500000020: 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e  ~~~~~~~~~~~~~~~~
34600000030: 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e  ~~~~~~~~~~~~~~~~
34700000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
34800000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
34900000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
35000000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
35100000080: 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11  ................
35200000090: 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11  ................
353000000a0: 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21  !!!!!!!!!!!!!!!!
354000000b0: 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21  !!!!!!!!!!!!!!!!
355000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
356000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
357000000e0: 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33  3333333333333333
358000000f0: 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33  3333333333333333
35900000100: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
36000000110: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
36100000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
36200000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
36300000140: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55  UUUUUUUUUUUUUUUU
36400000150: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55  UUUUUUUUUUUUUUUU
36500000160: 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66  ffffffffffffffff
36600000170: 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66  ffffffffffffffff
36700000180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
36800000190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
369000001a0: 41 50 50 4b 70 00 00 00 50 32 35 36 70 72 6f 64  APPKp...P256prod
370000001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
371000001c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
372000001d0: aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa  ................
373000001e0: aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa  ................
374000001f0: bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb  ................
37500000200: bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb  ................
37600000210: 46 4c 53 48 20 00 00 00 00 00 00 01 66 06 00 99  FLSH .......f...
37700000220: 66 06 00 00 00 01 00 02 77 17 11 88 77 17 11 11  f.......w...w...
37800000230: 49 4e 46 4f 20 00 00 00 00 01 00 00 66 06 00 99  INFO .......f...
37900000240: 66 06 00 00 01 05 00 00 77 17 11 88 77 17 11 11  f.......w...w...
38000000250: 52 45 53 51 50 00 00 00 58 00 00 40 20 00 e0 00  RESQP...X..@ ...
38100000260: 45 4d 50 54 4d 53 45 43 4e 45 58 54 55 4e 4c 4b  EMPTMSECNEXTUNLK
38200000270: 41 43 54 56 51 53 45 52 42 53 45 52 4f 42 45 52  ACTVQSERBSEROBER
38300000280: 47 4f 4c 42 51 45 52 42 50 53 52 42 52 4e 57 4f  GOLBQERBPSRBRNWO
38400000290: 30 47 50 4f 31 47 50 4f 44 49 54 4f 54 49 41 57  0GPO1GPODITOTIAW
385000002a0: 49 53 46 42 2c 00 00 00 01 08 00 00 66 06 00 00  ISFB,.......f...
386000002b0: 70 72 6f 64 00 00 00 00 00 00 00 00 00 00 00 00  prod............
387000002c0: 00 00 00 00 00 00 00 00 80 00 00 00 5a 5a 5a 5a  ............ZZZZ
388000002d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
389000002e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
390000002f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39100000300: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39200000310: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39300000320: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39400000330: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39500000340: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39600000350: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39700000360: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39800000370: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
39900000380: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40000000390: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
401000003a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
402000003b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
403000003c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
404000003d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
405000003e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
406000003f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40700000400: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40800000410: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
40900000420: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41000000430: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41100000440: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41200000450: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41300000460: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41400000470: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41500000480: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
41600000490: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
417000004a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
418000004b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
419000004c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
420000004d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
421000004e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
422000004f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42300000500: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42400000510: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42500000520: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42600000530: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42700000540: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42800000550: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
42900000560: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43000000570: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43100000580: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43200000590: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
433000005a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
434000005b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
435000005c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
436000005d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
437000005e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
438000005f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
43900000600: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44000000610: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44100000620: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44200000630: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44300000640: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44400000650: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44500000660: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44600000670: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44700000680: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
44800000690: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
449000006a0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
450000006b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
451000006c0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
452000006d0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
453000006e0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
454000006f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45500000700: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45600000710: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45700000720: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45800000730: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
45900000740: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46000000750: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46100000760: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46200000770: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46300000780: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
46400000790: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
465000007a0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77  wwwwwwwwwwwwwwww
466000007b0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77  wwwwwwwwwwwwwwww
467000007c0: 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88  ................
468000007d0: 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88  ................
469000007e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
470000007f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
471"#;
472
473    const OWNER_JSON: &str = r#"{
474  config_version: 0,
475  sram_exec: "DisabledLocked",
476  ownership_key_alg: "EcdsaP256",
477  update_mode: "Open",
478  min_security_version_bl0: "NoChange",
479  lock_constraint: 0,
480  owner_key: {
481    Ecdsa: {
482      x: "1111111111111111111111111111111111111111111111111111111111111111",
483      y: "2121212121212121212121212121212121212121212121212121212121212121"
484    }
485  },
486  activate_key: {
487    Ecdsa: {
488      x: "3333333333333333333333333333333333333333333333333333333333333333",
489      y: "4444444444444444444444444444444444444444444444444444444444444444"
490    }
491  },
492  unlock_key: {
493    Ecdsa: {
494      x: "5555555555555555555555555555555555555555555555555555555555555555",
495      y: "6666666666666666666666666666666666666666666666666666666666666666"
496    }
497  },
498  data: [
499    {
500      ApplicationKey: {
501        key_alg: "EcdsaP256",
502        key_domain: "Prod",
503        key_diversifier: [
504          0x0,
505          0x0,
506          0x0,
507          0x0,
508          0x0,
509          0x0,
510          0x0
511        ],
512        usage_constraint: 0x0,
513        key: {
514          Ecdsa: {
515            x: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
516            y: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
517          }
518        }
519      }
520    },
521    {
522      FlashConfig: {
523        config: [
524          {
525            start: 0,
526            size: 256,
527            read: true,
528            program: true,
529            erase: true,
530            scramble: true,
531            ecc: true,
532            high_endurance: true,
533            protect_when_active: false,
534            lock: false
535          },
536          {
537            start: 256,
538            size: 512,
539            read: true,
540            program: true,
541            erase: true,
542            scramble: true,
543            ecc: true,
544            high_endurance: true,
545            protect_when_active: false,
546            lock: false
547          }
548        ]
549      }
550    },
551    {
552      FlashInfoConfig: {
553        config: [
554          {
555            bank: 0,
556            page: 1,
557            pad: 0,
558            read: true,
559            program: true,
560            erase: true,
561            scramble: true,
562            ecc: true,
563            high_endurance: true,
564            protect_when_active: false,
565            lock: false
566          },
567          {
568            bank: 1,
569            page: 5,
570            pad: 0,
571            read: true,
572            program: true,
573            erase: true,
574            scramble: true,
575            ecc: true,
576            high_endurance: true,
577            protect_when_active: false,
578            lock: false
579          }
580        ]
581      }
582    },
583    {
584      RescueConfig: {
585        protocol: "Xmodem",
586        trigger: "UartBreak",
587        trigger_index: 0,
588        gpio_pull_en: false,
589        gpio_value: false,
590        start: 32,
591        size: 224,
592        command_allow: [
593          "Empty",
594          "MinBl0SecVerRequest",
595          "NextBl0SlotRequest",
596          "OwnershipUnlockRequest",
597          "OwnershipActivateRequest",
598          "Rescue",
599          "RescueB",
600          "Reboot",
601          "GetBootLog",
602          "BootSvcReq",
603          "BootSvcRsp",
604          "OwnerBlock",
605          "GetOwnerPage0",
606          "GetOwnerPage1",
607          "GetDeviceId",
608          "Wait"
609        ]
610      }
611    },
612    {
613      IsfbConfig: {
614        bank: 1,
615        page: 8,
616        erase_conditions: 0x666,
617        key_domain: "Prod",
618        product_words: 128
619      }
620    }
621  ],
622  signature: {
623    r: "7777777777777777777777777777777777777777777777777777777777777777",
624    s: "8888888888888888888888888888888888888888888888888888888888888888"
625  },
626  seal: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
627}"#;
628
629    #[test]
630    fn test_owner_write() -> Result<()> {
631        let own = OwnerBlock {
632            config_version: 0,
633            sram_exec: SramExecMode::default(),
634            ownership_key_alg: OwnershipKeyAlg::EcdsaP256,
635            owner_key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
636                x: hex::decode("1111111111111111111111111111111111111111111111111111111111111111")?,
637                y: hex::decode("2121212121212121212121212121212121212121212121212121212121212121")?,
638            }),
639            activate_key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
640                x: hex::decode("3333333333333333333333333333333333333333333333333333333333333333")?,
641                y: hex::decode("4444444444444444444444444444444444444444444444444444444444444444")?,
642            }),
643            unlock_key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
644                x: hex::decode("5555555555555555555555555555555555555555555555555555555555555555")?,
645                y: hex::decode("6666666666666666666666666666666666666666666666666666666666666666")?,
646            }),
647            data: vec![
648                OwnerConfigItem::ApplicationKey(OwnerApplicationKey {
649                    key_alg: OwnershipKeyAlg::EcdsaP256,
650                    key_domain: ApplicationKeyDomain::Prod,
651                    key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
652                        x: hex::decode(
653                            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
654                        )?,
655                        y: hex::decode(
656                            "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
657                        )?,
658                    }),
659                    ..Default::default()
660                }),
661                OwnerConfigItem::FlashConfig(OwnerFlashConfig {
662                    config: vec![
663                        OwnerFlashRegion {
664                            start: 0x000,
665                            size: 0x100,
666                            flags: FlashFlags::basic(),
667                        },
668                        OwnerFlashRegion {
669                            start: 0x100,
670                            size: 0x200,
671                            flags: FlashFlags::basic(),
672                        },
673                    ],
674                    ..Default::default()
675                }),
676                OwnerConfigItem::FlashInfoConfig(OwnerFlashInfoConfig {
677                    config: vec![
678                        OwnerInfoPage::new(0, 1, FlashFlags::basic()),
679                        OwnerInfoPage::new(1, 5, FlashFlags::basic()),
680                    ],
681                    ..Default::default()
682                }),
683                OwnerConfigItem::RescueConfig(OwnerRescueConfig::all()),
684                OwnerConfigItem::IsfbConfig(OwnerIsfbConfig {
685                    bank: 1,
686                    page: 8,
687                    pad: 0,
688                    erase_conditions: 0x0000_0666,
689                    key_domain: ApplicationKeyDomain::Prod,
690                    product_words: 128,
691                    ..Default::default()
692                }),
693            ],
694            signature: EcdsaRawSignature {
695                r: hex::decode("7777777777777777777777777777777777777777777777777777777777777777")?,
696                s: hex::decode("8888888888888888888888888888888888888888888888888888888888888888")?,
697            },
698            seal: hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")?,
699            ..Default::default()
700        };
701        let mut bin = Vec::new();
702        own.write(&mut bin)?;
703        eprintln!("{}", hexdump_string(&bin)?);
704        assert_eq!(hexdump_string(&bin)?, OWNER_BIN);
705        Ok(())
706    }
707
708    #[test]
709    fn test_owner_read() -> Result<()> {
710        let buf = hexdump_parse(OWNER_BIN)?;
711        let mut cur = std::io::Cursor::new(&buf);
712        let header = TlvHeader::read(&mut cur)?;
713        let own = OwnerBlock::read(&mut cur, header)?;
714        let doc = serde_annotate::serialize(&own)?.to_json5().to_string();
715        eprintln!("{}", doc);
716        assert_eq!(doc, OWNER_JSON);
717        Ok(())
718    }
719}