Skip to content

Commit b6fa5f8

Browse files
committed
Simplify transformation of TQ cert chain for use by rustls.
This approach puts simpliciy above efficiency: the SliceReader makes this very simple but it holds a reference to the TQ cert chain so we must copy each cert instead of draining the bytes from the original `Vec<u8>`.
1 parent 43dc6c5 commit b6fa5f8

1 file changed

Lines changed: 17 additions & 36 deletions

File tree

tls/src/keys.rs

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -56,46 +56,27 @@ impl CertResolver {
5656
fn load_ipcc_key(&self) -> Result<Arc<CertifiedKey>, crate::Error> {
5757
let ipcc = Ipcc::new().map_err(crate::Error::RotRequest)?;
5858
let cert_chain_bytes = ipcc.rot_get_tq_cert_chain()?;
59-
let mut idx = 0;
60-
let mut der_vec = vec![];
61-
// The cert chain returned is a concatenated series of DER certs.
62-
// rustls wants each cert as a member of a `Vec`. We don't know
63-
// the length of each cert so we have to parse the DER to find it.
64-
//
65-
// Note we could just return the length of each cert but that
66-
// either invovles more IPCC calls or more work on the RoT/SP.
67-
// This code runs on the Big CPU so we can do the Big Work here.
68-
// A note for our certificate manufacturing v2 would be to just
69-
// include the length of each cert along with the DER
70-
while idx < cert_chain_bytes.len() {
71-
let reader = der::SliceReader::new(&cert_chain_bytes[idx..])
72-
.map_err(crate::Error::Der)?;
73-
let header = reader.peek_header().map_err(crate::Error::Der)?;
74-
// DER certificates are supposed to be a `Sequence`.
75-
// We could check that here but we're going to get better
76-
// error messages by letting the cert parsing code say
77-
// exactly what went wrong
78-
let seq_len: usize =
79-
header.length.try_into().map_err(crate::Error::Der)?;
80-
let tag_len: usize = header
81-
.encoded_len()
82-
.map_err(crate::Error::Der)?
83-
.try_into()
84-
.map_err(crate::Error::Der)?;
85-
// Total len = length from the sequence plus the tag itself
86-
let end = idx + seq_len + tag_len;
8759

60+
// The cert chain returned is a concatenated series of DER certs.
61+
// rustls wants each cert as a member of a `Vec`. This loop uses a
62+
// `SliceReader` to walk the concatinated DER encoded cert chain parsing
63+
// each into an `x509_cert::Certificate` to ensure it's actually a cert.
64+
// It then collects the DER for each into the
65+
// `Vec<rustls::CertificateDer>` expected by rustls.
66+
let mut der_vec = vec![];
67+
let mut reader = der::SliceReader::new(&cert_chain_bytes)?;
68+
while !reader.is_finished() {
69+
let start: usize =
70+
reader.position().try_into().map_err(crate::Error::Der)?;
71+
let cert: Certificate = reader.decode()?;
72+
info!(self.log, "Certificate => {}", cert.tbs_certificate.subject);
73+
let end: usize =
74+
reader.position().try_into().map_err(crate::Error::Der)?;
8875
der_vec.push(CertificateDer::from(
89-
cert_chain_bytes[idx..end].to_vec(),
76+
cert_chain_bytes[start..end].to_vec(),
9077
));
91-
idx += seq_len + tag_len;
92-
}
93-
for c in &der_vec {
94-
// Apart from printing out a bit of certificate information this
95-
// also serves as a validation on the DER certificate.
96-
let cert = Certificate::from_der(c).map_err(crate::Error::Der)?;
97-
info!(self.log, "Certificate => {}", cert.tbs_certificate.subject);
9878
}
79+
9980
// TODO pass the existing ipcc handle. Right now we can't because
10081
// we need to review sync/send/copy/clone for libipcc
10182
Ok(Arc::new(CertifiedKey::new(der_vec, Arc::new(IpccKey {}))))

0 commit comments

Comments
 (0)