OSDN Git Service

8edbb11900c5f1dfa2b8f2db9b08c67d46cafc2e
[pf3gnuchains/gcc-fork.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.ErrorString("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.ErrorString("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.ErrorString("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
82 // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
83 // concatenation of an MD5 and SHA1 hash.
84 func md5SHA1Hash(slices ...[]byte) []byte {
85         md5sha1 := make([]byte, md5.Size+sha1.Size)
86         hmd5 := md5.New()
87         for _, slice := range slices {
88                 hmd5.Write(slice)
89         }
90         copy(md5sha1, hmd5.Sum())
91
92         hsha1 := sha1.New()
93         for _, slice := range slices {
94                 hsha1.Write(slice)
95         }
96         copy(md5sha1[md5.Size:], hsha1.Sum())
97         return md5sha1
98 }
99
100 // ecdheRSAKeyAgreement implements a TLS key agreement where the server
101 // generates a ephemeral EC public/private key pair and signs it. The
102 // pre-master secret is then calculated using ECDH.
103 type ecdheRSAKeyAgreement struct {
104         privateKey []byte
105         curve      *elliptic.Curve
106         x, y       *big.Int
107 }
108
109 func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, os.Error) {
110         var curveid uint16
111
112 Curve:
113         for _, c := range clientHello.supportedCurves {
114                 switch c {
115                 case curveP256:
116                         ka.curve = elliptic.P256()
117                         curveid = c
118                         break Curve
119                 case curveP384:
120                         ka.curve = elliptic.P384()
121                         curveid = c
122                         break Curve
123                 case curveP521:
124                         ka.curve = elliptic.P521()
125                         curveid = c
126                         break Curve
127                 }
128         }
129
130         var x, y *big.Int
131         var err os.Error
132         ka.privateKey, x, y, err = ka.curve.GenerateKey(config.rand())
133         if err != nil {
134                 return nil, err
135         }
136         ecdhePublic := ka.curve.Marshal(x, y)
137
138         // http://tools.ietf.org/html/rfc4492#section-5.4
139         serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
140         serverECDHParams[0] = 3 // named curve
141         serverECDHParams[1] = byte(curveid >> 8)
142         serverECDHParams[2] = byte(curveid)
143         serverECDHParams[3] = byte(len(ecdhePublic))
144         copy(serverECDHParams[4:], ecdhePublic)
145
146         md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
147         sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey, crypto.MD5SHA1, md5sha1)
148         if err != nil {
149                 return nil, os.ErrorString("failed to sign ECDHE parameters: " + err.String())
150         }
151
152         skx := new(serverKeyExchangeMsg)
153         skx.key = make([]byte, len(serverECDHParams)+2+len(sig))
154         copy(skx.key, serverECDHParams)
155         k := skx.key[len(serverECDHParams):]
156         k[0] = byte(len(sig) >> 8)
157         k[1] = byte(len(sig))
158         copy(k[2:], sig)
159
160         return skx, nil
161 }
162
163 func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg) ([]byte, os.Error) {
164         if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
165                 return nil, os.ErrorString("bad ClientKeyExchange")
166         }
167         x, y := ka.curve.Unmarshal(ckx.ciphertext[1:])
168         if x == nil {
169                 return nil, os.ErrorString("bad ClientKeyExchange")
170         }
171         x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
172         preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3)
173         xBytes := x.Bytes()
174         copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
175
176         return preMasterSecret, nil
177 }
178
179 func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) os.Error {
180         if len(skx.key) < 4 {
181                 goto Error
182         }
183         if skx.key[0] != 3 { // named curve
184                 return os.ErrorString("server selected unsupported curve")
185         }
186         curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2])
187
188         switch curveid {
189         case curveP256:
190                 ka.curve = elliptic.P256()
191         case curveP384:
192                 ka.curve = elliptic.P384()
193         case curveP521:
194                 ka.curve = elliptic.P521()
195         default:
196                 return os.ErrorString("server selected unsupported curve")
197         }
198
199         publicLen := int(skx.key[3])
200         if publicLen+4 > len(skx.key) {
201                 goto Error
202         }
203         ka.x, ka.y = ka.curve.Unmarshal(skx.key[4 : 4+publicLen])
204         if ka.x == nil {
205                 goto Error
206         }
207         serverECDHParams := skx.key[:4+publicLen]
208
209         sig := skx.key[4+publicLen:]
210         if len(sig) < 2 {
211                 goto Error
212         }
213         sigLen := int(sig[0])<<8 | int(sig[1])
214         if sigLen+2 != len(sig) {
215                 goto Error
216         }
217         sig = sig[2:]
218
219         md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams)
220         return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), crypto.MD5SHA1, md5sha1, sig)
221
222 Error:
223         return os.ErrorString("invalid ServerKeyExchange")
224 }
225
226 func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error) {
227         if ka.curve == nil {
228                 return nil, nil, os.ErrorString("missing ServerKeyExchange message")
229         }
230         priv, mx, my, err := ka.curve.GenerateKey(config.rand())
231         if err != nil {
232                 return nil, nil, err
233         }
234         x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
235         preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3)
236         xBytes := x.Bytes()
237         copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
238
239         serialised := ka.curve.Marshal(mx, my)
240
241         ckx := new(clientKeyExchangeMsg)
242         ckx.ciphertext = make([]byte, 1+len(serialised))
243         ckx.ciphertext[0] = byte(len(serialised))
244         copy(ckx.ciphertext[1:], serialised)
245
246         return preMasterSecret, ckx, nil
247 }