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