rustls_rustcrypto/sign/
ecdsa.rs

1#[cfg(feature = "alloc")]
2use alloc::{boxed::Box, format, sync::Arc};
3use core::marker::PhantomData;
4
5use paste::paste;
6use pkcs8::DecodePrivateKey;
7use pki_types::PrivateKeyDer;
8use rustls::sign::SigningKey;
9use rustls::{SignatureAlgorithm, SignatureScheme};
10use sec1::DecodeEcPrivateKey;
11
12macro_rules! impl_ecdsa {
13    ($name: ident, $scheme: expr, $signing_key: ty, $signature: ty) => {
14        paste! {
15            #[derive(Debug)]
16            pub struct [<EcdsaSigningKey $name>] {
17                key:    Arc<$signing_key>,
18                scheme: SignatureScheme,
19            }
20
21            impl TryFrom<&PrivateKeyDer<'_>> for [<EcdsaSigningKey $name>] {
22                type Error = rustls::Error;
23
24                fn try_from(value: &PrivateKeyDer<'_>) -> Result<Self, Self::Error> {
25                    let pkey = match value {
26                        PrivateKeyDer::Pkcs8(der) => {
27                            $signing_key::from_pkcs8_der(der.secret_pkcs8_der()).map_err(|e| format!("failed to decrypt private key: {e}"))
28                        },
29                        PrivateKeyDer::Sec1(sec1) => {
30                            $signing_key::from_sec1_der(sec1.secret_sec1_der()).map_err(|e| format!("failed to decrypt private key: {e}"))
31                        },
32                        PrivateKeyDer::Pkcs1(_) => Err(format!("ECDSA does not support PKCS#1 key")),
33                        _ => Err("not supported".into()),
34                    };
35                    pkey.map(|kp| {
36                        Self {
37                            key:    Arc::new(kp),
38                            scheme: $scheme,
39                        }
40                    }).map_err(rustls::Error::General)
41                }
42            }
43
44            impl SigningKey for [<EcdsaSigningKey $name>] {
45                fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn rustls::sign::Signer>> {
46                    if offered.contains(&self.scheme) {
47                        Some(Box::new(super::GenericRandomizedSigner::<$signature, _> {
48                            _marker: PhantomData,
49                            key:     self.key.clone(),
50                            scheme:  self.scheme,
51                        }))
52                    } else {
53                        None
54                    }
55                }
56
57                fn algorithm(&self) -> SignatureAlgorithm {
58                    SignatureAlgorithm::ECDSA
59                }
60            }
61        }
62    };
63}
64
65impl_ecdsa! {P256, SignatureScheme::ECDSA_NISTP256_SHA256, p256::ecdsa::SigningKey, p256::ecdsa::DerSignature}
66impl_ecdsa! {P384, SignatureScheme::ECDSA_NISTP384_SHA384, p384::ecdsa::SigningKey, p384::ecdsa::DerSignature}