Commit eea4e31a authored by Steven Fackler's avatar Steven Fackler Committed by GitHub
Browse files

Merge pull request #505 from sfackler/more-refs

More refs
parents f75f82e4 287f6df6
Loading
Loading
Loading
Loading
+93 −103
Original line number Diff line number Diff line
use error::ErrorStack;
use ffi;
use libc::{c_int, c_char, c_void};
use std::fmt;
use error::ErrorStack;
use std::ops::Deref;
use std::ptr;
use libc::{c_int, c_char, c_void};

use {cvt, cvt_p};
use bn::BigNumRef;
use bio::{MemBio, MemBioSlice};
use util::{CallbackState, invoke_passwd_cb};
use opaque::Opaque;

pub struct DsaRef(Opaque);

impl DsaRef {
    pub unsafe fn from_ptr<'a>(ptr: *mut ffi::DSA) -> &'a DsaRef {
        &*(ptr as *mut _)
    }

    pub fn as_ptr(&self) -> *mut ffi::DSA {
        self as *const _ as *mut _
    }

/// Builder for upfront DSA parameter generation
pub struct DsaParams(*mut ffi::DSA);
    /// Writes an DSA private key as unencrypted PEM formatted data
    pub fn private_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
        assert!(self.has_private_key());
        let mem_bio = try!(MemBio::new());

impl DsaParams {
    pub fn with_size(size: u32) -> Result<DsaParams, ErrorStack> {
        unsafe {
            let dsa = DsaParams(try!(cvt_p(ffi::DSA_new())));
            try!(cvt(ffi::DSA_generate_parameters_ex(dsa.0,
                                                     size as c_int,
                                                     ptr::null(),
                                                     0,
                                                     ptr::null_mut(),
                                                     ptr::null_mut(),
                                                     ptr::null_mut())));
            Ok(dsa)
            try!(cvt(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.as_ptr(), self.as_ptr(),
                                                      ptr::null(), ptr::null_mut(), 0,
                                                      None, ptr::null_mut())))
        };

        Ok(mem_bio.get_buf().to_owned())
    }

