Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade Rustls dependencies #615

Merged
merged 3 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading