Skip to content

Commit 034c247

Browse files
committed
Refactor DNSSEC to use crypto.{PrivateKey,Signer}
This will allow RRSIG.Sign to use generic crypto.Signer implementations. This is a interface breaking change, even if the required changes are most likely just type asserions from crypto.PrivateKey to the underlying type or crypto.Signer.
1 parent c50a9fc commit 034c247

File tree

8 files changed

+230
-267
lines changed

8 files changed

+230
-267
lines changed

dnssec.go

Lines changed: 129 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import (
66
"crypto/dsa"
77
"crypto/ecdsa"
88
"crypto/elliptic"
9-
"crypto/md5"
9+
_ "crypto/md5"
10+
"crypto/rand"
1011
"crypto/rsa"
11-
"crypto/sha1"
12-
"crypto/sha256"
13-
"crypto/sha512"
12+
_ "crypto/sha1"
13+
_ "crypto/sha256"
14+
_ "crypto/sha512"
15+
"encoding/asn1"
1416
"encoding/hex"
15-
"hash"
16-
"io"
1717
"math/big"
1818
"sort"
1919
"strings"
@@ -42,6 +42,38 @@ const (
4242
PRIVATEOID uint8 = 254
4343
)
4444

45+
// Map for algorithm names.
46+
var AlgorithmToString = map[uint8]string{
47+
RSAMD5: "RSAMD5",
48+
DH: "DH",
49+
DSA: "DSA",
50+
RSASHA1: "RSASHA1",
51+
DSANSEC3SHA1: "DSA-NSEC3-SHA1",
52+
RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1",
53+
RSASHA256: "RSASHA256",
54+
RSASHA512: "RSASHA512",
55+
ECCGOST: "ECC-GOST",
56+
ECDSAP256SHA256: "ECDSAP256SHA256",
57+
ECDSAP384SHA384: "ECDSAP384SHA384",
58+
INDIRECT: "INDIRECT",
59+
PRIVATEDNS: "PRIVATEDNS",
60+
PRIVATEOID: "PRIVATEOID",
61+
}
62+
63+
// Map of algorithm strings.
64+
var StringToAlgorithm = reverseInt8(AlgorithmToString)
65+
66+
// Map of algorithm crypto hashes.
67+
var AlgorithmToHash = map[uint8]crypto.Hash{
68+
RSAMD5: crypto.MD5, // Deprecated in RFC 6725
69+
RSASHA1: crypto.SHA1,
70+
RSASHA1NSEC3SHA1: crypto.SHA1,
71+
RSASHA256: crypto.SHA256,
72+
ECDSAP256SHA256: crypto.SHA256,
73+
ECDSAP384SHA384: crypto.SHA384,
74+
RSASHA512: crypto.SHA512,
75+
}
76+
4577
// DNSSEC hashing algorithm codes.
4678
const (
4779
_ uint8 = iota
@@ -52,6 +84,18 @@ const (
5284
SHA512 // Experimental
5385
)
5486

87+
// Map for hash names.
88+
var HashToString = map[uint8]string{
89+
SHA1: "SHA1",
90+
SHA256: "SHA256",
91+
GOST94: "GOST94",
92+
SHA384: "SHA384",
93+
SHA512: "SHA512",
94+
}
95+
96+
// Map of hash strings.
97+
var StringToHash = reverseInt8(HashToString)
98+
5599
// DNSKEY flag values.
56100
const (
57101
SEP = 1
@@ -168,24 +212,23 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
168212
// digest buffer
169213
digest := append(owner, wire...) // another copy
170214

215+
var hash crypto.Hash
171216
switch h {
172217
case SHA1:
173-
s := sha1.New()
174-
io.WriteString(s, string(digest))
175-
ds.Digest = hex.EncodeToString(s.Sum(nil))
218+
hash = crypto.SHA1
176219
case SHA256:
177-
s := sha256.New()
178-
io.WriteString(s, string(digest))
179-
ds.Digest = hex.EncodeToString(s.Sum(nil))
220+
hash = crypto.SHA256
180221
case SHA384:
181-
s := sha512.New384()
182-
io.WriteString(s, string(digest))
183-
ds.Digest = hex.EncodeToString(s.Sum(nil))
184-
case GOST94:
185-
/* I have no clue */
222+
hash = crypto.SHA384
223+
case SHA512:
224+
hash = crypto.SHA512
186225
default:
187226
return nil
188227
}
228+
229+
s := hash.New()
230+
s.Write(digest)
231+
ds.Digest = hex.EncodeToString(s.Sum(nil))
189232
return ds
190233
}
191234

@@ -212,7 +255,7 @@ func (d *DS) ToCDS() *CDS {
212255
// There is no check if RRSet is a proper (RFC 2181) RRSet.
213256
// If OrigTTL is non zero, it is used as-is, otherwise the TTL of the RRset
214257
// is used as the OrigTTL.
215-
func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
258+
func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
216259
if k == nil {
217260
return ErrPrivKey
218261
}
@@ -258,39 +301,66 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
258301
}
259302
signdata = append(signdata, wire...)
260303

261-
var h hash.Hash
262-
switch rr.Algorithm {
263-
case DSA, DSANSEC3SHA1:
264-
// TODO: this seems bugged, will panic
265-
case RSASHA1, RSASHA1NSEC3SHA1:
266-
h = sha1.New()
267-
case RSASHA256, ECDSAP256SHA256:
268-
h = sha256.New()
269-
case ECDSAP384SHA384:
270-
h = sha512.New384()
271-
case RSASHA512:
272-
h = sha512.New()
273-
case RSAMD5:
274-
fallthrough // Deprecated in RFC 6725
275-
default:
304+
hash, ok := AlgorithmToHash[rr.Algorithm]
305+
if !ok {
276306
return ErrAlg
277307
}
278308

279-
_, err = h.Write(signdata)
280-
if err != nil {
281-
return err
282-
}
283-
sighash := h.Sum(nil)
309+
h := hash.New()
310+
h.Write(signdata)
284311

285-
signature, err := k.Sign(sighash, rr.Algorithm)
312+
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
286313
if err != nil {
287314
return err
288315
}
316+
289317
rr.Signature = toBase64(signature)
290318

291319
return nil
292320
}
293321

322+
func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
323+
signature, err := k.Sign(rand.Reader, hashed, hash)
324+
if err != nil {
325+
return nil, err
326+
}
327+
328+
switch alg {
329+
case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
330+
return signature, nil
331+
332+
case ECDSAP256SHA256, ECDSAP384SHA384:
333+
ecdsaSignature := &struct {
334+
R, S *big.Int
335+
}{}
336+
if _, err := asn1.Unmarshal(signature, ecdsaSignature); err != nil {
337+
return nil, err
338+
}
339+
340+
var intlen int
341+
switch alg {
342+
case ECDSAP256SHA256:
343+
intlen = 32
344+
case ECDSAP384SHA384:
345+
intlen = 48
346+
}
347+
348+
signature := intToBytes(ecdsaSignature.R, intlen)
349+
signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
350+
return signature, nil
351+
352+
// There is no defined interface for what a DSA backed crypto.Signer returns
353+
case DSA, DSANSEC3SHA1:
354+
// t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
355+
// signature := []byte{byte(t)}
356+
// signature = append(signature, intToBytes(r1, 20)...)
357+
// signature = append(signature, intToBytes(s1, 20)...)
358+
// rr.Signature = signature
359+
}
360+
361+
return nil, ErrAlg
362+
}
363+
294364
// Verify validates an RRSet with the signature and key. This is only the
295365
// cryptographic test, the signature validity period must be checked separately.
296366
// This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.
@@ -355,59 +425,43 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
355425
// remove the domain name and assume its our
356426
}
357427

