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 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 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 .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}