From 57d10ebbc3c04d5089b034b9d88f40c302783c96 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 29 Oct 2016 14:19:09 -0700 Subject: [PATCH] Add PKeyRef --- openssl/src/pkey.rs | 111 +++++++++++++++++++++-------------- openssl/src/ssl/connector.rs | 6 +- openssl/src/ssl/mod.rs | 4 +- 3 files changed, 71 insertions(+), 50 deletions(-) diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index e62bbbd9..4cbfcce7 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -1,6 +1,7 @@ use libc::{c_void, c_char, c_int}; use std::ptr; use std::mem; +use std::ops::Deref; use ffi; use {cvt, cvt_p}; @@ -9,13 +10,66 @@ use dsa::Dsa; use rsa::Rsa; use error::ErrorStack; use util::{CallbackState, invoke_passwd_cb}; +use opaque::Opaque; +/// A borrowed `PKey`. +pub struct PKeyRef(Opaque); + +impl PKeyRef { + pub unsafe fn from_ptr<'a>(ptr: *mut ffi::EVP_PKEY) -> &'a PKeyRef { + &*(ptr as *mut _) + } + + pub fn as_ptr(&self) -> *mut ffi::EVP_PKEY { + self as *const _ as *mut _ + } + + /// Get a reference to the interal RSA key for direct access to the key components + pub fn rsa(&self) -> Result { + unsafe { + let rsa = try!(cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))); + // this is safe as the ffi increments a reference counter to the internal key + Ok(Rsa::from_ptr(rsa)) + } + } + + /// Stores private key as a PEM + // FIXME: also add password and encryption + pub fn private_key_to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + unsafe { + try!(cvt(ffi::PEM_write_bio_PrivateKey(mem_bio.as_ptr(), + self.as_ptr(), + ptr::null(), + ptr::null_mut(), + -1, + None, + ptr::null_mut()))); + + } + Ok(mem_bio.get_buf().to_owned()) + } + + /// Stores public key as a PEM + pub fn public_key_to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + unsafe { + try!(cvt(ffi::PEM_write_bio_PUBKEY(mem_bio.as_ptr(), self.as_ptr()))); + } + Ok(mem_bio.get_buf().to_owned()) + } + + pub fn public_eq(&self, other: &PKeyRef) -> bool { + unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 } + } +} + +/// Represents a public key, optionally with a private key attached. pub struct PKey(*mut ffi::EVP_PKEY); unsafe impl Send for PKey {} unsafe impl Sync for PKey {} -/// Represents a public key, optionally with a private key attached. impl PKey { /// Create a new `PKey` containing an RSA key. pub fn from_rsa(rsa: Rsa) -> Result { @@ -101,7 +155,7 @@ impl PKey { } } - /// assign RSA key to this pkey + /// Assign an RSA key to this pkey. pub fn set_rsa(&mut self, rsa: &Rsa) -> Result<(), ErrorStack> { unsafe { // this needs to be a reference as the set1_RSA ups the reference count @@ -110,49 +164,6 @@ impl PKey { Ok(()) } } - - /// Get a reference to the interal RSA key for direct access to the key components - pub fn rsa(&self) -> Result { - unsafe { - let rsa = try!(cvt_p(ffi::EVP_PKEY_get1_RSA(self.0))); - // this is safe as the ffi increments a reference counter to the internal key - Ok(Rsa::from_ptr(rsa)) - } - } - - /// Stores private key as a PEM - // FIXME: also add password and encryption - pub fn private_key_to_pem(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - unsafe { - try!(cvt(ffi::PEM_write_bio_PrivateKey(mem_bio.as_ptr(), - self.0, - ptr::null(), - ptr::null_mut(), - -1, - None, - ptr::null_mut()))); - - } - Ok(mem_bio.get_buf().to_owned()) - } - - /// Stores public key as a PEM - pub fn public_key_to_pem(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - unsafe { - try!(cvt(ffi::PEM_write_bio_PUBKEY(mem_bio.as_ptr(), self.0))); - } - Ok(mem_bio.get_buf().to_owned()) - } - - pub fn as_ptr(&self) -> *mut ffi::EVP_PKEY { - return self.0; - } - - pub fn public_eq(&self, other: &PKey) -> bool { - unsafe { ffi::EVP_PKEY_cmp(self.0, other.0) == 1 } - } } impl Drop for PKey { @@ -163,6 +174,16 @@ impl Drop for PKey { } } +impl Deref for PKey { + type Target = PKeyRef; + + fn deref(&self) -> &PKeyRef { + unsafe { + PKeyRef::from_ptr(self.0) + } + } +} + #[cfg(test)] mod tests { #[test] diff --git a/openssl/src/ssl/connector.rs b/openssl/src/ssl/connector.rs index aed01f8c..62f0a284 100644 --- a/openssl/src/ssl/connector.rs +++ b/openssl/src/ssl/connector.rs @@ -4,7 +4,7 @@ use dh::Dh; use error::ErrorStack; use ssl::{self, SslMethod, SslContextBuilder, SslContext, Ssl, SSL_VERIFY_PEER, SslStream, HandshakeError}; -use pkey::PKey; +use pkey::PKeyRef; use x509::X509Ref; // apps/dh2048.pem @@ -85,7 +85,7 @@ impl ClientConnector { pub struct ServerConnectorBuilder(SslContextBuilder); impl ServerConnectorBuilder { - pub fn tls(private_key: &PKey, + pub fn tls(private_key: &PKeyRef, certificate: &X509Ref, chain: I) -> Result @@ -96,7 +96,7 @@ impl ServerConnectorBuilder { } fn new(method: SslMethod, - private_key: &PKey, + private_key: &PKeyRef, certificate: &X509Ref, chain: I) -> Result diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 19b21d9d..9e39d8bf 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -24,7 +24,7 @@ use dh::Dh; use x509::{X509StoreContextRef, X509FileType, X509, X509Ref, X509VerifyError}; #[cfg(any(ossl102, ossl110))] use verify::X509VerifyParamRef; -use pkey::PKey; +use pkey::PKeyRef; use error::ErrorStack; use opaque::Opaque; @@ -532,7 +532,7 @@ impl SslContextBuilder { } /// Specifies the private key - pub fn set_private_key(&mut self, key: &PKey) -> Result<(), ErrorStack> { + pub fn set_private_key(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> { unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }