use std::error::Error as StdError;
use std::fmt;
use std::sync::Arc;
use ring::io::der;
use ring::rand::SecureRandom;
use ring::signature::{self, EcdsaKeyPair, Ed25519KeyPair, RsaKeyPair};
use crate::tls::rustls::error::Error;
use crate::tls::rustls::key;
use crate::tls::rustls::msgs::enums::{SignatureAlgorithm, SignatureScheme};
use crate::tls::rustls::x509::{wrap_in_asn1_len, wrap_in_sequence};
pub trait SigningKey: Send + Sync {
fn choose_scheme(
&self,
offered: &[SignatureScheme],
rng: Box<dyn SecureRandom + Send + Sync>,
) -> Option<Box<dyn Signer>>;
fn algorithm(&self) -> SignatureAlgorithm;
}
pub trait Signer: Send + Sync {
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error>;
fn scheme(&self) -> SignatureScheme;
}
#[derive(Clone)]
pub struct CertifiedKey {
pub cert: Vec<key::Certificate>,
pub key: Arc<dyn SigningKey>,
pub ocsp: Option<Vec<u8>>,
pub sct_list: Option<Vec<u8>>,
}
impl CertifiedKey {
pub fn new(cert: Vec<key::Certificate>, key: Arc<dyn SigningKey>) -> Self {
Self {
cert,
key,
ocsp: None,
sct_list: None,
}
}
pub fn end_entity_cert(&self) -> Result<&key::Certificate, SignError> {
self.cert.first().ok_or(SignError(()))
}
pub fn cross_check_end_entity_cert(
&self,
name: Option<webpki::DnsNameRef>,
) -> Result<(), Error> {
let end_entity_cert = self.end_entity_cert().map_err(|SignError(())| {
Error::General("No end-entity certificate in certificate chain".to_string())
})?;
let end_entity_cert =
webpki::EndEntityCert::try_from(end_entity_cert.as_ref()).map_err(|_| {
Error::General(
"End-entity certificate in certificate \
chain is syntactically invalid"
.to_string(),
)
})?;
if let Some(name) = name {
if end_entity_cert.verify_is_valid_for_dns_name(name).is_err() {
return Err(Error::General(
"The server certificate is not \
valid for the given name"
.to_string(),
));
}
}
Ok(())
}
}
pub fn any_supported_type(der: &key::PrivateKey) -> Result<Arc<dyn SigningKey>, SignError> {
if let Ok(rsa) = RsaSigningKey::new(der) {
Ok(Arc::new(rsa))
} else if let Ok(ecdsa) = any_ecdsa_type(der) {
Ok(ecdsa)
} else {
any_eddsa_type(der)
}
}
pub fn any_ecdsa_type(der: &key::PrivateKey) -> Result<Arc<dyn SigningKey>, SignError> {
if let Ok(ecdsa_p256) = EcdsaSigningKey::new(
der,
SignatureScheme::ECDSA_NISTP256_SHA256,
&signature::ECDSA_P256_SHA256_ASN1_SIGNING,
) {
return Ok(Arc::new(ecdsa_p256));
}
if let Ok(ecdsa_p384) = EcdsaSigningKey::new(
der,
SignatureScheme::ECDSA_NISTP384_SHA384,
&signature::ECDSA_P384_SHA384_ASN1_SIGNING,
) {
return Ok(Arc::new(ecdsa_p384));
}
Err(SignError(()))
}
pub fn any_eddsa_type(der: &key::PrivateKey) -> Result<Arc<dyn SigningKey>, SignError> {
if let Ok(ed25519) = Ed25519SigningKey::new(der, SignatureScheme::ED25519) {
return Ok(Arc::new(ed25519));
}
Err(SignError(()))
}
#[doc(hidden)]
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 {
pub fn new(der: &key::PrivateKey) -> Result<Self, SignError> {
RsaKeyPair::from_der(&der.0)
.or_else(|_| RsaKeyPair::from_pkcs8(&der.0))
.map(|s| Self { key: Arc::new(s) })
.map_err(|_| SignError(()))
}
}
impl SigningKey for RsaSigningKey {
fn choose_scheme(
&self,
offered: &[SignatureScheme],
rng: Box<dyn SecureRandom + Send + Sync>,
) -> Option<Box<dyn Signer>> {
ALL_RSA_SCHEMES
.iter()
.find(|scheme| offered.contains(scheme))
.map(|scheme| RsaSigner::new(Arc::clone(&self.key), *scheme, rng))
}
fn algorithm(&self) -> SignatureAlgorithm {
SignatureAlgorithm::RSA
}
}
#[allow(clippy::upper_case_acronyms)]
#[doc(hidden)]
#[deprecated(since = "0.20.0", note = "Use RsaSigningKey")]
pub type RSASigningKey = RsaSigningKey;
pub struct RsaSigner {
key: Arc<RsaKeyPair>,
scheme: SignatureScheme,
encoding: &'static dyn signature::RsaEncoding,
rng: Box<dyn SecureRandom + Send + Sync>,
}
impl RsaSigner {
pub fn new(
key: Arc<RsaKeyPair>,
scheme: SignatureScheme,
rng: Box<dyn SecureRandom + Send + Sync>,
) -> 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(Self {
key,
scheme,
encoding,
rng,
})
}
}
impl Signer for RsaSigner {
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
let mut sig = vec![0; self.key.public_modulus_len()];
self.key
.sign(self.encoding, self.rng.as_ref(), message, &mut sig)
.map(|_| sig)
.map_err(|_| Error::General("signing failed".to_string()))
}
fn scheme(&self) -> SignatureScheme {
self.scheme
}
}
pub struct EcdsaSigningKey {
key: Arc<EcdsaKeyPair>,
scheme: SignatureScheme,
}
impl EcdsaSigningKey {
pub fn new(
der: &key::PrivateKey,
scheme: SignatureScheme,
sigalg: &'static signature::EcdsaSigningAlgorithm,
) -> Result<Self, ()> {
EcdsaKeyPair::from_pkcs8(sigalg, &der.0)
.map_err(|_| ())
.or_else(|_| Self::convert_sec1_to_pkcs8(scheme, sigalg, &der.0))
.map(|kp| Self {
key: Arc::new(kp),
scheme,
})
}
fn convert_sec1_to_pkcs8(
scheme: SignatureScheme,
sigalg: &'static signature::EcdsaSigningAlgorithm,
maybe_sec1_der: &[u8],
) -> Result<EcdsaKeyPair, ()> {
let pkcs8_prefix = match scheme {
SignatureScheme::ECDSA_NISTP256_SHA256 => &PKCS8_PREFIX_ECDSA_NISTP256,
SignatureScheme::ECDSA_NISTP384_SHA384 => &PKCS8_PREFIX_ECDSA_NISTP384,
_ => unreachable!(), };
let mut sec1_wrap = Vec::with_capacity(maybe_sec1_der.len() + 8);
sec1_wrap.extend_from_slice(maybe_sec1_der);
wrap_in_asn1_len(&mut sec1_wrap);
sec1_wrap.insert(0, der::Tag::OctetString as u8);
let mut pkcs8 = Vec::with_capacity(pkcs8_prefix.len() + sec1_wrap.len() + 4);
pkcs8.extend_from_slice(pkcs8_prefix);
pkcs8.extend_from_slice(&sec1_wrap);
wrap_in_sequence(&mut pkcs8);
EcdsaKeyPair::from_pkcs8(sigalg, &pkcs8).map_err(|_| ())
}
}
const PKCS8_PREFIX_ECDSA_NISTP256: &[u8] = b"\x02\x01\x00\
\x30\x13\
\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\
\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07";
const PKCS8_PREFIX_ECDSA_NISTP384: &[u8] = b"\x02\x01\x00\
\x30\x10\
\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\
\x06\x05\x2b\x81\x04\x00\x22";
impl SigningKey for EcdsaSigningKey {
fn choose_scheme(
&self,
offered: &[SignatureScheme],
rng: Box<dyn SecureRandom + Send + Sync>,
) -> Option<Box<dyn Signer>> {
if offered.contains(&self.scheme) {
Some(Box::new(EcdsaSigner {
key: Arc::clone(&self.key),
scheme: self.scheme,
rng,
}))
} else {
None
}
}
fn algorithm(&self) -> SignatureAlgorithm {
use crate::tls::rustls::msgs::handshake::DecomposedSignatureScheme;
self.scheme.sign()
}
}
pub struct EcdsaSigner {
pub key: Arc<EcdsaKeyPair>,
pub scheme: SignatureScheme,
pub rng: Box<dyn SecureRandom + Send + Sync>,
}
impl Signer for EcdsaSigner {
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
self.key
.sign(self.rng.as_ref(), message)
.map_err(|_| Error::General("signing failed".into()))
.map(|sig| sig.as_ref().into())
}
fn scheme(&self) -> SignatureScheme {
self.scheme
}
}
struct Ed25519SigningKey {
key: Arc<Ed25519KeyPair>,
scheme: SignatureScheme,
}
impl Ed25519SigningKey {
fn new(der: &key::PrivateKey, scheme: SignatureScheme) -> Result<Self, SignError> {
Ed25519KeyPair::from_pkcs8_maybe_unchecked(&der.0)
.map(|kp| Self {
key: Arc::new(kp),
scheme,
})
.map_err(|_| SignError(()))
}
}
impl SigningKey for Ed25519SigningKey {
fn choose_scheme(
&self,
offered: &[SignatureScheme],
_rng: Box<dyn SecureRandom + Send + Sync>,
) -> Option<Box<dyn Signer>> {
if offered.contains(&self.scheme) {
Some(Box::new(Ed25519Signer {
key: Arc::clone(&self.key),
scheme: self.scheme,
}))
} else {
None
}
}
fn algorithm(&self) -> SignatureAlgorithm {
use crate::tls::rustls::msgs::handshake::DecomposedSignatureScheme;
self.scheme.sign()
}
}
struct Ed25519Signer {
key: Arc<Ed25519KeyPair>,
scheme: SignatureScheme,
}
impl Signer for Ed25519Signer {
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
Ok(self.key.sign(message).as_ref().into())
}
fn scheme(&self) -> SignatureScheme {
self.scheme
}
}
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,
SignatureScheme::ED25519,
]
}
#[derive(Debug)]
pub struct SignError(());
impl fmt::Display for SignError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("sign error")
}
}
impl StdError for SignError {}
#[cfg(test)]
mod tests {
use super::*;
#[test_log::test]
fn can_load_ecdsa_nistp256_pkcs8() {
let key = key::PrivateKey(include_bytes!("testdata/nistp256key.pkcs8.der").to_vec());
assert!(any_supported_type(&key).is_ok());
assert!(any_ecdsa_type(&key).is_ok());
assert!(any_eddsa_type(&key).is_err());
}
#[test_log::test]
fn can_load_ecdsa_nistp256_sec1() {
let key = key::PrivateKey(include_bytes!("testdata/nistp256key.der").to_vec());
assert!(any_supported_type(&key).is_ok());
assert!(any_ecdsa_type(&key).is_ok());
assert!(any_eddsa_type(&key).is_err());
}
#[test_log::test]
fn can_load_ecdsa_nistp384_pkcs8() {
let key = key::PrivateKey(include_bytes!("testdata/nistp384key.pkcs8.der").to_vec());
assert!(any_supported_type(&key).is_ok());
assert!(any_ecdsa_type(&key).is_ok());
assert!(any_eddsa_type(&key).is_err());
}
#[test_log::test]
fn can_load_ecdsa_nistp384_sec1() {
let key = key::PrivateKey(include_bytes!("testdata/nistp384key.der").to_vec());
assert!(any_supported_type(&key).is_ok());
assert!(any_ecdsa_type(&key).is_ok());
assert!(any_eddsa_type(&key).is_err());
}
#[test_log::test]
fn can_load_eddsa_pkcs8() {
let key = key::PrivateKey(include_bytes!("testdata/eddsakey.der").to_vec());
assert!(any_supported_type(&key).is_ok());
assert!(any_eddsa_type(&key).is_ok());
assert!(any_ecdsa_type(&key).is_err());
}
#[test_log::test]
fn can_load_rsa2048_pkcs8() {
let key = key::PrivateKey(include_bytes!("testdata/rsa2048key.pkcs8.der").to_vec());
assert!(any_supported_type(&key).is_ok());
assert!(any_eddsa_type(&key).is_err());
assert!(any_ecdsa_type(&key).is_err());
}
#[test_log::test]
fn can_load_rsa2048_pkcs1() {
let key = key::PrivateKey(include_bytes!("testdata/rsa2048key.pkcs1.der").to_vec());
assert!(any_supported_type(&key).is_ok());
assert!(any_eddsa_type(&key).is_err());
assert!(any_ecdsa_type(&key).is_err());
}
}