diff options
| author | Jonas Schievink <[email protected]> | 2016-06-13 21:17:20 +0200 |
|---|---|---|
| committer | Jonas Schievink <[email protected]> | 2016-06-26 18:25:54 +0200 |
| commit | 311af7c3be6eac14b257a695f3c3c428ca177b08 (patch) | |
| tree | 1bcf0013515ee95dcc8939efc310b26816d775a1 /openssl/src/crypto | |
| parent | Test on 1.8 (diff) | |
| download | rust-openssl-311af7c3be6eac14b257a695f3c3c428ca177b08.tar.xz rust-openssl-311af7c3be6eac14b257a695f3c3c428ca177b08.zip | |
Add PKey::private_key_from_pem_cb
Diffstat (limited to 'openssl/src/crypto')
| -rw-r--r-- | openssl/src/crypto/pkey.rs | 49 |
1 files changed, 48 insertions, 1 deletions
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<R, F>(reader: &mut R, mut pass_cb: F) -> Result<PKey, SslError> + where R: Read, F: FnMut(&mut [i8]) -> usize + { + extern "C" fn user_cb_wrapper<F>(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::<F>), + &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<R>(reader: &mut R) -> Result<PKey, SslError> where R: Read |