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