1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
/* * Copyright (C) 2016 Benjamin Fry <benjaminfry@me.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //! pointer record from parent zone to child zone for dnskey proof use ::serialize::binary::*; use ::error::*; use ::rr::dnssec::{Algorithm, DigestType}; /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-5) /// /// ```text /// 5.1. DS RDATA Wire Format /// /// The RDATA for a DS RR consists of a 2 octet Key Tag field, a 1 octet /// Algorithm field, a 1 octet Digest Type field, and a Digest field. /// /// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// | Key Tag | Algorithm | Digest Type | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// / / /// / Digest / /// / / /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// /// 5.2. Processing of DS RRs When Validating Responses /// /// The DS RR links the authentication chain across zone boundaries, so /// the DS RR requires extra care in processing. The DNSKEY RR referred /// to in the DS RR MUST be a DNSSEC zone key. The DNSKEY RR Flags MUST /// have Flags bit 7 set. If the DNSKEY flags do not indicate a DNSSEC /// zone key, the DS RR (and the DNSKEY RR it references) MUST NOT be /// used in the validation process. /// /// 5.3. The DS RR Presentation Format /// /// The presentation format of the RDATA portion is as follows: /// /// The Key Tag field MUST be represented as an unsigned decimal integer. /// /// The Algorithm field MUST be represented either as an unsigned decimal /// integer or as an algorithm mnemonic specified in Appendix A.1. /// /// The Digest Type field MUST be represented as an unsigned decimal /// integer. /// /// The Digest MUST be represented as a sequence of case-insensitive /// hexadecimal digits. Whitespace is allowed within the hexadecimal /// text. /// ``` #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub struct DS { key_tag: u16, algorithm: Algorithm, digest_type: DigestType, digest: Vec<u8> } impl DS { pub fn new(key_tag: u16, algorithm: Algorithm, digest_type: DigestType, digest: Vec<u8>) -> DS { DS { key_tag: key_tag, algorithm: algorithm, digest_type: digest_type, digest: digest } } /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-5.1.1) /// /// ```text /// 5.1.1. The Key Tag Field /// /// The Key Tag field lists the key tag of the DNSKEY RR referred to by /// the DS record, in network byte order. /// /// The Key Tag used by the DS RR is identical to the Key Tag used by /// RRSIG RRs. Appendix B describes how to compute a Key Tag. /// ``` pub fn get_key_tag(&self) -> u16 { self.key_tag } /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-5.1.1) /// /// ```text /// 5.1.2. The Algorithm Field /// /// The Algorithm field lists the algorithm number of the DNSKEY RR /// referred to by the DS record. /// /// The algorithm number used by the DS RR is identical to the algorithm /// number used by RRSIG and DNSKEY RRs. Appendix A.1 lists the /// algorithm number types. /// ``` pub fn get_algorithm(&self) -> &Algorithm { &self.algorithm } /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-5.1.1) /// /// ```text /// 5.1.3. The Digest Type Field /// /// The DS RR refers to a DNSKEY RR by including a digest of that DNSKEY /// RR. The Digest Type field identifies the algorithm used to construct /// the digest. Appendix A.2 lists the possible digest algorithm types. /// ``` pub fn get_digest_type(&self) -> DigestType { self.digest_type } /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-5.1.1) /// /// ```text /// 5.1.4. The Digest Field /// /// The DS record refers to a DNSKEY RR by including a digest of that /// DNSKEY RR. /// /// The digest is calculated by concatenating the canonical form of the /// fully qualified owner name of the DNSKEY RR with the DNSKEY RDATA, /// and then applying the digest algorithm. /// /// digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA); /// /// "|" denotes concatenation /// /// DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key. /// /// The size of the digest may vary depending on the digest algorithm and /// DNSKEY RR size. As of the time of this writing, the only defined /// digest algorithm is SHA-1, which produces a 20 octet digest. /// ``` pub fn get_digest(&self) -> &[u8] { &self.digest } } pub fn read(decoder: &mut BinDecoder, rdata_length: u16) -> DecodeResult<DS> { let start_idx = decoder.index(); let key_tag: u16 = try!(decoder.read_u16()); let algorithm: Algorithm = try!(Algorithm::read(decoder)); let digest_type: DigestType = try!(DigestType::from_u8(try!(decoder.read_u8()))); let left: usize = rdata_length as usize - (decoder.index() - start_idx);; let digest = try!(decoder.read_vec(left)); Ok(DS::new(key_tag, algorithm, digest_type, digest)) } pub fn emit(encoder: &mut BinEncoder, rdata: &DS) -> EncodeResult { try!(encoder.emit_u16(rdata.get_key_tag())); try!(rdata.get_algorithm().emit(encoder)); // always 3 for now try!(encoder.emit(rdata.get_digest_type().into())); try!(encoder.emit_vec(rdata.get_digest())); Ok(()) } #[test] pub fn test() { let rdata = DS::new(0xF00F, Algorithm::RSASHA256, DigestType::SHA256, vec![5,6,7,8]); let mut bytes = Vec::new(); let mut encoder: BinEncoder = BinEncoder::new(&mut bytes); assert!(emit(&mut encoder, &rdata).is_ok()); let bytes = encoder.as_bytes(); println!("bytes: {:?}", bytes); let mut decoder: BinDecoder = BinDecoder::new(bytes); let read_rdata = read(&mut decoder, bytes.len() as u16); assert!(read_rdata.is_ok(), format!("error decoding: {:?}", read_rdata.unwrap_err())); assert_eq!(rdata, read_rdata.unwrap()); }