From a7fa260331f856e45a4bb9c4eff78ed17a1cb595 Mon Sep 17 00:00:00 2001 From: oberien Date: Sun, 1 Dec 2019 03:02:01 +0100 Subject: [PATCH 1/6] Support for PKCS#8 unencrypted private key deserialization --- openssl-sys/src/ossl_typ.rs | 2 ++ openssl-sys/src/pem.rs | 7 +++++++ openssl/src/pkey.rs | 25 +++++++++++++++++++++++++ openssl/test/pkcs8-nocrypt.der | Bin 0 -> 1216 bytes 4 files changed, 34 insertions(+) create mode 100644 openssl/test/pkcs8-nocrypt.der diff --git a/openssl-sys/src/ossl_typ.rs b/openssl-sys/src/ossl_typ.rs index adf72684..fa6eb1ba 100644 --- a/openssl-sys/src/ossl_typ.rs +++ b/openssl-sys/src/ossl_typ.rs @@ -123,6 +123,8 @@ cfg_if! { } } +pub enum PKCS8_PRIV_KEY_INFO {} + pub enum EVP_PKEY_ASN1_METHOD {} pub enum EVP_PKEY_CTX {} diff --git a/openssl-sys/src/pem.rs b/openssl-sys/src/pem.rs index 64703377..d6a76f05 100644 --- a/openssl-sys/src/pem.rs +++ b/openssl-sys/src/pem.rs @@ -137,6 +137,13 @@ extern "C" { cb: pem_password_cb, u: *mut c_void, ) -> *mut EVP_PKEY; + pub fn d2i_PKCS8_PRIV_KEY_INFO_bio( + bp: *mut BIO, + x: *mut *mut PKCS8_PRIV_KEY_INFO, + ) -> *mut PKCS8_PRIV_KEY_INFO; + pub fn EVP_PKCS82PKEY( + p8: *const PKCS8_PRIV_KEY_INFO, + ) -> *mut EVP_PKEY; pub fn PEM_read_bio_PKCS7( bio: *mut BIO, diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index f1ab1e2e..bcbfc385 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -524,6 +524,25 @@ impl PKey { 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, ErrorStack> + { + unsafe { + ffi::init(); + let bio = MemBioSlice::new(der)?; + let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO_bio( + bio.as_ptr(), + ptr::null_mut(), + ))?; + cvt_p(ffi::EVP_PKCS82PKEY(p8inf)) + .map(|p| PKey::from_ptr(p)) + } + } + /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password /// if the key is encrpyted. /// @@ -639,6 +658,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"); diff --git a/openssl/test/pkcs8-nocrypt.der b/openssl/test/pkcs8-nocrypt.der new file mode 100644 index 0000000000000000000000000000000000000000..04fbdc208af21bef611cba201f4352939e934d5f GIT binary patch literal 1216 zcmV;x1V8&Qf&{z*0RS)!1_>&LNQUrrZ9p8q5=T`0)hbn0JtfNIjnox z>EEI=Ze~SK13M49-d&$kBOt<3&9k9a0P|d7N?y+QwntJ~9B&0j9K}X56I#~`3NM1` zijm?B8cr@(UH_HUVDw8UKFe%}zZ`8voa9cbWO`B4X0zc;_5jB5^nlh$(JX$y;o2(q z%r;kpWn6ZxR=C43P$<%a6aTylIIYlH zhcB!{Yo7-WBc(6KT}xXyvxYeb6r3uxVF*<}4-Z5N*0e}X8f+$AR)gdZ?W4zYuw9lm zSh=iB-Z)+y6lK>35p3;F8hN;}epWBQA~<#Eeo1Cgwf}=orERjV>$m_Hn4n!7Ga^oHlPN2+)Wr>;42PUb?>=NZxT zjeQ+;^D^lSC6so=(5n9(`d+IpogQhjuA#=TKg4%ZDJKsLa?P%7#3uv|XGf%28;4EG zp;}ZrpH;4Krr$*(Y9$!2dkRNnV5OqRE#Z?q3Yt@UyvBy52{NbFmJ?|eJ73|F>V;%b zWxsBqMJ3XcJ3wO2l@A$id$Lr0*qOrPDs9Xgs;(eHR?(_TGi**ozq0w%v3UZ4fdKFE zveNS_lp3vd%z!GG%VE%FAzev9(3r;{A5xXenPm5xG2r@HAl{;ySHN%BD<%DI@()eL z^tlPheDzjClo_OydkeitoRkL);!+EoaPZ zJ+@;XDQT4sA^nFGyponqwQrPEs?P#}fdIsONX~`2n}Z|Z(C&M?C3rht`CT{`s8~O> zuUoHbN)KdM4}5MGc9E!iC~D|pf#OXB5sJo(N(ze>e}LryvX~}JjUD*-}fV3oPy_GH~yRDej;@2z*qw38D?fIoHY5+%*D$ zfNQ)6VDnN_(~hFw$%IzQs|J~L&7c798cF^@QX+IBQPpDPmT{5iQcsK_ZiGpBMmv7L zEaU9RF7+3Z6V5@^lbty!j0B{>y!09tj(I{jI3{SVt5);2^^l3EH(Azz%O^ix9`{ z0)c=KT!UxWihsu=KAC|eAa=48mnzoE1hwL6PR+@+7KI_sl8v6FPRO{OT18S!El|Q8 zC5FznQMucjl~-%Zev#MtzV7D{ycin(H79?PT%WmuOozLSGRkfm5L<2yT;?3~(q^k< e{i>d=u^m@tp6-Ai2kOFUIU(JPR;qtZnHmW{L`6ve literal 0 HcmV?d00001 From 4218e121d09b48e65a81ad160227280d3ddf1c05 Mon Sep 17 00:00:00 2001 From: oberien Date: Sun, 1 Dec 2019 03:15:52 +0100 Subject: [PATCH 2/6] move EVP_PKCS82PKEY into evp module --- openssl-sys/src/evp.rs | 1 + openssl-sys/src/pem.rs | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/openssl-sys/src/evp.rs b/openssl-sys/src/evp.rs index 9b41d6de..41ef6c30 100644 --- a/openssl-sys/src/evp.rs +++ b/openssl-sys/src/evp.rs @@ -403,6 +403,7 @@ extern "C" { pub fn EVP_PKEY_keygen_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_keygen(ctx: *mut EVP_PKEY_CTX, key: *mut *mut EVP_PKEY) -> c_int; + pub fn EVP_PKCS82PKEY(p8: *const PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY; } extern "C" { diff --git a/openssl-sys/src/pem.rs b/openssl-sys/src/pem.rs index d6a76f05..7dc37b59 100644 --- a/openssl-sys/src/pem.rs +++ b/openssl-sys/src/pem.rs @@ -141,9 +141,6 @@ extern "C" { bp: *mut BIO, x: *mut *mut PKCS8_PRIV_KEY_INFO, ) -> *mut PKCS8_PRIV_KEY_INFO; - pub fn EVP_PKCS82PKEY( - p8: *const PKCS8_PRIV_KEY_INFO, - ) -> *mut EVP_PKEY; pub fn PEM_read_bio_PKCS7( bio: *mut BIO, From a042edd134996490cc31d30fd0a4f651f86ff6d1 Mon Sep 17 00:00:00 2001 From: oberien Date: Sun, 1 Dec 2019 03:29:57 +0100 Subject: [PATCH 3/6] Change *const to *mut to try if it fixes tests --- openssl-sys/src/evp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl-sys/src/evp.rs b/openssl-sys/src/evp.rs index 41ef6c30..62a6eee8 100644 --- a/openssl-sys/src/evp.rs +++ b/openssl-sys/src/evp.rs @@ -403,7 +403,7 @@ extern "C" { pub fn EVP_PKEY_keygen_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_keygen(ctx: *mut EVP_PKEY_CTX, key: *mut *mut EVP_PKEY) -> c_int; - pub fn EVP_PKCS82PKEY(p8: *const PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY; + pub fn EVP_PKCS82PKEY(p8: *mut PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY; } extern "C" { From 4b2d46c2528c8820213d7e92dcfa3074f634d11d Mon Sep 17 00:00:00 2001 From: oberien Date: Sun, 1 Dec 2019 03:37:39 +0100 Subject: [PATCH 4/6] Fix pointer constness correctly --- openssl-sys/src/evp.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/openssl-sys/src/evp.rs b/openssl-sys/src/evp.rs index 62a6eee8..a0b3fea9 100644 --- a/openssl-sys/src/evp.rs +++ b/openssl-sys/src/evp.rs @@ -403,7 +403,18 @@ extern "C" { pub fn EVP_PKEY_keygen_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_keygen(ctx: *mut EVP_PKEY_CTX, key: *mut *mut EVP_PKEY) -> c_int; - pub fn EVP_PKCS82PKEY(p8: *mut PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY; +} + +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" { From fc529b6c8148e45ec6a6d20ad4b33429e92e0bc2 Mon Sep 17 00:00:00 2001 From: oberien Date: Tue, 3 Dec 2019 03:05:05 +0100 Subject: [PATCH 5/6] Pkey::private_key_from_pkcs8 free p8inf --- openssl-sys/src/pem.rs | 3 +++ openssl/src/pkey.rs | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/openssl-sys/src/pem.rs b/openssl-sys/src/pem.rs index 7dc37b59..c7d79773 100644 --- a/openssl-sys/src/pem.rs +++ b/openssl-sys/src/pem.rs @@ -141,6 +141,9 @@ extern "C" { bp: *mut BIO, x: *mut *mut PKCS8_PRIV_KEY_INFO, ) -> *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, diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index bcbfc385..b5a12bf7 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -538,8 +538,10 @@ impl PKey { bio.as_ptr(), ptr::null_mut(), ))?; - cvt_p(ffi::EVP_PKCS82PKEY(p8inf)) - .map(|p| PKey::from_ptr(p)) + let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)) + .map(|p| PKey::from_ptr(p)); + ffi::PKCS8_PRIV_KEY_INFO_free(p8inf); + res } } From 9f4c4895883f2dbc86a3955cdefd68674fd25834 Mon Sep 17 00:00:00 2001 From: oberien Date: Wed, 4 Dec 2019 02:02:33 +0100 Subject: [PATCH 6/6] Use d2i_PKCS8_PRIV_KEY_INFO instead of *_bio --- openssl-sys/src/pem.rs | 7 ++++--- openssl/src/pkey.rs | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/openssl-sys/src/pem.rs b/openssl-sys/src/pem.rs index c7d79773..474cefd2 100644 --- a/openssl-sys/src/pem.rs +++ b/openssl-sys/src/pem.rs @@ -137,9 +137,10 @@ extern "C" { cb: pem_password_cb, u: *mut c_void, ) -> *mut EVP_PKEY; - pub fn d2i_PKCS8_PRIV_KEY_INFO_bio( - bp: *mut BIO, - x: *mut *mut PKCS8_PRIV_KEY_INFO, + 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, diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index b5a12bf7..98eb6355 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -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; @@ -533,10 +533,11 @@ impl PKey { { unsafe { ffi::init(); - let bio = MemBioSlice::new(der)?; - let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO_bio( - bio.as_ptr(), + 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));