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::Unknown(ty) => {
255                Err(PeerIncompatible::UnknownCertificateType(ty).into())
256            }
257        }
258    }
259
260    /// Convert this `PeerIdentity` into an owned version.
261    pub fn into_owned(self) -> Identity<'static> {
262        match self {
263            Self::X509(id) => Identity::X509(id.into_owned()),
264            Self::RawPublicKey(spki) => Identity::RawPublicKey(spki.into_owned()),
265        }
266    }
267
268    pub(crate) fn as_certificates(&'a self) -> impl Iterator<Item = CertificateDer<'a>> + 'a {
269        match self {
270            Self::X509(cert) => IdentityCertificateIterator::X509(
271                iter::once(CertificateDer::from(cert.end_entity.as_ref())).chain(
272                    cert.intermediates
273                        .iter()
274                        .map(|c| CertificateDer::from(c.as_ref())),
275                ),
276            ),
277            Self::RawPublicKey(spki) => IdentityCertificateIterator::RawPublicKey(iter::once(
278                CertificateDer::from(spki.as_ref()),
279            )),
280        }
281    }
282
283    /// Get the public key of this identity as a `SignerPublicKey`.
284    pub fn as_signer(&self) -> SignerPublicKey<'_> {
285        match self {
286            Self::X509(cert) => SignerPublicKey::X509(&cert.end_entity),
287            Self::RawPublicKey(spki) => SignerPublicKey::RawPublicKey(spki),
288        }
289    }
290}
291
292impl<'a> Codec<'a> for Identity<'a> {
293    fn encode(&self, bytes: &mut Vec<u8>) {
294        match self {
295            Self::X509(certificates) => {
296                0u8.encode(bytes);
297                certificates.end_entity.encode(bytes);
298                certificates.intermediates.encode(bytes);
299            }
300            Self::RawPublicKey(spki) => {
301                1u8.encode(bytes);
302                spki.encode(bytes);
303            }
304        }
305    }
306
307    fn read(reader: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
308        match u8::read(reader)? {
309            0 => Ok(Self::X509(CertificateIdentity {
310                end_entity: CertificateDer::read(reader)?.into_owned(),
311                intermediates: Vec::<CertificateDer<'_>>::read(reader)?
312                    .into_iter()
313                    .collect(),
314            })),
315            1 => Ok(Self::RawPublicKey(
316                SubjectPublicKeyInfoDer::read(reader)?.into_owned(),
317            )),
318            _ => Err(InvalidMessage::UnexpectedMessage(
319                "invalid PeerIdentity discriminant",
320            )),
321        }
322    }
323}
324
325enum IdentityCertificateIterator<C, R> {
326    X509(C),
327    RawPublicKey(R),
328}
329
330impl<'a, C, R> Iterator for IdentityCertificateIterator<C, R>
331where
332    C: Iterator<Item = CertificateDer<'a>>,
333    R: Iterator<Item = CertificateDer<'a>>,
334{
335    type Item = CertificateDer<'a>;
336
337    fn next(&mut self) -> Option<Self::Item> {
338        match self {
339            Self::X509(iter) => iter.next(),
340            Self::RawPublicKey(iter) => iter.next(),
341        }
342    }
343}
344
345/// Data required to verify the peer's identity.
346#[non_exhaustive]
347#[derive(Clone, Debug, Eq, Hash, PartialEq)]
348pub struct CertificateIdentity<'a> {
349    /// Certificate for the entity being verified.
350    pub end_entity: CertificateDer<'a>,
351    /// All certificates other than `end_entity` received in the peer's `Certificate` message.
352    ///
353    /// It is in the same order that the peer sent them and may be empty.
354    pub intermediates: Vec<CertificateDer<'a>>,
355}
356
357impl<'a> CertificateIdentity<'a> {
358    /// Create a new `CertificateIdentity` from an end-entity certificate and intermediates.
359    pub fn new(end_entity: CertificateDer<'a>, intermediates: Vec<CertificateDer<'a>>) -> Self {
360        Self {
361            end_entity,
362            intermediates,
363        }
364    }
365
366    /// Convert this `CertificateIdentity` into an owned version.
367    pub fn into_owned(self) -> CertificateIdentity<'static> {
368        CertificateIdentity {
369            end_entity: self.end_entity.into_owned(),
370            intermediates: self
371                .intermediates
372                .into_iter()
373                .map(|cert| cert.into_owned())
374                .collect(),
375        }
376    }
377}
378
379/// An abstract signing key.
380///
381/// This interface is used by rustls to use a private signing key
382/// for authentication.  This includes server and client authentication.
383///
384/// Objects of this type are always used within Rustls as
385/// `Arc<dyn SigningKey>`. There are no concrete public structs in Rustls
386/// that implement this trait.
387///
388/// You can obtain a `SigningKey` by calling the [`KeyProvider::load_private_key()`]
389/// method, which is usually referenced via [`CryptoProvider::key_provider`].
390///
391/// The `KeyProvider` method `load_private_key()` is called under the hood by
392/// [`ConfigBuilder::with_single_cert()`],
393/// [`ConfigBuilder::with_client_auth_cert()`], and
394/// [`ConfigBuilder::with_single_cert_with_ocsp()`].
395///
396/// A signing key created outside of the `KeyProvider` extension trait can be used
397/// to create a [`Credentials`], which in turn can be used to create a
398/// [`ServerNameResolver`]. Alternately, a `Credentials` can be returned from a
399/// custom implementation of the [`ServerCredentialResolver`] or [`ClientCredentialResolver`] traits.
400///
401/// [`KeyProvider::load_private_key()`]: crate::crypto::KeyProvider::load_private_key
402/// [`ConfigBuilder::with_single_cert()`]: crate::ConfigBuilder::with_single_cert
403/// [`ConfigBuilder::with_single_cert_with_ocsp()`]: crate::ConfigBuilder::with_single_cert_with_ocsp
404/// [`ConfigBuilder::with_client_auth_cert()`]: crate::ConfigBuilder::with_client_auth_cert
405/// [`ServerNameResolver`]: crate::server::ServerNameResolver
406/// [`ServerCredentialResolver`]: crate::server::ServerCredentialResolver
407/// [`ClientCredentialResolver`]: crate::client::ClientCredentialResolver
408pub trait SigningKey: Debug + Send + Sync {
409    /// Choose a `SignatureScheme` from those offered.
410    ///
411    /// Expresses the choice by returning something that implements `Signer`,
412    /// using the chosen scheme.
413    fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>>;
414
415    /// Get the RFC 5280-compliant SubjectPublicKeyInfo (SPKI) of this [`SigningKey`].
416    ///
417    /// If an implementation does not have the ability to derive this,
418    /// it can return `None`.
419    fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>>;
420}
421
422/// A thing that can sign a message.
423pub trait Signer: Debug + Send + Sync {
424    /// Signs `message` using the selected scheme.
425    ///
426    /// `message` is not hashed; the implementer must hash it using the hash function
427    /// implicit in [`Self::scheme()`].
428    ///
429    /// The returned signature format is also defined by [`Self::scheme()`].
430    fn sign(self: Box<Self>, message: &[u8]) -> Result<Vec<u8>, Error>;
431
432    /// Reveals which scheme will be used when you call [`Self::sign()`].
433    fn scheme(&self) -> SignatureScheme;
434}
435
436/// Convert a public key and algorithm identifier into [`SubjectPublicKeyInfoDer`].
437///
438/// In the returned encoding, `alg_id` is used as the `algorithm` field, and `public_key` is
439/// wrapped inside an ASN.1 `BIT STRING` and then used as the `subjectPublicKey` field.
440pub fn public_key_to_spki(
441    alg_id: &AlgorithmIdentifier,
442    public_key: impl AsRef<[u8]>,
443) -> SubjectPublicKeyInfoDer<'static> {
444    // SubjectPublicKeyInfo  ::=  SEQUENCE  {
445    //    algorithm            AlgorithmIdentifier,
446    //    subjectPublicKey     BIT STRING  }
447    //
448    // AlgorithmIdentifier  ::=  SEQUENCE  {
449    //    algorithm               OBJECT IDENTIFIER,
450    //    parameters              ANY DEFINED BY algorithm OPTIONAL  }
451    //
452    // note that the `pki_types::AlgorithmIdentifier` type is the
453    // concatenation of `algorithm` and `parameters`, but misses the
454    // outer `Sequence`.
455
456    let mut spki_inner = x509::wrap_in_sequence(alg_id.as_ref());
457    spki_inner.extend(&x509::wrap_in_bit_string(public_key.as_ref()));
458
459    let spki = x509::wrap_in_sequence(&spki_inner);
460
461    SubjectPublicKeyInfoDer::from(spki)
462}
463
464/// Specific failure cases from [`Credentials::new()`] or a [`crate::crypto::SigningKey`] that cannot produce a corresponding public key.
465///
466/// [`Credentials::new()`]: crate::crypto::Credentials::new()
467#[non_exhaustive]
468#[derive(Clone, Copy, Debug, Eq, PartialEq)]
469pub enum InconsistentKeys {
470    /// The public key returned by the [`SigningKey`] does not match the public key information in the certificate.
471    ///
472    /// [`SigningKey`]: crate::crypto::SigningKey
473    KeyMismatch,
474
475    /// The [`SigningKey`] cannot produce its corresponding public key.
476    ///
477    /// [`SigningKey`]: crate::crypto::SigningKey
478    Unknown,
479}