Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / boringssl / src / ssl / test / runner / 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 main
6
7 import (
8         "crypto"
9         "crypto/ecdsa"
10         "crypto/elliptic"
11         "crypto/md5"
12         "crypto/rand"
13         "crypto/rsa"
14         "crypto/sha1"
15         "crypto/sha256"
16         "crypto/x509"
17         "encoding/asn1"
18         "errors"
19         "io"
20         "math/big"
21 )
22
23 var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
24 var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
25
26 // rsaKeyAgreement implements the standard TLS key agreement where the client
27 // encrypts the pre-master secret to the server's public key.
28 type rsaKeyAgreement struct{}
29
30 func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
31         return nil, nil
32 }
33
34 func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
35         preMasterSecret := make([]byte, 48)
36         _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
37         if err != nil {
38                 return nil, err
39         }
40
41         if len(ckx.ciphertext) < 2 {
42                 return nil, errClientKeyExchange
43         }
44
45         ciphertext := ckx.ciphertext
46         if version != VersionSSL30 {
47                 ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
48                 if ciphertextLen != len(ckx.ciphertext)-2 {
49                         return nil, errClientKeyExchange
50                 }
51                 ciphertext = ckx.ciphertext[2:]
52         }
53
54         err = rsa.DecryptPKCS1v15SessionKey(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
55         if err != nil {
56                 return nil, err
57         }
58         // We don't check the version number in the premaster secret.  For one,
59         // by checking it, we would leak information about the validity of the
60         // encrypted pre-master secret. Secondly, it provides only a small
61         // benefit against a downgrade attack and some implementations send the
62         // wrong version anyway. See the discussion at the end of section
63         // 7.4.7.1 of RFC 4346.
64         return preMasterSecret, nil
65 }
66
67 func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
68         return errors.New("tls: unexpected ServerKeyExchange")
69 }
70
71 func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
72         preMasterSecret := make([]byte, 48)
73         preMasterSecret[0] = byte(clientHello.vers >> 8)
74         preMasterSecret[1] = byte(clientHello.vers)
75         _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
76         if err != nil {
77                 return nil, nil, err
78         }
79
80         encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
81         if err != nil {
82                 return nil, nil, err
83         }
84         ckx := new(clientKeyExchangeMsg)
85         ckx.ciphertext = make([]byte, len(encrypted)+2)
86         ckx.ciphertext[0] = byte(len(encrypted) >> 8)
87         ckx.ciphertext[1] = byte(len(encrypted))
88         copy(ckx.ciphertext[2:], encrypted)
89         return preMasterSecret, ckx, nil
90 }
91
92 // sha1Hash calculates a SHA1 hash over the given byte slices.
93 func sha1Hash(slices [][]byte) []byte {
94         hsha1 := sha1.New()
95         for _, slice := range slices {
96                 hsha1.Write(slice)
97         }
98         return hsha1.Sum(nil)
99 }
100
101 // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
102 // concatenation of an MD5 and SHA1 hash.
103 func md5SHA1Hash(slices [][]byte) []byte {
104         md5sha1 := make([]byte, md5.Size+sha1.Size)
105         hmd5 := md5.New()
106         for _, slice := range slices {
107                 hmd5.Write(slice)
108         }
109         copy(md5sha1, hmd5.Sum(nil))
110         copy(md5sha1[md5.Size:], sha1Hash(slices))
111         return md5sha1
112 }
113
114 // sha256Hash implements TLS 1.2's hash function.
115 func sha256Hash(slices [][]byte) []byte {
116         h := sha256.New()
117         for _, slice := range slices {
118                 h.Write(slice)
119         }
120         return h.Sum(nil)
121 }
122
123 // hashForServerKeyExchange hashes the given slices and returns their digest
124 // and the identifier of the hash function used. The hashFunc argument is only
125 // used for >= TLS 1.2 and precisely identifies the hash function to use.
126 func hashForServerKeyExchange(sigType, hashFunc uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
127         if version >= VersionTLS12 {
128                 switch hashFunc {
129                 case hashSHA256:
130                         return sha256Hash(slices), crypto.SHA256, nil
131                 case hashSHA1:
132                         return sha1Hash(slices), crypto.SHA1, nil
133                 default:
134                         return nil, crypto.Hash(0), errors.New("tls: unknown hash function used by peer")
135                 }
136         }
137         if sigType == signatureECDSA {
138                 return sha1Hash(slices), crypto.SHA1, nil
139         }
140         return md5SHA1Hash(slices), crypto.MD5SHA1, nil
141 }
142
143 // pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
144 // ServerKeyExchange given the signature type being used and the client's
145 // advertized list of supported signature and hash combinations.
146 func pickTLS12HashForSignature(sigType uint8, clientSignatureAndHashes []signatureAndHash) (uint8, error) {
147         if len(clientSignatureAndHashes) == 0 {
148                 // If the client didn't specify any signature_algorithms
149                 // extension then we can assume that it supports SHA1. See
150                 // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
151                 return hashSHA1, nil
152         }
153
154         for _, sigAndHash := range clientSignatureAndHashes {
155                 if sigAndHash.signature != sigType {
156                         continue
157                 }
158                 switch sigAndHash.hash {
159                 case hashSHA1, hashSHA256:
160                         return sigAndHash.hash, nil
161                 }
162         }
163
164         return 0, errors.New("tls: client doesn't support any common hash functions")
165 }
166
167 func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
168         switch id {
169         case CurveP256:
170                 return elliptic.P256(), true
171         case CurveP384:
172                 return elliptic.P384(), true
173         case CurveP521:
174                 return elliptic.P521(), true
175         default:
176                 return nil, false
177         }
178
179 }
180
181 // signedKeyAgreement implements helper functions for key agreement
182 // methods that involve signed parameters in the ServerKeyExchange.
183 type signedKeyAgreement struct {
184         version uint16
185         sigType uint8
186 }
187
188 func (ka *signedKeyAgreement) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) {
189         var tls12HashId uint8
190         var err error
191         if ka.version >= VersionTLS12 {
192                 if tls12HashId, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
193                         return nil, err
194                 }
195         }
196
197         digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, hello.random, params)
198         if err != nil {
199                 return nil, err
200         }
201
202         if config.Bugs.InvalidSKXSignature {
203                 digest[0] ^= 0x80
204         }
205
206         var sig []byte
207         switch ka.sigType {
208         case signatureECDSA:
209                 privKey, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
210                 if !ok {
211                         return nil, errors.New("ECDHE ECDSA requires an ECDSA server private key")
212                 }
213                 r, s, err := ecdsa.Sign(config.rand(), privKey, digest)
214                 if err != nil {
215                         return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
216                 }
217                 order := privKey.Curve.Params().N
218                 r = maybeCorruptECDSAValue(r, config.Bugs.BadECDSAR, order)
219                 s = maybeCorruptECDSAValue(s, config.Bugs.BadECDSAS, order)
220                 sig, err = asn1.Marshal(ecdsaSignature{r, s})
221         case signatureRSA:
222                 privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
223                 if !ok {
224                         return nil, errors.New("ECDHE RSA requires a RSA server private key")
225                 }
226                 sig, err = rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
227                 if err != nil {
228                         return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
229                 }
230         default:
231                 return nil, errors.New("unknown ECDHE signature algorithm")
232         }
233
234         skx := new(serverKeyExchangeMsg)
235         if config.Bugs.UnauthenticatedECDH {
236                 skx.key = params
237         } else {
238                 sigAndHashLen := 0
239                 if ka.version >= VersionTLS12 {
240                         sigAndHashLen = 2
241                 }
242                 skx.key = make([]byte, len(params)+sigAndHashLen+2+len(sig))
243                 copy(skx.key, params)
244                 k := skx.key[len(params):]
245                 if ka.version >= VersionTLS12 {
246                         k[0] = tls12HashId
247                         k[1] = ka.sigType
248                         k = k[2:]
249                 }
250                 k[0] = byte(len(sig) >> 8)
251                 k[1] = byte(len(sig))
252                 copy(k[2:], sig)
253         }
254
255         return skx, nil
256 }
257
258 func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
259         if len(sig) < 2 {
260                 return errServerKeyExchange
261         }
262
263         var tls12HashId uint8
264         if ka.version >= VersionTLS12 {
265                 // handle SignatureAndHashAlgorithm
266                 var sigAndHash []uint8
267                 sigAndHash, sig = sig[:2], sig[2:]
268                 if sigAndHash[1] != ka.sigType {
269                         return errServerKeyExchange
270                 }
271                 tls12HashId = sigAndHash[0]
272                 if len(sig) < 2 {
273                         return errServerKeyExchange
274                 }
275         }
276         sigLen := int(sig[0])<<8 | int(sig[1])
277         if sigLen+2 != len(sig) {
278                 return errServerKeyExchange
279         }
280         sig = sig[2:]
281
282         digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, serverHello.random, params)
283         if err != nil {
284                 return err
285         }
286         switch ka.sigType {
287         case signatureECDSA:
288                 pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
289                 if !ok {
290                         return errors.New("ECDHE ECDSA requires a ECDSA server public key")
291                 }
292                 ecdsaSig := new(ecdsaSignature)
293                 if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
294                         return err
295                 }
296                 if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
297                         return errors.New("ECDSA signature contained zero or negative values")
298                 }
299                 if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
300                         return errors.New("ECDSA verification failure")
301                 }
302         case signatureRSA:
303                 pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
304                 if !ok {
305                         return errors.New("ECDHE RSA requires a RSA server public key")
306                 }
307                 if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
308                         return err
309                 }
310         default:
311                 return errors.New("unknown ECDHE signature algorithm")
312         }
313
314         return nil
315 }
316
317 // ecdheRSAKeyAgreement implements a TLS key agreement where the server
318 // generates a ephemeral EC public/private key pair and signs it. The
319 // pre-master secret is then calculated using ECDH. The signature may
320 // either be ECDSA or RSA.
321 type ecdheKeyAgreement struct {
322         signedKeyAgreement
323         privateKey []byte
324         curve      elliptic.Curve
325         x, y       *big.Int
326 }
327
328 func maybeCorruptECDSAValue(n *big.Int, typeOfCorruption BadValue, limit *big.Int) *big.Int {
329         switch typeOfCorruption {
330         case BadValueNone:
331                 return n
332         case BadValueNegative:
333                 return new(big.Int).Neg(n)
334         case BadValueZero:
335                 return big.NewInt(0)
336         case BadValueLimit:
337                 return limit
338         case BadValueLarge:
339                 bad := new(big.Int).Set(limit)
340                 return bad.Lsh(bad, 20)
341         default:
342                 panic("unknown BadValue type")
343         }
344 }
345
346 func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
347         var curveid CurveID
348         preferredCurves := config.curvePreferences()
349
350 NextCandidate:
351         for _, candidate := range preferredCurves {
352                 for _, c := range clientHello.supportedCurves {
353                         if candidate == c {
354                                 curveid = c
355                                 break NextCandidate
356                         }
357                 }
358         }
359
360         if curveid == 0 {
361                 return nil, errors.New("tls: no supported elliptic curves offered")
362         }
363
364         var ok bool
365         if ka.curve, ok = curveForCurveID(curveid); !ok {
366                 return nil, errors.New("tls: preferredCurves includes unsupported curve")
367         }
368
369         var x, y *big.Int
370         var err error
371         ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
372         if err != nil {
373                 return nil, err
374         }
375         ecdhePublic := elliptic.Marshal(ka.curve, x, y)
376
377         // http://tools.ietf.org/html/rfc4492#section-5.4
378         serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
379         serverECDHParams[0] = 3 // named curve
380         serverECDHParams[1] = byte(curveid >> 8)
381         serverECDHParams[2] = byte(curveid)
382         if config.Bugs.InvalidSKXCurve {
383                 serverECDHParams[2] ^= 0xff
384         }
385         serverECDHParams[3] = byte(len(ecdhePublic))
386         copy(serverECDHParams[4:], ecdhePublic)
387
388         return ka.signParameters(config, cert, clientHello, hello, serverECDHParams)
389 }
390
391 func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
392         if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
393                 return nil, errClientKeyExchange
394         }
395         x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
396         if x == nil {
397                 return nil, errClientKeyExchange
398         }
399         x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
400         preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
401         xBytes := x.Bytes()
402         copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
403
404         return preMasterSecret, nil
405 }
406
407 func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
408         if len(skx.key) < 4 {
409                 return errServerKeyExchange
410         }
411         if skx.key[0] != 3 { // named curve
412                 return errors.New("tls: server selected unsupported curve")
413         }
414         curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
415
416         var ok bool
417         if ka.curve, ok = curveForCurveID(curveid); !ok {
418                 return errors.New("tls: server selected unsupported curve")
419         }
420
421         publicLen := int(skx.key[3])
422         if publicLen+4 > len(skx.key) {
423                 return errServerKeyExchange
424         }
425         ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
426         if ka.x == nil {
427                 return errServerKeyExchange
428         }
429         serverECDHParams := skx.key[:4+publicLen]
430         sig := skx.key[4+publicLen:]
431
432         return ka.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig)
433 }
434
435 func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
436         if ka.curve == nil {
437                 return nil, nil, errors.New("missing ServerKeyExchange message")
438         }
439         priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
440         if err != nil {
441                 return nil, nil, err
442         }
443         x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
444         preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
445         xBytes := x.Bytes()
446         copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
447
448         serialized := elliptic.Marshal(ka.curve, mx, my)
449
450         ckx := new(clientKeyExchangeMsg)
451         ckx.ciphertext = make([]byte, 1+len(serialized))
452         ckx.ciphertext[0] = byte(len(serialized))
453         copy(ckx.ciphertext[1:], serialized)
454
455         return preMasterSecret, ckx, nil
456 }
457
458 // dheRSAKeyAgreement implements a TLS key agreement where the server generates
459 // an ephemeral Diffie-Hellman public/private key pair and signs it. The
460 // pre-master secret is then calculated using Diffie-Hellman.
461 type dheKeyAgreement struct {
462         signedKeyAgreement
463         p, g    *big.Int
464         yTheirs *big.Int
465         xOurs   *big.Int
466 }
467
468 func (ka *dheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
469         // 2048-bit MODP Group with 256-bit Prime Order Subgroup (RFC
470         // 5114, Section 2.3)
471         ka.p, _ = new(big.Int).SetString("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597", 16)
472         ka.g, _ = new(big.Int).SetString("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659", 16)
473         q, _ := new(big.Int).SetString("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3", 16)
474
475         var err error
476         ka.xOurs, err = rand.Int(config.rand(), q)
477         if err != nil {
478                 return nil, err
479         }
480         yOurs := new(big.Int).Exp(ka.g, ka.xOurs, ka.p)
481
482         // http://tools.ietf.org/html/rfc5246#section-7.4.3
483         pBytes := ka.p.Bytes()
484         gBytes := ka.g.Bytes()
485         yBytes := yOurs.Bytes()
486         serverDHParams := make([]byte, 0, 2+len(pBytes)+2+len(gBytes)+2+len(yBytes))
487         serverDHParams = append(serverDHParams, byte(len(pBytes)>>8), byte(len(pBytes)))
488         serverDHParams = append(serverDHParams, pBytes...)
489         serverDHParams = append(serverDHParams, byte(len(gBytes)>>8), byte(len(gBytes)))
490         serverDHParams = append(serverDHParams, gBytes...)
491         serverDHParams = append(serverDHParams, byte(len(yBytes)>>8), byte(len(yBytes)))
492         serverDHParams = append(serverDHParams, yBytes...)
493
494         return ka.signParameters(config, cert, clientHello, hello, serverDHParams)
495 }
496
497 func (ka *dheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
498         if len(ckx.ciphertext) < 2 {
499                 return nil, errClientKeyExchange
500         }
501         yLen := (int(ckx.ciphertext[0]) << 8) | int(ckx.ciphertext[1])
502         if yLen != len(ckx.ciphertext)-2 {
503                 return nil, errClientKeyExchange
504         }
505         yTheirs := new(big.Int).SetBytes(ckx.ciphertext[2:])
506         if yTheirs.Sign() <= 0 || yTheirs.Cmp(ka.p) >= 0 {
507                 return nil, errClientKeyExchange
508         }
509         return new(big.Int).Exp(yTheirs, ka.xOurs, ka.p).Bytes(), nil
510 }
511
512 func (ka *dheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
513         // Read dh_p
514         k := skx.key
515         if len(k) < 2 {
516                 return errServerKeyExchange
517         }
518         pLen := (int(k[0]) << 8) | int(k[1])
519         k = k[2:]
520         if len(k) < pLen {
521                 return errServerKeyExchange
522         }
523         ka.p = new(big.Int).SetBytes(k[:pLen])
524         k = k[pLen:]
525
526         // Read dh_g
527         if len(k) < 2 {
528                 return errServerKeyExchange
529         }
530         gLen := (int(k[0]) << 8) | int(k[1])
531         k = k[2:]
532         if len(k) < gLen {
533                 return errServerKeyExchange
534         }
535         ka.g = new(big.Int).SetBytes(k[:gLen])
536         k = k[gLen:]
537
538         // Read dh_Ys
539         if len(k) < 2 {
540                 return errServerKeyExchange
541         }
542         yLen := (int(k[0]) << 8) | int(k[1])
543         k = k[2:]
544         if len(k) < yLen {
545                 return errServerKeyExchange
546         }
547         ka.yTheirs = new(big.Int).SetBytes(k[:yLen])
548         k = k[yLen:]
549         if ka.yTheirs.Sign() <= 0 || ka.yTheirs.Cmp(ka.p) >= 0 {
550                 return errServerKeyExchange
551         }
552
553         sig := k
554         serverDHParams := skx.key[:len(skx.key)-len(sig)]
555
556         return ka.verifyParameters(config, clientHello, serverHello, cert, serverDHParams, sig)
557 }
558
559 func (ka *dheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
560         if ka.p == nil || ka.g == nil || ka.yTheirs == nil {
561                 return nil, nil, errors.New("missing ServerKeyExchange message")
562         }
563
564         xOurs, err := rand.Int(config.rand(), ka.p)
565         if err != nil {
566                 return nil, nil, err
567         }
568         preMasterSecret := new(big.Int).Exp(ka.yTheirs, xOurs, ka.p).Bytes()
569
570         yOurs := new(big.Int).Exp(ka.g, xOurs, ka.p)
571         yBytes := yOurs.Bytes()
572         ckx := new(clientKeyExchangeMsg)
573         ckx.ciphertext = make([]byte, 2+len(yBytes))
574         ckx.ciphertext[0] = byte(len(yBytes) >> 8)
575         ckx.ciphertext[1] = byte(len(yBytes))
576         copy(ckx.ciphertext[2:], yBytes)
577
578         return preMasterSecret, ckx, nil
579 }