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#[derive(Debug)]
12pub struct KeyProvider;
13
14pub(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 crate::verify::ed25519_available() && offered.contains(&SignatureScheme::ED25519)
112 {
113 Some(Box::new(Signer {
114 key: Arc::clone(&self.0),
115 scheme: SignatureScheme::ED25519,
116 }))
117 } else {
118 None
119 }
120 }
121 SignatureAlgorithm::ED448 => {
122 if offered.contains(&SignatureScheme::ED448) {
123 Some(Box::new(Signer {
124 key: Arc::clone(&self.0),
125 scheme: SignatureScheme::ED448,
126 }))
127 } else {
128 None
129 }
130 }
131 SignatureAlgorithm::ECDSA => {
132 self.0
134 .ec_key()
135 .ok()
136 .and_then(|ec_key| {
137 let nid = ec_key.group().curve_name();
138 let scheme = match nid {
139 Some(openssl::nid::Nid::X9_62_PRIME256V1) => {
140 SignatureScheme::ECDSA_NISTP256_SHA256
141 }
142 Some(openssl::nid::Nid::SECP384R1) => {
143 SignatureScheme::ECDSA_NISTP384_SHA384
144 }
145 Some(openssl::nid::Nid::SECP521R1) => {
146 SignatureScheme::ECDSA_NISTP521_SHA512
147 }
148 _ => return None,
149 };
150 Some(scheme)
151 })
152 .and_then(|scheme| {
154 if offered.contains(&scheme) {
155 Some(Box::new(self.signer(scheme)) as Box<dyn rustls::sign::Signer>)
156 } else {
157 None
158 }
159 })
160 }
161 _ => None,
162 }
163 }
164
165 fn algorithm(&self) -> SignatureAlgorithm {
166 match self.0.id() {
167 Id::RSA => SignatureAlgorithm::RSA,
168 Id::EC => SignatureAlgorithm::ECDSA,
169 Id::ED448 => SignatureAlgorithm::ED448,
170 Id::ED25519 => SignatureAlgorithm::ED25519,
171 _ => SignatureAlgorithm::Unknown(self.0.id().as_raw().try_into().unwrap_or_default()),
172 }
173 }
174}
175
176impl rustls::sign::Signer for Signer {
177 fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
178 if let Some(message_digest) = message_digest(self.scheme) {
179 openssl::sign::Signer::new(message_digest, &self.key)
180 .and_then(|mut signer| {
181 if let Some(padding) = rsa_padding(self.scheme) {
182 signer.set_rsa_padding(padding)?;
183 }
184 if let Some(mgf1) = mgf1(self.scheme) {
185 signer.set_rsa_mgf1_md(mgf1)?;
186 }
187 if let Some(len) = pss_salt_len(self.scheme) {
188 signer.set_rsa_pss_saltlen(len)?;
189 }
190 signer.update(message)?;
191 signer.sign_to_vec()
192 })
193 .map_err(|e| Error::General(format!("OpenSSL error: {e}")))
194 } else {
195 openssl::sign::Signer::new_without_digest(&self.key)
196 .and_then(|mut signer| signer.sign_oneshot_to_vec(message))
197 .map_err(|e| Error::General(format!("OpenSSL error: {e}")))
198 }
199 }
200
201 fn scheme(&self) -> SignatureScheme {
202 self.scheme
203 }
204}