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.
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{}
23 func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, os.Error) {
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:])
34 if len(ckx.ciphertext) < 2 {
35 return nil, os.NewError("bad ClientKeyExchange")
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")
41 ciphertext := ckx.ciphertext[2:]
43 err = rsa.DecryptPKCS1v15SessionKey(config.rand(), config.Certificates[0].PrivateKey, ciphertext, preMasterSecret)
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
56 func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) os.Error {
57 return os.NewError("unexpected ServerKeyExchange")
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:])
69 encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
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
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)
86 for _, slice := range slices {
89 copy(md5sha1, hmd5.Sum())
92 for _, slice := range slices {
95 copy(md5sha1[md5.Size:], hsha1.Sum())
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 {
104 curve *elliptic.Curve
108 func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, os.Error) {
112 for _, c := range clientHello.supportedCurves {
115 ka.curve = elliptic.P256()
119 ka.curve = elliptic.P384()
123 ka.curve = elliptic.P521()
131 ka.privateKey, x, y, err = ka.curve.GenerateKey(config.rand())
135 ecdhePublic := ka.curve.Marshal(x, y)
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)
145 md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
146 sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey, crypto.MD5SHA1, md5sha1)
148 return nil, os.NewError("failed to sign ECDHE parameters: " + err.String())
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))
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")
166 x, y := ka.curve.Unmarshal(ckx.ciphertext[1:])
168 return nil, os.NewError("bad ClientKeyExchange")
170 x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
171 preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3)
173 copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
175 return preMasterSecret, nil
178 var errServerKeyExchange = os.NewError("invalid ServerKeyExchange")
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
184 if skx.key[0] != 3 { // named curve
185 return os.NewError("server selected unsupported curve")
187 curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2])
191 ka.curve = elliptic.P256()
193 ka.curve = elliptic.P384()
195 ka.curve = elliptic.P521()
197 return os.NewError("server selected unsupported curve")
200 publicLen := int(skx.key[3])
201 if publicLen+4 > len(skx.key) {
202 return errServerKeyExchange
204 ka.x, ka.y = ka.curve.Unmarshal(skx.key[4 : 4+publicLen])
206 return errServerKeyExchange
208 serverECDHParams := skx.key[:4+publicLen]
210 sig := skx.key[4+publicLen:]
212 return errServerKeyExchange
214 sigLen := int(sig[0])<<8 | int(sig[1])
215 if sigLen+2 != len(sig) {
216 return errServerKeyExchange
220 md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams)
221 return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), crypto.MD5SHA1, md5sha1, sig)
224 func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error) {
226 return nil, nil, os.NewError("missing ServerKeyExchange message")
228 priv, mx, my, err := ka.curve.GenerateKey(config.rand())
232 x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
233 preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3)
235 copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
237 serialized := ka.curve.Marshal(mx, my)
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)
244 return preMasterSecret, ckx, nil