rustls_rustcrypto/sign/
rsa.rs

1#[cfg(feature = "alloc")]
2use alloc::{boxed::Box, format, string::ToString, sync::Arc};
3
4use pkcs8::DecodePrivateKey;
5use pki_types::PrivateKeyDer;
6use rsa::pkcs1::DecodeRsaPrivateKey;
7use rsa::RsaPrivateKey;
8use rustls::sign::{Signer, SigningKey};
9use rustls::{SignatureAlgorithm, SignatureScheme};
10use sha2::{Sha256, Sha384, Sha512};
11
12const ALL_RSA_SCHEMES: &[SignatureScheme] = &[
13    SignatureScheme::RSA_PSS_SHA512,
14    SignatureScheme::RSA_PSS_SHA384,
15    SignatureScheme::RSA_PSS_SHA256,
16    SignatureScheme::RSA_PKCS1_SHA512,
17    SignatureScheme::RSA_PKCS1_SHA384,
18    SignatureScheme::RSA_PKCS1_SHA256,
19];
20
21#[derive(Debug)]
22pub struct RsaSigningKey(RsaPrivateKey);
23
24impl TryFrom<&PrivateKeyDer<'_>> for RsaSigningKey {
25    type Error = rustls::Error;
26
27    fn try_from(value: &PrivateKeyDer<'_>) -> Result<Self, Self::Error> {
28        let pkey = match value {
29            PrivateKeyDer::Pkcs8(der) => RsaPrivateKey::from_pkcs8_der(der.secret_pkcs8_der())
30                .map_err(|e| format!("failed to decrypt private key: {e}")),
31            PrivateKeyDer::Pkcs1(der) => RsaPrivateKey::from_pkcs1_der(der.secret_pkcs1_der())
32                .map_err(|e| format!("failed to decrypt private key: {e}")),
33            PrivateKeyDer::Sec1(_) => Err("RSA does not support SEC-1 key".to_string()),
34            _ => Err("not supported".into()),
35        };
36
37        pkey.map(Self).map_err(rustls::Error::General)
38    }
39}
40
41impl SigningKey for RsaSigningKey {
42    fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
43        ALL_RSA_SCHEMES
44            .iter()
45            .find(|scheme| offered.contains(scheme))
46            .and_then(|&scheme| {
47                macro_rules! signer {
48                    ($key:ty) => {{
49                        Some(Box::new(super::GenericRandomizedSigner {
50                            _marker: Default::default(),
51                            key: Arc::new(<$key>::new(self.0.clone())),
52                            scheme,
53                        }) as Box<_>)
54                    }};
55                }
56
57                match scheme {
58                    SignatureScheme::RSA_PSS_SHA512 => signer! {rsa::pss::SigningKey::<Sha512>},
59                    SignatureScheme::RSA_PSS_SHA384 => signer! {rsa::pss::SigningKey::<Sha384>},
60                    SignatureScheme::RSA_PSS_SHA256 => signer! {rsa::pss::SigningKey::<Sha256>},
61                    SignatureScheme::RSA_PKCS1_SHA512 => {
62                        signer! {rsa::pkcs1v15::SigningKey::<Sha512>}
63                    }
64                    SignatureScheme::RSA_PKCS1_SHA384 => {
65                        signer! {rsa::pkcs1v15::SigningKey::<Sha384>}
66                    }
67                    SignatureScheme::RSA_PKCS1_SHA256 => {
68                        signer! {rsa::pkcs1v15::SigningKey::<Sha256>}
69                    }
70                    _ => None,
71                }
72            })
73    }
74
75    fn algorithm(&self) -> SignatureAlgorithm {
76        SignatureAlgorithm::RSA
77    }
78}