SIG0 misc - doc, bounds checking, refactor tests
* expand documentation a little and tweak comments * add bounds checking in Verify() * refactor tests
This commit is contained in:
parent
deb8fe381f
commit
9862d7044a
43
sig0.go
43
sig0.go
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// SIG(0)
|
||||
// SIG0
|
||||
//
|
||||
// From RFC 2931:
|
||||
//
|
||||
|
@ -10,6 +10,10 @@
|
|||
// ... protection for glue records, DNS requests, protection for message headers
|
||||
// on requests and responses, and protection of the overall integrity of a response.
|
||||
//
|
||||
// Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and
|
||||
// RSASHA512.
|
||||
//
|
||||
// Signing subsequent messages in multi-message sessions is not implemented.
|
||||
//
|
||||
package dns
|
||||
|
||||
|
@ -19,7 +23,6 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -163,29 +166,34 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||
adc, offset := unpackUint16(buf, 10)
|
||||
var err error
|
||||
for i := uint16(0); i < qdc && offset < buflen; i++ {
|
||||
// decode a name
|
||||
_, offset, err = UnpackDomainName(buf, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// skip past Type and Class
|
||||
// Skip past Type and Class
|
||||
offset += 2 + 2
|
||||
}
|
||||
for i := uint16(1); i < anc+auc+adc && offset < buflen; i++ {
|
||||
// decode a name
|
||||
_, offset, err = UnpackDomainName(buf, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// skip past Type, Class and TTL
|
||||
// Skip past Type, Class and TTL
|
||||
offset += 2 + 2 + 4
|
||||
if offset+1 >= buflen {
|
||||
continue
|
||||
}
|
||||
var rdlen uint16
|
||||
rdlen, offset = unpackUint16(buf, offset)
|
||||
offset += int(rdlen)
|
||||
}
|
||||
if offset >= buflen {
|
||||
return &Error{err: "overflowing unpacking signed message"}
|
||||
}
|
||||
|
||||
// offset should be just prior to SIG
|
||||
bodyend := offset
|
||||
// Owner name SHOULD be root
|
||||
// owner name SHOULD be root
|
||||
_, offset, err = UnpackDomainName(buf, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -193,20 +201,21 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||
// Skip Type, Class, TTL, RDLen
|
||||
offset += 2 + 2 + 4 + 2
|
||||
sigstart := offset
|
||||
offset += 2 + 1 + 1 + 4 // skip Type Covered, Algorithm, Labels, Original TTL
|
||||
// TODO: This should be moved out and used elsewhere
|
||||
unpackUint32 := func(buf []byte, off int) (uint32, int) {
|
||||
r := uint32(buf[off])<<24 | uint32(buf[off+1])<<16 | uint32(buf[off+2])<<8 | uint32(buf[off+3])
|
||||
return r, off + 4
|
||||
// Skip Type Covered, Algorithm, Labels, Original TTL
|
||||
offset += 2 + 1 + 1 + 4
|
||||
if offset+4+4 >= buflen {
|
||||
return &Error{err: "overflow unpacking signed message"}
|
||||
}
|
||||
var expire, incept uint32
|
||||
expire, offset = unpackUint32(buf, offset)
|
||||
incept, offset = unpackUint32(buf, offset)
|
||||
expire := uint32(buf[offset])<<24 | uint32(buf[offset+1])<<16 | uint32(buf[offset+2])<<8 | uint32(buf[offset+3])
|
||||
offset += 4
|
||||
incept := uint32(buf[offset])<<24 | uint32(buf[offset+1])<<16 | uint32(buf[offset+2])<<8 | uint32(buf[offset+3])
|
||||
offset += 4
|
||||
now := uint32(time.Now().Unix())
|
||||
if now < incept || now > expire {
|
||||
return ErrTime
|
||||
}
|
||||
offset += 2 // skip key tag
|
||||
// Skip key tag
|
||||
offset += 2
|
||||
var signername string
|
||||
signername, offset, err = UnpackDomainName(buf, offset)
|
||||
if err != nil {
|
||||
|
@ -215,7 +224,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||
// If key has come from the DNS name compression might
|
||||
// have mangled the case of the name
|
||||
if strings.ToLower(signername) != strings.ToLower(k.Header().Name) {
|
||||
return fmt.Errorf("Signer name doesn't match key name")
|
||||
return &Error{err: "signer name doesn't match key name"}
|
||||
}
|
||||
sigend := offset
|
||||
hasher.Write(buf[sigstart:sigend])
|
||||
|
|
52
sig0_test.go
52
sig0_test.go
|
@ -6,51 +6,39 @@ import (
|
|||
)
|
||||
|
||||
func TestSIG0(t *testing.T) {
|
||||
keys := []struct {
|
||||
alg uint8
|
||||
rr *KEY
|
||||
pk PrivateKey
|
||||
}{{alg: DSA}, {alg: ECDSAP256SHA256}, {alg: ECDSAP384SHA384}, {alg: RSASHA1}, {alg: RSASHA256}, {alg: RSASHA512}}
|
||||
for i := range keys {
|
||||
keys[i].rr = new(KEY)
|
||||
keys[i].rr.Hdr.Name = AlgorithmToString[keys[i].alg] + "."
|
||||
keys[i].rr.Hdr.Rrtype = TypeKEY
|
||||
keys[i].rr.Hdr.Class = ClassINET
|
||||
keys[i].rr.Algorithm = keys[i].alg
|
||||
m := new(Msg)
|
||||
m.SetQuestion("example.org.", TypeSOA)
|
||||
for _, alg := range []uint8{DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256, RSASHA512} {
|
||||
algstr := AlgorithmToString[alg]
|
||||
keyrr := new(KEY)
|
||||
keyrr.Hdr.Name = algstr + "."
|
||||
keyrr.Hdr.Rrtype = TypeKEY
|
||||
keyrr.Hdr.Class = ClassINET
|
||||
keyrr.Algorithm = alg
|
||||
keysize := 1024
|
||||
switch keys[i].alg {
|
||||
switch alg {
|
||||
case ECDSAP256SHA256:
|
||||
keysize = 256
|
||||
case ECDSAP384SHA384:
|
||||
keysize = 384
|
||||
}
|
||||
pk, err := keys[i].rr.Generate(keysize)
|
||||
pk, err := keyrr.Generate(keysize)
|
||||
if err != nil {
|
||||
t.Logf("Failed to generate key for “%s”: %v", AlgorithmToString[keys[i].alg], err)
|
||||
t.Logf("Failed to generate key for “%s”: %v", algstr, err)
|
||||
t.Fail()
|
||||
continue
|
||||
}
|
||||
keys[i].pk = pk
|
||||
}
|
||||
|
||||
m := new(Msg)
|
||||
m.SetQuestion("example.org.", TypeSOA)
|
||||
for _, key := range keys {
|
||||
if key.pk == nil {
|
||||
continue
|
||||
}
|
||||
algstr := AlgorithmToString[key.alg]
|
||||
now := uint32(time.Now().Unix())
|
||||
sigrr := new(SIG)
|
||||
sigrr.Hdr.Name = "."
|
||||
sigrr.Hdr.Rrtype = TypeSIG
|
||||
sigrr.Hdr.Class = ClassANY
|
||||
sigrr.Algorithm = key.rr.Algorithm
|
||||
sigrr.Algorithm = alg
|
||||
sigrr.Expiration = now + 300
|
||||
sigrr.Inception = now - 300
|
||||
sigrr.KeyTag = key.rr.KeyTag()
|
||||
sigrr.SignerName = key.rr.Hdr.Name
|
||||
mb, err := sigrr.Sign(key.pk, m)
|
||||
sigrr.KeyTag = keyrr.KeyTag()
|
||||
sigrr.SignerName = keyrr.Hdr.Name
|
||||
mb, err := sigrr.Sign(pk, m)
|
||||
if err != nil {
|
||||
t.Logf("Failed to sign message using “%s”: %v", algstr, err)
|
||||
t.Fail()
|
||||
|
@ -81,22 +69,22 @@ func TestSIG0(t *testing.T) {
|
|||
if rr == sigrrwire {
|
||||
id = "sigrrwire"
|
||||
}
|
||||
if err := rr.Verify(key.rr, mb); err != nil {
|
||||
if err := rr.Verify(keyrr, mb); err != nil {
|
||||
t.Logf("Failed to verify “%s” signed SIG(%s): %v", algstr, id, err)
|
||||
t.Fail()
|
||||
continue
|
||||
}
|
||||
}
|
||||
mb[13]++
|
||||
if err := sigrr.Verify(key.rr, mb); err == nil {
|
||||
if err := sigrr.Verify(keyrr, mb); err == nil {
|
||||
t.Logf("Verify succeeded on an altered message using “%s”", algstr)
|
||||
t.Fail()
|
||||
continue
|
||||
}
|
||||
sigrr.Expiration = 2
|
||||
sigrr.Inception = 1
|
||||
mb, _ = sigrr.Sign(key.pk, m)
|
||||
if err := sigrr.Verify(key.rr, mb); err == nil {
|
||||
mb, _ = sigrr.Sign(pk, m)
|
||||
if err := sigrr.Verify(keyrr, mb); err == nil {
|
||||
t.Logf("Verify succeeded on an expired message using “%s”", algstr)
|
||||
t.Fail()
|
||||
continue
|
||||
|
|
Loading…
Reference in New Issue