1package dns
2
3import (
4	"crypto"
5	"crypto/dsa"
6	"crypto/ecdsa"
7	"crypto/elliptic"
8	"crypto/rand"
9	"crypto/rsa"
10	"math/big"
11
12	"golang.org/x/crypto/ed25519"
13)
14
15// Generate generates a DNSKEY of the given bit size.
16// The public part is put inside the DNSKEY record.
17// The Algorithm in the key must be set as this will define
18// what kind of DNSKEY will be generated.
19// The ECDSA algorithms imply a fixed keysize, in that case
20// bits should be set to the size of the algorithm.
21func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
22	switch k.Algorithm {
23	case DSA, DSANSEC3SHA1:
24		if bits != 1024 {
25			return nil, ErrKeySize
26		}
27	case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
28		if bits < 512 || bits > 4096 {
29			return nil, ErrKeySize
30		}
31	case RSASHA512:
32		if bits < 1024 || bits > 4096 {
33			return nil, ErrKeySize
34		}
35	case ECDSAP256SHA256:
36		if bits != 256 {
37			return nil, ErrKeySize
38		}
39	case ECDSAP384SHA384:
40		if bits != 384 {
41			return nil, ErrKeySize
42		}
43	case ED25519:
44		if bits != 256 {
45			return nil, ErrKeySize
46		}
47	}
48
49	switch k.Algorithm {
50	case DSA, DSANSEC3SHA1:
51		params := new(dsa.Parameters)
52		if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
53			return nil, err
54		}
55		priv := new(dsa.PrivateKey)
56		priv.PublicKey.Parameters = *params
57		err := dsa.GenerateKey(priv, rand.Reader)
58		if err != nil {
59			return nil, err
60		}
61		k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
62		return priv, nil
63	case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
64		priv, err := rsa.GenerateKey(rand.Reader, bits)
65		if err != nil {
66			return nil, err
67		}
68		k.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
69		return priv, nil
70	case ECDSAP256SHA256, ECDSAP384SHA384:
71		var c elliptic.Curve
72		switch k.Algorithm {
73		case ECDSAP256SHA256:
74			c = elliptic.P256()
75		case ECDSAP384SHA384:
76			c = elliptic.P384()
77		}
78		priv, err := ecdsa.GenerateKey(c, rand.Reader)
79		if err != nil {
80			return nil, err
81		}
82		k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
83		return priv, nil
84	case ED25519:
85		pub, priv, err := ed25519.GenerateKey(rand.Reader)
86		if err != nil {
87			return nil, err
88		}
89		k.setPublicKeyED25519(pub)
90		return priv, nil
91	default:
92		return nil, ErrAlg
93	}
94}
95
96// Set the public key (the value E and N)
97func (k *DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool {
98	if _E == 0 || _N == nil {
99		return false
100	}
101	buf := exponentToBuf(_E)
102	buf = append(buf, _N.Bytes()...)
103	k.PublicKey = toBase64(buf)
104	return true
105}
106
107// Set the public key for Elliptic Curves
108func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool {
109	if _X == nil || _Y == nil {
110		return false
111	}
112	var intlen int
113	switch k.Algorithm {
114	case ECDSAP256SHA256:
115		intlen = 32
116	case ECDSAP384SHA384:
117		intlen = 48
118	}
119	k.PublicKey = toBase64(curveToBuf(_X, _Y, intlen))
120	return true
121}
122
123// Set the public key for DSA
124func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
125	if _Q == nil || _P == nil || _G == nil || _Y == nil {
126		return false
127	}
128	buf := dsaToBuf(_Q, _P, _G, _Y)
129	k.PublicKey = toBase64(buf)
130	return true
131}
132
133// Set the public key for Ed25519
134func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool {
135	if _K == nil {
136		return false
137	}
138	k.PublicKey = toBase64(_K)
139	return true
140}
141
142// Set the public key (the values E and N) for RSA
143// RFC 3110: Section 2. RSA Public KEY Resource Records
144func exponentToBuf(_E int) []byte {
145	var buf []byte
146	i := big.NewInt(int64(_E)).Bytes()
147	if len(i) < 256 {
148		buf = make([]byte, 1, 1+len(i))
149		buf[0] = uint8(len(i))
150	} else {
151		buf = make([]byte, 3, 3+len(i))
152		buf[0] = 0
153		buf[1] = uint8(len(i) >> 8)
154		buf[2] = uint8(len(i))
155	}
156	buf = append(buf, i...)
157	return buf
158}
159
160// Set the public key for X and Y for Curve. The two
161// values are just concatenated.
162func curveToBuf(_X, _Y *big.Int, intlen int) []byte {
163	buf := intToBytes(_X, intlen)
164	buf = append(buf, intToBytes(_Y, intlen)...)
165	return buf
166}
167
168// Set the public key for X and Y for Curve. The two
169// values are just concatenated.
170func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte {
171	t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8)
172	buf := []byte{byte(t)}
173	buf = append(buf, intToBytes(_Q, 20)...)
174	buf = append(buf, intToBytes(_P, 64+t*8)...)
175	buf = append(buf, intToBytes(_G, 64+t*8)...)
176	buf = append(buf, intToBytes(_Y, 64+t*8)...)
177	return buf
178}
179