1 | use crate::enums::{SignatureAlgorithm, SignatureScheme}; |
2 | use crate::error::Error; |
3 | |
4 | use pki_types::CertificateDer; |
5 | |
6 | use alloc::boxed::Box; |
7 | use alloc::sync::Arc; |
8 | use alloc::vec::Vec; |
9 | use core::fmt::Debug; |
10 | |
11 | /// An abstract signing key. |
12 | /// |
13 | /// This interface is used by rustls to use a private signing key |
14 | /// for authentication. This includes server and client authentication. |
15 | /// |
16 | /// Objects of this type are always used within Rustls as |
17 | /// `Arc<dyn SigningKey>`. There are no concrete public structs in Rustls |
18 | /// that implement this trait. |
19 | /// |
20 | /// There are two main ways to get a signing key: |
21 | /// |
22 | /// - [`KeyProvider::load_private_key()`], or |
23 | /// - some other method outside of the `KeyProvider` extension trait, |
24 | /// for instance: |
25 | /// - [`crypto::ring::sign::any_ecdsa_type()`] |
26 | /// - [`crypto::ring::sign::any_eddsa_type()`] |
27 | /// - [`crypto::ring::sign::any_supported_type()`] |
28 | /// - [`crypto::aws_lc_rs::sign::any_ecdsa_type()`] |
29 | /// - [`crypto::aws_lc_rs::sign::any_eddsa_type()`] |
30 | /// - [`crypto::aws_lc_rs::sign::any_supported_type()`] |
31 | /// |
32 | /// The `KeyProvider` method `load_private_key()` is called under the hood by |
33 | /// [`ConfigBuilder::with_single_cert()`], |
34 | /// [`ConfigBuilder::with_client_auth_cert()`], and |
35 | /// [`ConfigBuilder::with_single_cert_with_ocsp()`]. |
36 | /// |
37 | /// A signing key created outside of the `KeyProvider` extension trait can be used |
38 | /// to create a [`CertifiedKey`], which in turn can be used to create a |
39 | /// [`ResolvesServerCertUsingSni`]. Alternately, a `CertifiedKey` can be returned from a |
40 | /// custom implementation of the [`ResolvesServerCert`] or [`ResolvesClientCert`] traits. |
41 | /// |
42 | /// [`KeyProvider::load_private_key()`]: crate::crypto::KeyProvider::load_private_key |
43 | /// [`ConfigBuilder::with_single_cert()`]: crate::ConfigBuilder::with_single_cert |
44 | /// [`ConfigBuilder::with_single_cert_with_ocsp()`]: crate::ConfigBuilder::with_single_cert_with_ocsp |
45 | /// [`ConfigBuilder::with_client_auth_cert()`]: crate::ConfigBuilder::with_client_auth_cert |
46 | /// [`crypto::ring::sign::any_ecdsa_type()`]: crate::crypto::ring::sign::any_ecdsa_type |
47 | /// [`crypto::ring::sign::any_eddsa_type()`]: crate::crypto::ring::sign::any_eddsa_type |
48 | /// [`crypto::ring::sign::any_supported_type()`]: crate::crypto::ring::sign::any_supported_type |
49 | /// [`crypto::aws_lc_rs::sign::any_ecdsa_type()`]: crate::crypto::aws_lc_rs::sign::any_ecdsa_type |
50 | /// [`crypto::aws_lc_rs::sign::any_eddsa_type()`]: crate::crypto::aws_lc_rs::sign::any_eddsa_type |
51 | /// [`crypto::aws_lc_rs::sign::any_supported_type()`]: crate::crypto::aws_lc_rs::sign::any_supported_type |
52 | /// [`ResolvesServerCertUsingSni`]: crate::server::ResolvesServerCertUsingSni |
53 | /// [`ResolvesServerCert`]: crate::server::ResolvesServerCert |
54 | /// [`ResolvesClientCert`]: crate::client::ResolvesClientCert |
55 | pub trait SigningKey: Debug + Send + Sync { |
56 | /// Choose a `SignatureScheme` from those offered. |
57 | /// |
58 | /// Expresses the choice by returning something that implements `Signer`, |
59 | /// using the chosen scheme. |
60 | fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>>; |
61 | |
62 | /// What kind of key we have. |
63 | fn algorithm(&self) -> SignatureAlgorithm; |
64 | } |
65 | |
66 | /// A thing that can sign a message. |
67 | pub trait Signer: Debug + Send + Sync { |
68 | /// Signs `message` using the selected scheme. |
69 | /// |
70 | /// `message` is not hashed; the implementer must hash it using the hash function |
71 | /// implicit in [`Self::scheme()`]. |
72 | /// |
73 | /// The returned signature format is also defined by [`Self::scheme()`]. |
74 | fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error>; |
75 | |
76 | /// Reveals which scheme will be used when you call [`Self::sign()`]. |
77 | fn scheme(&self) -> SignatureScheme; |
78 | } |
79 | |
80 | /// A packaged-together certificate chain, matching `SigningKey` and |
81 | /// optional stapled OCSP response. |
82 | #[derive (Clone, Debug)] |
83 | pub struct CertifiedKey { |
84 | /// The certificate chain. |
85 | pub cert: Vec<CertificateDer<'static>>, |
86 | |
87 | /// The certified key. |
88 | pub key: Arc<dyn SigningKey>, |
89 | |
90 | /// An optional OCSP response from the certificate issuer, |
91 | /// attesting to its continued validity. |
92 | pub ocsp: Option<Vec<u8>>, |
93 | } |
94 | |
95 | impl CertifiedKey { |
96 | /// Make a new CertifiedKey, with the given chain and key. |
97 | /// |
98 | /// The cert chain must not be empty. The first certificate in the chain |
99 | /// must be the end-entity certificate. |
100 | pub fn new(cert: Vec<CertificateDer<'static>>, key: Arc<dyn SigningKey>) -> Self { |
101 | Self { |
102 | cert, |
103 | key, |
104 | ocsp: None, |
105 | } |
106 | } |
107 | |
108 | /// The end-entity certificate. |
109 | pub fn end_entity_cert(&self) -> Result<&CertificateDer<'_>, Error> { |
110 | self.cert |
111 | .first() |
112 | .ok_or(err:Error::NoCertificatesPresented) |
113 | } |
114 | } |
115 | |