webpki_trust_handler.rs (21948B)
1 // Copyright 2023 Adobe. All rights reserved. 2 // This file is licensed to you under the Apache License, 3 // Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 4 // or the MIT license (http://opensource.org/licenses/MIT), 5 // at your option. 6 7 // Unless required by applicable law or agreed to in writing, 8 // this software is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or 10 // implied. See the LICENSE-MIT and LICENSE-APACHE files for the 11 // specific language governing permissions and limitations under 12 // each license. 13 14 use std::{ 15 collections::HashSet, 16 io::{BufRead, BufReader, Cursor, Read}, 17 str::FromStr, 18 }; 19 20 use asn1_rs::{nom::AsBytes, Any, Class, Header, Tag}; 21 use x509_parser::{ 22 der_parser::der::{parse_der_integer, parse_der_sequence_of}, 23 oid_registry::Oid, 24 prelude::*, 25 }; 26 27 use crate::{ 28 cose_validator::*, 29 error::{Error, Result}, 30 hash_utils::{hash_sha256, vec_compare}, 31 trust_handler::{ 32 has_allowed_oid, load_eku_configuration, load_trust_from_data, TrustHandlerConfig, 33 }, 34 utils::base64, 35 wasm::webcrypto_validator::async_validate, 36 SigningAlg, 37 }; 38 39 // Struct to handle verification of trust chains using WebPki 40 pub(crate) struct WebTrustHandlerConfig { 41 pub trust_anchors: Vec<Vec<u8>>, 42 pub private_anchors: Vec<Vec<u8>>, 43 allowed_cert_set: HashSet<String>, 44 config_store: Vec<u8>, 45 } 46 47 impl std::fmt::Debug for WebTrustHandlerConfig { 48 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 49 write!( 50 f, 51 "{} trust anchors, {} private anchors.", 52 self.trust_anchors.len(), 53 self.private_anchors.len() 54 ) 55 } 56 } 57 58 impl WebTrustHandlerConfig { 59 pub fn load_default_trust(&mut self) -> Result<()> { 60 // load config store 61 let config = include_bytes!("./store.cfg"); 62 let mut config_reader = Cursor::new(config); 63 self.load_configuration(&mut config_reader)?; 64 65 // load debug/test private trust anchors 66 if cfg!(test) { 67 let pa = include_bytes!("./test_cert_root_bundle.pem"); 68 let mut pa_reader = Cursor::new(pa); 69 70 self.append_private_trust_data(&mut pa_reader)?; 71 } 72 73 Ok(()) 74 } 75 } 76 77 impl TrustHandlerConfig for WebTrustHandlerConfig { 78 fn new() -> Self { 79 let mut th = WebTrustHandlerConfig { 80 trust_anchors: Vec::new(), 81 private_anchors: Vec::new(), 82 allowed_cert_set: HashSet::new(), 83 config_store: Vec::new(), 84 }; 85 86 if th.load_default_trust().is_err() { 87 th.clear(); // just use empty trust handler to fail automatically 88 } 89 90 th 91 } 92 93 // add trust anchors 94 fn load_trust_anchors_from_data(&mut self, trust_data_reader: &mut dyn Read) -> Result<()> { 95 let mut trust_data = Vec::new(); 96 trust_data_reader.read_to_end(&mut trust_data)?; 97 98 let mut anchors = load_trust_from_data(&trust_data)?; 99 self.trust_anchors.append(&mut anchors); 100 Ok(()) 101 } 102 103 // append private trust anchors 104 fn append_private_trust_data(&mut self, private_anchors_reader: &mut dyn Read) -> Result<()> { 105 let mut private_anchors_data = Vec::new(); 106 private_anchors_reader.read_to_end(&mut private_anchors_data)?; 107 108 let mut anchors = load_trust_from_data(&private_anchors_data)?; 109 self.private_anchors.append(&mut anchors); 110 111 Ok(()) 112 } 113 114 fn clear(&mut self) { 115 self.trust_anchors = Vec::new(); 116 self.private_anchors = Vec::new(); 117 } 118 119 // load EKU configuration 120 fn load_configuration(&mut self, config_data: &mut dyn Read) -> Result<()> { 121 config_data.read_to_end(&mut self.config_store)?; 122 Ok(()) 123 } 124 125 // list off auxillary allowed EKU Oid 126 fn get_auxillary_ekus(&self) -> Vec<Oid> { 127 let mut oids = Vec::new(); 128 if let Ok(oid_strings) = load_eku_configuration(&mut Cursor::new(&self.config_store)) { 129 for oid_str in &oid_strings { 130 if let Ok(oid) = Oid::from_str(oid_str) { 131 oids.push(oid); 132 } 133 } 134 } 135 oids 136 } 137 138 fn get_anchors(&self) -> Vec<Vec<u8>> { 139 let mut anchors = Vec::new(); 140 141 anchors.append(&mut self.trust_anchors.clone()); 142 anchors.append(&mut self.private_anchors.clone()); 143 144 anchors 145 } 146 147 // add allowed list entries 148 fn load_allowed_list(&mut self, allowed_list: &mut dyn Read) -> Result<()> { 149 let mut buffer = Vec::new(); 150 allowed_list.read_to_end(&mut buffer)?; 151 152 if let Ok(cert_list) = load_trust_from_data(&buffer) { 153 for cert_der in &cert_list { 154 let cert_sha256 = hash_sha256(cert_der); 155 let cert_hash_base64 = base64::encode(&cert_sha256); 156 157 self.allowed_cert_set.insert(cert_hash_base64); 158 } 159 } 160 161 // try to load the of base64 encoded encoding of the sha256 hash of the certificate DER encoding 162 let reader = Cursor::new(buffer); 163 let buf_reader = BufReader::new(reader); 164 165 let mut inside_cert_block = false; 166 for l in buf_reader.lines().flatten() { 167 if l.contains("-----BEGIN") { 168 inside_cert_block = true; 169 } 170 if l.contains("-----END") { 171 inside_cert_block = false; 172 } 173 174 // sanity check that data is base64 encoded and outside of certificate block 175 if !inside_cert_block && base64::decode(&l).is_ok() && !l.is_empty() { 176 self.allowed_cert_set.insert(l); 177 } 178 } 179 180 Ok(()) 181 } 182 183 // set of allowed cert hashes 184 fn get_allowed_list(&self) -> &HashSet<String> { 185 &self.allowed_cert_set 186 } 187 } 188 189 fn find_allowed_eku<'a>(cert_der: &'a [u8], allowed_ekus: &'a Vec<Oid<'a>>) -> Option<&'a Oid<'a>> { 190 if let Ok((_rem, cert)) = X509Certificate::from_der(cert_der) { 191 if let Ok(Some(eku)) = cert.extended_key_usage() { 192 if let Some(o) = has_allowed_oid(eku.value, allowed_ekus) { 193 return Some(o); 194 } 195 } 196 } 197 None 198 } 199 fn cert_signing_alg(cert: &x509_parser::certificate::X509Certificate) -> Option<String> { 200 let cert_alg = cert.signature_algorithm.algorithm.clone(); 201 202 let signing_alg = if cert_alg == SHA256_WITH_RSAENCRYPTION_OID { 203 "rsa256".to_string() 204 } else if cert_alg == SHA384_WITH_RSAENCRYPTION_OID { 205 "rsa384".to_string() 206 } else if cert_alg == SHA512_WITH_RSAENCRYPTION_OID { 207 "rsa512".to_string() 208 } else if cert_alg == ECDSA_WITH_SHA256_OID { 209 SigningAlg::Es256.to_string() 210 } else if cert_alg == ECDSA_WITH_SHA384_OID { 211 SigningAlg::Es384.to_string() 212 } else if cert_alg == ECDSA_WITH_SHA512_OID { 213 SigningAlg::Es512.to_string() 214 } else if cert_alg == RSASSA_PSS_OID { 215 if let Some(parameters) = &cert.signature_algorithm.parameters { 216 let seq = match parameters.as_sequence() { 217 Ok(s) => s, 218 Err(_) => return None, 219 }; 220 221 let (_i, (ha_alg, mgf_ai)) = match seq.parse(|i| { 222 let (i, h) = Header::from_der(i)?; 223 if h.class() != Class::ContextSpecific || h.tag() != Tag(0) { 224 return Err(nom::Err::Error(asn1_rs::Error::BerValueError)); 225 } 226 227 let (i, ha_alg) = AlgorithmIdentifier::from_der(i) 228 .map_err(|_| nom::Err::Error(asn1_rs::Error::BerValueError))?; 229 230 let (i, h) = Header::from_der(i)?; 231 if h.class() != Class::ContextSpecific || h.tag() != Tag(1) { 232 return Err(nom::Err::Error(asn1_rs::Error::BerValueError)); 233 } 234 235 let (i, mgf_ai) = AlgorithmIdentifier::from_der(i) 236 .map_err(|_| nom::Err::Error(asn1_rs::Error::BerValueError))?; 237 238 // Ignore anything that follows these two parameters. 239 240 Ok((i, (ha_alg, mgf_ai))) 241 }) { 242 Ok((ii, (h, m))) => (ii, (h, m)), 243 Err(_) => return None, 244 }; 245 246 let mgf_ai_parameters = match mgf_ai.parameters { 247 Some(m) => m, 248 None => return None, 249 }; 250 251 let mgf_ai_parameters = match mgf_ai_parameters.as_sequence() { 252 Ok(m) => m, 253 Err(_) => return None, 254 }; 255 256 let (_i, mgf_ai_params_algorithm) = match Any::from_der(&mgf_ai_parameters.content) { 257 Ok((i, m)) => (i, m), 258 Err(_) => return None, 259 }; 260 261 let mgf_ai_params_algorithm = match mgf_ai_params_algorithm.as_oid() { 262 Ok(m) => m, 263 Err(_) => return None, 264 }; 265 266 // must be the same 267 if ha_alg.algorithm != mgf_ai_params_algorithm { 268 return None; 269 } 270 271 // check for one of the mandatory types 272 if ha_alg.algorithm == SHA256_OID { 273 "ps256".to_string() 274 } else if ha_alg.algorithm == SHA384_OID { 275 "ps384".to_string() 276 } else if ha_alg.algorithm == SHA512_OID { 277 "ps512".to_string() 278 } else { 279 return None; 280 } 281 } else { 282 return None; 283 } 284 } else if cert_alg == ED25519_OID { 285 SigningAlg::Ed25519.to_string() 286 } else { 287 return None; 288 }; 289 290 Some(signing_alg) 291 } 292 293 async fn verify_data( 294 cert_der: Vec<u8>, 295 sig_alg: Option<String>, 296 sig: Vec<u8>, 297 data: Vec<u8>, 298 ) -> Result<bool> { 299 use x509_parser::prelude::*; 300 301 let (_, cert) = 302 X509Certificate::from_der(cert_der.as_bytes()).map_err(|_e| Error::CoseCertUntrusted)?; 303 304 let certificate_public_key = cert.public_key(); 305 if let Some(cert_alg_string) = sig_alg { 306 let (algo, hash, salt_len) = match cert_alg_string.as_str() { 307 "rsa256" => ( 308 "RSASSA-PKCS1-v1_5".to_string(), 309 "SHA-256".to_string().to_string(), 310 0, 311 ), 312 "rsa384" => ("RSASSA-PKCS1-v1_5".to_string(), "SHA-384".to_string(), 0), 313 "rsa512" => ("RSASSA-PKCS1-v1_5".to_string(), "SHA-512".to_string(), 0), 314 "es256" => ("ECDSA".to_string(), "SHA-256".to_string().to_string(), 0), 315 "es384" => ("ECDSA".to_string(), "SHA-384".to_string(), 0), 316 "es512" => ("ECDSA".to_string(), "SHA-512".to_string(), 0), 317 "ps256" => ("RSA-PSS".to_string(), "SHA-256".to_string(), 32), 318 "ps384" => ("RSA-PSS".to_string(), "SHA-384".to_string(), 48), 319 "ps512" => ("RSA-PSS".to_string(), "SHA-512".to_string(), 64), 320 "ed25519" => ("ED25519".to_string(), "SHA-512".to_string(), 0), 321 _ => return Err(Error::UnsupportedType), 322 }; 323 324 let adjusted_sig = if cert_alg_string.starts_with("es") { 325 let parsed_alg_string: SigningAlg = cert_alg_string 326 .parse() 327 .map_err(|_| Error::UnknownAlgorithm)?; 328 match der_to_p1363(&sig, parsed_alg_string) { 329 Some(p1363) => p1363, 330 None => sig, 331 } 332 } else { 333 sig 334 }; 335 336 async_validate( 337 algo, 338 hash, 339 salt_len, 340 certificate_public_key.raw.to_vec(), 341 adjusted_sig, 342 data, 343 ) 344 .await 345 } else { 346 return Err(Error::BadParam("unknown alg processing cert".to_string())); 347 } 348 } 349 // convert der signatures to P1363 format: r | s 350 fn der_to_p1363(data: &[u8], alg: SigningAlg) -> Option<Vec<u8>> { 351 // handle if this is a der sequence 352 if let Ok((_, bo)) = parse_der_sequence_of(parse_der_integer)(data) { 353 let seq = bo.as_sequence().ok()?; 354 355 if seq.len() != 2 { 356 return None; 357 } 358 359 let rp = seq[0].as_bigint().ok()?; 360 let sp = seq[1].as_bigint().ok()?; 361 362 let mut r = rp.to_str_radix(16); 363 let mut s = sp.to_str_radix(16); 364 365 let sig_len: usize = match alg { 366 SigningAlg::Es256 => 64, 367 SigningAlg::Es384 => 96, 368 SigningAlg::Es512 => 132, 369 _ => return None, 370 }; 371 372 // pad or truncate as needed 373 let rp = if r.len() > sig_len { 374 // truncate 375 let offset = r.len() - sig_len; 376 &r[offset..r.len()] 377 } else { 378 // pad 379 while r.len() != sig_len { 380 r.insert(0, '0'); 381 } 382 r.as_ref() 383 }; 384 385 let sp = if s.len() > sig_len { 386 // truncate 387 let offset = s.len() - sig_len; 388 &s[offset..s.len()] 389 } else { 390 // pad 391 while s.len() != sig_len { 392 s.insert(0, '0'); 393 } 394 s.as_ref() 395 }; 396 397 if rp.len() != sig_len || rp.len() != sp.len() { 398 return None; 399 } 400 401 // merge r and s strings 402 let mut new_sig = rp.to_string(); 403 new_sig.push_str(sp); 404 405 // convert back from hex string to byte array 406 let result = (0..new_sig.len()) 407 .step_by(2) 408 .map(|i| { 409 u8::from_str_radix(&new_sig[i..i + 2], 16) 410 .map_err(|_err| crate::Error::InvalidEcdsaSignature) 411 }) 412 .collect(); 413 414 if let Ok(p1363) = result { 415 Some(p1363) 416 } else { 417 None 418 } 419 } else { 420 Some(data.to_vec()) 421 } 422 } 423 424 async fn check_chain_order(certs: &[Vec<u8>]) -> Result<()> { 425 use x509_parser::prelude::*; 426 427 let chain_length = certs.len(); 428 if chain_length < 2 { 429 return Ok(()); 430 } 431 432 for i in 1..chain_length { 433 let (_, current_cert) = 434 X509Certificate::from_der(&certs[i - 1]).map_err(|_e| Error::CoseCertUntrusted)?; 435 436 let issuer_der = certs[i].to_vec(); 437 let data = current_cert.tbs_certificate.as_ref(); 438 let sig = current_cert.signature_value.as_ref(); 439 440 let sig_alg = cert_signing_alg(¤t_cert); 441 442 let result = verify_data(issuer_der, sig_alg, sig.to_vec(), data.to_vec()).await; 443 444 // keep going as long as it validate 445 match result { 446 Ok(b) => { 447 if !b { 448 return Err(Error::OtherError("cert chain order invalid".into())); 449 } 450 } 451 Err(e) => return Err(e), 452 } 453 } 454 Ok(()) 455 } 456 457 async fn on_trust_list( 458 th: &dyn TrustHandlerConfig, 459 certs: &[Vec<u8>], 460 ee_der: &[u8], 461 ) -> Result<bool> { 462 use x509_parser::prelude::*; 463 464 // check the cert against the allowed list first 465 let cert_sha256 = hash_sha256(ee_der); 466 let cert_hash_base64 = base64::encode(&cert_sha256); 467 if th.get_allowed_list().contains(&cert_hash_base64) { 468 return Ok(true); 469 } 470 471 // add ee cert if needed to the chain 472 let full_chain = if !certs.is_empty() && vec_compare(ee_der, &certs[0]) { 473 certs.to_vec() 474 } else { 475 let mut full_chain: Vec<Vec<u8>> = Vec::new(); 476 full_chain.push(ee_der.to_vec()); 477 let mut in_chain = certs.to_vec(); 478 full_chain.append(&mut in_chain); 479 full_chain 480 }; 481 482 // make sure chain is in the correct order and valid 483 check_chain_order(&full_chain).await?; 484 485 // build anchors and check against trust anchors, 486 let mut anchors: Vec<X509Certificate> = Vec::new(); 487 let source_anchors = th.get_anchors(); 488 for anchor_der in &source_anchors { 489 let (_, anchor) = 490 X509Certificate::from_der(anchor_der).map_err(|_e| Error::CoseCertUntrusted)?; 491 anchors.push(anchor); 492 } 493 494 if anchors.is_empty() { 495 return Ok(false); 496 } 497 498 // work back from last cert in chain against the trust anchors 499 for cert in certs.iter().rev() { 500 let (_, chain_cert) = 501 X509Certificate::from_der(cert).map_err(|_e| Error::CoseCertUntrusted)?; 502 503 for anchor in &source_anchors { 504 let data = chain_cert.tbs_certificate.as_ref(); 505 let sig = chain_cert.signature_value.as_ref(); 506 507 let sig_alg = cert_signing_alg(&chain_cert); 508 509 let (_, anchor_cert) = 510 X509Certificate::from_der(anchor).map_err(|_e| Error::CoseCertUntrusted)?; 511 512 if chain_cert.issuer() == anchor_cert.subject() { 513 let result = 514 verify_data(anchor.clone(), sig_alg, sig.to_vec(), data.to_vec()).await; 515 516 match result { 517 Ok(b) => { 518 if b { 519 return Ok(true); 520 } 521 } 522 Err(_) => continue, 523 } 524 } 525 } 526 } 527 // todo: consider (path check and names restrictions) 528 529 Ok(false) 530 } 531 532 // verify certificate and trust chain 533 pub(crate) async fn verify_trust_async( 534 th: &dyn TrustHandlerConfig, 535 chain_der: &[Vec<u8>], 536 cert_der: &[u8], 537 ) -> Result<bool> { 538 // check configured EKUs against end-entity cert 539 find_allowed_eku(cert_der, &th.get_auxillary_ekus()).ok_or(Error::CoseCertUntrusted)?; 540 541 on_trust_list(th, chain_der, cert_der).await 542 } 543 544 #[cfg(test)] 545 pub mod tests { 546 #![allow(clippy::expect_used)] 547 #![allow(clippy::panic)] 548 #![allow(clippy::unwrap_used)] 549 550 #[cfg(target_arch = "wasm32")] 551 use wasm_bindgen_test::*; 552 553 use super::*; 554 #[cfg_attr(not(target_arch = "wasm32"), test)] 555 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] 556 #[wasm_bindgen_test] 557 async fn test_trust_store() { 558 let mut th = WebTrustHandlerConfig::new(); 559 th.clear(); 560 561 th.load_default_trust().unwrap(); 562 563 // test all the certs 564 let ps256 = include_bytes!("../../tests/fixtures/certs/ps256.pub"); 565 let ps384 = include_bytes!("../../tests/fixtures/certs/ps384.pub"); 566 let ps512 = include_bytes!("../../tests/fixtures/certs/ps512.pub"); 567 let es256 = include_bytes!("../../tests/fixtures/certs/es256.pub"); 568 let es384 = include_bytes!("../../tests/fixtures/certs/es384.pub"); 569 let es512 = include_bytes!("../../tests/fixtures/certs/es512.pub"); 570 let ed25519 = include_bytes!("../../tests/fixtures/certs/ed25519.pub"); 571 572 let ps256_certs = load_trust_from_data(ps256).unwrap(); 573 let ps384_certs = load_trust_from_data(ps384).unwrap(); 574 let ps512_certs = load_trust_from_data(ps512).unwrap(); 575 let es256_certs = load_trust_from_data(es256).unwrap(); 576 let es384_certs = load_trust_from_data(es384).unwrap(); 577 let es512_certs = load_trust_from_data(es512).unwrap(); 578 let ed25519_certs = load_trust_from_data(ed25519).unwrap(); 579 580 assert!(verify_trust_async(&th, &ps256_certs[1..], &ps256_certs[0]) 581 .await 582 .unwrap()); 583 assert!(verify_trust_async(&th, &ps384_certs[1..], &ps384_certs[0]) 584 .await 585 .unwrap()); 586 assert!(verify_trust_async(&th, &ps512_certs[1..], &ps512_certs[0]) 587 .await 588 .unwrap()); 589 assert!(verify_trust_async(&th, &es256_certs[1..], &es256_certs[0]) 590 .await 591 .unwrap()); 592 593 assert!(verify_trust_async(&th, &es384_certs[1..], &es384_certs[0]) 594 .await 595 .unwrap()); 596 assert!(verify_trust_async(&th, &es512_certs[1..], &es512_certs[0]) 597 .await 598 .unwrap()); 599 600 assert!( 601 verify_trust_async(&th, &ed25519_certs[1..], &ed25519_certs[0]) 602 .await 603 .unwrap() 604 ); 605 } 606 607 #[cfg_attr(not(target_arch = "wasm32"), test)] 608 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] 609 #[wasm_bindgen_test] 610 async fn test_broken_trust_chain() { 611 let mut th = WebTrustHandlerConfig::new(); 612 th.clear(); 613 614 th.load_default_trust().unwrap(); 615 616 // test all the certs 617 let ps256 = include_bytes!("../../tests/fixtures/certs/ps256.pub"); 618 let ps384 = include_bytes!("../../tests/fixtures/certs/ps384.pub"); 619 let ps512 = include_bytes!("../../tests/fixtures/certs/ps512.pub"); 620 let es256 = include_bytes!("../../tests/fixtures/certs/es256.pub"); 621 let es384 = include_bytes!("../../tests/fixtures/certs/es384.pub"); 622 let es512 = include_bytes!("../../tests/fixtures/certs/es512.pub"); 623 let ed25519 = include_bytes!("../../tests/fixtures/certs/ed25519.pub"); 624 625 let ps256_certs = load_trust_from_data(ps256).unwrap(); 626 let ps384_certs = load_trust_from_data(ps384).unwrap(); 627 let ps512_certs = load_trust_from_data(ps512).unwrap(); 628 let es256_certs = load_trust_from_data(es256).unwrap(); 629 let es384_certs = load_trust_from_data(es384).unwrap(); 630 let es512_certs = load_trust_from_data(es512).unwrap(); 631 let ed25519_certs = load_trust_from_data(ed25519).unwrap(); 632 633 assert!(!verify_trust_async(&th, &ps256_certs[2..], &ps256_certs[0]) 634 .await 635 .unwrap()); 636 assert!(!verify_trust_async(&th, &ps384_certs[2..], &ps384_certs[0]) 637 .await 638 .unwrap()); 639 assert!(!verify_trust_async(&th, &ps512_certs[2..], &ps512_certs[0]) 640 .await 641 .unwrap()); 642 assert!(!verify_trust_async(&th, &es256_certs[2..], &es256_certs[0]) 643 .await 644 .unwrap()); 645 assert!(!verify_trust_async(&th, &es384_certs[2..], &es384_certs[0]) 646 .await 647 .unwrap()); 648 assert!(!verify_trust_async(&th, &es512_certs[2..], &es512_certs[0]) 649 .await 650 .unwrap()); 651 assert!( 652 !verify_trust_async(&th, &ed25519_certs[2..], &ed25519_certs[0]) 653 .await 654 .unwrap() 655 ); 656 } 657 }