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

Update rustls #153

Merged
merged 2 commits into from
Feb 15, 2024
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
4 changes: 2 additions & 2 deletions core/cert-manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ rand = "0.8.5"
random-manager = "0.0.5" # https://crates.io/crates/random-manager/versions
rcgen = { version = "0.12.1", features = ["pem", "x509-parser"] }
rsa = { version = "0.9.2", features = ["pem"] } # https://crates.io/crates/rsa
rustls = "0.21.8"
rustls-pemfile = "1.0.3"
rustls = "0.22.2"
rustls-pemfile = "2.0.0"
x509-parser = "0.15.1"

[dev-dependencies]
Expand Down
73 changes: 44 additions & 29 deletions core/cert-manager/src/x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ use rcgen::{
use rsa::{pkcs1::LineEnding, pkcs8::EncodePrivateKey, RsaPrivateKey};
use rustls_pemfile::{read_one, Item};

type PrivateKeyDer = rustls::pki_types::PrivateKeyDer<'static>;
type CertificateDer = rustls::pki_types::CertificateDer<'static>;

/// Represents a certificate authoriry.
/// CA acts as a trusted third party.
/// ref. <https://en.wikipedia.org/wiki/Certificate_authority>
Expand Down Expand Up @@ -651,7 +654,7 @@ fn test_pem() {
pub fn load_pem_key_cert_to_der(
key_path: &str,
cert_path: &str,
) -> io::Result<(rustls::PrivateKey, rustls::Certificate)> {
) -> io::Result<(PrivateKeyDer, CertificateDer)> {
log::info!("loading PEM from key path '{key_path}' and cert '{cert_path}' (to DER)");
if !Path::new(key_path).exists() {
return Err(Error::new(
Expand Down Expand Up @@ -690,51 +693,57 @@ pub fn load_pem_key_cert_to_der(
log::warn!("key path {} has unexpected certificate", key_path);
None
}
Item::RSAKey(key) => {
log::info!("loaded RSA key");
Some(key)
Item::Crl(_) => {
log::warn!("key path {} has unexpected CRL", key_path);
None
}
Item::Pkcs1Key(key) => {
log::info!("loaded PKCS1 key");
Some(PrivateKeyDer::from(key))
}
Item::PKCS8Key(key) => {
Item::Pkcs8Key(key) => {
log::info!("loaded PKCS8 key");
Some(key)
Some(PrivateKeyDer::from(key))
}
Item::ECKey(key) => {
Item::Sec1Key(key) => {
log::info!("loaded EC key");
Some(key)
Some(PrivateKeyDer::from(key))
}
_ => None,
}
};
if key.is_none() {
let Some(key_der) = key else {
return Err(Error::new(
ErrorKind::NotFound,
format!("key path '{key_path}' found no key"),
));
}
let key_der = key.unwrap();
};

let cert_file = File::open(cert_path)?;
let mut reader = BufReader::new(cert_file);
let pem_read = read_one(&mut reader)?;
let cert = {
match pem_read.unwrap() {
Item::X509Certificate(cert) => Some(cert),
Item::RSAKey(_) | Item::PKCS8Key(_) | Item::ECKey(_) => {
Item::Pkcs1Key(_) | Item::Pkcs8Key(_) | Item::Sec1Key(_) => {
log::warn!("cert path '{cert_path}' has unexpected private key");
None
}
Item::Crl(_) => {
log::warn!("cert path '{cert_path}' has unexpected CRL");
None
}
_ => None,
}
};
if cert.is_none() {
let Some(cert_der) = cert else {
return Err(Error::new(
ErrorKind::NotFound,
format!("cert path '{cert_path}' found no cert"),
));
}
let cert_der = cert.unwrap();
};

Ok((rustls::PrivateKey(key_der), rustls::Certificate(cert_der)))
Ok((key_der, cert_der))
}

/// Loads the serial number from the PEM-encoded certificate.
Expand Down Expand Up @@ -763,7 +772,7 @@ pub fn load_pem_cert_serial(cert_path: &str) -> io::Result<Vec<u8>> {
}

/// Loads the PEM-encoded certificate as DER.
pub fn load_pem_cert_to_der(cert_path: &str) -> io::Result<rustls::Certificate> {
pub fn load_pem_cert_to_der(cert_path: &str) -> io::Result<CertificateDer> {
log::info!("loading PEM cert '{cert_path}' (to DER)");
if !Path::new(cert_path).exists() {
return Err(Error::new(
Expand All @@ -778,29 +787,33 @@ pub fn load_pem_cert_to_der(cert_path: &str) -> io::Result<rustls::Certificate>
let cert = {
match pem_read.unwrap() {
Item::X509Certificate(cert) => Some(cert),
Item::RSAKey(_) | Item::PKCS8Key(_) | Item::ECKey(_) => {
Item::Pkcs1Key(_) | Item::Pkcs8Key(_) | Item::Sec1Key(_) => {
log::warn!("cert path '{cert_path}' has unexpected private key");
None
}
Item::Crl(_) => {
log::warn!("cert path '{cert_path}' has unexpected CRL");
None
}
_ => None,
}
};
if cert.is_none() {

let Some(cert_der) = cert else {
return Err(Error::new(
ErrorKind::NotFound,
format!("cert path '{cert_path}' found no cert"),
));
}
let cert_der = cert.unwrap();
};

Ok(rustls::Certificate(cert_der))
Ok(cert_der)
}

/// Generates a X509 certificate pair and returns them in DER format.
/// ref. <https://pkg.go.dev/github.com/ava-labs/avalanchego/staking#NewCertAndKeyBytes>
pub fn generate_der(
params: Option<CertificateParams>,
) -> io::Result<(rustls::PrivateKey, rustls::Certificate)> {
) -> io::Result<(PrivateKeyDer, CertificateDer)> {
log::info!("generating key and cert (DER format)");

let cert_params = if let Some(p) = params {
Expand All @@ -820,18 +833,20 @@ pub fn generate_der(
// ref. "crypto/tls.parsePrivateKey"
// ref. "crypto/x509.MarshalPKCS8PrivateKey"
let key_der = cert.serialize_private_key_der();
let key_der = rustls::pki_types::PrivatePkcs8KeyDer::from(key_der);
let key_der = key_der.into();
let cert_der = CertificateDer::from(cert_der);

Ok((rustls::PrivateKey(key_der), rustls::Certificate(cert_der)))
Ok((key_der, cert_der))
}

/// Loads the TLS key and certificate from the DER-encoded files.
pub fn load_der_key_cert(
key_path: &str,
cert_path: &str,
) -> io::Result<(rustls::PrivateKey, rustls::Certificate)> {
) -> io::Result<(PrivateKeyDer, CertificateDer)> {
log::info!("loading DER from key path '{key_path}' and cert '{cert_path}'");
let (key, cert) = fs::read(key_path).and_then(|x| Ok((x, fs::read(cert_path)?)))?;
Ok((rustls::PrivateKey(key), rustls::Certificate(cert)))
load_pem_key_cert_to_der(key_path, cert_path)
}

/// RUST_LOG=debug cargo test --all-features --lib -- x509::test_generate_der --exact --show-output
Expand All @@ -843,8 +858,8 @@ fn test_generate_der() {
.try_init();

let (key, cert) = generate_der(None).unwrap();
log::info!("key: {} bytes", key.0.len());
log::info!("cert: {} bytes", cert.0.len());
log::info!("key: {} bytes", key.secret_der().len());
log::info!("cert: {} bytes", cert.len());
}

/// ref. <https://doc.rust-lang.org/std/fs/fn.read.html>
Expand Down
6 changes: 3 additions & 3 deletions core/network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ readme = "README.md"
[dependencies]
avalanche-types = { path = "../../crates/avalanche-types", features = ["message"] }
log = "0.4.20"
rustls = { version = "0.21.5", features = ["logging", "dangerous_configuration"]} # https://github.com/rustls/rustls/tags
rustls = { version = "0.22.2", features = ["logging"] }
hyper-rustls = "0.26.0"
rustls-native-certs = "0.7.0"
hyper = { version = "0.14.27", features = ["full"], optional = true }
tokio-rustls = { version = "0.24.1", optional = true }
tokio-rustls = { version = "0.25.0", optional = true }
rand = "0.8.5"
random-manager = "0.0.5" # https://crates.io/crates/random-manager/versions
rcgen = { version = "0.12.1", features = ["pem", "x509-parser"] }
rsa = { version = "0.9.2", features = ["pem"] } # https://crates.io/crates/rsa
rustls-pemfile = "1.0.3"
rustls-pemfile = "2.0.0"
x509-parser = "0.15.1"
# for feature "pem"
pem = { version = "3.0.0", optional = true } # https://github.com/jcreekmore/pem-rs
Expand Down
1 change: 0 additions & 1 deletion core/network/src/peer/inbound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ impl Listener {
// ref. https://docs.rs/rustls/latest/rustls/struct.ConfigBuilder.html#method.with_single_cert
// ref. https://github.com/rustls/hyper-rustls/blob/main/examples/server.rs
let server_config = ServerConfig::builder()
.with_safe_defaults()
.with_client_cert_verifier(Arc::new(NoClientAuth))
.with_single_cert(vec![certificate], private_key)
.map_err(|e| {
Expand Down
1 change: 0 additions & 1 deletion core/network/src/peer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ mod test {

let join_handle = tokio::task::spawn(async move {
let server_config = ServerConfig::builder()
.with_safe_defaults()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://docs.rs/rustls/latest/src/rustls/server/server_conn.rs.html#349-354

Looks like "safe defaults" are automatically applied to the builder

.with_no_client_auth()
.with_single_cert(vec![certificate], private_key)
.unwrap();
Expand Down
Loading
Loading