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.
20 "golang_org/x/crypto/curve25519"
23 var errClientKeyExchange
= errors
.New("tls: invalid ClientKeyExchange message")
24 var errServerKeyExchange
= errors
.New("tls: invalid ServerKeyExchange message")
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{}
30 func (ka rsaKeyAgreement
) generateServerKeyExchange(config
*Config
, cert
*Certificate
, clientHello
*clientHelloMsg
, hello
*serverHelloMsg
) (*serverKeyExchangeMsg
, error
) {
34 func (ka rsaKeyAgreement
) processClientKeyExchange(config
*Config
, cert
*Certificate
, ckx
*clientKeyExchangeMsg
, version
uint16) ([]byte, error
) {
35 if len(ckx
.ciphertext
) < 2 {
36 return nil, errClientKeyExchange
39 ciphertext
:= ckx
.ciphertext
40 if version
!= VersionSSL30
{
41 ciphertextLen
:= int(ckx
.ciphertext
[0])<<8 |
int(ckx
.ciphertext
[1])
42 if ciphertextLen
!= len(ckx
.ciphertext
)-2 {
43 return nil, errClientKeyExchange
45 ciphertext
= ckx
.ciphertext
[2:]
47 priv
, ok
:= cert
.PrivateKey
.(crypto
.Decrypter
)
49 return nil, errors
.New("tls: certificate private key does not implement crypto.Decrypter")
51 // Perform constant time RSA PKCS#1 v1.5 decryption
52 preMasterSecret
, err
:= priv
.Decrypt(config
.rand(), ciphertext
, &rsa
.PKCS1v15DecryptOptions
{SessionKeyLen
: 48})
56 // We don't check the version number in the premaster secret. For one,
57 // by checking it, we would leak information about the validity of the
58 // encrypted pre-master secret. Secondly, it provides only a small
59 // benefit against a downgrade attack and some implementations send the
60 // wrong version anyway. See the discussion at the end of section
61 // 7.4.7.1 of RFC 4346.
62 return preMasterSecret
, nil
65 func (ka rsaKeyAgreement
) processServerKeyExchange(config
*Config
, clientHello
*clientHelloMsg
, serverHello
*serverHelloMsg
, cert
*x509
.Certificate
, skx
*serverKeyExchangeMsg
) error
{
66 return errors
.New("tls: unexpected ServerKeyExchange")
69 func (ka rsaKeyAgreement
) generateClientKeyExchange(config
*Config
, clientHello
*clientHelloMsg
, cert
*x509
.Certificate
) ([]byte, *clientKeyExchangeMsg
, error
) {
70 preMasterSecret
:= make([]byte, 48)
71 preMasterSecret
[0] = byte(clientHello
.vers
>> 8)
72 preMasterSecret
[1] = byte(clientHello
.vers
)
73 _
, err
:= io
.ReadFull(config
.rand(), preMasterSecret
[2:])
78 encrypted
, err
:= rsa
.EncryptPKCS1v15(config
.rand(), cert
.PublicKey
.(*rsa
.PublicKey
), preMasterSecret
)
82 ckx
:= new(clientKeyExchangeMsg
)
83 ckx
.ciphertext
= make([]byte, len(encrypted
)+2)
84 ckx
.ciphertext
[0] = byte(len(encrypted
) >> 8)
85 ckx
.ciphertext
[1] = byte(len(encrypted
))
86 copy(ckx
.ciphertext
[2:], encrypted
)
87 return preMasterSecret
, ckx
, nil
90 // sha1Hash calculates a SHA1 hash over the given byte slices.
91 func sha1Hash(slices
[][]byte) []byte {
93 for _
, slice
:= range slices
{
99 // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
100 // concatenation of an MD5 and SHA1 hash.
101 func md5SHA1Hash(slices
[][]byte) []byte {
102 md5sha1
:= make([]byte, md5
.Size
+sha1
.Size
)
104 for _
, slice
:= range slices
{
107 copy(md5sha1
, hmd5
.Sum(nil))
108 copy(md5sha1
[md5
.Size
:], sha1Hash(slices
))
112 // hashForServerKeyExchange hashes the given slices and returns their digest
113 // and the identifier of the hash function used. The signatureAlgorithm argument
114 // is only used for >= TLS 1.2 and identifies the hash function to use.
115 func hashForServerKeyExchange(sigType
uint8, signatureAlgorithm SignatureScheme
, version
uint16, slices
...[]byte) ([]byte, crypto
.Hash
, error
) {
116 if version
>= VersionTLS12
{
117 if !isSupportedSignatureAlgorithm(signatureAlgorithm
, supportedSignatureAlgorithms
) {
118 return nil, crypto
.Hash(0), errors
.New("tls: unsupported hash function used by peer")
120 hashFunc
, err
:= lookupTLSHash(signatureAlgorithm
)
122 return nil, crypto
.Hash(0), err
125 for _
, slice
:= range slices
{
129 return digest
, hashFunc
, nil
131 if sigType
== signatureECDSA
{
132 return sha1Hash(slices
), crypto
.SHA1
, nil
134 return md5SHA1Hash(slices
), crypto
.MD5SHA1
, nil
137 // pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
138 // ServerKeyExchange given the signature type being used and the client's
139 // advertised list of supported signature and hash combinations.
140 func pickTLS12HashForSignature(sigType
uint8, clientList
[]SignatureScheme
) (SignatureScheme
, error
) {
141 if len(clientList
) == 0 {
142 // If the client didn't specify any signature_algorithms
143 // extension then we can assume that it supports SHA1. See
144 // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
147 return PKCS1WithSHA1
, nil
149 return ECDSAWithSHA1
, nil
151 return 0, errors
.New("tls: unknown signature algorithm")
155 for _
, sigAlg
:= range clientList
{
156 if signatureFromSignatureScheme(sigAlg
) != sigType
{
159 if isSupportedSignatureAlgorithm(sigAlg
, supportedSignatureAlgorithms
) {
164 return 0, errors
.New("tls: client doesn't support any common hash functions")
167 func curveForCurveID(id CurveID
) (elliptic
.Curve
, bool) {
170 return elliptic
.P256(), true
172 return elliptic
.P384(), true
174 return elliptic
.P521(), true
181 // ecdheRSAKeyAgreement implements a TLS key agreement where the server
182 // generates an ephemeral EC public/private key pair and signs it. The
183 // pre-master secret is then calculated using ECDH. The signature may
184 // either be ECDSA or RSA.
185 type ecdheKeyAgreement
struct {
191 // publicKey is used to store the peer's public value when X25519 is
194 // x and y are used to store the peer's public value when one of the
195 // NIST curves is being used.
199 func (ka
*ecdheKeyAgreement
) generateServerKeyExchange(config
*Config
, cert
*Certificate
, clientHello
*clientHelloMsg
, hello
*serverHelloMsg
) (*serverKeyExchangeMsg
, error
) {
200 preferredCurves
:= config
.curvePreferences()
203 for _
, candidate
:= range preferredCurves
{
204 for _
, c
:= range clientHello
.supportedCurves
{
213 return nil, errors
.New("tls: no supported elliptic curves offered")
216 var ecdhePublic
[]byte
218 if ka
.curveid
== X25519
{
219 var scalar
, public
[32]byte
220 if _
, err
:= io
.ReadFull(config
.rand(), scalar
[:]); err
!= nil {
224 curve25519
.ScalarBaseMult(&public
, &scalar
)
225 ka
.privateKey
= scalar
[:]
226 ecdhePublic
= public
[:]
228 curve
, ok
:= curveForCurveID(ka
.curveid
)
230 return nil, errors
.New("tls: preferredCurves includes unsupported curve")
235 ka
.privateKey
, x
, y
, err
= elliptic
.GenerateKey(curve
, config
.rand())
239 ecdhePublic
= elliptic
.Marshal(curve
, x
, y
)
242 // http://tools.ietf.org/html/rfc4492#section-5.4
243 serverECDHParams
:= make([]byte, 1+2+1+len(ecdhePublic
))
244 serverECDHParams
[0] = 3 // named curve
245 serverECDHParams
[1] = byte(ka
.curveid
>> 8)
246 serverECDHParams
[2] = byte(ka
.curveid
)
247 serverECDHParams
[3] = byte(len(ecdhePublic
))
248 copy(serverECDHParams
[4:], ecdhePublic
)
250 var signatureAlgorithm SignatureScheme
252 if ka
.version
>= VersionTLS12
{
254 signatureAlgorithm
, err
= pickTLS12HashForSignature(ka
.sigType
, clientHello
.supportedSignatureAlgorithms
)
260 digest
, hashFunc
, err
:= hashForServerKeyExchange(ka
.sigType
, signatureAlgorithm
, ka
.version
, clientHello
.random
, hello
.random
, serverECDHParams
)
265 priv
, ok
:= cert
.PrivateKey
.(crypto
.Signer
)
267 return nil, errors
.New("tls: certificate private key does not implement crypto.Signer")
272 _
, ok
:= priv
.Public().(*ecdsa
.PublicKey
)
274 return nil, errors
.New("tls: ECDHE ECDSA requires an ECDSA server key")
277 _
, ok
:= priv
.Public().(*rsa
.PublicKey
)
279 return nil, errors
.New("tls: ECDHE RSA requires a RSA server key")
282 return nil, errors
.New("tls: unknown ECDHE signature algorithm")
284 sig
, err
= priv
.Sign(config
.rand(), digest
, hashFunc
)
286 return nil, errors
.New("tls: failed to sign ECDHE parameters: " + err
.Error())
289 skx
:= new(serverKeyExchangeMsg
)
291 if ka
.version
>= VersionTLS12
{
294 skx
.key
= make([]byte, len(serverECDHParams
)+sigAndHashLen
+2+len(sig
))
295 copy(skx
.key
, serverECDHParams
)
296 k
:= skx
.key
[len(serverECDHParams
):]
297 if ka
.version
>= VersionTLS12
{
298 k
[0] = byte(signatureAlgorithm
>> 8)
299 k
[1] = byte(signatureAlgorithm
)
302 k
[0] = byte(len(sig
) >> 8)
303 k
[1] = byte(len(sig
))
309 func (ka
*ecdheKeyAgreement
) processClientKeyExchange(config
*Config
, cert
*Certificate
, ckx
*clientKeyExchangeMsg
, version
uint16) ([]byte, error
) {
310 if len(ckx
.ciphertext
) == 0 ||
int(ckx
.ciphertext
[0]) != len(ckx
.ciphertext
)-1 {
311 return nil, errClientKeyExchange
314 if ka
.curveid
== X25519
{
315 if len(ckx
.ciphertext
) != 1+32 {
316 return nil, errClientKeyExchange
319 var theirPublic
, sharedKey
, scalar
[32]byte
320 copy(theirPublic
[:], ckx
.ciphertext
[1:])
321 copy(scalar
[:], ka
.privateKey
)
322 curve25519
.ScalarMult(&sharedKey
, &scalar
, &theirPublic
)
323 return sharedKey
[:], nil
326 curve
, ok
:= curveForCurveID(ka
.curveid
)
328 panic("internal error")
330 x
, y
:= elliptic
.Unmarshal(curve
, ckx
.ciphertext
[1:]) // Unmarshal also checks whether the given point is on the curve
332 return nil, errClientKeyExchange
334 x
, _
= curve
.ScalarMult(x
, y
, ka
.privateKey
)
335 preMasterSecret
:= make([]byte, (curve
.Params().BitSize
+7)>>3)
337 copy(preMasterSecret
[len(preMasterSecret
)-len(xBytes
):], xBytes
)
339 return preMasterSecret
, nil
342 func (ka
*ecdheKeyAgreement
) processServerKeyExchange(config
*Config
, clientHello
*clientHelloMsg
, serverHello
*serverHelloMsg
, cert
*x509
.Certificate
, skx
*serverKeyExchangeMsg
) error
{
343 if len(skx
.key
) < 4 {
344 return errServerKeyExchange
346 if skx
.key
[0] != 3 { // named curve
347 return errors
.New("tls: server selected unsupported curve")
349 ka
.curveid
= CurveID(skx
.key
[1])<<8 |
CurveID(skx
.key
[2])
351 publicLen
:= int(skx
.key
[3])
352 if publicLen
+4 > len(skx
.key
) {
353 return errServerKeyExchange
355 serverECDHParams
:= skx
.key
[:4+publicLen
]
356 publicKey
:= serverECDHParams
[4:]
358 sig
:= skx
.key
[4+publicLen
:]
360 return errServerKeyExchange
363 if ka
.curveid
== X25519
{
364 if len(publicKey
) != 32 {
365 return errors
.New("tls: bad X25519 public value")
367 ka
.publicKey
= publicKey
369 curve
, ok
:= curveForCurveID(ka
.curveid
)
371 return errors
.New("tls: server selected unsupported curve")
373 ka
.x
, ka
.y
= elliptic
.Unmarshal(curve
, publicKey
) // Unmarshal also checks whether the given point is on the curve
375 return errServerKeyExchange
379 var signatureAlgorithm SignatureScheme
380 if ka
.version
>= VersionTLS12
{
381 // handle SignatureAndHashAlgorithm
382 signatureAlgorithm
= SignatureScheme(sig
[0])<<8 |
SignatureScheme(sig
[1])
383 if signatureFromSignatureScheme(signatureAlgorithm
) != ka
.sigType
{
384 return errServerKeyExchange
388 return errServerKeyExchange
391 sigLen
:= int(sig
[0])<<8 |
int(sig
[1])
392 if sigLen
+2 != len(sig
) {
393 return errServerKeyExchange
397 digest
, hashFunc
, err
:= hashForServerKeyExchange(ka
.sigType
, signatureAlgorithm
, ka
.version
, clientHello
.random
, serverHello
.random
, serverECDHParams
)
403 pubKey
, ok
:= cert
.PublicKey
.(*ecdsa
.PublicKey
)
405 return errors
.New("tls: ECDHE ECDSA requires a ECDSA server public key")
407 ecdsaSig
:= new(ecdsaSignature
)
408 if _
, err
:= asn1
.Unmarshal(sig
, ecdsaSig
); err
!= nil {
411 if ecdsaSig
.R
.Sign() <= 0 || ecdsaSig
.S
.Sign() <= 0 {
412 return errors
.New("tls: ECDSA signature contained zero or negative values")
414 if !ecdsa
.Verify(pubKey
, digest
, ecdsaSig
.R
, ecdsaSig
.S
) {
415 return errors
.New("tls: ECDSA verification failure")
418 pubKey
, ok
:= cert
.PublicKey
.(*rsa
.PublicKey
)
420 return errors
.New("tls: ECDHE RSA requires a RSA server public key")
422 if err
:= rsa
.VerifyPKCS1v15(pubKey
, hashFunc
, digest
, sig
); err
!= nil {
426 return errors
.New("tls: unknown ECDHE signature algorithm")
432 func (ka
*ecdheKeyAgreement
) generateClientKeyExchange(config
*Config
, clientHello
*clientHelloMsg
, cert
*x509
.Certificate
) ([]byte, *clientKeyExchangeMsg
, error
) {
434 return nil, nil, errors
.New("tls: missing ServerKeyExchange message")
437 var serialized
, preMasterSecret
[]byte
439 if ka
.curveid
== X25519
{
440 var ourPublic
, theirPublic
, sharedKey
, scalar
[32]byte
442 if _
, err
:= io
.ReadFull(config
.rand(), scalar
[:]); err
!= nil {
446 copy(theirPublic
[:], ka
.publicKey
)
447 curve25519
.ScalarBaseMult(&ourPublic
, &scalar
)
448 curve25519
.ScalarMult(&sharedKey
, &scalar
, &theirPublic
)
449 serialized
= ourPublic
[:]
450 preMasterSecret
= sharedKey
[:]
452 curve
, ok
:= curveForCurveID(ka
.curveid
)
454 panic("internal error")
456 priv
, mx
, my
, err
:= elliptic
.GenerateKey(curve
, config
.rand())
460 x
, _
:= curve
.ScalarMult(ka
.x
, ka
.y
, priv
)
461 preMasterSecret
= make([]byte, (curve
.Params().BitSize
+7)>>3)
463 copy(preMasterSecret
[len(preMasterSecret
)-len(xBytes
):], xBytes
)
465 serialized
= elliptic
.Marshal(curve
, mx
, my
)
468 ckx
:= new(clientKeyExchangeMsg
)
469 ckx
.ciphertext
= make([]byte, 1+len(serialized
))
470 ckx
.ciphertext
[0] = byte(len(serialized
))
471 copy(ckx
.ciphertext
[1:], serialized
)
473 return preMasterSecret
, ckx
, nil