1use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
2
3use rustls_pki_types::{PrivateKeyDer, PrivatePkcs1KeyDer, PrivatePkcs8KeyDer};
4
5use super::ring_like::{
6 ECDSA_P256_SHA256_FIXED_SIGNING, ECDSA_P384_SHA384_FIXED_SIGNING, ED25519_PUBLIC_KEY_LEN,
7 EcdsaKeyPair, Ed25519KeyPair, KeyPair, PublicKeyComponents, RSA_PKCS1_SHA256, RSA_PKCS1_SHA512,
8 RsaKeyPair, SystemRandom, digest, signature,
9};
10use super::{
11 Algorithm, DigestType, DnsSecErrorKind, DnsSecResult, PublicKey, PublicKeyBuf, SigningKey, TBS,
12 ec_public_key::ECPublicKey, rsa_public_key::RSAPublicKey,
13};
14use crate::{ProtoError, ProtoErrorKind, error::ProtoResult};
15
16pub fn signing_key_from_der(
18 key_der: &PrivateKeyDer<'_>,
19 algorithm: Algorithm,
20) -> DnsSecResult<Box<dyn SigningKey>> {
21 #[allow(deprecated)]
22 match algorithm {
23 Algorithm::Unknown(v) => Err(format!("unknown algorithm: {v}").into()),
24 Algorithm::RSASHA256 | Algorithm::RSASHA512 => {
25 Ok(Box::new(RsaSigningKey::from_key_der(key_der, algorithm)?))
26 }
27 Algorithm::ECDSAP256SHA256 | Algorithm::ECDSAP384SHA384 => {
28 Ok(Box::new(EcdsaSigningKey::from_key_der(key_der, algorithm)?))
29 }
30 Algorithm::ED25519 => Ok(Box::new(Ed25519SigningKey::from_key_der(key_der)?)),
31 e => Err(format!("unsupported SigningKey algorithm for ring: {e:?}").into()),
32 }
33}
34
35pub(super) fn decode_public_key<'a>(
36 public_key: &'a [u8],
37 algorithm: Algorithm,
38) -> ProtoResult<Arc<dyn PublicKey + 'a>> {
39 debug_assert!(algorithm.is_supported());
41
42 #[allow(deprecated)]
43 match algorithm {
44 Algorithm::ECDSAP256SHA256 | Algorithm::ECDSAP384SHA384 => {
45 Ok(Arc::new(Ec::from_public_bytes(public_key, algorithm)?))
46 }
47 Algorithm::ED25519 => Ok(Arc::new(Ed25519::from_public_bytes(public_key.into())?)),
48 Algorithm::RSASHA1
49 | Algorithm::RSASHA1NSEC3SHA1
50 | Algorithm::RSASHA256
51 | Algorithm::RSASHA512 => Ok(Arc::new(Rsa::from_public_bytes(public_key, algorithm)?)),
52 _ => Err("public key algorithm not supported".into()),
53 }
54}
55
56pub struct EcdsaSigningKey {
58 inner: EcdsaKeyPair,
59 algorithm: Algorithm,
60}
61
62impl EcdsaSigningKey {
63 pub fn from_key_der(key: &PrivateKeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
70 match key {
71 PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key, algorithm),
72 _ => Err("unsupported key format (only PKCS#8 supported)".into()),
73 }
74 }
75
76 pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
83 let ring_algorithm = if algorithm == Algorithm::ECDSAP256SHA256 {
84 &ECDSA_P256_SHA256_FIXED_SIGNING
85 } else if algorithm == Algorithm::ECDSAP384SHA384 {
86 &ECDSA_P384_SHA384_FIXED_SIGNING
87 } else {
88 return Err(DnsSecErrorKind::Message("unsupported algorithm").into());
89 };
90
91 #[cfg(all(feature = "dnssec-aws-lc-rs", not(feature = "dnssec-ring")))]
92 let inner = EcdsaKeyPair::from_pkcs8(ring_algorithm, key.secret_pkcs8_der())?;
93
94 #[cfg(feature = "dnssec-ring")]
95 let inner =
96 EcdsaKeyPair::from_pkcs8(ring_algorithm, key.secret_pkcs8_der(), &SystemRandom::new())?;
97
98 Ok(Self { inner, algorithm })
99 }
100
101 pub fn from_ecdsa(inner: EcdsaKeyPair, algorithm: Algorithm) -> Self {
103 Self { inner, algorithm }
104 }
105
106 pub fn generate_pkcs8(algorithm: Algorithm) -> DnsSecResult<PrivatePkcs8KeyDer<'static>> {
113 let rng = SystemRandom::new();
114 let alg = if algorithm == Algorithm::ECDSAP256SHA256 {
115 &ECDSA_P256_SHA256_FIXED_SIGNING
116 } else if algorithm == Algorithm::ECDSAP384SHA384 {
117 &ECDSA_P384_SHA384_FIXED_SIGNING
118 } else {
119 return Err(DnsSecErrorKind::Message("unsupported algorithm").into());
120 };
121
122 let pkcs8 = EcdsaKeyPair::generate_pkcs8(alg, &rng)?;
123 Ok(PrivatePkcs8KeyDer::from(pkcs8.as_ref().to_vec()))
124 }
125}
126
127impl SigningKey for EcdsaSigningKey {
128 fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> {
129 let rng = SystemRandom::new();
130 Ok(self.inner.sign(&rng, tbs.as_ref())?.as_ref().to_vec())
131 }
132
133 fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> {
134 let mut bytes = self.inner.public_key().as_ref().to_vec();
135 bytes.remove(0);
136 Ok(PublicKeyBuf::new(bytes, self.algorithm))
137 }
138
139 fn algorithm(&self) -> Algorithm {
140 self.algorithm
141 }
142}
143
144pub struct Ed25519SigningKey {
146 inner: Ed25519KeyPair,
147}
148
149impl Ed25519SigningKey {
150 pub fn from_key_der(key: &PrivateKeyDer<'_>) -> DnsSecResult<Self> {
152 match key {
153 PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key),
154 _ => Err("unsupported key format (only PKCS#8 supported)".into()),
155 }
156 }
157
158 pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>) -> DnsSecResult<Self> {
160 Ok(Self {
161 inner: Ed25519KeyPair::from_pkcs8(key.secret_pkcs8_der())?,
162 })
163 }
164
165 pub fn from_ed25519(inner: Ed25519KeyPair) -> Self {
167 Self { inner }
168 }
169
170 pub fn generate_pkcs8() -> DnsSecResult<PrivatePkcs8KeyDer<'static>> {
172 let rng = SystemRandom::new();
173 let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rng)?;
174 Ok(PrivatePkcs8KeyDer::from(pkcs8.as_ref().to_vec()))
175 }
176}
177
178impl SigningKey for Ed25519SigningKey {
179 fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> {
180 Ok(self.inner.sign(tbs.as_ref()).as_ref().to_vec())
181 }
182
183 fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> {
184 Ok(PublicKeyBuf::new(
185 self.inner.public_key().as_ref().to_vec(),
186 Algorithm::ED25519,
187 ))
188 }
189
190 fn algorithm(&self) -> Algorithm {
191 Algorithm::ED25519
192 }
193}
194
195pub type Ec = ECPublicKey;
197
198impl Ec {
199 pub fn from_public_bytes(public_key: &[u8], algorithm: Algorithm) -> ProtoResult<Self> {
232 Self::from_unprefixed(public_key, algorithm)
233 }
234}
235
236impl PublicKey for Ec {
237 fn public_bytes(&self) -> &[u8] {
238 self.unprefixed_bytes()
239 }
240
241 fn verify(&self, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
242 let alg = match self.algorithm {
244 Algorithm::ECDSAP256SHA256 => &signature::ECDSA_P256_SHA256_FIXED,
245 Algorithm::ECDSAP384SHA384 => &signature::ECDSA_P384_SHA384_FIXED,
246 _ => return Err("only ECDSAP256SHA256 and ECDSAP384SHA384 are supported by Ec".into()),
247 };
248 let public_key = signature::UnparsedPublicKey::new(alg, self.prefixed_bytes());
249 public_key.verify(message, signature).map_err(Into::into)
250 }
251
252 fn algorithm(&self) -> Algorithm {
253 self.algorithm
254 }
255}
256
257pub struct Ed25519<'k> {
259 raw: Cow<'k, [u8]>,
260}
261
262impl<'k> Ed25519<'k> {
263 pub fn from_public_bytes(public_key: Cow<'k, [u8]>) -> ProtoResult<Self> {
272 if public_key.len() != ED25519_PUBLIC_KEY_LEN {
273 return Err(format!(
274 "expected {} byte public_key: {}",
275 ED25519_PUBLIC_KEY_LEN,
276 public_key.len()
277 )
278 .into());
279 }
280
281 Ok(Self { raw: public_key })
282 }
283}
284
285impl PublicKey for Ed25519<'_> {
286 fn public_bytes(&self) -> &[u8] {
288 self.raw.as_ref()
289 }
290
291 fn verify(&self, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
292 let public_key = signature::UnparsedPublicKey::new(&signature::ED25519, self.raw.as_ref());
293 public_key.verify(message, signature).map_err(Into::into)
294 }
295
296 fn algorithm(&self) -> Algorithm {
297 Algorithm::ED25519
298 }
299}
300
301pub struct Rsa<'k> {
303 raw: &'k [u8],
304 pkey: RSAPublicKey<'k>,
305 algorithm: Algorithm,
306}
307
308impl<'k> Rsa<'k> {
309 pub fn from_public_bytes(raw: &'k [u8], algorithm: Algorithm) -> ProtoResult<Self> {
342 let pkey = RSAPublicKey::try_from(raw)?;
343 Ok(Self {
344 raw,
345 pkey,
346 algorithm,
347 })
348 }
349}
350
351impl PublicKey for Rsa<'_> {
352 fn public_bytes(&self) -> &[u8] {
353 self.raw
354 }
355
356 fn verify(&self, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
357 #[allow(deprecated)]
358 let alg = match self.algorithm {
359 Algorithm::RSASHA256 => &signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY,
360 Algorithm::RSASHA512 => &signature::RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY,
361 Algorithm::RSASHA1 => &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
362 Algorithm::RSASHA1NSEC3SHA1 => {
363 return Err("*ring* doesn't support RSASHA1NSEC3SHA1 yet".into());
364 }
365 _ => unreachable!("non-RSA algorithm passed to RSA verify()"),
366 };
367 let public_key = signature::RsaPublicKeyComponents {
368 n: self.pkey.n(),
369 e: self.pkey.e(),
370 };
371 public_key
372 .verify(alg, message, signature)
373 .map_err(Into::into)
374 }
375
376 fn algorithm(&self) -> Algorithm {
377 self.algorithm
378 }
379}
380
381pub struct RsaSigningKey {
383 inner: RsaKeyPair,
384 algorithm: Algorithm,
385}
386
387impl RsaSigningKey {
388 pub fn from_key_der(key: &PrivateKeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
390 match key {
391 PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key, algorithm),
392 PrivateKeyDer::Pkcs1(key) => Self::from_pkcs1(key, algorithm),
393 _ => Err("unsupported key format (only PKCS#8 supported)".into()),
394 }
395 }
396
397 pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
399 match algorithm {
400 #[allow(deprecated)]
401 Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => {
402 return Err("unsupported Algorithm (insecure): {algorithm:?}".into());
403 }
404 Algorithm::RSASHA256 | Algorithm::RSASHA512 => {}
405 _ => return Err("unsupported Algorithm: {algorithm:?}".into()),
406 }
407
408 Ok(Self {
409 inner: RsaKeyPair::from_pkcs8(key.secret_pkcs8_der())?,
410 algorithm,
411 })
412 }
413
414 pub fn from_pkcs1(key: &PrivatePkcs1KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
416 match algorithm {
417 #[allow(deprecated)]
418 Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => {
419 return Err("unsupported Algorithm (insecure): {algorithm:?}".into());
420 }
421 Algorithm::RSASHA256 | Algorithm::RSASHA512 => {}
422 _ => return Err("unsupported Algorithm: {algorithm:?}".into()),
423 }
424
425 Ok(Self {
426 inner: RsaKeyPair::from_der(key.secret_pkcs1_der())?,
427 algorithm,
428 })
429 }
430}
431
432impl SigningKey for RsaSigningKey {
433 fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> {
434 let encoding = match self.algorithm {
435 Algorithm::RSASHA256 => &RSA_PKCS1_SHA256,
436 Algorithm::RSASHA512 => &RSA_PKCS1_SHA512,
437 _ => unreachable!(),
438 };
439
440 let rng = SystemRandom::new();
441 let mut signature = vec![0; self.inner.public_key().modulus_len()];
442 self.inner
443 .sign(encoding, &rng, tbs.as_ref(), &mut signature)?;
444 Ok(signature)
445 }
446
447 fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> {
448 let components = PublicKeyComponents::<Vec<u8>>::from(self.inner.public_key());
449
450 let mut buf = Vec::with_capacity(components.e.len() + components.n.len());
451 if components.e.len() > 255 {
452 buf.push(0);
453 buf.push((components.e.len() >> 8) as u8);
454 }
455
456 buf.push(components.e.len() as u8);
457 buf.extend(&components.e);
458 buf.extend(&components.n);
459 Ok(PublicKeyBuf::new(buf, self.algorithm))
460 }
461
462 fn algorithm(&self) -> Algorithm {
463 self.algorithm
464 }
465}
466
467#[derive(Clone, Copy, Debug)]
469pub struct Digest(digest::Digest);
470
471impl Digest {
472 pub fn iterated(
474 salt: &[u8],
475 bytes: &[u8],
476 r#type: DigestType,
477 mut iterations: u16,
478 ) -> Result<Self, ProtoError> {
479 let alg = r#type.try_into()?;
480 let mut cur = hash_iter([bytes, salt], alg);
481 while iterations > 0 {
482 cur = hash_iter([cur.as_ref(), salt], alg);
483 iterations -= 1;
484 }
485 Ok(Self(cur))
486 }
487
488 pub fn from_iter<'a>(
490 bytes: impl IntoIterator<Item = &'a [u8]>,
491 r#type: DigestType,
492 ) -> Result<Self, ProtoError> {
493 Ok(Self(hash_iter(bytes, r#type.try_into()?)))
494 }
495
496 pub fn new(bytes: &[u8], r#type: DigestType) -> Result<Self, ProtoError> {
498 Ok(Self(digest::digest(r#type.try_into()?, bytes)))
499 }
500}
501
502fn hash_iter<'a>(
503 iter: impl IntoIterator<Item = &'a [u8]>,
504 alg: &'static digest::Algorithm,
505) -> digest::Digest {
506 let mut ctx = digest::Context::new(alg);
507 for d in iter {
508 ctx.update(d);
509 }
510 ctx.finish()
511}
512
513impl AsRef<[u8]> for Digest {
514 fn as_ref(&self) -> &[u8] {
515 self.0.as_ref()
516 }
517}
518
519impl TryFrom<DigestType> for &'static digest::Algorithm {
520 type Error = ProtoError;
521
522 fn try_from(value: DigestType) -> Result<&'static digest::Algorithm, ProtoError> {
523 match value {
524 DigestType::SHA1 => Ok(&digest::SHA1_FOR_LEGACY_USE_ONLY),
525 DigestType::SHA256 => Ok(&digest::SHA256),
526 DigestType::SHA384 => Ok(&digest::SHA384),
527 DigestType::Unknown(other) => Err(ProtoErrorKind::UnknownDigestTypeValue(other).into()),
528 }
529 }
530}
531
532#[cfg(test)]
533mod tests {
534 use rustls_pki_types::pem::PemObject;
535
536 use super::*;
537 use crate::dnssec::test_utils::{hash_test, public_key_test};
538
539 #[test]
540 fn test_ec_p256_pkcs8() {
541 let algorithm = Algorithm::ECDSAP256SHA256;
542 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
543 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
544 public_key_test(&*key);
545
546 let neg_pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
547 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
548 hash_test(&*key, &*neg);
549 }
550
551 #[test]
552 fn test_ec_p384_pkcs8() {
553 let algorithm = Algorithm::ECDSAP384SHA384;
554 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
555 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
556 public_key_test(&*key);
557
558 let neg_pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
559 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
560 hash_test(&*key, &*neg);
561 }
562
563 #[test]
564 fn test_ed25519() {
565 let algorithm = Algorithm::ED25519;
566 let pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
567 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
568 public_key_test(&*key);
569
570 let neg_pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
571 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
572 hash_test(&*key, &*neg);
573 }
574
575 #[test]
576 fn test_rsa() {
577 const KEY_1: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-1.pk8");
580 const KEY_2: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-2.pk8");
581
582 let algorithm = Algorithm::RSASHA256;
583 let key_der = PrivateKeyDer::try_from(KEY_1).unwrap();
584 let key = signing_key_from_der(&key_der, algorithm).unwrap();
585 public_key_test(&*key);
586
587 let key_der = PrivateKeyDer::try_from(KEY_2).unwrap();
588 let neg = signing_key_from_der(&key_der, algorithm).unwrap();
589 hash_test(&*key, &*neg);
590 }
591
592 #[test]
593 fn test_ec_encode_decode_pkcs8() {
594 let algorithm = Algorithm::ECDSAP256SHA256;
595 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
596 signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
597 }
598
599 #[test]
600 fn test_ed25519_encode_decode_pkcs8() {
601 let pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
602 signing_key_from_der(&PrivateKeyDer::from(pkcs8), Algorithm::ED25519).unwrap();
603 }
604
605 #[test]
606 fn test_rsasha256_encode_decode_pkcs8() {
607 const KEY: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-1.pk8");
610 let key_der = PrivateKeyDer::try_from(KEY).unwrap();
611 signing_key_from_der(&key_der, Algorithm::RSASHA256).unwrap();
612 }
613
614 #[test]
615 fn test_rsasha256_decode_pkcs1() {
616 const KEY: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-pkcs1.pem");
617 let key_der = PrivateKeyDer::from_pem_slice(KEY).unwrap();
618 assert!(matches!(key_der, PrivateKeyDer::Pkcs1(_)));
619 signing_key_from_der(&key_der, Algorithm::RSASHA256).unwrap();
620 }
621}