428+
hash, ok := AlgorithmToHash[rr.Algorithm]
429+
if !ok {
430+
return ErrAlg
431+
}
432+
358433
switch rr.Algorithm {
359434
case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, RSAMD5:
360435
// TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere??
361436
pubkey := k.publicKeyRSA() // Get the key
362437
if pubkey == nil {
363438
return ErrKey
364439
}
365-
// Setup the hash as defined for this alg.
366-
var h hash.Hash
367-
var ch crypto.Hash
368-
switch rr.Algorithm {
369-
case RSAMD5:
370-
h = md5.New()
371-
ch = crypto.MD5
372-
case RSASHA1, RSASHA1NSEC3SHA1:
373-
h = sha1.New()
374-
ch = crypto.SHA1
375-
case RSASHA256:
376-
h = sha256.New()
377-
ch = crypto.SHA256
378-
case RSASHA512:
379-
h = sha512.New()
380-
ch = crypto.SHA512
381-
}
382-
io.WriteString(h, string(signeddata))
383-
sighash := h.Sum(nil)
384-
return rsa.VerifyPKCS1v15(pubkey, ch, sighash, sigbuf)
440+
441+
h := hash.New()
442+
h.Write(signeddata)
443+
return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
444+
385445
case ECDSAP256SHA256, ECDSAP384SHA384:
386446
pubkey := k.publicKeyECDSA()
387447
if pubkey == nil {
388448
return ErrKey
389449
}
390-
var h hash.Hash
391-
switch rr.Algorithm {
392-
case ECDSAP256SHA256:
393-
h = sha256.New()
394-
case ECDSAP384SHA384:
395-
h = sha512.New384()
396-
}
397-
io.WriteString(h, string(signeddata))
398-
sighash := h.Sum(nil)
450+
399451
// Split sigbuf into the r and s coordinates
400-
r := big.NewInt(0)
401-
r.SetBytes(sigbuf[:len(sigbuf)/2])
402-
s := big.NewInt(0)
403-
s.SetBytes(sigbuf[len(sigbuf)/2:])
404-
if ecdsa.Verify(pubkey, sighash, r, s) {
452+
r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2])
453+
s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:])
454+
455+
h := hash.New()
456+
h.Write(signeddata)
457+
if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
405458
return nil
406459
}
407460
return ErrSig
461+
462+
default:
463+
return ErrAlg
408464
}
409-
// Unknown alg
410-
return ErrAlg
411465
}
412466

