]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/crypto/tls/key_agreement.go
[dev.boringcrypto] all: merge master (nearly Go 1.10 beta 1) into dev.boringcrypto
[gostls13.git] / src / crypto / tls / key_agreement.go
index e8a46b87084454ab9ae8559cacd7126f09ee63eb..a168c5b260623cfdd079cd7cfff67b020861658e 100644 (file)
@@ -110,14 +110,14 @@ func md5SHA1Hash(slices [][]byte) []byte {
 }
 
 // hashForServerKeyExchange hashes the given slices and returns their digest
-// and the identifier of the hash function used. The sigAndHash argument is
-// only used for >= TLS 1.2 and precisely identifies the hash function to use.
-func hashForServerKeyExchange(sigAndHash signatureAndHash, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
+// and the identifier of the hash function used. The signatureAlgorithm argument
+// is only used for >= TLS 1.2 and identifies the hash function to use.
+func hashForServerKeyExchange(sigType uint8, signatureAlgorithm SignatureScheme, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
        if version >= VersionTLS12 {
-               if !isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms()) {
+               if !isSupportedSignatureAlgorithm(signatureAlgorithm, supportedSignatureAlgorithms()) {
                        return nil, crypto.Hash(0), errors.New("tls: unsupported hash function used by peer")
                }
-               hashFunc, err := lookupTLSHash(sigAndHash.hash)
+               hashFunc, err := lookupTLSHash(signatureAlgorithm)
                if err != nil {
                        return nil, crypto.Hash(0), err
                }
@@ -128,7 +128,7 @@ func hashForServerKeyExchange(sigAndHash signatureAndHash, version uint16, slice
                digest := h.Sum(nil)
                return digest, hashFunc, nil
        }
-       if sigAndHash.signature == signatureECDSA {
+       if sigType == signatureECDSA {
                return sha1Hash(slices), crypto.SHA1, nil
        }
        return md5SHA1Hash(slices), crypto.MD5SHA1, nil
@@ -137,20 +137,27 @@ func hashForServerKeyExchange(sigAndHash signatureAndHash, version uint16, slice
 // pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
 // ServerKeyExchange given the signature type being used and the client's
 // advertised list of supported signature and hash combinations.
-func pickTLS12HashForSignature(sigType uint8, clientList []signatureAndHash) (uint8, error) {
+func pickTLS12HashForSignature(sigType uint8, clientList []SignatureScheme) (SignatureScheme, error) {
        if len(clientList) == 0 {
                // If the client didn't specify any signature_algorithms
                // extension then we can assume that it supports SHA1. See
                // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
-               return hashSHA1, nil
+               switch sigType {
+               case signatureRSA:
+                       return PKCS1WithSHA1, nil
+               case signatureECDSA:
+                       return ECDSAWithSHA1, nil
+               default:
+                       return 0, errors.New("tls: unknown signature algorithm")
+               }
        }
 
-       for _, sigAndHash := range clientList {
-               if sigAndHash.signature != sigType {
+       for _, sigAlg := range clientList {
+               if signatureFromSignatureScheme(sigAlg) != sigType {
                        continue
                }
-               if isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms()) {
-                       return sigAndHash.hash, nil
+               if isSupportedSignatureAlgorithm(sigAlg, supportedSignatureAlgorithms()) {
+                       return sigAlg, nil
                }
        }
 
@@ -172,7 +179,7 @@ func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
 }
 
 // ecdheRSAKeyAgreement implements a TLS key agreement where the server
-// generates a ephemeral EC public/private key pair and signs it. The
+// generates an ephemeral EC public/private key pair and signs it. The
 // pre-master secret is then calculated using ECDH. The signature may
 // either be ECDSA or RSA.
 type ecdheKeyAgreement struct {
@@ -240,16 +247,17 @@ NextCandidate:
        serverECDHParams[3] = byte(len(ecdhePublic))
        copy(serverECDHParams[4:], ecdhePublic)
 
-       sigAndHash := signatureAndHash{signature: ka.sigType}
+       var signatureAlgorithm SignatureScheme
 
        if ka.version >= VersionTLS12 {
                var err error
-               if sigAndHash.hash, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
+               signatureAlgorithm, err = pickTLS12HashForSignature(ka.sigType, clientHello.supportedSignatureAlgorithms)
+               if err != nil {
                        return nil, err
                }
        }
 
-       digest, hashFunc, err := hashForServerKeyExchange(sigAndHash, ka.version, clientHello.random, hello.random, serverECDHParams)
+       digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, signatureAlgorithm, ka.version, clientHello.random, hello.random, serverECDHParams)
        if err != nil {
                return nil, err
        }
@@ -287,8 +295,8 @@ NextCandidate:
        copy(skx.key, serverECDHParams)
        k := skx.key[len(serverECDHParams):]
        if ka.version >= VersionTLS12 {
-               k[0] = sigAndHash.hash
-               k[1] = sigAndHash.signature
+               k[0] = byte(signatureAlgorithm >> 8)
+               k[1] = byte(signatureAlgorithm)
                k = k[2:]
        }
        k[0] = byte(len(sig) >> 8)
@@ -319,13 +327,10 @@ func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Cert
        if !ok {
                panic("internal error")
        }
-       x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:])
+       x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:]) // Unmarshal also checks whether the given point is on the curve
        if x == nil {
                return nil, errClientKeyExchange
        }
-       if !curve.IsOnCurve(x, y) {
-               return nil, errClientKeyExchange
-       }
        x, _ = curve.ScalarMult(x, y, ka.privateKey)
        preMasterSecret := make([]byte, (curve.Params().BitSize+7)>>3)
        xBytes := x.Bytes()
@@ -365,21 +370,17 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
                if !ok {
                        return errors.New("tls: server selected unsupported curve")
                }
-
-               ka.x, ka.y = elliptic.Unmarshal(curve, publicKey)
+               ka.x, ka.y = elliptic.Unmarshal(curve, publicKey) // Unmarshal also checks whether the given point is on the curve
                if ka.x == nil {
                        return errServerKeyExchange
                }
-               if !curve.IsOnCurve(ka.x, ka.y) {
-                       return errServerKeyExchange
-               }
        }
 
-       sigAndHash := signatureAndHash{signature: ka.sigType}
+       var signatureAlgorithm SignatureScheme
        if ka.version >= VersionTLS12 {
                // handle SignatureAndHashAlgorithm
-               sigAndHash = signatureAndHash{hash: sig[0], signature: sig[1]}
-               if sigAndHash.signature != ka.sigType {
+               signatureAlgorithm = SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1])
+               if signatureFromSignatureScheme(signatureAlgorithm) != ka.sigType {
                        return errServerKeyExchange
                }
                sig = sig[2:]
@@ -393,7 +394,7 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
        }
        sig = sig[2:]
 
-       digest, hashFunc, err := hashForServerKeyExchange(sigAndHash, ka.version, clientHello.random, serverHello.random, serverECDHParams)
+       digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, signatureAlgorithm, ka.version, clientHello.random, serverHello.random, serverECDHParams)
        if err != nil {
                return err
        }