From fa622326490e1dd27df4d42b4097ca574deedb3f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 30 Jan 2016 12:55:22 -0800 Subject: Error reform --- openssl/src/crypto/pkey.rs | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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); -- cgit v1.2.3 From 311af7c3be6eac14b257a695f3c3c428ca177b08 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 13 Jun 2016 21:17:20 +0200 Subject: Add PKey::private_key_from_pem_cb --- openssl/src/crypto/pkey.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'openssl/src/crypto/pkey.rs') 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 -- cgit v1.2.3 From f0b4a032d5a6cdf3928318e113dcfd7e0ecf03f9 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 13 Jun 2016 21:47:02 +0200 Subject: Try to propagate callback panics --- openssl/src/crypto/pkey.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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, -- cgit v1.2.3 From 8119f06ca5ca50a677cf584cbe816500153ce783 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 14 Jun 2016 18:12:50 +0200 Subject: Move into utility module --- openssl/src/crypto/pkey.rs | 43 ++++--------------------------------------- 1 file changed, 4 insertions(+), 39 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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, -- cgit v1.2.3 From c1b7cd2420c679b611c7ff28024db10cb0ffb8b5 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 22 Jun 2016 21:51:43 +0200 Subject: Make the callback take a `&mut [c_char]` --- openssl/src/crypto/pkey.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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); -- cgit v1.2.3 From 41b78547ad0357d3e86462f72c0cff333096d59f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 22 Jun 2016 22:05:03 +0200 Subject: Put password callbacks behind a cargo feature --- openssl/src/crypto/pkey.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'openssl/src/crypto/pkey.rs') 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 { -- cgit v1.2.3 From f24ab2693636f16ce71a171a4d4d63bd0f5bbea0 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 26 Jun 2016 19:44:53 +0200 Subject: FnMut -> FnOnce, update docs --- openssl/src/crypto/pkey.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'openssl/src/crypto/pkey.rs') 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); -- cgit v1.2.3 From e86eb68624592a31b4f59d27e6a9ace7c034e0bf Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 31 Jul 2016 15:49:09 -0700 Subject: Fix catch_unwind feature and drop feature gate --- openssl/src/crypto/pkey.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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(), -- cgit v1.2.3 From 08e27f31ed851873f7684ac806b837e8cff4a28f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 2 Aug 2016 20:48:42 -0700 Subject: 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/src/crypto/pkey.rs | 114 +++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 82 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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 = super::PKey::private_key_from_pem(&mut file).unwrap(); - - let mut priv_key = Vec::new(); - let mut pub_key = Vec::new(); + let key = include_bytes!("../../test/key.pem"); + let key = super::PKey::private_key_from_pem(key).unwrap(); - 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. -- cgit v1.2.3 From fe47e93f2f5b6c2b2243b15445bbfdd4e58780b1 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 5 Aug 2016 21:04:40 -0700 Subject: Fix pkey method safety --- openssl/src/crypto/pkey.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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 => { -- cgit v1.2.3 From bc97d088b0e71a1bde0a88bc548718c427124d0c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 5 Aug 2016 21:07:17 -0700 Subject: get_handle -> handle --- openssl/src/crypto/pkey.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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()) } -- cgit v1.2.3 From 05089bacb3cde8fe3ec9f68b5682668d4f63383c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 14:19:44 -0700 Subject: Refactor BigNum --- openssl/src/crypto/pkey.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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()); } } -- cgit v1.2.3 From 7ca5ccf0646478b6d3557b066594d7e7afc36c53 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 16:28:29 -0700 Subject: Hash reform Closes #430 --- openssl/src/crypto/pkey.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openssl/src/crypto/pkey.rs') 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; -- cgit v1.2.3 From 7855f428aa48fcb6f4e8ad4c452783df88d20935 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 20:38:46 -0700 Subject: PKey reform This deletes the vast majority of PKey's API, since it was weirdly tied to RSA and super broken. --- openssl/src/crypto/pkey.rs | 778 ++------------------------------------------- 1 file changed, 30 insertions(+), 748 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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); - } - } -} - -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 => {} + ffi::EVP_PKEY_free(self.0); } - 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()); - } } -- cgit v1.2.3 From 6b1016c86e72d26d15584789456bd317bee92bca Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 7 Aug 2016 22:56:44 -0700 Subject: Add PKey::from_rsa --- openssl/src/crypto/pkey.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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) } } -- cgit v1.2.3 From 59fe901357b6ceb8e60e49c97467829abbb64fe1 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 10 Aug 2016 21:28:17 -0700 Subject: Method renames --- openssl/src/crypto/pkey.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'openssl/src/crypto/pkey.rs') 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; } -- cgit v1.2.3