Unverified Commit 9ccddf7a authored by Steven Fackler's avatar Steven Fackler Committed by GitHub
Browse files

Merge pull request #1196 from oberien/private-key-from-pkcs8

Support for PKCS#8 unencrypted private key deserialization
parents 454cb6f9 9f4c4895
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -405,6 +405,18 @@ extern "C" {
    pub fn EVP_PKEY_keygen(ctx: *mut EVP_PKEY_CTX, key: *mut *mut EVP_PKEY) -> c_int;
}

cfg_if! {
    if #[cfg(any(ossl110, libressl280))] {
        extern "C" {
            pub fn EVP_PKCS82PKEY(p8: *const PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY;
        }
    } else {
        extern "C" {
            pub fn EVP_PKCS82PKEY(p8: *mut PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY;
        }
    }
}

extern "C" {
    pub fn EVP_EncodeBlock(dst: *mut c_uchar, src: *const c_uchar, src_len: c_int) -> c_int;
    pub fn EVP_DecodeBlock(dst: *mut c_uchar, src: *const c_uchar, src_len: c_int) -> c_int;
+2 −0
Original line number Diff line number Diff line
@@ -123,6 +123,8 @@ cfg_if! {
    }
}

pub enum PKCS8_PRIV_KEY_INFO {}

pub enum EVP_PKEY_ASN1_METHOD {}

pub enum EVP_PKEY_CTX {}
+8 −0
Original line number Diff line number Diff line
@@ -137,6 +137,14 @@ extern "C" {
        cb: pem_password_cb,
        u: *mut c_void,
    ) -> *mut EVP_PKEY;
    pub fn d2i_PKCS8_PRIV_KEY_INFO(
        k: *mut *mut PKCS8_PRIV_KEY_INFO,
        buf: *mut *const u8,
        length: c_long,
    ) -> *mut PKCS8_PRIV_KEY_INFO;
    pub fn PKCS8_PRIV_KEY_INFO_free(
        p8inf: *mut PKCS8_PRIV_KEY_INFO,
    );

    pub fn PEM_read_bio_PKCS7(
        bio: *mut BIO,
+29 −1
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@

use ffi;
use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int;
use libc::{c_int, c_long};
use std::ffi::CString;
use std::mem;
use std::ptr;
@@ -524,6 +524,28 @@ impl PKey<Private> {
        ffi::d2i_AutoPrivateKey
    }

    /// Deserializes a DER-formatted PKCS#8 unencrypted private key.
    ///
    /// This method is mainly for interoperability reasons. Encrypted keyfiles should be preferred.
    pub fn private_key_from_pkcs8(
        der: &[u8],
    ) -> Result<PKey<Private>, ErrorStack>
    {
        unsafe {
            ffi::init();
            let len = der.len().min(c_long::max_value() as usize) as c_long;
            let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO(
                ptr::null_mut(),
                &mut der.as_ptr(),
                len,
            ))?;
            let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf))
                .map(|p| PKey::from_ptr(p));
            ffi::PKCS8_PRIV_KEY_INFO_free(p8inf);
            res
        }
    }

    /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password
    /// if the key is encrpyted.
    ///
@@ -639,6 +661,12 @@ mod tests {
        assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
    }

    #[test]
    fn test_unencrypted_pkcs8() {
        let key = include_bytes!("../test/pkcs8-nocrypt.der");
        PKey::private_key_from_pkcs8(key).unwrap();
    }

    #[test]
    fn test_encrypted_pkcs8_passphrase() {
        let key = include_bytes!("../test/pkcs8.der");
+1.19 KiB

File added.

No diff preview for this file type.