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