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}