From 9add4e1001ce08d78c17e4a3d994fd805f872d2a Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Mon, 31 Aug 2015 16:28:14 +0200 Subject: Add support for set_tmp_dh() and RFC5114 DH parameters for forward secrecy. rust-openssl didn't support forward secrecy at all. This adds support for DHE, by exposing set_tmp_dh() as well as the RFC5114 parameters, which are conveniently exposed since OpenSSL 1.0.2. With OpenSSL >= 1.0.2, and the rfc5114 feature gate, enabling DHE is as simple as (here for 2048-bit MODP group with 256-bit prime order subgroup): use openssl::dh::DH; let dh = DH::get_2048_256().unwrap(); ctx.set_tmp_dh(dh).unwrap(); With OpenSSL < 1.0.2, DH::from_params() can be used to manually specify the DH parameters (here for 2048-bit MODP group with 256-bit prime order subgroup): use openssl::bn::BigNum; use openssl::dh::DH; let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597").unwrap(); let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659").unwrap(); let q = BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3").unwrap(); let dh = DH::from_params(p, g, q).unwrap(); ctx.set_tmp_dh(dh).unwrap(); --- openssl/src/ssl/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 35180d3a..ee2e1f9f 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -21,6 +21,7 @@ use std::slice; use bio::{MemBio}; use ffi; +use dh::DH; use ssl::error::{SslError, SslSessionClosed, StreamError, OpenSslErrors}; use x509::{X509StoreContext, X509FileType, X509}; use crypto::pkey::PKey; @@ -492,6 +493,12 @@ impl SslContext { } } + pub fn set_tmp_dh(&self, dh: DH) -> Result<(),SslError> { + wrap_ssl_result(unsafe { + ffi::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 + }) + } + #[allow(non_snake_case)] /// Specifies the file that contains trusted CA certificates. pub fn set_CA_file>(&mut self, file: P) -> Result<(),SslError> { -- cgit v1.2.3 From 50c5042c705a399ebc178b204a1e6148a26966e1 Mon Sep 17 00:00:00 2001 From: Cody P Schafer Date: Tue, 1 Sep 2015 17:09:19 -0400 Subject: ssl/npn+alpn: adjust protocol selection to fail if no protocols match The current behavior causes a server written using rust-openssl to (if it cannot negotiate a protocol) fallback to the first protocol it has avaliable. This makes it impossible to detect protocol mismatches. This updates our selection to be more similar to how openssl's s_server behaves: non-matching protocols are not supplied with a fallback. Note that some setups may actually want a fallback protocol supplied via ALPN. To support those cases, we should consider adding a generic callback that allows protocol selection to be entirely controlled by the programmer. For the purposes of having a sane default, however, not supplying a default (and mimicing s_server's behavior) is the best choice. --- openssl/src/ssl/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index ee2e1f9f..1f198643 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -308,8 +308,11 @@ unsafe fn select_proto_using(ssl: *mut ffi::SSL, let client_len = protocols.len() as c_uint; // Finally, let OpenSSL find a protocol to be used, by matching the given server and // client lists. - ffi::SSL_select_next_proto(out, outlen, inbuf, inlen, client, client_len); - ffi::SSL_TLSEXT_ERR_OK + if ffi::SSL_select_next_proto(out, outlen, inbuf, inlen, client, client_len) != ffi::OPENSSL_NPN_NEGOTIATED { + ffi::SSL_TLSEXT_ERR_NOACK + } else { + ffi::SSL_TLSEXT_ERR_OK + } } /// The function is given as the callback to `SSL_CTX_set_next_proto_select_cb`. -- cgit v1.2.3 From 6a2b4402e9f2e93008bd47470d88e12337edcfae Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Tue, 1 Sep 2015 09:25:41 +0200 Subject: Use try_ssl_null!() when relevant --- openssl/src/ssl/mod.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index ee2e1f9f..20c9234c 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -432,10 +432,7 @@ impl SslContext { pub fn new(method: SslMethod) -> Result { init(); - let ctx = unsafe { ffi::SSL_CTX_new(method.to_raw()) }; - if ctx == ptr::null_mut() { - return Err(SslError::get()); - } + let ctx = try_ssl_null!(unsafe { ffi::SSL_CTX_new(method.to_raw()) }); let ctx = SslContext { ctx: ctx }; @@ -690,10 +687,7 @@ impl Drop for Ssl { impl Ssl { pub fn new(ctx: &SslContext) -> Result { - let ssl = unsafe { ffi::SSL_new(ctx.ctx) }; - if ssl == ptr::null_mut() { - return Err(SslError::get()); - } + let ssl = try_ssl_null!(unsafe { ffi::SSL_new(ctx.ctx) }); let ssl = Ssl { ssl: ssl }; Ok(ssl) } @@ -1019,10 +1013,7 @@ impl DirectStream { impl DirectStream { fn new_base(ssl: Ssl, stream: S, sock: c_int) -> Result, SslError> { unsafe { - let bio = ffi::BIO_new_socket(sock, 0); - if bio == ptr::null_mut() { - return Err(SslError::get()); - } + let bio = try_ssl_null!(ffi::BIO_new_socket(sock, 0)); ffi::SSL_set_bio(ssl.ssl, bio, bio); } -- cgit v1.2.3 From 28320a65a734b2b38301ef149746a44cb23cd366 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Tue, 1 Sep 2015 10:56:33 +0200 Subject: Add SSL::set_ecdh_auto() This sets automatic curve selection and enables ECDH support. Requires LibreSSL or OpenSSL >= 1.0.2, so behind a feature gate. --- openssl/src/ssl/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 3adf89e6..40e06e93 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -570,6 +570,14 @@ impl SslContext { }) } + #[cfg(feature = "ecdh_auto")] + pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(),SslError> { + wrap_ssl_result( + unsafe { + ffi::SSL_CTX_set_ecdh_auto(self.ctx, onoff as c_int) + }) + } + pub fn set_options(&mut self, option: SslContextOptions) -> SslContextOptions { let raw_bits = option.bits(); let ret = unsafe { -- cgit v1.2.3 From ccc6d07da3b01fef78d9bc109aab8edd9ec4ccf1 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Fri, 25 Sep 2015 15:23:52 +0200 Subject: Add an ecdh_auto description --- openssl/src/ssl/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 40e06e93..a0553b44 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -570,6 +570,10 @@ impl SslContext { }) } + /// If `onoff` is set to `true`, enable ECDHE for key exchange with compatible + /// clients, and automatically select an appropriate elliptic curve. + /// + /// This method requires OpenSSL >= 1.2.0 or LibreSSL and the `ecdh_auto` feature. #[cfg(feature = "ecdh_auto")] pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(),SslError> { wrap_ssl_result( -- cgit v1.2.3 From df93e5e90bfb4f39c9583ac2e2e83a832afaf1c1 Mon Sep 17 00:00:00 2001 From: John Downey Date: Fri, 2 Oct 2015 16:13:22 -0500 Subject: Update documentation about SSLv23 In OpenSSL world, the SSLv23 option is a poorly name method that will negotiate what version of TLS or SSL to use. It starts with the best version the library supports and then precedes to keep trying all the way down to SSL 2.0. --- openssl/src/ssl/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index a0553b44..360f3f3e 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -106,7 +106,8 @@ pub enum SslMethod { #[cfg(feature = "sslv2")] /// Only support the SSLv2 protocol, requires the `sslv2` feature. Sslv2, - /// Support the SSLv2, SSLv3 and TLSv1 protocols. + /// Support the SSLv2, SSLv3, TLSv1, TLSv1.1, and TLSv1.2 protocols depending on what the + /// linked OpenSSL library supports. Sslv23, /// Only support the SSLv3 protocol. Sslv3, -- cgit v1.2.3