Source file src/pkg/crypto/tls/key_agreement.go
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package tls
6
7 import (
8 "crypto"
9 "crypto/elliptic"
10 "crypto/md5"
11 "crypto/rsa"
12 "crypto/sha1"
13 "crypto/x509"
14 "errors"
15 "io"
16 "math/big"
17 )
18
19 // rsaKeyAgreement implements the standard TLS key agreement where the client
20 // encrypts the pre-master secret to the server's public key.
21 type rsaKeyAgreement struct{}
22
23 func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
24 return nil, nil
25 }
26
27 func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
28 preMasterSecret := make([]byte, 48)
29 _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
30 if err != nil {
31 return nil, err
32 }
33
34 if len(ckx.ciphertext) < 2 {
35 return nil, errors.New("bad ClientKeyExchange")
36 }
37
38 ciphertext := ckx.ciphertext
39 if version != versionSSL30 {
40 ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
41 if ciphertextLen != len(ckx.ciphertext)-2 {
42 return nil, errors.New("bad ClientKeyExchange")
43 }
44 ciphertext = ckx.ciphertext[2:]
45 }
46
47 err = rsa.DecryptPKCS1v15SessionKey(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
48 if err != nil {
49 return nil, err
50 }
51 // We don't check the version number in the premaster secret. For one,
52 // by checking it, we would leak information about the validity of the
53 // encrypted pre-master secret. Secondly, it provides only a small
54 // benefit against a downgrade attack and some implementations send the
55 // wrong version anyway. See the discussion at the end of section
56 // 7.4.7.1 of RFC 4346.
57 return preMasterSecret, nil
58 }
59
60 func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
61 return errors.New("unexpected ServerKeyExchange")
62 }
63
64 func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
65 preMasterSecret := make([]byte, 48)
66 preMasterSecret[0] = byte(clientHello.vers >> 8)
67 preMasterSecret[1] = byte(clientHello.vers)
68 _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
69 if err != nil {
70 return nil, nil, err
71 }
72
73 encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
74 if err != nil {
75 return nil, nil, err
76 }
77 ckx := new(clientKeyExchangeMsg)
78 ckx.ciphertext = make([]byte, len(encrypted)+2)
79 ckx.ciphertext[0] = byte(len(encrypted) >> 8)
80 ckx.ciphertext[1] = byte(len(encrypted))
81 copy(ckx.ciphertext[2:], encrypted)
82 return preMasterSecret, ckx, nil
83 }
84
85 // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
86 // concatenation of an MD5 and SHA1 hash.
87 func md5SHA1Hash(slices ...[]byte) []byte {
88 md5sha1 := make([]byte, md5.Size+sha1.Size)
89 hmd5 := md5.New()
90 for _, slice := range slices {
91 hmd5.Write(slice)
92 }
93 copy(md5sha1, hmd5.Sum(nil))
94
95 hsha1 := sha1.New()
96 for _, slice := range slices {
97 hsha1.Write(slice)
98 }
99 copy(md5sha1[md5.Size:], hsha1.Sum(nil))
100 return md5sha1
101 }
102
103 // ecdheRSAKeyAgreement implements a TLS key agreement where the server
104 // generates a ephemeral EC public/private key pair and signs it. The
105 // pre-master secret is then calculated using ECDH.
106 type ecdheRSAKeyAgreement struct {
107 privateKey []byte
108 curve elliptic.Curve
109 x, y *big.Int
110 }
111
112 func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
113 var curveid uint16
114
115 Curve:
116 for _, c := range clientHello.supportedCurves {
117 switch c {
118 case curveP256:
119 ka.curve = elliptic.P256()
120 curveid = c
121 break Curve
122 case curveP384:
123 ka.curve = elliptic.P384()
124 curveid = c
125 break Curve
126 case curveP521:
127 ka.curve = elliptic.P521()
128 curveid = c
129 break Curve
130 }
131 }
132
133 if curveid == 0 {
134 return nil, errors.New("tls: no supported elliptic curves offered")
135 }
136
137 var x, y *big.Int
138 var err error
139 ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
140 if err != nil {
141 return nil, err
142 }
143 ecdhePublic := elliptic.Marshal(ka.curve, x, y)
144
145 // http://tools.ietf.org/html/rfc4492#section-5.4
146 serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
147 serverECDHParams[0] = 3 // named curve
148 serverECDHParams[1] = byte(curveid >> 8)
149 serverECDHParams[2] = byte(curveid)
150 serverECDHParams[3] = byte(len(ecdhePublic))
151 copy(serverECDHParams[4:], ecdhePublic)
152
153 md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
154 sig, err := rsa.SignPKCS1v15(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, md5sha1)
155 if err != nil {
156 return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
157 }
158
159 skx := new(serverKeyExchangeMsg)
160 skx.key = make([]byte, len(serverECDHParams)+2+len(sig))
161 copy(skx.key, serverECDHParams)
162 k := skx.key[len(serverECDHParams):]
163 k[0] = byte(len(sig) >> 8)
164 k[1] = byte(len(sig))
165 copy(k[2:], sig)
166
167 return skx, nil
168 }
169
170 func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
171 if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
172 return nil, errors.New("bad ClientKeyExchange")
173 }
174 x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
175 if x == nil {
176 return nil, errors.New("bad ClientKeyExchange")
177 }
178 x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
179 preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
180 xBytes := x.Bytes()
181 copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
182
183 return preMasterSecret, nil
184 }
185
186 var errServerKeyExchange = errors.New("invalid ServerKeyExchange")
187
188 func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
189 if len(skx.key) < 4 {
190 return errServerKeyExchange
191 }
192 if skx.key[0] != 3 { // named curve
193 return errors.New("server selected unsupported curve")
194 }
195 curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2])
196
197 switch curveid {
198 case curveP256:
199 ka.curve = elliptic.P256()
200 case curveP384:
201 ka.curve = elliptic.P384()
202 case curveP521:
203 ka.curve = elliptic.P521()
204 default:
205 return errors.New("server selected unsupported curve")
206 }
207
208 publicLen := int(skx.key[3])
209 if publicLen+4 > len(skx.key) {
210 return errServerKeyExchange
211 }
212 ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
213 if ka.x == nil {
214 return errServerKeyExchange
215 }
216 serverECDHParams := skx.key[:4+publicLen]
217
218 sig := skx.key[4+publicLen:]
219 if len(sig) < 2 {
220 return errServerKeyExchange
221 }
222 sigLen := int(sig[0])<<8 | int(sig[1])
223 if sigLen+2 != len(sig) {
224 return errServerKeyExchange
225 }
226 sig = sig[2:]
227
228 md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams)
229 return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), crypto.MD5SHA1, md5sha1, sig)
230 }
231
232 func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
233 if ka.curve == nil {
234 return nil, nil, errors.New("missing ServerKeyExchange message")
235 }
236 priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
237 if err != nil {
238 return nil, nil, err
239 }
240 x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
241 preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
242 xBytes := x.Bytes()
243 copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
244
245 serialized := elliptic.Marshal(ka.curve, mx, my)
246
247 ckx := new(clientKeyExchangeMsg)
248 ckx.ciphertext = make([]byte, 1+len(serialized))
249 ckx.ciphertext[0] = byte(len(serialized))
250 copy(ckx.ciphertext[1:], serialized)
251
252 return preMasterSecret, ckx, nil
253 }