diff --git a/go.mod b/go.mod index 911bc0ff..feead7cd 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.13.0 github.com/prometheus/client_model v0.2.0 - github.com/quic-go/quic-go v0.40.1-0.20231203135336-87ef8ec48d55 + github.com/quic-go/quic-go v0.40.1-0.20240101045026-22b7f7744eb6 github.com/rs/zerolog v1.20.0 github.com/stretchr/testify v1.8.4 github.com/urfave/cli/v2 v2.3.0 diff --git a/go.sum b/go.sum index b7ebc160..bebebca5 100644 --- a/go.sum +++ b/go.sum @@ -324,6 +324,8 @@ github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5 github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= github.com/quic-go/quic-go v0.40.1-0.20231203135336-87ef8ec48d55 h1:I4N3ZRnkZPbDN935Tg8QDf8fRpHp3bZ0U0/L42jBgNE= github.com/quic-go/quic-go v0.40.1-0.20231203135336-87ef8ec48d55/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c= +github.com/quic-go/quic-go v0.40.1-0.20240101045026-22b7f7744eb6 h1:OI4WiysowCcxLtcZMGBZildo12di3ljcMN4vWdUQpoU= +github.com/quic-go/quic-go v0.40.1-0.20240101045026-22b7f7744eb6/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= diff --git a/quic/quic_protocol_test.go b/quic/quic_protocol_test.go index ab6d7c1e..439089d1 100644 --- a/quic/quic_protocol_test.go +++ b/quic/quic_protocol_test.go @@ -109,63 +109,6 @@ func TestConnectResponseMeta(t *testing.T) { } } -func TestUnregisterUdpSession(t *testing.T) { - unregisterMessage := "closed by eyeball" - - var tests = []struct { - name string - sessionRPCServer mockSessionRPCServer - timeout time.Duration - }{ - - { - name: "UnregisterUdpSessionTimesout if the RPC server does not respond", - sessionRPCServer: mockSessionRPCServer{ - sessionID: uuid.New(), - dstIP: net.IP{172, 16, 0, 1}, - dstPort: 8000, - closeIdleAfter: testCloseIdleAfterHint, - unregisterMessage: unregisterMessage, - traceContext: "1241ce3ecdefc68854e8514e69ba42ca:b38f1bf5eae406f3:0:1", - }, - // very very low value so we trigger the timeout every time. - timeout: time.Nanosecond * 1, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - logger := zerolog.Nop() - clientStream, serverStream := newMockRPCStreams() - sessionRegisteredChan := make(chan struct{}) - go func() { - protocol, err := DetermineProtocol(serverStream) - assert.NoError(t, err) - rpcServerStream, err := NewRPCServerStream(serverStream, protocol) - assert.NoError(t, err) - err = rpcServerStream.Serve(test.sessionRPCServer, nil, &logger) - assert.NoError(t, err) - - serverStream.Close() - close(sessionRegisteredChan) - }() - - rpcClientStream, err := NewRPCClientStream(context.Background(), clientStream, test.timeout, &logger) - assert.NoError(t, err) - - reg, err := rpcClientStream.RegisterUdpSession(context.Background(), test.sessionRPCServer.sessionID, test.sessionRPCServer.dstIP, test.sessionRPCServer.dstPort, testCloseIdleAfterHint, test.sessionRPCServer.traceContext) - assert.NoError(t, err) - assert.NoError(t, reg.Err) - - assert.Error(t, rpcClientStream.UnregisterUdpSession(context.Background(), test.sessionRPCServer.sessionID, unregisterMessage)) - - rpcClientStream.Close() - <-sessionRegisteredChan - }) - } - -} - func TestRegisterUdpSession(t *testing.T) { unregisterMessage := "closed by eyeball" diff --git a/vendor/github.com/quic-go/qtls-go1-20/LICENSE b/vendor/github.com/quic-go/qtls-go1-20/LICENSE deleted file mode 100644 index 6a66aea5..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/quic-go/qtls-go1-20/README.md b/vendor/github.com/quic-go/qtls-go1-20/README.md deleted file mode 100644 index 2beaa2f2..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# qtls - -[![Go Reference](https://pkg.go.dev/badge/github.com/quic-go/qtls-go1-20.svg)](https://pkg.go.dev/github.com/quic-go/qtls-go1-20) -[![.github/workflows/go-test.yml](https://github.com/quic-go/qtls-go1-20/actions/workflows/go-test.yml/badge.svg)](https://github.com/quic-go/qtls-go1-20/actions/workflows/go-test.yml) - -This repository contains a modified version of the standard library's TLS implementation, modified for the QUIC protocol. It is used by [quic-go](https://github.com/quic-go/quic-go). diff --git a/vendor/github.com/quic-go/qtls-go1-20/alert.go b/vendor/github.com/quic-go/qtls-go1-20/alert.go deleted file mode 100644 index 687ada84..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/alert.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import "strconv" - -// An AlertError is a TLS alert. -// -// When using a QUIC transport, QUICConn methods will return an error -// which wraps AlertError rather than sending a TLS alert. -type AlertError uint8 - -func (e AlertError) Error() string { - return alert(e).String() -} - -type alert uint8 - -const ( - // alert level - alertLevelWarning = 1 - alertLevelError = 2 -) - -const ( - alertCloseNotify alert = 0 - alertUnexpectedMessage alert = 10 - alertBadRecordMAC alert = 20 - alertDecryptionFailed alert = 21 - alertRecordOverflow alert = 22 - alertDecompressionFailure alert = 30 - alertHandshakeFailure alert = 40 - alertBadCertificate alert = 42 - alertUnsupportedCertificate alert = 43 - alertCertificateRevoked alert = 44 - alertCertificateExpired alert = 45 - alertCertificateUnknown alert = 46 - alertIllegalParameter alert = 47 - alertUnknownCA alert = 48 - alertAccessDenied alert = 49 - alertDecodeError alert = 50 - alertDecryptError alert = 51 - alertExportRestriction alert = 60 - alertProtocolVersion alert = 70 - alertInsufficientSecurity alert = 71 - alertInternalError alert = 80 - alertInappropriateFallback alert = 86 - alertUserCanceled alert = 90 - alertNoRenegotiation alert = 100 - alertMissingExtension alert = 109 - alertUnsupportedExtension alert = 110 - alertCertificateUnobtainable alert = 111 - alertUnrecognizedName alert = 112 - alertBadCertificateStatusResponse alert = 113 - alertBadCertificateHashValue alert = 114 - alertUnknownPSKIdentity alert = 115 - alertCertificateRequired alert = 116 - alertNoApplicationProtocol alert = 120 -) - -var alertText = map[alert]string{ - alertCloseNotify: "close notify", - alertUnexpectedMessage: "unexpected message", - alertBadRecordMAC: "bad record MAC", - alertDecryptionFailed: "decryption failed", - alertRecordOverflow: "record overflow", - alertDecompressionFailure: "decompression failure", - alertHandshakeFailure: "handshake failure", - alertBadCertificate: "bad certificate", - alertUnsupportedCertificate: "unsupported certificate", - alertCertificateRevoked: "revoked certificate", - alertCertificateExpired: "expired certificate", - alertCertificateUnknown: "unknown certificate", - alertIllegalParameter: "illegal parameter", - alertUnknownCA: "unknown certificate authority", - alertAccessDenied: "access denied", - alertDecodeError: "error decoding message", - alertDecryptError: "error decrypting message", - alertExportRestriction: "export restriction", - alertProtocolVersion: "protocol version not supported", - alertInsufficientSecurity: "insufficient security level", - alertInternalError: "internal error", - alertInappropriateFallback: "inappropriate fallback", - alertUserCanceled: "user canceled", - alertNoRenegotiation: "no renegotiation", - alertMissingExtension: "missing extension", - alertUnsupportedExtension: "unsupported extension", - alertCertificateUnobtainable: "certificate unobtainable", - alertUnrecognizedName: "unrecognized name", - alertBadCertificateStatusResponse: "bad certificate status response", - alertBadCertificateHashValue: "bad certificate hash value", - alertUnknownPSKIdentity: "unknown PSK identity", - alertCertificateRequired: "certificate required", - alertNoApplicationProtocol: "no application protocol", -} - -func (e alert) String() string { - s, ok := alertText[e] - if ok { - return "tls: " + s - } - return "tls: alert(" + strconv.Itoa(int(e)) + ")" -} - -func (e alert) Error() string { - return e.String() -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/auth.go b/vendor/github.com/quic-go/qtls-go1-20/auth.go deleted file mode 100644 index effc9ace..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/auth.go +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "bytes" - "crypto" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/elliptic" - "crypto/rsa" - "errors" - "fmt" - "hash" - "io" -) - -// verifyHandshakeSignature verifies a signature against pre-hashed -// (if required) handshake contents. -func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc crypto.Hash, signed, sig []byte) error { - switch sigType { - case signatureECDSA: - pubKey, ok := pubkey.(*ecdsa.PublicKey) - if !ok { - return fmt.Errorf("expected an ECDSA public key, got %T", pubkey) - } - if !ecdsa.VerifyASN1(pubKey, signed, sig) { - return errors.New("ECDSA verification failure") - } - case signatureEd25519: - pubKey, ok := pubkey.(ed25519.PublicKey) - if !ok { - return fmt.Errorf("expected an Ed25519 public key, got %T", pubkey) - } - if !ed25519.Verify(pubKey, signed, sig) { - return errors.New("Ed25519 verification failure") - } - case signaturePKCS1v15: - pubKey, ok := pubkey.(*rsa.PublicKey) - if !ok { - return fmt.Errorf("expected an RSA public key, got %T", pubkey) - } - if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, signed, sig); err != nil { - return err - } - case signatureRSAPSS: - pubKey, ok := pubkey.(*rsa.PublicKey) - if !ok { - return fmt.Errorf("expected an RSA public key, got %T", pubkey) - } - signOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash} - if err := rsa.VerifyPSS(pubKey, hashFunc, signed, sig, signOpts); err != nil { - return err - } - default: - return errors.New("internal error: unknown signature type") - } - return nil -} - -const ( - serverSignatureContext = "TLS 1.3, server CertificateVerify\x00" - clientSignatureContext = "TLS 1.3, client CertificateVerify\x00" -) - -var signaturePadding = []byte{ - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, -} - -// signedMessage returns the pre-hashed (if necessary) message to be signed by -// certificate keys in TLS 1.3. See RFC 8446, Section 4.4.3. -func signedMessage(sigHash crypto.Hash, context string, transcript hash.Hash) []byte { - if sigHash == directSigning { - b := &bytes.Buffer{} - b.Write(signaturePadding) - io.WriteString(b, context) - b.Write(transcript.Sum(nil)) - return b.Bytes() - } - h := sigHash.New() - h.Write(signaturePadding) - io.WriteString(h, context) - h.Write(transcript.Sum(nil)) - return h.Sum(nil) -} - -// typeAndHashFromSignatureScheme returns the corresponding signature type and -// crypto.Hash for a given TLS SignatureScheme. -func typeAndHashFromSignatureScheme(signatureAlgorithm SignatureScheme) (sigType uint8, hash crypto.Hash, err error) { - switch signatureAlgorithm { - case PKCS1WithSHA1, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512: - sigType = signaturePKCS1v15 - case PSSWithSHA256, PSSWithSHA384, PSSWithSHA512: - sigType = signatureRSAPSS - case ECDSAWithSHA1, ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512: - sigType = signatureECDSA - case Ed25519: - sigType = signatureEd25519 - default: - return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) - } - switch signatureAlgorithm { - case PKCS1WithSHA1, ECDSAWithSHA1: - hash = crypto.SHA1 - case PKCS1WithSHA256, PSSWithSHA256, ECDSAWithP256AndSHA256: - hash = crypto.SHA256 - case PKCS1WithSHA384, PSSWithSHA384, ECDSAWithP384AndSHA384: - hash = crypto.SHA384 - case PKCS1WithSHA512, PSSWithSHA512, ECDSAWithP521AndSHA512: - hash = crypto.SHA512 - case Ed25519: - hash = directSigning - default: - return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) - } - return sigType, hash, nil -} - -// legacyTypeAndHashFromPublicKey returns the fixed signature type and crypto.Hash for -// a given public key used with TLS 1.0 and 1.1, before the introduction of -// signature algorithm negotiation. -func legacyTypeAndHashFromPublicKey(pub crypto.PublicKey) (sigType uint8, hash crypto.Hash, err error) { - switch pub.(type) { - case *rsa.PublicKey: - return signaturePKCS1v15, crypto.MD5SHA1, nil - case *ecdsa.PublicKey: - return signatureECDSA, crypto.SHA1, nil - case ed25519.PublicKey: - // RFC 8422 specifies support for Ed25519 in TLS 1.0 and 1.1, - // but it requires holding on to a handshake transcript to do a - // full signature, and not even OpenSSL bothers with the - // complexity, so we can't even test it properly. - return 0, 0, fmt.Errorf("tls: Ed25519 public keys are not supported before TLS 1.2") - default: - return 0, 0, fmt.Errorf("tls: unsupported public key: %T", pub) - } -} - -var rsaSignatureSchemes = []struct { - scheme SignatureScheme - minModulusBytes int - maxVersion uint16 -}{ - // RSA-PSS is used with PSSSaltLengthEqualsHash, and requires - // emLen >= hLen + sLen + 2 - {PSSWithSHA256, crypto.SHA256.Size()*2 + 2, VersionTLS13}, - {PSSWithSHA384, crypto.SHA384.Size()*2 + 2, VersionTLS13}, - {PSSWithSHA512, crypto.SHA512.Size()*2 + 2, VersionTLS13}, - // PKCS #1 v1.5 uses prefixes from hashPrefixes in crypto/rsa, and requires - // emLen >= len(prefix) + hLen + 11 - // TLS 1.3 dropped support for PKCS #1 v1.5 in favor of RSA-PSS. - {PKCS1WithSHA256, 19 + crypto.SHA256.Size() + 11, VersionTLS12}, - {PKCS1WithSHA384, 19 + crypto.SHA384.Size() + 11, VersionTLS12}, - {PKCS1WithSHA512, 19 + crypto.SHA512.Size() + 11, VersionTLS12}, - {PKCS1WithSHA1, 15 + crypto.SHA1.Size() + 11, VersionTLS12}, -} - -// signatureSchemesForCertificate returns the list of supported SignatureSchemes -// for a given certificate, based on the public key and the protocol version, -// and optionally filtered by its explicit SupportedSignatureAlgorithms. -// -// This function must be kept in sync with supportedSignatureAlgorithms. -// FIPS filtering is applied in the caller, selectSignatureScheme. -func signatureSchemesForCertificate(version uint16, cert *Certificate) []SignatureScheme { - priv, ok := cert.PrivateKey.(crypto.Signer) - if !ok { - return nil - } - - var sigAlgs []SignatureScheme - switch pub := priv.Public().(type) { - case *ecdsa.PublicKey: - if version != VersionTLS13 { - // In TLS 1.2 and earlier, ECDSA algorithms are not - // constrained to a single curve. - sigAlgs = []SignatureScheme{ - ECDSAWithP256AndSHA256, - ECDSAWithP384AndSHA384, - ECDSAWithP521AndSHA512, - ECDSAWithSHA1, - } - break - } - switch pub.Curve { - case elliptic.P256(): - sigAlgs = []SignatureScheme{ECDSAWithP256AndSHA256} - case elliptic.P384(): - sigAlgs = []SignatureScheme{ECDSAWithP384AndSHA384} - case elliptic.P521(): - sigAlgs = []SignatureScheme{ECDSAWithP521AndSHA512} - default: - return nil - } - case *rsa.PublicKey: - size := pub.Size() - sigAlgs = make([]SignatureScheme, 0, len(rsaSignatureSchemes)) - for _, candidate := range rsaSignatureSchemes { - if size >= candidate.minModulusBytes && version <= candidate.maxVersion { - sigAlgs = append(sigAlgs, candidate.scheme) - } - } - case ed25519.PublicKey: - sigAlgs = []SignatureScheme{Ed25519} - default: - return nil - } - - if cert.SupportedSignatureAlgorithms != nil { - var filteredSigAlgs []SignatureScheme - for _, sigAlg := range sigAlgs { - if isSupportedSignatureAlgorithm(sigAlg, cert.SupportedSignatureAlgorithms) { - filteredSigAlgs = append(filteredSigAlgs, sigAlg) - } - } - return filteredSigAlgs - } - return sigAlgs -} - -// selectSignatureScheme picks a SignatureScheme from the peer's preference list -// that works with the selected certificate. It's only called for protocol -// versions that support signature algorithms, so TLS 1.2 and 1.3. -func selectSignatureScheme(vers uint16, c *Certificate, peerAlgs []SignatureScheme) (SignatureScheme, error) { - supportedAlgs := signatureSchemesForCertificate(vers, c) - if len(supportedAlgs) == 0 { - return 0, unsupportedCertificateError(c) - } - if len(peerAlgs) == 0 && vers == VersionTLS12 { - // For TLS 1.2, if the client didn't send signature_algorithms then we - // can assume that it supports SHA1. See RFC 5246, Section 7.4.1.4.1. - peerAlgs = []SignatureScheme{PKCS1WithSHA1, ECDSAWithSHA1} - } - // Pick signature scheme in the peer's preference order, as our - // preference order is not configurable. - for _, preferredAlg := range peerAlgs { - if needFIPS() && !isSupportedSignatureAlgorithm(preferredAlg, fipsSupportedSignatureAlgorithms) { - continue - } - if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) { - return preferredAlg, nil - } - } - return 0, errors.New("tls: peer doesn't support any of the certificate's signature algorithms") -} - -// unsupportedCertificateError returns a helpful error for certificates with -// an unsupported private key. -func unsupportedCertificateError(cert *Certificate) error { - switch cert.PrivateKey.(type) { - case rsa.PrivateKey, ecdsa.PrivateKey: - return fmt.Errorf("tls: unsupported certificate: private key is %T, expected *%T", - cert.PrivateKey, cert.PrivateKey) - case *ed25519.PrivateKey: - return fmt.Errorf("tls: unsupported certificate: private key is *ed25519.PrivateKey, expected ed25519.PrivateKey") - } - - signer, ok := cert.PrivateKey.(crypto.Signer) - if !ok { - return fmt.Errorf("tls: certificate private key (%T) does not implement crypto.Signer", - cert.PrivateKey) - } - - switch pub := signer.Public().(type) { - case *ecdsa.PublicKey: - switch pub.Curve { - case elliptic.P256(): - case elliptic.P384(): - case elliptic.P521(): - default: - return fmt.Errorf("tls: unsupported certificate curve (%s)", pub.Curve.Params().Name) - } - case *rsa.PublicKey: - return fmt.Errorf("tls: certificate RSA key size too small for supported signature algorithms") - case ed25519.PublicKey: - default: - return fmt.Errorf("tls: unsupported certificate key (%T)", pub) - } - - if cert.SupportedSignatureAlgorithms != nil { - return fmt.Errorf("tls: peer doesn't support the certificate custom signature algorithms") - } - - return fmt.Errorf("tls: internal error: unsupported key (%T)", cert.PrivateKey) -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/cache.go b/vendor/github.com/quic-go/qtls-go1-20/cache.go deleted file mode 100644 index 99e0c5fb..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/cache.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "crypto/x509" - "runtime" - "sync" - "sync/atomic" -) - -type cacheEntry struct { - refs atomic.Int64 - cert *x509.Certificate -} - -// certCache implements an intern table for reference counted x509.Certificates, -// implemented in a similar fashion to BoringSSL's CRYPTO_BUFFER_POOL. This -// allows for a single x509.Certificate to be kept in memory and referenced from -// multiple Conns. Returned references should not be mutated by callers. Certificates -// are still safe to use after they are removed from the cache. -// -// Certificates are returned wrapped in a activeCert struct that should be held by -// the caller. When references to the activeCert are freed, the number of references -// to the certificate in the cache is decremented. Once the number of references -// reaches zero, the entry is evicted from the cache. -// -// The main difference between this implementation and CRYPTO_BUFFER_POOL is that -// CRYPTO_BUFFER_POOL is a more generic structure which supports blobs of data, -// rather than specific structures. Since we only care about x509.Certificates, -// certCache is implemented as a specific cache, rather than a generic one. -// -// See https://boringssl.googlesource.com/boringssl/+/master/include/openssl/pool.h -// and https://boringssl.googlesource.com/boringssl/+/master/crypto/pool/pool.c -// for the BoringSSL reference. -type certCache struct { - sync.Map -} - -var clientCertCache = new(certCache) - -// activeCert is a handle to a certificate held in the cache. Once there are -// no alive activeCerts for a given certificate, the certificate is removed -// from the cache by a finalizer. -type activeCert struct { - cert *x509.Certificate -} - -// active increments the number of references to the entry, wraps the -// certificate in the entry in a activeCert, and sets the finalizer. -// -// Note that there is a race between active and the finalizer set on the -// returned activeCert, triggered if active is called after the ref count is -// decremented such that refs may be > 0 when evict is called. We consider this -// safe, since the caller holding an activeCert for an entry that is no longer -// in the cache is fine, with the only side effect being the memory overhead of -// there being more than one distinct reference to a certificate alive at once. -func (cc *certCache) active(e *cacheEntry) *activeCert { - e.refs.Add(1) - a := &activeCert{e.cert} - runtime.SetFinalizer(a, func(_ *activeCert) { - if e.refs.Add(-1) == 0 { - cc.evict(e) - } - }) - return a -} - -// evict removes a cacheEntry from the cache. -func (cc *certCache) evict(e *cacheEntry) { - cc.Delete(string(e.cert.Raw)) -} - -// newCert returns a x509.Certificate parsed from der. If there is already a copy -// of the certificate in the cache, a reference to the existing certificate will -// be returned. Otherwise, a fresh certificate will be added to the cache, and -// the reference returned. The returned reference should not be mutated. -func (cc *certCache) newCert(der []byte) (*activeCert, error) { - if entry, ok := cc.Load(string(der)); ok { - return cc.active(entry.(*cacheEntry)), nil - } - - cert, err := x509.ParseCertificate(der) - if err != nil { - return nil, err - } - - entry := &cacheEntry{cert: cert} - if entry, loaded := cc.LoadOrStore(string(der), entry); loaded { - return cc.active(entry.(*cacheEntry)), nil - } - return cc.active(entry), nil -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/cipher_suites.go b/vendor/github.com/quic-go/qtls-go1-20/cipher_suites.go deleted file mode 100644 index 2946ffb3..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/cipher_suites.go +++ /dev/null @@ -1,691 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "crypto" - "crypto/aes" - "crypto/cipher" - "crypto/des" - "crypto/hmac" - "crypto/rc4" - "crypto/sha1" - "crypto/sha256" - "fmt" - "hash" - "runtime" - - "golang.org/x/crypto/chacha20poly1305" - "golang.org/x/sys/cpu" -) - -// CipherSuite is a TLS cipher suite. Note that most functions in this package -// accept and expose cipher suite IDs instead of this type. -type CipherSuite struct { - ID uint16 - Name string - - // Supported versions is the list of TLS protocol versions that can - // negotiate this cipher suite. - SupportedVersions []uint16 - - // Insecure is true if the cipher suite has known security issues - // due to its primitives, design, or implementation. - Insecure bool -} - -var ( - supportedUpToTLS12 = []uint16{VersionTLS10, VersionTLS11, VersionTLS12} - supportedOnlyTLS12 = []uint16{VersionTLS12} - supportedOnlyTLS13 = []uint16{VersionTLS13} -) - -// CipherSuites returns a list of cipher suites currently implemented by this -// package, excluding those with security issues, which are returned by -// InsecureCipherSuites. -// -// The list is sorted by ID. Note that the default cipher suites selected by -// this package might depend on logic that can't be captured by a static list, -// and might not match those returned by this function. -func CipherSuites() []*CipherSuite { - return []*CipherSuite{ - {TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, - {TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, - {TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS_RSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false}, - {TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS_RSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, false}, - - {TLS_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256", supportedOnlyTLS13, false}, - {TLS_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384", supportedOnlyTLS13, false}, - {TLS_CHACHA20_POLY1305_SHA256, "TLS_CHACHA20_POLY1305_SHA256", supportedOnlyTLS13, false}, - - {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, - {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, - {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, - {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, - {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false}, - {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, false}, - {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false}, - {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, false}, - {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", supportedOnlyTLS12, false}, - {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", supportedOnlyTLS12, false}, - } -} - -// InsecureCipherSuites returns a list of cipher suites currently implemented by -// this package and which have security issues. -// -// Most applications should not use the cipher suites in this list, and should -// only use those returned by CipherSuites. -func InsecureCipherSuites() []*CipherSuite { - // This list includes RC4, CBC_SHA256, and 3DES cipher suites. See - // cipherSuitesPreferenceOrder for details. - return []*CipherSuite{ - {TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, - {TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true}, - {TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, - {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, - {TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, - {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true}, - {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, - {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, - } -} - -// CipherSuiteName returns the standard name for the passed cipher suite ID -// (e.g. "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"), or a fallback representation -// of the ID value if the cipher suite is not implemented by this package. -func CipherSuiteName(id uint16) string { - for _, c := range CipherSuites() { - if c.ID == id { - return c.Name - } - } - for _, c := range InsecureCipherSuites() { - if c.ID == id { - return c.Name - } - } - return fmt.Sprintf("0x%04X", id) -} - -const ( - // suiteECDHE indicates that the cipher suite involves elliptic curve - // Diffie-Hellman. This means that it should only be selected when the - // client indicates that it supports ECC with a curve and point format - // that we're happy with. - suiteECDHE = 1 << iota - // suiteECSign indicates that the cipher suite involves an ECDSA or - // EdDSA signature and therefore may only be selected when the server's - // certificate is ECDSA or EdDSA. If this is not set then the cipher suite - // is RSA based. - suiteECSign - // suiteTLS12 indicates that the cipher suite should only be advertised - // and accepted when using TLS 1.2. - suiteTLS12 - // suiteSHA384 indicates that the cipher suite uses SHA384 as the - // handshake hash. - suiteSHA384 -) - -// A cipherSuite is a TLS 1.0–1.2 cipher suite, and defines the key exchange -// mechanism, as well as the cipher+MAC pair or the AEAD. -type cipherSuite struct { - id uint16 - // the lengths, in bytes, of the key material needed for each component. - keyLen int - macLen int - ivLen int - ka func(version uint16) keyAgreement - // flags is a bitmask of the suite* values, above. - flags int - cipher func(key, iv []byte, isRead bool) any - mac func(key []byte) hash.Hash - aead func(key, fixedNonce []byte) aead -} - -var cipherSuites = []*cipherSuite{ // TODO: replace with a map, since the order doesn't matter. - {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadChaCha20Poly1305}, - {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadChaCha20Poly1305}, - {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM}, - {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadAESGCM}, - {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, - {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, - {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil}, - {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, - {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, cipherAES, macSHA256, nil}, - {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil}, - {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, - {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil}, - {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM}, - {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, - {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil}, - {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, - {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, - {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil}, - {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil}, - {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, 0, cipherRC4, macSHA1, nil}, - {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE, cipherRC4, macSHA1, nil}, - {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherRC4, macSHA1, nil}, -} - -// selectCipherSuite returns the first TLS 1.0–1.2 cipher suite from ids which -// is also in supportedIDs and passes the ok filter. -func selectCipherSuite(ids, supportedIDs []uint16, ok func(*cipherSuite) bool) *cipherSuite { - for _, id := range ids { - candidate := cipherSuiteByID(id) - if candidate == nil || !ok(candidate) { - continue - } - - for _, suppID := range supportedIDs { - if id == suppID { - return candidate - } - } - } - return nil -} - -// A cipherSuiteTLS13 defines only the pair of the AEAD algorithm and hash -// algorithm to be used with HKDF. See RFC 8446, Appendix B.4. -type cipherSuiteTLS13 struct { - id uint16 - keyLen int - aead func(key, fixedNonce []byte) aead - hash crypto.Hash -} - -var cipherSuitesTLS13 = []*cipherSuiteTLS13{ // TODO: replace with a map. - {TLS_AES_128_GCM_SHA256, 16, aeadAESGCMTLS13, crypto.SHA256}, - {TLS_CHACHA20_POLY1305_SHA256, 32, aeadChaCha20Poly1305, crypto.SHA256}, - {TLS_AES_256_GCM_SHA384, 32, aeadAESGCMTLS13, crypto.SHA384}, -} - -// cipherSuitesPreferenceOrder is the order in which we'll select (on the -// server) or advertise (on the client) TLS 1.0–1.2 cipher suites. -// -// Cipher suites are filtered but not reordered based on the application and -// peer's preferences, meaning we'll never select a suite lower in this list if -// any higher one is available. This makes it more defensible to keep weaker -// cipher suites enabled, especially on the server side where we get the last -// word, since there are no known downgrade attacks on cipher suites selection. -// -// The list is sorted by applying the following priority rules, stopping at the -// first (most important) applicable one: -// -// - Anything else comes before RC4 -// -// RC4 has practically exploitable biases. See https://www.rc4nomore.com. -// -// - Anything else comes before CBC_SHA256 -// -// SHA-256 variants of the CBC ciphersuites don't implement any Lucky13 -// countermeasures. See http://www.isg.rhul.ac.uk/tls/Lucky13.html and -// https://www.imperialviolet.org/2013/02/04/luckythirteen.html. -// -// - Anything else comes before 3DES -// -// 3DES has 64-bit blocks, which makes it fundamentally susceptible to -// birthday attacks. See https://sweet32.info. -// -// - ECDHE comes before anything else -// -// Once we got the broken stuff out of the way, the most important -// property a cipher suite can have is forward secrecy. We don't -// implement FFDHE, so that means ECDHE. -// -// - AEADs come before CBC ciphers -// -// Even with Lucky13 countermeasures, MAC-then-Encrypt CBC cipher suites -// are fundamentally fragile, and suffered from an endless sequence of -// padding oracle attacks. See https://eprint.iacr.org/2015/1129, -// https://www.imperialviolet.org/2014/12/08/poodleagain.html, and -// https://blog.cloudflare.com/yet-another-padding-oracle-in-openssl-cbc-ciphersuites/. -// -// - AES comes before ChaCha20 -// -// When AES hardware is available, AES-128-GCM and AES-256-GCM are faster -// than ChaCha20Poly1305. -// -// When AES hardware is not available, AES-128-GCM is one or more of: much -// slower, way more complex, and less safe (because not constant time) -// than ChaCha20Poly1305. -// -// We use this list if we think both peers have AES hardware, and -// cipherSuitesPreferenceOrderNoAES otherwise. -// -// - AES-128 comes before AES-256 -// -// The only potential advantages of AES-256 are better multi-target -// margins, and hypothetical post-quantum properties. Neither apply to -// TLS, and AES-256 is slower due to its four extra rounds (which don't -// contribute to the advantages above). -// -// - ECDSA comes before RSA -// -// The relative order of ECDSA and RSA cipher suites doesn't matter, -// as they depend on the certificate. Pick one to get a stable order. -var cipherSuitesPreferenceOrder = []uint16{ - // AEADs w/ ECDHE - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, - - // CBC w/ ECDHE - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - - // AEADs w/o ECDHE - TLS_RSA_WITH_AES_128_GCM_SHA256, - TLS_RSA_WITH_AES_256_GCM_SHA384, - - // CBC w/o ECDHE - TLS_RSA_WITH_AES_128_CBC_SHA, - TLS_RSA_WITH_AES_256_CBC_SHA, - - // 3DES - TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - TLS_RSA_WITH_3DES_EDE_CBC_SHA, - - // CBC_SHA256 - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - TLS_RSA_WITH_AES_128_CBC_SHA256, - - // RC4 - TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, - TLS_RSA_WITH_RC4_128_SHA, -} - -var cipherSuitesPreferenceOrderNoAES = []uint16{ - // ChaCha20Poly1305 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, - - // AES-GCM w/ ECDHE - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - - // The rest of cipherSuitesPreferenceOrder. - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - TLS_RSA_WITH_AES_128_GCM_SHA256, - TLS_RSA_WITH_AES_256_GCM_SHA384, - TLS_RSA_WITH_AES_128_CBC_SHA, - TLS_RSA_WITH_AES_256_CBC_SHA, - TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - TLS_RSA_WITH_3DES_EDE_CBC_SHA, - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - TLS_RSA_WITH_AES_128_CBC_SHA256, - TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, - TLS_RSA_WITH_RC4_128_SHA, -} - -// disabledCipherSuites are not used unless explicitly listed in -// Config.CipherSuites. They MUST be at the end of cipherSuitesPreferenceOrder. -var disabledCipherSuites = []uint16{ - // CBC_SHA256 - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - TLS_RSA_WITH_AES_128_CBC_SHA256, - - // RC4 - TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, - TLS_RSA_WITH_RC4_128_SHA, -} - -var ( - defaultCipherSuitesLen = len(cipherSuitesPreferenceOrder) - len(disabledCipherSuites) - defaultCipherSuites = cipherSuitesPreferenceOrder[:defaultCipherSuitesLen] -) - -// defaultCipherSuitesTLS13 is also the preference order, since there are no -// disabled by default TLS 1.3 cipher suites. The same AES vs ChaCha20 logic as -// cipherSuitesPreferenceOrder applies. -var defaultCipherSuitesTLS13 = []uint16{ - TLS_AES_128_GCM_SHA256, - TLS_AES_256_GCM_SHA384, - TLS_CHACHA20_POLY1305_SHA256, -} - -var defaultCipherSuitesTLS13NoAES = []uint16{ - TLS_CHACHA20_POLY1305_SHA256, - TLS_AES_128_GCM_SHA256, - TLS_AES_256_GCM_SHA384, -} - -var ( - hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ - hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL - // Keep in sync with crypto/aes/cipher_s390x.go. - hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && - (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) - - hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || - runtime.GOARCH == "arm64" && hasGCMAsmARM64 || - runtime.GOARCH == "s390x" && hasGCMAsmS390X -) - -var aesgcmCiphers = map[uint16]bool{ - // TLS 1.2 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: true, - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: true, - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: true, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: true, - // TLS 1.3 - TLS_AES_128_GCM_SHA256: true, - TLS_AES_256_GCM_SHA384: true, -} - -var nonAESGCMAEADCiphers = map[uint16]bool{ - // TLS 1.2 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: true, - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: true, - // TLS 1.3 - TLS_CHACHA20_POLY1305_SHA256: true, -} - -// aesgcmPreferred returns whether the first known cipher in the preference list -// is an AES-GCM cipher, implying the peer has hardware support for it. -func aesgcmPreferred(ciphers []uint16) bool { - for _, cID := range ciphers { - if c := cipherSuiteByID(cID); c != nil { - return aesgcmCiphers[cID] - } - if c := cipherSuiteTLS13ByID(cID); c != nil { - return aesgcmCiphers[cID] - } - } - return false -} - -func cipherRC4(key, iv []byte, isRead bool) any { - cipher, _ := rc4.NewCipher(key) - return cipher -} - -func cipher3DES(key, iv []byte, isRead bool) any { - block, _ := des.NewTripleDESCipher(key) - if isRead { - return cipher.NewCBCDecrypter(block, iv) - } - return cipher.NewCBCEncrypter(block, iv) -} - -func cipherAES(key, iv []byte, isRead bool) any { - block, _ := aes.NewCipher(key) - if isRead { - return cipher.NewCBCDecrypter(block, iv) - } - return cipher.NewCBCEncrypter(block, iv) -} - -// macSHA1 returns a SHA-1 based constant time MAC. -func macSHA1(key []byte) hash.Hash { - h := sha1.New - h = newConstantTimeHash(h) - return hmac.New(h, key) -} - -// macSHA256 returns a SHA-256 based MAC. This is only supported in TLS 1.2 and -// is currently only used in disabled-by-default cipher suites. -func macSHA256(key []byte) hash.Hash { - return hmac.New(sha256.New, key) -} - -type aead interface { - cipher.AEAD - - // explicitNonceLen returns the number of bytes of explicit nonce - // included in each record. This is eight for older AEADs and - // zero for modern ones. - explicitNonceLen() int -} - -const ( - aeadNonceLength = 12 - noncePrefixLength = 4 -) - -// prefixNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to -// each call. -type prefixNonceAEAD struct { - // nonce contains the fixed part of the nonce in the first four bytes. - nonce [aeadNonceLength]byte - aead cipher.AEAD -} - -func (f *prefixNonceAEAD) NonceSize() int { return aeadNonceLength - noncePrefixLength } -func (f *prefixNonceAEAD) Overhead() int { return f.aead.Overhead() } -func (f *prefixNonceAEAD) explicitNonceLen() int { return f.NonceSize() } - -func (f *prefixNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { - copy(f.nonce[4:], nonce) - return f.aead.Seal(out, f.nonce[:], plaintext, additionalData) -} - -func (f *prefixNonceAEAD) Open(out, nonce, ciphertext, additionalData []byte) ([]byte, error) { - copy(f.nonce[4:], nonce) - return f.aead.Open(out, f.nonce[:], ciphertext, additionalData) -} - -// xorNonceAEAD wraps an AEAD by XORing in a fixed pattern to the nonce -// before each call. -type xorNonceAEAD struct { - nonceMask [aeadNonceLength]byte - aead cipher.AEAD -} - -func (f *xorNonceAEAD) NonceSize() int { return 8 } // 64-bit sequence number -func (f *xorNonceAEAD) Overhead() int { return f.aead.Overhead() } -func (f *xorNonceAEAD) explicitNonceLen() int { return 0 } - -func (f *xorNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { - for i, b := range nonce { - f.nonceMask[4+i] ^= b - } - result := f.aead.Seal(out, f.nonceMask[:], plaintext, additionalData) - for i, b := range nonce { - f.nonceMask[4+i] ^= b - } - - return result -} - -func (f *xorNonceAEAD) Open(out, nonce, ciphertext, additionalData []byte) ([]byte, error) { - for i, b := range nonce { - f.nonceMask[4+i] ^= b - } - result, err := f.aead.Open(out, f.nonceMask[:], ciphertext, additionalData) - for i, b := range nonce { - f.nonceMask[4+i] ^= b - } - - return result, err -} - -func aeadAESGCM(key, noncePrefix []byte) aead { - if len(noncePrefix) != noncePrefixLength { - panic("tls: internal error: wrong nonce length") - } - aes, err := aes.NewCipher(key) - if err != nil { - panic(err) - } - var aead cipher.AEAD - aead, err = cipher.NewGCM(aes) - if err != nil { - panic(err) - } - - ret := &prefixNonceAEAD{aead: aead} - copy(ret.nonce[:], noncePrefix) - return ret -} - -func aeadAESGCMTLS13(key, nonceMask []byte) aead { - if len(nonceMask) != aeadNonceLength { - panic("tls: internal error: wrong nonce length") - } - aes, err := aes.NewCipher(key) - if err != nil { - panic(err) - } - aead, err := cipher.NewGCM(aes) - if err != nil { - panic(err) - } - - ret := &xorNonceAEAD{aead: aead} - copy(ret.nonceMask[:], nonceMask) - return ret -} - -func aeadChaCha20Poly1305(key, nonceMask []byte) aead { - if len(nonceMask) != aeadNonceLength { - panic("tls: internal error: wrong nonce length") - } - aead, err := chacha20poly1305.New(key) - if err != nil { - panic(err) - } - - ret := &xorNonceAEAD{aead: aead} - copy(ret.nonceMask[:], nonceMask) - return ret -} - -type constantTimeHash interface { - hash.Hash - ConstantTimeSum(b []byte) []byte -} - -// cthWrapper wraps any hash.Hash that implements ConstantTimeSum, and replaces -// with that all calls to Sum. It's used to obtain a ConstantTimeSum-based HMAC. -type cthWrapper struct { - h constantTimeHash -} - -func (c *cthWrapper) Size() int { return c.h.Size() } -func (c *cthWrapper) BlockSize() int { return c.h.BlockSize() } -func (c *cthWrapper) Reset() { c.h.Reset() } -func (c *cthWrapper) Write(p []byte) (int, error) { return c.h.Write(p) } -func (c *cthWrapper) Sum(b []byte) []byte { return c.h.ConstantTimeSum(b) } - -func newConstantTimeHash(h func() hash.Hash) func() hash.Hash { - return func() hash.Hash { - return &cthWrapper{h().(constantTimeHash)} - } -} - -// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, Section 6.2.3. -func tls10MAC(h hash.Hash, out, seq, header, data, extra []byte) []byte { - h.Reset() - h.Write(seq) - h.Write(header) - h.Write(data) - res := h.Sum(out) - if extra != nil { - h.Write(extra) - } - return res -} - -func rsaKA(version uint16) keyAgreement { - return rsaKeyAgreement{} -} - -func ecdheECDSAKA(version uint16) keyAgreement { - return &ecdheKeyAgreement{ - isRSA: false, - version: version, - } -} - -func ecdheRSAKA(version uint16) keyAgreement { - return &ecdheKeyAgreement{ - isRSA: true, - version: version, - } -} - -// mutualCipherSuite returns a cipherSuite given a list of supported -// ciphersuites and the id requested by the peer. -func mutualCipherSuite(have []uint16, want uint16) *cipherSuite { - for _, id := range have { - if id == want { - return cipherSuiteByID(id) - } - } - return nil -} - -func cipherSuiteByID(id uint16) *cipherSuite { - for _, cipherSuite := range cipherSuites { - if cipherSuite.id == id { - return cipherSuite - } - } - return nil -} - -func mutualCipherSuiteTLS13(have []uint16, want uint16) *cipherSuiteTLS13 { - for _, id := range have { - if id == want { - return cipherSuiteTLS13ByID(id) - } - } - return nil -} - -func cipherSuiteTLS13ByID(id uint16) *cipherSuiteTLS13 { - for _, cipherSuite := range cipherSuitesTLS13 { - if cipherSuite.id == id { - return cipherSuite - } - } - return nil -} - -// A list of cipher suite IDs that are, or have been, implemented by this -// package. -// -// See https://www.iana.org/assignments/tls-parameters/tls-parameters.xml -const ( - // TLS 1.0 - 1.2 cipher suites. - TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005 - TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a - TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f - TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035 - TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c - TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c - TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d - TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007 - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009 - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a - TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011 - TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012 - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013 - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014 - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc023 - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc027 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca8 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca9 - - // TLS 1.3 cipher suites. - TLS_AES_128_GCM_SHA256 uint16 = 0x1301 - TLS_AES_256_GCM_SHA384 uint16 = 0x1302 - TLS_CHACHA20_POLY1305_SHA256 uint16 = 0x1303 - - // TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator - // that the client is doing version fallback. See RFC 7507. - TLS_FALLBACK_SCSV uint16 = 0x5600 - - // Legacy names for the corresponding cipher suites with the correct _SHA256 - // suffix, retained for backward compatibility. - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -) diff --git a/vendor/github.com/quic-go/qtls-go1-20/common.go b/vendor/github.com/quic-go/qtls-go1-20/common.go deleted file mode 100644 index ba776d7b..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/common.go +++ /dev/null @@ -1,1454 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "bytes" - "container/list" - "context" - "crypto" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "crypto/sha512" - "crypto/tls" - "crypto/x509" - "errors" - "fmt" - "io" - "net" - "strings" - "sync" - "time" -) - -const ( - VersionTLS10 = 0x0301 - VersionTLS11 = 0x0302 - VersionTLS12 = 0x0303 - VersionTLS13 = 0x0304 - - // Deprecated: SSLv3 is cryptographically broken, and is no longer - // supported by this package. See golang.org/issue/32716. - VersionSSL30 = 0x0300 -) - -const ( - maxPlaintext = 16384 // maximum plaintext payload length - maxCiphertext = 16384 + 2048 // maximum ciphertext payload length - maxCiphertextTLS13 = 16384 + 256 // maximum ciphertext length in TLS 1.3 - recordHeaderLen = 5 // record header length - maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) - maxUselessRecords = 16 // maximum number of consecutive non-advancing records -) - -// TLS record types. -type recordType uint8 - -const ( - recordTypeChangeCipherSpec recordType = 20 - recordTypeAlert recordType = 21 - recordTypeHandshake recordType = 22 - recordTypeApplicationData recordType = 23 -) - -// TLS handshake message types. -const ( - typeHelloRequest uint8 = 0 - typeClientHello uint8 = 1 - typeServerHello uint8 = 2 - typeNewSessionTicket uint8 = 4 - typeEndOfEarlyData uint8 = 5 - typeEncryptedExtensions uint8 = 8 - typeCertificate uint8 = 11 - typeServerKeyExchange uint8 = 12 - typeCertificateRequest uint8 = 13 - typeServerHelloDone uint8 = 14 - typeCertificateVerify uint8 = 15 - typeClientKeyExchange uint8 = 16 - typeFinished uint8 = 20 - typeCertificateStatus uint8 = 22 - typeKeyUpdate uint8 = 24 - typeNextProtocol uint8 = 67 // Not IANA assigned - typeMessageHash uint8 = 254 // synthetic message -) - -// TLS compression types. -const ( - compressionNone uint8 = 0 -) - -// TLS extension numbers -const ( - extensionServerName uint16 = 0 - extensionStatusRequest uint16 = 5 - extensionSupportedCurves uint16 = 10 // supported_groups in TLS 1.3, see RFC 8446, Section 4.2.7 - extensionSupportedPoints uint16 = 11 - extensionSignatureAlgorithms uint16 = 13 - extensionALPN uint16 = 16 - extensionSCT uint16 = 18 - extensionSessionTicket uint16 = 35 - extensionPreSharedKey uint16 = 41 - extensionEarlyData uint16 = 42 - extensionSupportedVersions uint16 = 43 - extensionCookie uint16 = 44 - extensionPSKModes uint16 = 45 - extensionCertificateAuthorities uint16 = 47 - extensionSignatureAlgorithmsCert uint16 = 50 - extensionKeyShare uint16 = 51 - extensionQUICTransportParameters uint16 = 57 - extensionRenegotiationInfo uint16 = 0xff01 -) - -// TLS signaling cipher suite values -const ( - scsvRenegotiation uint16 = 0x00ff -) - -// CurveID is a tls.CurveID -type CurveID = tls.CurveID - -const ( - CurveP256 CurveID = 23 - CurveP384 CurveID = 24 - CurveP521 CurveID = 25 - X25519 CurveID = 29 -) - -// TLS 1.3 Key Share. See RFC 8446, Section 4.2.8. -type keyShare struct { - group CurveID - data []byte -} - -// TLS 1.3 PSK Key Exchange Modes. See RFC 8446, Section 4.2.9. -const ( - pskModePlain uint8 = 0 - pskModeDHE uint8 = 1 -) - -// TLS 1.3 PSK Identity. Can be a Session Ticket, or a reference to a saved -// session. See RFC 8446, Section 4.2.11. -type pskIdentity struct { - label []byte - obfuscatedTicketAge uint32 -} - -// TLS Elliptic Curve Point Formats -// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 -const ( - pointFormatUncompressed uint8 = 0 -) - -// TLS CertificateStatusType (RFC 3546) -const ( - statusTypeOCSP uint8 = 1 -) - -// Certificate types (for certificateRequestMsg) -const ( - certTypeRSASign = 1 - certTypeECDSASign = 64 // ECDSA or EdDSA keys, see RFC 8422, Section 3. -) - -// Signature algorithms (for internal signaling use). Starting at 225 to avoid overlap with -// TLS 1.2 codepoints (RFC 5246, Appendix A.4.1), with which these have nothing to do. -const ( - signaturePKCS1v15 uint8 = iota + 225 - signatureRSAPSS - signatureECDSA - signatureEd25519 -) - -// directSigning is a standard Hash value that signals that no pre-hashing -// should be performed, and that the input should be signed directly. It is the -// hash function associated with the Ed25519 signature scheme. -var directSigning crypto.Hash = 0 - -// defaultSupportedSignatureAlgorithms contains the signature and hash algorithms that -// the code advertises as supported in a TLS 1.2+ ClientHello and in a TLS 1.2+ -// CertificateRequest. The two fields are merged to match with TLS 1.3. -// Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc. -var defaultSupportedSignatureAlgorithms = []SignatureScheme{ - PSSWithSHA256, - ECDSAWithP256AndSHA256, - Ed25519, - PSSWithSHA384, - PSSWithSHA512, - PKCS1WithSHA256, - PKCS1WithSHA384, - PKCS1WithSHA512, - ECDSAWithP384AndSHA384, - ECDSAWithP521AndSHA512, - PKCS1WithSHA1, - ECDSAWithSHA1, -} - -// helloRetryRequestRandom is set as the Random value of a ServerHello -// to signal that the message is actually a HelloRetryRequest. -var helloRetryRequestRandom = []byte{ // See RFC 8446, Section 4.1.3. - 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, - 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, - 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, - 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C, -} - -const ( - // downgradeCanaryTLS12 or downgradeCanaryTLS11 is embedded in the server - // random as a downgrade protection if the server would be capable of - // negotiating a higher version. See RFC 8446, Section 4.1.3. - downgradeCanaryTLS12 = "DOWNGRD\x01" - downgradeCanaryTLS11 = "DOWNGRD\x00" -) - -// testingOnlyForceDowngradeCanary is set in tests to force the server side to -// include downgrade canaries even if it's using its highers supported version. -var testingOnlyForceDowngradeCanary bool - -type ConnectionState = tls.ConnectionState - -// ConnectionState records basic TLS details about the connection. -type connectionState struct { - // Version is the TLS version used by the connection (e.g. VersionTLS12). - Version uint16 - - // HandshakeComplete is true if the handshake has concluded. - HandshakeComplete bool - - // DidResume is true if this connection was successfully resumed from a - // previous session with a session ticket or similar mechanism. - DidResume bool - - // CipherSuite is the cipher suite negotiated for the connection (e.g. - // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_AES_128_GCM_SHA256). - CipherSuite uint16 - - // NegotiatedProtocol is the application protocol negotiated with ALPN. - NegotiatedProtocol string - - // NegotiatedProtocolIsMutual used to indicate a mutual NPN negotiation. - // - // Deprecated: this value is always true. - NegotiatedProtocolIsMutual bool - - // ServerName is the value of the Server Name Indication extension sent by - // the client. It's available both on the server and on the client side. - ServerName string - - // PeerCertificates are the parsed certificates sent by the peer, in the - // order in which they were sent. The first element is the leaf certificate - // that the connection is verified against. - // - // On the client side, it can't be empty. On the server side, it can be - // empty if Config.ClientAuth is not RequireAnyClientCert or - // RequireAndVerifyClientCert. - // - // PeerCertificates and its contents should not be modified. - PeerCertificates []*x509.Certificate - - // VerifiedChains is a list of one or more chains where the first element is - // PeerCertificates[0] and the last element is from Config.RootCAs (on the - // client side) or Config.ClientCAs (on the server side). - // - // On the client side, it's set if Config.InsecureSkipVerify is false. On - // the server side, it's set if Config.ClientAuth is VerifyClientCertIfGiven - // (and the peer provided a certificate) or RequireAndVerifyClientCert. - // - // VerifiedChains and its contents should not be modified. - VerifiedChains [][]*x509.Certificate - - // SignedCertificateTimestamps is a list of SCTs provided by the peer - // through the TLS handshake for the leaf certificate, if any. - SignedCertificateTimestamps [][]byte - - // OCSPResponse is a stapled Online Certificate Status Protocol (OCSP) - // response provided by the peer for the leaf certificate, if any. - OCSPResponse []byte - - // TLSUnique contains the "tls-unique" channel binding value (see RFC 5929, - // Section 3). This value will be nil for TLS 1.3 connections and for all - // resumed connections. - // - // Deprecated: there are conditions in which this value might not be unique - // to a connection. See the Security Considerations sections of RFC 5705 and - // RFC 7627, and https://mitls.org/pages/attacks/3SHAKE#channelbindings. - TLSUnique []byte - - // ekm is a closure exposed via ExportKeyingMaterial. - ekm func(label string, context []byte, length int) ([]byte, error) -} - -// ClientAuthType is tls.ClientAuthType -type ClientAuthType = tls.ClientAuthType - -const ( - NoClientCert = tls.NoClientCert - RequestClientCert = tls.RequestClientCert - RequireAnyClientCert = tls.RequireAnyClientCert - VerifyClientCertIfGiven = tls.VerifyClientCertIfGiven - RequireAndVerifyClientCert = tls.RequireAndVerifyClientCert -) - -// requiresClientCert reports whether the ClientAuthType requires a client -// certificate to be provided. -func requiresClientCert(c ClientAuthType) bool { - switch c { - case RequireAnyClientCert, RequireAndVerifyClientCert: - return true - default: - return false - } -} - -// ClientSessionState contains the state needed by clients to resume TLS -// sessions. -type ClientSessionState = tls.ClientSessionState - -type clientSessionState struct { - sessionTicket []uint8 // Encrypted ticket used for session resumption with server - vers uint16 // TLS version negotiated for the session - cipherSuite uint16 // Ciphersuite negotiated for the session - masterSecret []byte // Full handshake MasterSecret, or TLS 1.3 resumption_master_secret - serverCertificates []*x509.Certificate // Certificate chain presented by the server - verifiedChains [][]*x509.Certificate // Certificate chains we built for verification - receivedAt time.Time // When the session ticket was received from the server - ocspResponse []byte // Stapled OCSP response presented by the server - scts [][]byte // SCTs presented by the server - - // TLS 1.3 fields. - nonce []byte // Ticket nonce sent by the server, to derive PSK - useBy time.Time // Expiration of the ticket lifetime as set by the server - ageAdd uint32 // Random obfuscation factor for sending the ticket age -} - -// ClientSessionCache is a cache of ClientSessionState objects that can be used -// by a client to resume a TLS session with a given server. ClientSessionCache -// implementations should expect to be called concurrently from different -// goroutines. Up to TLS 1.2, only ticket-based resumption is supported, not -// SessionID-based resumption. In TLS 1.3 they were merged into PSK modes, which -// are supported via this interface. -type ClientSessionCache = tls.ClientSessionCache - -// SignatureScheme is a tls.SignatureScheme -type SignatureScheme = tls.SignatureScheme - -const ( - // RSASSA-PKCS1-v1_5 algorithms. - PKCS1WithSHA256 SignatureScheme = 0x0401 - PKCS1WithSHA384 SignatureScheme = 0x0501 - PKCS1WithSHA512 SignatureScheme = 0x0601 - - // RSASSA-PSS algorithms with public key OID rsaEncryption. - PSSWithSHA256 SignatureScheme = 0x0804 - PSSWithSHA384 SignatureScheme = 0x0805 - PSSWithSHA512 SignatureScheme = 0x0806 - - // ECDSA algorithms. Only constrained to a specific curve in TLS 1.3. - ECDSAWithP256AndSHA256 SignatureScheme = 0x0403 - ECDSAWithP384AndSHA384 SignatureScheme = 0x0503 - ECDSAWithP521AndSHA512 SignatureScheme = 0x0603 - - // EdDSA algorithms. - Ed25519 SignatureScheme = 0x0807 - - // Legacy signature and hash algorithms for TLS 1.2. - PKCS1WithSHA1 SignatureScheme = 0x0201 - ECDSAWithSHA1 SignatureScheme = 0x0203 -) - -// ClientHelloInfo contains information from a ClientHello message in order to -// guide application logic in the GetCertificate and GetConfigForClient callbacks. -type ClientHelloInfo = tls.ClientHelloInfo - -type clientHelloInfo struct { - // CipherSuites lists the CipherSuites supported by the client (e.g. - // TLS_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256). - CipherSuites []uint16 - - // ServerName indicates the name of the server requested by the client - // in order to support virtual hosting. ServerName is only set if the - // client is using SNI (see RFC 4366, Section 3.1). - ServerName string - - // SupportedCurves lists the elliptic curves supported by the client. - // SupportedCurves is set only if the Supported Elliptic Curves - // Extension is being used (see RFC 4492, Section 5.1.1). - SupportedCurves []CurveID - - // SupportedPoints lists the point formats supported by the client. - // SupportedPoints is set only if the Supported Point Formats Extension - // is being used (see RFC 4492, Section 5.1.2). - SupportedPoints []uint8 - - // SignatureSchemes lists the signature and hash schemes that the client - // is willing to verify. SignatureSchemes is set only if the Signature - // Algorithms Extension is being used (see RFC 5246, Section 7.4.1.4.1). - SignatureSchemes []SignatureScheme - - // SupportedProtos lists the application protocols supported by the client. - // SupportedProtos is set only if the Application-Layer Protocol - // Negotiation Extension is being used (see RFC 7301, Section 3.1). - // - // Servers can select a protocol by setting Config.NextProtos in a - // GetConfigForClient return value. - SupportedProtos []string - - // SupportedVersions lists the TLS versions supported by the client. - // For TLS versions less than 1.3, this is extrapolated from the max - // version advertised by the client, so values other than the greatest - // might be rejected if used. - SupportedVersions []uint16 - - // Conn is the underlying net.Conn for the connection. Do not read - // from, or write to, this connection; that will cause the TLS - // connection to fail. - Conn net.Conn - - // config is embedded by the GetCertificate or GetConfigForClient caller, - // for use with SupportsCertificate. - config *Config - - // ctx is the context of the handshake that is in progress. - ctx context.Context -} - -// Context returns the context of the handshake that is in progress. -// This context is a child of the context passed to HandshakeContext, -// if any, and is canceled when the handshake concludes. -func (c *clientHelloInfo) Context() context.Context { - return c.ctx -} - -// CertificateRequestInfo contains information from a server's -// CertificateRequest message, which is used to demand a certificate and proof -// of control from a client. -type CertificateRequestInfo = tls.CertificateRequestInfo - -type certificateRequestInfo struct { - // AcceptableCAs contains zero or more, DER-encoded, X.501 - // Distinguished Names. These are the names of root or intermediate CAs - // that the server wishes the returned certificate to be signed by. An - // empty slice indicates that the server has no preference. - AcceptableCAs [][]byte - - // SignatureSchemes lists the signature schemes that the server is - // willing to verify. - SignatureSchemes []SignatureScheme - - // Version is the TLS version that was negotiated for this connection. - Version uint16 - - // ctx is the context of the handshake that is in progress. - ctx context.Context -} - -// Context returns the context of the handshake that is in progress. -// This context is a child of the context passed to HandshakeContext, -// if any, and is canceled when the handshake concludes. -func (c *certificateRequestInfo) Context() context.Context { - return c.ctx -} - -// RenegotiationSupport enumerates the different levels of support for TLS -// renegotiation. TLS renegotiation is the act of performing subsequent -// handshakes on a connection after the first. This significantly complicates -// the state machine and has been the source of numerous, subtle security -// issues. Initiating a renegotiation is not supported, but support for -// accepting renegotiation requests may be enabled. -// -// Even when enabled, the server may not change its identity between handshakes -// (i.e. the leaf certificate must be the same). Additionally, concurrent -// handshake and application data flow is not permitted so renegotiation can -// only be used with protocols that synchronise with the renegotiation, such as -// HTTPS. -// -// Renegotiation is not defined in TLS 1.3. -type RenegotiationSupport = tls.RenegotiationSupport - -const ( - // RenegotiateNever disables renegotiation. - RenegotiateNever = tls.RenegotiateNever - - // RenegotiateOnceAsClient allows a remote server to request - // renegotiation once per connection. - RenegotiateOnceAsClient = tls.RenegotiateOnceAsClient - - // RenegotiateFreelyAsClient allows a remote server to repeatedly - // request renegotiation. - RenegotiateFreelyAsClient = tls.RenegotiateFreelyAsClient -) - -// A Config structure is used to configure a TLS client or server. -// After one has been passed to a TLS function it must not be -// modified. A Config may be reused; the tls package will also not -// modify it. -type Config = tls.Config - -type config struct { - // Rand provides the source of entropy for nonces and RSA blinding. - // If Rand is nil, TLS uses the cryptographic random reader in package - // crypto/rand. - // The Reader must be safe for use by multiple goroutines. - Rand io.Reader - - // Time returns the current time as the number of seconds since the epoch. - // If Time is nil, TLS uses time.Now. - Time func() time.Time - - // Certificates contains one or more certificate chains to present to the - // other side of the connection. The first certificate compatible with the - // peer's requirements is selected automatically. - // - // Server configurations must set one of Certificates, GetCertificate or - // GetConfigForClient. Clients doing client-authentication may set either - // Certificates or GetClientCertificate. - // - // Note: if there are multiple Certificates, and they don't have the - // optional field Leaf set, certificate selection will incur a significant - // per-handshake performance cost. - Certificates []Certificate - - // NameToCertificate maps from a certificate name to an element of - // Certificates. Note that a certificate name can be of the form - // '*.example.com' and so doesn't have to be a domain name as such. - // - // Deprecated: NameToCertificate only allows associating a single - // certificate with a given name. Leave this field nil to let the library - // select the first compatible chain from Certificates. - NameToCertificate map[string]*Certificate - - // GetCertificate returns a Certificate based on the given - // ClientHelloInfo. It will only be called if the client supplies SNI - // information or if Certificates is empty. - // - // If GetCertificate is nil or returns nil, then the certificate is - // retrieved from NameToCertificate. If NameToCertificate is nil, the - // best element of Certificates will be used. - // - // Once a Certificate is returned it should not be modified. - GetCertificate func(*ClientHelloInfo) (*Certificate, error) - - // GetClientCertificate, if not nil, is called when a server requests a - // certificate from a client. If set, the contents of Certificates will - // be ignored. - // - // If GetClientCertificate returns an error, the handshake will be - // aborted and that error will be returned. Otherwise - // GetClientCertificate must return a non-nil Certificate. If - // Certificate.Certificate is empty then no certificate will be sent to - // the server. If this is unacceptable to the server then it may abort - // the handshake. - // - // GetClientCertificate may be called multiple times for the same - // connection if renegotiation occurs or if TLS 1.3 is in use. - // - // Once a Certificate is returned it should not be modified. - GetClientCertificate func(*CertificateRequestInfo) (*Certificate, error) - - // GetConfigForClient, if not nil, is called after a ClientHello is - // received from a client. It may return a non-nil Config in order to - // change the Config that will be used to handle this connection. If - // the returned Config is nil, the original Config will be used. The - // Config returned by this callback may not be subsequently modified. - // - // If GetConfigForClient is nil, the Config passed to Server() will be - // used for all connections. - // - // If SessionTicketKey was explicitly set on the returned Config, or if - // SetSessionTicketKeys was called on the returned Config, those keys will - // be used. Otherwise, the original Config keys will be used (and possibly - // rotated if they are automatically managed). - GetConfigForClient func(*ClientHelloInfo) (*Config, error) - - // VerifyPeerCertificate, if not nil, is called after normal - // certificate verification by either a TLS client or server. It - // receives the raw ASN.1 certificates provided by the peer and also - // any verified chains that normal processing found. If it returns a - // non-nil error, the handshake is aborted and that error results. - // - // If normal verification fails then the handshake will abort before - // considering this callback. If normal verification is disabled by - // setting InsecureSkipVerify, or (for a server) when ClientAuth is - // RequestClientCert or RequireAnyClientCert, then this callback will - // be considered but the verifiedChains argument will always be nil. - // - // verifiedChains and its contents should not be modified. - VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error - - // VerifyConnection, if not nil, is called after normal certificate - // verification and after VerifyPeerCertificate by either a TLS client - // or server. If it returns a non-nil error, the handshake is aborted - // and that error results. - // - // If normal verification fails then the handshake will abort before - // considering this callback. This callback will run for all connections - // regardless of InsecureSkipVerify or ClientAuth settings. - VerifyConnection func(ConnectionState) error - - // RootCAs defines the set of root certificate authorities - // that clients use when verifying server certificates. - // If RootCAs is nil, TLS uses the host's root CA set. - RootCAs *x509.CertPool - - // NextProtos is a list of supported application level protocols, in - // order of preference. If both peers support ALPN, the selected - // protocol will be one from this list, and the connection will fail - // if there is no mutually supported protocol. If NextProtos is empty - // or the peer doesn't support ALPN, the connection will succeed and - // ConnectionState.NegotiatedProtocol will be empty. - NextProtos []string - - // ServerName is used to verify the hostname on the returned - // certificates unless InsecureSkipVerify is given. It is also included - // in the client's handshake to support virtual hosting unless it is - // an IP address. - ServerName string - - // ClientAuth determines the server's policy for - // TLS Client Authentication. The default is NoClientCert. - ClientAuth ClientAuthType - - // ClientCAs defines the set of root certificate authorities - // that servers use if required to verify a client certificate - // by the policy in ClientAuth. - ClientCAs *x509.CertPool - - // InsecureSkipVerify controls whether a client verifies the server's - // certificate chain and host name. If InsecureSkipVerify is true, crypto/tls - // accepts any certificate presented by the server and any host name in that - // certificate. In this mode, TLS is susceptible to machine-in-the-middle - // attacks unless custom verification is used. This should be used only for - // testing or in combination with VerifyConnection or VerifyPeerCertificate. - InsecureSkipVerify bool - - // CipherSuites is a list of enabled TLS 1.0–1.2 cipher suites. The order of - // the list is ignored. Note that TLS 1.3 ciphersuites are not configurable. - // - // If CipherSuites is nil, a safe default list is used. The default cipher - // suites might change over time. - CipherSuites []uint16 - - // PreferServerCipherSuites is a legacy field and has no effect. - // - // It used to control whether the server would follow the client's or the - // server's preference. Servers now select the best mutually supported - // cipher suite based on logic that takes into account inferred client - // hardware, server hardware, and security. - // - // Deprecated: PreferServerCipherSuites is ignored. - PreferServerCipherSuites bool - - // SessionTicketsDisabled may be set to true to disable session ticket and - // PSK (resumption) support. Note that on clients, session ticket support is - // also disabled if ClientSessionCache is nil. - SessionTicketsDisabled bool - - // SessionTicketKey is used by TLS servers to provide session resumption. - // See RFC 5077 and the PSK mode of RFC 8446. If zero, it will be filled - // with random data before the first server handshake. - // - // Deprecated: if this field is left at zero, session ticket keys will be - // automatically rotated every day and dropped after seven days. For - // customizing the rotation schedule or synchronizing servers that are - // terminating connections for the same host, use SetSessionTicketKeys. - SessionTicketKey [32]byte - - // ClientSessionCache is a cache of ClientSessionState entries for TLS - // session resumption. It is only used by clients. - ClientSessionCache ClientSessionCache - - // MinVersion contains the minimum TLS version that is acceptable. - // - // By default, TLS 1.2 is currently used as the minimum when acting as a - // client, and TLS 1.0 when acting as a server. TLS 1.0 is the minimum - // supported by this package, both as a client and as a server. - // - // The client-side default can temporarily be reverted to TLS 1.0 by - // including the value "x509sha1=1" in the GODEBUG environment variable. - // Note that this option will be removed in Go 1.19 (but it will still be - // possible to set this field to VersionTLS10 explicitly). - MinVersion uint16 - - // MaxVersion contains the maximum TLS version that is acceptable. - // - // By default, the maximum version supported by this package is used, - // which is currently TLS 1.3. - MaxVersion uint16 - - // CurvePreferences contains the elliptic curves that will be used in - // an ECDHE handshake, in preference order. If empty, the default will - // be used. The client will use the first preference as the type for - // its key share in TLS 1.3. This may change in the future. - CurvePreferences []CurveID - - // DynamicRecordSizingDisabled disables adaptive sizing of TLS records. - // When true, the largest possible TLS record size is always used. When - // false, the size of TLS records may be adjusted in an attempt to - // improve latency. - DynamicRecordSizingDisabled bool - - // Renegotiation controls what types of renegotiation are supported. - // The default, none, is correct for the vast majority of applications. - Renegotiation RenegotiationSupport - - // KeyLogWriter optionally specifies a destination for TLS master secrets - // in NSS key log format that can be used to allow external programs - // such as Wireshark to decrypt TLS connections. - // See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. - // Use of KeyLogWriter compromises security and should only be - // used for debugging. - KeyLogWriter io.Writer - - // mutex protects sessionTicketKeys and autoSessionTicketKeys. - mutex sync.RWMutex - // sessionTicketKeys contains zero or more ticket keys. If set, it means - // the keys were set with SessionTicketKey or SetSessionTicketKeys. The - // first key is used for new tickets and any subsequent keys can be used to - // decrypt old tickets. The slice contents are not protected by the mutex - // and are immutable. - sessionTicketKeys []ticketKey - // autoSessionTicketKeys is like sessionTicketKeys but is owned by the - // auto-rotation logic. See Config.ticketKeys. - autoSessionTicketKeys []ticketKey -} - -type ExtraConfig struct { - // If Enable0RTT is enabled, the client will be allowed to send early data when resuming a session. - // - // It has no meaning on the client. - Enable0RTT bool - - // GetAppDataForSessionTicket requests application data to be sent with a session ticket. - // - // It has no meaning on the client. - GetAppDataForSessionTicket func() []byte - - // The Accept0RTT callback is called when the client offers 0-RTT. - // The server then has to decide if it wants to accept or reject 0-RTT. - // It is only used for servers. - Accept0RTT func(appData []byte) bool - - // Is called when the client saves a session ticket to the session ticket. - // This gives the application the opportunity to save some data along with the ticket, - // which can be restored when the session ticket is used. - GetAppDataForSessionState func() []byte - - // Is called when the client uses a session ticket. - // Restores the application data that was saved earlier on GetAppDataForSessionTicket. - SetAppDataFromSessionState func([]byte) (allowEarlyData bool) -} - -// Clone clones. -func (c *ExtraConfig) Clone() *ExtraConfig { - return &ExtraConfig{ - Enable0RTT: c.Enable0RTT, - GetAppDataForSessionTicket: c.GetAppDataForSessionTicket, - Accept0RTT: c.Accept0RTT, - GetAppDataForSessionState: c.GetAppDataForSessionState, - SetAppDataFromSessionState: c.SetAppDataFromSessionState, - } -} - -const ( - // ticketKeyNameLen is the number of bytes of identifier that is prepended to - // an encrypted session ticket in order to identify the key used to encrypt it. - ticketKeyNameLen = 16 - - // ticketKeyLifetime is how long a ticket key remains valid and can be used to - // resume a client connection. - ticketKeyLifetime = 7 * 24 * time.Hour // 7 days - - // ticketKeyRotation is how often the server should rotate the session ticket key - // that is used for new tickets. - ticketKeyRotation = 24 * time.Hour -) - -// ticketKey is the internal representation of a session ticket key. -type ticketKey struct { - // keyName is an opaque byte string that serves to identify the session - // ticket key. It's exposed as plaintext in every session ticket. - keyName [ticketKeyNameLen]byte - aesKey [16]byte - hmacKey [16]byte - // created is the time at which this ticket key was created. See Config.ticketKeys. - created time.Time -} - -// ticketKeyFromBytes converts from the external representation of a session -// ticket key to a ticketKey. Externally, session ticket keys are 32 random -// bytes and this function expands that into sufficient name and key material. -func (c *config) ticketKeyFromBytes(b [32]byte) (key ticketKey) { - hashed := sha512.Sum512(b[:]) - copy(key.keyName[:], hashed[:ticketKeyNameLen]) - copy(key.aesKey[:], hashed[ticketKeyNameLen:ticketKeyNameLen+16]) - copy(key.hmacKey[:], hashed[ticketKeyNameLen+16:ticketKeyNameLen+32]) - key.created = c.time() - return key -} - -// maxSessionTicketLifetime is the maximum allowed lifetime of a TLS 1.3 session -// ticket, and the lifetime we set for tickets we send. -const maxSessionTicketLifetime = 7 * 24 * time.Hour - -// Clone returns a shallow clone of c or nil if c is nil. It is safe to clone a Config that is -// being used concurrently by a TLS client or server. -func (c *config) Clone() *config { - if c == nil { - return nil - } - c.mutex.RLock() - defer c.mutex.RUnlock() - return &config{ - Rand: c.Rand, - Time: c.Time, - Certificates: c.Certificates, - NameToCertificate: c.NameToCertificate, - GetCertificate: c.GetCertificate, - GetClientCertificate: c.GetClientCertificate, - GetConfigForClient: c.GetConfigForClient, - VerifyPeerCertificate: c.VerifyPeerCertificate, - VerifyConnection: c.VerifyConnection, - RootCAs: c.RootCAs, - NextProtos: c.NextProtos, - ServerName: c.ServerName, - ClientAuth: c.ClientAuth, - ClientCAs: c.ClientCAs, - InsecureSkipVerify: c.InsecureSkipVerify, - CipherSuites: c.CipherSuites, - PreferServerCipherSuites: c.PreferServerCipherSuites, - SessionTicketsDisabled: c.SessionTicketsDisabled, - SessionTicketKey: c.SessionTicketKey, - ClientSessionCache: c.ClientSessionCache, - MinVersion: c.MinVersion, - MaxVersion: c.MaxVersion, - CurvePreferences: c.CurvePreferences, - DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, - Renegotiation: c.Renegotiation, - KeyLogWriter: c.KeyLogWriter, - sessionTicketKeys: c.sessionTicketKeys, - autoSessionTicketKeys: c.autoSessionTicketKeys, - } -} - -// deprecatedSessionTicketKey is set as the prefix of SessionTicketKey if it was -// randomized for backwards compatibility but is not in use. -var deprecatedSessionTicketKey = []byte("DEPRECATED") - -// initLegacySessionTicketKeyRLocked ensures the legacy SessionTicketKey field is -// randomized if empty, and that sessionTicketKeys is populated from it otherwise. -func (c *config) initLegacySessionTicketKeyRLocked() { - // Don't write if SessionTicketKey is already defined as our deprecated string, - // or if it is defined by the user but sessionTicketKeys is already set. - if c.SessionTicketKey != [32]byte{} && - (bytes.HasPrefix(c.SessionTicketKey[:], deprecatedSessionTicketKey) || len(c.sessionTicketKeys) > 0) { - return - } - - // We need to write some data, so get an exclusive lock and re-check any conditions. - c.mutex.RUnlock() - defer c.mutex.RLock() - c.mutex.Lock() - defer c.mutex.Unlock() - if c.SessionTicketKey == [32]byte{} { - if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil { - panic(fmt.Sprintf("tls: unable to generate random session ticket key: %v", err)) - } - // Write the deprecated prefix at the beginning so we know we created - // it. This key with the DEPRECATED prefix isn't used as an actual - // session ticket key, and is only randomized in case the application - // reuses it for some reason. - copy(c.SessionTicketKey[:], deprecatedSessionTicketKey) - } else if !bytes.HasPrefix(c.SessionTicketKey[:], deprecatedSessionTicketKey) && len(c.sessionTicketKeys) == 0 { - c.sessionTicketKeys = []ticketKey{c.ticketKeyFromBytes(c.SessionTicketKey)} - } - -} - -// ticketKeys returns the ticketKeys for this connection. -// If configForClient has explicitly set keys, those will -// be returned. Otherwise, the keys on c will be used and -// may be rotated if auto-managed. -// During rotation, any expired session ticket keys are deleted from -// c.sessionTicketKeys. If the session ticket key that is currently -// encrypting tickets (ie. the first ticketKey in c.sessionTicketKeys) -// is not fresh, then a new session ticket key will be -// created and prepended to c.sessionTicketKeys. -func (c *config) ticketKeys(configForClient *config) []ticketKey { - // If the ConfigForClient callback returned a Config with explicitly set - // keys, use those, otherwise just use the original Config. - if configForClient != nil { - configForClient.mutex.RLock() - if configForClient.SessionTicketsDisabled { - return nil - } - configForClient.initLegacySessionTicketKeyRLocked() - if len(configForClient.sessionTicketKeys) != 0 { - ret := configForClient.sessionTicketKeys - configForClient.mutex.RUnlock() - return ret - } - configForClient.mutex.RUnlock() - } - - c.mutex.RLock() - defer c.mutex.RUnlock() - if c.SessionTicketsDisabled { - return nil - } - c.initLegacySessionTicketKeyRLocked() - if len(c.sessionTicketKeys) != 0 { - return c.sessionTicketKeys - } - // Fast path for the common case where the key is fresh enough. - if len(c.autoSessionTicketKeys) > 0 && c.time().Sub(c.autoSessionTicketKeys[0].created) < ticketKeyRotation { - return c.autoSessionTicketKeys - } - - // autoSessionTicketKeys are managed by auto-rotation. - c.mutex.RUnlock() - defer c.mutex.RLock() - c.mutex.Lock() - defer c.mutex.Unlock() - // Re-check the condition in case it changed since obtaining the new lock. - if len(c.autoSessionTicketKeys) == 0 || c.time().Sub(c.autoSessionTicketKeys[0].created) >= ticketKeyRotation { - var newKey [32]byte - if _, err := io.ReadFull(c.rand(), newKey[:]); err != nil { - panic(fmt.Sprintf("unable to generate random session ticket key: %v", err)) - } - valid := make([]ticketKey, 0, len(c.autoSessionTicketKeys)+1) - valid = append(valid, c.ticketKeyFromBytes(newKey)) - for _, k := range c.autoSessionTicketKeys { - // While rotating the current key, also remove any expired ones. - if c.time().Sub(k.created) < ticketKeyLifetime { - valid = append(valid, k) - } - } - c.autoSessionTicketKeys = valid - } - return c.autoSessionTicketKeys -} - -// SetSessionTicketKeys updates the session ticket keys for a server. -// -// The first key will be used when creating new tickets, while all keys can be -// used for decrypting tickets. It is safe to call this function while the -// server is running in order to rotate the session ticket keys. The function -// will panic if keys is empty. -// -// Calling this function will turn off automatic session ticket key rotation. -// -// If multiple servers are terminating connections for the same host they should -// all have the same session ticket keys. If the session ticket keys leaks, -// previously recorded and future TLS connections using those keys might be -// compromised. -func (c *config) SetSessionTicketKeys(keys [][32]byte) { - if len(keys) == 0 { - panic("tls: keys must have at least one key") - } - - newKeys := make([]ticketKey, len(keys)) - for i, bytes := range keys { - newKeys[i] = c.ticketKeyFromBytes(bytes) - } - - c.mutex.Lock() - c.sessionTicketKeys = newKeys - c.mutex.Unlock() -} - -func (c *config) rand() io.Reader { - r := c.Rand - if r == nil { - return rand.Reader - } - return r -} - -func (c *config) time() time.Time { - t := c.Time - if t == nil { - t = time.Now - } - return t() -} - -func (c *config) cipherSuites() []uint16 { - if needFIPS() { - return fipsCipherSuites(c) - } - if c.CipherSuites != nil { - return c.CipherSuites - } - return defaultCipherSuites -} - -var supportedVersions = []uint16{ - VersionTLS13, - VersionTLS12, - VersionTLS11, - VersionTLS10, -} - -// roleClient and roleServer are meant to call supportedVersions and parents -// with more readability at the callsite. -const roleClient = true -const roleServer = false - -func (c *config) supportedVersions(isClient bool) []uint16 { - versions := make([]uint16, 0, len(supportedVersions)) - for _, v := range supportedVersions { - if needFIPS() && (v < fipsMinVersion(c) || v > fipsMaxVersion(c)) { - continue - } - if (c == nil || c.MinVersion == 0) && - isClient && v < VersionTLS12 { - continue - } - if c != nil && c.MinVersion != 0 && v < c.MinVersion { - continue - } - if c != nil && c.MaxVersion != 0 && v > c.MaxVersion { - continue - } - versions = append(versions, v) - } - return versions -} - -func (c *config) maxSupportedVersion(isClient bool) uint16 { - supportedVersions := c.supportedVersions(isClient) - if len(supportedVersions) == 0 { - return 0 - } - return supportedVersions[0] -} - -// supportedVersionsFromMax returns a list of supported versions derived from a -// legacy maximum version value. Note that only versions supported by this -// library are returned. Any newer peer will use supportedVersions anyway. -func supportedVersionsFromMax(maxVersion uint16) []uint16 { - versions := make([]uint16, 0, len(supportedVersions)) - for _, v := range supportedVersions { - if v > maxVersion { - continue - } - versions = append(versions, v) - } - return versions -} - -var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521} - -func (c *config) curvePreferences() []CurveID { - if needFIPS() { - return fipsCurvePreferences(c) - } - if c == nil || len(c.CurvePreferences) == 0 { - return defaultCurvePreferences - } - return c.CurvePreferences -} - -func (c *config) supportsCurve(curve CurveID) bool { - for _, cc := range c.curvePreferences() { - if cc == curve { - return true - } - } - return false -} - -// mutualVersion returns the protocol version to use given the advertised -// versions of the peer. Priority is given to the peer preference order. -func (c *config) mutualVersion(isClient bool, peerVersions []uint16) (uint16, bool) { - supportedVersions := c.supportedVersions(isClient) - for _, peerVersion := range peerVersions { - for _, v := range supportedVersions { - if v == peerVersion { - return v, true - } - } - } - return 0, false -} - -var errNoCertificates = errors.New("tls: no certificates configured") - -// getCertificate returns the best certificate for the given ClientHelloInfo, -// defaulting to the first element of c.Certificates. -func (c *config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) { - if c.GetCertificate != nil && - (len(c.Certificates) == 0 || len(clientHello.ServerName) > 0) { - cert, err := c.GetCertificate(clientHello) - if cert != nil || err != nil { - return cert, err - } - } - - if len(c.Certificates) == 0 { - return nil, errNoCertificates - } - - if len(c.Certificates) == 1 { - // There's only one choice, so no point doing any work. - return &c.Certificates[0], nil - } - - if c.NameToCertificate != nil { - name := strings.ToLower(clientHello.ServerName) - if cert, ok := c.NameToCertificate[name]; ok { - return cert, nil - } - if len(name) > 0 { - labels := strings.Split(name, ".") - labels[0] = "*" - wildcardName := strings.Join(labels, ".") - if cert, ok := c.NameToCertificate[wildcardName]; ok { - return cert, nil - } - } - } - - for _, cert := range c.Certificates { - if err := clientHello.SupportsCertificate(&cert); err == nil { - return &cert, nil - } - } - - // If nothing matches, return the first certificate. - return &c.Certificates[0], nil -} - -// SupportsCertificate returns nil if the provided certificate is supported by -// the client that sent the ClientHello. Otherwise, it returns an error -// describing the reason for the incompatibility. -// -// If this ClientHelloInfo was passed to a GetConfigForClient or GetCertificate -// callback, this method will take into account the associated Config. Note that -// if GetConfigForClient returns a different Config, the change can't be -// accounted for by this method. -// -// This function will call x509.ParseCertificate unless c.Leaf is set, which can -// incur a significant performance cost. -func (chi *clientHelloInfo) SupportsCertificate(c *Certificate) error { - // Note we don't currently support certificate_authorities nor - // signature_algorithms_cert, and don't check the algorithms of the - // signatures on the chain (which anyway are a SHOULD, see RFC 8446, - // Section 4.4.2.2). - - config := chi.config - if config == nil { - config = &Config{} - } - conf := fromConfig(config) - vers, ok := conf.mutualVersion(roleServer, chi.SupportedVersions) - if !ok { - return errors.New("no mutually supported protocol versions") - } - - // If the client specified the name they are trying to connect to, the - // certificate needs to be valid for it. - if chi.ServerName != "" { - x509Cert, err := leafCertificate(c) - if err != nil { - return fmt.Errorf("failed to parse certificate: %w", err) - } - if err := x509Cert.VerifyHostname(chi.ServerName); err != nil { - return fmt.Errorf("certificate is not valid for requested server name: %w", err) - } - } - - // supportsRSAFallback returns nil if the certificate and connection support - // the static RSA key exchange, and unsupported otherwise. The logic for - // supporting static RSA is completely disjoint from the logic for - // supporting signed key exchanges, so we just check it as a fallback. - supportsRSAFallback := func(unsupported error) error { - // TLS 1.3 dropped support for the static RSA key exchange. - if vers == VersionTLS13 { - return unsupported - } - // The static RSA key exchange works by decrypting a challenge with the - // RSA private key, not by signing, so check the PrivateKey implements - // crypto.Decrypter, like *rsa.PrivateKey does. - if priv, ok := c.PrivateKey.(crypto.Decrypter); ok { - if _, ok := priv.Public().(*rsa.PublicKey); !ok { - return unsupported - } - } else { - return unsupported - } - // Finally, there needs to be a mutual cipher suite that uses the static - // RSA key exchange instead of ECDHE. - rsaCipherSuite := selectCipherSuite(chi.CipherSuites, conf.cipherSuites(), func(c *cipherSuite) bool { - if c.flags&suiteECDHE != 0 { - return false - } - if vers < VersionTLS12 && c.flags&suiteTLS12 != 0 { - return false - } - return true - }) - if rsaCipherSuite == nil { - return unsupported - } - return nil - } - - // If the client sent the signature_algorithms extension, ensure it supports - // schemes we can use with this certificate and TLS version. - if len(chi.SignatureSchemes) > 0 { - if _, err := selectSignatureScheme(vers, c, chi.SignatureSchemes); err != nil { - return supportsRSAFallback(err) - } - } - - // In TLS 1.3 we are done because supported_groups is only relevant to the - // ECDHE computation, point format negotiation is removed, cipher suites are - // only relevant to the AEAD choice, and static RSA does not exist. - if vers == VersionTLS13 { - return nil - } - - // The only signed key exchange we support is ECDHE. - if !supportsECDHE(conf, chi.SupportedCurves, chi.SupportedPoints) { - return supportsRSAFallback(errors.New("client doesn't support ECDHE, can only use legacy RSA key exchange")) - } - - var ecdsaCipherSuite bool - if priv, ok := c.PrivateKey.(crypto.Signer); ok { - switch pub := priv.Public().(type) { - case *ecdsa.PublicKey: - var curve CurveID - switch pub.Curve { - case elliptic.P256(): - curve = CurveP256 - case elliptic.P384(): - curve = CurveP384 - case elliptic.P521(): - curve = CurveP521 - default: - return supportsRSAFallback(unsupportedCertificateError(c)) - } - var curveOk bool - for _, c := range chi.SupportedCurves { - if c == curve && conf.supportsCurve(c) { - curveOk = true - break - } - } - if !curveOk { - return errors.New("client doesn't support certificate curve") - } - ecdsaCipherSuite = true - case ed25519.PublicKey: - if vers < VersionTLS12 || len(chi.SignatureSchemes) == 0 { - return errors.New("connection doesn't support Ed25519") - } - ecdsaCipherSuite = true - case *rsa.PublicKey: - default: - return supportsRSAFallback(unsupportedCertificateError(c)) - } - } else { - return supportsRSAFallback(unsupportedCertificateError(c)) - } - - // Make sure that there is a mutually supported cipher suite that works with - // this certificate. Cipher suite selection will then apply the logic in - // reverse to pick it. See also serverHandshakeState.cipherSuiteOk. - cipherSuite := selectCipherSuite(chi.CipherSuites, conf.cipherSuites(), func(c *cipherSuite) bool { - if c.flags&suiteECDHE == 0 { - return false - } - if c.flags&suiteECSign != 0 { - if !ecdsaCipherSuite { - return false - } - } else { - if ecdsaCipherSuite { - return false - } - } - if vers < VersionTLS12 && c.flags&suiteTLS12 != 0 { - return false - } - return true - }) - if cipherSuite == nil { - return supportsRSAFallback(errors.New("client doesn't support any cipher suites compatible with the certificate")) - } - - return nil -} - -// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate -// from the CommonName and SubjectAlternateName fields of each of the leaf -// certificates. -// -// Deprecated: NameToCertificate only allows associating a single certificate -// with a given name. Leave that field nil to let the library select the first -// compatible chain from Certificates. -func (c *config) BuildNameToCertificate() { - c.NameToCertificate = make(map[string]*Certificate) - for i := range c.Certificates { - cert := &c.Certificates[i] - x509Cert, err := leafCertificate(cert) - if err != nil { - continue - } - // If SANs are *not* present, some clients will consider the certificate - // valid for the name in the Common Name. - if x509Cert.Subject.CommonName != "" && len(x509Cert.DNSNames) == 0 { - c.NameToCertificate[x509Cert.Subject.CommonName] = cert - } - for _, san := range x509Cert.DNSNames { - c.NameToCertificate[san] = cert - } - } -} - -const ( - keyLogLabelTLS12 = "CLIENT_RANDOM" - keyLogLabelClientHandshake = "CLIENT_HANDSHAKE_TRAFFIC_SECRET" - keyLogLabelServerHandshake = "SERVER_HANDSHAKE_TRAFFIC_SECRET" - keyLogLabelClientTraffic = "CLIENT_TRAFFIC_SECRET_0" - keyLogLabelServerTraffic = "SERVER_TRAFFIC_SECRET_0" -) - -func (c *config) writeKeyLog(label string, clientRandom, secret []byte) error { - if c.KeyLogWriter == nil { - return nil - } - - logLine := fmt.Appendf(nil, "%s %x %x\n", label, clientRandom, secret) - - writerMutex.Lock() - _, err := c.KeyLogWriter.Write(logLine) - writerMutex.Unlock() - - return err -} - -// writerMutex protects all KeyLogWriters globally. It is rarely enabled, -// and is only for debugging, so a global mutex saves space. -var writerMutex sync.Mutex - -// A Certificate is a chain of one or more certificates, leaf first. -type Certificate = tls.Certificate - -// leaf returns the parsed leaf certificate, either from c.Leaf or by parsing -// the corresponding c.Certificate[0]. -func leafCertificate(c *Certificate) (*x509.Certificate, error) { - if c.Leaf != nil { - return c.Leaf, nil - } - return x509.ParseCertificate(c.Certificate[0]) -} - -type handshakeMessage interface { - marshal() ([]byte, error) - unmarshal([]byte) bool -} - -// lruSessionCache is a ClientSessionCache implementation that uses an LRU -// caching strategy. -type lruSessionCache struct { - sync.Mutex - - m map[string]*list.Element - q *list.List - capacity int -} - -type lruSessionCacheEntry struct { - sessionKey string - state *ClientSessionState -} - -// NewLRUClientSessionCache returns a ClientSessionCache with the given -// capacity that uses an LRU strategy. If capacity is < 1, a default capacity -// is used instead. -func NewLRUClientSessionCache(capacity int) ClientSessionCache { - const defaultSessionCacheCapacity = 64 - - if capacity < 1 { - capacity = defaultSessionCacheCapacity - } - return &lruSessionCache{ - m: make(map[string]*list.Element), - q: list.New(), - capacity: capacity, - } -} - -// Put adds the provided (sessionKey, cs) pair to the cache. If cs is nil, the entry -// corresponding to sessionKey is removed from the cache instead. -func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) { - c.Lock() - defer c.Unlock() - - if elem, ok := c.m[sessionKey]; ok { - if cs == nil { - c.q.Remove(elem) - delete(c.m, sessionKey) - } else { - entry := elem.Value.(*lruSessionCacheEntry) - entry.state = cs - c.q.MoveToFront(elem) - } - return - } - - if c.q.Len() < c.capacity { - entry := &lruSessionCacheEntry{sessionKey, cs} - c.m[sessionKey] = c.q.PushFront(entry) - return - } - - elem := c.q.Back() - entry := elem.Value.(*lruSessionCacheEntry) - delete(c.m, entry.sessionKey) - entry.sessionKey = sessionKey - entry.state = cs - c.q.MoveToFront(elem) - c.m[sessionKey] = elem -} - -// Get returns the ClientSessionState value associated with a given key. It -// returns (nil, false) if no value is found. -func (c *lruSessionCache) Get(sessionKey string) (*ClientSessionState, bool) { - c.Lock() - defer c.Unlock() - - if elem, ok := c.m[sessionKey]; ok { - c.q.MoveToFront(elem) - return elem.Value.(*lruSessionCacheEntry).state, true - } - return nil, false -} - -var emptyConfig Config - -func defaultConfig() *Config { - return &emptyConfig -} - -func unexpectedMessageError(wanted, got any) error { - return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted) -} - -func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlgorithms []SignatureScheme) bool { - for _, s := range supportedSignatureAlgorithms { - if s == sigAlg { - return true - } - } - return false -} - -// CertificateVerificationError is returned when certificate verification fails during the handshake. -type CertificateVerificationError = tls.CertificateVerificationError diff --git a/vendor/github.com/quic-go/qtls-go1-20/conn.go b/vendor/github.com/quic-go/qtls-go1-20/conn.go deleted file mode 100644 index b7ebdb0a..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/conn.go +++ /dev/null @@ -1,1643 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// TLS low level connection and record layer - -package qtls - -import ( - "bytes" - "context" - "crypto/cipher" - "crypto/subtle" - "crypto/x509" - "errors" - "fmt" - "hash" - "io" - "net" - "sync" - "sync/atomic" - "time" -) - -// A Conn represents a secured connection. -// It implements the net.Conn interface. -type Conn struct { - // constant - conn net.Conn - isClient bool - handshakeFn func(context.Context) error // (*Conn).clientHandshake or serverHandshake - quic *quicState // nil for non-QUIC connections - - // isHandshakeComplete is true if the connection is currently transferring - // application data (i.e. is not currently processing a handshake). - // isHandshakeComplete is true implies handshakeErr == nil. - isHandshakeComplete atomic.Bool - // constant after handshake; protected by handshakeMutex - handshakeMutex sync.Mutex - handshakeErr error // error resulting from handshake - vers uint16 // TLS version - haveVers bool // version has been negotiated - config *config // configuration passed to constructor - extraConfig *ExtraConfig - // handshakes counts the number of handshakes performed on the - // connection so far. If renegotiation is disabled then this is either - // zero or one. - handshakes int - didResume bool // whether this connection was a session resumption - cipherSuite uint16 - ocspResponse []byte // stapled OCSP response - scts [][]byte // signed certificate timestamps from server - peerCertificates []*x509.Certificate - // activeCertHandles contains the cache handles to certificates in - // peerCertificates that are used to track active references. - activeCertHandles []*activeCert - // verifiedChains contains the certificate chains that we built, as - // opposed to the ones presented by the server. - verifiedChains [][]*x509.Certificate - // serverName contains the server name indicated by the client, if any. - serverName string - // secureRenegotiation is true if the server echoed the secure - // renegotiation extension. (This is meaningless as a server because - // renegotiation is not supported in that case.) - secureRenegotiation bool - // ekm is a closure for exporting keying material. - ekm func(label string, context []byte, length int) ([]byte, error) - // resumptionSecret is the resumption_master_secret for handling - // or sending NewSessionTicket messages. - resumptionSecret []byte - - // ticketKeys is the set of active session ticket keys for this - // connection. The first one is used to encrypt new tickets and - // all are tried to decrypt tickets. - ticketKeys []ticketKey - - // clientFinishedIsFirst is true if the client sent the first Finished - // message during the most recent handshake. This is recorded because - // the first transmitted Finished message is the tls-unique - // channel-binding value. - clientFinishedIsFirst bool - - // closeNotifyErr is any error from sending the alertCloseNotify record. - closeNotifyErr error - // closeNotifySent is true if the Conn attempted to send an - // alertCloseNotify record. - closeNotifySent bool - - // clientFinished and serverFinished contain the Finished message sent - // by the client or server in the most recent handshake. This is - // retained to support the renegotiation extension and tls-unique - // channel-binding. - clientFinished [12]byte - serverFinished [12]byte - - // clientProtocol is the negotiated ALPN protocol. - clientProtocol string - - // input/output - in, out halfConn - rawInput bytes.Buffer // raw input, starting with a record header - input bytes.Reader // application data waiting to be read, from rawInput.Next - hand bytes.Buffer // handshake data waiting to be read - buffering bool // whether records are buffered in sendBuf - sendBuf []byte // a buffer of records waiting to be sent - - // bytesSent counts the bytes of application data sent. - // packetsSent counts packets. - bytesSent int64 - packetsSent int64 - - // retryCount counts the number of consecutive non-advancing records - // received by Conn.readRecord. That is, records that neither advance the - // handshake, nor deliver application data. Protected by in.Mutex. - retryCount int - - // activeCall indicates whether Close has been call in the low bit. - // the rest of the bits are the number of goroutines in Conn.Write. - activeCall atomic.Int32 - - tmp [16]byte -} - -// Access to net.Conn methods. -// Cannot just embed net.Conn because that would -// export the struct field too. - -// LocalAddr returns the local network address. -func (c *Conn) LocalAddr() net.Addr { - return c.conn.LocalAddr() -} - -// RemoteAddr returns the remote network address. -func (c *Conn) RemoteAddr() net.Addr { - return c.conn.RemoteAddr() -} - -// SetDeadline sets the read and write deadlines associated with the connection. -// A zero value for t means Read and Write will not time out. -// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. -func (c *Conn) SetDeadline(t time.Time) error { - return c.conn.SetDeadline(t) -} - -// SetReadDeadline sets the read deadline on the underlying connection. -// A zero value for t means Read will not time out. -func (c *Conn) SetReadDeadline(t time.Time) error { - return c.conn.SetReadDeadline(t) -} - -// SetWriteDeadline sets the write deadline on the underlying connection. -// A zero value for t means Write will not time out. -// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. -func (c *Conn) SetWriteDeadline(t time.Time) error { - return c.conn.SetWriteDeadline(t) -} - -// NetConn returns the underlying connection that is wrapped by c. -// Note that writing to or reading from this connection directly will corrupt the -// TLS session. -func (c *Conn) NetConn() net.Conn { - return c.conn -} - -// A halfConn represents one direction of the record layer -// connection, either sending or receiving. -type halfConn struct { - sync.Mutex - - err error // first permanent error - version uint16 // protocol version - cipher any // cipher algorithm - mac hash.Hash - seq [8]byte // 64-bit sequence number - - scratchBuf [13]byte // to avoid allocs; interface method args escape - - nextCipher any // next encryption state - nextMac hash.Hash // next MAC algorithm - - level QUICEncryptionLevel // current QUIC encryption level - trafficSecret []byte // current TLS 1.3 traffic secret -} - -type permanentError struct { - err net.Error -} - -func (e *permanentError) Error() string { return e.err.Error() } -func (e *permanentError) Unwrap() error { return e.err } -func (e *permanentError) Timeout() bool { return e.err.Timeout() } -func (e *permanentError) Temporary() bool { return false } - -func (hc *halfConn) setErrorLocked(err error) error { - if e, ok := err.(net.Error); ok { - hc.err = &permanentError{err: e} - } else { - hc.err = err - } - return hc.err -} - -// prepareCipherSpec sets the encryption and MAC states -// that a subsequent changeCipherSpec will use. -func (hc *halfConn) prepareCipherSpec(version uint16, cipher any, mac hash.Hash) { - hc.version = version - hc.nextCipher = cipher - hc.nextMac = mac -} - -// changeCipherSpec changes the encryption and MAC states -// to the ones previously passed to prepareCipherSpec. -func (hc *halfConn) changeCipherSpec() error { - if hc.nextCipher == nil || hc.version == VersionTLS13 { - return alertInternalError - } - hc.cipher = hc.nextCipher - hc.mac = hc.nextMac - hc.nextCipher = nil - hc.nextMac = nil - for i := range hc.seq { - hc.seq[i] = 0 - } - return nil -} - -func (hc *halfConn) setTrafficSecret(suite *cipherSuiteTLS13, level QUICEncryptionLevel, secret []byte) { - hc.trafficSecret = secret - hc.level = level - key, iv := suite.trafficKey(secret) - hc.cipher = suite.aead(key, iv) - for i := range hc.seq { - hc.seq[i] = 0 - } -} - -// incSeq increments the sequence number. -func (hc *halfConn) incSeq() { - for i := 7; i >= 0; i-- { - hc.seq[i]++ - if hc.seq[i] != 0 { - return - } - } - - // Not allowed to let sequence number wrap. - // Instead, must renegotiate before it does. - // Not likely enough to bother. - panic("TLS: sequence number wraparound") -} - -// explicitNonceLen returns the number of bytes of explicit nonce or IV included -// in each record. Explicit nonces are present only in CBC modes after TLS 1.0 -// and in certain AEAD modes in TLS 1.2. -func (hc *halfConn) explicitNonceLen() int { - if hc.cipher == nil { - return 0 - } - - switch c := hc.cipher.(type) { - case cipher.Stream: - return 0 - case aead: - return c.explicitNonceLen() - case cbcMode: - // TLS 1.1 introduced a per-record explicit IV to fix the BEAST attack. - if hc.version >= VersionTLS11 { - return c.BlockSize() - } - return 0 - default: - panic("unknown cipher type") - } -} - -// extractPadding returns, in constant time, the length of the padding to remove -// from the end of payload. It also returns a byte which is equal to 255 if the -// padding was valid and 0 otherwise. See RFC 2246, Section 6.2.3.2. -func extractPadding(payload []byte) (toRemove int, good byte) { - if len(payload) < 1 { - return 0, 0 - } - - paddingLen := payload[len(payload)-1] - t := uint(len(payload)-1) - uint(paddingLen) - // if len(payload) >= (paddingLen - 1) then the MSB of t is zero - good = byte(int32(^t) >> 31) - - // The maximum possible padding length plus the actual length field - toCheck := 256 - // The length of the padded data is public, so we can use an if here - if toCheck > len(payload) { - toCheck = len(payload) - } - - for i := 0; i < toCheck; i++ { - t := uint(paddingLen) - uint(i) - // if i <= paddingLen then the MSB of t is zero - mask := byte(int32(^t) >> 31) - b := payload[len(payload)-1-i] - good &^= mask&paddingLen ^ mask&b - } - - // We AND together the bits of good and replicate the result across - // all the bits. - good &= good << 4 - good &= good << 2 - good &= good << 1 - good = uint8(int8(good) >> 7) - - // Zero the padding length on error. This ensures any unchecked bytes - // are included in the MAC. Otherwise, an attacker that could - // distinguish MAC failures from padding failures could mount an attack - // similar to POODLE in SSL 3.0: given a good ciphertext that uses a - // full block's worth of padding, replace the final block with another - // block. If the MAC check passed but the padding check failed, the - // last byte of that block decrypted to the block size. - // - // See also macAndPaddingGood logic below. - paddingLen &= good - - toRemove = int(paddingLen) + 1 - return -} - -func roundUp(a, b int) int { - return a + (b-a%b)%b -} - -// cbcMode is an interface for block ciphers using cipher block chaining. -type cbcMode interface { - cipher.BlockMode - SetIV([]byte) -} - -// decrypt authenticates and decrypts the record if protection is active at -// this stage. The returned plaintext might overlap with the input. -func (hc *halfConn) decrypt(record []byte) ([]byte, recordType, error) { - var plaintext []byte - typ := recordType(record[0]) - payload := record[recordHeaderLen:] - - // In TLS 1.3, change_cipher_spec messages are to be ignored without being - // decrypted. See RFC 8446, Appendix D.4. - if hc.version == VersionTLS13 && typ == recordTypeChangeCipherSpec { - return payload, typ, nil - } - - paddingGood := byte(255) - paddingLen := 0 - - explicitNonceLen := hc.explicitNonceLen() - - if hc.cipher != nil { - switch c := hc.cipher.(type) { - case cipher.Stream: - c.XORKeyStream(payload, payload) - case aead: - if len(payload) < explicitNonceLen { - return nil, 0, alertBadRecordMAC - } - nonce := payload[:explicitNonceLen] - if len(nonce) == 0 { - nonce = hc.seq[:] - } - payload = payload[explicitNonceLen:] - - var additionalData []byte - if hc.version == VersionTLS13 { - additionalData = record[:recordHeaderLen] - } else { - additionalData = append(hc.scratchBuf[:0], hc.seq[:]...) - additionalData = append(additionalData, record[:3]...) - n := len(payload) - c.Overhead() - additionalData = append(additionalData, byte(n>>8), byte(n)) - } - - var err error - plaintext, err = c.Open(payload[:0], nonce, payload, additionalData) - if err != nil { - return nil, 0, alertBadRecordMAC - } - case cbcMode: - blockSize := c.BlockSize() - minPayload := explicitNonceLen + roundUp(hc.mac.Size()+1, blockSize) - if len(payload)%blockSize != 0 || len(payload) < minPayload { - return nil, 0, alertBadRecordMAC - } - - if explicitNonceLen > 0 { - c.SetIV(payload[:explicitNonceLen]) - payload = payload[explicitNonceLen:] - } - c.CryptBlocks(payload, payload) - - // In a limited attempt to protect against CBC padding oracles like - // Lucky13, the data past paddingLen (which is secret) is passed to - // the MAC function as extra data, to be fed into the HMAC after - // computing the digest. This makes the MAC roughly constant time as - // long as the digest computation is constant time and does not - // affect the subsequent write, modulo cache effects. - paddingLen, paddingGood = extractPadding(payload) - default: - panic("unknown cipher type") - } - - if hc.version == VersionTLS13 { - if typ != recordTypeApplicationData { - return nil, 0, alertUnexpectedMessage - } - if len(plaintext) > maxPlaintext+1 { - return nil, 0, alertRecordOverflow - } - // Remove padding and find the ContentType scanning from the end. - for i := len(plaintext) - 1; i >= 0; i-- { - if plaintext[i] != 0 { - typ = recordType(plaintext[i]) - plaintext = plaintext[:i] - break - } - if i == 0 { - return nil, 0, alertUnexpectedMessage - } - } - } - } else { - plaintext = payload - } - - if hc.mac != nil { - macSize := hc.mac.Size() - if len(payload) < macSize { - return nil, 0, alertBadRecordMAC - } - - n := len(payload) - macSize - paddingLen - n = subtle.ConstantTimeSelect(int(uint32(n)>>31), 0, n) // if n < 0 { n = 0 } - record[3] = byte(n >> 8) - record[4] = byte(n) - remoteMAC := payload[n : n+macSize] - localMAC := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload[:n], payload[n+macSize:]) - - // This is equivalent to checking the MACs and paddingGood - // separately, but in constant-time to prevent distinguishing - // padding failures from MAC failures. Depending on what value - // of paddingLen was returned on bad padding, distinguishing - // bad MAC from bad padding can lead to an attack. - // - // See also the logic at the end of extractPadding. - macAndPaddingGood := subtle.ConstantTimeCompare(localMAC, remoteMAC) & int(paddingGood) - if macAndPaddingGood != 1 { - return nil, 0, alertBadRecordMAC - } - - plaintext = payload[:n] - } - - hc.incSeq() - return plaintext, typ, nil -} - -// sliceForAppend extends the input slice by n bytes. head is the full extended -// slice, while tail is the appended part. If the original slice has sufficient -// capacity no allocation is performed. -func sliceForAppend(in []byte, n int) (head, tail []byte) { - if total := len(in) + n; cap(in) >= total { - head = in[:total] - } else { - head = make([]byte, total) - copy(head, in) - } - tail = head[len(in):] - return -} - -// encrypt encrypts payload, adding the appropriate nonce and/or MAC, and -// appends it to record, which must already contain the record header. -func (hc *halfConn) encrypt(record, payload []byte, rand io.Reader) ([]byte, error) { - if hc.cipher == nil { - return append(record, payload...), nil - } - - var explicitNonce []byte - if explicitNonceLen := hc.explicitNonceLen(); explicitNonceLen > 0 { - record, explicitNonce = sliceForAppend(record, explicitNonceLen) - if _, isCBC := hc.cipher.(cbcMode); !isCBC && explicitNonceLen < 16 { - // The AES-GCM construction in TLS has an explicit nonce so that the - // nonce can be random. However, the nonce is only 8 bytes which is - // too small for a secure, random nonce. Therefore we use the - // sequence number as the nonce. The 3DES-CBC construction also has - // an 8 bytes nonce but its nonces must be unpredictable (see RFC - // 5246, Appendix F.3), forcing us to use randomness. That's not - // 3DES' biggest problem anyway because the birthday bound on block - // collision is reached first due to its similarly small block size - // (see the Sweet32 attack). - copy(explicitNonce, hc.seq[:]) - } else { - if _, err := io.ReadFull(rand, explicitNonce); err != nil { - return nil, err - } - } - } - - var dst []byte - switch c := hc.cipher.(type) { - case cipher.Stream: - mac := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload, nil) - record, dst = sliceForAppend(record, len(payload)+len(mac)) - c.XORKeyStream(dst[:len(payload)], payload) - c.XORKeyStream(dst[len(payload):], mac) - case aead: - nonce := explicitNonce - if len(nonce) == 0 { - nonce = hc.seq[:] - } - - if hc.version == VersionTLS13 { - record = append(record, payload...) - - // Encrypt the actual ContentType and replace the plaintext one. - record = append(record, record[0]) - record[0] = byte(recordTypeApplicationData) - - n := len(payload) + 1 + c.Overhead() - record[3] = byte(n >> 8) - record[4] = byte(n) - - record = c.Seal(record[:recordHeaderLen], - nonce, record[recordHeaderLen:], record[:recordHeaderLen]) - } else { - additionalData := append(hc.scratchBuf[:0], hc.seq[:]...) - additionalData = append(additionalData, record[:recordHeaderLen]...) - record = c.Seal(record, nonce, payload, additionalData) - } - case cbcMode: - mac := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload, nil) - blockSize := c.BlockSize() - plaintextLen := len(payload) + len(mac) - paddingLen := blockSize - plaintextLen%blockSize - record, dst = sliceForAppend(record, plaintextLen+paddingLen) - copy(dst, payload) - copy(dst[len(payload):], mac) - for i := plaintextLen; i < len(dst); i++ { - dst[i] = byte(paddingLen - 1) - } - if len(explicitNonce) > 0 { - c.SetIV(explicitNonce) - } - c.CryptBlocks(dst, dst) - default: - panic("unknown cipher type") - } - - // Update length to include nonce, MAC and any block padding needed. - n := len(record) - recordHeaderLen - record[3] = byte(n >> 8) - record[4] = byte(n) - hc.incSeq() - - return record, nil -} - -// RecordHeaderError is returned when a TLS record header is invalid. -type RecordHeaderError struct { - // Msg contains a human readable string that describes the error. - Msg string - // RecordHeader contains the five bytes of TLS record header that - // triggered the error. - RecordHeader [5]byte - // Conn provides the underlying net.Conn in the case that a client - // sent an initial handshake that didn't look like TLS. - // It is nil if there's already been a handshake or a TLS alert has - // been written to the connection. - Conn net.Conn -} - -func (e RecordHeaderError) Error() string { return "tls: " + e.Msg } - -func (c *Conn) newRecordHeaderError(conn net.Conn, msg string) (err RecordHeaderError) { - err.Msg = msg - err.Conn = conn - copy(err.RecordHeader[:], c.rawInput.Bytes()) - return err -} - -func (c *Conn) readRecord() error { - return c.readRecordOrCCS(false) -} - -func (c *Conn) readChangeCipherSpec() error { - return c.readRecordOrCCS(true) -} - -// readRecordOrCCS reads one or more TLS records from the connection and -// updates the record layer state. Some invariants: -// - c.in must be locked -// - c.input must be empty -// -// During the handshake one and only one of the following will happen: -// - c.hand grows -// - c.in.changeCipherSpec is called -// - an error is returned -// -// After the handshake one and only one of the following will happen: -// - c.hand grows -// - c.input is set -// - an error is returned -func (c *Conn) readRecordOrCCS(expectChangeCipherSpec bool) error { - if c.in.err != nil { - return c.in.err - } - handshakeComplete := c.isHandshakeComplete.Load() - - // This function modifies c.rawInput, which owns the c.input memory. - if c.input.Len() != 0 { - return c.in.setErrorLocked(errors.New("tls: internal error: attempted to read record with pending application data")) - } - c.input.Reset(nil) - - if c.quic != nil { - return c.in.setErrorLocked(errors.New("tls: internal error: attempted to read record with QUIC transport")) - } - - // Read header, payload. - if err := c.readFromUntil(c.conn, recordHeaderLen); err != nil { - // RFC 8446, Section 6.1 suggests that EOF without an alertCloseNotify - // is an error, but popular web sites seem to do this, so we accept it - // if and only if at the record boundary. - if err == io.ErrUnexpectedEOF && c.rawInput.Len() == 0 { - err = io.EOF - } - if e, ok := err.(net.Error); !ok || !e.Temporary() { - c.in.setErrorLocked(err) - } - return err - } - hdr := c.rawInput.Bytes()[:recordHeaderLen] - typ := recordType(hdr[0]) - - // No valid TLS record has a type of 0x80, however SSLv2 handshakes - // start with a uint16 length where the MSB is set and the first record - // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests - // an SSLv2 client. - if !handshakeComplete && typ == 0x80 { - c.sendAlert(alertProtocolVersion) - return c.in.setErrorLocked(c.newRecordHeaderError(nil, "unsupported SSLv2 handshake received")) - } - - vers := uint16(hdr[1])<<8 | uint16(hdr[2]) - n := int(hdr[3])<<8 | int(hdr[4]) - if c.haveVers && c.vers != VersionTLS13 && vers != c.vers { - c.sendAlert(alertProtocolVersion) - msg := fmt.Sprintf("received record with version %x when expecting version %x", vers, c.vers) - return c.in.setErrorLocked(c.newRecordHeaderError(nil, msg)) - } - if !c.haveVers { - // First message, be extra suspicious: this might not be a TLS - // client. Bail out before reading a full 'body', if possible. - // The current max version is 3.3 so if the version is >= 16.0, - // it's probably not real. - if (typ != recordTypeAlert && typ != recordTypeHandshake) || vers >= 0x1000 { - return c.in.setErrorLocked(c.newRecordHeaderError(c.conn, "first record does not look like a TLS handshake")) - } - } - if c.vers == VersionTLS13 && n > maxCiphertextTLS13 || n > maxCiphertext { - c.sendAlert(alertRecordOverflow) - msg := fmt.Sprintf("oversized record received with length %d", n) - return c.in.setErrorLocked(c.newRecordHeaderError(nil, msg)) - } - if err := c.readFromUntil(c.conn, recordHeaderLen+n); err != nil { - if e, ok := err.(net.Error); !ok || !e.Temporary() { - c.in.setErrorLocked(err) - } - return err - } - - // Process message. - record := c.rawInput.Next(recordHeaderLen + n) - data, typ, err := c.in.decrypt(record) - if err != nil { - return c.in.setErrorLocked(c.sendAlert(err.(alert))) - } - if len(data) > maxPlaintext { - return c.in.setErrorLocked(c.sendAlert(alertRecordOverflow)) - } - - // Application Data messages are always protected. - if c.in.cipher == nil && typ == recordTypeApplicationData { - return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - - if typ != recordTypeAlert && typ != recordTypeChangeCipherSpec && len(data) > 0 { - // This is a state-advancing message: reset the retry count. - c.retryCount = 0 - } - - // Handshake messages MUST NOT be interleaved with other record types in TLS 1.3. - if c.vers == VersionTLS13 && typ != recordTypeHandshake && c.hand.Len() > 0 { - return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - - switch typ { - default: - return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - - case recordTypeAlert: - if c.quic != nil { - return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - if len(data) != 2 { - return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - if alert(data[1]) == alertCloseNotify { - return c.in.setErrorLocked(io.EOF) - } - if c.vers == VersionTLS13 { - return c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])}) - } - switch data[0] { - case alertLevelWarning: - // Drop the record on the floor and retry. - return c.retryReadRecord(expectChangeCipherSpec) - case alertLevelError: - return c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])}) - default: - return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - - case recordTypeChangeCipherSpec: - if len(data) != 1 || data[0] != 1 { - return c.in.setErrorLocked(c.sendAlert(alertDecodeError)) - } - // Handshake messages are not allowed to fragment across the CCS. - if c.hand.Len() > 0 { - return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - // In TLS 1.3, change_cipher_spec records are ignored until the - // Finished. See RFC 8446, Appendix D.4. Note that according to Section - // 5, a server can send a ChangeCipherSpec before its ServerHello, when - // c.vers is still unset. That's not useful though and suspicious if the - // server then selects a lower protocol version, so don't allow that. - if c.vers == VersionTLS13 { - return c.retryReadRecord(expectChangeCipherSpec) - } - if !expectChangeCipherSpec { - return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - if err := c.in.changeCipherSpec(); err != nil { - return c.in.setErrorLocked(c.sendAlert(err.(alert))) - } - - case recordTypeApplicationData: - if !handshakeComplete || expectChangeCipherSpec { - return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - // Some OpenSSL servers send empty records in order to randomize the - // CBC IV. Ignore a limited number of empty records. - if len(data) == 0 { - return c.retryReadRecord(expectChangeCipherSpec) - } - // Note that data is owned by c.rawInput, following the Next call above, - // to avoid copying the plaintext. This is safe because c.rawInput is - // not read from or written to until c.input is drained. - c.input.Reset(data) - - case recordTypeHandshake: - if len(data) == 0 || expectChangeCipherSpec { - return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - c.hand.Write(data) - } - - return nil -} - -// retryReadRecord recurs into readRecordOrCCS to drop a non-advancing record, like -// a warning alert, empty application_data, or a change_cipher_spec in TLS 1.3. -func (c *Conn) retryReadRecord(expectChangeCipherSpec bool) error { - c.retryCount++ - if c.retryCount > maxUselessRecords { - c.sendAlert(alertUnexpectedMessage) - return c.in.setErrorLocked(errors.New("tls: too many ignored records")) - } - return c.readRecordOrCCS(expectChangeCipherSpec) -} - -// atLeastReader reads from R, stopping with EOF once at least N bytes have been -// read. It is different from an io.LimitedReader in that it doesn't cut short -// the last Read call, and in that it considers an early EOF an error. -type atLeastReader struct { - R io.Reader - N int64 -} - -func (r *atLeastReader) Read(p []byte) (int, error) { - if r.N <= 0 { - return 0, io.EOF - } - n, err := r.R.Read(p) - r.N -= int64(n) // won't underflow unless len(p) >= n > 9223372036854775809 - if r.N > 0 && err == io.EOF { - return n, io.ErrUnexpectedEOF - } - if r.N <= 0 && err == nil { - return n, io.EOF - } - return n, err -} - -// readFromUntil reads from r into c.rawInput until c.rawInput contains -// at least n bytes or else returns an error. -func (c *Conn) readFromUntil(r io.Reader, n int) error { - if c.rawInput.Len() >= n { - return nil - } - needs := n - c.rawInput.Len() - // There might be extra input waiting on the wire. Make a best effort - // attempt to fetch it so that it can be used in (*Conn).Read to - // "predict" closeNotify alerts. - c.rawInput.Grow(needs + bytes.MinRead) - _, err := c.rawInput.ReadFrom(&atLeastReader{r, int64(needs)}) - return err -} - -// sendAlert sends a TLS alert message. -func (c *Conn) sendAlertLocked(err alert) error { - if c.quic != nil { - return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) - } - switch err { - case alertNoRenegotiation, alertCloseNotify: - c.tmp[0] = alertLevelWarning - default: - c.tmp[0] = alertLevelError - } - c.tmp[1] = byte(err) - - _, writeErr := c.writeRecordLocked(recordTypeAlert, c.tmp[0:2]) - if err == alertCloseNotify { - // closeNotify is a special case in that it isn't an error. - return writeErr - } - - return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) -} - -// sendAlert sends a TLS alert message. -func (c *Conn) sendAlert(err alert) error { - c.out.Lock() - defer c.out.Unlock() - return c.sendAlertLocked(err) -} - -const ( - // tcpMSSEstimate is a conservative estimate of the TCP maximum segment - // size (MSS). A constant is used, rather than querying the kernel for - // the actual MSS, to avoid complexity. The value here is the IPv6 - // minimum MTU (1280 bytes) minus the overhead of an IPv6 header (40 - // bytes) and a TCP header with timestamps (32 bytes). - tcpMSSEstimate = 1208 - - // recordSizeBoostThreshold is the number of bytes of application data - // sent after which the TLS record size will be increased to the - // maximum. - recordSizeBoostThreshold = 128 * 1024 -) - -// maxPayloadSizeForWrite returns the maximum TLS payload size to use for the -// next application data record. There is the following trade-off: -// -// - For latency-sensitive applications, such as web browsing, each TLS -// record should fit in one TCP segment. -// - For throughput-sensitive applications, such as large file transfers, -// larger TLS records better amortize framing and encryption overheads. -// -// A simple heuristic that works well in practice is to use small records for -// the first 1MB of data, then use larger records for subsequent data, and -// reset back to smaller records after the connection becomes idle. See "High -// Performance Web Networking", Chapter 4, or: -// https://www.igvita.com/2013/10/24/optimizing-tls-record-size-and-buffering-latency/ -// -// In the interests of simplicity and determinism, this code does not attempt -// to reset the record size once the connection is idle, however. -func (c *Conn) maxPayloadSizeForWrite(typ recordType) int { - if c.config.DynamicRecordSizingDisabled || typ != recordTypeApplicationData { - return maxPlaintext - } - - if c.bytesSent >= recordSizeBoostThreshold { - return maxPlaintext - } - - // Subtract TLS overheads to get the maximum payload size. - payloadBytes := tcpMSSEstimate - recordHeaderLen - c.out.explicitNonceLen() - if c.out.cipher != nil { - switch ciph := c.out.cipher.(type) { - case cipher.Stream: - payloadBytes -= c.out.mac.Size() - case cipher.AEAD: - payloadBytes -= ciph.Overhead() - case cbcMode: - blockSize := ciph.BlockSize() - // The payload must fit in a multiple of blockSize, with - // room for at least one padding byte. - payloadBytes = (payloadBytes & ^(blockSize - 1)) - 1 - // The MAC is appended before padding so affects the - // payload size directly. - payloadBytes -= c.out.mac.Size() - default: - panic("unknown cipher type") - } - } - if c.vers == VersionTLS13 { - payloadBytes-- // encrypted ContentType - } - - // Allow packet growth in arithmetic progression up to max. - pkt := c.packetsSent - c.packetsSent++ - if pkt > 1000 { - return maxPlaintext // avoid overflow in multiply below - } - - n := payloadBytes * int(pkt+1) - if n > maxPlaintext { - n = maxPlaintext - } - return n -} - -func (c *Conn) write(data []byte) (int, error) { - if c.buffering { - c.sendBuf = append(c.sendBuf, data...) - return len(data), nil - } - - n, err := c.conn.Write(data) - c.bytesSent += int64(n) - return n, err -} - -func (c *Conn) flush() (int, error) { - if len(c.sendBuf) == 0 { - return 0, nil - } - - n, err := c.conn.Write(c.sendBuf) - c.bytesSent += int64(n) - c.sendBuf = nil - c.buffering = false - return n, err -} - -// outBufPool pools the record-sized scratch buffers used by writeRecordLocked. -var outBufPool = sync.Pool{ - New: func() any { - return new([]byte) - }, -} - -// writeRecordLocked writes a TLS record with the given type and payload to the -// connection and updates the record layer state. -func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) { - if c.quic != nil { - if typ != recordTypeHandshake { - return 0, errors.New("tls: internal error: sending non-handshake message to QUIC transport") - } - c.quicWriteCryptoData(c.out.level, data) - if !c.buffering { - if _, err := c.flush(); err != nil { - return 0, err - } - } - return len(data), nil - } - - outBufPtr := outBufPool.Get().(*[]byte) - outBuf := *outBufPtr - defer func() { - // You might be tempted to simplify this by just passing &outBuf to Put, - // but that would make the local copy of the outBuf slice header escape - // to the heap, causing an allocation. Instead, we keep around the - // pointer to the slice header returned by Get, which is already on the - // heap, and overwrite and return that. - *outBufPtr = outBuf - outBufPool.Put(outBufPtr) - }() - - var n int - for len(data) > 0 { - m := len(data) - if maxPayload := c.maxPayloadSizeForWrite(typ); m > maxPayload { - m = maxPayload - } - - _, outBuf = sliceForAppend(outBuf[:0], recordHeaderLen) - outBuf[0] = byte(typ) - vers := c.vers - if vers == 0 { - // Some TLS servers fail if the record version is - // greater than TLS 1.0 for the initial ClientHello. - vers = VersionTLS10 - } else if vers == VersionTLS13 { - // TLS 1.3 froze the record layer version to 1.2. - // See RFC 8446, Section 5.1. - vers = VersionTLS12 - } - outBuf[1] = byte(vers >> 8) - outBuf[2] = byte(vers) - outBuf[3] = byte(m >> 8) - outBuf[4] = byte(m) - - var err error - outBuf, err = c.out.encrypt(outBuf, data[:m], c.config.rand()) - if err != nil { - return n, err - } - if _, err := c.write(outBuf); err != nil { - return n, err - } - n += m - data = data[m:] - } - - if typ == recordTypeChangeCipherSpec && c.vers != VersionTLS13 { - if err := c.out.changeCipherSpec(); err != nil { - return n, c.sendAlertLocked(err.(alert)) - } - } - - return n, nil -} - -// writeHandshakeRecord writes a handshake message to the connection and updates -// the record layer state. If transcript is non-nil the marshalled message is -// written to it. -func (c *Conn) writeHandshakeRecord(msg handshakeMessage, transcript transcriptHash) (int, error) { - c.out.Lock() - defer c.out.Unlock() - - data, err := msg.marshal() - if err != nil { - return 0, err - } - if transcript != nil { - transcript.Write(data) - } - - return c.writeRecordLocked(recordTypeHandshake, data) -} - -// writeChangeCipherRecord writes a ChangeCipherSpec message to the connection and -// updates the record layer state. -func (c *Conn) writeChangeCipherRecord() error { - c.out.Lock() - defer c.out.Unlock() - _, err := c.writeRecordLocked(recordTypeChangeCipherSpec, []byte{1}) - return err -} - -// readHandshakeBytes reads handshake data until c.hand contains at least n bytes. -func (c *Conn) readHandshakeBytes(n int) error { - if c.quic != nil { - return c.quicReadHandshakeBytes(n) - } - for c.hand.Len() < n { - if err := c.readRecord(); err != nil { - return err - } - } - return nil -} - -// readHandshake reads the next handshake message from -// the record layer. If transcript is non-nil, the message -// is written to the passed transcriptHash. -func (c *Conn) readHandshake(transcript transcriptHash) (any, error) { - if err := c.readHandshakeBytes(4); err != nil { - return nil, err - } - data := c.hand.Bytes() - n := int(data[1])<<16 | int(data[2])<<8 | int(data[3]) - if n > maxHandshake { - c.sendAlertLocked(alertInternalError) - return nil, c.in.setErrorLocked(fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshake)) - } - if err := c.readHandshakeBytes(4 + n); err != nil { - return nil, err - } - data = c.hand.Next(4 + n) - return c.unmarshalHandshakeMessage(data, transcript) -} - -func (c *Conn) unmarshalHandshakeMessage(data []byte, transcript transcriptHash) (handshakeMessage, error) { - var m handshakeMessage - switch data[0] { - case typeHelloRequest: - m = new(helloRequestMsg) - case typeClientHello: - m = new(clientHelloMsg) - case typeServerHello: - m = new(serverHelloMsg) - case typeNewSessionTicket: - if c.vers == VersionTLS13 { - m = new(newSessionTicketMsgTLS13) - } else { - m = new(newSessionTicketMsg) - } - case typeCertificate: - if c.vers == VersionTLS13 { - m = new(certificateMsgTLS13) - } else { - m = new(certificateMsg) - } - case typeCertificateRequest: - if c.vers == VersionTLS13 { - m = new(certificateRequestMsgTLS13) - } else { - m = &certificateRequestMsg{ - hasSignatureAlgorithm: c.vers >= VersionTLS12, - } - } - case typeCertificateStatus: - m = new(certificateStatusMsg) - case typeServerKeyExchange: - m = new(serverKeyExchangeMsg) - case typeServerHelloDone: - m = new(serverHelloDoneMsg) - case typeClientKeyExchange: - m = new(clientKeyExchangeMsg) - case typeCertificateVerify: - m = &certificateVerifyMsg{ - hasSignatureAlgorithm: c.vers >= VersionTLS12, - } - case typeFinished: - m = new(finishedMsg) - case typeEncryptedExtensions: - m = new(encryptedExtensionsMsg) - case typeEndOfEarlyData: - m = new(endOfEarlyDataMsg) - case typeKeyUpdate: - m = new(keyUpdateMsg) - default: - return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - - // The handshake message unmarshalers - // expect to be able to keep references to data, - // so pass in a fresh copy that won't be overwritten. - data = append([]byte(nil), data...) - - if !m.unmarshal(data) { - return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) - } - - if transcript != nil { - transcript.Write(data) - } - - return m, nil -} - -var ( - errShutdown = errors.New("tls: protocol is shutdown") -) - -// Write writes data to the connection. -// -// As Write calls Handshake, in order to prevent indefinite blocking a deadline -// must be set for both Read and Write before Write is called when the handshake -// has not yet completed. See SetDeadline, SetReadDeadline, and -// SetWriteDeadline. -func (c *Conn) Write(b []byte) (int, error) { - // interlock with Close below - for { - x := c.activeCall.Load() - if x&1 != 0 { - return 0, net.ErrClosed - } - if c.activeCall.CompareAndSwap(x, x+2) { - break - } - } - defer c.activeCall.Add(-2) - - if err := c.Handshake(); err != nil { - return 0, err - } - - c.out.Lock() - defer c.out.Unlock() - - if err := c.out.err; err != nil { - return 0, err - } - - if !c.isHandshakeComplete.Load() { - return 0, alertInternalError - } - - if c.closeNotifySent { - return 0, errShutdown - } - - // TLS 1.0 is susceptible to a chosen-plaintext - // attack when using block mode ciphers due to predictable IVs. - // This can be prevented by splitting each Application Data - // record into two records, effectively randomizing the IV. - // - // https://www.openssl.org/~bodo/tls-cbc.txt - // https://bugzilla.mozilla.org/show_bug.cgi?id=665814 - // https://www.imperialviolet.org/2012/01/15/beastfollowup.html - - var m int - if len(b) > 1 && c.vers == VersionTLS10 { - if _, ok := c.out.cipher.(cipher.BlockMode); ok { - n, err := c.writeRecordLocked(recordTypeApplicationData, b[:1]) - if err != nil { - return n, c.out.setErrorLocked(err) - } - m, b = 1, b[1:] - } - } - - n, err := c.writeRecordLocked(recordTypeApplicationData, b) - return n + m, c.out.setErrorLocked(err) -} - -// handleRenegotiation processes a HelloRequest handshake message. -func (c *Conn) handleRenegotiation() error { - if c.vers == VersionTLS13 { - return errors.New("tls: internal error: unexpected renegotiation") - } - - msg, err := c.readHandshake(nil) - if err != nil { - return err - } - - helloReq, ok := msg.(*helloRequestMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(helloReq, msg) - } - - if !c.isClient { - return c.sendAlert(alertNoRenegotiation) - } - - switch c.config.Renegotiation { - case RenegotiateNever: - return c.sendAlert(alertNoRenegotiation) - case RenegotiateOnceAsClient: - if c.handshakes > 1 { - return c.sendAlert(alertNoRenegotiation) - } - case RenegotiateFreelyAsClient: - // Ok. - default: - c.sendAlert(alertInternalError) - return errors.New("tls: unknown Renegotiation value") - } - - c.handshakeMutex.Lock() - defer c.handshakeMutex.Unlock() - - c.isHandshakeComplete.Store(false) - if c.handshakeErr = c.clientHandshake(context.Background()); c.handshakeErr == nil { - c.handshakes++ - } - return c.handshakeErr -} - -// handlePostHandshakeMessage processes a handshake message arrived after the -// handshake is complete. Up to TLS 1.2, it indicates the start of a renegotiation. -func (c *Conn) handlePostHandshakeMessage() error { - if c.vers != VersionTLS13 { - return c.handleRenegotiation() - } - - msg, err := c.readHandshake(nil) - if err != nil { - return err - } - c.retryCount++ - if c.retryCount > maxUselessRecords { - c.sendAlert(alertUnexpectedMessage) - return c.in.setErrorLocked(errors.New("tls: too many non-advancing records")) - } - - switch msg := msg.(type) { - case *newSessionTicketMsgTLS13: - return c.handleNewSessionTicket(msg) - case *keyUpdateMsg: - return c.handleKeyUpdate(msg) - } - // The QUIC layer is supposed to treat an unexpected post-handshake CertificateRequest - // as a QUIC-level PROTOCOL_VIOLATION error (RFC 9001, Section 4.4). Returning an - // unexpected_message alert here doesn't provide it with enough information to distinguish - // this condition from other unexpected messages. This is probably fine. - c.sendAlert(alertUnexpectedMessage) - return fmt.Errorf("tls: received unexpected handshake message of type %T", msg) -} - -func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) error { - if c.quic != nil { - c.sendAlert(alertUnexpectedMessage) - return c.in.setErrorLocked(errors.New("tls: received unexpected key update message")) - } - - cipherSuite := cipherSuiteTLS13ByID(c.cipherSuite) - if cipherSuite == nil { - return c.in.setErrorLocked(c.sendAlert(alertInternalError)) - } - - newSecret := cipherSuite.nextTrafficSecret(c.in.trafficSecret) - c.in.setTrafficSecret(cipherSuite, QUICEncryptionLevelInitial, newSecret) - - if keyUpdate.updateRequested { - c.out.Lock() - defer c.out.Unlock() - - msg := &keyUpdateMsg{} - msgBytes, err := msg.marshal() - if err != nil { - return err - } - _, err = c.writeRecordLocked(recordTypeHandshake, msgBytes) - if err != nil { - // Surface the error at the next write. - c.out.setErrorLocked(err) - return nil - } - - newSecret := cipherSuite.nextTrafficSecret(c.out.trafficSecret) - c.out.setTrafficSecret(cipherSuite, QUICEncryptionLevelInitial, newSecret) - } - - return nil -} - -// Read reads data from the connection. -// -// As Read calls Handshake, in order to prevent indefinite blocking a deadline -// must be set for both Read and Write before Read is called when the handshake -// has not yet completed. See SetDeadline, SetReadDeadline, and -// SetWriteDeadline. -func (c *Conn) Read(b []byte) (int, error) { - if err := c.Handshake(); err != nil { - return 0, err - } - if len(b) == 0 { - // Put this after Handshake, in case people were calling - // Read(nil) for the side effect of the Handshake. - return 0, nil - } - - c.in.Lock() - defer c.in.Unlock() - - for c.input.Len() == 0 { - if err := c.readRecord(); err != nil { - return 0, err - } - for c.hand.Len() > 0 { - if err := c.handlePostHandshakeMessage(); err != nil { - return 0, err - } - } - } - - n, _ := c.input.Read(b) - - // If a close-notify alert is waiting, read it so that we can return (n, - // EOF) instead of (n, nil), to signal to the HTTP response reading - // goroutine that the connection is now closed. This eliminates a race - // where the HTTP response reading goroutine would otherwise not observe - // the EOF until its next read, by which time a client goroutine might - // have already tried to reuse the HTTP connection for a new request. - // See https://golang.org/cl/76400046 and https://golang.org/issue/3514 - if n != 0 && c.input.Len() == 0 && c.rawInput.Len() > 0 && - recordType(c.rawInput.Bytes()[0]) == recordTypeAlert { - if err := c.readRecord(); err != nil { - return n, err // will be io.EOF on closeNotify - } - } - - return n, nil -} - -// Close closes the connection. -func (c *Conn) Close() error { - // Interlock with Conn.Write above. - var x int32 - for { - x = c.activeCall.Load() - if x&1 != 0 { - return net.ErrClosed - } - if c.activeCall.CompareAndSwap(x, x|1) { - break - } - } - if x != 0 { - // io.Writer and io.Closer should not be used concurrently. - // If Close is called while a Write is currently in-flight, - // interpret that as a sign that this Close is really just - // being used to break the Write and/or clean up resources and - // avoid sending the alertCloseNotify, which may block - // waiting on handshakeMutex or the c.out mutex. - return c.conn.Close() - } - - var alertErr error - if c.isHandshakeComplete.Load() { - if err := c.closeNotify(); err != nil { - alertErr = fmt.Errorf("tls: failed to send closeNotify alert (but connection was closed anyway): %w", err) - } - } - - if err := c.conn.Close(); err != nil { - return err - } - return alertErr -} - -var errEarlyCloseWrite = errors.New("tls: CloseWrite called before handshake complete") - -// CloseWrite shuts down the writing side of the connection. It should only be -// called once the handshake has completed and does not call CloseWrite on the -// underlying connection. Most callers should just use Close. -func (c *Conn) CloseWrite() error { - if !c.isHandshakeComplete.Load() { - return errEarlyCloseWrite - } - - return c.closeNotify() -} - -func (c *Conn) closeNotify() error { - c.out.Lock() - defer c.out.Unlock() - - if !c.closeNotifySent { - // Set a Write Deadline to prevent possibly blocking forever. - c.SetWriteDeadline(time.Now().Add(time.Second * 5)) - c.closeNotifyErr = c.sendAlertLocked(alertCloseNotify) - c.closeNotifySent = true - // Any subsequent writes will fail. - c.SetWriteDeadline(time.Now()) - } - return c.closeNotifyErr -} - -// Handshake runs the client or server handshake -// protocol if it has not yet been run. -// -// Most uses of this package need not call Handshake explicitly: the -// first Read or Write will call it automatically. -// -// For control over canceling or setting a timeout on a handshake, use -// HandshakeContext or the Dialer's DialContext method instead. -func (c *Conn) Handshake() error { - return c.HandshakeContext(context.Background()) -} - -// HandshakeContext runs the client or server handshake -// protocol if it has not yet been run. -// -// The provided Context must be non-nil. If the context is canceled before -// the handshake is complete, the handshake is interrupted and an error is returned. -// Once the handshake has completed, cancellation of the context will not affect the -// connection. -// -// Most uses of this package need not call HandshakeContext explicitly: the -// first Read or Write will call it automatically. -func (c *Conn) HandshakeContext(ctx context.Context) error { - // Delegate to unexported method for named return - // without confusing documented signature. - return c.handshakeContext(ctx) -} - -func (c *Conn) handshakeContext(ctx context.Context) (ret error) { - // Fast sync/atomic-based exit if there is no handshake in flight and the - // last one succeeded without an error. Avoids the expensive context setup - // and mutex for most Read and Write calls. - if c.isHandshakeComplete.Load() { - return nil - } - - handshakeCtx, cancel := context.WithCancel(ctx) - // Note: defer this before starting the "interrupter" goroutine - // so that we can tell the difference between the input being canceled and - // this cancellation. In the former case, we need to close the connection. - defer cancel() - - if c.quic != nil { - c.quic.cancelc = handshakeCtx.Done() - c.quic.cancel = cancel - } else if ctx.Done() != nil { - // Start the "interrupter" goroutine, if this context might be canceled. - // (The background context cannot). - // - // The interrupter goroutine waits for the input context to be done and - // closes the connection if this happens before the function returns. - done := make(chan struct{}) - interruptRes := make(chan error, 1) - defer func() { - close(done) - if ctxErr := <-interruptRes; ctxErr != nil { - // Return context error to user. - ret = ctxErr - } - }() - go func() { - select { - case <-handshakeCtx.Done(): - // Close the connection, discarding the error - _ = c.conn.Close() - interruptRes <- handshakeCtx.Err() - case <-done: - interruptRes <- nil - } - }() - } - - c.handshakeMutex.Lock() - defer c.handshakeMutex.Unlock() - - if err := c.handshakeErr; err != nil { - return err - } - if c.isHandshakeComplete.Load() { - return nil - } - - c.in.Lock() - defer c.in.Unlock() - - c.handshakeErr = c.handshakeFn(handshakeCtx) - if c.handshakeErr == nil { - c.handshakes++ - } else { - // If an error occurred during the handshake try to flush the - // alert that might be left in the buffer. - c.flush() - } - - if c.handshakeErr == nil && !c.isHandshakeComplete.Load() { - c.handshakeErr = errors.New("tls: internal error: handshake should have had a result") - } - if c.handshakeErr != nil && c.isHandshakeComplete.Load() { - panic("tls: internal error: handshake returned an error but is marked successful") - } - - if c.quic != nil { - if c.handshakeErr == nil { - c.quicHandshakeComplete() - // Provide the 1-RTT read secret now that the handshake is complete. - // The QUIC layer MUST NOT decrypt 1-RTT packets prior to completing - // the handshake (RFC 9001, Section 5.7). - c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret) - } else { - var a alert - c.out.Lock() - if !errors.As(c.out.err, &a) { - a = alertInternalError - } - c.out.Unlock() - // Return an error which wraps both the handshake error and - // any alert error we may have sent, or alertInternalError - // if we didn't send an alert. - // Truncate the text of the alert to 0 characters. - c.handshakeErr = fmt.Errorf("%w%.0w", c.handshakeErr, AlertError(a)) - } - close(c.quic.blockedc) - close(c.quic.signalc) - } - - return c.handshakeErr -} - -// ConnectionState returns basic TLS details about the connection. -func (c *Conn) ConnectionState() ConnectionState { - c.handshakeMutex.Lock() - defer c.handshakeMutex.Unlock() - return c.connectionStateLocked() -} - -func (c *Conn) connectionStateLocked() ConnectionState { - var state connectionState - state.HandshakeComplete = c.isHandshakeComplete.Load() - state.Version = c.vers - state.NegotiatedProtocol = c.clientProtocol - state.DidResume = c.didResume - state.NegotiatedProtocolIsMutual = true - state.ServerName = c.serverName - state.CipherSuite = c.cipherSuite - state.PeerCertificates = c.peerCertificates - state.VerifiedChains = c.verifiedChains - state.SignedCertificateTimestamps = c.scts - state.OCSPResponse = c.ocspResponse - if !c.didResume && c.vers != VersionTLS13 { - if c.clientFinishedIsFirst { - state.TLSUnique = c.clientFinished[:] - } else { - state.TLSUnique = c.serverFinished[:] - } - } - if c.config.Renegotiation != RenegotiateNever { - state.ekm = noExportedKeyingMaterial - } else { - state.ekm = c.ekm - } - return toConnectionState(state) -} - -// OCSPResponse returns the stapled OCSP response from the TLS server, if -// any. (Only valid for client connections.) -func (c *Conn) OCSPResponse() []byte { - c.handshakeMutex.Lock() - defer c.handshakeMutex.Unlock() - - return c.ocspResponse -} - -// VerifyHostname checks that the peer certificate chain is valid for -// connecting to host. If so, it returns nil; if not, it returns an error -// describing the problem. -func (c *Conn) VerifyHostname(host string) error { - c.handshakeMutex.Lock() - defer c.handshakeMutex.Unlock() - if !c.isClient { - return errors.New("tls: VerifyHostname called on TLS server connection") - } - if !c.isHandshakeComplete.Load() { - return errors.New("tls: handshake has not yet been performed") - } - if len(c.verifiedChains) == 0 { - return errors.New("tls: handshake did not verify certificate chain") - } - return c.peerCertificates[0].VerifyHostname(host) -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/handshake_client.go b/vendor/github.com/quic-go/qtls-go1-20/handshake_client.go deleted file mode 100644 index cc9ceddd..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/handshake_client.go +++ /dev/null @@ -1,1131 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "bytes" - "context" - "crypto" - "crypto/ecdh" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/rsa" - "crypto/subtle" - "crypto/x509" - "errors" - "fmt" - "hash" - "io" - "net" - "strings" - "time" - - "golang.org/x/crypto/cryptobyte" -) - -const clientSessionStateVersion = 1 - -type clientHandshakeState struct { - c *Conn - ctx context.Context - serverHello *serverHelloMsg - hello *clientHelloMsg - suite *cipherSuite - finishedHash finishedHash - masterSecret []byte - session *clientSessionState -} - -var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme - -func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { - config := c.config - if len(config.ServerName) == 0 && !config.InsecureSkipVerify { - return nil, nil, errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") - } - - nextProtosLength := 0 - for _, proto := range config.NextProtos { - if l := len(proto); l == 0 || l > 255 { - return nil, nil, errors.New("tls: invalid NextProtos value") - } else { - nextProtosLength += 1 + l - } - } - if nextProtosLength > 0xffff { - return nil, nil, errors.New("tls: NextProtos values too large") - } - - supportedVersions := config.supportedVersions(roleClient) - if len(supportedVersions) == 0 { - return nil, nil, errors.New("tls: no supported versions satisfy MinVersion and MaxVersion") - } - - clientHelloVersion := config.maxSupportedVersion(roleClient) - // The version at the beginning of the ClientHello was capped at TLS 1.2 - // for compatibility reasons. The supported_versions extension is used - // to negotiate versions now. See RFC 8446, Section 4.2.1. - if clientHelloVersion > VersionTLS12 { - clientHelloVersion = VersionTLS12 - } - - hello := &clientHelloMsg{ - vers: clientHelloVersion, - compressionMethods: []uint8{compressionNone}, - random: make([]byte, 32), - ocspStapling: true, - scts: true, - serverName: hostnameInSNI(config.ServerName), - supportedCurves: config.curvePreferences(), - supportedPoints: []uint8{pointFormatUncompressed}, - secureRenegotiationSupported: true, - alpnProtocols: config.NextProtos, - supportedVersions: supportedVersions, - } - - if c.handshakes > 0 { - hello.secureRenegotiation = c.clientFinished[:] - } - - preferenceOrder := cipherSuitesPreferenceOrder - if !hasAESGCMHardwareSupport { - preferenceOrder = cipherSuitesPreferenceOrderNoAES - } - configCipherSuites := config.cipherSuites() - hello.cipherSuites = make([]uint16, 0, len(configCipherSuites)) - - for _, suiteId := range preferenceOrder { - suite := mutualCipherSuite(configCipherSuites, suiteId) - if suite == nil { - continue - } - // Don't advertise TLS 1.2-only cipher suites unless - // we're attempting TLS 1.2. - if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 { - continue - } - hello.cipherSuites = append(hello.cipherSuites, suiteId) - } - - _, err := io.ReadFull(config.rand(), hello.random) - if err != nil { - return nil, nil, errors.New("tls: short read from Rand: " + err.Error()) - } - - // A random session ID is used to detect when the server accepted a ticket - // and is resuming a session (see RFC 5077). In TLS 1.3, it's always set as - // a compatibility measure (see RFC 8446, Section 4.1.2). - // - // The session ID is not set for QUIC connections (see RFC 9001, Section 8.4). - if c.quic == nil { - hello.sessionId = make([]byte, 32) - if _, err := io.ReadFull(config.rand(), hello.sessionId); err != nil { - return nil, nil, errors.New("tls: short read from Rand: " + err.Error()) - } - } - - if hello.vers >= VersionTLS12 { - hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms() - } - if testingOnlyForceClientHelloSignatureAlgorithms != nil { - hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms - } - - var key *ecdh.PrivateKey - if hello.supportedVersions[0] == VersionTLS13 { - if len(hello.supportedVersions) == 1 { - hello.cipherSuites = hello.cipherSuites[:0] - } - if hasAESGCMHardwareSupport { - hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...) - } else { - hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...) - } - - curveID := config.curvePreferences()[0] - if _, ok := curveForCurveID(curveID); !ok { - return nil, nil, errors.New("tls: CurvePreferences includes unsupported curve") - } - key, err = generateECDHEKey(config.rand(), curveID) - if err != nil { - return nil, nil, err - } - hello.keyShares = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} - } - - if c.quic != nil { - p, err := c.quicGetTransportParameters() - if err != nil { - return nil, nil, err - } - if p == nil { - p = []byte{} - } - hello.quicTransportParameters = p - } - - return hello, key, nil -} - -func (c *Conn) clientHandshake(ctx context.Context) (err error) { - if c.config == nil { - c.config = fromConfig(defaultConfig()) - } - - // This may be a renegotiation handshake, in which case some fields - // need to be reset. - c.didResume = false - - hello, ecdheKey, err := c.makeClientHello() - if err != nil { - return err - } - c.serverName = hello.serverName - - cacheKey, session, earlySecret, binderKey, err := c.loadSession(hello) - if err != nil { - return err - } - if cacheKey != "" && session != nil { - defer func() { - // If we got a handshake failure when resuming a session, throw away - // the session ticket. See RFC 5077, Section 3.2. - // - // RFC 8446 makes no mention of dropping tickets on failure, but it - // does require servers to abort on invalid binders, so we need to - // delete tickets to recover from a corrupted PSK. - if err != nil { - c.config.ClientSessionCache.Put(cacheKey, nil) - } - }() - } - - if _, err := c.writeHandshakeRecord(hello, nil); err != nil { - return err - } - - if hello.earlyData { - suite := cipherSuiteTLS13ByID(session.cipherSuite) - transcript := suite.hash.New() - if err := transcriptMsg(hello, transcript); err != nil { - return err - } - earlyTrafficSecret := suite.deriveSecret(earlySecret, clientEarlyTrafficLabel, transcript) - c.quicSetWriteSecret(QUICEncryptionLevelEarly, suite.id, earlyTrafficSecret) - } - - // serverHelloMsg is not included in the transcript - msg, err := c.readHandshake(nil) - if err != nil { - return err - } - - serverHello, ok := msg.(*serverHelloMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(serverHello, msg) - } - - if err := c.pickTLSVersion(serverHello); err != nil { - return err - } - - // If we are negotiating a protocol version that's lower than what we - // support, check for the server downgrade canaries. - // See RFC 8446, Section 4.1.3. - maxVers := c.config.maxSupportedVersion(roleClient) - tls12Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS12 - tls11Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS11 - if maxVers == VersionTLS13 && c.vers <= VersionTLS12 && (tls12Downgrade || tls11Downgrade) || - maxVers == VersionTLS12 && c.vers <= VersionTLS11 && tls11Downgrade { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: downgrade attempt detected, possibly due to a MitM attack or a broken middlebox") - } - - if c.vers == VersionTLS13 { - hs := &clientHandshakeStateTLS13{ - c: c, - ctx: ctx, - serverHello: serverHello, - hello: hello, - ecdheKey: ecdheKey, - session: session, - earlySecret: earlySecret, - binderKey: binderKey, - } - - // In TLS 1.3, session tickets are delivered after the handshake. - return hs.handshake() - } - - hs := &clientHandshakeState{ - c: c, - ctx: ctx, - serverHello: serverHello, - hello: hello, - session: session, - } - - if err := hs.handshake(); err != nil { - return err - } - - // If we had a successful handshake and hs.session is different from - // the one already cached - cache a new one. - if cacheKey != "" && hs.session != nil && session != hs.session { - c.config.ClientSessionCache.Put(cacheKey, toClientSessionState(hs.session)) - } - - return nil -} - -// extract the app data saved in the session.nonce, -// and set the session.nonce to the actual nonce value -func (c *Conn) decodeSessionState(session *clientSessionState) (uint32 /* max early data */, []byte /* app data */, bool /* ok */) { - s := cryptobyte.String(session.nonce) - var version uint16 - if !s.ReadUint16(&version) { - return 0, nil, false - } - if version != clientSessionStateVersion { - return 0, nil, false - } - var maxEarlyData uint32 - if !s.ReadUint32(&maxEarlyData) { - return 0, nil, false - } - var appData []byte - if !readUint16LengthPrefixed(&s, &appData) { - return 0, nil, false - } - var nonce []byte - if !readUint16LengthPrefixed(&s, &nonce) { - return 0, nil, false - } - session.nonce = nonce - return maxEarlyData, appData, true -} - -func (c *Conn) loadSession(hello *clientHelloMsg) (cacheKey string, - session *clientSessionState, earlySecret, binderKey []byte, err error) { - if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil { - return "", nil, nil, nil, nil - } - - hello.ticketSupported = true - - if hello.supportedVersions[0] == VersionTLS13 { - // Require DHE on resumption as it guarantees forward secrecy against - // compromise of the session ticket key. See RFC 8446, Section 4.2.9. - hello.pskModes = []uint8{pskModeDHE} - } - - // Session resumption is not allowed if renegotiating because - // renegotiation is primarily used to allow a client to send a client - // certificate, which would be skipped if session resumption occurred. - if c.handshakes != 0 { - return "", nil, nil, nil, nil - } - - // Try to resume a previously negotiated TLS session, if available. - cacheKey = c.clientSessionCacheKey() - if cacheKey == "" { - return "", nil, nil, nil, nil - } - sess, ok := c.config.ClientSessionCache.Get(cacheKey) - if !ok || sess == nil { - return cacheKey, nil, nil, nil, nil - } - session = fromClientSessionState(sess) - - var appData []byte - var maxEarlyData uint32 - if session.vers == VersionTLS13 { - var ok bool - maxEarlyData, appData, ok = c.decodeSessionState(session) - if !ok { // delete it, if parsing failed - c.config.ClientSessionCache.Put(cacheKey, nil) - return cacheKey, nil, nil, nil, nil - } - } - - // Check that version used for the previous session is still valid. - versOk := false - for _, v := range hello.supportedVersions { - if v == session.vers { - versOk = true - break - } - } - if !versOk { - return cacheKey, nil, nil, nil, nil - } - - // Check that the cached server certificate is not expired, and that it's - // valid for the ServerName. This should be ensured by the cache key, but - // protect the application from a faulty ClientSessionCache implementation. - if !c.config.InsecureSkipVerify { - if len(session.verifiedChains) == 0 { - // The original connection had InsecureSkipVerify, while this doesn't. - return cacheKey, nil, nil, nil, nil - } - serverCert := session.serverCertificates[0] - if c.config.time().After(serverCert.NotAfter) { - // Expired certificate, delete the entry. - c.config.ClientSessionCache.Put(cacheKey, nil) - return cacheKey, nil, nil, nil, nil - } - if err := serverCert.VerifyHostname(c.config.ServerName); err != nil { - return cacheKey, nil, nil, nil, nil - } - } - - if session.vers != VersionTLS13 { - // In TLS 1.2 the cipher suite must match the resumed session. Ensure we - // are still offering it. - if mutualCipherSuite(hello.cipherSuites, session.cipherSuite) == nil { - return cacheKey, nil, nil, nil, nil - } - - hello.sessionTicket = session.sessionTicket - return - } - - // Check that the session ticket is not expired. - if c.config.time().After(session.useBy) { - c.config.ClientSessionCache.Put(cacheKey, nil) - return cacheKey, nil, nil, nil, nil - } - - // In TLS 1.3 the KDF hash must match the resumed session. Ensure we - // offer at least one cipher suite with that hash. - cipherSuite := cipherSuiteTLS13ByID(session.cipherSuite) - if cipherSuite == nil { - return cacheKey, nil, nil, nil, nil - } - cipherSuiteOk := false - for _, offeredID := range hello.cipherSuites { - offeredSuite := cipherSuiteTLS13ByID(offeredID) - if offeredSuite != nil && offeredSuite.hash == cipherSuite.hash { - cipherSuiteOk = true - break - } - } - if !cipherSuiteOk { - return cacheKey, nil, nil, nil, nil - } - - if c.quic != nil && maxEarlyData > 0 { - var earlyData bool - if session.vers == VersionTLS13 && c.extraConfig != nil && c.extraConfig.SetAppDataFromSessionState != nil { - earlyData = c.extraConfig.SetAppDataFromSessionState(appData) - } - // For 0-RTT, the cipher suite has to match exactly. - if earlyData && mutualCipherSuiteTLS13(hello.cipherSuites, session.cipherSuite) != nil { - hello.earlyData = true - } - } - - // Set the pre_shared_key extension. See RFC 8446, Section 4.2.11.1. - ticketAge := uint32(c.config.time().Sub(session.receivedAt) / time.Millisecond) - identity := pskIdentity{ - label: session.sessionTicket, - obfuscatedTicketAge: ticketAge + session.ageAdd, - } - hello.pskIdentities = []pskIdentity{identity} - hello.pskBinders = [][]byte{make([]byte, cipherSuite.hash.Size())} - - // Compute the PSK binders. See RFC 8446, Section 4.2.11.2. - psk := cipherSuite.expandLabel(session.masterSecret, "resumption", - session.nonce, cipherSuite.hash.Size()) - earlySecret = cipherSuite.extract(psk, nil) - binderKey = cipherSuite.deriveSecret(earlySecret, resumptionBinderLabel, nil) - transcript := cipherSuite.hash.New() - helloBytes, err := hello.marshalWithoutBinders() - if err != nil { - return "", nil, nil, nil, err - } - transcript.Write(helloBytes) - pskBinders := [][]byte{cipherSuite.finishedHash(binderKey, transcript)} - if err := hello.updateBinders(pskBinders); err != nil { - return "", nil, nil, nil, err - } - - return -} - -func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error { - peerVersion := serverHello.vers - if serverHello.supportedVersion != 0 { - peerVersion = serverHello.supportedVersion - } - - vers, ok := c.config.mutualVersion(roleClient, []uint16{peerVersion}) - if !ok { - c.sendAlert(alertProtocolVersion) - return fmt.Errorf("tls: server selected unsupported protocol version %x", peerVersion) - } - - c.vers = vers - c.haveVers = true - c.in.version = vers - c.out.version = vers - - return nil -} - -// Does the handshake, either a full one or resumes old session. Requires hs.c, -// hs.hello, hs.serverHello, and, optionally, hs.session to be set. -func (hs *clientHandshakeState) handshake() error { - c := hs.c - - isResume, err := hs.processServerHello() - if err != nil { - return err - } - - hs.finishedHash = newFinishedHash(c.vers, hs.suite) - - // No signatures of the handshake are needed in a resumption. - // Otherwise, in a full handshake, if we don't have any certificates - // configured then we will never send a CertificateVerify message and - // thus no signatures are needed in that case either. - if isResume || (len(c.config.Certificates) == 0 && c.config.GetClientCertificate == nil) { - hs.finishedHash.discardHandshakeBuffer() - } - - if err := transcriptMsg(hs.hello, &hs.finishedHash); err != nil { - return err - } - if err := transcriptMsg(hs.serverHello, &hs.finishedHash); err != nil { - return err - } - - c.buffering = true - c.didResume = isResume - if isResume { - if err := hs.establishKeys(); err != nil { - return err - } - if err := hs.readSessionTicket(); err != nil { - return err - } - if err := hs.readFinished(c.serverFinished[:]); err != nil { - return err - } - c.clientFinishedIsFirst = false - // Make sure the connection is still being verified whether or not this - // is a resumption. Resumptions currently don't reverify certificates so - // they don't call verifyServerCertificate. See Issue 31641. - if c.config.VerifyConnection != nil { - if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { - c.sendAlert(alertBadCertificate) - return err - } - } - if err := hs.sendFinished(c.clientFinished[:]); err != nil { - return err - } - if _, err := c.flush(); err != nil { - return err - } - } else { - if err := hs.doFullHandshake(); err != nil { - return err - } - if err := hs.establishKeys(); err != nil { - return err - } - if err := hs.sendFinished(c.clientFinished[:]); err != nil { - return err - } - if _, err := c.flush(); err != nil { - return err - } - c.clientFinishedIsFirst = true - if err := hs.readSessionTicket(); err != nil { - return err - } - if err := hs.readFinished(c.serverFinished[:]); err != nil { - return err - } - } - - c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random) - c.isHandshakeComplete.Store(true) - - return nil -} - -func (hs *clientHandshakeState) pickCipherSuite() error { - if hs.suite = mutualCipherSuite(hs.hello.cipherSuites, hs.serverHello.cipherSuite); hs.suite == nil { - hs.c.sendAlert(alertHandshakeFailure) - return errors.New("tls: server chose an unconfigured cipher suite") - } - - hs.c.cipherSuite = hs.suite.id - return nil -} - -func (hs *clientHandshakeState) doFullHandshake() error { - c := hs.c - - msg, err := c.readHandshake(&hs.finishedHash) - if err != nil { - return err - } - certMsg, ok := msg.(*certificateMsg) - if !ok || len(certMsg.certificates) == 0 { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(certMsg, msg) - } - - msg, err = c.readHandshake(&hs.finishedHash) - if err != nil { - return err - } - - cs, ok := msg.(*certificateStatusMsg) - if ok { - // RFC4366 on Certificate Status Request: - // The server MAY return a "certificate_status" message. - - if !hs.serverHello.ocspStapling { - // If a server returns a "CertificateStatus" message, then the - // server MUST have included an extension of type "status_request" - // with empty "extension_data" in the extended server hello. - - c.sendAlert(alertUnexpectedMessage) - return errors.New("tls: received unexpected CertificateStatus message") - } - - c.ocspResponse = cs.response - - msg, err = c.readHandshake(&hs.finishedHash) - if err != nil { - return err - } - } - - if c.handshakes == 0 { - // If this is the first handshake on a connection, process and - // (optionally) verify the server's certificates. - if err := c.verifyServerCertificate(certMsg.certificates); err != nil { - return err - } - } else { - // This is a renegotiation handshake. We require that the - // server's identity (i.e. leaf certificate) is unchanged and - // thus any previous trust decision is still valid. - // - // See https://mitls.org/pages/attacks/3SHAKE for the - // motivation behind this requirement. - if !bytes.Equal(c.peerCertificates[0].Raw, certMsg.certificates[0]) { - c.sendAlert(alertBadCertificate) - return errors.New("tls: server's identity changed during renegotiation") - } - } - - keyAgreement := hs.suite.ka(c.vers) - - skx, ok := msg.(*serverKeyExchangeMsg) - if ok { - err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx) - if err != nil { - c.sendAlert(alertUnexpectedMessage) - return err - } - - msg, err = c.readHandshake(&hs.finishedHash) - if err != nil { - return err - } - } - - var chainToSend *Certificate - var certRequested bool - certReq, ok := msg.(*certificateRequestMsg) - if ok { - certRequested = true - - cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq) - if chainToSend, err = c.getClientCertificate(cri); err != nil { - c.sendAlert(alertInternalError) - return err - } - - msg, err = c.readHandshake(&hs.finishedHash) - if err != nil { - return err - } - } - - shd, ok := msg.(*serverHelloDoneMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(shd, msg) - } - - // If the server requested a certificate then we have to send a - // Certificate message, even if it's empty because we don't have a - // certificate to send. - if certRequested { - certMsg = new(certificateMsg) - certMsg.certificates = chainToSend.Certificate - if _, err := hs.c.writeHandshakeRecord(certMsg, &hs.finishedHash); err != nil { - return err - } - } - - preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, c.peerCertificates[0]) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - if ckx != nil { - if _, err := hs.c.writeHandshakeRecord(ckx, &hs.finishedHash); err != nil { - return err - } - } - - if chainToSend != nil && len(chainToSend.Certificate) > 0 { - certVerify := &certificateVerifyMsg{} - - key, ok := chainToSend.PrivateKey.(crypto.Signer) - if !ok { - c.sendAlert(alertInternalError) - return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey) - } - - 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 := hs.finishedHash.hashForClientCertificate(sigType, sigHash) - signOpts := crypto.SignerOpts(sigHash) - if sigType == signatureRSAPSS { - signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} - } - certVerify.signature, err = key.Sign(c.config.rand(), signed, signOpts) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - - if _, err := hs.c.writeHandshakeRecord(certVerify, &hs.finishedHash); err != nil { - return err - } - } - - hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) - if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.hello.random, hs.masterSecret); err != nil { - c.sendAlert(alertInternalError) - return errors.New("tls: failed to write to key log: " + err.Error()) - } - - hs.finishedHash.discardHandshakeBuffer() - - return nil -} - -func (hs *clientHandshakeState) establishKeys() error { - c := hs.c - - clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := - keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) - var clientCipher, serverCipher any - var clientHash, serverHash hash.Hash - if hs.suite.cipher != nil { - clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) - clientHash = hs.suite.mac(clientMAC) - serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) - serverHash = hs.suite.mac(serverMAC) - } else { - clientCipher = hs.suite.aead(clientKey, clientIV) - serverCipher = hs.suite.aead(serverKey, serverIV) - } - - c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) - c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) - return nil -} - -func (hs *clientHandshakeState) serverResumedSession() bool { - // If the server responded with the same sessionId then it means the - // sessionTicket is being used to resume a TLS session. - return hs.session != nil && hs.hello.sessionId != nil && - bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId) -} - -func (hs *clientHandshakeState) processServerHello() (bool, error) { - c := hs.c - - if err := hs.pickCipherSuite(); err != nil { - return false, err - } - - if hs.serverHello.compressionMethod != compressionNone { - c.sendAlert(alertUnexpectedMessage) - return false, errors.New("tls: server selected unsupported compression format") - } - - if c.handshakes == 0 && hs.serverHello.secureRenegotiationSupported { - c.secureRenegotiation = true - if len(hs.serverHello.secureRenegotiation) != 0 { - c.sendAlert(alertHandshakeFailure) - return false, errors.New("tls: initial handshake had non-empty renegotiation extension") - } - } - - if c.handshakes > 0 && c.secureRenegotiation { - var expectedSecureRenegotiation [24]byte - copy(expectedSecureRenegotiation[:], c.clientFinished[:]) - copy(expectedSecureRenegotiation[12:], c.serverFinished[:]) - if !bytes.Equal(hs.serverHello.secureRenegotiation, expectedSecureRenegotiation[:]) { - c.sendAlert(alertHandshakeFailure) - return false, errors.New("tls: incorrect renegotiation extension contents") - } - } - - if err := checkALPN(hs.hello.alpnProtocols, hs.serverHello.alpnProtocol, false); err != nil { - c.sendAlert(alertUnsupportedExtension) - return false, err - } - c.clientProtocol = hs.serverHello.alpnProtocol - - c.scts = hs.serverHello.scts - - if !hs.serverResumedSession() { - return false, nil - } - - if hs.session.vers != c.vers { - c.sendAlert(alertHandshakeFailure) - return false, errors.New("tls: server resumed a session with a different version") - } - - if hs.session.cipherSuite != hs.suite.id { - c.sendAlert(alertHandshakeFailure) - return false, errors.New("tls: server resumed a session with a different cipher suite") - } - - // Restore masterSecret, peerCerts, and ocspResponse from previous state - hs.masterSecret = hs.session.masterSecret - c.peerCertificates = hs.session.serverCertificates - c.verifiedChains = hs.session.verifiedChains - c.ocspResponse = hs.session.ocspResponse - // Let the ServerHello SCTs override the session SCTs from the original - // connection, if any are provided - if len(c.scts) == 0 && len(hs.session.scts) != 0 { - c.scts = hs.session.scts - } - - return true, nil -} - -// checkALPN ensure that the server's choice of ALPN protocol is compatible with -// the protocols that we advertised in the Client Hello. -func checkALPN(clientProtos []string, serverProto string, quic bool) error { - if serverProto == "" { - if quic && len(clientProtos) > 0 { - // RFC 9001, Section 8.1 - return errors.New("tls: server did not select an ALPN protocol") - } - return nil - } - if len(clientProtos) == 0 { - return errors.New("tls: server advertised unrequested ALPN extension") - } - for _, proto := range clientProtos { - if proto == serverProto { - return nil - } - } - return errors.New("tls: server selected unadvertised ALPN protocol") -} - -func (hs *clientHandshakeState) readFinished(out []byte) error { - c := hs.c - - if err := c.readChangeCipherSpec(); err != nil { - return err - } - - // finishedMsg is included in the transcript, but not until after we - // check the client version, since the state before this message was - // sent is used during verification. - msg, err := c.readHandshake(nil) - if err != nil { - return err - } - serverFinished, ok := msg.(*finishedMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(serverFinished, msg) - } - - verify := hs.finishedHash.serverSum(hs.masterSecret) - if len(verify) != len(serverFinished.verifyData) || - subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { - c.sendAlert(alertHandshakeFailure) - return errors.New("tls: server's Finished message was incorrect") - } - - if err := transcriptMsg(serverFinished, &hs.finishedHash); err != nil { - return err - } - - copy(out, verify) - return nil -} - -func (hs *clientHandshakeState) readSessionTicket() error { - if !hs.serverHello.ticketSupported { - return nil - } - - c := hs.c - msg, err := c.readHandshake(&hs.finishedHash) - if err != nil { - return err - } - sessionTicketMsg, ok := msg.(*newSessionTicketMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(sessionTicketMsg, msg) - } - - hs.session = &clientSessionState{ - sessionTicket: sessionTicketMsg.ticket, - vers: c.vers, - cipherSuite: hs.suite.id, - masterSecret: hs.masterSecret, - serverCertificates: c.peerCertificates, - verifiedChains: c.verifiedChains, - receivedAt: c.config.time(), - ocspResponse: c.ocspResponse, - scts: c.scts, - } - - return nil -} - -func (hs *clientHandshakeState) sendFinished(out []byte) error { - c := hs.c - - if err := c.writeChangeCipherRecord(); err != nil { - return err - } - - finished := new(finishedMsg) - finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) - if _, err := hs.c.writeHandshakeRecord(finished, &hs.finishedHash); err != nil { - return err - } - copy(out, finished.verifyData) - return nil -} - -// maxRSAKeySize is the maximum RSA key size in bits that we are willing -// to verify the signatures of during a TLS handshake. -const maxRSAKeySize = 8192 - -// verifyServerCertificate parses and verifies the provided chain, setting -// c.verifiedChains and c.peerCertificates or sending the appropriate alert. -func (c *Conn) verifyServerCertificate(certificates [][]byte) error { - activeHandles := make([]*activeCert, len(certificates)) - certs := make([]*x509.Certificate, len(certificates)) - for i, asn1Data := range certificates { - cert, err := clientCertCache.newCert(asn1Data) - if err != nil { - c.sendAlert(alertBadCertificate) - return errors.New("tls: failed to parse certificate from server: " + err.Error()) - } - if cert.cert.PublicKeyAlgorithm == x509.RSA && cert.cert.PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize { - c.sendAlert(alertBadCertificate) - return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", maxRSAKeySize) - } - activeHandles[i] = cert - certs[i] = cert.cert - } - - if !c.config.InsecureSkipVerify { - opts := x509.VerifyOptions{ - Roots: c.config.RootCAs, - CurrentTime: c.config.time(), - DNSName: c.config.ServerName, - Intermediates: x509.NewCertPool(), - } - - for _, cert := range certs[1:] { - opts.Intermediates.AddCert(cert) - } - var err error - c.verifiedChains, err = certs[0].Verify(opts) - if err != nil { - c.sendAlert(alertBadCertificate) - return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err} - } - } - - switch certs[0].PublicKey.(type) { - case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey: - break - default: - c.sendAlert(alertUnsupportedCertificate) - return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey) - } - - c.activeCertHandles = activeHandles - c.peerCertificates = certs - - if c.config.VerifyPeerCertificate != nil { - if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil { - c.sendAlert(alertBadCertificate) - return err - } - } - - if c.config.VerifyConnection != nil { - if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { - c.sendAlert(alertBadCertificate) - return err - } - } - - return nil -} - -// certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS -// <= 1.2 CertificateRequest, making an effort to fill in missing information. -func certificateRequestInfoFromMsg(ctx context.Context, vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo { - cri := &certificateRequestInfo{ - AcceptableCAs: certReq.certificateAuthorities, - Version: vers, - ctx: ctx, - } - - var rsaAvail, ecAvail bool - for _, certType := range certReq.certificateTypes { - switch certType { - case certTypeRSASign: - rsaAvail = true - case certTypeECDSASign: - ecAvail = true - } - } - - if !certReq.hasSignatureAlgorithm { - // Prior to TLS 1.2, signature schemes did not exist. In this case we - // make up a list based on the acceptable certificate types, to help - // GetClientCertificate and SupportsCertificate select the right certificate. - // The hash part of the SignatureScheme is a lie here, because - // TLS 1.0 and 1.1 always use MD5+SHA1 for RSA and SHA1 for ECDSA. - switch { - case rsaAvail && ecAvail: - cri.SignatureSchemes = []SignatureScheme{ - ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, - PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512, PKCS1WithSHA1, - } - case rsaAvail: - cri.SignatureSchemes = []SignatureScheme{ - PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512, PKCS1WithSHA1, - } - case ecAvail: - cri.SignatureSchemes = []SignatureScheme{ - ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, - } - } - return toCertificateRequestInfo(cri) - } - - // Filter the signature schemes based on the certificate types. - // 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 { - sigType, _, err := typeAndHashFromSignatureScheme(sigScheme) - if err != nil { - continue - } - switch sigType { - case signatureECDSA, signatureEd25519: - if ecAvail { - cri.SignatureSchemes = append(cri.SignatureSchemes, sigScheme) - } - case signatureRSAPSS, signaturePKCS1v15: - if rsaAvail { - cri.SignatureSchemes = append(cri.SignatureSchemes, sigScheme) - } - } - } - - return toCertificateRequestInfo(cri) -} - -func (c *Conn) getClientCertificate(cri *CertificateRequestInfo) (*Certificate, error) { - if c.config.GetClientCertificate != nil { - return c.config.GetClientCertificate(cri) - } - - for _, chain := range c.config.Certificates { - if err := cri.SupportsCertificate(&chain); err != nil { - continue - } - return &chain, nil - } - - // No acceptable certificate found. Don't send a certificate. - return new(Certificate), nil -} - -// clientSessionCacheKey returns a key used to cache sessionTickets that could -// be used to resume previously negotiated TLS sessions with a server. -func (c *Conn) clientSessionCacheKey() string { - if len(c.config.ServerName) > 0 { - return c.config.ServerName - } - if c.conn != nil { - return c.conn.RemoteAddr().String() - } - return "" -} - -// 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 { - host := name - if len(host) > 0 && host[0] == '[' && host[len(host)-1] == ']' { - host = host[1 : len(host)-1] - } - if i := strings.LastIndex(host, "%"); i > 0 { - host = host[:i] - } - if net.ParseIP(host) != nil { - return "" - } - for len(name) > 0 && name[len(name)-1] == '.' { - name = name[:len(name)-1] - } - return name -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/handshake_client_tls13.go b/vendor/github.com/quic-go/qtls-go1-20/handshake_client_tls13.go deleted file mode 100644 index e9d0a533..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/handshake_client_tls13.go +++ /dev/null @@ -1,782 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "bytes" - "context" - "crypto" - "crypto/ecdh" - "crypto/hmac" - "crypto/rsa" - "encoding/binary" - "errors" - "hash" - "time" - - "golang.org/x/crypto/cryptobyte" -) - -type clientHandshakeStateTLS13 struct { - c *Conn - ctx context.Context - serverHello *serverHelloMsg - hello *clientHelloMsg - ecdheKey *ecdh.PrivateKey - - session *clientSessionState - earlySecret []byte - binderKey []byte - - certReq *certificateRequestMsgTLS13 - usingPSK bool - sentDummyCCS bool - suite *cipherSuiteTLS13 - transcript hash.Hash - masterSecret []byte - trafficSecret []byte // client_application_traffic_secret_0 -} - -// handshake requires hs.c, hs.hello, hs.serverHello, hs.ecdheKey, and, -// optionally, hs.session, hs.earlySecret and hs.binderKey to be set. -func (hs *clientHandshakeStateTLS13) handshake() error { - c := hs.c - - if needFIPS() { - return errors.New("tls: internal error: TLS 1.3 reached in FIPS mode") - } - - // The server must not select TLS 1.3 in a renegotiation. See RFC 8446, - // sections 4.1.2 and 4.1.3. - if c.handshakes > 0 { - c.sendAlert(alertProtocolVersion) - return errors.New("tls: server selected TLS 1.3 in a renegotiation") - } - - // Consistency check on the presence of a keyShare and its parameters. - if hs.ecdheKey == nil || len(hs.hello.keyShares) != 1 { - return c.sendAlert(alertInternalError) - } - - if err := hs.checkServerHelloOrHRR(); err != nil { - return err - } - - hs.transcript = hs.suite.hash.New() - - if err := transcriptMsg(hs.hello, hs.transcript); err != nil { - return err - } - - if bytes.Equal(hs.serverHello.random, helloRetryRequestRandom) { - if err := hs.sendDummyChangeCipherSpec(); err != nil { - return err - } - if err := hs.processHelloRetryRequest(); err != nil { - return err - } - } - - if err := transcriptMsg(hs.serverHello, hs.transcript); err != nil { - return err - } - - c.buffering = true - if err := hs.processServerHello(); err != nil { - return err - } - if err := hs.sendDummyChangeCipherSpec(); err != nil { - return err - } - if err := hs.establishHandshakeKeys(); err != nil { - return err - } - if err := hs.readServerParameters(); err != nil { - return err - } - if err := hs.readServerCertificate(); err != nil { - return err - } - if err := hs.readServerFinished(); err != nil { - return err - } - if err := hs.sendClientCertificate(); err != nil { - return err - } - if err := hs.sendClientFinished(); err != nil { - return err - } - if _, err := c.flush(); err != nil { - return err - } - - c.isHandshakeComplete.Store(true) - - return nil -} - -// checkServerHelloOrHRR does validity checks that apply to both ServerHello and -// HelloRetryRequest messages. It sets hs.suite. -func (hs *clientHandshakeStateTLS13) checkServerHelloOrHRR() error { - c := hs.c - - if hs.serverHello.supportedVersion == 0 { - c.sendAlert(alertMissingExtension) - return errors.New("tls: server selected TLS 1.3 using the legacy version field") - } - - if hs.serverHello.supportedVersion != VersionTLS13 { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server selected an invalid version after a HelloRetryRequest") - } - - if hs.serverHello.vers != VersionTLS12 { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server sent an incorrect legacy version") - } - - if hs.serverHello.ocspStapling || - hs.serverHello.ticketSupported || - hs.serverHello.secureRenegotiationSupported || - len(hs.serverHello.secureRenegotiation) != 0 || - len(hs.serverHello.alpnProtocol) != 0 || - len(hs.serverHello.scts) != 0 { - c.sendAlert(alertUnsupportedExtension) - return errors.New("tls: server sent a ServerHello extension forbidden in TLS 1.3") - } - - if !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server did not echo the legacy session ID") - } - - if hs.serverHello.compressionMethod != compressionNone { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server selected unsupported compression format") - } - - selectedSuite := mutualCipherSuiteTLS13(hs.hello.cipherSuites, hs.serverHello.cipherSuite) - if hs.suite != nil && selectedSuite != hs.suite { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server changed cipher suite after a HelloRetryRequest") - } - if selectedSuite == nil { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server chose an unconfigured cipher suite") - } - hs.suite = selectedSuite - c.cipherSuite = hs.suite.id - - return nil -} - -// sendDummyChangeCipherSpec sends a ChangeCipherSpec record for compatibility -// with middleboxes that didn't implement TLS correctly. See RFC 8446, Appendix D.4. -func (hs *clientHandshakeStateTLS13) sendDummyChangeCipherSpec() error { - if hs.c.quic != nil { - return nil - } - if hs.sentDummyCCS { - return nil - } - hs.sentDummyCCS = true - - return hs.c.writeChangeCipherRecord() -} - -// processHelloRetryRequest handles the HRR in hs.serverHello, modifies and -// resends hs.hello, and reads the new ServerHello into hs.serverHello. -func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { - c := hs.c - - // The first ClientHello gets double-hashed into the transcript upon a - // HelloRetryRequest. (The idea is that the server might offload transcript - // storage to the client in the cookie.) See RFC 8446, Section 4.4.1. - chHash := hs.transcript.Sum(nil) - hs.transcript.Reset() - hs.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) - hs.transcript.Write(chHash) - if err := transcriptMsg(hs.serverHello, hs.transcript); err != nil { - return err - } - - // The only HelloRetryRequest extensions we support are key_share and - // cookie, and clients must abort the handshake if the HRR would not result - // in any change in the ClientHello. - if hs.serverHello.selectedGroup == 0 && hs.serverHello.cookie == nil { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server sent an unnecessary HelloRetryRequest message") - } - - if hs.serverHello.cookie != nil { - hs.hello.cookie = hs.serverHello.cookie - } - - if hs.serverHello.serverShare.group != 0 { - c.sendAlert(alertDecodeError) - return errors.New("tls: received malformed key_share extension") - } - - // If the server sent a key_share extension selecting a group, ensure it's - // a group we advertised but did not send a key share for, and send a key - // share for it this time. - if curveID := hs.serverHello.selectedGroup; curveID != 0 { - curveOK := false - for _, id := range hs.hello.supportedCurves { - if id == curveID { - curveOK = true - break - } - } - if !curveOK { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server selected unsupported group") - } - if sentID, _ := curveIDForCurve(hs.ecdheKey.Curve()); sentID == curveID { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server sent an unnecessary HelloRetryRequest key_share") - } - if _, ok := curveForCurveID(curveID); !ok { - c.sendAlert(alertInternalError) - return errors.New("tls: CurvePreferences includes unsupported curve") - } - key, err := generateECDHEKey(c.config.rand(), curveID) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - hs.ecdheKey = key - hs.hello.keyShares = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} - } - - hs.hello.raw = nil - if len(hs.hello.pskIdentities) > 0 { - pskSuite := cipherSuiteTLS13ByID(hs.session.cipherSuite) - if pskSuite == nil { - return c.sendAlert(alertInternalError) - } - if pskSuite.hash == hs.suite.hash { - // Update binders and obfuscated_ticket_age. - ticketAge := uint32(c.config.time().Sub(hs.session.receivedAt) / time.Millisecond) - hs.hello.pskIdentities[0].obfuscatedTicketAge = ticketAge + hs.session.ageAdd - - transcript := hs.suite.hash.New() - transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) - transcript.Write(chHash) - if err := transcriptMsg(hs.serverHello, transcript); err != nil { - return err - } - helloBytes, err := hs.hello.marshalWithoutBinders() - if err != nil { - return err - } - transcript.Write(helloBytes) - pskBinders := [][]byte{hs.suite.finishedHash(hs.binderKey, transcript)} - if err := hs.hello.updateBinders(pskBinders); err != nil { - return err - } - } else { - // Server selected a cipher suite incompatible with the PSK. - hs.hello.pskIdentities = nil - hs.hello.pskBinders = nil - } - } - - if hs.hello.earlyData { - hs.hello.earlyData = false - c.quicRejectedEarlyData() - } - - if _, err := hs.c.writeHandshakeRecord(hs.hello, hs.transcript); err != nil { - return err - } - - // serverHelloMsg is not included in the transcript - msg, err := c.readHandshake(nil) - if err != nil { - return err - } - - serverHello, ok := msg.(*serverHelloMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(serverHello, msg) - } - hs.serverHello = serverHello - - if err := hs.checkServerHelloOrHRR(); err != nil { - return err - } - - return nil -} - -func (hs *clientHandshakeStateTLS13) processServerHello() error { - c := hs.c - - if bytes.Equal(hs.serverHello.random, helloRetryRequestRandom) { - c.sendAlert(alertUnexpectedMessage) - return errors.New("tls: server sent two HelloRetryRequest messages") - } - - if len(hs.serverHello.cookie) != 0 { - c.sendAlert(alertUnsupportedExtension) - return errors.New("tls: server sent a cookie in a normal ServerHello") - } - - if hs.serverHello.selectedGroup != 0 { - c.sendAlert(alertDecodeError) - return errors.New("tls: malformed key_share extension") - } - - if hs.serverHello.serverShare.group == 0 { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server did not send a key share") - } - if sentID, _ := curveIDForCurve(hs.ecdheKey.Curve()); hs.serverHello.serverShare.group != sentID { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server selected unsupported group") - } - - if !hs.serverHello.selectedIdentityPresent { - return nil - } - - if int(hs.serverHello.selectedIdentity) >= len(hs.hello.pskIdentities) { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server selected an invalid PSK") - } - - if len(hs.hello.pskIdentities) != 1 || hs.session == nil { - return c.sendAlert(alertInternalError) - } - pskSuite := cipherSuiteTLS13ByID(hs.session.cipherSuite) - if pskSuite == nil { - return c.sendAlert(alertInternalError) - } - if pskSuite.hash != hs.suite.hash { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: server selected an invalid PSK and cipher suite pair") - } - - hs.usingPSK = true - c.didResume = true - c.peerCertificates = hs.session.serverCertificates - c.verifiedChains = hs.session.verifiedChains - c.ocspResponse = hs.session.ocspResponse - c.scts = hs.session.scts - return nil -} - -func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error { - c := hs.c - - peerKey, err := hs.ecdheKey.Curve().NewPublicKey(hs.serverHello.serverShare.data) - if err != nil { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid server key share") - } - sharedKey, err := hs.ecdheKey.ECDH(peerKey) - if err != nil { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid server key share") - } - - earlySecret := hs.earlySecret - if !hs.usingPSK { - earlySecret = hs.suite.extract(nil, nil) - } - - handshakeSecret := hs.suite.extract(sharedKey, - hs.suite.deriveSecret(earlySecret, "derived", nil)) - - clientSecret := hs.suite.deriveSecret(handshakeSecret, - clientHandshakeTrafficLabel, hs.transcript) - c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, clientSecret) - serverSecret := hs.suite.deriveSecret(handshakeSecret, - serverHandshakeTrafficLabel, hs.transcript) - c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, serverSecret) - - if c.quic != nil { - if c.hand.Len() != 0 { - c.sendAlert(alertUnexpectedMessage) - } - c.quicSetWriteSecret(QUICEncryptionLevelHandshake, hs.suite.id, clientSecret) - c.quicSetReadSecret(QUICEncryptionLevelHandshake, hs.suite.id, serverSecret) - } - - err = c.config.writeKeyLog(keyLogLabelClientHandshake, hs.hello.random, clientSecret) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - err = c.config.writeKeyLog(keyLogLabelServerHandshake, hs.hello.random, serverSecret) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - - hs.masterSecret = hs.suite.extract(nil, - hs.suite.deriveSecret(handshakeSecret, "derived", nil)) - - return nil -} - -func (hs *clientHandshakeStateTLS13) readServerParameters() error { - c := hs.c - - msg, err := c.readHandshake(hs.transcript) - if err != nil { - return err - } - - encryptedExtensions, ok := msg.(*encryptedExtensionsMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(encryptedExtensions, msg) - } - - if err := checkALPN(hs.hello.alpnProtocols, encryptedExtensions.alpnProtocol, c.quic != nil); err != nil { - // RFC 8446 specifies that no_application_protocol is sent by servers, but - // does not specify how clients handle the selection of an incompatible protocol. - // RFC 9001 Section 8.1 specifies that QUIC clients send no_application_protocol - // in this case. Always sending no_application_protocol seems reasonable. - c.sendAlert(alertNoApplicationProtocol) - return err - } - c.clientProtocol = encryptedExtensions.alpnProtocol - - if c.quic != nil { - if encryptedExtensions.quicTransportParameters == nil { - // RFC 9001 Section 8.2. - c.sendAlert(alertMissingExtension) - return errors.New("tls: server did not send a quic_transport_parameters extension") - } - c.quicSetTransportParameters(encryptedExtensions.quicTransportParameters) - } else { - if encryptedExtensions.quicTransportParameters != nil { - c.sendAlert(alertUnsupportedExtension) - return errors.New("tls: server sent an unexpected quic_transport_parameters extension") - } - } - - if hs.hello.earlyData && !encryptedExtensions.earlyData { - c.quicRejectedEarlyData() - } - - return nil -} - -func (hs *clientHandshakeStateTLS13) readServerCertificate() error { - c := hs.c - - // Either a PSK or a certificate is always used, but not both. - // See RFC 8446, Section 4.1.1. - if hs.usingPSK { - // Make sure the connection is still being verified whether or not this - // is a resumption. Resumptions currently don't reverify certificates so - // they don't call verifyServerCertificate. See Issue 31641. - if c.config.VerifyConnection != nil { - if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { - c.sendAlert(alertBadCertificate) - return err - } - } - return nil - } - - msg, err := c.readHandshake(hs.transcript) - if err != nil { - return err - } - - certReq, ok := msg.(*certificateRequestMsgTLS13) - if ok { - hs.certReq = certReq - - msg, err = c.readHandshake(hs.transcript) - if err != nil { - return err - } - } - - certMsg, ok := msg.(*certificateMsgTLS13) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(certMsg, msg) - } - if len(certMsg.certificate.Certificate) == 0 { - c.sendAlert(alertDecodeError) - return errors.New("tls: received empty certificates message") - } - - c.scts = certMsg.certificate.SignedCertificateTimestamps - c.ocspResponse = certMsg.certificate.OCSPStaple - - if err := c.verifyServerCertificate(certMsg.certificate.Certificate); err != nil { - return err - } - - // certificateVerifyMsg is included in the transcript, but not until - // after we verify the handshake signature, since the state before - // this message was sent is used. - msg, err = c.readHandshake(nil) - if err != nil { - return err - } - - certVerify, ok := msg.(*certificateVerifyMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(certVerify, msg) - } - - // See RFC 8446, Section 4.4.3. - if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: certificate used with invalid signature algorithm") - } - sigType, sigHash, err := typeAndHashFromSignatureScheme(certVerify.signatureAlgorithm) - if err != nil { - return c.sendAlert(alertInternalError) - } - if sigType == signaturePKCS1v15 || sigHash == crypto.SHA1 { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: certificate used with invalid signature algorithm") - } - signed := signedMessage(sigHash, serverSignatureContext, hs.transcript) - if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey, - sigHash, signed, certVerify.signature); err != nil { - c.sendAlert(alertDecryptError) - return errors.New("tls: invalid signature by the server certificate: " + err.Error()) - } - - if err := transcriptMsg(certVerify, hs.transcript); err != nil { - return err - } - - return nil -} - -func (hs *clientHandshakeStateTLS13) readServerFinished() error { - c := hs.c - - // finishedMsg is included in the transcript, but not until after we - // check the client version, since the state before this message was - // sent is used during verification. - msg, err := c.readHandshake(nil) - if err != nil { - return err - } - - finished, ok := msg.(*finishedMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(finished, msg) - } - - expectedMAC := hs.suite.finishedHash(c.in.trafficSecret, hs.transcript) - if !hmac.Equal(expectedMAC, finished.verifyData) { - c.sendAlert(alertDecryptError) - return errors.New("tls: invalid server finished hash") - } - - if err := transcriptMsg(finished, hs.transcript); err != nil { - return err - } - - // Derive secrets that take context through the server Finished. - - hs.trafficSecret = hs.suite.deriveSecret(hs.masterSecret, - clientApplicationTrafficLabel, hs.transcript) - serverSecret := hs.suite.deriveSecret(hs.masterSecret, - serverApplicationTrafficLabel, hs.transcript) - c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, serverSecret) - - err = c.config.writeKeyLog(keyLogLabelClientTraffic, hs.hello.random, hs.trafficSecret) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - err = c.config.writeKeyLog(keyLogLabelServerTraffic, hs.hello.random, serverSecret) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - - c.ekm = hs.suite.exportKeyingMaterial(hs.masterSecret, hs.transcript) - - return nil -} - -func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { - c := hs.c - - if hs.certReq == nil { - return nil - } - - cert, err := c.getClientCertificate(toCertificateRequestInfo(&certificateRequestInfo{ - AcceptableCAs: hs.certReq.certificateAuthorities, - SignatureSchemes: hs.certReq.supportedSignatureAlgorithms, - Version: c.vers, - ctx: hs.ctx, - })) - if err != nil { - return err - } - - certMsg := new(certificateMsgTLS13) - - certMsg.certificate = *cert - certMsg.scts = hs.certReq.scts && len(cert.SignedCertificateTimestamps) > 0 - certMsg.ocspStapling = hs.certReq.ocspStapling && len(cert.OCSPStaple) > 0 - - if _, err := hs.c.writeHandshakeRecord(certMsg, hs.transcript); err != nil { - return err - } - - // If we sent an empty certificate message, skip the CertificateVerify. - if len(cert.Certificate) == 0 { - return nil - } - - certVerifyMsg := new(certificateVerifyMsg) - certVerifyMsg.hasSignatureAlgorithm = true - - certVerifyMsg.signatureAlgorithm, err = selectSignatureScheme(c.vers, cert, hs.certReq.supportedSignatureAlgorithms) - if err != nil { - // getClientCertificate returned a certificate incompatible with the - // CertificateRequestInfo supported signature algorithms. - c.sendAlert(alertHandshakeFailure) - return err - } - - sigType, sigHash, err := typeAndHashFromSignatureScheme(certVerifyMsg.signatureAlgorithm) - if err != nil { - return c.sendAlert(alertInternalError) - } - - signed := signedMessage(sigHash, clientSignatureContext, hs.transcript) - signOpts := crypto.SignerOpts(sigHash) - if sigType == signatureRSAPSS { - signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} - } - sig, err := cert.PrivateKey.(crypto.Signer).Sign(c.config.rand(), signed, signOpts) - if err != nil { - c.sendAlert(alertInternalError) - return errors.New("tls: failed to sign handshake: " + err.Error()) - } - certVerifyMsg.signature = sig - - if _, err := hs.c.writeHandshakeRecord(certVerifyMsg, hs.transcript); err != nil { - return err - } - - return nil -} - -func (hs *clientHandshakeStateTLS13) sendClientFinished() error { - c := hs.c - - finished := &finishedMsg{ - verifyData: hs.suite.finishedHash(c.out.trafficSecret, hs.transcript), - } - - if _, err := hs.c.writeHandshakeRecord(finished, hs.transcript); err != nil { - return err - } - - c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, hs.trafficSecret) - - if !c.config.SessionTicketsDisabled && c.config.ClientSessionCache != nil { - c.resumptionSecret = hs.suite.deriveSecret(hs.masterSecret, - resumptionLabel, hs.transcript) - } - - if c.quic != nil { - if c.hand.Len() != 0 { - c.sendAlert(alertUnexpectedMessage) - } - c.quicSetWriteSecret(QUICEncryptionLevelApplication, hs.suite.id, hs.trafficSecret) - } - - return nil -} - -func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error { - if !c.isClient { - c.sendAlert(alertUnexpectedMessage) - return errors.New("tls: received new session ticket from a client") - } - - if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil { - return nil - } - - // See RFC 8446, Section 4.6.1. - if msg.lifetime == 0 { - return nil - } - lifetime := time.Duration(msg.lifetime) * time.Second - if lifetime > maxSessionTicketLifetime { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: received a session ticket with invalid lifetime") - } - - cipherSuite := cipherSuiteTLS13ByID(c.cipherSuite) - if cipherSuite == nil || c.resumptionSecret == nil { - return c.sendAlert(alertInternalError) - } - - // We need to save the max_early_data_size that the server sent us, in order - // to decide if we're going to try 0-RTT with this ticket. - // However, at the same time, the qtls.ClientSessionTicket needs to be equal to - // the tls.ClientSessionTicket, so we can't just add a new field to the struct. - // We therefore abuse the nonce field (which is a byte slice) - nonceWithEarlyData := make([]byte, len(msg.nonce)+4) - binary.BigEndian.PutUint32(nonceWithEarlyData, msg.maxEarlyData) - copy(nonceWithEarlyData[4:], msg.nonce) - - var appData []byte - if c.extraConfig != nil && c.extraConfig.GetAppDataForSessionState != nil { - appData = c.extraConfig.GetAppDataForSessionState() - } - var b cryptobyte.Builder - b.AddUint16(clientSessionStateVersion) // revision - b.AddUint32(msg.maxEarlyData) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(appData) - }) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(msg.nonce) - }) - - // Save the resumption_master_secret and nonce instead of deriving the PSK - // to do the least amount of work on NewSessionTicket messages before we - // know if the ticket will be used. Forward secrecy of resumed connections - // is guaranteed by the requirement for pskModeDHE. - session := &clientSessionState{ - sessionTicket: msg.label, - vers: c.vers, - cipherSuite: c.cipherSuite, - masterSecret: c.resumptionSecret, - serverCertificates: c.peerCertificates, - verifiedChains: c.verifiedChains, - receivedAt: c.config.time(), - nonce: b.BytesOrPanic(), - useBy: c.config.time().Add(lifetime), - ageAdd: msg.ageAdd, - ocspResponse: c.ocspResponse, - scts: c.scts, - } - - cacheKey := c.clientSessionCacheKey() - if cacheKey != "" { - c.config.ClientSessionCache.Put(cacheKey, toClientSessionState(session)) - } - - return nil -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/handshake_messages.go b/vendor/github.com/quic-go/qtls-go1-20/handshake_messages.go deleted file mode 100644 index 37b01236..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/handshake_messages.go +++ /dev/null @@ -1,1886 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "errors" - "fmt" - "strings" - - "golang.org/x/crypto/cryptobyte" -) - -// The marshalingFunction type is an adapter to allow the use of ordinary -// functions as cryptobyte.MarshalingValue. -type marshalingFunction func(b *cryptobyte.Builder) error - -func (f marshalingFunction) Marshal(b *cryptobyte.Builder) error { - return f(b) -} - -// addBytesWithLength appends a sequence of bytes to the cryptobyte.Builder. If -// the length of the sequence is not the value specified, it produces an error. -func addBytesWithLength(b *cryptobyte.Builder, v []byte, n int) { - b.AddValue(marshalingFunction(func(b *cryptobyte.Builder) error { - if len(v) != n { - return fmt.Errorf("invalid value length: expected %d, got %d", n, len(v)) - } - b.AddBytes(v) - return nil - })) -} - -// addUint64 appends a big-endian, 64-bit value to the cryptobyte.Builder. -func addUint64(b *cryptobyte.Builder, v uint64) { - b.AddUint32(uint32(v >> 32)) - b.AddUint32(uint32(v)) -} - -// readUint64 decodes a big-endian, 64-bit value into out and advances over it. -// It reports whether the read was successful. -func readUint64(s *cryptobyte.String, out *uint64) bool { - var hi, lo uint32 - if !s.ReadUint32(&hi) || !s.ReadUint32(&lo) { - return false - } - *out = uint64(hi)<<32 | uint64(lo) - return true -} - -// readUint8LengthPrefixed acts like s.ReadUint8LengthPrefixed, but targets a -// []byte instead of a cryptobyte.String. -func readUint8LengthPrefixed(s *cryptobyte.String, out *[]byte) bool { - return s.ReadUint8LengthPrefixed((*cryptobyte.String)(out)) -} - -// readUint16LengthPrefixed acts like s.ReadUint16LengthPrefixed, but targets a -// []byte instead of a cryptobyte.String. -func readUint16LengthPrefixed(s *cryptobyte.String, out *[]byte) bool { - return s.ReadUint16LengthPrefixed((*cryptobyte.String)(out)) -} - -// readUint24LengthPrefixed acts like s.ReadUint24LengthPrefixed, but targets a -// []byte instead of a cryptobyte.String. -func readUint24LengthPrefixed(s *cryptobyte.String, out *[]byte) bool { - return s.ReadUint24LengthPrefixed((*cryptobyte.String)(out)) -} - -type clientHelloMsg struct { - raw []byte - vers uint16 - random []byte - sessionId []byte - cipherSuites []uint16 - compressionMethods []uint8 - serverName string - ocspStapling bool - supportedCurves []CurveID - supportedPoints []uint8 - ticketSupported bool - sessionTicket []uint8 - supportedSignatureAlgorithms []SignatureScheme - supportedSignatureAlgorithmsCert []SignatureScheme - secureRenegotiationSupported bool - secureRenegotiation []byte - alpnProtocols []string - scts bool - supportedVersions []uint16 - cookie []byte - keyShares []keyShare - earlyData bool - pskModes []uint8 - pskIdentities []pskIdentity - pskBinders [][]byte - quicTransportParameters []byte -} - -func (m *clientHelloMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var exts cryptobyte.Builder - if len(m.serverName) > 0 { - // RFC 6066, Section 3 - exts.AddUint16(extensionServerName) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint8(0) // name_type = host_name - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes([]byte(m.serverName)) - }) - }) - }) - } - if m.ocspStapling { - // RFC 4366, Section 3.6 - exts.AddUint16(extensionStatusRequest) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint8(1) // status_type = ocsp - exts.AddUint16(0) // empty responder_id_list - exts.AddUint16(0) // empty request_extensions - }) - } - if len(m.supportedCurves) > 0 { - // RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7 - exts.AddUint16(extensionSupportedCurves) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - for _, curve := range m.supportedCurves { - exts.AddUint16(uint16(curve)) - } - }) - }) - } - if len(m.supportedPoints) > 0 { - // RFC 4492, Section 5.1.2 - exts.AddUint16(extensionSupportedPoints) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(m.supportedPoints) - }) - }) - } - if m.ticketSupported { - // RFC 5077, Section 3.2 - exts.AddUint16(extensionSessionTicket) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(m.sessionTicket) - }) - } - if len(m.supportedSignatureAlgorithms) > 0 { - // RFC 5246, Section 7.4.1.4.1 - exts.AddUint16(extensionSignatureAlgorithms) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - for _, sigAlgo := range m.supportedSignatureAlgorithms { - exts.AddUint16(uint16(sigAlgo)) - } - }) - }) - } - if len(m.supportedSignatureAlgorithmsCert) > 0 { - // RFC 8446, Section 4.2.3 - exts.AddUint16(extensionSignatureAlgorithmsCert) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - for _, sigAlgo := range m.supportedSignatureAlgorithmsCert { - exts.AddUint16(uint16(sigAlgo)) - } - }) - }) - } - if m.secureRenegotiationSupported { - // RFC 5746, Section 3.2 - exts.AddUint16(extensionRenegotiationInfo) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(m.secureRenegotiation) - }) - }) - } - if len(m.alpnProtocols) > 0 { - // RFC 7301, Section 3.1 - exts.AddUint16(extensionALPN) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - for _, proto := range m.alpnProtocols { - exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes([]byte(proto)) - }) - } - }) - }) - } - if m.scts { - // RFC 6962, Section 3.3.1 - exts.AddUint16(extensionSCT) - exts.AddUint16(0) // empty extension_data - } - if len(m.supportedVersions) > 0 { - // RFC 8446, Section 4.2.1 - exts.AddUint16(extensionSupportedVersions) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) { - for _, vers := range m.supportedVersions { - exts.AddUint16(vers) - } - }) - }) - } - if len(m.cookie) > 0 { - // RFC 8446, Section 4.2.2 - exts.AddUint16(extensionCookie) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(m.cookie) - }) - }) - } - if len(m.keyShares) > 0 { - // RFC 8446, Section 4.2.8 - exts.AddUint16(extensionKeyShare) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - for _, ks := range m.keyShares { - exts.AddUint16(uint16(ks.group)) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(ks.data) - }) - } - }) - }) - } - if m.earlyData { - // RFC 8446, Section 4.2.10 - exts.AddUint16(extensionEarlyData) - exts.AddUint16(0) // empty extension_data - } - if len(m.pskModes) > 0 { - // RFC 8446, Section 4.2.9 - exts.AddUint16(extensionPSKModes) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(m.pskModes) - }) - }) - } - if m.quicTransportParameters != nil { // marshal zero-length parameters when present - // RFC 9001, Section 8.2 - exts.AddUint16(extensionQUICTransportParameters) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(m.quicTransportParameters) - }) - } - if len(m.pskIdentities) > 0 { // pre_shared_key must be the last extension - // RFC 8446, Section 4.2.11 - exts.AddUint16(extensionPreSharedKey) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - for _, psk := range m.pskIdentities { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(psk.label) - }) - exts.AddUint32(psk.obfuscatedTicketAge) - } - }) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - for _, binder := range m.pskBinders { - exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(binder) - }) - } - }) - }) - } - extBytes, err := exts.Bytes() - if err != nil { - return nil, err - } - - var b cryptobyte.Builder - b.AddUint8(typeClientHello) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint16(m.vers) - addBytesWithLength(b, m.random, 32) - b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.sessionId) - }) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - for _, suite := range m.cipherSuites { - b.AddUint16(suite) - } - }) - b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.compressionMethods) - }) - - if len(extBytes) > 0 { - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(extBytes) - }) - } - }) - - m.raw, err = b.Bytes() - return m.raw, err -} - -// marshalWithoutBinders returns the ClientHello through the -// PreSharedKeyExtension.identities field, according to RFC 8446, Section -// 4.2.11.2. Note that m.pskBinders must be set to slices of the correct length. -func (m *clientHelloMsg) marshalWithoutBinders() ([]byte, error) { - bindersLen := 2 // uint16 length prefix - for _, binder := range m.pskBinders { - bindersLen += 1 // uint8 length prefix - bindersLen += len(binder) - } - - fullMessage, err := m.marshal() - if err != nil { - return nil, err - } - return fullMessage[:len(fullMessage)-bindersLen], nil -} - -// updateBinders updates the m.pskBinders field, if necessary updating the -// cached marshaled representation. The supplied binders must have the same -// length as the current m.pskBinders. -func (m *clientHelloMsg) updateBinders(pskBinders [][]byte) error { - if len(pskBinders) != len(m.pskBinders) { - return errors.New("tls: internal error: pskBinders length mismatch") - } - for i := range m.pskBinders { - if len(pskBinders[i]) != len(m.pskBinders[i]) { - return errors.New("tls: internal error: pskBinders length mismatch") - } - } - m.pskBinders = pskBinders - if m.raw != nil { - helloBytes, err := m.marshalWithoutBinders() - if err != nil { - return err - } - lenWithoutBinders := len(helloBytes) - b := cryptobyte.NewFixedBuilder(m.raw[:lenWithoutBinders]) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - for _, binder := range m.pskBinders { - b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(binder) - }) - } - }) - if out, err := b.Bytes(); err != nil || len(out) != len(m.raw) { - return errors.New("tls: internal error: failed to update binders") - } - } - - return nil -} - -func (m *clientHelloMsg) unmarshal(data []byte) bool { - *m = clientHelloMsg{raw: data} - s := cryptobyte.String(data) - - if !s.Skip(4) || // message type and uint24 length field - !s.ReadUint16(&m.vers) || !s.ReadBytes(&m.random, 32) || - !readUint8LengthPrefixed(&s, &m.sessionId) { - return false - } - - var cipherSuites cryptobyte.String - if !s.ReadUint16LengthPrefixed(&cipherSuites) { - return false - } - m.cipherSuites = []uint16{} - m.secureRenegotiationSupported = false - for !cipherSuites.Empty() { - var suite uint16 - if !cipherSuites.ReadUint16(&suite) { - return false - } - if suite == scsvRenegotiation { - m.secureRenegotiationSupported = true - } - m.cipherSuites = append(m.cipherSuites, suite) - } - - if !readUint8LengthPrefixed(&s, &m.compressionMethods) { - return false - } - - if s.Empty() { - // ClientHello is optionally followed by extension data - return true - } - - var extensions cryptobyte.String - if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { - return false - } - - seenExts := make(map[uint16]bool) - for !extensions.Empty() { - var extension uint16 - var extData cryptobyte.String - if !extensions.ReadUint16(&extension) || - !extensions.ReadUint16LengthPrefixed(&extData) { - return false - } - - if seenExts[extension] { - return false - } - seenExts[extension] = true - - switch extension { - case extensionServerName: - // RFC 6066, Section 3 - var nameList cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&nameList) || nameList.Empty() { - return false - } - for !nameList.Empty() { - var nameType uint8 - var serverName cryptobyte.String - if !nameList.ReadUint8(&nameType) || - !nameList.ReadUint16LengthPrefixed(&serverName) || - serverName.Empty() { - return false - } - if nameType != 0 { - continue - } - if len(m.serverName) != 0 { - // Multiple names of the same name_type are prohibited. - return false - } - m.serverName = string(serverName) - // An SNI value may not include a trailing dot. - if strings.HasSuffix(m.serverName, ".") { - return false - } - } - case extensionStatusRequest: - // RFC 4366, Section 3.6 - var statusType uint8 - var ignored cryptobyte.String - if !extData.ReadUint8(&statusType) || - !extData.ReadUint16LengthPrefixed(&ignored) || - !extData.ReadUint16LengthPrefixed(&ignored) { - return false - } - m.ocspStapling = statusType == statusTypeOCSP - case extensionSupportedCurves: - // RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7 - var curves cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&curves) || curves.Empty() { - return false - } - for !curves.Empty() { - var curve uint16 - if !curves.ReadUint16(&curve) { - return false - } - m.supportedCurves = append(m.supportedCurves, CurveID(curve)) - } - case extensionSupportedPoints: - // RFC 4492, Section 5.1.2 - if !readUint8LengthPrefixed(&extData, &m.supportedPoints) || - len(m.supportedPoints) == 0 { - return false - } - case extensionSessionTicket: - // RFC 5077, Section 3.2 - m.ticketSupported = true - extData.ReadBytes(&m.sessionTicket, len(extData)) - case extensionSignatureAlgorithms: - // RFC 5246, Section 7.4.1.4.1 - var sigAndAlgs cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { - return false - } - for !sigAndAlgs.Empty() { - var sigAndAlg uint16 - if !sigAndAlgs.ReadUint16(&sigAndAlg) { - return false - } - m.supportedSignatureAlgorithms = append( - m.supportedSignatureAlgorithms, SignatureScheme(sigAndAlg)) - } - case extensionSignatureAlgorithmsCert: - // RFC 8446, Section 4.2.3 - var sigAndAlgs cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { - return false - } - for !sigAndAlgs.Empty() { - var sigAndAlg uint16 - if !sigAndAlgs.ReadUint16(&sigAndAlg) { - return false - } - m.supportedSignatureAlgorithmsCert = append( - m.supportedSignatureAlgorithmsCert, SignatureScheme(sigAndAlg)) - } - case extensionRenegotiationInfo: - // RFC 5746, Section 3.2 - if !readUint8LengthPrefixed(&extData, &m.secureRenegotiation) { - return false - } - m.secureRenegotiationSupported = true - case extensionALPN: - // RFC 7301, Section 3.1 - var protoList cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() { - return false - } - for !protoList.Empty() { - var proto cryptobyte.String - if !protoList.ReadUint8LengthPrefixed(&proto) || proto.Empty() { - return false - } - m.alpnProtocols = append(m.alpnProtocols, string(proto)) - } - case extensionSCT: - // RFC 6962, Section 3.3.1 - m.scts = true - case extensionSupportedVersions: - // RFC 8446, Section 4.2.1 - var versList cryptobyte.String - if !extData.ReadUint8LengthPrefixed(&versList) || versList.Empty() { - return false - } - for !versList.Empty() { - var vers uint16 - if !versList.ReadUint16(&vers) { - return false - } - m.supportedVersions = append(m.supportedVersions, vers) - } - case extensionCookie: - // RFC 8446, Section 4.2.2 - if !readUint16LengthPrefixed(&extData, &m.cookie) || - len(m.cookie) == 0 { - return false - } - case extensionKeyShare: - // RFC 8446, Section 4.2.8 - var clientShares cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&clientShares) { - return false - } - for !clientShares.Empty() { - var ks keyShare - if !clientShares.ReadUint16((*uint16)(&ks.group)) || - !readUint16LengthPrefixed(&clientShares, &ks.data) || - len(ks.data) == 0 { - return false - } - m.keyShares = append(m.keyShares, ks) - } - case extensionEarlyData: - // RFC 8446, Section 4.2.10 - m.earlyData = true - case extensionPSKModes: - // RFC 8446, Section 4.2.9 - if !readUint8LengthPrefixed(&extData, &m.pskModes) { - return false - } - case extensionQUICTransportParameters: - m.quicTransportParameters = make([]byte, len(extData)) - if !extData.CopyBytes(m.quicTransportParameters) { - return false - } - case extensionPreSharedKey: - // RFC 8446, Section 4.2.11 - if !extensions.Empty() { - return false // pre_shared_key must be the last extension - } - var identities cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&identities) || identities.Empty() { - return false - } - for !identities.Empty() { - var psk pskIdentity - if !readUint16LengthPrefixed(&identities, &psk.label) || - !identities.ReadUint32(&psk.obfuscatedTicketAge) || - len(psk.label) == 0 { - return false - } - m.pskIdentities = append(m.pskIdentities, psk) - } - var binders cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&binders) || binders.Empty() { - return false - } - for !binders.Empty() { - var binder []byte - if !readUint8LengthPrefixed(&binders, &binder) || - len(binder) == 0 { - return false - } - m.pskBinders = append(m.pskBinders, binder) - } - default: - // Ignore unknown extensions. - continue - } - - if !extData.Empty() { - return false - } - } - - return true -} - -type serverHelloMsg struct { - raw []byte - vers uint16 - random []byte - sessionId []byte - cipherSuite uint16 - compressionMethod uint8 - ocspStapling bool - ticketSupported bool - secureRenegotiationSupported bool - secureRenegotiation []byte - alpnProtocol string - scts [][]byte - supportedVersion uint16 - serverShare keyShare - selectedIdentityPresent bool - selectedIdentity uint16 - supportedPoints []uint8 - - // HelloRetryRequest extensions - cookie []byte - selectedGroup CurveID -} - -func (m *serverHelloMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var exts cryptobyte.Builder - if m.ocspStapling { - exts.AddUint16(extensionStatusRequest) - exts.AddUint16(0) // empty extension_data - } - if m.ticketSupported { - exts.AddUint16(extensionSessionTicket) - exts.AddUint16(0) // empty extension_data - } - if m.secureRenegotiationSupported { - exts.AddUint16(extensionRenegotiationInfo) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(m.secureRenegotiation) - }) - }) - } - if len(m.alpnProtocol) > 0 { - exts.AddUint16(extensionALPN) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes([]byte(m.alpnProtocol)) - }) - }) - }) - } - if len(m.scts) > 0 { - exts.AddUint16(extensionSCT) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - for _, sct := range m.scts { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(sct) - }) - } - }) - }) - } - if m.supportedVersion != 0 { - exts.AddUint16(extensionSupportedVersions) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16(m.supportedVersion) - }) - } - if m.serverShare.group != 0 { - exts.AddUint16(extensionKeyShare) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16(uint16(m.serverShare.group)) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(m.serverShare.data) - }) - }) - } - if m.selectedIdentityPresent { - exts.AddUint16(extensionPreSharedKey) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16(m.selectedIdentity) - }) - } - - if len(m.cookie) > 0 { - exts.AddUint16(extensionCookie) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(m.cookie) - }) - }) - } - if m.selectedGroup != 0 { - exts.AddUint16(extensionKeyShare) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint16(uint16(m.selectedGroup)) - }) - } - if len(m.supportedPoints) > 0 { - exts.AddUint16(extensionSupportedPoints) - exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) { - exts.AddBytes(m.supportedPoints) - }) - }) - } - - extBytes, err := exts.Bytes() - if err != nil { - return nil, err - } - - var b cryptobyte.Builder - b.AddUint8(typeServerHello) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint16(m.vers) - addBytesWithLength(b, m.random, 32) - b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.sessionId) - }) - b.AddUint16(m.cipherSuite) - b.AddUint8(m.compressionMethod) - - if len(extBytes) > 0 { - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(extBytes) - }) - } - }) - - m.raw, err = b.Bytes() - return m.raw, err -} - -func (m *serverHelloMsg) unmarshal(data []byte) bool { - *m = serverHelloMsg{raw: data} - s := cryptobyte.String(data) - - if !s.Skip(4) || // message type and uint24 length field - !s.ReadUint16(&m.vers) || !s.ReadBytes(&m.random, 32) || - !readUint8LengthPrefixed(&s, &m.sessionId) || - !s.ReadUint16(&m.cipherSuite) || - !s.ReadUint8(&m.compressionMethod) { - return false - } - - if s.Empty() { - // ServerHello is optionally followed by extension data - return true - } - - var extensions cryptobyte.String - if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { - return false - } - - seenExts := make(map[uint16]bool) - for !extensions.Empty() { - var extension uint16 - var extData cryptobyte.String - if !extensions.ReadUint16(&extension) || - !extensions.ReadUint16LengthPrefixed(&extData) { - return false - } - - if seenExts[extension] { - return false - } - seenExts[extension] = true - - switch extension { - case extensionStatusRequest: - m.ocspStapling = true - case extensionSessionTicket: - m.ticketSupported = true - case extensionRenegotiationInfo: - if !readUint8LengthPrefixed(&extData, &m.secureRenegotiation) { - return false - } - m.secureRenegotiationSupported = true - case extensionALPN: - var protoList cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() { - return false - } - var proto cryptobyte.String - if !protoList.ReadUint8LengthPrefixed(&proto) || - proto.Empty() || !protoList.Empty() { - return false - } - m.alpnProtocol = string(proto) - case extensionSCT: - var sctList cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&sctList) || sctList.Empty() { - return false - } - for !sctList.Empty() { - var sct []byte - if !readUint16LengthPrefixed(&sctList, &sct) || - len(sct) == 0 { - return false - } - m.scts = append(m.scts, sct) - } - case extensionSupportedVersions: - if !extData.ReadUint16(&m.supportedVersion) { - return false - } - case extensionCookie: - if !readUint16LengthPrefixed(&extData, &m.cookie) || - len(m.cookie) == 0 { - return false - } - case extensionKeyShare: - // This extension has different formats in SH and HRR, accept either - // and let the handshake logic decide. See RFC 8446, Section 4.2.8. - if len(extData) == 2 { - if !extData.ReadUint16((*uint16)(&m.selectedGroup)) { - return false - } - } else { - if !extData.ReadUint16((*uint16)(&m.serverShare.group)) || - !readUint16LengthPrefixed(&extData, &m.serverShare.data) { - return false - } - } - case extensionPreSharedKey: - m.selectedIdentityPresent = true - if !extData.ReadUint16(&m.selectedIdentity) { - return false - } - case extensionSupportedPoints: - // RFC 4492, Section 5.1.2 - if !readUint8LengthPrefixed(&extData, &m.supportedPoints) || - len(m.supportedPoints) == 0 { - return false - } - default: - // Ignore unknown extensions. - continue - } - - if !extData.Empty() { - return false - } - } - - return true -} - -type encryptedExtensionsMsg struct { - raw []byte - alpnProtocol string - quicTransportParameters []byte - earlyData bool -} - -func (m *encryptedExtensionsMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var b cryptobyte.Builder - b.AddUint8(typeEncryptedExtensions) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - if len(m.alpnProtocol) > 0 { - b.AddUint16(extensionALPN) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes([]byte(m.alpnProtocol)) - }) - }) - }) - } - if m.quicTransportParameters != nil { // marshal zero-length parameters when present - // draft-ietf-quic-tls-32, Section 8.2 - b.AddUint16(extensionQUICTransportParameters) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.quicTransportParameters) - }) - } - if m.earlyData { - // RFC 8446, Section 4.2.10 - b.AddUint16(extensionEarlyData) - b.AddUint16(0) // empty extension_data - } - }) - }) - - var err error - m.raw, err = b.Bytes() - return m.raw, err -} - -func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool { - *m = encryptedExtensionsMsg{raw: data} - s := cryptobyte.String(data) - - var extensions cryptobyte.String - if !s.Skip(4) || // message type and uint24 length field - !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { - return false - } - - for !extensions.Empty() { - var extension uint16 - var extData cryptobyte.String - if !extensions.ReadUint16(&extension) || - !extensions.ReadUint16LengthPrefixed(&extData) { - return false - } - - switch extension { - case extensionALPN: - var protoList cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() { - return false - } - var proto cryptobyte.String - if !protoList.ReadUint8LengthPrefixed(&proto) || - proto.Empty() || !protoList.Empty() { - return false - } - m.alpnProtocol = string(proto) - case extensionQUICTransportParameters: - m.quicTransportParameters = make([]byte, len(extData)) - if !extData.CopyBytes(m.quicTransportParameters) { - return false - } - case extensionEarlyData: - m.earlyData = true - default: - // Ignore unknown extensions. - continue - } - - if !extData.Empty() { - return false - } - } - - return true -} - -type endOfEarlyDataMsg struct{} - -func (m *endOfEarlyDataMsg) marshal() ([]byte, error) { - x := make([]byte, 4) - x[0] = typeEndOfEarlyData - return x, nil -} - -func (m *endOfEarlyDataMsg) unmarshal(data []byte) bool { - return len(data) == 4 -} - -type keyUpdateMsg struct { - raw []byte - updateRequested bool -} - -func (m *keyUpdateMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var b cryptobyte.Builder - b.AddUint8(typeKeyUpdate) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - if m.updateRequested { - b.AddUint8(1) - } else { - b.AddUint8(0) - } - }) - - var err error - m.raw, err = b.Bytes() - return m.raw, err -} - -func (m *keyUpdateMsg) unmarshal(data []byte) bool { - m.raw = data - s := cryptobyte.String(data) - - var updateRequested uint8 - if !s.Skip(4) || // message type and uint24 length field - !s.ReadUint8(&updateRequested) || !s.Empty() { - return false - } - switch updateRequested { - case 0: - m.updateRequested = false - case 1: - m.updateRequested = true - default: - return false - } - return true -} - -type newSessionTicketMsgTLS13 struct { - raw []byte - lifetime uint32 - ageAdd uint32 - nonce []byte - label []byte - maxEarlyData uint32 -} - -func (m *newSessionTicketMsgTLS13) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var b cryptobyte.Builder - b.AddUint8(typeNewSessionTicket) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint32(m.lifetime) - b.AddUint32(m.ageAdd) - b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.nonce) - }) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.label) - }) - - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - if m.maxEarlyData > 0 { - b.AddUint16(extensionEarlyData) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint32(m.maxEarlyData) - }) - } - }) - }) - - var err error - m.raw, err = b.Bytes() - return m.raw, err -} - -func (m *newSessionTicketMsgTLS13) unmarshal(data []byte) bool { - *m = newSessionTicketMsgTLS13{raw: data} - s := cryptobyte.String(data) - - var extensions cryptobyte.String - if !s.Skip(4) || // message type and uint24 length field - !s.ReadUint32(&m.lifetime) || - !s.ReadUint32(&m.ageAdd) || - !readUint8LengthPrefixed(&s, &m.nonce) || - !readUint16LengthPrefixed(&s, &m.label) || - !s.ReadUint16LengthPrefixed(&extensions) || - !s.Empty() { - return false - } - - for !extensions.Empty() { - var extension uint16 - var extData cryptobyte.String - if !extensions.ReadUint16(&extension) || - !extensions.ReadUint16LengthPrefixed(&extData) { - return false - } - - switch extension { - case extensionEarlyData: - if !extData.ReadUint32(&m.maxEarlyData) { - return false - } - default: - // Ignore unknown extensions. - continue - } - - if !extData.Empty() { - return false - } - } - - return true -} - -type certificateRequestMsgTLS13 struct { - raw []byte - ocspStapling bool - scts bool - supportedSignatureAlgorithms []SignatureScheme - supportedSignatureAlgorithmsCert []SignatureScheme - certificateAuthorities [][]byte -} - -func (m *certificateRequestMsgTLS13) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var b cryptobyte.Builder - b.AddUint8(typeCertificateRequest) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - // certificate_request_context (SHALL be zero length unless used for - // post-handshake authentication) - b.AddUint8(0) - - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - if m.ocspStapling { - b.AddUint16(extensionStatusRequest) - b.AddUint16(0) // empty extension_data - } - if m.scts { - // RFC 8446, Section 4.4.2.1 makes no mention of - // signed_certificate_timestamp in CertificateRequest, but - // "Extensions in the Certificate message from the client MUST - // correspond to extensions in the CertificateRequest message - // from the server." and it appears in the table in Section 4.2. - b.AddUint16(extensionSCT) - b.AddUint16(0) // empty extension_data - } - if len(m.supportedSignatureAlgorithms) > 0 { - b.AddUint16(extensionSignatureAlgorithms) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - for _, sigAlgo := range m.supportedSignatureAlgorithms { - b.AddUint16(uint16(sigAlgo)) - } - }) - }) - } - if len(m.supportedSignatureAlgorithmsCert) > 0 { - b.AddUint16(extensionSignatureAlgorithmsCert) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - for _, sigAlgo := range m.supportedSignatureAlgorithmsCert { - b.AddUint16(uint16(sigAlgo)) - } - }) - }) - } - if len(m.certificateAuthorities) > 0 { - b.AddUint16(extensionCertificateAuthorities) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - for _, ca := range m.certificateAuthorities { - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(ca) - }) - } - }) - }) - } - }) - }) - - var err error - m.raw, err = b.Bytes() - return m.raw, err -} - -func (m *certificateRequestMsgTLS13) unmarshal(data []byte) bool { - *m = certificateRequestMsgTLS13{raw: data} - s := cryptobyte.String(data) - - var context, extensions cryptobyte.String - if !s.Skip(4) || // message type and uint24 length field - !s.ReadUint8LengthPrefixed(&context) || !context.Empty() || - !s.ReadUint16LengthPrefixed(&extensions) || - !s.Empty() { - return false - } - - for !extensions.Empty() { - var extension uint16 - var extData cryptobyte.String - if !extensions.ReadUint16(&extension) || - !extensions.ReadUint16LengthPrefixed(&extData) { - return false - } - - switch extension { - case extensionStatusRequest: - m.ocspStapling = true - case extensionSCT: - m.scts = true - case extensionSignatureAlgorithms: - var sigAndAlgs cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { - return false - } - for !sigAndAlgs.Empty() { - var sigAndAlg uint16 - if !sigAndAlgs.ReadUint16(&sigAndAlg) { - return false - } - m.supportedSignatureAlgorithms = append( - m.supportedSignatureAlgorithms, SignatureScheme(sigAndAlg)) - } - case extensionSignatureAlgorithmsCert: - var sigAndAlgs cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { - return false - } - for !sigAndAlgs.Empty() { - var sigAndAlg uint16 - if !sigAndAlgs.ReadUint16(&sigAndAlg) { - return false - } - m.supportedSignatureAlgorithmsCert = append( - m.supportedSignatureAlgorithmsCert, SignatureScheme(sigAndAlg)) - } - case extensionCertificateAuthorities: - var auths cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&auths) || auths.Empty() { - return false - } - for !auths.Empty() { - var ca []byte - if !readUint16LengthPrefixed(&auths, &ca) || len(ca) == 0 { - return false - } - m.certificateAuthorities = append(m.certificateAuthorities, ca) - } - default: - // Ignore unknown extensions. - continue - } - - if !extData.Empty() { - return false - } - } - - return true -} - -type certificateMsg struct { - raw []byte - certificates [][]byte -} - -func (m *certificateMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var i int - for _, slice := range m.certificates { - i += len(slice) - } - - length := 3 + 3*len(m.certificates) + i - x := make([]byte, 4+length) - x[0] = typeCertificate - x[1] = uint8(length >> 16) - x[2] = uint8(length >> 8) - x[3] = uint8(length) - - certificateOctets := length - 3 - x[4] = uint8(certificateOctets >> 16) - x[5] = uint8(certificateOctets >> 8) - x[6] = uint8(certificateOctets) - - y := x[7:] - for _, slice := range m.certificates { - y[0] = uint8(len(slice) >> 16) - y[1] = uint8(len(slice) >> 8) - y[2] = uint8(len(slice)) - copy(y[3:], slice) - y = y[3+len(slice):] - } - - m.raw = x - return m.raw, nil -} - -func (m *certificateMsg) unmarshal(data []byte) bool { - if len(data) < 7 { - return false - } - - m.raw = data - certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6]) - if uint32(len(data)) != certsLen+7 { - return false - } - - numCerts := 0 - d := data[7:] - for certsLen > 0 { - if len(d) < 4 { - return false - } - certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2]) - if uint32(len(d)) < 3+certLen { - return false - } - d = d[3+certLen:] - certsLen -= 3 + certLen - numCerts++ - } - - m.certificates = make([][]byte, numCerts) - d = data[7:] - for i := 0; i < numCerts; i++ { - certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2]) - m.certificates[i] = d[3 : 3+certLen] - d = d[3+certLen:] - } - - return true -} - -type certificateMsgTLS13 struct { - raw []byte - certificate Certificate - ocspStapling bool - scts bool -} - -func (m *certificateMsgTLS13) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var b cryptobyte.Builder - b.AddUint8(typeCertificate) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint8(0) // certificate_request_context - - certificate := m.certificate - if !m.ocspStapling { - certificate.OCSPStaple = nil - } - if !m.scts { - certificate.SignedCertificateTimestamps = nil - } - marshalCertificate(b, certificate) - }) - - var err error - m.raw, err = b.Bytes() - return m.raw, err -} - -func marshalCertificate(b *cryptobyte.Builder, certificate Certificate) { - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - for i, cert := range certificate.Certificate { - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(cert) - }) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - if i > 0 { - // This library only supports OCSP and SCT for leaf certificates. - return - } - if certificate.OCSPStaple != nil { - b.AddUint16(extensionStatusRequest) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint8(statusTypeOCSP) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(certificate.OCSPStaple) - }) - }) - } - if certificate.SignedCertificateTimestamps != nil { - b.AddUint16(extensionSCT) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - for _, sct := range certificate.SignedCertificateTimestamps { - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(sct) - }) - } - }) - }) - } - }) - } - }) -} - -func (m *certificateMsgTLS13) unmarshal(data []byte) bool { - *m = certificateMsgTLS13{raw: data} - s := cryptobyte.String(data) - - var context cryptobyte.String - if !s.Skip(4) || // message type and uint24 length field - !s.ReadUint8LengthPrefixed(&context) || !context.Empty() || - !unmarshalCertificate(&s, &m.certificate) || - !s.Empty() { - return false - } - - m.scts = m.certificate.SignedCertificateTimestamps != nil - m.ocspStapling = m.certificate.OCSPStaple != nil - - return true -} - -func unmarshalCertificate(s *cryptobyte.String, certificate *Certificate) bool { - var certList cryptobyte.String - if !s.ReadUint24LengthPrefixed(&certList) { - return false - } - for !certList.Empty() { - var cert []byte - var extensions cryptobyte.String - if !readUint24LengthPrefixed(&certList, &cert) || - !certList.ReadUint16LengthPrefixed(&extensions) { - return false - } - certificate.Certificate = append(certificate.Certificate, cert) - for !extensions.Empty() { - var extension uint16 - var extData cryptobyte.String - if !extensions.ReadUint16(&extension) || - !extensions.ReadUint16LengthPrefixed(&extData) { - return false - } - if len(certificate.Certificate) > 1 { - // This library only supports OCSP and SCT for leaf certificates. - continue - } - - switch extension { - case extensionStatusRequest: - var statusType uint8 - if !extData.ReadUint8(&statusType) || statusType != statusTypeOCSP || - !readUint24LengthPrefixed(&extData, &certificate.OCSPStaple) || - len(certificate.OCSPStaple) == 0 { - return false - } - case extensionSCT: - var sctList cryptobyte.String - if !extData.ReadUint16LengthPrefixed(&sctList) || sctList.Empty() { - return false - } - for !sctList.Empty() { - var sct []byte - if !readUint16LengthPrefixed(&sctList, &sct) || - len(sct) == 0 { - return false - } - certificate.SignedCertificateTimestamps = append( - certificate.SignedCertificateTimestamps, sct) - } - default: - // Ignore unknown extensions. - continue - } - - if !extData.Empty() { - return false - } - } - } - return true -} - -type serverKeyExchangeMsg struct { - raw []byte - key []byte -} - -func (m *serverKeyExchangeMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - length := len(m.key) - x := make([]byte, length+4) - x[0] = typeServerKeyExchange - x[1] = uint8(length >> 16) - x[2] = uint8(length >> 8) - x[3] = uint8(length) - copy(x[4:], m.key) - - m.raw = x - return x, nil -} - -func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool { - m.raw = data - if len(data) < 4 { - return false - } - m.key = data[4:] - return true -} - -type certificateStatusMsg struct { - raw []byte - response []byte -} - -func (m *certificateStatusMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var b cryptobyte.Builder - b.AddUint8(typeCertificateStatus) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddUint8(statusTypeOCSP) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.response) - }) - }) - - var err error - m.raw, err = b.Bytes() - return m.raw, err -} - -func (m *certificateStatusMsg) unmarshal(data []byte) bool { - m.raw = data - s := cryptobyte.String(data) - - var statusType uint8 - if !s.Skip(4) || // message type and uint24 length field - !s.ReadUint8(&statusType) || statusType != statusTypeOCSP || - !readUint24LengthPrefixed(&s, &m.response) || - len(m.response) == 0 || !s.Empty() { - return false - } - return true -} - -type serverHelloDoneMsg struct{} - -func (m *serverHelloDoneMsg) marshal() ([]byte, error) { - x := make([]byte, 4) - x[0] = typeServerHelloDone - return x, nil -} - -func (m *serverHelloDoneMsg) unmarshal(data []byte) bool { - return len(data) == 4 -} - -type clientKeyExchangeMsg struct { - raw []byte - ciphertext []byte -} - -func (m *clientKeyExchangeMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - length := len(m.ciphertext) - x := make([]byte, length+4) - x[0] = typeClientKeyExchange - x[1] = uint8(length >> 16) - x[2] = uint8(length >> 8) - x[3] = uint8(length) - copy(x[4:], m.ciphertext) - - m.raw = x - return x, nil -} - -func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool { - m.raw = data - if len(data) < 4 { - return false - } - l := int(data[1])<<16 | int(data[2])<<8 | int(data[3]) - if l != len(data)-4 { - return false - } - m.ciphertext = data[4:] - return true -} - -type finishedMsg struct { - raw []byte - verifyData []byte -} - -func (m *finishedMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var b cryptobyte.Builder - b.AddUint8(typeFinished) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.verifyData) - }) - - var err error - m.raw, err = b.Bytes() - return m.raw, err -} - -func (m *finishedMsg) unmarshal(data []byte) bool { - m.raw = data - s := cryptobyte.String(data) - return s.Skip(1) && - readUint24LengthPrefixed(&s, &m.verifyData) && - s.Empty() -} - -type certificateRequestMsg struct { - raw []byte - // hasSignatureAlgorithm indicates whether this message includes a list of - // supported signature algorithms. This change was introduced with TLS 1.2. - hasSignatureAlgorithm bool - - certificateTypes []byte - supportedSignatureAlgorithms []SignatureScheme - certificateAuthorities [][]byte -} - -func (m *certificateRequestMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - // See RFC 4346, Section 7.4.4. - length := 1 + len(m.certificateTypes) + 2 - casLength := 0 - for _, ca := range m.certificateAuthorities { - casLength += 2 + len(ca) - } - length += casLength - - if m.hasSignatureAlgorithm { - length += 2 + 2*len(m.supportedSignatureAlgorithms) - } - - x := make([]byte, 4+length) - x[0] = typeCertificateRequest - x[1] = uint8(length >> 16) - x[2] = uint8(length >> 8) - x[3] = uint8(length) - - x[4] = uint8(len(m.certificateTypes)) - - copy(x[5:], m.certificateTypes) - y := x[5+len(m.certificateTypes):] - - if m.hasSignatureAlgorithm { - n := len(m.supportedSignatureAlgorithms) * 2 - y[0] = uint8(n >> 8) - y[1] = uint8(n) - y = y[2:] - for _, sigAlgo := range m.supportedSignatureAlgorithms { - y[0] = uint8(sigAlgo >> 8) - y[1] = uint8(sigAlgo) - y = y[2:] - } - } - - y[0] = uint8(casLength >> 8) - y[1] = uint8(casLength) - y = y[2:] - for _, ca := range m.certificateAuthorities { - y[0] = uint8(len(ca) >> 8) - y[1] = uint8(len(ca)) - y = y[2:] - copy(y, ca) - y = y[len(ca):] - } - - m.raw = x - return m.raw, nil -} - -func (m *certificateRequestMsg) unmarshal(data []byte) bool { - m.raw = data - - if len(data) < 5 { - return false - } - - length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3]) - if uint32(len(data))-4 != length { - return false - } - - numCertTypes := int(data[4]) - data = data[5:] - if numCertTypes == 0 || len(data) <= numCertTypes { - return false - } - - m.certificateTypes = make([]byte, numCertTypes) - if copy(m.certificateTypes, data) != numCertTypes { - return false - } - - data = data[numCertTypes:] - - if m.hasSignatureAlgorithm { - if len(data) < 2 { - return false - } - sigAndHashLen := uint16(data[0])<<8 | uint16(data[1]) - data = data[2:] - if sigAndHashLen&1 != 0 { - return false - } - if len(data) < int(sigAndHashLen) { - return false - } - numSigAlgos := sigAndHashLen / 2 - m.supportedSignatureAlgorithms = make([]SignatureScheme, numSigAlgos) - for i := range m.supportedSignatureAlgorithms { - m.supportedSignatureAlgorithms[i] = SignatureScheme(data[0])<<8 | SignatureScheme(data[1]) - data = data[2:] - } - } - - if len(data) < 2 { - return false - } - casLength := uint16(data[0])<<8 | uint16(data[1]) - data = data[2:] - if len(data) < int(casLength) { - return false - } - cas := make([]byte, casLength) - copy(cas, data) - data = data[casLength:] - - m.certificateAuthorities = nil - for len(cas) > 0 { - if len(cas) < 2 { - return false - } - caLen := uint16(cas[0])<<8 | uint16(cas[1]) - cas = cas[2:] - - if len(cas) < int(caLen) { - return false - } - - m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen]) - cas = cas[caLen:] - } - - return len(data) == 0 -} - -type certificateVerifyMsg struct { - raw []byte - hasSignatureAlgorithm bool // format change introduced in TLS 1.2 - signatureAlgorithm SignatureScheme - signature []byte -} - -func (m *certificateVerifyMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - var b cryptobyte.Builder - b.AddUint8(typeCertificateVerify) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - if m.hasSignatureAlgorithm { - b.AddUint16(uint16(m.signatureAlgorithm)) - } - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.signature) - }) - }) - - var err error - m.raw, err = b.Bytes() - return m.raw, err -} - -func (m *certificateVerifyMsg) unmarshal(data []byte) bool { - m.raw = data - s := cryptobyte.String(data) - - if !s.Skip(4) { // message type and uint24 length field - return false - } - if m.hasSignatureAlgorithm { - if !s.ReadUint16((*uint16)(&m.signatureAlgorithm)) { - return false - } - } - return readUint16LengthPrefixed(&s, &m.signature) && s.Empty() -} - -type newSessionTicketMsg struct { - raw []byte - ticket []byte -} - -func (m *newSessionTicketMsg) marshal() ([]byte, error) { - if m.raw != nil { - return m.raw, nil - } - - // See RFC 5077, Section 3.3. - ticketLen := len(m.ticket) - length := 2 + 4 + ticketLen - x := make([]byte, 4+length) - x[0] = typeNewSessionTicket - x[1] = uint8(length >> 16) - x[2] = uint8(length >> 8) - x[3] = uint8(length) - x[8] = uint8(ticketLen >> 8) - x[9] = uint8(ticketLen) - copy(x[10:], m.ticket) - - m.raw = x - - return m.raw, nil -} - -func (m *newSessionTicketMsg) unmarshal(data []byte) bool { - m.raw = data - - if len(data) < 10 { - return false - } - - length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3]) - if uint32(len(data))-4 != length { - return false - } - - ticketLen := int(data[8])<<8 + int(data[9]) - if len(data)-10 != ticketLen { - return false - } - - m.ticket = data[10:] - - return true -} - -type helloRequestMsg struct { -} - -func (*helloRequestMsg) marshal() ([]byte, error) { - return []byte{typeHelloRequest, 0, 0, 0}, nil -} - -func (*helloRequestMsg) unmarshal(data []byte) bool { - return len(data) == 4 -} - -type transcriptHash interface { - Write([]byte) (int, error) -} - -// transcriptMsg is a helper used to marshal and hash messages which typically -// are not written to the wire, and as such aren't hashed during Conn.writeRecord. -func transcriptMsg(msg handshakeMessage, h transcriptHash) error { - data, err := msg.marshal() - if err != nil { - return err - } - h.Write(data) - return nil -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/handshake_server.go b/vendor/github.com/quic-go/qtls-go1-20/handshake_server.go deleted file mode 100644 index 7539c95d..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/handshake_server.go +++ /dev/null @@ -1,899 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "context" - "crypto" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/rsa" - "crypto/subtle" - "crypto/x509" - "errors" - "fmt" - "hash" - "io" - "time" -) - -// serverHandshakeState contains details of a server handshake in progress. -// It's discarded once the handshake has completed. -type serverHandshakeState struct { - c *Conn - ctx context.Context - clientHello *clientHelloMsg - hello *serverHelloMsg - suite *cipherSuite - ecdheOk bool - ecSignOk bool - rsaDecryptOk bool - rsaSignOk bool - sessionState *sessionState - finishedHash finishedHash - masterSecret []byte - cert *Certificate -} - -// serverHandshake performs a TLS handshake as a server. -func (c *Conn) serverHandshake(ctx context.Context) error { - clientHello, err := c.readClientHello(ctx) - if err != nil { - return err - } - - if c.vers == VersionTLS13 { - hs := serverHandshakeStateTLS13{ - c: c, - ctx: ctx, - clientHello: clientHello, - } - return hs.handshake() - } - - hs := serverHandshakeState{ - c: c, - ctx: ctx, - clientHello: clientHello, - } - return hs.handshake() -} - -func (hs *serverHandshakeState) handshake() error { - c := hs.c - - if err := hs.processClientHello(); err != nil { - return err - } - - // For an overview of TLS handshaking, see RFC 5246, Section 7.3. - c.buffering = true - if hs.checkForResumption() { - // The client has included a session ticket and so we do an abbreviated handshake. - c.didResume = true - if err := hs.doResumeHandshake(); err != nil { - return err - } - if err := hs.establishKeys(); err != nil { - return err - } - if err := hs.sendSessionTicket(); err != nil { - return err - } - if err := hs.sendFinished(c.serverFinished[:]); err != nil { - return err - } - if _, err := c.flush(); err != nil { - return err - } - c.clientFinishedIsFirst = false - if err := hs.readFinished(nil); err != nil { - return err - } - } else { - // The client didn't include a session ticket, or it wasn't - // valid so we do a full handshake. - if err := hs.pickCipherSuite(); err != nil { - return err - } - if err := hs.doFullHandshake(); err != nil { - return err - } - if err := hs.establishKeys(); err != nil { - return err - } - if err := hs.readFinished(c.clientFinished[:]); err != nil { - return err - } - c.clientFinishedIsFirst = true - c.buffering = true - if err := hs.sendSessionTicket(); err != nil { - return err - } - if err := hs.sendFinished(nil); err != nil { - return err - } - if _, err := c.flush(); err != nil { - return err - } - } - - c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random) - c.isHandshakeComplete.Store(true) - - return nil -} - -// readClientHello reads a ClientHello message and selects the protocol version. -func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { - // clientHelloMsg is included in the transcript, but we haven't initialized - // it yet. The respective handshake functions will record it themselves. - msg, err := c.readHandshake(nil) - if err != nil { - return nil, err - } - clientHello, ok := msg.(*clientHelloMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return nil, unexpectedMessageError(clientHello, msg) - } - - var configForClient *config - originalConfig := c.config - if c.config.GetConfigForClient != nil { - chi := newClientHelloInfo(ctx, c, clientHello) - if cfc, err := c.config.GetConfigForClient(chi); err != nil { - c.sendAlert(alertInternalError) - return nil, err - } else if cfc != nil { - configForClient = fromConfig(cfc) - c.config = configForClient - } - } - c.ticketKeys = originalConfig.ticketKeys(configForClient) - - clientVersions := clientHello.supportedVersions - if len(clientHello.supportedVersions) == 0 { - clientVersions = supportedVersionsFromMax(clientHello.vers) - } - c.vers, ok = c.config.mutualVersion(roleServer, clientVersions) - if !ok { - c.sendAlert(alertProtocolVersion) - return nil, fmt.Errorf("tls: client offered only unsupported versions: %x", clientVersions) - } - c.haveVers = true - c.in.version = c.vers - c.out.version = c.vers - - return clientHello, nil -} - -func (hs *serverHandshakeState) processClientHello() error { - c := hs.c - - hs.hello = new(serverHelloMsg) - hs.hello.vers = c.vers - - foundCompression := false - // We only support null compression, so check that the client offered it. - for _, compression := range hs.clientHello.compressionMethods { - if compression == compressionNone { - foundCompression = true - break - } - } - - if !foundCompression { - c.sendAlert(alertHandshakeFailure) - return errors.New("tls: client does not support uncompressed connections") - } - - hs.hello.random = make([]byte, 32) - serverRandom := hs.hello.random - // Downgrade protection canaries. See RFC 8446, Section 4.1.3. - maxVers := c.config.maxSupportedVersion(roleServer) - if maxVers >= VersionTLS12 && c.vers < maxVers || testingOnlyForceDowngradeCanary { - if c.vers == VersionTLS12 { - copy(serverRandom[24:], downgradeCanaryTLS12) - } else { - copy(serverRandom[24:], downgradeCanaryTLS11) - } - serverRandom = serverRandom[:24] - } - _, err := io.ReadFull(c.config.rand(), serverRandom) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - - if len(hs.clientHello.secureRenegotiation) != 0 { - c.sendAlert(alertHandshakeFailure) - return errors.New("tls: initial handshake had non-empty renegotiation extension") - } - - hs.hello.secureRenegotiationSupported = hs.clientHello.secureRenegotiationSupported - hs.hello.compressionMethod = compressionNone - if len(hs.clientHello.serverName) > 0 { - c.serverName = hs.clientHello.serverName - } - - selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols, false) - if err != nil { - c.sendAlert(alertNoApplicationProtocol) - return err - } - hs.hello.alpnProtocol = selectedProto - c.clientProtocol = selectedProto - - hs.cert, err = c.config.getCertificate(newClientHelloInfo(hs.ctx, c, hs.clientHello)) - if err != nil { - if err == errNoCertificates { - c.sendAlert(alertUnrecognizedName) - } else { - c.sendAlert(alertInternalError) - } - return err - } - if hs.clientHello.scts { - hs.hello.scts = hs.cert.SignedCertificateTimestamps - } - - hs.ecdheOk = supportsECDHE(c.config, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints) - - if hs.ecdheOk && len(hs.clientHello.supportedPoints) > 0 { - // Although omitting the ec_point_formats extension is permitted, some - // old OpenSSL version will refuse to handshake if not present. - // - // Per RFC 4492, section 5.1.2, implementations MUST support the - // uncompressed point format. See golang.org/issue/31943. - hs.hello.supportedPoints = []uint8{pointFormatUncompressed} - } - - if priv, ok := hs.cert.PrivateKey.(crypto.Signer); ok { - switch priv.Public().(type) { - case *ecdsa.PublicKey: - hs.ecSignOk = true - case ed25519.PublicKey: - hs.ecSignOk = true - case *rsa.PublicKey: - hs.rsaSignOk = true - default: - c.sendAlert(alertInternalError) - return fmt.Errorf("tls: unsupported signing key type (%T)", priv.Public()) - } - } - if priv, ok := hs.cert.PrivateKey.(crypto.Decrypter); ok { - switch priv.Public().(type) { - case *rsa.PublicKey: - hs.rsaDecryptOk = true - default: - c.sendAlert(alertInternalError) - return fmt.Errorf("tls: unsupported decryption key type (%T)", priv.Public()) - } - } - - return nil -} - -// negotiateALPN picks a shared ALPN protocol that both sides support in server -// preference order. If ALPN is not configured or the peer doesn't support it, -// it returns "" and no error. -func negotiateALPN(serverProtos, clientProtos []string, quic bool) (string, error) { - if len(serverProtos) == 0 || len(clientProtos) == 0 { - if quic && len(serverProtos) != 0 { - // RFC 9001, Section 8.1 - return "", fmt.Errorf("tls: client did not request an application protocol") - } - return "", nil - } - var http11fallback bool - for _, s := range serverProtos { - for _, c := range clientProtos { - if s == c { - return s, nil - } - if s == "h2" && c == "http/1.1" { - http11fallback = true - } - } - } - // As a special case, let http/1.1 clients connect to h2 servers as if they - // didn't support ALPN. We used not to enforce protocol overlap, so over - // time a number of HTTP servers were configured with only "h2", but - // expected to accept connections from "http/1.1" clients. See Issue 46310. - if http11fallback { - return "", nil - } - return "", fmt.Errorf("tls: client requested unsupported application protocols (%s)", clientProtos) -} - -// supportsECDHE returns whether ECDHE key exchanges can be used with this -// pre-TLS 1.3 client. -func supportsECDHE(c *config, supportedCurves []CurveID, supportedPoints []uint8) bool { - supportsCurve := false - for _, curve := range supportedCurves { - if c.supportsCurve(curve) { - supportsCurve = true - break - } - } - - supportsPointFormat := false - for _, pointFormat := range supportedPoints { - if pointFormat == pointFormatUncompressed { - supportsPointFormat = true - break - } - } - // Per RFC 8422, Section 5.1.2, if the Supported Point Formats extension is - // missing, uncompressed points are supported. If supportedPoints is empty, - // the extension must be missing, as an empty extension body is rejected by - // the parser. See https://go.dev/issue/49126. - if len(supportedPoints) == 0 { - supportsPointFormat = true - } - - return supportsCurve && supportsPointFormat -} - -func (hs *serverHandshakeState) pickCipherSuite() error { - c := hs.c - - preferenceOrder := cipherSuitesPreferenceOrder - if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) { - preferenceOrder = cipherSuitesPreferenceOrderNoAES - } - - configCipherSuites := c.config.cipherSuites() - preferenceList := make([]uint16, 0, len(configCipherSuites)) - for _, suiteID := range preferenceOrder { - for _, id := range configCipherSuites { - if id == suiteID { - preferenceList = append(preferenceList, id) - break - } - } - } - - hs.suite = selectCipherSuite(preferenceList, hs.clientHello.cipherSuites, hs.cipherSuiteOk) - if hs.suite == nil { - c.sendAlert(alertHandshakeFailure) - return errors.New("tls: no cipher suite supported by both client and server") - } - c.cipherSuite = hs.suite.id - - for _, id := range hs.clientHello.cipherSuites { - if id == TLS_FALLBACK_SCSV { - // The client is doing a fallback connection. See RFC 7507. - if hs.clientHello.vers < c.config.maxSupportedVersion(roleServer) { - c.sendAlert(alertInappropriateFallback) - return errors.New("tls: client using inappropriate protocol fallback") - } - break - } - } - - return nil -} - -func (hs *serverHandshakeState) cipherSuiteOk(c *cipherSuite) bool { - if c.flags&suiteECDHE != 0 { - if !hs.ecdheOk { - return false - } - if c.flags&suiteECSign != 0 { - if !hs.ecSignOk { - return false - } - } else if !hs.rsaSignOk { - return false - } - } else if !hs.rsaDecryptOk { - return false - } - if hs.c.vers < VersionTLS12 && c.flags&suiteTLS12 != 0 { - return false - } - return true -} - -// checkForResumption reports whether we should perform resumption on this connection. -func (hs *serverHandshakeState) checkForResumption() bool { - c := hs.c - - if c.config.SessionTicketsDisabled { - return false - } - - plaintext, usedOldKey := c.decryptTicket(hs.clientHello.sessionTicket) - if plaintext == nil { - return false - } - hs.sessionState = &sessionState{usedOldKey: usedOldKey} - ok := hs.sessionState.unmarshal(plaintext) - if !ok { - return false - } - - createdAt := time.Unix(int64(hs.sessionState.createdAt), 0) - if c.config.time().Sub(createdAt) > maxSessionTicketLifetime { - return false - } - - // Never resume a session for a different TLS version. - if c.vers != hs.sessionState.vers { - return false - } - - cipherSuiteOk := false - // Check that the client is still offering the ciphersuite in the session. - for _, id := range hs.clientHello.cipherSuites { - if id == hs.sessionState.cipherSuite { - cipherSuiteOk = true - break - } - } - if !cipherSuiteOk { - return false - } - - // Check that we also support the ciphersuite from the session. - hs.suite = selectCipherSuite([]uint16{hs.sessionState.cipherSuite}, - c.config.cipherSuites(), hs.cipherSuiteOk) - if hs.suite == nil { - return false - } - - sessionHasClientCerts := len(hs.sessionState.certificates) != 0 - needClientCerts := requiresClientCert(c.config.ClientAuth) - if needClientCerts && !sessionHasClientCerts { - return false - } - if sessionHasClientCerts && c.config.ClientAuth == NoClientCert { - return false - } - - return true -} - -func (hs *serverHandshakeState) doResumeHandshake() error { - c := hs.c - - hs.hello.cipherSuite = hs.suite.id - c.cipherSuite = hs.suite.id - // We echo the client's session ID in the ServerHello to let it know - // that we're doing a resumption. - hs.hello.sessionId = hs.clientHello.sessionId - hs.hello.ticketSupported = hs.sessionState.usedOldKey - hs.finishedHash = newFinishedHash(c.vers, hs.suite) - hs.finishedHash.discardHandshakeBuffer() - if err := transcriptMsg(hs.clientHello, &hs.finishedHash); err != nil { - return err - } - if _, err := hs.c.writeHandshakeRecord(hs.hello, &hs.finishedHash); err != nil { - return err - } - - if err := c.processCertsFromClient(Certificate{ - Certificate: hs.sessionState.certificates, - }); err != nil { - return err - } - - if c.config.VerifyConnection != nil { - if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { - c.sendAlert(alertBadCertificate) - return err - } - } - - hs.masterSecret = hs.sessionState.masterSecret - - return nil -} - -func (hs *serverHandshakeState) doFullHandshake() error { - c := hs.c - - if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 { - hs.hello.ocspStapling = true - } - - hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled - hs.hello.cipherSuite = hs.suite.id - - hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite) - if c.config.ClientAuth == NoClientCert { - // No need to keep a full record of the handshake if client - // certificates won't be used. - hs.finishedHash.discardHandshakeBuffer() - } - if err := transcriptMsg(hs.clientHello, &hs.finishedHash); err != nil { - return err - } - if _, err := hs.c.writeHandshakeRecord(hs.hello, &hs.finishedHash); err != nil { - return err - } - - certMsg := new(certificateMsg) - certMsg.certificates = hs.cert.Certificate - if _, err := hs.c.writeHandshakeRecord(certMsg, &hs.finishedHash); err != nil { - return err - } - - if hs.hello.ocspStapling { - certStatus := new(certificateStatusMsg) - certStatus.response = hs.cert.OCSPStaple - if _, err := hs.c.writeHandshakeRecord(certStatus, &hs.finishedHash); err != nil { - return err - } - } - - keyAgreement := hs.suite.ka(c.vers) - skx, err := keyAgreement.generateServerKeyExchange(c.config, hs.cert, hs.clientHello, hs.hello) - if err != nil { - c.sendAlert(alertHandshakeFailure) - return err - } - if skx != nil { - if _, err := hs.c.writeHandshakeRecord(skx, &hs.finishedHash); err != nil { - return err - } - } - - var certReq *certificateRequestMsg - if c.config.ClientAuth >= RequestClientCert { - // Request a client certificate - certReq = new(certificateRequestMsg) - certReq.certificateTypes = []byte{ - byte(certTypeRSASign), - byte(certTypeECDSASign), - } - if c.vers >= VersionTLS12 { - certReq.hasSignatureAlgorithm = true - certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() - } - - // An empty list of certificateAuthorities signals to - // the client that it may send any certificate in response - // to our request. When we know the CAs we trust, then - // we can send them down, so that the client can choose - // an appropriate certificate to give to us. - if c.config.ClientCAs != nil { - certReq.certificateAuthorities = c.config.ClientCAs.Subjects() - } - if _, err := hs.c.writeHandshakeRecord(certReq, &hs.finishedHash); err != nil { - return err - } - } - - helloDone := new(serverHelloDoneMsg) - if _, err := hs.c.writeHandshakeRecord(helloDone, &hs.finishedHash); err != nil { - return err - } - - if _, err := c.flush(); err != nil { - return err - } - - var pub crypto.PublicKey // public key for client auth, if any - - msg, err := c.readHandshake(&hs.finishedHash) - if err != nil { - return err - } - - // If we requested a client certificate, then the client must send a - // certificate message, even if it's empty. - if c.config.ClientAuth >= RequestClientCert { - certMsg, ok := msg.(*certificateMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(certMsg, msg) - } - - if err := c.processCertsFromClient(Certificate{ - Certificate: certMsg.certificates, - }); err != nil { - return err - } - if len(certMsg.certificates) != 0 { - pub = c.peerCertificates[0].PublicKey - } - - msg, err = c.readHandshake(&hs.finishedHash) - if err != nil { - return err - } - } - if c.config.VerifyConnection != nil { - if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { - c.sendAlert(alertBadCertificate) - return err - } - } - - // Get client key exchange - ckx, ok := msg.(*clientKeyExchangeMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(ckx, msg) - } - - preMasterSecret, err := keyAgreement.processClientKeyExchange(c.config, hs.cert, ckx, c.vers) - if err != nil { - c.sendAlert(alertHandshakeFailure) - return err - } - hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random) - if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.clientHello.random, hs.masterSecret); err != nil { - c.sendAlert(alertInternalError) - return err - } - - // If we received a client cert in response to our certificate request message, - // the client will send us a certificateVerifyMsg immediately after the - // clientKeyExchangeMsg. This message is a digest of all preceding - // handshake-layer messages that is signed using the private key corresponding - // to the client's certificate. This allows us to verify that the client is in - // possession of the private key of the certificate. - if len(c.peerCertificates) > 0 { - // certificateVerifyMsg is included in the transcript, but not until - // after we verify the handshake signature, since the state before - // this message was sent is used. - msg, err = c.readHandshake(nil) - if err != nil { - return err - } - certVerify, ok := msg.(*certificateVerifyMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(certVerify, msg) - } - - var sigType uint8 - var sigHash crypto.Hash - if c.vers >= VersionTLS12 { - if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, certReq.supportedSignatureAlgorithms) { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: client certificate used with invalid signature algorithm") - } - sigType, sigHash, err = typeAndHashFromSignatureScheme(certVerify.signatureAlgorithm) - if err != nil { - return c.sendAlert(alertInternalError) - } - } else { - sigType, sigHash, err = legacyTypeAndHashFromPublicKey(pub) - if err != nil { - c.sendAlert(alertIllegalParameter) - return err - } - } - - signed := hs.finishedHash.hashForClientCertificate(sigType, sigHash) - if err := verifyHandshakeSignature(sigType, pub, sigHash, signed, certVerify.signature); err != nil { - c.sendAlert(alertDecryptError) - return errors.New("tls: invalid signature by the client certificate: " + err.Error()) - } - - if err := transcriptMsg(certVerify, &hs.finishedHash); err != nil { - return err - } - } - - hs.finishedHash.discardHandshakeBuffer() - - return nil -} - -func (hs *serverHandshakeState) establishKeys() error { - c := hs.c - - clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := - keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) - - var clientCipher, serverCipher any - var clientHash, serverHash hash.Hash - - if hs.suite.aead == nil { - clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */) - clientHash = hs.suite.mac(clientMAC) - serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */) - serverHash = hs.suite.mac(serverMAC) - } else { - clientCipher = hs.suite.aead(clientKey, clientIV) - serverCipher = hs.suite.aead(serverKey, serverIV) - } - - c.in.prepareCipherSpec(c.vers, clientCipher, clientHash) - c.out.prepareCipherSpec(c.vers, serverCipher, serverHash) - - return nil -} - -func (hs *serverHandshakeState) readFinished(out []byte) error { - c := hs.c - - if err := c.readChangeCipherSpec(); err != nil { - return err - } - - // finishedMsg is included in the transcript, but not until after we - // check the client version, since the state before this message was - // sent is used during verification. - msg, err := c.readHandshake(nil) - if err != nil { - return err - } - clientFinished, ok := msg.(*finishedMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(clientFinished, msg) - } - - verify := hs.finishedHash.clientSum(hs.masterSecret) - if len(verify) != len(clientFinished.verifyData) || - subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 { - c.sendAlert(alertHandshakeFailure) - return errors.New("tls: client's Finished message is incorrect") - } - - if err := transcriptMsg(clientFinished, &hs.finishedHash); err != nil { - return err - } - - copy(out, verify) - return nil -} - -func (hs *serverHandshakeState) sendSessionTicket() error { - // ticketSupported is set in a resumption handshake if the - // ticket from the client was encrypted with an old session - // ticket key and thus a refreshed ticket should be sent. - if !hs.hello.ticketSupported { - return nil - } - - c := hs.c - m := new(newSessionTicketMsg) - - createdAt := uint64(c.config.time().Unix()) - if hs.sessionState != nil { - // If this is re-wrapping an old key, then keep - // the original time it was created. - createdAt = hs.sessionState.createdAt - } - - var certsFromClient [][]byte - for _, cert := range c.peerCertificates { - certsFromClient = append(certsFromClient, cert.Raw) - } - state := sessionState{ - vers: c.vers, - cipherSuite: hs.suite.id, - createdAt: createdAt, - masterSecret: hs.masterSecret, - certificates: certsFromClient, - } - stateBytes, err := state.marshal() - if err != nil { - return err - } - m.ticket, err = c.encryptTicket(stateBytes) - if err != nil { - return err - } - - if _, err := hs.c.writeHandshakeRecord(m, &hs.finishedHash); err != nil { - return err - } - - return nil -} - -func (hs *serverHandshakeState) sendFinished(out []byte) error { - c := hs.c - - if err := c.writeChangeCipherRecord(); err != nil { - return err - } - - finished := new(finishedMsg) - finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret) - if _, err := hs.c.writeHandshakeRecord(finished, &hs.finishedHash); err != nil { - return err - } - - copy(out, finished.verifyData) - - return nil -} - -// processCertsFromClient takes a chain of client certificates either from a -// Certificates message or from a sessionState and verifies them. It returns -// the public key of the leaf certificate. -func (c *Conn) processCertsFromClient(certificate Certificate) error { - certificates := certificate.Certificate - certs := make([]*x509.Certificate, len(certificates)) - var err error - for i, asn1Data := range certificates { - if certs[i], err = x509.ParseCertificate(asn1Data); err != nil { - c.sendAlert(alertBadCertificate) - return errors.New("tls: failed to parse client certificate: " + err.Error()) - } - if certs[i].PublicKeyAlgorithm == x509.RSA && certs[i].PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize { - c.sendAlert(alertBadCertificate) - return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", maxRSAKeySize) - } - } - - if len(certs) == 0 && requiresClientCert(c.config.ClientAuth) { - c.sendAlert(alertBadCertificate) - return errors.New("tls: client didn't provide a certificate") - } - - if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 { - opts := x509.VerifyOptions{ - Roots: c.config.ClientCAs, - CurrentTime: c.config.time(), - Intermediates: x509.NewCertPool(), - KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - } - - for _, cert := range certs[1:] { - opts.Intermediates.AddCert(cert) - } - - chains, err := certs[0].Verify(opts) - if err != nil { - c.sendAlert(alertBadCertificate) - return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err} - } - - c.verifiedChains = chains - } - - c.peerCertificates = certs - c.ocspResponse = certificate.OCSPStaple - c.scts = certificate.SignedCertificateTimestamps - - if len(certs) > 0 { - switch certs[0].PublicKey.(type) { - case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey: - default: - c.sendAlert(alertUnsupportedCertificate) - return fmt.Errorf("tls: client certificate contains an unsupported public key of type %T", certs[0].PublicKey) - } - } - - if c.config.VerifyPeerCertificate != nil { - if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil { - c.sendAlert(alertBadCertificate) - return err - } - } - - return nil -} - -func newClientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo { - supportedVersions := clientHello.supportedVersions - if len(clientHello.supportedVersions) == 0 { - supportedVersions = supportedVersionsFromMax(clientHello.vers) - } - - return toClientHelloInfo(&clientHelloInfo{ - CipherSuites: clientHello.cipherSuites, - ServerName: clientHello.serverName, - SupportedCurves: clientHello.supportedCurves, - SupportedPoints: clientHello.supportedPoints, - SignatureSchemes: clientHello.supportedSignatureAlgorithms, - SupportedProtos: clientHello.alpnProtocols, - SupportedVersions: supportedVersions, - Conn: c.conn, - config: toConfig(c.config), - ctx: ctx, - }) -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/handshake_server_tls13.go b/vendor/github.com/quic-go/qtls-go1-20/handshake_server_tls13.go deleted file mode 100644 index 4ba906e5..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/handshake_server_tls13.go +++ /dev/null @@ -1,986 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "bytes" - "context" - "crypto" - "crypto/hmac" - "crypto/rsa" - "errors" - "hash" - "io" - "time" -) - -// maxClientPSKIdentities is the number of client PSK identities the server will -// attempt to validate. It will ignore the rest not to let cheap ClientHello -// messages cause too much work in session ticket decryption attempts. -const maxClientPSKIdentities = 5 - -type serverHandshakeStateTLS13 struct { - c *Conn - ctx context.Context - clientHello *clientHelloMsg - hello *serverHelloMsg - alpnNegotiationErr error - encryptedExtensions *encryptedExtensionsMsg - sentDummyCCS bool - usingPSK bool - suite *cipherSuiteTLS13 - cert *Certificate - sigAlg SignatureScheme - earlySecret []byte - sharedKey []byte - handshakeSecret []byte - masterSecret []byte - trafficSecret []byte // client_application_traffic_secret_0 - transcript hash.Hash - clientFinished []byte - earlyData bool -} - -func (hs *serverHandshakeStateTLS13) handshake() error { - c := hs.c - - if needFIPS() { - return errors.New("tls: internal error: TLS 1.3 reached in FIPS mode") - } - - // For an overview of the TLS 1.3 handshake, see RFC 8446, Section 2. - if err := hs.processClientHello(); err != nil { - return err - } - if err := hs.checkForResumption(); err != nil { - return err - } - if err := hs.pickCertificate(); err != nil { - return err - } - c.buffering = true - if err := hs.sendServerParameters(); err != nil { - return err - } - if err := hs.sendServerCertificate(); err != nil { - return err - } - if err := hs.sendServerFinished(); err != nil { - return err - } - // Note that at this point we could start sending application data without - // waiting for the client's second flight, but the application might not - // expect the lack of replay protection of the ClientHello parameters. - if _, err := c.flush(); err != nil { - return err - } - if err := hs.readClientCertificate(); err != nil { - return err - } - if err := hs.readClientFinished(); err != nil { - return err - } - - c.isHandshakeComplete.Store(true) - - return nil -} - -func (hs *serverHandshakeStateTLS13) processClientHello() error { - c := hs.c - - hs.hello = new(serverHelloMsg) - hs.encryptedExtensions = new(encryptedExtensionsMsg) - - // TLS 1.3 froze the ServerHello.legacy_version field, and uses - // supported_versions instead. See RFC 8446, sections 4.1.3 and 4.2.1. - hs.hello.vers = VersionTLS12 - hs.hello.supportedVersion = c.vers - - if len(hs.clientHello.supportedVersions) == 0 { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: client used the legacy version field to negotiate TLS 1.3") - } - - // Abort if the client is doing a fallback and landing lower than what we - // support. See RFC 7507, which however does not specify the interaction - // with supported_versions. The only difference is that with - // supported_versions a client has a chance to attempt a [TLS 1.2, TLS 1.4] - // handshake in case TLS 1.3 is broken but 1.2 is not. Alas, in that case, - // it will have to drop the TLS_FALLBACK_SCSV protection if it falls back to - // TLS 1.2, because a TLS 1.3 server would abort here. The situation before - // supported_versions was not better because there was just no way to do a - // TLS 1.4 handshake without risking the server selecting TLS 1.3. - for _, id := range hs.clientHello.cipherSuites { - if id == TLS_FALLBACK_SCSV { - // Use c.vers instead of max(supported_versions) because an attacker - // could defeat this by adding an arbitrary high version otherwise. - if c.vers < c.config.maxSupportedVersion(roleServer) { - c.sendAlert(alertInappropriateFallback) - return errors.New("tls: client using inappropriate protocol fallback") - } - break - } - } - - if len(hs.clientHello.compressionMethods) != 1 || - hs.clientHello.compressionMethods[0] != compressionNone { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: TLS 1.3 client supports illegal compression methods") - } - - hs.hello.random = make([]byte, 32) - if _, err := io.ReadFull(c.config.rand(), hs.hello.random); err != nil { - c.sendAlert(alertInternalError) - return err - } - - if len(hs.clientHello.secureRenegotiation) != 0 { - c.sendAlert(alertHandshakeFailure) - return errors.New("tls: initial handshake had non-empty renegotiation extension") - } - - hs.hello.sessionId = hs.clientHello.sessionId - hs.hello.compressionMethod = compressionNone - - preferenceList := defaultCipherSuitesTLS13 - if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) { - preferenceList = defaultCipherSuitesTLS13NoAES - } - for _, suiteID := range preferenceList { - hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID) - if hs.suite != nil { - break - } - } - if hs.suite == nil { - c.sendAlert(alertHandshakeFailure) - return errors.New("tls: no cipher suite supported by both client and server") - } - c.cipherSuite = hs.suite.id - hs.hello.cipherSuite = hs.suite.id - hs.transcript = hs.suite.hash.New() - - // Pick the ECDHE group in server preference order, but give priority to - // groups with a key share, to avoid a HelloRetryRequest round-trip. - var selectedGroup CurveID - var clientKeyShare *keyShare -GroupSelection: - for _, preferredGroup := range c.config.curvePreferences() { - for _, ks := range hs.clientHello.keyShares { - if ks.group == preferredGroup { - selectedGroup = ks.group - clientKeyShare = &ks - break GroupSelection - } - } - if selectedGroup != 0 { - continue - } - for _, group := range hs.clientHello.supportedCurves { - if group == preferredGroup { - selectedGroup = group - break - } - } - } - if selectedGroup == 0 { - c.sendAlert(alertHandshakeFailure) - return errors.New("tls: no ECDHE curve supported by both client and server") - } - if clientKeyShare == nil { - if err := hs.doHelloRetryRequest(selectedGroup); err != nil { - return err - } - clientKeyShare = &hs.clientHello.keyShares[0] - } - - if _, ok := curveForCurveID(selectedGroup); !ok { - c.sendAlert(alertInternalError) - return errors.New("tls: CurvePreferences includes unsupported curve") - } - key, err := generateECDHEKey(c.config.rand(), selectedGroup) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - hs.hello.serverShare = keyShare{group: selectedGroup, data: key.PublicKey().Bytes()} - peerKey, err := key.Curve().NewPublicKey(clientKeyShare.data) - if err != nil { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid client key share") - } - hs.sharedKey, err = key.ECDH(peerKey) - if err != nil { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid client key share") - } - - if c.quic != nil { - // RFC 9001 Section 4.2: Clients MUST NOT offer TLS versions older than 1.3. - for _, v := range hs.clientHello.supportedVersions { - if v < VersionTLS13 { - c.sendAlert(alertProtocolVersion) - return errors.New("tls: client offered TLS version older than TLS 1.3") - } - } - // RFC 9001 Section 8.2. - if hs.clientHello.quicTransportParameters == nil { - c.sendAlert(alertMissingExtension) - return errors.New("tls: client did not send a quic_transport_parameters extension") - } - c.quicSetTransportParameters(hs.clientHello.quicTransportParameters) - } else { - if hs.clientHello.quicTransportParameters != nil { - c.sendAlert(alertUnsupportedExtension) - return errors.New("tls: client sent an unexpected quic_transport_parameters extension") - } - } - - c.serverName = hs.clientHello.serverName - - selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols, c.quic != nil) - if err != nil { - hs.alpnNegotiationErr = err - } - hs.encryptedExtensions.alpnProtocol = selectedProto - c.clientProtocol = selectedProto - - return nil -} - -func (hs *serverHandshakeStateTLS13) checkForResumption() error { - c := hs.c - - if c.config.SessionTicketsDisabled { - return nil - } - - modeOK := false - for _, mode := range hs.clientHello.pskModes { - if mode == pskModeDHE { - modeOK = true - break - } - } - if !modeOK { - return nil - } - - if len(hs.clientHello.pskIdentities) != len(hs.clientHello.pskBinders) { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid or missing PSK binders") - } - if len(hs.clientHello.pskIdentities) == 0 { - return nil - } - - for i, identity := range hs.clientHello.pskIdentities { - if i >= maxClientPSKIdentities { - break - } - - plaintext, _ := c.decryptTicket(identity.label) - if plaintext == nil { - continue - } - sessionState := new(sessionStateTLS13) - if ok := sessionState.unmarshal(plaintext); !ok { - continue - } - - if hs.clientHello.earlyData { - if sessionState.maxEarlyData == 0 { - c.sendAlert(alertUnsupportedExtension) - return errors.New("tls: client sent unexpected early data") - } - - if hs.alpnNegotiationErr == nil && sessionState.alpn == c.clientProtocol && - c.extraConfig != nil && c.extraConfig.Enable0RTT && - c.extraConfig.Accept0RTT != nil && c.extraConfig.Accept0RTT(sessionState.appData) { - hs.encryptedExtensions.earlyData = true - } - } - - createdAt := time.Unix(int64(sessionState.createdAt), 0) - if c.config.time().Sub(createdAt) > maxSessionTicketLifetime { - continue - } - - // We don't check the obfuscated ticket age because it's affected by - // clock skew and it's only a freshness signal useful for shrinking the - // window for replay attacks, which don't affect us as we don't do 0-RTT. - - pskSuite := cipherSuiteTLS13ByID(sessionState.cipherSuite) - if pskSuite == nil || pskSuite.hash != hs.suite.hash { - continue - } - - // PSK connections don't re-establish client certificates, but carry - // them over in the session ticket. Ensure the presence of client certs - // in the ticket is consistent with the configured requirements. - sessionHasClientCerts := len(sessionState.certificate.Certificate) != 0 - needClientCerts := requiresClientCert(c.config.ClientAuth) - if needClientCerts && !sessionHasClientCerts { - continue - } - if sessionHasClientCerts && c.config.ClientAuth == NoClientCert { - continue - } - - psk := hs.suite.expandLabel(sessionState.resumptionSecret, "resumption", - nil, hs.suite.hash.Size()) - hs.earlySecret = hs.suite.extract(psk, nil) - binderKey := hs.suite.deriveSecret(hs.earlySecret, resumptionBinderLabel, nil) - // Clone the transcript in case a HelloRetryRequest was recorded. - transcript := cloneHash(hs.transcript, hs.suite.hash) - if transcript == nil { - c.sendAlert(alertInternalError) - return errors.New("tls: internal error: failed to clone hash") - } - clientHelloBytes, err := hs.clientHello.marshalWithoutBinders() - if err != nil { - c.sendAlert(alertInternalError) - return err - } - transcript.Write(clientHelloBytes) - pskBinder := hs.suite.finishedHash(binderKey, transcript) - if !hmac.Equal(hs.clientHello.pskBinders[i], pskBinder) { - c.sendAlert(alertDecryptError) - return errors.New("tls: invalid PSK binder") - } - - if c.quic != nil && hs.clientHello.earlyData && hs.encryptedExtensions.earlyData && i == 0 && - sessionState.maxEarlyData > 0 && sessionState.cipherSuite == hs.suite.id { - hs.earlyData = true - - transcript := hs.suite.hash.New() - if err := transcriptMsg(hs.clientHello, transcript); err != nil { - return err - } - earlyTrafficSecret := hs.suite.deriveSecret(hs.earlySecret, clientEarlyTrafficLabel, transcript) - c.quicSetReadSecret(QUICEncryptionLevelEarly, hs.suite.id, earlyTrafficSecret) - } - - c.didResume = true - if err := c.processCertsFromClient(sessionState.certificate); err != nil { - return err - } - - hs.hello.selectedIdentityPresent = true - hs.hello.selectedIdentity = uint16(i) - hs.usingPSK = true - return nil - } - - return nil -} - -// cloneHash uses the encoding.BinaryMarshaler and encoding.BinaryUnmarshaler -// interfaces implemented by standard library hashes to clone the state of in -// to a new instance of h. It returns nil if the operation fails. -func cloneHash(in hash.Hash, h crypto.Hash) hash.Hash { - // Recreate the interface to avoid importing encoding. - type binaryMarshaler interface { - MarshalBinary() (data []byte, err error) - UnmarshalBinary(data []byte) error - } - marshaler, ok := in.(binaryMarshaler) - if !ok { - return nil - } - state, err := marshaler.MarshalBinary() - if err != nil { - return nil - } - out := h.New() - unmarshaler, ok := out.(binaryMarshaler) - if !ok { - return nil - } - if err := unmarshaler.UnmarshalBinary(state); err != nil { - return nil - } - return out -} - -func (hs *serverHandshakeStateTLS13) pickCertificate() error { - c := hs.c - - // Only one of PSK and certificates are used at a time. - if hs.usingPSK { - return nil - } - - // signature_algorithms is required in TLS 1.3. See RFC 8446, Section 4.2.3. - if len(hs.clientHello.supportedSignatureAlgorithms) == 0 { - return c.sendAlert(alertMissingExtension) - } - - certificate, err := c.config.getCertificate(newClientHelloInfo(hs.ctx, c, hs.clientHello)) - if err != nil { - if err == errNoCertificates { - c.sendAlert(alertUnrecognizedName) - } else { - c.sendAlert(alertInternalError) - } - return err - } - hs.sigAlg, err = selectSignatureScheme(c.vers, certificate, hs.clientHello.supportedSignatureAlgorithms) - if err != nil { - // getCertificate returned a certificate that is unsupported or - // incompatible with the client's signature algorithms. - c.sendAlert(alertHandshakeFailure) - return err - } - hs.cert = certificate - - return nil -} - -// sendDummyChangeCipherSpec sends a ChangeCipherSpec record for compatibility -// with middleboxes that didn't implement TLS correctly. See RFC 8446, Appendix D.4. -func (hs *serverHandshakeStateTLS13) sendDummyChangeCipherSpec() error { - if hs.c.quic != nil { - return nil - } - if hs.sentDummyCCS { - return nil - } - hs.sentDummyCCS = true - - return hs.c.writeChangeCipherRecord() -} - -func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) error { - c := hs.c - - // The first ClientHello gets double-hashed into the transcript upon a - // HelloRetryRequest. See RFC 8446, Section 4.4.1. - if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil { - return err - } - chHash := hs.transcript.Sum(nil) - hs.transcript.Reset() - hs.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) - hs.transcript.Write(chHash) - - helloRetryRequest := &serverHelloMsg{ - vers: hs.hello.vers, - random: helloRetryRequestRandom, - sessionId: hs.hello.sessionId, - cipherSuite: hs.hello.cipherSuite, - compressionMethod: hs.hello.compressionMethod, - supportedVersion: hs.hello.supportedVersion, - selectedGroup: selectedGroup, - } - - if _, err := hs.c.writeHandshakeRecord(helloRetryRequest, hs.transcript); err != nil { - return err - } - - if err := hs.sendDummyChangeCipherSpec(); err != nil { - return err - } - - // clientHelloMsg is not included in the transcript. - msg, err := c.readHandshake(nil) - if err != nil { - return err - } - - clientHello, ok := msg.(*clientHelloMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(clientHello, msg) - } - - if len(clientHello.keyShares) != 1 || clientHello.keyShares[0].group != selectedGroup { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: client sent invalid key share in second ClientHello") - } - - if clientHello.earlyData { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: client indicated early data in second ClientHello") - } - - if illegalClientHelloChange(clientHello, hs.clientHello) { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: client illegally modified second ClientHello") - } - - if illegalClientHelloChange(clientHello, hs.clientHello) { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: client illegally modified second ClientHello") - } - - hs.clientHello = clientHello - return nil -} - -// illegalClientHelloChange reports whether the two ClientHello messages are -// different, with the exception of the changes allowed before and after a -// HelloRetryRequest. See RFC 8446, Section 4.1.2. -func illegalClientHelloChange(ch, ch1 *clientHelloMsg) bool { - if len(ch.supportedVersions) != len(ch1.supportedVersions) || - len(ch.cipherSuites) != len(ch1.cipherSuites) || - len(ch.supportedCurves) != len(ch1.supportedCurves) || - len(ch.supportedSignatureAlgorithms) != len(ch1.supportedSignatureAlgorithms) || - len(ch.supportedSignatureAlgorithmsCert) != len(ch1.supportedSignatureAlgorithmsCert) || - len(ch.alpnProtocols) != len(ch1.alpnProtocols) { - return true - } - for i := range ch.supportedVersions { - if ch.supportedVersions[i] != ch1.supportedVersions[i] { - return true - } - } - for i := range ch.cipherSuites { - if ch.cipherSuites[i] != ch1.cipherSuites[i] { - return true - } - } - for i := range ch.supportedCurves { - if ch.supportedCurves[i] != ch1.supportedCurves[i] { - return true - } - } - for i := range ch.supportedSignatureAlgorithms { - if ch.supportedSignatureAlgorithms[i] != ch1.supportedSignatureAlgorithms[i] { - return true - } - } - for i := range ch.supportedSignatureAlgorithmsCert { - if ch.supportedSignatureAlgorithmsCert[i] != ch1.supportedSignatureAlgorithmsCert[i] { - return true - } - } - for i := range ch.alpnProtocols { - if ch.alpnProtocols[i] != ch1.alpnProtocols[i] { - return true - } - } - return ch.vers != ch1.vers || - !bytes.Equal(ch.random, ch1.random) || - !bytes.Equal(ch.sessionId, ch1.sessionId) || - !bytes.Equal(ch.compressionMethods, ch1.compressionMethods) || - ch.serverName != ch1.serverName || - ch.ocspStapling != ch1.ocspStapling || - !bytes.Equal(ch.supportedPoints, ch1.supportedPoints) || - ch.ticketSupported != ch1.ticketSupported || - !bytes.Equal(ch.sessionTicket, ch1.sessionTicket) || - ch.secureRenegotiationSupported != ch1.secureRenegotiationSupported || - !bytes.Equal(ch.secureRenegotiation, ch1.secureRenegotiation) || - ch.scts != ch1.scts || - !bytes.Equal(ch.cookie, ch1.cookie) || - !bytes.Equal(ch.pskModes, ch1.pskModes) -} - -func (hs *serverHandshakeStateTLS13) sendServerParameters() error { - c := hs.c - - if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil { - return err - } - if _, err := hs.c.writeHandshakeRecord(hs.hello, hs.transcript); err != nil { - return err - } - - if err := hs.sendDummyChangeCipherSpec(); err != nil { - return err - } - - earlySecret := hs.earlySecret - if earlySecret == nil { - earlySecret = hs.suite.extract(nil, nil) - } - hs.handshakeSecret = hs.suite.extract(hs.sharedKey, - hs.suite.deriveSecret(earlySecret, "derived", nil)) - - clientSecret := hs.suite.deriveSecret(hs.handshakeSecret, - clientHandshakeTrafficLabel, hs.transcript) - c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, clientSecret) - serverSecret := hs.suite.deriveSecret(hs.handshakeSecret, - serverHandshakeTrafficLabel, hs.transcript) - c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, serverSecret) - - if c.quic != nil { - if c.hand.Len() != 0 { - c.sendAlert(alertUnexpectedMessage) - } - c.quicSetWriteSecret(QUICEncryptionLevelHandshake, hs.suite.id, serverSecret) - c.quicSetReadSecret(QUICEncryptionLevelHandshake, hs.suite.id, clientSecret) - } - - err := c.config.writeKeyLog(keyLogLabelClientHandshake, hs.clientHello.random, clientSecret) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - err = c.config.writeKeyLog(keyLogLabelServerHandshake, hs.clientHello.random, serverSecret) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - - selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols, c.quic != nil) - if err != nil { - c.sendAlert(alertNoApplicationProtocol) - return err - } - hs.encryptedExtensions.alpnProtocol = selectedProto - c.clientProtocol = selectedProto - - if c.quic != nil { - p, err := c.quicGetTransportParameters() - if err != nil { - return err - } - hs.encryptedExtensions.quicTransportParameters = p - } - - if _, err := hs.c.writeHandshakeRecord(hs.encryptedExtensions, hs.transcript); err != nil { - return err - } - - return nil -} - -func (hs *serverHandshakeStateTLS13) requestClientCert() bool { - return hs.c.config.ClientAuth >= RequestClientCert && !hs.usingPSK -} - -func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { - c := hs.c - - // Only one of PSK and certificates are used at a time. - if hs.usingPSK { - return nil - } - - if hs.requestClientCert() { - // Request a client certificate - certReq := new(certificateRequestMsgTLS13) - certReq.ocspStapling = true - certReq.scts = true - certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() - if c.config.ClientCAs != nil { - certReq.certificateAuthorities = c.config.ClientCAs.Subjects() - } - - if _, err := hs.c.writeHandshakeRecord(certReq, hs.transcript); err != nil { - return err - } - } - - certMsg := new(certificateMsgTLS13) - - certMsg.certificate = *hs.cert - certMsg.scts = hs.clientHello.scts && len(hs.cert.SignedCertificateTimestamps) > 0 - certMsg.ocspStapling = hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 - - if _, err := hs.c.writeHandshakeRecord(certMsg, hs.transcript); err != nil { - return err - } - - certVerifyMsg := new(certificateVerifyMsg) - certVerifyMsg.hasSignatureAlgorithm = true - certVerifyMsg.signatureAlgorithm = hs.sigAlg - - sigType, sigHash, err := typeAndHashFromSignatureScheme(hs.sigAlg) - if err != nil { - return c.sendAlert(alertInternalError) - } - - signed := signedMessage(sigHash, serverSignatureContext, hs.transcript) - signOpts := crypto.SignerOpts(sigHash) - if sigType == signatureRSAPSS { - signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} - } - sig, err := hs.cert.PrivateKey.(crypto.Signer).Sign(c.config.rand(), signed, signOpts) - if err != nil { - public := hs.cert.PrivateKey.(crypto.Signer).Public() - if rsaKey, ok := public.(*rsa.PublicKey); ok && sigType == signatureRSAPSS && - rsaKey.N.BitLen()/8 < sigHash.Size()*2+2 { // key too small for RSA-PSS - c.sendAlert(alertHandshakeFailure) - } else { - c.sendAlert(alertInternalError) - } - return errors.New("tls: failed to sign handshake: " + err.Error()) - } - certVerifyMsg.signature = sig - - if _, err := hs.c.writeHandshakeRecord(certVerifyMsg, hs.transcript); err != nil { - return err - } - - return nil -} - -func (hs *serverHandshakeStateTLS13) sendServerFinished() error { - c := hs.c - - finished := &finishedMsg{ - verifyData: hs.suite.finishedHash(c.out.trafficSecret, hs.transcript), - } - - if _, err := hs.c.writeHandshakeRecord(finished, hs.transcript); err != nil { - return err - } - - // Derive secrets that take context through the server Finished. - - hs.masterSecret = hs.suite.extract(nil, - hs.suite.deriveSecret(hs.handshakeSecret, "derived", nil)) - - hs.trafficSecret = hs.suite.deriveSecret(hs.masterSecret, - clientApplicationTrafficLabel, hs.transcript) - serverSecret := hs.suite.deriveSecret(hs.masterSecret, - serverApplicationTrafficLabel, hs.transcript) - c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, serverSecret) - - if c.quic != nil { - if c.hand.Len() != 0 { - // TODO: Handle this in setTrafficSecret? - c.sendAlert(alertUnexpectedMessage) - } - c.quicSetWriteSecret(QUICEncryptionLevelApplication, hs.suite.id, serverSecret) - } - - err := c.config.writeKeyLog(keyLogLabelClientTraffic, hs.clientHello.random, hs.trafficSecret) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - err = c.config.writeKeyLog(keyLogLabelServerTraffic, hs.clientHello.random, serverSecret) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - - c.ekm = hs.suite.exportKeyingMaterial(hs.masterSecret, hs.transcript) - - // If we did not request client certificates, at this point we can - // precompute the client finished and roll the transcript forward to send - // session tickets in our first flight. - if !hs.requestClientCert() { - if err := hs.sendSessionTickets(); err != nil { - return err - } - } - - return nil -} - -func (hs *serverHandshakeStateTLS13) shouldSendSessionTickets() bool { - if hs.c.config.SessionTicketsDisabled { - return false - } - - // QUIC tickets are sent by QUICConn.SendSessionTicket, not automatically. - if hs.c.quic != nil { - return false - } - // Don't send tickets the client wouldn't use. See RFC 8446, Section 4.2.9. - for _, pskMode := range hs.clientHello.pskModes { - if pskMode == pskModeDHE { - return true - } - } - return false -} - -func (hs *serverHandshakeStateTLS13) sendSessionTickets() error { - c := hs.c - - hs.clientFinished = hs.suite.finishedHash(c.in.trafficSecret, hs.transcript) - finishedMsg := &finishedMsg{ - verifyData: hs.clientFinished, - } - if err := transcriptMsg(finishedMsg, hs.transcript); err != nil { - return err - } - c.resumptionSecret = hs.suite.deriveSecret(hs.masterSecret, - resumptionLabel, hs.transcript) - - if !hs.shouldSendSessionTickets() { - return nil - } - return c.sendSessionTicket(false) -} - -func (c *Conn) sendSessionTicket(earlyData bool) error { - suite := cipherSuiteTLS13ByID(c.cipherSuite) - if suite == nil { - return errors.New("tls: internal error: unknown cipher suite") - } - - m := new(newSessionTicketMsgTLS13) - - var certsFromClient [][]byte - for _, cert := range c.peerCertificates { - certsFromClient = append(certsFromClient, cert.Raw) - } - state := sessionStateTLS13{ - cipherSuite: suite.id, - createdAt: uint64(c.config.time().Unix()), - resumptionSecret: c.resumptionSecret, - certificate: Certificate{ - Certificate: certsFromClient, - OCSPStaple: c.ocspResponse, - SignedCertificateTimestamps: c.scts, - }, - alpn: c.clientProtocol, - } - if earlyData { - state.maxEarlyData = 0xffffffff - state.appData = c.extraConfig.GetAppDataForSessionTicket() - } - stateBytes, err := state.marshal() - if err != nil { - c.sendAlert(alertInternalError) - return err - } - m.label, err = c.encryptTicket(stateBytes) - if err != nil { - return err - } - m.lifetime = uint32(maxSessionTicketLifetime / time.Second) - - // ticket_age_add is a random 32-bit value. See RFC 8446, section 4.6.1 - // The value is not stored anywhere; we never need to check the ticket age - // because 0-RTT is not supported. - ageAdd := make([]byte, 4) - _, err = c.config.rand().Read(ageAdd) - if err != nil { - return err - } - - if earlyData { - // RFC 9001, Section 4.6.1 - m.maxEarlyData = 0xffffffff - } - - if _, err := c.writeHandshakeRecord(m, nil); err != nil { - return err - } - - return nil -} - -func (hs *serverHandshakeStateTLS13) readClientCertificate() error { - c := hs.c - - if !hs.requestClientCert() { - // Make sure the connection is still being verified whether or not - // the server requested a client certificate. - if c.config.VerifyConnection != nil { - if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { - c.sendAlert(alertBadCertificate) - return err - } - } - return nil - } - - // If we requested a client certificate, then the client must send a - // certificate message. If it's empty, no CertificateVerify is sent. - - msg, err := c.readHandshake(hs.transcript) - if err != nil { - return err - } - - certMsg, ok := msg.(*certificateMsgTLS13) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(certMsg, msg) - } - - if err := c.processCertsFromClient(certMsg.certificate); err != nil { - return err - } - - if c.config.VerifyConnection != nil { - if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { - c.sendAlert(alertBadCertificate) - return err - } - } - - if len(certMsg.certificate.Certificate) != 0 { - // certificateVerifyMsg is included in the transcript, but not until - // after we verify the handshake signature, since the state before - // this message was sent is used. - msg, err = c.readHandshake(nil) - if err != nil { - return err - } - - certVerify, ok := msg.(*certificateVerifyMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(certVerify, msg) - } - - // See RFC 8446, Section 4.4.3. - if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: client certificate used with invalid signature algorithm") - } - sigType, sigHash, err := typeAndHashFromSignatureScheme(certVerify.signatureAlgorithm) - if err != nil { - return c.sendAlert(alertInternalError) - } - if sigType == signaturePKCS1v15 || sigHash == crypto.SHA1 { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: client certificate used with invalid signature algorithm") - } - signed := signedMessage(sigHash, clientSignatureContext, hs.transcript) - if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey, - sigHash, signed, certVerify.signature); err != nil { - c.sendAlert(alertDecryptError) - return errors.New("tls: invalid signature by the client certificate: " + err.Error()) - } - - if err := transcriptMsg(certVerify, hs.transcript); err != nil { - return err - } - } - - // If we waited until the client certificates to send session tickets, we - // are ready to do it now. - if err := hs.sendSessionTickets(); err != nil { - return err - } - - return nil -} - -func (hs *serverHandshakeStateTLS13) readClientFinished() error { - c := hs.c - - // finishedMsg is not included in the transcript. - msg, err := c.readHandshake(nil) - if err != nil { - return err - } - - finished, ok := msg.(*finishedMsg) - if !ok { - c.sendAlert(alertUnexpectedMessage) - return unexpectedMessageError(finished, msg) - } - - if !hmac.Equal(hs.clientFinished, finished.verifyData) { - c.sendAlert(alertDecryptError) - return errors.New("tls: invalid client finished hash") - } - - c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, hs.trafficSecret) - - return nil -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/key_agreement.go b/vendor/github.com/quic-go/qtls-go1-20/key_agreement.go deleted file mode 100644 index f926869a..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/key_agreement.go +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "crypto" - "crypto/ecdh" - "crypto/md5" - "crypto/rsa" - "crypto/sha1" - "crypto/x509" - "errors" - "fmt" - "io" -) - -// a keyAgreement implements the client and server side of a TLS key agreement -// protocol by generating and processing key exchange messages. -type keyAgreement interface { - // On the server side, the first two methods are called in order. - - // In the case that the key agreement protocol doesn't use a - // ServerKeyExchange message, generateServerKeyExchange can return nil, - // nil. - generateServerKeyExchange(*config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error) - processClientKeyExchange(*config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error) - - // On the client side, the next two methods are called in order. - - // This method may not be called if the server doesn't send a - // ServerKeyExchange message. - processServerKeyExchange(*config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error - generateClientKeyExchange(*config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) -} - -var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message") -var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message") - -// rsaKeyAgreement implements the standard TLS key agreement where the client -// encrypts the pre-master secret to the server's public key. -type rsaKeyAgreement struct{} - -func (ka rsaKeyAgreement) generateServerKeyExchange(config *config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { - return nil, nil -} - -func (ka rsaKeyAgreement) processClientKeyExchange(config *config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { - if len(ckx.ciphertext) < 2 { - return nil, errClientKeyExchange - } - ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) - if ciphertextLen != len(ckx.ciphertext)-2 { - return nil, errClientKeyExchange - } - ciphertext := ckx.ciphertext[2:] - - priv, ok := cert.PrivateKey.(crypto.Decrypter) - if !ok { - return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter") - } - // Perform constant time RSA PKCS #1 v1.5 decryption - preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48}) - if err != nil { - return nil, err - } - // We don't check the version number in the premaster secret. For one, - // by checking it, we would leak information about the validity of the - // encrypted pre-master secret. Secondly, it provides only a small - // benefit against a downgrade attack and some implementations send the - // wrong version anyway. See the discussion at the end of section - // 7.4.7.1 of RFC 4346. - return preMasterSecret, nil -} - -func (ka rsaKeyAgreement) processServerKeyExchange(config *config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { - return errors.New("tls: unexpected ServerKeyExchange") -} - -func (ka rsaKeyAgreement) generateClientKeyExchange(config *config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { - preMasterSecret := make([]byte, 48) - preMasterSecret[0] = byte(clientHello.vers >> 8) - preMasterSecret[1] = byte(clientHello.vers) - _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) - if err != nil { - return nil, nil, err - } - - rsaKey, ok := cert.PublicKey.(*rsa.PublicKey) - if !ok { - return nil, nil, errors.New("tls: server certificate contains incorrect key type for selected ciphersuite") - } - encrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret) - if err != nil { - return nil, nil, err - } - ckx := new(clientKeyExchangeMsg) - ckx.ciphertext = make([]byte, len(encrypted)+2) - ckx.ciphertext[0] = byte(len(encrypted) >> 8) - ckx.ciphertext[1] = byte(len(encrypted)) - copy(ckx.ciphertext[2:], encrypted) - return preMasterSecret, ckx, nil -} - -// sha1Hash calculates a SHA1 hash over the given byte slices. -func sha1Hash(slices [][]byte) []byte { - hsha1 := sha1.New() - for _, slice := range slices { - hsha1.Write(slice) - } - return hsha1.Sum(nil) -} - -// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the -// concatenation of an MD5 and SHA1 hash. -func md5SHA1Hash(slices [][]byte) []byte { - md5sha1 := make([]byte, md5.Size+sha1.Size) - hmd5 := md5.New() - for _, slice := range slices { - hmd5.Write(slice) - } - copy(md5sha1, hmd5.Sum(nil)) - copy(md5sha1[md5.Size:], sha1Hash(slices)) - return md5sha1 -} - -// hashForServerKeyExchange hashes the given slices and returns their digest -// using the given hash function (for >= TLS 1.2) or using a default based on -// the sigType (for earlier TLS versions). For Ed25519 signatures, which don't -// do pre-hashing, it returns the concatenation of the slices. -func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) []byte { - if sigType == signatureEd25519 { - var signed []byte - for _, slice := range slices { - signed = append(signed, slice...) - } - return signed - } - if version >= VersionTLS12 { - h := hashFunc.New() - for _, slice := range slices { - h.Write(slice) - } - digest := h.Sum(nil) - return digest - } - if sigType == signatureECDSA { - return sha1Hash(slices) - } - return md5SHA1Hash(slices) -} - -// ecdheKeyAgreement implements a TLS key agreement where the server -// generates an ephemeral EC public/private key pair and signs it. The -// pre-master secret is then calculated using ECDH. The signature may -// be ECDSA, Ed25519 or RSA. -type ecdheKeyAgreement struct { - version uint16 - isRSA bool - key *ecdh.PrivateKey - - // ckx and preMasterSecret are generated in processServerKeyExchange - // and returned in generateClientKeyExchange. - ckx *clientKeyExchangeMsg - preMasterSecret []byte -} - -func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { - var curveID CurveID - for _, c := range clientHello.supportedCurves { - if config.supportsCurve(c) { - curveID = c - break - } - } - - if curveID == 0 { - return nil, errors.New("tls: no supported elliptic curves offered") - } - if _, ok := curveForCurveID(curveID); !ok { - return nil, errors.New("tls: CurvePreferences includes unsupported curve") - } - - key, err := generateECDHEKey(config.rand(), curveID) - if err != nil { - return nil, err - } - ka.key = key - - // See RFC 4492, Section 5.4. - ecdhePublic := key.PublicKey().Bytes() - serverECDHEParams := make([]byte, 1+2+1+len(ecdhePublic)) - serverECDHEParams[0] = 3 // named curve - serverECDHEParams[1] = byte(curveID >> 8) - serverECDHEParams[2] = byte(curveID) - serverECDHEParams[3] = byte(len(ecdhePublic)) - copy(serverECDHEParams[4:], ecdhePublic) - - priv, ok := cert.PrivateKey.(crypto.Signer) - if !ok { - return nil, fmt.Errorf("tls: certificate private key of type %T does not implement crypto.Signer", cert.PrivateKey) - } - - var signatureAlgorithm SignatureScheme - var sigType uint8 - var sigHash crypto.Hash - if ka.version >= VersionTLS12 { - signatureAlgorithm, err = selectSignatureScheme(ka.version, cert, clientHello.supportedSignatureAlgorithms) - if err != nil { - return nil, err - } - sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) - if err != nil { - return nil, err - } - } else { - sigType, sigHash, err = legacyTypeAndHashFromPublicKey(priv.Public()) - if err != nil { - return nil, err - } - } - if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { - return nil, errors.New("tls: certificate cannot be used with the selected cipher suite") - } - - signed := hashForServerKeyExchange(sigType, sigHash, ka.version, clientHello.random, hello.random, serverECDHEParams) - - signOpts := crypto.SignerOpts(sigHash) - if sigType == signatureRSAPSS { - signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} - } - sig, err := priv.Sign(config.rand(), signed, signOpts) - if err != nil { - return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error()) - } - - skx := new(serverKeyExchangeMsg) - sigAndHashLen := 0 - if ka.version >= VersionTLS12 { - sigAndHashLen = 2 - } - skx.key = make([]byte, len(serverECDHEParams)+sigAndHashLen+2+len(sig)) - copy(skx.key, serverECDHEParams) - k := skx.key[len(serverECDHEParams):] - if ka.version >= VersionTLS12 { - k[0] = byte(signatureAlgorithm >> 8) - k[1] = byte(signatureAlgorithm) - k = k[2:] - } - k[0] = byte(len(sig) >> 8) - k[1] = byte(len(sig)) - copy(k[2:], sig) - - return skx, nil -} - -func (ka *ecdheKeyAgreement) processClientKeyExchange(config *config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { - if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { - return nil, errClientKeyExchange - } - - peerKey, err := ka.key.Curve().NewPublicKey(ckx.ciphertext[1:]) - if err != nil { - return nil, errClientKeyExchange - } - preMasterSecret, err := ka.key.ECDH(peerKey) - if err != nil { - return nil, errClientKeyExchange - } - - return preMasterSecret, nil -} - -func (ka *ecdheKeyAgreement) processServerKeyExchange(config *config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { - if len(skx.key) < 4 { - return errServerKeyExchange - } - if skx.key[0] != 3 { // named curve - return errors.New("tls: server selected unsupported curve") - } - curveID := CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) - - publicLen := int(skx.key[3]) - if publicLen+4 > len(skx.key) { - return errServerKeyExchange - } - serverECDHEParams := skx.key[:4+publicLen] - publicKey := serverECDHEParams[4:] - - sig := skx.key[4+publicLen:] - if len(sig) < 2 { - return errServerKeyExchange - } - - if _, ok := curveForCurveID(curveID); !ok { - return errors.New("tls: server selected unsupported curve") - } - - key, err := generateECDHEKey(config.rand(), curveID) - if err != nil { - return err - } - ka.key = key - - peerKey, err := key.Curve().NewPublicKey(publicKey) - if err != nil { - return errServerKeyExchange - } - ka.preMasterSecret, err = key.ECDH(peerKey) - if err != nil { - return errServerKeyExchange - } - - ourPublicKey := key.PublicKey().Bytes() - ka.ckx = new(clientKeyExchangeMsg) - ka.ckx.ciphertext = make([]byte, 1+len(ourPublicKey)) - ka.ckx.ciphertext[0] = byte(len(ourPublicKey)) - copy(ka.ckx.ciphertext[1:], ourPublicKey) - - var sigType uint8 - var sigHash crypto.Hash - if ka.version >= VersionTLS12 { - signatureAlgorithm := SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1]) - sig = sig[2:] - if len(sig) < 2 { - return errServerKeyExchange - } - - if !isSupportedSignatureAlgorithm(signatureAlgorithm, clientHello.supportedSignatureAlgorithms) { - return errors.New("tls: certificate used with invalid signature algorithm") - } - sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) - if err != nil { - return err - } - } else { - sigType, sigHash, err = legacyTypeAndHashFromPublicKey(cert.PublicKey) - if err != nil { - return err - } - } - if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { - return errServerKeyExchange - } - - sigLen := int(sig[0])<<8 | int(sig[1]) - if sigLen+2 != len(sig) { - return errServerKeyExchange - } - sig = sig[2:] - - signed := hashForServerKeyExchange(sigType, sigHash, ka.version, clientHello.random, serverHello.random, serverECDHEParams) - if err := verifyHandshakeSignature(sigType, cert.PublicKey, sigHash, signed, sig); err != nil { - return errors.New("tls: invalid signature by the server certificate: " + err.Error()) - } - return nil -} - -func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { - if ka.ckx == nil { - return nil, nil, errors.New("tls: missing ServerKeyExchange message") - } - - return ka.preMasterSecret, ka.ckx, nil -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/key_schedule.go b/vendor/github.com/quic-go/qtls-go1-20/key_schedule.go deleted file mode 100644 index a4568933..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/key_schedule.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "crypto/ecdh" - "crypto/hmac" - "errors" - "fmt" - "hash" - "io" - - "golang.org/x/crypto/cryptobyte" - "golang.org/x/crypto/hkdf" -) - -// This file contains the functions necessary to compute the TLS 1.3 key -// schedule. See RFC 8446, Section 7. - -const ( - resumptionBinderLabel = "res binder" - clientEarlyTrafficLabel = "c e traffic" - clientHandshakeTrafficLabel = "c hs traffic" - serverHandshakeTrafficLabel = "s hs traffic" - clientApplicationTrafficLabel = "c ap traffic" - serverApplicationTrafficLabel = "s ap traffic" - exporterLabel = "exp master" - resumptionLabel = "res master" - trafficUpdateLabel = "traffic upd" -) - -// expandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1. -func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []byte, length int) []byte { - var hkdfLabel cryptobyte.Builder - hkdfLabel.AddUint16(uint16(length)) - hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes([]byte("tls13 ")) - b.AddBytes([]byte(label)) - }) - hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(context) - }) - hkdfLabelBytes, err := hkdfLabel.Bytes() - if err != nil { - // Rather than calling BytesOrPanic, we explicitly handle this error, in - // order to provide a reasonable error message. It should be basically - // impossible for this to panic, and routing errors back through the - // tree rooted in this function is quite painful. The labels are fixed - // size, and the context is either a fixed-length computed hash, or - // parsed from a field which has the same length limitation. As such, an - // error here is likely to only be caused during development. - // - // NOTE: another reasonable approach here might be to return a - // randomized slice if we encounter an error, which would break the - // connection, but avoid panicking. This would perhaps be safer but - // significantly more confusing to users. - panic(fmt.Errorf("failed to construct HKDF label: %s", err)) - } - out := make([]byte, length) - n, err := hkdf.Expand(c.hash.New, secret, hkdfLabelBytes).Read(out) - if err != nil || n != length { - panic("tls: HKDF-Expand-Label invocation failed unexpectedly") - } - return out -} - -// deriveSecret implements Derive-Secret from RFC 8446, Section 7.1. -func (c *cipherSuiteTLS13) deriveSecret(secret []byte, label string, transcript hash.Hash) []byte { - if transcript == nil { - transcript = c.hash.New() - } - return c.expandLabel(secret, label, transcript.Sum(nil), c.hash.Size()) -} - -// extract implements HKDF-Extract with the cipher suite hash. -func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte { - if newSecret == nil { - newSecret = make([]byte, c.hash.Size()) - } - return hkdf.Extract(c.hash.New, newSecret, currentSecret) -} - -// nextTrafficSecret generates the next traffic secret, given the current one, -// according to RFC 8446, Section 7.2. -func (c *cipherSuiteTLS13) nextTrafficSecret(trafficSecret []byte) []byte { - return c.expandLabel(trafficSecret, trafficUpdateLabel, nil, c.hash.Size()) -} - -// trafficKey generates traffic keys according to RFC 8446, Section 7.3. -func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) { - key = c.expandLabel(trafficSecret, "key", nil, c.keyLen) - iv = c.expandLabel(trafficSecret, "iv", nil, aeadNonceLength) - return -} - -// finishedHash generates the Finished verify_data or PskBinderEntry according -// to RFC 8446, Section 4.4.4. See sections 4.4 and 4.2.11.2 for the baseKey -// selection. -func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) []byte { - finishedKey := c.expandLabel(baseKey, "finished", nil, c.hash.Size()) - verifyData := hmac.New(c.hash.New, finishedKey) - verifyData.Write(transcript.Sum(nil)) - return verifyData.Sum(nil) -} - -// exportKeyingMaterial implements RFC5705 exporters for TLS 1.3 according to -// RFC 8446, Section 7.5. -func (c *cipherSuiteTLS13) exportKeyingMaterial(masterSecret []byte, transcript hash.Hash) func(string, []byte, int) ([]byte, error) { - expMasterSecret := c.deriveSecret(masterSecret, exporterLabel, transcript) - return func(label string, context []byte, length int) ([]byte, error) { - secret := c.deriveSecret(expMasterSecret, label, nil) - h := c.hash.New() - h.Write(context) - return c.expandLabel(secret, "exporter", h.Sum(nil), length), nil - } -} - -// generateECDHEKey returns a PrivateKey that implements Diffie-Hellman -// according to RFC 8446, Section 4.2.8.2. -func generateECDHEKey(rand io.Reader, curveID CurveID) (*ecdh.PrivateKey, error) { - curve, ok := curveForCurveID(curveID) - if !ok { - return nil, errors.New("tls: internal error: unsupported curve") - } - - return curve.GenerateKey(rand) -} - -func curveForCurveID(id CurveID) (ecdh.Curve, bool) { - switch id { - case X25519: - return ecdh.X25519(), true - case CurveP256: - return ecdh.P256(), true - case CurveP384: - return ecdh.P384(), true - case CurveP521: - return ecdh.P521(), true - default: - return nil, false - } -} - -func curveIDForCurve(curve ecdh.Curve) (CurveID, bool) { - switch curve { - case ecdh.X25519(): - return X25519, true - case ecdh.P256(): - return CurveP256, true - case ecdh.P384(): - return CurveP384, true - case ecdh.P521(): - return CurveP521, true - default: - return 0, false - } -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/notboring.go b/vendor/github.com/quic-go/qtls-go1-20/notboring.go deleted file mode 100644 index f292e4f0..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/notboring.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -func needFIPS() bool { return false } - -func supportedSignatureAlgorithms() []SignatureScheme { - return defaultSupportedSignatureAlgorithms -} - -func fipsMinVersion(c *config) uint16 { panic("fipsMinVersion") } -func fipsMaxVersion(c *config) uint16 { panic("fipsMaxVersion") } -func fipsCurvePreferences(c *config) []CurveID { panic("fipsCurvePreferences") } -func fipsCipherSuites(c *config) []uint16 { panic("fipsCipherSuites") } - -var fipsSupportedSignatureAlgorithms []SignatureScheme diff --git a/vendor/github.com/quic-go/qtls-go1-20/prf.go b/vendor/github.com/quic-go/qtls-go1-20/prf.go deleted file mode 100644 index 14712891..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/prf.go +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "crypto" - "crypto/hmac" - "crypto/md5" - "crypto/sha1" - "crypto/sha256" - "crypto/sha512" - "errors" - "fmt" - "hash" -) - -// Split a premaster secret in two as specified in RFC 4346, Section 5. -func splitPreMasterSecret(secret []byte) (s1, s2 []byte) { - s1 = secret[0 : (len(secret)+1)/2] - s2 = secret[len(secret)/2:] - return -} - -// pHash implements the P_hash function, as defined in RFC 4346, Section 5. -func pHash(result, secret, seed []byte, hash func() hash.Hash) { - h := hmac.New(hash, secret) - h.Write(seed) - a := h.Sum(nil) - - j := 0 - for j < len(result) { - h.Reset() - h.Write(a) - h.Write(seed) - b := h.Sum(nil) - copy(result[j:], b) - j += len(b) - - h.Reset() - h.Write(a) - a = h.Sum(nil) - } -} - -// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5. -func prf10(result, secret, label, seed []byte) { - hashSHA1 := sha1.New - hashMD5 := md5.New - - labelAndSeed := make([]byte, len(label)+len(seed)) - copy(labelAndSeed, label) - copy(labelAndSeed[len(label):], seed) - - s1, s2 := splitPreMasterSecret(secret) - pHash(result, s1, labelAndSeed, hashMD5) - result2 := make([]byte, len(result)) - pHash(result2, s2, labelAndSeed, hashSHA1) - - for i, b := range result2 { - result[i] ^= b - } -} - -// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5. -func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) { - return func(result, secret, label, seed []byte) { - labelAndSeed := make([]byte, len(label)+len(seed)) - copy(labelAndSeed, label) - copy(labelAndSeed[len(label):], seed) - - pHash(result, secret, labelAndSeed, hashFunc) - } -} - -const ( - masterSecretLength = 48 // Length of a master secret in TLS 1.1. - finishedVerifyLength = 12 // Length of verify_data in a Finished message. -) - -var masterSecretLabel = []byte("master secret") -var keyExpansionLabel = []byte("key expansion") -var clientFinishedLabel = []byte("client finished") -var serverFinishedLabel = []byte("server finished") - -func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) { - switch version { - case VersionTLS10, VersionTLS11: - return prf10, crypto.Hash(0) - case VersionTLS12: - if suite.flags&suiteSHA384 != 0 { - return prf12(sha512.New384), crypto.SHA384 - } - return prf12(sha256.New), crypto.SHA256 - default: - panic("unknown version") - } -} - -func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) { - prf, _ := prfAndHashForVersion(version, suite) - return prf -} - -// masterFromPreMasterSecret generates the master secret from the pre-master -// secret. See RFC 5246, Section 8.1. -func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { - seed := make([]byte, 0, len(clientRandom)+len(serverRandom)) - seed = append(seed, clientRandom...) - seed = append(seed, serverRandom...) - - masterSecret := make([]byte, masterSecretLength) - prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed) - return masterSecret -} - -// keysFromMasterSecret generates the connection keys from the master -// secret, given the lengths of the MAC key, cipher key and IV, as defined in -// RFC 2246, Section 6.3. -func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { - seed := make([]byte, 0, len(serverRandom)+len(clientRandom)) - seed = append(seed, serverRandom...) - seed = append(seed, clientRandom...) - - n := 2*macLen + 2*keyLen + 2*ivLen - keyMaterial := make([]byte, n) - prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed) - clientMAC = keyMaterial[:macLen] - keyMaterial = keyMaterial[macLen:] - serverMAC = keyMaterial[:macLen] - keyMaterial = keyMaterial[macLen:] - clientKey = keyMaterial[:keyLen] - keyMaterial = keyMaterial[keyLen:] - serverKey = keyMaterial[:keyLen] - keyMaterial = keyMaterial[keyLen:] - clientIV = keyMaterial[:ivLen] - keyMaterial = keyMaterial[ivLen:] - serverIV = keyMaterial[:ivLen] - return -} - -func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { - var buffer []byte - if version >= VersionTLS12 { - buffer = []byte{} - } - - prf, hash := prfAndHashForVersion(version, cipherSuite) - if hash != 0 { - return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf} - } - - return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf} -} - -// A finishedHash calculates the hash of a set of handshake messages suitable -// for including in a Finished message. -type finishedHash struct { - client hash.Hash - server hash.Hash - - // Prior to TLS 1.2, an additional MD5 hash is required. - clientMD5 hash.Hash - serverMD5 hash.Hash - - // In TLS 1.2, a full buffer is sadly required. - buffer []byte - - version uint16 - prf func(result, secret, label, seed []byte) -} - -func (h *finishedHash) Write(msg []byte) (n int, err error) { - h.client.Write(msg) - h.server.Write(msg) - - if h.version < VersionTLS12 { - h.clientMD5.Write(msg) - h.serverMD5.Write(msg) - } - - if h.buffer != nil { - h.buffer = append(h.buffer, msg...) - } - - return len(msg), nil -} - -func (h finishedHash) Sum() []byte { - if h.version >= VersionTLS12 { - return h.client.Sum(nil) - } - - out := make([]byte, 0, md5.Size+sha1.Size) - out = h.clientMD5.Sum(out) - return h.client.Sum(out) -} - -// clientSum returns the contents of the verify_data member of a client's -// Finished message. -func (h finishedHash) clientSum(masterSecret []byte) []byte { - out := make([]byte, finishedVerifyLength) - h.prf(out, masterSecret, clientFinishedLabel, h.Sum()) - return out -} - -// serverSum returns the contents of the verify_data member of a server's -// Finished message. -func (h finishedHash) serverSum(masterSecret []byte) []byte { - out := make([]byte, finishedVerifyLength) - h.prf(out, masterSecret, serverFinishedLabel, h.Sum()) - return out -} - -// hashForClientCertificate returns the handshake messages so far, pre-hashed if -// necessary, suitable for signing by a TLS client certificate. -func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Hash) []byte { - if (h.version >= VersionTLS12 || sigType == signatureEd25519) && h.buffer == nil { - panic("tls: handshake hash for a client certificate requested after discarding the handshake buffer") - } - - if sigType == signatureEd25519 { - return h.buffer - } - - if h.version >= VersionTLS12 { - hash := hashAlg.New() - hash.Write(h.buffer) - return hash.Sum(nil) - } - - if sigType == signatureECDSA { - return h.server.Sum(nil) - } - - return h.Sum() -} - -// discardHandshakeBuffer is called when there is no more need to -// buffer the entirety of the handshake messages. -func (h *finishedHash) discardHandshakeBuffer() { - h.buffer = nil -} - -// noExportedKeyingMaterial is used as a value of -// ConnectionState.ekm when renegotiation is enabled and thus -// we wish to fail all key-material export requests. -func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) { - return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled") -} - -// ekmFromMasterSecret generates exported keying material as defined in RFC 5705. -func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) { - return func(label string, context []byte, length int) ([]byte, error) { - switch label { - case "client finished", "server finished", "master secret", "key expansion": - // These values are reserved and may not be used. - return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label) - } - - seedLen := len(serverRandom) + len(clientRandom) - if context != nil { - seedLen += 2 + len(context) - } - seed := make([]byte, 0, seedLen) - - seed = append(seed, clientRandom...) - seed = append(seed, serverRandom...) - - if context != nil { - if len(context) >= 1<<16 { - return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long") - } - seed = append(seed, byte(len(context)>>8), byte(len(context))) - seed = append(seed, context...) - } - - keyMaterial := make([]byte, length) - prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed) - return keyMaterial, nil - } -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/quic.go b/vendor/github.com/quic-go/qtls-go1-20/quic.go deleted file mode 100644 index f146688b..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/quic.go +++ /dev/null @@ -1,418 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "context" - "errors" - "fmt" -) - -// QUICEncryptionLevel represents a QUIC encryption level used to transmit -// handshake messages. -type QUICEncryptionLevel int - -const ( - QUICEncryptionLevelInitial = QUICEncryptionLevel(iota) - QUICEncryptionLevelEarly - QUICEncryptionLevelHandshake - QUICEncryptionLevelApplication -) - -func (l QUICEncryptionLevel) String() string { - switch l { - case QUICEncryptionLevelInitial: - return "Initial" - case QUICEncryptionLevelEarly: - return "Early" - case QUICEncryptionLevelHandshake: - return "Handshake" - case QUICEncryptionLevelApplication: - return "Application" - default: - return fmt.Sprintf("QUICEncryptionLevel(%v)", int(l)) - } -} - -// A QUICConn represents a connection which uses a QUIC implementation as the underlying -// transport as described in RFC 9001. -// -// Methods of QUICConn are not safe for concurrent use. -type QUICConn struct { - conn *Conn - - sessionTicketSent bool -} - -// A QUICConfig configures a QUICConn. -type QUICConfig struct { - TLSConfig *Config - ExtraConfig *ExtraConfig -} - -// A QUICEventKind is a type of operation on a QUIC connection. -type QUICEventKind int - -const ( - // QUICNoEvent indicates that there are no events available. - QUICNoEvent QUICEventKind = iota - - // QUICSetReadSecret and QUICSetWriteSecret provide the read and write - // secrets for a given encryption level. - // QUICEvent.Level, QUICEvent.Data, and QUICEvent.Suite are set. - // - // Secrets for the Initial encryption level are derived from the initial - // destination connection ID, and are not provided by the QUICConn. - QUICSetReadSecret - QUICSetWriteSecret - - // QUICWriteData provides data to send to the peer in CRYPTO frames. - // QUICEvent.Data is set. - QUICWriteData - - // QUICTransportParameters provides the peer's QUIC transport parameters. - // QUICEvent.Data is set. - QUICTransportParameters - - // QUICTransportParametersRequired indicates that the caller must provide - // QUIC transport parameters to send to the peer. The caller should set - // the transport parameters with QUICConn.SetTransportParameters and call - // QUICConn.NextEvent again. - // - // If transport parameters are set before calling QUICConn.Start, the - // connection will never generate a QUICTransportParametersRequired event. - QUICTransportParametersRequired - - // QUICRejectedEarlyData indicates that the server rejected 0-RTT data even - // if we offered it. It's returned before QUICEncryptionLevelApplication - // keys are returned. - QUICRejectedEarlyData - - // QUICHandshakeDone indicates that the TLS handshake has completed. - QUICHandshakeDone -) - -// A QUICEvent is an event occurring on a QUIC connection. -// -// The type of event is specified by the Kind field. -// The contents of the other fields are kind-specific. -type QUICEvent struct { - Kind QUICEventKind - - // Set for QUICSetReadSecret, QUICSetWriteSecret, and QUICWriteData. - Level QUICEncryptionLevel - - // Set for QUICTransportParameters, QUICSetReadSecret, QUICSetWriteSecret, and QUICWriteData. - // The contents are owned by crypto/tls, and are valid until the next NextEvent call. - Data []byte - - // Set for QUICSetReadSecret and QUICSetWriteSecret. - Suite uint16 -} - -type quicState struct { - events []QUICEvent - nextEvent int - - // eventArr is a statically allocated event array, large enough to handle - // the usual maximum number of events resulting from a single call: transport - // parameters, Initial data, Early read secret, Handshake write and read - // secrets, Handshake data, Application write secret, Application data. - eventArr [8]QUICEvent - - started bool - signalc chan struct{} // handshake data is available to be read - blockedc chan struct{} // handshake is waiting for data, closed when done - cancelc <-chan struct{} // handshake has been canceled - cancel context.CancelFunc - - // readbuf is shared between HandleData and the handshake goroutine. - // HandshakeCryptoData passes ownership to the handshake goroutine by - // reading from signalc, and reclaims ownership by reading from blockedc. - readbuf []byte - - transportParams []byte // to send to the peer -} - -// QUICClient returns a new TLS client side connection using QUICTransport as the -// underlying transport. The config cannot be nil. -// -// The config's MinVersion must be at least TLS 1.3. -func QUICClient(config *QUICConfig) *QUICConn { - return newQUICConn(Client(nil, config.TLSConfig), config.ExtraConfig) -} - -// QUICServer returns a new TLS server side connection using QUICTransport as the -// underlying transport. The config cannot be nil. -// -// The config's MinVersion must be at least TLS 1.3. -func QUICServer(config *QUICConfig) *QUICConn { - return newQUICConn(Server(nil, config.TLSConfig), config.ExtraConfig) -} - -func newQUICConn(conn *Conn, extraConfig *ExtraConfig) *QUICConn { - conn.quic = &quicState{ - signalc: make(chan struct{}), - blockedc: make(chan struct{}), - } - conn.quic.events = conn.quic.eventArr[:0] - conn.extraConfig = extraConfig - return &QUICConn{ - conn: conn, - } -} - -// Start starts the client or server handshake protocol. -// It may produce connection events, which may be read with NextEvent. -// -// Start must be called at most once. -func (q *QUICConn) Start(ctx context.Context) error { - if q.conn.quic.started { - return quicError(errors.New("tls: Start called more than once")) - } - q.conn.quic.started = true - if q.conn.config.MinVersion < VersionTLS13 { - return quicError(errors.New("tls: Config MinVersion must be at least TLS 1.13")) - } - go q.conn.HandshakeContext(ctx) - if _, ok := <-q.conn.quic.blockedc; !ok { - return q.conn.handshakeErr - } - return nil -} - -// NextEvent returns the next event occurring on the connection. -// It returns an event with a Kind of QUICNoEvent when no events are available. -func (q *QUICConn) NextEvent() QUICEvent { - qs := q.conn.quic - if last := qs.nextEvent - 1; last >= 0 && len(qs.events[last].Data) > 0 { - // Write over some of the previous event's data, - // to catch callers erroniously retaining it. - qs.events[last].Data[0] = 0 - } - if qs.nextEvent >= len(qs.events) { - qs.events = qs.events[:0] - qs.nextEvent = 0 - return QUICEvent{Kind: QUICNoEvent} - } - e := qs.events[qs.nextEvent] - qs.events[qs.nextEvent] = QUICEvent{} // zero out references to data - qs.nextEvent++ - return e -} - -// Close closes the connection and stops any in-progress handshake. -func (q *QUICConn) Close() error { - if q.conn.quic.cancel == nil { - return nil // never started - } - q.conn.quic.cancel() - for range q.conn.quic.blockedc { - // Wait for the handshake goroutine to return. - } - return q.conn.handshakeErr -} - -// HandleData handles handshake bytes received from the peer. -// It may produce connection events, which may be read with NextEvent. -func (q *QUICConn) HandleData(level QUICEncryptionLevel, data []byte) error { - c := q.conn - if c.in.level != level { - return quicError(c.in.setErrorLocked(errors.New("tls: handshake data received at wrong level"))) - } - c.quic.readbuf = data - <-c.quic.signalc - _, ok := <-c.quic.blockedc - if ok { - // The handshake goroutine is waiting for more data. - return nil - } - // The handshake goroutine has exited. - c.handshakeMutex.Lock() - defer c.handshakeMutex.Unlock() - c.hand.Write(c.quic.readbuf) - c.quic.readbuf = nil - for q.conn.hand.Len() >= 4 && q.conn.handshakeErr == nil { - b := q.conn.hand.Bytes() - n := int(b[1])<<16 | int(b[2])<<8 | int(b[3]) - if n > maxHandshake { - q.conn.handshakeErr = fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshake) - break - } - if len(b) < 4+n { - return nil - } - if err := q.conn.handlePostHandshakeMessage(); err != nil { - q.conn.handshakeErr = err - } - } - if q.conn.handshakeErr != nil { - return quicError(q.conn.handshakeErr) - } - return nil -} - -// SendSessionTicket sends a session ticket to the client. -// It produces connection events, which may be read with NextEvent. -// Currently, it can only be called once. -func (q *QUICConn) SendSessionTicket(earlyData bool) error { - c := q.conn - if !c.isHandshakeComplete.Load() { - return quicError(errors.New("tls: SendSessionTicket called before handshake completed")) - } - if c.isClient { - return quicError(errors.New("tls: SendSessionTicket called on the client")) - } - if q.sessionTicketSent { - return quicError(errors.New("tls: SendSessionTicket called multiple times")) - } - q.sessionTicketSent = true - return quicError(c.sendSessionTicket(earlyData)) -} - -// ConnectionState returns basic TLS details about the connection. -func (q *QUICConn) ConnectionState() ConnectionState { - return q.conn.ConnectionState() -} - -// SetTransportParameters sets the transport parameters to send to the peer. -// -// Server connections may delay setting the transport parameters until after -// receiving the client's transport parameters. See QUICTransportParametersRequired. -func (q *QUICConn) SetTransportParameters(params []byte) { - if params == nil { - params = []byte{} - } - q.conn.quic.transportParams = params - if q.conn.quic.started { - <-q.conn.quic.signalc - <-q.conn.quic.blockedc - } -} - -// quicError ensures err is an AlertError. -// If err is not already, quicError wraps it with alertInternalError. -func quicError(err error) error { - if err == nil { - return nil - } - var ae AlertError - if errors.As(err, &ae) { - return err - } - var a alert - if !errors.As(err, &a) { - a = alertInternalError - } - // Return an error wrapping the original error and an AlertError. - // Truncate the text of the alert to 0 characters. - return fmt.Errorf("%w%.0w", err, AlertError(a)) -} - -func (c *Conn) quicReadHandshakeBytes(n int) error { - for c.hand.Len() < n { - if err := c.quicWaitForSignal(); err != nil { - return err - } - } - return nil -} - -func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) { - c.quic.events = append(c.quic.events, QUICEvent{ - Kind: QUICSetReadSecret, - Level: level, - Suite: suite, - Data: secret, - }) -} - -func (c *Conn) quicSetWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) { - c.quic.events = append(c.quic.events, QUICEvent{ - Kind: QUICSetWriteSecret, - Level: level, - Suite: suite, - Data: secret, - }) -} - -func (c *Conn) quicWriteCryptoData(level QUICEncryptionLevel, data []byte) { - var last *QUICEvent - if len(c.quic.events) > 0 { - last = &c.quic.events[len(c.quic.events)-1] - } - if last == nil || last.Kind != QUICWriteData || last.Level != level { - c.quic.events = append(c.quic.events, QUICEvent{ - Kind: QUICWriteData, - Level: level, - }) - last = &c.quic.events[len(c.quic.events)-1] - } - last.Data = append(last.Data, data...) -} - -func (c *Conn) quicSetTransportParameters(params []byte) { - c.quic.events = append(c.quic.events, QUICEvent{ - Kind: QUICTransportParameters, - Data: params, - }) -} - -func (c *Conn) quicGetTransportParameters() ([]byte, error) { - if c.quic.transportParams == nil { - c.quic.events = append(c.quic.events, QUICEvent{ - Kind: QUICTransportParametersRequired, - }) - } - for c.quic.transportParams == nil { - if err := c.quicWaitForSignal(); err != nil { - return nil, err - } - } - return c.quic.transportParams, nil -} - -func (c *Conn) quicHandshakeComplete() { - c.quic.events = append(c.quic.events, QUICEvent{ - Kind: QUICHandshakeDone, - }) -} - -func (c *Conn) quicRejectedEarlyData() { - c.quic.events = append(c.quic.events, QUICEvent{ - Kind: QUICRejectedEarlyData, - }) -} - -// quicWaitForSignal notifies the QUICConn that handshake progress is blocked, -// and waits for a signal that the handshake should proceed. -// -// The handshake may become blocked waiting for handshake bytes -// or for the user to provide transport parameters. -func (c *Conn) quicWaitForSignal() error { - // Drop the handshake mutex while blocked to allow the user - // to call ConnectionState before the handshake completes. - c.handshakeMutex.Unlock() - defer c.handshakeMutex.Lock() - // Send on blockedc to notify the QUICConn that the handshake is blocked. - // Exported methods of QUICConn wait for the handshake to become blocked - // before returning to the user. - select { - case c.quic.blockedc <- struct{}{}: - case <-c.quic.cancelc: - return c.sendAlertLocked(alertCloseNotify) - } - // The QUICConn reads from signalc to notify us that the handshake may - // be able to proceed. (The QUICConn reads, because we close signalc to - // indicate that the handshake has completed.) - select { - case c.quic.signalc <- struct{}{}: - c.hand.Write(c.quic.readbuf) - c.quic.readbuf = nil - case <-c.quic.cancelc: - return c.sendAlertLocked(alertCloseNotify) - } - return nil -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/ticket.go b/vendor/github.com/quic-go/qtls-go1-20/ticket.go deleted file mode 100644 index 36662070..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/ticket.go +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package qtls - -import ( - "bytes" - "crypto/aes" - "crypto/cipher" - "crypto/hmac" - "crypto/sha256" - "crypto/subtle" - "errors" - "golang.org/x/crypto/cryptobyte" - "io" -) - -// sessionState contains the information that is serialized into a session -// ticket in order to later resume a connection. -type sessionState struct { - vers uint16 - cipherSuite uint16 - createdAt uint64 - masterSecret []byte // opaque master_secret<1..2^16-1>; - // struct { opaque certificate<1..2^24-1> } Certificate; - certificates [][]byte // Certificate certificate_list<0..2^24-1>; - - // usedOldKey is true if the ticket from which this session came from - // was encrypted with an older key and thus should be refreshed. - usedOldKey bool -} - -func (m *sessionState) marshal() ([]byte, error) { - var b cryptobyte.Builder - b.AddUint16(m.vers) - b.AddUint16(m.cipherSuite) - addUint64(&b, m.createdAt) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.masterSecret) - }) - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - for _, cert := range m.certificates { - b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(cert) - }) - } - }) - return b.Bytes() -} - -func (m *sessionState) unmarshal(data []byte) bool { - *m = sessionState{usedOldKey: m.usedOldKey} - s := cryptobyte.String(data) - if ok := s.ReadUint16(&m.vers) && - s.ReadUint16(&m.cipherSuite) && - readUint64(&s, &m.createdAt) && - readUint16LengthPrefixed(&s, &m.masterSecret) && - len(m.masterSecret) != 0; !ok { - return false - } - var certList cryptobyte.String - if !s.ReadUint24LengthPrefixed(&certList) { - return false - } - for !certList.Empty() { - var cert []byte - if !readUint24LengthPrefixed(&certList, &cert) { - return false - } - m.certificates = append(m.certificates, cert) - } - return s.Empty() -} - -// sessionStateTLS13 is the content of a TLS 1.3 session ticket. Its first -// version (revision = 0) doesn't carry any of the information needed for 0-RTT -// validation and the nonce is always empty. -// version (revision = 1) carries the max_early_data_size sent in the ticket. -// version (revision = 2) carries the ALPN sent in the ticket. -type sessionStateTLS13 struct { - // uint8 version = 0x0304; - // uint8 revision = 2; - cipherSuite uint16 - createdAt uint64 - resumptionSecret []byte // opaque resumption_master_secret<1..2^8-1>; - certificate Certificate // CertificateEntry certificate_list<0..2^24-1>; - maxEarlyData uint32 - alpn string - - appData []byte -} - -func (m *sessionStateTLS13) marshal() ([]byte, error) { - var b cryptobyte.Builder - b.AddUint16(VersionTLS13) - b.AddUint8(2) // revision - b.AddUint16(m.cipherSuite) - addUint64(&b, m.createdAt) - b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.resumptionSecret) - }) - marshalCertificate(&b, m.certificate) - b.AddUint32(m.maxEarlyData) - b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes([]byte(m.alpn)) - }) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { - b.AddBytes(m.appData) - }) - return b.Bytes() -} - -func (m *sessionStateTLS13) unmarshal(data []byte) bool { - *m = sessionStateTLS13{} - s := cryptobyte.String(data) - var version uint16 - var revision uint8 - var alpn []byte - ret := s.ReadUint16(&version) && - version == VersionTLS13 && - s.ReadUint8(&revision) && - revision == 2 && - s.ReadUint16(&m.cipherSuite) && - readUint64(&s, &m.createdAt) && - readUint8LengthPrefixed(&s, &m.resumptionSecret) && - len(m.resumptionSecret) != 0 && - unmarshalCertificate(&s, &m.certificate) && - s.ReadUint32(&m.maxEarlyData) && - readUint8LengthPrefixed(&s, &alpn) && - readUint16LengthPrefixed(&s, &m.appData) && - s.Empty() - m.alpn = string(alpn) - return ret -} - -func (c *Conn) encryptTicket(state []byte) ([]byte, error) { - if len(c.ticketKeys) == 0 { - return nil, errors.New("tls: internal error: session ticket keys unavailable") - } - - encrypted := make([]byte, ticketKeyNameLen+aes.BlockSize+len(state)+sha256.Size) - keyName := encrypted[:ticketKeyNameLen] - iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize] - macBytes := encrypted[len(encrypted)-sha256.Size:] - - if _, err := io.ReadFull(c.config.rand(), iv); err != nil { - return nil, err - } - key := c.ticketKeys[0] - copy(keyName, key.keyName[:]) - block, err := aes.NewCipher(key.aesKey[:]) - if err != nil { - return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error()) - } - cipher.NewCTR(block, iv).XORKeyStream(encrypted[ticketKeyNameLen+aes.BlockSize:], state) - - mac := hmac.New(sha256.New, key.hmacKey[:]) - mac.Write(encrypted[:len(encrypted)-sha256.Size]) - mac.Sum(macBytes[:0]) - - return encrypted, nil -} - -func (c *Conn) decryptTicket(encrypted []byte) (plaintext []byte, usedOldKey bool) { - if len(encrypted) < ticketKeyNameLen+aes.BlockSize+sha256.Size { - return nil, false - } - - keyName := encrypted[:ticketKeyNameLen] - iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize] - macBytes := encrypted[len(encrypted)-sha256.Size:] - ciphertext := encrypted[ticketKeyNameLen+aes.BlockSize : len(encrypted)-sha256.Size] - - keyIndex := -1 - for i, candidateKey := range c.ticketKeys { - if bytes.Equal(keyName, candidateKey.keyName[:]) { - keyIndex = i - break - } - } - if keyIndex == -1 { - return nil, false - } - key := &c.ticketKeys[keyIndex] - - mac := hmac.New(sha256.New, key.hmacKey[:]) - mac.Write(encrypted[:len(encrypted)-sha256.Size]) - expected := mac.Sum(nil) - - if subtle.ConstantTimeCompare(macBytes, expected) != 1 { - return nil, false - } - - block, err := aes.NewCipher(key.aesKey[:]) - if err != nil { - return nil, false - } - plaintext = make([]byte, len(ciphertext)) - cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext) - - return plaintext, keyIndex > 0 -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/tls.go b/vendor/github.com/quic-go/qtls-go1-20/tls.go deleted file mode 100644 index 47eed085..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/tls.go +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// package qtls partially implements TLS 1.2, as specified in RFC 5246, -// and TLS 1.3, as specified in RFC 8446. -package qtls - -// BUG(agl): The crypto/tls package only implements some countermeasures -// against Lucky13 attacks on CBC-mode encryption, and only on SHA1 -// variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and -// https://www.imperialviolet.org/2013/02/04/luckythirteen.html. - -import ( - "bytes" - "context" - "crypto" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "errors" - "fmt" - "net" - "os" - "strings" -) - -// Server returns a new TLS server side connection -// using conn as the underlying transport. -// The configuration config must be non-nil and must include -// at least one certificate or else set GetCertificate. -func Server(conn net.Conn, config *Config) *Conn { - c := &Conn{ - conn: conn, - config: fromConfig(config), - } - c.handshakeFn = c.serverHandshake - return c -} - -// Client returns a new TLS client side connection -// using conn as the underlying transport. -// The config cannot be nil: users must set either ServerName or -// InsecureSkipVerify in the config. -func Client(conn net.Conn, config *Config) *Conn { - c := &Conn{ - conn: conn, - config: fromConfig(config), - isClient: true, - } - c.handshakeFn = c.clientHandshake - return c -} - -// A listener implements a network listener (net.Listener) for TLS connections. -type listener struct { - net.Listener - config *Config -} - -// Accept waits for and returns the next incoming TLS connection. -// The returned connection is of type *Conn. -func (l *listener) Accept() (net.Conn, error) { - c, err := l.Listener.Accept() - if err != nil { - return nil, err - } - return Server(c, l.config), nil -} - -// NewListener creates a Listener which accepts connections from an inner -// Listener and wraps each connection with Server. -// The configuration config must be non-nil and must include -// at least one certificate or else set GetCertificate. -func NewListener(inner net.Listener, config *Config) net.Listener { - l := new(listener) - l.Listener = inner - l.config = config - return l -} - -// Listen creates a TLS listener accepting connections on the -// given network address using net.Listen. -// The configuration config must be non-nil and must include -// at least one certificate or else set GetCertificate. -func Listen(network, laddr string, config *Config) (net.Listener, error) { - if config == nil || len(config.Certificates) == 0 && - config.GetCertificate == nil && config.GetConfigForClient == nil { - return nil, errors.New("tls: neither Certificates, GetCertificate, nor GetConfigForClient set in Config") - } - l, err := net.Listen(network, laddr) - if err != nil { - return nil, err - } - return NewListener(l, config), nil -} - -type timeoutError struct{} - -func (timeoutError) Error() string { return "tls: DialWithDialer timed out" } -func (timeoutError) Timeout() bool { return true } -func (timeoutError) Temporary() bool { return true } - -// DialWithDialer connects to the given network address using dialer.Dial and -// then initiates a TLS handshake, returning the resulting TLS connection. Any -// timeout or deadline given in the dialer apply to connection and TLS -// handshake as a whole. -// -// DialWithDialer interprets a nil configuration as equivalent to the zero -// configuration; see the documentation of Config for the defaults. -// -// DialWithDialer uses context.Background internally; to specify the context, -// use Dialer.DialContext with NetDialer set to the desired dialer. -func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { - return dial(context.Background(), dialer, network, addr, config) -} - -func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { - if netDialer.Timeout != 0 { - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, netDialer.Timeout) - defer cancel() - } - - if !netDialer.Deadline.IsZero() { - var cancel context.CancelFunc - ctx, cancel = context.WithDeadline(ctx, netDialer.Deadline) - defer cancel() - } - - rawConn, err := netDialer.DialContext(ctx, network, addr) - if err != nil { - return nil, err - } - - colonPos := strings.LastIndex(addr, ":") - if colonPos == -1 { - colonPos = len(addr) - } - hostname := addr[:colonPos] - - if config == nil { - config = defaultConfig() - } - // If no ServerName is set, infer the ServerName - // from the hostname we're connecting to. - if config.ServerName == "" { - // Make a copy to avoid polluting argument or default. - c := config.Clone() - c.ServerName = hostname - config = c - } - - conn := Client(rawConn, config) - if err := conn.HandshakeContext(ctx); err != nil { - rawConn.Close() - return nil, err - } - return conn, nil -} - -// Dial connects to the given network address using net.Dial -// and then initiates a TLS handshake, returning the resulting -// TLS connection. -// Dial interprets a nil configuration as equivalent to -// the zero configuration; see the documentation of Config -// for the defaults. -func Dial(network, addr string, config *Config) (*Conn, error) { - return DialWithDialer(new(net.Dialer), network, addr, config) -} - -// Dialer dials TLS connections given a configuration and a Dialer for the -// underlying connection. -type Dialer struct { - // NetDialer is the optional dialer to use for the TLS connections' - // underlying TCP connections. - // A nil NetDialer is equivalent to the net.Dialer zero value. - NetDialer *net.Dialer - - // Config is the TLS configuration to use for new connections. - // A nil configuration is equivalent to the zero - // configuration; see the documentation of Config for the - // defaults. - Config *Config -} - -// Dial connects to the given network address and initiates a TLS -// handshake, returning the resulting TLS connection. -// -// The returned Conn, if any, will always be of type *Conn. -// -// Dial uses context.Background internally; to specify the context, -// use DialContext. -func (d *Dialer) Dial(network, addr string) (net.Conn, error) { - return d.DialContext(context.Background(), network, addr) -} - -func (d *Dialer) netDialer() *net.Dialer { - if d.NetDialer != nil { - return d.NetDialer - } - return new(net.Dialer) -} - -// DialContext connects to the given network address and initiates a TLS -// handshake, returning the resulting TLS connection. -// -// The provided Context must be non-nil. If the context expires before -// the connection is complete, an error is returned. Once successfully -// connected, any expiration of the context will not affect the -// connection. -// -// The returned Conn, if any, will always be of type *Conn. -func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { - c, err := dial(ctx, d.netDialer(), network, addr, d.Config) - if err != nil { - // Don't return c (a typed nil) in an interface. - return nil, err - } - return c, nil -} - -// LoadX509KeyPair reads and parses a public/private key pair from a pair -// of files. The files must contain PEM encoded data. The certificate file -// may contain intermediate certificates following the leaf certificate to -// form a certificate chain. On successful return, Certificate.Leaf will -// be nil because the parsed form of the certificate is not retained. -func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) { - certPEMBlock, err := os.ReadFile(certFile) - if err != nil { - return Certificate{}, err - } - keyPEMBlock, err := os.ReadFile(keyFile) - if err != nil { - return Certificate{}, err - } - return X509KeyPair(certPEMBlock, keyPEMBlock) -} - -// X509KeyPair parses a public/private key pair from a pair of -// PEM encoded data. On successful return, Certificate.Leaf will be nil because -// the parsed form of the certificate is not retained. -func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { - fail := func(err error) (Certificate, error) { return Certificate{}, err } - - var cert Certificate - var skippedBlockTypes []string - for { - var certDERBlock *pem.Block - certDERBlock, certPEMBlock = pem.Decode(certPEMBlock) - if certDERBlock == nil { - break - } - if certDERBlock.Type == "CERTIFICATE" { - cert.Certificate = append(cert.Certificate, certDERBlock.Bytes) - } else { - skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type) - } - } - - if len(cert.Certificate) == 0 { - if len(skippedBlockTypes) == 0 { - return fail(errors.New("tls: failed to find any PEM data in certificate input")) - } - if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") { - return fail(errors.New("tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched")) - } - return fail(fmt.Errorf("tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) - } - - skippedBlockTypes = skippedBlockTypes[:0] - var keyDERBlock *pem.Block - for { - keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock) - if keyDERBlock == nil { - if len(skippedBlockTypes) == 0 { - return fail(errors.New("tls: failed to find any PEM data in key input")) - } - if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" { - return fail(errors.New("tls: found a certificate rather than a key in the PEM for the private key")) - } - return fail(fmt.Errorf("tls: failed to find PEM block with type ending in \"PRIVATE KEY\" in key input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) - } - if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") { - break - } - skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type) - } - - // We don't need to parse the public key for TLS, but we so do anyway - // to check that it looks sane and matches the private key. - x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) - if err != nil { - return fail(err) - } - - cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes) - if err != nil { - return fail(err) - } - - switch pub := x509Cert.PublicKey.(type) { - case *rsa.PublicKey: - priv, ok := cert.PrivateKey.(*rsa.PrivateKey) - if !ok { - return fail(errors.New("tls: private key type does not match public key type")) - } - if pub.N.Cmp(priv.N) != 0 { - return fail(errors.New("tls: private key does not match public key")) - } - case *ecdsa.PublicKey: - priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey) - if !ok { - return fail(errors.New("tls: private key type does not match public key type")) - } - if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { - return fail(errors.New("tls: private key does not match public key")) - } - case ed25519.PublicKey: - priv, ok := cert.PrivateKey.(ed25519.PrivateKey) - if !ok { - return fail(errors.New("tls: private key type does not match public key type")) - } - if !bytes.Equal(priv.Public().(ed25519.PublicKey), pub) { - return fail(errors.New("tls: private key does not match public key")) - } - default: - return fail(errors.New("tls: unknown public key algorithm")) - } - - return cert, nil -} - -// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates -// PKCS #1 private keys by default, while OpenSSL 1.0.0 generates PKCS #8 keys. -// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. -func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { - if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { - return key, nil - } - if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { - switch key := key.(type) { - case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey: - return key, nil - default: - return nil, errors.New("tls: found unknown private key type in PKCS#8 wrapping") - } - } - if key, err := x509.ParseECPrivateKey(der); err == nil { - return key, nil - } - - return nil, errors.New("tls: failed to parse private key") -} diff --git a/vendor/github.com/quic-go/qtls-go1-20/unsafe.go b/vendor/github.com/quic-go/qtls-go1-20/unsafe.go deleted file mode 100644 index 67a75677..00000000 --- a/vendor/github.com/quic-go/qtls-go1-20/unsafe.go +++ /dev/null @@ -1,101 +0,0 @@ -package qtls - -import ( - "crypto/tls" - "reflect" - "unsafe" -) - -func init() { - if !structsEqual(&tls.ConnectionState{}, &connectionState{}) { - panic("qtls.ConnectionState doesn't match") - } - if !structsEqual(&tls.ClientSessionState{}, &clientSessionState{}) { - panic("qtls.ClientSessionState doesn't match") - } - if !structsEqual(&tls.CertificateRequestInfo{}, &certificateRequestInfo{}) { - panic("qtls.CertificateRequestInfo doesn't match") - } - if !structsEqual(&tls.Config{}, &config{}) { - panic("qtls.Config doesn't match") - } - if !structsEqual(&tls.ClientHelloInfo{}, &clientHelloInfo{}) { - panic("qtls.ClientHelloInfo doesn't match") - } -} - -func toConnectionState(c connectionState) ConnectionState { - return *(*ConnectionState)(unsafe.Pointer(&c)) -} - -func toClientSessionState(s *clientSessionState) *ClientSessionState { - return (*ClientSessionState)(unsafe.Pointer(s)) -} - -func fromClientSessionState(s *ClientSessionState) *clientSessionState { - return (*clientSessionState)(unsafe.Pointer(s)) -} - -func toCertificateRequestInfo(i *certificateRequestInfo) *CertificateRequestInfo { - return (*CertificateRequestInfo)(unsafe.Pointer(i)) -} - -func toConfig(c *config) *Config { - return (*Config)(unsafe.Pointer(c)) -} - -func fromConfig(c *Config) *config { - return (*config)(unsafe.Pointer(c)) -} - -func toClientHelloInfo(chi *clientHelloInfo) *ClientHelloInfo { - return (*ClientHelloInfo)(unsafe.Pointer(chi)) -} - -func structsEqual(a, b interface{}) bool { - return compare(reflect.ValueOf(a), reflect.ValueOf(b)) -} - -func compare(a, b reflect.Value) bool { - sa := a.Elem() - sb := b.Elem() - if sa.NumField() != sb.NumField() { - return false - } - for i := 0; i < sa.NumField(); i++ { - fa := sa.Type().Field(i) - fb := sb.Type().Field(i) - if !reflect.DeepEqual(fa.Index, fb.Index) || fa.Name != fb.Name || fa.Anonymous != fb.Anonymous || fa.Offset != fb.Offset || !reflect.DeepEqual(fa.Type, fb.Type) { - if fa.Type.Kind() != fb.Type.Kind() { - return false - } - if fa.Type.Kind() == reflect.Slice { - if !compareStruct(fa.Type.Elem(), fb.Type.Elem()) { - return false - } - continue - } - return false - } - } - return true -} - -func compareStruct(a, b reflect.Type) bool { - if a.NumField() != b.NumField() { - return false - } - for i := 0; i < a.NumField(); i++ { - fa := a.Field(i) - fb := b.Field(i) - if !reflect.DeepEqual(fa.Index, fb.Index) || fa.Name != fb.Name || fa.Anonymous != fb.Anonymous || fa.Offset != fb.Offset || !reflect.DeepEqual(fa.Type, fb.Type) { - return false - } - } - return true -} - -// InitSessionTicketKeys triggers the initialization of session ticket keys. -func InitSessionTicketKeys(conf *Config) { - fromConfig(conf).ticketKeys(nil) -} diff --git a/vendor/github.com/quic-go/quic-go/.golangci.yml b/vendor/github.com/quic-go/quic-go/.golangci.yml index 1315759b..f5e9b48b 100644 --- a/vendor/github.com/quic-go/quic-go/.golangci.yml +++ b/vendor/github.com/quic-go/quic-go/.golangci.yml @@ -3,15 +3,15 @@ run: - internal/handshake/cipher_suite.go linters-settings: depguard: - type: blacklist - packages: - - github.com/marten-seemann/qtls - - github.com/quic-go/qtls-go1-19 - - github.com/quic-go/qtls-go1-20 - packages-with-error-message: - - github.com/marten-seemann/qtls: "importing qtls only allowed in internal/qtls" - - github.com/quic-go/qtls-go1-19: "importing qtls only allowed in internal/qtls" - - github.com/quic-go/qtls-go1-20: "importing qtls only allowed in internal/qtls" + rules: + qtls: + list-mode: lax + files: + - "!internal/qtls/**" + - "$all" + deny: + - pkg: github.com/quic-go/qtls-go1-20 + desc: "importing qtls only allowed in internal/qtls" misspell: ignore-words: - ect diff --git a/vendor/github.com/quic-go/quic-go/README.md b/vendor/github.com/quic-go/quic-go/README.md index cfb4e612..a43375e9 100644 --- a/vendor/github.com/quic-go/quic-go/README.md +++ b/vendor/github.com/quic-go/quic-go/README.md @@ -227,12 +227,13 @@ http.Client{ ## Projects using quic-go | Project | Description | Stars | -| --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | +| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | | [AdGuardHome](https://github.com/AdguardTeam/AdGuardHome) | Free and open source, powerful network-wide ads & trackers blocking DNS server. | ![GitHub Repo stars](https://img.shields.io/github/stars/AdguardTeam/AdGuardHome?style=flat-square) | | [algernon](https://github.com/xyproto/algernon) | Small self-contained pure-Go web server with Lua, Markdown, HTTP/2, QUIC, Redis and PostgreSQL support | ![GitHub Repo stars](https://img.shields.io/github/stars/xyproto/algernon?style=flat-square) | | [caddy](https://github.com/caddyserver/caddy/) | Fast, multi-platform web server with automatic HTTPS | ![GitHub Repo stars](https://img.shields.io/github/stars/caddyserver/caddy?style=flat-square) | | [cloudflared](https://github.com/cloudflare/cloudflared) | A tunneling daemon that proxies traffic from the Cloudflare network to your origins | ![GitHub Repo stars](https://img.shields.io/github/stars/cloudflare/cloudflared?style=flat-square) | -| [go-libp2p](https://github.com/libp2p/go-libp2p) | libp2p implementation in Go, powering [Kubo](https://github.com/ipfs/kubo) (IPFS) and [Lotus](https://github.com/filecoin-project/lotus) (Filecoin), among others | ![GitHub Repo stars](https://img.shields.io/github/stars/libp2p/go-libp2p?style=flat-square) | +| [go-libp2p](https://github.com/libp2p/go-libp2p) | libp2p implementation in Go, powering [Kubo](https://github.com/ipfs/kubo) (IPFS) and [Lotus](https://github.com/filecoin-project/lotus) (Filecoin), among others | ![GitHub Repo stars](https://img.shields.io/github/stars/libp2p/go-libp2p?style=flat-square) | +| [gost](https://github.com/go-gost/gost) | A simple security tunnel written in Go | ![GitHub Repo stars](https://img.shields.io/github/stars/go-gost/gost?style=flat-square) | | [Hysteria](https://github.com/apernet/hysteria) | A powerful, lightning fast and censorship resistant proxy | ![GitHub Repo stars](https://img.shields.io/github/stars/apernet/hysteria?style=flat-square) | | [Mercure](https://github.com/dunglas/mercure) | An open, easy, fast, reliable and battery-efficient solution for real-time communications | ![GitHub Repo stars](https://img.shields.io/github/stars/dunglas/mercure?style=flat-square) | | [OONI Probe](https://github.com/ooni/probe-cli) | Next generation OONI Probe. Library and CLI tool. | ![GitHub Repo stars](https://img.shields.io/github/stars/ooni/probe-cli?style=flat-square) | @@ -247,11 +248,6 @@ If you'd like to see your project added to this list, please send us a PR. quic-go always aims to support the latest two Go releases. -### Dependency on forked crypto/tls - -Since the standard library didn't provide any QUIC APIs before the Go 1.21 release, we had to fork crypto/tls to add the required APIs ourselves: [qtls for Go 1.20](https://github.com/quic-go/qtls-go1-20). -This had led to a lot of pain in the Go ecosystem, and we're happy that we can rely on Go 1.21 going forward. - ## Contributing We are always happy to welcome new contributors! We have a number of self-contained issues that are suitable for first-time contributors, they are tagged with [help wanted](https://github.com/quic-go/quic-go/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22). If you have any questions, please feel free to reach out by opening an issue or leaving a comment. diff --git a/vendor/github.com/quic-go/quic-go/conn_id_generator.go b/vendor/github.com/quic-go/quic-go/conn_id_generator.go index 2d28dc61..9cf21d9a 100644 --- a/vendor/github.com/quic-go/quic-go/conn_id_generator.go +++ b/vendor/github.com/quic-go/quic-go/conn_id_generator.go @@ -5,7 +5,6 @@ import ( "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/qerr" - "github.com/quic-go/quic-go/internal/utils" "github.com/quic-go/quic-go/internal/wire" ) @@ -60,7 +59,7 @@ func (m *connIDGenerator) SetMaxActiveConnIDs(limit uint64) error { // transport parameter. // We currently don't send the preferred_address transport parameter, // so we can issue (limit - 1) connection IDs. - for i := uint64(len(m.activeSrcConnIDs)); i < utils.Min(limit, protocol.MaxIssuedConnectionIDs); i++ { + for i := uint64(len(m.activeSrcConnIDs)); i < min(limit, protocol.MaxIssuedConnectionIDs); i++ { if err := m.issueNewConnID(); err != nil { return err } diff --git a/vendor/github.com/quic-go/quic-go/conn_id_manager.go b/vendor/github.com/quic-go/quic-go/conn_id_manager.go index ba65aec0..4aa3f749 100644 --- a/vendor/github.com/quic-go/quic-go/conn_id_manager.go +++ b/vendor/github.com/quic-go/quic-go/conn_id_manager.go @@ -145,7 +145,7 @@ func (h *connIDManager) updateConnectionID() { h.queueControlFrame(&wire.RetireConnectionIDFrame{ SequenceNumber: h.activeSequenceNumber, }) - h.highestRetired = utils.Max(h.highestRetired, h.activeSequenceNumber) + h.highestRetired = max(h.highestRetired, h.activeSequenceNumber) if h.activeStatelessResetToken != nil { h.removeStatelessResetToken(*h.activeStatelessResetToken) } diff --git a/vendor/github.com/quic-go/quic-go/connection.go b/vendor/github.com/quic-go/quic-go/connection.go index 1b288a2b..082e95d7 100644 --- a/vendor/github.com/quic-go/quic-go/connection.go +++ b/vendor/github.com/quic-go/quic-go/connection.go @@ -629,7 +629,7 @@ runLoop: sendQueueAvailable = s.sendQueue.Available() continue } - if err := s.triggerSending(); err != nil { + if err := s.triggerSending(now); err != nil { s.closeLocal(err) } if s.sendQueue.WouldBlock() { @@ -681,7 +681,7 @@ func (s *connection) ConnectionState() ConnectionState { // Time when the connection should time out func (s *connection) nextIdleTimeoutTime() time.Time { - idleTimeout := utils.Max(s.idleTimeout, s.rttStats.PTO(true)*3) + idleTimeout := max(s.idleTimeout, s.rttStats.PTO(true)*3) return s.idleTimeoutStartTime().Add(idleTimeout) } @@ -691,7 +691,7 @@ func (s *connection) nextKeepAliveTime() time.Time { if s.config.KeepAlivePeriod == 0 || s.keepAlivePingSent || !s.firstAckElicitingPacketAfterIdleSentTime.IsZero() { return time.Time{} } - keepAliveInterval := utils.Max(s.keepAliveInterval, s.rttStats.PTO(true)*3/2) + keepAliveInterval := max(s.keepAliveInterval, s.rttStats.PTO(true)*3/2) return s.lastPacketReceivedTime.Add(keepAliveInterval) } @@ -731,6 +731,10 @@ func (s *connection) handleHandshakeComplete() error { s.connIDManager.SetHandshakeComplete() s.connIDGenerator.SetHandshakeComplete() + if s.tracer != nil && s.tracer.ChoseALPN != nil { + s.tracer.ChoseALPN(s.cryptoStreamHandler.ConnectionState().NegotiatedProtocol) + } + // The server applies transport parameters right away, but the client side has to wait for handshake completion. // During a 0-RTT connection, the client is only allowed to use the new transport parameters for 1-RTT packets. if s.perspective == protocol.PerspectiveClient { @@ -776,7 +780,7 @@ func (s *connection) handleHandshakeConfirmed() error { if maxPacketSize == 0 { maxPacketSize = protocol.MaxByteCount } - s.mtuDiscoverer.Start(utils.Min(maxPacketSize, protocol.MaxPacketBufferSize)) + s.mtuDiscoverer.Start(min(maxPacketSize, protocol.MaxPacketBufferSize)) } return nil } @@ -1751,7 +1755,7 @@ func (s *connection) applyTransportParameters() { params := s.peerParams // Our local idle timeout will always be > 0. s.idleTimeout = utils.MinNonZeroDuration(s.config.MaxIdleTimeout, params.MaxIdleTimeout) - s.keepAliveInterval = utils.Min(s.config.KeepAlivePeriod, utils.Min(s.idleTimeout/2, protocol.MaxKeepAliveInterval)) + s.keepAliveInterval = min(s.config.KeepAlivePeriod, min(s.idleTimeout/2, protocol.MaxKeepAliveInterval)) s.streamsMap.UpdateLimits(params) s.frameParser.SetAckDelayExponent(params.AckDelayExponent) s.connFlowController.UpdateSendWindow(params.InitialMaxData) @@ -1767,9 +1771,8 @@ func (s *connection) applyTransportParameters() { } } -func (s *connection) triggerSending() error { +func (s *connection) triggerSending(now time.Time) error { s.pacingDeadline = time.Time{} - now := time.Now() sendMode := s.sentPacketHandler.SendMode(now) //nolint:exhaustive // No need to handle pacing limited here. @@ -1801,7 +1804,7 @@ func (s *connection) triggerSending() error { s.scheduleSending() return nil } - return s.triggerSending() + return s.triggerSending(now) case ackhandler.SendPTOHandshake: if err := s.sendProbePacket(protocol.EncryptionHandshake, now); err != nil { return err @@ -1810,7 +1813,7 @@ func (s *connection) triggerSending() error { s.scheduleSending() return nil } - return s.triggerSending() + return s.triggerSending(now) case ackhandler.SendPTOAppData: if err := s.sendProbePacket(protocol.Encryption1RTT, now); err != nil { return err @@ -1819,7 +1822,7 @@ func (s *connection) triggerSending() error { s.scheduleSending() return nil } - return s.triggerSending() + return s.triggerSending(now) default: return fmt.Errorf("BUG: invalid send mode %d", sendMode) } @@ -1988,7 +1991,7 @@ func (s *connection) maybeSendAckOnlyPacket(now time.Time) error { if packet == nil { return nil } - return s.sendPackedCoalescedPacket(packet, ecn, time.Now()) + return s.sendPackedCoalescedPacket(packet, ecn, now) } ecn := s.sentPacketHandler.ECNMode(true) @@ -2356,7 +2359,7 @@ func (s *connection) SendDatagram(p []byte) error { } f.Data = make([]byte, len(p)) copy(f.Data, p) - return s.datagramQueue.AddAndWait(f) + return s.datagramQueue.Add(f) } func (s *connection) ReceiveDatagram(ctx context.Context) ([]byte, error) { diff --git a/vendor/github.com/quic-go/quic-go/crypto_stream.go b/vendor/github.com/quic-go/quic-go/crypto_stream.go index 4be2a07a..abc7ddcf 100644 --- a/vendor/github.com/quic-go/quic-go/crypto_stream.go +++ b/vendor/github.com/quic-go/quic-go/crypto_stream.go @@ -6,7 +6,6 @@ import ( "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/qerr" - "github.com/quic-go/quic-go/internal/utils" "github.com/quic-go/quic-go/internal/wire" ) @@ -56,7 +55,7 @@ func (s *cryptoStreamImpl) HandleCryptoFrame(f *wire.CryptoFrame) error { // could e.g. be a retransmission return nil } - s.highestOffset = utils.Max(s.highestOffset, highestOffset) + s.highestOffset = max(s.highestOffset, highestOffset) if err := s.queue.Push(f.Data, f.Offset, nil); err != nil { return err } @@ -99,7 +98,7 @@ func (s *cryptoStreamImpl) HasData() bool { func (s *cryptoStreamImpl) PopCryptoFrame(maxLen protocol.ByteCount) *wire.CryptoFrame { f := &wire.CryptoFrame{Offset: s.writeOffset} - n := utils.Min(f.MaxDataLen(maxLen), protocol.ByteCount(len(s.writeBuf))) + n := min(f.MaxDataLen(maxLen), protocol.ByteCount(len(s.writeBuf))) f.Data = s.writeBuf[:n] s.writeBuf = s.writeBuf[n:] s.writeOffset += n diff --git a/vendor/github.com/quic-go/quic-go/datagram_queue.go b/vendor/github.com/quic-go/quic-go/datagram_queue.go index ca80d404..e26285b2 100644 --- a/vendor/github.com/quic-go/quic-go/datagram_queue.go +++ b/vendor/github.com/quic-go/quic-go/datagram_queue.go @@ -4,14 +4,20 @@ import ( "context" "sync" - "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/utils" + "github.com/quic-go/quic-go/internal/utils/ringbuffer" "github.com/quic-go/quic-go/internal/wire" ) +const ( + maxDatagramSendQueueLen = 32 + maxDatagramRcvQueueLen = 128 +) + type datagramQueue struct { - sendQueue chan *wire.DatagramFrame - nextFrame *wire.DatagramFrame + sendMx sync.Mutex + sendQueue ringbuffer.RingBuffer[*wire.DatagramFrame] + sent chan struct{} // used to notify Add that a datagram was dequeued rcvMx sync.Mutex rcvQueue [][]byte @@ -22,60 +28,65 @@ type datagramQueue struct { hasData func() - dequeued chan struct{} - logger utils.Logger } func newDatagramQueue(hasData func(), logger utils.Logger) *datagramQueue { return &datagramQueue{ - hasData: hasData, - sendQueue: make(chan *wire.DatagramFrame, 1), - rcvd: make(chan struct{}, 1), - dequeued: make(chan struct{}), - closed: make(chan struct{}), - logger: logger, + hasData: hasData, + rcvd: make(chan struct{}, 1), + sent: make(chan struct{}, 1), + closed: make(chan struct{}), + logger: logger, } } -// AddAndWait queues a new DATAGRAM frame for sending. -// It blocks until the frame has been dequeued. -func (h *datagramQueue) AddAndWait(f *wire.DatagramFrame) error { - select { - case h.sendQueue <- f: - h.hasData() - case <-h.closed: - return h.closeErr - } +// Add queues a new DATAGRAM frame for sending. +// Up to 32 DATAGRAM frames will be queued. +// Once that limit is reached, Add blocks until the queue size has reduced. +func (h *datagramQueue) Add(f *wire.DatagramFrame) error { + h.sendMx.Lock() - select { - case <-h.dequeued: - return nil - case <-h.closed: - return h.closeErr + for { + if h.sendQueue.Len() < maxDatagramSendQueueLen { + h.sendQueue.PushBack(f) + h.sendMx.Unlock() + h.hasData() + return nil + } + select { + case <-h.sent: // drain the queue so we don't loop immediately + default: + } + h.sendMx.Unlock() + select { + case <-h.closed: + return h.closeErr + case <-h.sent: + } + h.sendMx.Lock() } } // Peek gets the next DATAGRAM frame for sending. // If actually sent out, Pop needs to be called before the next call to Peek. func (h *datagramQueue) Peek() *wire.DatagramFrame { - if h.nextFrame != nil { - return h.nextFrame - } - select { - case h.nextFrame = <-h.sendQueue: - h.dequeued <- struct{}{} - default: + h.sendMx.Lock() + defer h.sendMx.Unlock() + if h.sendQueue.Empty() { return nil } - return h.nextFrame + return h.sendQueue.PeekFront() } func (h *datagramQueue) Pop() { - if h.nextFrame == nil { - panic("datagramQueue BUG: Pop called for nil frame") + h.sendMx.Lock() + defer h.sendMx.Unlock() + _ = h.sendQueue.PopFront() + select { + case h.sent <- struct{}{}: + default: } - h.nextFrame = nil } // HandleDatagramFrame handles a received DATAGRAM frame. @@ -84,7 +95,7 @@ func (h *datagramQueue) HandleDatagramFrame(f *wire.DatagramFrame) { copy(data, f.Data) var queued bool h.rcvMx.Lock() - if len(h.rcvQueue) < protocol.DatagramRcvQueueLen { + if len(h.rcvQueue) < maxDatagramRcvQueueLen { h.rcvQueue = append(h.rcvQueue, data) queued = true select { @@ -94,7 +105,7 @@ func (h *datagramQueue) HandleDatagramFrame(f *wire.DatagramFrame) { } h.rcvMx.Unlock() if !queued && h.logger.Debug() { - h.logger.Debugf("Discarding DATAGRAM frame (%d bytes payload)", len(f.Data)) + h.logger.Debugf("Discarding received DATAGRAM frame (%d bytes payload)", len(f.Data)) } } diff --git a/vendor/github.com/quic-go/quic-go/framer.go b/vendor/github.com/quic-go/quic-go/framer.go index 9409af4c..d5c61bcf 100644 --- a/vendor/github.com/quic-go/quic-go/framer.go +++ b/vendor/github.com/quic-go/quic-go/framer.go @@ -23,6 +23,8 @@ type framer interface { Handle0RTTRejection() error } +const maxPathResponses = 256 + type framerI struct { mutex sync.Mutex @@ -33,6 +35,7 @@ type framerI struct { controlFrameMutex sync.Mutex controlFrames []wire.Frame + pathResponses []*wire.PathResponseFrame } var _ framer = &framerI{} @@ -52,20 +55,43 @@ func (f *framerI) HasData() bool { return true } f.controlFrameMutex.Lock() - hasData = len(f.controlFrames) > 0 - f.controlFrameMutex.Unlock() - return hasData + defer f.controlFrameMutex.Unlock() + return len(f.controlFrames) > 0 || len(f.pathResponses) > 0 } func (f *framerI) QueueControlFrame(frame wire.Frame) { f.controlFrameMutex.Lock() + defer f.controlFrameMutex.Unlock() + + if pr, ok := frame.(*wire.PathResponseFrame); ok { + // Only queue up to maxPathResponses PATH_RESPONSE frames. + // This limit should be high enough to never be hit in practice, + // unless the peer is doing something malicious. + if len(f.pathResponses) >= maxPathResponses { + return + } + f.pathResponses = append(f.pathResponses, pr) + return + } f.controlFrames = append(f.controlFrames, frame) - f.controlFrameMutex.Unlock() } func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount) { - var length protocol.ByteCount f.controlFrameMutex.Lock() + defer f.controlFrameMutex.Unlock() + + var length protocol.ByteCount + // add a PATH_RESPONSE first, but only pack a single PATH_RESPONSE per packet + if len(f.pathResponses) > 0 { + frame := f.pathResponses[0] + frameLen := frame.Length(v) + if frameLen <= maxLen { + frames = append(frames, ackhandler.Frame{Frame: frame}) + length += frameLen + f.pathResponses = f.pathResponses[1:] + } + } + for len(f.controlFrames) > 0 { frame := f.controlFrames[len(f.controlFrames)-1] frameLen := frame.Length(v) @@ -76,7 +102,6 @@ func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol length += frameLen f.controlFrames = f.controlFrames[:len(f.controlFrames)-1] } - f.controlFrameMutex.Unlock() return frames, length } diff --git a/vendor/github.com/quic-go/quic-go/interface.go b/vendor/github.com/quic-go/quic-go/interface.go index da0e5e2b..b269d790 100644 --- a/vendor/github.com/quic-go/quic-go/interface.go +++ b/vendor/github.com/quic-go/quic-go/interface.go @@ -187,8 +187,12 @@ type Connection interface { // Warning: This API should not be considered stable and might change soon. ConnectionState() ConnectionState - // SendDatagram sends a message as a datagram, as specified in RFC 9221. - SendDatagram([]byte) error + // SendDatagram sends a message using a QUIC datagram, as specified in RFC 9221. + // There is no delivery guarantee for DATAGRAM frames, they are not retransmitted if lost. + // The payload of the datagram needs to fit into a single QUIC packet. + // In addition, a datagram may be dropped before being sent out if the available packet size suddenly decreases. + // If the payload is too large to be sent at the current time, a DatagramTooLargeError is returned. + SendDatagram(payload []byte) error // ReceiveDatagram gets a message received in a datagram, as specified in RFC 9221. ReceiveDatagram(context.Context) ([]byte, error) } diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/packet_number_generator.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/packet_number_generator.go index e84171e3..4a9db863 100644 --- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/packet_number_generator.go +++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/packet_number_generator.go @@ -80,5 +80,5 @@ func (p *skippingPacketNumberGenerator) Pop() (bool, protocol.PacketNumber) { func (p *skippingPacketNumberGenerator) generateNewSkip() { // make sure that there are never two consecutive packet numbers that are skipped p.nextToSkip = p.next + 3 + protocol.PacketNumber(p.rng.Int31n(int32(2*p.period))) - p.period = utils.Min(2*p.period, p.maxPeriod) + p.period = min(2*p.period, p.maxPeriod) } diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_tracker.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_tracker.go index 8d15d7c1..6d8eec4e 100644 --- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_tracker.go +++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_tracker.go @@ -179,7 +179,7 @@ func (h *receivedPacketTracker) GetAckFrame(onlyIfQueued bool) *wire.AckFrame { ack = &wire.AckFrame{} } ack.Reset() - ack.DelayTime = utils.Max(0, now.Sub(h.largestObservedRcvdTime)) + ack.DelayTime = max(0, now.Sub(h.largestObservedRcvdTime)) ack.ECT0 = h.ect0 ack.ECT1 = h.ect1 ack.ECNCE = h.ecnce diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go index c8265a78..3cef8923 100644 --- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go +++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go @@ -245,7 +245,7 @@ func (h *sentPacketHandler) SentPacket( pnSpace := h.getPacketNumberSpace(encLevel) if h.logger.Debug() && pnSpace.history.HasOutstandingPackets() { - for p := utils.Max(0, pnSpace.largestSent+1); p < pn; p++ { + for p := max(0, pnSpace.largestSent+1); p < pn; p++ { h.logger.Debugf("Skipping packet number %d", p) } } @@ -336,7 +336,7 @@ func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.En // don't use the ack delay for Initial and Handshake packets var ackDelay time.Duration if encLevel == protocol.Encryption1RTT { - ackDelay = utils.Min(ack.DelayTime, h.rttStats.MaxAckDelay()) + ackDelay = min(ack.DelayTime, h.rttStats.MaxAckDelay()) } h.rttStats.UpdateRTT(rcvTime.Sub(p.SendTime), ackDelay, rcvTime) if h.logger.Debug() { @@ -354,7 +354,7 @@ func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.En } } - pnSpace.largestAcked = utils.Max(pnSpace.largestAcked, largestAcked) + pnSpace.largestAcked = max(pnSpace.largestAcked, largestAcked) if err := h.detectLostPackets(rcvTime, encLevel); err != nil { return false, err @@ -446,7 +446,7 @@ func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encL for _, p := range h.ackedPackets { if p.LargestAcked != protocol.InvalidPacketNumber && encLevel == protocol.Encryption1RTT { - h.lowestNotConfirmedAcked = utils.Max(h.lowestNotConfirmedAcked, p.LargestAcked+1) + h.lowestNotConfirmedAcked = max(h.lowestNotConfirmedAcked, p.LargestAcked+1) } for _, f := range p.Frames { @@ -607,11 +607,11 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time, encLevel protocol.E pnSpace := h.getPacketNumberSpace(encLevel) pnSpace.lossTime = time.Time{} - maxRTT := float64(utils.Max(h.rttStats.LatestRTT(), h.rttStats.SmoothedRTT())) + maxRTT := float64(max(h.rttStats.LatestRTT(), h.rttStats.SmoothedRTT())) lossDelay := time.Duration(timeThreshold * maxRTT) // Minimum time of granularity before packets are deemed lost. - lossDelay = utils.Max(lossDelay, protocol.TimerGranularity) + lossDelay = max(lossDelay, protocol.TimerGranularity) // Packets sent before this time are deemed lost. lostSendTime := now.Add(-lossDelay) @@ -890,7 +890,7 @@ func (h *sentPacketHandler) ResetForRetry(now time.Time) error { // Otherwise, we don't know which Initial the Retry was sent in response to. if h.ptoCount == 0 { // Don't set the RTT to a value lower than 5ms here. - h.rttStats.UpdateRTT(utils.Max(minRTTAfterRetry, now.Sub(firstPacketSendTime)), 0, now) + h.rttStats.UpdateRTT(max(minRTTAfterRetry, now.Sub(firstPacketSendTime)), 0, now) if h.logger.Debug() { h.logger.Debugf("\tupdated RTT: %s (σ: %s)", h.rttStats.SmoothedRTT(), h.rttStats.MeanDeviation()) } diff --git a/vendor/github.com/quic-go/quic-go/internal/congestion/cubic.go b/vendor/github.com/quic-go/quic-go/internal/congestion/cubic.go index a73cf82a..4e30de65 100644 --- a/vendor/github.com/quic-go/quic-go/internal/congestion/cubic.go +++ b/vendor/github.com/quic-go/quic-go/internal/congestion/cubic.go @@ -5,7 +5,6 @@ import ( "time" "github.com/quic-go/quic-go/internal/protocol" - "github.com/quic-go/quic-go/internal/utils" ) // This cubic implementation is based on the one found in Chromiums's QUIC @@ -187,7 +186,7 @@ func (c *Cubic) CongestionWindowAfterAck( targetCongestionWindow = c.originPointCongestionWindow - deltaCongestionWindow } // Limit the CWND increase to half the acked bytes. - targetCongestionWindow = utils.Min(targetCongestionWindow, currentCongestionWindow+c.ackedBytesCount/2) + targetCongestionWindow = min(targetCongestionWindow, currentCongestionWindow+c.ackedBytesCount/2) // Increase the window by approximately Alpha * 1 MSS of bytes every // time we ack an estimated tcp window of bytes. For small diff --git a/vendor/github.com/quic-go/quic-go/internal/congestion/cubic_sender.go b/vendor/github.com/quic-go/quic-go/internal/congestion/cubic_sender.go index ee558f2d..a1b06ab3 100644 --- a/vendor/github.com/quic-go/quic-go/internal/congestion/cubic_sender.go +++ b/vendor/github.com/quic-go/quic-go/internal/congestion/cubic_sender.go @@ -178,7 +178,7 @@ func (c *cubicSender) OnPacketAcked( priorInFlight protocol.ByteCount, eventTime time.Time, ) { - c.largestAckedPacketNumber = utils.Max(ackedPacketNumber, c.largestAckedPacketNumber) + c.largestAckedPacketNumber = max(ackedPacketNumber, c.largestAckedPacketNumber) if c.InRecovery() { return } @@ -246,7 +246,7 @@ func (c *cubicSender) maybeIncreaseCwnd( c.numAckedPackets = 0 } } else { - c.congestionWindow = utils.Min(c.maxCongestionWindow(), c.cubic.CongestionWindowAfterAck(ackedBytes, c.congestionWindow, c.rttStats.MinRTT(), eventTime)) + c.congestionWindow = min(c.maxCongestionWindow(), c.cubic.CongestionWindowAfterAck(ackedBytes, c.congestionWindow, c.rttStats.MinRTT(), eventTime)) } } diff --git a/vendor/github.com/quic-go/quic-go/internal/congestion/hybrid_slow_start.go b/vendor/github.com/quic-go/quic-go/internal/congestion/hybrid_slow_start.go index b2f7c908..9679d9e4 100644 --- a/vendor/github.com/quic-go/quic-go/internal/congestion/hybrid_slow_start.go +++ b/vendor/github.com/quic-go/quic-go/internal/congestion/hybrid_slow_start.go @@ -4,7 +4,6 @@ import ( "time" "github.com/quic-go/quic-go/internal/protocol" - "github.com/quic-go/quic-go/internal/utils" ) // Note(pwestin): the magic clamping numbers come from the original code in @@ -75,8 +74,8 @@ func (s *HybridSlowStart) ShouldExitSlowStart(latestRTT time.Duration, minRTT ti // Divide minRTT by 8 to get a rtt increase threshold for exiting. minRTTincreaseThresholdUs := int64(minRTT / time.Microsecond >> hybridStartDelayFactorExp) // Ensure the rtt threshold is never less than 2ms or more than 16ms. - minRTTincreaseThresholdUs = utils.Min(minRTTincreaseThresholdUs, hybridStartDelayMaxThresholdUs) - minRTTincreaseThreshold := time.Duration(utils.Max(minRTTincreaseThresholdUs, hybridStartDelayMinThresholdUs)) * time.Microsecond + minRTTincreaseThresholdUs = min(minRTTincreaseThresholdUs, hybridStartDelayMaxThresholdUs) + minRTTincreaseThreshold := time.Duration(max(minRTTincreaseThresholdUs, hybridStartDelayMinThresholdUs)) * time.Microsecond if s.currentMinRTT > (minRTT + minRTTincreaseThreshold) { s.hystartFound = true diff --git a/vendor/github.com/quic-go/quic-go/internal/congestion/pacer.go b/vendor/github.com/quic-go/quic-go/internal/congestion/pacer.go index 94eae8f8..34d3d1d0 100644 --- a/vendor/github.com/quic-go/quic-go/internal/congestion/pacer.go +++ b/vendor/github.com/quic-go/quic-go/internal/congestion/pacer.go @@ -4,7 +4,6 @@ import ( "time" "github.com/quic-go/quic-go/internal/protocol" - "github.com/quic-go/quic-go/internal/utils" ) const maxBurstSizePackets = 10 @@ -52,11 +51,11 @@ func (p *pacer) Budget(now time.Time) protocol.ByteCount { if budget < 0 { // protect against overflows budget = protocol.MaxByteCount } - return utils.Min(p.maxBurstSize(), budget) + return min(p.maxBurstSize(), budget) } func (p *pacer) maxBurstSize() protocol.ByteCount { - return utils.Max( + return max( protocol.ByteCount(uint64((protocol.MinPacingDelay+protocol.TimerGranularity).Nanoseconds())*p.adjustedBandwidth())/1e9, maxBurstSizePackets*p.maxDatagramSize, ) @@ -77,7 +76,7 @@ func (p *pacer) TimeUntilSend() time.Time { if diff%bw > 0 { d++ } - return p.lastSentTime.Add(utils.Max(protocol.MinPacingDelay, time.Duration(d)*time.Nanosecond)) + return p.lastSentTime.Add(max(protocol.MinPacingDelay, time.Duration(d)*time.Nanosecond)) } func (p *pacer) SetMaxDatagramSize(s protocol.ByteCount) { diff --git a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/base_flow_controller.go b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/base_flow_controller.go index f3f24a60..184aad34 100644 --- a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/base_flow_controller.go +++ b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/base_flow_controller.go @@ -107,7 +107,7 @@ func (c *baseFlowController) maybeAdjustWindowSize() { now := time.Now() if now.Sub(c.epochStartTime) < time.Duration(4*fraction*float64(rtt)) { // window is consumed too fast, try to increase the window size - newSize := utils.Min(2*c.receiveWindowSize, c.maxReceiveWindowSize) + newSize := min(2*c.receiveWindowSize, c.maxReceiveWindowSize) if newSize > c.receiveWindowSize && (c.allowWindowIncrease == nil || c.allowWindowIncrease(newSize-c.receiveWindowSize)) { c.receiveWindowSize = newSize } diff --git a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/connection_flow_controller.go b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/connection_flow_controller.go index 13e69d6c..8504cdcf 100644 --- a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/connection_flow_controller.go +++ b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/connection_flow_controller.go @@ -87,7 +87,7 @@ func (c *connectionFlowController) EnsureMinimumWindowSize(inc protocol.ByteCoun c.mutex.Lock() if inc > c.receiveWindowSize { c.logger.Debugf("Increasing receive flow control window for the connection to %d kB, in response to stream flow control window increase", c.receiveWindowSize/(1<<10)) - newSize := utils.Min(inc, c.maxReceiveWindowSize) + newSize := min(inc, c.maxReceiveWindowSize) if delta := newSize - c.receiveWindowSize; delta > 0 && c.allowWindowIncrease(delta) { c.receiveWindowSize = newSize } diff --git a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/stream_flow_controller.go b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/stream_flow_controller.go index 1770a9c8..1a69fb2b 100644 --- a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/stream_flow_controller.go +++ b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/stream_flow_controller.go @@ -123,7 +123,7 @@ func (c *streamFlowController) AddBytesSent(n protocol.ByteCount) { } func (c *streamFlowController) SendWindowSize() protocol.ByteCount { - return utils.Min(c.baseFlowController.sendWindowSize(), c.connection.SendWindowSize()) + return min(c.baseFlowController.sendWindowSize(), c.connection.SendWindowSize()) } func (c *streamFlowController) shouldQueueWindowUpdate() bool { diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/aead.go b/vendor/github.com/quic-go/quic-go/internal/handshake/aead.go index 6aa89fb3..6ab267a3 100644 --- a/vendor/github.com/quic-go/quic-go/internal/handshake/aead.go +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/aead.go @@ -5,7 +5,6 @@ import ( "encoding/binary" "github.com/quic-go/quic-go/internal/protocol" - "github.com/quic-go/quic-go/internal/utils" ) func createAEAD(suite *cipherSuite, trafficSecret []byte, v protocol.VersionNumber) cipher.AEAD { @@ -82,7 +81,7 @@ func (o *longHeaderOpener) Open(dst, src []byte, pn protocol.PacketNumber, ad [] // It uses the nonce provided here and XOR it with the IV. dec, err := o.aead.Open(dst, o.nonceBuf, src, ad) if err == nil { - o.highestRcvdPN = utils.Max(o.highestRcvdPN, pn) + o.highestRcvdPN = max(o.highestRcvdPN, pn) } else { err = ErrDecryptionFailed } diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/crypto_setup.go b/vendor/github.com/quic-go/quic-go/internal/handshake/crypto_setup.go index c5787e86..1e1874a5 100644 --- a/vendor/github.com/quic-go/quic-go/internal/handshake/crypto_setup.go +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/crypto_setup.go @@ -25,11 +25,11 @@ type quicVersionContextKey struct{} var QUICVersionContextKey = &quicVersionContextKey{} -const clientSessionStateRevision = 3 +const clientSessionStateRevision = 4 type cryptoSetup struct { tlsConf *tls.Config - conn *qtls.QUICConn + conn *tls.QUICConn events []Event @@ -93,12 +93,12 @@ func NewCryptoSetupClient( tlsConf = tlsConf.Clone() tlsConf.MinVersion = tls.VersionTLS13 - quicConf := &qtls.QUICConfig{TLSConfig: tlsConf} + quicConf := &tls.QUICConfig{TLSConfig: tlsConf} qtls.SetupConfigForClient(quicConf, cs.marshalDataForSessionState, cs.handleDataFromSessionState) cs.tlsConf = tlsConf cs.allow0RTT = enable0RTT - cs.conn = qtls.QUICClient(quicConf) + cs.conn = tls.QUICClient(quicConf) cs.conn.SetTransportParameters(cs.ourParams.Marshal(protocol.PerspectiveClient)) return cs @@ -127,12 +127,12 @@ func NewCryptoSetupServer( ) cs.allow0RTT = allow0RTT - quicConf := &qtls.QUICConfig{TLSConfig: tlsConf} + quicConf := &tls.QUICConfig{TLSConfig: tlsConf} qtls.SetupConfigForServer(quicConf, cs.allow0RTT, cs.getDataForSessionTicket, cs.handleSessionTicket) addConnToClientHelloInfo(quicConf.TLSConfig, localAddr, remoteAddr) cs.tlsConf = quicConf.TLSConfig - cs.conn = qtls.QUICServer(quicConf) + cs.conn = tls.QUICServer(quicConf) return cs } @@ -264,28 +264,28 @@ func (h *cryptoSetup) handleMessage(data []byte, encLevel protocol.EncryptionLev } } -func (h *cryptoSetup) handleEvent(ev qtls.QUICEvent) (done bool, err error) { +func (h *cryptoSetup) handleEvent(ev tls.QUICEvent) (done bool, err error) { switch ev.Kind { - case qtls.QUICNoEvent: + case tls.QUICNoEvent: return true, nil - case qtls.QUICSetReadSecret: + case tls.QUICSetReadSecret: h.SetReadKey(ev.Level, ev.Suite, ev.Data) return false, nil - case qtls.QUICSetWriteSecret: + case tls.QUICSetWriteSecret: h.SetWriteKey(ev.Level, ev.Suite, ev.Data) return false, nil - case qtls.QUICTransportParameters: + case tls.QUICTransportParameters: return false, h.handleTransportParameters(ev.Data) - case qtls.QUICTransportParametersRequired: + case tls.QUICTransportParametersRequired: h.conn.SetTransportParameters(h.ourParams.Marshal(h.perspective)) return false, nil - case qtls.QUICRejectedEarlyData: + case tls.QUICRejectedEarlyData: h.rejected0RTT() return false, nil - case qtls.QUICWriteData: - h.WriteRecord(ev.Level, ev.Data) + case tls.QUICWriteData: + h.writeRecord(ev.Level, ev.Data) return false, nil - case qtls.QUICHandshakeDone: + case tls.QUICHandshakeDone: h.handshakeComplete() return false, nil default: @@ -313,19 +313,24 @@ func (h *cryptoSetup) handleTransportParameters(data []byte) error { } // must be called after receiving the transport parameters -func (h *cryptoSetup) marshalDataForSessionState() []byte { +func (h *cryptoSetup) marshalDataForSessionState(earlyData bool) []byte { b := make([]byte, 0, 256) b = quicvarint.Append(b, clientSessionStateRevision) b = quicvarint.Append(b, uint64(h.rttStats.SmoothedRTT().Microseconds())) - return h.peerParams.MarshalForSessionTicket(b) + if earlyData { + // only save the transport parameters for 0-RTT enabled session tickets + return h.peerParams.MarshalForSessionTicket(b) + } + return b } -func (h *cryptoSetup) handleDataFromSessionState(data []byte) (allowEarlyData bool) { - tp, err := h.handleDataFromSessionStateImpl(data) +func (h *cryptoSetup) handleDataFromSessionState(data []byte, earlyData bool) (allowEarlyData bool) { + rtt, tp, err := decodeDataFromSessionState(data, earlyData) if err != nil { h.logger.Debugf("Restoring of transport parameters from session ticket failed: %s", err.Error()) return } + h.rttStats.SetInitialRTT(rtt) // The session ticket might have been saved from a connection that allowed 0-RTT, // and therefore contain transport parameters. // Only use them if 0-RTT is actually used on the new connection. @@ -336,25 +341,28 @@ func (h *cryptoSetup) handleDataFromSessionState(data []byte) (allowEarlyData bo return false } -func (h *cryptoSetup) handleDataFromSessionStateImpl(data []byte) (*wire.TransportParameters, error) { +func decodeDataFromSessionState(data []byte, earlyData bool) (time.Duration, *wire.TransportParameters, error) { r := bytes.NewReader(data) ver, err := quicvarint.Read(r) if err != nil { - return nil, err + return 0, nil, err } if ver != clientSessionStateRevision { - return nil, fmt.Errorf("mismatching version. Got %d, expected %d", ver, clientSessionStateRevision) + return 0, nil, fmt.Errorf("mismatching version. Got %d, expected %d", ver, clientSessionStateRevision) } - rtt, err := quicvarint.Read(r) + rttEncoded, err := quicvarint.Read(r) if err != nil { - return nil, err + return 0, nil, err + } + rtt := time.Duration(rttEncoded) * time.Microsecond + if !earlyData { + return rtt, nil, nil } - h.rttStats.SetInitialRTT(time.Duration(rtt) * time.Microsecond) var tp wire.TransportParameters if err := tp.UnmarshalFromSessionTicket(r); err != nil { - return nil, err + return 0, nil, err } - return &tp, nil + return rtt, &tp, nil } func (h *cryptoSetup) getDataForSessionTicket() []byte { @@ -371,7 +379,9 @@ func (h *cryptoSetup) getDataForSessionTicket() []byte { // Due to limitations in crypto/tls, it's only possible to generate a single session ticket per connection. // It is only valid for the server. func (h *cryptoSetup) GetSessionTicket() ([]byte, error) { - if err := qtls.SendSessionTicket(h.conn, h.allow0RTT); err != nil { + if err := h.conn.SendSessionTicket(tls.QUICSessionTicketOptions{ + EarlyData: h.allow0RTT, + }); err != nil { // Session tickets might be disabled by tls.Config.SessionTicketsDisabled. // We can't check h.tlsConfig here, since the actual config might have been obtained from // the GetConfigForClient callback. @@ -383,11 +393,11 @@ func (h *cryptoSetup) GetSessionTicket() ([]byte, error) { return nil, err } ev := h.conn.NextEvent() - if ev.Kind != qtls.QUICWriteData || ev.Level != qtls.QUICEncryptionLevelApplication { + if ev.Kind != tls.QUICWriteData || ev.Level != tls.QUICEncryptionLevelApplication { panic("crypto/tls bug: where's my session ticket?") } ticket := ev.Data - if ev := h.conn.NextEvent(); ev.Kind != qtls.QUICNoEvent { + if ev := h.conn.NextEvent(); ev.Kind != tls.QUICNoEvent { panic("crypto/tls bug: why more than one ticket?") } return ticket, nil @@ -434,12 +444,12 @@ func (h *cryptoSetup) rejected0RTT() { } } -func (h *cryptoSetup) SetReadKey(el qtls.QUICEncryptionLevel, suiteID uint16, trafficSecret []byte) { +func (h *cryptoSetup) SetReadKey(el tls.QUICEncryptionLevel, suiteID uint16, trafficSecret []byte) { suite := getCipherSuite(suiteID) h.mutex.Lock() //nolint:exhaustive // The TLS stack doesn't export Initial keys. switch el { - case qtls.QUICEncryptionLevelEarly: + case tls.QUICEncryptionLevelEarly: if h.perspective == protocol.PerspectiveClient { panic("Received 0-RTT read key for the client") } @@ -451,7 +461,7 @@ func (h *cryptoSetup) SetReadKey(el qtls.QUICEncryptionLevel, suiteID uint16, tr if h.logger.Debug() { h.logger.Debugf("Installed 0-RTT Read keys (using %s)", tls.CipherSuiteName(suite.ID)) } - case qtls.QUICEncryptionLevelHandshake: + case tls.QUICEncryptionLevelHandshake: h.handshakeOpener = newLongHeaderOpener( createAEAD(suite, trafficSecret, h.version), newHeaderProtector(suite, trafficSecret, true, h.version), @@ -459,7 +469,7 @@ func (h *cryptoSetup) SetReadKey(el qtls.QUICEncryptionLevel, suiteID uint16, tr if h.logger.Debug() { h.logger.Debugf("Installed Handshake Read keys (using %s)", tls.CipherSuiteName(suite.ID)) } - case qtls.QUICEncryptionLevelApplication: + case tls.QUICEncryptionLevelApplication: h.aead.SetReadKey(suite, trafficSecret) h.has1RTTOpener = true if h.logger.Debug() { @@ -475,12 +485,12 @@ func (h *cryptoSetup) SetReadKey(el qtls.QUICEncryptionLevel, suiteID uint16, tr } } -func (h *cryptoSetup) SetWriteKey(el qtls.QUICEncryptionLevel, suiteID uint16, trafficSecret []byte) { +func (h *cryptoSetup) SetWriteKey(el tls.QUICEncryptionLevel, suiteID uint16, trafficSecret []byte) { suite := getCipherSuite(suiteID) h.mutex.Lock() //nolint:exhaustive // The TLS stack doesn't export Initial keys. switch el { - case qtls.QUICEncryptionLevelEarly: + case tls.QUICEncryptionLevelEarly: if h.perspective == protocol.PerspectiveServer { panic("Received 0-RTT write key for the server") } @@ -497,7 +507,7 @@ func (h *cryptoSetup) SetWriteKey(el qtls.QUICEncryptionLevel, suiteID uint16, t } // don't set used0RTT here. 0-RTT might still get rejected. return - case qtls.QUICEncryptionLevelHandshake: + case tls.QUICEncryptionLevelHandshake: h.handshakeSealer = newLongHeaderSealer( createAEAD(suite, trafficSecret, h.version), newHeaderProtector(suite, trafficSecret, true, h.version), @@ -505,7 +515,7 @@ func (h *cryptoSetup) SetWriteKey(el qtls.QUICEncryptionLevel, suiteID uint16, t if h.logger.Debug() { h.logger.Debugf("Installed Handshake Write keys (using %s)", tls.CipherSuiteName(suite.ID)) } - case qtls.QUICEncryptionLevelApplication: + case tls.QUICEncryptionLevelApplication: h.aead.SetWriteKey(suite, trafficSecret) h.has1RTTSealer = true if h.logger.Debug() { @@ -529,15 +539,15 @@ func (h *cryptoSetup) SetWriteKey(el qtls.QUICEncryptionLevel, suiteID uint16, t } } -// WriteRecord is called when TLS writes data -func (h *cryptoSetup) WriteRecord(encLevel qtls.QUICEncryptionLevel, p []byte) { +// writeRecord is called when TLS writes data +func (h *cryptoSetup) writeRecord(encLevel tls.QUICEncryptionLevel, p []byte) { //nolint:exhaustive // handshake records can only be written for Initial and Handshake. switch encLevel { - case qtls.QUICEncryptionLevelInitial: + case tls.QUICEncryptionLevelInitial: h.events = append(h.events, Event{Kind: EventWriteInitialData, Data: p}) - case qtls.QUICEncryptionLevelHandshake: + case tls.QUICEncryptionLevelHandshake: h.events = append(h.events, Event{Kind: EventWriteHandshakeData, Data: p}) - case qtls.QUICEncryptionLevelApplication: + case tls.QUICEncryptionLevelApplication: panic("unexpected write") default: panic(fmt.Sprintf("unexpected write encryption level: %s", encLevel)) @@ -684,7 +694,7 @@ func (h *cryptoSetup) ConnectionState() ConnectionState { func wrapError(err error) error { // alert 80 is an internal error - if alertErr := qtls.AlertError(0); errors.As(err, &alertErr) && alertErr != 80 { + if alertErr := tls.AlertError(0); errors.As(err, &alertErr) && alertErr != 80 { return qerr.NewLocalCryptoError(uint8(alertErr), err) } return &qerr.TransportError{ErrorCode: qerr.InternalError, ErrorMessage: err.Error()} diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/updatable_aead.go b/vendor/github.com/quic-go/quic-go/internal/handshake/updatable_aead.go index a583f277..08b943f4 100644 --- a/vendor/github.com/quic-go/quic-go/internal/handshake/updatable_aead.go +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/updatable_aead.go @@ -172,7 +172,7 @@ func (a *updatableAEAD) Open(dst, src []byte, rcvTime time.Time, pn protocol.Pac } } if err == nil { - a.highestRcvdPN = utils.Max(a.highestRcvdPN, pn) + a.highestRcvdPN = max(a.highestRcvdPN, pn) } return dec, err } diff --git a/vendor/github.com/quic-go/quic-go/internal/protocol/params.go b/vendor/github.com/quic-go/quic-go/internal/protocol/params.go index 28b6da7c..487cbc06 100644 --- a/vendor/github.com/quic-go/quic-go/internal/protocol/params.go +++ b/vendor/github.com/quic-go/quic-go/internal/protocol/params.go @@ -129,9 +129,6 @@ const MaxPostHandshakeCryptoFrameSize = 1000 // but must ensure that a maximum size ACK frame fits into one packet. const MaxAckFrameSize ByteCount = 1000 -// DatagramRcvQueueLen is the length of the receive queue for DATAGRAM frames (RFC 9221) -const DatagramRcvQueueLen = 128 - // MaxNumAckRanges is the maximum number of ACK ranges that we send in an ACK frame. // It also serves as a limit for the packet history. // If at any point we keep track of more ranges, old ranges are discarded. diff --git a/vendor/github.com/quic-go/quic-go/internal/qerr/error_codes.go b/vendor/github.com/quic-go/quic-go/internal/qerr/error_codes.go index a037acd2..00361308 100644 --- a/vendor/github.com/quic-go/quic-go/internal/qerr/error_codes.go +++ b/vendor/github.com/quic-go/quic-go/internal/qerr/error_codes.go @@ -1,9 +1,8 @@ package qerr import ( + "crypto/tls" "fmt" - - "github.com/quic-go/quic-go/internal/qtls" ) // TransportErrorCode is a QUIC transport error. @@ -40,7 +39,7 @@ func (e TransportErrorCode) Message() string { if !e.IsCryptoError() { return "" } - return qtls.AlertError(e - 0x100).Error() + return tls.AlertError(e - 0x100).Error() } func (e TransportErrorCode) String() string { diff --git a/vendor/github.com/quic-go/quic-go/internal/qtls/cipher_suite_go121.go b/vendor/github.com/quic-go/quic-go/internal/qtls/cipher_suite.go similarity index 99% rename from vendor/github.com/quic-go/quic-go/internal/qtls/cipher_suite_go121.go rename to vendor/github.com/quic-go/quic-go/internal/qtls/cipher_suite.go index aa8c768f..16558f8b 100644 --- a/vendor/github.com/quic-go/quic-go/internal/qtls/cipher_suite_go121.go +++ b/vendor/github.com/quic-go/quic-go/internal/qtls/cipher_suite.go @@ -1,5 +1,3 @@ -//go:build go1.21 - package qtls import ( diff --git a/vendor/github.com/quic-go/quic-go/internal/qtls/client_session_cache.go b/vendor/github.com/quic-go/quic-go/internal/qtls/client_session_cache.go index 336d6035..d81eb8c3 100644 --- a/vendor/github.com/quic-go/quic-go/internal/qtls/client_session_cache.go +++ b/vendor/github.com/quic-go/quic-go/internal/qtls/client_session_cache.go @@ -7,8 +7,8 @@ import ( ) type clientSessionCache struct { - getData func() []byte - setData func([]byte) (allowEarlyData bool) + getData func(earlyData bool) []byte + setData func(data []byte, earlyData bool) (allowEarlyData bool) wrapped tls.ClientSessionCache } @@ -24,7 +24,7 @@ func (c clientSessionCache) Put(key string, cs *tls.ClientSessionState) { c.wrapped.Put(key, cs) return } - state.Extra = append(state.Extra, addExtraPrefix(c.getData())) + state.Extra = append(state.Extra, addExtraPrefix(c.getData(state.EarlyData))) newCS, err := tls.NewResumptionState(ticket, state) if err != nil { // It's not clear why this would error. Just save the original state. @@ -46,12 +46,13 @@ func (c clientSessionCache) Get(key string) (*tls.ClientSessionState, bool) { c.wrapped.Put(key, nil) return nil, false } - var earlyData bool // restore QUIC transport parameters and RTT stored in state.Extra if extra := findExtraData(state.Extra); extra != nil { - earlyData = c.setData(extra) + earlyData := c.setData(extra, state.EarlyData) + if state.EarlyData { + state.EarlyData = earlyData + } } - state.EarlyData = earlyData session, err := tls.NewResumptionState(ticket, state) if err != nil { // It's not clear why this would error. diff --git a/vendor/github.com/quic-go/quic-go/internal/qtls/go120.go b/vendor/github.com/quic-go/quic-go/internal/qtls/go120.go deleted file mode 100644 index 7e7eee1e..00000000 --- a/vendor/github.com/quic-go/quic-go/internal/qtls/go120.go +++ /dev/null @@ -1,147 +0,0 @@ -//go:build go1.20 && !go1.21 - -package qtls - -import ( - "crypto/tls" - "fmt" - "unsafe" - - "github.com/quic-go/quic-go/internal/protocol" - - "github.com/quic-go/qtls-go1-20" -) - -type ( - QUICConn = qtls.QUICConn - QUICConfig = qtls.QUICConfig - QUICEvent = qtls.QUICEvent - QUICEventKind = qtls.QUICEventKind - QUICEncryptionLevel = qtls.QUICEncryptionLevel - AlertError = qtls.AlertError -) - -const ( - QUICEncryptionLevelInitial = qtls.QUICEncryptionLevelInitial - QUICEncryptionLevelEarly = qtls.QUICEncryptionLevelEarly - QUICEncryptionLevelHandshake = qtls.QUICEncryptionLevelHandshake - QUICEncryptionLevelApplication = qtls.QUICEncryptionLevelApplication -) - -const ( - QUICNoEvent = qtls.QUICNoEvent - QUICSetReadSecret = qtls.QUICSetReadSecret - QUICSetWriteSecret = qtls.QUICSetWriteSecret - QUICWriteData = qtls.QUICWriteData - QUICTransportParameters = qtls.QUICTransportParameters - QUICTransportParametersRequired = qtls.QUICTransportParametersRequired - QUICRejectedEarlyData = qtls.QUICRejectedEarlyData - QUICHandshakeDone = qtls.QUICHandshakeDone -) - -func SetupConfigForServer(conf *QUICConfig, enable0RTT bool, getDataForSessionTicket func() []byte, handleSessionTicket func([]byte, bool) bool) { - qtls.InitSessionTicketKeys(conf.TLSConfig) - conf.TLSConfig = conf.TLSConfig.Clone() - conf.TLSConfig.MinVersion = tls.VersionTLS13 - conf.ExtraConfig = &qtls.ExtraConfig{ - Enable0RTT: enable0RTT, - Accept0RTT: func(data []byte) bool { - return handleSessionTicket(data, true) - }, - GetAppDataForSessionTicket: getDataForSessionTicket, - } -} - -func SetupConfigForClient(conf *QUICConfig, getDataForSessionState func() []byte, setDataFromSessionState func([]byte) bool) { - conf.ExtraConfig = &qtls.ExtraConfig{ - GetAppDataForSessionState: getDataForSessionState, - SetAppDataFromSessionState: setDataFromSessionState, - } -} - -func QUICServer(config *QUICConfig) *QUICConn { - return qtls.QUICServer(config) -} - -func QUICClient(config *QUICConfig) *QUICConn { - return qtls.QUICClient(config) -} - -func ToTLSEncryptionLevel(e protocol.EncryptionLevel) qtls.QUICEncryptionLevel { - switch e { - case protocol.EncryptionInitial: - return qtls.QUICEncryptionLevelInitial - case protocol.EncryptionHandshake: - return qtls.QUICEncryptionLevelHandshake - case protocol.Encryption1RTT: - return qtls.QUICEncryptionLevelApplication - case protocol.Encryption0RTT: - return qtls.QUICEncryptionLevelEarly - default: - panic(fmt.Sprintf("unexpected encryption level: %s", e)) - } -} - -func FromTLSEncryptionLevel(e qtls.QUICEncryptionLevel) protocol.EncryptionLevel { - switch e { - case qtls.QUICEncryptionLevelInitial: - return protocol.EncryptionInitial - case qtls.QUICEncryptionLevelHandshake: - return protocol.EncryptionHandshake - case qtls.QUICEncryptionLevelApplication: - return protocol.Encryption1RTT - case qtls.QUICEncryptionLevelEarly: - return protocol.Encryption0RTT - default: - panic(fmt.Sprintf("unexpect encryption level: %s", e)) - } -} - -//go:linkname cipherSuitesTLS13 github.com/quic-go/qtls-go1-20.cipherSuitesTLS13 -var cipherSuitesTLS13 []unsafe.Pointer - -//go:linkname defaultCipherSuitesTLS13 github.com/quic-go/qtls-go1-20.defaultCipherSuitesTLS13 -var defaultCipherSuitesTLS13 []uint16 - -//go:linkname defaultCipherSuitesTLS13NoAES github.com/quic-go/qtls-go1-20.defaultCipherSuitesTLS13NoAES -var defaultCipherSuitesTLS13NoAES []uint16 - -var cipherSuitesModified bool - -// SetCipherSuite modifies the cipherSuiteTLS13 slice of cipher suites inside qtls -// such that it only contains the cipher suite with the chosen id. -// The reset function returned resets them back to the original value. -func SetCipherSuite(id uint16) (reset func()) { - if cipherSuitesModified { - panic("cipher suites modified multiple times without resetting") - } - cipherSuitesModified = true - - origCipherSuitesTLS13 := append([]unsafe.Pointer{}, cipherSuitesTLS13...) - origDefaultCipherSuitesTLS13 := append([]uint16{}, defaultCipherSuitesTLS13...) - origDefaultCipherSuitesTLS13NoAES := append([]uint16{}, defaultCipherSuitesTLS13NoAES...) - // The order is given by the order of the slice elements in cipherSuitesTLS13 in qtls. - switch id { - case tls.TLS_AES_128_GCM_SHA256: - cipherSuitesTLS13 = cipherSuitesTLS13[:1] - case tls.TLS_CHACHA20_POLY1305_SHA256: - cipherSuitesTLS13 = cipherSuitesTLS13[1:2] - case tls.TLS_AES_256_GCM_SHA384: - cipherSuitesTLS13 = cipherSuitesTLS13[2:] - default: - panic(fmt.Sprintf("unexpected cipher suite: %d", id)) - } - defaultCipherSuitesTLS13 = []uint16{id} - defaultCipherSuitesTLS13NoAES = []uint16{id} - - return func() { - cipherSuitesTLS13 = origCipherSuitesTLS13 - defaultCipherSuitesTLS13 = origDefaultCipherSuitesTLS13 - defaultCipherSuitesTLS13NoAES = origDefaultCipherSuitesTLS13NoAES - cipherSuitesModified = false - } -} - -func SendSessionTicket(c *QUICConn, allow0RTT bool) error { - return c.SendSessionTicket(allow0RTT) -} diff --git a/vendor/github.com/quic-go/quic-go/internal/qtls/go_oldversion.go b/vendor/github.com/quic-go/quic-go/internal/qtls/go_oldversion.go deleted file mode 100644 index 0fca80a3..00000000 --- a/vendor/github.com/quic-go/quic-go/internal/qtls/go_oldversion.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build !go1.20 - -package qtls - -var _ int = "The version of quic-go you're using can't be built using outdated Go versions. For more details, please see https://github.com/quic-go/quic-go/wiki/quic-go-and-Go-versions." diff --git a/vendor/github.com/quic-go/quic-go/internal/qtls/go121.go b/vendor/github.com/quic-go/quic-go/internal/qtls/qtls.go similarity index 66% rename from vendor/github.com/quic-go/quic-go/internal/qtls/go121.go rename to vendor/github.com/quic-go/quic-go/internal/qtls/qtls.go index 35a52ce0..ebcd9d4d 100644 --- a/vendor/github.com/quic-go/quic-go/internal/qtls/go121.go +++ b/vendor/github.com/quic-go/quic-go/internal/qtls/qtls.go @@ -1,5 +1,3 @@ -//go:build go1.21 - package qtls import ( @@ -10,38 +8,7 @@ import ( "github.com/quic-go/quic-go/internal/protocol" ) -type ( - QUICConn = tls.QUICConn - QUICConfig = tls.QUICConfig - QUICEvent = tls.QUICEvent - QUICEventKind = tls.QUICEventKind - QUICEncryptionLevel = tls.QUICEncryptionLevel - QUICSessionTicketOptions = tls.QUICSessionTicketOptions - AlertError = tls.AlertError -) - -const ( - QUICEncryptionLevelInitial = tls.QUICEncryptionLevelInitial - QUICEncryptionLevelEarly = tls.QUICEncryptionLevelEarly - QUICEncryptionLevelHandshake = tls.QUICEncryptionLevelHandshake - QUICEncryptionLevelApplication = tls.QUICEncryptionLevelApplication -) - -const ( - QUICNoEvent = tls.QUICNoEvent - QUICSetReadSecret = tls.QUICSetReadSecret - QUICSetWriteSecret = tls.QUICSetWriteSecret - QUICWriteData = tls.QUICWriteData - QUICTransportParameters = tls.QUICTransportParameters - QUICTransportParametersRequired = tls.QUICTransportParametersRequired - QUICRejectedEarlyData = tls.QUICRejectedEarlyData - QUICHandshakeDone = tls.QUICHandshakeDone -) - -func QUICServer(config *QUICConfig) *QUICConn { return tls.QUICServer(config) } -func QUICClient(config *QUICConfig) *QUICConn { return tls.QUICClient(config) } - -func SetupConfigForServer(qconf *QUICConfig, _ bool, getData func() []byte, handleSessionTicket func([]byte, bool) bool) { +func SetupConfigForServer(qconf *tls.QUICConfig, _ bool, getData func() []byte, handleSessionTicket func([]byte, bool) bool) { conf := qconf.TLSConfig // Workaround for https://github.com/golang/go/issues/60506. @@ -93,7 +60,11 @@ func SetupConfigForServer(qconf *QUICConfig, _ bool, getData func() []byte, hand } } -func SetupConfigForClient(qconf *QUICConfig, getData func() []byte, setData func([]byte) bool) { +func SetupConfigForClient( + qconf *tls.QUICConfig, + getData func(earlyData bool) []byte, + setData func(data []byte, earlyData bool) (allowEarlyData bool), +) { conf := qconf.TLSConfig if conf.ClientSessionCache != nil { origCache := conf.ClientSessionCache @@ -151,9 +122,3 @@ func findExtraData(extras [][]byte) []byte { } return nil } - -func SendSessionTicket(c *QUICConn, allow0RTT bool) error { - return c.SendSessionTicket(tls.QUICSessionTicketOptions{ - EarlyData: allow0RTT, - }) -} diff --git a/vendor/github.com/quic-go/quic-go/internal/utils/minmax.go b/vendor/github.com/quic-go/quic-go/internal/utils/minmax.go index d191f751..6884ef40 100644 --- a/vendor/github.com/quic-go/quic-go/internal/utils/minmax.go +++ b/vendor/github.com/quic-go/quic-go/internal/utils/minmax.go @@ -3,27 +3,11 @@ package utils import ( "math" "time" - - "golang.org/x/exp/constraints" ) // InfDuration is a duration of infinite length const InfDuration = time.Duration(math.MaxInt64) -func Max[T constraints.Ordered](a, b T) T { - if a < b { - return b - } - return a -} - -func Min[T constraints.Ordered](a, b T) T { - if a < b { - return a - } - return b -} - // MinNonZeroDuration return the minimum duration that's not zero. func MinNonZeroDuration(a, b time.Duration) time.Duration { if a == 0 { @@ -32,15 +16,7 @@ func MinNonZeroDuration(a, b time.Duration) time.Duration { if b == 0 { return a } - return Min(a, b) -} - -// AbsDuration returns the absolute value of a time duration -func AbsDuration(d time.Duration) time.Duration { - if d >= 0 { - return d - } - return -d + return min(a, b) } // MinTime returns the earlier time diff --git a/vendor/github.com/quic-go/quic-go/internal/utils/ringbuffer/ringbuffer.go b/vendor/github.com/quic-go/quic-go/internal/utils/ringbuffer/ringbuffer.go index 81a5ad44..f9b2c797 100644 --- a/vendor/github.com/quic-go/quic-go/internal/utils/ringbuffer/ringbuffer.go +++ b/vendor/github.com/quic-go/quic-go/internal/utils/ringbuffer/ringbuffer.go @@ -8,7 +8,7 @@ type RingBuffer[T any] struct { full bool } -// Init preallocs a buffer with a certain size. +// Init preallocates a buffer with a certain size. func (r *RingBuffer[T]) Init(size int) { r.ring = make([]T, size) } @@ -62,6 +62,16 @@ func (r *RingBuffer[T]) PopFront() T { return t } +// PeekFront returns the next element. +// It must not be called when the buffer is empty, that means that +// callers might need to check if there are elements in the buffer first. +func (r *RingBuffer[T]) PeekFront() T { + if r.Empty() { + panic("github.com/quic-go/quic-go/internal/utils/ringbuffer: peek from an empty queue") + } + return r.ring[r.headPos] +} + // Grow the maximum size of the queue. // This method assume the queue is full. func (r *RingBuffer[T]) grow() { diff --git a/vendor/github.com/quic-go/quic-go/internal/utils/rtt_stats.go b/vendor/github.com/quic-go/quic-go/internal/utils/rtt_stats.go index 2cd9a191..463b9542 100644 --- a/vendor/github.com/quic-go/quic-go/internal/utils/rtt_stats.go +++ b/vendor/github.com/quic-go/quic-go/internal/utils/rtt_stats.go @@ -55,7 +55,7 @@ func (r *RTTStats) PTO(includeMaxAckDelay bool) time.Duration { if r.SmoothedRTT() == 0 { return 2 * defaultInitialRTT } - pto := r.SmoothedRTT() + Max(4*r.MeanDeviation(), protocol.TimerGranularity) + pto := r.SmoothedRTT() + max(4*r.MeanDeviation(), protocol.TimerGranularity) if includeMaxAckDelay { pto += r.MaxAckDelay() } @@ -90,7 +90,7 @@ func (r *RTTStats) UpdateRTT(sendDelta, ackDelay time.Duration, now time.Time) { r.smoothedRTT = sample r.meanDeviation = sample / 2 } else { - r.meanDeviation = time.Duration(oneMinusBeta*float32(r.meanDeviation/time.Microsecond)+rttBeta*float32(AbsDuration(r.smoothedRTT-sample)/time.Microsecond)) * time.Microsecond + r.meanDeviation = time.Duration(oneMinusBeta*float32(r.meanDeviation/time.Microsecond)+rttBeta*float32((r.smoothedRTT-sample).Abs()/time.Microsecond)) * time.Microsecond r.smoothedRTT = time.Duration((float32(r.smoothedRTT/time.Microsecond)*oneMinusAlpha)+(float32(sample/time.Microsecond)*rttAlpha)) * time.Microsecond } } @@ -126,6 +126,6 @@ func (r *RTTStats) OnConnectionMigration() { // is larger. The mean deviation is increased to the most recent deviation if // it's larger. func (r *RTTStats) ExpireSmoothedMetrics() { - r.meanDeviation = Max(r.meanDeviation, AbsDuration(r.smoothedRTT-r.latestRTT)) - r.smoothedRTT = Max(r.smoothedRTT, r.latestRTT) + r.meanDeviation = max(r.meanDeviation, (r.smoothedRTT - r.latestRTT).Abs()) + r.smoothedRTT = max(r.smoothedRTT, r.latestRTT) } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go index 9b23cc25..9ce98aee 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go @@ -37,7 +37,7 @@ func parseAckFrame(frame *AckFrame, r *bytes.Reader, typ uint64, ackDelayExponen delayTime := time.Duration(delay*1< maxDataLen { s.nextFrame = wire.GetStreamFrame() s.nextFrame.StreamID = s.streamID @@ -309,7 +309,7 @@ func (s *sendStream) popNewStreamFrameWithoutBuffer(f *wire.StreamFrame, maxByte if maxDataLen == 0 { // a STREAM frame must have at least one byte of data return s.dataForWriting != nil || s.nextFrame != nil || s.finishedWriting } - s.getDataForWriting(f, utils.Min(maxDataLen, sendWindow)) + s.getDataForWriting(f, min(maxDataLen, sendWindow)) return s.dataForWriting != nil || s.nextFrame != nil || s.finishedWriting } diff --git a/vendor/github.com/quic-go/quic-go/token_store.go b/vendor/github.com/quic-go/quic-go/token_store.go index 00460e50..a5c1c185 100644 --- a/vendor/github.com/quic-go/quic-go/token_store.go +++ b/vendor/github.com/quic-go/quic-go/token_store.go @@ -3,7 +3,6 @@ package quic import ( "sync" - "github.com/quic-go/quic-go/internal/utils" list "github.com/quic-go/quic-go/internal/utils/linkedlist" ) @@ -20,14 +19,14 @@ func newSingleOriginTokenStore(size int) *singleOriginTokenStore { func (s *singleOriginTokenStore) Add(token *ClientToken) { s.tokens[s.p] = token s.p = s.index(s.p + 1) - s.len = utils.Min(s.len+1, len(s.tokens)) + s.len = min(s.len+1, len(s.tokens)) } func (s *singleOriginTokenStore) Pop() *ClientToken { s.p = s.index(s.p - 1) token := s.tokens[s.p] s.tokens[s.p] = nil - s.len = utils.Max(s.len-1, 0) + s.len = max(s.len-1, 0) return token } diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1.go deleted file mode 100644 index 2492f796..00000000 --- a/vendor/golang.org/x/crypto/cryptobyte/asn1.go +++ /dev/null @@ -1,825 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cryptobyte - -import ( - encoding_asn1 "encoding/asn1" - "fmt" - "math/big" - "reflect" - "time" - - "golang.org/x/crypto/cryptobyte/asn1" -) - -// This file contains ASN.1-related methods for String and Builder. - -// Builder - -// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER. -func (b *Builder) AddASN1Int64(v int64) { - b.addASN1Signed(asn1.INTEGER, v) -} - -// AddASN1Int64WithTag appends a DER-encoded ASN.1 INTEGER with the -// given tag. -func (b *Builder) AddASN1Int64WithTag(v int64, tag asn1.Tag) { - b.addASN1Signed(tag, v) -} - -// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION. -func (b *Builder) AddASN1Enum(v int64) { - b.addASN1Signed(asn1.ENUM, v) -} - -func (b *Builder) addASN1Signed(tag asn1.Tag, v int64) { - b.AddASN1(tag, func(c *Builder) { - length := 1 - for i := v; i >= 0x80 || i < -0x80; i >>= 8 { - length++ - } - - for ; length > 0; length-- { - i := v >> uint((length-1)*8) & 0xff - c.AddUint8(uint8(i)) - } - }) -} - -// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER. -func (b *Builder) AddASN1Uint64(v uint64) { - b.AddASN1(asn1.INTEGER, func(c *Builder) { - length := 1 - for i := v; i >= 0x80; i >>= 8 { - length++ - } - - for ; length > 0; length-- { - i := v >> uint((length-1)*8) & 0xff - c.AddUint8(uint8(i)) - } - }) -} - -// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER. -func (b *Builder) AddASN1BigInt(n *big.Int) { - if b.err != nil { - return - } - - b.AddASN1(asn1.INTEGER, func(c *Builder) { - if n.Sign() < 0 { - // A negative number has to be converted to two's-complement form. So we - // invert and subtract 1. If the most-significant-bit isn't set then - // we'll need to pad the beginning with 0xff in order to keep the number - // negative. - nMinus1 := new(big.Int).Neg(n) - nMinus1.Sub(nMinus1, bigOne) - bytes := nMinus1.Bytes() - for i := range bytes { - bytes[i] ^= 0xff - } - if len(bytes) == 0 || bytes[0]&0x80 == 0 { - c.add(0xff) - } - c.add(bytes...) - } else if n.Sign() == 0 { - c.add(0) - } else { - bytes := n.Bytes() - if bytes[0]&0x80 != 0 { - c.add(0) - } - c.add(bytes...) - } - }) -} - -// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING. -func (b *Builder) AddASN1OctetString(bytes []byte) { - b.AddASN1(asn1.OCTET_STRING, func(c *Builder) { - c.AddBytes(bytes) - }) -} - -const generalizedTimeFormatStr = "20060102150405Z0700" - -// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME. -func (b *Builder) AddASN1GeneralizedTime(t time.Time) { - if t.Year() < 0 || t.Year() > 9999 { - b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t) - return - } - b.AddASN1(asn1.GeneralizedTime, func(c *Builder) { - c.AddBytes([]byte(t.Format(generalizedTimeFormatStr))) - }) -} - -// AddASN1UTCTime appends a DER-encoded ASN.1 UTCTime. -func (b *Builder) AddASN1UTCTime(t time.Time) { - b.AddASN1(asn1.UTCTime, func(c *Builder) { - // As utilized by the X.509 profile, UTCTime can only - // represent the years 1950 through 2049. - if t.Year() < 1950 || t.Year() >= 2050 { - b.err = fmt.Errorf("cryptobyte: cannot represent %v as a UTCTime", t) - return - } - c.AddBytes([]byte(t.Format(defaultUTCTimeFormatStr))) - }) -} - -// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not -// support BIT STRINGs that are not a whole number of bytes. -func (b *Builder) AddASN1BitString(data []byte) { - b.AddASN1(asn1.BIT_STRING, func(b *Builder) { - b.AddUint8(0) - b.AddBytes(data) - }) -} - -func (b *Builder) addBase128Int(n int64) { - var length int - if n == 0 { - length = 1 - } else { - for i := n; i > 0; i >>= 7 { - length++ - } - } - - for i := length - 1; i >= 0; i-- { - o := byte(n >> uint(i*7)) - o &= 0x7f - if i != 0 { - o |= 0x80 - } - - b.add(o) - } -} - -func isValidOID(oid encoding_asn1.ObjectIdentifier) bool { - if len(oid) < 2 { - return false - } - - if oid[0] > 2 || (oid[0] <= 1 && oid[1] >= 40) { - return false - } - - for _, v := range oid { - if v < 0 { - return false - } - } - - return true -} - -func (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier) { - b.AddASN1(asn1.OBJECT_IDENTIFIER, func(b *Builder) { - if !isValidOID(oid) { - b.err = fmt.Errorf("cryptobyte: invalid OID: %v", oid) - return - } - - b.addBase128Int(int64(oid[0])*40 + int64(oid[1])) - for _, v := range oid[2:] { - b.addBase128Int(int64(v)) - } - }) -} - -func (b *Builder) AddASN1Boolean(v bool) { - b.AddASN1(asn1.BOOLEAN, func(b *Builder) { - if v { - b.AddUint8(0xff) - } else { - b.AddUint8(0) - } - }) -} - -func (b *Builder) AddASN1NULL() { - b.add(uint8(asn1.NULL), 0) -} - -// MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if -// successful or records an error if one occurred. -func (b *Builder) MarshalASN1(v interface{}) { - // NOTE(martinkr): This is somewhat of a hack to allow propagation of - // encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a - // value embedded into a struct, its tag information is lost. - if b.err != nil { - return - } - bytes, err := encoding_asn1.Marshal(v) - if err != nil { - b.err = err - return - } - b.AddBytes(bytes) -} - -// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag. -// Tags greater than 30 are not supported and result in an error (i.e. -// low-tag-number form only). The child builder passed to the -// BuilderContinuation can be used to build the content of the ASN.1 object. -func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { - if b.err != nil { - return - } - // Identifiers with the low five bits set indicate high-tag-number format - // (two or more octets), which we don't support. - if tag&0x1f == 0x1f { - b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag) - return - } - b.AddUint8(uint8(tag)) - b.addLengthPrefixed(1, true, f) -} - -// String - -// ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean -// representation into out and advances. It reports whether the read -// was successful. -func (s *String) ReadASN1Boolean(out *bool) bool { - var bytes String - if !s.ReadASN1(&bytes, asn1.BOOLEAN) || len(bytes) != 1 { - return false - } - - switch bytes[0] { - case 0: - *out = false - case 0xff: - *out = true - default: - return false - } - - return true -} - -// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does -// not point to an integer, to a big.Int, or to a []byte it panics. Only -// positive and zero values can be decoded into []byte, and they are returned as -// big-endian binary values that share memory with s. Positive values will have -// no leading zeroes, and zero will be returned as a single zero byte. -// ReadASN1Integer reports whether the read was successful. -func (s *String) ReadASN1Integer(out interface{}) bool { - switch out := out.(type) { - case *int, *int8, *int16, *int32, *int64: - var i int64 - if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) { - return false - } - reflect.ValueOf(out).Elem().SetInt(i) - return true - case *uint, *uint8, *uint16, *uint32, *uint64: - var u uint64 - if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) { - return false - } - reflect.ValueOf(out).Elem().SetUint(u) - return true - case *big.Int: - return s.readASN1BigInt(out) - case *[]byte: - return s.readASN1Bytes(out) - default: - panic("out does not point to an integer type") - } -} - -func checkASN1Integer(bytes []byte) bool { - if len(bytes) == 0 { - // An INTEGER is encoded with at least one octet. - return false - } - if len(bytes) == 1 { - return true - } - if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 { - // Value is not minimally encoded. - return false - } - return true -} - -var bigOne = big.NewInt(1) - -func (s *String) readASN1BigInt(out *big.Int) bool { - var bytes String - if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { - return false - } - if bytes[0]&0x80 == 0x80 { - // Negative number. - neg := make([]byte, len(bytes)) - for i, b := range bytes { - neg[i] = ^b - } - out.SetBytes(neg) - out.Add(out, bigOne) - out.Neg(out) - } else { - out.SetBytes(bytes) - } - return true -} - -func (s *String) readASN1Bytes(out *[]byte) bool { - var bytes String - if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { - return false - } - if bytes[0]&0x80 == 0x80 { - return false - } - for len(bytes) > 1 && bytes[0] == 0 { - bytes = bytes[1:] - } - *out = bytes - return true -} - -func (s *String) readASN1Int64(out *int64) bool { - var bytes String - if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) { - return false - } - return true -} - -func asn1Signed(out *int64, n []byte) bool { - length := len(n) - if length > 8 { - return false - } - for i := 0; i < length; i++ { - *out <<= 8 - *out |= int64(n[i]) - } - // Shift up and down in order to sign extend the result. - *out <<= 64 - uint8(length)*8 - *out >>= 64 - uint8(length)*8 - return true -} - -func (s *String) readASN1Uint64(out *uint64) bool { - var bytes String - if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) { - return false - } - return true -} - -func asn1Unsigned(out *uint64, n []byte) bool { - length := len(n) - if length > 9 || length == 9 && n[0] != 0 { - // Too large for uint64. - return false - } - if n[0]&0x80 != 0 { - // Negative number. - return false - } - for i := 0; i < length; i++ { - *out <<= 8 - *out |= uint64(n[i]) - } - return true -} - -// ReadASN1Int64WithTag decodes an ASN.1 INTEGER with the given tag into out -// and advances. It reports whether the read was successful and resulted in a -// value that can be represented in an int64. -func (s *String) ReadASN1Int64WithTag(out *int64, tag asn1.Tag) bool { - var bytes String - return s.ReadASN1(&bytes, tag) && checkASN1Integer(bytes) && asn1Signed(out, bytes) -} - -// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It reports -// whether the read was successful. -func (s *String) ReadASN1Enum(out *int) bool { - var bytes String - var i int64 - if !s.ReadASN1(&bytes, asn1.ENUM) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) { - return false - } - if int64(int(i)) != i { - return false - } - *out = int(i) - return true -} - -func (s *String) readBase128Int(out *int) bool { - ret := 0 - for i := 0; len(*s) > 0; i++ { - if i == 5 { - return false - } - // Avoid overflowing int on a 32-bit platform. - // We don't want different behavior based on the architecture. - if ret >= 1<<(31-7) { - return false - } - ret <<= 7 - b := s.read(1)[0] - - // ITU-T X.690, section 8.19.2: - // The subidentifier shall be encoded in the fewest possible octets, - // that is, the leading octet of the subidentifier shall not have the value 0x80. - if i == 0 && b == 0x80 { - return false - } - - ret |= int(b & 0x7f) - if b&0x80 == 0 { - *out = ret - return true - } - } - return false // truncated -} - -// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and -// advances. It reports whether the read was successful. -func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool { - var bytes String - if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 { - return false - } - - // In the worst case, we get two elements from the first byte (which is - // encoded differently) and then every varint is a single byte long. - components := make([]int, len(bytes)+1) - - // The first varint is 40*value1 + value2: - // According to this packing, value1 can take the values 0, 1 and 2 only. - // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, - // then there are no restrictions on value2. - var v int - if !bytes.readBase128Int(&v) { - return false - } - if v < 80 { - components[0] = v / 40 - components[1] = v % 40 - } else { - components[0] = 2 - components[1] = v - 80 - } - - i := 2 - for ; len(bytes) > 0; i++ { - if !bytes.readBase128Int(&v) { - return false - } - components[i] = v - } - *out = components[:i] - return true -} - -// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and -// advances. It reports whether the read was successful. -func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { - var bytes String - if !s.ReadASN1(&bytes, asn1.GeneralizedTime) { - return false - } - t := string(bytes) - res, err := time.Parse(generalizedTimeFormatStr, t) - if err != nil { - return false - } - if serialized := res.Format(generalizedTimeFormatStr); serialized != t { - return false - } - *out = res - return true -} - -const defaultUTCTimeFormatStr = "060102150405Z0700" - -// ReadASN1UTCTime decodes an ASN.1 UTCTime into out and advances. -// It reports whether the read was successful. -func (s *String) ReadASN1UTCTime(out *time.Time) bool { - var bytes String - if !s.ReadASN1(&bytes, asn1.UTCTime) { - return false - } - t := string(bytes) - - formatStr := defaultUTCTimeFormatStr - var err error - res, err := time.Parse(formatStr, t) - if err != nil { - // Fallback to minute precision if we can't parse second - // precision. If we are following X.509 or X.690 we shouldn't - // support this, but we do. - formatStr = "0601021504Z0700" - res, err = time.Parse(formatStr, t) - } - if err != nil { - return false - } - - if serialized := res.Format(formatStr); serialized != t { - return false - } - - if res.Year() >= 2050 { - // UTCTime interprets the low order digits 50-99 as 1950-99. - // This only applies to its use in the X.509 profile. - // See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 - res = res.AddDate(-100, 0, 0) - } - *out = res - return true -} - -// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. -// It reports whether the read was successful. -func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { - var bytes String - if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 || - len(bytes)*8/8 != len(bytes) { - return false - } - - paddingBits := bytes[0] - bytes = bytes[1:] - if paddingBits > 7 || - len(bytes) == 0 && paddingBits != 0 || - len(bytes) > 0 && bytes[len(bytes)-1]&(1< 4 || len(*s) < int(2+lenLen) { - return false - } - - lenBytes := String((*s)[2 : 2+lenLen]) - if !lenBytes.readUnsigned(&len32, int(lenLen)) { - return false - } - - // ITU-T X.690 section 10.1 (DER length forms) requires encoding the length - // with the minimum number of octets. - if len32 < 128 { - // Length should have used short-form encoding. - return false - } - if len32>>((lenLen-1)*8) == 0 { - // Leading octet is 0. Length should have been at least one byte shorter. - return false - } - - headerLen = 2 + uint32(lenLen) - if headerLen+len32 < len32 { - // Overflow. - return false - } - length = headerLen + len32 - } - - if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) { - return false - } - if skipHeader && !out.Skip(int(headerLen)) { - panic("cryptobyte: internal error") - } - - return true -} diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go deleted file mode 100644 index cda8e3ed..00000000 --- a/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package asn1 contains supporting types for parsing and building ASN.1 -// messages with the cryptobyte package. -package asn1 // import "golang.org/x/crypto/cryptobyte/asn1" - -// Tag represents an ASN.1 identifier octet, consisting of a tag number -// (indicating a type) and class (such as context-specific or constructed). -// -// Methods in the cryptobyte package only support the low-tag-number form, i.e. -// a single identifier octet with bits 7-8 encoding the class and bits 1-6 -// encoding the tag number. -type Tag uint8 - -const ( - classConstructed = 0x20 - classContextSpecific = 0x80 -) - -// Constructed returns t with the constructed class bit set. -func (t Tag) Constructed() Tag { return t | classConstructed } - -// ContextSpecific returns t with the context-specific class bit set. -func (t Tag) ContextSpecific() Tag { return t | classContextSpecific } - -// The following is a list of standard tag and class combinations. -const ( - BOOLEAN = Tag(1) - INTEGER = Tag(2) - BIT_STRING = Tag(3) - OCTET_STRING = Tag(4) - NULL = Tag(5) - OBJECT_IDENTIFIER = Tag(6) - ENUM = Tag(10) - UTF8String = Tag(12) - SEQUENCE = Tag(16 | classConstructed) - SET = Tag(17 | classConstructed) - PrintableString = Tag(19) - T61String = Tag(20) - IA5String = Tag(22) - UTCTime = Tag(23) - GeneralizedTime = Tag(24) - GeneralString = Tag(27) -) diff --git a/vendor/golang.org/x/crypto/cryptobyte/builder.go b/vendor/golang.org/x/crypto/cryptobyte/builder.go deleted file mode 100644 index cf254f5f..00000000 --- a/vendor/golang.org/x/crypto/cryptobyte/builder.go +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cryptobyte - -import ( - "errors" - "fmt" -) - -// A Builder builds byte strings from fixed-length and length-prefixed values. -// Builders either allocate space as needed, or are ‘fixed’, which means that -// they write into a given buffer and produce an error if it's exhausted. -// -// The zero value is a usable Builder that allocates space as needed. -// -// Simple values are marshaled and appended to a Builder using methods on the -// Builder. Length-prefixed values are marshaled by providing a -// BuilderContinuation, which is a function that writes the inner contents of -// the value to a given Builder. See the documentation for BuilderContinuation -// for details. -type Builder struct { - err error - result []byte - fixedSize bool - child *Builder - offset int - pendingLenLen int - pendingIsASN1 bool - inContinuation *bool -} - -// NewBuilder creates a Builder that appends its output to the given buffer. -// Like append(), the slice will be reallocated if its capacity is exceeded. -// Use Bytes to get the final buffer. -func NewBuilder(buffer []byte) *Builder { - return &Builder{ - result: buffer, - } -} - -// NewFixedBuilder creates a Builder that appends its output into the given -// buffer. This builder does not reallocate the output buffer. Writes that -// would exceed the buffer's capacity are treated as an error. -func NewFixedBuilder(buffer []byte) *Builder { - return &Builder{ - result: buffer, - fixedSize: true, - } -} - -// SetError sets the value to be returned as the error from Bytes. Writes -// performed after calling SetError are ignored. -func (b *Builder) SetError(err error) { - b.err = err -} - -// Bytes returns the bytes written by the builder or an error if one has -// occurred during building. -func (b *Builder) Bytes() ([]byte, error) { - if b.err != nil { - return nil, b.err - } - return b.result[b.offset:], nil -} - -// BytesOrPanic returns the bytes written by the builder or panics if an error -// has occurred during building. -func (b *Builder) BytesOrPanic() []byte { - if b.err != nil { - panic(b.err) - } - return b.result[b.offset:] -} - -// AddUint8 appends an 8-bit value to the byte string. -func (b *Builder) AddUint8(v uint8) { - b.add(byte(v)) -} - -// AddUint16 appends a big-endian, 16-bit value to the byte string. -func (b *Builder) AddUint16(v uint16) { - b.add(byte(v>>8), byte(v)) -} - -// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest -// byte of the 32-bit input value is silently truncated. -func (b *Builder) AddUint24(v uint32) { - b.add(byte(v>>16), byte(v>>8), byte(v)) -} - -// AddUint32 appends a big-endian, 32-bit value to the byte string. -func (b *Builder) AddUint32(v uint32) { - b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) -} - -// AddUint48 appends a big-endian, 48-bit value to the byte string. -func (b *Builder) AddUint48(v uint64) { - b.add(byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) -} - -// AddUint64 appends a big-endian, 64-bit value to the byte string. -func (b *Builder) AddUint64(v uint64) { - b.add(byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) -} - -// AddBytes appends a sequence of bytes to the byte string. -func (b *Builder) AddBytes(v []byte) { - b.add(v...) -} - -// BuilderContinuation is a continuation-passing interface for building -// length-prefixed byte sequences. Builder methods for length-prefixed -// sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation -// supplied to them. The child builder passed to the continuation can be used -// to build the content of the length-prefixed sequence. For example: -// -// parent := cryptobyte.NewBuilder() -// parent.AddUint8LengthPrefixed(func (child *Builder) { -// child.AddUint8(42) -// child.AddUint8LengthPrefixed(func (grandchild *Builder) { -// grandchild.AddUint8(5) -// }) -// }) -// -// It is an error to write more bytes to the child than allowed by the reserved -// length prefix. After the continuation returns, the child must be considered -// invalid, i.e. users must not store any copies or references of the child -// that outlive the continuation. -// -// If the continuation panics with a value of type BuildError then the inner -// error will be returned as the error from Bytes. If the child panics -// otherwise then Bytes will repanic with the same value. -type BuilderContinuation func(child *Builder) - -// BuildError wraps an error. If a BuilderContinuation panics with this value, -// the panic will be recovered and the inner error will be returned from -// Builder.Bytes. -type BuildError struct { - Err error -} - -// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence. -func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) { - b.addLengthPrefixed(1, false, f) -} - -// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence. -func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) { - b.addLengthPrefixed(2, false, f) -} - -// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence. -func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) { - b.addLengthPrefixed(3, false, f) -} - -// AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence. -func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) { - b.addLengthPrefixed(4, false, f) -} - -func (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) { - if !*b.inContinuation { - *b.inContinuation = true - - defer func() { - *b.inContinuation = false - - r := recover() - if r == nil { - return - } - - if buildError, ok := r.(BuildError); ok { - b.err = buildError.Err - } else { - panic(r) - } - }() - } - - f(arg) -} - -func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) { - // Subsequent writes can be ignored if the builder has encountered an error. - if b.err != nil { - return - } - - offset := len(b.result) - b.add(make([]byte, lenLen)...) - - if b.inContinuation == nil { - b.inContinuation = new(bool) - } - - b.child = &Builder{ - result: b.result, - fixedSize: b.fixedSize, - offset: offset, - pendingLenLen: lenLen, - pendingIsASN1: isASN1, - inContinuation: b.inContinuation, - } - - b.callContinuation(f, b.child) - b.flushChild() - if b.child != nil { - panic("cryptobyte: internal error") - } -} - -func (b *Builder) flushChild() { - if b.child == nil { - return - } - b.child.flushChild() - child := b.child - b.child = nil - - if child.err != nil { - b.err = child.err - return - } - - length := len(child.result) - child.pendingLenLen - child.offset - - if length < 0 { - panic("cryptobyte: internal error") // result unexpectedly shrunk - } - - if child.pendingIsASN1 { - // For ASN.1, we reserved a single byte for the length. If that turned out - // to be incorrect, we have to move the contents along in order to make - // space. - if child.pendingLenLen != 1 { - panic("cryptobyte: internal error") - } - var lenLen, lenByte uint8 - if int64(length) > 0xfffffffe { - b.err = errors.New("pending ASN.1 child too long") - return - } else if length > 0xffffff { - lenLen = 5 - lenByte = 0x80 | 4 - } else if length > 0xffff { - lenLen = 4 - lenByte = 0x80 | 3 - } else if length > 0xff { - lenLen = 3 - lenByte = 0x80 | 2 - } else if length > 0x7f { - lenLen = 2 - lenByte = 0x80 | 1 - } else { - lenLen = 1 - lenByte = uint8(length) - length = 0 - } - - // Insert the initial length byte, make space for successive length bytes, - // and adjust the offset. - child.result[child.offset] = lenByte - extraBytes := int(lenLen - 1) - if extraBytes != 0 { - child.add(make([]byte, extraBytes)...) - childStart := child.offset + child.pendingLenLen - copy(child.result[childStart+extraBytes:], child.result[childStart:]) - } - child.offset++ - child.pendingLenLen = extraBytes - } - - l := length - for i := child.pendingLenLen - 1; i >= 0; i-- { - child.result[child.offset+i] = uint8(l) - l >>= 8 - } - if l != 0 { - b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen) - return - } - - if b.fixedSize && &b.result[0] != &child.result[0] { - panic("cryptobyte: BuilderContinuation reallocated a fixed-size buffer") - } - - b.result = child.result -} - -func (b *Builder) add(bytes ...byte) { - if b.err != nil { - return - } - if b.child != nil { - panic("cryptobyte: attempted write while child is pending") - } - if len(b.result)+len(bytes) < len(bytes) { - b.err = errors.New("cryptobyte: length overflow") - } - if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) { - b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer") - return - } - b.result = append(b.result, bytes...) -} - -// Unwrite rolls back non-negative n bytes written directly to the Builder. -// An attempt by a child builder passed to a continuation to unwrite bytes -// from its parent will panic. -func (b *Builder) Unwrite(n int) { - if b.err != nil { - return - } - if b.child != nil { - panic("cryptobyte: attempted unwrite while child is pending") - } - length := len(b.result) - b.pendingLenLen - b.offset - if length < 0 { - panic("cryptobyte: internal error") - } - if n < 0 { - panic("cryptobyte: attempted to unwrite negative number of bytes") - } - if n > length { - panic("cryptobyte: attempted to unwrite more than was written") - } - b.result = b.result[:len(b.result)-n] -} - -// A MarshalingValue marshals itself into a Builder. -type MarshalingValue interface { - // Marshal is called by Builder.AddValue. It receives a pointer to a builder - // to marshal itself into. It may return an error that occurred during - // marshaling, such as unset or invalid values. - Marshal(b *Builder) error -} - -// AddValue calls Marshal on v, passing a pointer to the builder to append to. -// If Marshal returns an error, it is set on the Builder so that subsequent -// appends don't have an effect. -func (b *Builder) AddValue(v MarshalingValue) { - err := v.Marshal(b) - if err != nil { - b.err = err - } -} diff --git a/vendor/golang.org/x/crypto/cryptobyte/string.go b/vendor/golang.org/x/crypto/cryptobyte/string.go deleted file mode 100644 index 10692a8a..00000000 --- a/vendor/golang.org/x/crypto/cryptobyte/string.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package cryptobyte contains types that help with parsing and constructing -// length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage -// contains useful ASN.1 constants.) -// -// The String type is for parsing. It wraps a []byte slice and provides helper -// functions for consuming structures, value by value. -// -// The Builder type is for constructing messages. It providers helper functions -// for appending values and also for appending length-prefixed submessages – -// without having to worry about calculating the length prefix ahead of time. -// -// See the documentation and examples for the Builder and String types to get -// started. -package cryptobyte // import "golang.org/x/crypto/cryptobyte" - -// String represents a string of bytes. It provides methods for parsing -// fixed-length and length-prefixed values from it. -type String []byte - -// read advances a String by n bytes and returns them. If less than n bytes -// remain, it returns nil. -func (s *String) read(n int) []byte { - if len(*s) < n || n < 0 { - return nil - } - v := (*s)[:n] - *s = (*s)[n:] - return v -} - -// Skip advances the String by n byte and reports whether it was successful. -func (s *String) Skip(n int) bool { - return s.read(n) != nil -} - -// ReadUint8 decodes an 8-bit value into out and advances over it. -// It reports whether the read was successful. -func (s *String) ReadUint8(out *uint8) bool { - v := s.read(1) - if v == nil { - return false - } - *out = uint8(v[0]) - return true -} - -// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it. -// It reports whether the read was successful. -func (s *String) ReadUint16(out *uint16) bool { - v := s.read(2) - if v == nil { - return false - } - *out = uint16(v[0])<<8 | uint16(v[1]) - return true -} - -// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it. -// It reports whether the read was successful. -func (s *String) ReadUint24(out *uint32) bool { - v := s.read(3) - if v == nil { - return false - } - *out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2]) - return true -} - -// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it. -// It reports whether the read was successful. -func (s *String) ReadUint32(out *uint32) bool { - v := s.read(4) - if v == nil { - return false - } - *out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3]) - return true -} - -// ReadUint48 decodes a big-endian, 48-bit value into out and advances over it. -// It reports whether the read was successful. -func (s *String) ReadUint48(out *uint64) bool { - v := s.read(6) - if v == nil { - return false - } - *out = uint64(v[0])<<40 | uint64(v[1])<<32 | uint64(v[2])<<24 | uint64(v[3])<<16 | uint64(v[4])<<8 | uint64(v[5]) - return true -} - -// ReadUint64 decodes a big-endian, 64-bit value into out and advances over it. -// It reports whether the read was successful. -func (s *String) ReadUint64(out *uint64) bool { - v := s.read(8) - if v == nil { - return false - } - *out = uint64(v[0])<<56 | uint64(v[1])<<48 | uint64(v[2])<<40 | uint64(v[3])<<32 | uint64(v[4])<<24 | uint64(v[5])<<16 | uint64(v[6])<<8 | uint64(v[7]) - return true -} - -func (s *String) readUnsigned(out *uint32, length int) bool { - v := s.read(length) - if v == nil { - return false - } - var result uint32 - for i := 0; i < length; i++ { - result <<= 8 - result |= uint32(v[i]) - } - *out = result - return true -} - -func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool { - lenBytes := s.read(lenLen) - if lenBytes == nil { - return false - } - var length uint32 - for _, b := range lenBytes { - length = length << 8 - length = length | uint32(b) - } - v := s.read(int(length)) - if v == nil { - return false - } - *outChild = v - return true -} - -// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value -// into out and advances over it. It reports whether the read was successful. -func (s *String) ReadUint8LengthPrefixed(out *String) bool { - return s.readLengthPrefixed(1, out) -} - -// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit -// length-prefixed value into out and advances over it. It reports whether the -// read was successful. -func (s *String) ReadUint16LengthPrefixed(out *String) bool { - return s.readLengthPrefixed(2, out) -} - -// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit -// length-prefixed value into out and advances over it. It reports whether -// the read was successful. -func (s *String) ReadUint24LengthPrefixed(out *String) bool { - return s.readLengthPrefixed(3, out) -} - -// ReadBytes reads n bytes into out and advances over them. It reports -// whether the read was successful. -func (s *String) ReadBytes(out *[]byte, n int) bool { - v := s.read(n) - if v == nil { - return false - } - *out = v - return true -} - -// CopyBytes copies len(out) bytes into out and advances over them. It reports -// whether the copy operation was successful -func (s *String) CopyBytes(out []byte) bool { - n := len(out) - v := s.read(n) - if v == nil { - return false - } - return copy(out, v) == n -} - -// Empty reports whether the string does not contain any bytes. -func (s String) Empty() bool { - return len(s) == 0 -} diff --git a/vendor/golang.org/x/exp/constraints/constraints.go b/vendor/golang.org/x/exp/constraints/constraints.go deleted file mode 100644 index 2c033dff..00000000 --- a/vendor/golang.org/x/exp/constraints/constraints.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package constraints defines a set of useful constraints to be used -// with type parameters. -package constraints - -// Signed is a constraint that permits any signed integer type. -// If future releases of Go add new predeclared signed integer types, -// this constraint will be modified to include them. -type Signed interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 -} - -// Unsigned is a constraint that permits any unsigned integer type. -// If future releases of Go add new predeclared unsigned integer types, -// this constraint will be modified to include them. -type Unsigned interface { - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr -} - -// Integer is a constraint that permits any integer type. -// If future releases of Go add new predeclared integer types, -// this constraint will be modified to include them. -type Integer interface { - Signed | Unsigned -} - -// Float is a constraint that permits any floating-point type. -// If future releases of Go add new predeclared floating-point types, -// this constraint will be modified to include them. -type Float interface { - ~float32 | ~float64 -} - -// Complex is a constraint that permits any complex numeric type. -// If future releases of Go add new predeclared complex numeric types, -// this constraint will be modified to include them. -type Complex interface { - ~complex64 | ~complex128 -} - -// Ordered is a constraint that permits any ordered type: any type -// that supports the operators < <= >= >. -// If future releases of Go add new ordered types, -// this constraint will be modified to include them. -type Ordered interface { - Integer | Float | ~string -} diff --git a/vendor/modules.txt b/vendor/modules.txt index d7818486..beaa4551 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -229,9 +229,8 @@ github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util # github.com/quic-go/qtls-go1-20 v0.4.1 ## explicit; go 1.20 -github.com/quic-go/qtls-go1-20 -# github.com/quic-go/quic-go v0.40.1-0.20231203135336-87ef8ec48d55 -## explicit; go 1.20 +# github.com/quic-go/quic-go v0.40.1-0.20240101045026-22b7f7744eb6 +## explicit; go 1.21 github.com/quic-go/quic-go github.com/quic-go/quic-go/internal/ackhandler github.com/quic-go/quic-go/internal/congestion @@ -323,8 +322,6 @@ golang.org/x/crypto/blake2b golang.org/x/crypto/blowfish golang.org/x/crypto/chacha20 golang.org/x/crypto/chacha20poly1305 -golang.org/x/crypto/cryptobyte -golang.org/x/crypto/cryptobyte/asn1 golang.org/x/crypto/curve25519 golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/hkdf @@ -338,7 +335,6 @@ golang.org/x/crypto/ssh golang.org/x/crypto/ssh/internal/bcrypt_pbkdf # golang.org/x/exp v0.0.0-20221205204356-47842c84f3db ## explicit; go 1.18 -golang.org/x/exp/constraints golang.org/x/exp/rand # golang.org/x/mod v0.11.0 ## explicit; go 1.17