aboutsummaryrefslogtreecommitdiff
path: root/openssl/src
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2016-11-13 15:02:38 +0000
committerSteven Fackler <[email protected]>2016-11-13 15:02:38 +0000
commit08e0c4ca9061c3dc0c951db0c08909689b04a310 (patch)
tree117d95bb3cc28cf88cdedb97c985bbe9db436415 /openssl/src
parentNo need to use a raw string anymore (diff)
downloadrust-openssl-08e0c4ca9061c3dc0c951db0c08909689b04a310.tar.xz
rust-openssl-08e0c4ca9061c3dc0c951db0c08909689b04a310.zip
Some serialization support for EcKey
Diffstat (limited to 'openssl/src')
-rw-r--r--openssl/src/dsa.rs35
-rw-r--r--openssl/src/ec_key.rs28
-rw-r--r--openssl/src/lib.rs42
-rw-r--r--openssl/src/macros.rs77
-rw-r--r--openssl/src/pkey.rs23
-rw-r--r--openssl/src/rsa.rs30
-rw-r--r--openssl/src/util.rs31
7 files changed, 148 insertions, 118 deletions
diff --git a/openssl/src/dsa.rs b/openssl/src/dsa.rs
index 72076775..962fcc9c 100644
--- a/openssl/src/dsa.rs
+++ b/openssl/src/dsa.rs
@@ -9,7 +9,7 @@ use bio::{MemBio, MemBioSlice};
use bn::BigNumRef;
use {cvt, cvt_p};
use types::OpenSslTypeRef;
-use util::{CallbackState, invoke_passwd_cb};
+use util::{CallbackState, invoke_passwd_cb_old};
type_!(Dsa, DsaRef, ffi::DSA, ffi::DSA_free);
@@ -125,25 +125,9 @@ impl Dsa {
}
}
- /// Reads a DSA private key from PEM formatted data.
- pub fn private_key_from_pem(buf: &[u8]) -> Result<Dsa, ErrorStack> {
- ffi::init();
- let mem_bio = try!(MemBioSlice::new(buf));
-
- unsafe {
- let dsa = try!(cvt_p(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.as_ptr(),
- ptr::null_mut(),
- None,
- ptr::null_mut())));
- Ok(Dsa(dsa))
- }
- }
+ private_key_from_pem!(Dsa, ffi::PEM_read_bio_DSAPrivateKey);
- /// 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.
+ #[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")]
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<Dsa, ErrorStack>
where F: FnOnce(&mut [c_char]) -> usize
{
@@ -155,7 +139,7 @@ impl Dsa {
let cb_ptr = &mut cb as *mut _ as *mut c_void;
let dsa = try!(cvt_p(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.as_ptr(),
ptr::null_mut(),
- Some(invoke_passwd_cb::<F>),
+ Some(invoke_passwd_cb_old::<F>),
cb_ptr)));
Ok(Dsa(dsa))
}
@@ -235,8 +219,6 @@ mod compat {
#[cfg(test)]
mod test {
- use libc::c_char;
-
use super::*;
#[test]
@@ -248,14 +230,9 @@ mod test {
pub fn test_password() {
let mut password_queried = false;
let key = include_bytes!("../test/dsa-encrypted.pem");
- Dsa::private_key_from_pem_cb(key, |password| {
+ Dsa::private_key_from_pem_callback(key, |password| {
password_queried = true;
- 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;
+ password[..6].copy_from_slice(b"mypass");
6
})
.unwrap();
diff --git a/openssl/src/ec_key.rs b/openssl/src/ec_key.rs
index ad85dc5e..99d62ad3 100644
--- a/openssl/src/ec_key.rs
+++ b/openssl/src/ec_key.rs
@@ -1,11 +1,27 @@
use ffi;
+use std::cmp;
+use libc::c_long;
+use std::ptr;
-use {cvt_p, init};
+use {cvt, cvt_p, init};
use error::ErrorStack;
use nid::Nid;
+use types::OpenSslTypeRef;
type_!(EcKey, EcKeyRef, ffi::EC_KEY, ffi::EC_KEY_free);
+impl EcKeyRef {
+ /// Serializes the private key components to DER.
+ pub fn private_key_to_der(&self) -> Result<Vec<u8>, ErrorStack> {
+ unsafe {
+ let len = try!(cvt(ffi::i2d_ECPrivateKey(self.as_ptr(), ptr::null_mut())));
+ let mut buf = vec![0; len as usize];
+ try!(cvt(ffi::i2d_ECPrivateKey(self.as_ptr(), &mut buf.as_mut_ptr())));
+ Ok(buf)
+ }
+ }
+}
+
impl EcKey {
pub fn new_by_curve_name(nid: Nid) -> Result<EcKey, ErrorStack> {
unsafe {
@@ -13,6 +29,16 @@ impl EcKey {
cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(EcKey)
}
}
+ /// Deserializes a DER-encoded private key.
+ pub fn private_key_from_der(der: &[u8]) -> Result<EcKey, ErrorStack> {
+ unsafe {
+ init();
+ let len = cmp::min(der.len(), c_long::max_value() as usize) as c_long;
+ cvt_p(ffi::d2i_ECPrivateKey(ptr::null_mut(), &mut der.as_ptr(), len)).map(EcKey)
+ }
+ }
+
+ private_key_from_pem!(EcKey, ffi::PEM_read_bio_ECPrivateKey);
}
#[cfg(test)]
diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs
index d3f99de7..c2c559dc 100644
--- a/openssl/src/lib.rs
+++ b/openssl/src/lib.rs
@@ -19,46 +19,8 @@ use libc::c_int;
use error::ErrorStack;
-macro_rules! type_ {
- ($n:ident, $r:ident, $c:path, $d:path) => {
- pub struct $n(*mut $c);
-
- impl ::types::OpenSslType for $n {
- type CType = $c;
- type Ref = $r;
-
- unsafe fn from_ptr(ptr: *mut $c) -> $n {
- $n(ptr)
- }
- }
-
- impl Drop for $n {
- fn drop(&mut self) {
- unsafe { $d(self.0) }
- }
- }
-
- impl ::std::ops::Deref for $n {
- type Target = $r;
-
- fn deref(&self) -> &$r {
- unsafe { ::types::OpenSslTypeRef::from_ptr(self.0) }
- }
- }
-
- impl ::std::ops::DerefMut for $n {
- fn deref_mut(&mut self) -> &mut $r {
- unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.0) }
- }
- }
-
- pub struct $r(::util::Opaque);
-
- impl ::types::OpenSslTypeRef for $r {
- type CType = $c;
- }
- }
-}
+#[macro_use]
+mod macros;
mod bio;
mod util;
diff --git a/openssl/src/macros.rs b/openssl/src/macros.rs
new file mode 100644
index 00000000..0db3401c
--- /dev/null
+++ b/openssl/src/macros.rs
@@ -0,0 +1,77 @@
+
+macro_rules! type_ {
+ ($n:ident, $r:ident, $c:path, $d:path) => {
+ pub struct $n(*mut $c);
+
+ impl ::types::OpenSslType for $n {
+ type CType = $c;
+ type Ref = $r;
+
+ unsafe fn from_ptr(ptr: *mut $c) -> $n {
+ $n(ptr)
+ }
+ }
+
+ impl Drop for $n {
+ fn drop(&mut self) {
+ unsafe { $d(self.0) }
+ }
+ }
+
+ impl ::std::ops::Deref for $n {
+ type Target = $r;
+
+ fn deref(&self) -> &$r {
+ unsafe { ::types::OpenSslTypeRef::from_ptr(self.0) }
+ }
+ }
+
+ impl ::std::ops::DerefMut for $n {
+ fn deref_mut(&mut self) -> &mut $r {
+ unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.0) }
+ }
+ }
+
+ pub struct $r(::util::Opaque);
+
+ impl ::types::OpenSslTypeRef for $r {
+ type CType = $c;
+ }
+ }
+}
+
+macro_rules! private_key_from_pem {
+ ($t:ident, $f:path) => {
+ /// Deserializes a PEM-formatted private key.
+ pub fn private_key_from_pem(pem: &[u8]) -> Result<$t, ::error::ErrorStack> {
+ unsafe {
+ ::init();
+ let bio = try!(::bio::MemBioSlice::new(pem));
+ cvt_p($f(bio.as_ptr(), ::std::ptr::null_mut(), None, ::std::ptr::null_mut()))
+ .map($t)
+ }
+ }
+
+ /// Deserializes a PEM-formatted private key, using a callback to retrieve a password if the
+ /// key is encrypted.
+ ///
+ /// The callback should copy the password into the provided buffer and return the number of
+ /// bytes written.
+ pub fn private_key_from_pem_callback<F>(pem: &[u8],
+ callback: F)
+ -> Result<$t, ::error::ErrorStack>
+ where F: FnOnce(&mut [u8]) -> usize
+ {
+ unsafe {
+ ffi::init();
+ let mut cb = ::util::CallbackState::new(callback);
+ let bio = try!(::bio::MemBioSlice::new(pem));
+ cvt_p($f(bio.as_ptr(),
+ ptr::null_mut(),
+ Some(::util::invoke_passwd_cb::<F>),
+ &mut cb as *mut _ as *mut ::libc::c_void))
+ .map($t)
+ }
+ }
+ }
+}
diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs
index 43eadd43..a56633a2 100644
--- a/openssl/src/pkey.rs
+++ b/openssl/src/pkey.rs
@@ -10,7 +10,7 @@ use dsa::Dsa;
use ec_key::EcKey;
use rsa::Rsa;
use error::ErrorStack;
-use util::{CallbackState, invoke_passwd_cb};
+use util::{CallbackState, invoke_passwd_cb_old};
use types::{OpenSslType, OpenSslTypeRef};
type_!(PKey, PKeyRef, ffi::EVP_PKEY, ffi::EVP_PKEY_free);
@@ -166,24 +166,9 @@ impl PKey {
}
}
- /// Reads a private key from PEM.
- pub fn private_key_from_pem(buf: &[u8]) -> Result<PKey, ErrorStack> {
- ffi::init();
- let mem_bio = try!(MemBioSlice::new(buf));
- unsafe {
- let evp = try!(cvt_p(ffi::PEM_read_bio_PrivateKey(mem_bio.as_ptr(),
- ptr::null_mut(),
- None,
- ptr::null_mut())));
- Ok(PKey::from_ptr(evp))
- }
- }
+ private_key_from_pem!(PKey, ffi::PEM_read_bio_PrivateKey);
- /// 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.
+ #[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")]
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<PKey, ErrorStack>
where F: FnOnce(&mut [c_char]) -> usize
{
@@ -193,7 +178,7 @@ impl PKey {
unsafe {
let evp = try!(cvt_p(ffi::PEM_read_bio_PrivateKey(mem_bio.as_ptr(),
ptr::null_mut(),
- Some(invoke_passwd_cb::<F>),
+ Some(invoke_passwd_cb_old::<F>),
&mut cb as *mut _ as *mut c_void)));
Ok(PKey::from_ptr(evp))
}
diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs
index bd36570d..22668e19 100644
--- a/openssl/src/rsa.rs
+++ b/openssl/src/rsa.rs
@@ -9,7 +9,7 @@ use {cvt, cvt_p, cvt_n};
use bn::{BigNum, BigNumRef};
use bio::{MemBio, MemBioSlice};
use error::ErrorStack;
-use util::{CallbackState, invoke_passwd_cb};
+use util::{CallbackState, invoke_passwd_cb_old};
use types::OpenSslTypeRef;
/// Type of encryption padding to use.
@@ -281,20 +281,9 @@ impl Rsa {
}
}
- /// Reads an RSA private key from PEM formatted data.
- pub fn private_key_from_pem(buf: &[u8]) -> Result<Rsa, ErrorStack> {
- ffi::init();
- let mem_bio = try!(MemBioSlice::new(buf));
- unsafe {
- let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(),
- ptr::null_mut(),
- None,
- ptr::null_mut())));
- Ok(Rsa(rsa))
- }
- }
+ private_key_from_pem!(Rsa, ffi::PEM_read_bio_RSAPrivateKey);
- /// Reads an RSA private key from PEM formatted data and supplies a password callback.
+ #[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")]
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<Rsa, ErrorStack>
where F: FnOnce(&mut [c_char]) -> usize
{
@@ -306,7 +295,7 @@ impl Rsa {
let cb_ptr = &mut cb as *mut _ as *mut c_void;
let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(),
ptr::null_mut(),
- Some(invoke_passwd_cb::<F>),
+ Some(invoke_passwd_cb_old::<F>),
cb_ptr)));
Ok(Rsa(rsa))
}
@@ -429,22 +418,15 @@ mod compat {
#[cfg(test)]
mod test {
- use libc::c_char;
-
use super::*;
#[test]
pub fn test_password() {
let mut password_queried = false;
let key = include_bytes!("../test/rsa-encrypted.pem");
- Rsa::private_key_from_pem_cb(key, |password| {
+ Rsa::private_key_from_pem_callback(key, |password| {
password_queried = true;
- 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;
+ password[..6].copy_from_slice(b"mypass");
6
})
.unwrap();
diff --git a/openssl/src/util.rs b/openssl/src/util.rs
index 302bd316..dea94668 100644
--- a/openssl/src/util.rs
+++ b/openssl/src/util.rs
@@ -33,10 +33,7 @@ impl<F> Drop for CallbackState<F> {
}
}
-/// Password callback function, passed to private key loading functions.
-///
-/// `cb_state` is expected to be a pointer to a `CallbackState`.
-pub unsafe extern "C" fn invoke_passwd_cb<F>(buf: *mut c_char,
+pub unsafe extern fn invoke_passwd_cb_old<F>(buf: *mut c_char,
size: c_int,
_rwflag: c_int,
cb_state: *mut c_void)
@@ -46,9 +43,33 @@ pub unsafe extern "C" fn invoke_passwd_cb<F>(buf: *mut c_char,
let callback = &mut *(cb_state as *mut CallbackState<F>);
let result = panic::catch_unwind(AssertUnwindSafe(|| {
- // build a `i8` slice to pass to the user callback
let pass_slice = slice::from_raw_parts_mut(buf, size as usize);
+ callback.cb.take().unwrap()(pass_slice)
+ }));
+ match result {
+ Ok(len) => len as c_int,
+ Err(err) => {
+ callback.panic = Some(err);
+ 0
+ }
+ }
+}
+
+/// Password callback function, passed to private key loading functions.
+///
+/// `cb_state` is expected to be a pointer to a `CallbackState`.
+pub unsafe extern fn invoke_passwd_cb<F>(buf: *mut c_char,
+ size: c_int,
+ _rwflag: c_int,
+ cb_state: *mut c_void)
+ -> c_int
+ where F: FnOnce(&mut [u8]) -> usize
+{
+ let callback = &mut *(cb_state as *mut CallbackState<F>);
+
+ let result = panic::catch_unwind(AssertUnwindSafe(|| {
+ let pass_slice = slice::from_raw_parts_mut(buf as *mut u8, size as usize);
callback.cb.take().unwrap()(pass_slice)
}));