summaryrefslogtreecommitdiff
path: root/openssl/src
diff options
context:
space:
mode:
authorSteven Fackler <sfackler@gmail.com>2017-12-30 21:46:17 -0800
committerSteven Fackler <sfackler@gmail.com>2017-12-30 21:53:39 -0800
commitd207897458f8fbd0b2ff6d879721b2f787a5d72b (patch)
treef5646108131916584291141407696ef894f2ff1e /openssl/src
parent6238b4a20a5775f59ddd47676ee07176a3b446ce (diff)
downloadrust-openssl-d207897458f8fbd0b2ff6d879721b2f787a5d72b.zip
Parameterize keys over what they contain
Closes #790
Diffstat (limited to 'openssl/src')
-rw-r--r--openssl/src/cms.rs20
-rw-r--r--openssl/src/derive.rs120
-rw-r--r--openssl/src/dh.rs36
-rw-r--r--openssl/src/dsa.rs105
-rw-r--r--openssl/src/ec.rs286
-rw-r--r--openssl/src/lib.rs1
-rw-r--r--openssl/src/macros.rs132
-rw-r--r--openssl/src/pkcs12.rs23
-rw-r--r--openssl/src/pkey.rs208
-rw-r--r--openssl/src/rsa.rs237
-rw-r--r--openssl/src/sign.rs105
-rw-r--r--openssl/src/ssl/callbacks.rs9
-rw-r--r--openssl/src/ssl/mod.rs53
-rw-r--r--openssl/src/x509/mod.rs24
-rw-r--r--openssl/src/x509/tests.rs4
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()
}