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}