Skip to content

Commit

Permalink
Upgrade Rustls dependencies (#615)
Browse files Browse the repository at this point in the history
  • Loading branch information
DariusIMP authored Dec 7, 2023
1 parent 3336af8 commit 78bff41
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 80 deletions.
17 changes: 15 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,9 @@ ringbuffer-spsc = "0.1.9"
rsa = "0.9"
rustc_version = "0.4.0"
rustls = { version = "0.21.5", features = ["dangerous_configuration"] }
rustls-native-certs = "0.6.2"
rustls-native-certs = "0.7.0"
rustls-pemfile = "2.0.0"
rustls-webpki = "0.102.0"
schemars = "0.8.12"
secrecy = {version = "0.8.0", features = ["serde", "alloc"]}
serde = { version = "1.0.154", default-features = false, features = [
Expand Down Expand Up @@ -154,7 +155,6 @@ uuid = { version = "1.3.0", default-features = false, features = [
] } # Default features are disabled due to usage in no_std crates
validated_struct = "2.1.0"
vec_map = "0.8.2"
rustls-webpki = "0.102.0"
webpki-roots = "0.26.0"
winapi = { version = "0.3.9", features = ["iphlpapi"] }
z-serial = "0.2.1"
Expand Down
58 changes: 34 additions & 24 deletions io/zenoh-links/zenoh-link-quic/src/unicast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ use async_std::sync::Mutex as AsyncMutex;
use async_std::task;
use async_std::task::JoinHandle;
use async_trait::async_trait;
use rustls::{Certificate, PrivateKey};
use rustls_pemfile::Item;
use std::collections::HashMap;
use std::fmt;
use std::io::BufReader;
Expand All @@ -35,7 +37,7 @@ use zenoh_link_commons::{
LinkManagerUnicastTrait, LinkUnicast, LinkUnicastTrait, NewLinkChannelSender,
};
use zenoh_protocol::core::{EndPoint, Locator};
use zenoh_result::{bail, zerror, ZResult};
use zenoh_result::{bail, zerror, ZError, ZResult};
use zenoh_sync::Signal;

pub struct LinkUnicastQuic {
Expand Down Expand Up @@ -261,14 +263,16 @@ impl LinkManagerUnicastTrait for LinkManagerUnicastQuic {
rustls_native_certs::load_native_certs()
.map_err(|e| zerror!("Invalid QUIC CA certificate file: {}", e))?
.drain(..)
.map(|x| rustls::Certificate(x.0))
.map(|x| rustls::Certificate(x.to_vec()))
.collect::<Vec<rustls::Certificate>>()
} else {
rustls_pemfile::certs(&mut BufReader::new(f.as_slice()))
.map_err(|e| zerror!("Invalid QUIC CA certificate file: {}", e))?
.drain(..)
.map(rustls::Certificate)
.collect::<Vec<rustls::Certificate>>()
.map(|result| {
result
.map_err(|err| zerror!("Invalid QUIC CA certificate file: {}", err))
.map(|der| Certificate(der.to_vec()))
})
.collect::<Result<Vec<rustls::Certificate>, ZError>>()?
};
for c in certificates.iter() {
root_cert_store.add(c).map_err(|e| zerror!("{}", e))?;
Expand Down Expand Up @@ -347,10 +351,12 @@ impl LinkManagerUnicastTrait for LinkManagerUnicastQuic {
bail!("No QUIC CA certificate has been provided.");
};
let certificates = rustls_pemfile::certs(&mut BufReader::new(f.as_slice()))
.map_err(|e| zerror!("Invalid QUIC CA certificate file: {}", e))?
.drain(..)
.map(rustls::Certificate)
.collect();
.map(|result| {
result
.map_err(|err| zerror!("Invalid QUIC CA certificate file: {}", err))
.map(|der| Certificate(der.to_vec()))
})
.collect::<Result<Vec<rustls::Certificate>, ZError>>()?;

// Private keys
let f = if let Some(value) = epconf.get(TLS_SERVER_PRIVATE_KEY_RAW) {
Expand All @@ -364,20 +370,24 @@ impl LinkManagerUnicastTrait for LinkManagerUnicastQuic {
} else {
bail!("No QUIC CA private key has been provided.");
};
let private_key = rustls::PrivateKey(
rustls_pemfile::read_all(&mut BufReader::new(f.as_slice()))
.map_err(|e| zerror!("Invalid QUIC CA private key file: {}", e))?
.iter()
.filter_map(|x| match x {
rustls_pemfile::Item::RSAKey(k)
| rustls_pemfile::Item::PKCS8Key(k)
| rustls_pemfile::Item::ECKey(k) => Some(k.to_vec()),
_ => None,
})
.take(1)
.next()
.ok_or_else(|| zerror!("No QUIC CA private key has been provided."))?,
);
let items: Vec<Item> = rustls_pemfile::read_all(&mut BufReader::new(f.as_slice()))
.map(|result| {
result.map_err(|err| zerror!("Invalid QUIC CA private key file: {}", err))
})
.collect::<Result<Vec<Item>, ZError>>()?;

let private_key = items
.into_iter()
.filter_map(|x| match x {
rustls_pemfile::Item::Pkcs1Key(k) => Some(k.secret_pkcs1_der().to_vec()),
rustls_pemfile::Item::Pkcs8Key(k) => Some(k.secret_pkcs8_der().to_vec()),
rustls_pemfile::Item::Sec1Key(k) => Some(k.secret_sec1_der().to_vec()),
_ => None,
})
.take(1)
.next()
.ok_or_else(|| zerror!("No QUIC CA private key has been provided."))
.map(PrivateKey)?;

// Server config
let mut server_crypto = rustls::ServerConfig::builder()
Expand Down
151 changes: 99 additions & 52 deletions io/zenoh-links/zenoh-link-tls/src/unicast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ use async_std::task::JoinHandle;
use async_trait::async_trait;
use futures::io::AsyncReadExt;
use futures::io::AsyncWriteExt;
use std::cell::UnsafeCell;
use std::collections::HashMap;
use std::convert::TryInto;
use std::fmt;
Expand All @@ -42,14 +41,18 @@ use std::net::{IpAddr, Shutdown};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, RwLock};
use std::time::Duration;
use webpki::TrustAnchor;
use std::{cell::UnsafeCell, io};
use webpki::{
anchor_from_trusted_cert,
types::{CertificateDer, TrustAnchor},
};
use zenoh_core::{zasynclock, zread, zwrite};
use zenoh_link_commons::{
LinkManagerUnicastTrait, LinkUnicast, LinkUnicastTrait, NewLinkChannelSender,
};
use zenoh_protocol::core::endpoint::Config;
use zenoh_protocol::core::{EndPoint, Locator};
use zenoh_result::{bail, zerror, ZResult};
use zenoh_result::{bail, zerror, ZError, ZResult};
use zenoh_sync::Signal;

pub struct LinkUnicastTls {
Expand Down Expand Up @@ -525,32 +528,48 @@ impl TlsServerConfig {
let tls_server_private_key = TlsServerConfig::load_tls_private_key(config).await?;
let tls_server_certificate = TlsServerConfig::load_tls_certificate(config).await?;

let certs: Vec<Certificate> =
rustls_pemfile::certs(&mut Cursor::new(&tls_server_certificate))
.map(|result| {
result
.map_err(|err| zerror!("Error processing server certificate: {err}."))
.map(|der| Certificate(der.to_vec()))
})
.collect::<Result<Vec<Certificate>, ZError>>()?;

let mut keys: Vec<PrivateKey> =
rustls_pemfile::rsa_private_keys(&mut Cursor::new(&tls_server_private_key))
.map_err(|e| zerror!(e))
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())?;
.map(|result| {
result
.map_err(|err| zerror!("Error processing server key: {err}."))
.map(|key| PrivateKey(key.secret_pkcs1_der().to_vec()))
})
.collect::<Result<Vec<PrivateKey>, ZError>>()?;

if keys.is_empty() {
keys = rustls_pemfile::pkcs8_private_keys(&mut Cursor::new(&tls_server_private_key))
.map_err(|e| zerror!(e))
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())?;
.map(|result| {
result
.map_err(|err| zerror!("Error processing server key: {err}."))
.map(|key| PrivateKey(key.secret_pkcs8_der().to_vec()))
})
.collect::<Result<Vec<PrivateKey>, ZError>>()?;
}

if keys.is_empty() {
keys = rustls_pemfile::ec_private_keys(&mut Cursor::new(&tls_server_private_key))
.map_err(|e| zerror!(e))
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())?;
.map(|result| {
result
.map_err(|err| zerror!("Error processing server key: {err}."))
.map(|key| PrivateKey(key.secret_sec1_der().to_vec()))
})
.collect::<Result<Vec<PrivateKey>, ZError>>()?;
}

if keys.is_empty() {
bail!("No private key found");
bail!("No private key found for TLS server.");
}

let certs: Vec<Certificate> =
rustls_pemfile::certs(&mut Cursor::new(&tls_server_certificate))
.map_err(|e| zerror!(e))
.map(|mut certs| certs.drain(..).map(Certificate).collect())?;

let sc = if tls_server_client_auth {
let root_cert_store = load_trust_anchors(config)?.map_or_else(
|| {
Expand Down Expand Up @@ -643,23 +662,45 @@ impl TlsClientConfig {

let certs: Vec<Certificate> =
rustls_pemfile::certs(&mut Cursor::new(&tls_client_certificate))
.map_err(|e| zerror!(e))
.map(|mut certs| certs.drain(..).map(Certificate).collect())?;
.map(|result| {
result
.map_err(|err| zerror!("Error processing client certificate: {err}."))
.map(|der| Certificate(der.to_vec()))
})
.collect::<Result<Vec<Certificate>, ZError>>()?;

let mut keys: Vec<PrivateKey> =
rustls_pemfile::rsa_private_keys(&mut Cursor::new(&tls_client_private_key))
.map_err(|e| zerror!(e))
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())?;
.map(|result| {
result
.map_err(|err| zerror!("Error processing client key: {err}."))
.map(|key| PrivateKey(key.secret_pkcs1_der().to_vec()))
})
.collect::<Result<Vec<PrivateKey>, ZError>>()?;

if keys.is_empty() {
keys =
rustls_pemfile::pkcs8_private_keys(&mut Cursor::new(&tls_client_private_key))
.map_err(|e| zerror!(e))
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())?;
.map(|result| {
result
.map_err(|err| zerror!("Error processing client key: {err}."))
.map(|key| PrivateKey(key.secret_pkcs8_der().to_vec()))
})
.collect::<Result<Vec<PrivateKey>, ZError>>()?;
}

if keys.is_empty() {
bail!("No private key found");
keys = rustls_pemfile::ec_private_keys(&mut Cursor::new(&tls_client_private_key))
.map(|result| {
result
.map_err(|err| zerror!("Error processing client key: {err}."))
.map(|key| PrivateKey(key.secret_sec1_der().to_vec()))
})
.collect::<Result<Vec<PrivateKey>, ZError>>()?;
}

if keys.is_empty() {
bail!("No private key found for TLS client.");
}

let builder = ClientConfig::builder()
Expand Down Expand Up @@ -765,57 +806,63 @@ fn load_trust_anchors(config: &Config<'_>) -> ZResult<Option<RootCertStore>> {
let mut root_cert_store = RootCertStore::empty();
if let Some(value) = config.get(TLS_ROOT_CA_CERTIFICATE_RAW) {
let mut pem = BufReader::new(value.as_bytes());
let certs = rustls_pemfile::certs(&mut pem)?;
let trust_anchors = certs.iter().map(|cert| {
let ta = TrustAnchor::try_from_cert_der(&cert[..]).unwrap();
OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
});
let trust_anchors = process_pem(&mut pem)?;
root_cert_store.add_trust_anchors(trust_anchors.into_iter());
return Ok(Some(root_cert_store));
}

if let Some(b64_certificate) = config.get(TLS_ROOT_CA_CERTIFICATE_BASE64) {
let certificate_pem = base64_decode(b64_certificate)?;
let mut pem = BufReader::new(certificate_pem.as_slice());
let certs = rustls_pemfile::certs(&mut pem)?;
let trust_anchors = certs.iter().map(|cert| {
let ta = TrustAnchor::try_from_cert_der(&cert[..]).unwrap();
OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
});
let trust_anchors = process_pem(&mut pem)?;
root_cert_store.add_trust_anchors(trust_anchors.into_iter());
return Ok(Some(root_cert_store));
}

if let Some(filename) = config.get(TLS_ROOT_CA_CERTIFICATE_FILE) {
let mut pem = BufReader::new(File::open(filename)?);
let certs = rustls_pemfile::certs(&mut pem)?;
let trust_anchors = certs.iter().map(|cert| {
let ta = TrustAnchor::try_from_cert_der(&cert[..]).unwrap();
OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
});
let trust_anchors = process_pem(&mut pem)?;
root_cert_store.add_trust_anchors(trust_anchors.into_iter());
return Ok(Some(root_cert_store));
}
Ok(None)
}

fn process_pem(pem: &mut dyn io::BufRead) -> ZResult<Vec<OwnedTrustAnchor>> {
let certs: Vec<CertificateDer> = rustls_pemfile::certs(pem)
.map(|result| result.map_err(|err| zerror!("Error processing PEM certificates: {err}.")))
.collect::<Result<Vec<CertificateDer>, ZError>>()?;

let trust_anchors: Vec<TrustAnchor> = certs
.into_iter()
.map(|cert| {
anchor_from_trusted_cert(&cert)
.map_err(|err| zerror!("Error processing trust anchor: {err}."))
.map(|trust_anchor| trust_anchor.to_owned())
})
.collect::<Result<Vec<TrustAnchor>, ZError>>()?;

let owned_trust_anchors: Vec<OwnedTrustAnchor> = trust_anchors
.into_iter()
.map(|ta| {
OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject.to_vec(),
ta.subject_public_key_info.to_vec(),
ta.name_constraints.map(|x| x.to_vec()),
)
})
.collect();

Ok(owned_trust_anchors)
}

fn load_default_webpki_certs() -> RootCertStore {
let mut root_cert_store = RootCertStore::empty();
root_cert_store.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| {
OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
ta.subject.to_vec(),
ta.subject_public_key_info.to_vec(),
ta.name_constraints.clone().map(|x| x.to_vec()),
)
}));
root_cert_store
Expand Down

0 comments on commit 78bff41

Please sign in to comment.