/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.35/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 super::CryptoProvider; |
8 | | use crate::client::ResolvesClientCert; |
9 | | use crate::enums::{SignatureAlgorithm, SignatureScheme}; |
10 | | use crate::error::{Error, InconsistentKeys}; |
11 | | use crate::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; |
12 | | use crate::sync::Arc; |
13 | | use 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 |
59 | | pub 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 | 0 | fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> { |
68 | | // Opt-out by default |
69 | 0 | None |
70 | 0 | } |
71 | | |
72 | | /// What kind of key we have. |
73 | | fn algorithm(&self) -> SignatureAlgorithm; |
74 | | } |
75 | | |
76 | | /// A thing that can sign a message. |
77 | | pub 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)] |
96 | | pub struct SingleCertAndKey(Arc<CertifiedKey>); |
97 | | |
98 | | impl From<CertifiedKey> for SingleCertAndKey { |
99 | 0 | fn from(certified_key: CertifiedKey) -> Self { |
100 | 0 | Self(Arc::new(certified_key)) |
101 | 0 | } |
102 | | } |
103 | | |
104 | | impl From<Arc<CertifiedKey>> for SingleCertAndKey { |
105 | 0 | fn from(certified_key: Arc<CertifiedKey>) -> Self { |
106 | 0 | Self(certified_key) |
107 | 0 | } |
108 | | } |
109 | | |
110 | | impl ResolvesClientCert for SingleCertAndKey { |
111 | 0 | fn resolve( |
112 | 0 | &self, |
113 | 0 | _root_hint_subjects: &[&[u8]], |
114 | 0 | _sigschemes: &[SignatureScheme], |
115 | 0 | ) -> Option<Arc<CertifiedKey>> { |
116 | 0 | Some(self.0.clone()) |
117 | 0 | } |
118 | | |
119 | 0 | fn has_certs(&self) -> bool { |
120 | 0 | true |
121 | 0 | } |
122 | | } |
123 | | |
124 | | impl ResolvesServerCert for SingleCertAndKey { |
125 | 0 | fn resolve(&self, _client_hello: ClientHello<'_>) -> Option<Arc<CertifiedKey>> { |
126 | 0 | Some(self.0.clone()) |
127 | 0 | } |
128 | | } |
129 | | |
130 | | /// A packaged-together certificate chain, matching `SigningKey` and |
131 | | /// optional stapled OCSP response. |
132 | | /// |
133 | | /// Note: this struct is also used to represent an [RFC 7250] raw public key, |
134 | | /// when the client/server is configured to use raw public keys instead of |
135 | | /// certificates. |
136 | | /// |
137 | | /// [RFC 7250]: https://tools.ietf.org/html/rfc7250 |
138 | | #[derive(Clone, Debug)] |
139 | | pub struct CertifiedKey { |
140 | | /// The certificate chain or raw public key. |
141 | | pub cert: Vec<CertificateDer<'static>>, |
142 | | |
143 | | /// The certified key. |
144 | | pub key: Arc<dyn SigningKey>, |
145 | | |
146 | | /// An optional OCSP response from the certificate issuer, |
147 | | /// attesting to its continued validity. |
148 | | pub ocsp: Option<Vec<u8>>, |
149 | | } |
150 | | |
151 | | impl CertifiedKey { |
152 | | /// Create a new `CertifiedKey` from a certificate chain and DER-encoded private key. |
153 | | /// |
154 | | /// Attempt to parse the private key with the given [`CryptoProvider`]'s [`KeyProvider`] and |
155 | | /// verify that it matches the public key in the first certificate of the `cert_chain` |
156 | | /// if possible. |
157 | | /// |
158 | | /// [`KeyProvider`]: crate::crypto::KeyProvider |
159 | 0 | pub fn from_der( |
160 | 0 | cert_chain: Vec<CertificateDer<'static>>, |
161 | 0 | key: PrivateKeyDer<'static>, |
162 | 0 | provider: &CryptoProvider, |
163 | 0 | ) -> Result<Self, Error> { |
164 | 0 | let private_key = provider |
165 | 0 | .key_provider |
166 | 0 | .load_private_key(key)?; |
167 | | |
168 | 0 | let certified_key = Self::new(cert_chain, private_key); |
169 | 0 | match certified_key.keys_match() { |
170 | | // Don't treat unknown consistency as an error |
171 | 0 | Ok(()) | Err(Error::InconsistentKeys(InconsistentKeys::Unknown)) => Ok(certified_key), |
172 | 0 | Err(err) => Err(err), |
173 | | } |
174 | 0 | } |
175 | | |
176 | | /// Make a new CertifiedKey, with the given chain and key. |
177 | | /// |
178 | | /// The cert chain must not be empty. The first certificate in the chain |
179 | | /// must be the end-entity certificate. |
180 | 0 | pub fn new(cert: Vec<CertificateDer<'static>>, key: Arc<dyn SigningKey>) -> Self { |
181 | 0 | Self { |
182 | 0 | cert, |
183 | 0 | key, |
184 | 0 | ocsp: None, |
185 | 0 | } |
186 | 0 | } |
187 | | |
188 | | /// Verify the consistency of this [`CertifiedKey`]'s public and private keys. |
189 | | /// This is done by performing a comparison of SubjectPublicKeyInfo bytes. |
190 | 0 | pub fn keys_match(&self) -> Result<(), Error> { |
191 | 0 | let Some(key_spki) = self.key.public_key() else { |
192 | 0 | return Err(InconsistentKeys::Unknown.into()); |
193 | | }; |
194 | | |
195 | 0 | let cert = ParsedCertificate::try_from(self.end_entity_cert()?)?; |
196 | 0 | match key_spki == cert.subject_public_key_info() { |
197 | 0 | true => Ok(()), |
198 | 0 | false => Err(InconsistentKeys::KeyMismatch.into()), |
199 | | } |
200 | 0 | } |
201 | | |
202 | | /// The end-entity certificate. |
203 | 0 | pub fn end_entity_cert(&self) -> Result<&CertificateDer<'_>, Error> { |
204 | 0 | self.cert |
205 | 0 | .first() |
206 | 0 | .ok_or(Error::NoCertificatesPresented) |
207 | 0 | } |
208 | | } |
209 | | |
210 | | /// Convert a public key and algorithm identifier into [`SubjectPublicKeyInfoDer`]. |
211 | 0 | pub fn public_key_to_spki( |
212 | 0 | alg_id: &AlgorithmIdentifier, |
213 | 0 | public_key: impl AsRef<[u8]>, |
214 | 0 | ) -> SubjectPublicKeyInfoDer<'static> { |
215 | | // SubjectPublicKeyInfo ::= SEQUENCE { |
216 | | // algorithm AlgorithmIdentifier, |
217 | | // subjectPublicKey BIT STRING } |
218 | | // |
219 | | // AlgorithmIdentifier ::= SEQUENCE { |
220 | | // algorithm OBJECT IDENTIFIER, |
221 | | // parameters ANY DEFINED BY algorithm OPTIONAL } |
222 | | // |
223 | | // note that the `pki_types::AlgorithmIdentifier` type is the |
224 | | // concatenation of `algorithm` and `parameters`, but misses the |
225 | | // outer `Sequence`. |
226 | | |
227 | 0 | let mut spki_inner = x509::wrap_in_sequence(alg_id.as_ref()); |
228 | 0 | spki_inner.extend(&x509::wrap_in_bit_string(public_key.as_ref())); |
229 | | |
230 | 0 | let spki = x509::wrap_in_sequence(&spki_inner); |
231 | | |
232 | 0 | SubjectPublicKeyInfoDer::from(spki) |
233 | 0 | } Unexecuted instantiation: rustls::crypto::signer::public_key_to_spki::<&ring::rsa::public_key::PublicKey> Unexecuted instantiation: rustls::crypto::signer::public_key_to_spki::<&ring::ec::curve25519::ed25519::signing::PublicKey> Unexecuted instantiation: rustls::crypto::signer::public_key_to_spki::<&ring::ec::suite_b::ecdsa::signing::PublicKey> |