Coverage Report

Created: 2025-12-28 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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>