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" 12 _ "crypto/sha256" 13 _ "crypto/sha512" 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. 375func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error { 376 // First the easy checks 377 if !IsRRset(rrset) { 378 return ErrRRset 379 } 380 if rr.KeyTag != k.KeyTag() { 381 return ErrKey 382 } 383 if rr.Hdr.Class != k.Hdr.Class { 384 return ErrKey 385 } 386 if rr.Algorithm != k.Algorithm { 387 return ErrKey 388 } 389 if !strings.EqualFold(rr.SignerName, k.Hdr.Name) { 390 return ErrKey 391 } 392 if k.Protocol != 3 { 393 return ErrKey 394 } 395 396 // IsRRset checked that we have at least one RR and that the RRs in 397 // the set have consistent type, class, and name. Also check that type and 398 // class matches the RRSIG record. 399 if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered { 400 return ErrRRset 401 } 402 403 // RFC 4035 5.3.2. Reconstructing the Signed Data 404 // Copy the sig, except the rrsig data 405 sigwire := new(rrsigWireFmt) 406 sigwire.TypeCovered = rr.TypeCovered 407 sigwire.Algorithm = rr.Algorithm 408 sigwire.Labels = rr.Labels 409 sigwire.OrigTtl = rr.OrigTtl 410 sigwire.Expiration = rr.Expiration 411 sigwire.Inception = rr.Inception 412 sigwire.KeyTag = rr.KeyTag 413 sigwire.SignerName = CanonicalName(rr.SignerName) 414 // Create the desired binary blob 415 signeddata := make([]byte, DefaultMsgSize) 416 n, err := packSigWire(sigwire, signeddata) 417 if err != nil { 418 return err 419 } 420 signeddata = signeddata[:n] 421 wire, err := rawSignatureData(rrset, rr) 422 if err != nil { 423 return err 424 } 425 426 sigbuf := rr.sigBuf() // Get the binary signature data 427 if rr.Algorithm == PRIVATEDNS { // PRIVATEOID 428 // TODO(miek) 429 // remove the domain name and assume its ours? 430 } 431 432 hash, ok := AlgorithmToHash[rr.Algorithm] 433 if !ok { 434 return ErrAlg 435 } 436 437 switch rr.Algorithm { 438 case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512: 439 // TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere?? 440 pubkey := k.publicKeyRSA() // Get the key 441 if pubkey == nil { 442 return ErrKey 443 } 444 445 h := hash.New() 446 h.Write(signeddata) 447 h.Write(wire) 448 return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf) 449 450 case ECDSAP256SHA256, ECDSAP384SHA384: 451 pubkey := k.publicKeyECDSA() 452 if pubkey == nil { 453 return ErrKey 454 } 455 456 // Split sigbuf into the r and s coordinates 457 r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2]) 458 s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:]) 459 460 h := hash.New() 461 h.Write(signeddata) 462 h.Write(wire) 463 if ecdsa.Verify(pubkey, h.Sum(nil), r, s) { 464 return nil 465 } 466 return ErrSig 467 468 case ED25519: 469 pubkey := k.publicKeyED25519() 470 if pubkey == nil { 471 return ErrKey 472 } 473 474 if ed25519.Verify(pubkey, append(signeddata, wire...), sigbuf) { 475 return nil 476 } 477 return ErrSig 478 479 default: 480 return ErrAlg 481 } 482} 483 484// ValidityPeriod uses RFC1982 serial arithmetic to calculate 485// if a signature period is valid. If t is the zero time, the 486// current time is taken other t is. Returns true if the signature 487// is valid at the given time, otherwise returns false. 488func (rr *RRSIG) ValidityPeriod(t time.Time) bool { 489 var utc int64 490 if t.IsZero() { 491 utc = time.Now().UTC().Unix() 492 } else { 493 utc = t.UTC().Unix() 494 } 495 modi := (int64(rr.Inception) - utc) / year68 496 mode := (int64(rr.Expiration) - utc) / year68 497 ti := int64(rr.Inception) + modi*year68 498 te := int64(rr.Expiration) + mode*year68 499 return ti <= utc && utc <= te 500} 501 502// Return the signatures base64 encoding sigdata as a byte slice. 503func (rr *RRSIG) sigBuf() []byte { 504 sigbuf, err := fromBase64([]byte(rr.Signature)) 505 if err != nil { 506 return nil 507 } 508 return sigbuf 509} 510 511// publicKeyRSA returns the RSA public key from a DNSKEY record. 512func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey { 513 keybuf, err := fromBase64([]byte(k.PublicKey)) 514 if err != nil { 515 return nil 516 } 517 518 if len(keybuf) < 1+1+64 { 519 // Exponent must be at least 1 byte and modulus at least 64 520 return nil 521 } 522 523 // RFC 2537/3110, section 2. RSA Public KEY Resource Records 524 // Length is in the 0th byte, unless its zero, then it 525 // it in bytes 1 and 2 and its a 16 bit number 526 explen := uint16(keybuf[0]) 527 keyoff := 1 528 if explen == 0 { 529 explen = uint16(keybuf[1])<<8 | uint16(keybuf[2]) 530 keyoff = 3 531 } 532 533 if explen > 4 || explen == 0 || keybuf[keyoff] == 0 { 534 // Exponent larger than supported by the crypto package, 535 // empty, or contains prohibited leading zero. 536 return nil 537 } 538 539 modoff := keyoff + int(explen) 540 modlen := len(keybuf) - modoff 541 if modlen < 64 || modlen > 512 || keybuf[modoff] == 0 { 542 // Modulus is too small, large, or contains prohibited leading zero. 543 return nil 544 } 545 546 pubkey := new(rsa.PublicKey) 547 548 var expo uint64 549 // The exponent of length explen is between keyoff and modoff. 550 for _, v := range keybuf[keyoff:modoff] { 551 expo <<= 8 552 expo |= uint64(v) 553 } 554 if expo > 1<<31-1 { 555 // Larger exponent than supported by the crypto package. 556 return nil 557 } 558 559 pubkey.E = int(expo) 560 pubkey.N = new(big.Int).SetBytes(keybuf[modoff:]) 561 return pubkey 562} 563 564// publicKeyECDSA returns the Curve public key from the DNSKEY record. 565func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey { 566 keybuf, err := fromBase64([]byte(k.PublicKey)) 567 if err != nil { 568 return nil 569 } 570 pubkey := new(ecdsa.PublicKey) 571 switch k.Algorithm { 572 case ECDSAP256SHA256: 573 pubkey.Curve = elliptic.P256() 574 if len(keybuf) != 64 { 575 // wrongly encoded key 576 return nil 577 } 578 case ECDSAP384SHA384: 579 pubkey.Curve = elliptic.P384() 580 if len(keybuf) != 96 { 581 // Wrongly encoded key 582 return nil 583 } 584 } 585 pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2]) 586 pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:]) 587 return pubkey 588} 589 590func (k *DNSKEY) publicKeyED25519() ed25519.PublicKey { 591 keybuf, err := fromBase64([]byte(k.PublicKey)) 592 if err != nil { 593 return nil 594 } 595 if len(keybuf) != ed25519.PublicKeySize { 596 return nil 597 } 598 return keybuf 599} 600 601type wireSlice [][]byte 602 603func (p wireSlice) Len() int { return len(p) } 604func (p wireSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 605func (p wireSlice) Less(i, j int) bool { 606 _, ioff, _ := UnpackDomainName(p[i], 0) 607 _, joff, _ := UnpackDomainName(p[j], 0) 608 return bytes.Compare(p[i][ioff+10:], p[j][joff+10:]) < 0 609} 610 611// Return the raw signature data. 612func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) { 613 wires := make(wireSlice, len(rrset)) 614 for i, r := range rrset { 615 r1 := r.copy() 616 h := r1.Header() 617 h.Ttl = s.OrigTtl 618 labels := SplitDomainName(h.Name) 619 // 6.2. Canonical RR Form. (4) - wildcards 620 if len(labels) > int(s.Labels) { 621 // Wildcard 622 h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "." 623 } 624 // RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase 625 h.Name = CanonicalName(h.Name) 626 // 6.2. Canonical RR Form. (3) - domain rdata to lowercase. 627 // NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR, 628 // HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, 629 // SRV, DNAME, A6 630 // 631 // RFC 6840 - Clarifications and Implementation Notes for DNS Security (DNSSEC): 632 // Section 6.2 of [RFC4034] also erroneously lists HINFO as a record 633 // that needs conversion to lowercase, and twice at that. Since HINFO 634 // records contain no domain names, they are not subject to case 635 // conversion. 636 switch x := r1.(type) { 637 case *NS: 638 x.Ns = CanonicalName(x.Ns) 639 case *MD: 640 x.Md = CanonicalName(x.Md) 641 case *MF: 642 x.Mf = CanonicalName(x.Mf) 643 case *CNAME: 644 x.Target = CanonicalName(x.Target) 645 case *SOA: 646 x.Ns = CanonicalName(x.Ns) 647 x.Mbox = CanonicalName(x.Mbox) 648 case *MB: 649 x.Mb = CanonicalName(x.Mb) 650 case *MG: 651 x.Mg = CanonicalName(x.Mg) 652 case *MR: 653 x.Mr = CanonicalName(x.Mr) 654 case *PTR: 655 x.Ptr = CanonicalName(x.Ptr) 656 case *MINFO: 657 x.Rmail = CanonicalName(x.Rmail) 658 x.Email = CanonicalName(x.Email) 659 case *MX: 660 x.Mx = CanonicalName(x.Mx) 661 case *RP: 662 x.Mbox = CanonicalName(x.Mbox) 663 x.Txt = CanonicalName(x.Txt) 664 case *AFSDB: 665 x.Hostname = CanonicalName(x.Hostname) 666 case *RT: 667 x.Host = CanonicalName(x.Host) 668 case *SIG: 669 x.SignerName = CanonicalName(x.SignerName) 670 case *PX: 671 x.Map822 = CanonicalName(x.Map822) 672 x.Mapx400 = CanonicalName(x.Mapx400) 673 case *NAPTR: 674 x.Replacement = CanonicalName(x.Replacement) 675 case *KX: 676 x.Exchanger = CanonicalName(x.Exchanger) 677 case *SRV: 678 x.Target = CanonicalName(x.Target) 679 case *DNAME: 680 x.Target = CanonicalName(x.Target) 681 } 682 // 6.2. Canonical RR Form. (5) - origTTL 683 wire := make([]byte, Len(r1)+1) // +1 to be safe(r) 684 off, err1 := PackRR(r1, wire, 0, nil, false) 685 if err1 != nil { 686 return nil, err1 687 } 688 wire = wire[:off] 689 wires[i] = wire 690 } 691 sort.Sort(wires) 692 for i, wire := range wires { 693 if i > 0 && bytes.Equal(wire, wires[i-1]) { 694 continue 695 } 696 buf = append(buf, wire...) 697 } 698 return buf, nil 699} 700 701func packSigWire(sw *rrsigWireFmt, msg []byte) (int, error) { 702 // copied from zmsg.go RRSIG packing 703 off, err := packUint16(sw.TypeCovered, msg, 0) 704 if err != nil { 705 return off, err 706 } 707 off, err = packUint8(sw.Algorithm, msg, off) 708 if err != nil { 709 return off, err 710 } 711 off, err = packUint8(sw.Labels, msg, off) 712 if err != nil { 713 return off, err 714 } 715 off, err = packUint32(sw.OrigTtl, msg, off) 716 if err != nil { 717 return off, err 718 } 719 off, err = packUint32(sw.Expiration, msg, off) 720 if err != nil { 721 return off, err 722 } 723 off, err = packUint32(sw.Inception, msg, off) 724 if err != nil { 725 return off, err 726 } 727 off, err = packUint16(sw.KeyTag, msg, off) 728 if err != nil { 729 return off, err 730 } 731 off, err = PackDomainName(sw.SignerName, msg, off, nil, false) 732 if err != nil { 733 return off, err 734 } 735 return off, nil 736} 737 738func packKeyWire(dw *dnskeyWireFmt, msg []byte) (int, error) { 739 // copied from zmsg.go DNSKEY packing 740 off, err := packUint16(dw.Flags, msg, 0) 741 if err != nil { 742 return off, err 743 } 744 off, err = packUint8(dw.Protocol, msg, off) 745 if err != nil { 746 return off, err 747 } 748 off, err = packUint8(dw.Algorithm, msg, off) 749 if err != nil { 750 return off, err 751 } 752 off, err = packStringBase64(dw.PublicKey, msg, off) 753 if err != nil { 754 return off, err 755 } 756 return off, nil 757} 758