Commit 57d10ebb authored by Steven Fackler's avatar Steven Fackler
Browse files

Add PKeyRef

parent 4c7a5a41
Loading
Loading
Loading
Loading
+65 −44
Original line number Diff line number Diff line
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<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);

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<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> {
        unsafe {
            // this needs to be a reference as the set1_RSA ups the reference count
@@ -110,55 +164,22 @@ impl PKey {
            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());
impl Drop for PKey {
    fn drop(&mut self) {
        unsafe {
            try!(cvt(ffi::PEM_write_bio_PUBKEY(mem_bio.as_ptr(), self.0)));
            ffi::EVP_PKEY_free(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 Deref for PKey {
    type Target = PKeyRef;

impl Drop for PKey {
    fn drop(&mut self) {
    fn deref(&self) -> &PKeyRef {
        unsafe {
            ffi::EVP_PKEY_free(self.0);
            PKeyRef::from_ptr(self.0)
        }
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -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<I, T>(private_key: &PKey,
    pub fn tls<I, T>(private_key: &PKeyRef,
                     certificate: &X509Ref,
                     chain: I)
                     -> Result<ServerConnectorBuilder, ErrorStack>
@@ -96,7 +96,7 @@ impl ServerConnectorBuilder {
    }

    fn new<I, T>(method: SslMethod,
                 private_key: &PKey,
                 private_key: &PKeyRef,
                 certificate: &X509Ref,
                 chain: I)
                 -> Result<ServerConnectorBuilder, ErrorStack>
+2 −2
Original line number Diff line number Diff line
@@ -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(|_| ())
        }