    /// Writes an DSA public key as PEM formatted data
    pub fn public_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
        let mem_bio = try!(MemBio::new());
        unsafe {
            try!(cvt(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.as_ptr(), self.as_ptr())));
        }
        Ok(mem_bio.get_buf().to_owned())
    }

    /// Generate a key pair from the initialized parameters
    pub fn generate(self) -> Result<Dsa, ErrorStack> {
    pub fn size(&self) -> Option<u32> {
        if self.q().is_some() {
            unsafe { Some(ffi::DSA_size(self.as_ptr()) as u32) }
        } else {
            None
        }
    }

    pub fn p(&self) -> Option<&BigNumRef> {
        unsafe {
            try!(cvt(ffi::DSA_generate_key(self.0)));
            let dsa = Dsa(self.0);
            ::std::mem::forget(self);
            Ok(dsa)
            let p = compat::pqg(self.as_ptr())[0];
            if p.is_null() {
                None
            } else {
                Some(BigNumRef::from_ptr(p as *mut _))
            }
        }
    }

impl Drop for DsaParams {
    fn drop(&mut self) {
    pub fn q(&self) -> Option<&BigNumRef> {
        unsafe {
            ffi::DSA_free(self.0);
            let q = compat::pqg(self.as_ptr())[1];
            if q.is_null() {
                None
            } else {
                Some(BigNumRef::from_ptr(q as *mut _))
            }
        }
    }

    pub fn g(&self) -> Option<&BigNumRef> {
        unsafe {
            let g = compat::pqg(self.as_ptr())[2];
            if g.is_null() {
                None
            } else {
                Some(BigNumRef::from_ptr(g as *mut _))
            }
        }
    }

    pub fn has_public_key(&self) -> bool {
        unsafe { !compat::keys(self.as_ptr())[0].is_null() }
    }

    pub fn has_private_key(&self) -> bool {
        unsafe { !compat::keys(self.as_ptr())[1].is_null() }
    }
}

pub struct Dsa(*mut ffi::DSA);

impl Drop for Dsa {
@@ -61,11 +110,20 @@ impl Dsa {
        Dsa(dsa)
    }

    /// Generate a DSA key pair
    /// For more complicated key generation scenarios see the `DSAParams` type
    pub fn generate(size: u32) -> Result<Dsa, ErrorStack> {
        let params = try!(DsaParams::with_size(size));
        params.generate()
    /// Generate a DSA key pair.
    pub fn generate(bits: u32) -> Result<Dsa, ErrorStack> {
        unsafe {
            let dsa = Dsa(try!(cvt_p(ffi::DSA_new())));
            try!(cvt(ffi::DSA_generate_parameters_ex(dsa.0,
                                                     bits as c_int,
                                                     ptr::null(),
                                                     0,
                                                     ptr::null_mut(),
                                                     ptr::null_mut(),
                                                     ptr::null_mut())));
            try!(cvt(ffi::DSA_generate_key(dsa .0)));
            Ok(dsa)
        }
    }

    /// Reads a DSA private key from PEM formatted data.
@@ -104,20 +162,6 @@ impl Dsa {
        }
    }

    /// Writes an DSA private key as unencrypted PEM formatted data
    pub fn private_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
        assert!(self.has_private_key());
        let mem_bio = try!(MemBio::new());

        unsafe {
            try!(cvt(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.as_ptr(), self.0,
                                                      ptr::null(), ptr::null_mut(), 0,
                                                      None, ptr::null_mut())))
        };

        Ok(mem_bio.get_buf().to_owned())
    }

    /// Reads an DSA public key from PEM formatted data.
    pub fn public_key_from_pem(buf: &[u8]) -> Result<Dsa, ErrorStack> {
        ffi::init();
@@ -131,67 +175,13 @@ impl Dsa {
            Ok(Dsa(dsa))
        }
    }

    /// Writes an DSA public key as PEM formatted data
    pub fn public_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
        let mem_bio = try!(MemBio::new());
        unsafe {
            try!(cvt(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.as_ptr(), self.0)));
        }
        Ok(mem_bio.get_buf().to_owned())
}

    pub fn size(&self) -> Option<u32> {
        if self.q().is_some() {
            unsafe { Some(ffi::DSA_size(self.0) as u32) }
        } else {
            None
        }
    }
impl Deref for Dsa {
    type Target = DsaRef;

    pub fn as_ptr(&self) -> *mut ffi::DSA {
        self.0
    }

    pub fn p(&self) -> Option<&BigNumRef> {
        unsafe {
            let p = compat::pqg(self.0)[0];
            if p.is_null() {
                None
            } else {
                Some(BigNumRef::from_ptr(p as *mut _))
            }
        }
    }

    pub fn q(&self) -> Option<&BigNumRef> {
        unsafe {
            let q = compat::pqg(self.0)[1];
            if q.is_null() {
                None
            } else {
                Some(BigNumRef::from_ptr(q as *mut _))
            }
        }
    }

    pub fn g(&self) -> Option<&BigNumRef> {
        unsafe {
            let g = compat::pqg(self.0)[2];
            if g.is_null() {
                None
            } else {
                Some(BigNumRef::from_ptr(g as *mut _))
            }
        }
    }

    pub fn has_public_key(&self) -> bool {
        unsafe { !compat::keys(self.0)[0].is_null() }
    }

