rustls_openssl/
signer.rs

1use openssl::hash::MessageDigest;
2use openssl::pkey::{Id, Private};
3use openssl::rsa::Padding;
4use openssl::sign::RsaPssSaltlen;
5use rustls::pki_types::PrivateKeyDer;
6use rustls::sign::SigningKey;
7use rustls::{Error, SignatureAlgorithm, SignatureScheme};
8use std::sync::Arc;
9
10/// A struct that implements [rustls::crypto::KeyProvider].
11#[derive(Debug)]
12pub struct KeyProvider;
13
14/// RSA schemes in descending order of preference
15pub(crate) static RSA_SCHEMES: &[SignatureScheme] = &[
16    SignatureScheme::RSA_PSS_SHA512,
17    SignatureScheme::RSA_PSS_SHA384,
18    SignatureScheme::RSA_PSS_SHA256,
19    SignatureScheme::RSA_PKCS1_SHA512,
20    SignatureScheme::RSA_PKCS1_SHA384,
21    SignatureScheme::RSA_PKCS1_SHA256,
22];
23
24#[derive(Debug)]
25struct Signer {
26    key: Arc<openssl::pkey::PKey<Private>>,
27    scheme: SignatureScheme,
28}
29
30#[derive(Debug)]
31struct PKey(Arc<openssl::pkey::PKey<Private>>);
32
33fn rsa_padding(scheme: SignatureScheme) -> Option<Padding> {
34    match scheme {
35        SignatureScheme::RSA_PKCS1_SHA256
36        | SignatureScheme::RSA_PKCS1_SHA384
37        | SignatureScheme::RSA_PKCS1_SHA512 => Some(Padding::PKCS1),
38        SignatureScheme::RSA_PSS_SHA256
39        | SignatureScheme::RSA_PSS_SHA384
40        | SignatureScheme::RSA_PSS_SHA512 => Some(Padding::PKCS1_PSS),
41        _ => None,
42    }
43}
44
45fn message_digest(scheme: SignatureScheme) -> Option<MessageDigest> {
46    match scheme {
47        SignatureScheme::RSA_PKCS1_SHA256
48        | SignatureScheme::RSA_PSS_SHA256
49        | SignatureScheme::ECDSA_NISTP256_SHA256 => Some(MessageDigest::sha256()),
50        SignatureScheme::RSA_PKCS1_SHA384
51        | SignatureScheme::RSA_PSS_SHA384
52        | SignatureScheme::ECDSA_NISTP384_SHA384 => Some(MessageDigest::sha384()),
53        SignatureScheme::RSA_PKCS1_SHA512
54        | SignatureScheme::RSA_PSS_SHA512
55        | SignatureScheme::ECDSA_NISTP521_SHA512 => Some(MessageDigest::sha512()),
56        _ => None,
57    }
58}
59
60fn mgf1(scheme: SignatureScheme) -> Option<MessageDigest> {
61    match scheme {
62        SignatureScheme::RSA_PSS_SHA256 => Some(MessageDigest::sha256()),
63        SignatureScheme::RSA_PSS_SHA384 => Some(MessageDigest::sha384()),
64        SignatureScheme::RSA_PSS_SHA512 => Some(MessageDigest::sha512()),
65        _ => None,
66    }
67}
68
69fn pss_salt_len(scheme: SignatureScheme) -> Option<RsaPssSaltlen> {
70    match scheme {
71        SignatureScheme::RSA_PSS_SHA256
72        | SignatureScheme::RSA_PSS_SHA384
73        | SignatureScheme::RSA_PSS_SHA512 => Some(RsaPssSaltlen::DIGEST_LENGTH),
74        _ => None,
75    }
76}
77
78impl PKey {
79    fn signer(&self, scheme: SignatureScheme) -> Signer {
80        Signer {
81            key: Arc::clone(&self.0),
82            scheme,
83        }
84    }
85}
86
87impl rustls::crypto::KeyProvider for KeyProvider {
88    fn load_private_key(
89        &self,
90        key_der: PrivateKeyDer<'static>,
91    ) -> Result<Arc<dyn SigningKey>, Error> {
92        let pkey = openssl::pkey::PKey::private_key_from_der(key_der.secret_der())
93            .map_err(|e| Error::General(format!("OpenSSL error: {e}")))?;
94        Ok(Arc::new(PKey(Arc::new(pkey))))
95    }
96
97    fn fips(&self) -> bool {
98        crate::fips::enabled()
99    }
100}
101
102impl SigningKey for PKey {
103    fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn rustls::sign::Signer>> {
104        match self.algorithm() {
105            SignatureAlgorithm::RSA => RSA_SCHEMES
106                .iter()
107                .find(|scheme| offered.contains(scheme))
108                .map(|scheme| Box::new(self.signer(*scheme)) as Box<dyn rustls::sign::Signer>),
109
110            SignatureAlgorithm::ED25519 => {
111                if offered.contains(&SignatureScheme::ED25519) {
112                    Some(Box::new(Signer {
113                        key: Arc::clone(&self.0),
114                        scheme: SignatureScheme::ED25519,
115                    }))
116                } else {
117                    None
118                }
119            }
120            SignatureAlgorithm::ED448 => {
121                if offered.contains(&SignatureScheme::ED448) {
122                    Some(Box::new(Signer {
123                        key: Arc::clone(&self.0),
124                        scheme: SignatureScheme::ED448,
125                    }))
126                } else {
127                    None
128                }
129            }
130            SignatureAlgorithm::ECDSA => {
131                // First determine our scheme
132                self.0
133                    .ec_key()
134                    .ok()
135                    .and_then(|ec_key| {
136                        let nid = ec_key.group().curve_name();
137                        let scheme = match nid {
138                            Some(openssl::nid::Nid::X9_62_PRIME256V1) => {
139                                SignatureScheme::ECDSA_NISTP256_SHA256
140                            }
141                            Some(openssl::nid::Nid::SECP384R1) => {
142                                SignatureScheme::ECDSA_NISTP384_SHA384
143                            }
144                            Some(openssl::nid::Nid::SECP521R1) => {
145                                SignatureScheme::ECDSA_NISTP521_SHA512
146                            }
147                            _ => return None,
148                        };
149                        Some(scheme)
150                    })
151                    // Now see if that was offered
152                    .and_then(|scheme| {
153                        if offered.contains(&scheme) {
154                            Some(Box::new(self.signer(scheme)) as Box<dyn rustls::sign::Signer>)
155                        } else {
156                            None
157                        }
158                    })
159            }
160            _ => None,
161        }
162    }
163
164    fn algorithm(&self) -> SignatureAlgorithm {
165        match self.0.id() {
166            Id::RSA => SignatureAlgorithm::RSA,
167            Id::EC => SignatureAlgorithm::ECDSA,
168            Id::ED448 => SignatureAlgorithm::ED448,
169            Id::ED25519 => SignatureAlgorithm::ED25519,
170            _ => SignatureAlgorithm::Unknown(self.0.id().as_raw().try_into().unwrap_or_default()),
171        }
172    }
173}
174
175impl rustls::sign::Signer for Signer {
176    fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
177        if let Some(message_digest) = message_digest(self.scheme) {
178            openssl::sign::Signer::new(message_digest, &self.key)
179                .and_then(|mut signer| {
180                    if let Some(padding) = rsa_padding(self.scheme) {
181                        signer.set_rsa_padding(padding)?;
182                    }
183                    if let Some(mgf1) = mgf1(self.scheme) {
184                        signer.set_rsa_mgf1_md(mgf1)?;
185                    }
186                    if let Some(len) = pss_salt_len(self.scheme) {
187                        signer.set_rsa_pss_saltlen(len)?;
188                    }
189                    signer.update(message)?;
190                    signer.sign_to_vec()
191                })
192                .map_err(|e| Error::General(format!("OpenSSL error: {e}")))
193        } else {
194            openssl::sign::Signer::new_without_digest(&self.key)
195                .and_then(|mut signer| signer.sign_oneshot_to_vec(message))
196                .map_err(|e| Error::General(format!("OpenSSL error: {e}")))
197        }
198    }
199
200    fn scheme(&self) -> SignatureScheme {
201        self.scheme
202    }
203}