Merge pull request #810 from sfackler/key-tag

Parameterize keys over what they contain
This commit is contained in:
Steven Fackler 2017-12-31 10:21:23 -08:00 committed by GitHub
commit d3fff74ae8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 800 additions and 611 deletions

View File

@ -1723,6 +1723,7 @@ extern "C" {
pub fn EC_KEY_new() -> *mut EC_KEY; pub fn EC_KEY_new() -> *mut EC_KEY;
pub fn EC_KEY_new_by_curve_name(nid: c_int) -> *mut EC_KEY; pub fn EC_KEY_new_by_curve_name(nid: c_int) -> *mut EC_KEY;
pub fn EC_KEY_dup(key: *const EC_KEY) -> *mut EC_KEY; pub fn EC_KEY_dup(key: *const EC_KEY) -> *mut EC_KEY;
pub fn EC_KEY_up_ref(key: *mut EC_KEY) -> c_int;
pub fn EC_KEY_set_group(key: *mut EC_KEY, group: *const EC_GROUP) -> c_int; pub fn EC_KEY_set_group(key: *mut EC_KEY, group: *const EC_GROUP) -> c_int;
pub fn EC_KEY_get0_group(key: *const EC_KEY) -> *const EC_GROUP; pub fn EC_KEY_get0_group(key: *const EC_KEY) -> *const EC_GROUP;
pub fn EC_KEY_set_public_key(key: *mut EC_KEY, key: *const EC_POINT) -> c_int; pub fn EC_KEY_set_public_key(key: *mut EC_KEY, key: *const EC_POINT) -> c_int;

View File

@ -7,14 +7,14 @@ use openssl::asn1::Asn1Time;
use openssl::bn::{BigNum, MsbOption}; use openssl::bn::{BigNum, MsbOption};
use openssl::error::ErrorStack; use openssl::error::ErrorStack;
use openssl::hash::MessageDigest; use openssl::hash::MessageDigest;
use openssl::pkey::{PKey, PKeyRef}; use openssl::pkey::{PKey, PKeyRef, Private};
use openssl::rsa::Rsa; use openssl::rsa::Rsa;
use openssl::x509::{X509, X509NameBuilder, X509Ref, X509Req, X509ReqBuilder, X509VerifyResult}; use openssl::x509::{X509, X509NameBuilder, X509Ref, X509Req, X509ReqBuilder, X509VerifyResult};
use openssl::x509::extension::{AuthorityKeyIdentifier, BasicConstraints, KeyUsage, use openssl::x509::extension::{AuthorityKeyIdentifier, BasicConstraints, KeyUsage,
SubjectAlternativeName, SubjectKeyIdentifier}; SubjectAlternativeName, SubjectKeyIdentifier};
/// Make a CA certificate and private key /// Make a CA certificate and private key
fn mk_ca_cert() -> Result<(X509, PKey), ErrorStack> { fn mk_ca_cert() -> Result<(X509, PKey<Private>), ErrorStack> {
let rsa = Rsa::generate(2048)?; let rsa = Rsa::generate(2048)?;
let privkey = PKey::from_rsa(rsa)?; let privkey = PKey::from_rsa(rsa)?;
@ -59,7 +59,7 @@ fn mk_ca_cert() -> Result<(X509, PKey), ErrorStack> {
} }
/// Make a X509 request with the given private key /// Make a X509 request with the given private key
fn mk_request(privkey: &PKey) -> Result<(X509Req), ErrorStack> { fn mk_request(privkey: &PKey<Private>) -> Result<X509Req, ErrorStack> {
let mut req_builder = X509ReqBuilder::new()?; let mut req_builder = X509ReqBuilder::new()?;
req_builder.set_pubkey(&privkey)?; req_builder.set_pubkey(&privkey)?;
@ -77,7 +77,10 @@ fn mk_request(privkey: &PKey) -> Result<(X509Req), ErrorStack> {
} }
/// Make a certificate and private key signed by the given CA cert and private key /// Make a certificate and private key signed by the given CA cert and private key
fn mk_ca_signed_cert(ca_cert: &X509Ref, ca_privkey: &PKeyRef) -> Result<(X509, PKey), ErrorStack> { fn mk_ca_signed_cert(
ca_cert: &X509Ref,
ca_privkey: &PKeyRef<Private>,
) -> Result<(X509, PKey<Private>), ErrorStack> {
let rsa = Rsa::generate(2048)?; let rsa = Rsa::generate(2048)?;
let privkey = PKey::from_rsa(rsa)?; let privkey = PKey::from_rsa(rsa)?;

View File

@ -8,15 +8,12 @@
use ffi; use ffi;
use foreign_types::{ForeignType, ForeignTypeRef}; use foreign_types::{ForeignType, ForeignTypeRef};
use std::ptr; use std::ptr;
use error::ErrorStack;
use {cvt, cvt_p};
use bio::{MemBio, MemBioSlice}; use bio::{MemBio, MemBioSlice};
use error::ErrorStack;
use pkey::{HasPrivate, PKeyRef};
use x509::X509; use x509::X509;
use pkey::PKeyRef;
use cvt;
use cvt_p;
foreign_type_and_impl_send_sync! { foreign_type_and_impl_send_sync! {
type CType = ffi::CMS_ContentInfo; type CType = ffi::CMS_ContentInfo;
@ -44,7 +41,10 @@ impl CmsContentInfoRef {
/// OpenSSL documentation at [`CMS_decrypt`] /// OpenSSL documentation at [`CMS_decrypt`]
/// ///
/// [`CMS_decrypt`]: https://www.openssl.org/docs/man1.1.0/crypto/CMS_decrypt.html /// [`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 { unsafe {
let pkey = pkey.as_ptr(); let pkey = pkey.as_ptr();
let cert = cert.as_ptr(); let cert = cert.as_ptr();
@ -63,7 +63,6 @@ impl CmsContentInfoRef {
Ok(out.get_buf().to_owned()) Ok(out.get_buf().to_owned())
} }
} }
} }
impl CmsContentInfo { impl CmsContentInfo {
@ -76,10 +75,7 @@ impl CmsContentInfo {
unsafe { unsafe {
let bio = MemBioSlice::new(smime)?; let bio = MemBioSlice::new(smime)?;
let cms = cvt_p(ffi::SMIME_read_CMS( let cms = cvt_p(ffi::SMIME_read_CMS(bio.as_ptr(), ptr::null_mut()))?;
bio.as_ptr(),
ptr::null_mut(),
))?;
Ok(CmsContentInfo::from_ptr(cms)) Ok(CmsContentInfo::from_ptr(cms))
} }

120
openssl/src/derive.rs Normal file
View File

@ -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());
}
}

View File

@ -1,30 +1,34 @@
use error::ErrorStack; use error::ErrorStack;
use ffi; use ffi;
use foreign_types::ForeignTypeRef; use foreign_types::{ForeignType, ForeignTypeRef};
use std::mem; use std::mem;
use std::ptr; use std::ptr;
use {cvt, cvt_p}; use {cvt, cvt_p};
use bn::BigNum; use bn::BigNum;
use pkey::{HasParams, Params};
foreign_type_and_impl_send_sync! { generic_foreign_type_and_impl_send_sync! {
type CType = ffi::DH; type CType = ffi::DH;
fn drop = ffi::DH_free; 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_pem!(ffi::PEM_write_bio_DHparams);
to_der!(ffi::i2d_DHparams); to_der!(ffi::i2d_DHparams);
} }
impl Dh { impl Dh<Params> {
pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<Dh, ErrorStack> { pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<Dh<Params>, ErrorStack> {
unsafe { unsafe {
let dh = Dh(cvt_p(ffi::DH_new())?); let dh = Dh::from_ptr(cvt_p(ffi::DH_new())?);
cvt(compat::DH_set0_pqg( cvt(compat::DH_set0_pqg(
dh.0, dh.0,
p.as_ptr(), p.as_ptr(),
@ -36,33 +40,33 @@ impl Dh {
} }
} }
from_pem!(Dh, ffi::PEM_read_bio_DHparams); from_pem!(Dh<Params>, ffi::PEM_read_bio_DHparams);
from_der!(Dh, ffi::d2i_DHparams); from_der!(Dh<Params>, ffi::d2i_DHparams);
/// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. /// 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)))] #[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 { unsafe {
ffi::init(); 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. /// 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)))] #[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 { unsafe {
ffi::init(); 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. /// 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)))] #[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 { unsafe {
ffi::init(); ffi::init();
cvt_p(ffi::DH_get_2048_256()).map(Dh) cvt_p(ffi::DH_get_2048_256()).map(|p| Dh::from_ptr(p))
} }
} }
} }

View File

@ -6,7 +6,7 @@
//! without the private key. //! without the private key.
use ffi; use ffi;
use foreign_types::ForeignTypeRef; use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int; use libc::c_int;
use std::fmt; use std::fmt;
use std::ptr; use std::ptr;
@ -14,8 +14,9 @@ use std::ptr;
use {cvt, cvt_p}; use {cvt, cvt_p};
use bn::BigNumRef; use bn::BigNumRef;
use error::ErrorStack; 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; type CType = ffi::DSA;
fn drop = ffi::DSA_free; fn drop = ffi::DSA_free;
@ -40,7 +41,9 @@ foreign_type_and_impl_send_sync! {
/// ``` /// ```
/// use openssl::dsa::Dsa; /// use openssl::dsa::Dsa;
/// use openssl::error::ErrorStack; /// 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)?; /// let sign = Dsa::generate(2048)?;
/// Ok(sign) /// Ok(sign)
/// } /// }
@ -48,83 +51,68 @@ foreign_type_and_impl_send_sync! {
/// # create_dsa(); /// # create_dsa();
/// # } /// # }
/// ``` /// ```
pub struct Dsa; pub struct Dsa<T>;
/// Reference to [`Dsa`]. /// Reference to [`Dsa`].
/// ///
/// [`Dsa`]: struct.Dsa.html /// [`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); 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); private_key_to_der!(ffi::i2d_DSAPrivateKey);
public_key_to_der!(ffi::i2d_DSAPublicKey); }
/// Returns the maximum size of the signature output by `self` in bytes. Returns impl<T> DsaRef<T>
/// None if the keys are uninitialized. where
T: HasPublic,
{
public_key_to_pem!(ffi::PEM_write_bio_DSA_PUBKEY);
public_key_to_der!(ffi::i2d_DSAPublicKey);
}
impl<T> DsaRef<T>
where
T: HasParams,
{
/// Returns the maximum size of the signature output by `self` in bytes.
/// ///
/// OpenSSL documentation at [`DSA_size`] /// OpenSSL documentation at [`DSA_size`]
/// ///
/// [`DSA_size`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_size.html /// [`DSA_size`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_size.html
pub fn size(&self) -> u32 { pub fn size(&self) -> u32 {
unsafe { unsafe { ffi::DSA_size(self.as_ptr()) as u32 }
assert!(self.q().is_some());
ffi::DSA_size(self.as_ptr()) as u32
}
} }
/// Returns the DSA prime parameter of `self`. /// Returns the DSA prime parameter of `self`.
pub fn p(&self) -> Option<&BigNumRef> { pub fn p(&self) -> &BigNumRef {
unsafe { unsafe {
let p = compat::pqg(self.as_ptr())[0]; let p = compat::pqg(self.as_ptr())[0];
if p.is_null() { BigNumRef::from_ptr(p as *mut _)
None
} else {
Some(BigNumRef::from_ptr(p as *mut _))
}
} }
} }
/// Returns the DSA sub-prime parameter of `self`. /// Returns the DSA sub-prime parameter of `self`.
pub fn q(&self) -> Option<&BigNumRef> { pub fn q(&self) -> &BigNumRef {
unsafe { unsafe {
let q = compat::pqg(self.as_ptr())[1]; let q = compat::pqg(self.as_ptr())[1];
if q.is_null() { BigNumRef::from_ptr(q as *mut _)
None
} else {
Some(BigNumRef::from_ptr(q as *mut _))
}
} }
} }
/// Returns the DSA base parameter of `self`. /// Returns the DSA base parameter of `self`.
pub fn g(&self) -> Option<&BigNumRef> { pub fn g(&self) -> &BigNumRef {
unsafe { unsafe {
let g = compat::pqg(self.as_ptr())[2]; let g = compat::pqg(self.as_ptr())[2];
if g.is_null() { BigNumRef::from_ptr(g as *mut _)
None
} else {
Some(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. /// Generate a DSA key pair.
/// ///
/// Calls [`DSA_generate_parameters_ex`] to populate the `p`, `g`, and `q` values. /// 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_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 /// [`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(); ffi::init();
unsafe { 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( cvt(ffi::DSA_generate_parameters_ex(
dsa.0, dsa.0,
bits as c_int, bits as c_int,
@ -152,13 +140,16 @@ impl Dsa {
} }
} }
private_key_from_pem!(Dsa, ffi::PEM_read_bio_DSAPrivateKey); private_key_from_pem!(Dsa<Private>, ffi::PEM_read_bio_DSAPrivateKey);
private_key_from_der!(Dsa, ffi::d2i_DSAPrivateKey); private_key_from_der!(Dsa<Private>, ffi::d2i_DSAPrivateKey);
public_key_from_pem!(Dsa, ffi::PEM_read_bio_DSA_PUBKEY);
public_key_from_der!(Dsa, ffi::d2i_DSAPublicKey);
} }
impl fmt::Debug for Dsa { 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<T> fmt::Debug for Dsa<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DSA") write!(f, "DSA")
} }
@ -174,12 +165,6 @@ mod compat {
ffi::DSA_get0_pqg(d, &mut p, &mut q, &mut g); ffi::DSA_get0_pqg(d, &mut p, &mut q, &mut g);
[p, q, 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)] #[cfg(ossl10x)]
@ -189,10 +174,6 @@ mod compat {
pub unsafe fn pqg(d: *const DSA) -> [*const BIGNUM; 3] { pub unsafe fn pqg(d: *const DSA) -> [*const BIGNUM; 3] {
[(*d).p, (*d).q, (*d).g] [(*d).p, (*d).q, (*d).g]
} }
pub unsafe fn keys(d: *const DSA) -> [*const BIGNUM; 2] {
[(*d).pub_key, (*d).priv_key]
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -34,13 +34,13 @@
use ffi; use ffi;
use foreign_types::{ForeignType, ForeignTypeRef}; use foreign_types::{ForeignType, ForeignTypeRef};
use std::ptr; use std::ptr;
use std::mem;
use libc::c_int; use libc::c_int;
use {cvt, cvt_n, cvt_p, init}; use {cvt, cvt_n, cvt_p, init};
use bn::{BigNumContextRef, BigNumRef}; use bn::{BigNumContextRef, BigNumRef};
use error::ErrorStack; use error::ErrorStack;
use nid::Nid; use nid::Nid;
use pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public};
/// Compressed or Uncompressed conversion /// 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; type CType = ffi::EC_KEY;
fn drop = ffi::EC_KEY_free; fn drop = ffi::EC_KEY_free;
@ -510,62 +510,64 @@ foreign_type_and_impl_send_sync! {
/// OpenSSL documentation at [`EC_KEY_new`] /// OpenSSL documentation at [`EC_KEY_new`]
/// ///
/// [`EC_KEY_new`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new.html /// [`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`] /// Reference to [`EcKey`]
/// ///
/// [`EcKey`]: struct.EcKey.html /// [`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_pem!(ffi::PEM_write_bio_ECPrivateKey);
private_key_to_der!(ffi::i2d_ECPrivateKey); private_key_to_der!(ffi::i2d_ECPrivateKey);
/// Return [`EcGroup`] of the `EcKey`
///
/// OpenSSL documentation at [`EC_KEY_get0_group`]
///
/// [`EC_KEY_get0_group`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_group.html
pub fn group(&self) -> Option<&EcGroupRef> {
unsafe {
let ptr = ffi::EC_KEY_get0_group(self.as_ptr());
if ptr.is_null() {
None
} else {
Some(EcGroupRef::from_ptr(ptr as *mut _))
}
}
}
/// Return [`EcPoint`] associated with 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> {
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 _))
}
}
}
/// Return [`EcPoint`] associated with the private key /// Return [`EcPoint`] associated with the private key
/// ///
/// OpenSSL documentation at [`EC_KEY_get0_private_key`] /// OpenSSL documentation at [`EC_KEY_get0_private_key`]
/// ///
/// [`EC_KEY_get0_private_key`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_private_key.html /// [`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> { pub fn private_key(&self) -> &BigNumRef {
unsafe { unsafe {
let ptr = ffi::EC_KEY_get0_private_key(self.as_ptr()); let ptr = ffi::EC_KEY_get0_private_key(self.as_ptr());
if ptr.is_null() { BigNumRef::from_ptr(ptr as *mut _)
None }
} else { }
Some(BigNumRef::from_ptr(ptr as *mut _)) }
}
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) -> &EcPointRef {
unsafe {
let ptr = ffi::EC_KEY_get0_public_key(self.as_ptr());
EcPointRef::from_ptr(ptr as *mut _)
}
}
}
impl<T> EcKeyRef<T>
where
T: HasParams,
{
/// Return [`EcGroup`] of the `EcKey`
///
/// OpenSSL documentation at [`EC_KEY_get0_group`]
///
/// [`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_group(self.as_ptr());
EcGroupRef::from_ptr(ptr as *mut _)
} }
} }
@ -577,14 +579,21 @@ impl EcKeyRef {
pub fn check_key(&self) -> Result<(), ErrorStack> { pub fn check_key(&self) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::EC_KEY_check_key(self.as_ptr())).map(|_| ()) } unsafe { cvt(ffi::EC_KEY_check_key(self.as_ptr())).map(|_| ()) }
} }
}
/// Create a copy of the `EcKey` to allow modification impl<T> ToOwned for EcKeyRef<T> {
pub fn to_owned(&self) -> Result<EcKey, ErrorStack> { type Owned = EcKey<T>;
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. /// 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 /// 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`] /// 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 /// [`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 { unsafe {
init(); 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. /// Constructs an `EcKey` from the specified group with the associated `EcPoint`, public_key.
/// ///
/// This will only have the associated public_key. /// This will only have the associated public_key.
@ -624,104 +650,67 @@ impl EcKey {
pub fn from_public_key( pub fn from_public_key(
group: &EcGroupRef, group: &EcGroupRef,
public_key: &EcPointRef, public_key: &EcPointRef,
) -> Result<EcKey, ErrorStack> { ) -> Result<EcKey<Public>, 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> {
unsafe { unsafe {
init(); cvt_p(ffi::EC_KEY_new())
cvt_p(ffi::EC_KEY_new()).map(EcKeyBuilder) .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`] /// Constructs a public key from its affine coordinates.
/// pub fn from_public_key_affine_coordinates(
/// [`EcKey`]: struct.EcKey.html group: &EcGroupRef,
pub fn build(self) -> EcKey {
unsafe {
let key = EcKey::from_ptr(self.as_ptr());
mem::forget(self);
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> {
unsafe {
cvt(ffi::EC_KEY_set_public_key(
self.as_ptr(),
public_key.as_ptr(),
)).map(|_| self)
}
}
/// 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, x: &BigNumRef,
y: &BigNumRef, y: &BigNumRef,
) -> Result<&mut EcKeyBuilderRef, ErrorStack> { ) -> Result<EcKey<Public>, ErrorStack> {
unsafe { unsafe {
cvt(ffi::EC_KEY_set_public_key_affine_coordinates( cvt_p(ffi::EC_KEY_new())
self.as_ptr(), .map(|p| EcKey::from_ptr(p))
x.as_ptr(), .and_then(|key| {
y.as_ptr(), cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key)
)).map(|_| self) })
.and_then(|key| {
cvt(ffi::EC_KEY_set_public_key_affine_coordinates(
key.as_ptr(),
x.as_ptr(),
y.as_ptr(),
)).map(|_| key)
})
}
}
}
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_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)
})
} }
} }
/// Sets the private key. private_key_from_pem!(EcKey<Private>, ffi::PEM_read_bio_ECPrivateKey);
pub fn set_private_key(&mut self, key: &BigNumRef) -> Result<&mut EcKeyBuilderRef, ErrorStack> { private_key_from_der!(EcKey<Private>, ffi::d2i_ECPrivateKey);
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() { fn generate() {
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let key = EcKey::generate(&group).unwrap(); let key = EcKey::generate(&group).unwrap();
key.public_key().unwrap();
key.private_key().unwrap();
} }
#[test] #[test]
fn dup() { fn dup() {
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let key = EcKey::generate(&group).unwrap(); let key = EcKey::generate(&group).unwrap();
key.to_owned().unwrap(); key.clone();
} }
#[test] #[test]
@ -762,7 +749,7 @@ mod test {
fn point_bytes() { fn point_bytes() {
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let key = EcKey::generate(&group).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 mut ctx = BigNumContext::new().unwrap();
let bytes = point let bytes = point
.to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx) .to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx)
@ -778,13 +765,9 @@ mod test {
let mut ctx = BigNumContext::new().unwrap(); let mut ctx = BigNumContext::new().unwrap();
let mut public_key = EcPoint::new(&group).unwrap(); let mut public_key = EcPoint::new(&group).unwrap();
public_key public_key
.mul_generator(&group, key.private_key().unwrap(), &mut ctx) .mul_generator(&group, key.private_key(), &mut ctx)
.unwrap(); .unwrap();
assert!( assert!(public_key.eq(&group, key.public_key(), &mut ctx).unwrap());
public_key
.eq(&group, key.public_key().unwrap(), &mut ctx)
.unwrap()
);
} }
#[test] #[test]
@ -793,7 +776,6 @@ mod test {
let key = EcKey::generate(&group).unwrap(); let key = EcKey::generate(&group).unwrap();
let mut ctx = BigNumContext::new().unwrap(); let mut ctx = BigNumContext::new().unwrap();
let bytes = key.public_key() let bytes = key.public_key()
.unwrap()
.to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx) .to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx)
.unwrap(); .unwrap();
@ -801,8 +783,6 @@ mod test {
let public_key = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap(); let public_key = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap();
let ec_key = EcKey::from_public_key(&group, &public_key).unwrap(); let ec_key = EcKey::from_public_key(&group, &public_key).unwrap();
assert!(ec_key.check_key().is_ok()); assert!(ec_key.check_key().is_ok());
assert!(ec_key.public_key().is_some());
assert!(ec_key.private_key().is_none());
} }
#[test] #[test]
@ -818,32 +798,8 @@ mod test {
let xbn = BigNum::from_slice(&x).unwrap(); let xbn = BigNum::from_slice(&x).unwrap();
let ybn = BigNum::from_slice(&y).unwrap(); let ybn = BigNum::from_slice(&y).unwrap();
let mut builder = EcKeyBuilder::new().unwrap(); let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap();
builder.set_group(&group).unwrap();
builder
.set_public_key_affine_coordinates(&xbn, &ybn)
.unwrap();
let ec_key = builder.build();
assert!(ec_key.check_key().is_ok()); 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] #[test]
@ -859,18 +815,12 @@ mod test {
let xbn = BigNum::from_slice(&x).unwrap(); let xbn = BigNum::from_slice(&x).unwrap();
let ybn = BigNum::from_slice(&y).unwrap(); let ybn = BigNum::from_slice(&y).unwrap();
let mut builder = EcKeyBuilder::new().unwrap(); let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap();
builder.set_group(&group).unwrap();
builder
.set_public_key_affine_coordinates(&xbn, &ybn)
.unwrap();
let ec_key = builder.build();
let mut xbn2 = BigNum::new().unwrap(); let mut xbn2 = BigNum::new().unwrap();
let mut ybn2 = BigNum::new().unwrap(); let mut ybn2 = BigNum::new().unwrap();
let mut ctx = BigNumContext::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 ec_key_pk
.affine_coordinates_gfp(&group, &mut xbn2, &mut ybn2, &mut ctx) .affine_coordinates_gfp(&group, &mut xbn2, &mut ybn2, &mut ctx)
.unwrap(); .unwrap();

View File

@ -35,6 +35,7 @@ pub mod bn;
#[cfg(not(libressl))] #[cfg(not(libressl))]
pub mod cms; pub mod cms;
pub mod conf; pub mod conf;
pub mod derive;
pub mod dh; pub mod dh;
pub mod dsa; pub mod dsa;
pub mod ec; pub mod ec;

View File

@ -1,6 +1,6 @@
macro_rules! private_key_from_pem { macro_rules! private_key_from_pem {
($t:ident, $f:path) => { ($t:ty, $f:path) => {
from_pem_inner!(/// Deserializes a PEM-formatted private key. from_pem_inner!(/// Deserializes a PEM-formatted private key.
private_key_from_pem, $t, $f); private_key_from_pem, $t, $f);
@ -21,7 +21,7 @@ macro_rules! private_key_from_pem {
ptr::null_mut(), ptr::null_mut(),
None, None,
passphrase.as_ptr() as *const _ as *mut _)) 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(), ptr::null_mut(),
Some(::util::invoke_passwd_cb::<F>), Some(::util::invoke_passwd_cb::<F>),
&mut cb as *mut _ as *mut _)) &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 { macro_rules! from_der_inner {
(#[$m:meta] $n:ident, $t:ident, $f:path) => { (#[$m:meta] $n:ident, $t:ty, $f:path) => {
#[$m] #[$m]
pub fn $n(der: &[u8]) -> Result<$t, ::error::ErrorStack> { pub fn $n(der: &[u8]) -> Result<$t, ::error::ErrorStack> {
unsafe { unsafe {
::ffi::init(); ::ffi::init();
let len = ::std::cmp::min(der.len(), ::libc::c_long::max_value() as usize) as ::libc::c_long; 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)) ::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 { macro_rules! from_der {
($t:ident, $f:path) => { ($t:ty, $f:path) => {
from_der_inner!(/// Deserializes a value from DER-formatted data. from_der_inner!(/// Deserializes a value from DER-formatted data.
from_der, $t, $f); from_der, $t, $f);
} }
} }
macro_rules! private_key_from_der { 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. from_der_inner!(/// Deserializes a private key from DER-formatted data.
private_key_from_der, $t, $f); private_key_from_der, $t, $f);
} }
} }
macro_rules! public_key_from_der { 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. from_der_inner!(/// Deserializes a public key from DER-formatted data.
public_key_from_der, $t, $f); public_key_from_der, $t, $f);
} }
} }
macro_rules! from_pem_inner { macro_rules! from_pem_inner {
(#[$m:meta] $n:ident, $t:ident, $f:path) => { (#[$m:meta] $n:ident, $t:ty, $f:path) => {
#[$m] #[$m]
pub fn $n(pem: &[u8]) -> Result<$t, ::error::ErrorStack> { pub fn $n(pem: &[u8]) -> Result<$t, ::error::ErrorStack> {
unsafe { unsafe {
::init(); ::init();
let bio = try!(::bio::MemBioSlice::new(pem)); let bio = try!(::bio::MemBioSlice::new(pem));
cvt_p($f(bio.as_ptr(), ::std::ptr::null_mut(), None, ::std::ptr::null_mut())) 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 { 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. from_pem_inner!(/// Deserializes a public key from PEM-formatted data.
public_key_from_pem, $t, $f); public_key_from_pem, $t, $f);
} }
} }
macro_rules! from_pem { macro_rules! from_pem {
($t:ident, $f:path) => { ($t:ty, $f:path) => {
from_pem_inner!(/// Deserializes a value from PEM-formatted data. from_pem_inner!(/// Deserializes a value from PEM-formatted data.
from_pem, $t, $f); from_pem, $t, $f);
} }
} }
macro_rules! foreign_type_and_impl_send_sync { macro_rules! foreign_type_and_impl_send_sync {
( (
$(#[$impl_attr:meta])* $(#[$impl_attr:meta])*
@ -246,3 +245,110 @@ macro_rules! foreign_type_and_impl_send_sync {
unsafe impl Sync for $borrowed{} 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>{}
};
}

View File

@ -7,7 +7,7 @@ use std::ptr;
use std::ffi::CString; use std::ffi::CString;
use {cvt, cvt_p}; use {cvt, cvt_p};
use pkey::{PKey, PKeyRef}; use pkey::{HasPrivate, PKey, PKeyRef, Private};
use error::ErrorStack; use error::ErrorStack;
use x509::{X509, X509Ref}; use x509::{X509, X509Ref};
use stack::Stack; use stack::Stack;
@ -25,9 +25,9 @@ impl Pkcs12Ref {
to_der!(ffi::i2d_PKCS12); to_der!(ffi::i2d_PKCS12);
/// Extracts the contents of the `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 { unsafe {
let pass = CString::new(pass).unwrap(); let pass = CString::new(pass.as_bytes()).unwrap();
let mut pkey = ptr::null_mut(); let mut pkey = ptr::null_mut();
let mut cert = ptr::null_mut(); let mut cert = ptr::null_mut();
@ -84,7 +84,7 @@ impl Pkcs12 {
} }
pub struct ParsedPkcs12 { pub struct ParsedPkcs12 {
pub pkey: PKey, pub pkey: PKey<Private>,
pub cert: X509, pub cert: X509,
pub chain: Option<Stack<X509>>, pub chain: Option<Stack<X509>>,
} }
@ -140,13 +140,16 @@ impl Pkcs12Builder {
/// * `friendly_name` - user defined name for the certificate /// * `friendly_name` - user defined name for the certificate
/// * `pkey` - key to store /// * `pkey` - key to store
/// * `cert` - certificate to store /// * `cert` - certificate to store
pub fn build( pub fn build<T>(
self, self,
password: &str, password: &str,
friendly_name: &str, friendly_name: &str,
pkey: &PKeyRef, pkey: &PKeyRef<T>,
cert: &X509Ref, cert: &X509Ref,
) -> Result<Pkcs12, ErrorStack> { ) -> Result<Pkcs12, ErrorStack>
where
T: HasPrivate,
{
unsafe { unsafe {
let pass = CString::new(password).unwrap(); let pass = CString::new(password).unwrap();
let friendly_name = CString::new(friendly_name).unwrap(); let friendly_name = CString::new(friendly_name).unwrap();
@ -198,7 +201,7 @@ mod test {
fn parse() { fn parse() {
let der = include_bytes!("../test/identity.p12"); let der = include_bytes!("../test/identity.p12");
let pkcs12 = Pkcs12::from_der(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!( assert_eq!(
parsed parsed
@ -224,7 +227,7 @@ mod test {
fn parse_empty_chain() { fn parse_empty_chain() {
let der = include_bytes!("../test/keystore-empty-chain.p12"); let der = include_bytes!("../test/keystore-empty-chain.p12");
let pkcs12 = Pkcs12::from_der(der).unwrap(); 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()); assert!(parsed.chain.is_none());
} }
@ -263,7 +266,7 @@ mod test {
let der = pkcs12.to_der().unwrap(); let der = pkcs12.to_der().unwrap();
let pkcs12 = Pkcs12::from_der(&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!( assert_eq!(
parsed.cert.fingerprint(MessageDigest::sha1()).unwrap(), parsed.cert.fingerprint(MessageDigest::sha1()).unwrap(),

View File

@ -1,4 +1,4 @@
use libc::{c_int, size_t}; use libc::c_int;
use std::ptr; use std::ptr;
use std::mem; use std::mem;
use std::ffi::CString; use std::ffi::CString;
@ -10,21 +10,57 @@ use bio::MemBioSlice;
use dh::Dh; use dh::Dh;
use dsa::Dsa; use dsa::Dsa;
use ec::EcKey; use ec::EcKey;
use rsa::{Padding, Rsa}; use rsa::Rsa;
use error::ErrorStack; use error::ErrorStack;
use util::{invoke_passwd_cb, CallbackState}; 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; type CType = ffi::EVP_PKEY;
fn drop = ffi::EVP_PKEY_free; fn drop = ffi::EVP_PKEY_free;
pub struct PKey; pub struct PKey<T>;
pub struct PKeyRef; pub struct PKeyRef<T>;
} }
impl PKeyRef { impl<T> PKeyRef<T> {
/// Returns a copy of the internal RSA key. /// Returns a copy of the internal RSA key.
pub fn rsa(&self) -> Result<Rsa, ErrorStack> { pub fn rsa(&self) -> Result<Rsa<T>, ErrorStack> {
unsafe { unsafe {
let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?; let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?;
Ok(Rsa::from_ptr(rsa)) Ok(Rsa::from_ptr(rsa))
@ -32,7 +68,7 @@ impl PKeyRef {
} }
/// Returns a copy of the internal DSA key. /// Returns a copy of the internal DSA key.
pub fn dsa(&self) -> Result<Dsa, ErrorStack> { pub fn dsa(&self) -> Result<Dsa<T>, ErrorStack> {
unsafe { unsafe {
let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?; let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?;
Ok(Dsa::from_ptr(dsa)) Ok(Dsa::from_ptr(dsa))
@ -40,7 +76,7 @@ impl PKeyRef {
} }
/// Returns a copy of the internal DH key. /// Returns a copy of the internal DH key.
pub fn dh(&self) -> Result<Dh, ErrorStack> { pub fn dh(&self) -> Result<Dh<T>, ErrorStack> {
unsafe { unsafe {
let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?; let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?;
Ok(Dh::from_ptr(dh)) Ok(Dh::from_ptr(dh))
@ -48,17 +84,19 @@ impl PKeyRef {
} }
/// Returns a copy of the internal elliptic curve key. /// 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 { unsafe {
let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?; let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?;
Ok(EcKey::from_ptr(ec_key)) Ok(EcKey::from_ptr(ec_key))
} }
} }
}
impl<T> PKeyRef<T>
where
T: HasPublic,
{
public_key_to_pem!(ffi::PEM_write_bio_PUBKEY); 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); public_key_to_der!(ffi::i2d_PUBKEY);
/// Returns the size of the key. /// Returns the size of the key.
@ -70,17 +108,28 @@ impl PKeyRef {
} }
/// Compares the public component of this key with another. /// 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 } 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. /// 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 { unsafe {
let evp = cvt_p(ffi::EVP_PKEY_new())?; let evp = cvt_p(ffi::EVP_PKEY_new())?;
let pkey = PKey(evp); let pkey = PKey::from_ptr(evp);
cvt(ffi::EVP_PKEY_assign( cvt(ffi::EVP_PKEY_assign(
pkey.0, pkey.0,
ffi::EVP_PKEY_RSA, ffi::EVP_PKEY_RSA,
@ -92,10 +141,10 @@ impl PKey {
} }
/// Creates a new `PKey` containing a DSA key. /// 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 { unsafe {
let evp = cvt_p(ffi::EVP_PKEY_new())?; let evp = cvt_p(ffi::EVP_PKEY_new())?;
let pkey = PKey(evp); let pkey = PKey::from_ptr(evp);
cvt(ffi::EVP_PKEY_assign( cvt(ffi::EVP_PKEY_assign(
pkey.0, pkey.0,
ffi::EVP_PKEY_DSA, ffi::EVP_PKEY_DSA,
@ -107,10 +156,10 @@ impl PKey {
} }
/// Creates a new `PKey` containing a Diffie-Hellman key. /// 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 { unsafe {
let evp = cvt_p(ffi::EVP_PKEY_new())?; let evp = cvt_p(ffi::EVP_PKEY_new())?;
let pkey = PKey(evp); let pkey = PKey::from_ptr(evp);
cvt(ffi::EVP_PKEY_assign( cvt(ffi::EVP_PKEY_assign(
pkey.0, pkey.0,
ffi::EVP_PKEY_DH, ffi::EVP_PKEY_DH,
@ -122,10 +171,10 @@ impl PKey {
} }
/// Creates a new `PKey` containing an elliptic curve key. /// 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 { unsafe {
let evp = cvt_p(ffi::EVP_PKEY_new())?; let evp = cvt_p(ffi::EVP_PKEY_new())?;
let pkey = PKey(evp); let pkey = PKey::from_ptr(evp);
cvt(ffi::EVP_PKEY_assign( cvt(ffi::EVP_PKEY_assign(
pkey.0, pkey.0,
ffi::EVP_PKEY_EC, ffi::EVP_PKEY_EC,
@ -135,12 +184,15 @@ impl PKey {
Ok(pkey) Ok(pkey)
} }
} }
}
impl PKey<Private> {
/// Creates a new `PKey` containing an HMAC key. /// Creates a new `PKey` containing an HMAC key.
/// ///
/// # Note /// # Note
///
/// To compute HMAC values, use the `sign` module. /// 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 { unsafe {
assert!(key.len() <= c_int::max_value() as usize); assert!(key.len() <= c_int::max_value() as usize);
let key = cvt_p(ffi::EVP_PKEY_new_mac_key( let key = cvt_p(ffi::EVP_PKEY_new_mac_key(
@ -149,21 +201,22 @@ impl PKey {
key.as_ptr() as *const _, key.as_ptr() as *const _,
key.len() as c_int, key.len() as c_int,
))?; ))?;
Ok(PKey(key)) Ok(PKey::from_ptr(key))
} }
} }
private_key_from_pem!(PKey, ffi::PEM_read_bio_PrivateKey); private_key_from_pem!(PKey<Private>, ffi::PEM_read_bio_PrivateKey);
public_key_from_pem!(PKey, ffi::PEM_read_bio_PUBKEY); private_key_from_der!(PKey<Public>, ffi::d2i_AutoPrivateKey);
public_key_from_der!(PKey, ffi::d2i_PUBKEY);
private_key_from_der!(PKey, ffi::d2i_AutoPrivateKey);
/// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password
/// if the key is encrpyted. /// if the key is encrpyted.
/// ///
/// The callback should copy the password into the provided buffer and return the number of /// The callback should copy the password into the provided buffer and return the number of
/// bytes written. /// 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 where
F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>, F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
{ {
@ -176,7 +229,7 @@ impl PKey {
ptr::null_mut(), ptr::null_mut(),
Some(invoke_passwd_cb::<F>), Some(invoke_passwd_cb::<F>),
&mut cb as *mut _ as *mut _, &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( pub fn private_key_from_pkcs8_passphrase(
der: &[u8], der: &[u8],
passphrase: &[u8], passphrase: &[u8],
) -> Result<PKey, ErrorStack> { ) -> Result<PKey<Private>, ErrorStack> {
unsafe { unsafe {
ffi::init(); ffi::init();
let bio = MemBioSlice::new(der)?; let bio = MemBioSlice::new(der)?;
@ -199,81 +252,14 @@ impl PKey {
ptr::null_mut(), ptr::null_mut(),
None, None,
passphrase.as_ptr() as *const _ as *mut _, passphrase.as_ptr() as *const _ as *mut _,
)).map(PKey) )).map(|p| PKey::from_ptr(p))
} }
} }
} }
foreign_type_and_impl_send_sync! { impl PKey<Public> {
type CType = ffi::EVP_PKEY_CTX; public_key_from_pem!(PKey<Public>, ffi::PEM_read_bio_PUBKEY);
fn drop = ffi::EVP_PKEY_CTX_free; public_key_from_der!(PKey<Public>, ffi::d2i_PUBKEY);
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)
}
} }
#[cfg(test)] #[cfg(test)]
@ -281,7 +267,7 @@ mod tests {
use symm::Cipher; use symm::Cipher;
use dh::Dh; use dh::Dh;
use dsa::Dsa; use dsa::Dsa;
use ec::{EcGroup, EcKey}; use ec::EcKey;
use rsa::Rsa; use rsa::Rsa;
use nid::Nid; use nid::Nid;
@ -385,18 +371,4 @@ mod tests {
pkey.ec_key().unwrap(); pkey.ec_key().unwrap();
assert!(pkey.rsa().is_err()); 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());
}
} }

View File

@ -3,11 +3,12 @@ use std::fmt;
use std::ptr; use std::ptr;
use std::mem; use std::mem;
use libc::c_int; use libc::c_int;
use foreign_types::ForeignTypeRef; use foreign_types::{ForeignType, ForeignTypeRef};
use {cvt, cvt_n, cvt_p}; use {cvt, cvt_n, cvt_p};
use bn::{BigNum, BigNumRef}; use bn::{BigNum, BigNumRef};
use error::ErrorStack; use error::ErrorStack;
use pkey::{HasPrivate, HasPublic, Private, Public};
/// Type of encryption padding to use. /// Type of encryption padding to use.
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -27,34 +28,21 @@ impl Padding {
pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_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; type CType = ffi::RSA;
fn drop = ffi::RSA_free; fn drop = ffi::RSA_free;
pub struct Rsa; pub struct Rsa<T>;
pub struct RsaRef; pub struct RsaRef<T>;
} }
impl RsaRef { impl<T> RsaRef<T>
where
T: HasPrivate,
{
// FIXME these need to specify output format // FIXME these need to specify output format
private_key_to_pem!(ffi::PEM_write_bio_RSAPrivateKey); 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); 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. /// Decrypts data using the private key, returning the number of decrypted bytes.
/// ///
@ -68,7 +56,6 @@ impl RsaRef {
to: &mut [u8], to: &mut [u8],
padding: Padding, padding: Padding,
) -> Result<usize, ErrorStack> { ) -> Result<usize, ErrorStack> {
assert!(self.d().is_some(), "private components missing");
assert!(from.len() <= i32::max_value() as usize); assert!(from.len() <= i32::max_value() as usize);
assert!(to.len() >= self.size() as usize); assert!(to.len() >= self.size() as usize);
@ -96,7 +83,6 @@ impl RsaRef {
to: &mut [u8], to: &mut [u8],
padding: Padding, padding: Padding,
) -> Result<usize, ErrorStack> { ) -> Result<usize, ErrorStack> {
assert!(self.d().is_some(), "private components missing");
assert!(from.len() <= i32::max_value() as usize); assert!(from.len() <= i32::max_value() as usize);
assert!(to.len() >= self.size() as usize); assert!(to.len() >= self.size() as usize);
@ -112,88 +98,10 @@ impl RsaRef {
} }
} }
/// Decrypts data using the public key, returning the number of decrypted bytes. pub fn d(&self) -> &BigNumRef {
///
/// # Panics
///
/// Panics if `to` is smaller than `self.size()`.
pub fn public_decrypt(
&self,
from: &[u8],
to: &mut [u8],
padding: Padding,
) -> Result<usize, ErrorStack> {
assert!(from.len() <= i32::max_value() as usize);
assert!(to.len() >= self.size() as usize);
unsafe {
let len = cvt_n(ffi::RSA_public_decrypt(
from.len() as c_int,
from.as_ptr(),
to.as_mut_ptr(),
self.as_ptr(),
padding.0,
))?;
Ok(len as usize)
}
}
/// Encrypts data using the public key, returning the number of encrypted bytes.
///
/// # Panics
///
/// Panics if `to` is smaller than `self.size()`.
pub fn public_encrypt(
&self,
from: &[u8],
to: &mut [u8],
padding: Padding,
) -> Result<usize, ErrorStack> {
assert!(from.len() <= i32::max_value() as usize);
assert!(to.len() >= self.size() as usize);
unsafe {
let len = cvt_n(ffi::RSA_public_encrypt(
from.len() as c_int,
from.as_ptr(),
to.as_mut_ptr(),
self.as_ptr(),
padding.0,
))?;
Ok(len as usize)
}
}
pub fn n(&self) -> Option<&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 { unsafe {
let d = compat::key(self.as_ptr())[2]; let d = compat::key(self.as_ptr())[2];
if d.is_null() { BigNumRef::from_ptr(d as *mut _)
None
} else {
Some(BigNumRef::from_ptr(d as *mut _))
}
}
}
pub fn e(&self) -> Option<&BigNumRef> {
unsafe {
let e = compat::key(self.as_ptr())[1];
if e.is_null() {
None
} else {
Some(BigNumRef::from_ptr(e as *mut _))
}
} }
} }
@ -253,12 +161,94 @@ impl RsaRef {
} }
} }
impl Rsa { impl<T> RsaRef<T>
/// only useful for associating the key material directly with the key, it's safer to use where
/// the supplied load and save methods for DER formatted keys. T: HasPublic,
pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa, ErrorStack> { {
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
///
/// Panics if `to` is smaller than `self.size()`.
pub fn public_decrypt(
&self,
from: &[u8],
to: &mut [u8],
padding: Padding,
) -> Result<usize, ErrorStack> {
assert!(from.len() <= i32::max_value() as usize);
assert!(to.len() >= self.size() as usize);
unsafe { unsafe {
let rsa = Rsa(cvt_p(ffi::RSA_new())?); let len = cvt_n(ffi::RSA_public_decrypt(
from.len() as c_int,
from.as_ptr(),
to.as_mut_ptr(),
self.as_ptr(),
padding.0,
))?;
Ok(len as usize)
}
}
/// Encrypts data using the public key, returning the number of encrypted bytes.
///
/// # Panics
///
/// Panics if `to` is smaller than `self.size()`.
pub fn public_encrypt(
&self,
from: &[u8],
to: &mut [u8],
padding: Padding,
) -> Result<usize, ErrorStack> {
assert!(from.len() <= i32::max_value() as usize);
assert!(to.len() >= self.size() as usize);
unsafe {
let len = cvt_n(ffi::RSA_public_encrypt(
from.len() as c_int,
from.as_ptr(),
to.as_mut_ptr(),
self.as_ptr(),
padding.0,
))?;
Ok(len as usize)
}
}
pub fn n(&self) -> &BigNumRef {
unsafe {
let n = compat::key(self.as_ptr())[0];
BigNumRef::from_ptr(n as *mut _)
}
}
pub fn e(&self) -> &BigNumRef {
unsafe {
let e = compat::key(self.as_ptr())[1];
BigNumRef::from_ptr(e as *mut _)
}
}
}
impl Rsa<Public> {
pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
unsafe {
let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?);
cvt(compat::set_key( cvt(compat::set_key(
rsa.0, rsa.0,
n.as_ptr(), 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( pub fn from_private_components(
n: BigNum, n: BigNum,
e: BigNum, e: BigNum,
@ -279,9 +281,9 @@ impl Rsa {
dp: BigNum, dp: BigNum,
dq: BigNum, dq: BigNum,
qi: BigNum, qi: BigNum,
) -> Result<Rsa, ErrorStack> { ) -> Result<Rsa<Private>, ErrorStack> {
unsafe { 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()))?; cvt(compat::set_key(rsa.0, n.as_ptr(), e.as_ptr(), d.as_ptr()))?;
mem::forget((n, e, d)); mem::forget((n, e, d));
cvt(compat::set_factors(rsa.0, p.as_ptr(), q.as_ptr()))?; 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. /// Generates a public/private key pair with the specified size.
/// ///
/// The public exponent will be 65537. /// 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(); ffi::init();
unsafe { 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)?; let e = BigNum::from_u32(ffi::RSA_F4 as u32)?;
cvt(ffi::RSA_generate_key_ex( cvt(ffi::RSA_generate_key_ex(
rsa.0, rsa.0,
@ -316,20 +318,11 @@ impl Rsa {
} }
// FIXME these need to identify input formats // FIXME these need to identify input formats
private_key_from_pem!(Rsa, ffi::PEM_read_bio_RSAPrivateKey); private_key_from_pem!(Rsa<Private>, ffi::PEM_read_bio_RSAPrivateKey);
private_key_from_der!(Rsa, ffi::d2i_RSAPrivateKey); private_key_from_der!(Rsa<Private>, 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
);
} }
impl fmt::Debug for Rsa { impl<T> fmt::Debug for Rsa<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Rsa") write!(f, "Rsa")
} }

View File

@ -69,8 +69,9 @@ use std::ptr;
use {cvt, cvt_p}; use {cvt, cvt_p};
use hash::MessageDigest; use hash::MessageDigest;
use pkey::{PKeyCtxRef, PKeyRef}; use pkey::{HasPrivate, HasPublic, PKeyRef};
use error::ErrorStack; use error::ErrorStack;
use rsa::Padding;
#[cfg(ossl110)] #[cfg(ossl110)]
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new}; 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. /// A type which computes cryptographic signatures of data.
pub struct Signer<'a> { pub struct Signer<'a> {
md_ctx: *mut ffi::EVP_MD_CTX, md_ctx: *mut ffi::EVP_MD_CTX,
pkey_ctx: *mut ffi::EVP_PKEY_CTX, pctx: *mut ffi::EVP_PKEY_CTX,
pkey_pd: PhantomData<&'a PKeyRef>, _p: PhantomData<&'a ()>,
} }
impl<'a> Drop for Signer<'a> { impl<'a> Drop for Signer<'a> {
@ -99,7 +100,10 @@ impl<'a> Signer<'a> {
/// OpenSSL documentation at [`EVP_DigestSignInit`]. /// OpenSSL documentation at [`EVP_DigestSignInit`].
/// ///
/// [`EVP_DigestSignInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html /// [`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 { unsafe {
ffi::init(); ffi::init();
@ -121,20 +125,39 @@ impl<'a> Signer<'a> {
Ok(Signer { Ok(Signer {
md_ctx: ctx, md_ctx: ctx,
pkey_ctx: pctx, pctx,
pkey_pd: PhantomData, _p: PhantomData,
}) })
} }
} }
/// Returns a shared reference to the `PKeyCtx` associated with the `Signer`. /// Returns the RSA padding mode in use.
pub fn pkey_ctx(&self) -> &PKeyCtxRef { ///
unsafe { PKeyCtxRef::from_ptr(self.pkey_ctx) } /// 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`. /// Sets the RSA padding mode.
pub fn pkey_ctx_mut(&mut self) -> &mut PKeyCtxRef { ///
unsafe { PKeyCtxRef::from_ptr_mut(self.pkey_ctx) } /// 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`. /// Feeds more data into the `Signer`.
@ -217,8 +240,8 @@ impl<'a> Write for Signer<'a> {
pub struct Verifier<'a> { pub struct Verifier<'a> {
md_ctx: *mut ffi::EVP_MD_CTX, md_ctx: *mut ffi::EVP_MD_CTX,
pkey_ctx: *mut ffi::EVP_PKEY_CTX, pctx: *mut ffi::EVP_PKEY_CTX,
pkey_pd: PhantomData<&'a PKeyRef>, pkey_pd: PhantomData<&'a ()>,
} }
impl<'a> Drop for Verifier<'a> { impl<'a> Drop for Verifier<'a> {
@ -237,7 +260,10 @@ impl<'a> Verifier<'a> {
/// OpenSSL documentation at [`EVP_DigestVerifyInit`]. /// OpenSSL documentation at [`EVP_DigestVerifyInit`].
/// ///
/// [`EVP_DigestVerifyInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestVerifyInit.html /// [`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 { unsafe {
ffi::init(); ffi::init();
@ -259,20 +285,39 @@ impl<'a> Verifier<'a> {
Ok(Verifier { Ok(Verifier {
md_ctx: ctx, md_ctx: ctx,
pkey_ctx: pctx, pctx,
pkey_pd: PhantomData, pkey_pd: PhantomData,
}) })
} }
} }
/// Returns a shared reference to the `PKeyCtx` associated with the `Verifier`. /// Returns the RSA padding mode in use.
pub fn pkey_ctx(&self) -> &PKeyCtxRef { ///
unsafe { PKeyCtxRef::from_ptr(self.pkey_ctx) } /// 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`. /// Sets the RSA padding mode.
pub fn pkey_ctx_mut(&mut self) -> &mut PKeyCtxRef { ///
unsafe { PKeyCtxRef::from_ptr_mut(self.pkey_ctx) } /// 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`. /// Feeds more data into the `Verifier`.
@ -368,11 +413,8 @@ mod test {
let pkey = PKey::from_rsa(private_key).unwrap(); let pkey = PKey::from_rsa(private_key).unwrap();
let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap(); let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap();
assert_eq!(signer.pkey_ctx_mut().rsa_padding().unwrap(), Padding::PKCS1); assert_eq!(signer.rsa_padding().unwrap(), Padding::PKCS1);
signer signer.set_rsa_padding(Padding::PKCS1).unwrap();
.pkey_ctx_mut()
.set_rsa_padding(Padding::PKCS1)
.unwrap();
signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
let result = signer.sign_to_vec().unwrap(); let result = signer.sign_to_vec().unwrap();
@ -386,10 +428,7 @@ mod test {
let pkey = PKey::from_rsa(private_key).unwrap(); let pkey = PKey::from_rsa(private_key).unwrap();
let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
assert_eq!( assert_eq!(verifier.rsa_padding().unwrap(), Padding::PKCS1);
verifier.pkey_ctx_mut().rsa_padding().unwrap(),
Padding::PKCS1
);
verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
assert!(verifier.verify(&Vec::from_hex(SIGNATURE).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(); let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
verifier.update(b"foobar").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] #[test]

View File

@ -10,6 +10,7 @@ use error::ErrorStack;
use dh::Dh; use dh::Dh;
#[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))] #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))]
use ec::EcKey; use ec::EcKey;
use pkey::Params;
use ssl::{get_callback_idx, get_ssl_callback_idx, SniError, SslRef}; use ssl::{get_callback_idx, get_ssl_callback_idx, SniError, SslRef};
#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
use ssl::AlpnError; use ssl::AlpnError;
@ -147,7 +148,7 @@ pub unsafe extern "C" fn raw_tmp_dh<F>(
keylength: c_int, keylength: c_int,
) -> *mut ffi::DH ) -> *mut ffi::DH
where 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 ctx = ffi::SSL_get_SSL_CTX(ssl);
let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>()); 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, keylength: c_int,
) -> *mut ffi::EC_KEY ) -> *mut ffi::EC_KEY
where 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 ctx = ffi::SSL_get_SSL_CTX(ssl);
let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>()); 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, keylength: c_int,
) -> *mut ffi::DH ) -> *mut ffi::DH
where 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 = ffi::SSL_get_ex_data(ssl, get_ssl_callback_idx::<F>());
let callback = &*(callback as *mut F); let callback = &*(callback as *mut F);
@ -226,7 +227,7 @@ pub unsafe extern "C" fn raw_tmp_ecdh_ssl<F>(
keylength: c_int, keylength: c_int,
) -> *mut ffi::EC_KEY ) -> *mut ffi::EC_KEY
where 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 = ffi::SSL_get_ex_data(ssl, get_ssl_callback_idx::<F>());
let callback = &*(callback as *mut F); let callback = &*(callback as *mut F);

View File

@ -92,7 +92,7 @@ use x509::store::{X509StoreBuilderRef, X509StoreRef};
use x509::store::X509Store; use x509::store::X509Store;
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, ossl110))]
use verify::X509VerifyParamRef; use verify::X509VerifyParamRef;
use pkey::PKeyRef; use pkey::{HasPrivate, PKeyRef, Params, Private};
use error::ErrorStack; use error::ErrorStack;
use ex_data::Index; use ex_data::Index;
use stack::{Stack, StackRef}; use stack::{Stack, StackRef};
@ -630,7 +630,7 @@ impl SslContextBuilder {
/// This corresponds to [`SSL_CTX_set_tmp_dh`]. /// 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 /// [`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(|_| ()) } 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 /// [`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) pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
where 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 { unsafe {
let callback = Box::new(callback); 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. /// Sets the parameters to be used during ephemeral elliptic curve Diffie-Hellman key exchange.
/// ///
/// This corresponds to `SSL_CTX_set_tmp_ecdh`. /// 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 { unsafe {
cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr())
as c_int) as c_int)
@ -684,7 +684,7 @@ impl SslContextBuilder {
#[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))] #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))]
pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
where 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 { unsafe {
let callback = Box::new(callback); let callback = Box::new(callback);
@ -864,7 +864,10 @@ impl SslContextBuilder {
/// This corresponds to [`SSL_CTX_use_PrivateKey`]. /// 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 /// [`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(|_| ()) } 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 /// [`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)))] #[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 { unsafe {
let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr()); let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
if ptr.is_null() { if ptr.is_null() {
@ -1535,7 +1538,7 @@ impl SslRef {
/// ///
/// [`SslContextBuilder::set_tmp_dh`]: struct.SslContextBuilder.html#method.set_tmp_dh /// [`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 /// [`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(|_| ()) } 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 /// [`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) pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
where 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 { unsafe {
let callback = Box::new(callback); let callback = Box::new(callback);
@ -1566,7 +1569,7 @@ impl SslRef {
/// This corresponds to `SSL_set_tmp_ecdh`. /// This corresponds to `SSL_set_tmp_ecdh`.
/// ///
/// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.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(|_| ()) } 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)))] #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))]
pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
where 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 { unsafe {
let callback = Box::new(callback); let callback = Box::new(callback);
@ -1723,7 +1726,7 @@ impl SslRef {
/// This corresponds to `SSL_get_privatekey`. /// This corresponds to `SSL_get_privatekey`.
/// ///
/// [`SslContext::private_key`]: struct.SslContext.html#method.private_key /// [`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 { unsafe {
let ptr = ffi::SSL_get_privatekey(self.as_ptr()); let ptr = ffi::SSL_get_privatekey(self.as_ptr());
if ptr.is_null() { if ptr.is_null() {
@ -2038,10 +2041,9 @@ impl Ssl {
ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock( ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock(
MidHandshakeSslStream { stream, error }, MidHandshakeSslStream { stream, error },
)), )),
_ => Err(HandshakeError::Failure(MidHandshakeSslStream { _ => Err(HandshakeError::Failure(
stream, MidHandshakeSslStream { stream, error },
error, )),
})),
} }
} }
} }
@ -2070,10 +2072,9 @@ impl Ssl {
ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock( ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock(
MidHandshakeSslStream { stream, error }, MidHandshakeSslStream { stream, error },
)), )),
_ => Err(HandshakeError::Failure(MidHandshakeSslStream { _ => Err(HandshakeError::Failure(
stream, MidHandshakeSslStream { stream, error },
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(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
Err(e) => { Err(e) => {
return Err(e.into_io_error() return Err(
.unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))) 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), Ok(n) => return Ok(n),
Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
Err(e) => { Err(e) => {
return Err(e.into_io_error() return Err(
.unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))) e.into_io_error()
.unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)),
)
} }
} }
} }

View File

@ -19,7 +19,7 @@ use error::ErrorStack;
use ex_data::Index; use ex_data::Index;
use hash::MessageDigest; use hash::MessageDigest;
use nid::Nid; use nid::Nid;
use pkey::{PKey, PKeyRef}; use pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public};
use stack::{Stack, StackRef, Stackable}; use stack::{Stack, StackRef, Stackable};
use string::OpensslString; use string::OpensslString;
use ssl::SslRef; use ssl::SslRef;
@ -196,7 +196,10 @@ impl X509Builder {
} }
/// Sets the public key associated with the certificate. /// 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(|_| ()) } 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. /// 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(|_| ()) } 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 { unsafe {
let pkey = cvt_p(ffi::X509_get_pubkey(self.as_ptr()))?; let pkey = cvt_p(ffi::X509_get_pubkey(self.as_ptr()))?;
Ok(PKey::from_ptr(pkey)) 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(|_| ()) } 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 { unsafe {
cvt(ffi::X509_REQ_sign( cvt(ffi::X509_REQ_sign(
self.0.as_ptr(), self.0.as_ptr(),

View File

@ -4,14 +4,14 @@ use asn1::Asn1Time;
use bn::{BigNum, MsbOption}; use bn::{BigNum, MsbOption};
use hash::MessageDigest; use hash::MessageDigest;
use nid::Nid; use nid::Nid;
use pkey::PKey; use pkey::{PKey, Private};
use rsa::Rsa; use rsa::Rsa;
use stack::Stack; use stack::Stack;
use x509::{X509, X509Name, X509Req, X509VerifyResult}; use x509::{X509, X509Name, X509Req, X509VerifyResult};
use x509::extension::{AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, use x509::extension::{AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage,
SubjectAlternativeName, SubjectKeyIdentifier}; SubjectAlternativeName, SubjectKeyIdentifier};
fn pkey() -> PKey { fn pkey() -> PKey<Private> {
let rsa = Rsa::generate(2048).unwrap(); let rsa = Rsa::generate(2048).unwrap();
PKey::from_rsa(rsa).unwrap() PKey::from_rsa(rsa).unwrap()
} }