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 => &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
303 Algorithm::RSASHA1NSEC3SHA1 => {
304 return Err("*ring* doesn't support RSASHA1NSEC3SHA1 yet".into());
305 }
306 _ => unreachable!("non-RSA algorithm passed to RSA verify()"),
307 };
308 let public_key = signature::RsaPublicKeyComponents {
309 n: self.pkey.n(),
310 e: self.pkey.e(),
311 };
312 public_key
313 .verify(alg, message, signature)
314 .map_err(|_| ProtoError::Crypto("RSA signature verification failed"))
315 }
316
317 fn algorithm(&self) -> Algorithm {
318 self.algorithm
319 }
320}
321
322pub struct RsaSigningKey {
324 inner: RsaKeyPair,
325 algorithm: Algorithm,
326}
327
328impl RsaSigningKey {
329 pub fn from_key_der(key: &PrivateKeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
331 match key {
332 PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key, algorithm),
333 PrivateKeyDer::Pkcs1(key) => Self::from_pkcs1(key, algorithm),
334 _ => Err("unsupported key format (only PKCS#8 supported)".into()),
335 }
336 }
337
338 pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
340 match algorithm {
341 #[allow(deprecated)]
342 Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => {
343 return Err("unsupported Algorithm (insecure): {algorithm:?}".into());
344 }
345 Algorithm::RSASHA256 | Algorithm::RSASHA512 => {}
346 _ => return Err("unsupported Algorithm: {algorithm:?}".into()),
347 }
348
349 Ok(Self {
350 inner: RsaKeyPair::from_pkcs8(key.secret_pkcs8_der())?,
351 algorithm,
352 })
353 }
354
355 pub fn from_pkcs1(key: &PrivatePkcs1KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> {
357 match algorithm {
358 #[allow(deprecated)]
359 Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => {
360 return Err("unsupported Algorithm (insecure): {algorithm:?}".into());
361 }
362 Algorithm::RSASHA256 | Algorithm::RSASHA512 => {}
363 _ => return Err("unsupported Algorithm: {algorithm:?}".into()),
364 }
365
366 Ok(Self {
367 inner: RsaKeyPair::from_der(key.secret_pkcs1_der())?,
368 algorithm,
369 })
370 }
371}
372
373impl SigningKey for RsaSigningKey {
374 fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> {
375 let encoding = match self.algorithm {
376 Algorithm::RSASHA256 => &RSA_PKCS1_SHA256,
377 Algorithm::RSASHA512 => &RSA_PKCS1_SHA512,
378 _ => unreachable!(),
379 };
380
381 let rng = SystemRandom::new();
382 let mut signature = vec![0; self.inner.public_key().modulus_len()];
383 self.inner
384 .sign(encoding, &rng, tbs.as_ref(), &mut signature)?;
385 Ok(signature)
386 }
387
388 fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> {
389 let components = PublicKeyComponents::<Vec<u8>>::from(self.inner.public_key());
390
391 let mut buf = Vec::with_capacity(components.e.len() + components.n.len());
392 if components.e.len() > 255 {
393 buf.push(0);
394 buf.push((components.e.len() >> 8) as u8);
395 }
396
397 buf.push(components.e.len() as u8);
398 buf.extend(&components.e);
399 buf.extend(&components.n);
400 Ok(PublicKeyBuf::new(buf, self.algorithm))
401 }
402
403 fn algorithm(&self) -> Algorithm {
404 self.algorithm
405 }
406}
407
408#[derive(Clone, Copy, Debug)]
410pub struct Digest(digest::Digest);
411
412impl Digest {
413 pub fn iterated(
415 salt: &[u8],
416 bytes: &[u8],
417 r#type: DigestType,
418 mut iterations: u16,
419 ) -> Result<Self, DecodeError> {
420 let alg = r#type.try_into()?;
421 let mut cur = hash_iter([bytes, salt], alg);
422 while iterations > 0 {
423 cur = hash_iter([cur.as_ref(), salt], alg);
424 iterations -= 1;
425 }
426 Ok(Self(cur))
427 }
428
429 pub fn from_iter<'a>(
431 bytes: impl IntoIterator<Item = &'a [u8]>,
432 r#type: DigestType,
433 ) -> Result<Self, DecodeError> {
434 Ok(Self(hash_iter(bytes, r#type.try_into()?)))
435 }
436
437 pub fn new(bytes: &[u8], r#type: DigestType) -> Result<Self, DecodeError> {
439 Ok(Self(digest::digest(r#type.try_into()?, bytes)))
440 }
441}
442
443fn hash_iter<'a>(
444 iter: impl IntoIterator<Item = &'a [u8]>,
445 alg: &'static digest::Algorithm,
446) -> digest::Digest {
447 let mut ctx = digest::Context::new(alg);
448 for d in iter {
449 ctx.update(d);
450 }
451 ctx.finish()
452}
453
454impl AsRef<[u8]> for Digest {
455 fn as_ref(&self) -> &[u8] {
456 self.0.as_ref()
457 }
458}
459
460impl TryFrom<DigestType> for &'static digest::Algorithm {
461 type Error = DecodeError;
462
463 fn try_from(value: DigestType) -> Result<&'static digest::Algorithm, Self::Error> {
464 match value {
465 DigestType::SHA1 => Ok(&digest::SHA1_FOR_LEGACY_USE_ONLY),
466 DigestType::SHA256 => Ok(&digest::SHA256),
467 DigestType::SHA384 => Ok(&digest::SHA384),
468 DigestType::Unknown(other) => Err(DecodeError::UnknownDigestAlgorithm(other)),
469 }
470 }
471}
472
473#[cfg(test)]
474mod tests {
475 use rustls_pki_types::pem::PemObject;
476
477 use super::*;
478 use crate::dnssec::test_utils::{hash_test, public_key_test};
479
480 #[test]
481 fn test_ec_p256_pkcs8() {
482 let algorithm = Algorithm::ECDSAP256SHA256;
483 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
484 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
485 public_key_test(&*key);
486
487 let neg_pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
488 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
489 hash_test(&*key, &*neg);
490 }
491
492 #[test]
493 fn test_ec_p384_pkcs8() {
494 let algorithm = Algorithm::ECDSAP384SHA384;
495 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
496 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
497 public_key_test(&*key);
498
499 let neg_pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
500 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
501 hash_test(&*key, &*neg);
502 }
503
504 #[test]
505 fn test_ed25519() {
506 let algorithm = Algorithm::ED25519;
507 let pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
508 let key = signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
509 public_key_test(&*key);
510
511 let neg_pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
512 let neg = signing_key_from_der(&PrivateKeyDer::from(neg_pkcs8), algorithm).unwrap();
513 hash_test(&*key, &*neg);
514 }
515
516 #[test]
517 fn test_rsa() {
518 const KEY_1: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-1.pk8");
521 const KEY_2: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-2.pk8");
522
523 let algorithm = Algorithm::RSASHA256;
524 let key_der = PrivateKeyDer::try_from(KEY_1).unwrap();
525 let key = signing_key_from_der(&key_der, algorithm).unwrap();
526 public_key_test(&*key);
527
528 let key_der = PrivateKeyDer::try_from(KEY_2).unwrap();
529 let neg = signing_key_from_der(&key_der, algorithm).unwrap();
530 hash_test(&*key, &*neg);
531 }
532
533 #[test]
534 fn test_ec_encode_decode_pkcs8() {
535 let algorithm = Algorithm::ECDSAP256SHA256;
536 let pkcs8 = EcdsaSigningKey::generate_pkcs8(algorithm).unwrap();
537 signing_key_from_der(&PrivateKeyDer::from(pkcs8), algorithm).unwrap();
538 }
539
540 #[test]
541 fn test_ed25519_encode_decode_pkcs8() {
542 let pkcs8 = Ed25519SigningKey::generate_pkcs8().unwrap();
543 signing_key_from_der(&PrivateKeyDer::from(pkcs8), Algorithm::ED25519).unwrap();
544 }
545
546 #[test]
547 fn test_rsasha256_encode_decode_pkcs8() {
548 const KEY: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-1.pk8");
551 let key_der = PrivateKeyDer::try_from(KEY).unwrap();
552 signing_key_from_der(&key_der, Algorithm::RSASHA256).unwrap();
553 }
554
555 #[test]
556 fn test_rsasha256_decode_pkcs1() {
557 const KEY: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-pkcs1.pem");
558 let key_der = PrivateKeyDer::from_pem_slice(KEY).unwrap();
559 assert!(matches!(key_der, PrivateKeyDer::Pkcs1(_)));
560 signing_key_from_der(&key_der, Algorithm::RSASHA256).unwrap();
561 }
562}