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