sig0.go 4.6 KB

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