Add PKeyRef

This commit is contained in:
Steven Fackler 2016-10-29 14:19:09 -07:00
parent 4c7a5a418e
commit 57d10ebbc3
3 changed files with 71 additions and 50 deletions

View File

@ -1,6 +1,7 @@
use libc::{c_void, c_char, c_int}; use libc::{c_void, c_char, c_int};
use std::ptr; use std::ptr;
use std::mem; use std::mem;
use std::ops::Deref;
use ffi; use ffi;
use {cvt, cvt_p}; use {cvt, cvt_p};
@ -9,13 +10,66 @@ use dsa::Dsa;
use rsa::Rsa; use rsa::Rsa;
use error::ErrorStack; use error::ErrorStack;
use util::{CallbackState, invoke_passwd_cb}; 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<Rsa, ErrorStack> {
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<Vec<u8>, 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<Vec<u8>, 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); pub struct PKey(*mut ffi::EVP_PKEY);
unsafe impl Send for PKey {} unsafe impl Send for PKey {}
unsafe impl Sync for PKey {} unsafe impl Sync for PKey {}
/// Represents a public key, optionally with a private key attached.
impl PKey { impl PKey {
/// Create a new `PKey` containing an RSA key. /// Create a new `PKey` containing an RSA key.
pub fn from_rsa(rsa: Rsa) -> Result<PKey, ErrorStack> { pub fn from_rsa(rsa: Rsa) -> Result<PKey, ErrorStack> {
@ -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> { pub fn set_rsa(&mut self, rsa: &Rsa) -> Result<(), ErrorStack> {
unsafe { unsafe {
// this needs to be a reference as the set1_RSA ups the reference count // this needs to be a reference as the set1_RSA ups the reference count
@ -110,49 +164,6 @@ impl PKey {
Ok(()) Ok(())
} }
} }
/// Get a reference to the interal RSA key for direct access to the key components
pub fn rsa(&self) -> Result<Rsa, ErrorStack> {
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<Vec<u8>, 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<Vec<u8>, 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 { 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)] #[cfg(test)]
mod tests { mod tests {
#[test] #[test]

View File

@ -4,7 +4,7 @@ use dh::Dh;
use error::ErrorStack; use error::ErrorStack;
use ssl::{self, SslMethod, SslContextBuilder, SslContext, Ssl, SSL_VERIFY_PEER, SslStream, use ssl::{self, SslMethod, SslContextBuilder, SslContext, Ssl, SSL_VERIFY_PEER, SslStream,
HandshakeError}; HandshakeError};
use pkey::PKey; use pkey::PKeyRef;
use x509::X509Ref; use x509::X509Ref;
// apps/dh2048.pem // apps/dh2048.pem
@ -85,7 +85,7 @@ impl ClientConnector {
pub struct ServerConnectorBuilder(SslContextBuilder); pub struct ServerConnectorBuilder(SslContextBuilder);
impl ServerConnectorBuilder { impl ServerConnectorBuilder {
pub fn tls<I, T>(private_key: &PKey, pub fn tls<I, T>(private_key: &PKeyRef,
certificate: &X509Ref, certificate: &X509Ref,
chain: I) chain: I)
-> Result<ServerConnectorBuilder, ErrorStack> -> Result<ServerConnectorBuilder, ErrorStack>
@ -96,7 +96,7 @@ impl ServerConnectorBuilder {
} }
fn new<I, T>(method: SslMethod, fn new<I, T>(method: SslMethod,
private_key: &PKey, private_key: &PKeyRef,
certificate: &X509Ref, certificate: &X509Ref,
chain: I) chain: I)
-> Result<ServerConnectorBuilder, ErrorStack> -> Result<ServerConnectorBuilder, ErrorStack>

View File

@ -24,7 +24,7 @@ use dh::Dh;
use x509::{X509StoreContextRef, X509FileType, X509, X509Ref, X509VerifyError}; use x509::{X509StoreContextRef, X509FileType, X509, X509Ref, X509VerifyError};
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, ossl110))]
use verify::X509VerifyParamRef; use verify::X509VerifyParamRef;
use pkey::PKey; use pkey::PKeyRef;
use error::ErrorStack; use error::ErrorStack;
use opaque::Opaque; use opaque::Opaque;
@ -532,7 +532,7 @@ impl SslContextBuilder {
} }
/// Specifies the private key /// 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 { unsafe {
cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ())
} }