/src/hickory-dns/crates/proto/src/dnssec/crypto.rs
Line | Count | Source |
1 | | use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec}; |
2 | | |
3 | | use rustls_pki_types::{PrivateKeyDer, PrivatePkcs1KeyDer, PrivatePkcs8KeyDer}; |
4 | | |
5 | | use 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 | | }; |
15 | | use crate::{ProtoError, error::ProtoResult, serialize::binary::DecodeError}; |
16 | | |
17 | | /// Decode private key |
18 | 0 | pub fn signing_key_from_der( |
19 | 0 | key_der: &PrivateKeyDer<'_>, |
20 | 0 | algorithm: Algorithm, |
21 | 0 | ) -> DnsSecResult<Box<dyn SigningKey>> { |
22 | | #[allow(deprecated)] |
23 | 0 | match algorithm { |
24 | 0 | Algorithm::Unknown(v) => Err(format!("unknown algorithm: {v}").into()), |
25 | | Algorithm::RSASHA256 | Algorithm::RSASHA512 => { |
26 | 0 | Ok(Box::new(RsaSigningKey::from_key_der(key_der, algorithm)?)) |
27 | | } |
28 | | Algorithm::ECDSAP256SHA256 | Algorithm::ECDSAP384SHA384 => { |
29 | 0 | Ok(Box::new(EcdsaSigningKey::from_key_der(key_der, algorithm)?)) |
30 | | } |
31 | 0 | Algorithm::ED25519 => Ok(Box::new(Ed25519SigningKey::from_key_der(key_der)?)), |
32 | 0 | e => Err(format!("unsupported SigningKey algorithm for ring: {e:?}").into()), |
33 | | } |
34 | 0 | } |
35 | | |
36 | 0 | pub(super) fn decode_public_key<'a>( |
37 | 0 | public_key: &'a [u8], |
38 | 0 | algorithm: Algorithm, |
39 | 0 | ) -> ProtoResult<Arc<dyn PublicKey + 'a>> { |
40 | | // try to keep this and `Algorithm::is_supported` in sync |
41 | 0 | debug_assert!(algorithm.is_supported()); |
42 | | |
43 | | #[allow(deprecated)] |
44 | 0 | match algorithm { |
45 | 0 | Algorithm::ECDSAP256SHA256 | Algorithm::ECDSAP384SHA384 => Ok(Arc::new( |
46 | 0 | ECPublicKey::from_public_bytes(public_key, algorithm)?, |
47 | | )), |
48 | 0 | Algorithm::ED25519 => Ok(Arc::new(Ed25519::from_public_bytes(public_key.into())?)), |
49 | | Algorithm::RSASHA1 |
50 | | | Algorithm::RSASHA1NSEC3SHA1 |
51 | | | Algorithm::RSASHA256 |
52 | 0 | | Algorithm::RSASHA512 => Ok(Arc::new(Rsa::from_public_bytes(public_key, algorithm)?)), |
53 | 0 | _ => Err("public key algorithm not supported".into()), |
54 | | } |
55 | 0 | } |
56 | | |
57 | | /// An ECDSA signing key pair (backed by ring). |
58 | | pub struct EcdsaSigningKey { |
59 | | inner: EcdsaKeyPair, |
60 | | algorithm: Algorithm, |
61 | | } |
62 | | |
63 | | impl EcdsaSigningKey { |
64 | | /// Decode signing key pair from DER. |
65 | | /// |
66 | | /// Errors unless the given algorithm is one of the following: |
67 | | /// |
68 | | /// - [`Algorithm::ECDSAP256SHA256`] |
69 | | /// - [`Algorithm::ECDSAP384SHA384`] |
70 | 0 | pub fn from_key_der(key: &PrivateKeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> { |
71 | 0 | match key { |
72 | 0 | PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key, algorithm), |
73 | 0 | _ => Err("unsupported key format (only PKCS#8 supported)".into()), |
74 | | } |
75 | 0 | } |
76 | | |
77 | | /// Decode signing key pair from DER-encoded PKCS#8 bytes. |
78 | | /// |
79 | | /// Errors unless the given algorithm is one of the following: |
80 | | /// |
81 | | /// - [`Algorithm::ECDSAP256SHA256`] |
82 | | /// - [`Algorithm::ECDSAP384SHA384`] |
83 | 0 | pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> { |
84 | 0 | let ring_algorithm = if algorithm == Algorithm::ECDSAP256SHA256 { |
85 | 0 | &ECDSA_P256_SHA256_FIXED_SIGNING |
86 | 0 | } else if algorithm == Algorithm::ECDSAP384SHA384 { |
87 | 0 | &ECDSA_P384_SHA384_FIXED_SIGNING |
88 | | } else { |
89 | 0 | return Err(DnsSecError::Message("unsupported algorithm")); |
90 | | }; |
91 | | |
92 | | #[cfg(all(feature = "dnssec-aws-lc-rs", not(feature = "dnssec-ring")))] |
93 | 0 | 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 | 0 | Ok(Self { inner, algorithm }) |
100 | 0 | } |
101 | | |
102 | | /// Creates an ECDSA key pair with ring. |
103 | 0 | pub fn from_ecdsa(inner: EcdsaKeyPair, algorithm: Algorithm) -> Self { |
104 | 0 | Self { inner, algorithm } |
105 | 0 | } |
106 | | |
107 | | /// Generate signing key pair and return the DER-encoded PKCS#8 bytes. |
108 | | /// |
109 | | /// Errors unless the given algorithm is one of the following: |
110 | | /// |
111 | | /// - [`Algorithm::ECDSAP256SHA256`] |
112 | | /// - [`Algorithm::ECDSAP384SHA384`] |
113 | 0 | pub fn generate_pkcs8(algorithm: Algorithm) -> DnsSecResult<PrivatePkcs8KeyDer<'static>> { |
114 | 0 | let rng = SystemRandom::new(); |
115 | 0 | let alg = if algorithm == Algorithm::ECDSAP256SHA256 { |
116 | 0 | &ECDSA_P256_SHA256_FIXED_SIGNING |
117 | 0 | } else if algorithm == Algorithm::ECDSAP384SHA384 { |
118 | 0 | &ECDSA_P384_SHA384_FIXED_SIGNING |
119 | | } else { |
120 | 0 | return Err(DnsSecError::Message("unsupported algorithm")); |
121 | | }; |
122 | | |
123 | 0 | let pkcs8 = EcdsaKeyPair::generate_pkcs8(alg, &rng)?; |
124 | 0 | Ok(PrivatePkcs8KeyDer::from(pkcs8.as_ref().to_vec())) |
125 | 0 | } |
126 | | } |
127 | | |
128 | | impl SigningKey for EcdsaSigningKey { |
129 | 0 | fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> { |
130 | 0 | let rng = SystemRandom::new(); |
131 | 0 | Ok(self.inner.sign(&rng, tbs.as_ref())?.as_ref().to_vec()) |
132 | 0 | } |
133 | | |
134 | 0 | fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> { |
135 | 0 | let mut bytes = self.inner.public_key().as_ref().to_vec(); |
136 | 0 | bytes.remove(0); |
137 | 0 | Ok(PublicKeyBuf::new(bytes, self.algorithm)) |
138 | 0 | } |
139 | | |
140 | 0 | fn algorithm(&self) -> Algorithm { |
141 | 0 | self.algorithm |
142 | 0 | } |
143 | | } |
144 | | |
145 | | /// An Ed25519 signing key pair (backed by ring). |
146 | | pub struct Ed25519SigningKey { |
147 | | inner: Ed25519KeyPair, |
148 | | } |
149 | | |
150 | | impl Ed25519SigningKey { |
151 | | /// Decode signing key pair from DER. |
152 | 0 | pub fn from_key_der(key: &PrivateKeyDer<'_>) -> DnsSecResult<Self> { |
153 | 0 | match key { |
154 | 0 | PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key), |
155 | 0 | _ => Err("unsupported key format (only PKCS#8 supported)".into()), |
156 | | } |
157 | 0 | } |
158 | | |
159 | | /// Decode signing key pair from DER-encoded PKCS#8 bytes. |
160 | 0 | pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>) -> DnsSecResult<Self> { |
161 | | Ok(Self { |
162 | 0 | inner: Ed25519KeyPair::from_pkcs8(key.secret_pkcs8_der())?, |
163 | | }) |
164 | 0 | } |
165 | | |
166 | | /// Creates an Ed25519 keypair. |
167 | 0 | pub fn from_ed25519(inner: Ed25519KeyPair) -> Self { |
168 | 0 | Self { inner } |
169 | 0 | } |
170 | | |
171 | | /// Generate signing key pair and return the DER-encoded PKCS#8 bytes. |
172 | 0 | pub fn generate_pkcs8() -> DnsSecResult<PrivatePkcs8KeyDer<'static>> { |
173 | 0 | let rng = SystemRandom::new(); |
174 | 0 | let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rng)?; |
175 | 0 | Ok(PrivatePkcs8KeyDer::from(pkcs8.as_ref().to_vec())) |
176 | 0 | } |
177 | | } |
178 | | |
179 | | impl SigningKey for Ed25519SigningKey { |
180 | 0 | fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> { |
181 | 0 | Ok(self.inner.sign(tbs.as_ref()).as_ref().to_vec()) |
182 | 0 | } |
183 | | |
184 | 0 | fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> { |
185 | 0 | Ok(PublicKeyBuf::new( |
186 | 0 | self.inner.public_key().as_ref().to_vec(), |
187 | 0 | Algorithm::ED25519, |
188 | 0 | )) |
189 | 0 | } |
190 | | |
191 | 0 | fn algorithm(&self) -> Algorithm { |
192 | 0 | Algorithm::ED25519 |
193 | 0 | } |
194 | | } |
195 | | |
196 | | /// Ed25519 Public key |
197 | | pub struct Ed25519<'k> { |
198 | | raw: Cow<'k, [u8]>, |
199 | | } |
200 | | |
201 | | impl<'k> Ed25519<'k> { |
202 | | /// ```text |
203 | | /// RFC 8080 EdDSA for DNSSEC February 2017 |
204 | | /// |
205 | | /// An Ed25519 public key consists of a 32-octet value, which is encoded |
206 | | /// into the Public Key field of a DNSKEY resource record as a simple bit |
207 | | /// string. The generation of a public key is defined in Section 5.1.5 |
208 | | /// of [RFC8032]. |
209 | | /// ``` |
210 | 0 | pub fn from_public_bytes(public_key: Cow<'k, [u8]>) -> ProtoResult<Self> { |
211 | 0 | if public_key.len() != ED25519_PUBLIC_KEY_LEN { |
212 | 0 | return Err(format!( |
213 | 0 | "expected {} byte public_key: {}", |
214 | 0 | ED25519_PUBLIC_KEY_LEN, |
215 | 0 | public_key.len() |
216 | 0 | ) |
217 | 0 | .into()); |
218 | 0 | } |
219 | | |
220 | 0 | Ok(Self { raw: public_key }) |
221 | 0 | } |
222 | | } |
223 | | |
224 | | impl PublicKey for Ed25519<'_> { |
225 | | // TODO: just store reference to public key bytes in ctor... |
226 | 0 | fn public_bytes(&self) -> &[u8] { |
227 | 0 | self.raw.as_ref() |
228 | 0 | } |
229 | | |
230 | 0 | fn verify(&self, message: &[u8], signature: &[u8]) -> ProtoResult<()> { |
231 | 0 | let public_key = signature::UnparsedPublicKey::new(&signature::ED25519, self.raw.as_ref()); |
232 | 0 | public_key |
233 | 0 | .verify(message, signature) |
234 | 0 | .map_err(|_| ProtoError::Crypto("ED25519 signature verification failed")) |
235 | 0 | } |
236 | | |
237 | 0 | fn algorithm(&self) -> Algorithm { |
238 | 0 | Algorithm::ED25519 |
239 | 0 | } |
240 | | } |
241 | | |
242 | | /// Rsa public key |
243 | | pub struct Rsa<'k> { |
244 | | raw: &'k [u8], |
245 | | pkey: RSAPublicKey<'k>, |
246 | | algorithm: Algorithm, |
247 | | } |
248 | | |
249 | | impl<'k> Rsa<'k> { |
250 | | /// ```text |
251 | | /// RFC 3110 RSA SIGs and KEYs in the DNS May 2001 |
252 | | /// |
253 | | /// 2. RSA Public KEY Resource Records |
254 | | /// |
255 | | /// RSA public keys are stored in the DNS as KEY RRs using algorithm |
256 | | /// number 5 [RFC2535]. The structure of the algorithm specific portion |
257 | | /// of the RDATA part of such RRs is as shown below. |
258 | | /// |
259 | | /// Field Size |
260 | | /// ----- ---- |
261 | | /// exponent length 1 or 3 octets (see text) |
262 | | /// exponent as specified by length field |
263 | | /// modulus remaining space |
264 | | /// |
265 | | /// For interoperability, the exponent and modulus are each limited to |
266 | | /// 4096 bits in length. The public key exponent is a variable length |
267 | | /// unsigned integer. Its length in octets is represented as one octet |
268 | | /// if it is in the range of 1 to 255 and by a zero octet followed by a |
269 | | /// two octet unsigned length if it is longer than 255 bytes. The public |
270 | | /// key modulus field is a multiprecision unsigned integer. The length |
271 | | /// of the modulus can be determined from the RDLENGTH and the preceding |
272 | | /// RDATA fields including the exponent. Leading zero octets are |
273 | | /// prohibited in the exponent and modulus. |
274 | | /// |
275 | | /// Note: KEY RRs for use with RSA/SHA1 DNS signatures MUST use this |
276 | | /// algorithm number (rather than the algorithm number specified in the |
277 | | /// obsoleted RFC 2537). |
278 | | /// |
279 | | /// Note: This changes the algorithm number for RSA KEY RRs to be the |
280 | | /// same as the new algorithm number for RSA/SHA1 SIGs. |
281 | | /// ``` |
282 | 0 | pub fn from_public_bytes(raw: &'k [u8], algorithm: Algorithm) -> ProtoResult<Self> { |
283 | 0 | let pkey = RSAPublicKey::try_from(raw)?; |
284 | 0 | Ok(Self { |
285 | 0 | raw, |
286 | 0 | pkey, |
287 | 0 | algorithm, |
288 | 0 | }) |
289 | 0 | } |
290 | | } |
291 | | |
292 | | impl PublicKey for Rsa<'_> { |
293 | 0 | fn public_bytes(&self) -> &[u8] { |
294 | 0 | self.raw |
295 | 0 | } |
296 | | |
297 | 0 | fn verify(&self, message: &[u8], signature: &[u8]) -> ProtoResult<()> { |
298 | | #[allow(deprecated)] |
299 | 0 | let alg = match self.algorithm { |
300 | 0 | Algorithm::RSASHA256 => &signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY, |
301 | 0 | Algorithm::RSASHA512 => &signature::RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY, |
302 | 0 | Algorithm::RSASHA1 => &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY, |
303 | | Algorithm::RSASHA1NSEC3SHA1 => { |
304 | 0 | return Err("*ring* doesn't support RSASHA1NSEC3SHA1 yet".into()); |
305 | | } |
306 | 0 | _ => unreachable!("non-RSA algorithm passed to RSA verify()"), |
307 | | }; |
308 | 0 | let public_key = signature::RsaPublicKeyComponents { |
309 | 0 | n: self.pkey.n(), |
310 | 0 | e: self.pkey.e(), |
311 | 0 | }; |
312 | 0 | public_key |
313 | 0 | .verify(alg, message, signature) |
314 | 0 | .map_err(|_| ProtoError::Crypto("RSA signature verification failed")) |
315 | 0 | } |
316 | | |
317 | 0 | fn algorithm(&self) -> Algorithm { |
318 | 0 | self.algorithm |
319 | 0 | } |
320 | | } |
321 | | |
322 | | /// An RSA signing key pair (backed by ring). |
323 | | pub struct RsaSigningKey { |
324 | | inner: RsaKeyPair, |
325 | | algorithm: Algorithm, |
326 | | } |
327 | | |
328 | | impl RsaSigningKey { |
329 | | /// Decode signing key pair from DER. |
330 | 0 | pub fn from_key_der(key: &PrivateKeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> { |
331 | 0 | match key { |
332 | 0 | PrivateKeyDer::Pkcs8(key) => Self::from_pkcs8(key, algorithm), |
333 | 0 | PrivateKeyDer::Pkcs1(key) => Self::from_pkcs1(key, algorithm), |
334 | 0 | _ => Err("unsupported key format (only PKCS#8 supported)".into()), |
335 | | } |
336 | 0 | } |
337 | | |
338 | | /// Decode signing key pair from DER-encoded PKCS#8 bytes. |
339 | 0 | pub fn from_pkcs8(key: &PrivatePkcs8KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> { |
340 | 0 | match algorithm { |
341 | | #[allow(deprecated)] |
342 | | Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => { |
343 | 0 | return Err("unsupported Algorithm (insecure): {algorithm:?}".into()); |
344 | | } |
345 | 0 | Algorithm::RSASHA256 | Algorithm::RSASHA512 => {} |
346 | 0 | _ => return Err("unsupported Algorithm: {algorithm:?}".into()), |
347 | | } |
348 | | |
349 | | Ok(Self { |
350 | 0 | inner: RsaKeyPair::from_pkcs8(key.secret_pkcs8_der())?, |
351 | 0 | algorithm, |
352 | | }) |
353 | 0 | } |
354 | | |
355 | | /// Decode signing key pair from DER-encoded PKCS#1 bytes. |
356 | 0 | pub fn from_pkcs1(key: &PrivatePkcs1KeyDer<'_>, algorithm: Algorithm) -> DnsSecResult<Self> { |
357 | 0 | match algorithm { |
358 | | #[allow(deprecated)] |
359 | | Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => { |
360 | 0 | return Err("unsupported Algorithm (insecure): {algorithm:?}".into()); |
361 | | } |
362 | 0 | Algorithm::RSASHA256 | Algorithm::RSASHA512 => {} |
363 | 0 | _ => return Err("unsupported Algorithm: {algorithm:?}".into()), |
364 | | } |
365 | | |
366 | | Ok(Self { |
367 | 0 | inner: RsaKeyPair::from_der(key.secret_pkcs1_der())?, |
368 | 0 | algorithm, |
369 | | }) |
370 | 0 | } |
371 | | } |
372 | | |
373 | | impl SigningKey for RsaSigningKey { |
374 | 0 | fn sign(&self, tbs: &TBS) -> DnsSecResult<Vec<u8>> { |
375 | 0 | let encoding = match self.algorithm { |
376 | 0 | Algorithm::RSASHA256 => &RSA_PKCS1_SHA256, |
377 | 0 | Algorithm::RSASHA512 => &RSA_PKCS1_SHA512, |
378 | 0 | _ => unreachable!(), |
379 | | }; |
380 | | |
381 | 0 | let rng = SystemRandom::new(); |
382 | 0 | let mut signature = vec![0; self.inner.public_key().modulus_len()]; |
383 | 0 | self.inner |
384 | 0 | .sign(encoding, &rng, tbs.as_ref(), &mut signature)?; |
385 | 0 | Ok(signature) |
386 | 0 | } |
387 | | |
388 | 0 | fn to_public_key(&self) -> DnsSecResult<PublicKeyBuf> { |
389 | 0 | let components = PublicKeyComponents::<Vec<u8>>::from(self.inner.public_key()); |
390 | | |
391 | 0 | let mut buf = Vec::with_capacity(components.e.len() + components.n.len()); |
392 | 0 | if components.e.len() > 255 { |
393 | 0 | buf.push(0); |
394 | 0 | buf.push((components.e.len() >> 8) as u8); |
395 | 0 | } |
396 | | |
397 | 0 | buf.push(components.e.len() as u8); |
398 | 0 | buf.extend(&components.e); |
399 | 0 | buf.extend(&components.n); |
400 | 0 | Ok(PublicKeyBuf::new(buf, self.algorithm)) |
401 | 0 | } |
402 | | |
403 | 0 | fn algorithm(&self) -> Algorithm { |
404 | 0 | self.algorithm |
405 | 0 | } |
406 | | } |
407 | | |
408 | | /// Hashing wrapper type. |
409 | | #[derive(Clone, Copy, Debug)] |
410 | | pub struct Digest(digest::Digest); |
411 | | |
412 | | impl Digest { |
413 | | /// Hashes the given `data` `iterations` times with the given `salt` and `r#type`. |
414 | 0 | pub fn iterated( |
415 | 0 | salt: &[u8], |
416 | 0 | bytes: &[u8], |
417 | 0 | r#type: DigestType, |
418 | 0 | mut iterations: u16, |
419 | 0 | ) -> Result<Self, DecodeError> { |
420 | 0 | let alg = r#type.try_into()?; |
421 | 0 | let mut cur = hash_iter([bytes, salt], alg); |
422 | 0 | while iterations > 0 { |
423 | 0 | cur = hash_iter([cur.as_ref(), salt], alg); |
424 | 0 | iterations -= 1; |
425 | 0 | } |
426 | 0 | Ok(Self(cur)) |
427 | 0 | } |
428 | | |
429 | | /// Hashes the data from the `bytes` iterator with the given `r#type`. |
430 | 0 | pub fn from_iter<'a>( |
431 | 0 | bytes: impl IntoIterator<Item = &'a [u8]>, |
432 | 0 | r#type: DigestType, |
433 | 0 | ) -> Result<Self, DecodeError> { |
434 | 0 | Ok(Self(hash_iter(bytes, r#type.try_into()?))) |
435 | 0 | } |
436 | | |
437 | | /// Hashes |
438 | 0 | pub fn new(bytes: &[u8], r#type: DigestType) -> Result<Self, DecodeError> { |
439 | 0 | Ok(Self(digest::digest(r#type.try_into()?, bytes))) |
440 | 0 | } |
441 | | } |
442 | | |
443 | 0 | fn hash_iter<'a>( |
444 | 0 | iter: impl IntoIterator<Item = &'a [u8]>, |
445 | 0 | alg: &'static digest::Algorithm, |
446 | 0 | ) -> digest::Digest { |
447 | 0 | let mut ctx = digest::Context::new(alg); |
448 | 0 | for d in iter { |
449 | 0 | ctx.update(d); |
450 | 0 | } |
451 | 0 | ctx.finish() |
452 | 0 | } |
453 | | |
454 | | impl AsRef<[u8]> for Digest { |
455 | 0 | fn as_ref(&self) -> &[u8] { |
456 | 0 | self.0.as_ref() |
457 | 0 | } |
458 | | } |
459 | | |
460 | | impl TryFrom<DigestType> for &'static digest::Algorithm { |
461 | | type Error = DecodeError; |
462 | | |
463 | 0 | fn try_from(value: DigestType) -> Result<&'static digest::Algorithm, Self::Error> { |
464 | 0 | match value { |
465 | 0 | DigestType::SHA1 => Ok(&digest::SHA1_FOR_LEGACY_USE_ONLY), |
466 | 0 | DigestType::SHA256 => Ok(&digest::SHA256), |
467 | 0 | DigestType::SHA384 => Ok(&digest::SHA384), |
468 | 0 | DigestType::Unknown(other) => Err(DecodeError::UnknownDigestAlgorithm(other)), |
469 | | } |
470 | 0 | } |
471 | | } |
472 | | |
473 | | #[cfg(test)] |
474 | | mod 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 | | // ring currently does not support RSA key generation support. |
519 | | // Generated per the documentation from https://docs.rs/ring/latest/ring/rsa/struct.KeyPair.html#method.from_pkcs8. |
520 | | 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 | | // ring currently does not support RSA key generation support. |
549 | | // Generated per the documentation from https://docs.rs/ring/latest/ring/rsa/struct.KeyPair.html#method.from_pkcs8. |
550 | | 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 | | } |