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> {
273 if public_key.len() != ED25519_PUBLIC_KEY_LEN {
274 return Err(format!(
275 "expected {} byte public_key: {}",
276 ED25519_PUBLIC_KEY_LEN,
277 public_key.len()
278 )
279 .into());
280 }
281
282 Ok(Self { raw: public_key })
283 }
284}
285
286impl PublicKey for Ed25519<'_> {
287 fn public_bytes(&self) -> &[u8] {
289 self.raw.as_ref()
290 }
291
292 fn verify(&self, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
293 let public_key = signature::UnparsedPublicKey::new(&signature::ED25519, self.raw.as_ref());
294 public_key.verify(message, signature).map_err(Into::into)
295 }
296
297 fn algorithm(&self) -> Algorithm {
298 Algorithm::ED25519
299 }
300}
301
302pub struct Rsa<'k> {
304 raw: &'k [u8],
305 pkey: RSAPublicKey<'k>,
306 algorithm: Algorithm,
307}
308
309impl<'k> Rsa<'k> {
310 pub fn from_public_bytes(raw: &'k [u8], algorithm: Algorithm) -> ProtoResult<Self> {
343 let pkey = RSAPublicKey::try_from(raw)?;
344 Ok(Self {
345 raw,
346 pkey,
347 algorithm,
348 })
349 }
350}
351
352impl PublicKey for Rsa<'_> {
353 fn public_bytes(&self) -> &[u8] {
354 self.raw
355 }
356
357 fn verify(&self, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
358 #[allow(deprecated)]
359 let alg = match self.algorithm {
360 Algorithm::RSASHA256 => &signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY,
361 Algorithm::RSASHA512 => &signature::RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY,
362 Algorithm::RSASHA1 => &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
363 Algorithm::RSASHA1NSEC3SHA1 => {
364 return Err("*ring* doesn't support RSASHA1NSEC3SHA1 yet".into());
365 }
366 _ => unreachable!("non-RSA algorithm passed to RSA verify()"),
367 };
368 let public_key = signature::RsaPublicKeyComponents {
369 n: self.pkey.n(),
370 e: self.pkey.e(),
371 };
372 public_key
373 .verify(alg, message, signature)
374 .map_err(Into::into)
375 }
376
377 fn algorithm(&self) -> Algorithm {
378 self.algorithm
379 }
380}
381
382pub struct RsaSigningKey {
384 inner: RsaKeyPair,
385 algorithm: Algorithm,
386}
387
388impl RsaSigningKey {
389 pub fn from_key_der(key: &PrivateKeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
391 match key {
392 PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key, algorithm),
393 PrivateKeyDer::Pkcs1(key) => Self::from_pkcs1(key, algorithm),
394 _ => Err("unsupported key format (only PKCS#8 supported)".into()),
395 }
396 }
397
398 pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
400 match algorithm {
401 #[allow(deprecated)]
402 Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => {
403 return Err("unsupported Algorithm (insecure): {algorithm:?}".into());
404 }
405 Algorithm::RSASHA256 | Algorithm::RSASHA512 => {}
406 _ => return Err("unsupported Algorithm: {algorithm:?}".into()),
407 }
408
409 Ok(Self {
410 inner: RsaKeyPair::from_pkcs8(key.secret_pkcs8_der())?,
411 algorithm,
412 })
413 }
414
415 pub fn from_pkcs1(key: &PrivatePkcs1KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
417 match algorithm {
418 #[allow(deprecated)]
419 Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => {
420 return Err("unsupported Algorithm (insecure): {algorithm:?}".into());
421 }
422 Algorithm::RSASHA256 | Algorithm::RSASHA512 => {}
423 _ => return Err("unsupported Algorithm: {algorithm:?}".into()),
424 }
425
426 Ok(Self {
427 inner: RsaKeyPair::from_der(key.secret_pkcs1_der())?,
428 algorithm,
429 })
430 }
431}
432
433impl SigningKey for RsaSigningKey {
434 fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> {
435 let encoding = match self.algorithm {
436 Algorithm::RSASHA256 => &RSA_PKCS1_SHA256,
437 Algorithm::RSASHA512 => &RSA_PKCS1_SHA512,
438 _ => unreachable!(),
439 };
440
441 let rng = SystemRandom::new();
442 let mut signature = vec![0; self.inner.public_key().modulus_len()];
443 self.inner
444 .sign(encoding, &rng, tbs.as_ref(), &mut signature)?;
445 Ok(signature)
446 }
447
448 fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> {
449 let components = PublicKeyComponents::<Vec<u8>>::from(self.inner.public_key());
450
451 let mut buf = Vec::with_capacity(components.e.len() + components.n.len());
452 if components.e.len() > 255 {
453 buf.push(0);
454 buf.push((components.e.len() >> 8) as u8);
455 }
456
457 buf.push(components.e.len() as u8);
458 buf.extend(&components.e);
459 buf.extend(&components.n);
460 Ok(PublicKeyBuf::new(buf, self.algorithm))
461 }
462
463 fn algorithm(&self) -> Algorithm {
464 self.algorithm
465 }
466}
467
468#[derive(Clone, Copy, Debug)]
470pub struct Digest(digest::Digest);
471
472impl Digest {
473 pub fn iterated(
475 salt: &[u8],
476 bytes: &[u8],
477 r#type: DigestType,
478 mut iterations: u16,
479 ) -> Result<Self, ProtoError> {
480 let alg = r#type.try_into()?;
481 let mut cur = hash_iter([bytes, salt], alg);
482 while iterations > 0 {
483 cur = hash_iter([cur.as_ref(), salt], alg);
484 iterations -= 1;
485 }
486 Ok(Self(cur))
487 }
488
489 pub fn from_iter<'a>(
491 bytes: impl IntoIterator<Item = &'a [u8]>,
492 r#type: DigestType,
493 ) -> Result<Self, ProtoError> {
494 Ok(Self(hash_iter(bytes, r#type.try_into()?)))
495 }
496
497 pub fn new(bytes: &[u8], r#type: DigestType) -> Result<Self, ProtoError> {
499 Ok(Self(digest::digest(r#type.try_into()?, bytes)))
500 }
501}
502
503fn hash_iter<'a>(
504 iter: impl IntoIterator<Item = &'a [u8]>,
505 alg: &'static digest::Algorithm,
506) -> digest::Digest {
507 let mut ctx = digest::Context::new(alg);
508 for d in iter {
509 ctx.update(d);
510 }
511 ctx.finish()
512}
513
514impl AsRef<[u8]> for Digest {
515 fn as_ref(&self) -> &[u8] {
516 self.0.as_ref()
517 }
518}
519
520impl TryFrom<DigestType> for &'static digest::Algorithm {
521 type Error = ProtoError;
522
523 fn try_from(value: DigestType) -> Result<&'static digest::Algorithm, ProtoError> {
524 match value {
525 DigestType::SHA1 => Ok(&digest::SHA1_FOR_LEGACY_USE_ONLY),
526 DigestType::SHA256 => Ok(&digest::SHA256),
527 DigestType::SHA384 => Ok(&digest::SHA384),
528 DigestType::Unknown(other) => Err(ProtoErrorKind::UnknownDigestTypeValue(other).into()),
529 }
530 }
531}
532
533#[cfg(test)]
534mod tests {
535 use rustls_pki_types::pem::PemObject;
536
537 use super::*;
538 use crate::dnssec::test_utils::{hash_test, public_key_test};
539
540 #[test]
541 fn test_ec_p256_pkcs8() {
542 let algorithm = Algorithm::ECDSAP256SHA256;
543 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
544 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
545 public_key_test(&*key);
546
547 let neg_pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
548 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
549 hash_test(&*key, &*neg);
550 }
551
552 #[test]
553 fn test_ec_p384_pkcs8() {
554 let algorithm = Algorithm::ECDSAP384SHA384;
555 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
556 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
557 public_key_test(&*key);
558
559 let neg_pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
560 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
561 hash_test(&*key, &*neg);
562 }
563
564 #[test]
565 fn test_ed25519() {
566 let algorithm = Algorithm::ED25519;
567 let pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
568 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
569 public_key_test(&*key);
570
571 let neg_pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
572 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
573 hash_test(&*key, &*neg);
574 }
575
576 #[test]
577 fn test_rsa() {
578 const KEY_1: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-1.pk8");
581 const KEY_2: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-2.pk8");
582
583 let algorithm = Algorithm::RSASHA256;
584 let key_der = PrivateKeyDer::try_from(KEY_1).unwrap();
585 let key = signing_key_from_der(&key_der, algorithm).unwrap();
586 public_key_test(&*key);
587
588 let key_der = PrivateKeyDer::try_from(KEY_2).unwrap();
589 let neg = signing_key_from_der(&key_der, algorithm).unwrap();
590 hash_test(&*key, &*neg);
591 }
592
593 #[test]
594 fn test_ec_encode_decode_pkcs8() {
595 let algorithm = Algorithm::ECDSAP256SHA256;
596 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
597 signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
598 }
599
600 #[test]
601 fn test_ed25519_encode_decode_pkcs8() {
602 let pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
603 signing_key_from_der(&PrivateKeyDer::from(pkcs8), Algorithm::ED25519).unwrap();
604 }
605
606 #[test]
607 fn test_rsasha256_encode_decode_pkcs8() {
608 const KEY: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-1.pk8");
611 let key_der = PrivateKeyDer::try_from(KEY).unwrap();
612 signing_key_from_der(&key_der, Algorithm::RSASHA256).unwrap();
613 }
614
615 #[test]
616 fn test_rsasha256_decode_pkcs1() {
617 const KEY: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-pkcs1.pem");
618 let key_der = PrivateKeyDer::from_pem_slice(KEY).unwrap();
619 assert!(matches!(key_der, PrivateKeyDer::Pkcs1(_)));
620 signing_key_from_der(&key_der, Algorithm::RSASHA256).unwrap();
621 }
622}