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