rustls/crypto/
signer.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt::Debug;
4use core::hash::{Hash, Hasher};
5use core::iter;
6
7use pki_types::{AlgorithmIdentifier, CertificateDer, PrivateKeyDer, SubjectPublicKeyInfoDer};
8
9use super::CryptoProvider;
10use crate::client::{ClientCredentialResolver, CredentialRequest};
11use crate::crypto::SignatureScheme;
12use crate::enums::CertificateType;
13use crate::error::{ApiMisuse, Error, InvalidMessage, PeerIncompatible};
14use crate::msgs::codec::{Codec, Reader};
15use crate::server::{ClientHello, ParsedCertificate, ServerCredentialResolver};
16use crate::sync::Arc;
17use crate::{DynHasher, SignerPublicKey, x509};
18
19/// Server certificate resolver which always resolves to the same identity and key.
20///
21/// For use with [`ConfigBuilder::with_server_credential_resolver()`] or
22/// [`ConfigBuilder::with_client_credential_resolver()`].
23///
24/// [`ConfigBuilder::with_server_credential_resolver()`]: crate::ConfigBuilder::with_server_credential_resolver
25/// [`ConfigBuilder::with_client_credential_resolver()`]: crate::ConfigBuilder::with_client_credential_resolver
26#[derive(Debug, Hash)]
27pub struct SingleCredential {
28    credentials: Credentials,
29    types: &'static [CertificateType],
30}
31
32impl From<Credentials> for SingleCredential {
33    fn from(credentials: Credentials) -> Self {
34        match &*credentials.identity {
35            Identity::X509(_) => Self {
36                credentials,
37                types: &[CertificateType::X509],
38            },
39            Identity::RawPublicKey(_) => Self {
40                credentials,
41                types: &[CertificateType::RawPublicKey],
42            },
43        }
44    }
45}
46
47impl ClientCredentialResolver for SingleCredential {
48    fn resolve(&self, request: &CredentialRequest<'_>) -> Option<SelectedCredential> {
49        match (&*self.credentials.identity, request.negotiated_type()) {
50            (Identity::X509(_), CertificateType::X509)
51            | (Identity::RawPublicKey(_), CertificateType::RawPublicKey) => self
52                .credentials
53                .signer(request.signature_schemes()),
54            _ => None,
55        }
56    }
57
58    fn supported_certificate_types(&self) -> &'static [CertificateType] {
59        self.types
60    }
61
62    fn hash_config(&self, h: &mut dyn Hasher) {
63        self.hash(&mut DynHasher(h));
64    }
65}
66
67impl ServerCredentialResolver for SingleCredential {
68    fn resolve(&self, client_hello: &ClientHello<'_>) -> Result<SelectedCredential, Error> {
69        self.credentials
70            .signer(client_hello.signature_schemes())
71            .ok_or(Error::PeerIncompatible(
72                PeerIncompatible::NoSignatureSchemesInCommon,
73            ))
74    }
75
76    fn supported_certificate_types(&self) -> &'static [CertificateType] {
77        self.types
78    }
79}
80
81/// A packaged-together certificate chain, matching `SigningKey` and
82/// optional stapled OCSP response.
83///
84/// Note: this struct is also used to represent an [RFC 7250] raw public key,
85/// when the client/server is configured to use raw public keys instead of
86/// certificates.
87///
88/// [RFC 7250]: https://tools.ietf.org/html/rfc7250
89#[non_exhaustive]
90#[derive(Debug)]
91pub struct Credentials {
92    /// The certificate chain or raw public key.
93    pub identity: Arc<Identity<'static>>,
94    /// The signing key matching the `identity`.
95    pub key: Box<dyn SigningKey>,
96    /// An optional OCSP response from the certificate issuer,
97    /// attesting to its continued validity.
98    pub ocsp: Option<Arc<[u8]>>,
99}
100
101impl Credentials {
102    /// Create a new [`Credentials`] from a certificate chain and DER-encoded private key.
103    ///
104    /// Attempt to parse the private key with the given [`CryptoProvider`]'s [`KeyProvider`] and
105    /// verify that it matches the public key in the first certificate of the `identity`
106    /// if possible (if it is an `X509` identity).
107    ///
108    /// [`KeyProvider`]: crate::crypto::KeyProvider
109    pub fn from_der(
110        identity: Arc<Identity<'static>>,
111        key: PrivateKeyDer<'static>,
112        provider: &CryptoProvider,
113    ) -> Result<Self, Error> {
114        Self::new(
115            identity,
116            provider
117                .key_provider
118                .load_private_key(key)?,
119        )
120    }
121
122    /// Make a new [`Credentials`], with the given identity and key.
123    ///
124    /// Yields [`Error::InconsistentKeys`] if the `identity` is `X509` and the end-entity certificate's subject
125    /// public key info does not match that of the `key`'s public key, or if the `key` does not
126    /// have a public key.
127    ///
128    /// This constructor should be used with all [`SigningKey`] implementations
129    /// that can provide a public key, including those provided by rustls itself.
130    pub fn new(identity: Arc<Identity<'static>>, key: Box<dyn SigningKey>) -> Result<Self, Error> {
131        if let Identity::X509(CertificateIdentity { end_entity, .. }) = &*identity {
132            let parsed = ParsedCertificate::try_from(end_entity)?;
133            match (key.public_key(), parsed.subject_public_key_info()) {
134                (None, _) => return Err(Error::InconsistentKeys(InconsistentKeys::Unknown)),
135                (Some(key_spki), cert_spki) if key_spki != cert_spki => {
136                    return Err(Error::InconsistentKeys(InconsistentKeys::KeyMismatch));
137                }
138                _ => {}
139            }
140        };
141
142        Ok(Self {
143            identity,
144            key,
145            ocsp: None,
146        })
147    }
148
149    /// Make a new `Credentials` from a raw private key.
150    ///
151    /// Unlike [`Credentials::new()`], this does not check that the end-entity certificate's
152    /// subject key matches `key`'s public key.
153    ///
154    /// This avoids parsing the end-entity certificate, which is useful when using client
155    /// certificates that are not fully standards compliant, but known to usable by the peer.
156    pub fn new_unchecked(identity: Arc<Identity<'static>>, key: Box<dyn SigningKey>) -> Self {
157        Self {
158            identity,
159            key,
160            ocsp: None,
161        }
162    }
163
164    /// Attempt to produce a `SelectedCredential` using one of the given signature schemes.
165    ///
166    /// Calls [`SigningKey::choose_scheme()`] and propagates `cert_chain` and `ocsp`.
167    pub fn signer(&self, sig_schemes: &[SignatureScheme]) -> Option<SelectedCredential> {
168        Some(SelectedCredential {
169            identity: self.identity.clone(),
170            signer: self.key.choose_scheme(sig_schemes)?,
171            ocsp: self.ocsp.clone(),
172        })
173    }
174}
175
176impl Hash for Credentials {
177    fn hash<H: Hasher>(&self, state: &mut H) {
178        self.identity.hash(state);
179        self.ocsp.hash(state);
180    }
181}
182
183/// A packaged-together certificate chain and one-time-use signer.
184///
185/// This is used in the [`ClientCredentialResolver`] and [`ServerCredentialResolver`] traits
186/// as the return value of their `resolve()` methods.
187#[non_exhaustive]
188#[derive(Debug)]
189pub struct SelectedCredential {
190    /// The certificate chain or raw public key.
191    pub identity: Arc<Identity<'static>>,
192    /// The signing key matching the `identity`.
193    pub signer: Box<dyn Signer>,
194    /// An optional OCSP response from the certificate issuer,
195    /// attesting to its continued validity.
196    pub ocsp: Option<Arc<[u8]>>,
197}
198
199/// A peer's identity, depending on the negotiated certificate type.
200#[non_exhaustive]
201#[derive(Clone, Debug, Eq, Hash, PartialEq)]
202pub enum Identity<'a> {
203    /// A standard X.509 certificate chain.
204    ///
205    /// This is the most common case.
206    X509(CertificateIdentity<'a>),
207    /// A raw public key, as defined in [RFC 7250](https://tools.ietf.org/html/rfc7250).
208    RawPublicKey(SubjectPublicKeyInfoDer<'a>),
209}
210
211impl<'a> Identity<'a> {
212    /// Create a `PeerIdentity::X509` from a certificate chain.
213    ///
214    /// Returns `None` if `cert_chain` is empty.
215    pub fn from_cert_chain(mut cert_chain: Vec<CertificateDer<'a>>) -> Result<Self, ApiMisuse> {
216        let mut iter = cert_chain.drain(..);
217        let Some(first) = iter.next() else {
218            return Err(ApiMisuse::EmptyCertificateChain);
219        };
220
221        Ok(Self::X509(CertificateIdentity {
222            end_entity: first,
223            intermediates: iter.collect(),
224        }))
225    }
226
227    pub(crate) fn from_peer(
228        mut cert_chain: Vec<CertificateDer<'a>>,
229        expected: CertificateType,
230    ) -> Result<Option<Self>, Error> {
231        let mut iter = cert_chain.drain(..);
232        let Some(first) = iter.next() else {
233            return Ok(None);
234        };
235
236        match expected {
237            CertificateType::X509 => Ok(Some(Self::X509(CertificateIdentity {
238                end_entity: first,
239                intermediates: iter.collect(),
240            }))),
241            CertificateType::RawPublicKey => match iter.count() {
242                0 => Ok(Some(Self::RawPublicKey(
243                    SubjectPublicKeyInfoDer::from(first.as_ref()).into_owned(),
244                ))),
245                _ => Err(PeerIncompatible::MultipleRawKeys.into()),
246            },
247            CertificateType::Unknown(ty) => {
248                Err(PeerIncompatible::UnknownCertificateType(ty).into())
249            }
250        }
251    }
252
253    /// Convert this `PeerIdentity` into an owned version.
254    pub fn into_owned(self) -> Identity<'static> {
255        match self {
256            Self::X509(id) => Identity::X509(id.into_owned()),
257            Self::RawPublicKey(spki) => Identity::RawPublicKey(spki.into_owned()),
258        }
259    }
260
261    pub(crate) fn as_certificates(&'a self) -> impl Iterator<Item = CertificateDer<'a>> + 'a {
262        match self {
263            Self::X509(cert) => IdentityCertificateIterator::X509(
264                iter::once(CertificateDer::from(cert.end_entity.as_ref())).chain(
265                    cert.intermediates
266                        .iter()
267                        .map(|c| CertificateDer::from(c.as_ref())),
268                ),
269            ),
270            Self::RawPublicKey(spki) => IdentityCertificateIterator::RawPublicKey(iter::once(
271                CertificateDer::from(spki.as_ref()),
272            )),
273        }
274    }
275
276    /// Get the public key of this identity as a `SignerPublicKey`.
277    pub fn as_signer(&self) -> SignerPublicKey<'_> {
278        match self {
279            Self::X509(cert) => SignerPublicKey::X509(&cert.end_entity),
280            Self::RawPublicKey(spki) => SignerPublicKey::RawPublicKey(spki),
281        }
282    }
283}
284
285impl<'a> Codec<'a> for Identity<'a> {
286    fn encode(&self, bytes: &mut Vec<u8>) {
287        match self {
288            Self::X509(certificates) => {
289                0u8.encode(bytes);
290                certificates.end_entity.encode(bytes);
291                certificates.intermediates.encode(bytes);
292            }
293            Self::RawPublicKey(spki) => {
294                1u8.encode(bytes);
295                spki.encode(bytes);
296            }
297        }
298    }
299
300    fn read(reader: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
301        match u8::read(reader)? {
302            0 => Ok(Self::X509(CertificateIdentity {
303                end_entity: CertificateDer::read(reader)?.into_owned(),
304                intermediates: Vec::<CertificateDer<'_>>::read(reader)?
305                    .into_iter()
306                    .collect(),
307            })),
308            1 => Ok(Self::RawPublicKey(
309                SubjectPublicKeyInfoDer::read(reader)?.into_owned(),
310            )),
311            _ => Err(InvalidMessage::UnexpectedMessage(
312                "invalid PeerIdentity discriminant",
313            )),
314        }
315    }
316}
317
318enum IdentityCertificateIterator<C, R> {
319    X509(C),
320    RawPublicKey(R),
321}
322
323impl<'a, C, R> Iterator for IdentityCertificateIterator<C, R>
324where
325    C: Iterator<Item = CertificateDer<'a>>,
326    R: Iterator<Item = CertificateDer<'a>>,
327{
328    type Item = CertificateDer<'a>;
329
330    fn next(&mut self) -> Option<Self::Item> {
331        match self {
332            Self::X509(iter) => iter.next(),
333            Self::RawPublicKey(iter) => iter.next(),
334        }
335    }
336}
337
338/// Data required to verify the peer's identity.
339#[non_exhaustive]
340#[derive(Clone, Debug, Eq, Hash, PartialEq)]
341pub struct CertificateIdentity<'a> {
342    /// Certificate for the entity being verified.
343    pub end_entity: CertificateDer<'a>,
344    /// All certificates other than `end_entity` received in the peer's `Certificate` message.
345    ///
346    /// It is in the same order that the peer sent them and may be empty.
347    pub intermediates: Vec<CertificateDer<'a>>,
348}
349
350impl<'a> CertificateIdentity<'a> {
351    /// Convert this `CertificateIdentity` into an owned version.
352    pub fn into_owned(self) -> CertificateIdentity<'static> {
353        CertificateIdentity {
354            end_entity: self.end_entity.into_owned(),
355            intermediates: self
356                .intermediates
357                .into_iter()
358                .map(|cert| cert.into_owned())
359                .collect(),
360        }
361    }
362}
363
364/// An abstract signing key.
365///
366/// This interface is used by rustls to use a private signing key
367/// for authentication.  This includes server and client authentication.
368///
369/// Objects of this type are always used within Rustls as
370/// `Arc<dyn SigningKey>`. There are no concrete public structs in Rustls
371/// that implement this trait.
372///
373/// You can obtain a `SigningKey` by calling the [`KeyProvider::load_private_key()`]
374/// method, which is usually referenced via [`CryptoProvider::key_provider`].
375///
376/// The `KeyProvider` method `load_private_key()` is called under the hood by
377/// [`ConfigBuilder::with_single_cert()`],
378/// [`ConfigBuilder::with_client_auth_cert()`], and
379/// [`ConfigBuilder::with_single_cert_with_ocsp()`].
380///
381/// A signing key created outside of the `KeyProvider` extension trait can be used
382/// to create a [`Credentials`], which in turn can be used to create a
383/// [`ServerNameResolver`]. Alternately, a `Credentials` can be returned from a
384/// custom implementation of the [`ServerCredentialResolver`] or [`ClientCredentialResolver`] traits.
385///
386/// [`KeyProvider::load_private_key()`]: crate::crypto::KeyProvider::load_private_key
387/// [`ConfigBuilder::with_single_cert()`]: crate::ConfigBuilder::with_single_cert
388/// [`ConfigBuilder::with_single_cert_with_ocsp()`]: crate::ConfigBuilder::with_single_cert_with_ocsp
389/// [`ConfigBuilder::with_client_auth_cert()`]: crate::ConfigBuilder::with_client_auth_cert
390/// [`ServerNameResolver`]: crate::server::ServerNameResolver
391/// [`ServerCredentialResolver`]: crate::server::ServerCredentialResolver
392/// [`ClientCredentialResolver`]: crate::client::ClientCredentialResolver
393pub trait SigningKey: Debug + Send + Sync {
394    /// Choose a `SignatureScheme` from those offered.
395    ///
396    /// Expresses the choice by returning something that implements `Signer`,
397    /// using the chosen scheme.
398    fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>>;
399
400    /// Get the RFC 5280-compliant SubjectPublicKeyInfo (SPKI) of this [`SigningKey`].
401    ///
402    /// If an implementation does not have the ability to derive this,
403    /// it can return `None`.
404    fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>>;
405}
406
407/// A thing that can sign a message.
408pub trait Signer: Debug + Send + Sync {
409    /// Signs `message` using the selected scheme.
410    ///
411    /// `message` is not hashed; the implementer must hash it using the hash function
412    /// implicit in [`Self::scheme()`].
413    ///
414    /// The returned signature format is also defined by [`Self::scheme()`].
415    fn sign(self: Box<Self>, message: &[u8]) -> Result<Vec<u8>, Error>;
416
417    /// Reveals which scheme will be used when you call [`Self::sign()`].
418    fn scheme(&self) -> SignatureScheme;
419}
420
421/// Convert a public key and algorithm identifier into [`SubjectPublicKeyInfoDer`].
422///
423/// In the returned encoding, `alg_id` is used as the `algorithm` field, and `public_key` is
424/// wrapped inside an ASN.1 `BIT STRING` and then used as the `subjectPublicKey` field.
425pub fn public_key_to_spki(
426    alg_id: &AlgorithmIdentifier,
427    public_key: impl AsRef<[u8]>,
428) -> SubjectPublicKeyInfoDer<'static> {
429    // SubjectPublicKeyInfo  ::=  SEQUENCE  {
430    //    algorithm            AlgorithmIdentifier,
431    //    subjectPublicKey     BIT STRING  }
432    //
433    // AlgorithmIdentifier  ::=  SEQUENCE  {
434    //    algorithm               OBJECT IDENTIFIER,
435    //    parameters              ANY DEFINED BY algorithm OPTIONAL  }
436    //
437    // note that the `pki_types::AlgorithmIdentifier` type is the
438    // concatenation of `algorithm` and `parameters`, but misses the
439    // outer `Sequence`.
440
441    let mut spki_inner = x509::wrap_in_sequence(alg_id.as_ref());
442    spki_inner.extend(&x509::wrap_in_bit_string(public_key.as_ref()));
443
444    let spki = x509::wrap_in_sequence(&spki_inner);
445
446    SubjectPublicKeyInfoDer::from(spki)
447}
448
449/// Specific failure cases from [`Credentials::new()`] or a [`crate::crypto::SigningKey`] that cannot produce a corresponding public key.
450///
451/// [`Credentials::new()`]: crate::crypto::Credentials::new()
452#[non_exhaustive]
453#[derive(Clone, Copy, Debug, Eq, PartialEq)]
454pub enum InconsistentKeys {
455    /// The public key returned by the [`SigningKey`] does not match the public key information in the certificate.
456    ///
457    /// [`SigningKey`]: crate::crypto::SigningKey
458    KeyMismatch,
459
460    /// The [`SigningKey`] cannot produce its corresponding public key.
461    ///
462    /// [`SigningKey`]: crate::crypto::SigningKey
463    Unknown,
464}