From b67bc14f824d9bbcd98cab4c994f4e38b9381c87 Mon Sep 17 00:00:00 2001 From: Yuxiang Cao Date: Fri, 3 Nov 2023 18:15:31 -0700 Subject: [PATCH 1/6] feat: update pki to use newer rustls --- Cargo.lock | 41 ++------- rustls-mbedpki-provider/Cargo.toml | 3 +- .../src/client_cert_verifier.rs | 72 ++++++++++----- rustls-mbedpki-provider/src/lib.rs | 25 ++++-- .../src/server_cert_verifier.rs | 88 +++++++++++-------- rustls-mbedpki-provider/src/tests_common.rs | 47 +++++----- 6 files changed, 146 insertions(+), 130 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e8e857d..7e1e6cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -636,18 +636,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "rustls" -version = "0.21.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" -dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - [[package]] name = "rustls" version = "0.22.0-alpha.4" @@ -656,7 +644,7 @@ dependencies = [ "log", "ring", "rustls-pki-types", - "rustls-webpki 0.102.0-alpha.6", + "rustls-webpki", "subtle", "zeroize", ] @@ -668,10 +656,10 @@ dependencies = [ "env_logger", "log", "mbedtls", - "rustls 0.22.0-alpha.4", + "rustls", "rustls-pemfile 2.0.0-alpha.1", "rustls-pki-types", - "rustls-webpki 0.102.0-alpha.6", + "rustls-webpki", "webpki-roots", ] @@ -681,8 +669,9 @@ version = "0.1.0" dependencies = [ "chrono", "mbedtls", - "rustls 0.21.8", + "rustls", "rustls-pemfile 1.0.3", + "rustls-pki-types", "x509-parser", ] @@ -711,16 +700,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a47003264dea418db67060fa420ad16d0d2f8f0a0360d825c00e177ac52cb5d8" -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "rustls-webpki" version = "0.102.0-alpha.6" @@ -732,16 +711,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "serde" version = "1.0.190" diff --git a/rustls-mbedpki-provider/Cargo.toml b/rustls-mbedpki-provider/Cargo.toml index 978e332..a351b81 100644 --- a/rustls-mbedpki-provider/Cargo.toml +++ b/rustls-mbedpki-provider/Cargo.toml @@ -11,7 +11,7 @@ categories = ["network-programming", "cryptography"] resolver = "2" [dependencies] -rustls = { version = "0.21", features = ["dangerous_configuration"] } +rustls = { git = "https://github.com/rustls/rustls", rev = "b776a5778ad333653670c34ff9125d8ae59b6047", version = "0.22.0-alpha.4" } mbedtls = { version = "0.12.0-alpha.2", features = [ "x509", "chrono", @@ -20,6 +20,7 @@ mbedtls = { version = "0.12.0-alpha.2", features = [ x509-parser = "0.15" chrono = "0.4" +pki-types = { package = "rustls-pki-types", version = "0.2.1", features = ["std"] } [target.'cfg(target_env = "msvc")'.dependencies] # mbedtls need feature `time` to build when targeting msvc diff --git a/rustls-mbedpki-provider/src/client_cert_verifier.rs b/rustls-mbedpki-provider/src/client_cert_verifier.rs index 205722e..a67ef38 100644 --- a/rustls-mbedpki-provider/src/client_cert_verifier.rs +++ b/rustls-mbedpki-provider/src/client_cert_verifier.rs @@ -5,10 +5,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use std::time::SystemTime; - +use chrono::NaiveDateTime; +use pki_types::{CertificateDer, UnixTime}; use rustls::{ - server::{ClientCertVerified, ClientCertVerifier}, + server::danger::{ClientCertVerified, ClientCertVerifier}, DistinguishedName, }; @@ -30,7 +30,7 @@ impl MbedTlsClientCertVerifier { /// certificates. /// /// Returns an error if any of the certificates are invalid. - pub fn new<'a>(trusted_cas: impl IntoIterator) -> mbedtls::Result { + pub fn new<'a>(trusted_cas: impl IntoIterator>) -> mbedtls::Result { let trusted_cas = trusted_cas .into_iter() .map(rustls_cert_to_mbedtls_cert) @@ -65,17 +65,23 @@ impl MbedTlsClientCertVerifier { } impl ClientCertVerifier for MbedTlsClientCertVerifier { - fn client_auth_root_subjects(&self) -> &[DistinguishedName] { + fn root_hint_subjects(&self) -> &[DistinguishedName] { &self.root_subjects } fn verify_client_cert( &self, - end_entity: &rustls::Certificate, - intermediates: &[rustls::Certificate], - now: SystemTime, - ) -> Result { - let now = chrono::DateTime::::from(now).naive_local(); + end_entity: &CertificateDer, + intermediates: &[CertificateDer], + now: UnixTime, + ) -> Result { + let now = NaiveDateTime::from_timestamp_opt( + now.as_secs() + .try_into() + .map_err(|_| rustls::Error::General(String::from("Invalid current unix timestamp")))?, + 0, + ) + .ok_or(rustls::Error::General(String::from("Invalid current unix timestamp")))?; let chain: mbedtls::alloc::List<_> = [end_entity] .into_iter() @@ -98,20 +104,24 @@ impl ClientCertVerifier for MbedTlsClientCertVerifier { fn verify_tls12_signature( &self, message: &[u8], - cert: &rustls::Certificate, + cert: &CertificateDer, dss: &rustls::DigitallySignedStruct, - ) -> Result { + ) -> Result { verify_tls_signature(message, cert, dss, false) } fn verify_tls13_signature( &self, message: &[u8], - cert: &rustls::Certificate, + cert: &CertificateDer, dss: &rustls::DigitallySignedStruct, - ) -> Result { + ) -> Result { verify_tls_signature(message, cert, dss, true) } + + fn supported_verify_schemes(&self) -> Vec { + crate::SUPPORTED_SIGNATURE_SCHEMA.to_vec() + } } // ../test-data/rsa/client.fullchain has these three certificates: @@ -122,8 +132,10 @@ impl ClientCertVerifier for MbedTlsClientCertVerifier { mod tests { use chrono::DateTime; + use pki_types::{CertificateDer, UnixTime}; use rustls::{ - server::ClientCertVerifier, Certificate, ClientConfig, ClientConnection, RootCertStore, ServerConfig, ServerConnection, + server::danger::ClientCertVerifier, CertificateError, ClientConfig, ClientConnection, RootCertStore, ServerConfig, + ServerConnection, }; use std::{sync::Arc, time::SystemTime}; @@ -144,9 +156,9 @@ mod tests { #[test] fn connection_client_cert_verifier() { let client_config = ClientConfig::builder().with_safe_defaults(); - let root_ca = Certificate(include_bytes!("../test-data/rsa/ca.der").to_vec()); + let root_ca = CertificateDer::from(include_bytes!("../test-data/rsa/ca.der").to_vec()); let mut root_store = RootCertStore::empty(); - root_store.add(&root_ca).unwrap(); + root_store.add(root_ca.clone()).unwrap(); let cert_chain = get_chain(include_bytes!("../test-data/rsa/client.fullchain")); let client_config = client_config @@ -164,11 +176,11 @@ mod tests { assert!(do_handshake_until_error(&mut client_conn, &mut server_conn).is_ok()); } - fn test_connection_client_cert_verifier_with_invalid_certs(invalid_cert_chain: Vec) { + fn test_connection_client_cert_verifier_with_invalid_certs(invalid_cert_chain: Vec>) { let client_config = ClientConfig::builder().with_safe_defaults(); - let root_ca = Certificate(include_bytes!("../test-data/rsa/ca.der").to_vec()); + let root_ca = CertificateDer::from(include_bytes!("../test-data/rsa/ca.der").to_vec()); let mut root_store = RootCertStore::empty(); - root_store.add(&root_ca).unwrap(); + root_store.add(root_ca.clone()).unwrap(); let client_config = client_config .with_root_certificates(root_store) @@ -207,11 +219,15 @@ mod tests { #[test] fn client_cert_verifier_valid_chain() { let cert_chain = get_chain(include_bytes!("../test-data/rsa/client.fullchain")); - let trusted_cas = [Certificate(include_bytes!("../test-data/rsa/ca.der").to_vec())]; + let trusted_cas = [CertificateDer::from(include_bytes!("../test-data/rsa/ca.der").to_vec())]; let verifier = MbedTlsClientCertVerifier::new(trusted_cas.iter()).unwrap(); let now = SystemTime::from(chrono::DateTime::parse_from_rfc3339("2023-11-26T12:00:00+00:00").unwrap()); + let now = UnixTime::since_unix_epoch( + now.duration_since(SystemTime::UNIX_EPOCH) + .unwrap(), + ); assert!(verifier .verify_client_cert(&cert_chain[0], &cert_chain[1..], now) @@ -222,11 +238,15 @@ mod tests { fn client_cert_verifier_broken_chain() { let mut cert_chain = get_chain(include_bytes!("../test-data/rsa/client.fullchain")); cert_chain.remove(1); - let trusted_cas = [Certificate(include_bytes!("../test-data/rsa/ca.der").to_vec())]; + let trusted_cas = [CertificateDer::from(include_bytes!("../test-data/rsa/ca.der").to_vec())]; let verifier = MbedTlsClientCertVerifier::new(trusted_cas.iter()).unwrap(); let now = SystemTime::from(DateTime::parse_from_rfc3339("2023-11-26T12:00:00+00:00").unwrap()); + let now = UnixTime::since_unix_epoch( + now.duration_since(SystemTime::UNIX_EPOCH) + .unwrap(), + ); let verify_res = verifier.verify_client_cert(&cert_chain[0], &cert_chain[1..], now); assert!(matches!(verify_res, Err(rustls::Error::InvalidCertificate(_)))); @@ -235,17 +255,21 @@ mod tests { #[test] fn client_cert_verifier_expired_certs() { let cert_chain = get_chain(include_bytes!("../test-data/rsa/client.fullchain")); - let trusted_cas = [Certificate(include_bytes!("../test-data/rsa/ca.der").to_vec())]; + let trusted_cas = [CertificateDer::from(include_bytes!("../test-data/rsa/ca.der").to_vec())]; let verifier = MbedTlsClientCertVerifier::new(trusted_cas.iter()).unwrap(); let now = SystemTime::from(DateTime::parse_from_rfc3339("2052-11-26T12:00:00+00:00").unwrap()); + let now = UnixTime::since_unix_epoch( + now.duration_since(SystemTime::UNIX_EPOCH) + .unwrap(), + ); assert_eq!( verifier .verify_client_cert(&cert_chain[0], &cert_chain[1..], now) .unwrap_err(), - rustls::Error::InvalidCertificate(rustls::CertificateError::Expired) + rustls::Error::InvalidCertificate(CertificateError::Expired) ); } } diff --git a/rustls-mbedpki-provider/src/lib.rs b/rustls-mbedpki-provider/src/lib.rs index d5aa91e..649ef69 100644 --- a/rustls-mbedpki-provider/src/lib.rs +++ b/rustls-mbedpki-provider/src/lib.rs @@ -7,6 +7,7 @@ use chrono::NaiveDateTime; use mbedtls::hash::Type; +use pki_types::CertificateDer; use rustls::SignatureScheme; use std::sync::Arc; @@ -19,10 +20,8 @@ pub mod server_cert_verifier; pub use client_cert_verifier::MbedTlsClientCertVerifier; pub use server_cert_verifier::MbedTlsServerCertVerifier; -pub fn rustls_cert_to_mbedtls_cert( - cert: &rustls::Certificate, -) -> mbedtls::Result> { - let cert = mbedtls::x509::Certificate::from_der(&cert.0)?; +pub fn rustls_cert_to_mbedtls_cert(cert: &CertificateDer) -> mbedtls::Result> { + let cert = mbedtls::x509::Certificate::from_der(cert)?; Ok(cert) } @@ -31,6 +30,18 @@ pub fn mbedtls_err_into_rustls_err(err: mbedtls::Error) -> rustls::Error { mbedtls_err_into_rustls_err_with_error_msg(err, "") } +pub const SUPPORTED_SIGNATURE_SCHEMA: [SignatureScheme; 9] = [ + rustls::SignatureScheme::RSA_PSS_SHA512, + rustls::SignatureScheme::RSA_PSS_SHA384, + rustls::SignatureScheme::RSA_PSS_SHA256, + rustls::SignatureScheme::RSA_PKCS1_SHA512, + rustls::SignatureScheme::RSA_PKCS1_SHA384, + rustls::SignatureScheme::RSA_PKCS1_SHA256, + rustls::SignatureScheme::RSA_PSS_SHA512, + rustls::SignatureScheme::RSA_PSS_SHA384, + rustls::SignatureScheme::RSA_PSS_SHA256, +]; + /// Converts an `mbedtls::Error` into a `rustls::Error`; may include the provided `msg` in the /// returned error (e.g., if returning a `rustls::Error::General` error). pub fn mbedtls_err_into_rustls_err_with_error_msg(err: mbedtls::Error, msg: &str) -> rustls::Error { @@ -185,10 +196,10 @@ fn verify_certificates_active<'a>( /// `ServerCertVerifier` fn verify_tls_signature( message: &[u8], - cert: &rustls::Certificate, + cert: &CertificateDer, dss: &rustls::DigitallySignedStruct, is_tls13: bool, -) -> Result { +) -> Result { let mut cert = rustls_cert_to_mbedtls_cert(cert).map_err(mbedtls_err_into_rustls_err)?; let pk = cert.public_key_mut(); let hash_type = rustls_signature_scheme_to_mbedtls_hash_type(dss.scheme); @@ -220,5 +231,5 @@ fn verify_tls_signature( pk.verify(hash_type, &hash[..hash_size], dss.signature()) .map_err(mbedtls_err_into_rustls_err)?; - Ok(rustls::client::HandshakeSignatureValid::assertion()) + Ok(rustls::client::danger::HandshakeSignatureValid::assertion()) } diff --git a/rustls-mbedpki-provider/src/server_cert_verifier.rs b/rustls-mbedpki-provider/src/server_cert_verifier.rs index 01ed2fd..698ee1c 100644 --- a/rustls-mbedpki-provider/src/server_cert_verifier.rs +++ b/rustls-mbedpki-provider/src/server_cert_verifier.rs @@ -5,8 +5,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use chrono::NaiveDateTime; +use pki_types::{CertificateDer, UnixTime}; use rustls::{ - client::{ServerCertVerified, ServerCertVerifier}, + client::danger::{ServerCertVerified, ServerCertVerifier}, ServerName, }; @@ -26,7 +28,7 @@ impl MbedTlsServerCertVerifier { /// certificates. /// /// Returns an error if any of the certificates are invalid. - pub fn new<'a>(trusted_cas: impl IntoIterator) -> mbedtls::Result { + pub fn new<'a>(trusted_cas: impl IntoIterator>) -> mbedtls::Result { let trusted_cas = trusted_cas .into_iter() .map(rustls_cert_to_mbedtls_cert) @@ -68,16 +70,20 @@ fn server_name_to_str(server_name: &rustls::ServerName) -> String { impl ServerCertVerifier for MbedTlsServerCertVerifier { fn verify_server_cert( &self, - end_entity: &rustls::Certificate, - intermediates: &[rustls::Certificate], + end_entity: &CertificateDer, + intermediates: &[CertificateDer], server_name: &rustls::ServerName, - // Signed certificate timestamps are experimental, https://datatracker.ietf.org/doc/html/rfc6962 - _scts: &mut dyn Iterator, // Mbedtls does not support OSCP (Online Certificate Status Protocol). _ocsp_response: &[u8], - now: std::time::SystemTime, - ) -> Result { - let now = chrono::DateTime::::from(now).naive_local(); + now: UnixTime, + ) -> Result { + let now = NaiveDateTime::from_timestamp_opt( + now.as_secs() + .try_into() + .map_err(|_| rustls::Error::General(String::from("Invalid current unix timestamp")))?, + 0, + ) + .ok_or(rustls::Error::General(String::from("Invalid current unix timestamp")))?; let chain: mbedtls::alloc::List<_> = [end_entity] .into_iter() @@ -104,28 +110,27 @@ impl ServerCertVerifier for MbedTlsServerCertVerifier { Ok(ServerCertVerified::assertion()) } - fn request_scts(&self) -> bool { - // Signed certificate timestamps are experimental, https://datatracker.ietf.org/doc/html/rfc6962 - false - } - fn verify_tls12_signature( &self, message: &[u8], - cert: &rustls::Certificate, + cert: &CertificateDer, dss: &rustls::DigitallySignedStruct, - ) -> Result { + ) -> Result { verify_tls_signature(message, cert, dss, false) } fn verify_tls13_signature( &self, message: &[u8], - cert: &rustls::Certificate, + cert: &CertificateDer, dss: &rustls::DigitallySignedStruct, - ) -> Result { + ) -> Result { verify_tls_signature(message, cert, dss, true) } + + fn supported_verify_schemes(&self) -> Vec { + crate::SUPPORTED_SIGNATURE_SCHEMA.to_vec() + } } // ../test-data/rsa/end.fullchain has these three certificates: @@ -136,10 +141,11 @@ impl ServerCertVerifier for MbedTlsServerCertVerifier { mod tests { use std::{sync::Arc, time::SystemTime}; + use pki_types::{CertificateDer, UnixTime}; use rustls::{ - client::ServerCertVerifier, + client::danger::ServerCertVerifier, version::{TLS12, TLS13}, - Certificate, ClientConfig, ClientConnection, RootCertStore, ServerConfig, ServerConnection, SignatureScheme, + ClientConfig, ClientConnection, RootCertStore, ServerConfig, ServerConnection, SignatureScheme, SupportedProtocolVersion, }; @@ -153,14 +159,17 @@ mod tests { .with_safe_default_kx_groups() .with_safe_default_protocol_versions() .unwrap() + .dangerous() .with_custom_certificate_verifier(Arc::new(server_cert_verifier)) .with_no_client_auth() } - fn test_connection_server_cert_verifier_with_invalid_certs(invalid_cert_chain: Vec) -> rustls::Error { - let root_ca = Certificate(include_bytes!("../test-data/rsa/ca.der").to_vec()); + fn test_connection_server_cert_verifier_with_invalid_certs( + invalid_cert_chain: Vec>, + ) -> rustls::Error { + let root_ca = CertificateDer::from(include_bytes!("../test-data/rsa/ca.der").to_vec()); let mut root_store = RootCertStore::empty(); - root_store.add(&root_ca).unwrap(); + root_store.add(root_ca.clone()).unwrap(); let client_config = client_config_with_verifier(MbedTlsServerCertVerifier::new(&[root_ca]).unwrap()); let server_config = ServerConfig::builder() @@ -181,9 +190,9 @@ mod tests { supported_verify_schemes: Vec, protocol_versions: &[&'static SupportedProtocolVersion], ) { - let root_ca = Certificate(include_bytes!("../test-data/rsa/ca.der").to_vec()); + let root_ca = CertificateDer::from(include_bytes!("../test-data/rsa/ca.der").to_vec()); let mut root_store = RootCertStore::empty(); - root_store.add(&root_ca).unwrap(); + root_store.add(root_ca.clone()).unwrap(); let cert_chain = get_chain(include_bytes!("../test-data/rsa/end.fullchain")); let verifier = VerifierWithSupportedVerifySchemes { @@ -247,41 +256,50 @@ mod tests { #[test] fn server_cert_verifier_valid_chain() { let cert_chain = get_chain(include_bytes!("../test-data/rsa/end.fullchain")); - let trusted_cas = [Certificate(include_bytes!("../test-data/rsa/ca.der").to_vec())]; + let trusted_cas = [CertificateDer::from(include_bytes!("../test-data/rsa/ca.der").to_vec())]; let verifier = MbedTlsServerCertVerifier::new(trusted_cas.iter()).unwrap(); let server_name = "testserver.com".try_into().unwrap(); let now = SystemTime::from(chrono::DateTime::parse_from_rfc3339("2023-11-26T12:00:00+00:00").unwrap()); - let verify_res = - verifier.verify_server_cert(&cert_chain[0], &cert_chain[1..], &server_name, &mut [].into_iter(), &[], now); + let now = UnixTime::since_unix_epoch( + now.duration_since(SystemTime::UNIX_EPOCH) + .unwrap(), + ); + let verify_res = verifier.verify_server_cert(&cert_chain[0], &cert_chain[1..], &server_name, &[], now); assert!(verify_res.is_ok()); } #[test] fn server_cert_verifier_wrong_subject_name() { let cert_chain = get_chain(include_bytes!("../test-data/rsa/end.fullchain")); - let trusted_cas = [Certificate(include_bytes!("../test-data/rsa/ca.der").to_vec())]; + let trusted_cas = [CertificateDer::from(include_bytes!("../test-data/rsa/ca.der").to_vec())]; let verifier = MbedTlsServerCertVerifier::new(trusted_cas.iter()).unwrap(); let server_name = "testserver.com.eu".try_into().unwrap(); let now = SystemTime::from(chrono::DateTime::parse_from_rfc3339("2023-11-26T12:00:00+00:00").unwrap()); - let verify_res = - verifier.verify_server_cert(&cert_chain[0], &cert_chain[1..], &server_name, &mut [].into_iter(), &[], now); + let now = UnixTime::since_unix_epoch( + now.duration_since(SystemTime::UNIX_EPOCH) + .unwrap(), + ); + let verify_res = verifier.verify_server_cert(&cert_chain[0], &cert_chain[1..], &server_name, &[], now); println!("verify res: {:?}", verify_res); assert!(matches!(verify_res, Err(rustls::Error::InvalidCertificate(_)))); } - fn test_server_cert_verifier_invalid_chain(cert_chain: &[Certificate]) { - let trusted_cas = [Certificate(include_bytes!("../test-data/rsa/ca.der").to_vec())]; + fn test_server_cert_verifier_invalid_chain(cert_chain: &[CertificateDer]) { + let trusted_cas = [CertificateDer::from(include_bytes!("../test-data/rsa/ca.der").to_vec())]; let verifier = MbedTlsServerCertVerifier::new(trusted_cas.iter()).unwrap(); let server_name = "testserver.com".try_into().unwrap(); let now = SystemTime::from(chrono::DateTime::parse_from_rfc3339("2023-11-26T12:00:00+00:00").unwrap()); - let verify_res = - verifier.verify_server_cert(&cert_chain[0], &cert_chain[1..], &server_name, &mut [].into_iter(), &[], now); + let now = UnixTime::since_unix_epoch( + now.duration_since(SystemTime::UNIX_EPOCH) + .unwrap(), + ); + let verify_res = verifier.verify_server_cert(&cert_chain[0], &cert_chain[1..], &server_name, &[], now); assert!(matches!(verify_res, Err(rustls::Error::InvalidCertificate(_)))); } diff --git a/rustls-mbedpki-provider/src/tests_common.rs b/rustls-mbedpki-provider/src/tests_common.rs index bd47613..402d3bc 100644 --- a/rustls-mbedpki-provider/src/tests_common.rs +++ b/rustls-mbedpki-provider/src/tests_common.rs @@ -10,28 +10,26 @@ use std::{ ops::{Deref, DerefMut}, }; -use rustls::{ - client::ServerCertVerifier, Certificate, ClientConnection, ConnectionCommon, PrivateKey, ServerConnection, SideData, -}; +use pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer, UnixTime}; +use rustls::{client::danger::ServerCertVerifier, ClientConnection, ConnectionCommon, ServerConnection, SideData}; /// Get a certificate chain from the contents of a pem file -pub fn get_chain(bytes: &[u8]) -> Vec { +pub fn get_chain(bytes: &[u8]) -> Vec { rustls_pemfile::certs(&mut io::BufReader::new(bytes)) .unwrap() .into_iter() - .map(Certificate) + .map(CertificateDer::from) .collect() } /// Get a private key from the contents of a pem file -pub fn get_key(bytes: &[u8]) -> PrivateKey { - PrivateKey( - rustls_pemfile::pkcs8_private_keys(&mut io::BufReader::new(bytes)) - .unwrap() - .into_iter() - .next() - .unwrap(), - ) +pub fn get_key(bytes: &[u8]) -> PrivateKeyDer { + let value = rustls_pemfile::pkcs8_private_keys(&mut io::BufReader::new(bytes)) + .unwrap() + .into_iter() + .next() + .unwrap(); + PrivateKeyDer::from(PrivatePkcs8KeyDer::from(value)) } // Copied from rustls repo @@ -84,23 +82,22 @@ pub struct VerifierWithSupportedVerifySchemes { impl ServerCertVerifier for VerifierWithSupportedVerifySchemes { fn verify_server_cert( &self, - end_entity: &Certificate, - intermediates: &[Certificate], + end_entity: &CertificateDer, + intermediates: &[CertificateDer], server_name: &rustls::ServerName, - scts: &mut dyn Iterator, ocsp_response: &[u8], - now: std::time::SystemTime, - ) -> Result { + now: UnixTime, + ) -> Result { self.verifier - .verify_server_cert(end_entity, intermediates, server_name, scts, ocsp_response, now) + .verify_server_cert(end_entity, intermediates, server_name, ocsp_response, now) } fn verify_tls12_signature( &self, message: &[u8], - cert: &Certificate, + cert: &CertificateDer, dss: &rustls::DigitallySignedStruct, - ) -> Result { + ) -> Result { self.verifier .verify_tls12_signature(message, cert, dss) } @@ -108,9 +105,9 @@ impl ServerCertVerifier for VerifierWithSupportedVerifySc fn verify_tls13_signature( &self, message: &[u8], - cert: &Certificate, + cert: &CertificateDer, dss: &rustls::DigitallySignedStruct, - ) -> Result { + ) -> Result { self.verifier .verify_tls13_signature(message, cert, dss) } @@ -118,8 +115,4 @@ impl ServerCertVerifier for VerifierWithSupportedVerifySc fn supported_verify_schemes(&self) -> Vec { self.supported_verify_schemes.clone() } - - fn request_scts(&self) -> bool { - self.verifier.request_scts() - } } From 4c2dcabd23acfd18e3b9ae0a8478b1415a19cb42 Mon Sep 17 00:00:00 2001 From: Yuxiang Cao Date: Fri, 3 Nov 2023 18:27:49 -0700 Subject: [PATCH 2/6] feat: add full example --- Cargo.lock | 71 ++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 5 +--- examples/Cargo.toml | 15 ++++++++++ examples/src/main.rs | 56 ++++++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 examples/Cargo.toml create mode 100644 examples/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 7e1e6cf..218ea84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -188,6 +188,16 @@ dependencies = [ "cc", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -515,6 +525,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -675,6 +691,29 @@ dependencies = [ "x509-parser", ] +[[package]] +name = "rustls-mbedtls-provider-examples" +version = "0.1.0" +dependencies = [ + "env_logger", + "rustls", + "rustls-mbedcrypto-provider", + "rustls-mbedpki-provider", + "rustls-native-certs", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.3", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "1.0.3" @@ -711,6 +750,38 @@ dependencies = [ "untrusted", ] +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "serde" version = "1.0.190" diff --git a/Cargo.toml b/Cargo.toml index bb156cb..7a370c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,4 @@ [workspace] -members = ["rustls-mbedcrypto-provider", "rustls-mbedpki-provider"] +members = ["examples","rustls-mbedcrypto-provider", "rustls-mbedpki-provider"] default-members = ["rustls-mbedcrypto-provider", "rustls-mbedpki-provider"] resolver = "2" - -[workspace.dependencies] -mbedtls = { version = "0.12.0-alpha.2", default_features = false } diff --git a/examples/Cargo.toml b/examples/Cargo.toml new file mode 100644 index 0000000..5a0d8ac --- /dev/null +++ b/examples/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "rustls-mbedtls-provider-examples" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rustls-mbedcrypto-provider = { path = "../rustls-mbedcrypto-provider" } +rustls-mbedpki-provider = { path = "../rustls-mbedpki-provider" } +env_logger = "0.10" +# TODO: upgrade to use formal 0.22.0 or 0.22.0-* versions when availabe +rustls = { git = "https://github.com/rustls/rustls", rev = "b776a5778ad333653670c34ff9125d8ae59b6047", version = "0.22.0-alpha.4", default-features = false } +rustls-native-certs = "0.6.3" + diff --git a/examples/src/main.rs b/examples/src/main.rs new file mode 100644 index 0000000..6c9c878 --- /dev/null +++ b/examples/src/main.rs @@ -0,0 +1,56 @@ +/* Copyright (c) Fortanix, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. +**/ + +use std::io::{stderr, stdout, Read, Write}; +use std::net::TcpStream; +use std::sync::Arc; + +use rustls_mbedcrypto_provider::MBEDTLS; +use rustls_mbedpki_provider::MbedTlsServerCertVerifier; + +fn main() { + env_logger::init(); + + let root_certs: Vec<_> = rustls_native_certs::load_native_certs() + .expect("could not load platform certs") + .into_iter() + .map(|cert| cert.0.into()) + .collect(); + let server_cert_verifier = MbedTlsServerCertVerifier::new(&root_certs).unwrap(); + let config = rustls::ClientConfig::builder_with_provider(MBEDTLS) + .with_safe_default_cipher_suites() + .with_safe_default_kx_groups() + .with_safe_default_protocol_versions() + .unwrap() + .dangerous() + .with_custom_certificate_verifier(Arc::new(server_cert_verifier)) + .with_no_client_auth(); + + let server_name = "www.rust-lang.org".try_into().unwrap(); + let mut conn = rustls::ClientConnection::new(Arc::new(config), server_name).unwrap(); + let mut sock = TcpStream::connect("www.rust-lang.org:443").unwrap(); + let mut tls = rustls::Stream::new(&mut conn, &mut sock); + tls.write_all( + concat!( + "GET / HTTP/1.1\r\n", + "Host: www.rust-lang.org\r\n", + "Connection: close\r\n", + "Accept-Encoding: identity\r\n", + "\r\n" + ) + .as_bytes(), + ) + .unwrap(); + let ciphersuite = tls + .conn + .negotiated_cipher_suite() + .unwrap(); + writeln!(&mut stderr(), "Current ciphersuite: {:?}", ciphersuite.suite()).unwrap(); + let mut plaintext = Vec::new(); + tls.read_to_end(&mut plaintext).unwrap(); + stdout().write_all(&plaintext).unwrap(); +} From 88a93249f507c41104b8aad81eaad905bfc8d3aa Mon Sep 17 00:00:00 2001 From: Yuxiang Cao Date: Fri, 3 Nov 2023 18:28:19 -0700 Subject: [PATCH 3/6] fix: rustls-mbedpki-provider no dep on ring --- rustls-mbedpki-provider/Cargo.toml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rustls-mbedpki-provider/Cargo.toml b/rustls-mbedpki-provider/Cargo.toml index a351b81..0bc0415 100644 --- a/rustls-mbedpki-provider/Cargo.toml +++ b/rustls-mbedpki-provider/Cargo.toml @@ -11,7 +11,7 @@ categories = ["network-programming", "cryptography"] resolver = "2" [dependencies] -rustls = { git = "https://github.com/rustls/rustls", rev = "b776a5778ad333653670c34ff9125d8ae59b6047", version = "0.22.0-alpha.4" } +rustls = { git = "https://github.com/rustls/rustls", rev = "b776a5778ad333653670c34ff9125d8ae59b6047", version = "0.22.0-alpha.4", default_features = false } mbedtls = { version = "0.12.0-alpha.2", features = [ "x509", "chrono", @@ -20,7 +20,9 @@ mbedtls = { version = "0.12.0-alpha.2", features = [ x509-parser = "0.15" chrono = "0.4" -pki-types = { package = "rustls-pki-types", version = "0.2.1", features = ["std"] } +pki-types = { package = "rustls-pki-types", version = "0.2.1", features = [ + "std", +] } [target.'cfg(target_env = "msvc")'.dependencies] # mbedtls need feature `time` to build when targeting msvc @@ -33,3 +35,4 @@ mbedtls = { version = "0.12.0-alpha.2", default-features = false, features = [ [dev-dependencies] rustls-pemfile = "1.0" +rustls = { git = "https://github.com/rustls/rustls", rev = "b776a5778ad333653670c34ff9125d8ae59b6047", version = "0.22.0-alpha.4" } From c6e210e41f04e21841e5cc05256745f5d47bdd72 Mon Sep 17 00:00:00 2001 From: Yuxiang Cao Date: Mon, 6 Nov 2023 10:28:12 -0800 Subject: [PATCH 4/6] ci: fix test feature --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 27ad325..67ad5d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -86,7 +86,7 @@ jobs: RUST_BACKTRACE: 1 - name: cargo test (debug; no default features) - run: cargo test --locked --no-default-features + run: cargo test --locked --no-default-features --workspace - name: cargo test (rustls_mbedcrypto_provider; debug; no default features; tls12) run: cargo test --locked --no-default-features --features tls12 --package rustls-mbedcrypto-provider @@ -95,7 +95,7 @@ jobs: run: cargo test --locked --no-default-features --features tls12,rdrand --package rustls-mbedcrypto-provider - name: cargo test (release; no run) - run: cargo test --locked --release --no-run + run: cargo test --locked --release --no-run --workspace # TODO: add fuzz tests # TODO: add benchmarks From 3386b3203a733c30ff52094d2ec4756ffcc90211 Mon Sep 17 00:00:00 2001 From: Yuxiang Cao Date: Mon, 6 Nov 2023 10:35:01 -0800 Subject: [PATCH 5/6] ci: add rustls-mbedtls-provider-examples check --- .github/workflows/build.yml | 5 ++++- examples/Cargo.toml | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 67ad5d1..7a3f247 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ on: - master merge_group: schedule: - - cron: '30 13 * * 1,5' + - cron: '30 13 * * *' env: CARGO_TERM_COLOR: always @@ -62,6 +62,9 @@ jobs: env: RUST_BACKTRACE: 1 + - name: cargo build (debug; rustls-mbedtls-provider-examples) + run: cargo build --locked -p rustls-mbedtls-provider-examples + features: name: Features runs-on: ubuntu-latest diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 5a0d8ac..0402e39 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -2,8 +2,9 @@ name = "rustls-mbedtls-provider-examples" version = "0.1.0" edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +license = "MPL-2.0" +description = "rustls-mbedtls-provider example code." +publish = false [dependencies] rustls-mbedcrypto-provider = { path = "../rustls-mbedcrypto-provider" } From 59c6b3d12e7a705ce019b65e0c31e057ddf4c16a Mon Sep 17 00:00:00 2001 From: Yuxiang Cao Date: Mon, 6 Nov 2023 10:35:25 -0800 Subject: [PATCH 6/6] build: use pre-release version --- Cargo.lock | 4 ++-- rustls-mbedcrypto-provider/Cargo.toml | 2 +- rustls-mbedpki-provider/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 218ea84..cf228f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -667,7 +667,7 @@ dependencies = [ [[package]] name = "rustls-mbedcrypto-provider" -version = "0.0.1" +version = "0.0.1-alpha.1" dependencies = [ "env_logger", "log", @@ -681,7 +681,7 @@ dependencies = [ [[package]] name = "rustls-mbedpki-provider" -version = "0.1.0" +version = "0.1.0-alpha.1" dependencies = [ "chrono", "mbedtls", diff --git a/rustls-mbedcrypto-provider/Cargo.toml b/rustls-mbedcrypto-provider/Cargo.toml index 5034ab4..22848cc 100644 --- a/rustls-mbedcrypto-provider/Cargo.toml +++ b/rustls-mbedcrypto-provider/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls-mbedcrypto-provider" -version = "0.0.1" +version = "0.0.1-alpha.1" edition = "2021" license = "MPL-2.0" description = "Mbedtls based crypto provider for rustls." diff --git a/rustls-mbedpki-provider/Cargo.toml b/rustls-mbedpki-provider/Cargo.toml index 0bc0415..4b66e99 100644 --- a/rustls-mbedpki-provider/Cargo.toml +++ b/rustls-mbedpki-provider/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls-mbedpki-provider" -version = "0.1.0" +version = "0.1.0-alpha.1" edition = "2021" license = "MPL-2.0" description = "Implements rustls PKI traits using mbedtls"