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