sig0.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. package dns
  2. import (
  3. "crypto"
  4. "crypto/ecdsa"
  5. "crypto/ed25519"
  6. "crypto/rsa"
  7. "encoding/binary"
  8. "math/big"
  9. "strings"
  10. "time"
  11. )
  12. // Sign signs a dns.Msg. It fills the signature with the appropriate data.
  13. // The SIG record should have the SignerName, KeyTag, Algorithm, Inception
  14. // and Expiration set.
  15. func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
  16. if k == nil {
  17. return nil, ErrPrivKey
  18. }
  19. if rr.KeyTag == 0 || rr.SignerName == "" || rr.Algorithm == 0 {
  20. return nil, ErrKey
  21. }
  22. rr.Hdr = RR_Header{Name: ".", Rrtype: TypeSIG, Class: ClassANY, Ttl: 0}
  23. rr.OrigTtl, rr.TypeCovered, rr.Labels = 0, 0, 0
  24. buf := make([]byte, m.Len()+Len(rr))
  25. mbuf, err := m.PackBuffer(buf)
  26. if err != nil {
  27. return nil, err
  28. }
  29. if &buf[0] != &mbuf[0] {
  30. return nil, ErrBuf
  31. }
  32. off, err := PackRR(rr, buf, len(mbuf), nil, false)
  33. if err != nil {
  34. return nil, err
  35. }
  36. buf = buf[:off:cap(buf)]
  37. h, cryptohash, err := hashFromAlgorithm(rr.Algorithm)
  38. if err != nil {
  39. return nil, err
  40. }
  41. // Write SIG rdata
  42. h.Write(buf[len(mbuf)+1+2+2+4+2:])
  43. // Write message
  44. h.Write(buf[:len(mbuf)])
  45. signature, err := sign(k, h.Sum(nil), cryptohash, rr.Algorithm)
  46. if err != nil {
  47. return nil, err
  48. }
  49. rr.Signature = toBase64(signature)
  50. buf = append(buf, signature...)
  51. if len(buf) > int(^uint16(0)) {
  52. return nil, ErrBuf
  53. }
  54. // Adjust sig data length
  55. rdoff := len(mbuf) + 1 + 2 + 2 + 4
  56. rdlen := binary.BigEndian.Uint16(buf[rdoff:])
  57. rdlen += uint16(len(signature))
  58. binary.BigEndian.PutUint16(buf[rdoff:], rdlen)
  59. // Adjust additional count
  60. adc := binary.BigEndian.Uint16(buf[10:])
  61. adc++
  62. binary.BigEndian.PutUint16(buf[10:], adc)
  63. return buf, nil
  64. }
  65. // Verify validates the message buf using the key k.
  66. // It's assumed that buf is a valid message from which rr was unpacked.
  67. func (rr *SIG) Verify(k *KEY, buf []byte) error {
  68. if k == nil {
  69. return ErrKey
  70. }
  71. if rr.KeyTag == 0 || rr.SignerName == "" || rr.Algorithm == 0 {
  72. return ErrKey
  73. }
  74. h, cryptohash, err := hashFromAlgorithm(rr.Algorithm)
  75. if err != nil {
  76. return err
  77. }
  78. buflen := len(buf)
  79. qdc := binary.BigEndian.Uint16(buf[4:])
  80. anc := binary.BigEndian.Uint16(buf[6:])
  81. auc := binary.BigEndian.Uint16(buf[8:])
  82. adc := binary.BigEndian.Uint16(buf[10:])
  83. offset := headerSize
  84. for i := uint16(0); i < qdc && offset < buflen; i++ {
  85. _, offset, err = UnpackDomainName(buf, offset)
  86. if err != nil {
  87. return err
  88. }
  89. // Skip past Type and Class
  90. offset += 2 + 2
  91. }
  92. for i := uint16(1); i < anc+auc+adc && offset < buflen; i++ {
  93. _, offset, err = UnpackDomainName(buf, offset)
  94. if err != nil {
  95. return err
  96. }
  97. // Skip past Type, Class and TTL
  98. offset += 2 + 2 + 4
  99. if offset+1 >= buflen {
  100. continue
  101. }
  102. rdlen := binary.BigEndian.Uint16(buf[offset:])
  103. offset += 2
  104. offset += int(rdlen)
  105. }
  106. if offset >= buflen {
  107. return &Error{err: "overflowing unpacking signed message"}
  108. }
  109. // offset should be just prior to SIG
  110. bodyend := offset
  111. // owner name SHOULD be root
  112. _, offset, err = UnpackDomainName(buf, offset)
  113. if err != nil {
  114. return err
  115. }
  116. // Skip Type, Class, TTL, RDLen
  117. offset += 2 + 2 + 4 + 2
  118. sigstart := offset
  119. // Skip Type Covered, Algorithm, Labels, Original TTL
  120. offset += 2 + 1 + 1 + 4
  121. if offset+4+4 >= buflen {
  122. return &Error{err: "overflow unpacking signed message"}
  123. }
  124. expire := binary.BigEndian.Uint32(buf[offset:])
  125. offset += 4
  126. incept := binary.BigEndian.Uint32(buf[offset:])
  127. offset += 4
  128. now := uint32(time.Now().Unix())
  129. if now < incept || now > expire {
  130. return ErrTime
  131. }
  132. // Skip key tag
  133. offset += 2
  134. var signername string
  135. signername, offset, err = UnpackDomainName(buf, offset)
  136. if err != nil {
  137. return err
  138. }
  139. // If key has come from the DNS name compression might
  140. // have mangled the case of the name
  141. if !strings.EqualFold(signername, k.Header().Name) {
  142. return &Error{err: "signer name doesn't match key name"}
  143. }
  144. sigend := offset
  145. h.Write(buf[sigstart:sigend])
  146. h.Write(buf[:10])
  147. h.Write([]byte{
  148. byte((adc - 1) << 8),
  149. byte(adc - 1),
  150. })
  151. h.Write(buf[12:bodyend])
  152. hashed := h.Sum(nil)
  153. sig := buf[sigend:]
  154. switch k.Algorithm {
  155. case RSASHA1, RSASHA256, RSASHA512:
  156. pk := k.publicKeyRSA()
  157. if pk != nil {
  158. return rsa.VerifyPKCS1v15(pk, cryptohash, hashed, sig)
  159. }
  160. case ECDSAP256SHA256, ECDSAP384SHA384:
  161. pk := k.publicKeyECDSA()
  162. r := new(big.Int).SetBytes(sig[:len(sig)/2])
  163. s := new(big.Int).SetBytes(sig[len(sig)/2:])
  164. if pk != nil {
  165. if ecdsa.Verify(pk, hashed, r, s) {
  166. return nil
  167. }
  168. return ErrSig
  169. }
  170. case ED25519:
  171. pk := k.publicKeyED25519()
  172. if pk != nil {
  173. if ed25519.Verify(pk, hashed, sig) {
  174. return nil
  175. }
  176. return ErrSig
  177. }
  178. }
  179. return ErrKeyAlg
  180. }