diff options
author | Steven Fackler <sfackler@gmail.com> | 2017-12-30 21:46:17 -0800 |
---|---|---|
committer | Steven Fackler <sfackler@gmail.com> | 2017-12-30 21:53:39 -0800 |
commit | d207897458f8fbd0b2ff6d879721b2f787a5d72b (patch) | |
tree | f5646108131916584291141407696ef894f2ff1e /openssl/src | |
parent | 6238b4a20a5775f59ddd47676ee07176a3b446ce (diff) | |
download | rust-openssl-d207897458f8fbd0b2ff6d879721b2f787a5d72b.zip |
Parameterize keys over what they contain
Closes #790
Diffstat (limited to 'openssl/src')
-rw-r--r-- | openssl/src/cms.rs | 20 | ||||
-rw-r--r-- | openssl/src/derive.rs | 120 | ||||
-rw-r--r-- | openssl/src/dh.rs | 36 | ||||
-rw-r--r-- | openssl/src/dsa.rs | 105 | ||||
-rw-r--r-- | openssl/src/ec.rs | 286 | ||||
-rw-r--r-- | openssl/src/lib.rs | 1 | ||||
-rw-r--r-- | openssl/src/macros.rs | 132 | ||||
-rw-r--r-- | openssl/src/pkcs12.rs | 23 | ||||
-rw-r--r-- | openssl/src/pkey.rs | 208 | ||||
-rw-r--r-- | openssl/src/rsa.rs | 237 | ||||
-rw-r--r-- | openssl/src/sign.rs | 105 | ||||
-rw-r--r-- | openssl/src/ssl/callbacks.rs | 9 | ||||
-rw-r--r-- | openssl/src/ssl/mod.rs | 53 | ||||
-rw-r--r-- | openssl/src/x509/mod.rs | 24 | ||||
-rw-r--r-- | openssl/src/x509/tests.rs | 4 |
15 files changed, 774 insertions, 589 deletions
diff --git a/openssl/src/cms.rs b/openssl/src/cms.rs index 160d2daf..8c60455c 100644 --- a/openssl/src/cms.rs +++ b/openssl/src/cms.rs @@ -8,15 +8,12 @@ use ffi; use foreign_types::{ForeignType, ForeignTypeRef}; use std::ptr; -use error::ErrorStack; +use {cvt, cvt_p}; use bio::{MemBio, MemBioSlice}; - +use error::ErrorStack; +use pkey::{HasPrivate, PKeyRef}; use x509::X509; -use pkey::PKeyRef; - -use cvt; -use cvt_p; foreign_type_and_impl_send_sync! { type CType = ffi::CMS_ContentInfo; @@ -44,7 +41,10 @@ impl CmsContentInfoRef { /// OpenSSL documentation at [`CMS_decrypt`] /// /// [`CMS_decrypt`]: https://www.openssl.org/docs/man1.1.0/crypto/CMS_decrypt.html - pub fn decrypt(&self, pkey: &PKeyRef, cert: &X509) -> Result<Vec<u8>, ErrorStack> { + pub fn decrypt<T>(&self, pkey: &PKeyRef<T>, cert: &X509) -> Result<Vec<u8>, ErrorStack> + where + T: HasPrivate, + { unsafe { let pkey = pkey.as_ptr(); let cert = cert.as_ptr(); @@ -63,7 +63,6 @@ impl CmsContentInfoRef { Ok(out.get_buf().to_owned()) } } - } impl CmsContentInfo { @@ -76,10 +75,7 @@ impl CmsContentInfo { unsafe { let bio = MemBioSlice::new(smime)?; - let cms = cvt_p(ffi::SMIME_read_CMS( - bio.as_ptr(), - ptr::null_mut(), - ))?; + let cms = cvt_p(ffi::SMIME_read_CMS(bio.as_ptr(), ptr::null_mut()))?; Ok(CmsContentInfo::from_ptr(cms)) } diff --git a/openssl/src/derive.rs b/openssl/src/derive.rs new file mode 100644 index 00000000..fb7bbf14 --- /dev/null +++ b/openssl/src/derive.rs @@ -0,0 +1,120 @@ +//! Shared secret derivation. +use ffi; +use std::marker::PhantomData; +use std::ptr; +use foreign_types::ForeignTypeRef; + +use {cvt, cvt_p}; +use error::ErrorStack; +use pkey::{HasPrivate, HasPublic, PKeyRef}; + +/// A type used to derive a shared secret between two keys. +pub struct Deriver<'a>(*mut ffi::EVP_PKEY_CTX, PhantomData<&'a ()>); + +impl<'a> Deriver<'a> { + /// Creates a new `Deriver` using the provided private key. + /// + /// This corresponds to [`EVP_PKEY_derive_init`]. + /// + /// [`EVP_PKEY_derive_init`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_derive_init.html + pub fn new<T>(key: &'a PKeyRef<T>) -> Result<Deriver<'a>, ErrorStack> + where + T: HasPrivate, + { + unsafe { + cvt_p(ffi::EVP_PKEY_CTX_new(key.as_ptr(), ptr::null_mut())) + .map(|p| Deriver(p, PhantomData)) + .and_then(|ctx| cvt(ffi::EVP_PKEY_derive_init(ctx.0)).map(|_| ctx)) + } + } + + /// Sets the peer key used for secret derivation. + /// + /// This corresponds to [`EVP_PKEY_derive_set_peer`]: + /// + /// [`EVP_PKEY_derive_set_peer`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_derive_init.html + pub fn set_peer<T>(&mut self, key: &'a PKeyRef<T>) -> Result<(), ErrorStack> + where + T: HasPublic, + { + unsafe { cvt(ffi::EVP_PKEY_derive_set_peer(self.0, key.as_ptr())).map(|_| ()) } + } + + /// Returns the size of the shared secret. + /// + /// It can be used to size the buffer passed to [`Deriver::derive`]. + /// + /// This corresponds to [`EVP_PKEY_derive`]. + /// + /// [`Deriver::derive`]: #method.derive + /// [`EVP_PKEY_derive`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_derive_init.html + pub fn len(&mut self) -> Result<usize, ErrorStack> { + unsafe { + let mut len = 0; + cvt(ffi::EVP_PKEY_derive(self.0, ptr::null_mut(), &mut len)).map(|_| len) + } + } + + /// Derives a shared secret between the two keys, writing it into the buffer. + /// + /// Returns the number of bytes written. + /// + /// This corresponds to [`EVP_PKEY_derive`]. + /// + /// [`EVP_PKEY_derive`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_derive_init.html + pub fn derive(&mut self, buf: &mut [u8]) -> Result<usize, ErrorStack> { + let mut len = buf.len(); + unsafe { + cvt(ffi::EVP_PKEY_derive( + self.0, + buf.as_mut_ptr() as *mut _, + &mut len, + )).map(|_| len) + } + } + + /// A convenience function which derives a shared secret and returns it in a new buffer. + /// + /// This simply wraps [`Deriver::len`] and [`Deriver::derive`]. + /// + /// [`Deriver::len`]: #method.len + /// [`Deriver::derive`]: #method.derive + pub fn derive_to_vec(&mut self) -> Result<Vec<u8>, ErrorStack> { + let len = self.len()?; + let mut buf = vec![0; len]; + let len = self.derive(&mut buf)?; + buf.truncate(len); + Ok(buf) + } +} + +#[cfg(test)] +mod test { + use super::*; + + use ec::{EcGroup, EcKey}; + use nid::Nid; + use pkey::PKey; + + #[test] + fn derive_without_peer() { + let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); + let ec_key = EcKey::generate(&group).unwrap(); + let pkey = PKey::from_ec_key(ec_key).unwrap(); + let mut deriver = Deriver::new(&pkey).unwrap(); + deriver.derive_to_vec().unwrap_err(); + } + + #[test] + fn test_ec_key_derive() { + let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); + let ec_key = EcKey::generate(&group).unwrap(); + let ec_key2 = EcKey::generate(&group).unwrap(); + let pkey = PKey::from_ec_key(ec_key).unwrap(); + let pkey2 = PKey::from_ec_key(ec_key2).unwrap(); + let mut deriver = Deriver::new(&pkey).unwrap(); + deriver.set_peer(&pkey2).unwrap(); + let shared = deriver.derive_to_vec().unwrap(); + assert!(!shared.is_empty()); + } +} diff --git a/openssl/src/dh.rs b/openssl/src/dh.rs index 35404b6c..2872f422 100644 --- a/openssl/src/dh.rs +++ b/openssl/src/dh.rs @@ -1,30 +1,34 @@ use error::ErrorStack; use ffi; -use foreign_types::ForeignTypeRef; +use foreign_types::{ForeignType, ForeignTypeRef}; use std::mem; use std::ptr; use {cvt, cvt_p}; use bn::BigNum; +use pkey::{HasParams, Params}; -foreign_type_and_impl_send_sync! { +generic_foreign_type_and_impl_send_sync! { type CType = ffi::DH; fn drop = ffi::DH_free; - pub struct Dh; + pub struct Dh<T>; - pub struct DhRef; + pub struct DhRef<T>; } -impl DhRef { +impl<T> DhRef<T> +where + T: HasParams, +{ to_pem!(ffi::PEM_write_bio_DHparams); to_der!(ffi::i2d_DHparams); } -impl Dh { - pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<Dh, ErrorStack> { +impl Dh<Params> { + pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<Dh<Params>, ErrorStack> { unsafe { - let dh = Dh(cvt_p(ffi::DH_new())?); + let dh = Dh::from_ptr(cvt_p(ffi::DH_new())?); cvt(compat::DH_set0_pqg( dh.0, p.as_ptr(), @@ -36,33 +40,33 @@ impl Dh { } } - from_pem!(Dh, ffi::PEM_read_bio_DHparams); - from_der!(Dh, ffi::d2i_DHparams); + from_pem!(Dh<Params>, ffi::PEM_read_bio_DHparams); + from_der!(Dh<Params>, ffi::d2i_DHparams); /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] - pub fn get_1024_160() -> Result<Dh, ErrorStack> { + pub fn get_1024_160() -> Result<Dh<Params>, ErrorStack> { unsafe { ffi::init(); - cvt_p(ffi::DH_get_1024_160()).map(Dh) + cvt_p(ffi::DH_get_1024_160()).map(|p| Dh::from_ptr(p)) } } /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] - pub fn get_2048_224() -> Result<Dh, ErrorStack> { + pub fn get_2048_224() -> Result<Dh<Params>, ErrorStack> { unsafe { ffi::init(); - cvt_p(ffi::DH_get_2048_224()).map(Dh) + cvt_p(ffi::DH_get_2048_224()).map(|p| Dh::from_ptr(p)) } } /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] - pub fn get_2048_256() -> Result<Dh, ErrorStack> { + pub fn get_2048_256() -> Result<Dh<Params>, ErrorStack> { unsafe { ffi::init(); - cvt_p(ffi::DH_get_2048_256()).map(Dh) + cvt_p(ffi::DH_get_2048_256()).map(|p| Dh::from_ptr(p)) } } } diff --git a/openssl/src/dsa.rs b/openssl/src/dsa.rs index 2c9f7de4..19ad2b6e 100644 --- a/openssl/src/dsa.rs +++ b/openssl/src/dsa.rs @@ -6,7 +6,7 @@ //! without the private key. use ffi; -use foreign_types::ForeignTypeRef; +use foreign_types::{ForeignType, ForeignTypeRef}; use libc::c_int; use std::fmt; use std::ptr; @@ -14,8 +14,9 @@ use std::ptr; use {cvt, cvt_p}; use bn::BigNumRef; use error::ErrorStack; +use pkey::{HasParams, HasPrivate, HasPublic, Private, Public}; -foreign_type_and_impl_send_sync! { +generic_foreign_type_and_impl_send_sync! { type CType = ffi::DSA; fn drop = ffi::DSA_free; @@ -40,7 +41,9 @@ foreign_type_and_impl_send_sync! { /// ``` /// use openssl::dsa::Dsa; /// use openssl::error::ErrorStack; - /// fn create_dsa() -> Result< Dsa, ErrorStack > { + /// use openssl::pkey::Private; + /// + /// fn create_dsa() -> Result<Dsa<Private>, ErrorStack> { /// let sign = Dsa::generate(2048)?; /// Ok(sign) /// } @@ -48,83 +51,68 @@ foreign_type_and_impl_send_sync! { /// # create_dsa(); /// # } /// ``` - pub struct Dsa; + pub struct Dsa<T>; /// Reference to [`Dsa`]. /// /// [`Dsa`]: struct.Dsa.html - pub struct DsaRef; + pub struct DsaRef<T>; } -impl DsaRef { +impl<T> DsaRef<T> +where + T: HasPrivate, +{ private_key_to_pem!(ffi::PEM_write_bio_DSAPrivateKey); - public_key_to_pem!(ffi::PEM_write_bio_DSA_PUBKEY); - private_key_to_der!(ffi::i2d_DSAPrivateKey); +} + +impl<T> DsaRef<T> +where + T: HasPublic, +{ + public_key_to_pem!(ffi::PEM_write_bio_DSA_PUBKEY); public_key_to_der!(ffi::i2d_DSAPublicKey); +} - /// Returns the maximum size of the signature output by `self` in bytes. Returns - /// None if the keys are uninitialized. +impl<T> DsaRef<T> +where + T: HasParams, +{ + /// Returns the maximum size of the signature output by `self` in bytes. /// /// OpenSSL documentation at [`DSA_size`] /// /// [`DSA_size`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_size.html pub fn size(&self) -> u32 { - unsafe { - assert!(self.q().is_some()); - ffi::DSA_size(self.as_ptr()) as u32 - } + unsafe { ffi::DSA_size(self.as_ptr()) as u32 } } /// Returns the DSA prime parameter of `self`. - pub fn p(&self) -> Option<&BigNumRef> { + pub fn p(&self) -> &BigNumRef { unsafe { let p = compat::pqg(self.as_ptr())[0]; - if p.is_null() { - None - } else { - Some(BigNumRef::from_ptr(p as *mut _)) - } + BigNumRef::from_ptr(p as *mut _) } } /// Returns the DSA sub-prime parameter of `self`. - pub fn q(&self) -> Option<&BigNumRef> { + pub fn q(&self) -> &BigNumRef { unsafe { let q = compat::pqg(self.as_ptr())[1]; - if q.is_null() { - None - } else { - Some(BigNumRef::from_ptr(q as *mut _)) - } + BigNumRef::from_ptr(q as *mut _) } } /// Returns the DSA base parameter of `self`. - pub fn g(&self) -> Option<&BigNumRef> { + pub fn g(&self) -> &BigNumRef { unsafe { let g = compat::pqg(self.as_ptr())[2]; - if g.is_null() { - None - } else { - Some(BigNumRef::from_ptr(g as *mut _)) - } + BigNumRef::from_ptr(g as *mut _) } } - - /// Returns whether the DSA includes a public key, used to confirm the authenticity - /// of the message. - pub fn has_public_key(&self) -> bool { - unsafe { !compat::keys(self.as_ptr())[0].is_null() } - } - - /// Returns whether the DSA includes a private key, used to prove the authenticity - /// of a message. - pub fn has_private_key(&self) -> bool { - unsafe { !compat::keys(self.as_ptr())[1].is_null() } - } } -impl Dsa { +impl Dsa<Private> { /// Generate a DSA key pair. /// /// Calls [`DSA_generate_parameters_ex`] to populate the `p`, `g`, and `q` values. @@ -134,10 +122,10 @@ impl Dsa { /// /// [`DSA_generate_parameters_ex`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_generate_parameters_ex.html /// [`DSA_generate_key`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_generate_key.html - pub fn generate(bits: u32) -> Result<Dsa, ErrorStack> { + pub fn generate(bits: u32) -> Result<Dsa<Private>, ErrorStack> { ffi::init(); unsafe { - let dsa = Dsa(cvt_p(ffi::DSA_new())?); + let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?); cvt(ffi::DSA_generate_parameters_ex( dsa.0, bits as c_int, @@ -152,13 +140,16 @@ impl Dsa { } } - private_key_from_pem!(Dsa, ffi::PEM_read_bio_DSAPrivateKey); - private_key_from_der!(Dsa, ffi::d2i_DSAPrivateKey); - public_key_from_pem!(Dsa, ffi::PEM_read_bio_DSA_PUBKEY); - public_key_from_der!(Dsa, ffi::d2i_DSAPublicKey); + private_key_from_pem!(Dsa<Private>, ffi::PEM_read_bio_DSAPrivateKey); + private_key_from_der!(Dsa<Private>, ffi::d2i_DSAPrivateKey); +} + +impl Dsa<Public> { + public_key_from_pem!(Dsa<Public>, ffi::PEM_read_bio_DSA_PUBKEY); + public_key_from_der!(Dsa<Public>, ffi::d2i_DSAPublicKey); } -impl fmt::Debug for Dsa { +impl<T> fmt::Debug for Dsa<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "DSA") } @@ -174,12 +165,6 @@ mod compat { ffi::DSA_get0_pqg(d, &mut p, &mut q, &mut g); [p, q, g] } - - pub unsafe fn keys(d: *const DSA) -> [*const BIGNUM; 2] { - let (mut pub_key, mut priv_key) = (ptr::null(), ptr::null()); - ffi::DSA_get0_key(d, &mut pub_key, &mut priv_key); - [pub_key, priv_key] - } } #[cfg(ossl10x)] @@ -189,10 +174,6 @@ mod compat { pub unsafe fn pqg(d: *const DSA) -> [*const BIGNUM; 3] { [(*d).p, (*d).q, (*d).g] } - - pub unsafe fn keys(d: *const DSA) -> [*const BIGNUM; 2] { - [(*d).pub_key, (*d).priv_key] - } } #[cfg(test)] diff --git a/openssl/src/ec.rs b/openssl/src/ec.rs index 524de79d..b85eb7f7 100644 --- a/openssl/src/ec.rs +++ b/openssl/src/ec.rs @@ -34,13 +34,13 @@ use ffi; use foreign_types::{ForeignType, ForeignTypeRef}; use std::ptr; -use std::mem; use libc::c_int; use {cvt, cvt_n, cvt_p, init}; use bn::{BigNumContextRef, BigNumRef}; use error::ErrorStack; use nid::Nid; +use pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public}; /// Compressed or Uncompressed conversion /// @@ -501,7 +501,7 @@ impl EcPoint { } } -foreign_type_and_impl_send_sync! { +generic_foreign_type_and_impl_send_sync! { type CType = ffi::EC_KEY; fn drop = ffi::EC_KEY_free; @@ -510,62 +510,64 @@ foreign_type_and_impl_send_sync! { /// OpenSSL documentation at [`EC_KEY_new`] /// /// [`EC_KEY_new`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new.html - pub struct EcKey; + pub struct EcKey<T>; + /// Reference to [`EcKey`] /// /// [`EcKey`]: struct.EcKey.html - pub struct EcKeyRef; + pub struct EcKeyRef<T>; } -impl EcKeyRef { +impl<T> EcKeyRef<T> +where + T: HasPrivate, +{ private_key_to_pem!(ffi::PEM_write_bio_ECPrivateKey); private_key_to_der!(ffi::i2d_ECPrivateKey); - /// Return [`EcGroup`] of the `EcKey` + /// Return [`EcPoint`] associated with the private key /// - /// OpenSSL documentation at [`EC_KEY_get0_group`] + /// OpenSSL documentation at [`EC_KEY_get0_private_key`] /// - /// [`EC_KEY_get0_group`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_group.html - pub fn group(&self) -> Option<&EcGroupRef> { + /// [`EC_KEY_get0_private_key`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_private_key.html + pub fn private_key(&self) -> &BigNumRef { unsafe { - let ptr = ffi::EC_KEY_get0_group(self.as_ptr()); - if ptr.is_null() { - None - } else { - Some(EcGroupRef::from_ptr(ptr as *mut _)) - } + let ptr = ffi::EC_KEY_get0_private_key(self.as_ptr()); + BigNumRef::from_ptr(ptr as *mut _) } } +} - /// Return [`EcPoint`] associated with the public key +impl<T> EcKeyRef<T> +where + T: HasPublic, +{ + /// Returns the public key. /// /// OpenSSL documentation at [`EC_KEY_get0_pubic_key`] /// /// [`EC_KEY_get0_pubic_key`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_public_key.html - pub fn public_key(&self) -> Option<&EcPointRef> { + pub fn public_key(&self) -> &EcPointRef { unsafe { let ptr = ffi::EC_KEY_get0_public_key(self.as_ptr()); - if ptr.is_null() { - None - } else { - Some(EcPointRef::from_ptr(ptr as *mut _)) - } + EcPointRef::from_ptr(ptr as *mut _) } } +} - /// Return [`EcPoint`] associated with the private key +impl<T> EcKeyRef<T> +where + T: HasParams, +{ + /// Return [`EcGroup`] of the `EcKey` /// - /// OpenSSL documentation at [`EC_KEY_get0_private_key`] + /// OpenSSL documentation at [`EC_KEY_get0_group`] /// - /// [`EC_KEY_get0_private_key`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_private_key.html - pub fn private_key(&self) -> Option<&BigNumRef> { + /// [`EC_KEY_get0_group`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_group.html + pub fn group(&self) -> &EcGroupRef { unsafe { - let ptr = ffi::EC_KEY_get0_private_key(self.as_ptr()); - if ptr.is_null() { - None - } else { - Some(BigNumRef::from_ptr(ptr as *mut _)) - } + let ptr = ffi::EC_KEY_get0_group(self.as_ptr()); + EcGroupRef::from_ptr(ptr as *mut _) } } @@ -577,14 +579,21 @@ impl EcKeyRef { pub fn check_key(&self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EC_KEY_check_key(self.as_ptr())).map(|_| ()) } } +} + +impl<T> ToOwned for EcKeyRef<T> { + type Owned = EcKey<T>; - /// Create a copy of the `EcKey` to allow modification - pub fn to_owned(&self) -> Result<EcKey, ErrorStack> { - unsafe { cvt_p(ffi::EC_KEY_dup(self.as_ptr())).map(EcKey) } + fn to_owned(&self) -> EcKey<T> { + unsafe { + let r = ffi::EC_KEY_up_ref(self.as_ptr()); + assert!(r == 1); + EcKey::from_ptr(self.as_ptr()) + } } } -impl EcKey { +impl EcKey<Params> { /// Constructs an `EcKey` corresponding to a known curve. /// /// It will not have an associated public or private key. This kind of key is primarily useful @@ -593,13 +602,30 @@ impl EcKey { /// OpenSSL documenation at [`EC_KEY_new_by_curve_name`] /// /// [`EC_KEY_new_by_curve_name`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new_by_curve_name.html - pub fn from_curve_name(nid: Nid) -> Result<EcKey, ErrorStack> { + pub fn from_curve_name(nid: Nid) -> Result<EcKey<Params>, ErrorStack> { unsafe { init(); - cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(EcKey) + cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(|p| EcKey::from_ptr(p)) + } + } + + /// Constructs an `EcKey` corresponding to a curve. + /// + /// This corresponds to [`EC_KEY_set_group`]. + /// + /// [`EC_KEY_set_group`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new.html + pub fn from_group(group: &EcGroupRef) -> Result<EcKey<Params>, ErrorStack> { + unsafe { + cvt_p(ffi::EC_KEY_new()) + .map(|p| EcKey::from_ptr(p)) + .and_then(|key| { + cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key) + }) } } +} +impl EcKey<Public> { /// Constructs an `EcKey` from the specified group with the associated `EcPoint`, public_key. /// /// This will only have the associated public_key. @@ -624,104 +650,67 @@ impl EcKey { pub fn from_public_key( group: &EcGroupRef, public_key: &EcPointRef, - ) -> Result<EcKey, ErrorStack> { - let mut builder = EcKeyBuilder::new()?; - builder.set_group(group)?; - builder.set_public_key(public_key)?; - Ok(builder.build()) - } - - /// Generates a new public/private key pair on the specified curve. - pub fn generate(group: &EcGroupRef) -> Result<EcKey, ErrorStack> { - let mut builder = EcKeyBuilder::new()?; - builder.set_group(group)?; - builder.generate_key()?; - Ok(builder.build()) - } - - private_key_from_pem!(EcKey, ffi::PEM_read_bio_ECPrivateKey); - private_key_from_der!(EcKey, ffi::d2i_ECPrivateKey); -} - -foreign_type_and_impl_send_sync! { - type CType = ffi::EC_KEY; - fn drop = ffi::EC_KEY_free; - - /// Builder pattern for key generation - /// - /// Returns a `EcKeyBuilder` to be consumed by `build` - pub struct EcKeyBuilder; - /// Reference to [`EcKeyBuilder`] - /// - /// [`EcKeyBuilder`]: struct.EcKeyBuilder.html - pub struct EcKeyBuilderRef; -} - -impl EcKeyBuilder { - /// Creates an empty `EcKeyBuilder` to be chained with additonal methods - pub fn new() -> Result<EcKeyBuilder, ErrorStack> { + ) -> Result<EcKey<Public>, ErrorStack> { unsafe { - init(); - cvt_p(ffi::EC_KEY_new()).map(EcKeyBuilder) + cvt_p(ffi::EC_KEY_new()) + .map(|p| EcKey::from_ptr(p)) + .and_then(|key| { + cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key) + }) + .and_then(|key| { + cvt(ffi::EC_KEY_set_public_key( + key.as_ptr(), + public_key.as_ptr(), + )).map(|_| key) + }) } } - /// Consume the `EcKeyBuilder` and return [`EcKey`] - /// - /// [`EcKey`]: struct.EcKey.html - pub fn build(self) -> EcKey { + /// Constructs a public key from its affine coordinates. + pub fn from_public_key_affine_coordinates( + group: &EcGroupRef, + x: &BigNumRef, + y: &BigNumRef, + ) -> Result<EcKey<Public>, ErrorStack> { unsafe { - let key = EcKey::from_ptr(self.as_ptr()); - mem::forget(self); - key + cvt_p(ffi::EC_KEY_new()) + .map(|p| EcKey::from_ptr(p)) + .and_then(|key| { + cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key) + }) + .and_then(|key| { + cvt(ffi::EC_KEY_set_public_key_affine_coordinates( + key.as_ptr(), + x.as_ptr(), + y.as_ptr(), + )).map(|_| key) + }) } } } -impl EcKeyBuilderRef { - /// Set the [`EcGroup`] explicitly - /// - /// [`EcGroup`]: struct.EcGroup.html - pub fn set_group(&mut self, group: &EcGroupRef) -> Result<&mut EcKeyBuilderRef, ErrorStack> { - unsafe { cvt(ffi::EC_KEY_set_group(self.as_ptr(), group.as_ptr())).map(|_| self) } - } - - /// Set public key to given `EcPoint` - pub fn set_public_key( - &mut self, - public_key: &EcPointRef, - ) -> Result<&mut EcKeyBuilderRef, ErrorStack> { +impl EcKey<Private> { + /// Generates a new public/private key pair on the specified curve. + pub fn generate(group: &EcGroupRef) -> Result<EcKey<Private>, ErrorStack> { unsafe { - cvt(ffi::EC_KEY_set_public_key( - self.as_ptr(), - public_key.as_ptr(), - )).map(|_| self) + cvt_p(ffi::EC_KEY_new()) + .map(|p| EcKey::from_ptr(p)) + .and_then(|key| { + cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key) + }) + .and_then(|key| { + cvt(ffi::EC_KEY_generate_key(key.as_ptr())).map(|_| key) + }) } } - /// Generate public and private keys. - pub fn generate_key(&mut self) -> Result<&mut EcKeyBuilderRef, ErrorStack> { - unsafe { cvt(ffi::EC_KEY_generate_key(self.as_ptr())).map(|_| self) } - } - - /// Sets the public key based on affine coordinates. - pub fn set_public_key_affine_coordinates( - &mut self, - x: &BigNumRef, - y: &BigNumRef, - ) -> Result<&mut EcKeyBuilderRef, ErrorStack> { - unsafe { - cvt(ffi::EC_KEY_set_public_key_affine_coordinates( - self.as_ptr(), - x.as_ptr(), - y.as_ptr(), - )).map(|_| self) - } - } + private_key_from_pem!(EcKey<Private>, ffi::PEM_read_bio_ECPrivateKey); + private_key_from_der!(EcKey<Private>, ffi::d2i_ECPrivateKey); +} - /// Sets the private key. - pub fn set_private_key(&mut self, key: &BigNumRef) -> Result<&mut EcKeyBuilderRef, ErrorStack> { - unsafe { cvt(ffi::EC_KEY_set_private_key(self.as_ptr(), key.as_ptr())).map(|_| self) } +impl<T> Clone for EcKey<T> { + fn clone(&self) -> EcKey<T> { + (**self).to_owned() } } @@ -741,15 +730,13 @@ mod test { fn generate() { let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let key = EcKey::generate(&group).unwrap(); - key.public_key().unwrap(); - key.private_key().unwrap(); } #[test] fn dup() { let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let key = EcKey::generate(&group).unwrap(); - key.to_owned().unwrap(); + key.clone(); } #[test] @@ -762,7 +749,7 @@ mod test { fn point_bytes() { let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let key = EcKey::generate(&group).unwrap(); - let point = key.public_key().unwrap(); + let point = key.public_key(); let mut ctx = BigNumContext::new().unwrap(); let bytes = point .to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx) @@ -778,13 +765,9 @@ mod test { let mut ctx = BigNumContext::new().unwrap(); let mut public_key = EcPoint::new(&group).unwrap(); public_key - .mul_generator(&group, key.private_key().unwrap(), &mut ctx) + .mul_generator(&group, key.private_key(), &mut ctx) .unwrap(); - assert!( - public_key - .eq(&group, key.public_key().unwrap(), &mut ctx) - .unwrap() - ); + assert!(public_key.eq(&group, key.public_key(), &mut ctx).unwrap()); } #[test] @@ -793,7 +776,6 @@ mod test { let key = EcKey::generate(&group).unwrap(); let mut ctx = BigNumContext::new().unwrap(); let bytes = key.public_key() - .unwrap() .to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx) .unwrap(); @@ -801,8 +783,6 @@ mod test { let public_key = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap(); let ec_key = EcKey::from_public_key(&group, &public_key).unwrap(); assert!(ec_key.check_key().is_ok()); - assert!(ec_key.public_key().is_some()); - assert!(ec_key.private_key().is_none()); } #[test] @@ -818,32 +798,8 @@ mod test { let xbn = BigNum::from_slice(&x).unwrap(); let ybn = BigNum::from_slice(&y).unwrap(); - let mut builder = EcKeyBuilder::new().unwrap(); - builder.set_group(&group).unwrap(); - builder - .set_public_key_affine_coordinates(&xbn, &ybn) - .unwrap(); - - let ec_key = builder.build(); + let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap(); assert!(ec_key.check_key().is_ok()); - assert!(ec_key.public_key().is_some()); - } - - #[test] - fn set_private_key() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let d = BASE64URL_NOPAD - .decode("870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE".as_bytes()) - .unwrap(); - - let dbn = BigNum::from_slice(&d).unwrap(); - - let mut builder = EcKeyBuilder::new().unwrap(); - builder.set_group(&group).unwrap(); - builder.set_private_key(&dbn).unwrap(); - - let ec_key = builder.build(); - assert!(ec_key.private_key().is_some()); } #[test] @@ -859,18 +815,12 @@ mod test { let xbn = BigNum::from_slice(&x).unwrap(); let ybn = BigNum::from_slice(&y).unwrap(); - let mut builder = EcKeyBuilder::new().unwrap(); - builder.set_group(&group).unwrap(); - builder - .set_public_key_affine_coordinates(&xbn, &ybn) - .unwrap(); - - let ec_key = builder.build(); + let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap(); let mut xbn2 = BigNum::new().unwrap(); let mut ybn2 = BigNum::new().unwrap(); let mut ctx = BigNumContext::new().unwrap(); - let ec_key_pk = ec_key.public_key().unwrap(); + let ec_key_pk = ec_key.public_key(); ec_key_pk .affine_coordinates_gfp(&group, &mut xbn2, &mut ybn2, &mut ctx) .unwrap(); diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 84c49d19..2302b7a4 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -35,6 +35,7 @@ pub mod bn; #[cfg(not(libressl))] pub mod cms; pub mod conf; +pub mod derive; pub mod dh; pub mod dsa; pub mod ec; diff --git a/openssl/src/macros.rs b/openssl/src/macros.rs index 721f4b0c..a2474922 100644 --- a/openssl/src/macros.rs +++ b/openssl/src/macros.rs @@ -1,6 +1,6 @@ macro_rules! private_key_from_pem { - ($t:ident, $f:path) => { + ($t:ty, $f:path) => { from_pem_inner!(/// Deserializes a PEM-formatted private key. private_key_from_pem, $t, $f); @@ -21,7 +21,7 @@ macro_rules! private_key_from_pem { ptr::null_mut(), None, passphrase.as_ptr() as *const _ as *mut _)) - .map($t) + .map(|p| ::foreign_types::ForeignType::from_ptr(p)) } } @@ -43,7 +43,7 @@ macro_rules! private_key_from_pem { ptr::null_mut(), Some(::util::invoke_passwd_cb::<F>), &mut cb as *mut _ as *mut _)) - .map($t) + .map(|p| ::foreign_types::ForeignType::from_ptr(p)) } } } @@ -153,69 +153,68 @@ macro_rules! public_key_to_der { } macro_rules! from_der_inner { - (#[$m:meta] $n:ident, $t:ident, $f:path) => { + (#[$m:meta] $n:ident, $t:ty, $f:path) => { #[$m] pub fn $n(der: &[u8]) -> Result<$t, ::error::ErrorStack> { unsafe { ::ffi::init(); let len = ::std::cmp::min(der.len(), ::libc::c_long::max_value() as usize) as ::libc::c_long; ::cvt_p($f(::std::ptr::null_mut(), &mut der.as_ptr(), len)) - .map($t) + .map(|p| ::foreign_types::ForeignType::from_ptr(p)) } } } } macro_rules! from_der { - ($t:ident, $f:path) => { + ($t:ty, $f:path) => { from_der_inner!(/// Deserializes a value from DER-formatted data. from_der, $t, $f); } } macro_rules! private_key_from_der { - ($t:ident, $f:path) => { + ($t:ty, $f:path) => { from_der_inner!(/// Deserializes a private key from DER-formatted data. private_key_from_der, $t, $f); } } macro_rules! public_key_from_der { - ($t:ident, $f:path) => { + ($t:ty, $f:path) => { from_der_inner!(/// Deserializes a public key from DER-formatted data. public_key_from_der, $t, $f); } } macro_rules! from_pem_inner { - (#[$m:meta] $n:ident, $t:ident, $f:path) => { + (#[$m:meta] $n:ident, $t:ty, $f:path) => { #[$m] pub fn $n(pem: &[u8]) -> Result<$t, ::error::ErrorStack> { unsafe { ::init(); let bio = try!(::bio::MemBioSlice::new(pem)); cvt_p($f(bio.as_ptr(), ::std::ptr::null_mut(), None, ::std::ptr::null_mut())) - .map($t) + .map(|p| ::foreign_types::ForeignType::from_ptr(p)) } } } } macro_rules! public_key_from_pem { - ($t:ident, $f:path) => { + ($t:ty, $f:path) => { from_pem_inner!(/// Deserializes a public key from PEM-formatted data. public_key_from_pem, $t, $f); } } macro_rules! from_pem { - ($t:ident, $f:path) => { + ($t:ty, $f:path) => { from_pem_inner!(/// Deserializes a value from PEM-formatted data. from_pem, $t, $f); } } - macro_rules! foreign_type_and_impl_send_sync { ( $(#[$impl_attr:meta])* @@ -246,3 +245,110 @@ macro_rules! foreign_type_and_impl_send_sync { unsafe impl Sync for $borrowed{} }; } + +macro_rules! generic_foreign_type_and_impl_send_sync { + ( + $(#[$impl_attr:meta])* + type CType = $ctype:ty; + fn drop = $drop:expr; + $(fn clone = $clone:expr;)* + + $(#[$owned_attr:meta])* + pub struct $owned:ident<T>; + $(#[$borrowed_attr:meta])* + pub struct $borrowed:ident<T>; + ) => { + $(#[$owned_attr])* + pub struct $owned<T>(*mut $ctype, ::std::marker::PhantomData<T>); + + $(#[$impl_attr])* + impl<T> ::foreign_types::ForeignType for $owned<T> { + type CType = $ctype; + type Ref = $borrowed<T>; + + #[inline] + unsafe fn from_ptr(ptr: *mut $ctype) -> $owned<T> { + $owned(ptr, ::std::marker::PhantomData) + } + + #[inline] + fn as_ptr(&self) -> *mut $ctype { + self.0 + } + } + + impl<T> Drop for $owned<T> { + #[inline] + fn drop(&mut self) { + unsafe { $drop(self.0) } + } + } + + $( + impl<T> Clone for $owned<T> { + #[inline] + fn clone(&self) -> $owned<T> { + unsafe { + let handle: *mut $ctype = $clone(self.0); + ::foreign_types::ForeignType::from_ptr(handle) + } + } + } + + impl<T> ::std::borrow::ToOwned for $borrowed<T> { + type Owned = $owned<T>; + #[inline] + fn to_owned(&self) -> $owned<T> { + unsafe { + let handle: *mut $ctype = + $clone(::foreign_types::ForeignTypeRef::as_ptr(self)); + $crate::ForeignType::from_ptr(handle) + } + } + } + )* + + impl<T> ::std::ops::Deref for $owned<T> { + type Target = $borrowed<T>; + + #[inline] + fn deref(&self) -> &$borrowed<T> { + unsafe { ::foreign_types::ForeignTypeRef::from_ptr(self.0) } + } + } + + impl<T> ::std::ops::DerefMut for $owned<T> { + #[inline] + fn deref_mut(&mut self) -> &mut $borrowed<T> { + unsafe { ::foreign_types::ForeignTypeRef::from_ptr_mut(self.0) } + } + } + + impl<T> ::std::borrow::Borrow<$borrowed<T>> for $owned<T> { + #[inline] + fn borrow(&self) -> &$borrowed<T> { + &**self + } + } + + impl<T> ::std::convert::AsRef<$borrowed<T>> for $owned<T> { + #[inline] + fn as_ref(&self) -> &$borrowed<T> { + &**self + } + } + + $(#[$borrowed_attr])* + pub struct $borrowed<T>(::foreign_types::Opaque, ::std::marker::PhantomData<T>); + + $(#[$impl_attr])* + impl<T> ::foreign_types::ForeignTypeRef for $borrowed<T> { + type CType = $ctype; + } + + unsafe impl<T> Send for $owned<T>{} + unsafe impl<T> Send for $borrowed<T>{} + unsafe impl<T> Sync for $owned<T>{} + unsafe impl<T> Sync for $borrowed<T>{} + }; +} diff --git a/openssl/src/pkcs12.rs b/openssl/src/pkcs12.rs index 663e8700..ff96df2a 100644 --- a/openssl/src/pkcs12.rs +++ b/openssl/src/pkcs12.rs @@ -7,7 +7,7 @@ use std::ptr; use std::ffi::CString; use {cvt, cvt_p}; -use pkey::{PKey, PKeyRef}; +use pkey::{HasPrivate, PKey, PKeyRef, Private}; use error::ErrorStack; use x509::{X509, X509Ref}; use stack::Stack; @@ -25,9 +25,9 @@ impl Pkcs12Ref { to_der!(ffi::i2d_PKCS12); /// Extracts the contents of the `Pkcs12`. - pub fn parse(&self, pass: &[u8]) -> Result<ParsedPkcs12, ErrorStack> { + pub fn parse(&self, pass: &str) -> Result<ParsedPkcs12, ErrorStack> { unsafe { - let pass = CString::new(pass).unwrap(); + let pass = CString::new(pass.as_bytes()).unwrap(); let mut pkey = ptr::null_mut(); let mut cert = ptr::null_mut(); @@ -84,7 +84,7 @@ impl Pkcs12 { } pub struct ParsedPkcs12 { - pub pkey: PKey, + pub pkey: PKey<Private>, pub cert: X509, pub chain: Option<Stack<X509>>, } @@ -140,13 +140,16 @@ impl Pkcs12Builder { /// * `friendly_name` - user defined name for the certificate /// * `pkey` - key to store /// * `cert` - certificate to store - pub fn build( + pub fn build<T>( self, password: &str, friendly_name: &str, - pkey: &PKeyRef, + pkey: &PKeyRef<T>, cert: &X509Ref, - ) -> Result<Pkcs12, ErrorStack> { + ) -> Result<Pkcs12, ErrorStack> + where + T: HasPrivate, + { unsafe { let pass = CString::new(password).unwrap(); let friendly_name = CString::new(friendly_name).unwrap(); @@ -198,7 +201,7 @@ mod test { fn parse() { let der = include_bytes!("../test/identity.p12"); let pkcs12 = Pkcs12::from_der(der).unwrap(); - let parsed = pkcs12.parse("mypass".as_bytes()).unwrap(); + let parsed = pkcs12.parse("mypass").unwrap(); assert_eq!( parsed @@ -224,7 +227,7 @@ mod test { fn parse_empty_chain() { let der = include_bytes!("../test/keystore-empty-chain.p12"); let pkcs12 = Pkcs12::from_der(der).unwrap(); - let parsed = pkcs12.parse("cassandra".as_bytes()).unwrap(); + let parsed = pkcs12.parse("cassandra").unwrap(); assert!(parsed.chain.is_none()); } @@ -263,7 +266,7 @@ mod test { let der = pkcs12.to_der().unwrap(); let pkcs12 = Pkcs12::from_der(&der).unwrap(); - let parsed = pkcs12.parse("mypass".as_bytes()).unwrap(); + let parsed = pkcs12.parse("mypass").unwrap(); assert_eq!( parsed.cert.fingerprint(MessageDigest::sha1()).unwrap(), diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index 68e4696d..2120313c 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -1,4 +1,4 @@ -use libc::{c_int, size_t}; +use libc::c_int; use std::ptr; use std::mem; use std::ffi::CString; @@ -10,21 +10,57 @@ use bio::MemBioSlice; use dh::Dh; use dsa::Dsa; use ec::EcKey; -use rsa::{Padding, Rsa}; +use rsa::Rsa; use error::ErrorStack; use util::{invoke_passwd_cb, CallbackState}; -foreign_type_and_impl_send_sync! { +/// A tag type indicating that a key only has parameters. +pub enum Params {} + +/// A tag type indicating that a key only has public components. +pub enum Public {} + +/// A tag type indicating that a key has private components. +pub enum Private {} + +/// A trait indicating that a key has parameters. +pub unsafe trait HasParams {} + +unsafe impl HasParams for Params {} + +unsafe impl<T> HasParams for T +where + T: HasPublic, +{ +} + +/// A trait indicating that a key has public components. +pub unsafe trait HasPublic {} + +unsafe impl HasPublic for Public {} + +unsafe impl<T> HasPublic for T +where + T: HasPrivate, +{ +} + +/// A trait indicating that a key has private components. +pub unsafe trait HasPrivate {} + +unsafe impl HasPrivate for Private {} + +generic_foreign_type_and_impl_send_sync! { type CType = ffi::EVP_PKEY; fn drop = ffi::EVP_PKEY_free; - pub struct PKey; - pub struct PKeyRef; + pub struct PKey<T>; + pub struct PKeyRef<T>; } -impl PKeyRef { +impl<T> PKeyRef<T> { /// Returns a copy of the internal RSA key. - pub fn rsa(&self) -> Result<Rsa, ErrorStack> { + pub fn rsa(&self) -> Result<Rsa<T>, ErrorStack> { unsafe { let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?; Ok(Rsa::from_ptr(rsa)) @@ -32,7 +68,7 @@ impl PKeyRef { } /// Returns a copy of the internal DSA key. - pub fn dsa(&self) -> Result<Dsa, ErrorStack> { + pub fn dsa(&self) -> Result<Dsa<T>, ErrorStack> { unsafe { let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?; Ok(Dsa::from_ptr(dsa)) @@ -40,7 +76,7 @@ impl PKeyRef { } /// Returns a copy of the internal DH key. - pub fn dh(&self) -> Result<Dh, ErrorStack> { + pub fn dh(&self) -> Result<Dh<T>, ErrorStack> { unsafe { let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?; Ok(Dh::from_ptr(dh)) @@ -48,17 +84,19 @@ impl PKeyRef { } /// Returns a copy of the internal elliptic curve key. - pub fn ec_key(&self) -> Result<EcKey, ErrorStack> { + pub fn ec_key(&self) -> Result<EcKey<T>, ErrorStack> { unsafe { let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?; Ok(EcKey::from_ptr(ec_key)) } } +} +impl<T> PKeyRef<T> +where + T: HasPublic, +{ public_key_to_pem!(ffi::PEM_write_bio_PUBKEY); - private_key_to_pem!(ffi::PEM_write_bio_PKCS8PrivateKey); - - private_key_to_der!(ffi::i2d_PrivateKey); public_key_to_der!(ffi::i2d_PUBKEY); /// Returns the size of the key. @@ -70,17 +108,28 @@ impl PKeyRef { } /// Compares the public component of this key with another. - pub fn public_eq(&self, other: &PKeyRef) -> bool { + pub fn public_eq<U>(&self, other: &PKeyRef<U>) -> bool + where + U: HasPublic, + { unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 } } } -impl PKey { +impl<T> PKeyRef<T> +where + T: HasPrivate, +{ + private_key_to_pem!(ffi::PEM_write_bio_PKCS8PrivateKey); + private_key_to_der!(ffi::i2d_PrivateKey); +} + +impl<T> PKey<T> { /// Creates a new `PKey` containing an RSA key. - pub fn from_rsa(rsa: Rsa) -> Result<PKey, ErrorStack> { + pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> { unsafe { let evp = cvt_p(ffi::EVP_PKEY_new())?; - let pkey = PKey(evp); + let pkey = PKey::from_ptr(evp); cvt(ffi::EVP_PKEY_assign( pkey.0, ffi::EVP_PKEY_RSA, @@ -92,10 +141,10 @@ impl PKey { } /// Creates a new `PKey` containing a DSA key. - pub fn from_dsa(dsa: Dsa) -> Result<PKey, ErrorStack> { + pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> { unsafe { let evp = cvt_p(ffi::EVP_PKEY_new())?; - let pkey = PKey(evp); + let pkey = PKey::from_ptr(evp); cvt(ffi::EVP_PKEY_assign( pkey.0, ffi::EVP_PKEY_DSA, @@ -107,10 +156,10 @@ impl PKey { } /// Creates a new `PKey` containing a Diffie-Hellman key. - pub fn from_dh(dh: Dh) -> Result<PKey, ErrorStack> { + pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> { unsafe { let evp = cvt_p(ffi::EVP_PKEY_new())?; - let pkey = PKey(evp); + let pkey = PKey::from_ptr(evp); cvt(ffi::EVP_PKEY_assign( pkey.0, ffi::EVP_PKEY_DH, @@ -122,10 +171,10 @@ impl PKey { } /// Creates a new `PKey` containing an elliptic curve key. - pub fn from_ec_key(ec_key: EcKey) -> Result<PKey, ErrorStack> { + pub fn from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> { unsafe { let evp = cvt_p(ffi::EVP_PKEY_new())?; - let pkey = PKey(evp); + let pkey = PKey::from_ptr(evp); cvt(ffi::EVP_PKEY_assign( pkey.0, ffi::EVP_PKEY_EC, @@ -135,12 +184,15 @@ impl PKey { Ok(pkey) } } +} +impl PKey<Private> { /// Creates a new `PKey` containing an HMAC key. /// /// # Note + /// /// To compute HMAC values, use the `sign` module. - pub fn hmac(key: &[u8]) -> Result<PKey, ErrorStack> { + pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> { unsafe { assert!(key.len() <= c_int::max_value() as usize); let key = cvt_p(ffi::EVP_PKEY_new_mac_key( @@ -149,21 +201,22 @@ impl PKey { key.as_ptr() as *const _, key.len() as c_int, ))?; - Ok(PKey(key)) + Ok(PKey::from_ptr(key)) } } - private_key_from_pem!(PKey, ffi::PEM_read_bio_PrivateKey); - public_key_from_pem!(PKey, ffi::PEM_read_bio_PUBKEY); - public_key_from_der!(PKey, ffi::d2i_PUBKEY); - private_key_from_der!(PKey, ffi::d2i_AutoPrivateKey); + private_key_from_pem!(PKey<Private>, ffi::PEM_read_bio_PrivateKey); + private_key_from_der!(PKey<Public>, ffi::d2i_AutoPrivateKey); /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password /// if the key is encrpyted. /// /// The callback should copy the password into the provided buffer and return the number of /// bytes written. - pub fn private_key_from_pkcs8_callback<F>(der: &[u8], callback: F) -> Result<PKey, ErrorStack> + pub fn private_key_from_pkcs8_callback<F>( + der: &[u8], + callback: F, + ) -> Result<PKey<Private>, ErrorStack> where F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>, { @@ -176,7 +229,7 @@ impl PKey { ptr::null_mut(), Some(invoke_passwd_cb::<F>), &mut cb as *mut _ as *mut _, - )).map(PKey) + )).map(|p| PKey::from_ptr(p)) } } @@ -189,7 +242,7 @@ impl PKey { pub fn private_key_from_pkcs8_passphrase( der: &[u8], passphrase: &[u8], - ) -> Result<PKey, ErrorStack> { + ) -> Result<PKey<Private>, ErrorStack> { unsafe { ffi::init(); let bio = MemBioSlice::new(der)?; @@ -199,81 +252,14 @@ impl PKey { ptr::null_mut(), None, passphrase.as_ptr() as *const _ as *mut _, - )).map(PKey) + )).map(|p| PKey::from_ptr(p)) } } } -foreign_type_and_impl_send_sync! { - type CType = ffi::EVP_PKEY_CTX; - fn drop = ffi::EVP_PKEY_CTX_free; - - pub struct PKeyCtx; - pub struct PKeyCtxRef; -} - -impl PKeyCtx { - pub fn from_pkey(pkey: &PKeyRef) -> Result<PKeyCtx, ErrorStack> { - unsafe { - let evp = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?; - Ok(PKeyCtx(evp)) - } - } -} - -impl PKeyCtxRef { - pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_CTX_set_rsa_padding( - self.as_ptr(), - pad.as_raw(), - ))?; - } - Ok(()) - } - - pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { - let mut pad: c_int = 0; - unsafe { - cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?; - }; - Ok(Padding::from_raw(pad)) - } - - pub fn derive_init(&mut self) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?; - } - Ok(()) - } - - pub fn derive_set_peer(&mut self, peer: &PKeyRef) -> Result<(), ErrorStack> { - unsafe { - cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), peer.as_ptr()))?; - } - Ok(()) - } - - pub fn derive(&mut self) -> Result<Vec<u8>, ErrorStack> { - let mut len: size_t = 0; - unsafe { - cvt(ffi::EVP_PKEY_derive( - self.as_ptr(), - ptr::null_mut(), - &mut len, - ))?; - } - - let mut key = vec![0u8; len]; - unsafe { - cvt(ffi::EVP_PKEY_derive( - self.as_ptr(), - key.as_mut_ptr(), - &mut len, - ))?; - } - Ok(key) - } +impl PKey<Public> { + public_key_from_pem!(PKey<Public>, ffi::PEM_read_bio_PUBKEY); + public_key_from_der!(PKey<Public>, ffi::d2i_PUBKEY); } #[cfg(test)] @@ -281,7 +267,7 @@ mod tests { use symm::Cipher; use dh::Dh; use dsa::Dsa; - use ec::{EcGroup, EcKey}; + use ec::EcKey; use rsa::Rsa; use nid::Nid; @@ -385,18 +371,4 @@ mod tests { pkey.ec_key().unwrap(); assert!(pkey.rsa().is_err()); } - - #[test] - fn test_ec_key_derive() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let ec_key = EcKey::generate(&group).unwrap(); - let ec_key2 = EcKey::generate(&group).unwrap(); - let pkey = PKey::from_ec_key(ec_key).unwrap(); - let pkey2 = PKey::from_ec_key(ec_key2).unwrap(); - let mut pkey_ctx = PKeyCtx::from_pkey(&pkey).unwrap(); - pkey_ctx.derive_init().unwrap(); - pkey_ctx.derive_set_peer(&pkey2).unwrap(); - let shared = pkey_ctx.derive().unwrap(); - assert!(!shared.is_empty()); - } } diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs index 6899fb10..21dd318a 100644 --- a/openssl/src/rsa.rs +++ b/openssl/src/rsa.rs @@ -3,11 +3,12 @@ use std::fmt; use std::ptr; use std::mem; use libc::c_int; -use foreign_types::ForeignTypeRef; +use foreign_types::{ForeignType, ForeignTypeRef}; use {cvt, cvt_n, cvt_p}; use bn::{BigNum, BigNumRef}; use error::ErrorStack; +use pkey::{HasPrivate, HasPublic, Private, Public}; /// Type of encryption padding to use. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -27,34 +28,21 @@ impl Padding { pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING); } -foreign_type_and_impl_send_sync! { +generic_foreign_type_and_impl_send_sync! { type CType = ffi::RSA; fn drop = ffi::RSA_free; - pub struct Rsa; - pub struct RsaRef; + pub struct Rsa<T>; + pub struct RsaRef<T>; } -impl RsaRef { +impl<T> RsaRef<T> +where + T: HasPrivate, +{ // FIXME these need to specify output format private_key_to_pem!(ffi::PEM_write_bio_RSAPrivateKey); - public_key_to_pem!(ffi::PEM_write_bio_RSA_PUBKEY); - private_key_to_der!(ffi::i2d_RSAPrivateKey); - public_key_to_der!(ffi::i2d_RSA_PUBKEY); - - to_der_inner!( - /// Serializes the public key to DER-encoded PKCS#1. - public_key_to_der_pkcs1, - ffi::i2d_RSAPublicKey - ); - - pub fn size(&self) -> u32 { - unsafe { - assert!(self.n().is_some()); - ffi::RSA_size(self.as_ptr()) as u32 - } - } /// Decrypts data using the private key, returning the number of decrypted bytes. /// @@ -68,7 +56,6 @@ impl RsaRef { to: &mut [u8], padding: Padding, ) -> Result<usize, ErrorStack> { - assert!(self.d().is_some(), "private components missing"); assert!(from.len() <= i32::max_value() as usize); assert!(to.len() >= self.size() as usize); @@ -96,7 +83,6 @@ impl RsaRef { to: &mut [u8], padding: Padding, ) -> Result<usize, ErrorStack> { - assert!(self.d().is_some(), "private components missing"); assert!(from.len() <= i32::max_value() as usize); assert!(to.len() >= self.size() as usize); @@ -112,6 +98,86 @@ impl RsaRef { } } + pub fn d(&self) -> &BigNumRef { + unsafe { + let d = compat::key(self.as_ptr())[2]; + BigNumRef::from_ptr(d as *mut _) + } + } + + pub fn p(&self) -> Option<&BigNumRef> { + unsafe { + let p = compat::factors(self.as_ptr())[0]; + if p.is_null() { + None + } else { + Some(BigNumRef::from_ptr(p as *mut _)) + } + } + } + + pub fn q(&self) -> Option<&BigNumRef> { + unsafe { + let q = compat::factors(self.as_ptr())[1]; + if q.is_null() { + None + } else { + Some(BigNumRef::from_ptr(q as *mut _)) + } + } + } + + pub fn dp(&self) -> Option<&BigNumRef> { + unsafe { + let dp = compat::crt_params(self.as_ptr())[0]; + if dp.is_null() { + None + } else { + Some(BigNumRef::from_ptr(dp as *mut _)) + } + } + } + + pub fn dq(&self) -> Option<&BigNumRef> { + unsafe { + let dq = compat::crt_params(self.as_ptr())[1]; + if dq.is_null() { + None + } else { + Some(BigNumRef::from_ptr(dq as *mut _)) + } + } + } + + pub fn qi(&self) -> Option<&BigNumRef> { + unsafe { + let qi = compat::crt_params(self.as_ptr())[2]; + if qi.is_null() { + None + } else { + Some(BigNumRef::from_ptr(qi as *mut _)) + } + } + } +} + +impl<T> RsaRef<T> +where + T: HasPublic, +{ + public_key_to_pem!(ffi::PEM_write_bio_RSA_PUBKEY); + public_key_to_der!(ffi::i2d_RSA_PUBKEY); + + to_der_inner!( + /// Serializes the public key to DER-encoded PKCS#1. + public_key_to_der_pkcs1, + ffi::i2d_RSAPublicKey + ); + + pub fn size(&self) -> u32 { + unsafe { ffi::RSA_size(self.as_ptr()) as u32 } + } + /// Decrypts data using the public key, returning the number of decrypted bytes. /// /// # Panics @@ -164,101 +230,25 @@ impl RsaRef { } } - pub fn n(&self) -> Option<&BigNumRef> { + pub fn n(&self) -> &BigNumRef { unsafe { let n = compat::key(self.as_ptr())[0]; - if n.is_null() { - None - } else { - Some(BigNumRef::from_ptr(n as *mut _)) - } - } - } - - pub fn d(&self) -> Option<&BigNumRef> { - unsafe { - let d = compat::key(self.as_ptr())[2]; - if d.is_null() { - None - } else { - Some(BigNumRef::from_ptr(d as *mut _)) - } + BigNumRef::from_ptr(n as *mut _) } } - pub fn e(&self) -> Option<&BigNumRef> { + pub fn e(&self) -> &BigNumRef { unsafe { let e = compat::key(self.as_ptr())[1]; - if e.is_null() { - None - } else { - Some(BigNumRef::from_ptr(e as *mut _)) - } - } - } - - pub fn p(&self) -> Option<&BigNumRef> { - unsafe { - let p = compat::factors(self.as_ptr())[0]; - if p.is_null() { - None - } else { - Some(BigNumRef::from_ptr(p as *mut _)) - } - } - } - - pub fn q(&self) -> Option<&BigNumRef> { - unsafe { - let q = compat::factors(self.as_ptr())[1]; - if q.is_null() { - None - } else { - Some(BigNumRef::from_ptr(q as *mut _)) - } - } - } - - pub fn dp(&self) -> Option<&BigNumRef> { - unsafe { - let dp = compat::crt_params(self.as_ptr())[0]; - if dp.is_null() { - None - } else { - Some(BigNumRef::from_ptr(dp as *mut _)) - } - } - } - - pub fn dq(&self) -> Option<&BigNumRef> { - unsafe { - let dq = compat::crt_params(self.as_ptr())[1]; - if dq.is_null() { - None - } else { - Some(BigNumRef::from_ptr(dq as *mut _)) - } - } - } - - pub fn qi(&self) -> Option<&BigNumRef> { - unsafe { - let qi = compat::crt_params(self.as_ptr())[2]; - if qi.is_null() { - None - } else { - Some(BigNumRef::from_ptr(qi as *mut _)) - } + BigNumRef::from_ptr(e as *mut _) } } } -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> { +impl Rsa<Public> { + pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> { unsafe { - let rsa = Rsa(cvt_p(ffi::RSA_new())?); + let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?); cvt(compat::set_key( rsa.0, n.as_ptr(), @@ -270,6 +260,18 @@ impl Rsa { } } + public_key_from_pem!(Rsa<Public>, ffi::PEM_read_bio_RSA_PUBKEY); + public_key_from_der!(Rsa<Public>, ffi::d2i_RSA_PUBKEY); + + from_der_inner!( + /// Deserializes a public key from DER-encoded PKCS#1 data. + public_key_from_der_pkcs1, + Rsa<Public>, + ffi::d2i_RSAPublicKey + ); +} + +impl Rsa<Private> { pub fn from_private_components( n: BigNum, e: BigNum, @@ -279,9 +281,9 @@ impl Rsa { dp: BigNum, dq: BigNum, qi: BigNum, - ) -> Result<Rsa, ErrorStack> { + ) -> Result<Rsa<Private>, ErrorStack> { unsafe { - let rsa = Rsa(cvt_p(ffi::RSA_new())?); + let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?); cvt(compat::set_key(rsa.0, n.as_ptr(), e.as_ptr(), d.as_ptr()))?; mem::forget((n, e, d)); cvt(compat::set_factors(rsa.0, p.as_ptr(), q.as_ptr()))?; @@ -300,10 +302,10 @@ impl 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> { + pub fn generate(bits: u32) -> Result<Rsa<Private>, ErrorStack> { ffi::init(); unsafe { - let rsa = Rsa(cvt_p(ffi::RSA_new())?); + let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?); let e = BigNum::from_u32(ffi::RSA_F4 as u32)?; cvt(ffi::RSA_generate_key_ex( rsa.0, @@ -316,20 +318,11 @@ impl Rsa { } // FIXME these need to identify input formats - private_key_from_pem!(Rsa, ffi::PEM_read_bio_RSAPrivateKey); - private_key_from_der!(Rsa, ffi::d2i_RSAPrivateKey); - public_key_from_pem!(Rsa, ffi::PEM_read_bio_RSA_PUBKEY); - public_key_from_der!(Rsa, ffi::d2i_RSA_PUBKEY); - - from_der_inner!( - /// Deserializes a public key from DER-encoded PKCS#1 data. - public_key_from_der_pkcs1, - Rsa, - ffi::d2i_RSAPublicKey - ); + private_key_from_pem!(Rsa<Private>, ffi::PEM_read_bio_RSAPrivateKey); + private_key_from_der!(Rsa<Private>, ffi::d2i_RSAPrivateKey); } -impl fmt::Debug for Rsa { +impl<T> fmt::Debug for Rsa<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Rsa") } diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs index 2d8b5887..f5f57a97 100644 --- a/openssl/src/sign.rs +++ b/openssl/src/sign.rs @@ -69,8 +69,9 @@ use std::ptr; use {cvt, cvt_p}; use hash::MessageDigest; -use pkey::{PKeyCtxRef, PKeyRef}; +use pkey::{HasPrivate, HasPublic, PKeyRef}; use error::ErrorStack; +use rsa::Padding; #[cfg(ossl110)] use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new}; @@ -80,8 +81,8 @@ use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_ /// A type which computes cryptographic signatures of data. pub struct Signer<'a> { md_ctx: *mut ffi::EVP_MD_CTX, - pkey_ctx: *mut ffi::EVP_PKEY_CTX, - pkey_pd: PhantomData<&'a PKeyRef>, + pctx: *mut ffi::EVP_PKEY_CTX, + _p: PhantomData<&'a ()>, } impl<'a> Drop for Signer<'a> { @@ -99,7 +100,10 @@ impl<'a> Signer<'a> { /// OpenSSL documentation at [`EVP_DigestSignInit`]. /// /// [`EVP_DigestSignInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html - pub fn new(type_: MessageDigest, pkey: &'a PKeyRef) -> Result<Signer<'a>, ErrorStack> { + pub fn new<T>(type_: MessageDigest, pkey: &'a PKeyRef<T>) -> Result<Signer<'a>, ErrorStack> + where + T: HasPrivate, + { unsafe { ffi::init(); @@ -121,20 +125,39 @@ impl<'a> Signer<'a> { Ok(Signer { md_ctx: ctx, - pkey_ctx: pctx, - pkey_pd: PhantomData, + pctx, + _p: PhantomData, }) } } - /// Returns a shared reference to the `PKeyCtx` associated with the `Signer`. - pub fn pkey_ctx(&self) -> &PKeyCtxRef { - unsafe { PKeyCtxRef::from_ptr(self.pkey_ctx) } + /// Returns the RSA padding mode in use. + /// + /// This is only useful for RSA keys. + /// + /// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`. + pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { + unsafe { + let mut pad = 0; + cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad)) + .map(|_| Padding::from_raw(pad)) + } } - /// Returns a mutable reference to the `PKeyCtx` associated with the `Signer`. - pub fn pkey_ctx_mut(&mut self) -> &mut PKeyCtxRef { - unsafe { PKeyCtxRef::from_ptr_mut(self.pkey_ctx) } + /// Sets the RSA padding mode. + /// + /// This is only useful for RSA keys. + /// + /// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`]. + /// + /// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_padding.html + pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::EVP_PKEY_CTX_set_rsa_padding( + self.pctx, + padding.as_raw(), + )).map(|_| ()) + } } /// Feeds more data into the `Signer`. @@ -217,8 +240,8 @@ impl<'a> Write for Signer<'a> { pub struct Verifier<'a> { md_ctx: *mut ffi::EVP_MD_CTX, - pkey_ctx: *mut ffi::EVP_PKEY_CTX, - pkey_pd: PhantomData<&'a PKeyRef>, + pctx: *mut ffi::EVP_PKEY_CTX, + pkey_pd: PhantomData<&'a ()>, } impl<'a> Drop for Verifier<'a> { @@ -237,7 +260,10 @@ impl<'a> Verifier<'a> { /// OpenSSL documentation at [`EVP_DigestVerifyInit`]. /// /// [`EVP_DigestVerifyInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestVerifyInit.html - pub fn new(type_: MessageDigest, pkey: &'a PKeyRef) -> Result<Verifier<'a>, ErrorStack> { + pub fn new<T>(type_: MessageDigest, pkey: &'a PKeyRef<T>) -> Result<Verifier<'a>, ErrorStack> + where + T: HasPublic, + { unsafe { ffi::init(); @@ -259,20 +285,39 @@ impl<'a> Verifier<'a> { Ok(Verifier { md_ctx: ctx, - pkey_ctx: pctx, + pctx, pkey_pd: PhantomData, }) } } - /// Returns a shared reference to the `PKeyCtx` associated with the `Verifier`. - pub fn pkey_ctx(&self) -> &PKeyCtxRef { - unsafe { PKeyCtxRef::from_ptr(self.pkey_ctx) } + /// Returns the RSA padding mode in use. + /// + /// This is only useful for RSA keys. + /// + /// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`. + pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { + unsafe { + let mut pad = 0; + cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad)) + .map(|_| Padding::from_raw(pad)) + } } - /// Returns a mutable reference to the `PKeyCtx` associated with the `Verifier`. - pub fn pkey_ctx_mut(&mut self) -> &mut PKeyCtxRef { - unsafe { PKeyCtxRef::from_ptr_mut(self.pkey_ctx) } + /// Sets the RSA padding mode. + /// + /// This is only useful for RSA keys. + /// + /// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`]. + /// + /// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_padding.html + pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::EVP_PKEY_CTX_set_rsa_padding( + self.pctx, + padding.as_raw(), + )).map(|_| ()) + } } /// Feeds more data into the `Verifier`. @@ -368,11 +413,8 @@ mod test { let pkey = PKey::from_rsa(private_key).unwrap(); let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap(); - assert_eq!(signer.pkey_ctx_mut().rsa_padding().unwrap(), Padding::PKCS1); - signer - .pkey_ctx_mut() - .set_rsa_padding(Padding::PKCS1) - .unwrap(); + assert_eq!(signer.rsa_padding().unwrap(), Padding::PKCS1); + signer.set_rsa_padding(Padding::PKCS1).unwrap(); signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); let result = signer.sign_to_vec().unwrap(); @@ -386,10 +428,7 @@ mod test { let pkey = PKey::from_rsa(private_key).unwrap(); let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); - assert_eq!( - verifier.pkey_ctx_mut().rsa_padding().unwrap(), - Padding::PKCS1 - ); + assert_eq!(verifier.rsa_padding().unwrap(), Padding::PKCS1); verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); assert!(verifier.verify(&Vec::from_hex(SIGNATURE).unwrap()).unwrap()); } @@ -403,7 +442,9 @@ mod test { let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); verifier.update(b"foobar").unwrap(); - assert!(!verifier.verify(&Vec::from_hex(SIGNATURE).unwrap()).unwrap()); + assert!(!verifier + .verify(&Vec::from_hex(SIGNATURE).unwrap()) + .unwrap()); } #[test] diff --git a/openssl/src/ssl/callbacks.rs b/openssl/src/ssl/callbacks.rs index 0d211691..17f8c1f6 100644 --- a/openssl/src/ssl/callbacks.rs +++ b/openssl/src/ssl/callbacks.rs @@ -10,6 +10,7 @@ use error::ErrorStack; use dh::Dh; #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))] use ec::EcKey; +use pkey::Params; use ssl::{get_callback_idx, get_ssl_callback_idx, SniError, SslRef}; #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] use ssl::AlpnError; @@ -147,7 +148,7 @@ pub unsafe extern "C" fn raw_tmp_dh<F>( keylength: c_int, ) -> *mut ffi::DH where - F: Fn(&mut SslRef, bool, u32) -> Result<Dh, ErrorStack> + 'static + Sync + Send, + F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, { let ctx = ffi::SSL_get_SSL_CTX(ssl); let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>()); @@ -174,7 +175,7 @@ pub unsafe extern "C" fn raw_tmp_ecdh<F>( keylength: c_int, ) -> *mut ffi::EC_KEY where - F: Fn(&mut SslRef, bool, u32) -> Result<EcKey, ErrorStack> + 'static + Sync + Send, + F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, { let ctx = ffi::SSL_get_SSL_CTX(ssl); let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>()); @@ -200,7 +201,7 @@ pub unsafe extern "C" fn raw_tmp_dh_ssl<F>( keylength: c_int, ) -> *mut ffi::DH where - F: Fn(&mut SslRef, bool, u32) -> Result<Dh, ErrorStack> + 'static + Sync + Send, + F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, { let callback = ffi::SSL_get_ex_data(ssl, get_ssl_callback_idx::<F>()); let callback = &*(callback as *mut F); @@ -226,7 +227,7 @@ pub unsafe extern "C" fn raw_tmp_ecdh_ssl<F>( keylength: c_int, ) -> *mut ffi::EC_KEY where - F: Fn(&mut SslRef, bool, u32) -> Result<EcKey, ErrorStack> + 'static + Sync + Send, + F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, { let callback = ffi::SSL_get_ex_data(ssl, get_ssl_callback_idx::<F>()); let callback = &*(callback as *mut F); diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 6da44373..cebb23b2 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -92,7 +92,7 @@ use x509::store::{X509StoreBuilderRef, X509StoreRef}; use x509::store::X509Store; #[cfg(any(ossl102, ossl110))] use verify::X509VerifyParamRef; -use pkey::PKeyRef; +use pkey::{HasPrivate, PKeyRef, Params, Private}; use error::ErrorStack; use ex_data::Index; use stack::{Stack, StackRef}; @@ -630,7 +630,7 @@ impl SslContextBuilder { /// This corresponds to [`SSL_CTX_set_tmp_dh`]. /// /// [`SSL_CTX_set_tmp_dh`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_tmp_dh.html - pub fn set_tmp_dh(&mut self, dh: &DhRef) -> Result<(), ErrorStack> { + pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> { unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) } } @@ -646,7 +646,7 @@ impl SslContextBuilder { /// [`SSL_CTX_set_tmp_dh_callback`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_tmp_dh.html pub fn set_tmp_dh_callback<F>(&mut self, callback: F) where - F: Fn(&mut SslRef, bool, u32) -> Result<Dh, ErrorStack> + 'static + Sync + Send, + F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, { unsafe { let callback = Box::new(callback); @@ -663,7 +663,7 @@ impl SslContextBuilder { /// Sets the parameters to be used during ephemeral elliptic curve Diffie-Hellman key exchange. /// /// This corresponds to `SSL_CTX_set_tmp_ecdh`. - pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef) -> Result<(), ErrorStack> { + pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> { unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int) @@ -684,7 +684,7 @@ impl SslContextBuilder { #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))] pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) where - F: Fn(&mut SslRef, bool, u32) -> Result<EcKey, ErrorStack> + 'static + Sync + Send, + F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, { unsafe { let callback = Box::new(callback); @@ -864,7 +864,10 @@ impl SslContextBuilder { /// This corresponds to [`SSL_CTX_use_PrivateKey`]. /// /// [`SSL_CTX_use_PrivateKey`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_use_PrivateKey_file.html - pub fn set_private_key(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> { + pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> + where + T: HasPrivate, + { unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) } } @@ -1202,7 +1205,7 @@ impl SslContextRef { /// /// [`SSL_CTX_get0_privatekey`]: https://www.openssl.org/docs/man1.1.0/ssl/ssl.html #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] - pub fn private_key(&self) -> Option<&PKeyRef> { + pub fn private_key(&self) -> Option<&PKeyRef<Private>> { unsafe { let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr()); if ptr.is_null() { @@ -1535,7 +1538,7 @@ impl SslRef { /// /// [`SslContextBuilder::set_tmp_dh`]: struct.SslContextBuilder.html#method.set_tmp_dh /// [`SSL_set_tmp_dh`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_tmp_dh.html - pub fn set_tmp_dh(&mut self, dh: &DhRef) -> Result<(), ErrorStack> { + pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> { unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) } } @@ -1547,7 +1550,7 @@ impl SslRef { /// [`SSL_set_tmp_dh_callback`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_tmp_dh.html pub fn set_tmp_dh_callback<F>(&mut self, callback: F) where - F: Fn(&mut SslRef, bool, u32) -> Result<Dh, ErrorStack> + 'static + Sync + Send, + F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, { unsafe { let callback = Box::new(callback); @@ -1566,7 +1569,7 @@ impl SslRef { /// This corresponds to `SSL_set_tmp_ecdh`. /// /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh - pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef) -> Result<(), ErrorStack> { + pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> { unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) } } @@ -1580,7 +1583,7 @@ impl SslRef { #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))] pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) where - F: Fn(&mut SslRef, bool, u32) -> Result<EcKey, ErrorStack> + 'static + Sync + Send, + F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, { unsafe { let callback = Box::new(callback); @@ -1723,7 +1726,7 @@ impl SslRef { /// This corresponds to `SSL_get_privatekey`. /// /// [`SslContext::private_key`]: struct.SslContext.html#method.private_key - pub fn private_key(&self) -> Option<&PKeyRef> { + pub fn private_key(&self) -> Option<&PKeyRef<Private>> { unsafe { let ptr = ffi::SSL_get_privatekey(self.as_ptr()); if ptr.is_null() { @@ -2038,10 +2041,9 @@ impl Ssl { ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock( MidHandshakeSslStream { stream, error }, )), - _ => Err(HandshakeError::Failure(MidHandshakeSslStream { - stream, - error, - })), + _ => Err(HandshakeError::Failure( + MidHandshakeSslStream { stream, error }, + )), } } } @@ -2070,10 +2072,9 @@ impl Ssl { ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock( MidHandshakeSslStream { stream, error }, )), - _ => Err(HandshakeError::Failure(MidHandshakeSslStream { - stream, - error, - })), + _ => Err(HandshakeError::Failure( + MidHandshakeSslStream { stream, error }, + )), } } } @@ -2318,8 +2319,10 @@ impl<S: Read + Write> Read for SslStream<S> { } Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} Err(e) => { - return Err(e.into_io_error() - .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))) + return Err( + e.into_io_error() + .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)), + ) } } } @@ -2333,8 +2336,10 @@ impl<S: Read + Write> Write for SslStream<S> { Ok(n) => return Ok(n), Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} Err(e) => { - return Err(e.into_io_error() - .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))) + return Err( + e.into_io_error() + .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)), + ) } } } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 52becf10..9491afce 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -19,7 +19,7 @@ use error::ErrorStack; use ex_data::Index; use hash::MessageDigest; use nid::Nid; -use pkey::{PKey, PKeyRef}; +use pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public}; use stack::{Stack, StackRef, Stackable}; use string::OpensslString; use ssl::SslRef; @@ -196,7 +196,10 @@ impl X509Builder { } /// Sets the public key associated with the certificate. - pub fn set_pubkey(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> { + pub fn set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> + where + T: HasPublic, + { unsafe { cvt(ffi::X509_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) } } @@ -244,7 +247,10 @@ impl X509Builder { } /// Signs the certificate with a private key. - pub fn sign(&mut self, key: &PKeyRef, hash: MessageDigest) -> Result<(), ErrorStack> { + pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack> + where + T: HasPrivate, + { unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) } } @@ -331,7 +337,7 @@ impl X509Ref { } } - pub fn public_key(&self) -> Result<PKey, ErrorStack> { + pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> { unsafe { let pkey = cvt_p(ffi::X509_get_pubkey(self.as_ptr()))?; Ok(PKey::from_ptr(pkey)) @@ -700,7 +706,10 @@ impl X509ReqBuilder { } } - pub fn set_pubkey(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> { + pub fn set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> + where + T: HasPublic, + { unsafe { cvt(ffi::X509_REQ_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) } } @@ -738,7 +747,10 @@ impl X509ReqBuilder { } } - pub fn sign(&mut self, key: &PKeyRef, hash: MessageDigest) -> Result<(), ErrorStack> { + pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack> + where + T: HasPrivate, + { unsafe { cvt(ffi::X509_REQ_sign( self.0.as_ptr(), diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 366b91e7..b6db948b 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -4,14 +4,14 @@ use asn1::Asn1Time; use bn::{BigNum, MsbOption}; use hash::MessageDigest; use nid::Nid; -use pkey::PKey; +use pkey::{PKey, Private}; use rsa::Rsa; use stack::Stack; use x509::{X509, X509Name, X509Req, X509VerifyResult}; use x509::extension::{AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, SubjectAlternativeName, SubjectKeyIdentifier}; -fn pkey() -> PKey { +fn pkey() -> PKey<Private> { let rsa = Rsa::generate(2048).unwrap(); PKey::from_rsa(rsa).unwrap() } |