Commit 3c197022 authored by Steven Fackler's avatar Steven Fackler
Browse files

Rename key serialization/deserialization methods

Also document their specific formats.

Closes #502
parent 753a7d07
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2620,6 +2620,8 @@ extern "C" {
    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_DSA_PUBKEY(k: *mut *mut DSA, pp: *mut *const c_uchar, length: c_long) -> *mut DSA;
    pub fn i2d_DSA_PUBKEY(a: *mut DSA, pp: *mut *mut c_uchar) -> c_int;

    pub fn d2i_ECPrivateKey(
        k: *mut *mut EC_KEY,
+48 −8
Original line number Diff line number Diff line
@@ -21,8 +21,27 @@ impl<T> DhRef<T>
where
    T: HasParams,
{
    to_pem!(ffi::PEM_write_bio_DHparams);
    to_der!(ffi::i2d_DHparams);
    to_pem! {
        /// Serializes the parameters into a PEM-encoded PKCS#3 DHparameter structure.
        ///
        /// The output will have a header of `-----BEGIN DH PARAMETERS-----`.
        ///
        /// This corresponds to [`PEM_write_bio_DHparams`].
        ///
        /// [`PEM_write_bio_DHparams`]: https://www.openssl.org/docs/manmaster/man3/PEM_write_bio_DHparams.html
        params_to_pem,
        ffi::PEM_write_bio_DHparams
    }

    to_der! {
        /// Serializes the parameters into a DER-encoded PKCS#3 DHparameter structure.
        ///
        /// This corresponds to [`i2d_DHparams`].
        ///
        /// [`i2d_DHparams`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_DHparams.html
        params_to_der,
        ffi::i2d_DHparams
    }
}

impl Dh<Params> {
@@ -40,8 +59,29 @@ impl Dh<Params> {
        }
    }

    from_pem!(Dh<Params>, ffi::PEM_read_bio_DHparams);
    from_der!(Dh<Params>, ffi::d2i_DHparams);
    from_pem! {
        /// Deserializes a PEM-encoded PKCS#3 DHpararameters structure.
        ///
        /// The input should have a header of `-----BEGIN DH PARAMETERS-----`.
        ///
        /// This corresponds to [`PEM_read_bio_DHparams`].
        ///
        /// [`PEM_read_bio_DHparams`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_DHparams.html
        params_from_pem,
        Dh<Params>,
        ffi::PEM_read_bio_DHparams
    }

    from_der! {
        /// Deserializes a DER-encoded PKCS#3 DHparameters structure.
        ///
        /// This corresponds to [`d2i_DHparams`].
        ///
        /// [`d2i_DHparams`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_DHparams.html
        params_from_der,
        Dh<Params>,
        ffi::d2i_DHparams
    }

    /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0.
    #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
@@ -143,15 +183,15 @@ mod tests {
    fn test_dh_from_pem() {
        let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
        let params = include_bytes!("../test/dhparams.pem");
        let dh = Dh::from_pem(params).unwrap();
        let dh = Dh::params_from_pem(params).unwrap();
        ctx.set_tmp_dh(&dh).unwrap();
    }

    #[test]
    fn test_dh_from_der() {
        let params = include_bytes!("../test/dhparams.pem");
        let dh = Dh::from_pem(params).unwrap();
        let der = dh.to_der().unwrap();
        Dh::from_der(&der).unwrap();
        let dh = Dh::params_from_pem(params).unwrap();
        let der = dh.params_to_der().unwrap();
        Dh::params_from_der(&der).unwrap();
    }
}
+45 −46
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@ use std::ptr;
use {cvt, cvt_p};
use bn::BigNumRef;
use error::ErrorStack;
use pkey::{HasParams, HasPrivate, HasPublic, Private, Public};
use pkey::{HasParams, HasPublic, Private, Public};

generic_foreign_type_and_impl_send_sync! {
    type CType = ffi::DSA;
@@ -60,18 +60,29 @@ generic_foreign_type_and_impl_send_sync! {

impl<T> DsaRef<T>
where
    T: HasPrivate,
    T: HasPublic,
{
    private_key_to_pem!(ffi::PEM_write_bio_DSAPrivateKey);
    private_key_to_der!(ffi::i2d_DSAPrivateKey);
    to_pem! {
        /// Serialies the public key into a PEM-encoded SubjectPublicKeyInfo structure.
        ///
        /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
        ///
        /// This corresponds to [`PEM_write_bio_DSA_PUBKEY`].
        ///
        /// [`PEM_write_bio_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_DSA_PUBKEY.html
        public_key_to_pem,
        ffi::PEM_write_bio_DSA_PUBKEY
    }

impl<T> DsaRef<T>
where
    T: HasPublic,
{
    public_key_to_pem!(ffi::PEM_write_bio_DSA_PUBKEY);
    public_key_to_der!(ffi::i2d_DSAPublicKey);
    to_der! {
        /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
        ///
        /// This corresponds to [`i2d_DSA_PUBKEY`].
        ///
        /// [`i2d_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_DSA_PUBKEY.html
        public_key_to_der,
        ffi::i2d_DSA_PUBKEY
    }
}

impl<T> DsaRef<T>
@@ -139,14 +150,32 @@ impl Dsa<Private> {
            Ok(dsa)
        }
    }

    private_key_from_pem!(Dsa<Private>, ffi::PEM_read_bio_DSAPrivateKey);
    private_key_from_der!(Dsa<Private>, ffi::d2i_DSAPrivateKey);
}

impl Dsa<Public> {
    public_key_from_pem!(Dsa<Public>, ffi::PEM_read_bio_DSA_PUBKEY);
    public_key_from_der!(Dsa<Public>, ffi::d2i_DSAPublicKey);
    from_pem! {
        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing a DSA key.
        ///
        /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
        ///
        /// This corresponds to [`PEM_read_bio_DSA_PUBKEY`].
        ///
        /// [`PEM_read_bio_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_DSA_PUBKEY.html
        public_key_from_pem,
        Dsa<Public>,
        ffi::PEM_read_bio_DSA_PUBKEY
    }

    from_der! {
        /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing a DSA key.
        ///
        /// This corresponds to [`d2i_DSA_PUBKEY`].
        ///
        /// [`d2i_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_DSA_PUBKEY.html
        public_key_from_der,
        Dsa<Public>,
        ffi::d2i_DSA_PUBKEY
    }
}

impl<T> fmt::Debug for Dsa<T> {
@@ -178,40 +207,10 @@ mod compat {

#[cfg(test)]
mod test {
    use symm::Cipher;

    use super::*;

    #[test]
    pub fn test_generate() {
        Dsa::generate(1024).unwrap();
    }

    #[test]
    pub fn test_password() {
        let key = include_bytes!("../test/dsa-encrypted.pem");
        Dsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
    }

    #[test]
    fn test_to_password() {
        let key = Dsa::generate(2048).unwrap();
        let pem = key.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
            .unwrap();
        Dsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
        assert!(Dsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
    }

    #[test]
    pub fn test_password_callback() {
        let mut password_queried = false;
        let key = include_bytes!("../test/dsa-encrypted.pem");
        Dsa::private_key_from_pem_callback(key, |password| {
            password_queried = true;
            password[..6].copy_from_slice(b"mypass");
            Ok(6)
        }).unwrap();

        assert!(password_queried);
    }
}
+66 −4
Original line number Diff line number Diff line
@@ -522,8 +522,35 @@ impl<T> EcKeyRef<T>
where
    T: HasPrivate,
{
    private_key_to_pem!(ffi::PEM_write_bio_ECPrivateKey);
    private_key_to_der!(ffi::i2d_ECPrivateKey);
    private_key_to_pem! {
        /// Serializes the private key to a PEM-encoded ECPrivateKey structure.
        ///
        /// The output will have a header of `-----BEGIN EC PRIVATE KEY-----`.
        ///
        /// This corresponds to [`PEM_write_bio_ECPrivateKey`].
        ///
        /// [`PEM_write_bio_ECPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_ECPrivateKey.html
        private_key_to_pem,
        /// Serializes the private key to a PEM-encoded encrypted ECPrivateKey structure.
        ///
        /// The output will have a header of `-----BEGIN EC PRIVATE KEY-----`.
        ///
        /// This corresponds to [`PEM_write_bio_ECPrivateKey`].
        ///
        /// [`PEM_write_bio_ECPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_ECPrivateKey.html
        private_key_to_pem_passphrase,
        ffi::PEM_write_bio_ECPrivateKey
    }

    to_der! {
        /// Serializes the private key into a DER-encoded ECPrivateKey structure.
        ///
        /// This corresponds to [`i2d_ECPrivateKey`].
        ///
        /// [`i2d_ECPrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_ECPrivate_key.html
        private_key_to_der,
        ffi::i2d_ECPrivateKey
    }

    /// Return [`EcPoint`] associated with the private key
    ///
@@ -702,8 +729,43 @@ impl EcKey<Private> {
        }
    }

    private_key_from_pem!(EcKey<Private>, ffi::PEM_read_bio_ECPrivateKey);
    private_key_from_der!(EcKey<Private>, ffi::d2i_ECPrivateKey);
    private_key_from_pem! {
        /// Deserializes a private key from a PEM-encoded ECPrivateKey structure.
        ///
        /// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`.
        ///
        /// This corresponds to `PEM_read_bio_ECPrivateKey`.
        private_key_from_pem,

        /// Deserializes a private key from a PEM-encoded encrypted ECPrivateKey structure.
        ///
        /// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`.
        ///
        /// This corresponds to `PEM_read_bio_ECPrivateKey`.
        private_key_from_pem_passphrase,

        /// Deserializes a private key from a PEM-encoded encrypted ECPrivateKey structure.
        ///
        /// The callback should fill the password into the provided buffer and return its length.
        ///
        /// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`.
        ///
        /// This corresponds to `PEM_read_bio_ECPrivateKey`.
        private_key_from_pem_callback,
        EcKey<Private>,
        ffi::PEM_read_bio_ECPrivateKey
    }

    from_der! {
        /// Decodes a DER-encoded elliptic curve private key structure.
        ///
        /// This corresponds to [`d2i_ECPrivateKey`].
        ///
        /// [`d2i_ECPrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_ECPrivate_key.html
        private_key_from_der,
        EcKey<Private>,
        ffi::d2i_ECPrivateKey
    }
}

impl<T> Clone for EcKey<T> {
+27 −112
Original line number Diff line number Diff line

macro_rules! private_key_from_pem {
    ($t:ty, $f:path) => {
        from_pem_inner!(/// Deserializes a PEM-formatted private key.
            private_key_from_pem, $t, $f);
    ($(#[$m:meta])* $n:ident, $(#[$m2:meta])* $n2:ident, $(#[$m3:meta])* $n3:ident, $t:ty, $f:path) => {
        from_pem!($(#[$m])* $n, $t, $f);

        /// Deserializes a PEM-formatted private key, using the supplied password if the key is
        /// encrypted.
        ///
        /// # Panics
        ///
        /// Panics if `passphrase` contains an embedded null.
        pub fn private_key_from_pem_passphrase(pem: &[u8],
                                               passphrase: &[u8])
                                               -> Result<$t, ::error::ErrorStack> {
        $(#[$m2])*
        pub fn $n2(pem: &[u8], passphrase: &[u8]) -> Result<$t, ::error::ErrorStack> {
            unsafe {
                ffi::init();
                let bio = try!(::bio::MemBioSlice::new(pem));
@@ -25,14 +16,8 @@ macro_rules! private_key_from_pem {
            }
        }

        /// 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>
        $(#[$m3])*
        pub fn $n3<F>(pem: &[u8], callback: F) -> Result<$t, ::error::ErrorStack>
            where F: FnOnce(&mut [u8]) -> Result<usize, ::error::ErrorStack>
        {
            unsafe {
@@ -50,9 +35,9 @@ macro_rules! private_key_from_pem {
}

macro_rules! private_key_to_pem {
    ($f:path) => {
        /// Serializes the private key to PEM.
        pub fn private_key_to_pem(&self) -> Result<Vec<u8>, ::error::ErrorStack> {
    ($(#[$m:meta])* $n:ident, $(#[$m2:meta])* $n2:ident, $f:path) => {
        $(#[$m])*
        pub fn $n(&self) -> Result<Vec<u8>, ::error::ErrorStack> {
            unsafe {
                let bio = try!(::bio::MemBio::new());
                try!(cvt($f(bio.as_ptr(),
@@ -66,12 +51,12 @@ macro_rules! private_key_to_pem {
            }
        }

        /// Serializes the private key to PEM, encrypting it with the specified symmetric cipher and
        /// passphrase.
        pub fn private_key_to_pem_passphrase(&self,
        $(#[$m2])*
        pub fn $n2(
            &self,
            cipher: ::symm::Cipher,
                                             passphrase: &[u8])
                                             -> Result<Vec<u8>, ::error::ErrorStack> {
            passphrase: &[u8]
        ) -> Result<Vec<u8>, ::error::ErrorStack> {
            unsafe {
                let bio = try!(::bio::MemBio::new());
                assert!(passphrase.len() <= ::libc::c_int::max_value() as usize);
@@ -88,9 +73,9 @@ macro_rules! private_key_to_pem {
    }
}

macro_rules! to_pem_inner {
    (#[$m:meta] $n:ident, $f:path) => {
        #[$m]
macro_rules! to_pem {
    ($(#[$m:meta])* $n:ident, $f:path) => {
        $(#[$m])*
        pub fn $n(&self) -> Result<Vec<u8>, ::error::ErrorStack> {
            unsafe {
                let bio = try!(::bio::MemBio::new());
@@ -101,23 +86,9 @@ macro_rules! to_pem_inner {
    }
}

macro_rules! public_key_to_pem {
    ($f:path) => {
        to_pem_inner!(/// Serializes a public key to PEM.
            public_key_to_pem, $f);
    }
}

macro_rules! to_pem {
    ($f:path) => {
        to_pem_inner!(/// Serializes this value to PEM.
            to_pem, $f);
    }
}

macro_rules! to_der_inner {
    (#[$m:meta] $n:ident, $f:path) => {
        #[$m]
macro_rules! to_der {
    ($(#[$m:meta])* $n:ident, $f:path) => {
        $(#[$m])*
        pub fn $n(&self) -> Result<Vec<u8>, ::error::ErrorStack> {
            unsafe {
                let len = try!(::cvt($f(::foreign_types::ForeignTypeRef::as_ptr(self),
@@ -131,30 +102,9 @@ macro_rules! to_der_inner {
    };
}

macro_rules! to_der {
    ($f:path) => {
        to_der_inner!(/// Serializes this value to DER.
            to_der, $f);
    }
}

macro_rules! private_key_to_der {
    ($f:path) => {
        to_der_inner!(/// Serializes the private key to DER.
            private_key_to_der, $f);
    }
}

macro_rules! public_key_to_der {
    ($f:path) => {
        to_der_inner!(/// Serializes the public key to DER.
            public_key_to_der, $f);
    }
}

macro_rules! from_der_inner {
    (#[$m:meta] $n:ident, $t:ty, $f:path) => {
        #[$m]
macro_rules! from_der {
    ($(#[$m:meta])* $n:ident, $t:ty, $f:path) => {
        $(#[$m])*
        pub fn $n(der: &[u8]) -> Result<$t, ::error::ErrorStack> {
            unsafe {
                ::ffi::init();
@@ -166,30 +116,9 @@ macro_rules! from_der_inner {
    }
}

macro_rules! from_der {
    ($t:ty, $f:path) => {
        from_der_inner!(/// Deserializes a value from DER-formatted data.
            from_der, $t, $f);
    }
}

macro_rules! private_key_from_der {
    ($t:ty, $f:path) => {
        from_der_inner!(/// Deserializes a private key from DER-formatted data.
            private_key_from_der, $t, $f);
    }
}

macro_rules! public_key_from_der {
    ($t:ty, $f:path) => {
        from_der_inner!(/// Deserializes a public key from DER-formatted data.
            public_key_from_der, $t, $f);
    }
}

macro_rules! from_pem_inner {
    (#[$m:meta] $n:ident, $t:ty, $f:path) => {
        #[$m]
macro_rules! from_pem {
    ($(#[$m:meta])* $n:ident, $t:ty, $f:path) => {
        $(#[$m])*
        pub fn $n(pem: &[u8]) -> Result<$t, ::error::ErrorStack> {
            unsafe {
                ::init();
@@ -201,20 +130,6 @@ macro_rules! from_pem_inner {
    }
}

macro_rules! public_key_from_pem {
    ($t:ty, $f:path) => {
        from_pem_inner!(/// Deserializes a public key from PEM-formatted data.
            public_key_from_pem, $t, $f);
    }
}

macro_rules! from_pem {
    ($t:ty, $f:path) => {
        from_pem_inner!(/// Deserializes a value from PEM-formatted data.
            from_pem, $t, $f);
    }
}

macro_rules! foreign_type_and_impl_send_sync {
    (
        $(#[$impl_attr:meta])*
Loading