/src/hickory-dns/crates/proto/src/dnssec/signer.rs
Line | Count | Source |
1 | | // Copyright 2015-2023 Benjamin Fry <benjaminfry@me.com> |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or |
4 | | // https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or |
5 | | // https://opensource.org/licenses/MIT>, at your option. This file may not be |
6 | | // copied, modified, or distributed except according to those terms. |
7 | | |
8 | | //! signer is a structure for performing many of the signing processes of the DNSSEC specification |
9 | | use alloc::{boxed::Box, vec::Vec}; |
10 | | use core::time::Duration; |
11 | | |
12 | | use super::{DnsSecResult, SigningKey}; |
13 | | use crate::{ |
14 | | dnssec::{TBS, rdata::DNSKEY}, |
15 | | error::{ProtoError, ProtoResult}, |
16 | | rr::Name, |
17 | | serialize::binary::{BinEncodable, BinEncoder}, |
18 | | }; |
19 | | |
20 | | /// A DNSSEC signer that bundles a DNSKEY with its corresponding private key for signing operations. |
21 | | /// |
22 | | /// This type is used to create RRSIG records for zone signing. It holds the public key material |
23 | | /// (DNSKEY), the private signing key, and metadata needed for signature creation. |
24 | | /// |
25 | | /// [RFC 4035](https://tools.ietf.org/html/rfc4035), DNSSEC Protocol Modifications, March 2005 |
26 | | /// |
27 | | /// ```text |
28 | | /// 5.3. Authenticating an RRset with an RRSIG RR |
29 | | /// |
30 | | /// A validator can use an RRSIG RR and its corresponding DNSKEY RR to |
31 | | /// attempt to authenticate RRsets. The validator first checks the RRSIG |
32 | | /// RR to verify that it covers the RRset, has a valid time interval, and |
33 | | /// identifies a valid DNSKEY RR. The validator then constructs the |
34 | | /// canonical form of the signed data by appending the RRSIG RDATA |
35 | | /// (excluding the Signature Field) with the canonical form of the |
36 | | /// covered RRset. Finally, the validator uses the public key and |
37 | | /// signature to authenticate the signed data. Sections 5.3.1, 5.3.2, |
38 | | /// and 5.3.3 describe each step in detail. |
39 | | /// |
40 | | /// 5.3.1. Checking the RRSIG RR Validity |
41 | | /// |
42 | | /// A security-aware resolver can use an RRSIG RR to authenticate an |
43 | | /// RRset if all of the following conditions hold: |
44 | | /// |
45 | | /// o The RRSIG RR and the RRset MUST have the same owner name and the |
46 | | /// same class. |
47 | | /// |
48 | | /// o The RRSIG RR's Signer's Name field MUST be the name of the zone |
49 | | /// that contains the RRset. |
50 | | /// |
51 | | /// o The RRSIG RR's Type Covered field MUST equal the RRset's type. |
52 | | /// |
53 | | /// o The number of labels in the RRset owner name MUST be greater than |
54 | | /// or equal to the value in the RRSIG RR's Labels field. |
55 | | /// |
56 | | /// o The validator's notion of the current time MUST be less than or |
57 | | /// equal to the time listed in the RRSIG RR's Expiration field. |
58 | | /// |
59 | | /// o The validator's notion of the current time MUST be greater than or |
60 | | /// equal to the time listed in the RRSIG RR's Inception field. |
61 | | /// |
62 | | /// o The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST |
63 | | /// match the owner name, algorithm, and key tag for some DNSKEY RR in |
64 | | /// the zone's apex DNSKEY RRset. |
65 | | /// |
66 | | /// o The matching DNSKEY RR MUST be present in the zone's apex DNSKEY |
67 | | /// RRset, and MUST have the Zone Flag bit (DNSKEY RDATA Flag bit 7) |
68 | | /// set. |
69 | | /// |
70 | | /// It is possible for more than one DNSKEY RR to match the conditions |
71 | | /// above. In this case, the validator cannot predetermine which DNSKEY |
72 | | /// RR to use to authenticate the signature, and it MUST try each |
73 | | /// matching DNSKEY RR until either the signature is validated or the |
74 | | /// validator has run out of matching public keys to try. |
75 | | /// |
76 | | /// Note that this authentication process is only meaningful if the |
77 | | /// validator authenticates the DNSKEY RR before using it to validate |
78 | | /// signatures. The matching DNSKEY RR is considered to be authentic if: |
79 | | /// |
80 | | /// o the apex DNSKEY RRset containing the DNSKEY RR is considered |
81 | | /// authentic; or |
82 | | /// |
83 | | /// o the RRset covered by the RRSIG RR is the apex DNSKEY RRset itself, |
84 | | /// and the DNSKEY RR either matches an authenticated DS RR from the |
85 | | /// parent zone or matches a trust anchor. |
86 | | /// |
87 | | /// 5.3.2. Reconstructing the Signed Data |
88 | | /// |
89 | | /// Once the RRSIG RR has met the validity requirements described in |
90 | | /// Section 5.3.1, the validator has to reconstruct the original signed |
91 | | /// data. The original signed data includes RRSIG RDATA (excluding the |
92 | | /// Signature field) and the canonical form of the RRset. Aside from |
93 | | /// being ordered, the canonical form of the RRset might also differ from |
94 | | /// the received RRset due to DNS name compression, decremented TTLs, or |
95 | | /// wildcard expansion. The validator should use the following to |
96 | | /// reconstruct the original signed data: |
97 | | /// |
98 | | /// signed_data = RRSIG_RDATA | RR(1) | RR(2)... where |
99 | | /// |
100 | | /// "|" denotes concatenation |
101 | | /// |
102 | | /// RRSIG_RDATA is the wire format of the RRSIG RDATA fields |
103 | | /// with the Signature field excluded and the Signer's Name |
104 | | /// in canonical form. |
105 | | /// |
106 | | /// RR(i) = name | type | class | OrigTTL | RDATA length | RDATA |
107 | | /// |
108 | | /// name is calculated according to the function below |
109 | | /// |
110 | | /// class is the RRset's class |
111 | | /// |
112 | | /// type is the RRset type and all RRs in the class |
113 | | /// |
114 | | /// OrigTTL is the value from the RRSIG Original TTL field |
115 | | /// |
116 | | /// All names in the RDATA field are in canonical form |
117 | | /// |
118 | | /// The set of all RR(i) is sorted into canonical order. |
119 | | /// |
120 | | /// To calculate the name: |
121 | | /// let rrsig_labels = the value of the RRSIG Labels field |
122 | | /// |
123 | | /// let fqdn = RRset's fully qualified domain name in |
124 | | /// canonical form |
125 | | /// |
126 | | /// let fqdn_labels = Label count of the fqdn above. |
127 | | /// |
128 | | /// if rrsig_labels = fqdn_labels, |
129 | | /// name = fqdn |
130 | | /// |
131 | | /// if rrsig_labels < fqdn_labels, |
132 | | /// name = "*." | the rightmost rrsig_label labels of the |
133 | | /// fqdn |
134 | | /// |
135 | | /// if rrsig_labels > fqdn_labels |
136 | | /// the RRSIG RR did not pass the necessary validation |
137 | | /// checks and MUST NOT be used to authenticate this |
138 | | /// RRset. |
139 | | /// |
140 | | /// The canonical forms for names and RRsets are defined in [RFC4034]. |
141 | | /// |
142 | | /// NSEC RRsets at a delegation boundary require special processing. |
143 | | /// There are two distinct NSEC RRsets associated with a signed delegated |
144 | | /// name. One NSEC RRset resides in the parent zone, and specifies which |
145 | | /// RRsets are present at the parent zone. The second NSEC RRset resides |
146 | | /// at the child zone and identifies which RRsets are present at the apex |
147 | | /// in the child zone. The parent NSEC RRset and child NSEC RRset can |
148 | | /// always be distinguished as only a child NSEC RR will indicate that an |
149 | | /// SOA RRset exists at the name. When reconstructing the original NSEC |
150 | | /// RRset for the delegation from the parent zone, the NSEC RRs MUST NOT |
151 | | /// be combined with NSEC RRs from the child zone. When reconstructing |
152 | | /// the original NSEC RRset for the apex of the child zone, the NSEC RRs |
153 | | /// MUST NOT be combined with NSEC RRs from the parent zone. |
154 | | /// |
155 | | /// Note that each of the two NSEC RRsets at a delegation point has a |
156 | | /// corresponding RRSIG RR with an owner name matching the delegated |
157 | | /// name, and each of these RRSIG RRs is authoritative data associated |
158 | | /// with the same zone that contains the corresponding NSEC RRset. If |
159 | | /// necessary, a resolver can tell these RRSIG RRs apart by checking the |
160 | | /// Signer's Name field. |
161 | | /// |
162 | | /// 5.3.3. Checking the Signature |
163 | | /// |
164 | | /// Once the resolver has validated the RRSIG RR as described in Section |
165 | | /// 5.3.1 and reconstructed the original signed data as described in |
166 | | /// Section 5.3.2, the validator can attempt to use the cryptographic |
167 | | /// signature to authenticate the signed data, and thus (finally!) |
168 | | /// authenticate the RRset. |
169 | | /// |
170 | | /// The Algorithm field in the RRSIG RR identifies the cryptographic |
171 | | /// algorithm used to generate the signature. The signature itself is |
172 | | /// contained in the Signature field of the RRSIG RDATA, and the public |
173 | | /// key used to verify the signature is contained in the Public Key field |
174 | | /// of the matching DNSKEY RR(s) (found in Section 5.3.1). [RFC4034] |
175 | | /// provides a list of algorithm types and provides pointers to the |
176 | | /// documents that define each algorithm's use. |
177 | | /// |
178 | | /// Note that it is possible for more than one DNSKEY RR to match the |
179 | | /// conditions in Section 5.3.1. In this case, the validator can only |
180 | | /// determine which DNSKEY RR is correct by trying each matching public |
181 | | /// key until the validator either succeeds in validating the signature |
182 | | /// or runs out of keys to try. |
183 | | /// |
184 | | /// If the Labels field of the RRSIG RR is not equal to the number of |
185 | | /// labels in the RRset's fully qualified owner name, then the RRset is |
186 | | /// either invalid or the result of wildcard expansion. The resolver |
187 | | /// MUST verify that wildcard expansion was applied properly before |
188 | | /// considering the RRset to be authentic. Section 5.3.4 describes how |
189 | | /// to determine whether a wildcard was applied properly. |
190 | | /// |
191 | | /// If other RRSIG RRs also cover this RRset, the local resolver security |
192 | | /// policy determines whether the resolver also has to test these RRSIG |
193 | | /// RRs and how to resolve conflicts if these RRSIG RRs lead to differing |
194 | | /// results. |
195 | | /// |
196 | | /// If the resolver accepts the RRset as authentic, the validator MUST |
197 | | /// set the TTL of the RRSIG RR and each RR in the authenticated RRset to |
198 | | /// a value no greater than the minimum of: |
199 | | /// |
200 | | /// o the RRset's TTL as received in the response; |
201 | | /// |
202 | | /// o the RRSIG RR's TTL as received in the response; |
203 | | /// |
204 | | /// o the value in the RRSIG RR's Original TTL field; and |
205 | | /// |
206 | | /// o the difference of the RRSIG RR's Signature Expiration time and the |
207 | | /// current time. |
208 | | /// |
209 | | /// 5.3.4. Authenticating a Wildcard Expanded RRset Positive Response |
210 | | /// |
211 | | /// If the number of labels in an RRset's owner name is greater than the |
212 | | /// Labels field of the covering RRSIG RR, then the RRset and its |
213 | | /// covering RRSIG RR were created as a result of wildcard expansion. |
214 | | /// Once the validator has verified the signature, as described in |
215 | | /// Section 5.3, it must take additional steps to verify the non- |
216 | | /// existence of an exact match or closer wildcard match for the query. |
217 | | /// Section 5.4 discusses these steps. |
218 | | /// |
219 | | /// Note that the response received by the resolver should include all |
220 | | /// NSEC RRs needed to authenticate the response (see Section 3.1.3). |
221 | | /// ``` |
222 | | pub struct DnssecSigner { |
223 | | dnskey: DNSKEY, |
224 | | key: Box<dyn SigningKey>, |
225 | | signer_name: Name, |
226 | | sig_duration: Duration, |
227 | | } |
228 | | |
229 | | impl DnssecSigner { |
230 | | /// Creates a new DNSSEC signer for creating RRSIGs. |
231 | | /// |
232 | | /// # Arguments |
233 | | /// |
234 | | /// * `dnskey` - the DNSKEY containing the public key material |
235 | | /// * `key` - the private key for signing |
236 | | /// * `signer_name` - name in the zone to which this DNSKEY is bound |
237 | | /// * `sig_duration` - time period for which signatures created by this key are valid |
238 | 0 | pub fn new( |
239 | 0 | dnskey: DNSKEY, |
240 | 0 | key: Box<dyn SigningKey>, |
241 | 0 | signer_name: Name, |
242 | 0 | sig_duration: Duration, |
243 | 0 | ) -> Self { |
244 | 0 | Self { |
245 | 0 | dnskey, |
246 | 0 | key, |
247 | 0 | signer_name, |
248 | 0 | sig_duration, |
249 | 0 | } |
250 | 0 | } |
251 | | |
252 | | /// Return the key used for validation/signing |
253 | 0 | pub fn key(&self) -> &dyn SigningKey { |
254 | 0 | &*self.key |
255 | 0 | } |
256 | | |
257 | | /// Returns the duration that this signature is valid for |
258 | 0 | pub fn sig_duration(&self) -> Duration { |
259 | 0 | self.sig_duration |
260 | 0 | } |
261 | | |
262 | | /// Returns whether this DNSKEY has the zone key flag set |
263 | 0 | pub fn is_zone_signing_key(&self) -> bool { |
264 | 0 | self.dnskey.zone_key() |
265 | 0 | } |
266 | | |
267 | | /// Signs a hash. |
268 | | /// |
269 | | /// This will panic if the `key` is not a private key and can be used for signing. |
270 | | /// |
271 | | /// # Arguments |
272 | | /// |
273 | | /// * `hash` - the hashed resource record set, see `rrset_tbs`. |
274 | | /// |
275 | | /// # Return value |
276 | | /// |
277 | | /// The signature, ready to be stored in an `RData::RRSIG`. |
278 | 0 | pub fn sign(&self, tbs: &TBS) -> ProtoResult<Vec<u8>> { |
279 | 0 | self.key |
280 | 0 | .sign(tbs) |
281 | 0 | .map_err(|e| ProtoError::Msg(format!("signing error: {e}"))) |
282 | 0 | } |
283 | | |
284 | | /// The name of the signing entity, e.g. the DNS server name. |
285 | | /// |
286 | | /// This should match the name on key in the zone. |
287 | 0 | pub fn signer_name(&self) -> &Name { |
288 | 0 | &self.signer_name |
289 | 0 | } |
290 | | |
291 | | // TODO: move this to DNSKEY/KEY? |
292 | | /// The key tag is calculated as a hash to more quickly lookup a DNSKEY. |
293 | | /// |
294 | | /// ```text |
295 | | /// RFC 2535 DNS Security Extensions March 1999 |
296 | | /// |
297 | | /// 4.1.6 Key Tag Field |
298 | | /// |
299 | | /// The "key Tag" is a two octet quantity that is used to efficiently |
300 | | /// select between multiple keys which may be applicable and thus check |
301 | | /// that a public key about to be used for the computationally expensive |
302 | | /// effort to check the signature is possibly valid. For algorithm 1 |
303 | | /// (MD5/RSA) as defined in [RFC 2537], it is the next to the bottom two |
304 | | /// octets of the public key modulus needed to decode the signature |
305 | | /// field. That is to say, the most significant 16 of the least |
306 | | /// significant 24 bits of the modulus in network (big endian) order. For |
307 | | /// all other algorithms, including private algorithms, it is calculated |
308 | | /// as a simple checksum of the KEY RR as described in Appendix C. |
309 | | /// |
310 | | /// Appendix C: Key Tag Calculation |
311 | | /// |
312 | | /// The key tag field in the SIG RR is just a means of more efficiently |
313 | | /// selecting the correct KEY RR to use when there is more than one KEY |
314 | | /// RR candidate available, for example, in verifying a signature. It is |
315 | | /// possible for more than one candidate key to have the same tag, in |
316 | | /// which case each must be tried until one works or all fail. The |
317 | | /// following reference implementation of how to calculate the Key Tag, |
318 | | /// for all algorithms other than algorithm 1, is in ANSI C. It is coded |
319 | | /// for clarity, not efficiency. (See section 4.1.6 for how to determine |
320 | | /// the Key Tag of an algorithm 1 key.) |
321 | | /// |
322 | | /// /* assumes int is at least 16 bits |
323 | | /// first byte of the key tag is the most significant byte of return |
324 | | /// value |
325 | | /// second byte of the key tag is the least significant byte of |
326 | | /// return value |
327 | | /// */ |
328 | | /// |
329 | | /// int keytag ( |
330 | | /// |
331 | | /// unsigned char key[], /* the RDATA part of the KEY RR */ |
332 | | /// unsigned int keysize, /* the RDLENGTH */ |
333 | | /// ) |
334 | | /// { |
335 | | /// long int ac; /* assumed to be 32 bits or larger */ |
336 | | /// |
337 | | /// for ( ac = 0, i = 0; i < keysize; ++i ) |
338 | | /// ac += (i&1) ? key[i] : key[i]<<8; |
339 | | /// ac += (ac>>16) & 0xFFFF; |
340 | | /// return ac & 0xFFFF; |
341 | | /// } |
342 | | /// ``` |
343 | 0 | pub fn calculate_key_tag(&self) -> ProtoResult<u16> { |
344 | 0 | let mut bytes: Vec<u8> = Vec::with_capacity(512); |
345 | | { |
346 | 0 | let mut e = BinEncoder::new(&mut bytes); |
347 | 0 | self.dnskey.emit(&mut e)?; |
348 | | } |
349 | 0 | Ok(DNSKEY::calculate_key_tag_internal(&bytes)) |
350 | 0 | } |
351 | | |
352 | | /// Returns a reference to the DNSKEY for this signer |
353 | 0 | pub fn dnskey(&self) -> &DNSKEY { |
354 | 0 | &self.dnskey |
355 | 0 | } |
356 | | |
357 | | /// Returns a clone of the DNSKEY for this signer |
358 | 0 | pub fn to_dnskey(&self) -> DNSKEY { |
359 | 0 | self.dnskey.clone() |
360 | 0 | } |
361 | | |
362 | | /// Test that this key is capable of signing and verifying data |
363 | 0 | pub fn test_key(&self) -> DnsSecResult<()> { |
364 | | // use proto::rr::dnssec::PublicKey; |
365 | | |
366 | | // // TODO: why doesn't this work for ecdsa_256 and 384? |
367 | | // let test_data = TBS::from(b"DEADBEEF" as &[u8]); |
368 | | |
369 | | // let signature = self.sign(&test_data).map_err(|e| {println!("failed to sign, {:?}", e); e})?; |
370 | | // let pk = self.key.to_public_key()?; |
371 | | // pk.verify(self.algorithm, test_data.as_ref(), &signature).map_err(|e| {println!("failed to verify, {:?}", e); e})?; |
372 | | |
373 | 0 | Ok(()) |
374 | 0 | } |
375 | | } |
376 | | |
377 | | #[cfg(test)] |
378 | | mod tests { |
379 | | #![allow(clippy::dbg_macro, clippy::print_stdout)] |
380 | | |
381 | | use rustls_pki_types::PrivatePkcs8KeyDer; |
382 | | |
383 | | use super::*; |
384 | | use crate::dnssec::{ |
385 | | Algorithm, PublicKey, SigningKey, TBS, crypto::RsaSigningKey, rdata::SigInput, |
386 | | }; |
387 | | use crate::rr::rdata::{CNAME, NS}; |
388 | | use crate::rr::{DNSClass, Name, RData, Record, RecordType, SerialNumber}; |
389 | | |
390 | | fn assert_send_and_sync<T: Send + Sync>() {} |
391 | | |
392 | | #[test] |
393 | | fn test_send_and_sync() { |
394 | | assert_send_and_sync::<DnssecSigner>(); |
395 | | } |
396 | | |
397 | | #[test] |
398 | | #[allow(deprecated)] |
399 | | fn test_sign_and_verify_rrset() { |
400 | | let key = |
401 | | RsaSigningKey::from_pkcs8(&PrivatePkcs8KeyDer::from(RSA_KEY), Algorithm::RSASHA256) |
402 | | .unwrap(); |
403 | | let pub_key = key.to_public_key().unwrap(); |
404 | | let dnskey = DNSKEY::from_key(&pub_key); |
405 | | let signer = DnssecSigner::new( |
406 | | dnskey, |
407 | | Box::new(key), |
408 | | Name::root(), |
409 | | Duration::from_secs(300), |
410 | | ); |
411 | | |
412 | | let origin = Name::parse("example.com.", None).unwrap(); |
413 | | let input = SigInput { |
414 | | type_covered: RecordType::NS, |
415 | | algorithm: Algorithm::RSASHA256, |
416 | | num_labels: origin.num_labels(), |
417 | | original_ttl: 86400, |
418 | | sig_expiration: SerialNumber(5), |
419 | | sig_inception: SerialNumber(0), |
420 | | key_tag: signer.calculate_key_tag().unwrap(), |
421 | | signer_name: origin.clone(), |
422 | | }; |
423 | | |
424 | | let rrset = [ |
425 | | Record::from_rdata( |
426 | | origin.clone(), |
427 | | 86400, |
428 | | RData::NS(NS(Name::parse("a.iana-servers.net.", None).unwrap())), |
429 | | ) |
430 | | .set_dns_class(DNSClass::IN) |
431 | | .clone(), |
432 | | Record::from_rdata( |
433 | | origin.clone(), |
434 | | 86400, |
435 | | RData::NS(NS(Name::parse("b.iana-servers.net.", None).unwrap())), |
436 | | ) |
437 | | .set_dns_class(DNSClass::IN) |
438 | | .clone(), |
439 | | ]; |
440 | | |
441 | | let tbs = TBS::from_input(&origin, DNSClass::IN, &input, rrset.iter()).unwrap(); |
442 | | let sig = signer.sign(&tbs).unwrap(); |
443 | | |
444 | | let pub_key = signer.key().to_public_key().unwrap(); |
445 | | assert!(pub_key.verify(tbs.as_ref(), &sig).is_ok()); |
446 | | } |
447 | | |
448 | | #[test] |
449 | | #[allow(deprecated)] |
450 | | fn test_calculate_key_tag_pem() { |
451 | | let key = |
452 | | RsaSigningKey::from_pkcs8(&PrivatePkcs8KeyDer::from(RSA_KEY), Algorithm::RSASHA256) |
453 | | .unwrap(); |
454 | | let pub_key = key.to_public_key().unwrap(); |
455 | | let dnskey = DNSKEY::from_key(&pub_key); |
456 | | let signer = DnssecSigner::new( |
457 | | dnskey, |
458 | | Box::new(key), |
459 | | Name::root(), |
460 | | Duration::from_secs(300), |
461 | | ); |
462 | | let key_tag = signer.calculate_key_tag().unwrap(); |
463 | | |
464 | | assert_eq!(key_tag, 3257); |
465 | | } |
466 | | |
467 | | #[test] |
468 | | fn test_rrset_tbs() { |
469 | | let key = |
470 | | RsaSigningKey::from_pkcs8(&PrivatePkcs8KeyDer::from(RSA_KEY), Algorithm::RSASHA256) |
471 | | .unwrap(); |
472 | | let pub_key = key.to_public_key().unwrap(); |
473 | | let dnskey = DNSKEY::from_key(&pub_key); |
474 | | let signer = DnssecSigner::new( |
475 | | dnskey, |
476 | | Box::new(key), |
477 | | Name::root(), |
478 | | Duration::from_secs(300), |
479 | | ); |
480 | | |
481 | | let origin = Name::parse("example.com.", None).unwrap(); |
482 | | let input = SigInput { |
483 | | type_covered: RecordType::NS, |
484 | | algorithm: Algorithm::RSASHA256, |
485 | | num_labels: origin.num_labels(), |
486 | | original_ttl: 86400, |
487 | | sig_expiration: SerialNumber(5), |
488 | | sig_inception: SerialNumber(0), |
489 | | key_tag: signer.calculate_key_tag().unwrap(), |
490 | | signer_name: origin.clone(), |
491 | | }; |
492 | | |
493 | | let rrset = [ |
494 | | Record::from_rdata( |
495 | | origin.clone(), |
496 | | 86400, |
497 | | RData::NS(NS(Name::parse("a.iana-servers.net.", None).unwrap())), |
498 | | ) |
499 | | .set_dns_class(DNSClass::IN) |
500 | | .clone(), |
501 | | Record::from_rdata( |
502 | | origin.clone(), |
503 | | 86400, |
504 | | RData::NS(NS(Name::parse("b.iana-servers.net.", None).unwrap())), |
505 | | ) |
506 | | .set_dns_class(DNSClass::IN) |
507 | | .clone(), |
508 | | ]; |
509 | | |
510 | | let tbs = TBS::from_input(&origin, DNSClass::IN, &input, rrset.iter()).unwrap(); |
511 | | assert!(!tbs.as_ref().is_empty()); |
512 | | |
513 | | let rrset = [ |
514 | | Record::from_rdata( |
515 | | origin.clone(), |
516 | | 86400, |
517 | | RData::CNAME(CNAME(Name::parse("a.iana-servers.net.", None).unwrap())), |
518 | | ) |
519 | | .set_dns_class(DNSClass::IN) |
520 | | .clone(), // different type |
521 | | Record::from_rdata( |
522 | | Name::parse("www.example.com.", None).unwrap(), |
523 | | 86400, |
524 | | RData::NS(NS(Name::parse("a.iana-servers.net.", None).unwrap())), |
525 | | ) |
526 | | .set_dns_class(DNSClass::IN) |
527 | | .clone(), // different name |
528 | | Record::from_rdata( |
529 | | origin.clone(), |
530 | | 86400, |
531 | | RData::NS(NS(Name::parse("a.iana-servers.net.", None).unwrap())), |
532 | | ) |
533 | | .set_dns_class(DNSClass::CH) |
534 | | .clone(), // different class |
535 | | Record::from_rdata( |
536 | | origin.clone(), |
537 | | 86400, |
538 | | RData::NS(NS(Name::parse("a.iana-servers.net.", None).unwrap())), |
539 | | ) |
540 | | .set_dns_class(DNSClass::IN) |
541 | | .clone(), |
542 | | Record::from_rdata( |
543 | | origin.clone(), |
544 | | 86400, |
545 | | RData::NS(NS(Name::parse("b.iana-servers.net.", None).unwrap())), |
546 | | ) |
547 | | .set_dns_class(DNSClass::IN) |
548 | | .clone(), |
549 | | ]; |
550 | | |
551 | | let filtered_tbs = TBS::from_input(&origin, DNSClass::IN, &input, rrset.iter()).unwrap(); |
552 | | assert!(!filtered_tbs.as_ref().is_empty()); |
553 | | assert_eq!(tbs.as_ref(), filtered_tbs.as_ref()); |
554 | | } |
555 | | |
556 | | const RSA_KEY: &[u8] = include_bytes!("../../tests/test-data/rsa-2048-private-key-1.pk8"); |
557 | | } |