blob: adb3153652095009f2110a8747b7ccc03da58f36 [file] [log] [blame]
use crate::msgs::enums::{SignatureAlgorithm, SignatureScheme};
use crate::key;
use crate::error::TLSError;
use ring::{self, signature::{self, EcdsaKeyPair, RsaKeyPair}};
use webpki;
use std::sync::Arc;
use std::mem;
/// An abstract signing key.
pub trait SigningKey : Send + Sync {
/// Choose a `SignatureScheme` from those offered.
///
/// Expresses the choice by returning something that implements `Signer`,
/// using the chosen scheme.
fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>>;
/// What kind of key we have.
fn algorithm(&self) -> SignatureAlgorithm;
}
/// A thing that can sign a message.
pub trait Signer : Send + Sync {
/// Signs `message` using the selected scheme.
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, TLSError>;
/// Reveals which scheme will be used when you call `sign()`.
fn get_scheme(&self) -> SignatureScheme;
}
/// A packaged-together certificate chain, matching `SigningKey` and
/// optional stapled OCSP response and/or SCT list.
#[derive(Clone)]
pub struct CertifiedKey {
/// The certificate chain.
pub cert: Vec<key::Certificate>,
/// The certified key.
pub key: Arc<Box<dyn SigningKey>>,
/// An optional OCSP response from the certificate issuer,
/// attesting to its continued validity.
pub ocsp: Option<Vec<u8>>,
/// An optional collection of SCTs from CT logs, proving the
/// certificate is included on those logs. This must be
/// a `SignedCertificateTimestampList` encoding; see RFC6962.
pub sct_list: Option<Vec<u8>>,
}
impl CertifiedKey {
/// Make a new CertifiedKey, with the given chain and key.
///
/// The cert chain must not be empty. The first certificate in the chain
/// must be the end-entity certificate.
pub fn new(cert: Vec<key::Certificate>, key: Arc<Box<dyn SigningKey>>) -> CertifiedKey {
CertifiedKey {
cert,
key,
ocsp: None,
sct_list: None,
}
}
/// The end-entity certificate.
pub fn end_entity_cert(&self) -> Result<&key::Certificate, ()> {
self.cert.get(0).ok_or(())
}
/// Steal ownership of the certificate chain.
pub fn take_cert(&mut self) -> Vec<key::Certificate> {
mem::replace(&mut self.cert, Vec::new())
}
/// Return true if there's an OCSP response.
pub fn has_ocsp(&self) -> bool {
self.ocsp.is_some()
}
/// Steal ownership of the OCSP response.
pub fn take_ocsp(&mut self) -> Option<Vec<u8>> {
mem::replace(&mut self.ocsp, None)
}
/// Return true if there's an SCT list.
pub fn has_sct_list(&self) -> bool {
self.sct_list.is_some()
}
/// Steal ownership of the SCT list.
pub fn take_sct_list(&mut self) -> Option<Vec<u8>> {
mem::replace(&mut self.sct_list, None)
}
/// Check the certificate chain for validity:
/// - it should be non-empty list
/// - the first certificate should be parsable as a x509v3,
/// - the first certificate should quote the given server name
/// (if provided)
///
/// These checks are not security-sensitive. They are the
/// *server* attempting to detect accidental misconfiguration.
pub fn cross_check_end_entity_cert(&self, name: Option<webpki::DNSNameRef>) -> Result<(), TLSError> {
// Always reject an empty certificate chain.
let end_entity_cert = self.end_entity_cert().map_err(|()| {
TLSError::General("No end-entity certificate in certificate chain".to_string())
})?;
// Reject syntactically-invalid end-entity certificates.
let end_entity_cert = webpki::EndEntityCert::from(end_entity_cert.as_ref()).map_err(|_| {
TLSError::General("End-entity certificate in certificate \
chain is syntactically invalid".to_string())
})?;
if let Some(name) = name {
// If SNI was offered then the certificate must be valid for
// that hostname. Note that this doesn't fully validate that the
// certificate is valid; it only validates that the name is one
// that the certificate is valid for, if the certificate is
// valid.
if end_entity_cert.verify_is_valid_for_dns_name(name).is_err() {
return Err(TLSError::General("The server certificate is not \
valid for the given name".to_string()));
}
}
Ok(())
}
}
/// Parse `der` as any supported key encoding/type, returning
/// the first which works.
pub fn any_supported_type(der: &key::PrivateKey) -> Result<Box<dyn SigningKey>, ()> {
if let Ok(rsa) = RSASigningKey::new(der) {
return Ok(Box::new(rsa));
}
any_ecdsa_type(der)
}
/// Parse `der` as any ECDSA key type, returning the first which works.
pub fn any_ecdsa_type(der: &key::PrivateKey) -> Result<Box<dyn SigningKey>, ()> {
if let Ok(ecdsa_p256) = SingleSchemeSigningKey::new(der,
SignatureScheme::ECDSA_NISTP256_SHA256,
&signature::ECDSA_P256_SHA256_ASN1_SIGNING) {
return Ok(Box::new(ecdsa_p256));
}
if let Ok(ecdsa_p384) = SingleSchemeSigningKey::new(der,
SignatureScheme::ECDSA_NISTP384_SHA384,
&signature::ECDSA_P384_SHA384_ASN1_SIGNING) {
return Ok(Box::new(ecdsa_p384));
}
Err(())
}
/// A `SigningKey` for RSA-PKCS1 or RSA-PSS
pub struct RSASigningKey {
key: Arc<RsaKeyPair>,
}
static ALL_RSA_SCHEMES: &[SignatureScheme] = &[
SignatureScheme::RSA_PSS_SHA512,
SignatureScheme::RSA_PSS_SHA384,
SignatureScheme::RSA_PSS_SHA256,
SignatureScheme::RSA_PKCS1_SHA512,
SignatureScheme::RSA_PKCS1_SHA384,
SignatureScheme::RSA_PKCS1_SHA256,
];
impl RSASigningKey {
/// Make a new `RSASigningKey` from a DER encoding, in either
/// PKCS#1 or PKCS#8 format.
pub fn new(der: &key::PrivateKey) -> Result<RSASigningKey, ()> {
RsaKeyPair::from_der(&der.0)
.or_else(|_| RsaKeyPair::from_pkcs8(&der.0))
.map(|s| {
RSASigningKey {
key: Arc::new(s),
}
})
.map_err(|_| ())
}
}
impl SigningKey for RSASigningKey {
fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
ALL_RSA_SCHEMES
.iter()
.filter(|scheme| offered.contains(scheme))
.nth(0)
.map(|scheme| RSASigner::new(self.key.clone(), *scheme))
}
fn algorithm(&self) -> SignatureAlgorithm {
SignatureAlgorithm::RSA
}
}
struct RSASigner {
key: Arc<RsaKeyPair>,
scheme: SignatureScheme,
encoding: &'static dyn signature::RsaEncoding
}
impl RSASigner {
fn new(key: Arc<RsaKeyPair>, scheme: SignatureScheme) -> Box<dyn Signer> {
let encoding: &dyn signature::RsaEncoding = match scheme {
SignatureScheme::RSA_PKCS1_SHA256 => &signature::RSA_PKCS1_SHA256,
SignatureScheme::RSA_PKCS1_SHA384 => &signature::RSA_PKCS1_SHA384,
SignatureScheme::RSA_PKCS1_SHA512 => &signature::RSA_PKCS1_SHA512,
SignatureScheme::RSA_PSS_SHA256 => &signature::RSA_PSS_SHA256,
SignatureScheme::RSA_PSS_SHA384 => &signature::RSA_PSS_SHA384,
SignatureScheme::RSA_PSS_SHA512 => &signature::RSA_PSS_SHA512,
_ => unreachable!(),
};
Box::new(RSASigner { key, scheme, encoding })
}
}
impl Signer for RSASigner {
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, TLSError> {
let mut sig = vec![0; self.key.public_modulus_len()];
let rng = ring::rand::SystemRandom::new();
self.key.sign(self.encoding, &rng, message, &mut sig)
.map(|_| sig)
.map_err(|_| TLSError::General("signing failed".to_string()))
}
fn get_scheme(&self) -> SignatureScheme {
self.scheme
}
}
/// A SigningKey that uses exactly one TLS-level SignatureScheme
/// and one ring-level signature::SigningAlgorithm.
///
/// Compare this to RSASigningKey, which for a particular key is
/// willing to sign with several algorithms. This is quite poor
/// cryptography practice, but is necessary because a given RSA key
/// is expected to work in TLS1.2 (PKCS#1 signatures) and TLS1.3
/// (PSS signatures) -- nobody is willing to obtain certificates for
/// different protocol versions.
///
/// Currently this is only implemented for ECDSA keys.
struct SingleSchemeSigningKey {
key: Arc<EcdsaKeyPair>,
scheme: SignatureScheme,
}
impl SingleSchemeSigningKey {
/// Make a new `ECDSASigningKey` from a DER encoding in PKCS#8 format,
/// expecting a key usable with precisely the given signature scheme.
pub fn new(der: &key::PrivateKey,
scheme: SignatureScheme,
sigalg: &'static signature::EcdsaSigningAlgorithm) -> Result<SingleSchemeSigningKey, ()> {
EcdsaKeyPair::from_pkcs8(sigalg, &der.0)
.map(|kp| SingleSchemeSigningKey { key: Arc::new(kp), scheme })
.map_err(|_| ())
}
}
impl SigningKey for SingleSchemeSigningKey {
fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
if offered.contains(&self.scheme) {
Some(Box::new(SingleSchemeSigner { key: self.key.clone(), scheme: self.scheme } ))
} else {
None
}
}
fn algorithm(&self) -> SignatureAlgorithm {
use crate::msgs::handshake::DecomposedSignatureScheme;
self.scheme.sign()
}
}
struct SingleSchemeSigner {
key: Arc<EcdsaKeyPair>,
scheme: SignatureScheme,
}
impl Signer for SingleSchemeSigner {
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, TLSError> {
let rng = ring::rand::SystemRandom::new();
self.key.sign(&rng, message)
.map_err(|_| TLSError::General("signing failed".into()))
.map(|sig| sig.as_ref().into())
}
fn get_scheme(&self) -> SignatureScheme {
self.scheme
}
}
/// The set of schemes we support for signatures and
/// that are allowed for TLS1.3.
pub fn supported_sign_tls13() -> &'static [SignatureScheme] {
&[
SignatureScheme::ECDSA_NISTP384_SHA384,
SignatureScheme::ECDSA_NISTP256_SHA256,
SignatureScheme::RSA_PSS_SHA512,
SignatureScheme::RSA_PSS_SHA384,
SignatureScheme::RSA_PSS_SHA256,
]
}