xref: /aosp_15_r20/tools/security/remote_provisioning/hwtrust/src/dice/chain.rs (revision d9ecfb0f4d734c9ce41cde8ac4d585b094fd4222)
1 use crate::dice::Payload;
2 use crate::publickey::PublicKey;
3 use crate::session::RkpInstance;
4 use anyhow::Result;
5 use std::collections::HashSet;
6 use std::fmt::{self, Display, Formatter};
7 use thiserror::Error;
8 
9 /// The minimum number of RKP VM markers required in a valid [RKP VM DICE chain][rkpvm-chain].
10 ///
11 /// An RKP VM chain must have a continuous presence of RKP VM markers, starting from a DICE
12 /// certificate derived in the TEE and extending to the leaf DICE certificate.
13 /// Therefore, a valid RKP VM chain should have at least two DICE certificates with RKP VM markers:
14 ///
15 /// * One added in the pVM (managed by Android).
16 /// * One added in the TEE (managed by vendors).
17 ///
18 /// [rkpvm-chain]: https://android.googlesource.com/platform/packages/modules/Virtualization/+/main/docs/vm_remote_attestation.md
19 const RKPVM_CHAIN_MIN_MARKER_NUM: usize = 2;
20 
21 /// Enumeration of the different forms that a DICE chain can take.
22 #[derive(Clone, Debug, Eq, PartialEq)]
23 pub enum ChainForm {
24     /// A proper DICE chain with multiple layers of trust.
25     Proper(Chain),
26     /// A degenerate DICE chain consisting of a single self-signed certificate.
27     Degenerate(DegenerateChain),
28 }
29 
30 /// Represents a DICE chain. This consists of the root public key (which signs the first
31 /// certificate), followed by a chain of certificates.
32 #[derive(Clone, Eq, PartialEq)]
33 pub struct Chain {
34     root_public_key: PublicKey,
35     payloads: Vec<Payload>,
36 }
37 
38 #[derive(Error, Debug, PartialEq, Eq)]
39 pub(crate) enum ValidationError {
40     #[error("no payloads")]
41     NoPayloads,
42     #[error("issuer `{1}` is not previous subject `{2}` in payload {0}")]
43     IssuerMismatch(usize, String, String),
44     #[error("repeated subject in payload {0}")]
45     RepeatedSubject(usize, String),
46     #[error("repeated key in payload {0}")]
47     RepeatedKey(usize),
48     #[error("RKP VM chain has discontinuous marker at the {0}th payload")]
49     RkpVmChainHasDiscontinuousMarker(usize),
50     #[error(
51         "RKP VM chain does not have enough RKP VM markers. \
52          Minimal marker number:{RKPVM_CHAIN_MIN_MARKER_NUM}, actual marker number:{0}"
53     )]
54     NotEnoughRkpVmMarker(usize),
55     #[error("non RKP VM chain should not have continuous RKP VM markers")]
56     UnexpectedRkpVmMarkers,
57 }
58 
59 impl ChainForm {
leaf_public_key(&self) -> &PublicKey60     pub(crate) fn leaf_public_key(&self) -> &PublicKey {
61         match self {
62             Self::Proper(chain) => chain.leaf().subject_public_key(),
63             Self::Degenerate(degenerate) => degenerate.public_key(),
64         }
65     }
66 
67     /// Return the length of the chain.
length(&self) -> usize68     pub fn length(&self) -> usize {
69         match self {
70             ChainForm::Proper(chain) => chain.payloads.len(),
71             ChainForm::Degenerate(_) => 1,
72         }
73     }
74 }
75 
76 impl Chain {
77     /// Builds a [`Chain`] after checking that it is well-formed. The issuer of each entry must be
78     /// equal to the subject of the previous entry. The chain is not allowed to contain any
79     /// repeated subjects or subject public keys as that would suggest something untoward has
80     /// happened.
81     ///
82     /// Additionally, `rkp_instance` provides additional context for the validation of the chain
83     /// according to the instance-specific chain validation rules.
84     ///
85     /// * AVF instance: The chain is validated against the RKP VM chain validation rules.
86     /// * Non-AVF instances: The chain must not contain RKP VM markers that conform to the RKP VM
87     ///   chain validation rules.
validate( root_public_key: PublicKey, payloads: Vec<Payload>, rkp_instance: RkpInstance, ) -> Result<Self, ValidationError>88     pub(crate) fn validate(
89         root_public_key: PublicKey,
90         payloads: Vec<Payload>,
91         rkp_instance: RkpInstance,
92     ) -> Result<Self, ValidationError> {
93         if payloads.is_empty() {
94             return Err(ValidationError::NoPayloads);
95         }
96 
97         let mut subjects = HashSet::with_capacity(payloads.len());
98         let mut keys = HashSet::with_capacity(1 + payloads.len());
99         keys.insert(root_public_key.to_pem());
100 
101         let mut previous_subject: Option<&str> = None;
102         for (n, payload) in payloads.iter().enumerate() {
103             if let Some(previous_subject) = previous_subject {
104                 if payload.issuer() != previous_subject {
105                     return Err(ValidationError::IssuerMismatch(
106                         n,
107                         payload.issuer().to_string(),
108                         previous_subject.to_string(),
109                     ));
110                 }
111             }
112             if subjects.replace(payload.subject()).is_some() {
113                 return Err(ValidationError::RepeatedSubject(n, payload.subject().to_string()));
114             }
115             if keys.replace(payload.subject_public_key().to_pem()).is_some() {
116                 return Err(ValidationError::RepeatedKey(n));
117             }
118             previous_subject = Some(payload.subject());
119         }
120         match rkp_instance {
121             RkpInstance::Avf => validate_rkpvm_chain(&payloads),
122             _ => validate_non_rkpvm_chain(&payloads),
123         }?;
124         Ok(Self { root_public_key, payloads })
125     }
126 
127     /// Get the root public key which verifies the first certificate in the chain.
root_public_key(&self) -> &PublicKey128     pub fn root_public_key(&self) -> &PublicKey {
129         &self.root_public_key
130     }
131 
132     /// Get the payloads of the certificates in the chain, from root to leaf.
payloads(&self) -> &[Payload]133     pub fn payloads(&self) -> &[Payload] {
134         &self.payloads
135     }
136 
137     /// Get the payload from the final certificate in the chain.
leaf(&self) -> &Payload138     pub fn leaf(&self) -> &Payload {
139         // There is always at least one payload.
140         self.payloads.last().unwrap()
141     }
142 }
143 
validate_rkpvm_chain(payloads: &[Payload]) -> Result<(), ValidationError>144 fn validate_rkpvm_chain(payloads: &[Payload]) -> Result<(), ValidationError> {
145     let mut rkpvm_marker_count = 0;
146     for (i, payload) in payloads.iter().enumerate() {
147         if payload.has_rkpvm_marker() {
148             rkpvm_marker_count += 1;
149         } else if rkpvm_marker_count > 0 {
150             return Err(ValidationError::RkpVmChainHasDiscontinuousMarker(i));
151         }
152     }
153     if rkpvm_marker_count < RKPVM_CHAIN_MIN_MARKER_NUM {
154         return Err(ValidationError::NotEnoughRkpVmMarker(rkpvm_marker_count));
155     }
156     Ok(())
157 }
158 
159 /// Validates a DICE chain that is not associated with an RKP VM.
160 ///
161 /// While non-RKP VM DICE chains might contain RKP VM markers in some vendor DICE certificates
162 /// (e.g., Microdroid pVM DICE chain), they should not have a continuous presence of markers up to
163 /// the last certificate in the chain.
validate_non_rkpvm_chain(payloads: &[Payload]) -> Result<(), ValidationError>164 fn validate_non_rkpvm_chain(payloads: &[Payload]) -> Result<(), ValidationError> {
165     validate_rkpvm_chain(payloads).map_or(Ok(()), |_| Err(ValidationError::UnexpectedRkpVmMarkers))
166 }
167 
168 impl Display for Chain {
fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error>169     fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
170         writeln!(f, "Root public key:")?;
171         writeln!(f, "{}", self.root_public_key.to_pem())?;
172         for (i, payload) in self.payloads.iter().enumerate() {
173             writeln!(f, "Cert {}:", i)?;
174             writeln!(f, "{}", payload)?;
175         }
176         Ok(())
177     }
178 }
179 
180 impl fmt::Debug for Chain {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result181     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
182         let mut debug = fmt.debug_struct("Chain");
183         debug.field("Root public key", &self.root_public_key.to_pem());
184         for (i, payload) in self.payloads.iter().enumerate() {
185             debug.field(&format!("DICE Certificate[{i}]"), payload);
186         }
187         debug.finish()
188     }
189 }
190 
191 #[derive(Error, Debug, PartialEq, Eq)]
192 pub(crate) enum DegenerateChainError {
193     #[error("issuer empty")]
194     IssuerEmpty,
195     #[error("subject empty")]
196     SubjectEmpty,
197 }
198 
199 /// A degenerate DICE chain. These chains consist of a single, self-signed certificate and the
200 /// entries contain less information than usual. They are expected from devices that haven't
201 /// implemented everything necessary to produce a proper DICE Chain.
202 #[derive(Clone, Debug, Eq, PartialEq)]
203 pub struct DegenerateChain {
204     issuer: String,
205     subject: String,
206     subject_public_key: PublicKey,
207 }
208 
209 impl DegenerateChain {
new<I: Into<String>, S: Into<String>>( issuer: I, subject: S, subject_public_key: PublicKey, ) -> Result<Self, DegenerateChainError>210     pub(crate) fn new<I: Into<String>, S: Into<String>>(
211         issuer: I,
212         subject: S,
213         subject_public_key: PublicKey,
214     ) -> Result<Self, DegenerateChainError> {
215         let issuer = issuer.into();
216         let subject = subject.into();
217         if issuer.is_empty() {
218             return Err(DegenerateChainError::IssuerEmpty);
219         }
220         if subject.is_empty() {
221             return Err(DegenerateChainError::SubjectEmpty);
222         }
223         Ok(Self { issuer, subject, subject_public_key })
224     }
225 
226     /// Gets the issuer of the degenerate chain.
issuer(&self) -> &str227     pub fn issuer(&self) -> &str {
228         &self.issuer
229     }
230 
231     /// Gets the subject of the degenerate chain.
subject(&self) -> &str232     pub fn subject(&self) -> &str {
233         &self.subject
234     }
235 
236     /// Gets the public key of the degenerate chain.
public_key(&self) -> &PublicKey237     pub fn public_key(&self) -> &PublicKey {
238         &self.subject_public_key
239     }
240 }
241 
242 impl Display for DegenerateChain {
fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error>243     fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
244         writeln!(f, "Public key:")?;
245         writeln!(f, "{}", self.public_key().to_pem())?;
246         writeln!(f, "Issuer: {}", self.issuer)?;
247         writeln!(f, "Subject: {}", self.subject)?;
248         Ok(())
249     }
250 }
251 
252 #[cfg(test)]
253 mod tests {
254     use super::*;
255     use crate::dice::{ConfigDescBuilder, DiceMode, PayloadBuilder};
256     use crate::publickey::testkeys::{PrivateKey, ED25519_KEY_PEM, P256_KEY_PEM, P384_KEY_PEM};
257 
258     #[test]
chain_validate_valid()259     fn chain_validate_valid() {
260         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
261         let keys = P256_KEY_PEM[1..4].iter().copied().enumerate();
262         let payloads = keys.map(|(n, key)| valid_payload(n, key).build().unwrap()).collect();
263         Chain::validate(root_public_key, payloads, RkpInstance::Default).unwrap();
264     }
265 
266     #[test]
chain_validate_valid_with_mixed_kinds_of_key()267     fn chain_validate_valid_with_mixed_kinds_of_key() {
268         let root_public_key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
269         let keys = [P256_KEY_PEM[0], P384_KEY_PEM[0]].into_iter().enumerate();
270         let payloads = keys.map(|(n, key)| valid_payload(n, key).build().unwrap()).collect();
271         Chain::validate(root_public_key, payloads, RkpInstance::Default).unwrap();
272     }
273 
274     #[test]
chain_validate_fails_without_payloads()275     fn chain_validate_fails_without_payloads() {
276         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
277         let payloads = Vec::new();
278         let err = Chain::validate(root_public_key, payloads, RkpInstance::Default).unwrap_err();
279         assert_eq!(err, ValidationError::NoPayloads);
280     }
281 
282     #[test]
chain_validate_fails_when_root_key_repeated()283     fn chain_validate_fails_when_root_key_repeated() {
284         let key = P256_KEY_PEM[0];
285         let root_public_key = PrivateKey::from_pem(key).public_key();
286         let payloads = vec![valid_payload(0, key).build().unwrap()];
287         let err = Chain::validate(root_public_key, payloads, RkpInstance::Default).unwrap_err();
288         assert_eq!(err, ValidationError::RepeatedKey(0));
289     }
290 
291     #[test]
chain_validate_fails_with_repeated_subject_public_keys()292     fn chain_validate_fails_with_repeated_subject_public_keys() {
293         let repeated_key = P256_KEY_PEM[0];
294         let root_public_key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
295         let payloads = vec![
296             valid_payload(0, repeated_key).build().unwrap(),
297             valid_payload(1, repeated_key).build().unwrap(),
298         ];
299         let err = Chain::validate(root_public_key, payloads, RkpInstance::Default).unwrap_err();
300         assert_eq!(err, ValidationError::RepeatedKey(1));
301     }
302 
303     #[test]
chain_validate_fails_with_repeated_subjects()304     fn chain_validate_fails_with_repeated_subjects() {
305         let keys = &P256_KEY_PEM[..3];
306         let repeated = "match";
307         let root_public_key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
308         let payloads = vec![
309             valid_payload(0, keys[0]).subject(repeated).build().unwrap(),
310             valid_payload(1, keys[1]).issuer(repeated).build().unwrap(),
311             valid_payload(2, keys[2]).subject(repeated).build().unwrap(),
312         ];
313         let err = Chain::validate(root_public_key, payloads, RkpInstance::Default).unwrap_err();
314         assert_eq!(err, ValidationError::RepeatedSubject(2, repeated.into()));
315     }
316 
317     #[test]
chain_validate_fails_with_mismatching_issuer_and_subject()318     fn chain_validate_fails_with_mismatching_issuer_and_subject() {
319         let expected = "expected";
320         let wrong = "wrong";
321         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
322         let payloads = vec![
323             valid_payload(0, P256_KEY_PEM[1]).subject(expected).build().unwrap(),
324             valid_payload(1, P256_KEY_PEM[2]).issuer(wrong).build().unwrap(),
325         ];
326         let err = Chain::validate(root_public_key, payloads, RkpInstance::Default).unwrap_err();
327         assert_eq!(err, ValidationError::IssuerMismatch(1, wrong.into(), expected.into()));
328     }
329 
330     #[test]
non_rkpvm_chain_validate_with_discontinuous_markers()331     fn non_rkpvm_chain_validate_with_discontinuous_markers() {
332         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
333         let config_desc = ConfigDescBuilder::new().rkp_vm_marker(true).build();
334         // This chain resembles a Microdroid pVM DICE chain where vendors add RKP VM markers in
335         // the vendor part of the chain, while pVM does not.
336         let payloads = vec![
337             valid_payload(0, P256_KEY_PEM[1]).build().unwrap(),
338             valid_payload(1, P256_KEY_PEM[2]).config_desc(config_desc.clone()).build().unwrap(),
339             valid_payload(2, P256_KEY_PEM[3]).build().unwrap(),
340         ];
341         Chain::validate(root_public_key, payloads, RkpInstance::Default).unwrap();
342     }
343 
344     #[test]
non_rkpvm_chain_validate_fails_with_continuous_markers()345     fn non_rkpvm_chain_validate_fails_with_continuous_markers() {
346         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
347         let config_desc = ConfigDescBuilder::new().rkp_vm_marker(true).build();
348         let payloads = vec![
349             valid_payload(0, P256_KEY_PEM[1]).build().unwrap(),
350             valid_payload(1, P256_KEY_PEM[2]).config_desc(config_desc.clone()).build().unwrap(),
351             valid_payload(2, P256_KEY_PEM[3]).config_desc(config_desc.clone()).build().unwrap(),
352         ];
353         let err = Chain::validate(root_public_key, payloads, RkpInstance::Default).unwrap_err();
354         assert_eq!(err, ValidationError::UnexpectedRkpVmMarkers);
355     }
356 
357     #[test]
rkpvm_chain_validate_with_continuous_markers()358     fn rkpvm_chain_validate_with_continuous_markers() {
359         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
360         let config_desc = ConfigDescBuilder::new().rkp_vm_marker(true).build();
361         let payloads = vec![
362             valid_payload(0, P256_KEY_PEM[1]).build().unwrap(),
363             valid_payload(1, P256_KEY_PEM[2]).config_desc(config_desc.clone()).build().unwrap(),
364             valid_payload(2, P256_KEY_PEM[3]).config_desc(config_desc.clone()).build().unwrap(),
365         ];
366         Chain::validate(root_public_key, payloads, RkpInstance::Avf).unwrap();
367     }
368 
369     #[test]
rkpvm_chain_validate_fails_with_no_marker()370     fn rkpvm_chain_validate_fails_with_no_marker() {
371         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
372         let payloads = vec![valid_payload(0, P256_KEY_PEM[1]).build().unwrap()];
373         let err = Chain::validate(root_public_key, payloads, RkpInstance::Avf).unwrap_err();
374         assert_eq!(err, ValidationError::NotEnoughRkpVmMarker(0));
375     }
376 
377     #[test]
rkpvm_chain_validate_fails_with_not_enough_markers()378     fn rkpvm_chain_validate_fails_with_not_enough_markers() {
379         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
380         let config_desc = ConfigDescBuilder::new().rkp_vm_marker(true).build();
381         let payloads = vec![
382             valid_payload(0, P256_KEY_PEM[1]).build().unwrap(),
383             valid_payload(1, P256_KEY_PEM[2]).config_desc(config_desc).build().unwrap(),
384         ];
385         let err = Chain::validate(root_public_key, payloads, RkpInstance::Avf).unwrap_err();
386         assert_eq!(err, ValidationError::NotEnoughRkpVmMarker(1));
387     }
388 
389     #[test]
rkpvm_chain_validate_fails_with_discontinous_markers()390     fn rkpvm_chain_validate_fails_with_discontinous_markers() {
391         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
392         let config_desc = ConfigDescBuilder::new().rkp_vm_marker(true).build();
393         let payloads = vec![
394             valid_payload(0, P256_KEY_PEM[1]).config_desc(config_desc.clone()).build().unwrap(),
395             valid_payload(1, P256_KEY_PEM[2]).build().unwrap(),
396             valid_payload(2, P256_KEY_PEM[3]).config_desc(config_desc.clone()).build().unwrap(),
397         ];
398         let err = Chain::validate(root_public_key, payloads, RkpInstance::Avf).unwrap_err();
399         assert_eq!(err, ValidationError::RkpVmChainHasDiscontinuousMarker(1));
400     }
401 
402     #[test]
rkpvm_chain_validate_fails_last_payload_has_no_marker()403     fn rkpvm_chain_validate_fails_last_payload_has_no_marker() {
404         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
405         let config_desc = ConfigDescBuilder::new().rkp_vm_marker(true).build();
406         let payloads = vec![
407             valid_payload(0, P256_KEY_PEM[1]).config_desc(config_desc.clone()).build().unwrap(),
408             valid_payload(1, P256_KEY_PEM[2]).config_desc(config_desc.clone()).build().unwrap(),
409             valid_payload(2, P256_KEY_PEM[3]).build().unwrap(),
410         ];
411         let err = Chain::validate(root_public_key, payloads, RkpInstance::Avf).unwrap_err();
412         assert_eq!(err, ValidationError::RkpVmChainHasDiscontinuousMarker(2));
413     }
414 
valid_payload(index: usize, pem: &str) -> PayloadBuilder415     fn valid_payload(index: usize, pem: &str) -> PayloadBuilder {
416         PayloadBuilder::with_subject_public_key(PrivateKey::from_pem(pem).public_key())
417             .issuer(format!("component {}", index))
418             .subject(format!("component {}", index + 1))
419             .mode(DiceMode::Normal)
420             .code_hash(vec![0; 64])
421             .authority_hash(vec![0; 64])
422     }
423 
424     #[test]
degenerate_chain_valid()425     fn degenerate_chain_valid() {
426         let key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
427         DegenerateChain::new("issuer", "issuer", key).unwrap();
428     }
429 
430     #[test]
degenerate_chain_empty_issuer()431     fn degenerate_chain_empty_issuer() {
432         let key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
433         let err = DegenerateChain::new("", "subject", key).unwrap_err();
434         assert_eq!(err, DegenerateChainError::IssuerEmpty);
435     }
436 
437     #[test]
degenerate_chain_empty_subject()438     fn degenerate_chain_empty_subject() {
439         let key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
440         let err = DegenerateChain::new("issuer", "", key).unwrap_err();
441         assert_eq!(err, DegenerateChainError::SubjectEmpty);
442     }
443 }
444