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