opentitanlib/ownership/
application_key.rs1use 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 crate::with_unknown;
15
16with_unknown! {
17 pub enum ApplicationKeyDomain: u32 [default = Self::Unknown] {
18 Unknown = 0,
19 Test = u32::from_le_bytes(*b"test"),
20 Dev = u32::from_le_bytes(*b"dev_"),
21 Prod = u32::from_le_bytes(*b"prod"),
22 }
23}
24
25#[derive(Debug, Serialize, Deserialize, Annotate)]
27pub struct OwnerApplicationKey {
28 #[serde(
30 skip_serializing_if = "GlobalFlags::not_debug",
31 default = "OwnerApplicationKey::default_header"
32 )]
33 pub header: TlvHeader,
34 pub key_alg: OwnershipKeyAlg,
36 pub key_domain: ApplicationKeyDomain,
38 #[serde(default)]
41 #[annotate(format=hex)]
42 pub key_diversifier: [u32; 7],
43 #[serde(default)]
46 #[annotate(format=hex)]
47 pub usage_constraint: u32,
48 pub key: KeyMaterial,
50}
51
52impl Default for OwnerApplicationKey {
53 fn default() -> Self {
54 Self {
55 header: Self::default_header(),
56 key_alg: OwnershipKeyAlg::default(),
57 key_domain: ApplicationKeyDomain::default(),
58 key_diversifier: [0u32; 7],
59 usage_constraint: 0u32,
60 key: KeyMaterial::default(),
61 }
62 }
63}
64
65impl OwnerApplicationKey {
66 pub fn default_header() -> TlvHeader {
67 TlvHeader::new(TlvTag::ApplicationKey, 0, "0.0")
68 }
69
70 pub fn read(src: &mut impl Read, header: TlvHeader) -> Result<Self> {
71 let key_alg = OwnershipKeyAlg(src.read_u32::<LittleEndian>()?);
72 let key_domain = ApplicationKeyDomain(src.read_u32::<LittleEndian>()?);
73 let mut key_diversifier = [0u32; 7];
74 src.read_u32_into::<LittleEndian>(&mut key_diversifier)?;
75 let usage_constraint = src.read_u32::<LittleEndian>()?;
76 let key = KeyMaterial::read_length(src, key_alg, 0)?;
77 Ok(Self {
78 header,
79 key_alg,
80 key_domain,
81 key_diversifier,
82 usage_constraint,
83 key,
84 })
85 }
86
87 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
88 let header = TlvHeader::new(TlvTag::ApplicationKey, 48 + self.key.len(), "0.0");
89 header.write(dest)?;
90 dest.write_u32::<LittleEndian>(u32::from(self.key_alg))?;
91 dest.write_u32::<LittleEndian>(u32::from(self.key_domain))?;
92 for kd in &self.key_diversifier {
93 dest.write_u32::<LittleEndian>(*kd)?;
94 }
95 dest.write_u32::<LittleEndian>(self.usage_constraint)?;
96 self.key.write_length(dest, 0)?;
97 Ok(())
98 }
99}
100
101#[cfg(test)]
102mod test {
103 use super::*;
104 use crate::crypto::ecdsa::EcdsaRawPublicKey;
105 use crate::util::hexdump::{hexdump_parse, hexdump_string};
106
107 const OWNER_APPLICATION_KEY_BIN: &str = "\
10800000000: 41 50 50 4b 70 00 00 00 50 32 35 36 70 72 6f 64 APPKp...P256prod\n\
10900000010: 00 00 00 00 99 00 00 00 66 00 00 00 aa 00 00 00 ........f.......\n\
11000000020: 55 00 00 00 11 00 00 00 ee 00 00 00 77 00 00 00 U...........w...\n\
11100000030: 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 ........ ...0...\n\
11200000040: 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 @...P...`...p...\n\
11300000050: 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 ................\n\
11400000060: c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 ................\n\
115";
116 const OWNER_APPLICATION_KEY_JSON: &str = r#"{
117 key_alg: "EcdsaP256",
118 key_domain: "Prod",
119 key_diversifier: [
120 0x0,
121 0x99,
122 0x66,
123 0xAA,
124 0x55,
125 0x11,
126 0xEE
127 ],
128 usage_constraint: 0x77,
129 key: {
130 Ecdsa: {
131 x: "0000000010000000200000003000000040000000500000006000000070000000",
132 y: "8000000090000000a0000000b0000000c0000000d0000000e0000000f0000000"
133 }
134 }
135}"#;
136
137 #[test]
138 fn test_owner_application_key_write() -> Result<()> {
139 let oak = OwnerApplicationKey {
140 header: TlvHeader::default(),
141 key_alg: OwnershipKeyAlg::EcdsaP256,
142 key_domain: ApplicationKeyDomain::Prod,
143 key_diversifier: [0x00, 0x99, 0x66, 0xAA, 0x55, 0x11, 0xEE],
144 usage_constraint: 0x77,
145 key: KeyMaterial::Ecdsa(EcdsaRawPublicKey {
146 x: hex::decode("0000000010000000200000003000000040000000500000006000000070000000")?,
147 y: hex::decode("8000000090000000a0000000b0000000c0000000d0000000e0000000f0000000")?,
148 }),
149 };
150 let mut bin = Vec::new();
151 oak.write(&mut bin)?;
152 eprintln!("{}", hexdump_string(&bin)?);
153 assert_eq!(hexdump_string(&bin)?, OWNER_APPLICATION_KEY_BIN);
154 Ok(())
155 }
156
157 #[test]
158 fn test_owner_application_key_read() -> Result<()> {
159 let buf = hexdump_parse(OWNER_APPLICATION_KEY_BIN)?;
160 let mut cur = std::io::Cursor::new(&buf);
161 let header = TlvHeader::read(&mut cur)?;
162 let oak = OwnerApplicationKey::read(&mut cur, header)?;
163 let doc = serde_annotate::serialize(&oak)?.to_json5().to_string();
164 eprintln!("{}", doc);
165 assert_eq!(doc, OWNER_APPLICATION_KEY_JSON);
166 Ok(())
167 }
168}