Skip to main content

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