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