    pub fn has_private_key(&self) -> bool {
        unsafe { !compat::keys(self.0)[1].is_null() }
    fn deref(&self) -> &DsaRef {
        unsafe { DsaRef::from_ptr(self.0) }
    }
}

+2 −2
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@ use ffi;
use {cvt, cvt_p};
use bio::{MemBio, MemBioSlice};
use dsa::Dsa;
use rsa::Rsa;
use rsa::{Rsa, RsaRef};
use error::ErrorStack;
use util::{CallbackState, invoke_passwd_cb};
use opaque::Opaque;
@@ -156,7 +156,7 @@ impl 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: &RsaRef) -> Result<(), ErrorStack> {
        unsafe {
            // this needs to be a reference as the set1_RSA ups the reference count
            let rsa_ptr = rsa.as_ptr();
+134 −116
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ use ffi;
use std::fmt;
use std::ptr;
use std::mem;
use std::ops::Deref;
use libc::{c_int, c_void, c_char};

use {cvt, cvt_p, cvt_n};
@@ -9,6 +10,7 @@ use bn::{BigNum, BigNumRef};
use bio::{MemBio, MemBioSlice};
use error::ErrorStack;
use util::{CallbackState, invoke_passwd_cb};
use opaque::Opaque;

/// Type of encryption padding to use.
#[derive(Copy, Clone)]
@@ -18,108 +20,15 @@ pub const NO_PADDING: Padding = Padding(ffi::RSA_NO_PADDING);
pub const PKCS1_PADDING: Padding = Padding(ffi::RSA_PKCS1_PADDING);
pub const PKCS1_OAEP_PADDING: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING);

pub struct Rsa(*mut ffi::RSA);

impl Drop for Rsa {
    fn drop(&mut self) {
        unsafe {
            ffi::RSA_free(self.0);
        }
    }
}

impl Rsa {
    /// only useful for associating the key material directly with the key, it's safer to use
    /// the supplied load and save methods for DER formatted keys.
    pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa, ErrorStack> {
        unsafe {
            let rsa = Rsa(try!(cvt_p(ffi::RSA_new())));
            try!(cvt(compat::set_key(rsa.0,
                                     n.as_ptr(),
                                     e.as_ptr(),
                                     ptr::null_mut())));
            mem::forget((n, e));
            Ok(rsa)
        }
    }

    pub fn from_private_components(n: BigNum,
                                   e: BigNum,
                                   d: BigNum,
                                   p: BigNum,
                                   q: BigNum,
                                   dp: BigNum,
                                   dq: BigNum,
                                   qi: BigNum)
                                   -> Result<Rsa, ErrorStack> {
        unsafe {
            let rsa = Rsa(try!(cvt_p(ffi::RSA_new())));
            try!(cvt(compat::set_key(rsa.0, n.as_ptr(), e.as_ptr(), d.as_ptr())));
            mem::forget((n, e, d));
            try!(cvt(compat::set_factors(rsa.0, p.as_ptr(), q.as_ptr())));
            mem::forget((p, q));
            try!(cvt(compat::set_crt_params(rsa.0, dp.as_ptr(), dq.as_ptr(),
                                            qi.as_ptr())));
            mem::forget((dp, dq, qi));
            Ok(rsa)
        }
    }

    pub unsafe fn from_ptr(rsa: *mut ffi::RSA) -> Rsa {
        Rsa(rsa)
    }

    /// Generates a public/private key pair with the specified size.
    ///
    /// The public exponent will be 65537.
    pub fn generate(bits: u32) -> Result<Rsa, ErrorStack> {
        unsafe {
            let rsa = Rsa(try!(cvt_p(ffi::RSA_new())));
            let e = try!(BigNum::from_u32(ffi::RSA_F4 as u32));
            try!(cvt(ffi::RSA_generate_key_ex(rsa.0, bits as c_int, e.as_ptr(), ptr::null_mut())));
            Ok(rsa)
        }
    }
pub struct RsaRef(Opaque);

    /// Reads an RSA private key from PEM formatted data.
    pub fn private_key_from_pem(buf: &[u8]) -> Result<Rsa, ErrorStack> {
        let mem_bio = try!(MemBioSlice::new(buf));
        unsafe {
            let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(),
                                                                 ptr::null_mut(),
                                                                 None,
                                                                 ptr::null_mut())));
            Ok(Rsa(rsa))
        }
impl RsaRef {
    pub unsafe fn from_ptr<'a>(ptr: *mut ffi::RSA) -> &'a RsaRef {
        &*(ptr as *mut _)
    }

    /// Reads an RSA private key from PEM formatted data and supplies a password callback.
    pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<Rsa, ErrorStack>
        where F: FnOnce(&mut [c_char]) -> usize
    {
        let mut cb = CallbackState::new(pass_cb);
        let mem_bio = try!(MemBioSlice::new(buf));

        unsafe {
            let cb_ptr = &mut cb as *mut _ as *mut c_void;
            let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(),
                                                                 ptr::null_mut(),
                                                                 Some(invoke_passwd_cb::<F>),
                                                                 cb_ptr)));
            Ok(Rsa(rsa))
        }
    }

    /// Reads an RSA public key from PEM formatted data.
    pub fn public_key_from_pem(buf: &[u8]) -> Result<Rsa, ErrorStack> {
        let mem_bio = try!(MemBioSlice::new(buf));
        unsafe {
            let rsa = try!(cvt_p(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.as_ptr(),
                                                              ptr::null_mut(),
                                                              None,
                                                              ptr::null_mut())));
            Ok(Rsa(rsa))
        }
    pub fn as_ptr(&self) -> *mut ffi::RSA {
        self as *const _ as *mut _
    }

    /// Writes an RSA private key as unencrypted PEM formatted data
