1use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
2
3use rustls_pki_types::{PrivateKeyDer, PrivatePkcs1KeyDer, PrivatePkcs8KeyDer};
4
5use super::{
6 Algorithm, DigestType, DnsSecError, DnsSecResult, PublicKey, PublicKeyBuf, SigningKey, TBS,
7 ec_public_key::ECPublicKey,
8 ring_like::{
9 ECDSA_P256_SHA256_FIXED_SIGNING, ECDSA_P384_SHA384_FIXED_SIGNING, ED25519_PUBLIC_KEY_LEN,
10 EcdsaKeyPair, Ed25519KeyPair, KeyPair, PublicKeyComponents, RSA_PKCS1_SHA256,
11 RSA_PKCS1_SHA512, RsaKeyPair, SystemRandom, digest, signature,
12 },
13 rsa_public_key::RSAPublicKey,
14};
15use crate::{ProtoError, error::ProtoResult, serialize::binary::DecodeError};
16
17pub fn signing_key_from_der(
19 key_der: &PrivateKeyDer<'_>,
20 algorithm: Algorithm,
21) -> DnsSecResult<Box<dyn SigningKey>> {
22 #[allow(deprecated)]
23 match algorithm {
24 Algorithm::Unknown(v) => Err(format!("unknown algorithm: {v}").into()),
25 Algorithm::RSASHA256 | Algorithm::RSASHA512 => {
26 Ok(Box::new(RsaSigningKey::from_key_der(key_der, algorithm)?))
27 }
28 Algorithm::ECDSAP256SHA256 | Algorithm::ECDSAP384SHA384 => {
29 Ok(Box::new(EcdsaSigningKey::from_key_der(key_der, algorithm)?))
30 }
31 Algorithm::ED25519 => Ok(Box::new(Ed25519SigningKey::from_key_der(key_der)?)),
32 e => Err(format!("unsupported SigningKey algorithm for ring: {e:?}").into()),
33 }
34}
35
36pub(super) fn decode_public_key<'a>(
37 public_key: &'a [u8],
38 algorithm: Algorithm,
39) -> ProtoResult<Arc<dyn PublicKey + 'a>> {
40 debug_assert!(algorithm.is_supported());
42
43 #[allow(deprecated)]
44 match algorithm {
45 Algorithm::ECDSAP256SHA256 | Algorithm::ECDSAP384SHA384 => Ok(Arc::new(
46 ECPublicKey::from_public_bytes(public_key, algorithm)?,
47 )),
48 Algorithm::ED25519 => Ok(Arc::new(Ed25519::from_public_bytes(public_key.into())?)),
49 Algorithm::RSASHA1
50 | Algorithm::RSASHA1NSEC3SHA1
51 | Algorithm::RSASHA256
52 | Algorithm::RSASHA512 => Ok(Arc::new(Rsa::from_public_bytes(public_key, algorithm)?)),
53 _ => Err("public key algorithm not supported".into()),
54 }
55}
56
57pub struct EcdsaSigningKey {
59 inner: EcdsaKeyPair,
60 algorithm: Algorithm,
61}
62
63impl EcdsaSigningKey {
64 pub fn from_key_der(key: &PrivateKeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
71 match key {
72 PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key, algorithm),
73 _ => Err("unsupported key format (only PKCS#8 supported)".into()),
74 }
75 }
76
77 pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
84 let ring_algorithm = if algorithm == Algorithm::ECDSAP256SHA256 {
85 &ECDSA_P256_SHA256_FIXED_SIGNING
86 } else if algorithm == Algorithm::ECDSAP384SHA384 {
87 &ECDSA_P384_SHA384_FIXED_SIGNING
88 } else {
89 return Err(DnsSecError::Message("unsupported algorithm"));
90 };
91
92 #[cfg(all(feature = "dnssec-aws-lc-rs", not(feature = "dnssec-ring")))]
93 let inner = EcdsaKeyPair::from_pkcs8(ring_algorithm, key.secret_pkcs8_der())?;
94
95 #[cfg(feature = "dnssec-ring")]
96 let inner =
97 EcdsaKeyPair::from_pkcs8(ring_algorithm, key.secret_pkcs8_der(), &SystemRandom::new())?;
98
99 Ok(Self { inner, algorithm })
100 }
101
102 pub fn from_ecdsa(inner: EcdsaKeyPair, algorithm: Algorithm) -> Self {
104 Self { inner, algorithm }
105 }
106
107 pub fn generate_pkcs8(algorithm: Algorithm) -> DnsSecResult<PrivatePkcs8KeyDer<'static>> {
114 let rng = SystemRandom::new();
115 let alg = if algorithm == Algorithm::ECDSAP256SHA256 {
116 &ECDSA_P256_SHA256_FIXED_SIGNING
117 } else if algorithm == Algorithm::ECDSAP384SHA384 {
118 &ECDSA_P384_SHA384_FIXED_SIGNING
119 } else {
120 return Err(DnsSecError::Message("unsupported algorithm"));
121 };
122
123 let pkcs8 = EcdsaKeyPair::generate_pkcs8(alg, &rng)?;
124 Ok(PrivatePkcs8KeyDer::from(pkcs8.as_ref().to_vec()))
125 }
126}
127
128impl SigningKey for EcdsaSigningKey {
129 fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> {
130 let rng = SystemRandom::new();
131 Ok(self.inner.sign(&rng, tbs.as_ref())?.as_ref().to_vec())
132 }
133
134 fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> {
135 let mut bytes = self.inner.public_key().as_ref().to_vec();
136 bytes.remove(0);
137 Ok(PublicKeyBuf::new(bytes, self.algorithm))
138 }
139
140 fn algorithm(&self) -> Algorithm {
141 self.algorithm
142 }
143}
144
145pub struct Ed25519SigningKey {
147 inner: Ed25519KeyPair,
148}
149
150impl Ed25519SigningKey {
151 pub fn from_key_der(key: &PrivateKeyDer<'_>) -> DnsSecResult<Self> {
153 match key {
154 PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key),
155 _ => Err("unsupported key format (only PKCS#8 supported)".into()),
156 }
157 }
158
159 pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>) -> DnsSecResult<Self> {
161 Ok(Self {
162 inner: Ed25519KeyPair::from_pkcs8(key.secret_pkcs8_der())?,
163 })
164 }
165
166 pub fn from_ed25519(inner: Ed25519KeyPair) -> Self {
168 Self { inner }
169 }
170
171 pub fn generate_pkcs8() -> DnsSecResult<PrivatePkcs8KeyDer<'static>> {
173 let rng = SystemRandom::new();
174 let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rng)?;
175 Ok(PrivatePkcs8KeyDer::from(pkcs8.as_ref().to_vec()))
176 }
177}
178
179impl SigningKey for Ed25519SigningKey {
180 fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> {
181 Ok(self.inner.sign(tbs.as_ref()).as_ref().to_vec())
182 }
183
184 fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> {
185 Ok(PublicKeyBuf::new(
186 self.inner.public_key().as_ref().to_vec(),
187 Algorithm::ED25519,
188 ))
189 }
190
191 fn algorithm(&self) -> Algorithm {
192 Algorithm::ED25519
193 }
194}
195
196pub struct Ed25519<'k> {
198 raw: Cow<'k, [u8]>,
199}
200
201impl<'k> Ed25519<'k> {
202 pub fn from_public_bytes(public_key: Cow<'k, [u8]>) -> ProtoResult<Self> {
211 if public_key.len() != ED25519_PUBLIC_KEY_LEN {
212 return Err(format!(
213 "expected {} byte public_key: {}",
214 ED25519_PUBLIC_KEY_LEN,
215 public_key.len()
216 )
217 .into());
218 }
219
220 Ok(Self { raw: public_key })
221 }
222}
223
224impl PublicKey for Ed25519<'_> {
225 fn public_bytes(&self) -> &[u8] {
227 self.raw.as_ref()
228 }
229
230 fn verify(&self, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
231 let public_key = signature::UnparsedPublicKey::new(&signature::ED25519, self.raw.as_ref());
232 public_key
233 .verify(message, signature)
234 .map_err(|_| ProtoError::Crypto("ED25519 signature verification failed"))
235 }
236
237 fn algorithm(&self) -> Algorithm {
238 Algorithm::ED25519
239 }
240}
241
242pub struct Rsa<'k> {
244 raw: &'k [u8],
245 pkey: RSAPublicKey<'k>,
246 algorithm: Algorithm,
247}
248
249impl<'k> Rsa<'k> {
250 pub fn from_public_bytes(raw: &'k [u8], algorithm: Algorithm) -> ProtoResult<Self> {
283 let pkey = RSAPublicKey::try_from(raw)?;
284 Ok(Self {
285 raw,
286 pkey,
287 algorithm,
288 })
289 }
290}
291
292impl PublicKey for Rsa<'_> {
293 fn public_bytes(&self) -> &[u8] {
294 self.raw
295 }
296
297 fn verify(&self, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
298 #[allow(deprecated)]
299 let alg = match self.algorithm {
300 Algorithm::RSASHA256 => &signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY,
301 Algorithm::RSASHA512 => &signature::RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY,
302 Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => {
305 &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY
306 }
307 _ => unreachable!("non-RSA algorithm passed to RSA verify()"),
308 };
309 let public_key = signature::RsaPublicKeyComponents {
310 n: self.pkey.n(),
311 e: self.pkey.e(),
312 };
313 public_key
314 .verify(alg, message, signature)
315 .map_err(|_| ProtoError::Crypto("RSA signature verification failed"))
316 }
317
318 fn algorithm(&self) -> Algorithm {
319 self.algorithm
320 }
321}
322
323pub struct RsaSigningKey {
325 inner: RsaKeyPair,
326 algorithm: Algorithm,
327}
328
329impl RsaSigningKey {
330 pub fn from_key_der(key: &PrivateKeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
332 match key {
333 PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key, algorithm),
334 PrivateKeyDer::Pkcs1(key) => Self::from_pkcs1(key, algorithm),
335 _ => Err("unsupported key format (only PKCS#8 supported)".into()),
336 }
337 }
338
339 pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
341 match algorithm {
342 #[allow(deprecated)]
343 Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => {
344 return Err("unsupported Algorithm (insecure): {algorithm:?}".into());
345 }
346 Algorithm::RSASHA256 | Algorithm::RSASHA512 => {}
347 _ => return Err("unsupported Algorithm: {algorithm:?}".into()),
348 }
349
350 Ok(Self {
351 inner: RsaKeyPair::from_pkcs8(key.secret_pkcs8_der())?,
352 algorithm,
353 })
354 }
355
356 pub fn from_pkcs1(key: &PrivatePkcs1KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
358 match algorithm {
359 #[allow(deprecated)]
360 Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => {
361 return Err("unsupported Algorithm (insecure): {algorithm:?}".into());
362 }
363 Algorithm::RSASHA256 | Algorithm::RSASHA512 => {}
364 _ => return Err("unsupported Algorithm: {algorithm:?}".into()),
365 }
366
367 Ok(Self {
368 inner: RsaKeyPair::from_der(key.secret_pkcs1_der())?,
369 algorithm,
370 })
371 }
372}
373
374impl SigningKey for RsaSigningKey {
375 fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> {
376 let encoding = match self.algorithm {
377 Algorithm::RSASHA256 => &RSA_PKCS1_SHA256,
378 Algorithm::RSASHA512 => &RSA_PKCS1_SHA512,
379 _ => unreachable!(),
380 };
381
382 let rng = SystemRandom::new();
383 let mut signature = vec![0; self.inner.public_key().modulus_len()];
384 self.inner
385 .sign(encoding, &rng, tbs.as_ref(), &mut signature)?;
386 Ok(signature)
387 }
388
389 fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> {
390 let components = PublicKeyComponents::<Vec<u8>>::from(self.inner.public_key());
391
392 let mut buf = Vec::with_capacity(components.e.len() + components.n.len());
393 if components.e.len() > 255 {
394 buf.push(0);
395 buf.push((components.e.len() >> 8) as u8);
396 }
397
398 buf.push(components.e.len() as u8);
399 buf.extend(&components.e);
400 buf.extend(&components.n);
401 Ok(PublicKeyBuf::new(buf, self.algorithm))
402 }
403
404 fn algorithm(&self) -> Algorithm {
405 self.algorithm
406 }
407}
408
409#[derive(Clone, Copy, Debug)]
411pub struct Digest(digest::Digest);
412
413impl Digest {
414 pub fn iterated(
416 salt: &[u8],
417 bytes: &[u8],
418 r#type: DigestType,
419 mut iterations: u16,
420 ) -> Result<Self, DecodeError> {
421 let alg = r#type.try_into()?;
422 let mut cur = hash_iter([bytes, salt], alg);
423 while iterations > 0 {
424 cur = hash_iter([cur.as_ref(), salt], alg);
425 iterations -= 1;
426 }
427 Ok(Self(cur))
428 }
429
430 pub fn from_iter<'a>(
432 bytes: impl IntoIterator<Item = &'a [u8]>,
433 r#type: DigestType,
434 ) -> Result<Self, DecodeError> {
435 Ok(Self(hash_iter(bytes, r#type.try_into()?)))
436 }
437
438 pub fn new(bytes: &[u8], r#type: DigestType) -> Result<Self, DecodeError> {
440 Ok(Self(digest::digest(r#type.try_into()?, bytes)))
441 }
442}
443
444fn hash_iter<'a>(
445 iter: impl IntoIterator<Item = &'a [u8]>,
446 alg: &'static digest::Algorithm,
447) -> digest::Digest {
448 let mut ctx = digest::Context::new(alg);
449 for d in iter {
450 ctx.update(d);
451 }
452 ctx.finish()
453}
454
455impl AsRef<[u8]> for Digest {
456 fn as_ref(&self) -> &[u8] {
457 self.0.as_ref()
458 }
459}
460
461impl TryFrom<DigestType> for &'static digest::Algorithm {
462 type Error = DecodeError;
463
464 fn try_from(value: DigestType) -> Result<&'static digest::Algorithm, Self::Error> {
465 match value {
466 DigestType::SHA1 => Ok(&digest::SHA1_FOR_LEGACY_USE_ONLY),
467 DigestType::SHA256 => Ok(&digest::SHA256),
468 DigestType::SHA384 => Ok(&digest::SHA384),
469 DigestType::Unknown(other) => Err(DecodeError::UnknownDigestAlgorithm(other)),
470 }
471 }
472}
473
474#[cfg(test)]
475mod tests {
476 use rustls_pki_types::pem::PemObject;
477
478 use super::*;
479 use crate::dnssec::test_utils::{hash_test, public_key_test};
480
481 #[test]
482 fn test_ec_p256_pkcs8() {
483 let algorithm = Algorithm::ECDSAP256SHA256;
484 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
485 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
486 public_key_test(&*key);
487
488 let neg_pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
489 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
490 hash_test(&*key, &*neg);
491 }
492
493 #[test]
494 fn test_ec_p384_pkcs8() {
495 let algorithm = Algorithm::ECDSAP384SHA384;
496 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
497 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
498 public_key_test(&*key);
499
500 let neg_pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
501 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
502 hash_test(&*key, &*neg);
503 }
504
505 #[test]
506 fn test_ed25519() {
507 let algorithm = Algorithm::ED25519;
508 let pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
509 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
510 public_key_test(&*key);
511
512 let neg_pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
513 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
514 hash_test(&*key, &*neg);
515 }
516
517 #[test]
518 fn test_rsa() {
519 const KEY_1: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-1.pk8");
522 const KEY_2: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-2.pk8");
523
524 let algorithm = Algorithm::RSASHA256;
525 let key_der = PrivateKeyDer::try_from(KEY_1).unwrap();
526 let key = signing_key_from_der(&key_der, algorithm).unwrap();
527 public_key_test(&*key);
528
529 let key_der = PrivateKeyDer::try_from(KEY_2).unwrap();
530 let neg = signing_key_from_der(&key_der, algorithm).unwrap();
531 hash_test(&*key, &*neg);
532 }
533
534 #[test]
535 fn test_ec_encode_decode_pkcs8() {
536 let algorithm = Algorithm::ECDSAP256SHA256;
537 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
538 signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
539 }
540
541 #[test]
542 fn test_ed25519_encode_decode_pkcs8() {
543 let pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
544 signing_key_from_der(&PrivateKeyDer::from(pkcs8), Algorithm::ED25519).unwrap();
545 }
546
547 #[test]
548 fn test_rsasha256_encode_decode_pkcs8() {
549 const KEY: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-1.pk8");
552 let key_der = PrivateKeyDer::try_from(KEY).unwrap();
553 signing_key_from_der(&key_der, Algorithm::RSASHA256).unwrap();
554 }
555
556 #[test]
557 fn test_rsasha256_decode_pkcs1() {
558 const KEY: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-pkcs1.pem");
559 let key_der = PrivateKeyDer::from_pem_slice(KEY).unwrap();
560 assert!(matches!(key_der, PrivateKeyDer::Pkcs1(_)));
561 signing_key_from_der(&key_der, Algorithm::RSASHA256).unwrap();
562 }
563
564 #[test]
571 #[allow(deprecated)]
572 fn test_rsasha1_nsec3sha1_uses_same_crypto_as_rsasha1() {
573 const KEY: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-1.pk8");
574 let signing =
575 RsaSigningKey::from_pkcs8(&PrivatePkcs8KeyDer::from(KEY), Algorithm::RSASHA256)
576 .unwrap();
577 let key_bytes = signing.to_public_key().unwrap().into_inner();
578
579 for algorithm in [Algorithm::RSASHA1, Algorithm::RSASHA1NSEC3SHA1] {
582 let key = Rsa::from_public_bytes(&key_bytes, algorithm).unwrap();
583 let err = key.verify(b"message", b"bogus signature").unwrap_err();
584 assert!(
585 matches!(err, ProtoError::Crypto("RSA signature verification failed")),
586 "unexpected error for {algorithm:?}: {err:?}",
587 );
588 }
589 }
590}