Build a verified certificate chain by adding CA certificates from the trust store Takes peer certificates (from TLS handshake) and extends the chain by finding issuer certificates from the trust store until reaching a root certificate. Returns the complete chain as DER-encoded bytes.
(
peer_certs: &[CertificateDer<'static>],
ca_certs_der: &[Vec<u8>],
)
| 547 | /// |
| 548 | /// Returns the complete chain as DER-encoded bytes. |
| 549 | pub fn build_verified_chain( |
| 550 | peer_certs: &[CertificateDer<'static>], |
| 551 | ca_certs_der: &[Vec<u8>], |
| 552 | ) -> Vec<Vec<u8>> { |
| 553 | let mut chain_der: Vec<Vec<u8>> = Vec::new(); |
| 554 | |
| 555 | // Start with peer certificates (what was sent during handshake) |
| 556 | for cert in peer_certs { |
| 557 | chain_der.push(cert.as_ref().to_vec()); |
| 558 | } |
| 559 | |
| 560 | // Keep adding issuers until we reach a root or can't find the issuer |
| 561 | while let Some(der) = chain_der.last() { |
| 562 | let last_cert_der = der; |
| 563 | |
| 564 | // Parse the last certificate in the chain |
| 565 | let (_, last_cert) = match X509Certificate::from_der(last_cert_der) { |
| 566 | Ok(parsed) => parsed, |
| 567 | Err(_) => break, |
| 568 | }; |
| 569 | |
| 570 | // Check if it's self-signed (root certificate) |
| 571 | if last_cert.subject() == last_cert.issuer() { |
| 572 | // This is a root certificate, we're done |
| 573 | break; |
| 574 | } |
| 575 | |
| 576 | // Try to find the issuer in the trust store |
| 577 | let issuer_name = last_cert.issuer(); |
| 578 | let mut found_issuer = false; |
| 579 | |
| 580 | for ca_der in ca_certs_der.iter() { |
| 581 | let (_, ca_cert) = match X509Certificate::from_der(ca_der) { |
| 582 | Ok(parsed) => parsed, |
| 583 | Err(_) => continue, |
| 584 | }; |
| 585 | |
| 586 | // Check if this CA's subject matches the certificate's issuer |
| 587 | if ca_cert.subject() == issuer_name { |
| 588 | // Check if we already have this certificate in the chain |
| 589 | if !chain_der.iter().any(|existing| existing == ca_der) { |
| 590 | chain_der.push(ca_der.clone()); |
| 591 | found_issuer = true; |
| 592 | break; |
| 593 | } |
| 594 | } |
| 595 | } |
| 596 | |
| 597 | if !found_issuer { |
| 598 | // Can't find issuer, stop here |
| 599 | break; |
| 600 | } |
| 601 | } |
| 602 | |
| 603 | chain_der |
| 604 | } |
| 605 | |
| 606 | /// Statistics from certificate loading operations |