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