mod curve;
pub use public::ec::curve::{PCurve, P256, P384, P521};
use std::fmt::{self, Debug, Formatter};
use boringssl::{CHeapWrapper, CStackWrapper};
use public::ec::curve::CurveKind;
use public::ec::inner::EcKey;
use public::{inner::DerKey, DerPrivateKey, DerPublicKey, PrivateKey, PublicKey};
use util::Sealed;
use Error;
mod inner {
use std::marker::PhantomData;
use boringssl::{self, BoringError, CHeapWrapper, CStackWrapper};
use public::ec::curve::PCurve;
use public::inner::BoringDerKey;
use Error;
#[derive(Clone)]
pub struct EcKey<C: PCurve> {
pub key: CHeapWrapper<boringssl::EC_KEY>,
_marker: PhantomData<C>,
}
impl<C: PCurve> EcKey<C> {
pub fn generate() -> Result<EcKey<C>, BoringError> {
let mut key = CHeapWrapper::default();
key.ec_key_set_group(&C::group()).unwrap();
key.ec_key_generate_key()?;
Ok(EcKey { key, _marker: PhantomData })
}
#[allow(non_snake_case)]
pub fn from_EC_KEY(key: CHeapWrapper<boringssl::EC_KEY>) -> Result<EcKey<C>, Error> {
C::validate_group(key.ec_key_get0_group().unwrap())?;
Ok(EcKey { key, _marker: PhantomData })
}
}
impl<C: PCurve> BoringDerKey for EcKey<C> {
fn pkey_assign(&self, pkey: &mut CHeapWrapper<boringssl::EVP_PKEY>) {
pkey.evp_pkey_assign_ec_key(self.key.clone())
}
fn pkey_get(pkey: &mut CHeapWrapper<boringssl::EVP_PKEY>) -> Result<Self, Error> {
let key = pkey.evp_pkey_get1_ec_key()?;
EcKey::from_EC_KEY(key)
}
fn parse_private_key(cbs: &mut CStackWrapper<boringssl::CBS>) -> Result<EcKey<C>, Error> {
let key = CHeapWrapper::ec_key_parse_private_key(cbs, Some(C::group()))?;
EcKey::from_EC_KEY(key)
}
fn marshal_private_key(
&self,
cbb: &mut CStackWrapper<boringssl::CBB>,
) -> Result<(), Error> {
self.key.ec_key_marshal_private_key(cbb).map_err(From::from)
}
}
#[cfg(test)]
mod tests {
use std::mem;
use super::*;
use public::ec::{P256, P384, P521};
#[test]
fn test_refcount() {
fn test<C: PCurve>() {
let key = EcKey::<C>::generate().unwrap();
for i in 0..8 {
let mut keys = Vec::new();
for _ in 0..i {
keys.push(key.clone());
}
mem::drop(keys);
}
mem::drop(key);
}
test::<P256>();
test::<P384>();
test::<P521>();
}
}
}
pub struct EcPubKey<C: PCurve> {
inner: EcKey<C>,
}
impl<C: PCurve> Sealed for EcPubKey<C> {}
impl<C: PCurve> DerPublicKey for EcPubKey<C> {}
impl<C: PCurve> DerKey for EcPubKey<C> {
type Boring = EcKey<C>;
fn boring(&self) -> &EcKey<C> {
&self.inner
}
fn from_boring(inner: EcKey<C>) -> EcPubKey<C> {
EcPubKey { inner }
}
}
impl<C: PCurve> PublicKey for EcPubKey<C> {
type Private = EcPrivKey<C>;
}
impl<C: PCurve> Debug for EcPubKey<C> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "EcPubKey")
}
}
pub struct EcPrivKey<C: PCurve> {
inner: EcKey<C>,
}
impl<C: PCurve> EcPrivKey<C> {
#[must_use]
pub fn generate() -> Result<EcPrivKey<C>, Error> {
Ok(EcPrivKey { inner: EcKey::generate()? })
}
}
impl<C: PCurve> Sealed for EcPrivKey<C> {}
impl<C: PCurve> DerPrivateKey for EcPrivKey<C> {}
impl<C: PCurve> DerKey for EcPrivKey<C> {
type Boring = EcKey<C>;
fn boring(&self) -> &EcKey<C> {
&self.inner
}
fn from_boring(inner: EcKey<C>) -> EcPrivKey<C> {
EcPrivKey { inner }
}
}
impl<C: PCurve> PrivateKey for EcPrivKey<C> {
type Public = EcPubKey<C>;
fn public(&self) -> EcPubKey<C> {
EcPubKey { inner: self.inner.clone() }
}
}
impl<C: PCurve> Debug for EcPrivKey<C> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "EcPrivKey")
}
}
#[allow(missing_docs)]
#[derive(Debug)]
pub enum EcPubKeyAnyCurve {
P256(EcPubKey<P256>),
P384(EcPubKey<P384>),
P521(EcPubKey<P521>),
}
impl EcPubKeyAnyCurve {
#[must_use]
pub fn parse_from_der(bytes: &[u8]) -> Result<EcPubKeyAnyCurve, Error> {
CStackWrapper::cbs_with_temp_buffer(bytes, |cbs| {
let mut evp_pkey = CHeapWrapper::evp_parse_public_key(cbs)?;
let key = evp_pkey.evp_pkey_get1_ec_key()?;
if cbs.cbs_len() > 0 {
return Err(Error::new("excess data provided after valid DER input".to_string()));
}
let group = key.ec_key_get0_group().unwrap();
Ok(match CurveKind::from_nid(group.ec_group_get_curve_name())? {
CurveKind::P256 => {
EcPubKeyAnyCurve::P256(EcPubKey { inner: EcKey::from_EC_KEY(key.clone())? })
}
CurveKind::P384 => {
EcPubKeyAnyCurve::P384(EcPubKey { inner: EcKey::from_EC_KEY(key.clone())? })
}
CurveKind::P521 => {
EcPubKeyAnyCurve::P521(EcPubKey { inner: EcKey::from_EC_KEY(key.clone())? })
}
})
})
}
}
#[allow(missing_docs)]
#[derive(Debug)]
pub enum EcPrivKeyAnyCurve {
P256(EcPrivKey<P256>),
P384(EcPrivKey<P384>),
P521(EcPrivKey<P521>),
}
impl EcPrivKeyAnyCurve {
#[must_use]
pub fn public(&self) -> EcPubKeyAnyCurve {
match self {
EcPrivKeyAnyCurve::P256(key) => EcPubKeyAnyCurve::P256(key.public()),
EcPrivKeyAnyCurve::P384(key) => EcPubKeyAnyCurve::P384(key.public()),
EcPrivKeyAnyCurve::P521(key) => EcPubKeyAnyCurve::P521(key.public()),
}
}
#[must_use]
pub fn parse_from_der(bytes: &[u8]) -> Result<EcPrivKeyAnyCurve, Error> {
CStackWrapper::cbs_with_temp_buffer(bytes, |cbs| {
let key = CHeapWrapper::ec_key_parse_private_key(cbs, None)?;
if cbs.cbs_len() > 0 {
return Err(Error::new("excess data provided after valid DER input".to_string()));
}
let group = key.ec_key_get0_group().unwrap();
Ok(match CurveKind::from_nid(group.ec_group_get_curve_name())? {
CurveKind::P256 => {
EcPrivKeyAnyCurve::P256(EcPrivKey { inner: EcKey::from_EC_KEY(key.clone())? })
}
CurveKind::P384 => {
EcPrivKeyAnyCurve::P384(EcPrivKey { inner: EcKey::from_EC_KEY(key.clone())? })
}
CurveKind::P521 => {
EcPrivKeyAnyCurve::P521(EcPrivKey { inner: EcKey::from_EC_KEY(key.clone())? })
}
})
})
}
}
pub mod ecdsa {
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomData;
use boringssl;
#[cfg(feature = "experimental-sha512-ec")]
use hash::Sha512;
use hash::{inner::Digest, Hasher, Sha256, Sha384};
use public::{
ec::{EcPrivKey, EcPubKey, PCurve, P256, P384, P521},
Signature,
};
use util::Sealed;
use Error;
pub trait EcdsaHash<C: PCurve>: Sealed {}
impl EcdsaHash<P256> for Sha256 {}
impl EcdsaHash<P384> for Sha256 {}
impl EcdsaHash<P384> for Sha384 {}
impl EcdsaHash<P521> for Sha256 {}
impl EcdsaHash<P521> for Sha384 {}
#[cfg(feature = "experimental-sha512-ec")]
impl EcdsaHash<P384> for Sha512 {}
#[cfg(feature = "experimental-sha512-ec")]
impl EcdsaHash<P521> for Sha512 {}
const MAX_SIGNATURE_LEN: usize = 141;
#[must_use]
pub struct EcdsaSignature<C: PCurve, H: Hasher + EcdsaHash<C>> {
bytes: [u8; MAX_SIGNATURE_LEN],
len: usize,
_marker: PhantomData<(C, H)>,
}
impl<C: PCurve, H: Hasher + EcdsaHash<C>> EcdsaSignature<C, H> {
#[must_use]
pub fn from_bytes(bytes: &[u8]) -> EcdsaSignature<C, H> {
if bytes.len() > MAX_SIGNATURE_LEN {
return Self::empty();
}
let mut ret = Self::empty();
(&mut ret.bytes[..bytes.len()]).copy_from_slice(bytes);
ret.len = bytes.len();
ret
}
#[must_use]
pub fn bytes(&self) -> &[u8] {
&self.bytes[..self.len]
}
fn is_valid_format(&self) -> bool {
self.len != 0
}
fn empty() -> EcdsaSignature<C, H> {
EcdsaSignature { bytes: [0u8; MAX_SIGNATURE_LEN], len: 0, _marker: PhantomData }
}
}
impl<C: PCurve, H: Hasher + EcdsaHash<C>> Sealed for EcdsaSignature<C, H> {}
impl<C: PCurve, H: Hasher + EcdsaHash<C>> Signature for EcdsaSignature<C, H> {
type PrivateKey = EcPrivKey<C>;
fn sign(key: &EcPrivKey<C>, message: &[u8]) -> Result<EcdsaSignature<C, H>, Error> {
let digest = H::hash(message);
let mut sig = EcdsaSignature::empty();
sig.len = boringssl::ecdsa_sign(digest.as_ref(), &mut sig.bytes[..], &key.inner.key)?;
Ok(sig)
}
fn is_valid(&self, key: &EcPubKey<C>, message: &[u8]) -> bool {
if !self.is_valid_format() {
return false;
}
let digest = H::hash(message);
boringssl::ecdsa_verify(digest.as_ref(), self.bytes(), &key.inner.key)
}
}
impl<C: PCurve, H: Hasher + EcdsaHash<C>> Debug for EcdsaSignature<C, H> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "EcdsaSignature")
}
}
#[cfg(test)]
mod tests {
use super::{super::*, *};
use public::testutil::test_signature_smoke;
#[test]
fn test_smoke() {
let p256 = EcPrivKey::<P256>::generate().unwrap();
let p384 = EcPrivKey::<P384>::generate().unwrap();
let p521 = EcPrivKey::<P521>::generate().unwrap();
test_signature_smoke(
&p256,
EcdsaSignature::<_, Sha256>::from_bytes,
EcdsaSignature::bytes,
);
test_signature_smoke(
&p384,
EcdsaSignature::<_, Sha256>::from_bytes,
EcdsaSignature::bytes,
);
test_signature_smoke(
&p384,
EcdsaSignature::<_, Sha384>::from_bytes,
EcdsaSignature::bytes,
);
test_signature_smoke(
&p521,
EcdsaSignature::<_, Sha256>::from_bytes,
EcdsaSignature::bytes,
);
test_signature_smoke(
&p521,
EcdsaSignature::<_, Sha384>::from_bytes,
EcdsaSignature::bytes,
);
#[cfg(feature = "experimental-sha512-ec")]
{
test_signature_smoke(
&p384,
EcdsaSignature::<_, Sha512>::from_bytes,
EcdsaSignature::bytes,
);
test_signature_smoke(
&p521,
EcdsaSignature::<_, Sha512>::from_bytes,
EcdsaSignature::bytes,
);
}
}
#[test]
fn test_invalid_signature() {
fn test_is_invalid(sig: &EcdsaSignature<P256, Sha256>) {
assert_eq!(sig.len, 0);
assert!(!sig.is_valid_format());
assert!(!sig.is_valid(&EcPrivKey::<P256>::generate().unwrap().public(), &[],));
}
test_is_invalid(&EcdsaSignature::from_bytes(&[0; MAX_SIGNATURE_LEN + 1]));
test_is_invalid(&EcdsaSignature::from_bytes(&[]));
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use hash::Sha256;
use public::ec::ecdsa::*;
use public::Signature;
use util::should_fail;
#[test]
fn test_generate() {
EcPrivKey::<P256>::generate().unwrap();
EcPrivKey::<P384>::generate().unwrap();
EcPrivKey::<P521>::generate().unwrap();
}
#[test]
fn test_marshal_parse() {
fn test<
C: PCurve,
F: Fn(EcPrivKeyAnyCurve) -> EcPrivKey<C>,
G: Fn(EcPubKeyAnyCurve) -> EcPubKey<C>,
>(
unwrap_priv_any: F,
unwrap_pub_any: G,
) where
Sha256: EcdsaHash<C>,
{
const MESSAGE: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7];
let key = EcPrivKey::<C>::generate().unwrap();
let parsed_key = EcPrivKey::<C>::parse_from_der(&key.marshal_to_der()).unwrap();
let parsed_key_any_curve =
unwrap_priv_any(EcPrivKeyAnyCurve::parse_from_der(&key.marshal_to_der()).unwrap());
let pubkey = key.public();
let parsed_pubkey = EcPubKey::<C>::parse_from_der(&pubkey.marshal_to_der()).unwrap();
let parsed_pubkey_any_curve =
unwrap_pub_any(EcPubKeyAnyCurve::parse_from_der(&pubkey.marshal_to_der()).unwrap());
fn sign_and_verify<C: PCurve>(privkey: &EcPrivKey<C>, pubkey: &EcPubKey<C>)
where
Sha256: EcdsaHash<C>,
{
let sig = EcdsaSignature::<C, Sha256>::sign(&privkey, MESSAGE).unwrap();
assert!(
EcdsaSignature::<C, Sha256>::from_bytes(sig.bytes()).is_valid(&pubkey, MESSAGE)
)
}
sign_and_verify(&key, &pubkey);
sign_and_verify(&key, &parsed_pubkey);
sign_and_verify(&key, &parsed_pubkey_any_curve);
sign_and_verify(&parsed_key, &pubkey);
sign_and_verify(&parsed_key, &parsed_pubkey);
sign_and_verify(&parsed_key, &parsed_pubkey_any_curve);
sign_and_verify(&parsed_key_any_curve, &pubkey);
sign_and_verify(&parsed_key_any_curve, &parsed_pubkey);
sign_and_verify(&parsed_key_any_curve, &parsed_pubkey_any_curve);
let _ = EcPubKey::<C>::marshal_to_der;
let _ = EcPubKey::<C>::parse_from_der;
}
macro_rules! unwrap_any_curve {
($name:ident, $any_type:ty, $key_type:ty, $curve_variant:path) => {
fn $name(key: $any_type) -> $key_type {
match key {
$curve_variant(key) => key,
_ => panic!("unexpected curve"),
}
}
};
}
unwrap_any_curve!(
unwrap_priv_key_any_p256,
EcPrivKeyAnyCurve,
EcPrivKey<P256>,
EcPrivKeyAnyCurve::P256
);
unwrap_any_curve!(
unwrap_priv_key_any_p384,
EcPrivKeyAnyCurve,
EcPrivKey<P384>,
EcPrivKeyAnyCurve::P384
);
unwrap_any_curve!(
unwrap_priv_key_any_p521,
EcPrivKeyAnyCurve,
EcPrivKey<P521>,
EcPrivKeyAnyCurve::P521
);
unwrap_any_curve!(
unwrap_pub_key_any_p256,
EcPubKeyAnyCurve,
EcPubKey<P256>,
EcPubKeyAnyCurve::P256
);
unwrap_any_curve!(
unwrap_pub_key_any_p384,
EcPubKeyAnyCurve,
EcPubKey<P384>,
EcPubKeyAnyCurve::P384
);
unwrap_any_curve!(
unwrap_pub_key_any_p521,
EcPubKeyAnyCurve,
EcPubKey<P521>,
EcPubKeyAnyCurve::P521
);
test::<P256, _, _>(unwrap_priv_key_any_p256, unwrap_pub_key_any_p256);
test::<P384, _, _>(unwrap_priv_key_any_p384, unwrap_pub_key_any_p384);
test::<P521, _, _>(unwrap_priv_key_any_p521, unwrap_pub_key_any_p521);
}
#[test]
fn test_parse_fail() {
fn test_parse_invalid<C: PCurve>() {
should_fail(
EcPrivKey::<C>::parse_from_der(&[]),
"EcPrivKey::parse_from_der",
"elliptic curve routines:OPENSSL_internal:DECODE_ERROR",
);
should_fail(
EcPubKey::<C>::parse_from_der(&[]),
"EcPubKey::parse_from_der",
"public key routines:OPENSSL_internal:DECODE_ERROR",
);
should_fail(
EcPrivKeyAnyCurve::parse_from_der(&[]),
"EcPrivKeyAnyCurve::parse_from_der",
"elliptic curve routines:OPENSSL_internal:DECODE_ERROR",
);
should_fail(
EcPubKeyAnyCurve::parse_from_der(&[]),
"EcPubKeyAnyCurve::parse_from_der",
"public key routines:OPENSSL_internal:DECODE_ERROR",
);
}
test_parse_invalid::<P256>();
test_parse_invalid::<P384>();
test_parse_invalid::<P521>();
fn test_parse_wrong_curve<C1: PCurve, C2: PCurve>() {
let privkey = EcPrivKey::<C1>::generate().unwrap();
let key_der = privkey.marshal_to_der();
should_fail(
EcPrivKey::<C2>::parse_from_der(&key_der),
"EcPrivKey::parse_from_der",
"elliptic curve routines:OPENSSL_internal:GROUP_MISMATCH",
);
let key_der = privkey.public().marshal_to_der();
should_fail(
EcPubKey::<C2>::parse_from_der(&key_der),
"EcPubKey::parse_from_der",
"unexpected curve:",
);
}
test_parse_wrong_curve::<P256, P384>();
test_parse_wrong_curve::<P256, P521>();
test_parse_wrong_curve::<P384, P256>();
test_parse_wrong_curve::<P384, P521>();
test_parse_wrong_curve::<P521, P256>();
test_parse_wrong_curve::<P521, P384>();
}
}