diff options
| author | Steven Fackler <[email protected]> | 2016-07-31 15:15:47 -0700 |
|---|---|---|
| committer | Steven Fackler <[email protected]> | 2016-07-31 15:15:47 -0700 |
| commit | f0ffa246b83102d70bc59f76d136981efdafb1e7 (patch) | |
| tree | 0f6036a20ba4eb7b333986206962abeb4bab6c2f /openssl/src/crypto/pkey.rs | |
| parent | Revert "Add a new trait based Nid setup" (diff) | |
| parent | Merge pull request #402 from bbatha/feat/dsa-ffi (diff) | |
| download | rust-openssl-f0ffa246b83102d70bc59f76d136981efdafb1e7.tar.xz rust-openssl-f0ffa246b83102d70bc59f76d136981efdafb1e7.zip | |
Merge remote-tracking branch 'origin/master' into breaks
Diffstat (limited to 'openssl/src/crypto/pkey.rs')
| -rw-r--r-- | openssl/src/crypto/pkey.rs | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 1020a82e..0231cc95 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -5,12 +5,19 @@ use std::iter::repeat; use std::mem; use std::ptr; use bio::MemBio; + +use crypto::HashTypeInternals; use crypto::hash; 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)] pub enum Parts { Neither, @@ -41,18 +48,6 @@ fn openssl_padding_code(padding: EncryptionPadding) -> c_int { } } -fn openssl_hash_nid(hash: HashType) -> c_int { - match hash { - HashType::MD5 => 4, // NID_md5, - HashType::SHA1 => 64, // NID_sha1 - HashType::SHA224 => 675, // NID_sha224 - HashType::SHA256 => 672, // NID_sha256 - HashType::SHA384 => 673, // NID_sha384 - HashType::SHA512 => 674, // NID_sha512 - HashType::RIPEMD160 => 117, // NID_ripemd160 - } -} - pub struct PKey { evp: *mut ffi::EVP_PKEY, parts: Parts, @@ -104,6 +99,35 @@ 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. + /// + /// Requires the `catch_unwind` feature. + #[cfg(feature = "catch_unwind")] + pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> Result<PKey, SslError> + 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 evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), + ptr::null_mut(), + Some(invoke_passwd_cb::<F>), + &mut 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<R>(reader: &mut R) -> io::Result<PKey> where R: Read @@ -125,7 +149,7 @@ impl PKey { /// Reads an RSA private key from PEM, takes ownership of handle pub fn private_rsa_key_from_pem<R>(reader: &mut R) -> io::Result<PKey> - where R: Read + where R: Read { let rsa = try!(RSA::private_key_from_pem(reader)); unsafe { @@ -143,7 +167,7 @@ impl PKey { /// Reads an RSA public key from PEM, takes ownership of handle pub fn public_rsa_key_from_pem<R>(reader: &mut R) -> io::Result<PKey> - where R: Read + where R: Read { let rsa = try!(RSA::public_key_from_pem(reader)); unsafe { @@ -561,7 +585,7 @@ impl PKey { let mut r = repeat(0u8).take(len as usize + 1).collect::<Vec<_>>(); let mut len = 0; - let rv = ffi::RSA_sign(openssl_hash_nid(hash), + let rv = ffi::RSA_sign(hash.as_nid() as c_int, s.as_ptr(), s.len() as c_uint, r.as_mut_ptr(), @@ -584,7 +608,7 @@ impl PKey { panic!("Could not get RSA key for verification"); } - let rv = ffi::RSA_verify(openssl_hash_nid(hash), + let rv = ffi::RSA_verify(hash.as_nid() as c_int, h.as_ptr(), h.len() as c_uint, s.as_ptr(), @@ -615,16 +639,15 @@ 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); - // copy by encoding to DER and back + // 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 => { - }, + } + Parts::Neither => {} } pkey } @@ -699,8 +722,8 @@ mod tests { 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`"); + .ok() + .expect("Failed to open `test/key.pem`"); super::PKey::private_rsa_key_from_pem(&mut file).unwrap(); } @@ -709,8 +732,8 @@ mod tests { 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`"); + .ok() + .expect("Failed to open `test/key.pem.pub`"); super::PKey::public_rsa_key_from_pem(&mut file).unwrap(); } |