• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::dice::Payload;
2 use crate::publickey::PublicKey;
3 use anyhow::Result;
4 use std::collections::HashSet;
5 use std::fmt::{self, Display, Formatter};
6 use thiserror::Error;
7 
8 /// Enumeration of the different forms that a DICE chain can take.
9 #[derive(Clone, Debug, Eq, PartialEq)]
10 pub enum ChainForm {
11     /// A proper DICE chain with multiple layers of trust.
12     Proper(Chain),
13     /// A degenerate DICE chain consisting of a single self-signed certificate.
14     Degenerate(DegenerateChain),
15 }
16 
17 /// Represents a DICE chain. This consists of the root public key (which signs the first
18 /// certificate), followed by a chain of certificates.
19 #[derive(Clone, Eq, PartialEq)]
20 pub struct Chain {
21     root_public_key: PublicKey,
22     payloads: Vec<Payload>,
23 }
24 
25 #[derive(Error, Debug, PartialEq, Eq)]
26 pub(crate) enum ValidationError {
27     #[error("no payloads")]
28     NoPayloads,
29     #[error("issuer `{1}` is not previous subject `{2}` in payload {0}")]
30     IssuerMismatch(usize, String, String),
31     #[error("repeated subject in payload {0}")]
32     RepeatedSubject(usize, String),
33     #[error("repeated key in payload {0}")]
34     RepeatedKey(usize),
35 }
36 
37 impl ChainForm {
leaf_public_key(&self) -> &PublicKey38     pub(crate) fn leaf_public_key(&self) -> &PublicKey {
39         match self {
40             Self::Proper(chain) => chain.leaf().subject_public_key(),
41             Self::Degenerate(degenerate) => degenerate.public_key(),
42         }
43     }
44 }
45 
46 impl Chain {
47     /// Builds a [`Chain`] after checking that it is well-formed. The issuer of each entry must be
48     /// equal to the subject of the previous entry. The chain is not allowed to contain any
49     /// repeated subjects or subject public keys as that would suggest something untoward has
50     /// happened.
validate( root_public_key: PublicKey, payloads: Vec<Payload>, ) -> Result<Self, ValidationError>51     pub(crate) fn validate(
52         root_public_key: PublicKey,
53         payloads: Vec<Payload>,
54     ) -> Result<Self, ValidationError> {
55         if payloads.is_empty() {
56             return Err(ValidationError::NoPayloads);
57         }
58 
59         let mut subjects = HashSet::with_capacity(payloads.len());
60         let mut keys = HashSet::with_capacity(1 + payloads.len());
61         keys.insert(root_public_key.to_pem());
62 
63         let mut previous_subject: Option<&str> = None;
64         for (n, payload) in payloads.iter().enumerate() {
65             if let Some(previous_subject) = previous_subject {
66                 if payload.issuer() != previous_subject {
67                     return Err(ValidationError::IssuerMismatch(
68                         n,
69                         payload.issuer().to_string(),
70                         previous_subject.to_string(),
71                     ));
72                 }
73             }
74             if subjects.replace(payload.subject()).is_some() {
75                 return Err(ValidationError::RepeatedSubject(n, payload.subject().to_string()));
76             }
77             if keys.replace(payload.subject_public_key().to_pem()).is_some() {
78                 return Err(ValidationError::RepeatedKey(n));
79             }
80             previous_subject = Some(payload.subject());
81         }
82 
83         Ok(Self { root_public_key, payloads })
84     }
85 
86     /// Get the root public key which verifies the first certificate in the chain.
root_public_key(&self) -> &PublicKey87     pub fn root_public_key(&self) -> &PublicKey {
88         &self.root_public_key
89     }
90 
91     /// Get the payloads of the certificates in the chain, from root to leaf.
payloads(&self) -> &[Payload]92     pub fn payloads(&self) -> &[Payload] {
93         &self.payloads
94     }
95 
96     /// Get the payload from the final certificate in the chain.
leaf(&self) -> &Payload97     pub fn leaf(&self) -> &Payload {
98         // There is always at least one payload.
99         self.payloads.last().unwrap()
100     }
101 }
102 
103 impl Display for Chain {
fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error>104     fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
105         writeln!(f, "Root public key:")?;
106         writeln!(f, "{}", self.root_public_key.to_pem())?;
107         for (i, payload) in self.payloads.iter().enumerate() {
108             writeln!(f, "Cert {}:", i)?;
109             writeln!(f, "{}", payload)?;
110         }
111         Ok(())
112     }
113 }
114 
115 impl fmt::Debug for Chain {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result116     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
117         let mut debug = fmt.debug_struct("Chain");
118         debug.field("Root public key", &self.root_public_key.to_pem());
119         for (i, payload) in self.payloads.iter().enumerate() {
120             debug.field(&format!("DICE Certificate[{i}]"), payload);
121         }
122         debug.finish()
123     }
124 }
125 
126 #[derive(Error, Debug, PartialEq, Eq)]
127 pub(crate) enum DegenerateChainError {
128     #[error("issuer empty")]
129     IssuerEmpty,
130     #[error("subject empty")]
131     SubjectEmpty,
132 }
133 
134 /// A degenerate DICE chain. These chains consist of a single, self-signed certificate and the
135 /// entries contain less information than usual. They are expected from devices that haven't
136 /// implemented everything necessary to produce a proper DICE Chain.
137 #[derive(Clone, Debug, Eq, PartialEq)]
138 pub struct DegenerateChain {
139     issuer: String,
140     subject: String,
141     subject_public_key: PublicKey,
142 }
143 
144 impl DegenerateChain {
new<I: Into<String>, S: Into<String>>( issuer: I, subject: S, subject_public_key: PublicKey, ) -> Result<Self, DegenerateChainError>145     pub(crate) fn new<I: Into<String>, S: Into<String>>(
146         issuer: I,
147         subject: S,
148         subject_public_key: PublicKey,
149     ) -> Result<Self, DegenerateChainError> {
150         let issuer = issuer.into();
151         let subject = subject.into();
152         if issuer.is_empty() {
153             return Err(DegenerateChainError::IssuerEmpty);
154         }
155         if subject.is_empty() {
156             return Err(DegenerateChainError::SubjectEmpty);
157         }
158         Ok(Self { issuer, subject, subject_public_key })
159     }
160 
161     /// Gets the issuer of the degenerate chain.
issuer(&self) -> &str162     pub fn issuer(&self) -> &str {
163         &self.issuer
164     }
165 
166     /// Gets the subject of the degenerate chain.
subject(&self) -> &str167     pub fn subject(&self) -> &str {
168         &self.subject
169     }
170 
171     /// Gets the public key of the degenerate chain.
public_key(&self) -> &PublicKey172     pub fn public_key(&self) -> &PublicKey {
173         &self.subject_public_key
174     }
175 }
176 
177 impl Display for DegenerateChain {
fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error>178     fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
179         writeln!(f, "Public key:")?;
180         writeln!(f, "{}", self.public_key().to_pem())?;
181         writeln!(f, "Issuer: {}", self.issuer)?;
182         writeln!(f, "Subject: {}", self.subject)?;
183         Ok(())
184     }
185 }
186 
187 #[cfg(test)]
188 mod tests {
189     use super::*;
190     use crate::dice::{DiceMode, PayloadBuilder};
191     use crate::publickey::testkeys::{PrivateKey, ED25519_KEY_PEM, P256_KEY_PEM, P384_KEY_PEM};
192 
193     #[test]
chain_validate_valid()194     fn chain_validate_valid() {
195         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
196         let keys = P256_KEY_PEM[1..4].iter().copied().enumerate();
197         let payloads = keys.map(|(n, key)| valid_payload(n, key).build().unwrap()).collect();
198         Chain::validate(root_public_key, payloads).unwrap();
199     }
200 
201     #[test]
chain_validate_valid_with_mixed_kinds_of_key()202     fn chain_validate_valid_with_mixed_kinds_of_key() {
203         let root_public_key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
204         let keys = [P256_KEY_PEM[0], P384_KEY_PEM[0]].into_iter().enumerate();
205         let payloads = keys.map(|(n, key)| valid_payload(n, key).build().unwrap()).collect();
206         Chain::validate(root_public_key, payloads).unwrap();
207     }
208 
209     #[test]
chain_validate_fails_without_payloads()210     fn chain_validate_fails_without_payloads() {
211         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
212         let payloads = Vec::new();
213         let err = Chain::validate(root_public_key, payloads).unwrap_err();
214         assert_eq!(err, ValidationError::NoPayloads);
215     }
216 
217     #[test]
chain_validate_fails_when_root_key_repeated()218     fn chain_validate_fails_when_root_key_repeated() {
219         let key = P256_KEY_PEM[0];
220         let root_public_key = PrivateKey::from_pem(key).public_key();
221         let payloads = vec![valid_payload(0, key).build().unwrap()];
222         let err = Chain::validate(root_public_key, payloads).unwrap_err();
223         assert_eq!(err, ValidationError::RepeatedKey(0));
224     }
225 
226     #[test]
chain_validate_fails_with_repeated_subject_public_keys()227     fn chain_validate_fails_with_repeated_subject_public_keys() {
228         let repeated_key = P256_KEY_PEM[0];
229         let root_public_key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
230         let payloads = vec![
231             valid_payload(0, repeated_key).build().unwrap(),
232             valid_payload(1, repeated_key).build().unwrap(),
233         ];
234         let err = Chain::validate(root_public_key, payloads).unwrap_err();
235         assert_eq!(err, ValidationError::RepeatedKey(1));
236     }
237 
238     #[test]
chain_validate_fails_with_repeated_subjects()239     fn chain_validate_fails_with_repeated_subjects() {
240         let keys = &P256_KEY_PEM[..3];
241         let repeated = "match";
242         let root_public_key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
243         let payloads = vec![
244             valid_payload(0, keys[0]).subject(repeated).build().unwrap(),
245             valid_payload(1, keys[1]).issuer(repeated).build().unwrap(),
246             valid_payload(2, keys[2]).subject(repeated).build().unwrap(),
247         ];
248         let err = Chain::validate(root_public_key, payloads).unwrap_err();
249         assert_eq!(err, ValidationError::RepeatedSubject(2, repeated.into()));
250     }
251 
252     #[test]
chain_validate_fails_with_mismatching_issuer_and_subject()253     fn chain_validate_fails_with_mismatching_issuer_and_subject() {
254         let expected = "expected";
255         let wrong = "wrong";
256         let root_public_key = PrivateKey::from_pem(P256_KEY_PEM[0]).public_key();
257         let payloads = vec![
258             valid_payload(0, P256_KEY_PEM[1]).subject(expected).build().unwrap(),
259             valid_payload(1, P256_KEY_PEM[2]).issuer(wrong).build().unwrap(),
260         ];
261         let err = Chain::validate(root_public_key, payloads).unwrap_err();
262         assert_eq!(err, ValidationError::IssuerMismatch(1, wrong.into(), expected.into()));
263     }
264 
valid_payload(index: usize, pem: &str) -> PayloadBuilder265     fn valid_payload(index: usize, pem: &str) -> PayloadBuilder {
266         PayloadBuilder::with_subject_public_key(PrivateKey::from_pem(pem).public_key())
267             .issuer(format!("component {}", index))
268             .subject(format!("component {}", index + 1))
269             .mode(DiceMode::Normal)
270             .code_hash(vec![0; 64])
271             .authority_hash(vec![0; 64])
272     }
273 
274     #[test]
degenerate_chain_valid()275     fn degenerate_chain_valid() {
276         let key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
277         DegenerateChain::new("issuer", "issuer", key).unwrap();
278     }
279 
280     #[test]
degenerate_chain_empty_issuer()281     fn degenerate_chain_empty_issuer() {
282         let key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
283         let err = DegenerateChain::new("", "subject", key).unwrap_err();
284         assert_eq!(err, DegenerateChainError::IssuerEmpty);
285     }
286 
287     #[test]
degenerate_chain_empty_subject()288     fn degenerate_chain_empty_subject() {
289         let key = PrivateKey::from_pem(ED25519_KEY_PEM[0]).public_key();
290         let err = DegenerateChain::new("issuer", "", key).unwrap_err();
291         assert_eq!(err, DegenerateChainError::SubjectEmpty);
292     }
293 }
294