Parameterize keys over what they contain

Closes #790
This commit is contained in:
Steven Fackler 2017-12-30 21:46:17 -08:00
parent 6238b4a20a
commit d207897458
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_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_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_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;

View File

@ -7,14 +7,14 @@ use openssl::asn1::Asn1Time;
use openssl::bn::{BigNum, MsbOption};
use openssl::error::ErrorStack;
use openssl::hash::MessageDigest;
use openssl::pkey::{PKey, PKeyRef};
use openssl::pkey::{PKey, PKeyRef, Private};
use openssl::rsa::Rsa;
use openssl::x509::{X509, X509NameBuilder, X509Ref, X509Req, X509ReqBuilder, X509VerifyResult};
use openssl::x509::extension::{AuthorityKeyIdentifier, BasicConstraints, KeyUsage,
SubjectAlternativeName, SubjectKeyIdentifier};
/// 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 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
fn mk_request(privkey: &PKey) -> Result<(X509Req), ErrorStack> {
fn mk_request(privkey: &PKey<Private>) -> Result<X509Req, ErrorStack> {
let mut req_builder = X509ReqBuilder::new()?;
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
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 privkey = PKey::from_rsa(rsa)?;

View File

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

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 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))
}
}
}

View File

@ -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);
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: 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`]
///
/// [`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 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 {
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)]

View File

@ -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`
///
/// 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
///
/// 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
pub fn private_key(&self) -> Option<&BigNumRef> {
pub fn private_key(&self) -> &BigNumRef {
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 _))
}
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> {
unsafe { cvt(ffi::EC_KEY_check_key(self.as_ptr())).map(|_| ()) }
}
}
/// 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) }
impl<T> ToOwned for EcKeyRef<T> {
type Owned = EcKey<T>;
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 {
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,
/// Constructs a public key from its affine coordinates.
pub fn from_public_key_affine_coordinates(
group: &EcGroupRef,
x: &BigNumRef,
y: &BigNumRef,
) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
) -> Result<EcKey<Public>, ErrorStack> {
unsafe {
cvt(ffi::EC_KEY_set_public_key_affine_coordinates(
self.as_ptr(),
x.as_ptr(),
y.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_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.
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) }
private_key_from_pem!(EcKey<Private>, ffi::PEM_read_bio_ECPrivateKey);
private_key_from_der!(EcKey<Private>, ffi::d2i_ECPrivateKey);
}
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();

View File

@ -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;

View File

@ -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>{}
};
}

View File

@ -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(),

View File

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

View File

@ -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,88 +98,10 @@ impl RsaRef {
}
}
/// 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 {
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> {
pub fn d(&self) -> &BigNumRef {
unsafe {
let d = compat::key(self.as_ptr())[2];
if d.is_null() {
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 _))
}
BigNumRef::from_ptr(d as *mut _)
}
}
@ -253,12 +161,94 @@ impl RsaRef {
}
}
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<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
///
/// 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 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(
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")
}

View File

@ -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]

View File

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

View File

@ -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)),
)
}
}
}

View File

@ -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(),

View File

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