413467
// ValidityPeriod uses RFC1982 serial arithmetic to calculate
@@ -603,36 +657,3 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
603657
}
604658
return buf, nil
605659
}
606-
607-
// Map for algorithm names.
608-
var AlgorithmToString = map[uint8]string{
609-
RSAMD5: "RSAMD5",
610-
DH: "DH",
611-
DSA: "DSA",
612-
RSASHA1: "RSASHA1",
613-
DSANSEC3SHA1: "DSA-NSEC3-SHA1",
614-
RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1",
615-
RSASHA256: "RSASHA256",
616-
RSASHA512: "RSASHA512",
617-
ECCGOST: "ECC-GOST",
618-
ECDSAP256SHA256: "ECDSAP256SHA256",
619-
ECDSAP384SHA384: "ECDSAP384SHA384",
620-
INDIRECT: "INDIRECT",
621-
PRIVATEDNS: "PRIVATEDNS",
622-
PRIVATEOID: "PRIVATEOID",
623-
}
624-
625-
// Map of algorithm strings.
626-
var StringToAlgorithm = reverseInt8(AlgorithmToString)
627-
628-
// Map for hash names.
629-
var HashToString = map[uint8]string{
630-
SHA1: "SHA1",
631-
SHA256: "SHA256",
632-
GOST94: "GOST94",
633-
SHA384: "SHA384",
634-
SHA512: "SHA512",
635-
}
636-
637-
// Map of hash strings.
638-
var StringToHash = reverseInt8(HashToString)

dnssec_keygen.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dns
22

33
import (
4+
"crypto"
45
"crypto/dsa"
56
"crypto/ecdsa"
67
"crypto/elliptic"
@@ -15,7 +16,7 @@ import (
1516
// what kind of DNSKEY will be generated.
1617
// The ECDSA algorithms imply a fixed keysize, in that case
1718
// bits should be set to the size of the algorithm.
18-
func (k *DNSKEY) Generate(bits int) (PrivateKey, error) {
19+
func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
1920
switch k.Algorithm {
2021
case DSA, DSANSEC3SHA1:
2122
if bits != 1024 {
@@ -52,14 +53,14 @@ func (k *DNSKEY) Generate(bits int) (PrivateKey, error) {
5253
return nil, err
5354
}
5455
k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
55-
return (*DSAPrivateKey)(priv), nil
56+
return priv, nil
5657
case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
5758
priv, err := rsa.GenerateKey(rand.Reader, bits)
5859
if err != nil {
5960
return nil, err
6061
}
6162
k.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
62-
return (*RSAPrivateKey)(priv), nil
63+
return priv, nil
6364
case ECDSAP256SHA256, ECDSAP384SHA384:
6465
var c elliptic.Curve
6566
switch k.Algorithm {
@@ -73,7 +74,7 @@ func (k *DNSKEY) Generate(bits int) (PrivateKey, error) {
7374
return nil, err
7475
}
7576
k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
76-
return (*ECDSAPrivateKey)(priv), nil
77+
return priv, nil
7778
default:
7879
return nil, ErrAlg
7980
}

0 commit comments

Comments
 (0)