From ce92c5dd76ef4b06157c60b45ae60b15d7f96cbe Mon Sep 17 00:00:00 2001 From: Abdullah Alyan Date: Mon, 25 Mar 2024 15:31:00 +0300 Subject: [PATCH] Update rustls to 0.23. Support 'CryptoProvider's. This commit updates rustls to 0.23 and adds support for custom 'CryptoProvider's installable via 'CryptoProvider::install_default()'. In particular, this enables using `aws-lc-rs` for cryptography related operation in TLS. The 'TLS' example was updated to test use of 'aws-lc-rs' on Unix. --- core/lib/Cargo.toml | 4 +- core/lib/src/listener/tls.rs | 4 +- core/lib/src/tls/util.rs | 17 +++++++- examples/tls/Cargo.toml | 1 + examples/tls/Rocket.toml | 4 ++ .../tls/private/ecdsa_nistp521_sha512.p12 | Bin 0 -> 1779 bytes .../private/ecdsa_nistp521_sha512_cert.pem | 23 +++++++++++ .../ecdsa_nistp521_sha512_key_pkcs8.pem | 8 ++++ examples/tls/private/gen_certs.sh | 24 +++++++++++ examples/tls/src/tests.rs | 38 +++++++++++------- 10 files changed, 104 insertions(+), 19 deletions(-) create mode 100644 examples/tls/private/ecdsa_nistp521_sha512.p12 create mode 100644 examples/tls/private/ecdsa_nistp521_sha512_cert.pem create mode 100644 examples/tls/private/ecdsa_nistp521_sha512_key_pkcs8.pem diff --git a/core/lib/Cargo.toml b/core/lib/Cargo.toml index c09efb11..c3820b0e 100644 --- a/core/lib/Cargo.toml +++ b/core/lib/Cargo.toml @@ -50,8 +50,8 @@ rmp-serde = { version = "1", optional = true } uuid_ = { package = "uuid", version = "1", optional = true, features = ["serde"] } # Optional TLS dependencies -rustls = { version = "0.22", optional = true } -tokio-rustls = { version = "0.25", optional = true } +rustls = { version = "0.23", default-features = false, features = ["ring", "logging", "std", "tls12"], optional = true } +tokio-rustls = { version = "0.26", default-features = false, features = ["logging", "tls12", "ring"], optional = true } rustls-pemfile = { version = "2.0.0", optional = true } # Optional MTLS dependencies diff --git a/core/lib/src/listener/tls.rs b/core/lib/src/listener/tls.rs index 7ff631f7..25dd1a6d 100644 --- a/core/lib/src/listener/tls.rs +++ b/core/lib/src/listener/tls.rs @@ -7,7 +7,7 @@ use tokio::io::{AsyncRead, AsyncWrite}; use tokio_rustls::TlsAcceptor; use crate::tls::{TlsConfig, Error}; -use crate::tls::util::{load_cert_chain, load_key, load_ca_certs}; +use crate::tls::util::{self, load_cert_chain, load_key, load_ca_certs}; use crate::listener::{Listener, Bindable, Connection, Certificates, Endpoint}; #[doc(inline)] @@ -31,7 +31,7 @@ impl TlsConfig { pub(crate) fn server_config(&self) -> Result { let provider = rustls::crypto::CryptoProvider { cipher_suites: self.ciphers().map(|c| c.into()).collect(), - ..rustls::crypto::ring::default_provider() + ..util::get_crypto_provider() }; #[cfg(feature = "mtls")] diff --git a/core/lib/src/tls/util.rs b/core/lib/src/tls/util.rs index c07135ad..497c5201 100644 --- a/core/lib/src/tls/util.rs +++ b/core/lib/src/tls/util.rs @@ -1,6 +1,7 @@ use std::io; use rustls::RootCertStore; +use rustls::crypto::CryptoProvider; use rustls::pki_types::{CertificateDer, PrivateKeyDer}; use crate::tls::error::{Result, Error, KeyError}; @@ -33,7 +34,8 @@ pub fn load_key(reader: &mut dyn io::BufRead) -> Result> // Ensure we can use the key. let key = keys.remove(0); - rustls::crypto::ring::sign::any_supported_type(&key).map_err(KeyError::Unsupported)?; + get_crypto_provider().key_provider.load_private_key(key.clone_key()) + .map_err(KeyError::Unsupported)?; Ok(key) } @@ -47,6 +49,19 @@ pub fn load_ca_certs(reader: &mut dyn io::BufRead) -> Result { Ok(roots) } +pub(crate) fn get_crypto_provider() -> CryptoProvider { + if let Some(crypto_provider) = rustls::crypto::CryptoProvider::get_default() { + CryptoProvider::clone(crypto_provider) + } else { + let crypto_provider = rustls::crypto::ring::default_provider(); + // Should only fail due to other concurrent install, so we ignore it + let _ = crypto_provider.clone().install_default(); + + crypto_provider + } + +} + #[cfg(test)] mod test { use super::*; diff --git a/examples/tls/Cargo.toml b/examples/tls/Cargo.toml index 27e5b61d..a505647f 100644 --- a/examples/tls/Cargo.toml +++ b/examples/tls/Cargo.toml @@ -7,4 +7,5 @@ publish = false [dependencies] rocket = { path = "../../core/lib", features = ["tls", "mtls", "secrets", "http3-preview"] } +rustls = { version = "0.23", features = ["aws_lc_rs"] } yansi = "1.0.1" diff --git a/examples/tls/Rocket.toml b/examples/tls/Rocket.toml index b7a538f9..36f2f158 100644 --- a/examples/tls/Rocket.toml +++ b/examples/tls/Rocket.toml @@ -25,6 +25,10 @@ key = "private/ecdsa_nistp256_sha256_key_pkcs8.pem" certs = "private/ecdsa_nistp384_sha384_cert.pem" key = "private/ecdsa_nistp384_sha384_key_pkcs8.pem" +[ecdsa_nistp521_sha512_pkcs8.tls] +certs = "private/ecdsa_nistp521_sha512_cert.pem" +key = "private/ecdsa_nistp521_sha512_key_pkcs8.pem" + [ecdsa_nistp256_sha256_sec1.tls] certs = "private/ecdsa_nistp256_sha256_cert.pem" key = "private/ecdsa_nistp256_sha256_key_sec1.pem" diff --git a/examples/tls/private/ecdsa_nistp521_sha512.p12 b/examples/tls/private/ecdsa_nistp521_sha512.p12 new file mode 100644 index 0000000000000000000000000000000000000000..b8db176cfb9c5ee3229e32281f56bfba9b013695 GIT binary patch literal 1779 zcmai#dpOgJAIJBdZRWR)-^SnMdI&2vXNZ{zODwvdR z8YyiZ1xNyAbXY!w4$Iz_ujA;D;U5;Pj1CcQOPycMss_i;dB}t2&i_$vcmaEEVkXE--$<_th z7glUq@m_bOWn!+>EhmL6IQ;K5o;io93^2w|eSY0mY!pZFeW?-r_^y6^6K`n80N*nc z8T`C#3?Y-)`Ysb3K>O3C@>U3qvJjIiUzd~teK`Edn*7tqqhj(r|2A6!uNs*=i?Ysf z4M$FxyZa6u_gO6m0_7|Xa|e$;X?5R^94+lN1ARPD+$&R?C`_Bo80)xw$#o*(Ot#k) zy#}qB=`_x5yri$}^b+WcIktzIJ6ZZ_?Lu8NIZcJAIeKdLymHZ~_E}c3r_m`Y{XH~9 zo|<&F|G=*5hV*LDSE%^6qHug3cO8y@P zd;3HVLJOBrUzzCmb>& z+Z2u-cCU5YLPV7(-W%RLW(3}GwcdlYHLNqa+=J&3Yfyb$xOup72j8r3VCT{PhzzSL-FcuzN#hu%{KL+|L`iPf+J zDSrh+9tdnOSQ=U{!lH?4KDLnf8pHEyQxeA>Sql`6eyp030NP2kD`x>iZ{zB&62k6vVQW%2FL-Y*jOk@1hka6DHw| zs9DX51Fltd=q#R{w1scr`z9F>O%YqmXU{`T;haS%9KI{HCa*i$;v#2LPULea*3*?T z?Z|xHT9%`ED{iN!VidDHeIa157#-cEWnJKgdt~1dxd=t$#uIsw0UI_xVdqT1-UU|H zbN!Vx@3)aIPoMh@V!Z7}lv_*m9s49qh!m4?%R-s~$8k~TPRApBeeTAFj=JPjRK<&z z-oL#Xkd)IPJ&lfyJch9!=O#t?F`u6vi*}wF&hH~-Rk^9h@vz~Q2bE+GZ?PMVn?3mN z!@q!wuyz)v7)2Z%X#CEnZ@>epAasDUEthOhAq?>k3z7c;z}u$pwn+Imz!jnJ{tivI z(*6~2mhuk6vg@cXP1c@8_ZK>owv#~z&-!}gP)((uB|R}~t;|$Z-c|8XEW=e^>7O?L z1cYZtWGv?^SeY`Oz9l*RGCi+XR#q)O5UncsnE;k*5d`B}NQ`htwPmkKn|p_x3Th9| zX^Ey)KMV#A4CLR8r;^Xx#{b@c*I_yZeuU-O*B#C+W}n;KdZwzP2IBWX zV+1u^d%iiY=M7QJ)cPsb`^4`20k8JR5I8aW-LQPBuhC`(pJ1SGZq`6^;kR4AokQ2< zhm2R7By?jq^yHv9PMZacAU52M)BIkD6xL7JiS!l<10*l^LNr2k3=|Bj)*-y=UVD|IF HZ`J$-@3IVK literal 0 HcmV?d00001 diff --git a/examples/tls/private/ecdsa_nistp521_sha512_cert.pem b/examples/tls/private/ecdsa_nistp521_sha512_cert.pem new file mode 100644 index 00000000..bdbea12a --- /dev/null +++ b/examples/tls/private/ecdsa_nistp521_sha512_cert.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID5DCCAcygAwIBAgIUZ2n0Lhg+9cVPCOtK7Ov1D5n58GIwDQYJKoZIhvcNAQEN +BQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg +Q0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTI0MDMyNzExMDYzMFoXDTM0 +MDMyNTExMDYzMFowPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQK +DAZSb2NrZXQxEjAQBgNVBAMMCWxvY2FsaG9zdDCBmzAQBgcqhkjOPQIBBgUrgQQA +IwOBhgAEAYXtydjaJR3BsC6NVEPD8wxIobzKO004WjyKFupkQcuQPg4DDzLTimho +SyH3ohaYX398MBSSgxo5A1zTb0TB/Yl1AYLiP6SWmZfejRdyZuRQSNrNIH07MIId +e+l8VD0DVSb9+Zej5eet4sRgcVgxIzfSCi1mVzSCttbwagpvZW/HBEEgo1gwVjAU +BgNVHREEDTALgglsb2NhbGhvc3QwHQYDVR0OBBYEFMvhtxA9Tm+8JRx1MfLdJk3Z +XW5DMB8GA1UdIwQYMBaAFEQDJSPSVPCilnYHVWae8w99S0KTMA0GCSqGSIb3DQEB +DQUAA4ICAQCscu1VBrqQRLON5s86UQv+sCATmW9kWWLCnHn78iGfxMa9N4L9rsf4 +aFTFpfklOHYBPLK0q2Jm681rzD09FN0DTxG5t9WIsQ2PEJc2akqbzx1Sm4sMZ/td +79oS/BLgKEOL8RDtU4dQu5DsrOqOYtDbH4ETwGs3TL3eWH+3sC9S25Sq/DJ9TFHm +pZIzEB9rEwgXMsZ0KVYzEAByKZvJZJbp5nRFJPO4riuY+RkyeqQh+oWxRAplqk2s +yZEgxgnJIPzVYJkZ8VxaWLF9mU2kHtJlHwlTf6Yp3LTuyr9mwVsNTY+xXco6d5p8 +bMVUBvVCxNmFHsv2maNOHF2AkxwncIkSNK00ohX5rSnZ1Tdipq3ckjpkbTccYWO2 +aEPUphZUkGNReSnJ0LKDyCW4Y4Yna3SG152DfMaIjQjflyh8jUnsrGdISxuemE/z +2RnTzoSJLGMZvw52BsPbq9aNiZy7kM495oANFSaHwDbkEAknYKyAj2uO2740qEOH +xhmsa67lPeofZBoU86gydkszCOWN1GzGOmoF9OFfD5H9M6mtYJ6l1h6/80ofx2Fv +SdaksbRdERx20hVPM6tsAbfeP2mmxelVmhxwziQe5ERybrBx23w+khsfsA8Ldv+7 +hbAqYufmcmsSxdEA+Fuo18vhHOT98UmKlXx1hyERm0hbJe9rW+rGKg== +-----END CERTIFICATE----- diff --git a/examples/tls/private/ecdsa_nistp521_sha512_key_pkcs8.pem b/examples/tls/private/ecdsa_nistp521_sha512_key_pkcs8.pem new file mode 100644 index 00000000..14d40eef --- /dev/null +++ b/examples/tls/private/ecdsa_nistp521_sha512_key_pkcs8.pem @@ -0,0 +1,8 @@ +-----BEGIN PRIVATE KEY----- +MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIA3a6vdhcCDC8p/8yG +eDASmWqQdkmgU9kaqqgmBh2gcLhTxxtjwAy8BxBy4UmRFo8VJtFUDLXt8ZR2vzTc +zKybjrmhgYkDgYYABAGF7cnY2iUdwbAujVRDw/MMSKG8yjtNOFo8ihbqZEHLkD4O +Aw8y04poaEsh96IWmF9/fDAUkoMaOQNc029Ewf2JdQGC4j+klpmX3o0XcmbkUEja +zSB9OzCCHXvpfFQ9A1Um/fmXo+XnreLEYHFYMSM30gotZlc0grbW8GoKb2VvxwRB +IA== +-----END PRIVATE KEY----- diff --git a/examples/tls/private/gen_certs.sh b/examples/tls/private/gen_certs.sh index 86e5d5a9..2418c27b 100755 --- a/examples/tls/private/gen_certs.sh +++ b/examples/tls/private/gen_certs.sh @@ -113,15 +113,39 @@ function gen_ecdsa_nistp384_sha384() { rm ca_cert.srl server.csr ecdsa_nistp384_sha384_key.pem } +function gen_ecdsa_nistp521_sha512() { + gen_ca_if_non_existent + + openssl ecparam -out ecdsa_nistp521_sha512_key.pem -name secp521r1 -genkey + + # Convert to pkcs8 format supported by rustls + openssl pkcs8 -topk8 -nocrypt -in ecdsa_nistp521_sha512_key.pem \ + -out ecdsa_nistp521_sha512_key_pkcs8.pem + + openssl req -new -nodes -sha512 -key ecdsa_nistp521_sha512_key_pkcs8.pem \ + -subj "${SUBJECT}" -out server.csr + + openssl x509 -req -sha512 -extfile <(printf "subjectAltName=${ALT}") -days 3650 \ + -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \ + -in server.csr -out ecdsa_nistp521_sha512_cert.pem + + openssl pkcs12 -export -password pass:rocket -in ecdsa_nistp521_sha512_cert.pem \ + -inkey ecdsa_nistp521_sha512_key_pkcs8.pem -out ecdsa_nistp521_sha512.p12 + + rm ca_cert.srl server.csr ecdsa_nistp521_sha512_key.pem +} + case $1 in ed25519) gen_ed25519 ;; rsa_sha256) gen_rsa_sha256 ;; ecdsa_nistp256_sha256) gen_ecdsa_nistp256_sha256 ;; ecdsa_nistp384_sha384) gen_ecdsa_nistp384_sha384 ;; + ecdsa_nistp521_sha512) gen_ecdsa_nistp521_sha512 ;; *) gen_ed25519 gen_rsa_sha256 gen_ecdsa_nistp256_sha256 gen_ecdsa_nistp384_sha384 + gen_ecdsa_nistp521_sha512 ;; esac diff --git a/examples/tls/src/tests.rs b/examples/tls/src/tests.rs index 61efbec9..cec2e9f7 100644 --- a/examples/tls/src/tests.rs +++ b/examples/tls/src/tests.rs @@ -69,8 +69,9 @@ fn insecure_cookies() { fn hello_world() { use rocket::listener::DefaultListener; use rocket::config::{Config, SecretKey}; + use rustls::crypto::aws_lc_rs; - let profiles = [ + let mut profiles = vec![ "rsa_sha256", "ecdsa_nistp256_sha256_pkcs8", "ecdsa_nistp384_sha384_pkcs8", @@ -79,20 +80,29 @@ fn hello_world() { "ed25519", ]; - for profile in profiles { - let config = Config { - secret_key: SecretKey::generate().unwrap(), - ..Config::debug_default() - }; + for use_aws_lc in [false, true] { + if use_aws_lc { + let crypto_provider = aws_lc_rs::default_provider(); + crypto_provider.install_default().unwrap(); - let figment = Config::figment().merge(config).select(profile); - let client = Client::tracked_secure(super::rocket().configure(figment)).unwrap(); - let response = client.get("/").dispatch(); - assert_eq!(response.into_string().unwrap(), "Hello, world!"); + profiles.push("ecdsa_nistp521_sha512_pkcs8"); + } - let figment = client.rocket().figment(); - let listener: DefaultListener = figment.extract().unwrap(); - assert_eq!(figment.profile(), profile); - listener.tls.as_ref().unwrap().validate().expect("valid TLS config"); + for profile in &profiles { + let config = Config { + secret_key: SecretKey::generate().unwrap(), + ..Config::debug_default() + }; + + let figment = Config::figment().merge(config).select(profile); + let client = Client::tracked_secure(super::rocket().configure(figment)).unwrap(); + let response = client.get("/").dispatch(); + assert_eq!(response.into_string().unwrap(), "Hello, world!"); + + let figment = client.rocket().figment(); + let listener: DefaultListener = figment.extract().unwrap(); + assert_eq!(figment.profile(), profile); + listener.tls.as_ref().unwrap().validate().expect("valid TLS config"); + } } }