gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }