192f3ab15Sopenharmony_ci//! Diffie-Hellman key agreement. 292f3ab15Sopenharmony_ci 392f3ab15Sopenharmony_ciuse cfg_if::cfg_if; 492f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef}; 592f3ab15Sopenharmony_ciuse std::mem; 692f3ab15Sopenharmony_ciuse std::ptr; 792f3ab15Sopenharmony_ci 892f3ab15Sopenharmony_ciuse crate::bn::{BigNum, BigNumRef}; 992f3ab15Sopenharmony_ciuse crate::error::ErrorStack; 1092f3ab15Sopenharmony_ciuse crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public}; 1192f3ab15Sopenharmony_ciuse crate::{cvt, cvt_p}; 1292f3ab15Sopenharmony_ciuse openssl_macros::corresponds; 1392f3ab15Sopenharmony_ci 1492f3ab15Sopenharmony_cigeneric_foreign_type_and_impl_send_sync! { 1592f3ab15Sopenharmony_ci type CType = ffi::DH; 1692f3ab15Sopenharmony_ci fn drop = ffi::DH_free; 1792f3ab15Sopenharmony_ci 1892f3ab15Sopenharmony_ci pub struct Dh<T>; 1992f3ab15Sopenharmony_ci 2092f3ab15Sopenharmony_ci pub struct DhRef<T>; 2192f3ab15Sopenharmony_ci} 2292f3ab15Sopenharmony_ci 2392f3ab15Sopenharmony_ciimpl<T> DhRef<T> 2492f3ab15Sopenharmony_ciwhere 2592f3ab15Sopenharmony_ci T: HasParams, 2692f3ab15Sopenharmony_ci{ 2792f3ab15Sopenharmony_ci to_pem! { 2892f3ab15Sopenharmony_ci /// Serializes the parameters into a PEM-encoded PKCS#3 DHparameter structure. 2992f3ab15Sopenharmony_ci /// 3092f3ab15Sopenharmony_ci /// The output will have a header of `-----BEGIN DH PARAMETERS-----`. 3192f3ab15Sopenharmony_ci #[corresponds(PEM_write_bio_DHparams)] 3292f3ab15Sopenharmony_ci params_to_pem, 3392f3ab15Sopenharmony_ci ffi::PEM_write_bio_DHparams 3492f3ab15Sopenharmony_ci } 3592f3ab15Sopenharmony_ci 3692f3ab15Sopenharmony_ci to_der! { 3792f3ab15Sopenharmony_ci /// Serializes the parameters into a DER-encoded PKCS#3 DHparameter structure. 3892f3ab15Sopenharmony_ci #[corresponds(i2d_DHparams)] 3992f3ab15Sopenharmony_ci params_to_der, 4092f3ab15Sopenharmony_ci ffi::i2d_DHparams 4192f3ab15Sopenharmony_ci } 4292f3ab15Sopenharmony_ci 4392f3ab15Sopenharmony_ci /// Validates DH parameters for correctness 4492f3ab15Sopenharmony_ci #[corresponds(DH_check_key)] 4592f3ab15Sopenharmony_ci pub fn check_key(&self) -> Result<bool, ErrorStack> { 4692f3ab15Sopenharmony_ci unsafe { 4792f3ab15Sopenharmony_ci let mut codes = 0; 4892f3ab15Sopenharmony_ci cvt(ffi::DH_check(self.as_ptr(), &mut codes))?; 4992f3ab15Sopenharmony_ci Ok(codes == 0) 5092f3ab15Sopenharmony_ci } 5192f3ab15Sopenharmony_ci } 5292f3ab15Sopenharmony_ci} 5392f3ab15Sopenharmony_ci 5492f3ab15Sopenharmony_ciimpl Dh<Params> { 5592f3ab15Sopenharmony_ci pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<Dh<Params>, ErrorStack> { 5692f3ab15Sopenharmony_ci Self::from_pqg(p, Some(q), g) 5792f3ab15Sopenharmony_ci } 5892f3ab15Sopenharmony_ci 5992f3ab15Sopenharmony_ci /// Creates a DH instance based upon the given primes and generator params. 6092f3ab15Sopenharmony_ci #[corresponds(DH_set0_pqg)] 6192f3ab15Sopenharmony_ci pub fn from_pqg( 6292f3ab15Sopenharmony_ci prime_p: BigNum, 6392f3ab15Sopenharmony_ci prime_q: Option<BigNum>, 6492f3ab15Sopenharmony_ci generator: BigNum, 6592f3ab15Sopenharmony_ci ) -> Result<Dh<Params>, ErrorStack> { 6692f3ab15Sopenharmony_ci unsafe { 6792f3ab15Sopenharmony_ci let dh = Dh::from_ptr(cvt_p(ffi::DH_new())?); 6892f3ab15Sopenharmony_ci cvt(DH_set0_pqg( 6992f3ab15Sopenharmony_ci dh.0, 7092f3ab15Sopenharmony_ci prime_p.as_ptr(), 7192f3ab15Sopenharmony_ci prime_q.as_ref().map_or(ptr::null_mut(), |q| q.as_ptr()), 7292f3ab15Sopenharmony_ci generator.as_ptr(), 7392f3ab15Sopenharmony_ci ))?; 7492f3ab15Sopenharmony_ci mem::forget((prime_p, prime_q, generator)); 7592f3ab15Sopenharmony_ci Ok(dh) 7692f3ab15Sopenharmony_ci } 7792f3ab15Sopenharmony_ci } 7892f3ab15Sopenharmony_ci 7992f3ab15Sopenharmony_ci /// Sets the public key on the DH object. 8092f3ab15Sopenharmony_ci pub fn set_public_key(self, pub_key: BigNum) -> Result<Dh<Public>, ErrorStack> { 8192f3ab15Sopenharmony_ci unsafe { 8292f3ab15Sopenharmony_ci let dh_ptr = self.0; 8392f3ab15Sopenharmony_ci cvt(DH_set0_key(dh_ptr, pub_key.as_ptr(), ptr::null_mut()))?; 8492f3ab15Sopenharmony_ci mem::forget((self, pub_key)); 8592f3ab15Sopenharmony_ci Ok(Dh::from_ptr(dh_ptr)) 8692f3ab15Sopenharmony_ci } 8792f3ab15Sopenharmony_ci } 8892f3ab15Sopenharmony_ci 8992f3ab15Sopenharmony_ci /// Sets the private key on the DH object and recomputes the public key. 9092f3ab15Sopenharmony_ci pub fn set_private_key(self, priv_key: BigNum) -> Result<Dh<Private>, ErrorStack> { 9192f3ab15Sopenharmony_ci unsafe { 9292f3ab15Sopenharmony_ci let dh_ptr = self.0; 9392f3ab15Sopenharmony_ci cvt(DH_set0_key(dh_ptr, ptr::null_mut(), priv_key.as_ptr()))?; 9492f3ab15Sopenharmony_ci mem::forget(priv_key); 9592f3ab15Sopenharmony_ci 9692f3ab15Sopenharmony_ci cvt(ffi::DH_generate_key(dh_ptr))?; 9792f3ab15Sopenharmony_ci mem::forget(self); 9892f3ab15Sopenharmony_ci Ok(Dh::from_ptr(dh_ptr)) 9992f3ab15Sopenharmony_ci } 10092f3ab15Sopenharmony_ci } 10192f3ab15Sopenharmony_ci 10292f3ab15Sopenharmony_ci /// Sets the public and private keys on the DH object. 10392f3ab15Sopenharmony_ci pub fn set_key(self, pub_key: BigNum, priv_key: BigNum) -> Result<Dh<Private>, ErrorStack> { 10492f3ab15Sopenharmony_ci unsafe { 10592f3ab15Sopenharmony_ci let dh_ptr = self.0; 10692f3ab15Sopenharmony_ci cvt(DH_set0_key(dh_ptr, pub_key.as_ptr(), priv_key.as_ptr()))?; 10792f3ab15Sopenharmony_ci mem::forget((self, pub_key, priv_key)); 10892f3ab15Sopenharmony_ci Ok(Dh::from_ptr(dh_ptr)) 10992f3ab15Sopenharmony_ci } 11092f3ab15Sopenharmony_ci } 11192f3ab15Sopenharmony_ci 11292f3ab15Sopenharmony_ci /// Generates DH params based on the given `prime_len` and a fixed `generator` value. 11392f3ab15Sopenharmony_ci #[corresponds(DH_generate_parameters_ex)] 11492f3ab15Sopenharmony_ci pub fn generate_params(prime_len: u32, generator: u32) -> Result<Dh<Params>, ErrorStack> { 11592f3ab15Sopenharmony_ci unsafe { 11692f3ab15Sopenharmony_ci let dh = Dh::from_ptr(cvt_p(ffi::DH_new())?); 11792f3ab15Sopenharmony_ci cvt(ffi::DH_generate_parameters_ex( 11892f3ab15Sopenharmony_ci dh.0, 11992f3ab15Sopenharmony_ci prime_len as i32, 12092f3ab15Sopenharmony_ci generator as i32, 12192f3ab15Sopenharmony_ci ptr::null_mut(), 12292f3ab15Sopenharmony_ci ))?; 12392f3ab15Sopenharmony_ci Ok(dh) 12492f3ab15Sopenharmony_ci } 12592f3ab15Sopenharmony_ci } 12692f3ab15Sopenharmony_ci 12792f3ab15Sopenharmony_ci /// Generates a public and a private key based on the DH params. 12892f3ab15Sopenharmony_ci #[corresponds(DH_generate_key)] 12992f3ab15Sopenharmony_ci pub fn generate_key(self) -> Result<Dh<Private>, ErrorStack> { 13092f3ab15Sopenharmony_ci unsafe { 13192f3ab15Sopenharmony_ci let dh_ptr = self.0; 13292f3ab15Sopenharmony_ci cvt(ffi::DH_generate_key(dh_ptr))?; 13392f3ab15Sopenharmony_ci mem::forget(self); 13492f3ab15Sopenharmony_ci Ok(Dh::from_ptr(dh_ptr)) 13592f3ab15Sopenharmony_ci } 13692f3ab15Sopenharmony_ci } 13792f3ab15Sopenharmony_ci 13892f3ab15Sopenharmony_ci from_pem! { 13992f3ab15Sopenharmony_ci /// Deserializes a PEM-encoded PKCS#3 DHpararameters structure. 14092f3ab15Sopenharmony_ci /// 14192f3ab15Sopenharmony_ci /// The input should have a header of `-----BEGIN DH PARAMETERS-----`. 14292f3ab15Sopenharmony_ci #[corresponds(PEM_read_bio_DHparams)] 14392f3ab15Sopenharmony_ci params_from_pem, 14492f3ab15Sopenharmony_ci Dh<Params>, 14592f3ab15Sopenharmony_ci ffi::PEM_read_bio_DHparams 14692f3ab15Sopenharmony_ci } 14792f3ab15Sopenharmony_ci 14892f3ab15Sopenharmony_ci from_der! { 14992f3ab15Sopenharmony_ci /// Deserializes a DER-encoded PKCS#3 DHparameters structure. 15092f3ab15Sopenharmony_ci #[corresponds(d2i_DHparams)] 15192f3ab15Sopenharmony_ci params_from_der, 15292f3ab15Sopenharmony_ci Dh<Params>, 15392f3ab15Sopenharmony_ci ffi::d2i_DHparams 15492f3ab15Sopenharmony_ci } 15592f3ab15Sopenharmony_ci 15692f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or newer. 15792f3ab15Sopenharmony_ci #[corresponds(DH_get_1024_160)] 15892f3ab15Sopenharmony_ci #[cfg(any(ossl102, ossl110))] 15992f3ab15Sopenharmony_ci pub fn get_1024_160() -> Result<Dh<Params>, ErrorStack> { 16092f3ab15Sopenharmony_ci unsafe { 16192f3ab15Sopenharmony_ci ffi::init(); 16292f3ab15Sopenharmony_ci cvt_p(ffi::DH_get_1024_160()).map(|p| Dh::from_ptr(p)) 16392f3ab15Sopenharmony_ci } 16492f3ab15Sopenharmony_ci } 16592f3ab15Sopenharmony_ci 16692f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or newer. 16792f3ab15Sopenharmony_ci #[corresponds(DH_get_2048_224)] 16892f3ab15Sopenharmony_ci #[cfg(any(ossl102, ossl110))] 16992f3ab15Sopenharmony_ci pub fn get_2048_224() -> Result<Dh<Params>, ErrorStack> { 17092f3ab15Sopenharmony_ci unsafe { 17192f3ab15Sopenharmony_ci ffi::init(); 17292f3ab15Sopenharmony_ci cvt_p(ffi::DH_get_2048_224()).map(|p| Dh::from_ptr(p)) 17392f3ab15Sopenharmony_ci } 17492f3ab15Sopenharmony_ci } 17592f3ab15Sopenharmony_ci 17692f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or newer. 17792f3ab15Sopenharmony_ci #[corresponds(DH_get_2048_256)] 17892f3ab15Sopenharmony_ci #[cfg(any(ossl102, ossl110))] 17992f3ab15Sopenharmony_ci pub fn get_2048_256() -> Result<Dh<Params>, ErrorStack> { 18092f3ab15Sopenharmony_ci unsafe { 18192f3ab15Sopenharmony_ci ffi::init(); 18292f3ab15Sopenharmony_ci cvt_p(ffi::DH_get_2048_256()).map(|p| Dh::from_ptr(p)) 18392f3ab15Sopenharmony_ci } 18492f3ab15Sopenharmony_ci } 18592f3ab15Sopenharmony_ci} 18692f3ab15Sopenharmony_ci 18792f3ab15Sopenharmony_ciimpl<T> Dh<T> 18892f3ab15Sopenharmony_ciwhere 18992f3ab15Sopenharmony_ci T: HasParams, 19092f3ab15Sopenharmony_ci{ 19192f3ab15Sopenharmony_ci /// Returns the prime `p` from the DH instance. 19292f3ab15Sopenharmony_ci #[corresponds(DH_get0_pqg)] 19392f3ab15Sopenharmony_ci pub fn prime_p(&self) -> &BigNumRef { 19492f3ab15Sopenharmony_ci let mut p = ptr::null(); 19592f3ab15Sopenharmony_ci unsafe { 19692f3ab15Sopenharmony_ci DH_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut()); 19792f3ab15Sopenharmony_ci BigNumRef::from_ptr(p as *mut _) 19892f3ab15Sopenharmony_ci } 19992f3ab15Sopenharmony_ci } 20092f3ab15Sopenharmony_ci 20192f3ab15Sopenharmony_ci /// Returns the prime `q` from the DH instance. 20292f3ab15Sopenharmony_ci #[corresponds(DH_get0_pqg)] 20392f3ab15Sopenharmony_ci pub fn prime_q(&self) -> Option<&BigNumRef> { 20492f3ab15Sopenharmony_ci let mut q = ptr::null(); 20592f3ab15Sopenharmony_ci unsafe { 20692f3ab15Sopenharmony_ci DH_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut()); 20792f3ab15Sopenharmony_ci if q.is_null() { 20892f3ab15Sopenharmony_ci None 20992f3ab15Sopenharmony_ci } else { 21092f3ab15Sopenharmony_ci Some(BigNumRef::from_ptr(q as *mut _)) 21192f3ab15Sopenharmony_ci } 21292f3ab15Sopenharmony_ci } 21392f3ab15Sopenharmony_ci } 21492f3ab15Sopenharmony_ci 21592f3ab15Sopenharmony_ci /// Returns the generator from the DH instance. 21692f3ab15Sopenharmony_ci #[corresponds(DH_get0_pqg)] 21792f3ab15Sopenharmony_ci pub fn generator(&self) -> &BigNumRef { 21892f3ab15Sopenharmony_ci let mut g = ptr::null(); 21992f3ab15Sopenharmony_ci unsafe { 22092f3ab15Sopenharmony_ci DH_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g); 22192f3ab15Sopenharmony_ci BigNumRef::from_ptr(g as *mut _) 22292f3ab15Sopenharmony_ci } 22392f3ab15Sopenharmony_ci } 22492f3ab15Sopenharmony_ci} 22592f3ab15Sopenharmony_ci 22692f3ab15Sopenharmony_ciimpl<T> DhRef<T> 22792f3ab15Sopenharmony_ciwhere 22892f3ab15Sopenharmony_ci T: HasPublic, 22992f3ab15Sopenharmony_ci{ 23092f3ab15Sopenharmony_ci /// Returns the public key from the DH instance. 23192f3ab15Sopenharmony_ci #[corresponds(DH_get0_key)] 23292f3ab15Sopenharmony_ci pub fn public_key(&self) -> &BigNumRef { 23392f3ab15Sopenharmony_ci let mut pub_key = ptr::null(); 23492f3ab15Sopenharmony_ci unsafe { 23592f3ab15Sopenharmony_ci DH_get0_key(self.as_ptr(), &mut pub_key, ptr::null_mut()); 23692f3ab15Sopenharmony_ci BigNumRef::from_ptr(pub_key as *mut _) 23792f3ab15Sopenharmony_ci } 23892f3ab15Sopenharmony_ci } 23992f3ab15Sopenharmony_ci} 24092f3ab15Sopenharmony_ci 24192f3ab15Sopenharmony_ciimpl<T> DhRef<T> 24292f3ab15Sopenharmony_ciwhere 24392f3ab15Sopenharmony_ci T: HasPrivate, 24492f3ab15Sopenharmony_ci{ 24592f3ab15Sopenharmony_ci /// Computes a shared secret from the own private key and the given `public_key`. 24692f3ab15Sopenharmony_ci #[corresponds(DH_compute_key)] 24792f3ab15Sopenharmony_ci pub fn compute_key(&self, public_key: &BigNumRef) -> Result<Vec<u8>, ErrorStack> { 24892f3ab15Sopenharmony_ci unsafe { 24992f3ab15Sopenharmony_ci let key_len = ffi::DH_size(self.as_ptr()); 25092f3ab15Sopenharmony_ci let mut key = vec![0u8; key_len as usize]; 25192f3ab15Sopenharmony_ci cvt(ffi::DH_compute_key( 25292f3ab15Sopenharmony_ci key.as_mut_ptr(), 25392f3ab15Sopenharmony_ci public_key.as_ptr(), 25492f3ab15Sopenharmony_ci self.as_ptr(), 25592f3ab15Sopenharmony_ci ))?; 25692f3ab15Sopenharmony_ci Ok(key) 25792f3ab15Sopenharmony_ci } 25892f3ab15Sopenharmony_ci } 25992f3ab15Sopenharmony_ci 26092f3ab15Sopenharmony_ci /// Returns the private key from the DH instance. 26192f3ab15Sopenharmony_ci #[corresponds(DH_get0_key)] 26292f3ab15Sopenharmony_ci pub fn private_key(&self) -> &BigNumRef { 26392f3ab15Sopenharmony_ci let mut priv_key = ptr::null(); 26492f3ab15Sopenharmony_ci unsafe { 26592f3ab15Sopenharmony_ci DH_get0_key(self.as_ptr(), ptr::null_mut(), &mut priv_key); 26692f3ab15Sopenharmony_ci BigNumRef::from_ptr(priv_key as *mut _) 26792f3ab15Sopenharmony_ci } 26892f3ab15Sopenharmony_ci } 26992f3ab15Sopenharmony_ci} 27092f3ab15Sopenharmony_ci 27192f3ab15Sopenharmony_cicfg_if! { 27292f3ab15Sopenharmony_ci if #[cfg(any(ossl110, libressl270, boringssl))] { 27392f3ab15Sopenharmony_ci use ffi::{DH_set0_pqg, DH_get0_pqg, DH_get0_key, DH_set0_key}; 27492f3ab15Sopenharmony_ci } else { 27592f3ab15Sopenharmony_ci #[allow(bad_style)] 27692f3ab15Sopenharmony_ci unsafe fn DH_set0_pqg( 27792f3ab15Sopenharmony_ci dh: *mut ffi::DH, 27892f3ab15Sopenharmony_ci p: *mut ffi::BIGNUM, 27992f3ab15Sopenharmony_ci q: *mut ffi::BIGNUM, 28092f3ab15Sopenharmony_ci g: *mut ffi::BIGNUM, 28192f3ab15Sopenharmony_ci ) -> ::libc::c_int { 28292f3ab15Sopenharmony_ci (*dh).p = p; 28392f3ab15Sopenharmony_ci (*dh).q = q; 28492f3ab15Sopenharmony_ci (*dh).g = g; 28592f3ab15Sopenharmony_ci 1 28692f3ab15Sopenharmony_ci } 28792f3ab15Sopenharmony_ci 28892f3ab15Sopenharmony_ci #[allow(bad_style)] 28992f3ab15Sopenharmony_ci unsafe fn DH_get0_pqg( 29092f3ab15Sopenharmony_ci dh: *mut ffi::DH, 29192f3ab15Sopenharmony_ci p: *mut *const ffi::BIGNUM, 29292f3ab15Sopenharmony_ci q: *mut *const ffi::BIGNUM, 29392f3ab15Sopenharmony_ci g: *mut *const ffi::BIGNUM, 29492f3ab15Sopenharmony_ci ) { 29592f3ab15Sopenharmony_ci if !p.is_null() { 29692f3ab15Sopenharmony_ci *p = (*dh).p; 29792f3ab15Sopenharmony_ci } 29892f3ab15Sopenharmony_ci if !q.is_null() { 29992f3ab15Sopenharmony_ci *q = (*dh).q; 30092f3ab15Sopenharmony_ci } 30192f3ab15Sopenharmony_ci if !g.is_null() { 30292f3ab15Sopenharmony_ci *g = (*dh).g; 30392f3ab15Sopenharmony_ci } 30492f3ab15Sopenharmony_ci } 30592f3ab15Sopenharmony_ci 30692f3ab15Sopenharmony_ci #[allow(bad_style)] 30792f3ab15Sopenharmony_ci unsafe fn DH_set0_key( 30892f3ab15Sopenharmony_ci dh: *mut ffi::DH, 30992f3ab15Sopenharmony_ci pub_key: *mut ffi::BIGNUM, 31092f3ab15Sopenharmony_ci priv_key: *mut ffi::BIGNUM, 31192f3ab15Sopenharmony_ci ) -> ::libc::c_int { 31292f3ab15Sopenharmony_ci (*dh).pub_key = pub_key; 31392f3ab15Sopenharmony_ci (*dh).priv_key = priv_key; 31492f3ab15Sopenharmony_ci 1 31592f3ab15Sopenharmony_ci } 31692f3ab15Sopenharmony_ci 31792f3ab15Sopenharmony_ci #[allow(bad_style)] 31892f3ab15Sopenharmony_ci unsafe fn DH_get0_key( 31992f3ab15Sopenharmony_ci dh: *mut ffi::DH, 32092f3ab15Sopenharmony_ci pub_key: *mut *const ffi::BIGNUM, 32192f3ab15Sopenharmony_ci priv_key: *mut *const ffi::BIGNUM, 32292f3ab15Sopenharmony_ci ) { 32392f3ab15Sopenharmony_ci if !pub_key.is_null() { 32492f3ab15Sopenharmony_ci *pub_key = (*dh).pub_key; 32592f3ab15Sopenharmony_ci } 32692f3ab15Sopenharmony_ci if !priv_key.is_null() { 32792f3ab15Sopenharmony_ci *priv_key = (*dh).priv_key; 32892f3ab15Sopenharmony_ci } 32992f3ab15Sopenharmony_ci } 33092f3ab15Sopenharmony_ci } 33192f3ab15Sopenharmony_ci} 33292f3ab15Sopenharmony_ci 33392f3ab15Sopenharmony_ci#[cfg(test)] 33492f3ab15Sopenharmony_cimod tests { 33592f3ab15Sopenharmony_ci use crate::bn::BigNum; 33692f3ab15Sopenharmony_ci use crate::dh::Dh; 33792f3ab15Sopenharmony_ci use crate::ssl::{SslContext, SslMethod}; 33892f3ab15Sopenharmony_ci 33992f3ab15Sopenharmony_ci #[test] 34092f3ab15Sopenharmony_ci #[cfg(ossl102)] 34192f3ab15Sopenharmony_ci fn test_dh_rfc5114() { 34292f3ab15Sopenharmony_ci let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); 34392f3ab15Sopenharmony_ci let dh2 = Dh::get_2048_224().unwrap(); 34492f3ab15Sopenharmony_ci ctx.set_tmp_dh(&dh2).unwrap(); 34592f3ab15Sopenharmony_ci let dh3 = Dh::get_2048_256().unwrap(); 34692f3ab15Sopenharmony_ci ctx.set_tmp_dh(&dh3).unwrap(); 34792f3ab15Sopenharmony_ci } 34892f3ab15Sopenharmony_ci 34992f3ab15Sopenharmony_ci #[test] 35092f3ab15Sopenharmony_ci fn test_dh_params() { 35192f3ab15Sopenharmony_ci let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); 35292f3ab15Sopenharmony_ci let prime_p = BigNum::from_hex_str( 35392f3ab15Sopenharmony_ci "87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF\ 35492f3ab15Sopenharmony_ci 4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B47\ 35592f3ab15Sopenharmony_ci 58C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B6\ 35692f3ab15Sopenharmony_ci 3ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5\ 35792f3ab15Sopenharmony_ci 140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710\ 35892f3ab15Sopenharmony_ci C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597", 35992f3ab15Sopenharmony_ci ).unwrap(); 36092f3ab15Sopenharmony_ci let prime_q = BigNum::from_hex_str( 36192f3ab15Sopenharmony_ci "3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED\ 36292f3ab15Sopenharmony_ci 4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A\ 36392f3ab15Sopenharmony_ci 57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5\ 36492f3ab15Sopenharmony_ci 045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E\ 36592f3ab15Sopenharmony_ci 052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67E\ 36692f3ab15Sopenharmony_ci B6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659", 36792f3ab15Sopenharmony_ci ).unwrap(); 36892f3ab15Sopenharmony_ci let generator = BigNum::from_hex_str( 36992f3ab15Sopenharmony_ci "8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3", 37092f3ab15Sopenharmony_ci ) 37192f3ab15Sopenharmony_ci .unwrap(); 37292f3ab15Sopenharmony_ci let dh = Dh::from_params( 37392f3ab15Sopenharmony_ci prime_p.to_owned().unwrap(), 37492f3ab15Sopenharmony_ci generator.to_owned().unwrap(), 37592f3ab15Sopenharmony_ci prime_q.to_owned().unwrap(), 37692f3ab15Sopenharmony_ci ) 37792f3ab15Sopenharmony_ci .unwrap(); 37892f3ab15Sopenharmony_ci ctx.set_tmp_dh(&dh).unwrap(); 37992f3ab15Sopenharmony_ci 38092f3ab15Sopenharmony_ci assert_eq!(dh.prime_p(), &prime_p); 38192f3ab15Sopenharmony_ci assert_eq!(dh.prime_q().unwrap(), &prime_q); 38292f3ab15Sopenharmony_ci assert_eq!(dh.generator(), &generator); 38392f3ab15Sopenharmony_ci } 38492f3ab15Sopenharmony_ci 38592f3ab15Sopenharmony_ci #[test] 38692f3ab15Sopenharmony_ci #[cfg(ossl102)] 38792f3ab15Sopenharmony_ci fn test_dh_stored_restored() { 38892f3ab15Sopenharmony_ci let dh1 = Dh::get_2048_256().unwrap(); 38992f3ab15Sopenharmony_ci let key1 = dh1.generate_key().unwrap(); 39092f3ab15Sopenharmony_ci 39192f3ab15Sopenharmony_ci let dh2 = Dh::get_2048_256().unwrap(); 39292f3ab15Sopenharmony_ci let key2 = dh2 39392f3ab15Sopenharmony_ci .set_private_key(key1.private_key().to_owned().unwrap()) 39492f3ab15Sopenharmony_ci .unwrap(); 39592f3ab15Sopenharmony_ci 39692f3ab15Sopenharmony_ci assert_eq!(key1.public_key(), key2.public_key()); 39792f3ab15Sopenharmony_ci assert_eq!(key1.private_key(), key2.private_key()); 39892f3ab15Sopenharmony_ci } 39992f3ab15Sopenharmony_ci 40092f3ab15Sopenharmony_ci #[test] 40192f3ab15Sopenharmony_ci #[cfg(ossl102)] 40292f3ab15Sopenharmony_ci fn test_set_keys() { 40392f3ab15Sopenharmony_ci let dh1 = Dh::get_2048_256().unwrap(); 40492f3ab15Sopenharmony_ci let key1 = dh1.generate_key().unwrap(); 40592f3ab15Sopenharmony_ci 40692f3ab15Sopenharmony_ci let dh2 = Dh::get_2048_256().unwrap(); 40792f3ab15Sopenharmony_ci let key2 = dh2 40892f3ab15Sopenharmony_ci .set_public_key(key1.public_key().to_owned().unwrap()) 40992f3ab15Sopenharmony_ci .unwrap(); 41092f3ab15Sopenharmony_ci 41192f3ab15Sopenharmony_ci assert_eq!(key1.public_key(), key2.public_key()); 41292f3ab15Sopenharmony_ci 41392f3ab15Sopenharmony_ci let dh3 = Dh::get_2048_256().unwrap(); 41492f3ab15Sopenharmony_ci let key3 = dh3 41592f3ab15Sopenharmony_ci .set_key( 41692f3ab15Sopenharmony_ci key1.public_key().to_owned().unwrap(), 41792f3ab15Sopenharmony_ci key1.private_key().to_owned().unwrap(), 41892f3ab15Sopenharmony_ci ) 41992f3ab15Sopenharmony_ci .unwrap(); 42092f3ab15Sopenharmony_ci assert_eq!(key1.public_key(), key3.public_key()); 42192f3ab15Sopenharmony_ci assert_eq!(key1.private_key(), key3.private_key()); 42292f3ab15Sopenharmony_ci } 42392f3ab15Sopenharmony_ci 42492f3ab15Sopenharmony_ci #[test] 42592f3ab15Sopenharmony_ci fn test_dh_from_pem() { 42692f3ab15Sopenharmony_ci let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); 42792f3ab15Sopenharmony_ci let params = include_bytes!("../test/dhparams.pem"); 42892f3ab15Sopenharmony_ci let dh = Dh::params_from_pem(params).unwrap(); 42992f3ab15Sopenharmony_ci ctx.set_tmp_dh(&dh).unwrap(); 43092f3ab15Sopenharmony_ci } 43192f3ab15Sopenharmony_ci 43292f3ab15Sopenharmony_ci #[test] 43392f3ab15Sopenharmony_ci fn test_dh_from_der() { 43492f3ab15Sopenharmony_ci let params = include_bytes!("../test/dhparams.pem"); 43592f3ab15Sopenharmony_ci let dh = Dh::params_from_pem(params).unwrap(); 43692f3ab15Sopenharmony_ci let der = dh.params_to_der().unwrap(); 43792f3ab15Sopenharmony_ci Dh::params_from_der(&der).unwrap(); 43892f3ab15Sopenharmony_ci } 43992f3ab15Sopenharmony_ci 44092f3ab15Sopenharmony_ci #[test] 44192f3ab15Sopenharmony_ci #[cfg(ossl102)] 44292f3ab15Sopenharmony_ci fn test_dh_generate_key_compute_key() { 44392f3ab15Sopenharmony_ci let dh1 = Dh::get_2048_224().unwrap().generate_key().unwrap(); 44492f3ab15Sopenharmony_ci let dh2 = Dh::get_2048_224().unwrap().generate_key().unwrap(); 44592f3ab15Sopenharmony_ci 44692f3ab15Sopenharmony_ci let shared_a = dh1.compute_key(dh2.public_key()).unwrap(); 44792f3ab15Sopenharmony_ci let shared_b = dh2.compute_key(dh1.public_key()).unwrap(); 44892f3ab15Sopenharmony_ci 44992f3ab15Sopenharmony_ci assert_eq!(shared_a, shared_b); 45092f3ab15Sopenharmony_ci } 45192f3ab15Sopenharmony_ci 45292f3ab15Sopenharmony_ci #[test] 45392f3ab15Sopenharmony_ci fn test_dh_generate_params_generate_key_compute_key() { 45492f3ab15Sopenharmony_ci let dh_params1 = Dh::generate_params(512, 2).unwrap(); 45592f3ab15Sopenharmony_ci let dh_params2 = Dh::from_pqg( 45692f3ab15Sopenharmony_ci dh_params1.prime_p().to_owned().unwrap(), 45792f3ab15Sopenharmony_ci None, 45892f3ab15Sopenharmony_ci dh_params1.generator().to_owned().unwrap(), 45992f3ab15Sopenharmony_ci ) 46092f3ab15Sopenharmony_ci .unwrap(); 46192f3ab15Sopenharmony_ci 46292f3ab15Sopenharmony_ci let dh1 = dh_params1.generate_key().unwrap(); 46392f3ab15Sopenharmony_ci let dh2 = dh_params2.generate_key().unwrap(); 46492f3ab15Sopenharmony_ci 46592f3ab15Sopenharmony_ci let shared_a = dh1.compute_key(dh2.public_key()).unwrap(); 46692f3ab15Sopenharmony_ci let shared_b = dh2.compute_key(dh1.public_key()).unwrap(); 46792f3ab15Sopenharmony_ci 46892f3ab15Sopenharmony_ci assert_eq!(shared_a, shared_b); 46992f3ab15Sopenharmony_ci } 47092f3ab15Sopenharmony_ci 47192f3ab15Sopenharmony_ci #[test] 47292f3ab15Sopenharmony_ci fn test_dh_check_key() { 47392f3ab15Sopenharmony_ci let dh1 = Dh::generate_params(512, 2).unwrap(); 47492f3ab15Sopenharmony_ci let p = BigNum::from_hex_str("04").unwrap(); 47592f3ab15Sopenharmony_ci let g = BigNum::from_hex_str("02").unwrap(); 47692f3ab15Sopenharmony_ci let dh2 = Dh::from_pqg(p, None, g).unwrap(); 47792f3ab15Sopenharmony_ci assert!(dh1.check_key().unwrap()); 47892f3ab15Sopenharmony_ci assert!(!dh2.check_key().unwrap()); 47992f3ab15Sopenharmony_ci } 48092f3ab15Sopenharmony_ci} 481