rustls/crypto/
signer.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt::Debug;
4
5use pki_types::{AlgorithmIdentifier, CertificateDer, PrivateKeyDer, SubjectPublicKeyInfoDer};
6
7use crate::client::ResolvesClientCert;
8use crate::enums::{SignatureAlgorithm, SignatureScheme};
9use crate::error::{Error, InconsistentKeys};
10use crate::server::{ClientHello, ParsedCertificate, ResolvesServerCert};
11use crate::sync::Arc;
12use crate::x509;
13
14use 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
60pub 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.
78pub 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)]
97pub struct SingleCertAndKey(Arc<CertifiedKey>);
98
99impl From<CertifiedKey> for SingleCertAndKey {
100    fn from(certified_key: CertifiedKey) -> Self {
101        Self(Arc::new(certified_key))
102    }
103}
104
105impl 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
119impl 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)]
134pub 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
146impl 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))]
206pub(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 = x509::wrap_in_sequence(alg_id.as_ref());
223    spki_inner.extend(&x509::wrap_in_bit_string(public_key.as_ref()));
224
225    let spki = x509::wrap_in_sequence(&spki_inner);
226
227    SubjectPublicKeyInfoDer::from(spki)
228}