From de47d158c20768b8526e939e7eb3ae9175e282f2 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 30 Jan 2016 10:41:47 -0800 Subject: [PATCH 01/96] Remove NonblockingSslStream --- openssl/src/ssl/error.rs | 46 ------------ openssl/src/ssl/mod.rs | 133 +---------------------------------- openssl/src/ssl/tests/mod.rs | 26 +++---- 3 files changed, 14 insertions(+), 191 deletions(-) diff --git a/openssl/src/ssl/error.rs b/openssl/src/ssl/error.rs index 2459a473..ba0c7458 100644 --- a/openssl/src/ssl/error.rs +++ b/openssl/src/ssl/error.rs @@ -149,19 +149,6 @@ pub enum SslError { OpenSslErrors(Vec), } -/// An error on a nonblocking stream. -#[derive(Debug)] -pub enum NonblockingSslError { - /// A standard SSL error occurred. - SslError(SslError), - /// The OpenSSL library wants data from the remote socket; - /// the caller should wait for read readiness. - WantRead, - /// The OpenSSL library wants to send data to the remote socket; - /// the caller should wait for write readiness. - WantWrite, -} - impl fmt::Display for SslError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(fmt.write_str(error::Error::description(self))); @@ -201,39 +188,6 @@ impl error::Error for SslError { } } -impl fmt::Display for NonblockingSslError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.write_str(error::Error::description(self)) - } -} - -impl error::Error for NonblockingSslError { - fn description(&self) -> &str { - match *self { - NonblockingSslError::SslError(ref e) => e.description(), - NonblockingSslError::WantRead => { - "The OpenSSL library wants data from the remote socket" - } - NonblockingSslError::WantWrite => { - "The OpenSSL library want to send data to the remote socket" - } - } - } - - fn cause(&self) -> Option<&error::Error> { - match *self { - NonblockingSslError::SslError(ref e) => e.cause(), - _ => None, - } - } -} - -impl From for NonblockingSslError { - fn from(e: SslError) -> NonblockingSslError { - NonblockingSslError::SslError(e) - } -} - /// An error from the OpenSSL library #[derive(Debug, Clone, PartialEq, Eq)] pub enum OpensslError { diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index aa785142..4404eb55 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -26,7 +26,7 @@ use std::os::windows::io::{AsRawSocket, RawSocket}; use ffi; use ffi_extras; use dh::DH; -use ssl::error::{NonblockingSslError, SslError, OpenSslError, OpensslError}; +use ssl::error::{SslError, OpenSslError}; use x509::{X509StoreContext, X509FileType, X509}; use crypto::pkey::PKey; @@ -1572,134 +1572,3 @@ impl MaybeSslStream { } } } - -/// # Deprecated -/// -/// Use `SslStream` with `ssl_read` and `ssl_write`. -pub struct NonblockingSslStream(SslStream); - -impl Clone for NonblockingSslStream { - fn clone(&self) -> Self { - NonblockingSslStream(self.0.clone()) - } -} - -#[cfg(unix)] -impl AsRawFd for NonblockingSslStream { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} - -#[cfg(windows)] -impl AsRawSocket for NonblockingSslStream { - fn as_raw_socket(&self) -> RawSocket { - self.0.as_raw_socket() - } -} - -impl NonblockingSslStream { - pub fn try_clone(&self) -> io::Result> { - self.0.try_clone().map(NonblockingSslStream) - } -} - -impl NonblockingSslStream { - /// Returns a reference to the underlying stream. - pub fn get_ref(&self) -> &S { - self.0.get_ref() - } - - /// Returns a mutable reference to the underlying stream. - /// - /// ## Warning - /// - /// It is inadvisable to read from or write to the underlying stream as it - /// will most likely corrupt the SSL session. - pub fn get_mut(&mut self) -> &mut S { - self.0.get_mut() - } - - /// Returns a reference to the Ssl. - pub fn ssl(&self) -> &Ssl { - self.0.ssl() - } -} - -impl NonblockingSslStream { - /// Create a new nonblocking client ssl connection on wrapped `stream`. - /// - /// Note that this method will most likely not actually complete the SSL - /// handshake because doing so requires several round trips; the handshake will - /// be completed in subsequent read/write calls managed by your event loop. - pub fn connect(ssl: T, stream: S) -> Result, SslError> { - SslStream::connect(ssl, stream).map(NonblockingSslStream) - } - - /// Create a new nonblocking server ssl connection on wrapped `stream`. - /// - /// Note that this method will most likely not actually complete the SSL - /// handshake because doing so requires several round trips; the handshake will - /// be completed in subsequent read/write calls managed by your event loop. - pub fn accept(ssl: T, stream: S) -> Result, SslError> { - SslStream::accept(ssl, stream).map(NonblockingSslStream) - } - - fn convert_err(&self, err: Error) -> NonblockingSslError { - match err { - Error::ZeroReturn => SslError::SslSessionClosed.into(), - Error::WantRead(_) => NonblockingSslError::WantRead, - Error::WantWrite(_) => NonblockingSslError::WantWrite, - Error::WantX509Lookup => unreachable!(), - Error::Stream(e) => SslError::StreamError(e).into(), - Error::Ssl(e) => { - SslError::OpenSslErrors(e.iter() - .map(|e| OpensslError::from_error_code(e.error_code())) - .collect()) - .into() - } - } - } - - /// Read bytes from the SSL stream into `buf`. - /// - /// Given the SSL state machine, this method may return either `WantWrite` - /// or `WantRead` to indicate that your event loop should respectively wait - /// for write or read readiness on the underlying stream. Upon readiness, - /// repeat your `read()` call with the same arguments each time until you - /// receive an `Ok(count)`. - /// - /// An `SslError` return value, is terminal; do not re-attempt your read. - /// - /// As expected of a nonblocking API, this method will never block your - /// thread on I/O. - /// - /// On a return value of `Ok(count)`, count is the number of decrypted - /// plaintext bytes copied into the `buf` slice. - pub fn read(&mut self, buf: &mut [u8]) -> Result { - match self.0.ssl_read(buf) { - Ok(n) => Ok(n), - Err(Error::ZeroReturn) => Ok(0), - Err(e) => Err(self.convert_err(e)), - } - } - - /// Write bytes from `buf` to the SSL stream. - /// - /// Given the SSL state machine, this method may return either `WantWrite` - /// or `WantRead` to indicate that your event loop should respectively wait - /// for write or read readiness on the underlying stream. Upon readiness, - /// repeat your `write()` call with the same arguments each time until you - /// receive an `Ok(count)`. - /// - /// An `SslError` return value, is terminal; do not re-attempt your write. - /// - /// As expected of a nonblocking API, this method will never block your - /// thread on I/O. - /// - /// Given a return value of `Ok(count)`, count is the number of plaintext bytes - /// from the `buf` slice that were encrypted and written onto the stream. - pub fn write(&mut self, buf: &[u8]) -> Result { - self.0.ssl_write(buf).map_err(|e| self.convert_err(e)) - } -} diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index c3e7a363..3fb7452a 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -18,8 +18,8 @@ use ssl; use ssl::SSL_VERIFY_PEER; use ssl::SslMethod::Sslv23; use ssl::SslMethod; -use ssl::error::NonblockingSslError; -use ssl::{SslContext, SslStream, VerifyCallback, NonblockingSslStream}; +use ssl::error::Error; +use ssl::{SslContext, SslStream, VerifyCallback}; use x509::X509StoreContext; use x509::X509FileType; use x509::X509; @@ -871,7 +871,7 @@ fn test_sslv2_connect_failure() { .unwrap(); } -fn wait_io(stream: &NonblockingSslStream, read: bool, timeout_ms: u32) -> bool { +fn wait_io(stream: &SslStream, read: bool, timeout_ms: u32) -> bool { unsafe { let mut set: select::fd_set = mem::zeroed(); select::fd_set(&mut set, stream.get_ref()); @@ -895,7 +895,7 @@ fn test_write_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); let cx = SslContext::new(Sslv23).unwrap(); - let mut stream = NonblockingSslStream::connect(&cx, stream).unwrap(); + let mut stream = SslStream::connect(&cx, stream).unwrap(); let mut iterations = 0; loop { @@ -905,15 +905,15 @@ fn test_write_nonblocking() { // openssl. panic!("Too many read/write round trips in handshake!!"); } - let result = stream.write(b"hello"); + let result = stream.ssl_write(b"hello"); match result { Ok(_) => { break; } - Err(NonblockingSslError::WantRead) => { + Err(Error::WantRead(_)) => { assert!(wait_io(&stream, true, 1000)); } - Err(NonblockingSslError::WantWrite) => { + Err(Error::WantWrite(_)) => { assert!(wait_io(&stream, false, 1000)); } Err(other) => { @@ -932,7 +932,7 @@ fn test_read_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); let cx = SslContext::new(Sslv23).unwrap(); - let mut stream = NonblockingSslStream::connect(&cx, stream).unwrap(); + let mut stream = SslStream::connect(&cx, stream).unwrap(); let mut iterations = 0; loop { @@ -942,16 +942,16 @@ fn test_read_nonblocking() { // openssl. panic!("Too many read/write round trips in handshake!!"); } - let result = stream.write(b"GET /\r\n\r\n"); + let result = stream.ssl_write(b"GET /\r\n\r\n"); match result { Ok(n) => { assert_eq!(n, 9); break; } - Err(NonblockingSslError::WantRead) => { + Err(Error::WantRead(..)) => { assert!(wait_io(&stream, true, 1000)); } - Err(NonblockingSslError::WantWrite) => { + Err(Error::WantWrite(..)) => { assert!(wait_io(&stream, false, 1000)); } Err(other) => { @@ -960,7 +960,7 @@ fn test_read_nonblocking() { } } let mut input_buffer = [0u8; 1500]; - let result = stream.read(&mut input_buffer); + let result = stream.ssl_read(&mut input_buffer); let bytes_read = match result { Ok(n) => { // This branch is unlikely, but on an overloaded VM with @@ -968,7 +968,7 @@ fn test_read_nonblocking() { // be in the receive buffer before we issue the read() syscall... n } - Err(NonblockingSslError::WantRead) => { + Err(Error::WantRead(..)) => { assert!(wait_io(&stream, true, 3000)); // Second read should return application data. stream.read(&mut input_buffer).unwrap() From 58654bc49140d37f28837ba1982ed4aa9fc5c466 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 30 Jan 2016 10:44:01 -0800 Subject: [PATCH 02/96] Remove deprecated methods --- openssl/src/ssl/mod.rs | 62 +----------------------------------- openssl/src/ssl/tests/mod.rs | 56 ++++++++++++++------------------ 2 files changed, 25 insertions(+), 93 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 4404eb55..c713aeb2 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -7,7 +7,6 @@ use std::io; use std::io::prelude::*; use std::mem; use std::str; -use std::net; use std::path::Path; use std::ptr; use std::sync::{Once, ONCE_INIT, Mutex, Arc}; @@ -922,15 +921,6 @@ impl Drop for Ssl { } } -impl Clone for Ssl { - /// # Deprecated - fn clone(&self) -> Ssl { - unsafe { rust_SSL_clone(self.ssl) }; - Ssl { ssl: self.ssl } - - } -} - impl Ssl { pub fn new(ctx: &SslContext) -> Result { let ssl = try_ssl_null!(unsafe { ffi::SSL_new(ctx.ctx) }); @@ -1210,19 +1200,7 @@ pub struct SslStream { _p: PhantomData, } -/// # Deprecated -/// -/// This method does not behave as expected and will be removed in a future -/// release. -impl Clone for SslStream { - fn clone(&self) -> SslStream { - SslStream { - ssl: self.ssl.clone(), - _method: self._method.clone(), - _p: PhantomData, - } - } -} +unsafe impl Send for SslStream {} impl fmt::Debug for SslStream where S: fmt::Debug { @@ -1292,20 +1270,6 @@ impl SslStream { } } - /// ### Deprecated - /// - /// Use `connect`. - pub fn connect_generic(ssl: T, stream: S) -> Result, SslError> { - Self::connect(ssl, stream) - } - - /// ### Deprecated - /// - /// Use `accept`. - pub fn accept_generic(ssl: T, stream: S) -> Result, SslError> { - Self::accept(ssl, stream) - } - /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`. /// /// This is particularly useful with a nonblocking socket, where the error @@ -1442,20 +1406,6 @@ impl SslStream { } } -impl SslStream<::std::net::TcpStream> { - /// # Deprecated - /// - /// This method does not behave as expected and will be removed in a future - /// release. - pub fn try_clone(&self) -> io::Result> { - Ok(SslStream { - ssl: self.ssl.clone(), - _method: self._method.clone(), - _p: PhantomData, - }) - } -} - impl Read for SslStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { match self.ssl_read(buf) { @@ -1562,13 +1512,3 @@ impl MaybeSslStream where S: Read + Write } } } - -impl MaybeSslStream { - /// Like `TcpStream::try_clone`. - pub fn try_clone(&self) -> io::Result> { - match *self { - MaybeSslStream::Ssl(ref s) => s.try_clone().map(MaybeSslStream::Ssl), - MaybeSslStream::Normal(ref s) => s.try_clone().map(MaybeSslStream::Normal), - } - } -} diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 3fb7452a..2ada0065 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -222,7 +222,7 @@ run_test!(new_ctx, |method, _| { }); run_test!(new_sslstream, |method, stream| { - SslStream::connect_generic(&SslContext::new(method).unwrap(), stream).unwrap(); + SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap(); }); run_test!(get_ssl_method, |method, _| { @@ -234,7 +234,7 @@ run_test!(verify_untrusted, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, None); - match SslStream::connect_generic(&ctx, stream) { + match SslStream::connect(&ctx, stream) { Ok(_) => panic!("expected failure"), Err(err) => println!("error {:?}", err) } @@ -248,7 +248,7 @@ run_test!(verify_trusted, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - match SslStream::connect_generic(&ctx, stream) { + match SslStream::connect(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -262,7 +262,7 @@ run_test!(verify_untrusted_callback_override_ok, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - match SslStream::connect_generic(&ctx, stream) { + match SslStream::connect(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -276,7 +276,7 @@ run_test!(verify_untrusted_callback_override_bad, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::connect_generic(&ctx, stream).is_err()); + assert!(SslStream::connect(&ctx, stream).is_err()); }); run_test!(verify_trusted_callback_override_ok, |method, stream| { @@ -291,7 +291,7 @@ run_test!(verify_trusted_callback_override_ok, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - match SslStream::connect_generic(&ctx, stream) { + match SslStream::connect(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -309,7 +309,7 @@ run_test!(verify_trusted_callback_override_bad, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - assert!(SslStream::connect_generic(&ctx, stream).is_err()); + assert!(SslStream::connect(&ctx, stream).is_err()); }); run_test!(verify_callback_load_certs, |method, stream| { @@ -321,7 +321,7 @@ run_test!(verify_callback_load_certs, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::connect_generic(&ctx, stream).is_ok()); + assert!(SslStream::connect(&ctx, stream).is_ok()); }); run_test!(verify_trusted_get_error_ok, |method, stream| { @@ -337,7 +337,7 @@ run_test!(verify_trusted_get_error_ok, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - assert!(SslStream::connect_generic(&ctx, stream).is_ok()); + assert!(SslStream::connect(&ctx, stream).is_ok()); }); run_test!(verify_trusted_get_error_err, |method, stream| { @@ -349,7 +349,7 @@ run_test!(verify_trusted_get_error_err, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::connect_generic(&ctx, stream).is_err()); + assert!(SslStream::connect(&ctx, stream).is_err()); }); run_test!(verify_callback_data, |method, stream| { @@ -375,7 +375,7 @@ run_test!(verify_callback_data, |method, stream| { ctx.set_verify_with_data(SSL_VERIFY_PEER, callback, node_id); ctx.set_verify_depth(1); - match SslStream::connect_generic(&ctx, stream) { + match SslStream::connect(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -420,7 +420,7 @@ fn test_write_hits_stream() { let guard = thread::spawn(move || { let ctx = SslContext::new(Sslv23).unwrap(); let stream = TcpStream::connect(addr).unwrap(); - let mut stream = SslStream::connect_generic(&ctx, stream).unwrap(); + let mut stream = SslStream::connect(&ctx, stream).unwrap(); stream.write_all(b"hello").unwrap(); stream @@ -481,7 +481,7 @@ run_test!(clear_ctx_options, |method, _| { #[test] fn test_write() { let (_s, stream) = Server::new(); - let mut stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -499,7 +499,7 @@ fn test_write_direct() { } run_test!(get_peer_certificate, |method, stream| { - let stream = SslStream::connect_generic(&SslContext::new(method).unwrap(), + let stream = SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap(); let cert = stream.ssl().peer_certificate().unwrap(); let fingerprint = cert.fingerprint(SHA256).unwrap(); @@ -513,7 +513,7 @@ run_test!(get_peer_certificate, |method, stream| { fn test_write_dtlsv1() { let (_s, stream) = Server::new_dtlsv1(iter::repeat("y\n")); - let mut stream = SslStream::connect_generic(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); stream.write_all(b"hello").unwrap(); stream.flush().unwrap(); stream.write_all(b" there").unwrap(); @@ -523,7 +523,7 @@ fn test_write_dtlsv1() { #[test] fn test_read() { let (_s, tcp) = Server::new(); - let mut stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); @@ -541,7 +541,7 @@ fn test_read_direct() { #[test] fn test_pending() { let (_s, tcp) = Server::new(); - let mut stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); @@ -564,7 +564,7 @@ fn test_pending() { #[test] fn test_state() { let (_s, tcp) = Server::new(); - let stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); assert_eq!(stream.ssl().state_string(), "SSLOK "); assert_eq!(stream.ssl().state_string_long(), "SSL negotiation finished successfully"); @@ -605,7 +605,7 @@ fn test_connect_with_unilateral_npn() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect_generic(&ctx, stream) { + let stream = match SslStream::connect(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -649,7 +649,7 @@ fn test_connect_with_npn_successful_multiple_matching() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect_generic(&ctx, stream) { + let stream = match SslStream::connect(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -696,7 +696,7 @@ fn test_connect_with_npn_successful_single_match() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect_generic(&ctx, stream) { + let stream = match SslStream::connect(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -738,7 +738,7 @@ fn test_npn_server_advertise_multiple() { } // Now connect to the socket and make sure the protocol negotiation works... let stream = TcpStream::connect(localhost).unwrap(); - let stream = match SslStream::connect_generic(&ctx, stream) { + let stream = match SslStream::connect(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -857,7 +857,7 @@ mod dtlsv1 { fn test_read_dtlsv1() { let (_s, stream) = Server::new_dtlsv1(Some("hello")); - let mut stream = SslStream::connect_generic(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); let mut buf = [0u8; 100]; assert!(stream.read(&mut buf).is_ok()); } @@ -866,7 +866,7 @@ fn test_read_dtlsv1() { #[cfg(feature = "sslv2")] fn test_sslv2_connect_failure() { let (_s, tcp) = Server::new_tcp(&["-no_ssl2", "-www"]); - SslStream::connect_generic(&SslContext::new(Sslv2).unwrap(), tcp) + SslStream::connect(&SslContext::new(Sslv2).unwrap(), tcp) .err() .unwrap(); } @@ -981,14 +981,6 @@ fn test_read_nonblocking() { assert_eq!(&input_buffer[..5], b"HTTP/"); } -#[test] -fn broken_try_clone_doesnt_crash() { - let context = SslContext::new(SslMethod::Sslv23).unwrap(); - let inner = TcpStream::connect("example.com:443").unwrap(); - let stream1 = SslStream::connect(&context, inner).unwrap(); - let _stream2 = stream1.try_clone().unwrap(); -} - #[test] #[should_panic(expected = "blammo")] #[cfg(feature = "nightly")] From fa622326490e1dd27df4d42b4097ca574deedb3f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 30 Jan 2016 12:55:22 -0800 Subject: [PATCH 03/96] Error reform --- openssl/src/asn1/mod.rs | 7 +- openssl/src/bio/mod.rs | 8 +- openssl/src/bn/mod.rs | 108 ++++++++--------- openssl/src/crypto/pkey.rs | 37 +++--- openssl/src/crypto/rsa.rs | 22 ++-- openssl/src/dh/mod.rs | 14 +-- openssl/src/error.rs | 137 +++++++++++++++++++++ openssl/src/lib.rs | 7 +- openssl/src/macros.rs | 4 +- openssl/src/ssl/bio.rs | 4 +- openssl/src/ssl/error.rs | 228 ++--------------------------------- openssl/src/ssl/mod.rs | 123 +++++++------------ openssl/src/ssl/tests/mod.rs | 2 +- openssl/src/x509/mod.rs | 32 ++--- 14 files changed, 318 insertions(+), 415 deletions(-) create mode 100644 openssl/src/error.rs diff --git a/openssl/src/asn1/mod.rs b/openssl/src/asn1/mod.rs index d5561b62..202909ec 100644 --- a/openssl/src/asn1/mod.rs +++ b/openssl/src/asn1/mod.rs @@ -2,8 +2,7 @@ use libc::c_long; use std::ptr; use ffi; -use ssl::error::SslError; - +use error::ErrorStack; pub struct Asn1Time { handle: *mut ffi::ASN1_TIME, @@ -19,7 +18,7 @@ impl Asn1Time { } } - fn new_with_period(period: u64) -> Result { + fn new_with_period(period: u64) -> Result { ffi::init(); let handle = unsafe { @@ -29,7 +28,7 @@ impl Asn1Time { } /// Creates a new time on specified interval in days from now - pub fn days_from_now(days: u32) -> Result { + pub fn days_from_now(days: u32) -> Result { Asn1Time::new_with_period(days as u64 * 60 * 60 * 24) } diff --git a/openssl/src/bio/mod.rs b/openssl/src/bio/mod.rs index 4c9b20b0..2e99284f 100644 --- a/openssl/src/bio/mod.rs +++ b/openssl/src/bio/mod.rs @@ -6,7 +6,7 @@ use std::cmp; use ffi; use ffi_extras; -use ssl::error::SslError; +use error::ErrorStack; pub struct MemBio { bio: *mut ffi::BIO, @@ -25,7 +25,7 @@ impl Drop for MemBio { impl MemBio { /// Creates a new owned memory based BIO - pub fn new() -> Result { + pub fn new() -> Result { ffi::init(); let bio = unsafe { ffi::BIO_new(ffi::BIO_s_mem()) }; @@ -81,7 +81,7 @@ impl Read for MemBio { if is_eof != 0 { Ok(0) } else { - Err(io::Error::new(io::ErrorKind::Other, SslError::get())) + Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get())) } } else { Ok(ret as usize) @@ -95,7 +95,7 @@ impl Write for MemBio { let ret = unsafe { ffi::BIO_write(self.bio, buf.as_ptr() as *const c_void, len) }; if ret < 0 { - Err(io::Error::new(io::ErrorKind::Other, SslError::get())) + Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get())) } else { Ok(ret as usize) } diff --git a/openssl/src/bn/mod.rs b/openssl/src/bn/mod.rs index d548e9ef..eb697248 100644 --- a/openssl/src/bn/mod.rs +++ b/openssl/src/bn/mod.rs @@ -4,7 +4,7 @@ use std::cmp::Ordering; use std::{fmt, ptr, mem}; use ffi; -use ssl::error::SslError; +use error::ErrorStack; pub struct BigNum(*mut ffi::BIGNUM); @@ -20,7 +20,7 @@ macro_rules! with_ctx( ($name:ident, $action:block) => ({ let $name = ffi::BN_CTX_new(); if ($name).is_null() { - Err(SslError::get()) + Err(ErrorStack::get()) } else { let r = $action; ffi::BN_CTX_free($name); @@ -37,7 +37,7 @@ macro_rules! with_bn( if $action { Ok($name) } else { - Err(SslError::get()) + Err(ErrorStack::get()) } }, Err(err) => Err(err), @@ -52,13 +52,13 @@ macro_rules! with_bn_in_ctx( Ok($name) => { let $ctx_name = ffi::BN_CTX_new(); if ($ctx_name).is_null() { - Err(SslError::get()) + Err(ErrorStack::get()) } else { let r = if $action { Ok($name) } else { - Err(SslError::get()) + Err(ErrorStack::get()) }; ffi::BN_CTX_free($ctx_name); r @@ -70,7 +70,7 @@ macro_rules! with_bn_in_ctx( ); impl BigNum { - pub fn new() -> Result { + pub fn new() -> Result { unsafe { ffi::init(); @@ -79,14 +79,14 @@ impl BigNum { } } - pub fn new_from(n: u64) -> Result { + pub fn new_from(n: u64) -> Result { BigNum::new().and_then(|v| unsafe { try_ssl!(ffi::BN_set_word(v.raw(), n as c_ulong)); Ok(v) }) } - pub fn from_dec_str(s: &str) -> Result { + pub fn from_dec_str(s: &str) -> Result { BigNum::new().and_then(|v| unsafe { let c_str = CString::new(s.as_bytes()).unwrap(); try_ssl!(ffi::BN_dec2bn(v.raw_ptr(), c_str.as_ptr() as *const _)); @@ -94,7 +94,7 @@ impl BigNum { }) } - pub fn from_hex_str(s: &str) -> Result { + pub fn from_hex_str(s: &str) -> Result { BigNum::new().and_then(|v| unsafe { let c_str = CString::new(s.as_bytes()).unwrap(); try_ssl!(ffi::BN_hex2bn(v.raw_ptr(), c_str.as_ptr() as *const _)); @@ -102,26 +102,26 @@ impl BigNum { }) } - pub unsafe fn new_from_ffi(orig: *mut ffi::BIGNUM) -> Result { + pub unsafe fn new_from_ffi(orig: *mut ffi::BIGNUM) -> Result { if orig.is_null() { panic!("Null Pointer was supplied to BigNum::new_from_ffi"); } let r = ffi::BN_dup(orig); if r.is_null() { - Err(SslError::get()) + Err(ErrorStack::get()) } else { Ok(BigNum(r)) } } - pub fn new_from_slice(n: &[u8]) -> Result { + pub fn new_from_slice(n: &[u8]) -> Result { BigNum::new().and_then(|v| unsafe { try_ssl_null!(ffi::BN_bin2bn(n.as_ptr(), n.len() as c_int, v.raw())); Ok(v) }) } - pub fn checked_sqr(&self) -> Result { + pub fn checked_sqr(&self) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_sqr(r.raw(), self.raw(), ctx) == 1 @@ -129,7 +129,7 @@ impl BigNum { } } - pub fn checked_nnmod(&self, n: &BigNum) -> Result { + pub fn checked_nnmod(&self, n: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_nnmod(r.raw(), self.raw(), n.raw(), ctx) == 1 @@ -137,7 +137,7 @@ impl BigNum { } } - pub fn checked_mod_add(&self, a: &BigNum, n: &BigNum) -> Result { + pub fn checked_mod_add(&self, a: &BigNum, n: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mod_add(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1 @@ -145,7 +145,7 @@ impl BigNum { } } - pub fn checked_mod_sub(&self, a: &BigNum, n: &BigNum) -> Result { + pub fn checked_mod_sub(&self, a: &BigNum, n: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mod_sub(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1 @@ -153,7 +153,7 @@ impl BigNum { } } - pub fn checked_mod_mul(&self, a: &BigNum, n: &BigNum) -> Result { + pub fn checked_mod_mul(&self, a: &BigNum, n: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mod_mul(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1 @@ -161,7 +161,7 @@ impl BigNum { } } - pub fn checked_mod_sqr(&self, n: &BigNum) -> Result { + pub fn checked_mod_sqr(&self, n: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mod_sqr(r.raw(), self.raw(), n.raw(), ctx) == 1 @@ -169,7 +169,7 @@ impl BigNum { } } - pub fn checked_exp(&self, p: &BigNum) -> Result { + pub fn checked_exp(&self, p: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_exp(r.raw(), self.raw(), p.raw(), ctx) == 1 @@ -177,7 +177,7 @@ impl BigNum { } } - pub fn checked_mod_exp(&self, p: &BigNum, n: &BigNum) -> Result { + pub fn checked_mod_exp(&self, p: &BigNum, n: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mod_exp(r.raw(), self.raw(), p.raw(), n.raw(), ctx) == 1 @@ -185,7 +185,7 @@ impl BigNum { } } - pub fn checked_mod_inv(&self, n: &BigNum) -> Result { + pub fn checked_mod_inv(&self, n: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { !ffi::BN_mod_inverse(r.raw(), self.raw(), n.raw(), ctx).is_null() @@ -193,59 +193,59 @@ impl BigNum { } } - pub fn add_word(&mut self, w: c_ulong) -> Result<(), SslError> { + pub fn add_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> { unsafe { if ffi::BN_add_word(self.raw(), w) == 1 { Ok(()) } else { - Err(SslError::get()) + Err(ErrorStack::get()) } } } - pub fn sub_word(&mut self, w: c_ulong) -> Result<(), SslError> { + pub fn sub_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> { unsafe { if ffi::BN_sub_word(self.raw(), w) == 1 { Ok(()) } else { - Err(SslError::get()) + Err(ErrorStack::get()) } } } - pub fn mul_word(&mut self, w: c_ulong) -> Result<(), SslError> { + pub fn mul_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> { unsafe { if ffi::BN_mul_word(self.raw(), w) == 1 { Ok(()) } else { - Err(SslError::get()) + Err(ErrorStack::get()) } } } - pub fn div_word(&mut self, w: c_ulong) -> Result { + pub fn div_word(&mut self, w: c_ulong) -> Result { unsafe { let result = ffi::BN_div_word(self.raw(), w); if result != !0 as c_ulong { Ok(result) } else { - Err(SslError::get()) + Err(ErrorStack::get()) } } } - pub fn mod_word(&self, w: c_ulong) -> Result { + pub fn mod_word(&self, w: c_ulong) -> Result { unsafe { let result = ffi::BN_mod_word(self.raw(), w); if result != !0 as c_ulong { Ok(result) } else { - Err(SslError::get()) + Err(ErrorStack::get()) } } } - pub fn checked_gcd(&self, a: &BigNum) -> Result { + pub fn checked_gcd(&self, a: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_gcd(r.raw(), self.raw(), a.raw(), ctx) == 1 @@ -257,7 +257,7 @@ impl BigNum { safe: bool, add: Option<&BigNum>, rem: Option<&BigNum>) - -> Result { + -> Result { unsafe { with_bn_in_ctx!(r, ctx, { let add_arg = add.map(|a| a.raw()).unwrap_or(ptr::null_mut()); @@ -273,7 +273,7 @@ impl BigNum { } } - pub fn is_prime(&self, checks: i32) -> Result { + pub fn is_prime(&self, checks: i32) -> Result { unsafe { with_ctx!(ctx, { Ok(ffi::BN_is_prime_ex(self.raw(), checks as c_int, ctx, ptr::null()) == 1) @@ -281,7 +281,7 @@ impl BigNum { } } - pub fn is_prime_fast(&self, checks: i32, do_trial_division: bool) -> Result { + pub fn is_prime_fast(&self, checks: i32, do_trial_division: bool) -> Result { unsafe { with_ctx!(ctx, { Ok(ffi::BN_is_prime_fasttest_ex(self.raw(), @@ -293,7 +293,7 @@ impl BigNum { } } - pub fn checked_new_random(bits: i32, prop: RNGProperty, odd: bool) -> Result { + pub fn checked_new_random(bits: i32, prop: RNGProperty, odd: bool) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_rand(r.raw(), bits as c_int, prop as c_int, odd as c_int) == 1 @@ -304,7 +304,7 @@ impl BigNum { pub fn checked_new_pseudo_random(bits: i32, prop: RNGProperty, odd: bool) - -> Result { + -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_pseudo_rand(r.raw(), bits as c_int, prop as c_int, odd as c_int) == 1 @@ -312,7 +312,7 @@ impl BigNum { } } - pub fn checked_rand_in_range(&self) -> Result { + pub fn checked_rand_in_range(&self) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_rand_range(r.raw(), self.raw()) == 1 @@ -320,7 +320,7 @@ impl BigNum { } } - pub fn checked_pseudo_rand_in_range(&self) -> Result { + pub fn checked_pseudo_rand_in_range(&self) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_pseudo_rand_range(r.raw(), self.raw()) == 1 @@ -328,22 +328,22 @@ impl BigNum { } } - pub fn set_bit(&mut self, n: i32) -> Result<(), SslError> { + pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> { unsafe { if ffi::BN_set_bit(self.raw(), n as c_int) == 1 { Ok(()) } else { - Err(SslError::get()) + Err(ErrorStack::get()) } } } - pub fn clear_bit(&mut self, n: i32) -> Result<(), SslError> { + pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> { unsafe { if ffi::BN_clear_bit(self.raw(), n as c_int) == 1 { Ok(()) } else { - Err(SslError::get()) + Err(ErrorStack::get()) } } } @@ -352,17 +352,17 @@ impl BigNum { unsafe { ffi::BN_is_bit_set(self.raw(), n as c_int) == 1 } } - pub fn mask_bits(&mut self, n: i32) -> Result<(), SslError> { + pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> { unsafe { if ffi::BN_mask_bits(self.raw(), n as c_int) == 1 { Ok(()) } else { - Err(SslError::get()) + Err(ErrorStack::get()) } } } - pub fn checked_shl1(&self) -> Result { + pub fn checked_shl1(&self) -> Result { unsafe { with_bn!(r, { ffi::BN_lshift1(r.raw(), self.raw()) == 1 @@ -370,7 +370,7 @@ impl BigNum { } } - pub fn checked_shr1(&self) -> Result { + pub fn checked_shr1(&self) -> Result { unsafe { with_bn!(r, { ffi::BN_rshift1(r.raw(), self.raw()) == 1 @@ -378,7 +378,7 @@ impl BigNum { } } - pub fn checked_add(&self, a: &BigNum) -> Result { + pub fn checked_add(&self, a: &BigNum) -> Result { unsafe { with_bn!(r, { ffi::BN_add(r.raw(), self.raw(), a.raw()) == 1 @@ -386,7 +386,7 @@ impl BigNum { } } - pub fn checked_sub(&self, a: &BigNum) -> Result { + pub fn checked_sub(&self, a: &BigNum) -> Result { unsafe { with_bn!(r, { ffi::BN_sub(r.raw(), self.raw(), a.raw()) == 1 @@ -394,7 +394,7 @@ impl BigNum { } } - pub fn checked_mul(&self, a: &BigNum) -> Result { + pub fn checked_mul(&self, a: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mul(r.raw(), self.raw(), a.raw(), ctx) == 1 @@ -402,7 +402,7 @@ impl BigNum { } } - pub fn checked_div(&self, a: &BigNum) -> Result { + pub fn checked_div(&self, a: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_div(r.raw(), ptr::null_mut(), self.raw(), a.raw(), ctx) == 1 @@ -410,7 +410,7 @@ impl BigNum { } } - pub fn checked_mod(&self, a: &BigNum) -> Result { + pub fn checked_mod(&self, a: &BigNum) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_div(ptr::null_mut(), r.raw(), self.raw(), a.raw(), ctx) == 1 @@ -418,7 +418,7 @@ impl BigNum { } } - pub fn checked_shl(&self, a: &i32) -> Result { + pub fn checked_shl(&self, a: &i32) -> Result { unsafe { with_bn!(r, { ffi::BN_lshift(r.raw(), self.raw(), *a as c_int) == 1 @@ -426,7 +426,7 @@ impl BigNum { } } - pub fn checked_shr(&self, a: &i32) -> Result { + pub fn checked_shr(&self, a: &i32) -> Result { unsafe { with_bn!(r, { ffi::BN_rshift(r.raw(), self.raw(), *a as c_int) == 1 diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index ba0a16b6..1020a82e 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -8,8 +8,8 @@ use bio::MemBio; use crypto::hash; use crypto::hash::Type as HashType; use ffi; -use ssl::error::{SslError, StreamError}; use crypto::rsa::RSA; +use error::ErrorStack; #[derive(Copy, Clone)] pub enum Parts { @@ -85,17 +85,18 @@ impl PKey { } /// Reads private key from PEM, takes ownership of handle - pub fn private_key_from_pem(reader: &mut R) -> Result + pub fn private_key_from_pem(reader: &mut R) -> io::Result where R: Read { let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio)); unsafe { let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), ptr::null_mut(), None, ptr::null_mut())); + Ok(PKey { evp: evp as *mut ffi::EVP_PKEY, parts: Parts::Both, @@ -104,11 +105,11 @@ impl PKey { } /// Reads public key from PEM, takes ownership of handle - pub fn public_key_from_pem(reader: &mut R) -> Result + pub fn public_key_from_pem(reader: &mut R) -> io::Result where R: Read { let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio)); unsafe { let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.get_handle(), @@ -123,13 +124,15 @@ impl PKey { } /// Reads an RSA private key from PEM, takes ownership of handle - pub fn private_rsa_key_from_pem(reader: &mut R) -> Result + pub fn private_rsa_key_from_pem(reader: &mut R) -> io::Result where R: Read { let rsa = try!(RSA::private_key_from_pem(reader)); unsafe { let evp = try_ssl_null!(ffi::EVP_PKEY_new()); - try_ssl!(ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr())); + if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 { + return Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get())); + } Ok(PKey { evp: evp, @@ -139,13 +142,15 @@ impl PKey { } /// Reads an RSA public key from PEM, takes ownership of handle - pub fn public_rsa_key_from_pem(reader: &mut R) -> Result + pub fn public_rsa_key_from_pem(reader: &mut R) -> io::Result where R: Read { let rsa = try!(RSA::public_key_from_pem(reader)); unsafe { let evp = try_ssl_null!(ffi::EVP_PKEY_new()); - try_ssl!(ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr())); + if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 { + return Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get())); + } Ok(PKey { evp: evp, @@ -260,7 +265,7 @@ impl PKey { // FIXME: also add password and encryption pub fn write_pem(&self, writer: &mut W /* , password: Option */) - -> Result<(), SslError> { + -> io::Result<()> { let mut mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.get_handle(), @@ -273,19 +278,19 @@ impl PKey { } let mut buf = vec![]; - try!(mem_bio.read_to_end(&mut buf).map_err(StreamError)); - writer.write_all(&buf).map_err(StreamError) + try!(mem_bio.read_to_end(&mut buf)); + writer.write_all(&buf) } /// Stores public key as a PEM pub fn write_pub_pem(&self, writer: &mut W /* , password: Option */) - -> Result<(), SslError> { + -> io::Result<()> { let mut mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.get_handle(), self.evp)) } let mut buf = vec![]; - try!(mem_bio.read_to_end(&mut buf).map_err(StreamError)); - writer.write_all(&buf).map_err(StreamError) + try!(mem_bio.read_to_end(&mut buf)); + writer.write_all(&buf) } /** @@ -370,7 +375,7 @@ impl PKey { openssl_padding_code(padding)); if rv < 0 as c_int { - // println!("{:?}", SslError::get()); + // println!("{:?}", ErrorStack::get()); vec![] } else { r.truncate(rv as usize); diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 6fcb5b07..11970933 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -1,11 +1,11 @@ use ffi; use std::fmt; -use ssl::error::{SslError, StreamError}; use std::ptr; use std::io::{self, Read}; use bn::BigNum; use bio::MemBio; +use error::ErrorStack; pub struct RSA(*mut ffi::RSA); @@ -20,7 +20,7 @@ impl Drop for RSA { impl RSA { /// only useful for associating the key material directly with the key, it's safer to use /// the supplied load and save methods for DER formatted keys. - pub fn from_public_components(n: BigNum, e: BigNum) -> Result { + pub fn from_public_components(n: BigNum, e: BigNum) -> Result { unsafe { let rsa = try_ssl_null!(ffi::RSA_new()); (*rsa).n = n.into_raw(); @@ -35,11 +35,11 @@ impl RSA { } /// Reads an RSA private key from PEM formatted data. - pub fn private_key_from_pem(reader: &mut R) -> Result + pub fn private_key_from_pem(reader: &mut R) -> io::Result where R: Read { let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio)); unsafe { let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.get_handle(), @@ -51,11 +51,11 @@ impl RSA { } /// Reads an RSA public key from PEM formatted data. - pub fn public_key_from_pem(reader: &mut R) -> Result + pub fn public_key_from_pem(reader: &mut R) -> io::Result where R: Read { let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio)); unsafe { let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.get_handle(), @@ -71,7 +71,7 @@ impl RSA { } // The following getters are unsafe, since BigNum::new_from_ffi fails upon null pointers - pub fn n(&self) -> Result { + pub fn n(&self) -> Result { unsafe { BigNum::new_from_ffi((*self.0).n) } @@ -83,13 +83,13 @@ impl RSA { } } - pub fn d(&self) -> Result { + pub fn d(&self) -> Result { unsafe { BigNum::new_from_ffi((*self.0).d) } } - pub fn e(&self) -> Result { + pub fn e(&self) -> Result { unsafe { BigNum::new_from_ffi((*self.0).e) } @@ -101,13 +101,13 @@ impl RSA { } } - pub fn p(&self) -> Result { + pub fn p(&self) -> Result { unsafe { BigNum::new_from_ffi((*self.0).p) } } - pub fn q(&self) -> Result { + pub fn q(&self) -> Result { unsafe { BigNum::new_from_ffi((*self.0).q) } diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index d2f26c3f..14bf076d 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -1,7 +1,7 @@ use ffi; use std::io; use std::io::prelude::*; -use ssl::error::{SslError, StreamError}; +use error::ErrorStack; use bio::MemBio; use bn::BigNum; use std::mem; @@ -10,7 +10,7 @@ use std::ptr; pub struct DH(*mut ffi::DH); impl DH { - pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result { + pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result { let dh = try_ssl_null!(unsafe { ffi::DH_new_from_params(p.raw(), g.raw(), q.raw()) }); mem::forget(p); mem::forget(g); @@ -18,11 +18,11 @@ impl DH { Ok(DH(dh)) } - pub fn from_pem(reader: &mut R) -> Result + pub fn from_pem(reader: &mut R) -> io::Result where R: Read { let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio)); let dh = unsafe { ffi::PEM_read_bio_DHparams(mem_bio.get_handle(), ptr::null_mut(), None, ptr::null_mut()) }; @@ -31,19 +31,19 @@ impl DH { } #[cfg(feature = "rfc5114")] - pub fn get_1024_160() -> Result { + pub fn get_1024_160() -> Result { let dh = try_ssl_null!(unsafe { ffi::DH_get_1024_160() }); Ok(DH(dh)) } #[cfg(feature = "rfc5114")] - pub fn get_2048_224() -> Result { + pub fn get_2048_224() -> Result { let dh = try_ssl_null!(unsafe { ffi::DH_get_2048_224() }); Ok(DH(dh)) } #[cfg(feature = "rfc5114")] - pub fn get_2048_256() -> Result { + pub fn get_2048_256() -> Result { let dh = try_ssl_null!(unsafe { ffi::DH_get_2048_256() }); Ok(DH(dh)) } diff --git a/openssl/src/error.rs b/openssl/src/error.rs new file mode 100644 index 00000000..5fa542c2 --- /dev/null +++ b/openssl/src/error.rs @@ -0,0 +1,137 @@ +use libc::c_ulong; +use std::fmt; +use std::error; +use std::ffi::CStr; +use std::io; +use std::str; + +use ffi; + +#[derive(Debug)] +pub struct ErrorStack(Vec); + +impl ErrorStack { + /// Returns the contents of the OpenSSL error stack. + pub fn get() -> ErrorStack { + let mut vec = vec![]; + while let Some(err) = Error::get() { + vec.push(err); + } + ErrorStack(vec) + } +} + +impl ErrorStack { + /// Returns the errors in the stack. + pub fn errors(&self) -> &[Error] { + &self.0 + } +} + +impl fmt::Display for ErrorStack { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut first = true; + for err in &self.0 { + if first { + try!(fmt.write_str(", ")); + first = false; + } + try!(write!(fmt, "{}", err)); + } + Ok(()) + } +} + +impl error::Error for ErrorStack { + fn description(&self) -> &str { + "An OpenSSL error stack" + } +} + +impl From for io::Error { + fn from(e: ErrorStack) -> io::Error { + io::Error::new(io::ErrorKind::Other, e) + } +} + +/// An error reported from OpenSSL. +pub struct Error(c_ulong); + +impl Error { + /// Returns the first error on the OpenSSL error stack. + pub fn get() -> Option { + ffi::init(); + + match unsafe { ffi::ERR_get_error() } { + 0 => None, + err => Some((Error(err))), + } + } + + /// Returns the raw OpenSSL error code for this error. + pub fn error_code(&self) -> c_ulong { + self.0 + } + + /// Returns the name of the library reporting the error. + pub fn library(&self) -> &'static str { + get_lib(self.0) + } + + /// Returns the name of the function reporting the error. + pub fn function(&self) -> &'static str { + get_func(self.0) + } + + /// Returns the reason for the error. + pub fn reason(&self) -> &'static str { + get_reason(self.0) + } +} + +impl fmt::Debug for Error { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Error") + .field("library", &self.library()) + .field("function", &self.function()) + .field("reason", &self.reason()) + .finish() + } +} + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(&self.reason()) + } +} + +impl error::Error for Error { + fn description(&self) -> &str { + "An OpenSSL error" + } +} + +fn get_lib(err: c_ulong) -> &'static str { + unsafe { + let cstr = ffi::ERR_lib_error_string(err); + let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); + str::from_utf8(bytes).unwrap() + } +} + +fn get_func(err: c_ulong) -> &'static str { + unsafe { + let cstr = ffi::ERR_func_error_string(err); + let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); + str::from_utf8(bytes).unwrap() + } +} + +fn get_reason(err: c_ulong) -> &'static str { + unsafe { + let cstr = ffi::ERR_reason_error_string(err); + let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); + str::from_utf8(bytes).unwrap() + } +} + diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 63926615..ae347eee 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -18,11 +18,12 @@ extern crate net2; mod macros; pub mod asn1; -pub mod bn; pub mod bio; +pub mod bn; pub mod crypto; pub mod dh; -pub mod ssl; -pub mod x509; +pub mod error; pub mod nid; +pub mod ssl; pub mod version; +pub mod x509; diff --git a/openssl/src/macros.rs b/openssl/src/macros.rs index 3e4bb429..35221f1c 100644 --- a/openssl/src/macros.rs +++ b/openssl/src/macros.rs @@ -13,7 +13,7 @@ macro_rules! try_ssl_stream { macro_rules! try_ssl_if { ($e:expr) => ( if $e { - return Err(SslError::get()) + return Err(::error::ErrorStack::get().into()) } ) } @@ -45,7 +45,7 @@ macro_rules! try_ssl_null{ macro_rules! lift_ssl_if{ ($e:expr) => ( { if $e { - Err(SslError::get()) + Err(::error::ErrorStack::get().into()) } else { Ok(()) } diff --git a/openssl/src/ssl/bio.rs b/openssl/src/ssl/bio.rs index e53545d7..44893b88 100644 --- a/openssl/src/ssl/bio.rs +++ b/openssl/src/ssl/bio.rs @@ -9,7 +9,7 @@ use std::ptr; use std::slice; use std::sync::Arc; -use ssl::error::SslError; +use error::ErrorStack; pub struct StreamState { pub stream: S, @@ -39,7 +39,7 @@ impl BioMethod { unsafe impl Send for BioMethod {} -pub fn new(stream: S) -> Result<(*mut BIO, Arc), SslError> { +pub fn new(stream: S) -> Result<(*mut BIO, Arc), ErrorStack> { let method = Arc::new(BioMethod::new::()); let state = Box::new(StreamState { diff --git a/openssl/src/ssl/error.rs b/openssl/src/ssl/error.rs index ba0c7458..95213361 100644 --- a/openssl/src/ssl/error.rs +++ b/openssl/src/ssl/error.rs @@ -1,15 +1,8 @@ -pub use self::SslError::*; -pub use self::OpensslError::*; - -use libc::c_ulong; use std::error; use std::error::Error as StdError; use std::fmt; -use std::ffi::CStr; use std::io; -use std::str; - -use ffi; +use error::ErrorStack; /// An SSL error. #[derive(Debug)] @@ -27,30 +20,16 @@ pub enum Error { /// An error reported by the underlying stream. Stream(io::Error), /// An error in the OpenSSL library. - Ssl(Vec), + Ssl(ErrorStack), } impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(fmt.write_str(self.description())); - match *self { - Error::Stream(ref err) => write!(fmt, ": {}", err), - Error::WantRead(ref err) => write!(fmt, ": {}", err), - Error::WantWrite(ref err) => write!(fmt, ": {}", err), - Error::Ssl(ref errs) => { - let mut first = true; - for err in errs { - if first { - try!(fmt.write_str(": ")); - first = false; - } else { - try!(fmt.write_str(", ")); - } - try!(fmt.write_str(&err.reason())) - } - Ok(()) - } - _ => Ok(()), + if let Some(err) = self.cause() { + write!(fmt, ": {}", err) + } else { + Ok(()) } } } @@ -72,201 +51,14 @@ impl error::Error for Error { Error::WantRead(ref err) => Some(err), Error::WantWrite(ref err) => Some(err), Error::Stream(ref err) => Some(err), + Error::Ssl(ref err) => Some(err), _ => None, } } } -/// An error reported from OpenSSL. -pub struct OpenSslError(c_ulong); - -impl OpenSslError { - /// Returns the contents of the OpenSSL error stack. - pub fn get_stack() -> Vec { - ffi::init(); - - let mut errs = vec![]; - loop { - match unsafe { ffi::ERR_get_error() } { - 0 => break, - err => errs.push(OpenSslError(err)), - } - } - errs - } - - /// Returns the raw OpenSSL error code for this error. - pub fn error_code(&self) -> c_ulong { - self.0 - } - - /// Returns the name of the library reporting the error. - pub fn library(&self) -> &'static str { - get_lib(self.0) - } - - /// Returns the name of the function reporting the error. - pub fn function(&self) -> &'static str { - get_func(self.0) - } - - /// Returns the reason for the error. - pub fn reason(&self) -> &'static str { - get_reason(self.0) +impl From for Error { + fn from(e: ErrorStack) -> Error { + Error::Ssl(e) } } - -impl fmt::Debug for OpenSslError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("OpenSslError") - .field("library", &self.library()) - .field("function", &self.function()) - .field("reason", &self.reason()) - .finish() - } -} - -impl fmt::Display for OpenSslError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.write_str(&self.reason()) - } -} - -impl error::Error for OpenSslError { - fn description(&self) -> &str { - "An OpenSSL error" - } -} - -/// An SSL error -#[derive(Debug)] -pub enum SslError { - /// The underlying stream reported an error - StreamError(io::Error), - /// The SSL session has been closed by the other end - SslSessionClosed, - /// An error in the OpenSSL library - OpenSslErrors(Vec), -} - -impl fmt::Display for SslError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - try!(fmt.write_str(error::Error::description(self))); - if let OpenSslErrors(ref errs) = *self { - let mut first = true; - for err in errs { - if first { - try!(fmt.write_str(": ")); - first = false; - } else { - try!(fmt.write_str(", ")); - } - match *err { - UnknownError { ref reason, .. } => try!(fmt.write_str(reason)), - } - } - } - - Ok(()) - } -} - -impl error::Error for SslError { - fn description(&self) -> &str { - match *self { - StreamError(_) => "The underlying stream reported an error", - SslSessionClosed => "The SSL session has been closed by the other end", - OpenSslErrors(_) => "An error in the OpenSSL library", - } - } - - fn cause(&self) -> Option<&error::Error> { - match *self { - StreamError(ref err) => Some(err as &error::Error), - _ => None, - } - } -} - -/// An error from the OpenSSL library -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum OpensslError { - /// An unknown error - UnknownError { - /// The library reporting the error - library: String, - /// The function reporting the error - function: String, - /// The reason for the error - reason: String, - }, -} - -impl OpensslError { - pub fn from_error_code(err: c_ulong) -> OpensslError { - ffi::init(); - UnknownError { - library: get_lib(err).to_owned(), - function: get_func(err).to_owned(), - reason: get_reason(err).to_owned(), - } - } -} - -fn get_lib(err: c_ulong) -> &'static str { - unsafe { - let cstr = ffi::ERR_lib_error_string(err); - let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); - str::from_utf8(bytes).unwrap() - } -} - -fn get_func(err: c_ulong) -> &'static str { - unsafe { - let cstr = ffi::ERR_func_error_string(err); - let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); - str::from_utf8(bytes).unwrap() - } -} - -fn get_reason(err: c_ulong) -> &'static str { - unsafe { - let cstr = ffi::ERR_reason_error_string(err); - let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); - str::from_utf8(bytes).unwrap() - } -} - -impl SslError { - /// Creates a new `OpenSslErrors` with the current contents of the error - /// stack. - pub fn get() -> SslError { - let mut errs = vec![]; - loop { - match unsafe { ffi::ERR_get_error() } { - 0 => break, - err => errs.push(OpensslError::from_error_code(err)), - } - } - OpenSslErrors(errs) - } - - /// Creates an `SslError` from the raw numeric error code. - pub fn from_error(err: c_ulong) -> SslError { - OpenSslErrors(vec![OpensslError::from_error_code(err)]) - } -} - -#[test] -fn test_uknown_error_should_have_correct_messages() { - let errs = match SslError::from_error(336032784) { - OpenSslErrors(errs) => errs, - _ => panic!("This should always be an `OpenSslErrors` variant."), - }; - - let UnknownError { ref library, ref function, ref reason } = errs[0]; - - assert_eq!(&library[..], "SSL routines"); - assert_eq!(&function[..], "SSL23_GET_SERVER_HELLO"); - assert_eq!(&reason[..], "sslv3 alert handshake failure"); -} diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index c713aeb2..f9534bc2 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -25,9 +25,9 @@ use std::os::windows::io::{AsRawSocket, RawSocket}; use ffi; use ffi_extras; use dh::DH; -use ssl::error::{SslError, OpenSslError}; use x509::{X509StoreContext, X509FileType, X509}; use crypto::pkey::PKey; +use error::ErrorStack; pub mod error; mod bio; @@ -513,9 +513,9 @@ pub type ServerNameCallbackData = fn(ssl: &mut Ssl, ad: &mut i32, data: &T) - // FIXME: macro may be instead of inlining? #[inline] -fn wrap_ssl_result(res: c_int) -> Result<(), SslError> { +fn wrap_ssl_result(res: c_int) -> Result<(), ErrorStack> { if res == 0 { - Err(SslError::get()) + Err(ErrorStack::get()) } else { Ok(()) } @@ -558,7 +558,7 @@ impl SslContext { } /// Creates a new SSL context. - pub fn new(method: SslMethod) -> Result { + pub fn new(method: SslMethod) -> Result { init(); let ctx = try_ssl_null!(unsafe { ffi::SSL_CTX_new(method.to_raw()) }); @@ -647,7 +647,7 @@ impl SslContext { } } - pub fn set_tmp_dh(&self, dh: DH) -> Result<(), SslError> { + pub fn set_tmp_dh(&self, dh: DH) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 }) } @@ -656,13 +656,13 @@ impl SslContext { /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR` /// environment variables if present, or defaults specified at OpenSSL /// build time otherwise. - pub fn set_default_verify_paths(&mut self) -> Result<(), SslError> { + pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_set_default_verify_paths(self.ctx) }) } #[allow(non_snake_case)] /// Specifies the file that contains trusted CA certificates. - pub fn set_CA_file>(&mut self, file: P) -> Result<(), SslError> { + pub fn set_CA_file>(&mut self, file: P) -> Result<(), ErrorStack> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result(unsafe { ffi::SSL_CTX_load_verify_locations(self.ctx, file.as_ptr() as *const _, ptr::null()) @@ -677,7 +677,7 @@ impl SslContext { /// /// This value should be set when using client certificates, or each request will fail /// handshake and need to be restarted. - pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), SslError> { + pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_set_session_id_context(self.ctx, sid_ctx.as_ptr(), sid_ctx.len() as u32) }) @@ -687,7 +687,7 @@ impl SslContext { pub fn set_certificate_file>(&mut self, file: P, file_type: X509FileType) - -> Result<(), SslError> { + -> Result<(), ErrorStack> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate_file(self.ctx, @@ -700,7 +700,7 @@ impl SslContext { pub fn set_certificate_chain_file>(&mut self, file: P, file_type: X509FileType) - -> Result<(), SslError> { + -> Result<(), ErrorStack> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate_chain_file(self.ctx, @@ -710,13 +710,13 @@ impl SslContext { } /// Specifies the certificate - pub fn set_certificate(&mut self, cert: &X509) -> Result<(), SslError> { + pub fn set_certificate(&mut self, cert: &X509) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate(self.ctx, cert.get_handle()) }) } /// Adds a certificate to the certificate chain presented together with the /// certificate specified using set_certificate() - pub fn add_extra_chain_cert(&mut self, cert: &X509) -> Result<(), SslError> { + pub fn add_extra_chain_cert(&mut self, cert: &X509) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_add_extra_chain_cert(self.ctx, cert.get_handle()) as c_int }) @@ -726,7 +726,7 @@ impl SslContext { pub fn set_private_key_file>(&mut self, file: P, file_type: X509FileType) - -> Result<(), SslError> { + -> Result<(), ErrorStack> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey_file(self.ctx, @@ -736,16 +736,16 @@ impl SslContext { } /// Specifies the private key - pub fn set_private_key(&mut self, key: &PKey) -> Result<(), SslError> { + pub fn set_private_key(&mut self, key: &PKey) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey(self.ctx, key.get_handle()) }) } /// Check consistency of private key and certificate - pub fn check_private_key(&mut self) -> Result<(), SslError> { + pub fn check_private_key(&mut self) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_check_private_key(self.ctx) }) } - pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), SslError> { + pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { let cipher_list = CString::new(cipher_list).unwrap(); ffi::SSL_CTX_set_cipher_list(self.ctx, cipher_list.as_ptr() as *const _) @@ -757,7 +757,7 @@ impl SslContext { /// /// This method requires OpenSSL >= 1.0.2 or LibreSSL and the `ecdh_auto` feature. #[cfg(feature = "ecdh_auto")] - pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), SslError> { + pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_ecdh_auto(self.ctx, onoff as c_int) }) } @@ -922,7 +922,7 @@ impl Drop for Ssl { } impl Ssl { - pub fn new(ctx: &SslContext) -> Result { + pub fn new(ctx: &SslContext) -> Result { let ssl = try_ssl_null!(unsafe { ffi::SSL_new(ctx.ctx) }); let ssl = Ssl { ssl: ssl }; Ok(ssl) @@ -950,9 +950,9 @@ impl Ssl { unsafe { ffi::SSL_write(self.ssl, buf.as_ptr() as *const c_void, len) } } - fn get_error(&self, ret: c_int) -> LibSslError { + fn get_error(&self, ret: c_int) -> LibErrorStack { let err = unsafe { ffi::SSL_get_error(self.ssl, ret) }; - match LibSslError::from_i32(err as i32) { + match LibErrorStack::from_i32(err as i32) { Some(err) => err, None => unreachable!(), } @@ -1013,7 +1013,7 @@ impl Ssl { } /// Sets the host name to be used with SNI (Server Name Indication). - pub fn set_hostname(&self, hostname: &str) -> Result<(), SslError> { + pub fn set_hostname(&self, hostname: &str) -> Result<(), ErrorStack> { let cstr = CString::new(hostname).unwrap(); let ret = unsafe { ffi_extras::SSL_set_tlsext_host_name(self.ssl, cstr.as_ptr() as *const _) @@ -1021,7 +1021,7 @@ impl Ssl { // For this case, 0 indicates failure. if ret == 0 { - Err(SslError::get()) + Err(ErrorStack::get()) } else { Ok(()) } @@ -1162,18 +1162,18 @@ impl Ssl { } } -macro_rules! make_LibSslError { +macro_rules! make_LibErrorStack { ($($variant:ident = $value:ident),+) => { #[derive(Debug)] #[repr(i32)] - enum LibSslError { + enum LibErrorStack { $($variant = ffi::$value),+ } - impl LibSslError { - fn from_i32(val: i32) -> Option { + impl LibErrorStack { + fn from_i32(val: i32) -> Option { match val { - $(ffi::$value => Some(LibSslError::$variant),)+ + $(ffi::$value => Some(LibErrorStack::$variant),)+ _ => None } } @@ -1181,7 +1181,7 @@ macro_rules! make_LibSslError { } } -make_LibSslError! { +make_LibErrorStack! { ErrorNone = SSL_ERROR_NONE, ErrorSsl = SSL_ERROR_SSL, ErrorWantRead = SSL_ERROR_WANT_READ, @@ -1241,31 +1241,31 @@ impl SslStream { } /// Creates an SSL/TLS client operating over the provided stream. - pub fn connect(ssl: T, stream: S) -> Result { + pub fn connect(ssl: T, stream: S) -> Result { let ssl = try!(ssl.into_ssl()); let mut stream = Self::new_base(ssl, stream); let ret = stream.ssl.connect(); if ret > 0 { Ok(stream) } else { - match stream.make_old_error(ret) { - Some(err) => Err(err), - None => Ok(stream), + match stream.make_error(ret) { + Error::WantRead(..) | Error::WantWrite(..) => Ok(stream), + err => Err(err) } } } /// Creates an SSL/TLS server operating over the provided stream. - pub fn accept(ssl: T, stream: S) -> Result { + pub fn accept(ssl: T, stream: S) -> Result { let ssl = try!(ssl.into_ssl()); let mut stream = Self::new_base(ssl, stream); let ret = stream.ssl.accept(); if ret > 0 { Ok(stream) } else { - match stream.make_old_error(ret) { - Some(err) => Err(err), - None => Ok(stream), + match stream.make_error(ret) { + Error::WantRead(..) | Error::WantWrite(..) => Ok(stream), + err => Err(err) } } } @@ -1302,10 +1302,10 @@ impl SslStream { self.check_panic(); match self.ssl.get_error(ret) { - LibSslError::ErrorSsl => Error::Ssl(OpenSslError::get_stack()), - LibSslError::ErrorSyscall => { - let errs = OpenSslError::get_stack(); - if errs.is_empty() { + LibErrorStack::ErrorSsl => Error::Ssl(ErrorStack::get()), + LibErrorStack::ErrorSyscall => { + let errs = ErrorStack::get(); + if errs.errors().is_empty() { if ret == 0 { Error::Stream(io::Error::new(io::ErrorKind::ConnectionAborted, "unexpected EOF observed")) @@ -1316,9 +1316,9 @@ impl SslStream { Error::Ssl(errs) } } - LibSslError::ErrorZeroReturn => Error::ZeroReturn, - LibSslError::ErrorWantWrite => Error::WantWrite(self.get_bio_error()), - LibSslError::ErrorWantRead => Error::WantRead(self.get_bio_error()), + LibErrorStack::ErrorZeroReturn => Error::ZeroReturn, + LibErrorStack::ErrorWantWrite => Error::WantWrite(self.get_bio_error()), + LibErrorStack::ErrorWantRead => Error::WantRead(self.get_bio_error()), err => { Error::Stream(io::Error::new(io::ErrorKind::Other, format!("unexpected error {:?}", err))) @@ -1326,37 +1326,6 @@ impl SslStream { } } - fn make_old_error(&mut self, ret: c_int) -> Option { - self.check_panic(); - - match self.ssl.get_error(ret) { - LibSslError::ErrorSsl => Some(SslError::get()), - LibSslError::ErrorSyscall => { - let err = SslError::get(); - let count = match err { - SslError::OpenSslErrors(ref v) => v.len(), - _ => unreachable!(), - }; - if count == 0 { - if ret == 0 { - Some(SslError::StreamError(io::Error::new(io::ErrorKind::ConnectionAborted, - "unexpected EOF observed"))) - } else { - Some(SslError::StreamError(self.get_bio_error())) - } - } else { - Some(err) - } - } - LibSslError::ErrorZeroReturn => Some(SslError::SslSessionClosed), - LibSslError::ErrorWantWrite | LibSslError::ErrorWantRead => None, - err => { - Some(SslError::StreamError(io::Error::new(io::ErrorKind::Other, - format!("unexpected error {:?}", err)))) - } - } - } - #[cfg(feature = "nightly")] fn check_panic(&mut self) { if let Some(err) = unsafe { bio::take_panic::(self.ssl.get_raw_rbio()) } { @@ -1437,17 +1406,17 @@ impl Write for SslStream { } pub trait IntoSsl { - fn into_ssl(self) -> Result; + fn into_ssl(self) -> Result; } impl IntoSsl for Ssl { - fn into_ssl(self) -> Result { + fn into_ssl(self) -> Result { Ok(self) } } impl<'a> IntoSsl for &'a SslContext { - fn into_ssl(self) -> Result { + fn into_ssl(self) -> Result { Ssl::new(self) } } diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 2ada0065..7f0f3415 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -403,7 +403,7 @@ run_test!(ssl_verify_callback, |method, stream| { } }); - match SslStream::connect_generic(ssl, stream) { + match SslStream::connect(ssl, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 0a242a15..a928b533 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -21,8 +21,8 @@ use crypto::pkey::{PKey, Parts}; use crypto::rand::rand_bytes; use ffi; use ffi_extras; -use ssl::error::{SslError, StreamError}; use nid::Nid; +use error::ErrorStack; pub mod extension; @@ -256,7 +256,7 @@ impl X509Generator { fn add_extension_internal(x509: *mut ffi::X509, exttype: &extension::ExtensionType, value: &str) - -> Result<(), SslError> { + -> Result<(), ErrorStack> { unsafe { let mut ctx: ffi::X509V3_CTX = mem::zeroed(); ffi::X509V3_set_ctx(&mut ctx, x509, x509, ptr::null_mut(), ptr::null_mut(), 0); @@ -288,7 +288,7 @@ impl X509Generator { fn add_name_internal(name: *mut ffi::X509_NAME, key: &str, value: &str) - -> Result<(), SslError> { + -> Result<(), ErrorStack> { let value_len = value.len() as c_int; lift_ssl!(unsafe { let key = CString::new(key.as_bytes()).unwrap(); @@ -319,7 +319,7 @@ impl X509Generator { } /// Generates a private key and a self-signed certificate and returns them - pub fn generate<'a>(&self) -> Result<(X509<'a>, PKey), SslError> { + pub fn generate<'a>(&self) -> Result<(X509<'a>, PKey), ErrorStack> { ffi::init(); let mut p_key = PKey::new(); @@ -331,7 +331,7 @@ impl X509Generator { /// Sets the certificate public-key, then self-sign and return it /// Note: That the bit-length of the private key is used (set_bitlength is ignored) - pub fn sign<'a>(&self, p_key: &PKey) -> Result, SslError> { + pub fn sign<'a>(&self, p_key: &PKey) -> Result, ErrorStack> { ffi::init(); unsafe { @@ -389,7 +389,7 @@ impl X509Generator { } /// Obtain a certificate signing request (CSR) - pub fn request(&self, p_key: &PKey) -> Result { + pub fn request(&self, p_key: &PKey) -> Result { let cert = match self.sign(p_key) { Ok(c) => c, Err(x) => return Err(x), @@ -442,11 +442,11 @@ impl<'ctx> X509<'ctx> { } /// Reads certificate from PEM, takes ownership of handle - pub fn from_pem(reader: &mut R) -> Result, SslError> + pub fn from_pem(reader: &mut R) -> io::Result> where R: Read { let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio)); unsafe { let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(), @@ -521,14 +521,14 @@ impl<'ctx> X509<'ctx> { } /// Writes certificate as PEM - pub fn write_pem(&self, writer: &mut W) -> Result<(), SslError> + pub fn write_pem(&self, writer: &mut W) -> io::Result<()> where W: Write { let mut mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), self.handle)); } - io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ()) + io::copy(&mut mem_bio, writer).map(|_| ()) } } @@ -610,11 +610,11 @@ impl X509Req { } /// Reads CSR from PEM - pub fn from_pem(reader: &mut R) -> Result + pub fn from_pem(reader: &mut R) -> io::Result where R: Read { let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio)); unsafe { let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.get_handle(), @@ -626,14 +626,14 @@ impl X509Req { } /// Writes CSR as PEM - pub fn write_pem(&self, writer: &mut W) -> Result<(), SslError> + pub fn write_pem(&self, writer: &mut W) -> io::Result<()> where W: Write { let mut mem_bio = try!(MemBio::new()); - unsafe { - try_ssl!(ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), self.handle)); + if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), self.handle) } != 1 { + return Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get())); } - io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ()) + io::copy(&mut mem_bio, writer).map(|_| ()) } } From a0549c160675c69935a71049143cabff4ec9aeee Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 8 Feb 2016 23:03:25 -0800 Subject: [PATCH 04/96] Adjust set_ssl_context API --- openssl/src/ssl/mod.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index f9534bc2..55a97c94 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1139,18 +1139,11 @@ impl Ssl { /// change the context corresponding to the current connection /// /// Returns a clone of the SslContext @ctx (ie: the new context). The old context is freed. - pub fn set_ssl_context(&self, ctx: &SslContext) -> SslContext { - // If duplication of @ctx's cert fails, this returns NULL. This _appears_ to only occur on - // allocation failures (meaning panicing is probably appropriate), but it might be nice to - // propogate the error. - assert!(unsafe { ffi::SSL_set_SSL_CTX(self.ssl, ctx.ctx) } != ptr::null_mut()); - - // FIXME: we return this reference here for compatibility, but it isn't actually required. - // This should be removed when a api-incompatabile version is to be released. - // - // ffi:SSL_set_SSL_CTX() returns copy of the ctx pointer passed to it, so it's easier for - // us to do the clone directly. - ctx.clone() + pub fn set_ssl_context(&self, ctx: &SslContext) -> Result<(), ErrorStack> { + unsafe { + try_ssl_null!(ffi::SSL_set_SSL_CTX(self.ssl, ctx.ctx)); + } + Ok(()) } /// obtain the context corresponding to the current connection From 696b1961ce31e77aebf5fcf13398c8c54ed22d87 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 1 May 2016 21:02:29 -0700 Subject: [PATCH 05/96] Rename getters in line with conventions --- openssl/src/ssl/mod.rs | 16 +++++++--------- openssl/src/ssl/tests/mod.rs | 4 ++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 55a97c94..1bb4a2d8 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -767,7 +767,7 @@ impl SslContext { SslContextOptions::from_bits(ret).unwrap() } - pub fn get_options(&mut self) -> SslContextOptions { + pub fn options(&mut self) -> SslContextOptions { let ret = unsafe { ffi_extras::SSL_CTX_get_options(self.ctx) }; SslContextOptions::from_bits(ret).unwrap() } @@ -982,7 +982,7 @@ impl Ssl { } } - pub fn get_current_cipher<'a>(&'a self) -> Option> { + pub fn current_cipher<'a>(&'a self) -> Option> { unsafe { let ptr = ffi::SSL_get_current_cipher(self.ssl); @@ -1119,7 +1119,7 @@ impl Ssl { Some(s) } - pub fn get_ssl_method(&self) -> Option { + pub fn ssl_method(&self) -> Option { unsafe { let method = ffi::SSL_get_ssl_method(self.ssl); SslMethod::from_raw(method) @@ -1127,7 +1127,7 @@ impl Ssl { } /// Returns the server's name for the current connection - pub fn get_servername(&self) -> Option { + pub fn servername(&self) -> Option { let name = unsafe { ffi::SSL_get_servername(self.ssl, ffi::TLSEXT_NAMETYPE_host_name) }; if name == ptr::null() { return None; @@ -1136,9 +1136,7 @@ impl Ssl { unsafe { String::from_utf8(CStr::from_ptr(name as *const _).to_bytes().to_vec()).ok() } } - /// change the context corresponding to the current connection - /// - /// Returns a clone of the SslContext @ctx (ie: the new context). The old context is freed. + /// Changes the context corresponding to the current connection. pub fn set_ssl_context(&self, ctx: &SslContext) -> Result<(), ErrorStack> { unsafe { try_ssl_null!(ffi::SSL_set_SSL_CTX(self.ssl, ctx.ctx)); @@ -1146,8 +1144,8 @@ impl Ssl { Ok(()) } - /// obtain the context corresponding to the current connection - pub fn get_ssl_context(&self) -> SslContext { + /// Returns the context corresponding to the current connection + pub fn ssl_context(&self) -> SslContext { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(self.ssl); SslContext::new_ref(ssl_ctx) diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 7f0f3415..e3b0a340 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -227,7 +227,7 @@ run_test!(new_sslstream, |method, stream| { run_test!(get_ssl_method, |method, _| { let ssl = Ssl::new(&SslContext::new(method).unwrap()).unwrap(); - assert_eq!(ssl.get_ssl_method(), Some(method)); + assert_eq!(ssl.ssl_method(), Some(method)); }); run_test!(verify_untrusted, |method, stream| { @@ -462,7 +462,7 @@ fn test_set_certificate_and_private_key() { run_test!(get_ctx_options, |method, _| { let mut ctx = SslContext::new(method).unwrap(); - ctx.get_options(); + ctx.options(); }); run_test!(set_ctx_options, |method, _| { From 61f65cd8d636dc0c7f08876f404819b20cc56ca0 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 1 May 2016 21:30:24 -0700 Subject: [PATCH 06/96] Move SslContext::set_verify to a closure based API --- openssl/src/ssl/mod.rs | 81 +++++--------------------- openssl/src/ssl/tests/mod.rs | 108 ++++++++++++++--------------------- 2 files changed, 56 insertions(+), 133 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 1bb4a2d8..9ef27238 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -44,7 +44,6 @@ extern "C" { fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX); } -static mut VERIFY_IDX: c_int = -1; static mut SNI_IDX: c_int = -1; /// Manually initialize SSL. @@ -56,10 +55,6 @@ pub fn init() { INIT.call_once(|| { ffi::init(); - let verify_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None); - assert!(verify_idx >= 0); - VERIFY_IDX = verify_idx; - let sni_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None); assert!(sni_idx >= 0); SNI_IDX = sni_idx; @@ -291,47 +286,19 @@ fn get_new_ssl_idx() -> c_int { } } -extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int { - unsafe { - let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); - let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx); - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, VERIFY_IDX); - let verify: Option = mem::transmute(verify); - - let ctx = X509StoreContext::new(x509_ctx); - - match verify { - None => preverify_ok, - Some(verify) => verify(preverify_ok != 0, &ctx) as c_int, - } - } -} - -extern "C" fn raw_verify_with_data(preverify_ok: c_int, - x509_ctx: *mut ffi::X509_STORE_CTX) - -> c_int - where T: Any + 'static +extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int + where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send { unsafe { let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx); let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - - let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, VERIFY_IDX); - let verify: Option> = mem::transmute(verify); - - let data = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); - let data: &T = mem::transmute(data); + let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); + let verify: &F = mem::transmute(verify); let ctx = X509StoreContext::new(x509_ctx); - let res = match verify { - None => preverify_ok, - Some(verify) => verify(preverify_ok != 0, &ctx, data) as c_int, - }; - - res + verify(preverify_ok != 0, &ctx) as c_int } } @@ -498,14 +465,6 @@ fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec { enc } -/// The signature of functions that can be used to manually verify certificates -pub type VerifyCallback = fn(preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool; - -/// The signature of functions that can be used to manually verify certificates -/// when user-data should be carried for all verification process -pub type VerifyCallbackData = fn(preverify_ok: bool, x509_ctx: &X509StoreContext, data: &T) - -> bool; - /// The signature of functions that can be used to choose the context depending on the server name pub type ServerNameCallback = fn(ssl: &mut Ssl, ad: &mut i32) -> i32; @@ -573,33 +532,21 @@ impl SslContext { } /// Configures the certificate verification method for new connections. - pub fn set_verify(&mut self, mode: SslVerifyMode, verify: Option) { + pub fn set_verify(&mut self, mode: SslVerifyMode) { unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, VERIFY_IDX, mem::transmute(verify)); - let f: extern "C" fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int = raw_verify; - - ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f)); + ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, None); } } - /// Configures the certificate verification method for new connections also - /// carrying supplied data. - // Note: no option because there is no point to set data without providing - // a function handling it - pub fn set_verify_with_data(&mut self, - mode: SslVerifyMode, - verify: VerifyCallbackData, - data: T) - where T: Any + 'static + /// Configures the certificate verification method for new connections and + /// registers a verification callback. + pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) + where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send { - let data = Box::new(data); unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, VERIFY_IDX, mem::transmute(Some(verify))); - ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::(), mem::transmute(data)); - let f: extern "C" fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int = - raw_verify_with_data::; - - ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f)); + let verify = Box::new(verify); + ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::(), mem::transmute(verify)); + ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(raw_verify::)); } } diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index e3b0a340..cc376cf4 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -19,7 +19,7 @@ use ssl::SSL_VERIFY_PEER; use ssl::SslMethod::Sslv23; use ssl::SslMethod; use ssl::error::Error; -use ssl::{SslContext, SslStream, VerifyCallback}; +use ssl::{SslContext, SslStream}; use x509::X509StoreContext; use x509::X509FileType; use x509::X509; @@ -194,7 +194,7 @@ macro_rules! run_test( use std::net::TcpStream; use ssl; use ssl::SslMethod; - use ssl::{SslContext, Ssl, SslStream, VerifyCallback}; + use ssl::{SslContext, Ssl, SslStream}; use ssl::SSL_VERIFY_PEER; use crypto::hash::Type::SHA256; use x509::X509StoreContext; @@ -232,7 +232,7 @@ run_test!(get_ssl_method, |method, _| { run_test!(verify_untrusted, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); match SslStream::connect(&ctx, stream) { Ok(_) => panic!("expected failure"), @@ -242,7 +242,7 @@ run_test!(verify_untrusted, |method, stream| { run_test!(verify_trusted, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -255,12 +255,8 @@ run_test!(verify_trusted, |method, stream| { }); run_test!(verify_untrusted_callback_override_ok, |method, stream| { - fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool { - true - } - let mut ctx = SslContext::new(method).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); + ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| true); match SslStream::connect(&ctx, stream) { Ok(_) => (), @@ -269,23 +265,15 @@ run_test!(verify_untrusted_callback_override_ok, |method, stream| { }); run_test!(verify_untrusted_callback_override_bad, |method, stream| { - fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool { - false - } - let mut ctx = SslContext::new(method).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); + ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| false); assert!(SslStream::connect(&ctx, stream).is_err()); }); run_test!(verify_trusted_callback_override_ok, |method, stream| { - fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool { - true - } - let mut ctx = SslContext::new(method).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); + ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| true); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -298,12 +286,8 @@ run_test!(verify_trusted_callback_override_ok, |method, stream| { }); run_test!(verify_trusted_callback_override_bad, |method, stream| { - fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool { - false - } - let mut ctx = SslContext::new(method).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); + ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| false); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -313,25 +297,21 @@ run_test!(verify_trusted_callback_override_bad, |method, stream| { }); run_test!(verify_callback_load_certs, |method, stream| { - fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool { + let mut ctx = SslContext::new(method).unwrap(); + ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { assert!(x509_ctx.get_current_cert().is_some()); true - } - - let mut ctx = SslContext::new(method).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); + }); assert!(SslStream::connect(&ctx, stream).is_ok()); }); run_test!(verify_trusted_get_error_ok, |method, stream| { - fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool { + let mut ctx = SslContext::new(method).unwrap(); + ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { assert!(x509_ctx.get_error().is_none()); true - } - - let mut ctx = SslContext::new(method).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); + }); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -341,29 +321,16 @@ run_test!(verify_trusted_get_error_ok, |method, stream| { }); run_test!(verify_trusted_get_error_err, |method, stream| { - fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool { + let mut ctx = SslContext::new(method).unwrap(); + ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { assert!(x509_ctx.get_error().is_some()); false - } - - let mut ctx = SslContext::new(method).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); + }); assert!(SslStream::connect(&ctx, stream).is_err()); }); run_test!(verify_callback_data, |method, stream| { - fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext, - node_id: &Vec) -> bool { - let cert = x509_ctx.get_current_cert(); - match cert { - None => false, - Some(cert) => { - let fingerprint = cert.fingerprint(SHA256).unwrap(); - &fingerprint == node_id - } - } - } let mut ctx = SslContext::new(method).unwrap(); // Node id was generated as SHA256 hash of certificate "test/cert.pem" @@ -372,7 +339,16 @@ run_test!(verify_callback_data, |method, stream| { // Please update if "test/cert.pem" will ever change let node_hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b"; let node_id = node_hash_str.from_hex().unwrap(); - ctx.set_verify_with_data(SSL_VERIFY_PEER, callback, node_id); + ctx.set_verify_callback(SSL_VERIFY_PEER, move |_preverify_ok, x509_ctx| { + let cert = x509_ctx.get_current_cert(); + match cert { + None => false, + Some(cert) => { + let fingerprint = cert.fingerprint(SHA256).unwrap(); + fingerprint == node_id + } + } + }); ctx.set_verify_depth(1); match SslStream::connect(&ctx, stream) { @@ -427,7 +403,7 @@ fn test_write_hits_stream() { }); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM).unwrap(); ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM).unwrap(); let stream = listener.accept().unwrap().0; @@ -577,7 +553,7 @@ fn test_state() { fn test_connect_with_unilateral_alpn() { let (_s, stream) = Server::new(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -599,7 +575,7 @@ fn test_connect_with_unilateral_alpn() { fn test_connect_with_unilateral_npn() { let (_s, stream) = Server::new(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -621,7 +597,7 @@ fn test_connect_with_unilateral_npn() { fn test_connect_with_alpn_successful_multiple_matching() { let (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"spdy/3.1", b"http/1.1"]); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -643,7 +619,7 @@ fn test_connect_with_alpn_successful_multiple_matching() { fn test_connect_with_npn_successful_multiple_matching() { let (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -666,7 +642,7 @@ fn test_connect_with_npn_successful_multiple_matching() { fn test_connect_with_alpn_successful_single_match() { let (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -690,7 +666,7 @@ fn test_connect_with_alpn_successful_single_match() { fn test_connect_with_npn_successful_single_match() { let (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_npn_protocols(&[b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -715,7 +691,7 @@ fn test_npn_server_advertise_multiple() { // We create a different context instance for the server... let listener_ctx = { let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]); assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM) .is_ok()); @@ -730,7 +706,7 @@ fn test_npn_server_advertise_multiple() { }); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_npn_protocols(&[b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -756,7 +732,7 @@ fn test_alpn_server_advertise_multiple() { // We create a different context instance for the server... let listener_ctx = { let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM) .is_ok()); @@ -771,7 +747,7 @@ fn test_alpn_server_advertise_multiple() { }); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -797,7 +773,7 @@ fn test_alpn_server_select_none() { // We create a different context instance for the server... let listener_ctx = { let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM) .is_ok()); @@ -812,7 +788,7 @@ fn test_alpn_server_select_none() { }); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"http/2"]); match ctx.set_CA_file(&Path::new("test/cert.pem")) { Ok(_) => {} @@ -840,7 +816,7 @@ mod dtlsv1 { use crypto::hash::Type::SHA256; use ssl::SslMethod; use ssl::SslMethod::Dtlsv1; - use ssl::{SslContext, SslStream, VerifyCallback}; + use ssl::{SslContext, SslStream}; use ssl::SSL_VERIFY_PEER; use x509::X509StoreContext; @@ -1087,7 +1063,7 @@ fn refcount_ssl_context() { fn default_verify_paths() { let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap(); ctx.set_default_verify_paths().unwrap(); - ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_verify(SSL_VERIFY_PEER); let s = TcpStream::connect("google.com:443").unwrap(); let mut socket = SslStream::connect(&ctx, s).unwrap(); From f09ca6fee26dc04e7f5d8d879ccfde311257db61 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 1 May 2016 22:28:09 -0700 Subject: [PATCH 07/96] Clean up SNI APIs --- openssl/src/ssl/mod.rs | 103 ++++++++++++----------------------------- 1 file changed, 30 insertions(+), 73 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 9ef27238..0b7d8b27 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -44,22 +44,11 @@ extern "C" { fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX); } -static mut SNI_IDX: c_int = -1; - /// Manually initialize SSL. /// It is optional to call this function and safe to do so more than once. pub fn init() { static mut INIT: Once = ONCE_INIT; - - unsafe { - INIT.call_once(|| { - ffi::init(); - - let sni_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None); - assert!(sni_idx >= 0); - SNI_IDX = sni_idx; - }); - } + unsafe { INIT.call_once(|| ffi::init()); } } bitflags! { @@ -317,50 +306,31 @@ extern "C" fn ssl_raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_ST } } -extern "C" fn raw_sni(ssl: *mut ffi::SSL, ad: &mut c_int, _arg: *mut c_void) -> c_int { - unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX); - let callback: Option = mem::transmute(callback); - rust_SSL_clone(ssl); - let mut s = Ssl { ssl: ssl }; - - let res = match callback { - None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL, - Some(callback) => callback(&mut s, ad), - }; - - res - } -} - -extern "C" fn raw_sni_with_data(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_void) -> c_int - where T: Any + 'static +extern "C" fn raw_sni(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) -> c_int + where F: Fn(&mut Ssl) -> Result<(), SniError> + Any + 'static + Sync + Send { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX); - let callback: Option> = mem::transmute(callback); + let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); + let callback: &F = mem::transmute(callback); rust_SSL_clone(ssl); - let mut s = Ssl { ssl: ssl }; + let mut ssl = Ssl { ssl: ssl }; - let data: &T = mem::transmute(arg); - - let res = match callback { - None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL, - Some(callback) => callback(&mut s, ad, &*data), - }; - - // Since data might be required on the next verification - // it is time to forget about it and avoid dropping - // data will be freed once OpenSSL considers it is time - // to free all context data - res + match callback(&mut ssl) { + Ok(()) => ffi::SSL_TLSEXT_ERR_OK, + Err(SniError::Fatal(e)) => { + *al = e; + ffi::SSL_TLSEXT_ERR_ALERT_FATAL + } + Err(SniError::Warning(e)) => { + *al = e; + ffi::SSL_TLSEXT_ERR_ALERT_WARNING + } + Err(SniError::NoAck) => ffi::SSL_TLSEXT_ERR_NOACK, + } } } - #[cfg(any(feature = "npn", feature = "alpn"))] unsafe fn select_proto_using(ssl: *mut ffi::SSL, out: *mut *mut c_uchar, @@ -465,10 +435,12 @@ fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec { enc } -/// The signature of functions that can be used to choose the context depending on the server name -pub type ServerNameCallback = fn(ssl: &mut Ssl, ad: &mut i32) -> i32; - -pub type ServerNameCallbackData = fn(ssl: &mut Ssl, ad: &mut i32, data: &T) -> i32; +/// An error returned from an SNI callback. +pub enum SniError { + Fatal(c_int), + Warning(c_int), + NoAck, +} // FIXME: macro may be instead of inlining? #[inline] @@ -552,30 +524,15 @@ impl SslContext { /// Configures the server name indication (SNI) callback for new connections /// - /// obtain the server name with `get_servername` then set the corresponding context + /// Obtain the server name with `servername` then set the corresponding context /// with `set_ssl_context` - pub fn set_servername_callback(&mut self, callback: Option) { - unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(callback)); - let f: extern "C" fn(_, _, _) -> _ = raw_sni; - let f: extern "C" fn() = mem::transmute(f); - ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); - } - } - - /// Configures the server name indication (SNI) callback for new connections - /// carrying supplied data - pub fn set_servername_callback_with_data(&mut self, - callback: ServerNameCallbackData, - data: T) - where T: Any + 'static + pub fn set_servername_callback(&mut self, callback: F) + where F: Fn(&mut Ssl) -> Result<(), SniError> + Any + 'static + Sync + Send { - let data = Box::new(data); unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(Some(callback))); - - ffi_extras::SSL_CTX_set_tlsext_servername_arg(self.ctx, mem::transmute(data)); - let f: extern "C" fn(_, _, _) -> _ = raw_sni_with_data::; + let callback = Box::new(callback); + ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::(), mem::transmute(callback)); + let f: extern "C" fn(_, _, _) -> _ = raw_sni::; let f: extern "C" fn() = mem::transmute(f); ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); } From 085b2e6f035b74a51bd648b36fb8be98fa3e5405 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 2 May 2016 20:10:12 -0700 Subject: [PATCH 08/96] Drop is_dtls methods on SslMethod --- openssl/src/ssl/mod.rs | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 0b7d8b27..f9ba99ca 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -169,30 +169,6 @@ impl SslMethod { _ => None, } } - - #[cfg(feature = "dtlsv1")] - pub fn is_dtlsv1(&self) -> bool { - *self == SslMethod::Dtlsv1 - } - - #[cfg(feature = "dtlsv1_2")] - pub fn is_dtlsv1_2(&self) -> bool { - *self == SslMethod::Dtlsv1_2 - } - - pub fn is_dtls(&self) -> bool { - self.is_dtlsv1() || self.is_dtlsv1_2() - } - - #[cfg(not(feature = "dtlsv1"))] - pub fn is_dtlsv1(&self) -> bool { - false - } - - #[cfg(not(feature = "dtlsv1_2"))] - pub fn is_dtlsv1_2(&self) -> bool { - false - } } /// Determines the type of certificate verification used @@ -496,8 +472,12 @@ impl SslContext { let ctx = SslContext { ctx: ctx }; - if method.is_dtls() { - ctx.set_read_ahead(1); + match method { + #[cfg(feature = "dtlsv1")] + SslMethod::Dtlsv1 => ctx.set_read_ahead(1), + #[cfg(feature = "dtlsv1_2")] + SslMethod::Dtlsv1_2 => ctx.set_read_ahead(1), + _ => {} } Ok(ctx) From 00f517d2cdb10dfe113caa1476c85a3b57722eae Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 2 May 2016 20:22:00 -0700 Subject: [PATCH 09/96] Drop MaybeSslStream It should be inlined into crates that depend on it. --- openssl/src/ssl/mod.rs | 61 ------------------------------------------ 1 file changed, 61 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index f9ba99ca..08f85dfb 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1295,64 +1295,3 @@ impl<'a> IntoSsl for &'a SslContext { Ssl::new(self) } } - -/// A utility type to help in cases where the use of SSL is decided at runtime. -#[derive(Debug)] -pub enum MaybeSslStream - where S: Read + Write -{ - /// A connection using SSL - Ssl(SslStream), - /// A connection not using SSL - Normal(S), -} - -impl Read for MaybeSslStream where S: Read + Write -{ - fn read(&mut self, buf: &mut [u8]) -> io::Result { - match *self { - MaybeSslStream::Ssl(ref mut s) => s.read(buf), - MaybeSslStream::Normal(ref mut s) => s.read(buf), - } - } -} - -impl Write for MaybeSslStream where S: Read + Write -{ - fn write(&mut self, buf: &[u8]) -> io::Result { - match *self { - MaybeSslStream::Ssl(ref mut s) => s.write(buf), - MaybeSslStream::Normal(ref mut s) => s.write(buf), - } - } - - fn flush(&mut self) -> io::Result<()> { - match *self { - MaybeSslStream::Ssl(ref mut s) => s.flush(), - MaybeSslStream::Normal(ref mut s) => s.flush(), - } - } -} - -impl MaybeSslStream where S: Read + Write -{ - /// Returns a reference to the underlying stream. - pub fn get_ref(&self) -> &S { - match *self { - MaybeSslStream::Ssl(ref s) => s.get_ref(), - MaybeSslStream::Normal(ref s) => s, - } - } - - /// Returns a mutable reference to the underlying stream. - /// - /// ## Warning - /// - /// It is inadvisable to read from or write to the underlying stream. - pub fn get_mut(&mut self) -> &mut S { - match *self { - MaybeSslStream::Ssl(ref mut s) => s.get_mut(), - MaybeSslStream::Normal(ref mut s) => s, - } - } -} From f1846bce7840b16cdcf079d2d96d6ed24d2cc269 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 2 May 2016 21:20:13 -0700 Subject: [PATCH 10/96] Remove silly internal error enum --- openssl/src/ssl/mod.rs | 53 +++++++----------------------------------- 1 file changed, 9 insertions(+), 44 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 08f85dfb..c6ebb397 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -834,12 +834,8 @@ impl Ssl { unsafe { ffi::SSL_write(self.ssl, buf.as_ptr() as *const c_void, len) } } - fn get_error(&self, ret: c_int) -> LibErrorStack { - let err = unsafe { ffi::SSL_get_error(self.ssl, ret) }; - match LibErrorStack::from_i32(err as i32) { - Some(err) => err, - None => unreachable!(), - } + fn get_error(&self, ret: c_int) -> c_int { + unsafe { ffi::SSL_get_error(self.ssl, ret) } } /// Sets the verification mode to be used during the handshake process. @@ -1037,37 +1033,6 @@ impl Ssl { } } -macro_rules! make_LibErrorStack { - ($($variant:ident = $value:ident),+) => { - #[derive(Debug)] - #[repr(i32)] - enum LibErrorStack { - $($variant = ffi::$value),+ - } - - impl LibErrorStack { - fn from_i32(val: i32) -> Option { - match val { - $(ffi::$value => Some(LibErrorStack::$variant),)+ - _ => None - } - } - } - } -} - -make_LibErrorStack! { - ErrorNone = SSL_ERROR_NONE, - ErrorSsl = SSL_ERROR_SSL, - ErrorWantRead = SSL_ERROR_WANT_READ, - ErrorWantWrite = SSL_ERROR_WANT_WRITE, - ErrorWantX509Lookup = SSL_ERROR_WANT_X509_LOOKUP, - ErrorSyscall = SSL_ERROR_SYSCALL, - ErrorZeroReturn = SSL_ERROR_ZERO_RETURN, - ErrorWantConnect = SSL_ERROR_WANT_CONNECT, - ErrorWantAccept = SSL_ERROR_WANT_ACCEPT -} - /// A stream wrapper which handles SSL encryption for an underlying stream. pub struct SslStream { ssl: Ssl, @@ -1177,8 +1142,8 @@ impl SslStream { self.check_panic(); match self.ssl.get_error(ret) { - LibErrorStack::ErrorSsl => Error::Ssl(ErrorStack::get()), - LibErrorStack::ErrorSyscall => { + ffi::SSL_ERROR_SSL => Error::Ssl(ErrorStack::get()), + ffi::SSL_ERROR_SYSCALL => { let errs = ErrorStack::get(); if errs.errors().is_empty() { if ret == 0 { @@ -1191,12 +1156,12 @@ impl SslStream { Error::Ssl(errs) } } - LibErrorStack::ErrorZeroReturn => Error::ZeroReturn, - LibErrorStack::ErrorWantWrite => Error::WantWrite(self.get_bio_error()), - LibErrorStack::ErrorWantRead => Error::WantRead(self.get_bio_error()), + ffi::SSL_ERROR_ZERO_RETURN => Error::ZeroReturn, + ffi::SSL_ERROR_WANT_WRITE => Error::WantWrite(self.get_bio_error()), + ffi::SSL_ERROR_WANT_READ => Error::WantRead(self.get_bio_error()), err => { - Error::Stream(io::Error::new(io::ErrorKind::Other, - format!("unexpected error {:?}", err))) + Error::Stream(io::Error::new(io::ErrorKind::InvalidData, + format!("unexpected error {}", err))) } } } From 356d4a0420e73dc55491322a21ad5872d2a08415 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 2 May 2016 21:29:25 -0700 Subject: [PATCH 11/96] Remove AsRaw{Fd, Socket} impls An SslStream can't really act as a raw socket since you'd skip the whole TLS layer --- openssl/src/ssl/mod.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index c6ebb397..5536a99e 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -17,10 +17,6 @@ use libc::{c_uchar, c_uint}; #[cfg(any(feature = "npn", feature = "alpn"))] use std::slice; use std::marker::PhantomData; -#[cfg(unix)] -use std::os::unix::io::{AsRawFd, RawFd}; -#[cfg(windows)] -use std::os::windows::io::{AsRawSocket, RawSocket}; use ffi; use ffi_extras; @@ -1052,20 +1048,6 @@ impl fmt::Debug for SslStream where S: fmt::Debug } } -#[cfg(unix)] -impl AsRawFd for SslStream { - fn as_raw_fd(&self) -> RawFd { - self.get_ref().as_raw_fd() - } -} - -#[cfg(windows)] -impl AsRawSocket for SslStream { - fn as_raw_socket(&self) -> RawSocket { - self.get_ref().as_raw_socket() - } -} - impl SslStream { fn new_base(ssl: Ssl, stream: S) -> Self { unsafe { From 49db4c84dfde2adac65d7834121d09e95d6dbd65 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 3 May 2016 21:15:39 -0700 Subject: [PATCH 12/96] Add a new trait based Nid setup --- openssl/src/lib.rs | 1 + openssl/src/nid2.rs | 206 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 openssl/src/nid2.rs diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index ae347eee..aeba9680 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -24,6 +24,7 @@ pub mod crypto; pub mod dh; pub mod error; pub mod nid; +pub mod nid2; pub mod ssl; pub mod version; pub mod x509; diff --git a/openssl/src/nid2.rs b/openssl/src/nid2.rs new file mode 100644 index 00000000..1f3d4cc8 --- /dev/null +++ b/openssl/src/nid2.rs @@ -0,0 +1,206 @@ +use libc::c_int; + +pub trait Nid { + fn nid() -> c_int; +} + +macro_rules! make_nids { + ($($name:ident $id:expr,)+) => { + $( + pub struct $name; + + impl Nid for $name { + fn nid() -> c_int { + $id + } + } + )+ + } +} + +make_nids! { + Undef 0, + Algorithm 38, + Rsadsi 1, + Pkcs 2, + Md2 3, + Md5 4, + Rc4 5, + RsaEncryption 6, + Md2WithRsaEncryption 7, + Md5WithRsaEncryption 8, + PbeWithMd2AndDesCbc 9, + PbeWithMd5AndDesCbc 10, + X500 11, + X509 12, + CommonName 13, + CountryName 14, + LocalityName 15, + StateOrProvinceName 16, + OrganizationName 17, + OrganizationalUnitName 18, + Rsa 19, + Pkcs7 20, + Pkcs7Data 21, + Pkcs7Signed 22, + Pkcs7Enveloped 23, + Pkcs7SignedAndEnveloped 24, + Pkcs7Digest 25, + Pkcs7Encrypted 26, + Pkcs3 27, + DhKeyAgreement 28, + DesEcb 29, + DesCfb64 30, + DesCbc 31, + DesEde 32, + DesEde3 33, + IdeaCbc 34, + IdeaCfb64 35, + IdeaEcb 36, + Rc2Cbc 37, + Rc2Ecb 38, + Rc2Cfb64 39, + Rc2Ofb64 40, + Sha 41, + ShaWithRsaEncryption 42, + DesEdeCbc 43, + DesEde3Cbc 44, + DesOfb64 45, + IdeaOfb64 46, + Pkcs9 47, + Pkcs9EmailAddress 48, + Pkcs9UnstructuredName 49, + Pkcs9ContentType 50, + Pkcs9MessageDigest 51, + Pkcs9SigningTime 52, + Pkcs9CounterSignature 53, + Pkcs9ChallengePassword 54, + Pkcs9UnstructuredAddress 55, + Pkcs99ExtCertAttributes 56, + Netscape 57, + NetscapeCertExtension 58, + NetscapeDataType 59, + DesEdeCfb64 60, + DesEde3Cfb64 61, + DesEdeOfb64 62, + DesEde3Ofb64 63, + Sha1 64, + Sha1WithRsaEncryption 65, + DsaWithSha 66, + Dsa2 67, + PbeWithSha1AndRc2Cbc 68, + IdPbkdf2 69, + DsaWithSha12 70, + NetscapeCertType 71, + NetscapeBaseUrl 72, + NetscapeRevocationUrl 73, + NetscapeCaRevocationUrl 74, + NetscapeRenewalUrl 75, + NetscapeCaPolicyUrl 76, + NetscapSslServerName 77, + NetscapeComment 78, + NetscapeCertSequence 79, + DesxCbc 80, + IdCe 81, + SubjectKeyIdentifier 82, + KeyUsage 83, + PrivateKeyUsagePeriod 84, + SubjectAltName 85, + IssuerAltName 86, + BasicConstraints 87, + CrlNumber 88, + CertificatePolicies 89, + AuthorityKeyIdentifier 90, + BfCbc 91, + BfEcb 92, + BfCbc64 93, + BfOfb64 94, + Mdc2 95, + Mdc2WithRsa 96, + Rc440 97, + Rc240Cbc 98, + GivenName 99, + Surname 100, + Initials 101, + UniqueIdentifier 102, + CrlDistributionPoints 103, + Md5WithRsa 104, + SerialNumber 105, + Title 106, + Description 107, + Cast5Cbc 108, + Cast5Ecb 109, + Cast5Cfb64 110, + Cast5Ofb64 111, + PbeWithMd5AndCast5Cbc 112, + DsaWithSha1 113, + Md5Sha1 114, + Sha1WithRsa 115, + Dsa 116, + Ripemd160 117, + // No 118 + Ripemd160WithRsa 119, + Rc5Cbc 120, + Rc5Ecb 121, + Rc5Cfb64 122, + Rc5Ofb64 123, + RleCompression 124, + ZlibCompression 125, + ExtKeyUsage 126, + IdPkix 127, + IdKp 128, + ServerAuth 129, + ClientAuth 130, + CodeSign 131, + EmailProtect 132, + TimeStamp 133, + MsCodeInd 134, + MsCodeCom 135, + MsCtlSign 136, + MsSgc 137, + MsEfs 138, + NsSgc 138, + DeltaCrl 140, + CrlReason 141, + InvalidityDate 142, + Sxnet 143, + PbeWithSha1And128BitRc4 144, + PbeWithSha1And40BitRc4 145, + PbeWithSha1And3KeyTripleDesCbc 146, + PbeWithSha1And2KeyTripleDesCbc 147, + Pb3WithSha1And128BitRc2Cbc 148, + PbeWithSha1And40BigRc2Cbc 149, + KeyBag 150, + Pkcs8ShroudedKeyBag 151, + CertBag 152, + CrlBag 153, + SecretBag 154, + SafeContentsBag 155, + FriendlyName 156, + LocalKeyId 157, + X509Certificate 158, + SdsiCertificate 159, + X509Crl 160, + Pbes2 161, + Pbmac1 162, + HmacWithSha1 163, + IdQtCps 164, + IdQtUnotice 165, + Rc264Cbc 166, + SmimeCapabilities 167, + PbeWithMd2AndRc2Cbc 168, + PbeWithMd5AndRc2Dbc 169, + PbeWithSha1AndDesCbc 170, + MsExtReq 171, + ExtReq 172, + Name 173, + DnQualifier 174, + IdPe 175, + IdAd 176, + InfoAccess 177, + AdOcsp 178, + AdCaIssuers 179, + OcspSign 180, + + UserId 458, +} From f4f6412fcb54f54df8667587de39fcb3c3781204 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Thu, 2 Jun 2016 00:05:57 -0400 Subject: [PATCH 13/96] Fix a few mutable types for `self` parameters. --- openssl/src/dh/mod.rs | 6 +++--- openssl/src/ssl/mod.rs | 6 +++--- openssl/src/ssl/tests/mod.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index 14bf076d..bf1ca73e 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -81,7 +81,7 @@ mod tests { #[test] #[cfg(feature = "rfc5114")] fn test_dh_rfc5114() { - let ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Sslv23).unwrap(); let dh1 = DH::get_1024_160().unwrap(); ctx.set_tmp_dh(dh1).unwrap(); let dh2 = DH::get_2048_224().unwrap(); @@ -92,7 +92,7 @@ mod tests { #[test] fn test_dh() { - let ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Sslv23).unwrap(); let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435\ E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF429\ 6D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C02\ @@ -122,7 +122,7 @@ mod tests { #[test] fn test_dh_from_pem() { - let ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Sslv23).unwrap(); let pem_path = Path::new("test/dhparams.pem"); let mut file = File::open(&pem_path) .ok() diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 5536a99e..89a7f7d4 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -521,13 +521,13 @@ impl SslContext { } } - pub fn set_read_ahead(&self, m: u32) { + pub fn set_read_ahead(&mut self, m: u32) { unsafe { ffi_extras::SSL_CTX_set_read_ahead(self.ctx, m as c_long); } } - pub fn set_tmp_dh(&self, dh: DH) -> Result<(), ErrorStack> { + pub fn set_tmp_dh(&mut self, dh: DH) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 }) } @@ -647,7 +647,7 @@ impl SslContext { SslContextOptions::from_bits(ret).unwrap() } - pub fn options(&mut self) -> SslContextOptions { + pub fn options(&self) -> SslContextOptions { let ret = unsafe { ffi_extras::SSL_CTX_get_options(self.ctx) }; SslContextOptions::from_bits(ret).unwrap() } diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index cc376cf4..94bb4b4b 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -437,7 +437,7 @@ fn test_set_certificate_and_private_key() { } run_test!(get_ctx_options, |method, _| { - let mut ctx = SslContext::new(method).unwrap(); + let ctx = SslContext::new(method).unwrap(); ctx.options(); }); From 311af7c3be6eac14b257a695f3c3c428ca177b08 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 13 Jun 2016 21:17:20 +0200 Subject: [PATCH 14/96] Add PKey::private_key_from_pem_cb --- openssl/src/crypto/pkey.rs | 49 +++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index c4111860..f59ee40a 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,9 +1,11 @@ -use libc::{c_int, c_uint, c_ulong}; +use libc::{c_int, c_uint, c_ulong, c_char, c_void}; use std::io; use std::io::prelude::*; use std::iter::repeat; use std::mem; +use std::panic::catch_unwind; use std::ptr; +use std::slice; use bio::MemBio; use crypto::HashTypeInternals; @@ -93,6 +95,51 @@ impl PKey { } } + /// Read a private key from PEM, supplying a password callback to be invoked if the private key + /// is encrypted. + /// + /// The callback will be passed the password buffer and should return the number of characters + /// placed into the buffer. + pub fn private_key_from_pem_cb(reader: &mut R, mut pass_cb: F) -> Result + where R: Read, F: FnMut(&mut [i8]) -> usize + { + extern "C" fn user_cb_wrapper(buf: *mut c_char, + size: c_int, + _rwflag: c_int, + user_cb: *mut c_void) + -> c_int + where F: FnMut(&mut [i8]) -> usize { + let result = catch_unwind(|| { + // build a `i8` slice to pass to the user callback + let pass_slice = unsafe { slice::from_raw_parts_mut(buf, size as usize) }; + let callback = unsafe { &mut *(user_cb as *mut F) }; + + callback(pass_slice) + }); + + if let Ok(len) = result { + return len as c_int; + } else { + return 0; + } + } + + let mut mem_bio = try!(MemBio::new()); + try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + + unsafe { + let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), + ptr::null_mut(), + Some(user_cb_wrapper::), + &mut pass_cb as *mut _ as *mut c_void)); + + Ok(PKey { + evp: evp as *mut ffi::EVP_PKEY, + parts: Parts::Both, + }) + } + } + /// Reads public key from PEM, takes ownership of handle pub fn public_key_from_pem(reader: &mut R) -> Result where R: Read From f0b4a032d5a6cdf3928318e113dcfd7e0ecf03f9 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 13 Jun 2016 21:47:02 +0200 Subject: [PATCH 15/96] Try to propagate callback panics --- openssl/src/crypto/pkey.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index f59ee40a..8ae9aa20 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,9 +1,10 @@ use libc::{c_int, c_uint, c_ulong, c_char, c_void}; +use std::any::Any; use std::io; use std::io::prelude::*; use std::iter::repeat; use std::mem; -use std::panic::catch_unwind; +use std::panic; use std::ptr; use std::slice; use bio::MemBio; @@ -100,21 +101,26 @@ impl PKey { /// /// The callback will be passed the password buffer and should return the number of characters /// placed into the buffer. - pub fn private_key_from_pem_cb(reader: &mut R, mut pass_cb: F) -> Result + pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result where R: Read, F: FnMut(&mut [i8]) -> usize { + struct CallbackState usize> { + cb: F, + panic: Option>, + } + extern "C" fn user_cb_wrapper(buf: *mut c_char, size: c_int, _rwflag: c_int, user_cb: *mut c_void) -> c_int where F: FnMut(&mut [i8]) -> usize { - let result = catch_unwind(|| { + let result = panic::catch_unwind(|| { // build a `i8` slice to pass to the user callback let pass_slice = unsafe { slice::from_raw_parts_mut(buf, size as usize) }; - let callback = unsafe { &mut *(user_cb as *mut F) }; + let callback = unsafe { &mut *(user_cb as *mut CallbackState) }; - callback(pass_slice) + (callback.cb)(pass_slice) }); if let Ok(len) = result { @@ -124,6 +130,11 @@ impl PKey { } } + let mut cb = CallbackState { + cb: pass_cb, + panic: None, + }; + let mut mem_bio = try!(MemBio::new()); try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); @@ -131,7 +142,11 @@ impl PKey { let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), ptr::null_mut(), Some(user_cb_wrapper::), - &mut pass_cb as *mut _ as *mut c_void)); + &mut cb as *mut _ as *mut c_void)); + + if let Some(panic) = cb.panic { + panic::resume_unwind(panic); + } Ok(PKey { evp: evp as *mut ffi::EVP_PKEY, From 8119f06ca5ca50a677cf584cbe816500153ce783 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 14 Jun 2016 18:12:50 +0200 Subject: [PATCH 16/96] Move into utility module --- openssl/src/crypto/mod.rs | 1 + openssl/src/crypto/pkey.rs | 43 +++------------------------- openssl/src/crypto/util.rs | 58 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 39 deletions(-) create mode 100644 openssl/src/crypto/util.rs diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs index 95b27022..9d79b8b0 100644 --- a/openssl/src/crypto/mod.rs +++ b/openssl/src/crypto/mod.rs @@ -24,6 +24,7 @@ pub mod rand; pub mod symm; pub mod memcmp; pub mod rsa; +mod util; mod symm_internal; diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 8ae9aa20..605aed42 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,12 +1,9 @@ -use libc::{c_int, c_uint, c_ulong, c_char, c_void}; -use std::any::Any; +use libc::{c_int, c_uint, c_ulong, c_void}; use std::io; use std::io::prelude::*; use std::iter::repeat; use std::mem; -use std::panic; use std::ptr; -use std::slice; use bio::MemBio; use crypto::HashTypeInternals; @@ -15,6 +12,7 @@ use crypto::hash::Type as HashType; use ffi; use ssl::error::{SslError, StreamError}; use crypto::rsa::RSA; +use crypto::util::{CallbackState, invoke_passwd_cb}; #[derive(Copy, Clone)] pub enum Parts { @@ -104,36 +102,7 @@ impl PKey { pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result where R: Read, F: FnMut(&mut [i8]) -> usize { - struct CallbackState usize> { - cb: F, - panic: Option>, - } - - extern "C" fn user_cb_wrapper(buf: *mut c_char, - size: c_int, - _rwflag: c_int, - user_cb: *mut c_void) - -> c_int - where F: FnMut(&mut [i8]) -> usize { - let result = panic::catch_unwind(|| { - // build a `i8` slice to pass to the user callback - let pass_slice = unsafe { slice::from_raw_parts_mut(buf, size as usize) }; - let callback = unsafe { &mut *(user_cb as *mut CallbackState) }; - - (callback.cb)(pass_slice) - }); - - if let Ok(len) = result { - return len as c_int; - } else { - return 0; - } - } - - let mut cb = CallbackState { - cb: pass_cb, - panic: None, - }; + let mut cb = CallbackState::new(pass_cb); let mut mem_bio = try!(MemBio::new()); try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); @@ -141,13 +110,9 @@ impl PKey { unsafe { let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), ptr::null_mut(), - Some(user_cb_wrapper::), + Some(invoke_passwd_cb::), &mut cb as *mut _ as *mut c_void)); - if let Some(panic) = cb.panic { - panic::resume_unwind(panic); - } - Ok(PKey { evp: evp as *mut ffi::EVP_PKEY, parts: Parts::Both, diff --git a/openssl/src/crypto/util.rs b/openssl/src/crypto/util.rs new file mode 100644 index 00000000..85df86b7 --- /dev/null +++ b/openssl/src/crypto/util.rs @@ -0,0 +1,58 @@ +use libc::{c_int, c_char, c_void}; + +use std::any::Any; +use std::panic; +use std::slice; + +/// Wraps a user-supplied callback and a slot for panics thrown inside the callback (while FFI +/// frames are on the stack). +/// +/// When dropped, checks if the callback has panicked, and resumes unwinding if so. +pub struct CallbackState { + /// The user callback. Taken out of the `Option` when called. + cb: Option, + /// If the callback panics, we place the panic object here, to be re-thrown once OpenSSL + /// returns. + panic: Option>, +} + +impl CallbackState { + pub fn new(callback: F) -> Self { + CallbackState { + cb: Some(callback), + panic: None, + } + } +} + +impl Drop for CallbackState { + fn drop(&mut self) { + if let Some(panic) = self.panic.take() { + panic::resume_unwind(panic); + } + } +} + +/// Password callback function, passed to private key loading functions. +/// +/// `cb_state` is expected to be a pointer to a `CallbackState`. +pub extern "C" fn invoke_passwd_cb(buf: *mut c_char, + size: c_int, + _rwflag: c_int, + cb_state: *mut c_void) + -> c_int + where F: FnMut(&mut [i8]) -> usize { + let result = panic::catch_unwind(|| { + // build a `i8` slice to pass to the user callback + let pass_slice = unsafe { slice::from_raw_parts_mut(buf, size as usize) }; + let callback = unsafe { &mut *(cb_state as *mut CallbackState) }; + + callback.cb.take().unwrap()(pass_slice) + }); + + if let Ok(len) = result { + return len as c_int; + } else { + return 0; + } +} From c399c2475d71c313970dc4e3b271f0086e90b013 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 14 Jun 2016 18:17:25 +0200 Subject: [PATCH 17/96] Add RSA::private_key_from_pem_cb --- openssl/src/crypto/rsa.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 52b8590e..d451aab6 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -3,12 +3,13 @@ use std::fmt; use ssl::error::{SslError, StreamError}; use std::ptr; use std::io::{self, Read, Write}; -use libc::c_int; +use libc::{c_int, c_void}; use bn::BigNum; use bio::MemBio; use crypto::HashTypeInternals; use crypto::hash; +use crypto::util::{CallbackState, invoke_passwd_cb}; pub struct RSA(*mut ffi::RSA); @@ -76,6 +77,26 @@ impl RSA { } } + /// Reads an RSA private key from PEM formatted data and supplies a password callback. + pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result + where R: Read, F: FnMut(&mut [i8]) -> usize + { + let mut cb = CallbackState::new(pass_cb); + + let mut mem_bio = try!(MemBio::new()); + try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + + unsafe { + let cb_ptr = &mut cb as *mut _ as *mut c_void; + let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.get_handle(), + ptr::null_mut(), + Some(invoke_passwd_cb::), + cb_ptr)); + + Ok(RSA(rsa)) + } + } + /// Writes an RSA private key as unencrypted PEM formatted data pub fn private_key_to_pem(&self, writer: &mut W) -> Result<(), SslError> where W: Write From c1b7cd2420c679b611c7ff28024db10cb0ffb8b5 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 22 Jun 2016 21:51:43 +0200 Subject: [PATCH 18/96] Make the callback take a `&mut [c_char]` --- openssl/src/crypto/pkey.rs | 4 ++-- openssl/src/crypto/rsa.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 605aed42..238c1b9e 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,4 +1,4 @@ -use libc::{c_int, c_uint, c_ulong, c_void}; +use libc::{c_int, c_uint, c_ulong, c_void, c_char}; use std::io; use std::io::prelude::*; use std::iter::repeat; @@ -100,7 +100,7 @@ impl PKey { /// The callback will be passed the password buffer and should return the number of characters /// placed into the buffer. pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result - where R: Read, F: FnMut(&mut [i8]) -> usize + where R: Read, F: FnMut(&mut [c_char]) -> usize { let mut cb = CallbackState::new(pass_cb); diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index d451aab6..c7f5cfaf 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -3,7 +3,7 @@ use std::fmt; use ssl::error::{SslError, StreamError}; use std::ptr; use std::io::{self, Read, Write}; -use libc::{c_int, c_void}; +use libc::{c_int, c_void, c_char}; use bn::BigNum; use bio::MemBio; @@ -79,7 +79,7 @@ impl RSA { /// Reads an RSA private key from PEM formatted data and supplies a password callback. pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result - where R: Read, F: FnMut(&mut [i8]) -> usize + where R: Read, F: FnMut(&mut [c_char]) -> usize { let mut cb = CallbackState::new(pass_cb); From 41b78547ad0357d3e86462f72c0cff333096d59f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 22 Jun 2016 22:05:03 +0200 Subject: [PATCH 19/96] Put password callbacks behind a cargo feature --- openssl/Cargo.toml | 1 + openssl/src/crypto/mod.rs | 1 + openssl/src/crypto/pkey.rs | 7 ++++++- openssl/src/crypto/rsa.rs | 7 ++++++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 39f2fc65..f9288bfa 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -27,6 +27,7 @@ ecdh_auto = ["openssl-sys-extras/ecdh_auto"] pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"] nightly = [] +catch_unwind = [] [dependencies] bitflags = ">= 0.5.0, < 0.8.0" diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs index 9d79b8b0..481eb05c 100644 --- a/openssl/src/crypto/mod.rs +++ b/openssl/src/crypto/mod.rs @@ -24,6 +24,7 @@ pub mod rand; pub mod symm; pub mod memcmp; pub mod rsa; +#[cfg(feature = "catch_unwind")] mod util; mod symm_internal; diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 238c1b9e..bbb8427d 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,4 +1,4 @@ -use libc::{c_int, c_uint, c_ulong, c_void, c_char}; +use libc::{c_int, c_uint, c_ulong}; use std::io; use std::io::prelude::*; use std::iter::repeat; @@ -12,6 +12,10 @@ use crypto::hash::Type as HashType; use ffi; use ssl::error::{SslError, StreamError}; use crypto::rsa::RSA; + +#[cfg(feature = "catch_unwind")] +use libc::{c_void, c_char}; +#[cfg(feature = "catch_unwind")] use crypto::util::{CallbackState, invoke_passwd_cb}; #[derive(Copy, Clone)] @@ -99,6 +103,7 @@ impl PKey { /// /// The callback will be passed the password buffer and should return the number of characters /// placed into the buffer. + #[cfg(feature = "catch_unwind")] pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result where R: Read, F: FnMut(&mut [c_char]) -> usize { diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index c7f5cfaf..a67fe38e 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -3,12 +3,16 @@ use std::fmt; use ssl::error::{SslError, StreamError}; use std::ptr; use std::io::{self, Read, Write}; -use libc::{c_int, c_void, c_char}; +use libc::c_int; use bn::BigNum; use bio::MemBio; use crypto::HashTypeInternals; use crypto::hash; + +#[cfg(feature = "catch_unwind")] +use libc::{c_void, c_char}; +#[cfg(feature = "catch_unwind")] use crypto::util::{CallbackState, invoke_passwd_cb}; pub struct RSA(*mut ffi::RSA); @@ -78,6 +82,7 @@ impl RSA { } /// Reads an RSA private key from PEM formatted data and supplies a password callback. + #[cfg(feature = "catch_unwind")] pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result where R: Read, F: FnMut(&mut [c_char]) -> usize { From d176ea1c6e7aaa4e96d27eb0c62dc11fdb990aca Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 22 Jun 2016 22:27:53 +0200 Subject: [PATCH 20/96] Add an RSA key decryption test --- openssl/src/crypto/rsa.rs | 18 ++++++++++++++++++ openssl/test/rsa-encrypted.pem | 30 ++++++++++++++++++++++++++++++ openssl/test/run.sh | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 openssl/test/rsa-encrypted.pem diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index a67fe38e..d0303283 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -303,4 +303,22 @@ mod test { assert!(result); } + + #[test] + pub fn test_password() { + let mut password_queried = false; + let mut buffer = File::open("test/rsa-encrypted.pem").unwrap(); + let rsa = RSA::private_key_from_pem_cb(&mut buffer, |password| { + password_queried = true; + password[0] = b'm' as _; + password[1] = b'y' as _; + password[2] = b'p' as _; + password[3] = b'a' as _; + password[4] = b's' as _; + password[5] = b's' as _; + 6 + }).unwrap(); + + assert!(password_queried); + } } diff --git a/openssl/test/rsa-encrypted.pem b/openssl/test/rsa-encrypted.pem new file mode 100644 index 00000000..a6249997 --- /dev/null +++ b/openssl/test/rsa-encrypted.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,E2F16153E2BA3D617285A68C896BA6AF + +vO9SnhtGjGe8pG1pN//vsONnvJr+DjU+lFCiSqGMPT7tezDnbehLfS+9kus2HV7r +HmI14JvVG9O7NpF7zMyBRlHYdWcCCWED9Yar0NsWN9419e5pMe/bqIXAzAiJbtT4 +OB9U5XF3m+349zjN1dVXPPLGRmMC1pcHAlofeb5nIUFTvUi5xcsbe1itGjgkkvHb +Bt8NioHTBun8kKrlsFQOuB55ylBU/eWG8DQBtvFOmQ7iWp0RnGQfh8k5e5rcZNpQ +fD9ygc7UVISl0xTrIG4IH15g34H+nrBauKtIPOpNPuXQPOMHCZv3XH8wnhrWHHwT +ZFnQBdXbSpQtMsRh0phG2G+VIlyCgSn4+CxjCJ+TgFtsoK/tU0unmRYc59QnTxxb +qkHYsPs3E0NApQAgH1ENEGl1M+FGLYQH7gftjc3ophBTeRA17sRmD7Y4QBInggsq +Gv6tImPVBdekAjz/Ls/EyMwjAvvrL5eAokqrIsAarGo+zmbJKHzknw2KUz2En0+k +YYaxB4oy9u7bzuQlvio6xYHJEb4K197bby4Dldmqv7YCCJBJwhOBAInMD687viKv +vcUwL8YuS6cW5E8MbvEENlY4+lvKKj3M8Bnyb79cYIPQe92EuCwXU9DZXPRMLwwM +oFEJpF5E/PmNJzu+B52ahHtDrh83WSx71fWqjdTqwkPZhAYo3ztsfFkb/UqUcq8u +rBSebeUjZh0XZ9B04eshZQ5vJUcXGtYIe/77beV3Pv89/fw+zTZjpiP9Q3sZALzf +Qt0YGp0/6qBuqR1tcqdu65AS2hun7yFw7uRavqYKvww4axRiz2do+xWmZFuoCAwD +EWktaUujltpvAc1lo7lg4C6nByefJB9Xqk22N/vpqOsWr1NbAntT42Qj/HF9BVWR +osvN3yMnKYWYe6oSTVnNBDM5obWAIHd3I9gcxTOTb1KsEwt2RrDs5EpB5ptS3Fjo +JfBRhNZQ3cXttrIIhsHgDn9BDNg865/xpIgktKj0gEd60Abx0PqkAIm6IZTh4Efg +7uZwfzxB+saOcddbrW2gNdzVZMC0s2Ye3sqHhtLbAJ3BlXYTxE4CAvTg54Ny+5hF +IjvjlOKgXceSG1cSfk21/wyp9RY3Ft0AEYvvp0kZScWZaoA2aSFDUrchXVhgrEbn +lJ7UptjefwRFIreAlwbKSbIDDNWnyzvIWyHfQ2aYqgnb7W7XqNPSgH9cALCfzirI +dlRHjha0bMUtrjPCC/YfMXzJBVniy0gG6Pd5uC7vz/Awn6/6HRQVNaTQASphPBQ7 +bJuz+JTfzI9OUVCMRMdnb6b35U4P9tibFmnPvzTIPe+3WUmf8aRsLS3NN3G1Webd +PMYVZpMycPaAI0Ht87axhsOzlxCWHYWjdHa+WoNNc1J90TxLCmAHquh5BDaWvjMK +0DySftJZjV7Tf1p2KosmU83LRl39B5NHMbZb1xOEZl9IWwhT/PVKTVZ25xdxWLfb +hF4l8rfvKehIp5r4t8zW1bvI2Hl6vrUvmcUVWt3BfKjxlgwRVD0vvwonMt1INesF +204vUBeXbDsUUicLwOyUgaFvJ3XU3dOyvL9MhOgM5OgoFRRhG+4AS8a5JCD8iLtq +-----END RSA PRIVATE KEY----- diff --git a/openssl/test/run.sh b/openssl/test/run.sh index 829f11e9..1c23067f 100755 --- a/openssl/test/run.sh +++ b/openssl/test/run.sh @@ -8,7 +8,7 @@ if [ "$TEST_FEATURES" == "true" ]; then fi if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then - FEATURES="$FEATURES nightly" + FEATURES="$FEATURES nightly catch_unwind" fi if [ "$TRAVIS_OS_NAME" != "osx" ]; then From 351bc569a46ab1590736114a50179351de8719d7 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 26 Jun 2016 18:24:47 +0200 Subject: [PATCH 21/96] Put the test behind the catch_unwind feature And fix an unused variable warning --- openssl/src/crypto/rsa.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index d0303283..9a04bf7f 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -305,10 +305,11 @@ mod test { } #[test] + #[cfg(feature = "catch_unwind")] pub fn test_password() { let mut password_queried = false; let mut buffer = File::open("test/rsa-encrypted.pem").unwrap(); - let rsa = RSA::private_key_from_pem_cb(&mut buffer, |password| { + RSA::private_key_from_pem_cb(&mut buffer, |password| { password_queried = true; password[0] = b'm' as _; password[1] = b'y' as _; From f24ab2693636f16ce71a171a4d4d63bd0f5bbea0 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 26 Jun 2016 19:44:53 +0200 Subject: [PATCH 22/96] FnMut -> FnOnce, update docs --- openssl/src/crypto/pkey.rs | 4 +++- openssl/src/crypto/rsa.rs | 4 +++- openssl/src/crypto/util.rs | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index bbb8427d..15744047 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -103,9 +103,11 @@ impl PKey { /// /// The callback will be passed the password buffer and should return the number of characters /// placed into the buffer. + /// + /// Requires the `catch_unwind` feature. #[cfg(feature = "catch_unwind")] pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result - where R: Read, F: FnMut(&mut [c_char]) -> usize + where R: Read, F: FnOnce(&mut [c_char]) -> usize { let mut cb = CallbackState::new(pass_cb); diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 9a04bf7f..3b420fbc 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -82,9 +82,11 @@ impl RSA { } /// Reads an RSA private key from PEM formatted data and supplies a password callback. + /// + /// Requires the `catch_unwind` feature. #[cfg(feature = "catch_unwind")] pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result - where R: Read, F: FnMut(&mut [c_char]) -> usize + where R: Read, F: FnOnce(&mut [c_char]) -> usize { let mut cb = CallbackState::new(pass_cb); diff --git a/openssl/src/crypto/util.rs b/openssl/src/crypto/util.rs index 85df86b7..be72aa59 100644 --- a/openssl/src/crypto/util.rs +++ b/openssl/src/crypto/util.rs @@ -41,7 +41,7 @@ pub extern "C" fn invoke_passwd_cb(buf: *mut c_char, _rwflag: c_int, cb_state: *mut c_void) -> c_int - where F: FnMut(&mut [i8]) -> usize { + where F: FnOnce(&mut [i8]) -> usize { let result = panic::catch_unwind(|| { // build a `i8` slice to pass to the user callback let pass_slice = unsafe { slice::from_raw_parts_mut(buf, size as usize) }; From 722a2bd673bac57faf450d5548a057481fa98cf0 Mon Sep 17 00:00:00 2001 From: Shaun Taheri Date: Fri, 22 Jul 2016 18:16:55 +0200 Subject: [PATCH 23/96] Set SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER flag --- openssl-sys/src/lib.rs | 1 + openssl/src/ssl/mod.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index ef327a93..96a24e48 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -272,6 +272,7 @@ pub const SSL_CTRL_SET_TLSEXT_HOSTNAME: c_int = 55; pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; pub const SSL_CTRL_SET_READ_AHEAD: c_int = 41; +pub const SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER: c_long = 2; pub const SSL_MODE_AUTO_RETRY: c_long = 4; pub const SSL_ERROR_NONE: c_int = 0; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index d0954bc7..0252b114 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -567,7 +567,7 @@ impl SslContext { let ctx = SslContext { ctx: ctx }; // this is a bit dubious (?) - try!(ctx.set_mode(ffi::SSL_MODE_AUTO_RETRY)); + try!(ctx.set_mode(ffi::SSL_MODE_AUTO_RETRY | ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)); if method.is_dtls() { ctx.set_read_ahead(1); From 8ff61f6b737cfa9a91e98179f18fdce4a14bd9c5 Mon Sep 17 00:00:00 2001 From: Ben Batha Date: Thu, 28 Jul 2016 20:20:11 -0400 Subject: [PATCH 24/96] start using cargo workspaces --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Cargo.toml diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..3e02eded --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["openssl", "openssl-sys", "openssl-sys-extras"] From 5ed77df197afc33c04569edcd3db5993a695fbae Mon Sep 17 00:00:00 2001 From: Onur Aslan Date: Fri, 29 Jul 2016 12:11:53 +0300 Subject: [PATCH 25/96] Implement save_der for X509 and X509Req --- openssl-sys/src/lib.rs | 3 +++ openssl/src/x509/mod.rs | 22 ++++++++++++++++++++++ openssl/src/x509/tests.rs | 13 +++++++++++++ 3 files changed, 38 insertions(+) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 96a24e48..1e0d5fe5 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -841,6 +841,9 @@ extern "C" { pub fn X509_REQ_add_extensions(req: *mut X509_REQ, exts: *mut stack_st_X509_EXTENSION) -> c_int; pub fn X509_REQ_sign(x: *mut X509_REQ, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int; + pub fn i2d_X509_bio(b: *mut BIO, x: *mut X509) -> c_int; + pub fn i2d_X509_REQ_bio(b: *mut BIO, x: *mut X509_REQ) -> c_int; + pub fn i2d_RSA_PUBKEY(k: *mut RSA, buf: *const *mut u8) -> c_int; pub fn d2i_RSA_PUBKEY(k: *const *mut RSA, buf: *const *const u8, len: c_uint) -> *mut RSA; pub fn i2d_RSAPrivateKey(k: *mut RSA, buf: *const *mut u8) -> c_int; diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 3150cc6e..396d50df 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -532,6 +532,17 @@ impl<'ctx> X509<'ctx> { } io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ()) } + + /// Returns a DER serialized form of the certificate + pub fn save_der(&self) -> Result, SslError> { + let mut mem_bio = try!(MemBio::new()); + unsafe { + ffi::i2d_X509_bio(mem_bio.get_handle(), self.handle); + } + let mut v = Vec::new(); + try!(io::copy(&mut mem_bio, &mut v).map_err(StreamError)); + Ok(v) + } } extern "C" { @@ -637,6 +648,17 @@ impl X509Req { } io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ()) } + + /// Returns a DER serialized form of the CSR + pub fn save_der(&self) -> Result, SslError> { + let mut mem_bio = try!(MemBio::new()); + unsafe { + ffi::i2d_X509_REQ_bio(mem_bio.get_handle(), self.handle); + } + let mut v = Vec::new(); + try!(io::copy(&mut mem_bio, &mut v).map_err(StreamError)); + Ok(v) + } } impl Drop for X509Req { diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index f547a982..5d9b30ab 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -92,6 +92,19 @@ fn test_cert_loading() { assert_eq!(fingerprint, hash_vec); } +#[test] +fn test_save_der() { + let cert_path = Path::new("test/cert.pem"); + let mut file = File::open(&cert_path) + .ok() + .expect("Failed to open `test/cert.pem`"); + + let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM"); + + let der = cert.save_der().unwrap(); + assert!(!der.is_empty()); +} + #[test] fn test_subject_read_cn() { let cert_path = Path::new("test/cert.pem"); From 39be51943d632634353ae00c95efe6883edb649c Mon Sep 17 00:00:00 2001 From: Ben Batha Date: Fri, 29 Jul 2016 09:20:47 -0400 Subject: [PATCH 26/96] add RUST_BACKTRACE=1 to make debugging ci failures easier --- openssl/test/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/test/run.sh b/openssl/test/run.sh index 1c23067f..85603773 100755 --- a/openssl/test/run.sh +++ b/openssl/test/run.sh @@ -33,4 +33,4 @@ else fi export PATH=$HOME/openssl/bin:$PATH -(cd openssl && cargo $COMMAND $FLAGS --features "$FEATURES") +(cd openssl && RUST_BACKTRACE=1 cargo $COMMAND $FLAGS --features "$FEATURES") From 7c082904fcfbce919396b372f4e236a0828fd7a0 Mon Sep 17 00:00:00 2001 From: Onur Aslan Date: Fri, 29 Jul 2016 16:30:24 +0300 Subject: [PATCH 27/96] Implement get_handle for X509Req --- openssl/src/x509/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 3150cc6e..daeb9283 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -611,6 +611,10 @@ impl X509Req { X509Req { handle: handle } } + pub fn get_handle(&self) -> *mut ffi::X509_REQ { + self.handle + } + /// Reads CSR from PEM pub fn from_pem(reader: &mut R) -> Result where R: Read From a3a602be515cfc8fdd44a11b89fee012baec0e0b Mon Sep 17 00:00:00 2001 From: Ben Batha Date: Tue, 17 May 2016 18:10:06 -0400 Subject: [PATCH 28/96] add low level dsa primitives --- openssl-sys/src/lib.rs | 50 ++++- openssl/src/crypto/dsa.rs | 351 +++++++++++++++++++++++++++++++++ openssl/src/crypto/mod.rs | 1 + openssl/test/dsa-encrypted.pem | 15 ++ openssl/test/dsa.pem | 12 ++ openssl/test/dsa.pem.pub | 12 ++ openssl/test/dsaparam.pem | 9 + 7 files changed, 448 insertions(+), 2 deletions(-) create mode 100644 openssl/src/crypto/dsa.rs create mode 100644 openssl/test/dsa-encrypted.pem create mode 100644 openssl/test/dsa.pem create mode 100644 openssl/test/dsa.pem.pub create mode 100644 openssl/test/dsaparam.pem diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 96a24e48..168848ca 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -114,6 +114,28 @@ pub struct RSA { pub mt_blinding: *mut c_void, } +#[repr(C)] +pub struct DSA { + pub pad: c_int, + pub version: c_long, + pub write_params: c_int, + + pub p: *mut BIGNUM, + pub q: *mut BIGNUM, + pub g: *mut BIGNUM, + pub pub_key: *mut BIGNUM, + pub priv_key: *mut BIGNUM, + pub kinv: *mut BIGNUM, + pub r: *mut BIGNUM, + + pub flags: c_int, + pub _method_mont_p: *mut c_void, + pub references: c_int, + pub ex_data: *mut c_void, + pub meth: *const c_void, + pub engine: *const c_void, +} + #[repr(C)] pub struct EVP_PKEY { pub type_: c_int, @@ -626,16 +648,28 @@ extern "C" { pub fn PEM_read_bio_RSA_PUBKEY(bio: *mut BIO, rsa: *mut *mut RSA, callback: Option, user_data: *mut c_void) -> *mut RSA; pub fn PEM_write_bio_PrivateKey(bio: *mut BIO, pkey: *mut EVP_PKEY, cipher: *const EVP_CIPHER, - kstr: *mut c_char, klen: c_int, + kstr: *mut c_uchar, klen: c_int, callback: Option, user_data: *mut c_void) -> c_int; pub fn PEM_write_bio_PUBKEY(bp: *mut BIO, x: *mut EVP_PKEY) -> c_int; pub fn PEM_write_bio_RSAPrivateKey(bp: *mut BIO, rsa: *mut RSA, cipher: *const EVP_CIPHER, - kstr: *mut c_char, klen: c_int, + kstr: *mut c_uchar, klen: c_int, callback: Option, user_data: *mut c_void) -> c_int; pub fn PEM_write_bio_RSAPublicKey(bp: *mut BIO, rsa: *mut RSA) -> c_int; pub fn PEM_write_bio_RSA_PUBKEY(bp: *mut BIO, rsa: *mut RSA) -> c_int; + + pub fn PEM_read_bio_DSAPrivateKey(bp: *mut BIO, dsa: *mut *mut DSA, callback: Option, + user_data: *mut c_void) -> *mut DSA; + pub fn PEM_read_bio_DSA_PUBKEY(bp: *mut BIO, dsa: *mut *mut DSA, callback: Option, + user_data: *mut c_void) -> *mut DSA; + pub fn PEM_write_bio_DSAPrivateKey(bp: *mut BIO, dsa: *mut DSA, cipher: *const EVP_CIPHER, + kstr: *mut c_uchar, klen: c_int, callback: Option, + user_data: *mut c_void) -> c_int; + pub fn PEM_write_bio_DSA_PUBKEY(bp: *mut BIO, dsa: *mut DSA) -> c_int; + + + pub fn PEM_write_bio_X509(bio: *mut BIO, x509: *mut X509) -> c_int; pub fn PEM_write_bio_X509_REQ(bio: *mut BIO, x509: *mut X509_REQ) -> c_int; @@ -669,6 +703,18 @@ extern "C" { pub fn RSA_verify(t: c_int, m: *const u8, mlen: c_uint, sig: *const u8, siglen: c_uint, k: *mut RSA) -> c_int; + pub fn DSA_new() -> *mut DSA; + pub fn DSA_free(dsa: *mut DSA); + pub fn DSA_size(dsa: *const DSA) -> c_int; + pub fn DSA_generate_parameters_ex(dsa: *mut DSA, bits: c_int, seed: *const c_uchar, seed_len: c_int, + counter_ref: *mut c_int, h_ret: *mut c_ulong, + cb: *const c_void) -> c_int; + pub fn DSA_generate_key(dsa: *mut DSA) -> c_int; + pub fn DSA_sign(dummy: c_int, dgst: *const c_uchar, len: c_int, sigret: *mut c_uchar, + siglen: *mut c_uint, dsa: *mut DSA) -> c_int; + pub fn DSA_verify(dummy: c_int, dgst: *const c_uchar, len: c_int, sigbuf: *const c_uchar, + siglen: c_int, dsa: *mut DSA) -> c_int; + pub fn SSL_library_init() -> c_int; pub fn SSL_load_error_strings(); diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs new file mode 100644 index 00000000..7e384ae3 --- /dev/null +++ b/openssl/src/crypto/dsa.rs @@ -0,0 +1,351 @@ +use ffi; +use std::fmt; +use ssl::error::{SslError, StreamError}; +use std::ptr; +use std::io::{self, Read, Write}; +use libc::{c_uint, c_int}; + +use bn::BigNum; +use bio::MemBio; +use crypto::hash; +use crypto::HashTypeInternals; + +#[cfg(feature = "catch_unwind")] +use libc::{c_char, c_void}; +#[cfg(feature = "catch_unwind")] +use crypto::util::{CallbackState, invoke_passwd_cb}; + +/// Builder for upfront DSA parameter generateration +pub struct DSAParams(*mut ffi::DSA); + +impl DSAParams { + pub fn with_size(size: usize) -> Result { + unsafe { + // Wrap it so that if we panic we'll call the dtor + let dsa = DSAParams(try_ssl_null!(ffi::DSA_new())); + try_ssl!(ffi::DSA_generate_parameters_ex(dsa.0, size as c_int, ptr::null(), 0, + ptr::null_mut(), ptr::null_mut(), ptr::null())); + Ok(dsa) + } + } + + /// Generate a key pair from the initialized parameters + pub fn generate(self) -> Result { + unsafe { + try_ssl!(ffi::DSA_generate_key(self.0)); + let dsa = DSA(self.0); + ::std::mem::forget(self); + Ok(dsa) + } + } +} + +impl Drop for DSAParams { + fn drop(&mut self) { + unsafe { + ffi::DSA_free(self.0); + } + } +} + +pub struct DSA(*mut ffi::DSA); + +impl Drop for DSA { + fn drop(&mut self) { + unsafe { + ffi::DSA_free(self.0); + } + } +} + +impl DSA { + /// the caller should assert that the dsa pointer is valid. + pub unsafe fn from_raw(dsa: *mut ffi::DSA) -> DSA { + DSA(dsa) + } + + /// Generate a DSA key pair + /// For more complicated key generation scenarios see the `DSAParams` type + pub fn generate(size: usize) -> Result { + let params = try!(DSAParams::with_size(size)); + params.generate() + } + + /// Reads a DSA private key from PEM formatted data. + pub fn private_key_from_pem(reader: &mut R) -> Result + where R: Read + { + let mut mem_bio = try!(MemBio::new()); + try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + + unsafe { + let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.get_handle(), + ptr::null_mut(), + None, + ptr::null_mut())); + let dsa = DSA(dsa); + assert!(dsa.has_private_key()); + Ok(dsa) + } + } + + /// Read a private key from PEM supplying a password callback to be invoked if the private key + /// is encrypted. + /// + /// The callback will be passed the password buffer and should return the number of characters + /// placed into the buffer. + /// + /// Requires the `catch_unwind` feature. + #[cfg(feature = "catch_unwind")] + pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result + where R: Read, F: FnOnce(&mut [c_char]) -> usize + { + let mut cb = CallbackState::new(pass_cb); + let mut mem_bio = try!(MemBio::new()); + try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + + unsafe { + let cb_ptr = &mut cb as *mut _ as *mut c_void; + let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.get_handle(), + ptr::null_mut(), + Some(invoke_passwd_cb::), + cb_ptr)); + let dsa = DSA(dsa); + assert!(dsa.has_private_key()); + Ok(dsa) + } + } + + /// Writes an DSA private key as unencrypted PEM formatted data + pub fn private_key_to_pem(&self, writer: &mut W) -> Result<(), SslError> + where W: Write + { + assert!(self.has_private_key()); + let mut mem_bio = try!(MemBio::new()); + + unsafe { + try_ssl!(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.get_handle(), self.0, + ptr::null(), ptr::null_mut(), 0, + None, ptr::null_mut())) + }; + + + try!(io::copy(&mut mem_bio, writer).map_err(StreamError)); + Ok(()) + } + + /// Reads an DSA public key from PEM formatted data. + pub fn public_key_from_pem(reader: &mut R) -> Result + where R: Read + { + let mut mem_bio = try!(MemBio::new()); + try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + + unsafe { + let dsa = try_ssl_null!(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.get_handle(), + ptr::null_mut(), + None, + ptr::null_mut())); + Ok(DSA(dsa)) + } + } + + /// Writes an DSA public key as PEM formatted data + pub fn public_key_to_pem(&self, writer: &mut W) -> Result<(), SslError> + where W: Write + { + let mut mem_bio = try!(MemBio::new()); + + unsafe { try_ssl!(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.get_handle(), self.0)) }; + + try!(io::copy(&mut mem_bio, writer).map_err(StreamError)); + Ok(()) + } + + pub fn size(&self) -> Result { + if self.has_q() { + unsafe { Ok(ffi::DSA_size(self.0) as isize) } + } else { + Err(SslError::OpenSslErrors(vec![])) + } + } + + pub fn sign(&self, hash: hash::Type, message: &[u8]) -> Result, SslError> { + let k_len = try!(self.size()) as c_uint; + let mut sig = vec![0;k_len as usize]; + let mut sig_len = k_len; + assert!(self.has_private_key()); + + unsafe { + try_ssl!(ffi::DSA_sign(hash.as_nid() as c_int, + message.as_ptr(), + message.len() as c_int, + sig.as_mut_ptr(), + &mut sig_len, + self.0)); + sig.set_len(sig_len as usize); + sig.shrink_to_fit(); + Ok(sig) + } + } + + pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result { + unsafe { + let result = ffi::DSA_verify(hash.as_nid() as c_int, + message.as_ptr(), + message.len() as c_int, + sig.as_ptr(), + sig.len() as c_int, + self.0); + + try_ssl_if!(result == -1); + Ok(result == 1) + } + } + + pub fn as_ptr(&self) -> *mut ffi::DSA { + self.0 + } + + // The following getters are unsafe, since BigNum::new_from_ffi fails upon null pointers + pub fn p(&self) -> Result { + unsafe { BigNum::new_from_ffi((*self.0).p) } + } + + pub fn has_p(&self) -> bool { + unsafe { !(*self.0).p.is_null() } + } + + pub fn q(&self) -> Result { + unsafe { BigNum::new_from_ffi((*self.0).q) } + } + + pub fn has_q(&self) -> bool { + unsafe { !(*self.0).q.is_null() } + } + + pub fn g(&self) -> Result { + unsafe { BigNum::new_from_ffi((*self.0).g) } + } + + pub fn has_g(&self) -> bool { + unsafe { !(*self.0).q.is_null() } + } + + pub fn has_public_key(&self) -> bool { + unsafe { !(*self.0).pub_key.is_null() } + } + + pub fn has_private_key(&self) -> bool { + unsafe { !(*self.0).priv_key.is_null() } + } +} + +impl fmt::Debug for DSA { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "DSA") + } +} + +#[cfg(test)] +mod test { + use std::fs::File; + use std::io::{Write, Cursor}; + use super::*; + use crypto::hash::*; + + #[test] + pub fn test_generate() { + let key = DSA::generate(1024).unwrap(); + let mut priv_buf = Cursor::new(vec![]); + let mut pub_buf = Cursor::new(vec![]); + + key.public_key_to_pem(&mut pub_buf).unwrap(); + key.private_key_to_pem(&mut priv_buf).unwrap(); + + let input: Vec = (0..25).cycle().take(1024).collect(); + + let digest = { + let mut sha = Hasher::new(Type::SHA1); + sha.write_all(&input).unwrap(); + sha.finish() + }; + + let sig = key.sign(Type::SHA1, &digest).unwrap(); + let verified = key.verify(Type::SHA1, &digest, &sig).unwrap(); + assert!(verified); + } + + #[test] + pub fn test_sign_verify() { + let input: Vec = (0..25).cycle().take(1024).collect(); + + let private_key = { + let mut buffer = File::open("test/dsa.pem").unwrap(); + DSA::private_key_from_pem(&mut buffer).unwrap() + }; + + let public_key = { + let mut buffer = File::open("test/dsa.pem.pub").unwrap(); + DSA::public_key_from_pem(&mut buffer).unwrap() + }; + + let digest = { + let mut sha = Hasher::new(Type::SHA1); + sha.write_all(&input).unwrap(); + sha.finish() + }; + + let sig = private_key.sign(Type::SHA1, &digest).unwrap(); + let verified = public_key.verify(Type::SHA1, &digest, &sig).unwrap(); + assert!(verified); + } + + #[test] + pub fn test_sign_verify_fail() { + let input: Vec = (0..25).cycle().take(128).collect(); + let private_key = { + let mut buffer = File::open("test/dsa.pem").unwrap(); + DSA::private_key_from_pem(&mut buffer).unwrap() + }; + + let public_key = { + let mut buffer = File::open("test/dsa.pem.pub").unwrap(); + DSA::public_key_from_pem(&mut buffer).unwrap() + }; + + let digest = { + let mut sha = Hasher::new(Type::SHA1); + sha.write_all(&input).unwrap(); + sha.finish() + }; + + let mut sig = private_key.sign(Type::SHA1, &digest).unwrap(); + // tamper with the sig this should cause a failure + let len = sig.len(); + sig[len / 2] = 0; + sig[len - 1] = 0; + if let Ok(true) = public_key.verify(Type::SHA1, &digest, &sig) { + panic!("Tampered with signatures should not verify!"); + } + } + + #[test] + #[cfg(feature = "catch_unwind")] + pub fn test_password() { + let mut password_queried = false; + let mut buffer = File::open("test/dsa-encrypted.pem").unwrap(); + DSA::private_key_from_pem_cb(&mut buffer, |password| { + password_queried = true; + password[0] = b'm' as _; + password[1] = b'y' as _; + password[2] = b'p' as _; + password[3] = b'a' as _; + password[4] = b's' as _; + password[5] = b's' as _; + 6 + }).unwrap(); + + assert!(password_queried); + } +} diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs index 481eb05c..6a34bd59 100644 --- a/openssl/src/crypto/mod.rs +++ b/openssl/src/crypto/mod.rs @@ -24,6 +24,7 @@ pub mod rand; pub mod symm; pub mod memcmp; pub mod rsa; +pub mod dsa; #[cfg(feature = "catch_unwind")] mod util; diff --git a/openssl/test/dsa-encrypted.pem b/openssl/test/dsa-encrypted.pem new file mode 100644 index 00000000..9b1984eb --- /dev/null +++ b/openssl/test/dsa-encrypted.pem @@ -0,0 +1,15 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,5B99FC62C376CA1F + +5nN039tLa3AHnSaQ0lk+Zsguu1EE+EyUlW1GHKs7ls2gOsZH1kR0+A+MiwNKlP24 +Syy8KYyAbgsirhtwN5IOSsA97feR/vHTY4xQ8nEef8tB7VeRJzOFLHGgS0hwIxOM +Tb8gb4y0FtoWdAgorieP4c1emu8VwTTkHd44AArDXsP1Y7s+a3IEMcHcc3tW+qBk +xuVnqBEETL1t0I5rKy+AYvPmGgEZ0dGRRnUlVMC5jMTozJFcStdSzKUY27prUBz2 +FREOJOA/dIjVn1UGijI64Io5sPCAbDPPmG2k4kywbEbd7Ee/MxEvRNcAyv4boyA8 +GnHZTILKi/WY5+SNlHE3YepCFo1XU+59SovB1lDhRmi43L4vfdGc/6y8L/+rbLuU +Y58DxLdOZLTjpf9GLLf9WcpHhNZhwFfBFA8HuT8FtKDPqlf2t65z+1AVV8JTH2wM +BrRHXTrBKn8YgafXD5MisKFmajoAtNZTvhYGm0D8BLIiNwOwLsGfXZ0hYAie0eoI +Xl6MbHp1n/e+R+XKJ3M9DPM8mzWntlltAhS5+Az0Zi4aBdzqQaTpqvEku21sygq8 +Hwm0fpAq7y4bMnjNbMqQVw== +-----END DSA PRIVATE KEY----- diff --git a/openssl/test/dsa.pem b/openssl/test/dsa.pem new file mode 100644 index 00000000..9b550184 --- /dev/null +++ b/openssl/test/dsa.pem @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCkKe/jtYKJNQafaE7kg2aaJOEPUV0Doi451jkXHp5UfLh6+t42 +eabSGkE9WBAlILgaB8yHckLe9+zozN39+SUDp94kb2r38/8w/9Ffhbsep9uiyOj2 +ZRQur6SkpKQDKcnAd6IMZXZcvdSgPC90A6qraYUZKq7Csjn63gbC+IvXHwIVAIgS +PE43lXD8/rGYxos4cxCgGGAxAoGASMV56WhLvVQtWMVI36WSIxbZnC2EsnNIKeVW +yXnP/OmPJ2mdezG7i1alcwsO2TnSLbvjvGPlyzIqZzHvWC8EmDqsfbU+n8we/Eal +sm5nloC8m9ECWpbTzbNdvrAAj9UPVWjcDwg7grAGGysh6lGbBv5P+4zL/niq1UiE +LnKcifgCgYEAo6mAasO0+MVcu8shxxUXXNeTLsZ8NB/BIx9EZ/dzE23ivNW8dq1A +eecAAYhssI2m/CspQvyKw+seCvg4FccxJgB3+mGOe+blFHwO3eAwoyRn/t3DZDHh +FjxKKRsQdy4BkZv+vhTyIYYCw0iPZ5Wfln+pyGGTveIDED1MPG+J6c8CFCJAUlEl +4nHvbC15xLXXpd46zycY +-----END DSA PRIVATE KEY----- diff --git a/openssl/test/dsa.pem.pub b/openssl/test/dsa.pem.pub new file mode 100644 index 00000000..ae298d09 --- /dev/null +++ b/openssl/test/dsa.pem.pub @@ -0,0 +1,12 @@ +-----BEGIN PUBLIC KEY----- +MIIBtzCCASsGByqGSM44BAEwggEeAoGBAKQp7+O1gok1Bp9oTuSDZpok4Q9RXQOi +LjnWORcenlR8uHr63jZ5ptIaQT1YECUguBoHzIdyQt737OjM3f35JQOn3iRvavfz +/zD/0V+Fux6n26LI6PZlFC6vpKSkpAMpycB3ogxldly91KA8L3QDqqtphRkqrsKy +OfreBsL4i9cfAhUAiBI8TjeVcPz+sZjGizhzEKAYYDECgYBIxXnpaEu9VC1YxUjf +pZIjFtmcLYSyc0gp5VbJec/86Y8naZ17MbuLVqVzCw7ZOdItu+O8Y+XLMipnMe9Y +LwSYOqx9tT6fzB78RqWybmeWgLyb0QJaltPNs12+sACP1Q9VaNwPCDuCsAYbKyHq +UZsG/k/7jMv+eKrVSIQucpyJ+AOBhQACgYEAo6mAasO0+MVcu8shxxUXXNeTLsZ8 +NB/BIx9EZ/dzE23ivNW8dq1AeecAAYhssI2m/CspQvyKw+seCvg4FccxJgB3+mGO +e+blFHwO3eAwoyRn/t3DZDHhFjxKKRsQdy4BkZv+vhTyIYYCw0iPZ5Wfln+pyGGT +veIDED1MPG+J6c8= +-----END PUBLIC KEY----- diff --git a/openssl/test/dsaparam.pem b/openssl/test/dsaparam.pem new file mode 100644 index 00000000..53bda543 --- /dev/null +++ b/openssl/test/dsaparam.pem @@ -0,0 +1,9 @@ +-----BEGIN DSA PARAMETERS----- +MIIBHgKBgQCkKe/jtYKJNQafaE7kg2aaJOEPUV0Doi451jkXHp5UfLh6+t42eabS +GkE9WBAlILgaB8yHckLe9+zozN39+SUDp94kb2r38/8w/9Ffhbsep9uiyOj2ZRQu +r6SkpKQDKcnAd6IMZXZcvdSgPC90A6qraYUZKq7Csjn63gbC+IvXHwIVAIgSPE43 +lXD8/rGYxos4cxCgGGAxAoGASMV56WhLvVQtWMVI36WSIxbZnC2EsnNIKeVWyXnP +/OmPJ2mdezG7i1alcwsO2TnSLbvjvGPlyzIqZzHvWC8EmDqsfbU+n8we/Ealsm5n +loC8m9ECWpbTzbNdvrAAj9UPVWjcDwg7grAGGysh6lGbBv5P+4zL/niq1UiELnKc +ifg= +-----END DSA PARAMETERS----- From 67d3067dbf152c2431e002cbe39ee13286d6d503 Mon Sep 17 00:00:00 2001 From: Ben Batha Date: Fri, 29 Jul 2016 20:01:54 -0400 Subject: [PATCH 29/96] improve error handling in rsa --- openssl/src/crypto/rsa.rs | 42 +++++++++++++-------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 3b420fbc..2b563a7a 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -110,23 +110,17 @@ impl RSA { { let mut mem_bio = try!(MemBio::new()); - let result = unsafe { - ffi::PEM_write_bio_RSAPrivateKey(mem_bio.get_handle(), + unsafe { + try_ssl!(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.get_handle(), self.0, ptr::null(), ptr::null_mut(), 0, None, - ptr::null_mut()) - }; - - if result == 1 { - try!(io::copy(&mut mem_bio, writer).map_err(StreamError)); - - Ok(()) - } else { - Err(SslError::OpenSslErrors(vec![])) + ptr::null_mut())); } + try!(io::copy(&mut mem_bio, writer).map_err(StreamError)); + Ok(()) } /// Reads an RSA public key from PEM formatted data. @@ -151,15 +145,12 @@ impl RSA { { let mut mem_bio = try!(MemBio::new()); - let result = unsafe { ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.get_handle(), self.0) }; + unsafe { + try_ssl!(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.get_handle(), self.0)) + }; - if result == 1 { - try!(io::copy(&mut mem_bio, writer).map_err(StreamError)); - - Ok(()) - } else { - Err(SslError::OpenSslErrors(vec![])) - } + try!(io::copy(&mut mem_bio, writer).map_err(StreamError)); + Ok(()) } pub fn size(&self) -> Result { @@ -176,19 +167,14 @@ impl RSA { let mut sig_len = k_len; unsafe { - let result = ffi::RSA_sign(hash.as_nid() as c_int, + try_ssl!(ffi::RSA_sign(hash.as_nid() as c_int, message.as_ptr(), message.len() as u32, sig.as_mut_ptr(), &mut sig_len, - self.0); + self.0)); assert!(sig_len == k_len); - - if result == 1 { - Ok(sig) - } else { - Err(SslError::OpenSslErrors(vec![])) - } + Ok(sig) } } @@ -200,7 +186,7 @@ impl RSA { sig.as_ptr(), sig.len() as u32, self.0); - + try_ssl_if!(result == -1); Ok(result == 1) } } From 18c1ded8c7bbae8e49fbfbe1f86c63f5dfe29191 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 31 Jul 2016 14:41:11 -0700 Subject: [PATCH 30/96] Revert "Add a new trait based Nid setup" This reverts commit 49db4c84dfde2adac65d7834121d09e95d6dbd65. Unclear that this is a good idea --- openssl/src/lib.rs | 1 - openssl/src/nid2.rs | 206 -------------------------------------------- 2 files changed, 207 deletions(-) delete mode 100644 openssl/src/nid2.rs diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index aeba9680..ae347eee 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -24,7 +24,6 @@ pub mod crypto; pub mod dh; pub mod error; pub mod nid; -pub mod nid2; pub mod ssl; pub mod version; pub mod x509; diff --git a/openssl/src/nid2.rs b/openssl/src/nid2.rs deleted file mode 100644 index 1f3d4cc8..00000000 --- a/openssl/src/nid2.rs +++ /dev/null @@ -1,206 +0,0 @@ -use libc::c_int; - -pub trait Nid { - fn nid() -> c_int; -} - -macro_rules! make_nids { - ($($name:ident $id:expr,)+) => { - $( - pub struct $name; - - impl Nid for $name { - fn nid() -> c_int { - $id - } - } - )+ - } -} - -make_nids! { - Undef 0, - Algorithm 38, - Rsadsi 1, - Pkcs 2, - Md2 3, - Md5 4, - Rc4 5, - RsaEncryption 6, - Md2WithRsaEncryption 7, - Md5WithRsaEncryption 8, - PbeWithMd2AndDesCbc 9, - PbeWithMd5AndDesCbc 10, - X500 11, - X509 12, - CommonName 13, - CountryName 14, - LocalityName 15, - StateOrProvinceName 16, - OrganizationName 17, - OrganizationalUnitName 18, - Rsa 19, - Pkcs7 20, - Pkcs7Data 21, - Pkcs7Signed 22, - Pkcs7Enveloped 23, - Pkcs7SignedAndEnveloped 24, - Pkcs7Digest 25, - Pkcs7Encrypted 26, - Pkcs3 27, - DhKeyAgreement 28, - DesEcb 29, - DesCfb64 30, - DesCbc 31, - DesEde 32, - DesEde3 33, - IdeaCbc 34, - IdeaCfb64 35, - IdeaEcb 36, - Rc2Cbc 37, - Rc2Ecb 38, - Rc2Cfb64 39, - Rc2Ofb64 40, - Sha 41, - ShaWithRsaEncryption 42, - DesEdeCbc 43, - DesEde3Cbc 44, - DesOfb64 45, - IdeaOfb64 46, - Pkcs9 47, - Pkcs9EmailAddress 48, - Pkcs9UnstructuredName 49, - Pkcs9ContentType 50, - Pkcs9MessageDigest 51, - Pkcs9SigningTime 52, - Pkcs9CounterSignature 53, - Pkcs9ChallengePassword 54, - Pkcs9UnstructuredAddress 55, - Pkcs99ExtCertAttributes 56, - Netscape 57, - NetscapeCertExtension 58, - NetscapeDataType 59, - DesEdeCfb64 60, - DesEde3Cfb64 61, - DesEdeOfb64 62, - DesEde3Ofb64 63, - Sha1 64, - Sha1WithRsaEncryption 65, - DsaWithSha 66, - Dsa2 67, - PbeWithSha1AndRc2Cbc 68, - IdPbkdf2 69, - DsaWithSha12 70, - NetscapeCertType 71, - NetscapeBaseUrl 72, - NetscapeRevocationUrl 73, - NetscapeCaRevocationUrl 74, - NetscapeRenewalUrl 75, - NetscapeCaPolicyUrl 76, - NetscapSslServerName 77, - NetscapeComment 78, - NetscapeCertSequence 79, - DesxCbc 80, - IdCe 81, - SubjectKeyIdentifier 82, - KeyUsage 83, - PrivateKeyUsagePeriod 84, - SubjectAltName 85, - IssuerAltName 86, - BasicConstraints 87, - CrlNumber 88, - CertificatePolicies 89, - AuthorityKeyIdentifier 90, - BfCbc 91, - BfEcb 92, - BfCbc64 93, - BfOfb64 94, - Mdc2 95, - Mdc2WithRsa 96, - Rc440 97, - Rc240Cbc 98, - GivenName 99, - Surname 100, - Initials 101, - UniqueIdentifier 102, - CrlDistributionPoints 103, - Md5WithRsa 104, - SerialNumber 105, - Title 106, - Description 107, - Cast5Cbc 108, - Cast5Ecb 109, - Cast5Cfb64 110, - Cast5Ofb64 111, - PbeWithMd5AndCast5Cbc 112, - DsaWithSha1 113, - Md5Sha1 114, - Sha1WithRsa 115, - Dsa 116, - Ripemd160 117, - // No 118 - Ripemd160WithRsa 119, - Rc5Cbc 120, - Rc5Ecb 121, - Rc5Cfb64 122, - Rc5Ofb64 123, - RleCompression 124, - ZlibCompression 125, - ExtKeyUsage 126, - IdPkix 127, - IdKp 128, - ServerAuth 129, - ClientAuth 130, - CodeSign 131, - EmailProtect 132, - TimeStamp 133, - MsCodeInd 134, - MsCodeCom 135, - MsCtlSign 136, - MsSgc 137, - MsEfs 138, - NsSgc 138, - DeltaCrl 140, - CrlReason 141, - InvalidityDate 142, - Sxnet 143, - PbeWithSha1And128BitRc4 144, - PbeWithSha1And40BitRc4 145, - PbeWithSha1And3KeyTripleDesCbc 146, - PbeWithSha1And2KeyTripleDesCbc 147, - Pb3WithSha1And128BitRc2Cbc 148, - PbeWithSha1And40BigRc2Cbc 149, - KeyBag 150, - Pkcs8ShroudedKeyBag 151, - CertBag 152, - CrlBag 153, - SecretBag 154, - SafeContentsBag 155, - FriendlyName 156, - LocalKeyId 157, - X509Certificate 158, - SdsiCertificate 159, - X509Crl 160, - Pbes2 161, - Pbmac1 162, - HmacWithSha1 163, - IdQtCps 164, - IdQtUnotice 165, - Rc264Cbc 166, - SmimeCapabilities 167, - PbeWithMd2AndRc2Cbc 168, - PbeWithMd5AndRc2Dbc 169, - PbeWithSha1AndDesCbc 170, - MsExtReq 171, - ExtReq 172, - Name 173, - DnQualifier 174, - IdPe 175, - IdAd 176, - InfoAccess 177, - AdOcsp 178, - AdCaIssuers 179, - OcspSign 180, - - UserId 458, -} From 5cb04db787baefc7f6368bd40cc1d4378760cf68 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 31 Jul 2016 15:35:45 -0700 Subject: [PATCH 31/96] Fix build with dtls --- openssl/src/ssl/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index b18df7b3..aba809fd 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -466,7 +466,7 @@ impl SslContext { let ctx = try_ssl_null!(unsafe { ffi::SSL_CTX_new(method.to_raw()) }); - let ctx = SslContext { ctx: ctx }; + let mut ctx = SslContext { ctx: ctx }; match method { #[cfg(feature = "dtlsv1")] @@ -529,7 +529,7 @@ impl SslContext { } } - fn set_mode(&self, mode: c_long) -> Result<(), ErrorStack> { + fn set_mode(&mut self, mode: c_long) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_mode(self.ctx, mode) as c_int }) } From e86eb68624592a31b4f59d27e6a9ace7c034e0bf Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 31 Jul 2016 15:49:09 -0700 Subject: [PATCH 32/96] Fix catch_unwind feature and drop feature gate --- openssl/src/crypto/dsa.rs | 15 ++++----------- openssl/src/crypto/mod.rs | 1 - openssl/src/crypto/pkey.rs | 13 +++---------- openssl/src/crypto/rsa.rs | 14 +++----------- 4 files changed, 10 insertions(+), 33 deletions(-) diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index 36806a48..df6c255b 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -3,18 +3,15 @@ use std::fmt; use error::ErrorStack; use std::ptr; use std::io::{self, Read, Write}; -use libc::{c_uint, c_int}; +use libc::{c_uint, c_int, c_char, c_void}; use bn::BigNum; use bio::MemBio; use crypto::hash; use crypto::HashTypeInternals; - -#[cfg(feature = "catch_unwind")] -use libc::{c_char, c_void}; -#[cfg(feature = "catch_unwind")] use crypto::util::{CallbackState, invoke_passwd_cb}; + /// Builder for upfront DSA parameter generateration pub struct DSAParams(*mut ffi::DSA); @@ -94,15 +91,12 @@ impl DSA { /// /// The callback will be passed the password buffer and should return the number of characters /// placed into the buffer. - /// - /// Requires the `catch_unwind` feature. - #[cfg(feature = "catch_unwind")] - pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result + pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> io::Result where R: Read, F: FnOnce(&mut [c_char]) -> usize { let mut cb = CallbackState::new(pass_cb); let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio)); unsafe { let cb_ptr = &mut cb as *mut _ as *mut c_void; @@ -331,7 +325,6 @@ mod test { } #[test] - #[cfg(feature = "catch_unwind")] pub fn test_password() { let mut password_queried = false; let mut buffer = File::open("test/dsa-encrypted.pem").unwrap(); diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs index 6a34bd59..5b891ce7 100644 --- a/openssl/src/crypto/mod.rs +++ b/openssl/src/crypto/mod.rs @@ -25,7 +25,6 @@ pub mod symm; pub mod memcmp; pub mod rsa; pub mod dsa; -#[cfg(feature = "catch_unwind")] mod util; mod symm_internal; diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 0231cc95..29feb016 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,4 +1,4 @@ -use libc::{c_int, c_uint, c_ulong}; +use libc::{c_int, c_uint, c_ulong, c_void, c_char}; use std::io; use std::io::prelude::*; use std::iter::repeat; @@ -12,10 +12,6 @@ use crypto::hash::Type as HashType; use ffi; use crypto::rsa::RSA; use error::ErrorStack; - -#[cfg(feature = "catch_unwind")] -use libc::{c_void, c_char}; -#[cfg(feature = "catch_unwind")] use crypto::util::{CallbackState, invoke_passwd_cb}; #[derive(Copy, Clone)] @@ -104,16 +100,13 @@ impl PKey { /// /// The callback will be passed the password buffer and should return the number of characters /// placed into the buffer. - /// - /// Requires the `catch_unwind` feature. - #[cfg(feature = "catch_unwind")] - pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result + pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> io::Result where R: Read, F: FnOnce(&mut [c_char]) -> usize { let mut cb = CallbackState::new(pass_cb); let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio)); unsafe { let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index b403eab5..cf946d35 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -2,17 +2,13 @@ use ffi; use std::fmt; use std::ptr; use std::io::{self, Read, Write}; -use libc::c_int; +use libc::{c_int, c_void, c_char}; use bn::BigNum; use bio::MemBio; use error::ErrorStack; use crypto::HashTypeInternals; use crypto::hash; - -#[cfg(feature = "catch_unwind")] -use libc::{c_void, c_char}; -#[cfg(feature = "catch_unwind")] use crypto::util::{CallbackState, invoke_passwd_cb}; pub struct RSA(*mut ffi::RSA); @@ -82,16 +78,13 @@ impl RSA { } /// Reads an RSA private key from PEM formatted data and supplies a password callback. - /// - /// Requires the `catch_unwind` feature. - #[cfg(feature = "catch_unwind")] - pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> Result + pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> io::Result where R: Read, F: FnOnce(&mut [c_char]) -> usize { let mut cb = CallbackState::new(pass_cb); let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio)); unsafe { let cb_ptr = &mut cb as *mut _ as *mut c_void; @@ -303,7 +296,6 @@ mod test { } #[test] - #[cfg(feature = "catch_unwind")] pub fn test_password() { let mut password_queried = false; let mut buffer = File::open("test/rsa-encrypted.pem").unwrap(); From 6f40b65d2c3e1a9414b2b79d5c49e4ba061f4811 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 31 Jul 2016 15:55:32 -0700 Subject: [PATCH 33/96] Build against 1.9 --- .travis.yml | 2 +- appveyor.yml | 2 +- openssl/Cargo.toml | 3 --- openssl/test/run.sh | 4 ---- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 91c6ad62..0d76be3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ addons: - gcc-arm-linux-gnueabihf rust: - nightly -- 1.8.0 +- 1.9.0 os: - osx - linux diff --git a/appveyor.yml b/appveyor.yml index f835d9f6..8cd9e32b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,7 +10,7 @@ environment: install: - ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2h.exe" - Win%BITS%OpenSSL-1_0_2h.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL" - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.8.0-${env:TARGET}.exe" + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.9.0-${env:TARGET}.exe" - rust-1.8.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - SET PATH=%PATH%;C:\MinGW\bin diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 218969eb..3d4b098c 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -26,9 +26,6 @@ rfc5114 = ["openssl-sys/rfc5114"] ecdh_auto = ["openssl-sys-extras/ecdh_auto"] pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"] -nightly = [] -catch_unwind = [] - [dependencies] bitflags = ">= 0.5.0, < 0.8.0" lazy_static = "0.2" diff --git a/openssl/test/run.sh b/openssl/test/run.sh index 85603773..cbd46cc6 100755 --- a/openssl/test/run.sh +++ b/openssl/test/run.sh @@ -7,10 +7,6 @@ if [ "$TEST_FEATURES" == "true" ]; then FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac" fi -if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then - FEATURES="$FEATURES nightly catch_unwind" -fi - if [ "$TRAVIS_OS_NAME" != "osx" ]; then export OPENSSL_LIB_DIR=$HOME/openssl/lib export OPENSSL_INCLUDE_DIR=$HOME/openssl/include From 3539be33660dc136e0b585400f70447e31ccb62a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 27 Jul 2016 14:18:02 -0700 Subject: [PATCH 34/96] Add MidHandshakeSslStream Allows recognizing when a stream is still in handshake mode and can gracefully transition when ready. The blocking usage of the API should still be the same, just helps nonblocking implementations! --- openssl-sys/src/lib.rs | 1 + openssl/src/ssl/mod.rs | 120 ++++++++++++++++++++++++++++++++--- openssl/src/ssl/tests/mod.rs | 35 ++++++---- 3 files changed, 137 insertions(+), 19 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 1a15fecb..3c31f671 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -741,6 +741,7 @@ extern "C" { pub fn SSL_get_wbio(ssl: *mut SSL) -> *mut BIO; pub fn SSL_accept(ssl: *mut SSL) -> c_int; pub fn SSL_connect(ssl: *mut SSL) -> c_int; + pub fn SSL_do_handshake(ssl: *mut SSL) -> c_int; pub fn SSL_ctrl(ssl: *mut SSL, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long; pub fn SSL_get_error(ssl: *mut SSL, ret: c_int) -> c_int; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index b18df7b3..9215a928 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -5,6 +5,7 @@ use std::ffi::{CStr, CString}; use std::fmt; use std::io; use std::io::prelude::*; +use std::error as stderror; use std::mem; use std::str; use std::path::Path; @@ -832,6 +833,10 @@ impl Ssl { unsafe { ffi::SSL_accept(self.ssl) } } + fn handshake(&self) -> c_int { + unsafe { ffi::SSL_do_handshake(self.ssl) } + } + fn read(&self, buf: &mut [u8]) -> c_int { let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; unsafe { ffi::SSL_read(self.ssl, buf.as_ptr() as *mut c_void, len) } @@ -1081,31 +1086,49 @@ impl SslStream { } /// Creates an SSL/TLS client operating over the provided stream. - pub fn connect(ssl: T, stream: S) -> Result { - let ssl = try!(ssl.into_ssl()); + pub fn connect(ssl: T, stream: S) + -> Result>{ + let ssl = try!(ssl.into_ssl().map_err(|e| { + HandshakeError::Failure(Error::Ssl(e)) + })); let mut stream = Self::new_base(ssl, stream); let ret = stream.ssl.connect(); if ret > 0 { Ok(stream) } else { match stream.make_error(ret) { - Error::WantRead(..) | Error::WantWrite(..) => Ok(stream), - err => Err(err) + e @ Error::WantWrite(_) | + e @ Error::WantRead(_) => { + Err(HandshakeError::Interrupted(MidHandshakeSslStream { + stream: stream, + error: e, + })) + } + err => Err(HandshakeError::Failure(err)), } } } /// Creates an SSL/TLS server operating over the provided stream. - pub fn accept(ssl: T, stream: S) -> Result { - let ssl = try!(ssl.into_ssl()); + pub fn accept(ssl: T, stream: S) + -> Result> { + let ssl = try!(ssl.into_ssl().map_err(|e| { + HandshakeError::Failure(Error::Ssl(e)) + })); let mut stream = Self::new_base(ssl, stream); let ret = stream.ssl.accept(); if ret > 0 { Ok(stream) } else { match stream.make_error(ret) { - Error::WantRead(..) | Error::WantWrite(..) => Ok(stream), - err => Err(err) + e @ Error::WantWrite(_) | + e @ Error::WantRead(_) => { + Err(HandshakeError::Interrupted(MidHandshakeSslStream { + stream: stream, + error: e, + })) + } + err => Err(HandshakeError::Failure(err)), } } } @@ -1137,6 +1160,87 @@ impl SslStream { } } +/// An error or intermediate state after a TLS handshake attempt. +#[derive(Debug)] +pub enum HandshakeError { + /// The handshake failed. + Failure(Error), + /// The handshake was interrupted midway through. + Interrupted(MidHandshakeSslStream), +} + +impl stderror::Error for HandshakeError { + fn description(&self) -> &str { + match *self { + HandshakeError::Failure(ref e) => e.description(), + HandshakeError::Interrupted(ref e) => e.error.description(), + } + } + + fn cause(&self) -> Option<&stderror::Error> { + match *self { + HandshakeError::Failure(ref e) => Some(e), + HandshakeError::Interrupted(ref e) => Some(&e.error), + } + } +} + +impl fmt::Display for HandshakeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(f.write_str(stderror::Error::description(self))); + if let Some(e) = stderror::Error::cause(self) { + try!(write!(f, ": {}", e)); + } + Ok(()) + } +} + +/// An SSL stream midway through the handshake process. +#[derive(Debug)] +pub struct MidHandshakeSslStream { + stream: SslStream, + error: Error, +} + +impl MidHandshakeSslStream { + /// Returns a shared reference to the inner stream. + pub fn get_ref(&self) -> &S { + self.stream.get_ref() + } + + /// Returns a mutable reference to the inner stream. + pub fn get_mut(&mut self) -> &mut S { + self.stream.get_mut() + } + + /// Returns a shared reference to the `SslContext` of the stream. + pub fn ssl(&self) -> &Ssl { + self.stream.ssl() + } + + /// Returns the underlying error which interrupted this handshake. + pub fn error(&self) -> &Error { + &self.error + } + + /// Restarts the handshake process. + pub fn handshake(mut self) -> Result, HandshakeError> { + let ret = self.stream.ssl.handshake(); + if ret > 0 { + Ok(self.stream) + } else { + match self.stream.make_error(ret) { + e @ Error::WantWrite(_) | + e @ Error::WantRead(_) => { + self.error = e; + Err(HandshakeError::Interrupted(self)) + } + err => Err(HandshakeError::Failure(err)), + } + } + } +} + impl SslStream { fn make_error(&mut self, ret: c_int) -> Error { self.check_panic(); diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 1fc0076b..0b638546 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -17,7 +17,7 @@ use crypto::hash::Type::SHA256; use ssl; use ssl::SSL_VERIFY_PEER; use ssl::SslMethod::Sslv23; -use ssl::SslMethod; +use ssl::{SslMethod, HandshakeError}; use ssl::error::Error; use ssl::{SslContext, SslStream}; use x509::X509StoreContext; @@ -133,6 +133,7 @@ impl Drop for Server { } #[cfg(feature = "dtlsv1")] +#[derive(Debug)] struct UdpConnected(UdpSocket); #[cfg(feature = "dtlsv1")] @@ -846,10 +847,10 @@ fn test_sslv2_connect_failure() { .unwrap(); } -fn wait_io(stream: &SslStream, read: bool, timeout_ms: u32) -> bool { +fn wait_io(stream: &TcpStream, read: bool, timeout_ms: u32) -> bool { unsafe { let mut set: select::fd_set = mem::zeroed(); - select::fd_set(&mut set, stream.get_ref()); + select::fd_set(&mut set, stream); let write = if read { 0 as *mut _ @@ -861,7 +862,19 @@ fn wait_io(stream: &SslStream, read: bool, timeout_ms: u32) -> bool { } else { &mut set as *mut _ }; - select::select(stream.get_ref(), read, write, 0 as *mut _, timeout_ms).unwrap() + select::select(stream, read, write, 0 as *mut _, timeout_ms).unwrap() + } +} + +fn handshake(res: Result, HandshakeError>) + -> SslStream { + match res { + Ok(s) => s, + Err(HandshakeError::Interrupted(s)) => { + wait_io(s.get_ref(), true, 1_000); + handshake(s.handshake()) + } + Err(err) => panic!("error on handshake {:?}", err), } } @@ -870,7 +883,7 @@ fn test_write_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); let cx = SslContext::new(Sslv23).unwrap(); - let mut stream = SslStream::connect(&cx, stream).unwrap(); + let mut stream = handshake(SslStream::connect(&cx, stream)); let mut iterations = 0; loop { @@ -886,10 +899,10 @@ fn test_write_nonblocking() { break; } Err(Error::WantRead(_)) => { - assert!(wait_io(&stream, true, 1000)); + assert!(wait_io(stream.get_ref(), true, 1000)); } Err(Error::WantWrite(_)) => { - assert!(wait_io(&stream, false, 1000)); + assert!(wait_io(stream.get_ref(), false, 1000)); } Err(other) => { panic!("Unexpected SSL Error: {:?}", other); @@ -907,7 +920,7 @@ fn test_read_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); let cx = SslContext::new(Sslv23).unwrap(); - let mut stream = SslStream::connect(&cx, stream).unwrap(); + let mut stream = handshake(SslStream::connect(&cx, stream)); let mut iterations = 0; loop { @@ -924,10 +937,10 @@ fn test_read_nonblocking() { break; } Err(Error::WantRead(..)) => { - assert!(wait_io(&stream, true, 1000)); + assert!(wait_io(stream.get_ref(), true, 1000)); } Err(Error::WantWrite(..)) => { - assert!(wait_io(&stream, false, 1000)); + assert!(wait_io(stream.get_ref(), false, 1000)); } Err(other) => { panic!("Unexpected SSL Error: {:?}", other); @@ -944,7 +957,7 @@ fn test_read_nonblocking() { n } Err(Error::WantRead(..)) => { - assert!(wait_io(&stream, true, 3000)); + assert!(wait_io(stream.get_ref(), true, 3000)); // Second read should return application data. stream.read(&mut input_buffer).unwrap() } From f1b64aa2eefc98630efefed223ae30a1c33d85e0 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 31 Jul 2016 15:59:34 -0700 Subject: [PATCH 35/96] Fix weird inference issue on 1.9 --- openssl/src/crypto/dsa.rs | 14 ++++++++------ openssl/src/crypto/rsa.rs | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index df6c255b..a1e4572a 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -245,6 +245,8 @@ impl fmt::Debug for DSA { mod test { use std::fs::File; use std::io::{Write, Cursor}; + use libc::c_char; + use super::*; use crypto::hash::*; @@ -330,12 +332,12 @@ mod test { let mut buffer = File::open("test/dsa-encrypted.pem").unwrap(); DSA::private_key_from_pem_cb(&mut buffer, |password| { password_queried = true; - password[0] = b'm' as _; - password[1] = b'y' as _; - password[2] = b'p' as _; - password[3] = b'a' as _; - password[4] = b's' as _; - password[5] = b's' as _; + password[0] = b'm' as c_char; + password[1] = b'y' as c_char; + password[2] = b'p' as c_char; + password[3] = b'a' as c_char; + password[4] = b's' as c_char; + password[5] = b's' as c_char; 6 }).unwrap(); diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index cf946d35..05c1c774 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -238,6 +238,8 @@ impl fmt::Debug for RSA { mod test { use std::fs::File; use std::io::Write; + use libc::c_char; + use super::*; use crypto::hash::*; @@ -301,12 +303,12 @@ mod test { let mut buffer = File::open("test/rsa-encrypted.pem").unwrap(); RSA::private_key_from_pem_cb(&mut buffer, |password| { password_queried = true; - password[0] = b'm' as _; - password[1] = b'y' as _; - password[2] = b'p' as _; - password[3] = b'a' as _; - password[4] = b's' as _; - password[5] = b's' as _; + password[0] = b'm' as c_char; + password[1] = b'y' as c_char; + password[2] = b'p' as c_char; + password[3] = b'a' as c_char; + password[4] = b's' as c_char; + password[5] = b's' as c_char; 6 }).unwrap(); From 5377472e9ad1b83edbfd117140bfbb7a3ad987e3 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 31 Jul 2016 16:19:40 -0700 Subject: [PATCH 36/96] Fix appveyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 8cd9e32b..054b88f2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,7 +11,7 @@ install: - ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2h.exe" - Win%BITS%OpenSSL-1_0_2h.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL" - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.9.0-${env:TARGET}.exe" - - rust-1.8.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - rust-1.9.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - SET PATH=%PATH%;C:\MinGW\bin - rustc -V From 92abf49b961febf5332766916059a4fd7947a3f6 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 31 Jul 2016 16:23:48 -0700 Subject: [PATCH 37/96] Drop unused feature gate --- openssl/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index aafbac76..d12af41c 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -1,5 +1,4 @@ #![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.14")] -#![cfg_attr(feature = "nightly", feature(const_fn))] #[macro_use] extern crate bitflags; From 635bdb45a812c1434cf94aea7e8ce5abe1321774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 1 Aug 2016 22:22:39 +0200 Subject: [PATCH 38/96] BigNum binary operators with different lifetimes. --- openssl/src/bn/mod.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/openssl/src/bn/mod.rs b/openssl/src/bn/mod.rs index 5054f0ab..ab0e0f2e 100644 --- a/openssl/src/bn/mod.rs +++ b/openssl/src/bn/mod.rs @@ -730,42 +730,42 @@ pub mod unchecked { use ffi; use super::BigNum; - impl<'a> Add<&'a BigNum> for &'a BigNum { + impl<'a, 'b> Add<&'b BigNum> for &'a BigNum { type Output = BigNum; - fn add(self, oth: &'a BigNum) -> BigNum { + fn add(self, oth: &'b BigNum) -> BigNum { self.checked_add(oth).unwrap() } } - impl<'a> Sub<&'a BigNum> for &'a BigNum { + impl<'a, 'b> Sub<&'b BigNum> for &'a BigNum { type Output = BigNum; - fn sub(self, oth: &'a BigNum) -> BigNum { + fn sub(self, oth: &'b BigNum) -> BigNum { self.checked_sub(oth).unwrap() } } - impl<'a> Mul<&'a BigNum> for &'a BigNum { + impl<'a, 'b> Mul<&'b BigNum> for &'a BigNum { type Output = BigNum; - fn mul(self, oth: &'a BigNum) -> BigNum { + fn mul(self, oth: &'b BigNum) -> BigNum { self.checked_mul(oth).unwrap() } } - impl<'a> Div<&'a BigNum> for &'a BigNum { + impl<'a, 'b> Div<&'b BigNum> for &'a BigNum { type Output = BigNum; - fn div(self, oth: &'a BigNum) -> BigNum { + fn div(self, oth: &'b BigNum) -> BigNum { self.checked_div(oth).unwrap() } } - impl<'a> Rem<&'a BigNum> for &'a BigNum { + impl<'a, 'b> Rem<&'b BigNum> for &'a BigNum { type Output = BigNum; - fn rem(self, oth: &'a BigNum) -> BigNum { + fn rem(self, oth: &'b BigNum) -> BigNum { self.checked_mod(oth).unwrap() } } From 08e27f31ed851873f7684ac806b837e8cff4a28f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 2 Aug 2016 20:48:42 -0700 Subject: [PATCH 39/96] Restructure PEM input/output methods Dealing with byte buffers directly avoids error handling weirdness and we were loading it all into memory before anyway. --- openssl-sys/src/lib.rs | 7 +++ openssl/src/bio.rs | 67 ++++++++++++++++++++ openssl/src/bio/mod.rs | 107 -------------------------------- openssl/src/crypto/dsa.rs | 75 +++++++++-------------- openssl/src/crypto/pkey.rs | 114 ++++++++++------------------------- openssl/src/crypto/rsa.rs | 58 ++++++------------ openssl/src/dh/mod.rs | 20 ++---- openssl/src/lib.rs | 2 +- openssl/src/ssl/tests/mod.rs | 15 ++--- openssl/src/x509/mod.rs | 70 ++++++--------------- openssl/src/x509/tests.rs | 57 ++++++------------ 11 files changed, 201 insertions(+), 391 deletions(-) create mode 100644 openssl/src/bio.rs delete mode 100644 openssl/src/bio/mod.rs diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 3c31f671..2deef976 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -269,6 +269,7 @@ pub type PasswordCallback = extern "C" fn(buf: *mut c_char, size: c_int, pub const BIO_TYPE_NONE: c_int = 0; pub const BIO_CTRL_EOF: c_int = 2; +pub const BIO_CTRL_INFO: c_int = 3; pub const BIO_CTRL_FLUSH: c_int = 11; pub const BIO_C_SET_BUF_MEM_EOF_RETURN: c_int = 130; @@ -453,6 +454,11 @@ fn set_id_callback() { #[cfg(not(unix))] fn set_id_callback() {} +// macros +pub unsafe fn BIO_get_mem_data(b: *mut BIO, pp: *mut *mut c_char) -> c_long { + BIO_ctrl(b, BIO_CTRL_INFO, 0, pp as *mut c_void) +} + // True functions extern "C" { pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int; @@ -466,6 +472,7 @@ extern "C" { pub fn BIO_read(b: *mut BIO, buf: *mut c_void, len: c_int) -> c_int; pub fn BIO_write(b: *mut BIO, buf: *const c_void, len: c_int) -> c_int; pub fn BIO_s_mem() -> *const BIO_METHOD; + pub fn BIO_new_mem_buf(buf: *const c_void, len: c_int) -> *mut BIO; pub fn BN_new() -> *mut BIGNUM; pub fn BN_dup(n: *mut BIGNUM) -> *mut BIGNUM; diff --git a/openssl/src/bio.rs b/openssl/src/bio.rs new file mode 100644 index 00000000..841aca0e --- /dev/null +++ b/openssl/src/bio.rs @@ -0,0 +1,67 @@ +use std::marker::PhantomData; +use std::ptr; +use std::slice; +use libc::c_int; +use ffi; + +use error::ErrorStack; + +pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>); + +impl<'a> Drop for MemBioSlice<'a> { + fn drop(&mut self) { + unsafe { + ffi::BIO_free_all(self.0); + } + } +} + +impl<'a> MemBioSlice<'a> { + pub fn new(buf: &'a [u8]) -> Result, ErrorStack> { + ffi::init(); + + assert!(buf.len() <= c_int::max_value() as usize); + let bio = unsafe { + try_ssl_null!(ffi::BIO_new_mem_buf(buf.as_ptr() as *const _, buf.len() as c_int)) + }; + + Ok(MemBioSlice(bio, PhantomData)) + } + + pub fn get_handle(&self) -> *mut ffi::BIO { + self.0 + } +} + +pub struct MemBio(*mut ffi::BIO); + +impl Drop for MemBio { + fn drop(&mut self) { + unsafe { + ffi::BIO_free_all(self.0); + } + } +} + +impl MemBio { + pub fn new() -> Result { + ffi::init(); + + let bio = unsafe { + try_ssl_null!(ffi::BIO_new(ffi::BIO_s_mem())) + }; + Ok(MemBio(bio)) + } + + pub fn get_handle(&self) -> *mut ffi::BIO { + self.0 + } + + pub fn get_buf(&self) -> &[u8] { + unsafe { + let mut ptr = ptr::null_mut(); + let len = ffi::BIO_get_mem_data(self.0, &mut ptr); + slice::from_raw_parts(ptr as *const _ as *const _, len as usize) + } + } +} diff --git a/openssl/src/bio/mod.rs b/openssl/src/bio/mod.rs deleted file mode 100644 index 2e99284f..00000000 --- a/openssl/src/bio/mod.rs +++ /dev/null @@ -1,107 +0,0 @@ -use libc::{c_void, c_int}; -use std::io; -use std::io::prelude::*; -use std::ptr; -use std::cmp; - -use ffi; -use ffi_extras; -use error::ErrorStack; - -pub struct MemBio { - bio: *mut ffi::BIO, - owned: bool, -} - -impl Drop for MemBio { - fn drop(&mut self) { - if self.owned { - unsafe { - ffi::BIO_free_all(self.bio); - } - } - } -} - -impl MemBio { - /// Creates a new owned memory based BIO - pub fn new() -> Result { - ffi::init(); - - let bio = unsafe { ffi::BIO_new(ffi::BIO_s_mem()) }; - try_ssl_null!(bio); - - Ok(MemBio { - bio: bio, - owned: true, - }) - } - - /// Returns a "borrow", i.e. it has no ownership - pub fn borrowed(bio: *mut ffi::BIO) -> MemBio { - MemBio { - bio: bio, - owned: false, - } - } - - /// Consumes current bio and returns wrapped value - /// Note that data ownership is lost and - /// should be managed manually - pub unsafe fn unwrap(mut self) -> *mut ffi::BIO { - self.owned = false; - self.bio - } - - /// Temporarily gets wrapped value - pub unsafe fn get_handle(&self) -> *mut ffi::BIO { - self.bio - } - - /// Sets the BIO's EOF state. - pub fn set_eof(&self, eof: bool) { - let v = if eof { - 0 - } else { - -1 - }; - unsafe { - ffi_extras::BIO_set_mem_eof_return(self.bio, v); - } - } -} - -impl Read for MemBio { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; - let ret = unsafe { ffi::BIO_read(self.bio, buf.as_ptr() as *mut c_void, len) }; - - if ret <= 0 { - let is_eof = unsafe { ffi_extras::BIO_eof(self.bio) }; - if is_eof != 0 { - Ok(0) - } else { - Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get())) - } - } else { - Ok(ret as usize) - } - } -} - -impl Write for MemBio { - fn write(&mut self, buf: &[u8]) -> io::Result { - let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; - let ret = unsafe { ffi::BIO_write(self.bio, buf.as_ptr() as *const c_void, len) }; - - if ret < 0 { - Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get())) - } else { - Ok(ret as usize) - } - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index a1e4572a..de35893b 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -2,11 +2,10 @@ use ffi; use std::fmt; use error::ErrorStack; use std::ptr; -use std::io::{self, Read, Write}; use libc::{c_uint, c_int, c_char, c_void}; use bn::BigNum; -use bio::MemBio; +use bio::{MemBio, MemBioSlice}; use crypto::hash; use crypto::HashTypeInternals; use crypto::util::{CallbackState, invoke_passwd_cb}; @@ -69,11 +68,9 @@ impl DSA { } /// Reads a DSA private key from PEM formatted data. - pub fn private_key_from_pem(reader: &mut R) -> io::Result - where R: Read - { - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); + pub fn private_key_from_pem(buf: &[u8]) -> Result { + ffi::init(); + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.get_handle(), @@ -91,12 +88,12 @@ impl DSA { /// /// The callback will be passed the password buffer and should return the number of characters /// placed into the buffer. - pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> io::Result - where R: Read, F: FnOnce(&mut [c_char]) -> usize + pub fn private_key_from_pem_cb(buf: &[u8], pass_cb: F) -> Result + where F: FnOnce(&mut [c_char]) -> usize { + ffi::init(); let mut cb = CallbackState::new(pass_cb); - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let cb_ptr = &mut cb as *mut _ as *mut c_void; @@ -111,11 +108,10 @@ impl DSA { } /// Writes an DSA private key as unencrypted PEM formatted data - pub fn private_key_to_pem(&self, writer: &mut W) -> io::Result<()> - where W: Write + pub fn private_key_to_pem(&self) -> Result, ErrorStack> { assert!(self.has_private_key()); - let mut mem_bio = try!(MemBio::new()); + let mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.get_handle(), self.0, @@ -123,18 +119,15 @@ impl DSA { None, ptr::null_mut())) }; - - try!(io::copy(&mut mem_bio, writer)); - Ok(()) + Ok(mem_bio.get_buf().to_owned()) } /// Reads an DSA public key from PEM formatted data. - pub fn public_key_from_pem(reader: &mut R) -> io::Result - where R: Read + pub fn public_key_from_pem(buf: &[u8]) -> Result { - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); + ffi::init(); + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let dsa = try_ssl_null!(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.get_handle(), ptr::null_mut(), @@ -145,15 +138,10 @@ impl DSA { } /// Writes an DSA public key as PEM formatted data - pub fn public_key_to_pem(&self, writer: &mut W) -> io::Result<()> - where W: Write - { - let mut mem_bio = try!(MemBio::new()); - + pub fn public_key_to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.get_handle(), self.0)) }; - - try!(io::copy(&mut mem_bio, writer)); - Ok(()) + Ok(mem_bio.get_buf().to_owned()) } pub fn size(&self) -> Option { @@ -243,8 +231,7 @@ impl fmt::Debug for DSA { #[cfg(test)] mod test { - use std::fs::File; - use std::io::{Write, Cursor}; + use std::io::Write; use libc::c_char; use super::*; @@ -253,11 +240,9 @@ mod test { #[test] pub fn test_generate() { let key = DSA::generate(1024).unwrap(); - let mut priv_buf = Cursor::new(vec![]); - let mut pub_buf = Cursor::new(vec![]); - key.public_key_to_pem(&mut pub_buf).unwrap(); - key.private_key_to_pem(&mut priv_buf).unwrap(); + key.public_key_to_pem().unwrap(); + key.private_key_to_pem().unwrap(); let input: Vec = (0..25).cycle().take(1024).collect(); @@ -277,13 +262,13 @@ mod test { let input: Vec = (0..25).cycle().take(1024).collect(); let private_key = { - let mut buffer = File::open("test/dsa.pem").unwrap(); - DSA::private_key_from_pem(&mut buffer).unwrap() + let key = include_bytes!("../../test/dsa.pem"); + DSA::private_key_from_pem(key).unwrap() }; let public_key = { - let mut buffer = File::open("test/dsa.pem.pub").unwrap(); - DSA::public_key_from_pem(&mut buffer).unwrap() + let key = include_bytes!("../../test/dsa.pem.pub"); + DSA::public_key_from_pem(key).unwrap() }; let digest = { @@ -301,13 +286,13 @@ mod test { pub fn test_sign_verify_fail() { let input: Vec = (0..25).cycle().take(128).collect(); let private_key = { - let mut buffer = File::open("test/dsa.pem").unwrap(); - DSA::private_key_from_pem(&mut buffer).unwrap() + let key = include_bytes!("../../test/dsa.pem"); + DSA::private_key_from_pem(key).unwrap() }; let public_key = { - let mut buffer = File::open("test/dsa.pem.pub").unwrap(); - DSA::public_key_from_pem(&mut buffer).unwrap() + let key = include_bytes!("../../test/dsa.pem.pub"); + DSA::public_key_from_pem(key).unwrap() }; let digest = { @@ -329,8 +314,8 @@ mod test { #[test] pub fn test_password() { let mut password_queried = false; - let mut buffer = File::open("test/dsa-encrypted.pem").unwrap(); - DSA::private_key_from_pem_cb(&mut buffer, |password| { + let key = include_bytes!("../../test/dsa-encrypted.pem"); + DSA::private_key_from_pem_cb(key, |password| { password_queried = true; password[0] = b'm' as c_char; password[1] = b'y' as c_char; diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 29feb016..ab9a4a95 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,10 +1,8 @@ use libc::{c_int, c_uint, c_ulong, c_void, c_char}; -use std::io; -use std::io::prelude::*; use std::iter::repeat; use std::mem; use std::ptr; -use bio::MemBio; +use bio::{MemBio, MemBioSlice}; use crypto::HashTypeInternals; use crypto::hash; @@ -76,12 +74,8 @@ impl PKey { } /// Reads private key from PEM, takes ownership of handle - pub fn private_key_from_pem(reader: &mut R) -> io::Result - where R: Read - { - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); - + pub fn private_key_from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), ptr::null_mut(), @@ -100,14 +94,11 @@ impl PKey { /// /// The callback will be passed the password buffer and should return the number of characters /// placed into the buffer. - pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> io::Result - where R: Read, F: FnOnce(&mut [c_char]) -> usize + pub fn private_key_from_pem_cb(buf: &[u8], pass_cb: F) -> Result + where F: FnOnce(&mut [c_char]) -> usize { let mut cb = CallbackState::new(pass_cb); - - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); - + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), ptr::null_mut(), @@ -122,12 +113,8 @@ impl PKey { } /// Reads public key from PEM, takes ownership of handle - pub fn public_key_from_pem(reader: &mut R) -> io::Result - where R: Read - { - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); - + pub fn public_key_from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.get_handle(), ptr::null_mut(), @@ -141,14 +128,12 @@ impl PKey { } /// Reads an RSA private key from PEM, takes ownership of handle - pub fn private_rsa_key_from_pem(reader: &mut R) -> io::Result - where R: Read - { - let rsa = try!(RSA::private_key_from_pem(reader)); + pub fn private_rsa_key_from_pem(buf: &[u8]) -> Result { + let rsa = try!(RSA::private_key_from_pem(buf)); unsafe { let evp = try_ssl_null!(ffi::EVP_PKEY_new()); if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 { - return Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get())); + return Err(ErrorStack::get()); } Ok(PKey { @@ -159,14 +144,12 @@ impl PKey { } /// Reads an RSA public key from PEM, takes ownership of handle - pub fn public_rsa_key_from_pem(reader: &mut R) -> io::Result - where R: Read - { - let rsa = try!(RSA::public_key_from_pem(reader)); + pub fn public_rsa_key_from_pem(buf: &[u8]) -> Result { + let rsa = try!(RSA::public_key_from_pem(buf)); unsafe { let evp = try_ssl_null!(ffi::EVP_PKEY_new()); if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 { - return Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get())); + return Err(ErrorStack::get()); } Ok(PKey { @@ -280,10 +263,8 @@ impl PKey { /// Stores private key as a PEM // FIXME: also add password and encryption - pub fn write_pem(&self, - writer: &mut W /* , password: Option */) - -> io::Result<()> { - let mut mem_bio = try!(MemBio::new()); + pub fn write_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.get_handle(), self.evp, @@ -294,20 +275,14 @@ impl PKey { ptr::null_mut())); } - let mut buf = vec![]; - try!(mem_bio.read_to_end(&mut buf)); - writer.write_all(&buf) + Ok(mem_bio.get_buf().to_owned()) } /// Stores public key as a PEM - pub fn write_pub_pem(&self, - writer: &mut W /* , password: Option */) - -> io::Result<()> { - let mut mem_bio = try!(MemBio::new()); + pub fn write_pub_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.get_handle(), self.evp)) } - let mut buf = vec![]; - try!(mem_bio.read_to_end(&mut buf)); - writer.write_all(&buf) + Ok(mem_bio.get_buf().to_owned()) } /** @@ -648,8 +623,6 @@ impl Clone for PKey { #[cfg(test)] mod tests { - use std::path::Path; - use std::fs::File; use crypto::hash::Type::{MD5, SHA1}; use crypto::rsa::RSA; @@ -693,42 +666,26 @@ mod tests { #[test] fn test_private_key_from_pem() { - let key_path = Path::new("test/key.pem"); - let mut file = File::open(&key_path) - .ok() - .expect("Failed to open `test/key.pem`"); - - super::PKey::private_key_from_pem(&mut file).unwrap(); + let key = include_bytes!("../../test/key.pem"); + super::PKey::private_key_from_pem(key).unwrap(); } #[test] fn test_public_key_from_pem() { - let key_path = Path::new("test/key.pem.pub"); - let mut file = File::open(&key_path) - .ok() - .expect("Failed to open `test/key.pem.pub`"); - - super::PKey::public_key_from_pem(&mut file).unwrap(); + let key = include_bytes!("../../test/key.pem.pub"); + super::PKey::public_key_from_pem(key).unwrap(); } #[test] fn test_private_rsa_key_from_pem() { - let key_path = Path::new("test/key.pem"); - let mut file = File::open(&key_path) - .ok() - .expect("Failed to open `test/key.pem`"); - - super::PKey::private_rsa_key_from_pem(&mut file).unwrap(); + let key = include_bytes!("../../test/key.pem"); + super::PKey::private_rsa_key_from_pem(key).unwrap(); } #[test] fn test_public_rsa_key_from_pem() { - let key_path = Path::new("test/key.pem.pub"); - let mut file = File::open(&key_path) - .ok() - .expect("Failed to open `test/key.pem.pub`"); - - super::PKey::public_rsa_key_from_pem(&mut file).unwrap(); + let key = include_bytes!("../../test/key.pem.pub"); + super::PKey::public_rsa_key_from_pem(key).unwrap(); } #[test] @@ -819,18 +776,11 @@ mod tests { #[test] fn test_pem() { - let key_path = Path::new("test/key.pem"); - let mut file = File::open(&key_path) - .ok() - .expect("Failed to open `test/key.pem`"); + let key = include_bytes!("../../test/key.pem"); + let key = super::PKey::private_key_from_pem(key).unwrap(); - let key = super::PKey::private_key_from_pem(&mut file).unwrap(); - - let mut priv_key = Vec::new(); - let mut pub_key = Vec::new(); - - key.write_pem(&mut priv_key).unwrap(); - key.write_pub_pem(&mut pub_key).unwrap(); + let priv_key = key.write_pem().unwrap(); + let pub_key = key.write_pub_pem().unwrap(); // As a super-simple verification, just check that the buffers contain // the `PRIVATE KEY` or `PUBLIC KEY` strings. diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 05c1c774..226b2aab 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -1,11 +1,10 @@ use ffi; use std::fmt; use std::ptr; -use std::io::{self, Read, Write}; use libc::{c_int, c_void, c_char}; use bn::BigNum; -use bio::MemBio; +use bio::{MemBio, MemBioSlice}; use error::ErrorStack; use crypto::HashTypeInternals; use crypto::hash; @@ -62,12 +61,8 @@ impl RSA { } /// Reads an RSA private key from PEM formatted data. - pub fn private_key_from_pem(reader: &mut R) -> io::Result - where R: Read - { - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); - + pub fn private_key_from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.get_handle(), ptr::null_mut(), @@ -78,13 +73,11 @@ impl RSA { } /// Reads an RSA private key from PEM formatted data and supplies a password callback. - pub fn private_key_from_pem_cb(reader: &mut R, pass_cb: F) -> io::Result - where R: Read, F: FnOnce(&mut [c_char]) -> usize + pub fn private_key_from_pem_cb(buf: &[u8], pass_cb: F) -> Result + where F: FnOnce(&mut [c_char]) -> usize { let mut cb = CallbackState::new(pass_cb); - - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let cb_ptr = &mut cb as *mut _ as *mut c_void; @@ -98,10 +91,8 @@ impl RSA { } /// Writes an RSA private key as unencrypted PEM formatted data - pub fn private_key_to_pem(&self, writer: &mut W) -> io::Result<()> - where W: Write - { - let mut mem_bio = try!(MemBio::new()); + pub fn private_key_to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.get_handle(), @@ -112,17 +103,12 @@ impl RSA { None, ptr::null_mut())); } - try!(io::copy(&mut mem_bio, writer)); - Ok(()) + Ok(mem_bio.get_buf().to_owned()) } /// Reads an RSA public key from PEM formatted data. - pub fn public_key_from_pem(reader: &mut R) -> io::Result - where R: Read - { - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); - + pub fn public_key_from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.get_handle(), ptr::null_mut(), @@ -133,17 +119,14 @@ impl RSA { } /// Writes an RSA public key as PEM formatted data - pub fn public_key_to_pem(&self, writer: &mut W) -> io::Result<()> - where W: Write - { - let mut mem_bio = try!(MemBio::new()); + pub fn public_key_to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.get_handle(), self.0)) }; - try!(io::copy(&mut mem_bio, writer)); - Ok(()) + Ok(mem_bio.get_buf().to_owned()) } pub fn size(&self) -> Option { @@ -236,7 +219,6 @@ impl fmt::Debug for RSA { #[cfg(test)] mod test { - use std::fs::File; use std::io::Write; use libc::c_char; @@ -271,8 +253,8 @@ mod test { #[test] pub fn test_sign() { - let mut buffer = File::open("test/rsa.pem").unwrap(); - let private_key = RSA::private_key_from_pem(&mut buffer).unwrap(); + let key = include_bytes!("../../test/rsa.pem"); + let private_key = RSA::private_key_from_pem(key).unwrap(); let mut sha = Hasher::new(Type::SHA256); sha.write_all(&signing_input_rs256()).unwrap(); @@ -285,8 +267,8 @@ mod test { #[test] pub fn test_verify() { - let mut buffer = File::open("test/rsa.pem.pub").unwrap(); - let public_key = RSA::public_key_from_pem(&mut buffer).unwrap(); + let key = include_bytes!("../../test/rsa.pem.pub"); + let public_key = RSA::public_key_from_pem(key).unwrap(); let mut sha = Hasher::new(Type::SHA256); sha.write_all(&signing_input_rs256()).unwrap(); @@ -300,8 +282,8 @@ mod test { #[test] pub fn test_password() { let mut password_queried = false; - let mut buffer = File::open("test/rsa-encrypted.pem").unwrap(); - RSA::private_key_from_pem_cb(&mut buffer, |password| { + let key = include_bytes!("../../test/rsa-encrypted.pem"); + RSA::private_key_from_pem_cb(key, |password| { password_queried = true; password[0] = b'm' as c_char; password[1] = b'y' as c_char; diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index bf1ca73e..df6f1b0a 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -1,8 +1,6 @@ use ffi; -use std::io; -use std::io::prelude::*; use error::ErrorStack; -use bio::MemBio; +use bio::MemBioSlice; use bn::BigNum; use std::mem; use std::ptr; @@ -18,11 +16,8 @@ impl DH { Ok(DH(dh)) } - pub fn from_pem(reader: &mut R) -> io::Result - where R: Read - { - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); + pub fn from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); let dh = unsafe { ffi::PEM_read_bio_DHparams(mem_bio.get_handle(), ptr::null_mut(), None, ptr::null_mut()) }; @@ -71,8 +66,6 @@ impl Drop for DH { #[cfg(test)] mod tests { - use std::fs::File; - use std::path::Path; use super::DH; use bn::BigNum; use ssl::SslContext; @@ -123,11 +116,8 @@ mod tests { #[test] fn test_dh_from_pem() { let mut ctx = SslContext::new(Sslv23).unwrap(); - let pem_path = Path::new("test/dhparams.pem"); - let mut file = File::open(&pem_path) - .ok() - .expect("Failed to open `test/dhparams.pem`"); - let dh = DH::from_pem(&mut file).ok().expect("Failed to load PEM"); + let params = include_bytes!("../../test/dhparams.pem"); + let dh = DH::from_pem(params).ok().expect("Failed to load PEM"); ctx.set_tmp_dh(dh).unwrap(); } } diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index d12af41c..4cd76613 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -17,7 +17,7 @@ extern crate net2; mod macros; pub mod asn1; -pub mod bio; +mod bio; pub mod bn; pub mod crypto; pub mod dh; diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 0b638546..b774b383 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -418,17 +418,10 @@ fn test_write_hits_stream() { #[test] fn test_set_certificate_and_private_key() { - let key_path = Path::new("test/key.pem"); - let cert_path = Path::new("test/cert.pem"); - let mut key_file = File::open(&key_path) - .ok() - .expect("Failed to open `test/key.pem`"); - let mut cert_file = File::open(&cert_path) - .ok() - .expect("Failed to open `test/cert.pem`"); - - let key = PKey::private_key_from_pem(&mut key_file).unwrap(); - let cert = X509::from_pem(&mut cert_file).unwrap(); + let key = include_bytes!("../../../test/key.pem"); + let key = PKey::private_key_from_pem(key).unwrap(); + let cert = include_bytes!("../../../test/cert.pem"); + let cert = X509::from_pem(cert).unwrap(); let mut ctx = SslContext::new(Sslv23).unwrap(); ctx.set_private_key(&key).unwrap(); diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 05d8221e..64a61df0 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -1,6 +1,4 @@ use libc::{c_char, c_int, c_long, c_ulong, c_uint, c_void}; -use std::io; -use std::io::prelude::*; use std::cmp::Ordering; use std::ffi::CString; use std::iter::repeat; @@ -14,7 +12,7 @@ use std::collections::HashMap; use std::marker::PhantomData; use asn1::Asn1Time; -use bio::MemBio; +use bio::{MemBio, MemBioSlice}; use crypto::hash; use crypto::hash::Type as HashType; use crypto::pkey::{PKey, Parts}; @@ -116,13 +114,6 @@ impl X509StoreContext { /// # Example /// /// ``` -/// # #[allow(unstable)] -/// # fn main() { -/// use std::fs; -/// use std::fs::File; -/// use std::io::prelude::*; -/// use std::path::Path; -/// /// use openssl::crypto::hash::Type; /// use openssl::x509::X509Generator; /// use openssl::x509::extension::{Extension, KeyUsageOption}; @@ -135,17 +126,8 @@ impl X509StoreContext { /// .add_extension(Extension::KeyUsage(vec![KeyUsageOption::DigitalSignature])); /// /// let (cert, pkey) = gen.generate().unwrap(); -/// -/// let cert_path = "doc_cert.pem"; -/// let mut file = File::create(cert_path).unwrap(); -/// assert!(cert.write_pem(&mut file).is_ok()); -/// # let _ = fs::remove_file(cert_path); -/// -/// let pkey_path = "doc_key.pem"; -/// let mut file = File::create(pkey_path).unwrap(); -/// assert!(pkey.write_pem(&mut file).is_ok()); -/// # let _ = fs::remove_file(pkey_path); -/// # } +/// let cert_pem = cert.write_pem().unwrap(); +/// let pkey_pem = pkey.write_pem().unwrap(); /// ``` pub struct X509Generator { bits: u32, @@ -444,12 +426,8 @@ impl<'ctx> X509<'ctx> { } /// Reads certificate from PEM, takes ownership of handle - pub fn from_pem(reader: &mut R) -> io::Result> - where R: Read - { - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); - + pub fn from_pem(buf: &[u8]) -> Result, ErrorStack> { + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(), ptr::null_mut(), @@ -523,25 +501,21 @@ impl<'ctx> X509<'ctx> { } /// Writes certificate as PEM - pub fn write_pem(&self, writer: &mut W) -> io::Result<()> - where W: Write - { - let mut mem_bio = try!(MemBio::new()); + pub fn write_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), self.handle)); } - io::copy(&mut mem_bio, writer).map(|_| ()) + Ok(mem_bio.get_buf().to_owned()) } /// Returns a DER serialized form of the certificate pub fn save_der(&self) -> Result, ErrorStack> { - let mut mem_bio = try!(MemBio::new()); + let mem_bio = try!(MemBio::new()); unsafe { ffi::i2d_X509_bio(mem_bio.get_handle(), self.handle); } - let mut v = Vec::new(); - drop(io::copy(&mut mem_bio, &mut v)); - Ok(v) + Ok(mem_bio.get_buf().to_owned()) } } @@ -627,12 +601,8 @@ impl X509Req { } /// Reads CSR from PEM - pub fn from_pem(reader: &mut R) -> io::Result - where R: Read - { - let mut mem_bio = try!(MemBio::new()); - try!(io::copy(reader, &mut mem_bio)); - + pub fn from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.get_handle(), ptr::null_mut(), @@ -643,25 +613,21 @@ impl X509Req { } /// Writes CSR as PEM - pub fn write_pem(&self, writer: &mut W) -> io::Result<()> - where W: Write - { - let mut mem_bio = try!(MemBio::new()); + pub fn write_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), self.handle) } != 1 { - return Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get())); + return Err(ErrorStack::get()); } - io::copy(&mut mem_bio, writer).map(|_| ()) + Ok(mem_bio.get_buf().to_owned()) } /// Returns a DER serialized form of the CSR pub fn save_der(&self) -> Result, ErrorStack> { - let mut mem_bio = try!(MemBio::new()); + let mem_bio = try!(MemBio::new()); unsafe { ffi::i2d_X509_REQ_bio(mem_bio.get_handle(), self.handle); } - let mut v = Vec::new(); - drop(io::copy(&mut mem_bio, &mut v)); - Ok(v) + Ok(mem_bio.get_buf().to_owned()) } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 5d9b30ab..167ca8cf 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -1,7 +1,4 @@ use serialize::hex::FromHex; -use std::io; -use std::path::Path; -use std::fs::File; use crypto::hash::Type::SHA1; use crypto::pkey::PKey; @@ -30,8 +27,8 @@ fn get_generator() -> X509Generator { #[test] fn test_cert_gen() { let (cert, pkey) = get_generator().generate().unwrap(); - cert.write_pem(&mut io::sink()).unwrap(); - pkey.write_pem(&mut io::sink()).unwrap(); + cert.write_pem().unwrap(); + pkey.write_pem().unwrap(); // FIXME: check data in result to be correct, needs implementation // of X509 getters @@ -70,7 +67,7 @@ fn test_req_gen() { pkey.gen(512); let req = get_generator().request(&pkey).unwrap(); - req.write_pem(&mut io::sink()).unwrap(); + req.write_pem().unwrap(); // FIXME: check data in result to be correct, needs implementation // of X509_REQ getters @@ -78,12 +75,8 @@ fn test_req_gen() { #[test] fn test_cert_loading() { - let cert_path = Path::new("test/cert.pem"); - let mut file = File::open(&cert_path) - .ok() - .expect("Failed to open `test/cert.pem`"); - - let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM"); + let cert = include_bytes!("../../test/cert.pem"); + let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); let fingerprint = cert.fingerprint(SHA1).unwrap(); let hash_str = "E19427DAC79FBE758394945276A6E4F15F0BEBE6"; @@ -94,12 +87,8 @@ fn test_cert_loading() { #[test] fn test_save_der() { - let cert_path = Path::new("test/cert.pem"); - let mut file = File::open(&cert_path) - .ok() - .expect("Failed to open `test/cert.pem`"); - - let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM"); + let cert = include_bytes!("../../test/cert.pem"); + let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); let der = cert.save_der().unwrap(); assert!(!der.is_empty()); @@ -107,12 +96,8 @@ fn test_save_der() { #[test] fn test_subject_read_cn() { - let cert_path = Path::new("test/cert.pem"); - let mut file = File::open(&cert_path) - .ok() - .expect("Failed to open `test/cert.pem`"); - - let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM"); + let cert = include_bytes!("../../test/cert.pem"); + let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); let subject = cert.subject_name(); let cn = match subject.text_by_nid(Nid::CN) { Some(x) => x, @@ -124,12 +109,8 @@ fn test_subject_read_cn() { #[test] fn test_nid_values() { - let cert_path = Path::new("test/nid_test_cert.pem"); - let mut file = File::open(&cert_path) - .ok() - .expect("Failed to open `test/nid_test_cert.pem`"); - - let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM"); + let cert = include_bytes!("../../test/nid_test_cert.pem"); + let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); let subject = cert.subject_name(); let cn = match subject.text_by_nid(Nid::CN) { @@ -153,12 +134,8 @@ fn test_nid_values() { #[test] fn test_nid_uid_value() { - let cert_path = Path::new("test/nid_uid_test_cert.pem"); - let mut file = File::open(&cert_path) - .ok() - .expect("Failed to open `test/nid_uid_test_cert.pem`"); - - let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM"); + let cert = include_bytes!("../../test/nid_uid_test_cert.pem"); + let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); let subject = cert.subject_name(); let cn = match subject.text_by_nid(Nid::UserId) { @@ -170,8 +147,8 @@ fn test_nid_uid_value() { #[test] fn test_subject_alt_name() { - let mut file = File::open("test/alt_name_cert.pem").unwrap(); - let cert = X509::from_pem(&mut file).unwrap(); + let cert = include_bytes!("../../test/alt_name_cert.pem"); + let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); let subject_alt_names = cert.subject_alt_names().unwrap(); assert_eq!(3, subject_alt_names.len()); @@ -184,8 +161,8 @@ fn test_subject_alt_name() { #[test] fn test_subject_alt_name_iter() { - let mut file = File::open("test/alt_name_cert.pem").unwrap(); - let cert = X509::from_pem(&mut file).unwrap(); + let cert = include_bytes!("../../test/alt_name_cert.pem"); + let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); let subject_alt_names = cert.subject_alt_names().unwrap(); let mut subject_alt_names_iter = subject_alt_names.iter(); From abacc8bb18c73ef6fbec5dabe8398ca9735d86e0 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 2 Aug 2016 22:14:44 -0700 Subject: [PATCH 40/96] Define SSL_CTX_set_mode in openssl-sys --- openssl-sys/src/lib.rs | 7 +++++++ openssl/src/ssl/mod.rs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 2deef976..ba51b597 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -9,6 +9,7 @@ extern crate libressl_pnacl_sys; use libc::{c_void, c_int, c_char, c_ulong, c_long, c_uint, c_uchar, size_t}; use std::mem; +use std::ptr; use std::sync::{Mutex, MutexGuard}; use std::sync::{Once, ONCE_INIT}; @@ -287,6 +288,7 @@ pub const NID_key_usage: c_int = 83; pub const PKCS5_SALT_LEN: c_int = 8; pub const SSL_CTRL_OPTIONS: c_int = 32; +pub const SSL_CTRL_MODE: c_int = 33; pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77; pub const SSL_CTRL_SET_TLSEXT_SERVERNAME_CB: c_int = 53; @@ -459,6 +461,10 @@ pub unsafe fn BIO_get_mem_data(b: *mut BIO, pp: *mut *mut c_char) -> c_long { BIO_ctrl(b, BIO_CTRL_INFO, 0, pp as *mut c_void) } +pub unsafe fn SSL_CTX_set_mode(ctx: *mut SSL_CTX, op: c_long) -> c_long { + SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, op, ptr::null_mut()) +} + // True functions extern "C" { pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int; @@ -787,6 +793,7 @@ extern "C" { pub fn SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX; pub fn SSL_CTX_free(ctx: *mut SSL_CTX); + pub fn SSL_CTX_ctrl(ctx: *mut SSL_CTX, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long; pub fn SSL_CTX_set_verify(ctx: *mut SSL_CTX, mode: c_int, verify_callback: Option c_int>); pub fn SSL_CTX_set_verify_depth(ctx: *mut SSL_CTX, depth: c_int); diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 3d1ec6e5..2db2f0f9 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -531,7 +531,7 @@ impl SslContext { } fn set_mode(&mut self, mode: c_long) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_mode(self.ctx, mode) as c_int }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_set_mode(self.ctx, mode) as c_int }) } pub fn set_tmp_dh(&mut self, dh: DH) -> Result<(), ErrorStack> { From 17474520bc2130cb93e6804c7a36b4ebf9984c0b Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 4 Aug 2016 22:14:18 -0700 Subject: [PATCH 41/96] Support basic SSL options without C shims --- openssl-sys/src/lib.rs | 48 +++++++++++++++++++++++++ openssl/src/ssl/mod.rs | 82 ++++++++++++++++-------------------------- 2 files changed, 79 insertions(+), 51 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index ba51b597..cf57196e 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -313,6 +313,42 @@ pub const SSL_VERIFY_NONE: c_int = 0; pub const SSL_VERIFY_PEER: c_int = 1; pub const SSL_VERIFY_FAIL_IF_NO_PEER_CERT: c_int = 2; +pub const SSL_OP_MICROSOFT_SESS_ID_BUG: c_long = 0x00000001; +pub const SSL_OP_NETSCAPE_CHALLENGE_BUG: c_long = 0x00000002; +pub const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: c_long = 0x00000008; +pub const SSL_OP_TLSEXT_PADDING: c_long = 0x00000010; +pub const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: c_long = 0x00000020; +pub const SSL_OP_SSLEAY_080_CLIENT_DH_BUG: c_long = 0x00000080; +pub const SSL_OP_TLS_D5_BUG: c_long = 0x00000100; +pub const SSL_OP_TLS_BLOCK_PADDING_BUG: c_long = 0x00000200; +pub const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: c_long = 0x00000800; +pub const SSL_OP_ALL: c_long = 0x80000BFF; +pub const SSL_OP_NO_QUERY_MTU: c_long = 0x00001000; +pub const SSL_OP_COOKIE_EXCHANGE: c_long = 0x00002000; +pub const SSL_OP_NO_TICKET: c_long = 0x00004000; +pub const SSL_OP_CISCO_ANYCONNECT: c_long = 0x00008000; +pub const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: c_long = 0x00010000; +pub const SSL_OP_NO_COMPRESSION: c_long = 0x00020000; +pub const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: c_long = 0x00040000; +pub const SSL_OP_SINGLE_ECDH_USE: c_long = 0x00080000; +pub const SSL_OP_SINGLE_DH_USE: c_long = 0x00100000; +pub const SSL_OP_CIPHER_SERVER_PREFERENCE: c_long = 0x00400000; +pub const SSL_OP_TLS_ROLLBACK_BUG: c_long = 0x00800000; +pub const SSL_OP_NO_SSLv2: c_long = 0x01000000; +pub const SSL_OP_NO_SSLv3: c_long = 0x02000000; +pub const SSL_OP_NO_TLSv1: c_long = 0x04000000; + +// Intentionally not bound since they conflict with SSL_OP_PKCS1_CHECK_1 and +// SSL_OP_PKCS1_CHECK_2 on 0.9.8 :( +/* +pub const SSL_OP_NO_TLSv1_2: c_long = 0x08000000; +pub const SSL_OP_NO_TLSv1_1: c_long = 0x10000000; +pub const SSL_OP_NO_DTLSv1: c_long = 0x04000000; +pub const SSL_OP_NO_DTLSv1_2: c_long = 0x08000000; +pub const SSL_OP_NO_SSL_MASK: c_long = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | + SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2; +*/ + pub const TLSEXT_NAMETYPE_host_name: c_long = 0; pub const SSL_TLSEXT_ERR_OK: c_int = 0; @@ -465,6 +501,18 @@ pub unsafe fn SSL_CTX_set_mode(ctx: *mut SSL_CTX, op: c_long) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, op, ptr::null_mut()) } +pub unsafe fn SSL_CTX_set_options(ctx: *mut SSL_CTX, op: c_long) -> c_long { + SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, op, ptr::null_mut()) +} + +pub unsafe fn SSL_CTX_clear_options(ctx: *mut SSL_CTX, op: c_long) -> c_long { + SSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_OPTIONS, op, ptr::null_mut()) +} + +pub unsafe fn SSL_CTX_get_options(ctx: *mut SSL_CTX) -> c_long { + SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, 0, ptr::null_mut()) +} + // True functions extern "C" { pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 2db2f0f9..39dd80de 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -49,52 +49,34 @@ pub fn init() { } bitflags! { - pub flags SslContextOptions: u64 { - const SSL_OP_MICROSOFT_SESS_ID_BUG = ::ffi_extras::SSL_OP_MICROSOFT_SESS_ID_BUG, - const SSL_OP_NETSCAPE_CHALLENGE_BUG = ::ffi_extras::SSL_OP_NETSCAPE_CHALLENGE_BUG, - const SSL_OP_LEGACY_SERVER_CONNECT = ::ffi_extras::SSL_OP_LEGACY_SERVER_CONNECT, - const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = ::ffi_extras::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG, - const SSL_OP_TLSEXT_PADDING = ::ffi_extras::SSL_OP_TLSEXT_PADDING, - const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = ::ffi_extras::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER, - const SSL_OP_SAFARI_ECDHE_ECDSA_BUG = ::ffi_extras::SSL_OP_SAFARI_ECDHE_ECDSA_BUG, - const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = ::ffi_extras::SSL_OP_SSLEAY_080_CLIENT_DH_BUG, - const SSL_OP_TLS_D5_BUG = ::ffi_extras::SSL_OP_TLS_D5_BUG, - const SSL_OP_TLS_BLOCK_PADDING_BUG = ::ffi_extras::SSL_OP_TLS_BLOCK_PADDING_BUG, - const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = ::ffi_extras::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, - const SSL_OP_NO_QUERY_MTU = ::ffi_extras::SSL_OP_NO_QUERY_MTU, - const SSL_OP_COOKIE_EXCHANGE = ::ffi_extras::SSL_OP_COOKIE_EXCHANGE, - const SSL_OP_NO_TICKET = ::ffi_extras::SSL_OP_NO_TICKET, - const SSL_OP_CISCO_ANYCONNECT = ::ffi_extras::SSL_OP_CISCO_ANYCONNECT, - const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = ::ffi_extras::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, - const SSL_OP_NO_COMPRESSION = ::ffi_extras::SSL_OP_NO_COMPRESSION, - const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = ::ffi_extras::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, - const SSL_OP_SINGLE_ECDH_USE = ::ffi_extras::SSL_OP_SINGLE_ECDH_USE, - const SSL_OP_SINGLE_DH_USE = ::ffi_extras::SSL_OP_SINGLE_DH_USE, - const SSL_OP_CIPHER_SERVER_PREFERENCE = ::ffi_extras::SSL_OP_CIPHER_SERVER_PREFERENCE, - const SSL_OP_TLS_ROLLBACK_BUG = ::ffi_extras::SSL_OP_TLS_ROLLBACK_BUG, - const SSL_OP_NO_SSLV2 = ::ffi_extras::SSL_OP_NO_SSLv2, - const SSL_OP_NO_SSLV3 = ::ffi_extras::SSL_OP_NO_SSLv3, - const SSL_OP_NO_DTLSV1 = ::ffi_extras::SSL_OP_NO_DTLSv1, - const SSL_OP_NO_TLSV1 = ::ffi_extras::SSL_OP_NO_TLSv1, - const SSL_OP_NO_DTLSV1_2 = ::ffi_extras::SSL_OP_NO_DTLSv1_2, - const SSL_OP_NO_TLSV1_2 = ::ffi_extras::SSL_OP_NO_TLSv1_2, - const SSL_OP_NO_TLSV1_1 = ::ffi_extras::SSL_OP_NO_TLSv1_1, - const SSL_OP_NETSCAPE_CA_DN_BUG = ::ffi_extras::SSL_OP_NETSCAPE_CA_DN_BUG, - const SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = ::ffi_extras::SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG, - const SSL_OP_CRYPTOPRO_TLSEXT_BUG = ::ffi_extras::SSL_OP_CRYPTOPRO_TLSEXT_BUG, - const SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = ::ffi_extras::SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG, - const SSL_OP_MSIE_SSLV2_RSA_PADDING = ::ffi_extras::SSL_OP_MSIE_SSLV2_RSA_PADDING, - const SSL_OP_PKCS1_CHECK_1 = ::ffi_extras::SSL_OP_PKCS1_CHECK_1, - const SSL_OP_PKCS1_CHECK_2 = ::ffi_extras::SSL_OP_PKCS1_CHECK_2, - const SSL_OP_EPHEMERAL_RSA = ::ffi_extras::SSL_OP_EPHEMERAL_RSA, - const SSL_OP_ALL = SSL_OP_MICROSOFT_SESS_ID_BUG.bits|SSL_OP_NETSCAPE_CHALLENGE_BUG.bits - |SSL_OP_LEGACY_SERVER_CONNECT.bits|SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG.bits - |SSL_OP_TLSEXT_PADDING.bits|SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER.bits - |SSL_OP_SAFARI_ECDHE_ECDSA_BUG.bits|SSL_OP_SSLEAY_080_CLIENT_DH_BUG.bits - |SSL_OP_TLS_D5_BUG.bits|SSL_OP_TLS_BLOCK_PADDING_BUG.bits - |SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS.bits|SSL_OP_CRYPTOPRO_TLSEXT_BUG.bits, - const SSL_OP_NO_SSL_MASK = SSL_OP_NO_SSLV2.bits|SSL_OP_NO_SSLV3.bits|SSL_OP_NO_TLSV1.bits - |SSL_OP_NO_TLSV1_1.bits|SSL_OP_NO_TLSV1_2.bits, + pub flags SslContextOptions: c_long { + const SSL_OP_MICROSOFT_SESS_ID_BUG = ffi::SSL_OP_MICROSOFT_SESS_ID_BUG, + const SSL_OP_NETSCAPE_CHALLENGE_BUG = ffi::SSL_OP_NETSCAPE_CHALLENGE_BUG, + const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = + ffi::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG, + const SSL_OP_TLSEXT_PADDING = ffi::SSL_OP_TLSEXT_PADDING, + const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = ffi::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER, + const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = ffi::SSL_OP_SSLEAY_080_CLIENT_DH_BUG, + const SSL_OP_TLS_D5_BUG = ffi::SSL_OP_TLS_D5_BUG, + const SSL_OP_TLS_BLOCK_PADDING_BUG = ffi::SSL_OP_TLS_BLOCK_PADDING_BUG, + const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, + const SSL_OP_ALL = ffi::SSL_OP_ALL, + const SSL_OP_NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU, + const SSL_OP_COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE, + const SSL_OP_NO_TICKET = ffi::SSL_OP_NO_TICKET, + const SSL_OP_CISCO_ANYCONNECT = ffi::SSL_OP_CISCO_ANYCONNECT, + const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = + ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, + const SSL_OP_NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION, + const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = + ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, + const SSL_OP_SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE, + const SSL_OP_SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE, + const SSL_OP_CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE, + const SSL_OP_TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG, + const SSL_OP_NO_SSLV2 = ffi::SSL_OP_NO_SSLv2, + const SSL_OP_NO_SSLV3 = ffi::SSL_OP_NO_SSLv3, + const SSL_OP_NO_TLSV1 = ffi::SSL_OP_NO_TLSv1, } } @@ -649,19 +631,17 @@ impl SslContext { } pub fn set_options(&mut self, option: SslContextOptions) -> SslContextOptions { - let raw_bits = option.bits(); - let ret = unsafe { ffi_extras::SSL_CTX_set_options(self.ctx, raw_bits) }; + let ret = unsafe { ffi::SSL_CTX_set_options(self.ctx, option.bits()) }; SslContextOptions::from_bits(ret).unwrap() } pub fn options(&self) -> SslContextOptions { - let ret = unsafe { ffi_extras::SSL_CTX_get_options(self.ctx) }; + let ret = unsafe { ffi::SSL_CTX_get_options(self.ctx) }; SslContextOptions::from_bits(ret).unwrap() } pub fn clear_options(&mut self, option: SslContextOptions) -> SslContextOptions { - let raw_bits = option.bits(); - let ret = unsafe { ffi_extras::SSL_CTX_clear_options(self.ctx, raw_bits) }; + let ret = unsafe { ffi::SSL_CTX_clear_options(self.ctx, option.bits()) }; SslContextOptions::from_bits(ret).unwrap() } From dd16f64f896c01804a03883bf15cf4d40a7a9ed8 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 4 Aug 2016 22:15:50 -0700 Subject: [PATCH 42/96] Stop once-ing init wrapper The underlying function already once-s itself --- openssl/src/ssl/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 39dd80de..84d3613c 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -10,7 +10,7 @@ use std::mem; use std::str; use std::path::Path; use std::ptr; -use std::sync::{Once, ONCE_INIT, Mutex, Arc}; +use std::sync::{Mutex, Arc}; use std::cmp; use std::any::Any; #[cfg(any(feature = "npn", feature = "alpn"))] @@ -44,8 +44,7 @@ extern "C" { /// Manually initialize SSL. /// It is optional to call this function and safe to do so more than once. pub fn init() { - static mut INIT: Once = ONCE_INIT; - unsafe { INIT.call_once(|| ffi::init()); } + ffi::init(); } bitflags! { From b29ea624915454cc52b00a6ba7a2b8e3cfb03bc9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 4 Aug 2016 22:22:55 -0700 Subject: [PATCH 43/96] Move BIO macros into -sys --- openssl-sys/src/lib.rs | 20 ++++++++++++++++++++ openssl/src/ssl/bio.rs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index cf57196e..5bfe3d4a 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -274,6 +274,12 @@ pub const BIO_CTRL_INFO: c_int = 3; pub const BIO_CTRL_FLUSH: c_int = 11; pub const BIO_C_SET_BUF_MEM_EOF_RETURN: c_int = 130; +pub const BIO_FLAGS_READ: c_int = 0x01; +pub const BIO_FLAGS_WRITE: c_int = 0x02; +pub const BIO_FLAGS_IO_SPECIAL: c_int = 0x04; +pub const BIO_FLAGS_RWS: c_int = BIO_FLAGS_READ | BIO_FLAGS_WRITE | BIO_FLAGS_IO_SPECIAL; +pub const BIO_FLAGS_SHOULD_RETRY: c_int = 0x08; + pub const CRYPTO_LOCK: c_int = 1; pub const MBSTRING_ASC: c_int = MBSTRING_FLAG | 1; @@ -497,6 +503,18 @@ pub unsafe fn BIO_get_mem_data(b: *mut BIO, pp: *mut *mut c_char) -> c_long { BIO_ctrl(b, BIO_CTRL_INFO, 0, pp as *mut c_void) } +pub unsafe fn BIO_clear_retry_flags(b: *mut BIO) { + BIO_clear_flags(b, BIO_FLAGS_RWS | BIO_FLAGS_SHOULD_RETRY) +} + +pub unsafe fn BIO_set_retry_read(b: *mut BIO) { + BIO_set_flags(b, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY) +} + +pub unsafe fn BIO_set_retry_write(b: *mut BIO) { + BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY) +} + pub unsafe fn SSL_CTX_set_mode(ctx: *mut SSL_CTX, op: c_long) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, op, ptr::null_mut()) } @@ -527,6 +545,8 @@ extern "C" { pub fn BIO_write(b: *mut BIO, buf: *const c_void, len: c_int) -> c_int; pub fn BIO_s_mem() -> *const BIO_METHOD; pub fn BIO_new_mem_buf(buf: *const c_void, len: c_int) -> *mut BIO; + pub fn BIO_set_flags(b: *mut BIO, flags: c_int); + pub fn BIO_clear_flags(b: *mut BIO, flags: c_int); pub fn BN_new() -> *mut BIGNUM; pub fn BN_dup(n: *mut BIGNUM) -> *mut BIGNUM; diff --git a/openssl/src/ssl/bio.rs b/openssl/src/ssl/bio.rs index 3ced1c95..c5663eb1 100644 --- a/openssl/src/ssl/bio.rs +++ b/openssl/src/ssl/bio.rs @@ -1,6 +1,6 @@ use libc::{c_char, c_int, c_long, c_void, strlen}; -use ffi::{self, BIO, BIO_CTRL_FLUSH, BIO_TYPE_NONE, BIO_new}; -use ffi_extras::{BIO_clear_retry_flags, BIO_set_retry_read, BIO_set_retry_write}; +use ffi::{self, BIO, BIO_CTRL_FLUSH, BIO_TYPE_NONE, BIO_new, BIO_clear_retry_flags, + BIO_set_retry_read, BIO_set_retry_write}; use std::any::Any; use std::io; use std::io::prelude::*; From c2a7c5b7f00b88c4aa6bc723afdca2bd785017d1 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 4 Aug 2016 22:28:33 -0700 Subject: [PATCH 44/96] Move SSL_set_tlsext_host_name to -sys --- openssl-sys/src/lib.rs | 4 ++++ openssl/src/ssl/mod.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 5bfe3d4a..b99214cf 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -531,6 +531,10 @@ pub unsafe fn SSL_CTX_get_options(ctx: *mut SSL_CTX) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, 0, ptr::null_mut()) } +pub unsafe fn SSL_set_tlsext_host_name(s: *mut SSL, name: *mut c_char) -> c_long { + SSL_ctrl(s, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, name as *mut c_void) +} + // True functions extern "C" { pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 84d3613c..f40e1bcb 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -893,7 +893,7 @@ impl Ssl { pub fn set_hostname(&self, hostname: &str) -> Result<(), ErrorStack> { let cstr = CString::new(hostname).unwrap(); let ret = unsafe { - ffi_extras::SSL_set_tlsext_host_name(self.ssl, cstr.as_ptr() as *const _) + ffi::SSL_set_tlsext_host_name(self.ssl, cstr.as_ptr() as *mut _) }; // For this case, 0 indicates failure. From 77dbab2cadd825aa5932c301d8d51a3e87dda22e Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 4 Aug 2016 22:37:39 -0700 Subject: [PATCH 45/96] Move SSL_CTX_set_tlsext_servername_callback to -sys --- openssl-sys/src/lib.rs | 7 +++++++ openssl/src/ssl/mod.rs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index b99214cf..9ba306c0 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -531,6 +531,12 @@ pub unsafe fn SSL_CTX_get_options(ctx: *mut SSL_CTX) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, 0, ptr::null_mut()) } +pub unsafe fn SSL_CTX_set_tlsext_servername_callback(ctx: *mut SSL_CTX, + cb: Option) + -> c_long { + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, cb) +} + pub unsafe fn SSL_set_tlsext_host_name(s: *mut SSL, name: *mut c_char) -> c_long { SSL_ctrl(s, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, name as *mut c_void) } @@ -866,6 +872,7 @@ extern "C" { pub fn SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX; pub fn SSL_CTX_free(ctx: *mut SSL_CTX); pub fn SSL_CTX_ctrl(ctx: *mut SSL_CTX, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long; + pub fn SSL_CTX_callback_ctrl(ctx: *mut SSL_CTX, cmd: c_int, fp: Option) -> c_long; pub fn SSL_CTX_set_verify(ctx: *mut SSL_CTX, mode: c_int, verify_callback: Option c_int>); pub fn SSL_CTX_set_verify_depth(ctx: *mut SSL_CTX, depth: c_int); diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index f40e1bcb..737cbd27 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -494,7 +494,7 @@ impl SslContext { ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::(), mem::transmute(callback)); let f: extern "C" fn(_, _, _) -> _ = raw_sni::; let f: extern "C" fn() = mem::transmute(f); - ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); + ffi::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); } } From 7fb7f4671d57cf242f94f6ad4f3ccb1d90d1e034 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 4 Aug 2016 22:40:01 -0700 Subject: [PATCH 46/96] Move SSL_CTX_set_read_ahead to -sys --- openssl-sys/src/lib.rs | 4 ++++ openssl/src/ssl/mod.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 9ba306c0..40d51498 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -531,6 +531,10 @@ pub unsafe fn SSL_CTX_get_options(ctx: *mut SSL_CTX) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, 0, ptr::null_mut()) } +pub unsafe fn SSL_CTX_set_read_ahead(ctx: *mut SSL_CTX, m: c_long) -> c_long { + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_READ_AHEAD, m, ptr::null_mut()) +} + pub unsafe fn SSL_CTX_set_tlsext_servername_callback(ctx: *mut SSL_CTX, cb: Option) -> c_long { diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 737cbd27..385fab85 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -507,7 +507,7 @@ impl SslContext { pub fn set_read_ahead(&mut self, m: u32) { unsafe { - ffi_extras::SSL_CTX_set_read_ahead(self.ctx, m as c_long); + ffi::SSL_CTX_set_read_ahead(self.ctx, m as c_long); } } From 378b86326cccceb1c21658a1a70ea442acc91495 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 4 Aug 2016 22:43:24 -0700 Subject: [PATCH 47/96] Move SSL_CTX_set_tmp_dh to -sys --- openssl-sys/src/lib.rs | 5 +++++ openssl/src/ssl/mod.rs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 40d51498..95c0fe92 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -293,6 +293,7 @@ pub const NID_key_usage: c_int = 83; pub const PKCS5_SALT_LEN: c_int = 8; +pub const SSL_CTRL_SET_TMP_DH: c_int = 3; pub const SSL_CTRL_OPTIONS: c_int = 32; pub const SSL_CTRL_MODE: c_int = 33; pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77; @@ -535,6 +536,10 @@ pub unsafe fn SSL_CTX_set_read_ahead(ctx: *mut SSL_CTX, m: c_long) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_SET_READ_AHEAD, m, ptr::null_mut()) } +pub unsafe fn SSL_CTX_set_tmp_dh(ctx: *mut SSL_CTX, dh: *mut DH) -> c_long { + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_DH, 0, dh as *mut c_void) +} + pub unsafe fn SSL_CTX_set_tlsext_servername_callback(ctx: *mut SSL_CTX, cb: Option) -> c_long { diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 385fab85..21764bfb 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -516,7 +516,7 @@ impl SslContext { } pub fn set_tmp_dh(&mut self, dh: DH) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 }) } /// Use the default locations of trusted certificates for verification. From ee67ea8ea08c95697b286487f4585ff03e5fd382 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 4 Aug 2016 22:46:47 -0700 Subject: [PATCH 48/96] Mvoe SSL_CTX_add_extra_chain_cert to -sys --- openssl-sys/src/lib.rs | 4 ++++ openssl/src/ssl/mod.rs | 5 ++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 95c0fe92..f13a3dd5 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -540,6 +540,10 @@ pub unsafe fn SSL_CTX_set_tmp_dh(ctx: *mut SSL_CTX, dh: *mut DH) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_DH, 0, dh as *mut c_void) } +pub unsafe fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) -> c_long { + SSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, x509 as *mut c_void) +} + pub unsafe fn SSL_CTX_set_tlsext_servername_callback(ctx: *mut SSL_CTX, cb: Option) -> c_long { diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 21764bfb..48e9f1c8 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -20,7 +20,6 @@ use std::slice; use std::marker::PhantomData; use ffi; -use ffi_extras; use dh::DH; use x509::{X509StoreContext, X509FileType, X509}; use crypto::pkey::PKey; @@ -586,7 +585,7 @@ impl SslContext { /// certificate specified using set_certificate() pub fn add_extra_chain_cert(&mut self, cert: &X509) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { - ffi_extras::SSL_CTX_add_extra_chain_cert(self.ctx, cert.get_handle()) as c_int + ffi::SSL_CTX_add_extra_chain_cert(self.ctx, cert.get_handle()) as c_int }) } @@ -626,7 +625,7 @@ impl SslContext { /// This method requires OpenSSL >= 1.0.2 or LibreSSL and the `ecdh_auto` feature. #[cfg(feature = "ecdh_auto")] pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_ecdh_auto(self.ctx, onoff as c_int) }) + wrap_ssl_result(unsafe { ::ffi_extras::SSL_CTX_set_ecdh_auto(self.ctx, onoff as c_int) }) } pub fn set_options(&mut self, option: SslContextOptions) -> SslContextOptions { From c47be8b14b43afff4b99c771688accb3e47982ff Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 4 Aug 2016 22:52:40 -0700 Subject: [PATCH 49/96] Move SSL_CTX_set_ecdh_auto to -sys --- openssl-sys/Cargo.toml | 1 + openssl-sys/src/lib.rs | 14 ++++++++++---- openssl/Cargo.toml | 2 +- openssl/src/ssl/mod.rs | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index c203b6d6..45424bbf 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -23,6 +23,7 @@ npn = [] alpn = [] rfc5114 = [] pkcs5_pbkdf2_hmac = [] +ecdh_auto = [] [dependencies] libc = "0.2" diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index f13a3dd5..250bb054 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -294,15 +294,16 @@ pub const NID_key_usage: c_int = 83; pub const PKCS5_SALT_LEN: c_int = 8; pub const SSL_CTRL_SET_TMP_DH: c_int = 3; +pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; pub const SSL_CTRL_OPTIONS: c_int = 32; pub const SSL_CTRL_MODE: c_int = 33; -pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77; - +pub const SSL_CTRL_SET_READ_AHEAD: c_int = 41; pub const SSL_CTRL_SET_TLSEXT_SERVERNAME_CB: c_int = 53; pub const SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG: c_int = 54; pub const SSL_CTRL_SET_TLSEXT_HOSTNAME: c_int = 55; -pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; -pub const SSL_CTRL_SET_READ_AHEAD: c_int = 41; +pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77; +#[cfg(feature = "ecdh_auto")] +pub const SSL_CTRL_SET_ECDH_AUTO: c_int = 94; pub const SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER: c_long = 2; pub const SSL_MODE_AUTO_RETRY: c_long = 4; @@ -544,6 +545,11 @@ pub unsafe fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) - SSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, x509 as *mut c_void) } +#[cfg(feature = "ecdh_auto")] +pub unsafe fn SSL_CTX_set_ecdh_auto(ctx: *mut SSL_CTX, onoff: c_long) -> c_long { + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, ptr::null_mut()) +} + pub unsafe fn SSL_CTX_set_tlsext_servername_callback(ctx: *mut SSL_CTX, cb: Option) -> c_long { diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 3d4b098c..4f7243b9 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -23,7 +23,7 @@ aes_ctr = ["openssl-sys/aes_ctr"] npn = ["openssl-sys/npn"] alpn = ["openssl-sys/alpn"] rfc5114 = ["openssl-sys/rfc5114"] -ecdh_auto = ["openssl-sys-extras/ecdh_auto"] +ecdh_auto = ["openssl-sys/ecdh_auto"] pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"] [dependencies] diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 48e9f1c8..8cfc209a 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -625,7 +625,7 @@ impl SslContext { /// This method requires OpenSSL >= 1.0.2 or LibreSSL and the `ecdh_auto` feature. #[cfg(feature = "ecdh_auto")] pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ::ffi_extras::SSL_CTX_set_ecdh_auto(self.ctx, onoff as c_int) }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_set_ecdh_auto(self.ctx, onoff as c_long) as c_int }) } pub fn set_options(&mut self, option: SslContextOptions) -> SslContextOptions { From 4e911e79725cc45ae70a2c2750863218812405b5 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 5 Aug 2016 19:51:59 -0700 Subject: [PATCH 50/96] Make x509 constructors unsafe --- openssl/src/x509/mod.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 64a61df0..4887172b 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -407,7 +407,7 @@ pub struct X509<'ctx> { impl<'ctx> X509<'ctx> { /// Creates new from handle with desired ownership. - pub fn new(handle: *mut ffi::X509, owned: bool) -> X509<'ctx> { + pub unsafe fn new(handle: *mut ffi::X509, owned: bool) -> X509<'ctx> { X509 { ctx: None, handle: handle, @@ -417,7 +417,7 @@ impl<'ctx> X509<'ctx> { /// Creates a new certificate from context. Doesn't take ownership /// of handle. - pub fn new_in_ctx(handle: *mut ffi::X509, ctx: &'ctx X509StoreContext) -> X509<'ctx> { + pub unsafe fn new_in_ctx(handle: *mut ffi::X509, ctx: &'ctx X509StoreContext) -> X509<'ctx> { X509 { ctx: Some(ctx), handle: handle, @@ -525,11 +525,13 @@ extern "C" { impl<'ctx> Clone for X509<'ctx> { fn clone(&self) -> X509<'ctx> { - unsafe { rust_X509_clone(self.handle) } - // FIXME: given that we now have refcounting control, 'owned' should be uneeded, the 'ctx - // is probably also uneeded. We can remove both to condense the x509 api quite a bit - // - X509::new(self.handle, true) + unsafe { + rust_X509_clone(self.handle); + // FIXME: given that we now have refcounting control, 'owned' should be uneeded, the 'ctx + // is probably also uneeded. We can remove both to condense the x509 api quite a bit + // + X509::new(self.handle, true) + } } } From b4145c6fa51ad59b0df2e0f48f67b8a0e56e1863 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 5 Aug 2016 20:55:05 -0700 Subject: [PATCH 51/96] Clean up x509 --- openssl/src/ssl/mod.rs | 12 +-- openssl/src/ssl/tests/mod.rs | 6 +- openssl/src/x509/mod.rs | 186 +++++++++++++++-------------------- 3 files changed, 88 insertions(+), 116 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 8cfc209a..c95f2646 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -21,7 +21,7 @@ use std::marker::PhantomData; use ffi; use dh::DH; -use x509::{X509StoreContext, X509FileType, X509}; +use x509::{X509StoreContext, X509FileType, X509, X509Ref}; use crypto::pkey::PKey; use error::ErrorStack; @@ -577,15 +577,15 @@ impl SslContext { } /// Specifies the certificate - pub fn set_certificate(&mut self, cert: &X509) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate(self.ctx, cert.get_handle()) }) + pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { + wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate(self.ctx, cert.handle()) }) } /// Adds a certificate to the certificate chain presented together with the /// certificate specified using set_certificate() - pub fn add_extra_chain_cert(&mut self, cert: &X509) -> Result<(), ErrorStack> { + pub fn add_extra_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { - ffi::SSL_CTX_add_extra_chain_cert(self.ctx, cert.get_handle()) as c_int + ffi::SSL_CTX_add_extra_chain_cert(self.ctx, cert.handle()) as c_int }) } @@ -910,7 +910,7 @@ impl Ssl { if ptr.is_null() { None } else { - Some(X509::new(ptr, true)) + Some(X509::new(ptr)) } } } diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index b774b383..b89517da 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -300,7 +300,7 @@ run_test!(verify_trusted_callback_override_bad, |method, stream| { run_test!(verify_callback_load_certs, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { - assert!(x509_ctx.get_current_cert().is_some()); + assert!(x509_ctx.current_cert().is_some()); true }); @@ -341,7 +341,7 @@ run_test!(verify_callback_data, |method, stream| { let node_hash_str = "E19427DAC79FBE758394945276A6E4F15F0BEBE6"; let node_id = node_hash_str.from_hex().unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, move |_preverify_ok, x509_ctx| { - let cert = x509_ctx.get_current_cert(); + let cert = x509_ctx.current_cert(); match cert { None => false, Some(cert) => { @@ -371,7 +371,7 @@ run_test!(ssl_verify_callback, |method, stream| { let node_id = node_hash_str.from_hex().unwrap(); ssl.set_verify_callback(SSL_VERIFY_PEER, move |_, x509| { CHECKED.store(1, Ordering::SeqCst); - match x509.get_current_cert() { + match x509.current_cert() { None => false, Some(cert) => { let fingerprint = cert.fingerprint(SHA1).unwrap(); diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 4887172b..5bb17e35 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -89,17 +89,15 @@ impl X509StoreContext { X509ValidationError::from_raw(err) } - pub fn get_current_cert<'a>(&'a self) -> Option> { - let ptr = unsafe { ffi::X509_STORE_CTX_get_current_cert(self.ctx) }; + pub fn current_cert<'a>(&'a self) -> Option> { + unsafe { + let ptr = ffi::X509_STORE_CTX_get_current_cert(self.ctx); - if ptr.is_null() { - None - } else { - Some(X509 { - ctx: Some(self), - handle: ptr, - owned: false, - }) + if ptr.is_null() { + None + } else { + Some(X509Ref::new(ptr)) + } } } @@ -301,7 +299,7 @@ impl X509Generator { } /// Generates a private key and a self-signed certificate and returns them - pub fn generate<'a>(&self) -> Result<(X509<'a>, PKey), ErrorStack> { + pub fn generate(&self) -> Result<(X509, PKey), ErrorStack> { ffi::init(); let mut p_key = PKey::new(); @@ -313,37 +311,31 @@ impl X509Generator { /// Sets the certificate public-key, then self-sign and return it /// Note: That the bit-length of the private key is used (set_bitlength is ignored) - pub fn sign<'a>(&self, p_key: &PKey) -> Result, ErrorStack> { + pub fn sign(&self, p_key: &PKey) -> Result { ffi::init(); unsafe { - let x509 = ffi::X509_new(); - try_ssl_null!(x509); + let x509 = try_ssl_null!(ffi::X509_new()); + let x509 = X509::new(x509); - let x509 = X509 { - handle: x509, - ctx: None, - owned: true, - }; - - try_ssl!(ffi::X509_set_version(x509.handle, 2)); - try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.handle), + try_ssl!(ffi::X509_set_version(x509.handle(), 2)); + try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.handle()), X509Generator::random_serial())); let not_before = try!(Asn1Time::days_from_now(0)); let not_after = try!(Asn1Time::days_from_now(self.days)); - try_ssl!(ffi::X509_set_notBefore(x509.handle, mem::transmute(not_before.get_handle()))); + try_ssl!(ffi::X509_set_notBefore(x509.handle(), mem::transmute(not_before.get_handle()))); // If prev line succeded - ownership should go to cert mem::forget(not_before); - try_ssl!(ffi::X509_set_notAfter(x509.handle, mem::transmute(not_after.get_handle()))); + try_ssl!(ffi::X509_set_notAfter(x509.handle(), mem::transmute(not_after.get_handle()))); // If prev line succeded - ownership should go to cert mem::forget(not_after); - try_ssl!(ffi::X509_set_pubkey(x509.handle, p_key.get_handle())); + try_ssl!(ffi::X509_set_pubkey(x509.handle(), p_key.get_handle())); - let name = ffi::X509_get_subject_name(x509.handle); + let name = ffi::X509_get_subject_name(x509.handle()); try_ssl_null!(name); let default = [("CN", "rust-openssl")]; @@ -358,16 +350,16 @@ impl X509Generator { for (key, val) in iter { try!(X509Generator::add_name_internal(name, &key, &val)); } - ffi::X509_set_issuer_name(x509.handle, name); + ffi::X509_set_issuer_name(x509.handle(), name); for (exttype, ext) in self.extensions.iter() { - try!(X509Generator::add_extension_internal(x509.handle, + try!(X509Generator::add_extension_internal(x509.handle(), &exttype, &ext.to_string())); } let hash_fn = self.hash_type.evp_md(); - try_ssl!(ffi::X509_sign(x509.handle, p_key.get_handle(), hash_fn)); + try_ssl!(ffi::X509_sign(x509.handle(), p_key.get_handle(), hash_fn)); Ok(x509) } } @@ -380,10 +372,10 @@ impl X509Generator { }; unsafe { - let req = ffi::X509_to_X509_REQ(cert.handle, ptr::null_mut(), ptr::null()); + let req = ffi::X509_to_X509_REQ(cert.handle(), ptr::null_mut(), ptr::null()); try_ssl_null!(req); - let exts = ffi_extras::X509_get_extensions(cert.handle); + let exts = ffi_extras::X509_get_extensions(cert.handle()); if exts != ptr::null_mut() { try_ssl!(ffi::X509_REQ_add_extensions(req, exts)); } @@ -396,63 +388,28 @@ impl X509Generator { } } +/// A borrowed public key certificate. +pub struct X509Ref<'a>(*mut ffi::X509, PhantomData<&'a ()>); -#[allow(dead_code)] -/// A public key certificate -pub struct X509<'ctx> { - ctx: Option<&'ctx X509StoreContext>, - handle: *mut ffi::X509, - owned: bool, -} - -impl<'ctx> X509<'ctx> { - /// Creates new from handle with desired ownership. - pub unsafe fn new(handle: *mut ffi::X509, owned: bool) -> X509<'ctx> { - X509 { - ctx: None, - handle: handle, - owned: owned, - } +impl<'a> X509Ref<'a> { + /// Creates a new `X509` wrapping the provided handle. + pub unsafe fn new(handle: *mut ffi::X509) -> X509Ref<'a> { + X509Ref(handle, PhantomData) } - /// Creates a new certificate from context. Doesn't take ownership - /// of handle. - pub unsafe fn new_in_ctx(handle: *mut ffi::X509, ctx: &'ctx X509StoreContext) -> X509<'ctx> { - X509 { - ctx: Some(ctx), - handle: handle, - owned: false, - } + pub fn handle(&self) -> *mut ffi::X509 { + self.0 } - /// Reads certificate from PEM, takes ownership of handle - pub fn from_pem(buf: &[u8]) -> Result, ErrorStack> { - let mem_bio = try!(MemBioSlice::new(buf)); - unsafe { - let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(), - ptr::null_mut(), - None, - ptr::null_mut())); - Ok(X509::new(handle, true)) - } - } - - pub fn get_handle(&self) -> *mut ffi::X509 { - self.handle - } - - pub fn subject_name<'a>(&'a self) -> X509Name<'a> { - let name = unsafe { ffi::X509_get_subject_name(self.handle) }; - X509Name { - x509: self, - name: name, - } + pub fn subject_name<'b>(&'b self) -> X509Name<'b> { + let name = unsafe { ffi::X509_get_subject_name(self.0) }; + X509Name(name, PhantomData) } /// Returns this certificate's SAN entries, if they exist. - pub fn subject_alt_names<'a>(&'a self) -> Option> { + pub fn subject_alt_names<'b>(&'b self) -> Option> { unsafe { - let stack = ffi::X509_get_ext_d2i(self.handle, + let stack = ffi::X509_get_ext_d2i(self.0, Nid::SubjectAltName as c_int, ptr::null_mut(), ptr::null_mut()); @@ -468,7 +425,7 @@ impl<'ctx> X509<'ctx> { } pub fn public_key(&self) -> PKey { - let pkey = unsafe { ffi::X509_get_pubkey(self.handle) }; + let pkey = unsafe { ffi::X509_get_pubkey(self.0) }; assert!(!pkey.is_null()); PKey::from_handle(pkey, Parts::Public) @@ -481,7 +438,7 @@ impl<'ctx> X509<'ctx> { let v: Vec = repeat(0).take(len as usize).collect(); let act_len: c_uint = 0; let res = unsafe { - ffi::X509_digest(self.handle, + ffi::X509_digest(self.0, evp, mem::transmute(v.as_ptr()), mem::transmute(&act_len)) @@ -504,7 +461,7 @@ impl<'ctx> X509<'ctx> { pub fn write_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), self.handle)); + try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), self.0)); } Ok(mem_bio.get_buf().to_owned()) } @@ -513,57 +470,72 @@ impl<'ctx> X509<'ctx> { pub fn save_der(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - ffi::i2d_X509_bio(mem_bio.get_handle(), self.handle); + ffi::i2d_X509_bio(mem_bio.get_handle(), self.0); } Ok(mem_bio.get_buf().to_owned()) } } +/// An owned public key certificate. +pub struct X509(X509Ref<'static>); + +impl X509 { + /// Returns a new `X509`, taking ownership of the handle. + pub unsafe fn new(x509: *mut ffi::X509) -> X509 { + X509(X509Ref::new(x509)) + } + + /// Reads a certificate from PEM. + pub fn from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); + unsafe { + let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(), + ptr::null_mut(), + None, + ptr::null_mut())); + Ok(X509::new(handle)) + } + } +} + +impl Deref for X509 { + type Target = X509Ref<'static>; + + fn deref(&self) -> &X509Ref<'static> { + &self.0 + } +} + extern "C" { fn rust_X509_clone(x509: *mut ffi::X509); } -impl<'ctx> Clone for X509<'ctx> { - fn clone(&self) -> X509<'ctx> { +impl Clone for X509 { + fn clone(&self) -> X509 { unsafe { - rust_X509_clone(self.handle); - // FIXME: given that we now have refcounting control, 'owned' should be uneeded, the 'ctx - // is probably also uneeded. We can remove both to condense the x509 api quite a bit - // - X509::new(self.handle, true) + rust_X509_clone(self.handle()); + X509::new(self.handle()) } } } -impl<'ctx> Drop for X509<'ctx> { +impl Drop for X509 { fn drop(&mut self) { - if self.owned { - unsafe { ffi::X509_free(self.handle) }; - } + unsafe { ffi::X509_free(self.handle()) }; } } -#[allow(dead_code)] -pub struct X509Name<'x> { - x509: &'x X509<'x>, - name: *mut ffi::X509_NAME, -} - -#[allow(dead_code)] -pub struct X509NameEntry<'x> { - x509_name: &'x X509Name<'x>, - ne: *mut ffi::X509_NAME_ENTRY, -} +pub struct X509Name<'x>(*mut ffi::X509_NAME, PhantomData<&'x ()>); impl<'x> X509Name<'x> { pub fn text_by_nid(&self, nid: Nid) -> Option { unsafe { - let loc = ffi::X509_NAME_get_index_by_NID(self.name, nid as c_int, -1); + let loc = ffi::X509_NAME_get_index_by_NID(self.0, nid as c_int, -1); if loc == -1 { return None; } - let ne = ffi::X509_NAME_get_entry(self.name, loc); + let ne = ffi::X509_NAME_get_entry(self.0, loc); if ne.is_null() { return None; } From fe47e93f2f5b6c2b2243b15445bbfdd4e58780b1 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 5 Aug 2016 21:04:40 -0700 Subject: [PATCH 52/96] Fix pkey method safety --- openssl/src/crypto/pkey.rs | 7 ++++--- openssl/src/ssl/mod.rs | 2 +- openssl/src/x509/mod.rs | 14 ++++++++------ 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index ab9a4a95..9f72464b 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -63,7 +63,7 @@ impl PKey { } } - pub fn from_handle(handle: *mut ffi::EVP_PKEY, parts: Parts) -> PKey { + pub unsafe fn from_handle(handle: *mut ffi::EVP_PKEY, parts: Parts) -> PKey { ffi::init(); assert!(!handle.is_null()); @@ -587,7 +587,7 @@ impl PKey { } } - pub unsafe fn get_handle(&self) -> *mut ffi::EVP_PKEY { + pub fn handle(&self) -> *mut ffi::EVP_PKEY { return self.evp; } @@ -606,7 +606,8 @@ impl Drop for PKey { impl Clone for PKey { fn clone(&self) -> Self { - let mut pkey = PKey::from_handle(unsafe { ffi::EVP_PKEY_new() }, self.parts); + let mut pkey = unsafe { PKey::from_handle(ffi::EVP_PKEY_new(), self.parts) }; + // copy by encoding to DER and back match self.parts { Parts::Public => { diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index c95f2646..7ef8a7a5 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -604,7 +604,7 @@ impl SslContext { /// Specifies the private key pub fn set_private_key(&mut self, key: &PKey) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey(self.ctx, key.get_handle()) }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey(self.ctx, key.handle()) }) } /// Check consistency of private key and certificate diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 5bb17e35..f81c74a1 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -333,7 +333,7 @@ impl X509Generator { // If prev line succeded - ownership should go to cert mem::forget(not_after); - try_ssl!(ffi::X509_set_pubkey(x509.handle(), p_key.get_handle())); + try_ssl!(ffi::X509_set_pubkey(x509.handle(), p_key.handle())); let name = ffi::X509_get_subject_name(x509.handle()); try_ssl_null!(name); @@ -359,7 +359,7 @@ impl X509Generator { } let hash_fn = self.hash_type.evp_md(); - try_ssl!(ffi::X509_sign(x509.handle(), p_key.get_handle(), hash_fn)); + try_ssl!(ffi::X509_sign(x509.handle(), p_key.handle(), hash_fn)); Ok(x509) } } @@ -381,7 +381,7 @@ impl X509Generator { } let hash_fn = self.hash_type.evp_md(); - try_ssl!(ffi::X509_REQ_sign(req, p_key.get_handle(), hash_fn)); + try_ssl!(ffi::X509_REQ_sign(req, p_key.handle(), hash_fn)); Ok(X509Req::new(req)) } @@ -425,10 +425,12 @@ impl<'a> X509Ref<'a> { } pub fn public_key(&self) -> PKey { - let pkey = unsafe { ffi::X509_get_pubkey(self.0) }; - assert!(!pkey.is_null()); + unsafe { + let pkey = ffi::X509_get_pubkey(self.0); + assert!(!pkey.is_null()); - PKey::from_handle(pkey, Parts::Public) + PKey::from_handle(pkey, Parts::Public) + } } /// Returns certificate fingerprint calculated using provided hash From bc97d088b0e71a1bde0a88bc548718c427124d0c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 5 Aug 2016 21:07:17 -0700 Subject: [PATCH 53/96] get_handle -> handle --- openssl/src/asn1/mod.rs | 2 +- openssl/src/bio.rs | 4 ++-- openssl/src/crypto/dsa.rs | 10 +++++----- openssl/src/crypto/pkey.rs | 10 +++++----- openssl/src/crypto/rsa.rs | 10 +++++----- openssl/src/dh/mod.rs | 2 +- openssl/src/x509/mod.rs | 18 +++++++++--------- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/openssl/src/asn1/mod.rs b/openssl/src/asn1/mod.rs index 202909ec..39273cb8 100644 --- a/openssl/src/asn1/mod.rs +++ b/openssl/src/asn1/mod.rs @@ -33,7 +33,7 @@ impl Asn1Time { } /// Returns raw handle - pub unsafe fn get_handle(&self) -> *mut ffi::ASN1_TIME { + pub unsafe fn handle(&self) -> *mut ffi::ASN1_TIME { return self.handle; } } diff --git a/openssl/src/bio.rs b/openssl/src/bio.rs index 841aca0e..7adcc4e6 100644 --- a/openssl/src/bio.rs +++ b/openssl/src/bio.rs @@ -28,7 +28,7 @@ impl<'a> MemBioSlice<'a> { Ok(MemBioSlice(bio, PhantomData)) } - pub fn get_handle(&self) -> *mut ffi::BIO { + pub fn handle(&self) -> *mut ffi::BIO { self.0 } } @@ -53,7 +53,7 @@ impl MemBio { Ok(MemBio(bio)) } - pub fn get_handle(&self) -> *mut ffi::BIO { + pub fn handle(&self) -> *mut ffi::BIO { self.0 } diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index de35893b..40702627 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -73,7 +73,7 @@ impl DSA { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.get_handle(), + let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut())); @@ -97,7 +97,7 @@ impl DSA { unsafe { let cb_ptr = &mut cb as *mut _ as *mut c_void; - let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.get_handle(), + let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.handle(), ptr::null_mut(), Some(invoke_passwd_cb::), cb_ptr)); @@ -114,7 +114,7 @@ impl DSA { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.get_handle(), self.0, + try_ssl!(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.handle(), self.0, ptr::null(), ptr::null_mut(), 0, None, ptr::null_mut())) }; @@ -129,7 +129,7 @@ impl DSA { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let dsa = try_ssl_null!(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.get_handle(), + let dsa = try_ssl_null!(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut())); @@ -140,7 +140,7 @@ impl DSA { /// Writes an DSA public key as PEM formatted data pub fn public_key_to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); - unsafe { try_ssl!(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.get_handle(), self.0)) }; + unsafe { try_ssl!(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.handle(), self.0)) }; Ok(mem_bio.get_buf().to_owned()) } diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 9f72464b..e554f3b2 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -77,7 +77,7 @@ impl PKey { pub fn private_key_from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), + let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut())); @@ -100,7 +100,7 @@ impl PKey { let mut cb = CallbackState::new(pass_cb); let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), + let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.handle(), ptr::null_mut(), Some(invoke_passwd_cb::), &mut cb as *mut _ as *mut c_void)); @@ -116,7 +116,7 @@ impl PKey { pub fn public_key_from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.get_handle(), + let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut())); @@ -266,7 +266,7 @@ impl PKey { pub fn write_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.get_handle(), + try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.handle(), self.evp, ptr::null(), ptr::null_mut(), @@ -281,7 +281,7 @@ impl PKey { /// Stores public key as a PEM pub fn write_pub_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); - unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.get_handle(), self.evp)) } + unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.handle(), self.evp)) } Ok(mem_bio.get_buf().to_owned()) } diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 226b2aab..5c70c8ea 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -64,7 +64,7 @@ impl RSA { pub fn private_key_from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.get_handle(), + let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut())); @@ -81,7 +81,7 @@ impl RSA { unsafe { let cb_ptr = &mut cb as *mut _ as *mut c_void; - let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.get_handle(), + let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.handle(), ptr::null_mut(), Some(invoke_passwd_cb::), cb_ptr)); @@ -95,7 +95,7 @@ impl RSA { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.get_handle(), + try_ssl!(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.handle(), self.0, ptr::null(), ptr::null_mut(), @@ -110,7 +110,7 @@ impl RSA { pub fn public_key_from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.get_handle(), + let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut())); @@ -123,7 +123,7 @@ impl RSA { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.get_handle(), self.0)) + try_ssl!(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.handle(), self.0)) }; Ok(mem_bio.get_buf().to_owned()) diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index df6f1b0a..6a5bd9c4 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -19,7 +19,7 @@ impl DH { pub fn from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); let dh = unsafe { - ffi::PEM_read_bio_DHparams(mem_bio.get_handle(), ptr::null_mut(), None, ptr::null_mut()) + ffi::PEM_read_bio_DHparams(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut()) }; try_ssl_null!(dh); Ok(DH(dh)) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index f81c74a1..82448212 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -325,11 +325,11 @@ impl X509Generator { let not_before = try!(Asn1Time::days_from_now(0)); let not_after = try!(Asn1Time::days_from_now(self.days)); - try_ssl!(ffi::X509_set_notBefore(x509.handle(), mem::transmute(not_before.get_handle()))); + try_ssl!(ffi::X509_set_notBefore(x509.handle(), mem::transmute(not_before.handle()))); // If prev line succeded - ownership should go to cert mem::forget(not_before); - try_ssl!(ffi::X509_set_notAfter(x509.handle(), mem::transmute(not_after.get_handle()))); + try_ssl!(ffi::X509_set_notAfter(x509.handle(), mem::transmute(not_after.handle()))); // If prev line succeded - ownership should go to cert mem::forget(not_after); @@ -463,7 +463,7 @@ impl<'a> X509Ref<'a> { pub fn write_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), self.0)); + try_ssl!(ffi::PEM_write_bio_X509(mem_bio.handle(), self.0)); } Ok(mem_bio.get_buf().to_owned()) } @@ -472,7 +472,7 @@ impl<'a> X509Ref<'a> { pub fn save_der(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - ffi::i2d_X509_bio(mem_bio.get_handle(), self.0); + ffi::i2d_X509_bio(mem_bio.handle(), self.0); } Ok(mem_bio.get_buf().to_owned()) } @@ -491,7 +491,7 @@ impl X509 { pub fn from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(), + let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut())); @@ -572,7 +572,7 @@ impl X509Req { X509Req { handle: handle } } - pub fn get_handle(&self) -> *mut ffi::X509_REQ { + pub fn handle(&self) -> *mut ffi::X509_REQ { self.handle } @@ -580,7 +580,7 @@ impl X509Req { pub fn from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.get_handle(), + let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut())); @@ -591,7 +591,7 @@ impl X509Req { /// Writes CSR as PEM pub fn write_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); - if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), self.handle) } != 1 { + if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.handle(), self.handle) } != 1 { return Err(ErrorStack::get()); } Ok(mem_bio.get_buf().to_owned()) @@ -601,7 +601,7 @@ impl X509Req { pub fn save_der(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - ffi::i2d_X509_REQ_bio(mem_bio.get_handle(), self.handle); + ffi::i2d_X509_REQ_bio(mem_bio.handle(), self.handle); } Ok(mem_bio.get_buf().to_owned()) } From 5af01a5dbd42a20cd8114f03168b014ae4d9d023 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 6 Aug 2016 22:23:03 -0700 Subject: [PATCH 54/96] Clean up asn1time --- openssl/src/asn1/mod.rs | 34 ++++++++------------ openssl/src/ssl/mod.rs | 70 ++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 54 deletions(-) diff --git a/openssl/src/asn1/mod.rs b/openssl/src/asn1/mod.rs index 39273cb8..e79a0fd2 100644 --- a/openssl/src/asn1/mod.rs +++ b/openssl/src/asn1/mod.rs @@ -4,44 +4,36 @@ use std::ptr; use ffi; use error::ErrorStack; -pub struct Asn1Time { - handle: *mut ffi::ASN1_TIME, - owned: bool, -} +pub struct Asn1Time(*mut ffi::ASN1_TIME); impl Asn1Time { /// Wraps existing ASN1_TIME and takes ownership - pub fn new(handle: *mut ffi::ASN1_TIME) -> Asn1Time { - Asn1Time { - handle: handle, - owned: true, - } + pub unsafe fn from_raw(handle: *mut ffi::ASN1_TIME) -> Asn1Time { + Asn1Time(handle) } - fn new_with_period(period: u64) -> Result { + fn from_period(period: u64) -> Result { ffi::init(); - let handle = unsafe { - try_ssl_null!(ffi::X509_gmtime_adj(ptr::null_mut(), period as c_long)) - }; - Ok(Asn1Time::new(handle)) + unsafe { + let handle = try_ssl_null!(ffi::X509_gmtime_adj(ptr::null_mut(), period as c_long)); + Ok(Asn1Time::from_raw(handle)) + } } /// Creates a new time on specified interval in days from now pub fn days_from_now(days: u32) -> Result { - Asn1Time::new_with_period(days as u64 * 60 * 60 * 24) + Asn1Time::from_period(days as u64 * 60 * 60 * 24) } - /// Returns raw handle - pub unsafe fn handle(&self) -> *mut ffi::ASN1_TIME { - return self.handle; + /// Returns the raw handle + pub fn handle(&self) -> *mut ffi::ASN1_TIME { + self.0 } } impl Drop for Asn1Time { fn drop(&mut self) { - if self.owned { - unsafe { ffi::ASN1_TIME_free(self.handle) }; - } + unsafe { ffi::ASN1_TIME_free(self.0) }; } } diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 7ef8a7a5..aa8d9657 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -108,42 +108,46 @@ pub enum SslMethod { } impl SslMethod { - unsafe fn to_raw(&self) -> *const ffi::SSL_METHOD { - match *self { - #[cfg(feature = "sslv2")] - SslMethod::Sslv2 => ffi::SSLv2_method(), - #[cfg(feature = "sslv3")] - SslMethod::Sslv3 => ffi::SSLv3_method(), - SslMethod::Tlsv1 => ffi::TLSv1_method(), - SslMethod::Sslv23 => ffi::SSLv23_method(), - #[cfg(feature = "tlsv1_1")] - SslMethod::Tlsv1_1 => ffi::TLSv1_1_method(), - #[cfg(feature = "tlsv1_2")] - SslMethod::Tlsv1_2 => ffi::TLSv1_2_method(), - #[cfg(feature = "dtlsv1")] - SslMethod::Dtlsv1 => ffi::DTLSv1_method(), - #[cfg(feature = "dtlsv1_2")] - SslMethod::Dtlsv1_2 => ffi::DTLSv1_2_method(), + fn to_raw(&self) -> *const ffi::SSL_METHOD { + unsafe { + match *self { + #[cfg(feature = "sslv2")] + SslMethod::Sslv2 => ffi::SSLv2_method(), + #[cfg(feature = "sslv3")] + SslMethod::Sslv3 => ffi::SSLv3_method(), + SslMethod::Tlsv1 => ffi::TLSv1_method(), + SslMethod::Sslv23 => ffi::SSLv23_method(), + #[cfg(feature = "tlsv1_1")] + SslMethod::Tlsv1_1 => ffi::TLSv1_1_method(), + #[cfg(feature = "tlsv1_2")] + SslMethod::Tlsv1_2 => ffi::TLSv1_2_method(), + #[cfg(feature = "dtlsv1")] + SslMethod::Dtlsv1 => ffi::DTLSv1_method(), + #[cfg(feature = "dtlsv1_2")] + SslMethod::Dtlsv1_2 => ffi::DTLSv1_2_method(), + } } } - unsafe fn from_raw(method: *const ffi::SSL_METHOD) -> Option { - match method { - #[cfg(feature = "sslv2")] - x if x == ffi::SSLv2_method() => Some(SslMethod::Sslv2), - #[cfg(feature = "sslv3")] - x if x == ffi::SSLv3_method() => Some(SslMethod::Sslv3), - x if x == ffi::TLSv1_method() => Some(SslMethod::Tlsv1), - x if x == ffi::SSLv23_method() => Some(SslMethod::Sslv23), - #[cfg(feature = "tlsv1_1")] - x if x == ffi::TLSv1_1_method() => Some(SslMethod::Tlsv1_1), - #[cfg(feature = "tlsv1_2")] - x if x == ffi::TLSv1_2_method() => Some(SslMethod::Tlsv1_2), - #[cfg(feature = "dtlsv1")] - x if x == ffi::DTLSv1_method() => Some(SslMethod::Dtlsv1), - #[cfg(feature = "dtlsv1_2")] - x if x == ffi::DTLSv1_2_method() => Some(SslMethod::Dtlsv1_2), - _ => None, + fn from_raw(method: *const ffi::SSL_METHOD) -> Option { + unsafe { + match method { + #[cfg(feature = "sslv2")] + x if x == ffi::SSLv2_method() => Some(SslMethod::Sslv2), + #[cfg(feature = "sslv3")] + x if x == ffi::SSLv3_method() => Some(SslMethod::Sslv3), + x if x == ffi::TLSv1_method() => Some(SslMethod::Tlsv1), + x if x == ffi::SSLv23_method() => Some(SslMethod::Sslv23), + #[cfg(feature = "tlsv1_1")] + x if x == ffi::TLSv1_1_method() => Some(SslMethod::Tlsv1_1), + #[cfg(feature = "tlsv1_2")] + x if x == ffi::TLSv1_2_method() => Some(SslMethod::Tlsv1_2), + #[cfg(feature = "dtlsv1")] + x if x == ffi::DTLSv1_method() => Some(SslMethod::Dtlsv1), + #[cfg(feature = "dtlsv1_2")] + x if x == ffi::DTLSv1_2_method() => Some(SslMethod::Dtlsv1_2), + _ => None, + } } } } From 05089bacb3cde8fe3ec9f68b5682668d4f63383c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 14:19:44 -0700 Subject: [PATCH 55/96] Refactor BigNum --- openssl/src/bn/mod.rs | 656 ++++++++++++++++++++++++------------- openssl/src/crypto/dsa.rs | 18 +- openssl/src/crypto/pkey.rs | 11 +- openssl/src/crypto/rsa.rs | 50 +-- 4 files changed, 467 insertions(+), 268 deletions(-) diff --git a/openssl/src/bn/mod.rs b/openssl/src/bn/mod.rs index d6febe51..3a1efb4a 100644 --- a/openssl/src/bn/mod.rs +++ b/openssl/src/bn/mod.rs @@ -2,17 +2,12 @@ use libc::{c_int, c_ulong, c_void}; use std::ffi::{CStr, CString}; use std::cmp::Ordering; use std::{fmt, ptr, mem}; +use std::marker::PhantomData; +use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Deref, DerefMut}; use ffi; use error::ErrorStack; -/// A signed arbitrary-precision integer. -/// -/// `BigNum` provides wrappers around OpenSSL's checked arithmetic functions. Additionally, it -/// implements the standard operators (`std::ops`), which perform unchecked arithmetic, unwrapping -/// the returned `Result` of the checked operations. -pub struct BigNum(*mut ffi::BIGNUM); - /// Specifies the desired properties of a randomly generated `BigNum`. #[derive(Copy, Clone)] #[repr(C)] @@ -79,68 +74,14 @@ macro_rules! with_bn_in_ctx( }); ); -impl BigNum { - /// Creates a new `BigNum` with the value 0. - pub fn new() -> Result { - unsafe { - ffi::init(); +/// A borrowed, signed, arbitrary-precision integer. +#[derive(Copy, Clone)] +pub struct BigNumRef<'a>(*mut ffi::BIGNUM, PhantomData<&'a ()>); - let v = try_ssl_null!(ffi::BN_new()); - Ok(BigNum(v)) - } - } - /// Creates a new `BigNum` with the given value. - pub fn new_from(n: u64) -> Result { - BigNum::new().and_then(|v| unsafe { - try_ssl!(ffi::BN_set_word(v.raw(), n as c_ulong)); - Ok(v) - }) - } - - /// Creates a `BigNum` from a decimal string. - pub fn from_dec_str(s: &str) -> Result { - BigNum::new().and_then(|v| unsafe { - let c_str = CString::new(s.as_bytes()).unwrap(); - try_ssl!(ffi::BN_dec2bn(v.raw_ptr(), c_str.as_ptr() as *const _)); - Ok(v) - }) - } - - /// Creates a `BigNum` from a hexadecimal string. - pub fn from_hex_str(s: &str) -> Result { - BigNum::new().and_then(|v| unsafe { - let c_str = CString::new(s.as_bytes()).unwrap(); - try_ssl!(ffi::BN_hex2bn(v.raw_ptr(), c_str.as_ptr() as *const _)); - Ok(v) - }) - } - - pub unsafe fn new_from_ffi(orig: *mut ffi::BIGNUM) -> Result { - if orig.is_null() { - panic!("Null Pointer was supplied to BigNum::new_from_ffi"); - } - let r = ffi::BN_dup(orig); - if r.is_null() { - Err(ErrorStack::get()) - } else { - Ok(BigNum(r)) - } - } - - /// Creates a new `BigNum` from an unsigned, big-endian encoded number of arbitrary length. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let bignum = BigNum::new_from_slice(&[0x12, 0x00, 0x34]).unwrap(); - /// - /// assert_eq!(bignum, BigNum::new_from(0x120034).unwrap()); - /// ``` - pub fn new_from_slice(n: &[u8]) -> Result { - BigNum::new().and_then(|v| unsafe { - try_ssl_null!(ffi::BN_bin2bn(n.as_ptr(), n.len() as c_int, v.raw())); - Ok(v) - }) +impl<'a> BigNumRef<'a> { + pub unsafe fn from_handle(handle: *mut ffi::BIGNUM) -> BigNumRef<'a> { + BigNumRef(handle, PhantomData) } /// Returns the square of `self`. @@ -162,7 +103,7 @@ impl BigNum { } /// Returns the unsigned remainder of the division `self / n`. - pub fn checked_nnmod(&self, n: &BigNum) -> Result { + pub fn checked_nnmod(&self, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_nnmod(r.raw(), self.raw(), n.raw(), ctx) == 1 @@ -181,7 +122,7 @@ impl BigNum { /// /// assert_eq!(s.checked_mod_add(a, n).unwrap(), result); /// ``` - pub fn checked_mod_add(&self, a: &BigNum, n: &BigNum) -> Result { + pub fn checked_mod_add(&self, a: &BigNumRef, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mod_add(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1 @@ -190,7 +131,7 @@ impl BigNum { } /// Equivalent to `(self - a) mod n`. - pub fn checked_mod_sub(&self, a: &BigNum, n: &BigNum) -> Result { + pub fn checked_mod_sub(&self, a: &BigNumRef, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mod_sub(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1 @@ -199,7 +140,7 @@ impl BigNum { } /// Equivalent to `(self * a) mod n`. - pub fn checked_mod_mul(&self, a: &BigNum, n: &BigNum) -> Result { + pub fn checked_mod_mul(&self, a: &BigNumRef, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mod_mul(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1 @@ -208,7 +149,7 @@ impl BigNum { } /// Equivalent to `self² mod n`. - pub fn checked_mod_sqr(&self, n: &BigNum) -> Result { + pub fn checked_mod_sqr(&self, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mod_sqr(r.raw(), self.raw(), n.raw(), ctx) == 1 @@ -217,7 +158,7 @@ impl BigNum { } /// Raises `self` to the `p`th power. - pub fn checked_exp(&self, p: &BigNum) -> Result { + pub fn checked_exp(&self, p: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_exp(r.raw(), self.raw(), p.raw(), ctx) == 1 @@ -226,7 +167,7 @@ impl BigNum { } /// Equivalent to `self.checked_exp(p) mod n`. - pub fn checked_mod_exp(&self, p: &BigNum, n: &BigNum) -> Result { + pub fn checked_mod_exp(&self, p: &BigNumRef, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mod_exp(r.raw(), self.raw(), p.raw(), n.raw(), ctx) == 1 @@ -236,7 +177,7 @@ impl BigNum { /// Calculates the modular multiplicative inverse of `self` modulo `n`, that is, an integer `r` /// such that `(self * r) % n == 1`. - pub fn checked_mod_inv(&self, n: &BigNum) -> Result { + pub fn checked_mod_inv(&self, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { !ffi::BN_mod_inverse(r.raw(), self.raw(), n.raw(), ctx).is_null() @@ -298,7 +239,7 @@ impl BigNum { } /// Computes the greatest common denominator of `self` and `a`. - pub fn checked_gcd(&self, a: &BigNum) -> Result { + pub fn checked_gcd(&self, a: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_gcd(r.raw(), self.raw(), a.raw(), ctx) == 1 @@ -306,34 +247,6 @@ impl BigNum { } } - /// Generates a prime number. - /// - /// # Parameters - /// - /// * `bits`: The length of the prime in bits (lower bound). - /// * `safe`: If true, returns a "safe" prime `p` so that `(p-1)/2` is also prime. - /// * `add`/`rem`: If `add` is set to `Some(add)`, `p % add == rem` will hold, where `p` is the - /// generated prime and `rem` is `1` if not specified (`None`). - pub fn checked_generate_prime(bits: i32, - safe: bool, - add: Option<&BigNum>, - rem: Option<&BigNum>) - -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - let add_arg = add.map(|a| a.raw()).unwrap_or(ptr::null_mut()); - let rem_arg = rem.map(|r| r.raw()).unwrap_or(ptr::null_mut()); - - ffi::BN_generate_prime_ex(r.raw(), - bits as c_int, - safe as c_int, - add_arg, - rem_arg, - ptr::null()) == 1 - }) - } - } - /// Checks whether `self` is prime. /// /// Performs a Miller-Rabin probabilistic primality test with `checks` iterations. @@ -370,33 +283,6 @@ impl BigNum { } } - /// Generates a cryptographically strong pseudo-random `BigNum`. - /// - /// # Parameters - /// - /// * `bits`: Length of the number in bits. - /// * `prop`: The desired properties of the number. - /// * `odd`: If `true`, the generated number will be odd. - pub fn checked_new_random(bits: i32, prop: RNGProperty, odd: bool) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_rand(r.raw(), bits as c_int, prop as c_int, odd as c_int) == 1 - }) - } - } - - /// The cryptographically weak counterpart to `checked_new_random`. - pub fn checked_new_pseudo_random(bits: i32, - prop: RNGProperty, - odd: bool) - -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_pseudo_rand(r.raw(), bits as c_int, prop as c_int, odd as c_int) == 1 - }) - } - } - /// Generates a cryptographically strong pseudo-random `BigNum` `r` in the range /// `0 <= r < self`. pub fn checked_rand_in_range(&self) -> Result { @@ -495,7 +381,7 @@ impl BigNum { } } - pub fn checked_add(&self, a: &BigNum) -> Result { + pub fn checked_add(&self, a: &BigNumRef) -> Result { unsafe { with_bn!(r, { ffi::BN_add(r.raw(), self.raw(), a.raw()) == 1 @@ -503,7 +389,7 @@ impl BigNum { } } - pub fn checked_sub(&self, a: &BigNum) -> Result { + pub fn checked_sub(&self, a: &BigNumRef) -> Result { unsafe { with_bn!(r, { ffi::BN_sub(r.raw(), self.raw(), a.raw()) == 1 @@ -511,7 +397,7 @@ impl BigNum { } } - pub fn checked_mul(&self, a: &BigNum) -> Result { + pub fn checked_mul(&self, a: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_mul(r.raw(), self.raw(), a.raw(), ctx) == 1 @@ -519,7 +405,7 @@ impl BigNum { } } - pub fn checked_div(&self, a: &BigNum) -> Result { + pub fn checked_div(&self, a: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_div(r.raw(), ptr::null_mut(), self.raw(), a.raw(), ctx) == 1 @@ -527,7 +413,7 @@ impl BigNum { } } - pub fn checked_mod(&self, a: &BigNum) -> Result { + pub fn checked_mod(&self, a: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { ffi::BN_div(ptr::null_mut(), r.raw(), self.raw(), a.raw(), ctx) == 1 @@ -551,6 +437,13 @@ impl BigNum { } } + pub fn to_owned(&self) -> Result { + unsafe { + let r = try_ssl_null!(ffi::BN_dup(self.raw())); + Ok(BigNum::from_handle(r)) + } + } + /// Inverts the sign of `self`. /// /// ``` @@ -574,9 +467,9 @@ impl BigNum { /// let s = -BigNum::new_from(8).unwrap(); /// let o = BigNum::new_from(8).unwrap(); /// - /// assert_eq!(s.abs_cmp(o), Ordering::Equal); + /// assert_eq!(s.abs_cmp(&o), Ordering::Equal); /// ``` - pub fn abs_cmp(&self, oth: BigNum) -> Ordering { + pub fn abs_cmp(&self, oth: &BigNumRef) -> Ordering { unsafe { let res = ffi::BN_ucmp(self.raw(), oth.raw()) as i32; if res < 0 { @@ -603,19 +496,12 @@ impl BigNum { (self.num_bits() + 7) / 8 } - pub unsafe fn raw(&self) -> *mut ffi::BIGNUM { - let BigNum(n) = *self; - n + pub fn raw(&self) -> *mut ffi::BIGNUM { + self.0 } - pub unsafe fn raw_ptr(&self) -> *const *mut ffi::BIGNUM { - let BigNum(ref n) = *self; - n - } - - pub fn into_raw(self) -> *mut ffi::BIGNUM { - let mut me = self; - mem::replace(&mut me.0, ptr::null_mut()) + pub fn raw_ptr(&self) -> *const *mut ffi::BIGNUM { + &self.0 } /// Returns a big-endian byte vector representation of the absolute value of `self`. @@ -679,134 +565,438 @@ impl BigNum { } } +/// An owned, signed, arbitrary-precision integer. +/// +/// `BigNum` provides wrappers around OpenSSL's checked arithmetic functions. +/// Additionally, it implements the standard operators (`std::ops`), which +/// perform unchecked arithmetic, unwrapping the returned `Result` of the +/// checked operations. +pub struct BigNum(BigNumRef<'static>); + +impl BigNum { + /// Creates a new `BigNum` with the value 0. + pub fn new() -> Result { + unsafe { + ffi::init(); + let v = try_ssl_null!(ffi::BN_new()); + Ok(BigNum::from_handle(v)) + } + } + + /// Creates a new `BigNum` with the given value. + pub fn new_from(n: u64) -> Result { + BigNum::new().and_then(|v| unsafe { + try_ssl!(ffi::BN_set_word(v.raw(), n as c_ulong)); + Ok(v) + }) + } + + /// Creates a `BigNum` from a decimal string. + pub fn from_dec_str(s: &str) -> Result { + BigNum::new().and_then(|v| unsafe { + let c_str = CString::new(s.as_bytes()).unwrap(); + try_ssl!(ffi::BN_dec2bn(v.raw_ptr(), c_str.as_ptr() as *const _)); + Ok(v) + }) + } + + /// Creates a `BigNum` from a hexadecimal string. + pub fn from_hex_str(s: &str) -> Result { + BigNum::new().and_then(|v| unsafe { + let c_str = CString::new(s.as_bytes()).unwrap(); + try_ssl!(ffi::BN_hex2bn(v.raw_ptr(), c_str.as_ptr() as *const _)); + Ok(v) + }) + } + + pub unsafe fn from_handle(handle: *mut ffi::BIGNUM) -> BigNum { + BigNum(BigNumRef::from_handle(handle)) + } + + /// Creates a new `BigNum` from an unsigned, big-endian encoded number of arbitrary length. + /// + /// ``` + /// # use openssl::bn::BigNum; + /// let bignum = BigNum::new_from_slice(&[0x12, 0x00, 0x34]).unwrap(); + /// + /// assert_eq!(bignum, BigNum::new_from(0x120034).unwrap()); + /// ``` + pub fn new_from_slice(n: &[u8]) -> Result { + BigNum::new().and_then(|v| unsafe { + try_ssl_null!(ffi::BN_bin2bn(n.as_ptr(), n.len() as c_int, v.raw())); + Ok(v) + }) + } + /// Generates a prime number. + /// + /// # Parameters + /// + /// * `bits`: The length of the prime in bits (lower bound). + /// * `safe`: If true, returns a "safe" prime `p` so that `(p-1)/2` is also prime. + /// * `add`/`rem`: If `add` is set to `Some(add)`, `p % add == rem` will hold, where `p` is the + /// generated prime and `rem` is `1` if not specified (`None`). + pub fn checked_generate_prime(bits: i32, + safe: bool, + add: Option<&BigNum>, + rem: Option<&BigNum>) + -> Result { + unsafe { + with_bn_in_ctx!(r, ctx, { + let add_arg = add.map(|a| a.raw()).unwrap_or(ptr::null_mut()); + let rem_arg = rem.map(|r| r.raw()).unwrap_or(ptr::null_mut()); + + ffi::BN_generate_prime_ex(r.raw(), + bits as c_int, + safe as c_int, + add_arg, + rem_arg, + ptr::null()) == 1 + }) + } + } + + /// Generates a cryptographically strong pseudo-random `BigNum`. + /// + /// # Parameters + /// + /// * `bits`: Length of the number in bits. + /// * `prop`: The desired properties of the number. + /// * `odd`: If `true`, the generated number will be odd. + pub fn checked_new_random(bits: i32, prop: RNGProperty, odd: bool) -> Result { + unsafe { + with_bn_in_ctx!(r, ctx, { + ffi::BN_rand(r.raw(), bits as c_int, prop as c_int, odd as c_int) == 1 + }) + } + } + + /// The cryptographically weak counterpart to `checked_new_random`. + pub fn checked_new_pseudo_random(bits: i32, + prop: RNGProperty, + odd: bool) + -> Result { + unsafe { + with_bn_in_ctx!(r, ctx, { + ffi::BN_pseudo_rand(r.raw(), bits as c_int, prop as c_int, odd as c_int) == 1 + }) + } + } + + pub fn into_raw(self) -> *mut ffi::BIGNUM { + let ptr = self.raw(); + mem::forget(self); + ptr + } +} + +impl Drop for BigNum { + fn drop(&mut self) { + unsafe { ffi::BN_clear_free(self.raw()); } + } +} + +impl Deref for BigNum { + type Target = BigNumRef<'static>; + + fn deref(&self) -> &BigNumRef<'static> { + &self.0 + } +} + +impl DerefMut for BigNum { + fn deref_mut(&mut self) -> &mut BigNumRef<'static> { + &mut self.0 + } +} + +impl AsRef> for BigNum { + fn as_ref(&self) -> &BigNumRef<'static> { + self.deref() + } +} + +impl<'a> fmt::Debug for BigNumRef<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_dec_str()) + } +} + impl fmt::Debug for BigNum { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.to_dec_str()) } } -impl Eq for BigNum {} -impl PartialEq for BigNum { - fn eq(&self, oth: &BigNum) -> bool { +impl<'a> fmt::Display for BigNumRef<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_dec_str()) + } +} + +impl fmt::Display for BigNum { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_dec_str()) + } +} + +impl<'a, 'b> PartialEq> for BigNumRef<'a> { + fn eq(&self, oth: &BigNumRef) -> bool { unsafe { ffi::BN_cmp(self.raw(), oth.raw()) == 0 } } } -impl Ord for BigNum { - fn cmp(&self, oth: &BigNum) -> Ordering { - self.partial_cmp(oth).unwrap() +impl<'a> PartialEq for BigNumRef<'a> { + fn eq(&self, oth: &BigNum) -> bool { + self.eq(oth.deref()) + } +} + +impl<'a> Eq for BigNumRef<'a> {} + +impl PartialEq for BigNum { + fn eq(&self, oth: &BigNum) -> bool { + self.deref().eq(oth) + } +} + +impl<'a> PartialEq> for BigNum { + fn eq(&self, oth: &BigNumRef) -> bool { + self.deref().eq(oth) + } +} + +impl Eq for BigNum {} + +impl<'a, 'b> PartialOrd> for BigNumRef<'a> { + fn partial_cmp(&self, oth: &BigNumRef) -> Option { + Some(self.cmp(oth)) + } +} + +impl<'a> PartialOrd for BigNumRef<'a> { + fn partial_cmp(&self, oth: &BigNum) -> Option { + Some(self.cmp(oth.deref())) + } +} + +impl<'a> Ord for BigNumRef<'a> { + fn cmp(&self, oth: &BigNumRef) -> Ordering { + unsafe { ffi::BN_cmp(self.raw(), oth.raw()).cmp(&0) } } } impl PartialOrd for BigNum { fn partial_cmp(&self, oth: &BigNum) -> Option { - unsafe { - let v = ffi::BN_cmp(self.raw(), oth.raw()); - let ret = if v == 0 { - Ordering::Equal - } else if v < 0 { - Ordering::Less - } else { - Ordering::Greater - }; - Some(ret) - } + self.deref().partial_cmp(oth.deref()) } } -impl Drop for BigNum { - fn drop(&mut self) { - unsafe { - if !self.raw().is_null() { - ffi::BN_clear_free(self.raw()); - } - } +impl<'a> PartialOrd> for BigNum { + fn partial_cmp(&self, oth: &BigNumRef) -> Option { + self.deref().partial_cmp(oth) } } -#[doc(hidden)] // This module only contains impls, so it's empty when generating docs -pub mod unchecked { - use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub}; - use ffi; - use super::BigNum; - - impl<'a, 'b> Add<&'b BigNum> for &'a BigNum { - type Output = BigNum; - - fn add(self, oth: &'b BigNum) -> BigNum { - self.checked_add(oth).unwrap() - } +impl Ord for BigNum { + fn cmp(&self, oth: &BigNum) -> Ordering { + self.deref().cmp(oth.deref()) } +} - impl<'a, 'b> Sub<&'b BigNum> for &'a BigNum { - type Output = BigNum; +impl<'a, 'b> Add<&'b BigNumRef<'b>> for &'a BigNumRef<'a> { + type Output = BigNum; - fn sub(self, oth: &'b BigNum) -> BigNum { - self.checked_sub(oth).unwrap() - } + fn add(self, oth: &BigNumRef) -> BigNum { + self.checked_add(oth).unwrap() } +} - impl<'a, 'b> Mul<&'b BigNum> for &'a BigNum { - type Output = BigNum; +impl<'a, 'b> Sub<&'b BigNumRef<'b>> for &'a BigNumRef<'a> { + type Output = BigNum; - fn mul(self, oth: &'b BigNum) -> BigNum { - self.checked_mul(oth).unwrap() - } + fn sub(self, oth: &BigNumRef) -> BigNum { + self.checked_sub(oth).unwrap() } +} - impl<'a, 'b> Div<&'b BigNum> for &'a BigNum { - type Output = BigNum; +impl<'a, 'b> Sub<&'b BigNum> for &'a BigNumRef<'a> { + type Output = BigNum; - fn div(self, oth: &'b BigNum) -> BigNum { - self.checked_div(oth).unwrap() - } + fn sub(self, oth: &BigNum) -> BigNum { + self.checked_sub(oth).unwrap() } +} - impl<'a, 'b> Rem<&'b BigNum> for &'a BigNum { - type Output = BigNum; +impl<'a, 'b> Sub<&'b BigNum> for &'a BigNum { + type Output = BigNum; - fn rem(self, oth: &'b BigNum) -> BigNum { - self.checked_mod(oth).unwrap() - } + fn sub(self, oth: &BigNum) -> BigNum { + self.checked_sub(oth).unwrap() } +} - impl<'a> Shl for &'a BigNum { - type Output = BigNum; +impl<'a, 'b> Sub<&'b BigNumRef<'b>> for &'a BigNum { + type Output = BigNum; - fn shl(self, n: i32) -> BigNum { - self.checked_shl(&n).unwrap() - } + fn sub(self, oth: &BigNumRef) -> BigNum { + self.checked_sub(oth).unwrap() } +} - impl<'a> Shr for &'a BigNum { - type Output = BigNum; +impl<'a, 'b> Mul<&'b BigNumRef<'b>> for &'a BigNumRef<'a> { + type Output = BigNum; - fn shr(self, n: i32) -> BigNum { - self.checked_shr(&n).unwrap() - } + fn mul(self, oth: &BigNumRef) -> BigNum { + self.checked_mul(oth).unwrap() } +} - impl Clone for BigNum { - fn clone(&self) -> BigNum { - unsafe { - let r = ffi::BN_dup(self.raw()); - if r.is_null() { - panic!("Unexpected null pointer from BN_dup(..)") - } else { - BigNum(r) - } - } - } +impl<'a, 'b> Mul<&'b BigNum> for &'a BigNumRef<'a> { + type Output = BigNum; + + fn mul(self, oth: &BigNum) -> BigNum { + self.checked_mul(oth).unwrap() } +} - impl Neg for BigNum { - type Output = BigNum; +impl<'a, 'b> Mul<&'b BigNum> for &'a BigNum { + type Output = BigNum; - fn neg(self) -> BigNum { - let mut n = self.clone(); - n.negate(); - n - } + fn mul(self, oth: &BigNum) -> BigNum { + self.checked_mul(oth).unwrap() + } +} + +impl<'a, 'b> Mul<&'b BigNumRef<'b>> for &'a BigNum { + type Output = BigNum; + + fn mul(self, oth: &BigNumRef) -> BigNum { + self.checked_mul(oth).unwrap() + } +} + +impl<'a, 'b> Div<&'b BigNumRef<'b>> for &'a BigNumRef<'a> { + type Output = BigNum; + + fn div(self, oth: &'b BigNumRef<'b>) -> BigNum { + self.checked_div(oth).unwrap() + } +} + +impl<'a, 'b> Div<&'b BigNum> for &'a BigNumRef<'a> { + type Output = BigNum; + + fn div(self, oth: &'b BigNum) -> BigNum { + self.checked_div(oth).unwrap() + } +} + +impl<'a, 'b> Div<&'b BigNum> for &'a BigNum { + type Output = BigNum; + + fn div(self, oth: &'b BigNum) -> BigNum { + self.checked_div(oth).unwrap() + } +} + +impl<'a, 'b> Div<&'b BigNumRef<'b>> for &'a BigNum { + type Output = BigNum; + + fn div(self, oth: &'b BigNumRef<'b>) -> BigNum { + self.checked_div(oth).unwrap() + } +} + +impl<'a, 'b> Rem<&'b BigNumRef<'b>> for &'a BigNumRef<'a> { + type Output = BigNum; + + fn rem(self, oth: &'b BigNumRef<'b>) -> BigNum { + self.checked_mod(oth).unwrap() + } +} + +impl<'a, 'b> Rem<&'b BigNum> for &'a BigNumRef<'a> { + type Output = BigNum; + + fn rem(self, oth: &'b BigNum) -> BigNum { + self.checked_mod(oth).unwrap() + } +} + +impl<'a, 'b> Rem<&'b BigNumRef<'b>> for &'a BigNum { + type Output = BigNum; + + fn rem(self, oth: &'b BigNumRef<'b>) -> BigNum { + self.checked_mod(oth).unwrap() + } +} + +impl<'a, 'b> Rem<&'b BigNum> for &'a BigNum { + type Output = BigNum; + + fn rem(self, oth: &'b BigNum) -> BigNum { + self.checked_mod(oth).unwrap() + } +} + +impl<'a> Shl for &'a BigNumRef<'a> { + type Output = BigNum; + + fn shl(self, n: i32) -> BigNum { + self.checked_shl(&n).unwrap() + } +} + +impl<'a> Shl for &'a BigNum { + type Output = BigNum; + + fn shl(self, n: i32) -> BigNum { + self.checked_shl(&n).unwrap() + } +} + +impl<'a> Shr for &'a BigNumRef<'a> { + type Output = BigNum; + + fn shr(self, n: i32) -> BigNum { + self.checked_shr(&n).unwrap() + } +} + +impl<'a> Shr for &'a BigNum { + type Output = BigNum; + + fn shr(self, n: i32) -> BigNum { + self.checked_shr(&n).unwrap() + } +} + +impl<'a> Neg for &'a BigNumRef<'a> { + type Output = BigNum; + + fn neg(self) -> BigNum { + let mut n = self.to_owned().unwrap(); + n.negate(); + n + } +} + +impl<'a> Neg for &'a BigNum { + type Output = BigNum; + + fn neg(self) -> BigNum { + let mut n = self.deref().to_owned().unwrap(); + n.negate(); + n + } +} + +impl Neg for BigNum { + type Output = BigNum; + + fn neg(mut self) -> BigNum { + self.negate(); + self } } diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index 40702627..84024379 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -4,7 +4,7 @@ use error::ErrorStack; use std::ptr; use libc::{c_uint, c_int, c_char, c_void}; -use bn::BigNum; +use bn::BigNumRef; use bio::{MemBio, MemBioSlice}; use crypto::hash; use crypto::HashTypeInternals; @@ -189,25 +189,27 @@ impl DSA { self.0 } - // The following getters are unsafe, since BigNum::new_from_ffi fails upon null pointers - pub fn p(&self) -> Result { - unsafe { BigNum::new_from_ffi((*self.0).p) } + pub fn p<'a>(&'a self) -> BigNumRef<'a> { + assert!(self.has_p()); + unsafe { BigNumRef::from_handle((*self.0).p) } } pub fn has_p(&self) -> bool { unsafe { !(*self.0).p.is_null() } } - pub fn q(&self) -> Result { - unsafe { BigNum::new_from_ffi((*self.0).q) } + pub fn q<'a>(&'a self) -> BigNumRef<'a> { + assert!(self.has_q()); + unsafe { BigNumRef::from_handle((*self.0).q) } } pub fn has_q(&self) -> bool { unsafe { !(*self.0).q.is_null() } } - pub fn g(&self) -> Result { - unsafe { BigNum::new_from_ffi((*self.0).g) } + pub fn g<'a>(&'a self) -> BigNumRef<'a> { + assert!(self.has_g()); + unsafe { BigNumRef::from_handle((*self.0).g) } } pub fn has_g(&self) -> bool { diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index e554f3b2..9a3e140a 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -799,7 +799,7 @@ mod tests { let sig = k0.sign(&msg); let r0 = k0.get_rsa(); - let r1 = RSA::from_public_components(r0.n().expect("n"), r0.e().expect("e")).expect("r1"); + let r1 = RSA::from_public_components(r0.n().to_owned().unwrap(), r0.e().to_owned().unwrap()).expect("r1"); k1.set_rsa(&r1); assert!(k1.can(super::Role::Encrypt)); @@ -847,12 +847,13 @@ mod tests { fn test_pkey_clone_creates_copy() { let mut pkey = super::PKey::new(); pkey.gen(512); - let old_pkey_n = pkey.get_rsa().n().unwrap(); + let rsa = pkey.get_rsa(); + let old_pkey_n = rsa.n(); let mut pkey2 = pkey.clone(); pkey2.gen(512); - assert!(old_pkey_n == pkey.get_rsa().n().unwrap()); + assert!(old_pkey_n == rsa.n()); } #[test] @@ -862,7 +863,7 @@ mod tests { let pkey2 = pkey.clone(); - assert!(pkey.get_rsa().q().unwrap() == pkey2.get_rsa().q().unwrap()); + assert!(pkey.get_rsa().q() == pkey2.get_rsa().q()); } #[test] @@ -874,6 +875,6 @@ mod tests { let pub_key2 = pub_key.clone(); - assert!(pub_key.get_rsa().n().unwrap() == pub_key2.get_rsa().n().unwrap()); + assert!(pub_key.get_rsa().n() == pub_key2.get_rsa().n()); } } diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 5c70c8ea..73239731 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -3,7 +3,7 @@ use std::fmt; use std::ptr; use libc::{c_int, c_void, c_char}; -use bn::BigNum; +use bn::{BigNum, BigNumRef}; use bio::{MemBio, MemBioSlice}; use error::ErrorStack; use crypto::HashTypeInternals; @@ -171,43 +171,49 @@ impl RSA { self.0 } - // The following getters are unsafe, since BigNum::new_from_ffi fails upon null pointers - pub fn n(&self) -> Result { - unsafe { - BigNum::new_from_ffi((*self.0).n) - } + pub fn n<'a>(&'a self) -> BigNumRef<'a> { + assert!(self.has_n()); + unsafe { BigNumRef::from_handle((*self.0).n) } } pub fn has_n(&self) -> bool { unsafe { !(*self.0).n.is_null() } } - pub fn d(&self) -> Result { - unsafe { - BigNum::new_from_ffi((*self.0).d) - } + pub fn d<'a>(&self) -> BigNumRef<'a> { + assert!(self.has_d()); + unsafe { BigNumRef::from_handle((*self.0).d) } } - pub fn e(&self) -> Result { - unsafe { - BigNum::new_from_ffi((*self.0).e) - } + pub fn has_d(&self) -> bool { + unsafe { !(*self.0).d.is_null() } + } + + pub fn e<'a>(&'a self) -> BigNumRef<'a> { + assert!(self.has_e()); + unsafe { BigNumRef::from_handle((*self.0).e) } } pub fn has_e(&self) -> bool { unsafe { !(*self.0).e.is_null() } } - pub fn p(&self) -> Result { - unsafe { - BigNum::new_from_ffi((*self.0).p) - } + pub fn p<'a>(&'a self) -> BigNumRef<'a> { + assert!(self.has_p()); + unsafe { BigNumRef::from_handle((*self.0).p) } } - pub fn q(&self) -> Result { - unsafe { - BigNum::new_from_ffi((*self.0).q) - } + pub fn has_p(&self) -> bool { + unsafe { !(*self.0).p.is_null() } + } + + pub fn q<'a>(&'a self) -> BigNumRef<'a> { + assert!(self.has_q()); + unsafe { BigNumRef::from_handle((*self.0).q) } + } + + pub fn has_q(&self) -> bool { + unsafe { !(*self.0).q.is_null() } } } From 7ca5ccf0646478b6d3557b066594d7e7afc36c53 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 16:28:29 -0700 Subject: [PATCH 56/96] Hash reform Closes #430 --- openssl-sys/src/lib.rs | 2 + openssl/src/crypto/dsa.rs | 14 ++-- openssl/src/crypto/hash.rs | 156 ++++++++++++++--------------------- openssl/src/crypto/hmac.rs | 158 +++++++++++++++++------------------- openssl/src/crypto/mod.rs | 6 -- openssl/src/crypto/pkcs5.rs | 48 +++++++---- openssl/src/crypto/pkey.rs | 2 +- openssl/src/crypto/rsa.rs | 10 +-- openssl/src/lib.rs | 7 ++ openssl/src/x509/mod.rs | 35 +++----- 10 files changed, 200 insertions(+), 238 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 250bb054..6951a7db 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -282,6 +282,8 @@ pub const BIO_FLAGS_SHOULD_RETRY: c_int = 0x08; pub const CRYPTO_LOCK: c_int = 1; +pub const EVP_MAX_MD_SIZE: c_uint = 64; + pub const MBSTRING_ASC: c_int = MBSTRING_FLAG | 1; pub const MBSTRING_BMP: c_int = MBSTRING_FLAG | 2; pub const MBSTRING_FLAG: c_int = 0x1000; diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index 84024379..099657da 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -7,7 +7,7 @@ use libc::{c_uint, c_int, c_char, c_void}; use bn::BigNumRef; use bio::{MemBio, MemBioSlice}; use crypto::hash; -use crypto::HashTypeInternals; +use HashTypeInternals; use crypto::util::{CallbackState, invoke_passwd_cb}; @@ -249,9 +249,9 @@ mod test { let input: Vec = (0..25).cycle().take(1024).collect(); let digest = { - let mut sha = Hasher::new(Type::SHA1); + let mut sha = Hasher::new(Type::SHA1).unwrap(); sha.write_all(&input).unwrap(); - sha.finish() + sha.finish().unwrap() }; let sig = key.sign(Type::SHA1, &digest).unwrap(); @@ -274,9 +274,9 @@ mod test { }; let digest = { - let mut sha = Hasher::new(Type::SHA1); + let mut sha = Hasher::new(Type::SHA1).unwrap(); sha.write_all(&input).unwrap(); - sha.finish() + sha.finish().unwrap() }; let sig = private_key.sign(Type::SHA1, &digest).unwrap(); @@ -298,9 +298,9 @@ mod test { }; let digest = { - let mut sha = Hasher::new(Type::SHA1); + let mut sha = Hasher::new(Type::SHA1).unwrap(); sha.write_all(&input).unwrap(); - sha.finish() + sha.finish().unwrap() }; let mut sig = private_key.sign(Type::SHA1, &digest).unwrap(); diff --git a/openssl/src/crypto/hash.rs b/openssl/src/crypto/hash.rs index 69d3a350..207a55f5 100644 --- a/openssl/src/crypto/hash.rs +++ b/openssl/src/crypto/hash.rs @@ -1,10 +1,12 @@ use libc::c_uint; -use std::iter::repeat; use std::io::prelude::*; use std::io; +use std::ptr; +use std::cmp; use ffi; -use crypto::HashTypeInternals; +use HashTypeInternals; +use error::ErrorStack; use nid::Nid; /// Message digest (hash) type. @@ -31,26 +33,8 @@ impl HashTypeInternals for Type { Type::RIPEMD160 => Nid::RIPEMD160, } } -} -impl Type { - /// Returns the length of the message digest. - #[inline] - pub fn md_len(&self) -> usize { - match *self { - Type::MD5 => 16, - Type::SHA1 => 20, - Type::SHA224 => 28, - Type::SHA256 => 32, - Type::SHA384 => 48, - Type::SHA512 => 64, - Type::RIPEMD160 => 20, - } - } - - /// Internal interface subject to removal. - #[inline] - pub fn evp_md(&self) -> *const ffi::EVP_MD { + fn evp_md(&self) -> *const ffi::EVP_MD { unsafe { match *self { Type::MD5 => ffi::EVP_md5(), @@ -84,21 +68,20 @@ use self::State::*; /// use openssl::crypto::hash::{hash, Type}; /// let data = b"\x42\xF4\x97\xE0"; /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2"; -/// let res = hash(Type::MD5, data); +/// let res = hash(Type::MD5, data).unwrap(); /// assert_eq!(res, spec); /// ``` /// /// Use the `Write` trait to supply the input in chunks. /// /// ``` -/// use std::io::prelude::*; /// use openssl::crypto::hash::{Hasher, Type}; /// let data = [b"\x42\xF4", b"\x97\xE0"]; /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2"; -/// let mut h = Hasher::new(Type::MD5); -/// h.write_all(data[0]); -/// h.write_all(data[1]); -/// let res = h.finish(); +/// let mut h = Hasher::new(Type::MD5).unwrap(); +/// h.update(data[0]).unwrap(); +/// h.update(data[1]).unwrap(); +/// let res = h.finish().unwrap(); /// assert_eq!(res, spec); /// ``` /// @@ -116,14 +99,10 @@ pub struct Hasher { impl Hasher { /// Creates a new `Hasher` with the specified hash type. - pub fn new(ty: Type) -> Hasher { + pub fn new(ty: Type) -> Result { ffi::init(); - let ctx = unsafe { - let r = ffi::EVP_MD_CTX_create(); - assert!(!r.is_null()); - r - }; + let ctx = unsafe { try_ssl_null!(ffi::EVP_MD_CTX_create()) }; let md = ty.evp_md(); let mut h = Hasher { @@ -132,67 +111,60 @@ impl Hasher { type_: ty, state: Finalized, }; - h.init(); - h + try!(h.init()); + Ok(h) } - #[inline] - fn init(&mut self) { + fn init(&mut self) -> Result<(), ErrorStack> { match self.state { - Reset => return, + Reset => return Ok(()), Updated => { - self.finalize(); + try!(self.finish()); } Finalized => (), } - unsafe { - let r = ffi::EVP_DigestInit_ex(self.ctx, self.md, 0 as *const _); - assert_eq!(r, 1); - } + unsafe { try_ssl!(ffi::EVP_DigestInit_ex(self.ctx, self.md, 0 as *const _)); } self.state = Reset; + Ok(()) } - #[inline] - fn update(&mut self, data: &[u8]) { + /// Feeds data into the hasher. + pub fn update(&mut self, mut data: &[u8]) -> Result<(), ErrorStack> { if self.state == Finalized { - self.init(); + try!(self.init()); } - unsafe { - let r = ffi::EVP_DigestUpdate(self.ctx, data.as_ptr(), data.len() as c_uint); - assert_eq!(r, 1); + while !data.is_empty() { + let len = cmp::min(data.len(), c_uint::max_value() as usize); + unsafe { + try_ssl!(ffi::EVP_DigestUpdate(self.ctx, data.as_ptr(), len as c_uint)); + } + data = &data[len..]; } self.state = Updated; - } - - #[inline] - fn finalize(&mut self) -> Vec { - if self.state == Finalized { - self.init(); - } - let md_len = self.type_.md_len(); - let mut res: Vec = repeat(0).take(md_len).collect(); - unsafe { - let mut len = 0; - let r = ffi::EVP_DigestFinal_ex(self.ctx, res.as_mut_ptr(), &mut len); - self.state = Finalized; - assert_eq!(len as usize, md_len); - assert_eq!(r, 1); - } - res + Ok(()) } /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. - #[inline] - pub fn finish(&mut self) -> Vec { - self.finalize() + pub fn finish(&mut self) -> Result, ErrorStack> { + if self.state == Finalized { + try!(self.init()); + } + unsafe { + let mut len = ffi::EVP_MAX_MD_SIZE; + let mut res = vec![0; len as usize]; + try_ssl!(ffi::EVP_DigestFinal_ex(self.ctx, res.as_mut_ptr(), &mut len)); + res.truncate(len as usize); + self.state = Finalized; + Ok(res) + } } } impl Write for Hasher { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { - self.update(buf); + try!(self.update(buf)); Ok(buf.len()) } @@ -223,9 +195,7 @@ impl Drop for Hasher { fn drop(&mut self) { unsafe { if self.state != Finalized { - let mut buf: Vec = repeat(0).take(self.type_.md_len()).collect(); - let mut len = 0; - ffi::EVP_DigestFinal_ex(self.ctx, buf.as_mut_ptr(), &mut len); + drop(self.finish()); } ffi::EVP_MD_CTX_destroy(self.ctx); } @@ -233,9 +203,9 @@ impl Drop for Hasher { } /// Computes the hash of the `data` with the hash `t`. -pub fn hash(t: Type, data: &[u8]) -> Vec { - let mut h = Hasher::new(t); - let _ = h.write_all(data); +pub fn hash(t: Type, data: &[u8]) -> Result, ErrorStack> { + let mut h = try!(Hasher::new(t)); + try!(h.update(data)); h.finish() } @@ -246,13 +216,13 @@ mod tests { use std::io::prelude::*; fn hash_test(hashtype: Type, hashtest: &(&str, &str)) { - let res = hash(hashtype, &*hashtest.0.from_hex().unwrap()); + let res = hash(hashtype, &*hashtest.0.from_hex().unwrap()).unwrap(); assert_eq!(res.to_hex(), hashtest.1); } fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) { - let _ = h.write_all(&*hashtest.0.from_hex().unwrap()); - let res = h.finish(); + let _ = h.write_all(&*hashtest.0.from_hex().unwrap()).unwrap(); + let res = h.finish().unwrap(); assert_eq!(res.to_hex(), hashtest.1); } @@ -294,7 +264,7 @@ mod tests { #[test] fn test_md5_recycle() { - let mut h = Hasher::new(Type::MD5); + let mut h = Hasher::new(Type::MD5).unwrap(); for test in md5_tests.iter() { hash_recycle_test(&mut h, test); } @@ -302,11 +272,11 @@ mod tests { #[test] fn test_finish_twice() { - let mut h = Hasher::new(Type::MD5); - let _ = h.write_all(&*md5_tests[6].0.from_hex().unwrap()); - let _ = h.finish(); - let res = h.finish(); - let null = hash(Type::MD5, &[]); + let mut h = Hasher::new(Type::MD5).unwrap(); + h.write_all(&*md5_tests[6].0.from_hex().unwrap()).unwrap(); + h.finish().unwrap(); + let res = h.finish().unwrap(); + let null = hash(Type::MD5, &[]).unwrap(); assert_eq!(res, null); } @@ -316,26 +286,26 @@ mod tests { let inp = md5_tests[i].0.from_hex().unwrap(); assert!(inp.len() > 2); let p = inp.len() / 2; - let h0 = Hasher::new(Type::MD5); + let h0 = Hasher::new(Type::MD5).unwrap(); println!("Clone a new hasher"); let mut h1 = h0.clone(); - let _ = h1.write_all(&inp[..p]); + h1.write_all(&inp[..p]).unwrap(); { println!("Clone an updated hasher"); let mut h2 = h1.clone(); - let _ = h2.write_all(&inp[p..]); - let res = h2.finish(); + h2.write_all(&inp[p..]).unwrap(); + let res = h2.finish().unwrap(); assert_eq!(res.to_hex(), md5_tests[i].1); } - let _ = h1.write_all(&inp[p..]); - let res = h1.finish(); + h1.write_all(&inp[p..]).unwrap(); + let res = h1.finish().unwrap(); assert_eq!(res.to_hex(), md5_tests[i].1); println!("Clone a finished hasher"); let mut h3 = h1.clone(); - let _ = h3.write_all(&*md5_tests[i + 1].0.from_hex().unwrap()); - let res = h3.finish(); + h3.write_all(&*md5_tests[i + 1].0.from_hex().unwrap()).unwrap(); + let res = h3.finish().unwrap(); assert_eq!(res.to_hex(), md5_tests[i + 1].1); } diff --git a/openssl/src/crypto/hmac.rs b/openssl/src/crypto/hmac.rs index 143c7b75..453511ac 100644 --- a/openssl/src/crypto/hmac.rs +++ b/openssl/src/crypto/hmac.rs @@ -14,14 +14,16 @@ // use libc::{c_int, c_uint}; -use std::iter::repeat; use std::io; use std::io::prelude::*; - -use crypto::hash::Type; +use std::cmp; use ffi; use ffi_extras; +use HashTypeInternals; +use crypto::hash::Type; +use error::ErrorStack; + #[derive(PartialEq, Copy, Clone)] enum State { Reset, @@ -43,23 +45,22 @@ use self::State::*; /// let key = b"Jefe"; /// let data = b"what do ya want for nothing?"; /// let spec = b"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38"; -/// let res = hmac(Type::MD5, key, data); +/// let res = hmac(Type::MD5, key, data).unwrap(); /// assert_eq!(res, spec); /// ``` /// /// Use the `Write` trait to supply the input in chunks. /// /// ``` -/// use std::io::prelude::*; /// use openssl::crypto::hash::Type; /// use openssl::crypto::hmac::HMAC; /// let key = b"Jefe"; /// let data: &[&[u8]] = &[b"what do ya ", b"want for nothing?"]; /// let spec = b"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38"; -/// let mut h = HMAC::new(Type::MD5, &*key); -/// h.write_all(data[0]); -/// h.write_all(data[1]); -/// let res = h.finish(); +/// let mut h = HMAC::new(Type::MD5, &*key).unwrap(); +/// h.update(data[0]).unwrap(); +/// h.update(data[1]).unwrap(); +/// let res = h.finish().unwrap(); /// assert_eq!(res, spec); /// ``` pub struct HMAC { @@ -70,7 +71,7 @@ pub struct HMAC { impl HMAC { /// Creates a new `HMAC` with the specified hash type using the `key`. - pub fn new(ty: Type, key: &[u8]) -> HMAC { + pub fn new(ty: Type, key: &[u8]) -> Result { ffi::init(); let ctx = unsafe { @@ -85,86 +86,79 @@ impl HMAC { type_: ty, state: Finalized, }; - h.init_once(md, key); - h + try!(h.init_once(md, key)); + Ok(h) } - #[inline] - fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) { + fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) -> Result<(), ErrorStack> { unsafe { - let r = ffi_extras::HMAC_Init_ex(&mut self.ctx, - key.as_ptr(), - key.len() as c_int, - md, - 0 as *const _); - assert_eq!(r, 1); + try_ssl!(ffi_extras::HMAC_Init_ex(&mut self.ctx, + key.as_ptr(), + key.len() as c_int, + md, + 0 as *const _)); } self.state = Reset; + Ok(()) } - #[inline] - fn init(&mut self) { + fn init(&mut self) -> Result<(), ErrorStack> { match self.state { - Reset => return, + Reset => return Ok(()), Updated => { - self.finalize(); + try!(self.finish()); } Finalized => (), } // If the key and/or md is not supplied it's reused from the last time // avoiding redundant initializations unsafe { - let r = ffi_extras::HMAC_Init_ex(&mut self.ctx, - 0 as *const _, - 0, - 0 as *const _, - 0 as *const _); - assert_eq!(r, 1); + try_ssl!(ffi_extras::HMAC_Init_ex(&mut self.ctx, + 0 as *const _, + 0, + 0 as *const _, + 0 as *const _)); } self.state = Reset; + Ok(()) } - #[inline] - fn update(&mut self, data: &[u8]) { + pub fn update(&mut self, mut data: &[u8]) -> Result<(), ErrorStack> { if self.state == Finalized { - self.init(); + try!(self.init()); } - unsafe { - let r = ffi_extras::HMAC_Update(&mut self.ctx, data.as_ptr(), data.len() as c_uint); - assert_eq!(r, 1); + while !data.is_empty() { + let len = cmp::min(data.len(), c_uint::max_value() as usize); + unsafe { + try_ssl!(ffi_extras::HMAC_Update(&mut self.ctx, data.as_ptr(), len as c_uint)); + } + data = &data[len..]; } self.state = Updated; - } - - #[inline] - fn finalize(&mut self) -> Vec { - if self.state == Finalized { - self.init(); - } - let md_len = self.type_.md_len(); - let mut res: Vec = repeat(0).take(md_len).collect(); - unsafe { - let mut len = 0; - let r = ffi_extras::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len); - self.state = Finalized; - assert_eq!(len as usize, md_len); - assert_eq!(r, 1); - } - res + Ok(()) } /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. - #[inline] - pub fn finish(&mut self) -> Vec { - self.finalize() + pub fn finish(&mut self) -> Result, ErrorStack> { + if self.state == Finalized { + try!(self.init()); + } + unsafe { + let mut len = ffi::EVP_MAX_MD_SIZE; + let mut res = vec![0; len as usize]; + try_ssl!(ffi_extras::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len)); + res.truncate(len as usize); + self.state = Finalized; + Ok(res) + } } } impl Write for HMAC { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { - self.update(buf); + try!(self.update(buf)); Ok(buf.len()) } @@ -193,9 +187,7 @@ impl Drop for HMAC { fn drop(&mut self) { unsafe { if self.state != Finalized { - let mut buf: Vec = repeat(0).take(self.type_.md_len()).collect(); - let mut len = 0; - ffi_extras::HMAC_Final(&mut self.ctx, buf.as_mut_ptr(), &mut len); + drop(self.finish()); } ffi::HMAC_CTX_cleanup(&mut self.ctx); } @@ -203,9 +195,9 @@ impl Drop for HMAC { } /// Computes the HMAC of the `data` with the hash `t` and `key`. -pub fn hmac(t: Type, key: &[u8], data: &[u8]) -> Vec { - let mut h = HMAC::new(t, key); - let _ = h.write_all(data); +pub fn hmac(t: Type, key: &[u8], data: &[u8]) -> Result, ErrorStack> { + let mut h = try!(HMAC::new(t, key)); + try!(h.update(data)); h.finish() } @@ -220,14 +212,14 @@ mod tests { fn test_hmac(ty: Type, tests: &[(Vec, Vec, Vec)]) { for &(ref key, ref data, ref res) in tests.iter() { - assert_eq!(hmac(ty, &**key, &**data), *res); + assert_eq!(hmac(ty, &**key, &**data).unwrap(), *res); } } fn test_hmac_recycle(h: &mut HMAC, test: &(Vec, Vec, Vec)) { let &(_, ref data, ref res) = test; - let _ = h.write_all(&**data); - assert_eq!(h.finish(), *res); + h.write_all(&**data).unwrap(); + assert_eq!(h.finish().unwrap(), *res); } #[test] @@ -273,7 +265,7 @@ mod tests { .to_vec(), "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())]; - let mut h = HMAC::new(MD5, &*tests[0].0); + let mut h = HMAC::new(MD5, &*tests[0].0).unwrap(); for i in 0..100usize { let test = &tests[i % 2]; test_hmac_recycle(&mut h, test); @@ -287,11 +279,11 @@ mod tests { b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd".from_hex().unwrap()); - let mut h = HMAC::new(Type::MD5, &*test.0); - let _ = h.write_all(&*test.1); - let _ = h.finish(); - let res = h.finish(); - let null = hmac(Type::MD5, &*test.0, &[]); + let mut h = HMAC::new(Type::MD5, &*test.0).unwrap(); + h.write_all(&*test.1).unwrap(); + h.finish().unwrap(); + let res = h.finish().unwrap(); + let null = hmac(Type::MD5, &*test.0, &[]).unwrap(); assert_eq!(res, null); } @@ -307,26 +299,26 @@ mod tests { .to_vec(), "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())]; let p = tests[0].0.len() / 2; - let h0 = HMAC::new(Type::MD5, &*tests[0].0); + let h0 = HMAC::new(Type::MD5, &*tests[0].0).unwrap(); println!("Clone a new hmac"); let mut h1 = h0.clone(); - let _ = h1.write_all(&tests[0].1[..p]); + h1.write_all(&tests[0].1[..p]).unwrap(); { println!("Clone an updated hmac"); let mut h2 = h1.clone(); - let _ = h2.write_all(&tests[0].1[p..]); - let res = h2.finish(); + h2.write_all(&tests[0].1[p..]).unwrap(); + let res = h2.finish().unwrap(); assert_eq!(res, tests[0].2); } - let _ = h1.write_all(&tests[0].1[p..]); - let res = h1.finish(); + h1.write_all(&tests[0].1[p..]).unwrap(); + let res = h1.finish().unwrap(); assert_eq!(res, tests[0].2); println!("Clone a finished hmac"); let mut h3 = h1.clone(); - let _ = h3.write_all(&*tests[1].1); - let res = h3.finish(); + h3.write_all(&*tests[1].1).unwrap(); + let res = h3.finish().unwrap(); assert_eq!(res, tests[1].2); } @@ -373,7 +365,7 @@ mod tests { .to_vec(), "e8e99d0f45237d786d6bbaa7965c7808bbff1a91".from_hex().unwrap())]; - let mut h = HMAC::new(SHA1, &*tests[0].0); + let mut h = HMAC::new(SHA1, &*tests[0].0).unwrap(); for i in 0..100usize { let test = &tests[i % 2]; test_hmac_recycle(&mut h, test); @@ -399,11 +391,11 @@ mod tests { .to_vec())]; for (&(ref key, ref data), res) in tests.iter().zip(results.iter()) { - assert_eq!(hmac(ty, &**key, &**data), *res); + assert_eq!(hmac(ty, &**key, &**data).unwrap(), *res); } // recycle test - let mut h = HMAC::new(ty, &*tests[5].0); + let mut h = HMAC::new(ty, &*tests[5].0).unwrap(); for i in 0..100usize { let test = &tests[4 + i % 2]; let tup = (test.0.clone(), test.1.clone(), results[4 + i % 2].clone()); diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs index 5b891ce7..873f9d47 100644 --- a/openssl/src/crypto/mod.rs +++ b/openssl/src/crypto/mod.rs @@ -14,8 +14,6 @@ // limitations under the License. // -use nid::Nid; - pub mod hash; pub mod hmac; pub mod pkcs5; @@ -28,7 +26,3 @@ pub mod dsa; mod util; mod symm_internal; - -trait HashTypeInternals { - fn as_nid(&self) -> Nid; -} diff --git a/openssl/src/crypto/pkcs5.rs b/openssl/src/crypto/pkcs5.rs index 0ba005cc..e23909d1 100644 --- a/openssl/src/crypto/pkcs5.rs +++ b/openssl/src/crypto/pkcs5.rs @@ -1,10 +1,12 @@ use libc::c_int; -use std::ptr::null; +use std::ptr; +use ffi; +use HashTypeInternals; use crypto::symm_internal::evpc; use crypto::hash; use crypto::symm; -use ffi; +use error::ErrorStack; #[derive(Clone, Eq, PartialEq, Hash, Debug)] pub struct KeyIvPair { @@ -27,7 +29,7 @@ pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type, data: &[u8], salt: Option<&[u8]>, count: u32) - -> KeyIvPair { + -> Result { unsafe { @@ -36,30 +38,40 @@ pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type, assert_eq!(salt.len(), ffi::PKCS5_SALT_LEN as usize); salt.as_ptr() } - None => null(), + None => ptr::null(), }; ffi::init(); - let (evp, keylen, _) = evpc(typ); + let (evp, _, _) = evpc(typ); let message_digest = message_digest_type.evp_md(); - let mut key = vec![0; keylen as usize]; - let mut iv = vec![0; keylen as usize]; + let len = ffi::EVP_BytesToKey(evp, + message_digest, + salt_ptr, + data.as_ptr(), + data.len() as c_int, + count as c_int, + ptr::null_mut(), + ptr::null_mut()); + if len == 0 { + return Err(ErrorStack::get()); + } + let mut key = vec![0; len as usize]; + let mut iv = vec![0; len as usize]; - let ret: c_int = ffi::EVP_BytesToKey(evp, - message_digest, - salt_ptr, - data.as_ptr(), - data.len() as c_int, - count as c_int, - key.as_mut_ptr(), - iv.as_mut_ptr()); - assert!(ret == keylen as c_int); + try_ssl!(ffi::EVP_BytesToKey(evp, + message_digest, + salt_ptr, + data.as_ptr(), + data.len() as c_int, + count as c_int, + key.as_mut_ptr(), + iv.as_mut_ptr())); - KeyIvPair { key: key, iv: iv } + Ok(KeyIvPair { key: key, iv: iv }) } } @@ -257,7 +269,7 @@ mod tests { hash::Type::SHA1, &data, Some(&salt), - 1), + 1).unwrap(), super::KeyIvPair { key: expected_key, iv: expected_iv, diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 9a3e140a..2a928b23 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -4,7 +4,7 @@ use std::mem; use std::ptr; use bio::{MemBio, MemBioSlice}; -use crypto::HashTypeInternals; +use HashTypeInternals; use crypto::hash; use crypto::hash::Type as HashType; use ffi; diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 73239731..c9433b10 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -6,7 +6,7 @@ use libc::{c_int, c_void, c_char}; use bn::{BigNum, BigNumRef}; use bio::{MemBio, MemBioSlice}; use error::ErrorStack; -use crypto::HashTypeInternals; +use HashTypeInternals; use crypto::hash; use crypto::util::{CallbackState, invoke_passwd_cb}; @@ -262,9 +262,9 @@ mod test { let key = include_bytes!("../../test/rsa.pem"); let private_key = RSA::private_key_from_pem(key).unwrap(); - let mut sha = Hasher::new(Type::SHA256); + let mut sha = Hasher::new(Type::SHA256).unwrap(); sha.write_all(&signing_input_rs256()).unwrap(); - let digest = sha.finish(); + let digest = sha.finish().unwrap(); let result = private_key.sign(Type::SHA256, &digest).unwrap(); @@ -276,9 +276,9 @@ mod test { let key = include_bytes!("../../test/rsa.pem.pub"); let public_key = RSA::public_key_from_pem(key).unwrap(); - let mut sha = Hasher::new(Type::SHA256); + let mut sha = Hasher::new(Type::SHA256).unwrap(); sha.write_all(&signing_input_rs256()).unwrap(); - let digest = sha.finish(); + let digest = sha.finish().unwrap(); let result = public_key.verify(Type::SHA256, &digest, &signature_rs256()).unwrap(); diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 4cd76613..8dc73dde 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -14,6 +14,8 @@ extern crate rustc_serialize as serialize; #[cfg(test)] extern crate net2; +use nid::Nid; + mod macros; pub mod asn1; @@ -26,3 +28,8 @@ pub mod nid; pub mod ssl; pub mod version; pub mod x509; + +trait HashTypeInternals { + fn as_nid(&self) -> Nid; + fn evp_md(&self) -> *const ffi::EVP_MD; +} diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 82448212..22182d32 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -1,7 +1,5 @@ -use libc::{c_char, c_int, c_long, c_ulong, c_uint, c_void}; -use std::cmp::Ordering; +use libc::{c_char, c_int, c_long, c_ulong, c_void}; use std::ffi::CString; -use std::iter::repeat; use std::mem; use std::ptr; use std::ops::Deref; @@ -11,6 +9,7 @@ use std::slice; use std::collections::HashMap; use std::marker::PhantomData; +use HashTypeInternals; use asn1::Asn1Time; use bio::{MemBio, MemBioSlice}; use crypto::hash; @@ -434,28 +433,14 @@ impl<'a> X509Ref<'a> { } /// Returns certificate fingerprint calculated using provided hash - pub fn fingerprint(&self, hash_type: hash::Type) -> Option> { - let evp = hash_type.evp_md(); - let len = hash_type.md_len(); - let v: Vec = repeat(0).take(len as usize).collect(); - let act_len: c_uint = 0; - let res = unsafe { - ffi::X509_digest(self.0, - evp, - mem::transmute(v.as_ptr()), - mem::transmute(&act_len)) - }; - - match res { - 0 => None, - _ => { - let act_len = act_len as usize; - match len.cmp(&act_len) { - Ordering::Greater => None, - Ordering::Equal => Some(v), - Ordering::Less => panic!("Fingerprint buffer was corrupted!"), - } - } + pub fn fingerprint(&self, hash_type: hash::Type) -> Result, ErrorStack> { + unsafe { + let evp = hash_type.evp_md(); + let mut len = ffi::EVP_MAX_MD_SIZE; + let mut buf = vec![0u8; len as usize]; + try_ssl!(ffi::X509_digest(self.0, evp, buf.as_mut_ptr() as *mut _, &mut len)); + buf.truncate(len as usize); + Ok(buf) } } From b56908a3924f68c86ba4a5686c670182ef12c6e4 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 17:48:18 -0700 Subject: [PATCH 57/96] Take a c_ulong directly in BN construction Closes #416 --- openssl/src/bn/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openssl/src/bn/mod.rs b/openssl/src/bn/mod.rs index 3a1efb4a..254e674e 100644 --- a/openssl/src/bn/mod.rs +++ b/openssl/src/bn/mod.rs @@ -584,9 +584,9 @@ impl BigNum { } /// Creates a new `BigNum` with the given value. - pub fn new_from(n: u64) -> Result { + pub fn new_from(n: c_ulong) -> Result { BigNum::new().and_then(|v| unsafe { - try_ssl!(ffi::BN_set_word(v.raw(), n as c_ulong)); + try_ssl!(ffi::BN_set_word(v.raw(), n)); Ok(v) }) } From 6091c674c99fb80baef79647d8e131064a4887a0 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 17:52:13 -0700 Subject: [PATCH 58/96] Fix bn tests on 32 bit --- openssl/src/bn/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openssl/src/bn/mod.rs b/openssl/src/bn/mod.rs index 254e674e..a933157c 100644 --- a/openssl/src/bn/mod.rs +++ b/openssl/src/bn/mod.rs @@ -1006,7 +1006,7 @@ mod tests { #[test] fn test_to_from_slice() { - let v0 = BigNum::new_from(10203004_u64).unwrap(); + let v0 = BigNum::new_from(10203004).unwrap(); let vec = v0.to_vec(); let v1 = BigNum::new_from_slice(&vec).unwrap(); @@ -1015,7 +1015,7 @@ mod tests { #[test] fn test_negation() { - let a = BigNum::new_from(909829283_u64).unwrap(); + let a = BigNum::new_from(909829283).unwrap(); assert!(!a.is_negative()); assert!((-a).is_negative()); @@ -1024,7 +1024,7 @@ mod tests { #[test] fn test_prime_numbers() { - let a = BigNum::new_from(19029017_u64).unwrap(); + let a = BigNum::new_from(19029017).unwrap(); let p = BigNum::checked_generate_prime(128, true, None, Some(&a)).unwrap(); assert!(p.is_prime(100).unwrap()); From 7515272692ea30ee320667563027f75508f1dc60 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 18:03:13 -0700 Subject: [PATCH 59/96] Fix RSA::verify It never returns -1 - all errors are indicated by 0 --- openssl/src/crypto/rsa.rs | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index c9433b10..3410239f 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -144,27 +144,26 @@ impl RSA { unsafe { try_ssl!(ffi::RSA_sign(hash.as_nid() as c_int, - message.as_ptr(), - message.len() as u32, - sig.as_mut_ptr(), - &mut sig_len, - self.0)); + message.as_ptr(), + message.len() as u32, + sig.as_mut_ptr(), + &mut sig_len, + self.0)); assert!(sig_len == k_len); Ok(sig) } } - pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result { + pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result<(), ErrorStack> { unsafe { - let result = ffi::RSA_verify(hash.as_nid() as c_int, - message.as_ptr(), - message.len() as u32, - sig.as_ptr(), - sig.len() as u32, - self.0); - try_ssl_if!(result == -1); - Ok(result == 1) + try_ssl!(ffi::RSA_verify(hash.as_nid() as c_int, + message.as_ptr(), + message.len() as u32, + sig.as_ptr(), + sig.len() as u32, + self.0)); } + Ok(()) } pub fn as_ptr(&self) -> *mut ffi::RSA { @@ -280,9 +279,7 @@ mod test { sha.write_all(&signing_input_rs256()).unwrap(); let digest = sha.finish().unwrap(); - let result = public_key.verify(Type::SHA256, &digest, &signature_rs256()).unwrap(); - - assert!(result); + assert!(public_key.verify(Type::SHA256, &digest, &signature_rs256()).is_ok()); } #[test] From 7855f428aa48fcb6f4e8ad4c452783df88d20935 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 20:38:46 -0700 Subject: [PATCH 60/96] PKey reform This deletes the vast majority of PKey's API, since it was weirdly tied to RSA and super broken. --- openssl-sys/src/lib.rs | 4 +- openssl/src/crypto/pkey.rs | 778 ++----------------------------------- openssl/src/x509/mod.rs | 26 +- openssl/src/x509/tests.rs | 2 + 4 files changed, 41 insertions(+), 769 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 6951a7db..b141fa9d 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -752,9 +752,9 @@ extern "C" { pub fn PEM_read_bio_X509_REQ(bio: *mut BIO, out: *mut *mut X509_REQ, callback: Option, user_data: *mut c_void) -> *mut X509_REQ; pub fn PEM_read_bio_PrivateKey(bio: *mut BIO, out: *mut *mut EVP_PKEY, callback: Option, - user_data: *mut c_void) -> *mut X509; + user_data: *mut c_void) -> *mut EVP_PKEY; pub fn PEM_read_bio_PUBKEY(bio: *mut BIO, out: *mut *mut EVP_PKEY, callback: Option, - user_data: *mut c_void) -> *mut X509; + user_data: *mut c_void) -> *mut EVP_PKEY; pub fn PEM_read_bio_RSAPrivateKey(bio: *mut BIO, rsa: *mut *mut RSA, callback: Option, user_data: *mut c_void) -> *mut RSA; pub fn PEM_read_bio_RSA_PUBKEY(bio: *mut BIO, rsa: *mut *mut RSA, callback: Option, user_data: *mut c_void) -> *mut RSA; diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 2a928b23..501ffa37 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,91 +1,41 @@ -use libc::{c_int, c_uint, c_ulong, c_void, c_char}; -use std::iter::repeat; -use std::mem; +use libc::{c_void, c_char}; use std::ptr; use bio::{MemBio, MemBioSlice}; -use HashTypeInternals; -use crypto::hash; -use crypto::hash::Type as HashType; use ffi; use crypto::rsa::RSA; use error::ErrorStack; use crypto::util::{CallbackState, invoke_passwd_cb}; -#[derive(Copy, Clone)] -pub enum Parts { - Neither, - Public, - Both, -} - -/// Represents a role an asymmetric key might be appropriate for. -#[derive(Copy, Clone)] -pub enum Role { - Encrypt, - Decrypt, - Sign, - Verify, -} - -/// Type of encryption padding to use. -#[derive(Copy, Clone)] -pub enum EncryptionPadding { - OAEP, - PKCS1v15, -} - -fn openssl_padding_code(padding: EncryptionPadding) -> c_int { - match padding { - EncryptionPadding::OAEP => 4, - EncryptionPadding::PKCS1v15 => 1, - } -} - -pub struct PKey { - evp: *mut ffi::EVP_PKEY, - parts: Parts, -} +pub struct PKey(*mut ffi::EVP_PKEY); unsafe impl Send for PKey {} unsafe impl Sync for PKey {} /// Represents a public key, optionally with a private key attached. impl PKey { - pub fn new() -> PKey { + pub fn new() -> Result { + ffi::init(); unsafe { - ffi::init(); - - PKey { - evp: ffi::EVP_PKEY_new(), - parts: Parts::Neither, - } + let evp = try_ssl_null!(ffi::EVP_PKEY_new()); + Ok(PKey::from_handle(evp)) } } - pub unsafe fn from_handle(handle: *mut ffi::EVP_PKEY, parts: Parts) -> PKey { - ffi::init(); - assert!(!handle.is_null()); - - PKey { - evp: handle, - parts: parts, - } + pub unsafe fn from_handle(handle: *mut ffi::EVP_PKEY) -> PKey { + PKey(handle) } /// Reads private key from PEM, takes ownership of handle pub fn private_key_from_pem(buf: &[u8]) -> Result { + ffi::init(); let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut())); - - Ok(PKey { - evp: evp as *mut ffi::EVP_PKEY, - parts: Parts::Both, - }) + Ok(PKey::from_handle(evp)) } } @@ -97,6 +47,7 @@ impl PKey { pub fn private_key_from_pem_cb(buf: &[u8], pass_cb: F) -> Result where F: FnOnce(&mut [c_char]) -> usize { + ffi::init(); let mut cb = CallbackState::new(pass_cb); let mem_bio = try!(MemBioSlice::new(buf)); unsafe { @@ -104,170 +55,49 @@ impl PKey { ptr::null_mut(), Some(invoke_passwd_cb::), &mut cb as *mut _ as *mut c_void)); - - Ok(PKey { - evp: evp as *mut ffi::EVP_PKEY, - parts: Parts::Both, - }) + Ok(PKey::from_handle(evp)) } } /// Reads public key from PEM, takes ownership of handle pub fn public_key_from_pem(buf: &[u8]) -> Result { + ffi::init(); let mem_bio = try!(MemBioSlice::new(buf)); unsafe { let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut())); - Ok(PKey { - evp: evp as *mut ffi::EVP_PKEY, - parts: Parts::Public, - }) - } - } - - /// Reads an RSA private key from PEM, takes ownership of handle - pub fn private_rsa_key_from_pem(buf: &[u8]) -> Result { - let rsa = try!(RSA::private_key_from_pem(buf)); - unsafe { - let evp = try_ssl_null!(ffi::EVP_PKEY_new()); - if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 { - return Err(ErrorStack::get()); - } - - Ok(PKey { - evp: evp, - parts: Parts::Public, - }) - } - } - - /// Reads an RSA public key from PEM, takes ownership of handle - pub fn public_rsa_key_from_pem(buf: &[u8]) -> Result { - let rsa = try!(RSA::public_key_from_pem(buf)); - unsafe { - let evp = try_ssl_null!(ffi::EVP_PKEY_new()); - if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 { - return Err(ErrorStack::get()); - } - - Ok(PKey { - evp: evp, - parts: Parts::Public, - }) - } - } - - fn _tostr(&self, f: unsafe extern "C" fn(*mut ffi::RSA, *const *mut u8) -> c_int) -> Vec { - unsafe { - let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); - let len = f(rsa, ptr::null()); - if len < 0 as c_int { - return vec![]; - } - let mut s = repeat(0u8).take(len as usize).collect::>(); - - let r = f(rsa, &s.as_mut_ptr()); - ffi::RSA_free(rsa); - - s.truncate(r as usize); - s - } - } - - fn _fromstr(&mut self, - s: &[u8], - f: unsafe extern "C" fn(*const *mut ffi::RSA, *const *const u8, c_uint) - -> *mut ffi::RSA) - -> bool { - unsafe { - let rsa = ptr::null_mut(); - f(&rsa, &s.as_ptr(), s.len() as c_uint); - if !rsa.is_null() { - ffi::EVP_PKEY_set1_RSA(self.evp, rsa) == 1 - } else { - false - } - } - } - - pub fn gen(&mut self, keysz: usize) { - unsafe { - let rsa = ffi::RSA_generate_key(keysz as c_int, - 65537 as c_ulong, - ptr::null(), - ptr::null()); - - // XXX: 6 == NID_rsaEncryption - ffi::EVP_PKEY_assign(self.evp, 6 as c_int, mem::transmute(rsa)); - - self.parts = Parts::Both; + Ok(PKey::from_handle(evp)) } } /// assign RSA key to this pkey - pub fn set_rsa(&mut self, rsa: &RSA) { + pub fn set_rsa(&mut self, rsa: &RSA) -> Result<(), ErrorStack> { unsafe { // this needs to be a reference as the set1_RSA ups the reference count let rsa_ptr = rsa.as_ptr(); - if ffi::EVP_PKEY_set1_RSA(self.evp, rsa_ptr) == 1 { - if rsa.has_e() && rsa.has_n() { - self.parts = Parts::Public; - } - } + try_ssl!(ffi::EVP_PKEY_set1_RSA(self.0, rsa_ptr)); + Ok(()) } } - /// get a reference to the interal RSA key for direct access to the key components - pub fn get_rsa(&self) -> RSA { + /// Get a reference to the interal RSA key for direct access to the key components + pub fn get_rsa(&self) -> Result { unsafe { - let evp_pkey: *mut ffi::EVP_PKEY = self.evp; + let rsa = try_ssl_null!(ffi::EVP_PKEY_get1_RSA(self.0)); // this is safe as the ffi increments a reference counter to the internal key - RSA::from_raw(ffi::EVP_PKEY_get1_RSA(evp_pkey)) - } - } - - /** - * Returns a DER serialized form of the public key, suitable for load_pub(). - */ - pub fn save_pub(&self) -> Vec { - self._tostr(ffi::i2d_RSA_PUBKEY) - } - - /** - * Loads a DER serialized form of the public key, as produced by save_pub(). - */ - pub fn load_pub(&mut self, s: &[u8]) { - if self._fromstr(s, ffi::d2i_RSA_PUBKEY) { - self.parts = Parts::Public; - } - } - - /** - * Returns a serialized form of the public and private keys, suitable for - * load_priv(). - */ - pub fn save_priv(&self) -> Vec { - self._tostr(ffi::i2d_RSAPrivateKey) - } - /** - * Loads a serialized form of the public and private keys, as produced by - * save_priv(). - */ - pub fn load_priv(&mut self, s: &[u8]) { - if self._fromstr(s, ffi::d2i_RSAPrivateKey) { - self.parts = Parts::Both; + Ok(RSA::from_raw(rsa)) } } /// Stores private key as a PEM // FIXME: also add password and encryption - pub fn write_pem(&self) -> Result, ErrorStack> { + pub fn private_key_to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.handle(), - self.evp, + self.0, ptr::null(), ptr::null_mut(), -1, @@ -279,392 +109,31 @@ impl PKey { } /// Stores public key as a PEM - pub fn write_pub_pem(&self) -> Result, ErrorStack> { + pub fn public_key_to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); - unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.handle(), self.evp)) } + unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.handle(), self.0)) } Ok(mem_bio.get_buf().to_owned()) } - /** - * Returns the size of the public key modulus. - */ - pub fn size(&self) -> usize { - unsafe { - let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); - if rsa.is_null() { - 0 - } else { - ffi::RSA_size(rsa) as usize - } - } - } - - /** - * Returns whether this pkey object can perform the specified role. - */ - pub fn can(&self, r: Role) -> bool { - match r { - Role::Encrypt => { - match self.parts { - Parts::Neither => false, - _ => true, - } - } - Role::Verify => { - match self.parts { - Parts::Neither => false, - _ => true, - } - } - Role::Decrypt => { - match self.parts { - Parts::Both => true, - _ => false, - } - } - Role::Sign => { - match self.parts { - Parts::Both => true, - _ => false, - } - } - } - } - - /** - * Returns the maximum amount of data that can be encrypted by an encrypt() - * call. - */ - pub fn max_data(&self) -> usize { - unsafe { - let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); - if rsa.is_null() { - return 0; - } - let len = ffi::RSA_size(rsa); - - // 41 comes from RSA_public_encrypt(3) for OAEP - len as usize - 41 - } - } - - pub fn private_encrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec { - unsafe { - let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); - if rsa.is_null() { - panic!("Could not get RSA key for encryption"); - } - let len = ffi::RSA_size(rsa); - - assert!(s.len() < self.max_data()); - - let mut r = repeat(0u8).take(len as usize + 1).collect::>(); - - let rv = ffi::RSA_private_encrypt(s.len() as c_int, - s.as_ptr(), - r.as_mut_ptr(), - rsa, - openssl_padding_code(padding)); - - if rv < 0 as c_int { - // println!("{:?}", ErrorStack::get()); - vec![] - } else { - r.truncate(rv as usize); - r - } - } - } - - pub fn public_encrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec { - unsafe { - let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); - if rsa.is_null() { - panic!("Could not get RSA key for encryption"); - } - let len = ffi::RSA_size(rsa); - - assert!(s.len() < self.max_data()); - - let mut r = repeat(0u8).take(len as usize + 1).collect::>(); - - let rv = ffi::RSA_public_encrypt(s.len() as c_int, - s.as_ptr(), - r.as_mut_ptr(), - rsa, - openssl_padding_code(padding)); - - if rv < 0 as c_int { - vec![] - } else { - r.truncate(rv as usize); - r - } - } - } - - pub fn private_decrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec { - unsafe { - let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); - if rsa.is_null() { - panic!("Could not get RSA key for decryption"); - } - let len = ffi::RSA_size(rsa); - - assert_eq!(s.len() as c_int, ffi::RSA_size(rsa)); - - let mut r = repeat(0u8).take(len as usize + 1).collect::>(); - - let rv = ffi::RSA_private_decrypt(s.len() as c_int, - s.as_ptr(), - r.as_mut_ptr(), - rsa, - openssl_padding_code(padding)); - - if rv < 0 as c_int { - vec![] - } else { - r.truncate(rv as usize); - r - } - } - } - - pub fn public_decrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec { - unsafe { - let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); - if rsa.is_null() { - panic!("Could not get RSA key for decryption"); - } - let len = ffi::RSA_size(rsa); - - assert_eq!(s.len() as c_int, ffi::RSA_size(rsa)); - - let mut r = repeat(0u8).take(len as usize + 1).collect::>(); - - let rv = ffi::RSA_public_decrypt(s.len() as c_int, - s.as_ptr(), - r.as_mut_ptr(), - rsa, - openssl_padding_code(padding)); - - if rv < 0 as c_int { - vec![] - } else { - r.truncate(rv as usize); - r - } - } - } - - /** - * Encrypts data with the public key, using OAEP padding, returning the encrypted data. The - * supplied data must not be larger than max_data(). - */ - pub fn encrypt(&self, s: &[u8]) -> Vec { - self.public_encrypt_with_padding(s, EncryptionPadding::OAEP) - } - - /** - * Encrypts data with the public key, using provided padding, returning the encrypted data. The - * supplied data must not be larger than max_data(). - */ - pub fn encrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec { - self.public_encrypt_with_padding(s, padding) - } - - /** - * Encrypts data with the public key, using OAEP padding, returning the encrypted data. The - * supplied data must not be larger than max_data(). - */ - pub fn public_encrypt(&self, s: &[u8]) -> Vec { - self.public_encrypt_with_padding(s, EncryptionPadding::OAEP) - } - - /** - * Decrypts data with the public key, using PKCS1v15 padding, returning the decrypted data. - */ - pub fn public_decrypt(&self, s: &[u8]) -> Vec { - self.public_decrypt_with_padding(s, EncryptionPadding::PKCS1v15) - } - - /** - * Decrypts data with the private key, expecting OAEP padding, returning the decrypted data. - */ - pub fn decrypt(&self, s: &[u8]) -> Vec { - self.private_decrypt_with_padding(s, EncryptionPadding::OAEP) - } - - /** - * Decrypts data with the private key, using provided padding, returning the encrypted data. The - * supplied data must not be larger than max_data(). - */ - pub fn decrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec { - self.private_decrypt_with_padding(s, padding) - } - - /** - * Decrypts data with the private key, expecting OAEP padding, returning the decrypted data. - */ - pub fn private_decrypt(&self, s: &[u8]) -> Vec { - self.private_decrypt_with_padding(s, EncryptionPadding::OAEP) - } - - /** - * Encrypts data with the private key, using PKCS1v15 padding, returning the encrypted data. The - * supplied data must not be larger than max_data(). - */ - pub fn private_encrypt(&self, s: &[u8]) -> Vec { - self.private_encrypt_with_padding(s, EncryptionPadding::PKCS1v15) - } - - /** - * Signs data, using OpenSSL's default scheme and adding sha256 ASN.1 information to the - * signature. - * The bytes to sign must be the result of a sha256 hashing; - * returns the signature. - */ - pub fn sign(&self, s: &[u8]) -> Vec { - self.sign_with_hash(s, HashType::SHA256) - } - - /** - * Verifies a signature s (using OpenSSL's default scheme and sha256) on the SHA256 hash of a - * message. - * Returns true if the signature is valid, and false otherwise. - */ - pub fn verify(&self, h: &[u8], s: &[u8]) -> bool { - self.verify_with_hash(h, s, HashType::SHA256) - } - - /** - * Signs data, using OpenSSL's default scheme and add ASN.1 information for the given hash type to the - * signature. - * The bytes to sign must be the result of this type of hashing; - * returns the signature. - */ - pub fn sign_with_hash(&self, s: &[u8], hash: hash::Type) -> Vec { - unsafe { - let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); - if rsa.is_null() { - panic!("Could not get RSA key for signing"); - } - let len = ffi::RSA_size(rsa); - let mut r = repeat(0u8).take(len as usize + 1).collect::>(); - - let mut len = 0; - let rv = ffi::RSA_sign(hash.as_nid() as c_int, - s.as_ptr(), - s.len() as c_uint, - r.as_mut_ptr(), - &mut len, - rsa); - - if rv < 0 as c_int { - vec![] - } else { - r.truncate(len as usize); - r - } - } - } - - pub fn verify_with_hash(&self, h: &[u8], s: &[u8], hash: hash::Type) -> bool { - unsafe { - let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); - if rsa.is_null() { - panic!("Could not get RSA key for verification"); - } - - let rv = ffi::RSA_verify(hash.as_nid() as c_int, - h.as_ptr(), - h.len() as c_uint, - s.as_ptr(), - s.len() as c_uint, - rsa); - - rv == 1 as c_int - } - } - pub fn handle(&self) -> *mut ffi::EVP_PKEY { - return self.evp; + return self.0; } pub fn public_eq(&self, other: &PKey) -> bool { - unsafe { ffi::EVP_PKEY_cmp(self.evp, other.evp) == 1 } + unsafe { ffi::EVP_PKEY_cmp(self.0, other.0) == 1 } } } impl Drop for PKey { fn drop(&mut self) { unsafe { - ffi::EVP_PKEY_free(self.evp); + ffi::EVP_PKEY_free(self.0); } } } -impl Clone for PKey { - fn clone(&self) -> Self { - let mut pkey = unsafe { PKey::from_handle(ffi::EVP_PKEY_new(), self.parts) }; - - // copy by encoding to DER and back - match self.parts { - Parts::Public => { - pkey.load_pub(&self.save_pub()[..]); - } - Parts::Both => { - pkey.load_priv(&self.save_priv()[..]); - } - Parts::Neither => {} - } - pkey - } -} - #[cfg(test)] mod tests { - use crypto::hash::Type::{MD5, SHA1}; - use crypto::rsa::RSA; - - #[test] - fn test_gen_pub() { - let mut k0 = super::PKey::new(); - let mut k1 = super::PKey::new(); - k0.gen(512); - k1.load_pub(&k0.save_pub()); - assert_eq!(k0.save_pub(), k1.save_pub()); - assert!(k0.public_eq(&k1)); - assert_eq!(k0.size(), k1.size()); - assert!(k0.can(super::Role::Encrypt)); - assert!(k0.can(super::Role::Decrypt)); - assert!(k0.can(super::Role::Verify)); - assert!(k0.can(super::Role::Sign)); - assert!(k1.can(super::Role::Encrypt)); - assert!(!k1.can(super::Role::Decrypt)); - assert!(k1.can(super::Role::Verify)); - assert!(!k1.can(super::Role::Sign)); - } - - #[test] - fn test_gen_priv() { - let mut k0 = super::PKey::new(); - let mut k1 = super::PKey::new(); - k0.gen(512); - k1.load_priv(&k0.save_priv()); - assert_eq!(k0.save_priv(), k1.save_priv()); - assert!(k0.public_eq(&k1)); - assert_eq!(k0.size(), k1.size()); - assert!(k0.can(super::Role::Encrypt)); - assert!(k0.can(super::Role::Decrypt)); - assert!(k0.can(super::Role::Verify)); - assert!(k0.can(super::Role::Sign)); - assert!(k1.can(super::Role::Encrypt)); - assert!(k1.can(super::Role::Decrypt)); - assert!(k1.can(super::Role::Verify)); - assert!(k1.can(super::Role::Sign)); - } - #[test] fn test_private_key_from_pem() { let key = include_bytes!("../../test/key.pem"); @@ -677,204 +146,17 @@ mod tests { super::PKey::public_key_from_pem(key).unwrap(); } - #[test] - fn test_private_rsa_key_from_pem() { - let key = include_bytes!("../../test/key.pem"); - super::PKey::private_rsa_key_from_pem(key).unwrap(); - } - - #[test] - fn test_public_rsa_key_from_pem() { - let key = include_bytes!("../../test/key.pem.pub"); - super::PKey::public_rsa_key_from_pem(key).unwrap(); - } - - #[test] - fn test_private_encrypt() { - let mut k0 = super::PKey::new(); - let mut k1 = super::PKey::new(); - let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8]; - k0.gen(512); - k1.load_pub(&k0.save_pub()); - let emsg = k0.private_encrypt(&msg); - let dmsg = k1.public_decrypt(&emsg); - assert!(msg == dmsg); - } - - #[test] - fn test_public_encrypt() { - let mut k0 = super::PKey::new(); - let mut k1 = super::PKey::new(); - let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8]; - k0.gen(512); - k1.load_pub(&k0.save_pub()); - let emsg = k1.public_encrypt(&msg); - let dmsg = k0.private_decrypt(&emsg); - assert!(msg == dmsg); - } - - #[test] - fn test_public_encrypt_pkcs() { - let mut k0 = super::PKey::new(); - let mut k1 = super::PKey::new(); - let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8]; - k0.gen(512); - k1.load_pub(&k0.save_pub()); - let emsg = k1.public_encrypt_with_padding(&msg, super::EncryptionPadding::PKCS1v15); - let dmsg = k0.private_decrypt_with_padding(&emsg, super::EncryptionPadding::PKCS1v15); - assert!(msg == dmsg); - } - - #[test] - fn test_sign() { - let mut k0 = super::PKey::new(); - let mut k1 = super::PKey::new(); - let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8]; - k0.gen(512); - k1.load_pub(&k0.save_pub()); - let sig = k0.sign(&msg); - let rv = k1.verify(&msg, &sig); - assert!(rv == true); - } - - #[test] - fn test_sign_hashes() { - let mut k0 = super::PKey::new(); - let mut k1 = super::PKey::new(); - let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8]; - k0.gen(512); - k1.load_pub(&k0.save_pub()); - - let sig = k0.sign_with_hash(&msg, MD5); - - assert!(k1.verify_with_hash(&msg, &sig, MD5)); - assert!(!k1.verify_with_hash(&msg, &sig, SHA1)); - } - - #[test] - fn test_eq() { - let mut k0 = super::PKey::new(); - let mut p0 = super::PKey::new(); - let mut k1 = super::PKey::new(); - let mut p1 = super::PKey::new(); - k0.gen(512); - k1.gen(512); - p0.load_pub(&k0.save_pub()); - p1.load_pub(&k1.save_pub()); - - assert!(k0.public_eq(&k0)); - assert!(k1.public_eq(&k1)); - assert!(p0.public_eq(&p0)); - assert!(p1.public_eq(&p1)); - assert!(k0.public_eq(&p0)); - assert!(k1.public_eq(&p1)); - - assert!(!k0.public_eq(&k1)); - assert!(!p0.public_eq(&p1)); - assert!(!k0.public_eq(&p1)); - assert!(!p0.public_eq(&k1)); - } - #[test] fn test_pem() { let key = include_bytes!("../../test/key.pem"); let key = super::PKey::private_key_from_pem(key).unwrap(); - let priv_key = key.write_pem().unwrap(); - let pub_key = key.write_pub_pem().unwrap(); + let priv_key = key.private_key_to_pem().unwrap(); + let pub_key = key.public_key_to_pem().unwrap(); // As a super-simple verification, just check that the buffers contain // the `PRIVATE KEY` or `PUBLIC KEY` strings. assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY")); assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY")); } - - #[test] - fn test_public_key_from_raw() { - let mut k0 = super::PKey::new(); - let mut k1 = super::PKey::new(); - let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8]; - - k0.gen(512); - let sig = k0.sign(&msg); - - let r0 = k0.get_rsa(); - let r1 = RSA::from_public_components(r0.n().to_owned().unwrap(), r0.e().to_owned().unwrap()).expect("r1"); - k1.set_rsa(&r1); - - assert!(k1.can(super::Role::Encrypt)); - assert!(!k1.can(super::Role::Decrypt)); - assert!(k1.can(super::Role::Verify)); - assert!(!k1.can(super::Role::Sign)); - - let rv = k1.verify(&msg, &sig); - assert!(rv == true); - } - - #[test] - #[should_panic(expected = "Could not get RSA key for encryption")] - fn test_nokey_encrypt() { - let mut pkey = super::PKey::new(); - pkey.load_pub(&[]); - pkey.encrypt(&[]); - } - - #[test] - #[should_panic(expected = "Could not get RSA key for decryption")] - fn test_nokey_decrypt() { - let mut pkey = super::PKey::new(); - pkey.load_priv(&[]); - pkey.decrypt(&[]); - } - - #[test] - #[should_panic(expected = "Could not get RSA key for signing")] - fn test_nokey_sign() { - let mut pkey = super::PKey::new(); - pkey.load_priv(&[]); - pkey.sign(&[]); - } - - #[test] - #[should_panic(expected = "Could not get RSA key for verification")] - fn test_nokey_verify() { - let mut pkey = super::PKey::new(); - pkey.load_pub(&[]); - pkey.verify(&[], &[]); - } - - #[test] - fn test_pkey_clone_creates_copy() { - let mut pkey = super::PKey::new(); - pkey.gen(512); - let rsa = pkey.get_rsa(); - let old_pkey_n = rsa.n(); - - let mut pkey2 = pkey.clone(); - pkey2.gen(512); - - assert!(old_pkey_n == rsa.n()); - } - - #[test] - fn test_pkey_clone_copies_private() { - let mut pkey = super::PKey::new(); - pkey.gen(512); - - let pkey2 = pkey.clone(); - - assert!(pkey.get_rsa().q() == pkey2.get_rsa().q()); - } - - #[test] - fn test_pkey_clone_copies_public() { - let mut pkey = super::PKey::new(); - pkey.gen(512); - let mut pub_key = super::PKey::new(); - pub_key.load_pub(&pkey.save_pub()[..]); - - let pub_key2 = pub_key.clone(); - - assert!(pub_key.get_rsa().n() == pub_key2.get_rsa().n()); - } } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 22182d32..fb9d466d 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -14,7 +14,7 @@ use asn1::Asn1Time; use bio::{MemBio, MemBioSlice}; use crypto::hash; use crypto::hash::Type as HashType; -use crypto::pkey::{PKey, Parts}; +use crypto::pkey::PKey; use crypto::rand::rand_bytes; use ffi; use ffi_extras; @@ -106,11 +106,12 @@ impl X509StoreContext { } #[allow(non_snake_case)] +// FIXME /// Generator of private key/certificate pairs /// /// # Example /// -/// ``` +/// ```ignore /// use openssl::crypto::hash::Type; /// use openssl::x509::X509Generator; /// use openssl::x509::extension::{Extension, KeyUsageOption}; @@ -124,7 +125,7 @@ impl X509StoreContext { /// /// let (cert, pkey) = gen.generate().unwrap(); /// let cert_pem = cert.write_pem().unwrap(); -/// let pkey_pem = pkey.write_pem().unwrap(); +/// let pkey_pem = pkey.private_key_to_pem().unwrap(); /// ``` pub struct X509Generator { bits: u32, @@ -297,17 +298,6 @@ impl X509Generator { ((res as c_ulong) >> 1) as c_long } - /// Generates a private key and a self-signed certificate and returns them - pub fn generate(&self) -> Result<(X509, PKey), ErrorStack> { - ffi::init(); - - let mut p_key = PKey::new(); - p_key.gen(self.bits as usize); - - let x509 = try!(self.sign(&p_key)); - Ok((x509, p_key)) - } - /// Sets the certificate public-key, then self-sign and return it /// Note: That the bit-length of the private key is used (set_bitlength is ignored) pub fn sign(&self, p_key: &PKey) -> Result { @@ -423,12 +413,10 @@ impl<'a> X509Ref<'a> { } } - pub fn public_key(&self) -> PKey { + pub fn public_key(&self) -> Result { unsafe { - let pkey = ffi::X509_get_pubkey(self.0); - assert!(!pkey.is_null()); - - PKey::from_handle(pkey, Parts::Public) + let pkey = try_ssl_null!(ffi::X509_get_pubkey(self.0)); + Ok(PKey::from_handle(pkey)) } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 167ca8cf..141e1fdb 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -24,6 +24,7 @@ fn get_generator() -> X509Generator { .add_extension(OtherStr("2.999.2".to_owned(), "ASN1:UTF8:example value".to_owned())) } +/* #[test] fn test_cert_gen() { let (cert, pkey) = get_generator().generate().unwrap(); @@ -72,6 +73,7 @@ fn test_req_gen() { // FIXME: check data in result to be correct, needs implementation // of X509_REQ getters } +*/ #[test] fn test_cert_loading() { From 4d3c6868e7a895b45ff6e8f97bd5c5ba026e84f9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 20:57:44 -0700 Subject: [PATCH 61/96] pkcs5 reform --- openssl/src/crypto/pkcs5.rs | 119 +++++++++++++----------------------- 1 file changed, 44 insertions(+), 75 deletions(-) diff --git a/openssl/src/crypto/pkcs5.rs b/openssl/src/crypto/pkcs5.rs index e23909d1..48e61a20 100644 --- a/openssl/src/crypto/pkcs5.rs +++ b/openssl/src/crypto/pkcs5.rs @@ -30,9 +30,7 @@ pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type, salt: Option<&[u8]>, count: u32) -> Result { - unsafe { - let salt_ptr = match salt { Some(salt) => { assert_eq!(salt.len(), ffi::PKCS5_SALT_LEN as usize); @@ -76,77 +74,47 @@ pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type, } /// Derives a key from a password and salt using the PBKDF2-HMAC-SHA1 algorithm. -pub fn pbkdf2_hmac_sha1(pass: &str, salt: &[u8], iter: usize, keylen: usize) -> Vec { +pub fn pbkdf2_hmac_sha1(pass: &[u8], + salt: &[u8], + iter: usize, + keylen: usize) + -> Result, ErrorStack> { unsafe { - assert!(iter >= 1); - assert!(keylen >= 1); - - let mut out = Vec::with_capacity(keylen); + let mut out = vec![0; keylen]; ffi::init(); - let r = ffi::PKCS5_PBKDF2_HMAC_SHA1(pass.as_ptr(), - pass.len() as c_int, - salt.as_ptr(), - salt.len() as c_int, - iter as c_int, - keylen as c_int, - out.as_mut_ptr()); - - if r != 1 { - panic!(); - } - - out.set_len(keylen); - - out + try_ssl!(ffi::PKCS5_PBKDF2_HMAC_SHA1(pass.as_ptr(), + pass.len() as c_int, + salt.as_ptr(), + salt.len() as c_int, + iter as c_int, + keylen as c_int, + out.as_mut_ptr())); + Ok(out) } } -/// Derives a key from a password and salt using the PBKDF2-HMAC-SHA256 algorithm. -#[cfg(feature = "pkcs5_pbkdf2_hmac")] -pub fn pbkdf2_hmac_sha256(pass: &str, salt: &[u8], iter: usize, keylen: usize) -> Vec { - pbkdf2_hmac_sha(pass, salt, iter, unsafe { ffi::EVP_sha256() }, keylen) -} - -/// Derives a key from a password and salt using the PBKDF2-HMAC-SHA512 algorithm. -#[cfg(feature = "pkcs5_pbkdf2_hmac")] -pub fn pbkdf2_hmac_sha512(pass: &str, salt: &[u8], iter: usize, keylen: usize) -> Vec { - pbkdf2_hmac_sha(pass, salt, iter, unsafe { ffi::EVP_sha512() }, keylen) -} - /// Derives a key from a password and salt using the PBKDF2-HMAC algorithm with a digest function. #[cfg(feature = "pkcs5_pbkdf2_hmac")] -fn pbkdf2_hmac_sha(pass: &str, +pub fn pbkdf2_hmac(pass: &[u8], salt: &[u8], iter: usize, - digest: *const ffi::EVP_MD, + hash: hash::Type, keylen: usize) - -> Vec { + -> Result, ErrorStack> { unsafe { - assert!(iter >= 1); - assert!(keylen >= 1); - - let mut out = Vec::with_capacity(keylen); - + let mut out = vec![0; keylen]; ffi::init(); - - let r = ffi::PKCS5_PBKDF2_HMAC(pass.as_ptr(), - pass.len() as c_int, - salt.as_ptr(), - salt.len() as c_int, - iter as c_int, - digest, - keylen as c_int, - out.as_mut_ptr()); - - if r != 1 { - panic!(); - } - - out.set_len(keylen); - - out + try_ssl!(ffi::PKCS5_PBKDF2_HMAC(pass.as_ptr(), + pass.len() as c_int, + salt.as_ptr(), + salt.len() as c_int, + iter as c_int, + hash.evp_md(), + keylen as c_int, + out.as_mut_ptr())); + Ok(out) } } @@ -159,36 +127,36 @@ mod tests { // http://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-06 #[test] fn test_pbkdf2_hmac_sha1() { - assert_eq!(super::pbkdf2_hmac_sha1("password", "salt".as_bytes(), 1, 20), + assert_eq!(super::pbkdf2_hmac_sha1(b"password", b"salt", 1, 20).unwrap(), vec![0x0c_u8, 0x60_u8, 0xc8_u8, 0x0f_u8, 0x96_u8, 0x1f_u8, 0x0e_u8, 0x71_u8, 0xf3_u8, 0xa9_u8, 0xb5_u8, 0x24_u8, 0xaf_u8, 0x60_u8, 0x12_u8, 0x06_u8, 0x2f_u8, 0xe0_u8, 0x37_u8, 0xa6_u8]); - assert_eq!(super::pbkdf2_hmac_sha1("password", "salt".as_bytes(), 2, 20), + assert_eq!(super::pbkdf2_hmac_sha1(b"password", b"salt", 2, 20).unwrap(), vec![0xea_u8, 0x6c_u8, 0x01_u8, 0x4d_u8, 0xc7_u8, 0x2d_u8, 0x6f_u8, 0x8c_u8, 0xcd_u8, 0x1e_u8, 0xd9_u8, 0x2a_u8, 0xce_u8, 0x1d_u8, 0x41_u8, 0xf0_u8, 0xd8_u8, 0xde_u8, 0x89_u8, 0x57_u8]); - assert_eq!(super::pbkdf2_hmac_sha1("password", "salt".as_bytes(), 4096, 20), + assert_eq!(super::pbkdf2_hmac_sha1(b"password", b"salt", 4096, 20).unwrap(), vec![0x4b_u8, 0x00_u8, 0x79_u8, 0x01_u8, 0xb7_u8, 0x65_u8, 0x48_u8, 0x9a_u8, 0xbe_u8, 0xad_u8, 0x49_u8, 0xd9_u8, 0x26_u8, 0xf7_u8, 0x21_u8, 0xd0_u8, 0x65_u8, 0xa4_u8, 0x29_u8, 0xc1_u8]); - assert_eq!(super::pbkdf2_hmac_sha1("password", "salt".as_bytes(), 16777216, 20), + assert_eq!(super::pbkdf2_hmac_sha1(b"password", b"salt", 16777216, 20).unwrap(), vec![0xee_u8, 0xfe_u8, 0x3d_u8, 0x61_u8, 0xcd_u8, 0x4d_u8, 0xa4_u8, 0xe4_u8, 0xe9_u8, 0x94_u8, 0x5b_u8, 0x3d_u8, 0x6b_u8, 0xa2_u8, 0x15_u8, 0x8c_u8, 0x26_u8, 0x34_u8, 0xe9_u8, 0x84_u8]); - assert_eq!(super::pbkdf2_hmac_sha1("passwordPASSWORDpassword", - "saltSALTsaltSALTsaltSALTsaltSALTsalt".as_bytes(), + assert_eq!(super::pbkdf2_hmac_sha1(b"passwordPASSWORDpassword", + b"saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, - 25), + 25).unwrap(), vec![0x3d_u8, 0x2e_u8, 0xec_u8, 0x4f_u8, 0xe4_u8, 0x1c_u8, 0x84_u8, 0x9b_u8, 0x80_u8, 0xc8_u8, 0xd8_u8, 0x36_u8, 0x62_u8, 0xc0_u8, 0xe4_u8, 0x4a_u8, 0x8b_u8, 0x29_u8, 0x1a_u8, 0x96_u8, 0x4c_u8, 0xf2_u8, 0xf0_u8, 0x70_u8, 0x38_u8]); - assert_eq!(super::pbkdf2_hmac_sha1("pass\x00word", "sa\x00lt".as_bytes(), 4096, 16), + assert_eq!(super::pbkdf2_hmac_sha1(b"pass\x00word", b"sa\x00lt", 4096, 16).unwrap(), vec![0x56_u8, 0xfa_u8, 0x6a_u8, 0xa7_u8, 0x55_u8, 0x48_u8, 0x09_u8, 0x9d_u8, 0xcc_u8, 0x37_u8, 0xd7_u8, 0xf0_u8, 0x34_u8, 0x25_u8, 0xe0_u8, 0xc3_u8]); } @@ -198,11 +166,11 @@ mod tests { #[test] #[cfg(feature = "pkcs5_pbkdf2_hmac")] fn test_pbkdf2_hmac_sha256() { - assert_eq!(super::pbkdf2_hmac_sha256("passwd", "salt".as_bytes(), 1, 16), + assert_eq!(super::pbkdf2_hmac(b"passwd", b"salt", 1, hash::Type::SHA256, 16).unwrap(), vec![0x55_u8, 0xac_u8, 0x04_u8, 0x6e_u8, 0x56_u8, 0xe3_u8, 0x08_u8, 0x9f_u8, 0xec_u8, 0x16_u8, 0x91_u8, 0xc2_u8, 0x25_u8, 0x44_u8, 0xb6_u8, 0x05_u8]); - assert_eq!(super::pbkdf2_hmac_sha256("Password", "NaCl".as_bytes(), 80000, 16), + assert_eq!(super::pbkdf2_hmac(b"Password", b"NaCl", 80000, hash::Type::SHA256, 16).unwrap(), vec![0x4d_u8, 0xdc_u8, 0xd8_u8, 0xf6_u8, 0x0b_u8, 0x98_u8, 0xbe_u8, 0x21_u8, 0x83_u8, 0x0c_u8, 0xee_u8, 0x5e_u8, 0xf2_u8, 0x27_u8, 0x01_u8, 0xf9_u8]); } @@ -212,7 +180,7 @@ mod tests { #[test] #[cfg(feature = "pkcs5_pbkdf2_hmac")] fn test_pbkdf2_hmac_sha512() { - assert_eq!(super::pbkdf2_hmac_sha512("password", "NaCL".as_bytes(), 1, 64), + assert_eq!(super::pbkdf2_hmac(b"password", b"NaCL", 1, hash::Type::SHA512, 64).unwrap(), vec![0x73_u8, 0xde_u8, 0xcf_u8, 0xa5_u8, 0x8a_u8, 0xa2_u8, 0xe8_u8, 0x4f_u8, 0x94_u8, 0x77_u8, 0x1a_u8, 0x75_u8, 0x73_u8, 0x6b_u8, 0xb8_u8, 0x8b_u8, 0xd3_u8, 0xc7_u8, 0xb3_u8, 0x82_u8, 0x70_u8, 0xcf_u8, 0xb5_u8, 0x0c_u8, @@ -222,7 +190,7 @@ mod tests { 0x60_u8, 0x60_u8, 0xa0_u8, 0x9f_u8, 0x76_u8, 0x41_u8, 0x5e_u8, 0x9f_u8, 0x71_u8, 0xea_u8, 0x47_u8, 0xf9_u8, 0xe9_u8, 0x06_u8, 0x43_u8, 0x06_u8]); - assert_eq!(super::pbkdf2_hmac_sha512("pass\0word", "sa\0lt".as_bytes(), 1, 64), + assert_eq!(super::pbkdf2_hmac(b"pass\0word", b"sa\0lt", 1, hash::Type::SHA512, 64).unwrap(), vec![0x71_u8, 0xa0_u8, 0xec_u8, 0x84_u8, 0x2a_u8, 0xbd_u8, 0x5c_u8, 0x67_u8, 0x8b_u8, 0xcf_u8, 0xd1_u8, 0x45_u8, 0xf0_u8, 0x9d_u8, 0x83_u8, 0x52_u8, 0x2f_u8, 0x93_u8, 0x36_u8, 0x15_u8, 0x60_u8, 0x56_u8, 0x3c_u8, 0x4d_u8, @@ -232,10 +200,11 @@ mod tests { 0xb2_u8, 0x0f_u8, 0x06_u8, 0xbc_u8, 0x53_u8, 0x5e_u8, 0x5a_u8, 0xb5_u8, 0x44_u8, 0x0d_u8, 0xf7_u8, 0xe8_u8, 0x78_u8, 0x29_u8, 0x6f_u8, 0xa7_u8]); - assert_eq!(super::pbkdf2_hmac_sha512("passwordPASSWORDpassword", - "salt\0\0\0".as_bytes(), - 50, - 64), + assert_eq!(super::pbkdf2_hmac(b"passwordPASSWORDpassword", + b"salt\0\0\0", + 50, + hash::Type::SHA512, + 64).unwrap(), vec![0x01_u8, 0x68_u8, 0x71_u8, 0xa4_u8, 0xc4_u8, 0xb7_u8, 0x5f_u8, 0x96_u8, 0x85_u8, 0x7f_u8, 0xd2_u8, 0xb9_u8, 0xf8_u8, 0xca_u8, 0x28_u8, 0x02_u8, 0x3b_u8, 0x30_u8, 0xee_u8, 0x2a_u8, 0x39_u8, 0xf5_u8, 0xad_u8, 0xca_u8, From a0a6c03d74a58aa199e06b50be865eda1bbc925f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 21:19:40 -0700 Subject: [PATCH 62/96] DH cleanup --- openssl/src/dh/mod.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index 6a5bd9c4..9058e8db 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -2,17 +2,15 @@ use ffi; use error::ErrorStack; use bio::MemBioSlice; use bn::BigNum; -use std::mem; use std::ptr; pub struct DH(*mut ffi::DH); impl DH { pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result { - let dh = try_ssl_null!(unsafe { ffi::DH_new_from_params(p.raw(), g.raw(), q.raw()) }); - mem::forget(p); - mem::forget(g); - mem::forget(q); + let dh = unsafe { + try_ssl_null!(ffi::DH_new_from_params(p.into_raw(), g.into_raw(), q.into_raw())) + }; Ok(DH(dh)) } @@ -47,19 +45,12 @@ impl DH { let DH(n) = *self; n } - - pub unsafe fn raw_ptr(&self) -> *const *mut ffi::DH { - let DH(ref n) = *self; - n - } } impl Drop for DH { fn drop(&mut self) { unsafe { - if !self.raw().is_null() { - ffi::DH_free(self.raw()) - } + ffi::DH_free(self.raw()) } } } From 79602b6af4eaad34c277ec6a6219efc514c1342e Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 21:34:58 -0700 Subject: [PATCH 63/96] get_error -> error --- openssl/src/ssl/tests/mod.rs | 4 ++-- openssl/src/x509/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index b89517da..3216e066 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -310,7 +310,7 @@ run_test!(verify_callback_load_certs, |method, stream| { run_test!(verify_trusted_get_error_ok, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { - assert!(x509_ctx.get_error().is_none()); + assert!(x509_ctx.error().is_none()); true }); @@ -324,7 +324,7 @@ run_test!(verify_trusted_get_error_ok, |method, stream| { run_test!(verify_trusted_get_error_err, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { - assert!(x509_ctx.get_error().is_some()); + assert!(x509_ctx.error().is_some()); false }); diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index fb9d466d..b551a544 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -83,7 +83,7 @@ impl X509StoreContext { X509StoreContext { ctx: ctx } } - pub fn get_error(&self) -> Option { + pub fn error(&self) -> Option { let err = unsafe { ffi::X509_STORE_CTX_get_error(self.ctx) }; X509ValidationError::from_raw(err) } From 77ba043acf0cc6a536042814d92a2df9a6bf2784 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 21:53:05 -0700 Subject: [PATCH 64/96] x509 cleanup --- openssl/src/x509/mod.rs | 35 ++++++++++++++++------------------- openssl/src/x509/tests.rs | 2 +- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index b551a544..347c9736 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -314,18 +314,17 @@ impl X509Generator { let not_before = try!(Asn1Time::days_from_now(0)); let not_after = try!(Asn1Time::days_from_now(self.days)); - try_ssl!(ffi::X509_set_notBefore(x509.handle(), mem::transmute(not_before.handle()))); + try_ssl!(ffi::X509_set_notBefore(x509.handle(), not_before.handle() as *const _)); // If prev line succeded - ownership should go to cert mem::forget(not_before); - try_ssl!(ffi::X509_set_notAfter(x509.handle(), mem::transmute(not_after.handle()))); + try_ssl!(ffi::X509_set_notAfter(x509.handle(), not_after.handle() as *const _)); // If prev line succeded - ownership should go to cert mem::forget(not_after); try_ssl!(ffi::X509_set_pubkey(x509.handle(), p_key.handle())); - let name = ffi::X509_get_subject_name(x509.handle()); - try_ssl_null!(name); + let name = try_ssl_null!(ffi::X509_get_subject_name(x509.handle())); let default = [("CN", "rust-openssl")]; let default_iter = &mut default.iter().map(|&(k, v)| (k, v)); @@ -339,7 +338,7 @@ impl X509Generator { for (key, val) in iter { try!(X509Generator::add_name_internal(name, &key, &val)); } - ffi::X509_set_issuer_name(x509.handle(), name); + try_ssl!(ffi::X509_set_issuer_name(x509.handle(), name)); for (exttype, ext) in self.extensions.iter() { try!(X509Generator::add_extension_internal(x509.handle(), @@ -381,7 +380,7 @@ impl X509Generator { pub struct X509Ref<'a>(*mut ffi::X509, PhantomData<&'a ()>); impl<'a> X509Ref<'a> { - /// Creates a new `X509` wrapping the provided handle. + /// Creates a new `X509Ref` wrapping the provided handle. pub unsafe fn new(handle: *mut ffi::X509) -> X509Ref<'a> { X509Ref(handle, PhantomData) } @@ -433,7 +432,7 @@ impl<'a> X509Ref<'a> { } /// Writes certificate as PEM - pub fn write_pem(&self) -> Result, ErrorStack> { + pub fn to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_X509(mem_bio.handle(), self.0)); @@ -442,7 +441,7 @@ impl<'a> X509Ref<'a> { } /// Returns a DER serialized form of the certificate - pub fn save_der(&self) -> Result, ErrorStack> { + pub fn to_der(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { ffi::i2d_X509_bio(mem_bio.handle(), self.0); @@ -535,18 +534,16 @@ impl<'x> X509Name<'x> { } /// A certificate signing request -pub struct X509Req { - handle: *mut ffi::X509_REQ, -} +pub struct X509Req(*mut ffi::X509_REQ); impl X509Req { /// Creates new from handle - pub fn new(handle: *mut ffi::X509_REQ) -> X509Req { - X509Req { handle: handle } + pub unsafe fn new(handle: *mut ffi::X509_REQ) -> X509Req { + X509Req(handle) } pub fn handle(&self) -> *mut ffi::X509_REQ { - self.handle + self.0 } /// Reads CSR from PEM @@ -562,19 +559,19 @@ impl X509Req { } /// Writes CSR as PEM - pub fn write_pem(&self) -> Result, ErrorStack> { + pub fn to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); - if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.handle(), self.handle) } != 1 { + if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.handle(), self.0) } != 1 { return Err(ErrorStack::get()); } Ok(mem_bio.get_buf().to_owned()) } /// Returns a DER serialized form of the CSR - pub fn save_der(&self) -> Result, ErrorStack> { + pub fn to_der(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - ffi::i2d_X509_REQ_bio(mem_bio.handle(), self.handle); + ffi::i2d_X509_REQ_bio(mem_bio.handle(), self.0); } Ok(mem_bio.get_buf().to_owned()) } @@ -582,7 +579,7 @@ impl X509Req { impl Drop for X509Req { fn drop(&mut self) { - unsafe { ffi::X509_REQ_free(self.handle) }; + unsafe { ffi::X509_REQ_free(self.0) }; } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 141e1fdb..86b5f92b 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -92,7 +92,7 @@ fn test_save_der() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); - let der = cert.save_der().unwrap(); + let der = cert.to_der().unwrap(); assert!(!der.is_empty()); } From 25752280ae72c39617b3648d61922d3a3020a40e Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 22:04:00 -0700 Subject: [PATCH 65/96] Move init to crate root --- openssl/src/lib.rs | 3 +++ openssl/src/ssl/mod.rs | 9 ++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 8dc73dde..a694d536 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -14,6 +14,9 @@ extern crate rustc_serialize as serialize; #[cfg(test)] extern crate net2; +#[doc(inline)] +pub use ffi::init; + use nid::Nid; mod macros; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index aa8d9657..2bb15497 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -18,8 +18,9 @@ use libc::{c_uchar, c_uint}; #[cfg(any(feature = "npn", feature = "alpn"))] use std::slice; use std::marker::PhantomData; - use ffi; + +use init; use dh::DH; use x509::{X509StoreContext, X509FileType, X509, X509Ref}; use crypto::pkey::PKey; @@ -40,12 +41,6 @@ extern "C" { fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX); } -/// Manually initialize SSL. -/// It is optional to call this function and safe to do so more than once. -pub fn init() { - ffi::init(); -} - bitflags! { pub flags SslContextOptions: c_long { const SSL_OP_MICROSOFT_SESS_ID_BUG = ffi::SSL_OP_MICROSOFT_SESS_ID_BUG, From 2a3e9a28564626bea0bf729a0ecee43553697654 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 22:35:37 -0700 Subject: [PATCH 66/96] Add RSA::generate --- openssl-sys/src/lib.rs | 5 ++++- openssl/src/crypto/rsa.rs | 40 ++++++++++++++++++++++++++------------- openssl/src/x509/tests.rs | 10 ++++++---- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index b141fa9d..6966bb8f 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -17,6 +17,7 @@ pub type ASN1_INTEGER = c_void; pub type ASN1_STRING = c_void; pub type ASN1_TIME = c_void; pub type BN_CTX = c_void; +pub type BN_GENCB = c_void; pub type COMP_METHOD = c_void; pub type DH = c_void; pub type ENGINE = c_void; @@ -295,6 +296,8 @@ pub const NID_key_usage: c_int = 83; pub const PKCS5_SALT_LEN: c_int = 8; +pub const RSA_F4: c_long = 0x10001; + pub const SSL_CTRL_SET_TMP_DH: c_int = 3; pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; pub const SSL_CTRL_OPTIONS: c_int = 32; @@ -800,7 +803,7 @@ extern "C" { pub fn RSA_new() -> *mut RSA; pub fn RSA_free(rsa: *mut RSA); pub fn RSA_generate_key(modsz: c_int, e: c_ulong, cb: *const c_void, cbarg: *const c_void) -> *mut RSA; - pub fn RSA_generate_key_ex(rsa: *mut RSA, bits: c_int, e: *mut BIGNUM, cb: *const c_void) -> c_int; + pub fn RSA_generate_key_ex(rsa: *mut RSA, bits: c_int, e: *mut BIGNUM, cb: *mut BN_GENCB) -> c_int; pub fn RSA_private_decrypt(flen: c_int, from: *const u8, to: *mut u8, k: *mut RSA, pad: c_int) -> c_int; pub fn RSA_public_decrypt(flen: c_int, from: *const u8, to: *mut u8, k: *mut RSA, diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 3410239f..ba73d215 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -55,11 +55,25 @@ impl RSA { } } - /// the caller should assert that the rsa pointer is valid. pub unsafe fn from_raw(rsa: *mut ffi::RSA) -> RSA { RSA(rsa) } + /// Generates a public/private key pair with the specified size. + /// + /// The public exponent will be 65537. + pub fn generate(bits: u32) -> Result { + unsafe { + let rsa = try_ssl_null!(ffi::RSA_new()); + let rsa = RSA(rsa); + let e = try!(BigNum::new_from(ffi::RSA_F4 as _)); + + try_ssl!(ffi::RSA_generate_key_ex(rsa.0, bits as c_int, e.raw(), ptr::null_mut())); + + Ok(rsa) + } + } + /// Reads an RSA private key from PEM formatted data. pub fn private_key_from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); @@ -90,6 +104,18 @@ impl RSA { } } + /// Reads an RSA public key from PEM formatted data. + pub fn public_key_from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); + unsafe { + let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.handle(), + ptr::null_mut(), + None, + ptr::null_mut())); + Ok(RSA(rsa)) + } + } + /// Writes an RSA private key as unencrypted PEM formatted data pub fn private_key_to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); @@ -106,18 +132,6 @@ impl RSA { Ok(mem_bio.get_buf().to_owned()) } - /// Reads an RSA public key from PEM formatted data. - pub fn public_key_from_pem(buf: &[u8]) -> Result { - let mem_bio = try!(MemBioSlice::new(buf)); - unsafe { - let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.handle(), - ptr::null_mut(), - None, - ptr::null_mut())); - Ok(RSA(rsa)) - } - } - /// Writes an RSA public key as PEM formatted data pub fn public_key_to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 86b5f92b..aedcaf55 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -2,6 +2,7 @@ use serialize::hex::FromHex; use crypto::hash::Type::SHA1; use crypto::pkey::PKey; +use crypto::rsa::RSA; use x509::{X509, X509Generator}; use x509::extension::Extension::{KeyUsage, ExtKeyUsage, SubjectAltName, OtherNid, OtherStr}; use x509::extension::AltNameOption as SAN; @@ -61,19 +62,20 @@ fn test_cert_gen_extension_bad_ordering() { assert!(result.is_err()); } +*/ #[test] fn test_req_gen() { - let mut pkey = PKey::new(); - pkey.gen(512); + let rsa = RSA::generate(512).unwrap(); + let mut pkey = PKey::new().unwrap(); + pkey.set_rsa(&rsa).unwrap(); let req = get_generator().request(&pkey).unwrap(); - req.write_pem().unwrap(); + req.to_pem().unwrap(); // FIXME: check data in result to be correct, needs implementation // of X509_REQ getters } -*/ #[test] fn test_cert_loading() { From 19689565360cc4bf54a1a083321d46871be0b1f5 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 22:40:51 -0700 Subject: [PATCH 67/96] Restore disabled tests --- openssl/src/x509/tests.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index aedcaf55..ba747c83 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -25,17 +25,23 @@ fn get_generator() -> X509Generator { .add_extension(OtherStr("2.999.2".to_owned(), "ASN1:UTF8:example value".to_owned())) } -/* +fn pkey() -> PKey { + let rsa = RSA::generate(512).unwrap(); + let mut pkey = PKey::new().unwrap(); + pkey.set_rsa(&rsa).unwrap(); + pkey +} + #[test] fn test_cert_gen() { - let (cert, pkey) = get_generator().generate().unwrap(); - cert.write_pem().unwrap(); - pkey.write_pem().unwrap(); + let pkey = pkey(); + let cert = get_generator().sign(&pkey).unwrap(); // FIXME: check data in result to be correct, needs implementation // of X509 getters - assert_eq!(pkey.save_pub(), cert.public_key().save_pub()); + assert_eq!(pkey.public_key_to_pem().unwrap(), + cert.public_key().unwrap().public_key_to_pem().unwrap()); } /// SubjectKeyIdentifier must be added before AuthorityKeyIdentifier or OpenSSL @@ -43,10 +49,11 @@ fn test_cert_gen() { /// for extensions is preserved when the cert is signed. #[test] fn test_cert_gen_extension_ordering() { + let pkey = pkey(); get_generator() .add_extension(OtherNid(Nid::SubjectKeyIdentifier, "hash".to_owned())) .add_extension(OtherNid(Nid::AuthorityKeyIdentifier, "keyid:always".to_owned())) - .generate() + .sign(&pkey) .expect("Failed to generate cert with order-dependent extensions"); } @@ -54,21 +61,19 @@ fn test_cert_gen_extension_ordering() { /// deterministic by reversing the order of extensions and asserting failure. #[test] fn test_cert_gen_extension_bad_ordering() { + let pkey = pkey(); let result = get_generator() .add_extension(OtherNid(Nid::AuthorityKeyIdentifier, "keyid:always".to_owned())) .add_extension(OtherNid(Nid::SubjectKeyIdentifier, "hash".to_owned())) - .generate(); + .sign(&pkey); assert!(result.is_err()); } -*/ #[test] fn test_req_gen() { - let rsa = RSA::generate(512).unwrap(); - let mut pkey = PKey::new().unwrap(); - pkey.set_rsa(&rsa).unwrap(); + let pkey = pkey(); let req = get_generator().request(&pkey).unwrap(); req.to_pem().unwrap(); From a8f827d28c21a9fc816ac4291a9dbfe943e23027 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 22:44:42 -0700 Subject: [PATCH 68/96] Fix example --- openssl/src/x509/mod.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 347c9736..407c5fbc 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -106,16 +106,21 @@ impl X509StoreContext { } #[allow(non_snake_case)] -// FIXME /// Generator of private key/certificate pairs /// /// # Example /// -/// ```ignore +/// ``` /// use openssl::crypto::hash::Type; +/// use openssl::crypto::pkey::PKey; +/// use openssl::crypto::rsa::RSA; /// use openssl::x509::X509Generator; /// use openssl::x509::extension::{Extension, KeyUsageOption}; /// +/// let rsa = RSA::generate(2048).unwrap(); +/// let mut pkey = PKey::new().unwrap(); +/// pkey.set_rsa(&rsa).unwrap(); +/// /// let gen = X509Generator::new() /// .set_bitlength(2048) /// .set_valid_period(365*2) @@ -123,8 +128,8 @@ impl X509StoreContext { /// .set_sign_hash(Type::SHA256) /// .add_extension(Extension::KeyUsage(vec![KeyUsageOption::DigitalSignature])); /// -/// let (cert, pkey) = gen.generate().unwrap(); -/// let cert_pem = cert.write_pem().unwrap(); +/// let cert = gen.sign(&pkey).unwrap(); +/// let cert_pem = cert.to_pem().unwrap(); /// let pkey_pem = pkey.private_key_to_pem().unwrap(); /// ``` pub struct X509Generator { From 6e5cd7ef47c2d328f419b14cbef4f41337a7321a Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 22:46:14 -0700 Subject: [PATCH 69/96] Remove X509Generator::bitlenth --- openssl/src/x509/mod.rs | 11 ----------- openssl/src/x509/tests.rs | 3 +-- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 407c5fbc..1bce71c6 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -122,7 +122,6 @@ impl X509StoreContext { /// pkey.set_rsa(&rsa).unwrap(); /// /// let gen = X509Generator::new() -/// .set_bitlength(2048) /// .set_valid_period(365*2) /// .add_name("CN".to_owned(), "SuperMegaCorp Inc.".to_owned()) /// .set_sign_hash(Type::SHA256) @@ -133,7 +132,6 @@ impl X509StoreContext { /// let pkey_pem = pkey.private_key_to_pem().unwrap(); /// ``` pub struct X509Generator { - bits: u32, days: u32, names: Vec<(String, String)>, extensions: Extensions, @@ -143,8 +141,6 @@ pub struct X509Generator { impl X509Generator { /// Creates a new generator with the following defaults: /// - /// bit length: 1024 - /// /// validity period: 365 days /// /// CN: "rust-openssl" @@ -152,7 +148,6 @@ impl X509Generator { /// hash: SHA1 pub fn new() -> X509Generator { X509Generator { - bits: 1024, days: 365, names: vec![], extensions: Extensions::new(), @@ -160,12 +155,6 @@ impl X509Generator { } } - /// Sets desired bit length - pub fn set_bitlength(mut self, bits: u32) -> X509Generator { - self.bits = bits; - self - } - /// Sets certificate validity period in days since today pub fn set_valid_period(mut self, days: u32) -> X509Generator { self.days = days; diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index ba747c83..f701736a 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -12,7 +12,6 @@ use nid::Nid; fn get_generator() -> X509Generator { X509Generator::new() - .set_bitlength(2048) .set_valid_period(365 * 2) .add_name("CN".to_string(), "test_me".to_string()) .set_sign_hash(SHA1) @@ -26,7 +25,7 @@ fn get_generator() -> X509Generator { } fn pkey() -> PKey { - let rsa = RSA::generate(512).unwrap(); + let rsa = RSA::generate(2048).unwrap(); let mut pkey = PKey::new().unwrap(); pkey.set_rsa(&rsa).unwrap(); pkey From 6b1016c86e72d26d15584789456bd317bee92bca Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 22:56:44 -0700 Subject: [PATCH 70/96] Add PKey::from_rsa --- openssl-sys/src/lib.rs | 2 ++ openssl/src/crypto/pkey.rs | 14 +++++++++----- openssl/src/x509/mod.rs | 3 +-- openssl/src/x509/tests.rs | 3 +-- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 6966bb8f..58b78d9f 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -284,6 +284,7 @@ pub const BIO_FLAGS_SHOULD_RETRY: c_int = 0x08; pub const CRYPTO_LOCK: c_int = 1; pub const EVP_MAX_MD_SIZE: c_uint = 64; +pub const EVP_PKEY_RSA: c_int = NID_rsaEncryption; pub const MBSTRING_ASC: c_int = MBSTRING_FLAG | 1; pub const MBSTRING_BMP: c_int = MBSTRING_FLAG | 2; @@ -291,6 +292,7 @@ pub const MBSTRING_FLAG: c_int = 0x1000; pub const MBSTRING_UNIV: c_int = MBSTRING_FLAG | 4; pub const MBSTRING_UTF8: c_int = MBSTRING_FLAG; +pub const NID_rsaEncryption: c_int = 6; pub const NID_ext_key_usage: c_int = 126; pub const NID_key_usage: c_int = 83; diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 501ffa37..607d4986 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,8 +1,9 @@ use libc::{c_void, c_char}; use std::ptr; -use bio::{MemBio, MemBioSlice}; - +use std::mem; use ffi; + +use bio::{MemBio, MemBioSlice}; use crypto::rsa::RSA; use error::ErrorStack; use crypto::util::{CallbackState, invoke_passwd_cb}; @@ -14,11 +15,14 @@ unsafe impl Sync for PKey {} /// Represents a public key, optionally with a private key attached. impl PKey { - pub fn new() -> Result { - ffi::init(); + /// Create a new `PKey` containing an RSA key. + pub fn from_rsa(rsa: RSA) -> Result { unsafe { let evp = try_ssl_null!(ffi::EVP_PKEY_new()); - Ok(PKey::from_handle(evp)) + let pkey = PKey(evp); + try_ssl!(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_RSA, rsa.as_ptr() as *mut _)); + mem::forget(rsa); + Ok(pkey) } } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 1bce71c6..10537ea2 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -118,8 +118,7 @@ impl X509StoreContext { /// use openssl::x509::extension::{Extension, KeyUsageOption}; /// /// let rsa = RSA::generate(2048).unwrap(); -/// let mut pkey = PKey::new().unwrap(); -/// pkey.set_rsa(&rsa).unwrap(); +/// let pkey = PKey::from_rsa(rsa).unwrap(); /// /// let gen = X509Generator::new() /// .set_valid_period(365*2) diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index f701736a..da1523af 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -26,8 +26,7 @@ fn get_generator() -> X509Generator { fn pkey() -> PKey { let rsa = RSA::generate(2048).unwrap(); - let mut pkey = PKey::new().unwrap(); - pkey.set_rsa(&rsa).unwrap(); + let mut pkey = PKey::from_rsa(rsa).unwrap(); pkey } From deb94a904b9a6e47782b828f8c5e33140fd77eaa Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 22:58:20 -0700 Subject: [PATCH 71/96] Fix build on 1.9 --- openssl/src/crypto/rsa.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index ba73d215..66341a8b 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -1,7 +1,7 @@ use ffi; use std::fmt; use std::ptr; -use libc::{c_int, c_void, c_char}; +use libc::{c_int, c_void, c_char, c_ulong}; use bn::{BigNum, BigNumRef}; use bio::{MemBio, MemBioSlice}; @@ -66,7 +66,7 @@ impl RSA { unsafe { let rsa = try_ssl_null!(ffi::RSA_new()); let rsa = RSA(rsa); - let e = try!(BigNum::new_from(ffi::RSA_F4 as _)); + let e = try!(BigNum::new_from(ffi::RSA_F4 as c_ulong)); try_ssl!(ffi::RSA_generate_key_ex(rsa.0, bits as c_int, e.raw(), ptr::null_mut())); From e4b97921a9ff2f1bddd49f4a64981ccfeadd9b04 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 8 Aug 2016 19:04:30 -0700 Subject: [PATCH 72/96] Clean up RSA and DSA accessors --- openssl/src/crypto/dsa.rs | 50 +++++++++++++----------- openssl/src/crypto/rsa.rs | 82 ++++++++++++++++++++++----------------- 2 files changed, 74 insertions(+), 58 deletions(-) diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index 099657da..7852d391 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -145,7 +145,7 @@ impl DSA { } pub fn size(&self) -> Option { - if self.has_q() { + if self.q().is_some() { unsafe { Some(ffi::DSA_size(self.0) as u32) } } else { None @@ -189,31 +189,37 @@ impl DSA { self.0 } - pub fn p<'a>(&'a self) -> BigNumRef<'a> { - assert!(self.has_p()); - unsafe { BigNumRef::from_handle((*self.0).p) } + pub fn p<'a>(&'a self) -> Option> { + unsafe { + let p = (*self.0).p; + if p.is_null() { + None + } else { + Some(BigNumRef::from_handle((*self.0).p)) + } + } } - pub fn has_p(&self) -> bool { - unsafe { !(*self.0).p.is_null() } + pub fn q<'a>(&'a self) -> Option> { + unsafe { + let q = (*self.0).q; + if q.is_null() { + None + } else { + Some(BigNumRef::from_handle((*self.0).q)) + } + } } - pub fn q<'a>(&'a self) -> BigNumRef<'a> { - assert!(self.has_q()); - unsafe { BigNumRef::from_handle((*self.0).q) } - } - - pub fn has_q(&self) -> bool { - unsafe { !(*self.0).q.is_null() } - } - - pub fn g<'a>(&'a self) -> BigNumRef<'a> { - assert!(self.has_g()); - unsafe { BigNumRef::from_handle((*self.0).g) } - } - - pub fn has_g(&self) -> bool { - unsafe { !(*self.0).q.is_null() } + pub fn g<'a>(&'a self) -> Option> { + unsafe { + let g = (*self.0).g; + if g.is_null() { + None + } else { + Some(BigNumRef::from_handle((*self.0).g)) + } + } } pub fn has_public_key(&self) -> bool { diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 66341a8b..2dfa64a6 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -144,7 +144,7 @@ impl RSA { } pub fn size(&self) -> Option { - if self.has_n() { + if self.n().is_some() { unsafe { Some(ffi::RSA_size(self.0) as u32) } } else { None @@ -184,49 +184,59 @@ impl RSA { self.0 } - pub fn n<'a>(&'a self) -> BigNumRef<'a> { - assert!(self.has_n()); - unsafe { BigNumRef::from_handle((*self.0).n) } + pub fn n<'a>(&'a self) -> Option> { + unsafe { + let n = (*self.0).n; + if n.is_null() { + None + } else { + Some(BigNumRef::from_handle(n)) + } + } } - pub fn has_n(&self) -> bool { - unsafe { !(*self.0).n.is_null() } + pub fn d<'a>(&self) -> Option> { + unsafe { + let d = (*self.0).d; + if d.is_null() { + None + } else { + Some(BigNumRef::from_handle(d)) + } + } } - pub fn d<'a>(&self) -> BigNumRef<'a> { - assert!(self.has_d()); - unsafe { BigNumRef::from_handle((*self.0).d) } + pub fn e<'a>(&'a self) -> Option> { + unsafe { + let e = (*self.0).e; + if e.is_null() { + None + } else { + Some(BigNumRef::from_handle(e)) + } + } } - pub fn has_d(&self) -> bool { - unsafe { !(*self.0).d.is_null() } + pub fn p<'a>(&'a self) -> Option> { + unsafe { + let p = (*self.0).p; + if p.is_null() { + None + } else { + Some(BigNumRef::from_handle(p)) + } + } } - pub fn e<'a>(&'a self) -> BigNumRef<'a> { - assert!(self.has_e()); - unsafe { BigNumRef::from_handle((*self.0).e) } - } - - pub fn has_e(&self) -> bool { - unsafe { !(*self.0).e.is_null() } - } - - pub fn p<'a>(&'a self) -> BigNumRef<'a> { - assert!(self.has_p()); - unsafe { BigNumRef::from_handle((*self.0).p) } - } - - pub fn has_p(&self) -> bool { - unsafe { !(*self.0).p.is_null() } - } - - pub fn q<'a>(&'a self) -> BigNumRef<'a> { - assert!(self.has_q()); - unsafe { BigNumRef::from_handle((*self.0).q) } - } - - pub fn has_q(&self) -> bool { - unsafe { !(*self.0).q.is_null() } + pub fn q<'a>(&'a self) -> Option> { + unsafe { + let q = (*self.0).q; + if q.is_null() { + None + } else { + Some(BigNumRef::from_handle(q)) + } + } } } From bf07dd9a4e4d0b1d7c003ec68dc92135a642fd5a Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 8 Aug 2016 20:26:04 -0700 Subject: [PATCH 73/96] Remove symm_internal --- openssl-sys/src/lib.rs | 35 ++++++++++++- openssl/src/crypto/mod.rs | 2 - openssl/src/crypto/pkcs5.rs | 14 +++--- openssl/src/crypto/symm.rs | 77 ++++++++++++++++++++++++++--- openssl/src/crypto/symm_internal.rs | 35 ------------- 5 files changed, 110 insertions(+), 53 deletions(-) delete mode 100644 openssl/src/crypto/symm_internal.rs diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 58b78d9f..6d2090ca 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -16,12 +16,12 @@ use std::sync::{Once, ONCE_INIT}; pub type ASN1_INTEGER = c_void; pub type ASN1_STRING = c_void; pub type ASN1_TIME = c_void; +pub type ASN1_TYPE = c_void; pub type BN_CTX = c_void; pub type BN_GENCB = c_void; pub type COMP_METHOD = c_void; pub type DH = c_void; pub type ENGINE = c_void; -pub type EVP_CIPHER = c_void; pub type EVP_CIPHER_CTX = c_void; pub type EVP_MD = c_void; pub type EVP_PKEY_CTX = c_void; @@ -196,6 +196,39 @@ impl Clone for EVP_MD_CTX { fn clone(&self) -> EVP_MD_CTX { *self } } +#[repr(C)] +pub struct EVP_CIPHER { + pub nid: c_int, + pub block_size: c_int, + pub key_len: c_int, + pub iv_len: c_int, + pub flags: c_ulong, + pub init: Option c_int>, + pub do_cipher: Option c_int>, + pub cleanup: Option c_int>, + pub ctx_size: c_int, + pub set_asn1_parameters: Option c_int>, + pub get_asn1_parameters: Option c_int>, + pub ctrl: Option c_int>, + pub app_data: *mut c_void, +} + +impl Copy for EVP_CIPHER {} +impl Clone for EVP_CIPHER { + fn clone(&self) -> EVP_CIPHER { *self } +} + #[repr(C)] pub struct HMAC_CTX { md: *mut EVP_MD, diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs index 873f9d47..453291aa 100644 --- a/openssl/src/crypto/mod.rs +++ b/openssl/src/crypto/mod.rs @@ -24,5 +24,3 @@ pub mod memcmp; pub mod rsa; pub mod dsa; mod util; - -mod symm_internal; diff --git a/openssl/src/crypto/pkcs5.rs b/openssl/src/crypto/pkcs5.rs index 48e61a20..0098de8c 100644 --- a/openssl/src/crypto/pkcs5.rs +++ b/openssl/src/crypto/pkcs5.rs @@ -3,7 +3,6 @@ use std::ptr; use ffi; use HashTypeInternals; -use crypto::symm_internal::evpc; use crypto::hash; use crypto::symm; use error::ErrorStack; @@ -41,12 +40,11 @@ pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type, ffi::init(); - let (evp, _, _) = evpc(typ); + let typ = typ.as_ptr(); + let message_digest_type = message_digest_type.evp_md(); - let message_digest = message_digest_type.evp_md(); - - let len = ffi::EVP_BytesToKey(evp, - message_digest, + let len = ffi::EVP_BytesToKey(typ, + message_digest_type, salt_ptr, data.as_ptr(), data.len() as c_int, @@ -60,8 +58,8 @@ pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type, let mut key = vec![0; len as usize]; let mut iv = vec![0; len as usize]; - try_ssl!(ffi::EVP_BytesToKey(evp, - message_digest, + try_ssl!(ffi::EVP_BytesToKey(typ, + message_digest_type, salt_ptr, data.as_ptr(), data.len() as c_int, diff --git a/openssl/src/crypto/symm.rs b/openssl/src/crypto/symm.rs index 935980f3..b9fc5933 100644 --- a/openssl/src/crypto/symm.rs +++ b/openssl/src/crypto/symm.rs @@ -1,7 +1,6 @@ use std::iter::repeat; use libc::c_int; -use crypto::symm_internal::evpc; use ffi; #[derive(Copy, Clone)] @@ -43,13 +42,78 @@ pub enum Type { RC4_128, } +impl Type { + pub fn as_ptr(&self) -> *const ffi::EVP_CIPHER { + unsafe { + match *self { + Type::AES_128_ECB => ffi::EVP_aes_128_ecb(), + Type::AES_128_CBC => ffi::EVP_aes_128_cbc(), + #[cfg(feature = "aes_xts")] + Type::AES_128_XTS => ffi::EVP_aes_128_xts(), + #[cfg(feature = "aes_ctr")] + Type::AES_128_CTR => ffi::EVP_aes_128_ctr(), + // AES_128_GCM => (EVP_aes_128_gcm(), 16, 16), + Type::AES_128_CFB1 => ffi::EVP_aes_128_cfb1(), + Type::AES_128_CFB128 => ffi::EVP_aes_128_cfb128(), + Type::AES_128_CFB8 => ffi::EVP_aes_128_cfb8(), + + Type::AES_256_ECB => ffi::EVP_aes_256_ecb(), + Type::AES_256_CBC => ffi::EVP_aes_256_cbc(), + #[cfg(feature = "aes_xts")] + Type::AES_256_XTS => ffi::EVP_aes_256_xts(), + #[cfg(feature = "aes_ctr")] + Type::AES_256_CTR => ffi::EVP_aes_256_ctr(), + // AES_256_GCM => (EVP_aes_256_gcm(), 32, 16), + Type::AES_256_CFB1 => ffi::EVP_aes_256_cfb1(), + Type::AES_256_CFB128 => ffi::EVP_aes_256_cfb128(), + Type::AES_256_CFB8 => ffi::EVP_aes_256_cfb8(), + + Type::DES_CBC => ffi::EVP_des_cbc(), + Type::DES_ECB => ffi::EVP_des_ecb(), + + Type::RC4_128 => ffi::EVP_rc4(), + } + } + } + + /// Returns the length of keys used with this cipher. + pub fn key_len(&self) -> usize { + unsafe { + (*self.as_ptr()).key_len as usize + } + } + + /// Returns the length of the IV used with this cipher, or `None` if the + /// cipher does not use an IV. + pub fn iv_len(&self) -> Option { + unsafe { + let len = (*self.as_ptr()).iv_len as usize; + if len == 0 { + None + } else { + Some(len) + } + } + } + + /// Returns the block size of the cipher. + /// + /// # Note + /// + /// Stream ciphers such as RC4 have a block size of 1. + pub fn block_size(&self) -> usize { + unsafe { + (*self.as_ptr()).block_size as usize + } + } +} /// Represents a symmetric cipher context. pub struct Crypter { evp: *const ffi::EVP_CIPHER, ctx: *mut ffi::EVP_CIPHER_CTX, - keylen: u32, - blocksize: u32, + keylen: usize, + blocksize: usize, } impl Crypter { @@ -57,12 +121,11 @@ impl Crypter { ffi::init(); let ctx = unsafe { ffi::EVP_CIPHER_CTX_new() }; - let (evp, keylen, blocksz) = evpc(t); Crypter { - evp: evp, + evp: t.as_ptr(), ctx: ctx, - keylen: keylen, - blocksize: blocksz, + keylen: t.key_len(), + blocksize: t.block_size(), } } diff --git a/openssl/src/crypto/symm_internal.rs b/openssl/src/crypto/symm_internal.rs deleted file mode 100644 index ba01e1c1..00000000 --- a/openssl/src/crypto/symm_internal.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crypto::symm; -use ffi; - -pub fn evpc(t: symm::Type) -> (*const ffi::EVP_CIPHER, u32, u32) { - unsafe { - match t { - symm::Type::AES_128_ECB => (ffi::EVP_aes_128_ecb(), 16, 16), - symm::Type::AES_128_CBC => (ffi::EVP_aes_128_cbc(), 16, 16), - #[cfg(feature = "aes_xts")] - symm::Type::AES_128_XTS => (ffi::EVP_aes_128_xts(), 32, 16), - #[cfg(feature = "aes_ctr")] - symm::Type::AES_128_CTR => (ffi::EVP_aes_128_ctr(), 16, 0), - // AES_128_GCM => (EVP_aes_128_gcm(), 16, 16), - symm::Type::AES_128_CFB1 => (ffi::EVP_aes_128_cfb1(), 16, 16), - symm::Type::AES_128_CFB128 => (ffi::EVP_aes_128_cfb128(), 16, 16), - symm::Type::AES_128_CFB8 => (ffi::EVP_aes_128_cfb8(), 16, 16), - - symm::Type::AES_256_ECB => (ffi::EVP_aes_256_ecb(), 32, 16), - symm::Type::AES_256_CBC => (ffi::EVP_aes_256_cbc(), 32, 16), - #[cfg(feature = "aes_xts")] - symm::Type::AES_256_XTS => (ffi::EVP_aes_256_xts(), 64, 16), - #[cfg(feature = "aes_ctr")] - symm::Type::AES_256_CTR => (ffi::EVP_aes_256_ctr(), 32, 0), - // AES_256_GCM => (EVP_aes_256_gcm(), 32, 16), - symm::Type::AES_256_CFB1 => (ffi::EVP_aes_256_cfb1(), 32, 16), - symm::Type::AES_256_CFB128 => (ffi::EVP_aes_256_cfb128(), 32, 16), - symm::Type::AES_256_CFB8 => (ffi::EVP_aes_256_cfb8(), 32, 16), - - symm::Type::DES_CBC => (ffi::EVP_des_cbc(), 8, 8), - symm::Type::DES_ECB => (ffi::EVP_des_ecb(), 8, 8), - - symm::Type::RC4_128 => (ffi::EVP_rc4(), 16, 0), - } - } -} From 522447378e058b60822f5caa752506924a226872 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 8 Aug 2016 20:37:48 -0700 Subject: [PATCH 74/96] Copy over getter macros --- openssl-sys/src/lib.rs | 12 ++++++++++++ openssl/src/crypto/pkcs5.rs | 6 +++--- openssl/src/crypto/symm.rs | 6 +++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 6d2090ca..d102478a 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -600,6 +600,18 @@ pub unsafe fn SSL_set_tlsext_host_name(s: *mut SSL, name: *mut c_char) -> c_long SSL_ctrl(s, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, name as *mut c_void) } +pub unsafe fn EVP_CIPHER_block_size(e: *const EVP_CIPHER) -> c_int { + (*e).block_size +} + +pub unsafe fn EVP_CIPHER_key_length(e: *const EVP_CIPHER) -> c_int { + (*e).key_len +} + +pub unsafe fn EVP_CIPHER_iv_length(e: *const EVP_CIPHER) -> c_int { + (*e).iv_len +} + // True functions extern "C" { pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int; diff --git a/openssl/src/crypto/pkcs5.rs b/openssl/src/crypto/pkcs5.rs index 0098de8c..ef84fbe1 100644 --- a/openssl/src/crypto/pkcs5.rs +++ b/openssl/src/crypto/pkcs5.rs @@ -17,11 +17,11 @@ pub struct KeyIvPair { /// /// If specified `salt` must be 8 bytes in length. /// -/// If the total key and IV length is less than 16 bytes and MD5 is used then -/// the algorithm is compatible with the key derivation algorithm from PKCS#5 +/// If the total key and IV length is less than 16 bytes and MD5 is used then +/// the algorithm is compatible with the key derivation algorithm from PKCS#5 /// v1.5 or PBKDF1 from PKCS#5 v2.0. /// -/// New applications should not use this and instead use `pbkdf2_hmac_sha1` or +/// New applications should not use this and instead use `pbkdf2_hmac_sha1` or /// another more modern key derivation algorithm. pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type, message_digest_type: hash::Type, diff --git a/openssl/src/crypto/symm.rs b/openssl/src/crypto/symm.rs index b9fc5933..84bbbb8d 100644 --- a/openssl/src/crypto/symm.rs +++ b/openssl/src/crypto/symm.rs @@ -79,7 +79,7 @@ impl Type { /// Returns the length of keys used with this cipher. pub fn key_len(&self) -> usize { unsafe { - (*self.as_ptr()).key_len as usize + ffi::EVP_CIPHER_key_length(self.as_ptr()) as usize } } @@ -87,7 +87,7 @@ impl Type { /// cipher does not use an IV. pub fn iv_len(&self) -> Option { unsafe { - let len = (*self.as_ptr()).iv_len as usize; + let len = ffi::EVP_CIPHER_iv_length(self.as_ptr()) as usize; if len == 0 { None } else { @@ -103,7 +103,7 @@ impl Type { /// Stream ciphers such as RC4 have a block size of 1. pub fn block_size(&self) -> usize { unsafe { - (*self.as_ptr()).block_size as usize + ffi::EVP_CIPHER_block_size(self.as_ptr()) as usize } } } From a8224d199b60552945ac03bbf406551252e01adb Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 8 Aug 2016 23:10:03 -0700 Subject: [PATCH 75/96] symm reform --- openssl-sys/src/lib.rs | 7 ++ openssl/src/crypto/symm.rs | 246 +++++++++++++++++++++---------------- 2 files changed, 148 insertions(+), 105 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index d102478a..4dccc67e 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -766,10 +766,17 @@ extern "C" { pub fn EVP_CIPHER_CTX_new() -> *mut EVP_CIPHER_CTX; pub fn EVP_CIPHER_CTX_set_padding(ctx: *mut EVP_CIPHER_CTX, padding: c_int) -> c_int; + pub fn EVP_CIPHER_CTX_set_key_length(ctx: *mut EVP_CIPHER_CTX, keylen: c_int) -> c_int; pub fn EVP_CIPHER_CTX_free(ctx: *mut EVP_CIPHER_CTX); pub fn EVP_CipherInit(ctx: *mut EVP_CIPHER_CTX, evp: *const EVP_CIPHER, key: *const u8, iv: *const u8, mode: c_int) -> c_int; + pub fn EVP_CipherInit_ex(ctx: *mut EVP_CIPHER_CTX, + type_: *const EVP_CIPHER, + impl_: *mut ENGINE, + key: *mut c_uchar, + iv: *mut c_uchar, + enc: c_int) -> c_int; pub fn EVP_CipherUpdate(ctx: *mut EVP_CIPHER_CTX, outbuf: *mut u8, outlen: &mut c_int, inbuf: *const u8, inlen: c_int) -> c_int; pub fn EVP_CipherFinal(ctx: *mut EVP_CIPHER_CTX, res: *mut u8, len: &mut c_int) -> c_int; diff --git a/openssl/src/crypto/symm.rs b/openssl/src/crypto/symm.rs index 84bbbb8d..b6f1746f 100644 --- a/openssl/src/crypto/symm.rs +++ b/openssl/src/crypto/symm.rs @@ -1,8 +1,10 @@ -use std::iter::repeat; +use std::cmp; +use std::ptr; use libc::c_int; - use ffi; +use error::ErrorStack; + #[derive(Copy, Clone)] pub enum Mode { Encrypt, @@ -110,90 +112,110 @@ impl Type { /// Represents a symmetric cipher context. pub struct Crypter { - evp: *const ffi::EVP_CIPHER, ctx: *mut ffi::EVP_CIPHER_CTX, - keylen: usize, - blocksize: usize, + block_size: usize, } impl Crypter { - pub fn new(t: Type) -> Crypter { + pub fn new(t: Type, mode: Mode, key: &[u8], iv: Option<&[u8]>) -> Result { ffi::init(); - let ctx = unsafe { ffi::EVP_CIPHER_CTX_new() }; - Crypter { - evp: t.as_ptr(), - ctx: ctx, - keylen: t.key_len(), - blocksize: t.block_size(), - } - } - - /** - * Enables or disables padding. If padding is disabled, total amount of - * data encrypted must be a multiple of block size. - */ - pub fn pad(&self, padding: bool) { - if self.blocksize > 0 { - unsafe { - let v = if padding { - 1 as c_int - } else { - 0 - }; - ffi::EVP_CIPHER_CTX_set_padding(self.ctx, v); - } - } - } - - /** - * Initializes this crypter. - */ - pub fn init(&self, mode: Mode, key: &[u8], iv: &[u8]) { unsafe { - let mode = match mode { - Mode::Encrypt => 1 as c_int, - Mode::Decrypt => 0 as c_int, + let ctx = try_ssl_null!(ffi::EVP_CIPHER_CTX_new()); + let crypter = Crypter { + ctx: ctx, + block_size: t.block_size(), }; - assert_eq!(key.len(), self.keylen as usize); - ffi::EVP_CipherInit(self.ctx, self.evp, key.as_ptr(), iv.as_ptr(), mode); + let mode = match mode { + Mode::Encrypt => 1, + Mode::Decrypt => 0, + }; + + try_ssl!(ffi::EVP_CipherInit_ex(crypter.ctx, + t.as_ptr(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + mode)); + + assert!(key.len() <= c_int::max_value() as usize); + try_ssl!(ffi::EVP_CIPHER_CTX_set_key_length(crypter.ctx, key.len() as c_int)); + + let key = key.as_ptr() as *mut _; + let iv = match (iv, t.iv_len()) { + (Some(iv), Some(len)) => { + assert!(iv.len() == len); + iv.as_ptr() as *mut _ + } + (Some(_), None) | (None, None) => ptr::null_mut(), + (None, Some(_)) => panic!("an IV is required for this cipher"), + }; + try_ssl!(ffi::EVP_CipherInit_ex(crypter.ctx, + ptr::null(), + ptr::null_mut(), + key, + iv, + mode)); + + Ok(crypter) } } - /** - * Update this crypter with more data to encrypt or decrypt. Returns - * encrypted or decrypted bytes. - */ - pub fn update(&self, data: &[u8]) -> Vec { + /// Enables or disables padding. + /// + /// If padding is disabled, total amount of data encrypted/decrypted must + /// be a multiple of the cipher's block size. + pub fn pad(&mut self, padding: bool) { + unsafe { ffi::EVP_CIPHER_CTX_set_padding(self.ctx, padding as c_int); } + } + + /// Feeds data from `input` through the cipher, writing encrypted/decrypted + /// bytes into `output`. + /// + /// The number of bytes written to `output` is returned. Note that this may + /// not be equal to the length of `input`. + /// + /// # Panics + /// + /// Panics if `output.len() < input.len() + block_size - 1` where + /// `block_size` is the block size of the cipher (see `Type::block_size`), + /// or if `output.len() > c_int::max_value()`. + pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result { unsafe { - let sum = data.len() + (self.blocksize as usize); - let mut res = repeat(0u8).take(sum).collect::>(); - let mut reslen = sum as c_int; + assert!(output.len() >= input.len() + self.block_size - 1); + assert!(output.len() <= c_int::max_value() as usize); + let mut outl = output.len() as c_int; + let inl = input.len() as c_int; - ffi::EVP_CipherUpdate(self.ctx, - res.as_mut_ptr(), - &mut reslen, - data.as_ptr(), - data.len() as c_int); + try_ssl!(ffi::EVP_CipherUpdate(self.ctx, + output.as_mut_ptr(), + &mut outl, + input.as_ptr(), + inl)); - res.truncate(reslen as usize); - res + Ok(outl as usize) } } - /** - * Finish crypting. Returns the remaining partial block of output, if any. - */ - pub fn finalize(&self) -> Vec { + /// Finishes the encryption/decryption process, writing any remaining data + /// to `output`. + /// + /// The number of bytes written to `output` is returned. + /// + /// `update` should not be called after this method. + /// + /// # Panics + /// + /// Panics if `output` is less than the cipher's block size. + pub fn finalize(&mut self, output: &mut [u8]) -> Result { unsafe { - let mut res = repeat(0u8).take(self.blocksize as usize).collect::>(); - let mut reslen = self.blocksize as c_int; + assert!(output.len() >= self.block_size); + let mut outl = cmp::min(output.len(), c_int::max_value() as usize) as c_int; - ffi::EVP_CipherFinal(self.ctx, res.as_mut_ptr(), &mut reslen); + try_ssl!(ffi::EVP_CipherFinal(self.ctx, output.as_mut_ptr(), &mut outl)); - res.truncate(reslen as usize); - res + Ok(outl as usize) } } } @@ -210,31 +232,35 @@ impl Drop for Crypter { * Encrypts data, using the specified crypter type in encrypt mode with the * specified key and iv; returns the resulting (encrypted) data. */ -pub fn encrypt(t: Type, key: &[u8], iv: &[u8], data: &[u8]) -> Vec { - let c = Crypter::new(t); - c.init(Mode::Encrypt, key, iv); - let mut r = c.update(data); - let rest = c.finalize(); - r.extend(rest.into_iter()); - r +pub fn encrypt(t: Type, key: &[u8], iv: Option<&[u8]>, data: &[u8]) -> Result, ErrorStack> { + cipher(t, Mode::Encrypt, key, iv, data) } /** * Decrypts data, using the specified crypter type in decrypt mode with the * specified key and iv; returns the resulting (decrypted) data. */ -pub fn decrypt(t: Type, key: &[u8], iv: &[u8], data: &[u8]) -> Vec { - let c = Crypter::new(t); - c.init(Mode::Decrypt, key, iv); - let mut r = c.update(data); - let rest = c.finalize(); - r.extend(rest.into_iter()); - r +pub fn decrypt(t: Type, key: &[u8], iv: Option<&[u8]>, data: &[u8]) -> Result, ErrorStack> { + cipher(t, Mode::Decrypt, key, iv, data) +} + +fn cipher(t: Type, + mode: Mode, + key: &[u8], + iv: Option<&[u8]>, + data: &[u8]) + -> Result, ErrorStack> { + let mut c = try!(Crypter::new(t, mode, key, iv)); + let mut out = vec![0; data.len() + t.block_size()]; + let count = try!(c.update(data, &mut out)); + let rest = try!(c.finalize(&mut out[count..])); + out.truncate(count + rest); + Ok(out) } #[cfg(test)] mod tests { - use serialize::hex::FromHex; + use serialize::hex::{FromHex, ToHex}; // Test vectors from FIPS-197: // http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf @@ -248,25 +274,33 @@ mod tests { 0xaau8, 0xbbu8, 0xccu8, 0xddu8, 0xeeu8, 0xffu8]; let c0 = [0x8eu8, 0xa2u8, 0xb7u8, 0xcau8, 0x51u8, 0x67u8, 0x45u8, 0xbfu8, 0xeau8, 0xfcu8, 0x49u8, 0x90u8, 0x4bu8, 0x49u8, 0x60u8, 0x89u8]; - let c = super::Crypter::new(super::Type::AES_256_ECB); - c.init(super::Mode::Encrypt, &k0, &[]); + let mut c = super::Crypter::new(super::Type::AES_256_ECB, + super::Mode::Encrypt, + &k0, + None).unwrap(); c.pad(false); - let mut r0 = c.update(&p0); - r0.extend(c.finalize().into_iter()); - assert!(r0 == c0); - c.init(super::Mode::Decrypt, &k0, &[]); + let mut r0 = vec![0; c0.len() + super::Type::AES_256_ECB.block_size()]; + let count = c.update(&p0, &mut r0).unwrap(); + let rest = c.finalize(&mut r0[count..]).unwrap(); + r0.truncate(count + rest); + assert_eq!(r0.to_hex(), c0.to_hex()); + + let mut c = super::Crypter::new(super::Type::AES_256_ECB, + super::Mode::Decrypt, + &k0, + None).unwrap(); c.pad(false); - let mut p1 = c.update(&r0); - p1.extend(c.finalize().into_iter()); - assert!(p1 == p0); + let mut p1 = vec![0; r0.len() + super::Type::AES_256_ECB.block_size()]; + let count = c.update(&r0, &mut p1).unwrap(); + let rest = c.finalize(&mut p1[count..]).unwrap(); + p1.truncate(count + rest); + assert_eq!(p1.to_hex(), p0.to_hex()); } #[test] fn test_aes_256_cbc_decrypt() { - let cr = super::Crypter::new(super::Type::AES_256_CBC); let iv = [4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, 69_u8, - 98_u8, 107_u8, 208_u8, 14_u8, 236_u8, 60_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, - 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8]; + 98_u8, 107_u8, 208_u8, 14_u8, 236_u8, 60_u8]; let data = [143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, 154_u8, 56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, 55_u8, 119_u8, 233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, @@ -274,29 +308,31 @@ mod tests { let ciphered_data = [0x4a_u8, 0x2e_u8, 0xe5_u8, 0x6_u8, 0xbf_u8, 0xcf_u8, 0xf2_u8, 0xd7_u8, 0xea_u8, 0x2d_u8, 0xb1_u8, 0x85_u8, 0x6c_u8, 0x93_u8, 0x65_u8, 0x6f_u8]; - cr.init(super::Mode::Decrypt, &data, &iv); + let mut cr = super::Crypter::new(super::Type::AES_256_CBC, + super::Mode::Decrypt, + &data, + Some(&iv)).unwrap(); cr.pad(false); - let unciphered_data_1 = cr.update(&ciphered_data); - let unciphered_data_2 = cr.finalize(); + let mut unciphered_data = vec![0; data.len() + super::Type::AES_256_CBC.block_size()]; + let count = cr.update(&ciphered_data, &mut unciphered_data).unwrap(); + let rest = cr.finalize(&mut unciphered_data[count..]).unwrap(); + unciphered_data.truncate(count + rest); let expected_unciphered_data = b"I love turtles.\x01"; - assert!(unciphered_data_2.len() == 0); - - assert_eq!(&unciphered_data_1, expected_unciphered_data); + assert_eq!(&unciphered_data, expected_unciphered_data); } fn cipher_test(ciphertype: super::Type, pt: &str, ct: &str, key: &str, iv: &str) { use serialize::hex::ToHex; - let cipher = super::Crypter::new(ciphertype); - cipher.init(super::Mode::Encrypt, - &key.from_hex().unwrap(), - &iv.from_hex().unwrap()); + let pt = pt.from_hex().unwrap(); + let ct = ct.from_hex().unwrap(); + let key = key.from_hex().unwrap(); + let iv = iv.from_hex().unwrap(); - let expected = ct.from_hex().unwrap(); - let mut computed = cipher.update(&pt.from_hex().unwrap()); - computed.extend(cipher.finalize().into_iter()); + let computed = super::decrypt(ciphertype, &key, Some(&iv), &ct).unwrap(); + let expected = pt; if computed != expected { println!("Computed: {}", computed.to_hex()); From b8712c5c510c047696367ecb28db1bfadc5885cd Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 8 Aug 2016 23:25:06 -0700 Subject: [PATCH 76/96] Fix size check Decryption requires an extra byte of space --- openssl/src/crypto/symm.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/openssl/src/crypto/symm.rs b/openssl/src/crypto/symm.rs index b6f1746f..ecb643f7 100644 --- a/openssl/src/crypto/symm.rs +++ b/openssl/src/crypto/symm.rs @@ -178,12 +178,12 @@ impl Crypter { /// /// # Panics /// - /// Panics if `output.len() < input.len() + block_size - 1` where + /// Panics if `output.len() < input.len() + block_size` where /// `block_size` is the block size of the cipher (see `Type::block_size`), /// or if `output.len() > c_int::max_value()`. pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result { unsafe { - assert!(output.len() >= input.len() + self.block_size - 1); + assert!(output.len() >= input.len() + self.block_size); assert!(output.len() <= c_int::max_value() as usize); let mut outl = output.len() as c_int; let inl = input.len() as c_int; @@ -232,7 +232,11 @@ impl Drop for Crypter { * Encrypts data, using the specified crypter type in encrypt mode with the * specified key and iv; returns the resulting (encrypted) data. */ -pub fn encrypt(t: Type, key: &[u8], iv: Option<&[u8]>, data: &[u8]) -> Result, ErrorStack> { +pub fn encrypt(t: Type, + key: &[u8], + iv: Option<&[u8]>, + data: &[u8]) + -> Result, ErrorStack> { cipher(t, Mode::Encrypt, key, iv, data) } @@ -240,7 +244,11 @@ pub fn encrypt(t: Type, key: &[u8], iv: Option<&[u8]>, data: &[u8]) -> Result, data: &[u8]) -> Result, ErrorStack> { +pub fn decrypt(t: Type, + key: &[u8], + iv: Option<&[u8]>, + data: &[u8]) + -> Result, ErrorStack> { cipher(t, Mode::Decrypt, key, iv, data) } From 15e8997052668453083108c7aa33f4ad28ccb1fd Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 8 Aug 2016 23:31:25 -0700 Subject: [PATCH 77/96] Docs for Crypter::new --- openssl/src/crypto/symm.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openssl/src/crypto/symm.rs b/openssl/src/crypto/symm.rs index ecb643f7..93764e4d 100644 --- a/openssl/src/crypto/symm.rs +++ b/openssl/src/crypto/symm.rs @@ -117,6 +117,12 @@ pub struct Crypter { } impl Crypter { + /// Creates a new `Crypter`. + /// + /// # Panics + /// + /// Panics if an IV is required by the cipher but not provided, or if the + /// IV's length does not match the expected length (see `Type::iv_len`). pub fn new(t: Type, mode: Mode, key: &[u8], iv: Option<&[u8]>) -> Result { ffi::init(); From 2f46c793e5fa6bb33a3bf7bb84c65b7ebc56c9b9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 9 Aug 2016 21:23:54 -0700 Subject: [PATCH 78/96] Remove rust_SSL_clone --- openssl/src/c_helpers.c | 4 - openssl/src/ssl/mod.rs | 153 +++++++++++++++++++++-------------- openssl/src/ssl/tests/mod.rs | 2 +- 3 files changed, 95 insertions(+), 64 deletions(-) diff --git a/openssl/src/c_helpers.c b/openssl/src/c_helpers.c index e884bebd..5b1b9615 100644 --- a/openssl/src/c_helpers.c +++ b/openssl/src/c_helpers.c @@ -1,9 +1,5 @@ #include -void rust_SSL_clone(SSL *ssl) { - CRYPTO_add(&ssl->references, 1, CRYPTO_LOCK_SSL); -} - void rust_SSL_CTX_clone(SSL_CTX *ctx) { CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); } diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 2bb15497..4f5dee61 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1,18 +1,19 @@ use libc::{c_int, c_void, c_long}; +use std::any::Any; use std::any::TypeId; +use std::cmp; use std::collections::HashMap; +use std::error as stderror; use std::ffi::{CStr, CString}; use std::fmt; use std::io; use std::io::prelude::*; -use std::error as stderror; use std::mem; -use std::str; +use std::ops::{Deref, DerefMut}; use std::path::Path; use std::ptr; +use std::str; use std::sync::{Mutex, Arc}; -use std::cmp; -use std::any::Any; #[cfg(any(feature = "npn", feature = "alpn"))] use libc::{c_uchar, c_uint}; #[cfg(any(feature = "npn", feature = "alpn"))] @@ -37,7 +38,6 @@ use self::bio::BioMethod; pub use ssl::error::Error; extern "C" { - fn rust_SSL_clone(ssl: *mut ffi::SSL); fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX); } @@ -259,14 +259,13 @@ extern "C" fn ssl_raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_ST } extern "C" fn raw_sni(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) -> c_int - where F: Fn(&mut Ssl) -> Result<(), SniError> + Any + 'static + Sync + Send + where F: Fn(&mut SslSlice) -> Result<(), SniError> + Any + 'static + Sync + Send { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); let callback: &F = mem::transmute(callback); - rust_SSL_clone(ssl); - let mut ssl = Ssl { ssl: ssl }; + let mut ssl = SslSlice::from_ptr(ssl); match callback(&mut ssl) { Ok(()) => ffi::SSL_TLSEXT_ERR_OK, @@ -485,7 +484,7 @@ impl SslContext { /// Obtain the server name with `servername` then set the corresponding context /// with `set_ssl_context` pub fn set_servername_callback(&mut self, callback: F) - where F: Fn(&mut Ssl) -> Result<(), SniError> + Any + 'static + Sync + Send + where F: Fn(&mut SslSlice) -> Result<(), SniError> + Any + 'static + Sync + Send { unsafe { let callback = Box::new(callback); @@ -769,70 +768,63 @@ impl<'a> SslCipher<'a> { } } +pub struct SslSlice<'a>(*mut ffi::SSL, PhantomData<&'a ()>); -pub struct Ssl { - ssl: *mut ffi::SSL, -} +unsafe impl<'a> Send for SslSlice<'a> {} +unsafe impl<'a> Sync for SslSlice<'a> {} -unsafe impl Send for Ssl {} -unsafe impl Sync for Ssl {} - -impl fmt::Debug for Ssl { +impl<'a> fmt::Debug for SslSlice<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("Ssl") + fmt.debug_struct("SslSlice") .field("state", &self.state_string_long()) .finish() } } -impl Drop for Ssl { - fn drop(&mut self) { - unsafe { ffi::SSL_free(self.ssl) } +impl<'a> SslSlice<'a> { + pub unsafe fn from_ptr(ssl: *mut ffi::SSL) -> SslSlice<'a> { + SslSlice(ssl, PhantomData) } -} -impl Ssl { - pub fn new(ctx: &SslContext) -> Result { - let ssl = try_ssl_null!(unsafe { ffi::SSL_new(ctx.ctx) }); - let ssl = Ssl { ssl: ssl }; - Ok(ssl) + pub fn as_ptr(&self) -> *mut ffi::SSL { + self.0 } fn get_raw_rbio(&self) -> *mut ffi::BIO { - unsafe { ffi::SSL_get_rbio(self.ssl) } + unsafe { ffi::SSL_get_rbio(self.as_ptr()) } } - fn connect(&self) -> c_int { - unsafe { ffi::SSL_connect(self.ssl) } + fn connect(&mut self) -> c_int { + unsafe { ffi::SSL_connect(self.as_ptr()) } } - fn accept(&self) -> c_int { - unsafe { ffi::SSL_accept(self.ssl) } + fn accept(&mut self) -> c_int { + unsafe { ffi::SSL_accept(self.as_ptr()) } } - fn handshake(&self) -> c_int { - unsafe { ffi::SSL_do_handshake(self.ssl) } + fn handshake(&mut self) -> c_int { + unsafe { ffi::SSL_do_handshake(self.as_ptr()) } } - fn read(&self, buf: &mut [u8]) -> c_int { + fn read(&mut self, buf: &mut [u8]) -> c_int { let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; - unsafe { ffi::SSL_read(self.ssl, buf.as_ptr() as *mut c_void, len) } + unsafe { ffi::SSL_read(self.as_ptr(), buf.as_ptr() as *mut c_void, len) } } - fn write(&self, buf: &[u8]) -> c_int { + fn write(&mut self, buf: &[u8]) -> c_int { let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; - unsafe { ffi::SSL_write(self.ssl, buf.as_ptr() as *const c_void, len) } + unsafe { ffi::SSL_write(self.as_ptr(), buf.as_ptr() as *const c_void, len) } } fn get_error(&self, ret: c_int) -> c_int { - unsafe { ffi::SSL_get_error(self.ssl, ret) } + unsafe { ffi::SSL_get_error(self.as_ptr(), ret) } } /// Sets the verification mode to be used during the handshake process. /// /// Use `set_verify_callback` to additionally add a callback. pub fn set_verify(&mut self, mode: SslVerifyMode) { - unsafe { ffi::SSL_set_verify(self.ssl, mode.bits as c_int, None) } + unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, None) } } /// Sets the certificate verification callback to be used during the @@ -847,16 +839,16 @@ impl Ssl { { unsafe { let verify = Box::new(verify); - ffi::SSL_set_ex_data(self.ssl, + ffi::SSL_set_ex_data(self.as_ptr(), get_ssl_verify_data_idx::(), mem::transmute(verify)); - ffi::SSL_set_verify(self.ssl, mode.bits as c_int, Some(ssl_raw_verify::)); + ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, Some(ssl_raw_verify::)); } } - pub fn current_cipher<'a>(&'a self) -> Option> { + pub fn current_cipher(&self) -> Option> { unsafe { - let ptr = ffi::SSL_get_current_cipher(self.ssl); + let ptr = ffi::SSL_get_current_cipher(self.as_ptr()); if ptr.is_null() { None @@ -871,7 +863,7 @@ impl Ssl { pub fn state_string(&self) -> &'static str { let state = unsafe { - let ptr = ffi::SSL_state_string(self.ssl); + let ptr = ffi::SSL_state_string(self.as_ptr()); CStr::from_ptr(ptr as *const _) }; @@ -880,7 +872,7 @@ impl Ssl { pub fn state_string_long(&self) -> &'static str { let state = unsafe { - let ptr = ffi::SSL_state_string_long(self.ssl); + let ptr = ffi::SSL_state_string_long(self.as_ptr()); CStr::from_ptr(ptr as *const _) }; @@ -888,10 +880,10 @@ impl Ssl { } /// Sets the host name to be used with SNI (Server Name Indication). - pub fn set_hostname(&self, hostname: &str) -> Result<(), ErrorStack> { + pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> { let cstr = CString::new(hostname).unwrap(); let ret = unsafe { - ffi::SSL_set_tlsext_host_name(self.ssl, cstr.as_ptr() as *mut _) + ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) }; // For this case, 0 indicates failure. @@ -905,7 +897,7 @@ impl Ssl { /// Returns the certificate of the peer, if present. pub fn peer_certificate(&self) -> Option { unsafe { - let ptr = ffi::SSL_get_peer_certificate(self.ssl); + let ptr = ffi::SSL_get_peer_certificate(self.as_ptr()); if ptr.is_null() { None } else { @@ -917,7 +909,7 @@ impl Ssl { /// Returns the name of the protocol used for the connection, e.g. "TLSv1.2", "SSLv3", etc. pub fn version(&self) -> &'static str { let version = unsafe { - let ptr = ffi::SSL_get_version(self.ssl); + let ptr = ffi::SSL_get_version(self.as_ptr()); CStr::from_ptr(ptr as *const _) }; @@ -937,7 +929,7 @@ impl Ssl { let mut len: c_uint = 0; // Get the negotiated protocol from the SSL instance. // `data` will point at a `c_uchar` array; `len` will contain the length of this array. - ffi::SSL_get0_next_proto_negotiated(self.ssl, &mut data, &mut len); + ffi::SSL_get0_next_proto_negotiated(self.as_ptr(), &mut data, &mut len); if data.is_null() { None @@ -960,7 +952,7 @@ impl Ssl { let mut len: c_uint = 0; // Get the negotiated protocol from the SSL instance. // `data` will point at a `c_uchar` array; `len` will contain the length of this array. - ffi::SSL_get0_alpn_selected(self.ssl, &mut data, &mut len); + ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len); if data.is_null() { None @@ -973,7 +965,7 @@ impl Ssl { /// Returns the number of bytes remaining in the currently processed TLS /// record. pub fn pending(&self) -> usize { - unsafe { ffi::SSL_pending(self.ssl) as usize } + unsafe { ffi::SSL_pending(self.as_ptr()) as usize } } /// Returns the compression currently in use. @@ -981,7 +973,7 @@ impl Ssl { /// The result will be either None, indicating no compression is in use, or /// a string with the compression name. pub fn compression(&self) -> Option { - let ptr = unsafe { ffi::SSL_get_current_compression(self.ssl) }; + let ptr = unsafe { ffi::SSL_get_current_compression(self.as_ptr()) }; if ptr == ptr::null() { return None; } @@ -996,14 +988,14 @@ impl Ssl { pub fn ssl_method(&self) -> Option { unsafe { - let method = ffi::SSL_get_ssl_method(self.ssl); + let method = ffi::SSL_get_ssl_method(self.as_ptr()); SslMethod::from_raw(method) } } /// Returns the server's name for the current connection pub fn servername(&self) -> Option { - let name = unsafe { ffi::SSL_get_servername(self.ssl, ffi::TLSEXT_NAMETYPE_host_name) }; + let name = unsafe { ffi::SSL_get_servername(self.as_ptr(), ffi::TLSEXT_NAMETYPE_host_name) }; if name == ptr::null() { return None; } @@ -1012,9 +1004,9 @@ impl Ssl { } /// Changes the context corresponding to the current connection. - pub fn set_ssl_context(&self, ctx: &SslContext) -> Result<(), ErrorStack> { + pub fn set_ssl_context(&mut self, ctx: &SslContext) -> Result<(), ErrorStack> { unsafe { - try_ssl_null!(ffi::SSL_set_SSL_CTX(self.ssl, ctx.ctx)); + try_ssl_null!(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.ctx)); } Ok(()) } @@ -1022,12 +1014,55 @@ impl Ssl { /// Returns the context corresponding to the current connection pub fn ssl_context(&self) -> SslContext { unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(self.ssl); + let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr()); SslContext::new_ref(ssl_ctx) } } } +pub struct Ssl(SslSlice<'static>); + +impl fmt::Debug for Ssl { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Ssl") + .field("state", &self.state_string_long()) + .finish() + } +} + +impl Drop for Ssl { + fn drop(&mut self) { + unsafe { ffi::SSL_free(self.as_ptr()) } + } +} + +impl Deref for Ssl { + type Target = SslSlice<'static>; + + fn deref(&self) -> &SslSlice<'static> { + &self.0 + } +} + +impl DerefMut for Ssl { + fn deref_mut(&mut self) -> &mut SslSlice<'static> { + &mut self.0 + } +} + +impl Ssl { + pub fn new(ctx: &SslContext) -> Result { + unsafe { + let ssl = try_ssl_null!(ffi::SSL_new(ctx.ctx)); + Ok(Ssl::from_ptr(ssl)) + } + } + + pub unsafe fn from_ptr(ssl: *mut ffi::SSL) -> Ssl { + Ssl(SslSlice::from_ptr(ssl)) + } +} + /// A stream wrapper which handles SSL encryption for an underlying stream. pub struct SslStream { ssl: Ssl, @@ -1052,7 +1087,7 @@ impl SslStream { fn new_base(ssl: Ssl, stream: S) -> Self { unsafe { let (bio, method) = bio::new(stream).unwrap(); - ffi::SSL_set_bio(ssl.ssl, bio, bio); + ffi::SSL_set_bio(ssl.as_ptr(), bio, bio); SslStream { ssl: ssl, diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 3216e066..692add2c 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -1052,7 +1052,7 @@ fn flush_panic() { #[test] fn refcount_ssl_context() { - let ssl = { + let mut ssl = { let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); ssl::Ssl::new(&ctx).unwrap() }; From 0854632ff5c5c340e3300951dd06a767a16b11db Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 9 Aug 2016 21:58:48 -0700 Subject: [PATCH 79/96] Make c_helpers optional --- openssl/Cargo.toml | 6 +- openssl/build.rs | 36 ++++-- openssl/src/c_helpers.rs | 7 ++ openssl/src/dh/mod.rs | 4 +- openssl/src/lib.rs | 2 + openssl/src/ssl/mod.rs | 245 +++++++++++++++++++++----------------- openssl/src/x509/mod.rs | 8 +- openssl/src/x509/tests.rs | 3 +- openssl/test/run.sh | 2 +- 9 files changed, 182 insertions(+), 131 deletions(-) create mode 100644 openssl/src/c_helpers.rs diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 4f7243b9..4669f7e5 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -26,6 +26,10 @@ rfc5114 = ["openssl-sys/rfc5114"] ecdh_auto = ["openssl-sys/ecdh_auto"] pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"] +c_helpers = ["gcc"] +x509_clone = ["c_helpers"] +ssl_context_clone = ["c_helpers"] + [dependencies] bitflags = ">= 0.5.0, < 0.8.0" lazy_static = "0.2" @@ -34,7 +38,7 @@ openssl-sys = { version = "0.7.14", path = "../openssl-sys" } openssl-sys-extras = { version = "0.7.14", path = "../openssl-sys-extras" } [build-dependencies] -gcc = "0.3" +gcc = { version = "0.3", optional = true } [dev-dependencies] rustc-serialize = "0.3" diff --git a/openssl/build.rs b/openssl/build.rs index 640b024c..b07c1b3e 100644 --- a/openssl/build.rs +++ b/openssl/build.rs @@ -1,16 +1,28 @@ -extern crate gcc; +#[cfg(feature = "c_helpers")] +mod imp { + extern crate gcc; -use std::env; -use std::path::PathBuf; + use std::env; + use std::path::PathBuf; + + pub fn main() { + let mut config = gcc::Config::new(); + + if let Some(paths) = env::var_os("DEP_OPENSSL_INCLUDE") { + for path in env::split_paths(&paths) { + config.include(PathBuf::from(path)); + } + } + + config.file("src/c_helpers.c").compile("libc_helpers.a"); + } +} + +#[cfg(not(feature = "c_helpers"))] +mod imp { + pub fn main() {} +} fn main() { - let mut config = gcc::Config::new(); - - if let Some(paths) = env::var_os("DEP_OPENSSL_INCLUDE") { - for path in env::split_paths(&paths) { - config.include(PathBuf::from(path)); - } - } - - config.file("src/c_helpers.c").compile("libc_helpers.a"); + imp::main() } diff --git a/openssl/src/c_helpers.rs b/openssl/src/c_helpers.rs new file mode 100644 index 00000000..3d938192 --- /dev/null +++ b/openssl/src/c_helpers.rs @@ -0,0 +1,7 @@ +use ffi; + +#[allow(dead_code)] +extern "C" { + pub fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX); + pub fn rust_X509_clone(x509: *mut ffi::X509); +} diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index 9058e8db..101e2b0d 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -101,7 +101,7 @@ mod tests { 5FBD3") .unwrap(); let dh = DH::from_params(p, g, q).unwrap(); - ctx.set_tmp_dh(dh).unwrap(); + ctx.set_tmp_dh(&dh).unwrap(); } #[test] @@ -109,6 +109,6 @@ mod tests { let mut ctx = SslContext::new(Sslv23).unwrap(); let params = include_bytes!("../../test/dhparams.pem"); let dh = DH::from_pem(params).ok().expect("Failed to load PEM"); - ctx.set_tmp_dh(dh).unwrap(); + ctx.set_tmp_dh(&dh).unwrap(); } } diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index a694d536..2f3664ac 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -24,6 +24,8 @@ mod macros; pub mod asn1; mod bio; pub mod bn; +#[cfg(feature = "c_helpers")] +mod c_helpers; pub mod crypto; pub mod dh; pub mod error; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 4f5dee61..792762a9 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -37,10 +37,6 @@ use self::bio::BioMethod; #[doc(inline)] pub use ssl::error::Error; -extern "C" { - fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX); -} - bitflags! { pub flags SslContextOptions: c_long { const SSL_OP_MICROSOFT_SESS_ID_BUG = ffi::SSL_OP_MICROSOFT_SESS_ID_BUG, @@ -259,13 +255,13 @@ extern "C" fn ssl_raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_ST } extern "C" fn raw_sni(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) -> c_int - where F: Fn(&mut SslSlice) -> Result<(), SniError> + Any + 'static + Sync + Send + where F: Fn(&mut SslRef) -> Result<(), SniError> + Any + 'static + Sync + Send { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); let callback: &F = mem::transmute(callback); - let mut ssl = SslSlice::from_ptr(ssl); + let mut ssl = SslRef::from_ptr(ssl); match callback(&mut ssl) { Ok(()) => ffi::SSL_TLSEXT_ERR_OK, @@ -403,67 +399,22 @@ fn wrap_ssl_result(res: c_int) -> Result<(), ErrorStack> { } } -/// An SSL context object -/// -/// Internally ref-counted, use `.clone()` in the same way as Rc and Arc. -pub struct SslContext { - ctx: *mut ffi::SSL_CTX, -} +/// A borrowed SSL context object. +pub struct SslContextRef<'a>(*mut ffi::SSL_CTX, PhantomData<&'a ()>); -unsafe impl Send for SslContext {} -unsafe impl Sync for SslContext {} - -impl Clone for SslContext { - fn clone(&self) -> Self { - unsafe { SslContext::new_ref(self.ctx) } - } -} - -// TODO: add useful info here -impl fmt::Debug for SslContext { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "SslContext") - } -} - -impl Drop for SslContext { - fn drop(&mut self) { - unsafe { ffi::SSL_CTX_free(self.ctx) } - } -} - -impl SslContext { - // Create a new SslContext given an existing ref, and incriment ref-count appropriately. - unsafe fn new_ref(ctx: *mut ffi::SSL_CTX) -> SslContext { - rust_SSL_CTX_clone(ctx); - SslContext { ctx: ctx } +impl<'a> SslContextRef<'a> { + pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextRef<'a> { + SslContextRef(ctx, PhantomData) } - /// Creates a new SSL context. - pub fn new(method: SslMethod) -> Result { - init(); - - let ctx = try_ssl_null!(unsafe { ffi::SSL_CTX_new(method.to_raw()) }); - - let mut ctx = SslContext { ctx: ctx }; - - match method { - #[cfg(feature = "dtlsv1")] - SslMethod::Dtlsv1 => ctx.set_read_ahead(1), - #[cfg(feature = "dtlsv1_2")] - SslMethod::Dtlsv1_2 => ctx.set_read_ahead(1), - _ => {} - } - // this is a bit dubious (?) - try!(ctx.set_mode(ffi::SSL_MODE_AUTO_RETRY | ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)); - - Ok(ctx) + pub fn as_ptr(&self) -> *mut ffi::SSL_CTX { + self.0 } /// Configures the certificate verification method for new connections. pub fn set_verify(&mut self, mode: SslVerifyMode) { unsafe { - ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, None); + ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, None); } } @@ -474,8 +425,8 @@ impl SslContext { { unsafe { let verify = Box::new(verify); - ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::(), mem::transmute(verify)); - ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(raw_verify::)); + ffi::SSL_CTX_set_ex_data(self.as_ptr(), get_verify_data_idx::(), mem::transmute(verify)); + ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, Some(raw_verify::)); } } @@ -484,36 +435,38 @@ impl SslContext { /// Obtain the server name with `servername` then set the corresponding context /// with `set_ssl_context` pub fn set_servername_callback(&mut self, callback: F) - where F: Fn(&mut SslSlice) -> Result<(), SniError> + Any + 'static + Sync + Send + where F: Fn(&mut SslRef) -> Result<(), SniError> + Any + 'static + Sync + Send { unsafe { let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::(), mem::transmute(callback)); + ffi::SSL_CTX_set_ex_data(self.as_ptr(), + get_verify_data_idx::(), + mem::transmute(callback)); let f: extern "C" fn(_, _, _) -> _ = raw_sni::; let f: extern "C" fn() = mem::transmute(f); - ffi::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); + ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(f)); } } /// Sets verification depth pub fn set_verify_depth(&mut self, depth: u32) { unsafe { - ffi::SSL_CTX_set_verify_depth(self.ctx, depth as c_int); + ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int); } } pub fn set_read_ahead(&mut self, m: u32) { unsafe { - ffi::SSL_CTX_set_read_ahead(self.ctx, m as c_long); + ffi::SSL_CTX_set_read_ahead(self.as_ptr(), m as c_long); } } fn set_mode(&mut self, mode: c_long) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_set_mode(self.ctx, mode) as c_int }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_set_mode(self.as_ptr(), mode) as c_int }) } - pub fn set_tmp_dh(&mut self, dh: DH) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 }) + pub fn set_tmp_dh(&mut self, dh: &DH) -> Result<(), ErrorStack> { + wrap_ssl_result(unsafe { ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.raw()) as i32 }) } /// Use the default locations of trusted certificates for verification. @@ -522,7 +475,7 @@ impl SslContext { /// environment variables if present, or defaults specified at OpenSSL /// build time otherwise. pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_set_default_verify_paths(self.ctx) }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_set_default_verify_paths(self.as_ptr()) }) } #[allow(non_snake_case)] @@ -530,7 +483,7 @@ impl SslContext { pub fn set_CA_file>(&mut self, file: P) -> Result<(), ErrorStack> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result(unsafe { - ffi::SSL_CTX_load_verify_locations(self.ctx, file.as_ptr() as *const _, ptr::null()) + ffi::SSL_CTX_load_verify_locations(self.as_ptr(), file.as_ptr() as *const _, ptr::null()) }) } @@ -544,7 +497,7 @@ impl SslContext { /// handshake and need to be restarted. pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { - ffi::SSL_CTX_set_session_id_context(self.ctx, sid_ctx.as_ptr(), sid_ctx.len() as u32) + ffi::SSL_CTX_set_session_id_context(self.as_ptr(), sid_ctx.as_ptr(), sid_ctx.len() as u32) }) } @@ -555,7 +508,7 @@ impl SslContext { -> Result<(), ErrorStack> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result(unsafe { - ffi::SSL_CTX_use_certificate_file(self.ctx, + ffi::SSL_CTX_use_certificate_file(self.as_ptr(), file.as_ptr() as *const _, file_type as c_int) }) @@ -568,7 +521,7 @@ impl SslContext { -> Result<(), ErrorStack> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result(unsafe { - ffi::SSL_CTX_use_certificate_chain_file(self.ctx, + ffi::SSL_CTX_use_certificate_chain_file(self.as_ptr(), file.as_ptr() as *const _, file_type as c_int) }) @@ -576,14 +529,14 @@ impl SslContext { /// Specifies the certificate pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate(self.ctx, cert.handle()) }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.handle()) }) } /// Adds a certificate to the certificate chain presented together with the /// certificate specified using set_certificate() pub fn add_extra_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { - ffi::SSL_CTX_add_extra_chain_cert(self.ctx, cert.handle()) as c_int + ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.handle()) as c_int }) } @@ -594,7 +547,7 @@ impl SslContext { -> Result<(), ErrorStack> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result(unsafe { - ffi::SSL_CTX_use_PrivateKey_file(self.ctx, + ffi::SSL_CTX_use_PrivateKey_file(self.as_ptr(), file.as_ptr() as *const _, file_type as c_int) }) @@ -602,18 +555,18 @@ impl SslContext { /// Specifies the private key pub fn set_private_key(&mut self, key: &PKey) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey(self.ctx, key.handle()) }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.handle()) }) } /// Check consistency of private key and certificate pub fn check_private_key(&mut self) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_check_private_key(self.ctx) }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_check_private_key(self.as_ptr()) }) } pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { let cipher_list = CString::new(cipher_list).unwrap(); - ffi::SSL_CTX_set_cipher_list(self.ctx, cipher_list.as_ptr() as *const _) + ffi::SSL_CTX_set_cipher_list(self.as_ptr(), cipher_list.as_ptr() as *const _) }) } @@ -623,21 +576,21 @@ impl SslContext { /// This method requires OpenSSL >= 1.0.2 or LibreSSL and the `ecdh_auto` feature. #[cfg(feature = "ecdh_auto")] pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_set_ecdh_auto(self.ctx, onoff as c_long) as c_int }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_long) as c_int }) } pub fn set_options(&mut self, option: SslContextOptions) -> SslContextOptions { - let ret = unsafe { ffi::SSL_CTX_set_options(self.ctx, option.bits()) }; + let ret = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) }; SslContextOptions::from_bits(ret).unwrap() } pub fn options(&self) -> SslContextOptions { - let ret = unsafe { ffi::SSL_CTX_get_options(self.ctx) }; + let ret = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) }; SslContextOptions::from_bits(ret).unwrap() } pub fn clear_options(&mut self, option: SslContextOptions) -> SslContextOptions { - let ret = unsafe { ffi::SSL_CTX_clear_options(self.ctx, option.bits()) }; + let ret = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) }; SslContextOptions::from_bits(ret).unwrap() } @@ -654,16 +607,16 @@ impl SslContext { unsafe { // Attach the protocol list to the OpenSSL context structure, // so that we can refer to it within the callback. - ffi::SSL_CTX_set_ex_data(self.ctx, *NPN_PROTOS_IDX, mem::transmute(protocols)); + ffi::SSL_CTX_set_ex_data(self.as_ptr(), *NPN_PROTOS_IDX, mem::transmute(protocols)); // Now register the callback that performs the default protocol // matching based on the client-supported list of protocols that // has been saved. - ffi::SSL_CTX_set_next_proto_select_cb(self.ctx, + ffi::SSL_CTX_set_next_proto_select_cb(self.as_ptr(), raw_next_proto_select_cb, ptr::null_mut()); // Also register the callback to advertise these protocols, if a server socket is // created with the context. - ffi::SSL_CTX_set_next_protos_advertised_cb(self.ctx, + ffi::SSL_CTX_set_next_protos_advertised_cb(self.as_ptr(), raw_next_protos_advertise_cb, ptr::null_mut()); } @@ -682,22 +635,98 @@ impl SslContext { let protocols: Box> = Box::new(ssl_encode_byte_strings(protocols)); unsafe { // Set the context's internal protocol list for use if we are a server - ffi::SSL_CTX_set_alpn_protos(self.ctx, protocols.as_ptr(), protocols.len() as c_uint); + ffi::SSL_CTX_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as c_uint); // Rather than use the argument to the callback to contain our data, store it in the // ssl ctx's ex_data so that we can configure a function to free it later. In the // future, it might make sense to pull this into our internal struct Ssl instead of // leaning on openssl and using function pointers. - ffi::SSL_CTX_set_ex_data(self.ctx, *ALPN_PROTOS_IDX, mem::transmute(protocols)); + ffi::SSL_CTX_set_ex_data(self.as_ptr(), *ALPN_PROTOS_IDX, mem::transmute(protocols)); // Now register the callback that performs the default protocol // matching based on the client-supported list of protocols that // has been saved. - ffi::SSL_CTX_set_alpn_select_cb(self.ctx, raw_alpn_select_cb, ptr::null_mut()); + ffi::SSL_CTX_set_alpn_select_cb(self.as_ptr(), raw_alpn_select_cb, ptr::null_mut()); } } } +/// An owned SSL context object. +pub struct SslContext(SslContextRef<'static>); + +unsafe impl Send for SslContext {} +unsafe impl Sync for SslContext {} + +#[cfg(feature = "ssl_context_clone")] +impl Clone for SslContext { + /// Requires the `ssl_context_clone` feature. + fn clone(&self) -> Self { + unsafe { + ::c_helpers::rust_SSL_CTX_clone(self.as_ptr()); + SslContext::from_ptr(self.as_ptr()) + } + } +} + +// TODO: add useful info here +impl fmt::Debug for SslContext { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "SslContext") + } +} + +impl Drop for SslContext { + fn drop(&mut self) { + unsafe { ffi::SSL_CTX_free(self.as_ptr()) } + } +} + +impl Deref for SslContext { + type Target = SslContextRef<'static>; + + fn deref(&self) -> &SslContextRef<'static> { + &self.0 + } +} + +impl DerefMut for SslContext { + fn deref_mut(&mut self) -> &mut SslContextRef<'static> { + &mut self.0 + } +} + +impl SslContext { + /// Creates a new SSL context. + pub fn new(method: SslMethod) -> Result { + init(); + + let mut ctx = unsafe { + let ctx = try_ssl_null!(ffi::SSL_CTX_new(method.to_raw())); + SslContext::from_ptr(ctx) + }; + + match method { + #[cfg(feature = "dtlsv1")] + SslMethod::Dtlsv1 => ctx.set_read_ahead(1), + #[cfg(feature = "dtlsv1_2")] + SslMethod::Dtlsv1_2 => ctx.set_read_ahead(1), + _ => {} + } + // this is a bit dubious (?) + try!(ctx.set_mode(ffi::SSL_MODE_AUTO_RETRY | ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)); + + Ok(ctx) + } + + pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContext { + SslContext(SslContextRef::from_ptr(ctx)) + } + + pub fn as_ptr(&self) -> *mut ffi::SSL_CTX { + (**self).as_ptr() + } +} + pub struct CipherBits { /// The number of secret bits used for the cipher. @@ -768,22 +797,22 @@ impl<'a> SslCipher<'a> { } } -pub struct SslSlice<'a>(*mut ffi::SSL, PhantomData<&'a ()>); +pub struct SslRef<'a>(*mut ffi::SSL, PhantomData<&'a ()>); -unsafe impl<'a> Send for SslSlice<'a> {} -unsafe impl<'a> Sync for SslSlice<'a> {} +unsafe impl<'a> Send for SslRef<'a> {} +unsafe impl<'a> Sync for SslRef<'a> {} -impl<'a> fmt::Debug for SslSlice<'a> { +impl<'a> fmt::Debug for SslRef<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("SslSlice") + fmt.debug_struct("SslRef") .field("state", &self.state_string_long()) .finish() } } -impl<'a> SslSlice<'a> { - pub unsafe fn from_ptr(ssl: *mut ffi::SSL) -> SslSlice<'a> { - SslSlice(ssl, PhantomData) +impl<'a> SslRef<'a> { + pub unsafe fn from_ptr(ssl: *mut ffi::SSL) -> SslRef<'a> { + SslRef(ssl, PhantomData) } pub fn as_ptr(&self) -> *mut ffi::SSL { @@ -1004,23 +1033,23 @@ impl<'a> SslSlice<'a> { } /// Changes the context corresponding to the current connection. - pub fn set_ssl_context(&mut self, ctx: &SslContext) -> Result<(), ErrorStack> { + pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> { unsafe { - try_ssl_null!(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.ctx)); + try_ssl_null!(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())); } Ok(()) } /// Returns the context corresponding to the current connection - pub fn ssl_context(&self) -> SslContext { + pub fn ssl_context(&self) -> SslContextRef<'a> { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr()); - SslContext::new_ref(ssl_ctx) + SslContextRef::from_ptr(ssl_ctx) } } } -pub struct Ssl(SslSlice<'static>); +pub struct Ssl(SslRef<'static>); impl fmt::Debug for Ssl { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { @@ -1037,15 +1066,15 @@ impl Drop for Ssl { } impl Deref for Ssl { - type Target = SslSlice<'static>; + type Target = SslRef<'static>; - fn deref(&self) -> &SslSlice<'static> { + fn deref(&self) -> &SslRef<'static> { &self.0 } } impl DerefMut for Ssl { - fn deref_mut(&mut self) -> &mut SslSlice<'static> { + fn deref_mut(&mut self) -> &mut SslRef<'static> { &mut self.0 } } @@ -1053,13 +1082,13 @@ impl DerefMut for Ssl { impl Ssl { pub fn new(ctx: &SslContext) -> Result { unsafe { - let ssl = try_ssl_null!(ffi::SSL_new(ctx.ctx)); + let ssl = try_ssl_null!(ffi::SSL_new(ctx.as_ptr())); Ok(Ssl::from_ptr(ssl)) } } pub unsafe fn from_ptr(ssl: *mut ffi::SSL) -> Ssl { - Ssl(SslSlice::from_ptr(ssl)) + Ssl(SslRef::from_ptr(ssl)) } } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 10537ea2..b7503e0a 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -473,14 +473,12 @@ impl Deref for X509 { } } -extern "C" { - fn rust_X509_clone(x509: *mut ffi::X509); -} - +#[cfg(feature = "x509_clone")] impl Clone for X509 { + /// Requires the `x509_clone` feature. fn clone(&self) -> X509 { unsafe { - rust_X509_clone(self.handle()); + ::c_helpers::rust_X509_clone(self.handle()); X509::new(self.handle()) } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index da1523af..ab480836 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -26,8 +26,7 @@ fn get_generator() -> X509Generator { fn pkey() -> PKey { let rsa = RSA::generate(2048).unwrap(); - let mut pkey = PKey::from_rsa(rsa).unwrap(); - pkey + PKey::from_rsa(rsa).unwrap() } #[test] diff --git a/openssl/test/run.sh b/openssl/test/run.sh index cbd46cc6..9f833e65 100755 --- a/openssl/test/run.sh +++ b/openssl/test/run.sh @@ -4,7 +4,7 @@ set -e MAIN_TARGETS=https://static.rust-lang.org/dist if [ "$TEST_FEATURES" == "true" ]; then - FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac" + FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac x509_clone ssl_context_clone" fi if [ "$TRAVIS_OS_NAME" != "osx" ]; then From 1ac54b06e9c68ecc79e4bb0c4f65296c669a6cc8 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 9 Aug 2016 22:15:16 -0700 Subject: [PATCH 80/96] Move X509_get_extensions to openssl helpers --- openssl-sys-extras/src/openssl_shim.c | 4 ---- openssl/Cargo.toml | 1 + openssl/src/c_helpers.c | 4 ++++ openssl/src/c_helpers.rs | 1 + openssl/src/x509/mod.rs | 6 ++++-- openssl/src/x509/tests.rs | 1 + openssl/test/run.sh | 2 +- 7 files changed, 12 insertions(+), 7 deletions(-) diff --git a/openssl-sys-extras/src/openssl_shim.c b/openssl-sys-extras/src/openssl_shim.c index db2a8786..974312b9 100644 --- a/openssl-sys-extras/src/openssl_shim.c +++ b/openssl-sys-extras/src/openssl_shim.c @@ -138,7 +138,3 @@ DH *DH_new_from_params(BIGNUM *p, BIGNUM *g, BIGNUM *q) { long SSL_set_tlsext_host_name_shim(SSL *s, char *name) { return SSL_set_tlsext_host_name(s, name); } - -STACK_OF(X509_EXTENSION) *X509_get_extensions_shim(X509 *x) { - return x->cert_info ? x->cert_info->extensions : NULL; -} diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 4669f7e5..f4f4673c 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -28,6 +28,7 @@ pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"] c_helpers = ["gcc"] x509_clone = ["c_helpers"] +x509_generator_request = ["c_helpers"] ssl_context_clone = ["c_helpers"] [dependencies] diff --git a/openssl/src/c_helpers.c b/openssl/src/c_helpers.c index 5b1b9615..f8bc2d0d 100644 --- a/openssl/src/c_helpers.c +++ b/openssl/src/c_helpers.c @@ -7,3 +7,7 @@ void rust_SSL_CTX_clone(SSL_CTX *ctx) { void rust_X509_clone(X509 *x509) { CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); } + +STACK_OF(X509_EXTENSION) *rust_X509_get_extensions(X509 *x) { + return x->cert_info ? x->cert_info->extensions : NULL; +} diff --git a/openssl/src/c_helpers.rs b/openssl/src/c_helpers.rs index 3d938192..f074d404 100644 --- a/openssl/src/c_helpers.rs +++ b/openssl/src/c_helpers.rs @@ -4,4 +4,5 @@ use ffi; extern "C" { pub fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX); pub fn rust_X509_clone(x509: *mut ffi::X509); + pub fn rust_X509_get_extensions(x: *mut ffi::X509) -> *mut ffi::stack_st_X509_EXTENSION; } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index b7503e0a..3bdbaa67 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -17,7 +17,6 @@ use crypto::hash::Type as HashType; use crypto::pkey::PKey; use crypto::rand::rand_bytes; use ffi; -use ffi_extras; use nid::Nid; use error::ErrorStack; @@ -346,6 +345,9 @@ impl X509Generator { } /// Obtain a certificate signing request (CSR) + /// + /// Requries the `x509_generator_request` feature. + #[cfg(feature = "x509_generator_request")] pub fn request(&self, p_key: &PKey) -> Result { let cert = match self.sign(p_key) { Ok(c) => c, @@ -356,7 +358,7 @@ impl X509Generator { let req = ffi::X509_to_X509_REQ(cert.handle(), ptr::null_mut(), ptr::null()); try_ssl_null!(req); - let exts = ffi_extras::X509_get_extensions(cert.handle()); + let exts = ::c_helpers::rust_X509_get_extensions(cert.handle()); if exts != ptr::null_mut() { try_ssl!(ffi::X509_REQ_add_extensions(req, exts)); } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index ab480836..c09b31cd 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -69,6 +69,7 @@ fn test_cert_gen_extension_bad_ordering() { } #[test] +#[cfg(feature = "x509_generator_request")] fn test_req_gen() { let pkey = pkey(); diff --git a/openssl/test/run.sh b/openssl/test/run.sh index 9f833e65..22a54c4d 100755 --- a/openssl/test/run.sh +++ b/openssl/test/run.sh @@ -4,7 +4,7 @@ set -e MAIN_TARGETS=https://static.rust-lang.org/dist if [ "$TEST_FEATURES" == "true" ]; then - FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac x509_clone ssl_context_clone" + FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac x509_clone ssl_context_clone x509_generator_request" fi if [ "$TRAVIS_OS_NAME" != "osx" ]; then From 966c5385ea3203a8c273b8000a23d4fc4145aeb5 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 9 Aug 2016 22:26:18 -0700 Subject: [PATCH 81/96] Fix build --- openssl/src/dh/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index 101e2b0d..c0122d44 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -67,11 +67,11 @@ mod tests { fn test_dh_rfc5114() { let mut ctx = SslContext::new(Sslv23).unwrap(); let dh1 = DH::get_1024_160().unwrap(); - ctx.set_tmp_dh(dh1).unwrap(); + ctx.set_tmp_dh(&dh1).unwrap(); let dh2 = DH::get_2048_224().unwrap(); - ctx.set_tmp_dh(dh2).unwrap(); + ctx.set_tmp_dh(&dh2).unwrap(); let dh3 = DH::get_2048_256().unwrap(); - ctx.set_tmp_dh(dh3).unwrap(); + ctx.set_tmp_dh(&dh3).unwrap(); } #[test] From 67b5b4d814066eaf0debbe3b95d68ae0d7b9226a Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 9 Aug 2016 22:52:12 -0700 Subject: [PATCH 82/96] Make hmac support optional and remove openssl-sys-extras rust-openssl no longer requires headers for the default feature set. --- openssl-sys-extras/Cargo.toml | 19 ---- openssl-sys-extras/build.rs | 77 -------------- openssl-sys-extras/src/lib.rs | 82 --------------- openssl-sys-extras/src/openssl_shim.c | 140 -------------------------- openssl-sys-extras/src/ssl_options.rs | 46 --------- openssl-sys/Cargo.toml | 1 + openssl-sys/src/lib.rs | 2 + openssl/Cargo.toml | 3 +- openssl/src/c_helpers.c | 34 +++++++ openssl/src/c_helpers.rs | 5 + openssl/src/crypto/hmac.rs | 36 +++---- openssl/src/crypto/mod.rs | 1 + openssl/src/lib.rs | 1 - 13 files changed, 64 insertions(+), 383 deletions(-) delete mode 100644 openssl-sys-extras/Cargo.toml delete mode 100644 openssl-sys-extras/build.rs delete mode 100644 openssl-sys-extras/src/lib.rs delete mode 100644 openssl-sys-extras/src/openssl_shim.c delete mode 100644 openssl-sys-extras/src/ssl_options.rs diff --git a/openssl-sys-extras/Cargo.toml b/openssl-sys-extras/Cargo.toml deleted file mode 100644 index 903305d7..00000000 --- a/openssl-sys-extras/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "openssl-sys-extras" -version = "0.7.14" -authors = ["Steven Fackler "] -license = "MIT" -description = "Extra FFI bindings to OpenSSL that require a C shim" -repository = "https://github.com/sfackler/rust-openssl" -documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.14/openssl_sys_extras" -build = "build.rs" - -[features] -ecdh_auto = [] - -[dependencies] -libc = "0.2" -openssl-sys = { version = "0.7.14", path = "../openssl-sys" } - -[build-dependencies] -gcc = "0.3" diff --git a/openssl-sys-extras/build.rs b/openssl-sys-extras/build.rs deleted file mode 100644 index e3c695b1..00000000 --- a/openssl-sys-extras/build.rs +++ /dev/null @@ -1,77 +0,0 @@ -extern crate gcc; - -use std::env; -use std::path::PathBuf; -use std::fs::File; -use std::io::Write as IoWrite; -use std::fmt::Write; - -fn main() { - let options_shim_file = generate_options_shim(); - let mut config = gcc::Config::new(); - - if let Some(paths) = env::var_os("DEP_OPENSSL_INCLUDE") { - for path in env::split_paths(&paths) { - config.include(PathBuf::from(path)); - } - } - - config.file("src/openssl_shim.c") - .file(options_shim_file) - .compile("libopenssl_shim.a"); -} - -macro_rules! import_options { - ( $( $name:ident $val:expr )* ) => { - &[ $( (stringify!($name),$val), )* ] - }; -} - -fn generate_options_shim() -> PathBuf { - let options: &[(&'static str,u64)]=include!("src/ssl_options.rs"); - let mut shim = String::new(); - writeln!(shim,"#include ").unwrap(); - writeln!(shim,"#include ").unwrap(); - - for &(name,value) in options { - writeln!(shim,"#define RUST_{} UINT64_C({})",name,value).unwrap(); - writeln!(shim,"#ifndef {}",name).unwrap(); - writeln!(shim,"# define {} 0",name).unwrap(); - writeln!(shim,"#endif").unwrap(); - } - - writeln!(shim,"#define COPY_MASK ( \\").unwrap(); - - let mut it=options.iter().peekable(); - while let Some(&(name,_))=it.next() { - let eol=match it.peek() { - Some(_) => " | \\", - None => " )" - }; - writeln!(shim," ((RUST_{0}==(uint64_t)(uint32_t){0})?RUST_{0}:UINT64_C(0)){1}",name,eol).unwrap(); - } - - writeln!(shim,"long rust_openssl_ssl_ctx_options_rust_to_c(uint64_t rustval) {{").unwrap(); - writeln!(shim," long cval=rustval©_MASK;").unwrap(); - for &(name,_) in options { - writeln!(shim," if (rustval&RUST_{0}) cval|={0};",name).unwrap(); - } - writeln!(shim," return cval;").unwrap(); - writeln!(shim,"}}").unwrap(); - - writeln!(shim,"uint64_t rust_openssl_ssl_ctx_options_c_to_rust(long cval) {{").unwrap(); - writeln!(shim," uint64_t rustval=cval©_MASK;").unwrap(); - for &(name,_) in options { - writeln!(shim," if (cval&{0}) rustval|=RUST_{0};",name).unwrap(); - } - writeln!(shim," return rustval;").unwrap(); - writeln!(shim,"}}").unwrap(); - - let out_dir = env::var("OUT_DIR").unwrap(); - let dest_file = PathBuf::from(&out_dir).join("ssl_ctx_options_shim.c"); - let mut f = File::create(&dest_file).unwrap(); - - f.write_all(shim.as_bytes()).unwrap(); - - dest_file -} diff --git a/openssl-sys-extras/src/lib.rs b/openssl-sys-extras/src/lib.rs deleted file mode 100644 index 8e7542fc..00000000 --- a/openssl-sys-extras/src/lib.rs +++ /dev/null @@ -1,82 +0,0 @@ -#![allow(non_upper_case_globals, non_snake_case)] -#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.14")] - -extern crate openssl_sys; -extern crate libc; - -use libc::{c_int, c_uint, c_long, c_char, c_void}; -use openssl_sys::{HMAC_CTX, EVP_MD, ENGINE, SSL_CTX, BIO, X509, stack_st_X509_EXTENSION, SSL, DH}; - -macro_rules! import_options { - ( $( $name:ident $val:expr )* ) => { - $( pub const $name: u64 = $val; )* - }; -} - -include!("ssl_options.rs"); - -pub unsafe fn SSL_CTX_set_options(ssl: *mut SSL_CTX, op: u64) -> u64 { - rust_openssl_ssl_ctx_options_c_to_rust(SSL_CTX_set_options_shim(ssl, rust_openssl_ssl_ctx_options_rust_to_c(op))) -} - -pub unsafe fn SSL_CTX_get_options(ssl: *mut SSL_CTX) -> u64 { - rust_openssl_ssl_ctx_options_c_to_rust(SSL_CTX_get_options_shim(ssl)) -} - -pub unsafe fn SSL_CTX_clear_options(ssl: *mut SSL_CTX, op: u64) -> u64 { - rust_openssl_ssl_ctx_options_c_to_rust(SSL_CTX_clear_options_shim(ssl, rust_openssl_ssl_ctx_options_rust_to_c(op))) -} - -extern { - fn rust_openssl_ssl_ctx_options_rust_to_c(rustval: u64) -> c_long; - fn rust_openssl_ssl_ctx_options_c_to_rust(cval: c_long) -> u64; - - // Pre-1.0 versions of these didn't return anything, so the shims bridge that gap - #[cfg_attr(not(target_os = "nacl"), link_name = "HMAC_Init_ex_shim")] - pub fn HMAC_Init_ex(ctx: *mut HMAC_CTX, key: *const u8, keylen: c_int, md: *const EVP_MD, imple: *const ENGINE) -> c_int; - #[cfg_attr(not(target_os = "nacl"), link_name = "HMAC_Final_shim")] - pub fn HMAC_Final(ctx: *mut HMAC_CTX, output: *mut u8, len: *mut c_uint) -> c_int; - #[cfg_attr(not(target_os = "nacl"), link_name = "HMAC_Update_shim")] - pub fn HMAC_Update(ctx: *mut HMAC_CTX, input: *const u8, len: c_uint) -> c_int; - - // This isn't defined in < 1.0 so we copy the implementation there - pub fn HMAC_CTX_copy(dst: *mut HMAC_CTX, src: *const HMAC_CTX) -> c_int; - - // These functions are defined in OpenSSL as macros, so we shim them - #[link_name = "BIO_eof_shim"] - pub fn BIO_eof(b: *mut BIO) -> c_int; - #[link_name = "BIO_set_nbio_shim"] - pub fn BIO_set_nbio(b: *mut BIO, enabled: c_long) -> c_long; - #[link_name = "BIO_set_mem_eof_return_shim"] - pub fn BIO_set_mem_eof_return(b: *mut BIO, v: c_int); - #[link_name = "BIO_clear_retry_flags_shim"] - pub fn BIO_clear_retry_flags(b: *mut BIO); - #[link_name = "BIO_set_retry_read_shim"] - pub fn BIO_set_retry_read(b: *mut BIO); - #[link_name = "BIO_set_retry_write_shim"] - pub fn BIO_set_retry_write(b: *mut BIO); - #[link_name = "BIO_flush"] - pub fn BIO_flush(b: *mut BIO) -> c_long; - pub fn SSL_CTX_set_options_shim(ctx: *mut SSL_CTX, options: c_long) -> c_long; - pub fn SSL_CTX_get_options_shim(ctx: *mut SSL_CTX) -> c_long; - pub fn SSL_CTX_clear_options_shim(ctx: *mut SSL_CTX, options: c_long) -> c_long; - #[link_name = "SSL_CTX_set_mode_shim"] - pub fn SSL_CTX_set_mode(ctx: *mut SSL_CTX, options: c_long) -> c_long; - #[link_name = "SSL_CTX_add_extra_chain_cert_shim"] - pub fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) -> c_long; - #[link_name = "SSL_CTX_set_read_ahead_shim"] - pub fn SSL_CTX_set_read_ahead(ctx: *mut SSL_CTX, m: c_long) -> c_long; - #[cfg(feature = "ecdh_auto")] - #[link_name = "SSL_CTX_set_ecdh_auto_shim"] - pub fn SSL_CTX_set_ecdh_auto(ssl: *mut SSL_CTX, onoff: c_int) -> c_int; - #[link_name = "SSL_set_tlsext_host_name_shim"] - pub fn SSL_set_tlsext_host_name(s: *mut SSL, name: *const c_char) -> c_long; - #[link_name = "SSL_CTX_set_tmp_dh_shim"] - pub fn SSL_CTX_set_tmp_dh(s: *mut SSL, dh: *const DH) -> c_long; - #[link_name = "X509_get_extensions_shim"] - pub fn X509_get_extensions(x: *mut X509) -> *mut stack_st_X509_EXTENSION; - #[link_name = "SSL_CTX_set_tlsext_servername_callback_shim"] - pub fn SSL_CTX_set_tlsext_servername_callback(ssl: *mut SSL_CTX, callback: Option); - #[link_name = "SSL_CTX_set_tlsext_servername_arg_shim"] - pub fn SSL_CTX_set_tlsext_servername_arg(ssl: *mut SSL_CTX, arg: *const c_void); -} diff --git a/openssl-sys-extras/src/openssl_shim.c b/openssl-sys-extras/src/openssl_shim.c deleted file mode 100644 index 974312b9..00000000 --- a/openssl-sys-extras/src/openssl_shim.c +++ /dev/null @@ -1,140 +0,0 @@ -#include -#include -#include -#include - -#if OPENSSL_VERSION_NUMBER < 0x10000000L -// Copied from openssl crypto/hmac/hmac.c -int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) - { - if (!EVP_MD_CTX_copy(&dctx->i_ctx, &sctx->i_ctx)) - goto err; - if (!EVP_MD_CTX_copy(&dctx->o_ctx, &sctx->o_ctx)) - goto err; - if (!EVP_MD_CTX_copy(&dctx->md_ctx, &sctx->md_ctx)) - goto err; - memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK); - dctx->key_length = sctx->key_length; - dctx->md = sctx->md; - return 1; - err: - return 0; - } - -int HMAC_Init_ex_shim(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl) { - HMAC_Init_ex(ctx, key, key_len, md, impl); - return 1; -} - -int HMAC_Update_shim(HMAC_CTX *ctx, const unsigned char *data, int len) { - HMAC_Update(ctx, data, len); - return 1; -} - -int HMAC_Final_shim(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) { - HMAC_Final(ctx, md, len); - return 1; -} - -#else - -int HMAC_Init_ex_shim(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl) { - return HMAC_Init_ex(ctx, key, key_len, md, impl); -} - -int HMAC_Update_shim(HMAC_CTX *ctx, const unsigned char *data, int len) { - return HMAC_Update(ctx, data, len); -} - -int HMAC_Final_shim(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) { - return HMAC_Final(ctx, md, len); -} -#endif - -// shims for OpenSSL macros - -int BIO_eof_shim(BIO *b) { - return BIO_eof(b); -} - -long BIO_set_nbio_shim(BIO *b, long enabled) { - return BIO_set_nbio(b, enabled); -} - -void BIO_set_mem_eof_return_shim(BIO *b, int v) { - BIO_set_mem_eof_return(b, v); -} - -void BIO_clear_retry_flags_shim(BIO *b) { - BIO_clear_retry_flags(b); -} - -void BIO_set_retry_read_shim(BIO *b) { - BIO_set_retry_read(b); -} - -void BIO_set_retry_write_shim(BIO *b) { - BIO_set_retry_write(b); -} - -long BIO_flush_shim(BIO *b) { - return BIO_flush(b); -} - -long SSL_CTX_set_options_shim(SSL_CTX *ctx, long options) { - return SSL_CTX_set_options(ctx, options); -} - -long SSL_CTX_get_options_shim(SSL_CTX *ctx) { - return SSL_CTX_get_options(ctx); -} - -long SSL_CTX_clear_options_shim(SSL_CTX *ctx, long options) { - return SSL_CTX_clear_options(ctx, options); -} - -long SSL_CTX_set_mode_shim(SSL_CTX *ctx, long options) { - return SSL_CTX_set_mode(ctx, options); -} - -long SSL_CTX_add_extra_chain_cert_shim(SSL_CTX *ctx, X509 *x509) { - return SSL_CTX_add_extra_chain_cert(ctx, x509); -} - -long SSL_CTX_set_read_ahead_shim(SSL_CTX *ctx, long m) { - return SSL_CTX_set_read_ahead(ctx, m); -} - -long SSL_CTX_set_tmp_dh_shim(SSL_CTX *ctx, DH *dh) { - return SSL_CTX_set_tmp_dh(ctx, dh); -} - -long SSL_CTX_set_tlsext_servername_callback_shim(SSL_CTX *ctx, int (*callback)(SSL_CTX *, int *, void*)) { - return SSL_CTX_set_tlsext_servername_callback(ctx, callback); -} - -long SSL_CTX_set_tlsext_servername_arg_shim(SSL_CTX *ctx, void* arg) { - return SSL_CTX_set_tlsext_servername_arg(ctx, arg); -} - -#if OPENSSL_VERSION_NUMBER >= 0x10002000L -int SSL_CTX_set_ecdh_auto_shim(SSL_CTX *ctx, int onoff) { - return SSL_CTX_set_ecdh_auto(ctx, onoff); -} -#endif - -DH *DH_new_from_params(BIGNUM *p, BIGNUM *g, BIGNUM *q) { - DH *dh; - - if ((dh = DH_new()) == NULL) { - return NULL; - } - dh->p = p; - dh->g = g; - dh->q = q; - return dh; -} - -long SSL_set_tlsext_host_name_shim(SSL *s, char *name) { - return SSL_set_tlsext_host_name(s, name); -} diff --git a/openssl-sys-extras/src/ssl_options.rs b/openssl-sys-extras/src/ssl_options.rs deleted file mode 100644 index a1c778ac..00000000 --- a/openssl-sys-extras/src/ssl_options.rs +++ /dev/null @@ -1,46 +0,0 @@ -import_options!{ -// The following values are directly from recent OpenSSL -SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001 -SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002 -SSL_OP_LEGACY_SERVER_CONNECT 0x00000004 -SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008 -SSL_OP_TLSEXT_PADDING 0x00000010 -SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020 -SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040 -SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080 -SSL_OP_TLS_D5_BUG 0x00000100 -SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200 -// unused: 0x00000400 -SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800 -SSL_OP_NO_QUERY_MTU 0x00001000 -SSL_OP_COOKIE_EXCHANGE 0x00002000 -SSL_OP_NO_TICKET 0x00004000 -SSL_OP_CISCO_ANYCONNECT 0x00008000 -SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000 -SSL_OP_NO_COMPRESSION 0x00020000 -SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000 -SSL_OP_SINGLE_ECDH_USE 0x00080000 -SSL_OP_SINGLE_DH_USE 0x00100000 -// unused: 0x00200000 -SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000 -SSL_OP_TLS_ROLLBACK_BUG 0x00800000 -SSL_OP_NO_SSLv2 0x01000000 -SSL_OP_NO_SSLv3 0x02000000 -SSL_OP_NO_DTLSv1 0x04000000 -SSL_OP_NO_TLSv1 0x04000000 -SSL_OP_NO_DTLSv1_2 0x08000000 -SSL_OP_NO_TLSv1_2 0x08000000 -SSL_OP_NO_TLSv1_1 0x10000000 -SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000 -SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000 -SSL_OP_CRYPTOPRO_TLSEXT_BUG 0x80000000 - -// The following values were in 32-bit range in old OpenSSL -SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x100000000 -SSL_OP_MSIE_SSLV2_RSA_PADDING 0x200000000 -SSL_OP_PKCS1_CHECK_1 0x400000000 -SSL_OP_PKCS1_CHECK_2 0x800000000 - -// The following values were redefined to 0 for security reasons -SSL_OP_EPHEMERAL_RSA 0x0 -} diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 45424bbf..9e923eb0 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -24,6 +24,7 @@ alpn = [] rfc5114 = [] pkcs5_pbkdf2_hmac = [] ecdh_auto = [] +hmac_clone = [] [dependencies] libc = "0.2" diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 4dccc67e..55375d8d 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -801,6 +801,8 @@ extern "C" { pub fn HMAC_CTX_init(ctx: *mut HMAC_CTX); pub fn HMAC_CTX_cleanup(ctx: *mut HMAC_CTX); + #[cfg(feature = "hmac_clone")] + pub fn HMAC_CTX_copy(dst: *mut HMAC_CTX, src: *const HMAC_CTX) -> c_int; pub fn PEM_read_bio_DHparams(bio: *mut BIO, out: *mut *mut DH, callback: Option, user_data: *mut c_void) -> *mut DH; diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index f4f4673c..d06accce 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -25,18 +25,19 @@ alpn = ["openssl-sys/alpn"] rfc5114 = ["openssl-sys/rfc5114"] ecdh_auto = ["openssl-sys/ecdh_auto"] pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"] +hmac_clone = ["openssl-sys/hmac_clone"] c_helpers = ["gcc"] x509_clone = ["c_helpers"] x509_generator_request = ["c_helpers"] ssl_context_clone = ["c_helpers"] +hmac = ["c_helpers"] [dependencies] bitflags = ">= 0.5.0, < 0.8.0" lazy_static = "0.2" libc = "0.2" openssl-sys = { version = "0.7.14", path = "../openssl-sys" } -openssl-sys-extras = { version = "0.7.14", path = "../openssl-sys-extras" } [build-dependencies] gcc = { version = "0.3", optional = true } diff --git a/openssl/src/c_helpers.c b/openssl/src/c_helpers.c index f8bc2d0d..4a2021e4 100644 --- a/openssl/src/c_helpers.c +++ b/openssl/src/c_helpers.c @@ -1,4 +1,7 @@ +#include #include +#include +#include void rust_SSL_CTX_clone(SSL_CTX *ctx) { CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); @@ -11,3 +14,34 @@ void rust_X509_clone(X509 *x509) { STACK_OF(X509_EXTENSION) *rust_X509_get_extensions(X509 *x) { return x->cert_info ? x->cert_info->extensions : NULL; } + +#if OPENSSL_VERSION_NUMBER < 0x10000000L +int rust_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl) { + HMAC_Init_ex(ctx, key, key_len, md, impl); + return 1; +} + +int rust_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, int len) { + HMAC_Update(ctx, data, len); + return 1; +} + +int rust_HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) { + HMAC_Final(ctx, md, len); + return 1; +} + +#else + +int rust_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl) { + return HMAC_Init_ex(ctx, key, key_len, md, impl); +} + +int rust_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, int len) { + return HMAC_Update(ctx, data, len); +} + +int rust_HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) { + return HMAC_Final(ctx, md, len); +} +#endif diff --git a/openssl/src/c_helpers.rs b/openssl/src/c_helpers.rs index f074d404..a195d88f 100644 --- a/openssl/src/c_helpers.rs +++ b/openssl/src/c_helpers.rs @@ -1,8 +1,13 @@ use ffi; +use libc::{c_int, c_void, c_uint, c_uchar}; #[allow(dead_code)] extern "C" { pub fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX); pub fn rust_X509_clone(x509: *mut ffi::X509); pub fn rust_X509_get_extensions(x: *mut ffi::X509) -> *mut ffi::stack_st_X509_EXTENSION; + + pub fn rust_HMAC_Init_ex(ctx: *mut ffi::HMAC_CTX, key: *const c_void, keylen: c_int, md: *const ffi::EVP_MD, impl_: *mut ffi::ENGINE) -> c_int; + pub fn rust_HMAC_Final(ctx: *mut ffi::HMAC_CTX, output: *mut c_uchar, len: *mut c_uint) -> c_int; + pub fn rust_HMAC_Update(ctx: *mut ffi::HMAC_CTX, input: *const c_uchar, len: c_uint) -> c_int; } diff --git a/openssl/src/crypto/hmac.rs b/openssl/src/crypto/hmac.rs index 453511ac..857be339 100644 --- a/openssl/src/crypto/hmac.rs +++ b/openssl/src/crypto/hmac.rs @@ -18,11 +18,11 @@ use std::io; use std::io::prelude::*; use std::cmp; use ffi; -use ffi_extras; use HashTypeInternals; use crypto::hash::Type; use error::ErrorStack; +use c_helpers; #[derive(PartialEq, Copy, Clone)] enum State { @@ -35,6 +35,8 @@ use self::State::*; /// Provides HMAC computation. /// +/// Requires the `hmac` feature. +/// /// # Examples /// /// Calculate a HMAC in one go. @@ -65,7 +67,6 @@ use self::State::*; /// ``` pub struct HMAC { ctx: ffi::HMAC_CTX, - type_: Type, state: State, } @@ -83,7 +84,6 @@ impl HMAC { let mut h = HMAC { ctx: ctx, - type_: ty, state: Finalized, }; try!(h.init_once(md, key)); @@ -92,11 +92,11 @@ impl HMAC { fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) -> Result<(), ErrorStack> { unsafe { - try_ssl!(ffi_extras::HMAC_Init_ex(&mut self.ctx, - key.as_ptr(), - key.len() as c_int, - md, - 0 as *const _)); + try_ssl!(c_helpers::rust_HMAC_Init_ex(&mut self.ctx, + key.as_ptr() as *const _, + key.len() as c_int, + md, + 0 as *mut _)); } self.state = Reset; Ok(()) @@ -113,11 +113,11 @@ impl HMAC { // If the key and/or md is not supplied it's reused from the last time // avoiding redundant initializations unsafe { - try_ssl!(ffi_extras::HMAC_Init_ex(&mut self.ctx, - 0 as *const _, - 0, - 0 as *const _, - 0 as *const _)); + try_ssl!(c_helpers::rust_HMAC_Init_ex(&mut self.ctx, + 0 as *const _, + 0, + 0 as *const _, + 0 as *mut _)); } self.state = Reset; Ok(()) @@ -130,7 +130,7 @@ impl HMAC { while !data.is_empty() { let len = cmp::min(data.len(), c_uint::max_value() as usize); unsafe { - try_ssl!(ffi_extras::HMAC_Update(&mut self.ctx, data.as_ptr(), len as c_uint)); + try_ssl!(c_helpers::rust_HMAC_Update(&mut self.ctx, data.as_ptr(), len as c_uint)); } data = &data[len..]; } @@ -147,7 +147,7 @@ impl HMAC { unsafe { let mut len = ffi::EVP_MAX_MD_SIZE; let mut res = vec![0; len as usize]; - try_ssl!(ffi_extras::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len)); + try_ssl!(c_helpers::rust_HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len)); res.truncate(len as usize); self.state = Finalized; Ok(res) @@ -167,17 +167,18 @@ impl Write for HMAC { } } +#[cfg(feature = "hmac_clone")] impl Clone for HMAC { + /// Requires the `hmac_clone` feature. fn clone(&self) -> HMAC { let mut ctx: ffi::HMAC_CTX; unsafe { ctx = ::std::mem::uninitialized(); - let r = ffi_extras::HMAC_CTX_copy(&mut ctx, &self.ctx); + let r = ffi::HMAC_CTX_copy(&mut ctx, &self.ctx); assert_eq!(r, 1); } HMAC { ctx: ctx, - type_: self.type_, state: self.state, } } @@ -288,6 +289,7 @@ mod tests { } #[test] + #[cfg(feature = "hmac_clone")] fn test_clone() { let tests: [(Vec, Vec, Vec); 2] = [(repeat(0xaa_u8).take(80).collect(), diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs index 453291aa..93aba9eb 100644 --- a/openssl/src/crypto/mod.rs +++ b/openssl/src/crypto/mod.rs @@ -15,6 +15,7 @@ // pub mod hash; +#[cfg(feature = "hmac")] pub mod hmac; pub mod pkcs5; pub mod pkey; diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 2f3664ac..fdf9548c 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -6,7 +6,6 @@ extern crate libc; #[macro_use] extern crate lazy_static; extern crate openssl_sys as ffi; -extern crate openssl_sys_extras as ffi_extras; #[cfg(test)] extern crate rustc_serialize as serialize; From 00db0bc4b312218b4f4165909a8bbf56522b0099 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 9 Aug 2016 22:56:08 -0700 Subject: [PATCH 83/96] Test hmac features --- openssl/test/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/test/run.sh b/openssl/test/run.sh index 22a54c4d..7dc01f50 100755 --- a/openssl/test/run.sh +++ b/openssl/test/run.sh @@ -4,7 +4,7 @@ set -e MAIN_TARGETS=https://static.rust-lang.org/dist if [ "$TEST_FEATURES" == "true" ]; then - FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac x509_clone ssl_context_clone x509_generator_request" + FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac x509_clone ssl_context_clone x509_generator_request hmac hmac_clone" fi if [ "$TRAVIS_OS_NAME" != "osx" ]; then From 35c79d176811af9e5cb0c012fe8daecbf7b0cdd4 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 9 Aug 2016 23:13:56 -0700 Subject: [PATCH 84/96] Fix build --- openssl-sys/src/lib.rs | 2 -- openssl/Cargo.toml | 1 + openssl/src/c_helpers.c | 12 ++++++++++++ openssl/src/c_helpers.rs | 1 + openssl/src/dh/mod.rs | 5 ++++- openssl/test/run.sh | 2 +- 6 files changed, 19 insertions(+), 4 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 55375d8d..2f01196f 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -717,8 +717,6 @@ extern "C" { #[cfg(feature = "rfc5114")] pub fn DH_get_2048_256() -> *mut DH; - pub fn DH_new_from_params(p: *mut BIGNUM, g: *mut BIGNUM, q: *mut BIGNUM) -> *mut DH; - pub fn ERR_get_error() -> c_ulong; pub fn ERR_lib_error_string(err: c_ulong) -> *const c_char; diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index d06accce..17802aed 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -32,6 +32,7 @@ x509_clone = ["c_helpers"] x509_generator_request = ["c_helpers"] ssl_context_clone = ["c_helpers"] hmac = ["c_helpers"] +dh_from_params = ["c_helpers"] [dependencies] bitflags = ">= 0.5.0, < 0.8.0" diff --git a/openssl/src/c_helpers.c b/openssl/src/c_helpers.c index 4a2021e4..13041956 100644 --- a/openssl/src/c_helpers.c +++ b/openssl/src/c_helpers.c @@ -15,6 +15,18 @@ STACK_OF(X509_EXTENSION) *rust_X509_get_extensions(X509 *x) { return x->cert_info ? x->cert_info->extensions : NULL; } +DH *rust_DH_new_from_params(BIGNUM *p, BIGNUM *g, BIGNUM *q) { + DH *dh; + + if ((dh = DH_new()) == NULL) { + return NULL; + } + dh->p = p; + dh->g = g; + dh->q = q; + return dh; +} + #if OPENSSL_VERSION_NUMBER < 0x10000000L int rust_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl) { HMAC_Init_ex(ctx, key, key_len, md, impl); diff --git a/openssl/src/c_helpers.rs b/openssl/src/c_helpers.rs index a195d88f..90fcf877 100644 --- a/openssl/src/c_helpers.rs +++ b/openssl/src/c_helpers.rs @@ -10,4 +10,5 @@ extern "C" { pub fn rust_HMAC_Init_ex(ctx: *mut ffi::HMAC_CTX, key: *const c_void, keylen: c_int, md: *const ffi::EVP_MD, impl_: *mut ffi::ENGINE) -> c_int; pub fn rust_HMAC_Final(ctx: *mut ffi::HMAC_CTX, output: *mut c_uchar, len: *mut c_uint) -> c_int; pub fn rust_HMAC_Update(ctx: *mut ffi::HMAC_CTX, input: *const c_uchar, len: c_uint) -> c_int; + pub fn rust_DH_new_from_params(p: *mut ffi::BIGNUM, g: *mut ffi::BIGNUM, q: *mut ffi::BIGNUM) -> *mut ffi::DH; } diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index c0122d44..b9613a1d 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -7,9 +7,11 @@ use std::ptr; pub struct DH(*mut ffi::DH); impl DH { + /// Requires the `dh_from_params` feature. + #[cfg(feature = "dh_from_params")] pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result { let dh = unsafe { - try_ssl_null!(ffi::DH_new_from_params(p.into_raw(), g.into_raw(), q.into_raw())) + try_ssl_null!(::c_helpers::rust_DH_new_from_params(p.into_raw(), g.into_raw(), q.into_raw())) }; Ok(DH(dh)) } @@ -75,6 +77,7 @@ mod tests { } #[test] + #[cfg(feature = "dh_from_params")] fn test_dh() { let mut ctx = SslContext::new(Sslv23).unwrap(); let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435\ diff --git a/openssl/test/run.sh b/openssl/test/run.sh index 7dc01f50..b9481837 100755 --- a/openssl/test/run.sh +++ b/openssl/test/run.sh @@ -4,7 +4,7 @@ set -e MAIN_TARGETS=https://static.rust-lang.org/dist if [ "$TEST_FEATURES" == "true" ]; then - FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac x509_clone ssl_context_clone x509_generator_request hmac hmac_clone" + FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac x509_clone ssl_context_clone x509_generator_request hmac hmac_clone dh_from_params" fi if [ "$TRAVIS_OS_NAME" != "osx" ]; then From dece5d116a10bf1121946a4feebfc895ffa7d4cd Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 09:02:10 -0700 Subject: [PATCH 85/96] Fix workspace declaration --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3e02eded..0bd2c005 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ["openssl", "openssl-sys", "openssl-sys-extras"] +members = ["openssl", "openssl-sys"] From c4e7743c57bde2d25b8a14521c48bba85fe72e68 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 20:51:06 -0700 Subject: [PATCH 86/96] Asn1 and Bignum renames --- openssl/src/asn1/mod.rs | 12 ++-- openssl/src/bn/mod.rs | 122 ++++++++++++++++++-------------------- openssl/src/crypto/dsa.rs | 6 +- openssl/src/crypto/rsa.rs | 12 ++-- openssl/src/dh/mod.rs | 1 - openssl/src/x509/mod.rs | 4 +- 6 files changed, 76 insertions(+), 81 deletions(-) diff --git a/openssl/src/asn1/mod.rs b/openssl/src/asn1/mod.rs index e79a0fd2..7d209775 100644 --- a/openssl/src/asn1/mod.rs +++ b/openssl/src/asn1/mod.rs @@ -8,26 +8,26 @@ pub struct Asn1Time(*mut ffi::ASN1_TIME); impl Asn1Time { /// Wraps existing ASN1_TIME and takes ownership - pub unsafe fn from_raw(handle: *mut ffi::ASN1_TIME) -> Asn1Time { + pub unsafe fn from_ptr(handle: *mut ffi::ASN1_TIME) -> Asn1Time { Asn1Time(handle) } - fn from_period(period: u64) -> Result { + fn from_period(period: c_long) -> Result { ffi::init(); unsafe { - let handle = try_ssl_null!(ffi::X509_gmtime_adj(ptr::null_mut(), period as c_long)); - Ok(Asn1Time::from_raw(handle)) + let handle = try_ssl_null!(ffi::X509_gmtime_adj(ptr::null_mut(), period)); + Ok(Asn1Time::from_ptr(handle)) } } /// Creates a new time on specified interval in days from now pub fn days_from_now(days: u32) -> Result { - Asn1Time::from_period(days as u64 * 60 * 60 * 24) + Asn1Time::from_period(days as c_long * 60 * 60 * 24) } /// Returns the raw handle - pub fn handle(&self) -> *mut ffi::ASN1_TIME { + pub fn as_ptr(&self) -> *mut ffi::ASN1_TIME { self.0 } } diff --git a/openssl/src/bn/mod.rs b/openssl/src/bn/mod.rs index a933157c..2f751037 100644 --- a/openssl/src/bn/mod.rs +++ b/openssl/src/bn/mod.rs @@ -80,7 +80,7 @@ pub struct BigNumRef<'a>(*mut ffi::BIGNUM, PhantomData<&'a ()>); impl<'a> BigNumRef<'a> { - pub unsafe fn from_handle(handle: *mut ffi::BIGNUM) -> BigNumRef<'a> { + pub unsafe fn from_ptr(handle: *mut ffi::BIGNUM) -> BigNumRef<'a> { BigNumRef(handle, PhantomData) } @@ -97,7 +97,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_sqr(&self) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_sqr(r.raw(), self.raw(), ctx) == 1 + ffi::BN_sqr(r.as_ptr(), self.as_ptr(), ctx) == 1 }) } } @@ -106,7 +106,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_nnmod(&self, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_nnmod(r.raw(), self.raw(), n.raw(), ctx) == 1 + ffi::BN_nnmod(r.as_ptr(), self.as_ptr(), n.as_ptr(), ctx) == 1 }) } } @@ -125,7 +125,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_mod_add(&self, a: &BigNumRef, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_mod_add(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1 + ffi::BN_mod_add(r.as_ptr(), self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx) == 1 }) } } @@ -134,7 +134,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_mod_sub(&self, a: &BigNumRef, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_mod_sub(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1 + ffi::BN_mod_sub(r.as_ptr(), self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx) == 1 }) } } @@ -143,7 +143,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_mod_mul(&self, a: &BigNumRef, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_mod_mul(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1 + ffi::BN_mod_mul(r.as_ptr(), self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx) == 1 }) } } @@ -152,7 +152,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_mod_sqr(&self, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_mod_sqr(r.raw(), self.raw(), n.raw(), ctx) == 1 + ffi::BN_mod_sqr(r.as_ptr(), self.as_ptr(), n.as_ptr(), ctx) == 1 }) } } @@ -161,7 +161,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_exp(&self, p: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_exp(r.raw(), self.raw(), p.raw(), ctx) == 1 + ffi::BN_exp(r.as_ptr(), self.as_ptr(), p.as_ptr(), ctx) == 1 }) } } @@ -170,7 +170,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_mod_exp(&self, p: &BigNumRef, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_mod_exp(r.raw(), self.raw(), p.raw(), n.raw(), ctx) == 1 + ffi::BN_mod_exp(r.as_ptr(), self.as_ptr(), p.as_ptr(), n.as_ptr(), ctx) == 1 }) } } @@ -180,7 +180,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_mod_inv(&self, n: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - !ffi::BN_mod_inverse(r.raw(), self.raw(), n.raw(), ctx).is_null() + !ffi::BN_mod_inverse(r.as_ptr(), self.as_ptr(), n.as_ptr(), ctx).is_null() }) } } @@ -188,7 +188,7 @@ impl<'a> BigNumRef<'a> { /// Add an `unsigned long` to `self`. This is more efficient than adding a `BigNum`. pub fn add_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> { unsafe { - if ffi::BN_add_word(self.raw(), w) == 1 { + if ffi::BN_add_word(self.as_ptr(), w) == 1 { Ok(()) } else { Err(ErrorStack::get()) @@ -198,7 +198,7 @@ impl<'a> BigNumRef<'a> { pub fn sub_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> { unsafe { - if ffi::BN_sub_word(self.raw(), w) == 1 { + if ffi::BN_sub_word(self.as_ptr(), w) == 1 { Ok(()) } else { Err(ErrorStack::get()) @@ -208,7 +208,7 @@ impl<'a> BigNumRef<'a> { pub fn mul_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> { unsafe { - if ffi::BN_mul_word(self.raw(), w) == 1 { + if ffi::BN_mul_word(self.as_ptr(), w) == 1 { Ok(()) } else { Err(ErrorStack::get()) @@ -218,7 +218,7 @@ impl<'a> BigNumRef<'a> { pub fn div_word(&mut self, w: c_ulong) -> Result { unsafe { - let result = ffi::BN_div_word(self.raw(), w); + let result = ffi::BN_div_word(self.as_ptr(), w); if result != !0 as c_ulong { Ok(result) } else { @@ -229,7 +229,7 @@ impl<'a> BigNumRef<'a> { pub fn mod_word(&self, w: c_ulong) -> Result { unsafe { - let result = ffi::BN_mod_word(self.raw(), w); + let result = ffi::BN_mod_word(self.as_ptr(), w); if result != !0 as c_ulong { Ok(result) } else { @@ -242,7 +242,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_gcd(&self, a: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_gcd(r.raw(), self.raw(), a.raw(), ctx) == 1 + ffi::BN_gcd(r.as_ptr(), self.as_ptr(), a.as_ptr(), ctx) == 1 }) } } @@ -257,7 +257,7 @@ impl<'a> BigNumRef<'a> { pub fn is_prime(&self, checks: i32) -> Result { unsafe { with_ctx!(ctx, { - Ok(ffi::BN_is_prime_ex(self.raw(), checks as c_int, ctx, ptr::null()) == 1) + Ok(ffi::BN_is_prime_ex(self.as_ptr(), checks as c_int, ctx, ptr::null()) == 1) }) } } @@ -274,7 +274,7 @@ impl<'a> BigNumRef<'a> { pub fn is_prime_fast(&self, checks: i32, do_trial_division: bool) -> Result { unsafe { with_ctx!(ctx, { - Ok(ffi::BN_is_prime_fasttest_ex(self.raw(), + Ok(ffi::BN_is_prime_fasttest_ex(self.as_ptr(), checks as c_int, ctx, do_trial_division as c_int, @@ -288,7 +288,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_rand_in_range(&self) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_rand_range(r.raw(), self.raw()) == 1 + ffi::BN_rand_range(r.as_ptr(), self.as_ptr()) == 1 }) } } @@ -297,7 +297,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_pseudo_rand_in_range(&self) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_pseudo_rand_range(r.raw(), self.raw()) == 1 + ffi::BN_pseudo_rand_range(r.as_ptr(), self.as_ptr()) == 1 }) } } @@ -307,7 +307,7 @@ impl<'a> BigNumRef<'a> { /// When setting a bit outside of `self`, it is expanded. pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> { unsafe { - if ffi::BN_set_bit(self.raw(), n as c_int) == 1 { + if ffi::BN_set_bit(self.as_ptr(), n as c_int) == 1 { Ok(()) } else { Err(ErrorStack::get()) @@ -320,7 +320,7 @@ impl<'a> BigNumRef<'a> { /// When clearing a bit outside of `self`, an error is returned. pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> { unsafe { - if ffi::BN_clear_bit(self.raw(), n as c_int) == 1 { + if ffi::BN_clear_bit(self.as_ptr(), n as c_int) == 1 { Ok(()) } else { Err(ErrorStack::get()) @@ -330,7 +330,7 @@ impl<'a> BigNumRef<'a> { /// Returns `true` if the `n`th bit of `self` is set to 1, `false` otherwise. pub fn is_bit_set(&self, n: i32) -> bool { - unsafe { ffi::BN_is_bit_set(self.raw(), n as c_int) == 1 } + unsafe { ffi::BN_is_bit_set(self.as_ptr(), n as c_int) == 1 } } /// Truncates `self` to the lowest `n` bits. @@ -338,7 +338,7 @@ impl<'a> BigNumRef<'a> { /// An error occurs if `self` is already shorter than `n` bits. pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> { unsafe { - if ffi::BN_mask_bits(self.raw(), n as c_int) == 1 { + if ffi::BN_mask_bits(self.as_ptr(), n as c_int) == 1 { Ok(()) } else { Err(ErrorStack::get()) @@ -367,7 +367,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_shl1(&self) -> Result { unsafe { with_bn!(r, { - ffi::BN_lshift1(r.raw(), self.raw()) == 1 + ffi::BN_lshift1(r.as_ptr(), self.as_ptr()) == 1 }) } } @@ -376,7 +376,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_shr1(&self) -> Result { unsafe { with_bn!(r, { - ffi::BN_rshift1(r.raw(), self.raw()) == 1 + ffi::BN_rshift1(r.as_ptr(), self.as_ptr()) == 1 }) } } @@ -384,7 +384,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_add(&self, a: &BigNumRef) -> Result { unsafe { with_bn!(r, { - ffi::BN_add(r.raw(), self.raw(), a.raw()) == 1 + ffi::BN_add(r.as_ptr(), self.as_ptr(), a.as_ptr()) == 1 }) } } @@ -392,7 +392,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_sub(&self, a: &BigNumRef) -> Result { unsafe { with_bn!(r, { - ffi::BN_sub(r.raw(), self.raw(), a.raw()) == 1 + ffi::BN_sub(r.as_ptr(), self.as_ptr(), a.as_ptr()) == 1 }) } } @@ -400,7 +400,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_mul(&self, a: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_mul(r.raw(), self.raw(), a.raw(), ctx) == 1 + ffi::BN_mul(r.as_ptr(), self.as_ptr(), a.as_ptr(), ctx) == 1 }) } } @@ -408,7 +408,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_div(&self, a: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_div(r.raw(), ptr::null_mut(), self.raw(), a.raw(), ctx) == 1 + ffi::BN_div(r.as_ptr(), ptr::null_mut(), self.as_ptr(), a.as_ptr(), ctx) == 1 }) } } @@ -416,7 +416,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_mod(&self, a: &BigNumRef) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_div(ptr::null_mut(), r.raw(), self.raw(), a.raw(), ctx) == 1 + ffi::BN_div(ptr::null_mut(), r.as_ptr(), self.as_ptr(), a.as_ptr(), ctx) == 1 }) } } @@ -424,7 +424,7 @@ impl<'a> BigNumRef<'a> { pub fn checked_shl(&self, a: &i32) -> Result { unsafe { with_bn!(r, { - ffi::BN_lshift(r.raw(), self.raw(), *a as c_int) == 1 + ffi::BN_lshift(r.as_ptr(), self.as_ptr(), *a as c_int) == 1 }) } } @@ -432,15 +432,15 @@ impl<'a> BigNumRef<'a> { pub fn checked_shr(&self, a: &i32) -> Result { unsafe { with_bn!(r, { - ffi::BN_rshift(r.raw(), self.raw(), *a as c_int) == 1 + ffi::BN_rshift(r.as_ptr(), self.as_ptr(), *a as c_int) == 1 }) } } pub fn to_owned(&self) -> Result { unsafe { - let r = try_ssl_null!(ffi::BN_dup(self.raw())); - Ok(BigNum::from_handle(r)) + let r = try_ssl_null!(ffi::BN_dup(self.as_ptr())); + Ok(BigNum::from_ptr(r)) } } @@ -456,7 +456,7 @@ impl<'a> BigNumRef<'a> { /// assert_eq!(s, BigNum::new_from(8).unwrap()); /// ``` pub fn negate(&mut self) { - unsafe { ffi::BN_set_negative(self.raw(), !self.is_negative() as c_int) } + unsafe { ffi::BN_set_negative(self.as_ptr(), !self.is_negative() as c_int) } } /// Compare the absolute values of `self` and `oth`. @@ -471,7 +471,7 @@ impl<'a> BigNumRef<'a> { /// ``` pub fn abs_cmp(&self, oth: &BigNumRef) -> Ordering { unsafe { - let res = ffi::BN_ucmp(self.raw(), oth.raw()) as i32; + let res = ffi::BN_ucmp(self.as_ptr(), oth.as_ptr()) as i32; if res < 0 { Ordering::Less } else if res > 0 { @@ -483,12 +483,12 @@ impl<'a> BigNumRef<'a> { } pub fn is_negative(&self) -> bool { - unsafe { (*self.raw()).neg == 1 } + unsafe { (*self.as_ptr()).neg == 1 } } /// Returns the number of significant bits in `self`. pub fn num_bits(&self) -> i32 { - unsafe { ffi::BN_num_bits(self.raw()) as i32 } + unsafe { ffi::BN_num_bits(self.as_ptr()) as i32 } } /// Returns the size of `self` in bytes. @@ -496,14 +496,10 @@ impl<'a> BigNumRef<'a> { (self.num_bits() + 7) / 8 } - pub fn raw(&self) -> *mut ffi::BIGNUM { + pub fn as_ptr(&self) -> *mut ffi::BIGNUM { self.0 } - pub fn raw_ptr(&self) -> *const *mut ffi::BIGNUM { - &self.0 - } - /// Returns a big-endian byte vector representation of the absolute value of `self`. /// /// `self` can be recreated by using `new_from_slice`. @@ -520,7 +516,7 @@ impl<'a> BigNumRef<'a> { let size = self.num_bytes() as usize; let mut v = Vec::with_capacity(size); unsafe { - ffi::BN_bn2bin(self.raw(), v.as_mut_ptr()); + ffi::BN_bn2bin(self.as_ptr(), v.as_mut_ptr()); v.set_len(size); } v @@ -536,7 +532,7 @@ impl<'a> BigNumRef<'a> { /// ``` pub fn to_dec_str(&self) -> String { unsafe { - let buf = ffi::BN_bn2dec(self.raw()); + let buf = ffi::BN_bn2dec(self.as_ptr()); assert!(!buf.is_null()); let str = String::from_utf8(CStr::from_ptr(buf as *const _).to_bytes().to_vec()) .unwrap(); @@ -555,7 +551,7 @@ impl<'a> BigNumRef<'a> { /// ``` pub fn to_hex_str(&self) -> String { unsafe { - let buf = ffi::BN_bn2hex(self.raw()); + let buf = ffi::BN_bn2hex(self.as_ptr()); assert!(!buf.is_null()); let str = String::from_utf8(CStr::from_ptr(buf as *const _).to_bytes().to_vec()) .unwrap(); @@ -579,14 +575,14 @@ impl BigNum { unsafe { ffi::init(); let v = try_ssl_null!(ffi::BN_new()); - Ok(BigNum::from_handle(v)) + Ok(BigNum::from_ptr(v)) } } /// Creates a new `BigNum` with the given value. pub fn new_from(n: c_ulong) -> Result { BigNum::new().and_then(|v| unsafe { - try_ssl!(ffi::BN_set_word(v.raw(), n)); + try_ssl!(ffi::BN_set_word(v.as_ptr(), n)); Ok(v) }) } @@ -595,7 +591,7 @@ impl BigNum { pub fn from_dec_str(s: &str) -> Result { BigNum::new().and_then(|v| unsafe { let c_str = CString::new(s.as_bytes()).unwrap(); - try_ssl!(ffi::BN_dec2bn(v.raw_ptr(), c_str.as_ptr() as *const _)); + try_ssl!(ffi::BN_dec2bn(&(v.0).0, c_str.as_ptr() as *const _)); Ok(v) }) } @@ -604,13 +600,13 @@ impl BigNum { pub fn from_hex_str(s: &str) -> Result { BigNum::new().and_then(|v| unsafe { let c_str = CString::new(s.as_bytes()).unwrap(); - try_ssl!(ffi::BN_hex2bn(v.raw_ptr(), c_str.as_ptr() as *const _)); + try_ssl!(ffi::BN_hex2bn(&(v.0).0, c_str.as_ptr() as *const _)); Ok(v) }) } - pub unsafe fn from_handle(handle: *mut ffi::BIGNUM) -> BigNum { - BigNum(BigNumRef::from_handle(handle)) + pub unsafe fn from_ptr(handle: *mut ffi::BIGNUM) -> BigNum { + BigNum(BigNumRef::from_ptr(handle)) } /// Creates a new `BigNum` from an unsigned, big-endian encoded number of arbitrary length. @@ -623,7 +619,7 @@ impl BigNum { /// ``` pub fn new_from_slice(n: &[u8]) -> Result { BigNum::new().and_then(|v| unsafe { - try_ssl_null!(ffi::BN_bin2bn(n.as_ptr(), n.len() as c_int, v.raw())); + try_ssl_null!(ffi::BN_bin2bn(n.as_ptr(), n.len() as c_int, v.as_ptr())); Ok(v) }) } @@ -642,10 +638,10 @@ impl BigNum { -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - let add_arg = add.map(|a| a.raw()).unwrap_or(ptr::null_mut()); - let rem_arg = rem.map(|r| r.raw()).unwrap_or(ptr::null_mut()); + let add_arg = add.map(|a| a.as_ptr()).unwrap_or(ptr::null_mut()); + let rem_arg = rem.map(|r| r.as_ptr()).unwrap_or(ptr::null_mut()); - ffi::BN_generate_prime_ex(r.raw(), + ffi::BN_generate_prime_ex(r.as_ptr(), bits as c_int, safe as c_int, add_arg, @@ -665,7 +661,7 @@ impl BigNum { pub fn checked_new_random(bits: i32, prop: RNGProperty, odd: bool) -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_rand(r.raw(), bits as c_int, prop as c_int, odd as c_int) == 1 + ffi::BN_rand(r.as_ptr(), bits as c_int, prop as c_int, odd as c_int) == 1 }) } } @@ -677,13 +673,13 @@ impl BigNum { -> Result { unsafe { with_bn_in_ctx!(r, ctx, { - ffi::BN_pseudo_rand(r.raw(), bits as c_int, prop as c_int, odd as c_int) == 1 + ffi::BN_pseudo_rand(r.as_ptr(), bits as c_int, prop as c_int, odd as c_int) == 1 }) } } pub fn into_raw(self) -> *mut ffi::BIGNUM { - let ptr = self.raw(); + let ptr = self.as_ptr(); mem::forget(self); ptr } @@ -691,7 +687,7 @@ impl BigNum { impl Drop for BigNum { fn drop(&mut self) { - unsafe { ffi::BN_clear_free(self.raw()); } + unsafe { ffi::BN_clear_free(self.as_ptr()); } } } @@ -741,7 +737,7 @@ impl fmt::Display for BigNum { impl<'a, 'b> PartialEq> for BigNumRef<'a> { fn eq(&self, oth: &BigNumRef) -> bool { - unsafe { ffi::BN_cmp(self.raw(), oth.raw()) == 0 } + unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()) == 0 } } } @@ -781,7 +777,7 @@ impl<'a> PartialOrd for BigNumRef<'a> { impl<'a> Ord for BigNumRef<'a> { fn cmp(&self, oth: &BigNumRef) -> Ordering { - unsafe { ffi::BN_cmp(self.raw(), oth.raw()).cmp(&0) } + unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) } } } diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index 7852d391..7e6f0381 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -195,7 +195,7 @@ impl DSA { if p.is_null() { None } else { - Some(BigNumRef::from_handle((*self.0).p)) + Some(BigNumRef::from_ptr((*self.0).p)) } } } @@ -206,7 +206,7 @@ impl DSA { if q.is_null() { None } else { - Some(BigNumRef::from_handle((*self.0).q)) + Some(BigNumRef::from_ptr((*self.0).q)) } } } @@ -217,7 +217,7 @@ impl DSA { if g.is_null() { None } else { - Some(BigNumRef::from_handle((*self.0).g)) + Some(BigNumRef::from_ptr((*self.0).g)) } } } diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 2dfa64a6..e68b2420 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -68,7 +68,7 @@ impl RSA { let rsa = RSA(rsa); let e = try!(BigNum::new_from(ffi::RSA_F4 as c_ulong)); - try_ssl!(ffi::RSA_generate_key_ex(rsa.0, bits as c_int, e.raw(), ptr::null_mut())); + try_ssl!(ffi::RSA_generate_key_ex(rsa.0, bits as c_int, e.as_ptr(), ptr::null_mut())); Ok(rsa) } @@ -190,7 +190,7 @@ impl RSA { if n.is_null() { None } else { - Some(BigNumRef::from_handle(n)) + Some(BigNumRef::from_ptr(n)) } } } @@ -201,7 +201,7 @@ impl RSA { if d.is_null() { None } else { - Some(BigNumRef::from_handle(d)) + Some(BigNumRef::from_ptr(d)) } } } @@ -212,7 +212,7 @@ impl RSA { if e.is_null() { None } else { - Some(BigNumRef::from_handle(e)) + Some(BigNumRef::from_ptr(e)) } } } @@ -223,7 +223,7 @@ impl RSA { if p.is_null() { None } else { - Some(BigNumRef::from_handle(p)) + Some(BigNumRef::from_ptr(p)) } } } @@ -234,7 +234,7 @@ impl RSA { if q.is_null() { None } else { - Some(BigNumRef::from_handle(q)) + Some(BigNumRef::from_ptr(q)) } } } diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index b9613a1d..0a37a5e2 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -1,7 +1,6 @@ use ffi; use error::ErrorStack; use bio::MemBioSlice; -use bn::BigNum; use std::ptr; pub struct DH(*mut ffi::DH); diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 3bdbaa67..31c67453 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -306,11 +306,11 @@ impl X509Generator { let not_before = try!(Asn1Time::days_from_now(0)); let not_after = try!(Asn1Time::days_from_now(self.days)); - try_ssl!(ffi::X509_set_notBefore(x509.handle(), not_before.handle() as *const _)); + try_ssl!(ffi::X509_set_notBefore(x509.handle(), not_before.as_ptr() as *const _)); // If prev line succeded - ownership should go to cert mem::forget(not_before); - try_ssl!(ffi::X509_set_notAfter(x509.handle(), not_after.handle() as *const _)); + try_ssl!(ffi::X509_set_notAfter(x509.handle(), not_after.as_ptr() as *const _)); // If prev line succeded - ownership should go to cert mem::forget(not_after); From 5e6b8e68fdcc94c6d7a931925bb32b145caeb3db Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 21:07:41 -0700 Subject: [PATCH 87/96] More API cleanup --- openssl/src/bn/mod.rs | 8 +------- openssl/src/crypto/rsa.rs | 31 +++++++++++++++++++++---------- openssl/src/dh/mod.rs | 9 ++++++--- openssl/src/ssl/mod.rs | 2 +- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/openssl/src/bn/mod.rs b/openssl/src/bn/mod.rs index 2f751037..de9d0d2a 100644 --- a/openssl/src/bn/mod.rs +++ b/openssl/src/bn/mod.rs @@ -1,7 +1,7 @@ use libc::{c_int, c_ulong, c_void}; use std::ffi::{CStr, CString}; use std::cmp::Ordering; -use std::{fmt, ptr, mem}; +use std::{fmt, ptr}; use std::marker::PhantomData; use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Deref, DerefMut}; @@ -677,12 +677,6 @@ impl BigNum { }) } } - - pub fn into_raw(self) -> *mut ffi::BIGNUM { - let ptr = self.as_ptr(); - mem::forget(self); - ptr - } } impl Drop for BigNum { diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index e68b2420..822f305f 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -1,6 +1,7 @@ use ffi; use std::fmt; use std::ptr; +use std::mem; use libc::{c_int, c_void, c_char, c_ulong}; use bn::{BigNum, BigNumRef}; @@ -26,8 +27,10 @@ impl RSA { pub fn from_public_components(n: BigNum, e: BigNum) -> Result { unsafe { let rsa = try_ssl_null!(ffi::RSA_new()); - (*rsa).n = n.into_raw(); - (*rsa).e = e.into_raw(); + (*rsa).n = n.as_ptr(); + (*rsa).e = e.as_ptr(); + mem::forget(n); + mem::forget(e); Ok(RSA(rsa)) } } @@ -43,14 +46,22 @@ impl RSA { -> Result { unsafe { let rsa = try_ssl_null!(ffi::RSA_new()); - (*rsa).n = n.into_raw(); - (*rsa).e = e.into_raw(); - (*rsa).d = d.into_raw(); - (*rsa).p = p.into_raw(); - (*rsa).q = q.into_raw(); - (*rsa).dmp1 = dp.into_raw(); - (*rsa).dmq1 = dq.into_raw(); - (*rsa).iqmp = qi.into_raw(); + (*rsa).n = n.as_ptr(); + (*rsa).e = e.as_ptr(); + (*rsa).d = d.as_ptr(); + (*rsa).p = p.as_ptr(); + (*rsa).q = q.as_ptr(); + (*rsa).dmp1 = dp.as_ptr(); + (*rsa).dmq1 = dq.as_ptr(); + (*rsa).iqmp = qi.as_ptr(); + mem::forget(n); + mem::forget(e); + mem::forget(d); + mem::forget(p); + mem::forget(q); + mem::forget(dp); + mem::forget(dq); + mem::forget(qi); Ok(RSA(rsa)) } } diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index 0a37a5e2..1f4fd7fe 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -10,8 +10,11 @@ impl DH { #[cfg(feature = "dh_from_params")] pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result { let dh = unsafe { - try_ssl_null!(::c_helpers::rust_DH_new_from_params(p.into_raw(), g.into_raw(), q.into_raw())) + try_ssl_null!(::c_helpers::rust_DH_new_from_params(p.as_ptr(), g.as_ptr(), q.as_ptr())) }; + mem::forget(p); + mem::forget(g); + mem::forget(q); Ok(DH(dh)) } @@ -42,7 +45,7 @@ impl DH { Ok(DH(dh)) } - pub unsafe fn raw(&self) -> *mut ffi::DH { + pub unsafe fn as_ptr(&self) -> *mut ffi::DH { let DH(n) = *self; n } @@ -51,7 +54,7 @@ impl DH { impl Drop for DH { fn drop(&mut self) { unsafe { - ffi::DH_free(self.raw()) + ffi::DH_free(self.as_ptr()) } } } diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 792762a9..5c2cdd64 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -466,7 +466,7 @@ impl<'a> SslContextRef<'a> { } pub fn set_tmp_dh(&mut self, dh: &DH) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.raw()) as i32 }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as i32 }) } /// Use the default locations of trusted certificates for verification. From c15642ccea8e38362ab65cfbb94d638518375658 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 21:25:18 -0700 Subject: [PATCH 88/96] Tweaks --- openssl/src/crypto/dsa.rs | 7 +++---- openssl/src/crypto/rand.rs | 20 +++++++------------- openssl/src/x509/mod.rs | 11 ++++++----- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index 7e6f0381..7d6e1c05 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -15,7 +15,7 @@ use crypto::util::{CallbackState, invoke_passwd_cb}; pub struct DSAParams(*mut ffi::DSA); impl DSAParams { - pub fn with_size(size: usize) -> Result { + pub fn with_size(size: u32) -> Result { unsafe { // Wrap it so that if we panic we'll call the dtor let dsa = DSAParams(try_ssl_null!(ffi::DSA_new())); @@ -55,14 +55,13 @@ impl Drop for DSA { } impl DSA { - /// the caller should assert that the dsa pointer is valid. - pub unsafe fn from_raw(dsa: *mut ffi::DSA) -> DSA { + pub unsafe fn from_ptr(dsa: *mut ffi::DSA) -> DSA { DSA(dsa) } /// Generate a DSA key pair /// For more complicated key generation scenarios see the `DSAParams` type - pub fn generate(size: usize) -> Result { + pub fn generate(size: u32) -> Result { let params = try!(DSAParams::with_size(size)); params.generate() } diff --git a/openssl/src/crypto/rand.rs b/openssl/src/crypto/rand.rs index ba57a8a1..519449e9 100644 --- a/openssl/src/crypto/rand.rs +++ b/openssl/src/crypto/rand.rs @@ -1,19 +1,13 @@ use libc::c_int; use ffi; +use error::ErrorStack; -pub fn rand_bytes(len: usize) -> Vec { +pub fn rand_bytes(buf: &mut [u8]) -> Result<(), ErrorStack> { unsafe { - let mut out = Vec::with_capacity(len); - ffi::init(); - let r = ffi::RAND_bytes(out.as_mut_ptr(), len as c_int); - if r != 1 as c_int { - panic!() - } - - out.set_len(len); - - out + assert!(buf.len() <= c_int::max_value() as usize); + try_ssl_if!(ffi::RAND_bytes(buf.as_mut_ptr(), buf.len() as c_int) != 1); + Ok(()) } } @@ -23,7 +17,7 @@ mod tests { #[test] fn test_rand_bytes() { - let bytes = rand_bytes(32); - println!("{:?}", bytes); + let mut buf = [0; 32]; + rand_bytes(&mut buf).unwrap(); } } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 31c67453..cf5f4595 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -275,9 +275,10 @@ impl X509Generator { }) } - fn random_serial() -> c_long { + fn random_serial() -> Result { let len = mem::size_of::(); - let bytes = rand_bytes(len); + let mut bytes = vec![0; len]; + try!(rand_bytes(&mut bytes)); let mut res = 0; for b in bytes.iter() { res = res << 8; @@ -287,7 +288,7 @@ impl X509Generator { // While OpenSSL is actually OK to have negative serials // other libraries (for example, Go crypto) can drop // such certificates as invalid, so we clear the high bit - ((res as c_ulong) >> 1) as c_long + Ok(((res as c_ulong) >> 1) as c_long) } /// Sets the certificate public-key, then self-sign and return it @@ -301,7 +302,7 @@ impl X509Generator { try_ssl!(ffi::X509_set_version(x509.handle(), 2)); try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.handle()), - X509Generator::random_serial())); + try!(X509Generator::random_serial()))); let not_before = try!(Asn1Time::days_from_now(0)); let not_after = try!(Asn1Time::days_from_now(self.days)); @@ -839,7 +840,7 @@ impl<'a> GeneralName<'a> { fn test_negative_serial() { // I guess that's enough to get a random negative number for _ in 0..1000 { - assert!(X509Generator::random_serial() > 0, + assert!(X509Generator::random_serial().unwrap() > 0, "All serials should be positive"); } } From 59fe901357b6ceb8e60e49c97467829abbb64fe1 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 21:28:17 -0700 Subject: [PATCH 89/96] Method renames --- openssl/src/bio.rs | 4 ++-- openssl/src/crypto/dsa.rs | 10 ++++---- openssl/src/crypto/pkey.rs | 22 ++++++++--------- openssl/src/crypto/rsa.rs | 12 +++++----- openssl/src/dh/mod.rs | 2 +- openssl/src/ssl/mod.rs | 6 ++--- openssl/src/x509/mod.rs | 48 +++++++++++++++++++------------------- 7 files changed, 52 insertions(+), 52 deletions(-) diff --git a/openssl/src/bio.rs b/openssl/src/bio.rs index 7adcc4e6..0d82a6c3 100644 --- a/openssl/src/bio.rs +++ b/openssl/src/bio.rs @@ -28,7 +28,7 @@ impl<'a> MemBioSlice<'a> { Ok(MemBioSlice(bio, PhantomData)) } - pub fn handle(&self) -> *mut ffi::BIO { + pub fn as_ptr(&self) -> *mut ffi::BIO { self.0 } } @@ -53,7 +53,7 @@ impl MemBio { Ok(MemBio(bio)) } - pub fn handle(&self) -> *mut ffi::BIO { + pub fn as_ptr(&self) -> *mut ffi::BIO { self.0 } diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index 7d6e1c05..97ba7a97 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -72,7 +72,7 @@ impl DSA { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.handle(), + let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut())); @@ -96,7 +96,7 @@ impl DSA { unsafe { let cb_ptr = &mut cb as *mut _ as *mut c_void; - let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.handle(), + let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.as_ptr(), ptr::null_mut(), Some(invoke_passwd_cb::), cb_ptr)); @@ -113,7 +113,7 @@ impl DSA { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.handle(), self.0, + try_ssl!(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.as_ptr(), self.0, ptr::null(), ptr::null_mut(), 0, None, ptr::null_mut())) }; @@ -128,7 +128,7 @@ impl DSA { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let dsa = try_ssl_null!(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.handle(), + let dsa = try_ssl_null!(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut())); @@ -139,7 +139,7 @@ impl DSA { /// Writes an DSA public key as PEM formatted data pub fn public_key_to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); - unsafe { try_ssl!(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.handle(), self.0)) }; + unsafe { try_ssl!(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.as_ptr(), self.0)) }; Ok(mem_bio.get_buf().to_owned()) } diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 607d4986..a2a6f9c1 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -26,7 +26,7 @@ impl PKey { } } - pub unsafe fn from_handle(handle: *mut ffi::EVP_PKEY) -> PKey { + pub unsafe fn from_ptr(handle: *mut ffi::EVP_PKEY) -> PKey { PKey(handle) } @@ -35,11 +35,11 @@ impl PKey { ffi::init(); let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.handle(), + let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut())); - Ok(PKey::from_handle(evp)) + Ok(PKey::from_ptr(evp)) } } @@ -55,11 +55,11 @@ impl PKey { let mut cb = CallbackState::new(pass_cb); let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.handle(), + let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.as_ptr(), ptr::null_mut(), Some(invoke_passwd_cb::), &mut cb as *mut _ as *mut c_void)); - Ok(PKey::from_handle(evp)) + Ok(PKey::from_ptr(evp)) } } @@ -68,11 +68,11 @@ impl PKey { ffi::init(); let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.handle(), + let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut())); - Ok(PKey::from_handle(evp)) + Ok(PKey::from_ptr(evp)) } } @@ -91,7 +91,7 @@ impl PKey { unsafe { let rsa = try_ssl_null!(ffi::EVP_PKEY_get1_RSA(self.0)); // this is safe as the ffi increments a reference counter to the internal key - Ok(RSA::from_raw(rsa)) + Ok(RSA::from_ptr(rsa)) } } @@ -100,7 +100,7 @@ impl PKey { pub fn private_key_to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.handle(), + try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.as_ptr(), self.0, ptr::null(), ptr::null_mut(), @@ -115,11 +115,11 @@ impl PKey { /// Stores public key as a PEM pub fn public_key_to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); - unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.handle(), self.0)) } + unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.as_ptr(), self.0)) } Ok(mem_bio.get_buf().to_owned()) } - pub fn handle(&self) -> *mut ffi::EVP_PKEY { + pub fn as_ptr(&self) -> *mut ffi::EVP_PKEY { return self.0; } diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 822f305f..feb66a6f 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -66,7 +66,7 @@ impl RSA { } } - pub unsafe fn from_raw(rsa: *mut ffi::RSA) -> RSA { + pub unsafe fn from_ptr(rsa: *mut ffi::RSA) -> RSA { RSA(rsa) } @@ -89,7 +89,7 @@ impl RSA { pub fn private_key_from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.handle(), + let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut())); @@ -106,7 +106,7 @@ impl RSA { unsafe { let cb_ptr = &mut cb as *mut _ as *mut c_void; - let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.handle(), + let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(), ptr::null_mut(), Some(invoke_passwd_cb::), cb_ptr)); @@ -119,7 +119,7 @@ impl RSA { pub fn public_key_from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.handle(), + let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut())); @@ -132,7 +132,7 @@ impl RSA { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.handle(), + try_ssl!(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.as_ptr(), self.0, ptr::null(), ptr::null_mut(), @@ -148,7 +148,7 @@ impl RSA { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.handle(), self.0)) + try_ssl!(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.as_ptr(), self.0)) }; Ok(mem_bio.get_buf().to_owned()) diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index 1f4fd7fe..4dc17158 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -21,7 +21,7 @@ impl DH { pub fn from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); let dh = unsafe { - ffi::PEM_read_bio_DHparams(mem_bio.handle(), ptr::null_mut(), None, ptr::null_mut()) + ffi::PEM_read_bio_DHparams(mem_bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut()) }; try_ssl_null!(dh); Ok(DH(dh)) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 5c2cdd64..78a5b2ce 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -529,14 +529,14 @@ impl<'a> SslContextRef<'a> { /// Specifies the certificate pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.handle()) }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr()) }) } /// Adds a certificate to the certificate chain presented together with the /// certificate specified using set_certificate() pub fn add_extra_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { - ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.handle()) as c_int + ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int }) } @@ -555,7 +555,7 @@ impl<'a> SslContextRef<'a> { /// Specifies the private key pub fn set_private_key(&mut self, key: &PKey) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.handle()) }) + wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr()) }) } /// Check consistency of private key and certificate diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index cf5f4595..4cb4458a 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -300,24 +300,24 @@ impl X509Generator { let x509 = try_ssl_null!(ffi::X509_new()); let x509 = X509::new(x509); - try_ssl!(ffi::X509_set_version(x509.handle(), 2)); - try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.handle()), + try_ssl!(ffi::X509_set_version(x509.as_ptr(), 2)); + try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.as_ptr()), try!(X509Generator::random_serial()))); let not_before = try!(Asn1Time::days_from_now(0)); let not_after = try!(Asn1Time::days_from_now(self.days)); - try_ssl!(ffi::X509_set_notBefore(x509.handle(), not_before.as_ptr() as *const _)); + try_ssl!(ffi::X509_set_notBefore(x509.as_ptr(), not_before.as_ptr() as *const _)); // If prev line succeded - ownership should go to cert mem::forget(not_before); - try_ssl!(ffi::X509_set_notAfter(x509.handle(), not_after.as_ptr() as *const _)); + try_ssl!(ffi::X509_set_notAfter(x509.as_ptr(), not_after.as_ptr() as *const _)); // If prev line succeded - ownership should go to cert mem::forget(not_after); - try_ssl!(ffi::X509_set_pubkey(x509.handle(), p_key.handle())); + try_ssl!(ffi::X509_set_pubkey(x509.as_ptr(), p_key.as_ptr())); - let name = try_ssl_null!(ffi::X509_get_subject_name(x509.handle())); + let name = try_ssl_null!(ffi::X509_get_subject_name(x509.as_ptr())); let default = [("CN", "rust-openssl")]; let default_iter = &mut default.iter().map(|&(k, v)| (k, v)); @@ -331,16 +331,16 @@ impl X509Generator { for (key, val) in iter { try!(X509Generator::add_name_internal(name, &key, &val)); } - try_ssl!(ffi::X509_set_issuer_name(x509.handle(), name)); + try_ssl!(ffi::X509_set_issuer_name(x509.as_ptr(), name)); for (exttype, ext) in self.extensions.iter() { - try!(X509Generator::add_extension_internal(x509.handle(), + try!(X509Generator::add_extension_internal(x509.as_ptr(), &exttype, &ext.to_string())); } let hash_fn = self.hash_type.evp_md(); - try_ssl!(ffi::X509_sign(x509.handle(), p_key.handle(), hash_fn)); + try_ssl!(ffi::X509_sign(x509.as_ptr(), p_key.as_ptr(), hash_fn)); Ok(x509) } } @@ -356,16 +356,16 @@ impl X509Generator { }; unsafe { - let req = ffi::X509_to_X509_REQ(cert.handle(), ptr::null_mut(), ptr::null()); + let req = ffi::X509_to_X509_REQ(cert.as_ptr(), ptr::null_mut(), ptr::null()); try_ssl_null!(req); - let exts = ::c_helpers::rust_X509_get_extensions(cert.handle()); + let exts = ::c_helpers::rust_X509_get_extensions(cert.as_ptr()); if exts != ptr::null_mut() { try_ssl!(ffi::X509_REQ_add_extensions(req, exts)); } let hash_fn = self.hash_type.evp_md(); - try_ssl!(ffi::X509_REQ_sign(req, p_key.handle(), hash_fn)); + try_ssl!(ffi::X509_REQ_sign(req, p_key.as_ptr(), hash_fn)); Ok(X509Req::new(req)) } @@ -381,7 +381,7 @@ impl<'a> X509Ref<'a> { X509Ref(handle, PhantomData) } - pub fn handle(&self) -> *mut ffi::X509 { + pub fn as_ptr(&self) -> *mut ffi::X509 { self.0 } @@ -411,7 +411,7 @@ impl<'a> X509Ref<'a> { pub fn public_key(&self) -> Result { unsafe { let pkey = try_ssl_null!(ffi::X509_get_pubkey(self.0)); - Ok(PKey::from_handle(pkey)) + Ok(PKey::from_ptr(pkey)) } } @@ -431,7 +431,7 @@ impl<'a> X509Ref<'a> { pub fn to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_X509(mem_bio.handle(), self.0)); + try_ssl!(ffi::PEM_write_bio_X509(mem_bio.as_ptr(), self.0)); } Ok(mem_bio.get_buf().to_owned()) } @@ -440,7 +440,7 @@ impl<'a> X509Ref<'a> { pub fn to_der(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - ffi::i2d_X509_bio(mem_bio.handle(), self.0); + ffi::i2d_X509_bio(mem_bio.as_ptr(), self.0); } Ok(mem_bio.get_buf().to_owned()) } @@ -459,7 +459,7 @@ impl X509 { pub fn from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.handle(), + let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut())); @@ -481,15 +481,15 @@ impl Clone for X509 { /// Requires the `x509_clone` feature. fn clone(&self) -> X509 { unsafe { - ::c_helpers::rust_X509_clone(self.handle()); - X509::new(self.handle()) + ::c_helpers::rust_X509_clone(self.as_ptr()); + X509::new(self.as_ptr()) } } } impl Drop for X509 { fn drop(&mut self) { - unsafe { ffi::X509_free(self.handle()) }; + unsafe { ffi::X509_free(self.as_ptr()) }; } } @@ -536,7 +536,7 @@ impl X509Req { X509Req(handle) } - pub fn handle(&self) -> *mut ffi::X509_REQ { + pub fn as_ptr(&self) -> *mut ffi::X509_REQ { self.0 } @@ -544,7 +544,7 @@ impl X509Req { pub fn from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.handle(), + let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut())); @@ -555,7 +555,7 @@ impl X509Req { /// Writes CSR as PEM pub fn to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); - if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.handle(), self.0) } != 1 { + if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.as_ptr(), self.0) } != 1 { return Err(ErrorStack::get()); } Ok(mem_bio.get_buf().to_owned()) @@ -565,7 +565,7 @@ impl X509Req { pub fn to_der(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - ffi::i2d_X509_REQ_bio(mem_bio.handle(), self.0); + ffi::i2d_X509_REQ_bio(mem_bio.as_ptr(), self.0); } Ok(mem_bio.get_buf().to_owned()) } From 9a3fa4d98dc0fe9d2bd7ae10e465fb425c8ca041 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 21:37:24 -0700 Subject: [PATCH 90/96] Fix build --- openssl/src/dh/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index 4dc17158..78dcb778 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -3,6 +3,11 @@ use error::ErrorStack; use bio::MemBioSlice; use std::ptr; +#[cfg(feature = "dh_from_params")] +use bn::BigNum; +#[cfg(feature = "dh_from_params")] +use std::mem; + pub struct DH(*mut ffi::DH); impl DH { From 0359afb99ec7452ebc524d4e9999c6ef72ac951d Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 22:02:36 -0700 Subject: [PATCH 91/96] Little tweaks --- openssl/src/ssl/mod.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 78a5b2ce..82ee3127 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -733,6 +733,7 @@ pub struct CipherBits { pub secret: i32, /// The number of bits processed by the chosen algorithm, if not None. pub algorithm: Option, + _p: (), } @@ -771,11 +772,13 @@ impl<'a> SslCipher<'a> { CipherBits { secret: secret_bits, algorithm: Some(*algo_bits), + _p: (), } } else { CipherBits { secret: secret_bits, algorithm: None, + _p: (), } } } @@ -1015,10 +1018,10 @@ impl<'a> SslRef<'a> { Some(s) } - pub fn ssl_method(&self) -> Option { + pub fn ssl_method(&self) -> SslMethod { unsafe { let method = ffi::SSL_get_ssl_method(self.as_ptr()); - SslMethod::from_raw(method) + SslMethod::from_raw(method).unwrap() } } @@ -1254,7 +1257,7 @@ impl MidHandshakeSslStream { self.stream.get_mut() } - /// Returns a shared reference to the `SslContext` of the stream. + /// Returns a shared reference to the `Ssl` of the stream. pub fn ssl(&self) -> &Ssl { self.stream.ssl() } From b21805f541074beb2bd7e939e15ad72aa2758c4c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 22:10:32 -0700 Subject: [PATCH 92/96] Fix tests --- openssl/src/ssl/tests/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 692add2c..bfcaa5e4 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -228,7 +228,7 @@ run_test!(new_sslstream, |method, stream| { run_test!(get_ssl_method, |method, _| { let ssl = Ssl::new(&SslContext::new(method).unwrap()).unwrap(); - assert_eq!(ssl.ssl_method(), Some(method)); + assert_eq!(ssl.ssl_method(), method); }); run_test!(verify_untrusted, |method, stream| { From 0cc863e8576808e73669e0d96a6e63ae46a308ee Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 22:13:17 -0700 Subject: [PATCH 93/96] Use new target syntax for windows stuff --- openssl-sys/Cargo.toml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 9e923eb0..d1c0bd80 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -42,15 +42,6 @@ libressl-pnacl-sys = "2.1.0" libressl-pnacl-sys = "2.1.0" # Only here to make sure we link to these in a static build on Windows -[target.i686-pc-windows-gnu.dependencies] -user32-sys = "0.2" -gdi32-sys = "0.2" -[target.x86_64-pc-windows-gnu.dependencies] -user32-sys = "0.2" -gdi32-sys = "0.2" -[target.i686-pc-windows-msvc.dependencies] -user32-sys = "0.2" -gdi32-sys = "0.2" -[target.x86_64-pc-windows-msvc.dependencies] +[target.'cfg(windows)'.dependencies] user32-sys = "0.2" gdi32-sys = "0.2" From 207d8e6b306a8224b79c93b7b07fb3b4cf783cff Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 22:16:58 -0700 Subject: [PATCH 94/96] Undelete bogus extern declaration Old rust-openssl versions rely on it being there --- openssl-sys/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 2f01196f..7058e194 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -717,6 +717,9 @@ extern "C" { #[cfg(feature = "rfc5114")] pub fn DH_get_2048_256() -> *mut DH; + // FIXME delete on next version bump + pub fn DH_new_from_params(p: *mut BIGNUM, g: *mut BIGNUM, q: *mut BIGNUM) -> *mut DH; + pub fn ERR_get_error() -> c_ulong; pub fn ERR_lib_error_string(err: c_ulong) -> *const c_char; From 63239bf3eea469ec34ebf2ebd21876c4cdb61de4 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 11 Aug 2016 20:52:43 -0700 Subject: [PATCH 95/96] Require bitflags 7 --- openssl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 17802aed..47d0a8e0 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -35,7 +35,7 @@ hmac = ["c_helpers"] dh_from_params = ["c_helpers"] [dependencies] -bitflags = ">= 0.5.0, < 0.8.0" +bitflags = "0.7" lazy_static = "0.2" libc = "0.2" openssl-sys = { version = "0.7.14", path = "../openssl-sys" } From 2e8f19ca2fc889e9f143ecda997e17e7955683ab Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 11 Aug 2016 21:00:43 -0700 Subject: [PATCH 96/96] Release openssl-sys v0.7.15, openssl v0.8.0 --- README.md | 2 +- openssl-sys/Cargo.toml | 4 ++-- openssl-sys/src/lib.rs | 2 +- openssl/Cargo.toml | 6 +++--- openssl/src/lib.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b3ce0bc0..ec7eecf1 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/sfackler/rust-openssl.svg?branch=master)](https://travis-ci.org/sfackler/rust-openssl) -[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.7.14/openssl). +[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.8.0/openssl). ## Building diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index d1c0bd80..e09c2020 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "openssl-sys" -version = "0.7.14" +version = "0.7.15" authors = ["Alex Crichton ", "Steven Fackler "] license = "MIT" description = "FFI bindings to OpenSSL" repository = "https://github.com/sfackler/rust-openssl" -documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.14/openssl_sys" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.15/openssl_sys" links = "openssl" build = "build.rs" diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 7058e194..24d3bf57 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] #![allow(dead_code)] -#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.14")] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.15")] extern crate libc; diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 47d0a8e0..a5d0de8b 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "openssl" -version = "0.7.14" +version = "0.8.0" authors = ["Steven Fackler "] license = "Apache-2.0" description = "OpenSSL bindings" repository = "https://github.com/sfackler/rust-openssl" -documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.14/openssl" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.8.0/openssl" readme = "../README.md" keywords = ["crypto", "tls", "ssl", "dtls"] build = "build.rs" @@ -38,7 +38,7 @@ dh_from_params = ["c_helpers"] bitflags = "0.7" lazy_static = "0.2" libc = "0.2" -openssl-sys = { version = "0.7.14", path = "../openssl-sys" } +openssl-sys = { version = "0.7.15", path = "../openssl-sys" } [build-dependencies] gcc = { version = "0.3", optional = true } diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index fdf9548c..d7e69b0c 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.14")] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.8.0")] #[macro_use] extern crate bitflags;