blob: 7ec6643e6e82eefc3ef389fe182bc5a029179c09 [file] [log] [blame]
// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
//! Public key cryptography.
pub mod ec;
pub mod ed25519;
pub mod rsa;
use boringssl::{CHeapWrapper, CStackWrapper};
use public::inner::BoringDerKey;
use util::Sealed;
use Error;
/// The public component of a public/private key pair.
pub trait PublicKey: Sealed + Sized {
/// The type of the private component.
type Private: PrivateKey<Public = Self>;
/// Verifies a message with this public key.
///
/// `verify` verifies that a message was signed by the private key
/// corresponding to this public key. It is equivalent to
/// `signature.verify(self, message)`.
#[must_use]
fn verify<S: Signature<PrivateKey = Self::Private>>(
&self,
message: &[u8],
signature: &S,
) -> bool {
signature.verify(self, message)
}
}
/// The private component of a public/private key pair.
pub trait PrivateKey: Sealed + Sized {
/// The type of the public component.
type Public: PublicKey<Private = Self>;
/// Gets the public key corresponding to this private key.
#[must_use]
fn public(&self) -> Self::Public;
/// Signs a message with this private key.
///
/// `sign` signs a message with this key using the signature scheme `S`. It
/// is equivalent to `S::sign(self, message)`.
#[must_use]
fn sign<S: Signature<PrivateKey = Self>>(&self, message: &[u8]) -> Result<S, Error> {
S::sign(self, message)
}
}
/// A public key which can be encoded as a DER object.
pub trait DerPublicKey: PublicKey + self::inner::DerKey {
/// Marshals a public key in DER format.
///
/// `marshal_to_der` marshals a public key as a DER-encoded
/// SubjectPublicKeyInfo structure as defined in [RFC 5280].
///
/// [RFC 5280]: https://tools.ietf.org/html/rfc5280
#[must_use]
fn marshal_to_der(&self) -> Vec<u8> {
let mut evp_pkey = CHeapWrapper::default();
self.boring().pkey_assign(&mut evp_pkey);
// cbb_new can only fail due to OOM
let mut cbb = CStackWrapper::cbb_new(64).unwrap();
evp_pkey
.evp_marshal_public_key(&mut cbb)
.expect("failed to marshal public key");
cbb.cbb_with_data(<[u8]>::to_vec)
}
/// Parses a public key in DER format.
///
/// `parse_from_der` parses a public key from a DER-encoded
/// SubjectPublicKeyInfo structure as defined in [RFC 5280].
///
/// # Elliptic Curve Keys
///
/// For Elliptic Curve keys ([`EcPubKey`]), the curve itself is validated.
/// If the curve is not known ahead of time, and any curve must be supported
/// at runtime, use the [`EcPubKeyAnyCurve::parse_from_der`] function.
///
/// [RFC 5280]: https://tools.ietf.org/html/rfc5280
/// [`EcPubKey`]: ::public::ec::EcPubKey
/// [`EcPubKeyAnyCurve::parse_from_der`]: ::public::ec::EcPubKeyAnyCurve::parse_from_der
#[must_use]
fn parse_from_der(bytes: &[u8]) -> Result<Self, Error> {
CStackWrapper::cbs_with_temp_buffer(bytes, |cbs| {
let mut evp_pkey = CHeapWrapper::evp_parse_public_key(cbs)?;
// NOTE: For EC, panics if evp_pkey doesn't have its group set. This is
// OK because EVP_parse_public_key guarantees that the returned key has
// its group set.
let key = Self::Boring::pkey_get(&mut evp_pkey)?;
if cbs.cbs_len() > 0 {
return Err(Error::new("malformed DER input".to_string()));
}
Ok(Self::from_boring(key))
})
}
}
/// A private key which can be encoded as a DER object.
pub trait DerPrivateKey: PrivateKey + self::inner::DerKey {
/// Marshals a private key in DER format.
///
/// `marshal_to_der` marshal a private key as a DER-encoded structure. The
/// exact structure encoded depends on the type of key:
/// - For an EC key, it is an ECPrivateKey structure as defined in [RFC
/// 5915].
/// - For an RSA key, it is an RSAPrivateKey structure as defined in [RFC
/// 3447].
///
/// [RFC 5915]: https://tools.ietf.org/html/rfc5915
/// [RFC 3447]: https://tools.ietf.org/html/rfc3447
#[must_use]
fn marshal_to_der(&self) -> Vec<u8> {
// cbb_new can only fail due to OOM
let mut cbb = CStackWrapper::cbb_new(64).unwrap();
self.boring()
.marshal_private_key(&mut cbb)
.expect("failed to marshal private key");
cbb.cbb_with_data(<[u8]>::to_vec)
}
/// Parses a private key in DER format.
///
/// `parse_from_der` parses a private key from a DER-encoded format. The
/// exact structure expected depends on the type of key:
/// - For an EC key, it is an ECPrivateKey structure as defined in [RFC
/// 5915].
/// - For an RSA key, it is an RSAPrivateKey structure as defined in [RFC
/// 3447].
///
/// # Elliptic Curve Keys
///
/// For Elliptic Curve keys ([`EcPrivKey`]), the curve itself is validated. If
/// the curve is not known ahead of time, and any curve must be supported at
/// runtime, use the [`EcPrivKeyAnyCurve::parse_from_der`] function.
///
/// [RFC 5915]: https://tools.ietf.org/html/rfc5915
/// [RFC 3447]: https://tools.ietf.org/html/rfc3447
/// [`EcPrivKey`]: ::public::ec::EcPrivKey
/// [`EcPrivKeyAnyCurve::parse_from_der`]: ::public::ec::EcPrivKeyAnyCurve::parse_from_der
#[must_use]
fn parse_from_der(bytes: &[u8]) -> Result<Self, Error> {
CStackWrapper::cbs_with_temp_buffer(bytes, |cbs| {
let key = Self::Boring::parse_private_key(cbs)?;
if cbs.cbs_len() > 0 {
return Err(Error::new("malformed DER input".to_string()));
}
Ok(Self::from_boring(key))
})
}
}
/// A cryptographic signature generated by a private key.
pub trait Signature: Sealed + Sized {
/// The private key type used to generate this signature.
type PrivateKey: PrivateKey;
/// Sign a message.
///
/// The input to this function is always a message, never a digest. If a
/// signature scheme calls for hashing a message and signing the hash
/// digest, `sign` is responsible for both hashing and signing.
#[must_use]
fn sign(key: &Self::PrivateKey, message: &[u8]) -> Result<Self, Error>;
/// Verify a signature.
///
/// The input to this function is always a message, never a digest. If a
/// signature scheme calls for hashing a message and signing the hash
/// digest, `verify` is responsible for both hashing and verifying the
/// digest.
#[must_use]
fn verify(&self, key: &<Self::PrivateKey as PrivateKey>::Public, message: &[u8]) -> bool;
}
mod inner {
use boringssl::{self, CHeapWrapper, CStackWrapper};
use Error;
/// A wrapper around a BoringSSL key object.
pub trait BoringDerKey: Sized {
// evp_pkey_assign_xxx
fn pkey_assign(&self, pkey: &mut CHeapWrapper<boringssl::EVP_PKEY>);
// evp_pkey_get_xxx; panics if the key is an EC key and doesn't have a group set,
// and errors if pkey isn't the expected key type
fn pkey_get(pkey: &mut CHeapWrapper<boringssl::EVP_PKEY>) -> Result<Self, Error>;
// xxx_parse_private_key
fn parse_private_key(cbs: &mut CStackWrapper<boringssl::CBS>) -> Result<Self, Error>;
// xxx_marshal_private_key
fn marshal_private_key(&self, cbb: &mut CStackWrapper<boringssl::CBB>)
-> Result<(), Error>;
}
/// Properties shared by both public and private keys of a given type.
pub trait DerKey {
/// The underlying BoringSSL object wrapper type.
type Boring: BoringDerKey;
fn boring(&self) -> &Self::Boring;
fn from_boring(Self::Boring) -> Self;
}
}
#[cfg(test)]
mod testutil {
use super::*;
/// Smoke test a signature scheme.
///
/// `sig_from_bytes` takes a byte slice and converts it into a signature. If
/// the byte slice is too long, it either truncate it or treats it as
/// invalid (it's up to the caller). If the byte slice is too short, it
/// fills in the remaining bytes with zeroes.
pub fn test_signature_smoke<S: Signature, F: Fn(&[u8]) -> S, G: Fn(&S) -> &[u8]>(
key: &S::PrivateKey,
sig_from_bytes: F,
bytes_from_sig: G,
) {
// Sign the message, verify the signature, and return the signature.
// Also verify that, if the wrong signature is used, the signature fails
// to verify. Also verify that sig_from_bytes works.
fn sign_and_verify<S: Signature, F: Fn(&[u8]) -> S, G: Fn(&S) -> &[u8]>(
key: &S::PrivateKey,
message: &[u8],
sig_from_bytes: F,
bytes_from_sig: G,
) -> S {
let sig = S::sign(key, message).unwrap();
assert!(sig.verify(&key.public(), message));
// Make sure the PrivateKey::sign and PublicKey::verify convenience
// functions also work.
let sig = key.sign::<S>(message).unwrap();
assert!(key.public().verify(message, &sig));
let sig2 = S::sign(&key, bytes_from_sig(&sig)).unwrap();
assert!(!sig2.verify(&key.public(), message));
// Make sure the PrivateKey::sign and PublicKey::verify convenience
// functions also work.
let sig2 = key.sign::<S>(bytes_from_sig(&sig)).unwrap();
assert!(!key.public().verify(message, &sig2));
sig_from_bytes(bytes_from_sig(&sig))
}
// Sign an empty message, and verify the signature. Use the signature as
// the next message to test, and repeat many times.
let mut msg = Vec::new();
for _ in 0..16 {
msg = bytes_from_sig(&sign_and_verify(
key,
&msg,
&sig_from_bytes,
&bytes_from_sig,
))
.to_vec();
}
}
}