sig0.go (4629B)
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 // Sign signs a dns.Msg. It fills the signature with the appropriate data. 15 // The SIG record should have the SignerName, KeyTag, Algorithm, Inception 16 // and Expiration set. 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 // Write SIG rdata 48 h.Write(buf[len(mbuf)+1+2+2+4+2:]) 49 // Write message 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 // Adjust sig data length 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 // Adjust additional count 69 adc := binary.BigEndian.Uint16(buf[10:]) 70 adc++ 71 binary.BigEndian.PutUint16(buf[10:], adc) 72 return buf, nil 73 } 74 75 // Verify validates the message buf using the key k. 76 // It's assumed that buf is a valid message from which rr was unpacked. 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 // Skip past Type and Class 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 // Skip past Type, Class and TTL 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 // offset should be just prior to SIG 123 bodyend := offset 124 // owner name SHOULD be root 125 _, offset, err = UnpackDomainName(buf, offset) 126 if err != nil { 127 return err 128 } 129 // Skip Type, Class, TTL, RDLen 130 offset += 2 + 2 + 4 + 2 131 sigstart := offset 132 // Skip Type Covered, Algorithm, Labels, Original TTL 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 // Skip key tag 146 offset += 2 147 var signername string 148 signername, offset, err = UnpackDomainName(buf, offset) 149 if err != nil { 150 return err 151 } 152 // If key has come from the DNS name compression might 153 // have mangled the case of the name 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 }