From 15490a43e399ce0f6e3838c96c609abf08b1c5db Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 11 Nov 2016 19:17:26 +0000 Subject: [PATCH] Add EcKey <-> PKey conversions Closes #499 --- openssl-sys/src/lib.rs | 2 ++ openssl/src/ec_key.rs | 7 +++++-- openssl/src/pkey.rs | 32 +++++++++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 16ba529e..bdfe9b8c 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -114,6 +114,7 @@ pub const EVP_PKEY_RSA: c_int = NID_rsaEncryption; pub const EVP_PKEY_HMAC: c_int = NID_hmac; pub const EVP_PKEY_DSA: c_int = NID_dsa; pub const EVP_PKEY_DH: c_int = NID_dhKeyAgreement; +pub const EVP_PKEY_EC: c_int = NID_X9_62_id_ecPublicKey; pub const EVP_CTRL_GCM_SET_IVLEN: c_int = 0x9; pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10; @@ -1458,6 +1459,7 @@ extern { pub fn EVP_PKEY_set1_RSA(k: *mut EVP_PKEY, r: *mut RSA) -> c_int; pub fn EVP_PKEY_get1_DSA(k: *mut EVP_PKEY) -> *mut DSA; pub fn EVP_PKEY_get1_DH(k: *mut EVP_PKEY) -> *mut DH; + pub fn EVP_PKEY_get1_EC_KEY(k: *mut EVP_PKEY) -> *mut EC_KEY; pub fn EVP_PKEY_cmp(a: *const EVP_PKEY, b: *const EVP_PKEY) -> c_int; pub fn EVP_PKEY_new_mac_key(type_: c_int, e: *mut ENGINE, diff --git a/openssl/src/ec_key.rs b/openssl/src/ec_key.rs index 41501c14..ad85dc5e 100644 --- a/openssl/src/ec_key.rs +++ b/openssl/src/ec_key.rs @@ -1,6 +1,6 @@ use ffi; -use cvt_p; +use {cvt_p, init}; use error::ErrorStack; use nid::Nid; @@ -8,7 +8,10 @@ type_!(EcKey, EcKeyRef, ffi::EC_KEY, ffi::EC_KEY_free); impl EcKey { pub fn new_by_curve_name(nid: Nid) -> Result { - unsafe { cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(EcKey) } + unsafe { + init(); + cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(EcKey) + } } } diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index 72e73017..f424e337 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -7,6 +7,7 @@ use {cvt, cvt_p}; use bio::{MemBio, MemBioSlice}; use dh::Dh; use dsa::Dsa; +use ec_key::EcKey; use rsa::Rsa; use error::ErrorStack; use util::{CallbackState, invoke_passwd_cb}; @@ -39,6 +40,14 @@ impl PKeyRef { } } + /// Returns a copy of the internal elliptic curve key. + pub fn ec_key(&self) -> Result { + unsafe { + let ec_key = try!(cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))); + Ok(EcKey::from_ptr(ec_key)) + } + } + /// Stores private key as a PEM // FIXME: also add password and encryption pub fn private_key_to_pem(&self) -> Result, ErrorStack> { @@ -105,7 +114,7 @@ impl PKey { } } - /// Creates a new `PKey` containing a DH key. + /// Creates a new `PKey` containing a Diffie-Hellman key. pub fn from_dh(dh: Dh) -> Result { unsafe { let evp = try!(cvt_p(ffi::EVP_PKEY_new())); @@ -116,6 +125,17 @@ impl PKey { } } + /// Creates a new `PKey` containing an elliptic curve key. + pub fn from_ec_key(ec_key: EcKey) -> Result { + unsafe { + let evp = try!(cvt_p(ffi::EVP_PKEY_new())); + let pkey = PKey(evp); + try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_EC, ec_key.as_ptr() as *mut _))); + mem::forget(ec_key); + Ok(pkey) + } + } + /// Creates a new `PKey` containing an HMAC key. pub fn hmac(key: &[u8]) -> Result { unsafe { @@ -179,7 +199,9 @@ impl PKey { mod tests { use dh::Dh; use dsa::Dsa; + use ec_key::EcKey; use rsa::Rsa; + use nid; use super::*; @@ -233,4 +255,12 @@ mod tests { pkey.dh().unwrap(); assert!(pkey.rsa().is_err()); } + + #[test] + fn test_ec_key_accessor() { + let ec_key = EcKey::new_by_curve_name(nid::X9_62_PRIME256V1).unwrap(); + let pkey = PKey::from_ec_key(ec_key).unwrap(); + pkey.ec_key().unwrap(); + assert!(pkey.rsa().is_err()); + } }