Unverified Commit e75fd02f authored by Christoph Walcher's avatar Christoph Walcher
Browse files

advanced DH support

parent d9d805f3
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -4,6 +4,17 @@ extern "C" {
    pub fn DH_new() -> *mut DH;
    pub fn DH_free(dh: *mut DH);

    pub fn DH_generate_parameters(
        prime_len: c_int,
        generator: c_int,
        callback: Option<extern "C" fn(c_int, c_int, *mut c_void)>,
        cb_arg: *mut c_void,
    ) -> *mut DH;

    pub fn DH_generate_key(dh: *mut DH) -> c_int;
    pub fn DH_compute_key(key: *mut c_uchar, pub_key: *const BIGNUM, dh: *mut DH) -> c_int;
    pub fn DH_size(dh: *const DH) -> c_int;

    pub fn d2i_DHparams(k: *mut *mut DH, pp: *mut *const c_uchar, length: c_long) -> *mut DH;
    pub fn i2d_DHparams(dh: *const DH, pp: *mut *mut c_uchar) -> c_int;

@@ -16,4 +27,7 @@ extern "C" {

    #[cfg(any(ossl110, libressl273))]
    pub fn DH_set0_pqg(dh: *mut DH, p: *mut BIGNUM, q: *mut BIGNUM, g: *mut BIGNUM) -> c_int;

    #[cfg(ossl102)]
    pub fn DH_get0_key(dh: *const DH, pub_key: *mut *const BIGNUM, priv_key: *mut *const BIGNUM);
}
+1 −1
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ foreign_type_and_impl_send_sync! {
    type CType = ffi::BIGNUM;
    fn drop = ffi::BN_free;

    /// Dynamically sized large number impelementation
    /// Dynamically sized large number implementation
    ///
    /// Perform large number mathematics.  Create a new BigNum
    /// with [`new`].  Perform standard mathematics on large numbers using
+53 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ use std::mem;
use std::ptr;

use bn::BigNum;
use pkey::{HasParams, Params};
use pkey::{HasParams, HasPrivate, HasPublic, Params, Private};
use {cvt, cvt_p};

generic_foreign_type_and_impl_send_sync! {
@@ -54,6 +54,26 @@ impl Dh<Params> {
        }
    }

    pub fn generate_params(prime_len: u32, generator: u32) -> Result<Dh<Params>, ErrorStack> {
        unsafe {
            Ok(Dh::from_ptr(cvt_p(ffi::DH_generate_parameters(
                prime_len as i32,
                generator as i32,
                None,
                ptr::null_mut(),
            ))?))
        }
    }

    pub fn generate_key(self) -> Result<Dh<Private>, ErrorStack> {
        unsafe {
            let dh_ptr = self.0;
            cvt(ffi::DH_generate_key(dh_ptr))?;
            mem::forget(self);
            Ok(Dh::from_ptr(dh_ptr))
        }
    }

    from_pem! {
        /// Deserializes a PEM-encoded PKCS#3 DHpararameters structure.
        ///
@@ -106,6 +126,38 @@ impl Dh<Params> {
    }
}

impl<T> Dh<T>
where
    T: HasPublic,
{
    pub fn get_public_key(&self) -> Result<BigNum, ErrorStack> {
        let mut pub_key = ptr::null();
        let mut priv_key = ptr::null();
        unsafe {
            ffi::DH_get0_key(self.0, &mut pub_key, &mut priv_key);
            Ok(BigNum::from_ptr(cvt_p(ffi::BN_dup(pub_key))?))
        }
    }
}

impl<T> Dh<T>
where
    T: HasPrivate,
{
    pub fn compute_key(&self, public_key: BigNum) -> Result<Vec<u8>, ErrorStack> {
        unsafe {
            let key_len = ffi::DH_size(self.0);
            let mut key = vec![0u8; key_len as usize];
            cvt(ffi::DH_compute_key(
                key.as_mut_ptr(),
                public_key.as_ptr(),
                self.0,
            ))?;
            Ok(key)
        }
    }
}

cfg_if! {
    if #[cfg(any(ossl110, libressl273))] {
        use ffi::DH_set0_pqg;