| 1 | use alloc::boxed::Box; |
| 2 | use alloc::vec::Vec; |
| 3 | use core::fmt::Debug; |
| 4 | |
| 5 | use pki_types::{AlgorithmIdentifier, CertificateDer, PrivateKeyDer, SubjectPublicKeyInfoDer}; |
| 6 | |
| 7 | use crate::client::ResolvesClientCert; |
| 8 | use crate::enums::{SignatureAlgorithm, SignatureScheme}; |
| 9 | use crate::error::{Error, InconsistentKeys}; |
| 10 | use crate::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; |
| 11 | use crate::sync::Arc; |
| 12 | use crate::x509; |
| 13 | |
| 14 | use super::CryptoProvider; |
| 15 | |
| 16 | /// An abstract signing key. |
| 17 | /// |
| 18 | /// This interface is used by rustls to use a private signing key |
| 19 | /// for authentication. This includes server and client authentication. |
| 20 | /// |
| 21 | /// Objects of this type are always used within Rustls as |
| 22 | /// `Arc<dyn SigningKey>`. There are no concrete public structs in Rustls |
| 23 | /// that implement this trait. |
| 24 | /// |
| 25 | /// There are two main ways to get a signing key: |
| 26 | /// |
| 27 | /// - [`KeyProvider::load_private_key()`], or |
| 28 | /// - some other method outside of the `KeyProvider` extension trait, |
| 29 | /// for instance: |
| 30 | /// - [`crypto::ring::sign::any_ecdsa_type()`] |
| 31 | /// - [`crypto::ring::sign::any_eddsa_type()`] |
| 32 | /// - [`crypto::ring::sign::any_supported_type()`] |
| 33 | /// - [`crypto::aws_lc_rs::sign::any_ecdsa_type()`] |
| 34 | /// - [`crypto::aws_lc_rs::sign::any_eddsa_type()`] |
| 35 | /// - [`crypto::aws_lc_rs::sign::any_supported_type()`] |
| 36 | /// |
| 37 | /// The `KeyProvider` method `load_private_key()` is called under the hood by |
| 38 | /// [`ConfigBuilder::with_single_cert()`], |
| 39 | /// [`ConfigBuilder::with_client_auth_cert()`], and |
| 40 | /// [`ConfigBuilder::with_single_cert_with_ocsp()`]. |
| 41 | /// |
| 42 | /// A signing key created outside of the `KeyProvider` extension trait can be used |
| 43 | /// to create a [`CertifiedKey`], which in turn can be used to create a |
| 44 | /// [`ResolvesServerCertUsingSni`]. Alternately, a `CertifiedKey` can be returned from a |
| 45 | /// custom implementation of the [`ResolvesServerCert`] or [`ResolvesClientCert`] traits. |
| 46 | /// |
| 47 | /// [`KeyProvider::load_private_key()`]: crate::crypto::KeyProvider::load_private_key |
| 48 | /// [`ConfigBuilder::with_single_cert()`]: crate::ConfigBuilder::with_single_cert |
| 49 | /// [`ConfigBuilder::with_single_cert_with_ocsp()`]: crate::ConfigBuilder::with_single_cert_with_ocsp |
| 50 | /// [`ConfigBuilder::with_client_auth_cert()`]: crate::ConfigBuilder::with_client_auth_cert |
| 51 | /// [`crypto::ring::sign::any_ecdsa_type()`]: crate::crypto::ring::sign::any_ecdsa_type |
| 52 | /// [`crypto::ring::sign::any_eddsa_type()`]: crate::crypto::ring::sign::any_eddsa_type |
| 53 | /// [`crypto::ring::sign::any_supported_type()`]: crate::crypto::ring::sign::any_supported_type |
| 54 | /// [`crypto::aws_lc_rs::sign::any_ecdsa_type()`]: crate::crypto::aws_lc_rs::sign::any_ecdsa_type |
| 55 | /// [`crypto::aws_lc_rs::sign::any_eddsa_type()`]: crate::crypto::aws_lc_rs::sign::any_eddsa_type |
| 56 | /// [`crypto::aws_lc_rs::sign::any_supported_type()`]: crate::crypto::aws_lc_rs::sign::any_supported_type |
| 57 | /// [`ResolvesServerCertUsingSni`]: crate::server::ResolvesServerCertUsingSni |
| 58 | /// [`ResolvesServerCert`]: crate::server::ResolvesServerCert |
| 59 | /// [`ResolvesClientCert`]: crate::client::ResolvesClientCert |
| 60 | pub trait SigningKey: Debug + Send + Sync { |
| 61 | /// Choose a `SignatureScheme` from those offered. |
| 62 | /// |
| 63 | /// Expresses the choice by returning something that implements `Signer`, |
| 64 | /// using the chosen scheme. |
| 65 | fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>>; |
| 66 | |
| 67 | /// Get the RFC 5280-compliant SubjectPublicKeyInfo (SPKI) of this [`SigningKey`] if available. |
| 68 | fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> { |
| 69 | // Opt-out by default |
| 70 | None |
| 71 | } |
| 72 | |
| 73 | /// What kind of key we have. |
| 74 | fn algorithm(&self) -> SignatureAlgorithm; |
| 75 | } |
| 76 | |
| 77 | /// A thing that can sign a message. |
| 78 | pub trait Signer: Debug + Send + Sync { |
| 79 | /// Signs `message` using the selected scheme. |
| 80 | /// |
| 81 | /// `message` is not hashed; the implementer must hash it using the hash function |
| 82 | /// implicit in [`Self::scheme()`]. |
| 83 | /// |
| 84 | /// The returned signature format is also defined by [`Self::scheme()`]. |
| 85 | fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error>; |
| 86 | |
| 87 | /// Reveals which scheme will be used when you call [`Self::sign()`]. |
| 88 | fn scheme(&self) -> SignatureScheme; |
| 89 | } |
| 90 | |
| 91 | /// Server certificate resolver which always resolves to the same certificate and key. |
| 92 | /// |
| 93 | /// For use with [`ConfigBuilder::with_cert_resolver()`]. |
| 94 | /// |
| 95 | /// [`ConfigBuilder::with_cert_resolver()`]: crate::ConfigBuilder::with_cert_resolver |
| 96 | #[derive (Debug)] |
| 97 | pub struct SingleCertAndKey(Arc<CertifiedKey>); |
| 98 | |
| 99 | impl From<CertifiedKey> for SingleCertAndKey { |
| 100 | fn from(certified_key: CertifiedKey) -> Self { |
| 101 | Self(Arc::new(data:certified_key)) |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | impl ResolvesClientCert for SingleCertAndKey { |
| 106 | fn resolve( |
| 107 | &self, |
| 108 | _root_hint_subjects: &[&[u8]], |
| 109 | _sigschemes: &[SignatureScheme], |
| 110 | ) -> Option<Arc<CertifiedKey>> { |
| 111 | Some(Arc::clone(&self.0)) |
| 112 | } |
| 113 | |
| 114 | fn has_certs(&self) -> bool { |
| 115 | true |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | impl ResolvesServerCert for SingleCertAndKey { |
| 120 | fn resolve(&self, _client_hello: ClientHello<'_>) -> Option<Arc<CertifiedKey>> { |
| 121 | Some(Arc::clone(&self.0)) |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | /// A packaged-together certificate chain, matching `SigningKey` and |
| 126 | /// optional stapled OCSP response. |
| 127 | /// |
| 128 | /// Note: this struct is also used to represent an [RFC 7250] raw public key, |
| 129 | /// when the client/server is configured to use raw public keys instead of |
| 130 | /// certificates. |
| 131 | /// |
| 132 | /// [RFC 7250]: https://tools.ietf.org/html/rfc7250 |
| 133 | #[derive (Clone, Debug)] |
| 134 | pub struct CertifiedKey { |
| 135 | /// The certificate chain or raw public key. |
| 136 | pub cert: Vec<CertificateDer<'static>>, |
| 137 | |
| 138 | /// The certified key. |
| 139 | pub key: Arc<dyn SigningKey>, |
| 140 | |
| 141 | /// An optional OCSP response from the certificate issuer, |
| 142 | /// attesting to its continued validity. |
| 143 | pub ocsp: Option<Vec<u8>>, |
| 144 | } |
| 145 | |
| 146 | impl CertifiedKey { |
| 147 | /// Create a new `CertifiedKey` from a certificate chain and DER-encoded private key. |
| 148 | /// |
| 149 | /// Attempt to parse the private key with the given [`CryptoProvider`]'s [`KeyProvider`] and |
| 150 | /// verify that it matches the public key in the first certificate of the `cert_chain` |
| 151 | /// if possible. |
| 152 | /// |
| 153 | /// [`KeyProvider`]: crate::crypto::KeyProvider |
| 154 | pub fn from_der( |
| 155 | cert_chain: Vec<CertificateDer<'static>>, |
| 156 | key: PrivateKeyDer<'static>, |
| 157 | provider: &CryptoProvider, |
| 158 | ) -> Result<Self, Error> { |
| 159 | let private_key = provider |
| 160 | .key_provider |
| 161 | .load_private_key(key)?; |
| 162 | |
| 163 | let certified_key = Self::new(cert_chain, private_key); |
| 164 | match certified_key.keys_match() { |
| 165 | // Don't treat unknown consistency as an error |
| 166 | Ok(()) | Err(Error::InconsistentKeys(InconsistentKeys::Unknown)) => Ok(certified_key), |
| 167 | Err(err) => Err(err), |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | /// Make a new CertifiedKey, with the given chain and key. |
| 172 | /// |
| 173 | /// The cert chain must not be empty. The first certificate in the chain |
| 174 | /// must be the end-entity certificate. |
| 175 | pub fn new(cert: Vec<CertificateDer<'static>>, key: Arc<dyn SigningKey>) -> Self { |
| 176 | Self { |
| 177 | cert, |
| 178 | key, |
| 179 | ocsp: None, |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | /// Verify the consistency of this [`CertifiedKey`]'s public and private keys. |
| 184 | /// This is done by performing a comparison of SubjectPublicKeyInfo bytes. |
| 185 | pub fn keys_match(&self) -> Result<(), Error> { |
| 186 | let Some(key_spki) = self.key.public_key() else { |
| 187 | return Err(InconsistentKeys::Unknown.into()); |
| 188 | }; |
| 189 | |
| 190 | let cert = ParsedCertificate::try_from(self.end_entity_cert()?)?; |
| 191 | match key_spki == cert.subject_public_key_info() { |
| 192 | true => Ok(()), |
| 193 | false => Err(InconsistentKeys::KeyMismatch.into()), |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | /// The end-entity certificate. |
| 198 | pub fn end_entity_cert(&self) -> Result<&CertificateDer<'_>, Error> { |
| 199 | self.cert |
| 200 | .first() |
| 201 | .ok_or(Error::NoCertificatesPresented) |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | #[cfg_attr (not(any(feature = "aws_lc_rs" , feature = "ring" )), allow(dead_code))] |
| 206 | pub(crate) fn public_key_to_spki( |
| 207 | alg_id: &AlgorithmIdentifier, |
| 208 | public_key: impl AsRef<[u8]>, |
| 209 | ) -> SubjectPublicKeyInfoDer<'static> { |
| 210 | // SubjectPublicKeyInfo ::= SEQUENCE { |
| 211 | // algorithm AlgorithmIdentifier, |
| 212 | // subjectPublicKey BIT STRING } |
| 213 | // |
| 214 | // AlgorithmIdentifier ::= SEQUENCE { |
| 215 | // algorithm OBJECT IDENTIFIER, |
| 216 | // parameters ANY DEFINED BY algorithm OPTIONAL } |
| 217 | // |
| 218 | // note that the `pki_types::AlgorithmIdentifier` type is the |
| 219 | // concatenation of `algorithm` and `parameters`, but misses the |
| 220 | // outer `Sequence`. |
| 221 | |
| 222 | let mut spki_inner: Vec = x509::wrap_in_sequence(bytes:alg_id.as_ref()); |
| 223 | spki_inner.extend(&x509::wrap_in_bit_string(bytes:public_key.as_ref())); |
| 224 | |
| 225 | let spki: Vec = x509::wrap_in_sequence(&spki_inner); |
| 226 | |
| 227 | SubjectPublicKeyInfoDer::from(spki) |
| 228 | } |
| 229 | |