1use core::fmt;
2use once_cell::sync::Lazy;
3use openssl::{
4 bn::BigNumContext,
5 ec::{EcGroup, EcKey, EcPoint},
6 hash::MessageDigest,
7 nid::Nid,
8 pkey::{Id, PKey, Public},
9 rsa::{Padding, Rsa},
10 sign::{RsaPssSaltlen, Verifier},
11};
12use rustls::pki_types::alg_id;
13use rustls::{
14 SignatureScheme,
15 crypto::WebPkiSupportedAlgorithms,
16 pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm},
17};
18
19pub static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
21 all: &[
22 ECDSA_P256_SHA256,
23 ECDSA_P256_SHA384,
24 ECDSA_P384_SHA256,
25 ECDSA_P384_SHA384,
26 ECDSA_P521_SHA256,
27 ECDSA_P521_SHA384,
28 ECDSA_P521_SHA512,
29 ED25519,
30 RSA_PSS_SHA512,
31 RSA_PSS_SHA384,
32 RSA_PSS_SHA256,
33 RSA_PKCS1_SHA512,
34 RSA_PKCS1_SHA384,
35 RSA_PKCS1_SHA256,
36 ],
37 mapping: &[
38 (
40 SignatureScheme::ECDSA_NISTP384_SHA384,
41 &[ECDSA_P384_SHA384, ECDSA_P256_SHA384, ECDSA_P521_SHA384],
42 ),
43 (
44 SignatureScheme::ECDSA_NISTP256_SHA256,
45 &[ECDSA_P256_SHA256, ECDSA_P384_SHA256, ECDSA_P521_SHA256],
46 ),
47 (SignatureScheme::ECDSA_NISTP521_SHA512, &[ECDSA_P521_SHA512]),
48 (SignatureScheme::ED25519, &[ED25519]),
49 (SignatureScheme::RSA_PSS_SHA512, &[RSA_PSS_SHA512]),
50 (SignatureScheme::RSA_PSS_SHA384, &[RSA_PSS_SHA384]),
51 (SignatureScheme::RSA_PSS_SHA256, &[RSA_PSS_SHA256]),
52 (SignatureScheme::RSA_PKCS1_SHA512, &[RSA_PKCS1_SHA512]),
53 (SignatureScheme::RSA_PKCS1_SHA384, &[RSA_PKCS1_SHA384]),
54 (SignatureScheme::RSA_PKCS1_SHA256, &[RSA_PKCS1_SHA256]),
55 ],
56};
57
58static SUPPORTED_SIG_ALGS_NO_ED25519: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
61 all: &[
62 ECDSA_P256_SHA256,
63 ECDSA_P256_SHA384,
64 ECDSA_P384_SHA256,
65 ECDSA_P384_SHA384,
66 ECDSA_P521_SHA256,
67 ECDSA_P521_SHA384,
68 ECDSA_P521_SHA512,
69 RSA_PSS_SHA512,
70 RSA_PSS_SHA384,
71 RSA_PSS_SHA256,
72 RSA_PKCS1_SHA512,
73 RSA_PKCS1_SHA384,
74 RSA_PKCS1_SHA256,
75 ],
76 mapping: &[
77 (
78 SignatureScheme::ECDSA_NISTP384_SHA384,
79 &[ECDSA_P384_SHA384, ECDSA_P256_SHA384, ECDSA_P521_SHA384],
80 ),
81 (
82 SignatureScheme::ECDSA_NISTP256_SHA256,
83 &[ECDSA_P256_SHA256, ECDSA_P384_SHA256, ECDSA_P521_SHA256],
84 ),
85 (SignatureScheme::ECDSA_NISTP521_SHA512, &[ECDSA_P521_SHA512]),
86 (SignatureScheme::RSA_PSS_SHA512, &[RSA_PSS_SHA512]),
87 (SignatureScheme::RSA_PSS_SHA384, &[RSA_PSS_SHA384]),
88 (SignatureScheme::RSA_PSS_SHA256, &[RSA_PSS_SHA256]),
89 (SignatureScheme::RSA_PKCS1_SHA512, &[RSA_PKCS1_SHA512]),
90 (SignatureScheme::RSA_PKCS1_SHA384, &[RSA_PKCS1_SHA384]),
91 (SignatureScheme::RSA_PKCS1_SHA256, &[RSA_PKCS1_SHA256]),
92 ],
93};
94
95static AVAILABLE_SIG_ALGS: Lazy<&'static WebPkiSupportedAlgorithms> = Lazy::new(|| {
96 if ed25519_available() {
98 &SUPPORTED_SIG_ALGS
99 } else {
100 &SUPPORTED_SIG_ALGS_NO_ED25519
101 }
102});
103
104static ED25519_AVAILABLE: Lazy<bool> = Lazy::new(|| PKey::generate_ed25519().is_ok());
105
106pub(crate) fn available_supported_sig_algs() -> &'static WebPkiSupportedAlgorithms {
107 *AVAILABLE_SIG_ALGS
108}
109
110pub(crate) fn ed25519_available() -> bool {
111 *ED25519_AVAILABLE
112}
113
114pub(crate) static RSA_PKCS1_SHA256: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
116 display_name: "RSA_PKCS1_SHA256",
117 public_key_alg_id: alg_id::RSA_ENCRYPTION,
118 signature_alg_id: alg_id::RSA_PKCS1_SHA256,
119};
120
121pub(crate) static RSA_PKCS1_SHA384: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
123 display_name: "RSA_PKCS1_SHA384",
124 public_key_alg_id: alg_id::RSA_ENCRYPTION,
125 signature_alg_id: alg_id::RSA_PKCS1_SHA384,
126};
127
128pub(crate) static RSA_PKCS1_SHA512: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
130 display_name: "RSA_PKCS1_SHA512",
131 public_key_alg_id: alg_id::RSA_ENCRYPTION,
132 signature_alg_id: alg_id::RSA_PKCS1_SHA512,
133};
134
135pub(crate) static RSA_PSS_SHA256: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
137 display_name: "RSA_PSS_SHA256",
138 public_key_alg_id: alg_id::RSA_ENCRYPTION,
139 signature_alg_id: alg_id::RSA_PSS_SHA256,
140};
141
142pub(crate) static RSA_PSS_SHA384: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
144 display_name: "RSA_PSS_SHA384",
145 public_key_alg_id: alg_id::RSA_ENCRYPTION,
146 signature_alg_id: alg_id::RSA_PSS_SHA384,
147};
148
149pub(crate) static RSA_PSS_SHA512: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
151 display_name: "RSA_PSS_SHA512",
152 public_key_alg_id: alg_id::RSA_ENCRYPTION,
153 signature_alg_id: alg_id::RSA_PSS_SHA512,
154};
155
156pub(crate) static ED25519: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
158 display_name: "ED25519",
159 public_key_alg_id: alg_id::ED25519,
160 signature_alg_id: alg_id::ED25519,
161};
162
163pub(crate) static ECDSA_P256_SHA256: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
165 display_name: "ECDSA_P256_SHA256",
166 public_key_alg_id: alg_id::ECDSA_P256,
167 signature_alg_id: alg_id::ECDSA_SHA256,
168};
169
170pub(crate) static ECDSA_P256_SHA384: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
172 display_name: "ECDSA_P256_SHA384",
173 public_key_alg_id: alg_id::ECDSA_P256,
174 signature_alg_id: alg_id::ECDSA_SHA384,
175};
176
177pub(crate) static ECDSA_P384_SHA256: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
179 display_name: "ECDSA_P384_SHA256",
180 public_key_alg_id: alg_id::ECDSA_P384,
181 signature_alg_id: alg_id::ECDSA_SHA256,
182};
183
184pub(crate) static ECDSA_P384_SHA384: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
186 display_name: "ECDSA_P384_SHA384",
187 public_key_alg_id: alg_id::ECDSA_P384,
188 signature_alg_id: alg_id::ECDSA_SHA384,
189};
190
191pub(crate) static ECDSA_P521_SHA256: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
193 display_name: "ECDSA_P521_SHA256",
194 public_key_alg_id: alg_id::ECDSA_P521,
195 signature_alg_id: alg_id::ECDSA_SHA256,
196};
197
198pub(crate) static ECDSA_P521_SHA384: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
200 display_name: "ECDSA_P521_SHA384",
201 public_key_alg_id: alg_id::ECDSA_P521,
202 signature_alg_id: alg_id::ECDSA_SHA384,
203};
204
205pub(crate) static ECDSA_P521_SHA512: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
207 display_name: "ECDSA_P521_SHA512",
208 public_key_alg_id: alg_id::ECDSA_P521,
209 signature_alg_id: alg_id::ECDSA_SHA512,
210};
211
212struct OpenSslAlgorithm {
213 display_name: &'static str,
214 public_key_alg_id: AlgorithmIdentifier,
215 signature_alg_id: AlgorithmIdentifier,
216}
217
218impl fmt::Debug for OpenSslAlgorithm {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 write!(
221 f,
222 "rustls_openssl Signature Verification Algorithm: {}",
223 self.display_name
224 )
225 }
226}
227
228fn ecdsa_public_key(curve_name: Nid, public_key: &[u8]) -> Result<PKey<Public>, InvalidSignature> {
229 EcGroup::from_curve_name(curve_name)
230 .and_then(|group| {
231 let mut ctx = BigNumContext::new()?;
232 let point = EcPoint::from_bytes(&group, public_key, &mut ctx)?;
233 let key = EcKey::from_public_key(&group, &point)?;
234 key.try_into()
235 })
236 .map_err(|_| InvalidSignature)
237}
238
239impl OpenSslAlgorithm {
240 fn public_key(&self, public_key: &[u8]) -> Result<PKey<Public>, InvalidSignature> {
241 match self.public_key_alg_id {
242 alg_id::RSA_ENCRYPTION => Rsa::public_key_from_der_pkcs1(public_key)
243 .and_then(std::convert::TryInto::try_into)
244 .map_err(|_| InvalidSignature),
245 alg_id::ECDSA_P521 => ecdsa_public_key(Nid::SECP521R1, public_key),
246 alg_id::ECDSA_P384 => ecdsa_public_key(Nid::SECP384R1, public_key),
247 alg_id::ECDSA_P256 => ecdsa_public_key(Nid::X9_62_PRIME256V1, public_key),
248 alg_id::ED25519 => PKey::public_key_from_raw_bytes(public_key, Id::ED25519)
249 .map_err(|_| InvalidSignature),
250
251 _ => Err(InvalidSignature),
252 }
253 }
254
255 fn message_digest(&self) -> Option<MessageDigest> {
256 match self.signature_alg_id {
257 alg_id::RSA_PKCS1_SHA256 | alg_id::ECDSA_SHA256 | alg_id::RSA_PSS_SHA256 => {
258 Some(MessageDigest::sha256())
259 }
260 alg_id::RSA_PKCS1_SHA384 | alg_id::ECDSA_SHA384 | alg_id::RSA_PSS_SHA384 => {
261 Some(MessageDigest::sha384())
262 }
263 alg_id::RSA_PKCS1_SHA512 | alg_id::ECDSA_SHA512 | alg_id::RSA_PSS_SHA512 => {
264 Some(MessageDigest::sha512())
265 }
266 _ => None,
267 }
268 }
269
270 fn mgf1(&self) -> Option<MessageDigest> {
271 match self.signature_alg_id {
272 alg_id::RSA_PSS_SHA256 => Some(MessageDigest::sha256()),
273 alg_id::RSA_PSS_SHA384 => Some(MessageDigest::sha384()),
274 alg_id::RSA_PSS_SHA512 => Some(MessageDigest::sha512()),
275 _ => None,
276 }
277 }
278
279 fn pss_salt_len(&self) -> Option<RsaPssSaltlen> {
280 match self.signature_alg_id {
281 alg_id::RSA_PSS_SHA256 | alg_id::RSA_PSS_SHA384 | alg_id::RSA_PSS_SHA512 => {
282 Some(RsaPssSaltlen::DIGEST_LENGTH)
283 }
284 _ => None,
285 }
286 }
287
288 fn rsa_padding(&self) -> Option<Padding> {
289 match self.signature_alg_id {
290 alg_id::RSA_PSS_SHA512 | alg_id::RSA_PSS_SHA384 | alg_id::RSA_PSS_SHA256 => {
291 Some(Padding::PKCS1_PSS)
292 }
293 alg_id::RSA_PKCS1_SHA512 | alg_id::RSA_PKCS1_SHA384 | alg_id::RSA_PKCS1_SHA256 => {
294 Some(Padding::PKCS1)
295 }
296 _ => None,
297 }
298 }
299}
300
301impl SignatureVerificationAlgorithm for OpenSslAlgorithm {
302 fn public_key_alg_id(&self) -> AlgorithmIdentifier {
303 self.public_key_alg_id
304 }
305
306 fn signature_alg_id(&self) -> AlgorithmIdentifier {
307 self.signature_alg_id
308 }
309
310 fn verify_signature(
311 &self,
312 public_key: &[u8],
313 message: &[u8],
314 signature: &[u8],
315 ) -> Result<(), InvalidSignature> {
316 if matches!(
317 self.public_key_alg_id,
318 alg_id::ECDSA_P256 | alg_id::ECDSA_P384 | alg_id::ECDSA_P521
319 ) {
320 match public_key.first() {
329 Some(0x02..=0x04) => {}
330 _ => {
331 return Err(InvalidSignature);
332 }
333 };
334 }
335 let pkey = self.public_key(public_key)?;
336
337 if let Some(message_digest) = self.message_digest() {
338 Verifier::new(message_digest, &pkey).and_then(|mut verifier| {
339 if let Some(padding) = self.rsa_padding() {
340 verifier.set_rsa_padding(padding)?;
341 }
342 if let Some(mgf1_md) = self.mgf1() {
343 verifier.set_rsa_mgf1_md(mgf1_md)?;
344 }
345 if let Some(salt_len) = self.pss_salt_len() {
346 verifier.set_rsa_pss_saltlen(salt_len)?;
347 }
348 verifier.update(message)?;
349 verifier.verify(signature)
350 })
351 } else {
352 Verifier::new_without_digest(&pkey)
353 .and_then(|mut verifier| verifier.verify_oneshot(signature, message))
354 }
355 .map_err(|e| {
356 std::dbg!(e);
357 InvalidSignature
358 })
359 .and_then(|valid| if valid { Ok(()) } else { Err(InvalidSignature) })
360 }
361
362 fn fips(&self) -> bool {
363 crate::fips::enabled()
364 }
365}
366
367#[cfg(test)]
368mod tests {
369 use super::*;
370
371 #[test]
372 fn test_open_ssl_algorithm_debug() {
373 assert_eq!(
374 format!("{:?}", ECDSA_P256_SHA256),
375 "rustls_openssl Signature Verification Algorithm: ECDSA_P256_SHA256"
376 );
377 assert_eq!(
378 format!("{:?}", RSA_PSS_SHA256),
379 "rustls_openssl Signature Verification Algorithm: RSA_PSS_SHA256"
380 );
381 }
382}