1package dns 2 3import ( 4 "bytes" 5 "crypto" 6 "crypto/ecdsa" 7 "crypto/ed25519" 8 "crypto/elliptic" 9 "crypto/rand" 10 "crypto/rsa" 11 _ "crypto/sha1" // need its init function 12 _ "crypto/sha256" // need its init function 13 _ "crypto/sha512" // need its init function 14 "encoding/asn1" 15 "encoding/binary" 16 "encoding/hex" 17 "math/big" 18 "sort" 19 "strings" 20 "time" 21) 22 23// DNSSEC encryption algorithm codes. 24const ( 25 _ uint8 = iota 26 RSAMD5 27 DH 28 DSA 29 _ // Skip 4, RFC 6725, section 2.1 30 RSASHA1 31 DSANSEC3SHA1 32 RSASHA1NSEC3SHA1 33 RSASHA256 34 _ // Skip 9, RFC 6725, section 2.1 35 RSASHA512 36 _ // Skip 11, RFC 6725, section 2.1 37 ECCGOST 38 ECDSAP256SHA256 39 ECDSAP384SHA384 40 ED25519 41 ED448 42 INDIRECT uint8 = 252 43 PRIVATEDNS uint8 = 253 // Private (experimental keys) 44 PRIVATEOID uint8 = 254 45) 46 47// AlgorithmToString is a map of algorithm IDs to algorithm names. 48var AlgorithmToString = map[uint8]string{ 49 RSAMD5: "RSAMD5", 50 DH: "DH", 51 DSA: "DSA", 52 RSASHA1: "RSASHA1", 53 DSANSEC3SHA1: "DSA-NSEC3-SHA1", 54 RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1", 55 RSASHA256: "RSASHA256", 56 RSASHA512: "RSASHA512", 57 ECCGOST: "ECC-GOST", 58 ECDSAP256SHA256: "ECDSAP256SHA256", 59 ECDSAP384SHA384: "ECDSAP384SHA384", 60 ED25519: "ED25519", 61 ED448: "ED448", 62 INDIRECT: "INDIRECT", 63 PRIVATEDNS: "PRIVATEDNS", 64 PRIVATEOID: "PRIVATEOID", 65} 66 67// AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's. 68var AlgorithmToHash = map[uint8]crypto.Hash{ 69 RSAMD5: crypto.MD5, // Deprecated in RFC 6725 70 DSA: crypto.SHA1, 71 RSASHA1: crypto.SHA1, 72 RSASHA1NSEC3SHA1: crypto.SHA1, 73 RSASHA256: crypto.SHA256, 74 ECDSAP256SHA256: crypto.SHA256, 75 ECDSAP384SHA384: crypto.SHA384, 76 RSASHA512: crypto.SHA512, 77 ED25519: crypto.Hash(0), 78} 79 80// DNSSEC hashing algorithm codes. 81const ( 82 _ uint8 = iota 83 SHA1 // RFC 4034 84 SHA256 // RFC 4509 85 GOST94 // RFC 5933 86 SHA384 // Experimental 87 SHA512 // Experimental 88) 89 90// HashToString is a map of hash IDs to names. 91var HashToString = map[uint8]string{ 92 SHA1: "SHA1", 93 SHA256: "SHA256", 94 GOST94: "GOST94", 95 SHA384: "SHA384", 96 SHA512: "SHA512", 97} 98 99// DNSKEY flag values. 100const ( 101 SEP = 1 102 REVOKE = 1 << 7 103 ZONE = 1 << 8 104) 105 106// The RRSIG needs to be converted to wireformat with some of the rdata (the signature) missing. 107type rrsigWireFmt struct { 108 TypeCovered uint16 109 Algorithm uint8 110 Labels uint8 111 OrigTtl uint32 112 Expiration uint32 113 Inception uint32 114 KeyTag uint16 115 SignerName string `dns:"domain-name"` 116 /* No Signature */ 117} 118 119// Used for converting DNSKEY's rdata to wirefmt. 120type dnskeyWireFmt struct { 121 Flags uint16 122 Protocol uint8 123 Algorithm uint8 124 PublicKey string `dns:"base64"` 125 /* Nothing is left out */ 126} 127 128func divRoundUp(a, b int) int { 129 return (a + b - 1) / b 130} 131 132// KeyTag calculates the keytag (or key-id) of the DNSKEY. 133func (k *DNSKEY) KeyTag() uint16 { 134 if k == nil { 135 return 0 136 } 137 var keytag int 138 switch k.Algorithm { 139 case RSAMD5: 140 // Look at the bottom two bytes of the modules, which the last 141 // item in the pubkey. 142 // This algorithm has been deprecated, but keep this key-tag calculation. 143 modulus, _ := fromBase64([]byte(k.PublicKey)) 144 if len(modulus) > 1 { 145 x := binary.BigEndian.Uint16(modulus[len(modulus)-2:]) 146 keytag = int(x) 147 } 148 default: 149 keywire := new(dnskeyWireFmt) 150 keywire.Flags = k.Flags 151 keywire.Protocol = k.Protocol 152 keywire.Algorithm = k.Algorithm 153 keywire.PublicKey = k.PublicKey 154 wire := make([]byte, DefaultMsgSize) 155 n, err := packKeyWire(keywire, wire) 156 if err != nil { 157 return 0 158 } 159 wire = wire[:n] 160 for i, v := range wire { 161 if i&1 != 0 { 162 keytag += int(v) // must be larger than uint32 163 } else { 164 keytag += int(v) << 8 165 } 166 } 167 keytag += keytag >> 16 & 0xFFFF 168 keytag &= 0xFFFF 169 } 170 return uint16(keytag) 171} 172 173// ToDS converts a DNSKEY record to a DS record. 174func (k *DNSKEY) ToDS(h uint8) *DS { 175 if k == nil { 176 return nil 177 } 178 ds := new(DS) 179 ds.Hdr.Name = k.Hdr.Name 180 ds.Hdr.Class = k.Hdr.Class 181 ds.Hdr.Rrtype = TypeDS 182 ds.Hdr.Ttl = k.Hdr.Ttl 183 ds.Algorithm = k.Algorithm 184 ds.DigestType = h 185 ds.KeyTag = k.KeyTag() 186 187 keywire := new(dnskeyWireFmt) 188 keywire.Flags = k.Flags 189 keywire.Protocol = k.Protocol 190 keywire.Algorithm = k.Algorithm 191 keywire.PublicKey = k.PublicKey 192 wire := make([]byte, DefaultMsgSize) 193 n, err := packKeyWire(keywire, wire) 194 if err != nil { 195 return nil 196 } 197 wire = wire[:n] 198 199 owner := make([]byte, 255) 200 off, err1 := PackDomainName(CanonicalName(k.Hdr.Name), owner, 0, nil, false) 201 if err1 != nil { 202 return nil 203 } 204 owner = owner[:off] 205 // RFC4034: 206 // digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA); 207 // "|" denotes concatenation 208 // DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key. 209 210 var hash crypto.Hash 211 switch h { 212 case SHA1: 213 hash = crypto.SHA1 214 case SHA256: 215 hash = crypto.SHA256 216 case SHA384: 217 hash = crypto.SHA384 218 case SHA512: 219 hash = crypto.SHA512 220 default: 221 return nil 222 } 223 224 s := hash.New() 225 s.Write(owner) 226 s.Write(wire) 227 ds.Digest = hex.EncodeToString(s.Sum(nil)) 228 return ds 229} 230 231// ToCDNSKEY converts a DNSKEY record to a CDNSKEY record. 232func (k *DNSKEY) ToCDNSKEY() *CDNSKEY { 233 c := &CDNSKEY{DNSKEY: *k} 234 c.Hdr = k.Hdr 235 c.Hdr.Rrtype = TypeCDNSKEY 236 return c 237} 238 239// ToCDS converts a DS record to a CDS record. 240func (d *DS) ToCDS() *CDS { 241 c := &CDS{DS: *d} 242 c.Hdr = d.Hdr 243 c.Hdr.Rrtype = TypeCDS 244 return c 245} 246 247// Sign signs an RRSet. The signature needs to be filled in with the values: 248// Inception, Expiration, KeyTag, SignerName and Algorithm. The rest is copied 249// from the RRset. Sign returns a non-nill error when the signing went OK. 250// There is no check if RRSet is a proper (RFC 2181) RRSet. If OrigTTL is non 251// zero, it is used as-is, otherwise the TTL of the RRset is used as the 252// OrigTTL. 253func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error { 254 if k == nil { 255 return ErrPrivKey 256 } 257 // s.Inception and s.Expiration may be 0 (rollover etc.), the rest must be set 258 if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 { 259 return ErrKey 260 } 261 262 h0 := rrset[0].Header() 263 rr.Hdr.Rrtype = TypeRRSIG 264 rr.Hdr.Name = h0.Name 265 rr.Hdr.Class = h0.Class 266 if rr.OrigTtl == 0 { // If set don't override 267 rr.OrigTtl = h0.Ttl 268 } 269 rr.TypeCovered = h0.Rrtype 270 rr.Labels = uint8(CountLabel(h0.Name)) 271 272 if strings.HasPrefix(h0.Name, "*") { 273 rr.Labels-- // wildcard, remove from label count 274 } 275 276 sigwire := new(rrsigWireFmt) 277 sigwire.TypeCovered = rr.TypeCovered 278 sigwire.Algorithm = rr.Algorithm 279 sigwire.Labels = rr.Labels 280 sigwire.OrigTtl = rr.OrigTtl 281 sigwire.Expiration = rr.Expiration 282 sigwire.Inception = rr.Inception 283 sigwire.KeyTag = rr.KeyTag 284 // For signing, lowercase this name 285 sigwire.SignerName = CanonicalName(rr.SignerName) 286 287 // Create the desired binary blob 288 signdata := make([]byte, DefaultMsgSize) 289 n, err := packSigWire(sigwire, signdata) 290 if err != nil { 291 return err 292 } 293 signdata = signdata[:n] 294 wire, err := rawSignatureData(rrset, rr) 295 if err != nil { 296 return err 297 } 298 299 hash, ok := AlgorithmToHash[rr.Algorithm] 300 if !ok { 301 return ErrAlg 302 } 303 304 switch rr.Algorithm { 305 case ED25519: 306 // ed25519 signs the raw message and performs hashing internally. 307 // All other supported signature schemes operate over the pre-hashed 308 // message, and thus ed25519 must be handled separately here. 309 // 310 // The raw message is passed directly into sign and crypto.Hash(0) is 311 // used to signal to the crypto.Signer that the data has not been hashed. 312 signature, err := sign(k, append(signdata, wire...), crypto.Hash(0), rr.Algorithm) 313 if err != nil { 314 return err 315 } 316 317 rr.Signature = toBase64(signature) 318 return nil 319 case RSAMD5, DSA, DSANSEC3SHA1: 320 // See RFC 6944. 321 return ErrAlg 322 default: 323 h := hash.New() 324 h.Write(signdata) 325 h.Write(wire) 326 327 signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm) 328 if err != nil { 329 return err 330 } 331 332 rr.Signature = toBase64(signature) 333 return nil 334 } 335} 336 337func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) { 338 signature, err := k.Sign(rand.Reader, hashed, hash) 339 if err != nil { 340 return nil, err 341 } 342 343 switch alg { 344 case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512: 345 return signature, nil 346 case ECDSAP256SHA256, ECDSAP384SHA384: 347 ecdsaSignature := &struct { 348 R, S *big.Int 349 }{} 350 if _, err := asn1.Unmarshal(signature, ecdsaSignature); err != nil { 351 return nil, err 352 } 353 354 var intlen int 355 switch alg { 356 case ECDSAP256SHA256: 357 intlen = 32 358 case ECDSAP384SHA384: 359 intlen = 48 360 } 361 362 signature := intToBytes(ecdsaSignature.R, intlen) 363 signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...) 364 return signature, nil 365 case ED25519: 366 return signature, nil 367 default: 368 return nil, ErrAlg 369 } 370} 371 372// Verify validates an RRSet with the signature and key. This is only the 373// cryptographic test, the signature validity period must be checked separately. 374// This function copies the rdata of some RRs (to lowercase domain names) for the validation to work. 375// It also checks that the Zone Key bit (RFC 4034 2.1.1) is set on the DNSKEY 376// and that the Protocol field is set to 3 (RFC 4034 2.1.2). 377func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error { 378 // First the easy checks 379 if !IsRRset(rrset) { 380 return ErrRRset 381 } 382 if rr.KeyTag != k.KeyTag() { 383 return ErrKey 384 } 385 if rr.Hdr.Class != k.Hdr.Class { 386 return ErrKey 387 } 388 if rr.Algorithm != k.Algorithm { 389 return ErrKey 390 } 391 if !strings.EqualFold(rr.SignerName, k.Hdr.Name) { 392 return ErrKey 393 } 394 if k.Protocol != 3 { 395 return ErrKey 396 } 397 // RFC 4034 2.1.1 If bit 7 has value 0, then the DNSKEY record holds some 398 // other type of DNS public key and MUST NOT be used to verify RRSIGs that 399 // cover RRsets. 400 if k.Flags&ZONE == 0 { 401 return ErrKey 402 } 403 404 // IsRRset checked that we have at least one RR and that the RRs in 405 // the set have consistent type, class, and name. Also check that type and 406 // class matches the RRSIG record. 407 if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered { 408 return ErrRRset 409 } 410 411 // RFC 4035 5.3.2. Reconstructing the Signed Data 412 // Copy the sig, except the rrsig data 413 sigwire := new(rrsigWireFmt) 414 sigwire.TypeCovered = rr.TypeCovered 415 sigwire.Algorithm = rr.Algorithm 416 sigwire.Labels = rr.Labels 417 sigwire.OrigTtl = rr.OrigTtl 418 sigwire.Expiration = rr.Expiration 419 sigwire.Inception = rr.Inception 420 sigwire.KeyTag = rr.KeyTag 421 sigwire.SignerName = CanonicalName(rr.SignerName) 422 // Create the desired binary blob 423 signeddata := make([]byte, DefaultMsgSize) 424 n, err := packSigWire(sigwire, signeddata) 425 if err != nil { 426 return err 427 } 428 signeddata = signeddata[:n] 429 wire, err := rawSignatureData(rrset, rr) 430 if err != nil { 431 return err 432 } 433 434 sigbuf := rr.sigBuf() // Get the binary signature data 435 if rr.Algorithm == PRIVATEDNS { // PRIVATEOID 436 // TODO(miek) 437 // remove the domain name and assume its ours? 438 } 439 440 hash, ok := AlgorithmToHash[rr.Algorithm] 441 if !ok { 442 return ErrAlg 443 } 444 445 switch rr.Algorithm { 446 case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512: 447 // TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere?? 448 pubkey := k.publicKeyRSA() // Get the key 449 if pubkey == nil { 450 return ErrKey 451 } 452 453 h := hash.New() 454 h.Write(signeddata) 455 h.Write(wire) 456 return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf) 457 458 case ECDSAP256SHA256, ECDSAP384SHA384: 459 pubkey := k.publicKeyECDSA() 460 if pubkey == nil { 461 return ErrKey 462 } 463 464 // Split sigbuf into the r and s coordinates 465 r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2]) 466 s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:]) 467 468 h := hash.New() 469 h.Write(signeddata) 470 h.Write(wire) 471 if ecdsa.Verify(pubkey, h.Sum(nil), r, s) { 472 return nil 473 } 474 return ErrSig 475 476 case ED25519: 477 pubkey := k.publicKeyED25519() 478 if pubkey == nil { 479 return ErrKey 480 } 481 482 if ed25519.Verify(pubkey, append(signeddata, wire...), sigbuf) { 483 return nil 484 } 485 return ErrSig 486 487 default: 488 return ErrAlg 489 } 490} 491 492// ValidityPeriod uses RFC1982 serial arithmetic to calculate 493// if a signature period is valid. If t is the zero time, the 494// current time is taken other t is. Returns true if the signature 495// is valid at the given time, otherwise returns false. 496func (rr *RRSIG) ValidityPeriod(t time.Time) bool { 497 var utc int64 498 if t.IsZero() { 499 utc = time.Now().UTC().Unix() 500 } else { 501 utc = t.UTC().Unix() 502 } 503 modi := (int64(rr.Inception) - utc) / year68 504 mode := (int64(rr.Expiration) - utc) / year68 505 ti := int64(rr.Inception) + modi*year68 506 te := int64(rr.Expiration) + mode*year68 507 return ti <= utc && utc <= te 508} 509 510// Return the signatures base64 encoding sigdata as a byte slice. 511func (rr *RRSIG) sigBuf() []byte { 512 sigbuf, err := fromBase64([]byte(rr.Signature)) 513 if err != nil { 514 return nil 515 } 516 return sigbuf 517} 518 519// publicKeyRSA returns the RSA public key from a DNSKEY record. 520func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey { 521 keybuf, err := fromBase64([]byte(k.PublicKey)) 522 if err != nil { 523 return nil 524 } 525 526 if len(keybuf) < 1+1+64 { 527 // Exponent must be at least 1 byte and modulus at least 64 528 return nil 529 } 530 531 // RFC 2537/3110, section 2. RSA Public KEY Resource Records 532 // Length is in the 0th byte, unless its zero, then it 533 // it in bytes 1 and 2 and its a 16 bit number 534 explen := uint16(keybuf[0]) 535 keyoff := 1 536 if explen == 0 { 537 explen = uint16(keybuf[1])<<8 | uint16(keybuf[2]) 538 keyoff = 3 539 } 540 541 if explen > 4 || explen == 0 || keybuf[keyoff] == 0 { 542 // Exponent larger than supported by the crypto package, 543 // empty, or contains prohibited leading zero. 544 return nil 545 } 546 547 modoff := keyoff + int(explen) 548 modlen := len(keybuf) - modoff 549 if modlen < 64 || modlen > 512 || keybuf[modoff] == 0 { 550 // Modulus is too small, large, or contains prohibited leading zero. 551 return nil 552 } 553 554 pubkey := new(rsa.PublicKey) 555 556 var expo uint64 557 // The exponent of length explen is between keyoff and modoff. 558 for _, v := range keybuf[keyoff:modoff] { 559 expo <<= 8 560 expo |= uint64(v) 561 } 562 if expo > 1<<31-1 { 563 // Larger exponent than supported by the crypto package. 564 return nil 565 } 566 567 pubkey.E = int(expo) 568 pubkey.N = new(big.Int).SetBytes(keybuf[modoff:]) 569 return pubkey 570} 571 572// publicKeyECDSA returns the Curve public key from the DNSKEY record. 573func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey { 574 keybuf, err := fromBase64([]byte(k.PublicKey)) 575 if err != nil { 576 return nil 577 } 578 pubkey := new(ecdsa.PublicKey) 579 switch k.Algorithm { 580 case ECDSAP256SHA256: 581 pubkey.Curve = elliptic.P256() 582 if len(keybuf) != 64 { 583 // wrongly encoded key 584 return nil 585 } 586 case ECDSAP384SHA384: 587 pubkey.Curve = elliptic.P384() 588 if len(keybuf) != 96 { 589 // Wrongly encoded key 590 return nil 591 } 592 } 593 pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2]) 594 pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:]) 595 return pubkey 596} 597 598func (k *DNSKEY) publicKeyED25519() ed25519.PublicKey { 599 keybuf, err := fromBase64([]byte(k.PublicKey)) 600 if err != nil { 601 return nil 602 } 603 if len(keybuf) != ed25519.PublicKeySize { 604 return nil 605 } 606 return keybuf 607} 608 609type wireSlice [][]byte 610 611func (p wireSlice) Len() int { return len(p) } 612func (p wireSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 613func (p wireSlice) Less(i, j int) bool { 614 _, ioff, _ := UnpackDomainName(p[i], 0) 615 _, joff, _ := UnpackDomainName(p[j], 0) 616 return bytes.Compare(p[i][ioff+10:], p[j][joff+10:]) < 0 617} 618 619// Return the raw signature data. 620func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) { 621 wires := make(wireSlice, len(rrset)) 622 for i, r := range rrset { 623 r1 := r.copy() 624 h := r1.Header() 625 h.Ttl = s.OrigTtl 626 labels := SplitDomainName(h.Name) 627 // 6.2. Canonical RR Form. (4) - wildcards 628 if len(labels) > int(s.Labels) { 629 // Wildcard 630 h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "." 631 } 632 // RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase 633 h.Name = CanonicalName(h.Name) 634 // 6.2. Canonical RR Form. (3) - domain rdata to lowercase. 635 // NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR, 636 // HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, 637 // SRV, DNAME, A6 638 // 639 // RFC 6840 - Clarifications and Implementation Notes for DNS Security (DNSSEC): 640 // Section 6.2 of [RFC4034] also erroneously lists HINFO as a record 641 // that needs conversion to lowercase, and twice at that. Since HINFO 642 // records contain no domain names, they are not subject to case 643 // conversion. 644 switch x := r1.(type) { 645 case *NS: 646 x.Ns = CanonicalName(x.Ns) 647 case *MD: 648 x.Md = CanonicalName(x.Md) 649 case *MF: 650 x.Mf = CanonicalName(x.Mf) 651 case *CNAME: 652 x.Target = CanonicalName(x.Target) 653 case *SOA: 654 x.Ns = CanonicalName(x.Ns) 655 x.Mbox = CanonicalName(x.Mbox) 656 case *MB: 657 x.Mb = CanonicalName(x.Mb) 658 case *MG: 659 x.Mg = CanonicalName(x.Mg) 660 case *MR: 661 x.Mr = CanonicalName(x.Mr) 662 case *PTR: 663 x.Ptr = CanonicalName(x.Ptr) 664 case *MINFO: 665 x.Rmail = CanonicalName(x.Rmail) 666 x.Email = CanonicalName(x.Email) 667 case *MX: 668 x.Mx = CanonicalName(x.Mx) 669 case *RP: 670 x.Mbox = CanonicalName(x.Mbox) 671 x.Txt = CanonicalName(x.Txt) 672 case *AFSDB: 673 x.Hostname = CanonicalName(x.Hostname) 674 case *RT: 675 x.Host = CanonicalName(x.Host) 676 case *SIG: 677 x.SignerName = CanonicalName(x.SignerName) 678 case *PX: 679 x.Map822 = CanonicalName(x.Map822) 680 x.Mapx400 = CanonicalName(x.Mapx400) 681 case *NAPTR: 682 x.Replacement = CanonicalName(x.Replacement) 683 case *KX: 684 x.Exchanger = CanonicalName(x.Exchanger) 685 case *SRV: 686 x.Target = CanonicalName(x.Target) 687 case *DNAME: 688 x.Target = CanonicalName(x.Target) 689 } 690 // 6.2. Canonical RR Form. (5) - origTTL 691 wire := make([]byte, Len(r1)+1) // +1 to be safe(r) 692 off, err1 := PackRR(r1, wire, 0, nil, false) 693 if err1 != nil { 694 return nil, err1 695 } 696 wire = wire[:off] 697 wires[i] = wire 698 } 699 sort.Sort(wires) 700 for i, wire := range wires { 701 if i > 0 && bytes.Equal(wire, wires[i-1]) { 702 continue 703 } 704 buf = append(buf, wire...) 705 } 706 return buf, nil 707} 708 709func packSigWire(sw *rrsigWireFmt, msg []byte) (int, error) { 710 // copied from zmsg.go RRSIG packing 711 off, err := packUint16(sw.TypeCovered, msg, 0) 712 if err != nil { 713 return off, err 714 } 715 off, err = packUint8(sw.Algorithm, msg, off) 716 if err != nil { 717 return off, err 718 } 719 off, err = packUint8(sw.Labels, msg, off) 720 if err != nil { 721 return off, err 722 } 723 off, err = packUint32(sw.OrigTtl, msg, off) 724 if err != nil { 725 return off, err 726 } 727 off, err = packUint32(sw.Expiration, msg, off) 728 if err != nil { 729 return off, err 730 } 731 off, err = packUint32(sw.Inception, msg, off) 732 if err != nil { 733 return off, err 734 } 735 off, err = packUint16(sw.KeyTag, msg, off) 736 if err != nil { 737 return off, err 738 } 739 off, err = PackDomainName(sw.SignerName, msg, off, nil, false) 740 if err != nil { 741 return off, err 742 } 743 return off, nil 744} 745 746func packKeyWire(dw *dnskeyWireFmt, msg []byte) (int, error) { 747 // copied from zmsg.go DNSKEY packing 748 off, err := packUint16(dw.Flags, msg, 0) 749 if err != nil { 750 return off, err 751 } 752 off, err = packUint8(dw.Protocol, msg, off) 753 if err != nil { 754 return off, err 755 } 756 off, err = packUint8(dw.Algorithm, msg, off) 757 if err != nil { 758 return off, err 759 } 760 off, err = packStringBase64(dw.PublicKey, msg, off) 761 if err != nil { 762 return off, err 763 } 764 return off, nil 765} 766