rustls/crypto/signer.rs
1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt::Debug;
4
5use pki_types::{AlgorithmIdentifier, CertificateDer, PrivateKeyDer, SubjectPublicKeyInfoDer};
6
7use super::CryptoProvider;
8use crate::client::ResolvesClientCert;
9use crate::enums::{SignatureAlgorithm, SignatureScheme};
10use crate::error::{Error, InconsistentKeys};
11use crate::server::{ClientHello, ParsedCertificate, ResolvesServerCert};
12use crate::sync::Arc;
13use crate::x509;
14
15/// An abstract signing key.
16///
17/// This interface is used by rustls to use a private signing key
18/// for authentication. This includes server and client authentication.
19///
20/// Objects of this type are always used within Rustls as
21/// `Arc<dyn SigningKey>`. There are no concrete public structs in Rustls
22/// that implement this trait.
23///
24/// There are two main ways to get a signing key:
25///
26/// - [`KeyProvider::load_private_key()`], or
27/// - some other method outside of the `KeyProvider` extension trait,
28/// for instance:
29/// - [`crypto::ring::sign::any_ecdsa_type()`]
30/// - [`crypto::ring::sign::any_eddsa_type()`]
31/// - [`crypto::ring::sign::any_supported_type()`]
32/// - [`crypto::aws_lc_rs::sign::any_ecdsa_type()`]
33/// - [`crypto::aws_lc_rs::sign::any_eddsa_type()`]
34/// - [`crypto::aws_lc_rs::sign::any_supported_type()`]
35///
36/// The `KeyProvider` method `load_private_key()` is called under the hood by
37/// [`ConfigBuilder::with_single_cert()`],
38/// [`ConfigBuilder::with_client_auth_cert()`], and
39/// [`ConfigBuilder::with_single_cert_with_ocsp()`].
40///
41/// A signing key created outside of the `KeyProvider` extension trait can be used
42/// to create a [`CertifiedKey`], which in turn can be used to create a
43/// [`ResolvesServerCertUsingSni`]. Alternately, a `CertifiedKey` can be returned from a
44/// custom implementation of the [`ResolvesServerCert`] or [`ResolvesClientCert`] traits.
45///
46/// [`KeyProvider::load_private_key()`]: crate::crypto::KeyProvider::load_private_key
47/// [`ConfigBuilder::with_single_cert()`]: crate::ConfigBuilder::with_single_cert
48/// [`ConfigBuilder::with_single_cert_with_ocsp()`]: crate::ConfigBuilder::with_single_cert_with_ocsp
49/// [`ConfigBuilder::with_client_auth_cert()`]: crate::ConfigBuilder::with_client_auth_cert
50/// [`crypto::ring::sign::any_ecdsa_type()`]: crate::crypto::ring::sign::any_ecdsa_type
51/// [`crypto::ring::sign::any_eddsa_type()`]: crate::crypto::ring::sign::any_eddsa_type
52/// [`crypto::ring::sign::any_supported_type()`]: crate::crypto::ring::sign::any_supported_type
53/// [`crypto::aws_lc_rs::sign::any_ecdsa_type()`]: crate::crypto::aws_lc_rs::sign::any_ecdsa_type
54/// [`crypto::aws_lc_rs::sign::any_eddsa_type()`]: crate::crypto::aws_lc_rs::sign::any_eddsa_type
55/// [`crypto::aws_lc_rs::sign::any_supported_type()`]: crate::crypto::aws_lc_rs::sign::any_supported_type
56/// [`ResolvesServerCertUsingSni`]: crate::server::ResolvesServerCertUsingSni
57/// [`ResolvesServerCert`]: crate::server::ResolvesServerCert
58/// [`ResolvesClientCert`]: crate::client::ResolvesClientCert
59pub trait SigningKey: Debug + Send + Sync {
60 /// Choose a `SignatureScheme` from those offered.
61 ///
62 /// Expresses the choice by returning something that implements `Signer`,
63 /// using the chosen scheme.
64 fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>>;
65
66 /// Get the RFC 5280-compliant SubjectPublicKeyInfo (SPKI) of this [`SigningKey`] if available.
67 fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> {
68 // Opt-out by default
69 None
70 }
71
72 /// What kind of key we have.
73 fn algorithm(&self) -> SignatureAlgorithm;
74}
75
76/// A thing that can sign a message.
77pub trait Signer: Debug + Send + Sync {
78 /// Signs `message` using the selected scheme.
79 ///
80 /// `message` is not hashed; the implementer must hash it using the hash function
81 /// implicit in [`Self::scheme()`].
82 ///
83 /// The returned signature format is also defined by [`Self::scheme()`].
84 fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error>;
85
86 /// Reveals which scheme will be used when you call [`Self::sign()`].
87 fn scheme(&self) -> SignatureScheme;
88}
89
90/// Server certificate resolver which always resolves to the same certificate and key.
91///
92/// For use with [`ConfigBuilder::with_cert_resolver()`].
93///
94/// [`ConfigBuilder::with_cert_resolver()`]: crate::ConfigBuilder::with_cert_resolver
95#[derive(Debug)]
96pub struct SingleCertAndKey(Arc<CertifiedKey>);
97
98impl From<CertifiedKey> for SingleCertAndKey {
99 fn from(certified_key: CertifiedKey) -> Self {
100 Self(Arc::new(certified_key))
101 }
102}
103
104impl ResolvesClientCert for SingleCertAndKey {
105 fn resolve(
106 &self,
107 _root_hint_subjects: &[&[u8]],
108 _sigschemes: &[SignatureScheme],
109 ) -> Option<Arc<CertifiedKey>> {
110 Some(self.0.clone())
111 }
112
113 fn has_certs(&self) -> bool {
114 true
115 }
116}
117
118impl ResolvesServerCert for SingleCertAndKey {
119 fn resolve(&self, _client_hello: ClientHello<'_>) -> Option<Arc<CertifiedKey>> {
120 Some(self.0.clone())
121 }
122}
123
124/// A packaged-together certificate chain, matching `SigningKey` and
125/// optional stapled OCSP response.
126///
127/// Note: this struct is also used to represent an [RFC 7250] raw public key,
128/// when the client/server is configured to use raw public keys instead of
129/// certificates.
130///
131/// [RFC 7250]: https://tools.ietf.org/html/rfc7250
132#[derive(Clone, Debug)]
133pub struct CertifiedKey {
134 /// The certificate chain or raw public key.
135 pub cert: Vec<CertificateDer<'static>>,
136
137 /// The certified key.
138 pub key: Arc<dyn SigningKey>,
139
140 /// An optional OCSP response from the certificate issuer,
141 /// attesting to its continued validity.
142 pub ocsp: Option<Vec<u8>>,
143}
144
145impl CertifiedKey {
146 /// Create a new `CertifiedKey` from a certificate chain and DER-encoded private key.
147 ///
148 /// Attempt to parse the private key with the given [`CryptoProvider`]'s [`KeyProvider`] and
149 /// verify that it matches the public key in the first certificate of the `cert_chain`
150 /// if possible.
151 ///
152 /// [`KeyProvider`]: crate::crypto::KeyProvider
153 pub fn from_der(
154 cert_chain: Vec<CertificateDer<'static>>,
155 key: PrivateKeyDer<'static>,
156 provider: &CryptoProvider,
157 ) -> Result<Self, Error> {
158 let private_key = provider
159 .key_provider
160 .load_private_key(key)?;
161
162 let certified_key = Self::new(cert_chain, private_key);
163 match certified_key.keys_match() {
164 // Don't treat unknown consistency as an error
165 Ok(()) | Err(Error::InconsistentKeys(InconsistentKeys::Unknown)) => Ok(certified_key),
166 Err(err) => Err(err),
167 }
168 }
169
170 /// Make a new CertifiedKey, with the given chain and key.
171 ///
172 /// The cert chain must not be empty. The first certificate in the chain
173 /// must be the end-entity certificate.
174 pub fn new(cert: Vec<CertificateDer<'static>>, key: Arc<dyn SigningKey>) -> Self {
175 Self {
176 cert,
177 key,
178 ocsp: None,
179 }
180 }
181
182 /// Verify the consistency of this [`CertifiedKey`]'s public and private keys.
183 /// This is done by performing a comparison of SubjectPublicKeyInfo bytes.
184 pub fn keys_match(&self) -> Result<(), Error> {
185 let Some(key_spki) = self.key.public_key() else {
186 return Err(InconsistentKeys::Unknown.into());
187 };
188
189 let cert = ParsedCertificate::try_from(self.end_entity_cert()?)?;
190 match key_spki == cert.subject_public_key_info() {
191 true => Ok(()),
192 false => Err(InconsistentKeys::KeyMismatch.into()),
193 }
194 }
195
196 /// The end-entity certificate.
197 pub fn end_entity_cert(&self) -> Result<&CertificateDer<'_>, Error> {
198 self.cert
199 .first()
200 .ok_or(Error::NoCertificatesPresented)
201 }
202}
203
204#[cfg_attr(not(any(feature = "aws_lc_rs", feature = "ring")), allow(dead_code))]
205pub(crate) fn public_key_to_spki(
206 alg_id: &AlgorithmIdentifier,
207 public_key: impl AsRef<[u8]>,
208) -> SubjectPublicKeyInfoDer<'static> {
209 // SubjectPublicKeyInfo ::= SEQUENCE {
210 // algorithm AlgorithmIdentifier,
211 // subjectPublicKey BIT STRING }
212 //
213 // AlgorithmIdentifier ::= SEQUENCE {
214 // algorithm OBJECT IDENTIFIER,
215 // parameters ANY DEFINED BY algorithm OPTIONAL }
216 //
217 // note that the `pki_types::AlgorithmIdentifier` type is the
218 // concatenation of `algorithm` and `parameters`, but misses the
219 // outer `Sequence`.
220
221 let mut spki_inner = x509::wrap_in_sequence(alg_id.as_ref());
222 spki_inner.extend(&x509::wrap_in_bit_string(public_key.as_ref()));
223
224 let spki = x509::wrap_in_sequence(&spki_inner);
225
226 SubjectPublicKeyInfoDer::from(spki)
227}