@@ -128,7 +37,7 @@ impl Rsa {

        unsafe {
            try!(cvt(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.as_ptr(),
                                                      self.0,
                                                      self.as_ptr(),
                                                      ptr::null(),
                                                      ptr::null_mut(),
                                                      0,
@@ -143,7 +52,7 @@ impl Rsa {
        let mem_bio = try!(MemBio::new());

        unsafe {
            try!(cvt(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.as_ptr(), self.0)));
            try!(cvt(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.as_ptr(), self.as_ptr())));
        }

        Ok(mem_bio.get_buf().to_owned())
@@ -153,7 +62,7 @@ impl Rsa {
        unsafe {
            assert!(self.n().is_some());

            ffi::RSA_size(self.0) as usize
            ffi::RSA_size(self.as_ptr()) as usize
        }
    }

@@ -176,7 +85,7 @@ impl Rsa {
            let len = try!(cvt_n(ffi::RSA_private_decrypt(from.len() as c_int,
                                                          from.as_ptr(),
                                                          to.as_mut_ptr(),
                                                          self.0,
                                                          self.as_ptr(),
                                                          padding.0)));
            Ok(len as usize)
        }
@@ -201,7 +110,7 @@ impl Rsa {
            let len = try!(cvt_n(ffi::RSA_private_encrypt(from.len() as c_int,
                                                          from.as_ptr(),
                                                          to.as_mut_ptr(),
                                                          self.0,
                                                          self.as_ptr(),
                                                          padding.0)));
            Ok(len as usize)
        }
@@ -224,7 +133,7 @@ impl Rsa {
            let len = try!(cvt_n(ffi::RSA_public_decrypt(from.len() as c_int,
                                                         from.as_ptr(),
                                                         to.as_mut_ptr(),
                                                         self.0,
                                                         self.as_ptr(),
                                                         padding.0)));
            Ok(len as usize)
        }
@@ -247,19 +156,15 @@ impl Rsa {
            let len = try!(cvt_n(ffi::RSA_public_encrypt(from.len() as c_int,
                                                         from.as_ptr(),
                                                         to.as_mut_ptr(),
                                                         self.0,
                                                         self.as_ptr(),
                                                         padding.0)));
            Ok(len as usize)
        }
    }

    pub fn as_ptr(&self) -> *mut ffi::RSA {
        self.0
    }

    pub fn n(&self) -> Option<&BigNumRef> {
        unsafe {
            let n = compat::key(self.0)[0];
            let n = compat::key(self.as_ptr())[0];
            if n.is_null() {
                None
            } else {
@@ -270,7 +175,7 @@ impl Rsa {

    pub fn d(&self) -> Option<&BigNumRef> {
        unsafe {
            let d = compat::key(self.0)[2];
            let d = compat::key(self.as_ptr())[2];
            if d.is_null() {
                None
            } else {
@@ -281,7 +186,7 @@ impl Rsa {

    pub fn e(&self) -> Option<&BigNumRef> {
        unsafe {
            let e = compat::key(self.0)[1];
            let e = compat::key(self.as_ptr())[1];
            if e.is_null() {
                None
            } else {
@@ -292,7 +197,7 @@ impl Rsa {

    pub fn p(&self) -> Option<&BigNumRef> {
        unsafe {
            let p = compat::factors(self.0)[0];
            let p = compat::factors(self.as_ptr())[0];
            if p.is_null() {
                None
            } else {
@@ -303,7 +208,7 @@ impl Rsa {

    pub fn q(&self) -> Option<&BigNumRef> {
        unsafe {
            let q = compat::factors(self.0)[1];
            let q = compat::factors(self.as_ptr())[1];
            if q.is_null() {
                None
            } else {
@@ -313,9 +218,122 @@ impl Rsa {
    }
}

pub struct Rsa(*mut ffi::RSA);

impl Drop for Rsa {
    fn drop(&mut self) {
        unsafe {
            ffi::RSA_free(self.0);
        }
    }
}

impl Rsa {
    /// only useful for associating the key material directly with the key, it's safer to use
    /// the supplied load and save methods for DER formatted keys.
    pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa, ErrorStack> {
        unsafe {
            let rsa = Rsa(try!(cvt_p(ffi::RSA_new())));
            try!(cvt(compat::set_key(rsa.0,
                                     n.as_ptr(),
                                     e.as_ptr(),
                                     ptr::null_mut())));
            mem::forget((n, e));
            Ok(rsa)
        }
    }

    pub fn from_private_components(n: BigNum,
                                   e: BigNum,
                                   d: BigNum,
                                   p: BigNum,
                                   q: BigNum,
                                   dp: BigNum,
                                   dq: BigNum,
                                   qi: BigNum)
                                   -> Result<Rsa, ErrorStack> {
        unsafe {
            let rsa = Rsa(try!(cvt_p(ffi::RSA_new())));
            try!(cvt(compat::set_key(rsa.0, n.as_ptr(), e.as_ptr(), d.as_ptr())));
            mem::forget((n, e, d));
            try!(cvt(compat::set_factors(rsa.0, p.as_ptr(), q.as_ptr())));
            mem::forget((p, q));
            try!(cvt(compat::set_crt_params(rsa.0, dp.as_ptr(), dq.as_ptr(),
                                            qi.as_ptr())));
            mem::forget((dp, dq, qi));
            Ok(rsa)
        }
    }

    pub unsafe fn from_ptr(rsa: *mut ffi::RSA) -> Rsa {
        Rsa(rsa)
    }

    /// Generates a public/private key pair with the specified size.
    ///
    /// The public exponent will be 65537.
    pub fn generate(bits: u32) -> Result<Rsa, ErrorStack> {
        unsafe {
            let rsa = Rsa(try!(cvt_p(ffi::RSA_new())));
            let e = try!(BigNum::from_u32(ffi::RSA_F4 as u32));
            try!(cvt(ffi::RSA_generate_key_ex(rsa.0, bits as c_int, e.as_ptr(), ptr::null_mut())));
            Ok(rsa)
        }
    }

    /// Reads an RSA private key from PEM formatted data.
    pub fn private_key_from_pem(buf: &[u8]) -> Result<Rsa, ErrorStack> {
        let mem_bio = try!(MemBioSlice::new(buf));
        unsafe {
            let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(),
                                                                 ptr::null_mut(),
                                                                 None,
                                                                 ptr::null_mut())));
            Ok(Rsa(rsa))
        }
    }

    /// Reads an RSA private key from PEM formatted data and supplies a password callback.
    pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<Rsa, ErrorStack>
        where F: FnOnce(&mut [c_char]) -> usize
    {
        let mut cb = CallbackState::new(pass_cb);
        let mem_bio = try!(MemBioSlice::new(buf));

        unsafe {
            let cb_ptr = &mut cb as *mut _ as *mut c_void;
            let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(),
                                                                 ptr::null_mut(),
                                                                 Some(invoke_passwd_cb::<F>),
                                                                 cb_ptr)));
            Ok(Rsa(rsa))
        }
    }

    /// Reads an RSA public key from PEM formatted data.
    pub fn public_key_from_pem(buf: &[u8]) -> Result<Rsa, ErrorStack> {
        let mem_bio = try!(MemBioSlice::new(buf));
        unsafe {
            let rsa = try!(cvt_p(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.as_ptr(),
                                                              ptr::null_mut(),
                                                              None,
                                                              ptr::null_mut())));
            Ok(Rsa(rsa))
        }
    }
}

impl fmt::Debug for Rsa {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RSA")
        write!(f, "Rsa")
    }
}

impl Deref for Rsa {
    type Target = RsaRef;

    fn deref(&self) -> &RsaRef {
        unsafe { RsaRef::from_ptr(self.0) }
    }
}