1use std::sync::Arc;
8
9use rustls::pki_types::PrivateKeyDer;
10use rustls::sign::{Signer, SigningKey};
11use rustls::{Error as RustlsError, SignatureAlgorithm, SignatureScheme};
12
13use ferritls_core::sign::{ecdsa, ed25519, rsa};
14
15pub struct EcdsaP256Key(ecdsa::p256::SigningKey);
17
18pub struct EcdsaP384Key(ecdsa::p384::SigningKey);
20
21pub struct Ed25519Key(ed25519::SigningKey);
23
24pub struct RsaKey(rsa::SigningKey);
26
27impl std::fmt::Debug for EcdsaP256Key {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 f.write_str("EcdsaP256Key")
30 }
31}
32
33impl std::fmt::Debug for EcdsaP384Key {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 f.write_str("EcdsaP384Key")
36 }
37}
38
39impl std::fmt::Debug for Ed25519Key {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 f.write_str("Ed25519Key")
42 }
43}
44
45impl std::fmt::Debug for RsaKey {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 f.write_str("RsaKey")
48 }
49}
50
51impl EcdsaP256Key {
52 pub fn new(d: &[u8; 32]) -> Self {
54 Self(ecdsa::p256::SigningKey::from_seed(*d))
55 }
56}
57
58impl EcdsaP384Key {
59 pub fn new(d: &[u8; 48]) -> Self {
61 Self(ecdsa::p384::SigningKey::from_seed(*d))
62 }
63}
64
65impl Ed25519Key {
66 pub fn new(seed: &[u8; 32]) -> Self {
68 Self(ed25519::SigningKey::from_seed(*seed))
69 }
70}
71
72impl RsaKey {
73 pub fn from_pkcs1_der(der: &[u8]) -> Result<Self, RustlsError> {
75 rsa::SigningKey::from_pkcs1_der(der)
76 .map(Self)
77 .map_err(|_| RustlsError::General("invalid RSA private key".into()))
78 }
79
80 pub fn from_pkcs8_der(der: &[u8]) -> Result<Self, RustlsError> {
82 rsa::SigningKey::from_pkcs8_der(der)
83 .map(Self)
84 .map_err(|_| RustlsError::General("invalid RSA private key".into()))
85 }
86}
87
88impl SigningKey for EcdsaP256Key {
89 fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
90 if offered.contains(&SignatureScheme::ECDSA_NISTP256_SHA256) {
91 Some(Box::new(EcdsaP256Signer(self.0.clone())))
92 } else {
93 None
94 }
95 }
96
97 fn algorithm(&self) -> SignatureAlgorithm {
98 SignatureAlgorithm::ECDSA
99 }
100}
101
102impl SigningKey for EcdsaP384Key {
103 fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
104 if offered.contains(&SignatureScheme::ECDSA_NISTP384_SHA384) {
105 Some(Box::new(EcdsaP384Signer(self.0.clone())))
106 } else {
107 None
108 }
109 }
110
111 fn algorithm(&self) -> SignatureAlgorithm {
112 SignatureAlgorithm::ECDSA
113 }
114}
115
116impl SigningKey for Ed25519Key {
117 fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
118 if offered.contains(&SignatureScheme::ED25519) {
119 Some(Box::new(Ed25519Signer(self.0.clone())))
120 } else {
121 None
122 }
123 }
124
125 fn algorithm(&self) -> SignatureAlgorithm {
126 SignatureAlgorithm::ED25519
127 }
128}
129
130impl SigningKey for RsaKey {
131 fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
132 const PREFERRED: [SignatureScheme; 6] = [
134 SignatureScheme::RSA_PSS_SHA256,
135 SignatureScheme::RSA_PSS_SHA384,
136 SignatureScheme::RSA_PSS_SHA512,
137 SignatureScheme::RSA_PKCS1_SHA256,
138 SignatureScheme::RSA_PKCS1_SHA384,
139 SignatureScheme::RSA_PKCS1_SHA512,
140 ];
141 PREFERRED.iter().find_map(|s| {
142 if offered.contains(s) {
143 Some(Box::new(RsaSigner {
144 scheme: *s,
145 key: self.0.clone(),
146 }) as Box<dyn Signer>)
147 } else {
148 None
149 }
150 })
151 }
152
153 fn algorithm(&self) -> SignatureAlgorithm {
154 SignatureAlgorithm::RSA
155 }
156}
157
158pub struct EcdsaP256Signer(ecdsa::p256::SigningKey);
160
161pub struct EcdsaP384Signer(ecdsa::p384::SigningKey);
163
164pub struct Ed25519Signer(ed25519::SigningKey);
166
167pub struct RsaSigner {
169 pub scheme: SignatureScheme,
171 key: rsa::SigningKey,
172}
173
174impl std::fmt::Debug for EcdsaP256Signer {
175 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176 f.write_str("EcdsaP256Signer")
177 }
178}
179
180impl std::fmt::Debug for EcdsaP384Signer {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 f.write_str("EcdsaP384Signer")
183 }
184}
185
186impl std::fmt::Debug for Ed25519Signer {
187 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188 f.write_str("Ed25519Signer")
189 }
190}
191
192impl std::fmt::Debug for RsaSigner {
193 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
194 f.write_str("RsaSigner")
195 }
196}
197
198fn map_sign_err(_: ferritls_core::Error) -> RustlsError {
199 RustlsError::General("signing failed".into())
200}
201
202impl Signer for EcdsaP256Signer {
203 fn sign(&self, message: &[u8]) -> Result<Vec<u8>, RustlsError> {
204 self.0.sign(message).map_err(map_sign_err)
205 }
206
207 fn scheme(&self) -> SignatureScheme {
208 SignatureScheme::ECDSA_NISTP256_SHA256
209 }
210}
211
212impl Signer for EcdsaP384Signer {
213 fn sign(&self, message: &[u8]) -> Result<Vec<u8>, RustlsError> {
214 self.0.sign(message).map_err(map_sign_err)
215 }
216
217 fn scheme(&self) -> SignatureScheme {
218 SignatureScheme::ECDSA_NISTP384_SHA384
219 }
220}
221
222impl Signer for Ed25519Signer {
223 fn sign(&self, message: &[u8]) -> Result<Vec<u8>, RustlsError> {
224 Ok(self.0.sign(message).to_vec())
225 }
226
227 fn scheme(&self) -> SignatureScheme {
228 SignatureScheme::ED25519
229 }
230}
231
232impl Signer for RsaSigner {
233 fn sign(&self, message: &[u8]) -> Result<Vec<u8>, RustlsError> {
234 let bits = match self.scheme {
235 SignatureScheme::RSA_PSS_SHA256 | SignatureScheme::RSA_PKCS1_SHA256 => 256,
236 SignatureScheme::RSA_PSS_SHA384 | SignatureScheme::RSA_PKCS1_SHA384 => 384,
237 SignatureScheme::RSA_PSS_SHA512 | SignatureScheme::RSA_PKCS1_SHA512 => 512,
238 _ => return Err(RustlsError::General("unsupported RSA scheme".into())),
239 };
240 let pss = matches!(
241 self.scheme,
242 SignatureScheme::RSA_PSS_SHA256
243 | SignatureScheme::RSA_PSS_SHA384
244 | SignatureScheme::RSA_PSS_SHA512
245 );
246 let result = if pss {
247 self.key.sign_pss(bits, message)
248 } else {
249 self.key.sign_pkcs1v15(bits, message)
250 };
251 result.map_err(map_sign_err)
252 }
253
254 fn scheme(&self) -> SignatureScheme {
255 self.scheme
256 }
257}
258
259#[derive(Debug)]
262pub struct KeyLoader;
263
264impl KeyLoader {
265 pub fn from_pkcs8(der: &[u8]) -> Result<Arc<dyn SigningKey>, RustlsError> {
267 let parsed = ferritls_core::der::parse_pkcs8_private_key(der)
268 .map_err(|_| RustlsError::General("invalid private key".into()))?;
269 match parsed {
270 ferritls_core::der::ParsedPrivateKey::P256 { scalar, .. } => {
271 Ok(Arc::new(EcdsaP256Key::new(&scalar)))
272 }
273 ferritls_core::der::ParsedPrivateKey::P384 { scalar, .. } => {
274 Ok(Arc::new(EcdsaP384Key::new(&scalar)))
275 }
276 ferritls_core::der::ParsedPrivateKey::RsaPkcs1(pkcs1) => {
277 RsaKey::from_pkcs1_der(&pkcs1).map(|k| Arc::new(k) as Arc<dyn SigningKey>)
278 }
279 ferritls_core::der::ParsedPrivateKey::Ed25519(seed) => Ok(Arc::new(Ed25519Key::new(
280 seed.as_slice().try_into().expect("32-byte seed"),
281 ))),
282 }
283 }
284}
285
286impl rustls::crypto::KeyProvider for KeyLoader {
287 fn load_private_key(
288 &self,
289 key_der: PrivateKeyDer<'static>,
290 ) -> Result<Arc<dyn SigningKey>, RustlsError> {
291 any_supported_type(&key_der)
292 }
293
294 fn fips(&self) -> bool {
295 false
297 }
298}
299
300pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result<Arc<dyn SigningKey>, RustlsError> {
302 let der_bytes = der.secret_der();
303 if let Ok(key) = KeyLoader::from_pkcs8(der_bytes) {
305 return Ok(key);
306 }
307 if let Ok(key) = RsaKey::from_pkcs1_der(der_bytes) {
309 return Ok(Arc::new(key));
310 }
311 Err(RustlsError::General(
312 "unsupported private key format or algorithm".into(),
313 ))
314}
315
316pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result<Arc<dyn SigningKey>, RustlsError> {
318 let der_bytes = der.secret_der();
319 if let Ok(key) = KeyLoader::from_pkcs8(der_bytes) {
320 let alg = key.algorithm();
321 if alg == SignatureAlgorithm::ECDSA {
322 return Ok(key);
323 }
324 }
325 Err(RustlsError::General("not an ECDSA key".into()))
326}
327
328pub static KEY_LOADER: &dyn rustls::crypto::KeyProvider = &KeyLoader;