xref: /aosp_15_r20/tools/security/remote_provisioning/hwtrust/src/dice/entry.rs (revision d9ecfb0f4d734c9ce41cde8ac4d585b094fd4222)
1 use crate::publickey::PublicKey;
2 use std::fmt::{self, Display, Formatter};
3 use thiserror::Error;
4 
5 /// Enumeration of modes used in the DICE chain payloads.
6 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
7 pub enum DiceMode {
8     /// This mode also acts as a catch-all for configurations which do not fit the other modes and
9     /// invalid modes.
10     #[default]
11     NotConfigured,
12     /// The device is operating normally under secure configuration.
13     Normal,
14     /// At least one criteria for [`Normal`] is not met and the device is not in a secure state.
15     Debug,
16     /// A recovery or maintenance mode of some kind.
17     Recovery,
18 }
19 
20 /// The payload of a DICE chain entry.
21 #[derive(Clone, Eq, PartialEq)]
22 pub struct Payload {
23     issuer: String,
24     subject: String,
25     subject_public_key: PublicKey,
26     mode: DiceMode,
27     code_desc: Option<Vec<u8>>,
28     code_hash: Vec<u8>,
29     config_desc: ConfigDesc,
30     config_hash: Option<Vec<u8>>,
31     authority_desc: Option<Vec<u8>>,
32     authority_hash: Vec<u8>,
33 }
34 
35 impl Payload {
36     /// Gets the issuer of the payload.
issuer(&self) -> &str37     pub fn issuer(&self) -> &str {
38         &self.issuer
39     }
40 
41     /// Gets the subject of the payload.
subject(&self) -> &str42     pub fn subject(&self) -> &str {
43         &self.subject
44     }
45 
46     /// Gets the subject public key of the payload.
subject_public_key(&self) -> &PublicKey47     pub fn subject_public_key(&self) -> &PublicKey {
48         &self.subject_public_key
49     }
50 
51     /// Gets the mode of the payload.
mode(&self) -> DiceMode52     pub fn mode(&self) -> DiceMode {
53         self.mode
54     }
55 
56     /// Gets the code descriptor of the payload.
code_desc(&self) -> Option<&[u8]>57     pub fn code_desc(&self) -> Option<&[u8]> {
58         self.code_desc.as_deref()
59     }
60 
61     /// Gets the code hash of the payload.
code_hash(&self) -> &[u8]62     pub fn code_hash(&self) -> &[u8] {
63         &self.code_hash
64     }
65 
66     /// Gets the configuration descriptor of the payload.
config_desc(&self) -> &ConfigDesc67     pub fn config_desc(&self) -> &ConfigDesc {
68         &self.config_desc
69     }
70 
71     /// Gets the configuration hash of the payload.
config_hash(&self) -> Option<&[u8]>72     pub fn config_hash(&self) -> Option<&[u8]> {
73         self.config_hash.as_deref()
74     }
75 
76     /// Gets the authority descriptor of the payload.
authority_desc(&self) -> Option<&[u8]>77     pub fn authority_desc(&self) -> Option<&[u8]> {
78         self.authority_desc.as_deref()
79     }
80 
81     /// Gets the authority hash of the payload.
authority_hash(&self) -> &[u8]82     pub fn authority_hash(&self) -> &[u8] {
83         &self.authority_hash
84     }
85 
86     /// Returns whether the payload has an RKP VM marker.
has_rkpvm_marker(&self) -> bool87     pub fn has_rkpvm_marker(&self) -> bool {
88         self.config_desc.rkp_vm_marker()
89     }
90 }
91 
92 impl Display for Payload {
fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error>93     fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
94         writeln!(f, "Issuer: {}", self.issuer)?;
95         writeln!(f, "Subject: {}", self.subject)?;
96         writeln!(f, "Mode: {:?}", self.mode)?;
97         if let Some(code_desc) = &self.code_desc {
98             writeln!(f, "Code Desc: {}", hex::encode(code_desc))?;
99         }
100         writeln!(f, "Code Hash: {}", hex::encode(&self.code_hash))?;
101         if let Some(config_hash) = &self.config_hash {
102             writeln!(f, "Config Hash: {}", hex::encode(config_hash))?;
103         }
104         if let Some(authority_desc) = &self.authority_desc {
105             writeln!(f, "Authority Desc: {}", hex::encode(authority_desc))?;
106         }
107         writeln!(f, "Authority Hash: {}", hex::encode(&self.authority_hash))?;
108         writeln!(f, "Config Desc {{")?;
109         write!(f, "{}", &self.config_desc)?;
110         writeln!(f, "}}")?;
111         Ok(())
112     }
113 }
114 
115 impl fmt::Debug for Payload {
fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error>116     fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
117         let mut debug = f.debug_struct("Payload");
118         debug.field("Issuer", &self.issuer);
119         debug.field("Subject", &self.subject);
120         debug.field("Mode", &self.mode);
121         if let Some(code_desc) = &self.code_desc {
122             debug.field("Code Desc", &hex::encode(code_desc));
123         }
124         debug.field("Code Hash", &hex::encode(&self.code_hash));
125         if let Some(config_hash) = &self.config_hash {
126             debug.field("Config Hash", &hex::encode(config_hash));
127         }
128         if let Some(authority_desc) = &self.authority_desc {
129             debug.field("Authority Desc", &hex::encode(authority_desc));
130         }
131         debug.field("Authority Hash", &hex::encode(&self.authority_hash));
132         debug.field("Config Desc", &self.config_desc);
133         debug.finish()
134     }
135 }
136 
137 #[derive(Error, Debug, PartialEq, Eq)]
138 pub(crate) enum PayloadBuilderError {
139     #[error("issuer empty")]
140     IssuerEmpty,
141     #[error("subject empty")]
142     SubjectEmpty,
143 }
144 
145 pub(crate) struct PayloadBuilder(Payload);
146 
147 impl PayloadBuilder {
148     /// Constructs a new builder with the given subject public key.
with_subject_public_key(subject_public_key: PublicKey) -> Self149     pub fn with_subject_public_key(subject_public_key: PublicKey) -> Self {
150         Self(Payload {
151             issuer: Default::default(),
152             subject: Default::default(),
153             subject_public_key,
154             mode: Default::default(),
155             code_desc: Default::default(),
156             code_hash: Default::default(),
157             config_desc: Default::default(),
158             config_hash: Default::default(),
159             authority_desc: Default::default(),
160             authority_hash: Default::default(),
161         })
162     }
163 
164     /// Builds the [`Payload`] after validating the issuer and subject.
build(self) -> Result<Payload, PayloadBuilderError>165     pub fn build(self) -> Result<Payload, PayloadBuilderError> {
166         if self.0.issuer.is_empty() {
167             return Err(PayloadBuilderError::IssuerEmpty);
168         }
169         if self.0.subject.is_empty() {
170             return Err(PayloadBuilderError::SubjectEmpty);
171         }
172         Ok(self.0)
173     }
174 
175     /// Sets the issuer of the payload.
176     #[must_use]
issuer<S: Into<String>>(mut self, issuer: S) -> Self177     pub fn issuer<S: Into<String>>(mut self, issuer: S) -> Self {
178         self.0.issuer = issuer.into();
179         self
180     }
181 
182     /// Sets the subject of the payload.
183     #[must_use]
subject<S: Into<String>>(mut self, subject: S) -> Self184     pub fn subject<S: Into<String>>(mut self, subject: S) -> Self {
185         self.0.subject = subject.into();
186         self
187     }
188 
189     /// Sets the mode of the payload.
190     #[must_use]
mode(mut self, mode: DiceMode) -> Self191     pub fn mode(mut self, mode: DiceMode) -> Self {
192         self.0.mode = mode;
193         self
194     }
195 
196     /// Sets the code descriptor of the payload.
197     #[must_use]
code_desc(mut self, code_desc: Option<Vec<u8>>) -> Self198     pub fn code_desc(mut self, code_desc: Option<Vec<u8>>) -> Self {
199         self.0.code_desc = code_desc;
200         self
201     }
202 
203     /// Sets the code hash of the payload.
204     #[must_use]
code_hash(mut self, code_hash: Vec<u8>) -> Self205     pub fn code_hash(mut self, code_hash: Vec<u8>) -> Self {
206         self.0.code_hash = code_hash;
207         self
208     }
209 
210     /// Sets the configuration descriptor of the payload.
211     #[must_use]
config_desc(mut self, config_desc: ConfigDesc) -> Self212     pub fn config_desc(mut self, config_desc: ConfigDesc) -> Self {
213         self.0.config_desc = config_desc;
214         self
215     }
216 
217     /// Sets the configuration hash of the payload.
218     #[must_use]
config_hash(mut self, config_hash: Option<Vec<u8>>) -> Self219     pub fn config_hash(mut self, config_hash: Option<Vec<u8>>) -> Self {
220         self.0.config_hash = config_hash;
221         self
222     }
223 
224     /// Sets the authority descriptor of the payload.
225     #[must_use]
authority_desc(mut self, authority_desc: Option<Vec<u8>>) -> Self226     pub fn authority_desc(mut self, authority_desc: Option<Vec<u8>>) -> Self {
227         self.0.authority_desc = authority_desc;
228         self
229     }
230 
231     /// Sets the authority hash of the payload.
232     #[must_use]
authority_hash(mut self, authority_hash: Vec<u8>) -> Self233     pub fn authority_hash(mut self, authority_hash: Vec<u8>) -> Self {
234         self.0.authority_hash = authority_hash;
235         self
236     }
237 }
238 
239 /// Version of the component from the configuration descriptor.
240 #[derive(Debug, Clone, PartialEq, Eq)]
241 pub enum ComponentVersion {
242     /// An integer component version number.
243     Integer(i64),
244     /// A free-form string component version.
245     String(String),
246 }
247 
248 impl Display for ComponentVersion {
fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error>249     fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
250         match self {
251             ComponentVersion::Integer(n) => write!(f, "{n}")?,
252             ComponentVersion::String(s) => write!(f, "{s}")?,
253         }
254         Ok(())
255     }
256 }
257 
258 /// Fields from the configuration descriptor.
259 #[derive(Debug, Default, Clone, PartialEq, Eq)]
260 pub struct ConfigDesc {
261     component_name: Option<String>,
262     component_instance_name: Option<String>,
263     component_version: Option<ComponentVersion>,
264     resettable: bool,
265     security_version: Option<u64>,
266     rkp_vm_marker: bool,
267     extensions: Vec<(String, String)>,
268 }
269 
270 impl ConfigDesc {
271     /// Gets the component name.
component_name(&self) -> Option<&str>272     pub fn component_name(&self) -> Option<&str> {
273         self.component_name.as_deref()
274     }
275 
276     /// Gets the component instance name.
component_instance_name(&self) -> Option<&str>277     pub fn component_instance_name(&self) -> Option<&str> {
278         self.component_instance_name.as_deref()
279     }
280 
281     /// Gets the component version.
component_version(&self) -> Option<&ComponentVersion>282     pub fn component_version(&self) -> Option<&ComponentVersion> {
283         self.component_version.as_ref()
284     }
285 
286     /// Returns whether the component is factory resettable.
resettable(&self) -> bool287     pub fn resettable(&self) -> bool {
288         self.resettable
289     }
290 
291     /// Gets the security version.
security_version(&self) -> Option<u64>292     pub fn security_version(&self) -> Option<u64> {
293         self.security_version
294     }
295 
296     /// Returns whether the component may be part of an RPK VM.
rkp_vm_marker(&self) -> bool297     pub fn rkp_vm_marker(&self) -> bool {
298         self.rkp_vm_marker
299     }
300 
301     /// Return any extensions present in the descriptor.
extensions(&self) -> &[(String, String)]302     pub fn extensions(&self) -> &[(String, String)] {
303         &self.extensions
304     }
305 }
306 
307 impl Display for ConfigDesc {
fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error>308     fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
309         if let Some(component_name) = &self.component_name {
310             writeln!(f, "Component Name: {}", component_name)?;
311         }
312         if let Some(component_instance_name) = &self.component_instance_name {
313             writeln!(f, "Component Instance Name: {}", component_instance_name)?;
314         }
315         if let Some(component_version) = &self.component_version {
316             writeln!(f, "Component Version: {}", component_version)?;
317         }
318         if self.resettable {
319             writeln!(f, "Resettable")?;
320         }
321         if let Some(security_version) = &self.security_version {
322             writeln!(f, "Security Version: {}", security_version)?;
323         }
324         if self.rkp_vm_marker {
325             writeln!(f, "RKP VM Marker")?;
326         }
327         for (key, value) in &self.extensions {
328             writeln!(f, "{key}: {value}")?;
329         }
330         Ok(())
331     }
332 }
333 
334 pub(crate) struct ConfigDescBuilder(ConfigDesc);
335 
336 impl ConfigDescBuilder {
337     /// Constructs a new builder with default values.
new() -> Self338     pub fn new() -> Self {
339         Self(ConfigDesc::default())
340     }
341 
342     /// Builds the [`ConfigDesc`].
build(self) -> ConfigDesc343     pub fn build(self) -> ConfigDesc {
344         self.0
345     }
346 
347     /// Sets the component name.
348     #[must_use]
component_name(mut self, name: Option<String>) -> Self349     pub fn component_name(mut self, name: Option<String>) -> Self {
350         self.0.component_name = name;
351         self
352     }
353 
354     /// Sets the component instance name.
355     #[must_use]
component_instance_name(mut self, name: Option<String>) -> Self356     pub fn component_instance_name(mut self, name: Option<String>) -> Self {
357         self.0.component_instance_name = name;
358         self
359     }
360 
361     /// Sets the component version.
362     #[must_use]
component_version(mut self, version: Option<ComponentVersion>) -> Self363     pub fn component_version(mut self, version: Option<ComponentVersion>) -> Self {
364         self.0.component_version = version;
365         self
366     }
367 
368     /// Sets whether the component is factory resettable.
369     #[must_use]
resettable(mut self, resettable: bool) -> Self370     pub fn resettable(mut self, resettable: bool) -> Self {
371         self.0.resettable = resettable;
372         self
373     }
374 
375     /// Sets the security version.
376     #[must_use]
security_version(mut self, version: Option<u64>) -> Self377     pub fn security_version(mut self, version: Option<u64>) -> Self {
378         self.0.security_version = version;
379         self
380     }
381 
382     /// Sets whether the component may be part of an RKP VM.
383     #[must_use]
rkp_vm_marker(mut self, rkp_vm_marker: bool) -> Self384     pub fn rkp_vm_marker(mut self, rkp_vm_marker: bool) -> Self {
385         self.0.rkp_vm_marker = rkp_vm_marker;
386         self
387     }
388 
389     /// Sets the extension key/value pairs.
390     #[must_use]
extensions(mut self, extensions: Vec<(String, String)>) -> Self391     pub fn extensions(mut self, extensions: Vec<(String, String)>) -> Self {
392         self.0.extensions = extensions;
393         self
394     }
395 }
396 
397 #[cfg(test)]
398 mod tests {
399     use super::*;
400     use crate::publickey::testkeys::{PrivateKey, P256_KEY_PEM};
401 
402     #[test]
payload_builder_valid()403     fn payload_builder_valid() {
404         valid_payload().build().unwrap();
405     }
406 
407     #[test]
payload_builder_valid_512_bit_hashes()408     fn payload_builder_valid_512_bit_hashes() {
409         valid_payload()
410             .code_hash(vec![1; 64])
411             .authority_hash(vec![2; 64])
412             .config_hash(Some(vec![3; 64]))
413             .build()
414             .unwrap();
415     }
416 
417     #[test]
payload_builder_valid_384_bit_hashes()418     fn payload_builder_valid_384_bit_hashes() {
419         valid_payload()
420             .code_hash(vec![1; 48])
421             .authority_hash(vec![2; 48])
422             .config_hash(Some(vec![3; 48]))
423             .build()
424             .unwrap();
425     }
426 
427     #[test]
payload_builder_valid_256_bit_hashes()428     fn payload_builder_valid_256_bit_hashes() {
429         valid_payload()
430             .code_hash(vec![1; 32])
431             .authority_hash(vec![2; 32])
432             .config_hash(Some(vec![3; 32]))
433             .build()
434             .unwrap();
435     }
436 
437     #[test]
payload_builder_empty_issuer()438     fn payload_builder_empty_issuer() {
439         let err = valid_payload().issuer("").build().unwrap_err();
440         assert_eq!(err, PayloadBuilderError::IssuerEmpty);
441     }
442 
443     #[test]
payload_builder_empty_subject()444     fn payload_builder_empty_subject() {
445         let err = valid_payload().subject("").build().unwrap_err();
446         assert_eq!(err, PayloadBuilderError::SubjectEmpty);
447     }
448 
valid_payload() -> PayloadBuilder449     fn valid_payload() -> PayloadBuilder {
450         let key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
451         PayloadBuilder::with_subject_public_key(key)
452             .issuer("issuer")
453             .subject("subject")
454             .code_hash(vec![1; 64])
455             .authority_hash(vec![2; 64])
456     }
457 }
458