Commit 08e0c4ca authored by Steven Fackler's avatar Steven Fackler
Browse files

Some serialization support for EcKey

parent 85c1474c
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -1513,11 +1513,19 @@ extern {
                                       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;

    pub fn PEM_write_bio_ECPrivateKey(bio: *mut BIO,
                                      key: *mut EC_KEY,
                                      cipher: *const EVP_CIPHER,
                                      kstr: *mut c_uchar,
                                      klen: c_int,
                                      callback: Option<PasswordCallback>,
                                      user_data: *mut c_void)
                                      -> c_int;
    pub fn PEM_read_bio_ECPrivateKey(bio: *mut BIO, key: *mut *mut EC_KEY, callback: Option<PasswordCallback>, user_data: *mut c_void) -> *mut EC_KEY;

    pub fn PKCS5_PBKDF2_HMAC_SHA1(pass: *const c_char, passlen: c_int,
                                  salt: *const u8, saltlen: c_int,
                                  iter: c_int, keylen: c_int,
@@ -1744,6 +1752,9 @@ extern {
    pub fn d2i_DSAPrivateKey(a: *mut *mut DSA, pp: *mut *const c_uchar, length: c_long) -> *mut DSA;
    pub fn i2d_DSAPrivateKey(a: *const DSA, pp: *mut *mut c_uchar) -> c_int;

    pub fn d2i_ECPrivateKey(k: *mut *mut EC_KEY, pp: *mut *const c_uchar, length: c_long) -> *mut EC_KEY;
    pub fn i2d_ECPrivateKey(ec_key: *mut EC_KEY, pp: *mut *mut c_uchar) -> c_int;

    pub fn d2i_X509(a: *mut *mut X509, pp: *mut *const c_uchar, length: c_long) -> *mut X509;
    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;
+6 −29
Original line number Diff line number Diff line
@@ -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();
+27 −1
Original line number Diff line number Diff line
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)]
+2 −40
Original line number Diff line number Diff line
@@ -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;

openssl/src/macros.rs

0 → 100644
+77 −0
Original line number Diff line number Diff line

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)
            }
        }
    }
}
Loading