]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/crypto/tls/handshake_client.go
[dev.boringcrypto] all: merge master into dev.boringcrypto
[gostls13.git] / src / crypto / tls / handshake_client.go
index 35f4539db904dc07185ce38d38c4d08b6006774b..3572129ffb144c4a4e641c4ba371fc66e5110010 100644 (file)
@@ -73,7 +73,6 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
                serverName:                   hostnameInSNI(config.ServerName),
                supportedCurves:              config.curvePreferences(),
                supportedPoints:              []uint8{pointFormatUncompressed},
-               nextProtoNeg:                 len(config.NextProtos) > 0,
                secureRenegotiationSupported: true,
                alpnProtocols:                config.NextProtos,
                supportedVersions:            supportedVersions,
@@ -566,9 +565,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
        }
 
        if chainToSend != nil && len(chainToSend.Certificate) > 0 {
-               certVerify := &certificateVerifyMsg{
-                       hasSignatureAlgorithm: c.vers >= VersionTLS12,
-               }
+               certVerify := &certificateVerifyMsg{}
 
                key, ok := chainToSend.PrivateKey.(crypto.Signer)
                if !ok {
@@ -576,23 +573,32 @@ func (hs *clientHandshakeState) doFullHandshake() error {
                        return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey)
                }
 
-               signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(key.Public(), certReq.supportedSignatureAlgorithms, supportedSignatureAlgorithmsTLS12(), c.vers)
-               if err != nil {
-                       c.sendAlert(alertInternalError)
-                       return err
-               }
-               // SignatureAndHashAlgorithm was introduced in TLS 1.2.
-               if certVerify.hasSignatureAlgorithm {
+               var sigType uint8
+               var sigHash crypto.Hash
+               if c.vers >= VersionTLS12 {
+                       signatureAlgorithm, err := selectSignatureScheme(c.vers, chainToSend, certReq.supportedSignatureAlgorithms)
+                       if err != nil {
+                               c.sendAlert(alertIllegalParameter)
+                               return err
+                       }
+                       sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm)
+                       if err != nil {
+                               return c.sendAlert(alertInternalError)
+                       }
+                       certVerify.hasSignatureAlgorithm = true
                        certVerify.signatureAlgorithm = signatureAlgorithm
+               } else {
+                       sigType, sigHash, err = legacyTypeAndHashFromPublicKey(key.Public())
+                       if err != nil {
+                               c.sendAlert(alertIllegalParameter)
+                               return err
+                       }
                }
-               signed, err := hs.finishedHash.hashForClientCertificate(sigType, hashFunc, hs.masterSecret)
-               if err != nil {
-                       c.sendAlert(alertInternalError)
-                       return err
-               }
-               signOpts := crypto.SignerOpts(hashFunc)
+
+               signed := hs.finishedHash.hashForClientCertificate(sigType, sigHash, hs.masterSecret)
+               signOpts := crypto.SignerOpts(sigHash)
                if sigType == signatureRSAPSS {
-                       signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc}
+                       signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash}
                }
                certVerify.signature, err = key.Sign(c.config.rand(), signed, signOpts)
                if err != nil {
@@ -676,26 +682,14 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
                }
        }
 
-       clientDidNPN := hs.hello.nextProtoNeg
        clientDidALPN := len(hs.hello.alpnProtocols) > 0
-       serverHasNPN := hs.serverHello.nextProtoNeg
        serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
 
-       if !clientDidNPN && serverHasNPN {
-               c.sendAlert(alertHandshakeFailure)
-               return false, errors.New("tls: server advertised unrequested NPN extension")
-       }
-
        if !clientDidALPN && serverHasALPN {
                c.sendAlert(alertHandshakeFailure)
                return false, errors.New("tls: server advertised unrequested ALPN extension")
        }
 
-       if serverHasNPN && serverHasALPN {
-               c.sendAlert(alertHandshakeFailure)
-               return false, errors.New("tls: server advertised both NPN and ALPN extensions")
-       }
-
        if serverHasALPN {
                c.clientProtocol = hs.serverHello.alpnProtocol
                c.clientProtocolFallback = false
@@ -787,18 +781,6 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error {
        if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil {
                return err
        }
-       if hs.serverHello.nextProtoNeg {
-               nextProto := new(nextProtoMsg)
-               proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos)
-               nextProto.proto = proto
-               c.clientProtocol = proto
-               c.clientProtocolFallback = fallback
-
-               hs.finishedHash.Write(nextProto.marshal())
-               if _, err := c.writeRecord(recordTypeHandshake, nextProto.marshal()); err != nil {
-                       return err
-               }
-       }
 
        finished := new(finishedMsg)
        finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
@@ -908,7 +890,11 @@ func certificateRequestInfoFromMsg(certReq *certificateRequestMsg) *CertificateR
        // See RFC 5246, Section 7.4.4 (where it calls this "somewhat complicated").
        cri.SignatureSchemes = make([]SignatureScheme, 0, len(certReq.supportedSignatureAlgorithms))
        for _, sigScheme := range certReq.supportedSignatureAlgorithms {
-               switch signatureFromSignatureScheme(sigScheme) {
+               sigType, _, err := typeAndHashFromSignatureScheme(sigScheme)
+               if err != nil {
+                       continue
+               }
+               switch sigType {
                case signatureECDSA, signatureEd25519:
                        if ecAvail {
                                cri.SignatureSchemes = append(cri.SignatureSchemes, sigScheme)
@@ -996,7 +982,7 @@ func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
        return protos[0], true
 }
 
-// hostnameInSNI converts name into an approriate hostname for SNI.
+// hostnameInSNI converts name into an appropriate hostname for SNI.
 // Literal IP addresses and absolute FQDNs are not permitted as SNI values.
 // See RFC 6066, Section 3.
 func hostnameInSNI(name string) string {