mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 23:19:58 +00:00
TUN-4961: Update quic-go to latest
- Updates fips-go to be the latest on cfsetup.yaml - Updates sumtype's x/tools to be latest to avoid Internal: nil pkg errors with fips.
This commit is contained in:
6
vendor/github.com/marten-seemann/qtls-go1-15/README.md
generated
vendored
6
vendor/github.com/marten-seemann/qtls-go1-15/README.md
generated
vendored
@@ -1,6 +0,0 @@
|
||||
# qtls
|
||||
|
||||
[](https://godoc.org/github.com/marten-seemann/qtls)
|
||||
[](https://circleci.com/gh/marten-seemann/qtls)
|
||||
|
||||
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/lucas-clemente/quic-go).
|
9
vendor/github.com/marten-seemann/qtls-go1-15/go.mod
generated
vendored
9
vendor/github.com/marten-seemann/qtls-go1-15/go.mod
generated
vendored
@@ -1,9 +0,0 @@
|
||||
module github.com/marten-seemann/qtls-go1-15
|
||||
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/golang/mock v1.4.4
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae
|
||||
)
|
14
vendor/github.com/marten-seemann/qtls-go1-15/go.sum
generated
vendored
14
vendor/github.com/marten-seemann/qtls-go1-15/go.sum
generated
vendored
@@ -1,14 +0,0 @@
|
||||
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
6
vendor/github.com/marten-seemann/qtls-go1-16/key_agreement.go
generated
vendored
6
vendor/github.com/marten-seemann/qtls-go1-16/key_agreement.go
generated
vendored
@@ -67,7 +67,11 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *config, clientHello
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
|
||||
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
|
||||
}
|
||||
|
29
vendor/github.com/marten-seemann/qtls-go1-16/key_schedule.go
generated
vendored
29
vendor/github.com/marten-seemann/qtls-go1-16/key_schedule.go
generated
vendored
@@ -5,7 +5,6 @@
|
||||
package qtls
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/elliptic"
|
||||
"crypto/hmac"
|
||||
"errors"
|
||||
@@ -32,20 +31,8 @@ const (
|
||||
trafficUpdateLabel = "traffic upd"
|
||||
)
|
||||
|
||||
// HkdfExtract generates a pseudorandom key for use with Expand from an input secret and an optional independent salt.
|
||||
func HkdfExtract(hash crypto.Hash, newSecret, currentSecret []byte) []byte {
|
||||
if newSecret == nil {
|
||||
newSecret = make([]byte, hash.Size())
|
||||
}
|
||||
return hkdf.Extract(hash.New, newSecret, currentSecret)
|
||||
}
|
||||
|
||||
// HkdfExpandLabel HKDF expands a label
|
||||
func HkdfExpandLabel(hash crypto.Hash, secret, hashValue []byte, label string, L int) []byte {
|
||||
return hkdfExpandLabel(hash, secret, hashValue, label, L)
|
||||
}
|
||||
|
||||
func hkdfExpandLabel(hash crypto.Hash, secret, context []byte, label string, length int) []byte {
|
||||
// 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) {
|
||||
@@ -56,18 +43,13 @@ func hkdfExpandLabel(hash crypto.Hash, secret, context []byte, label string, len
|
||||
b.AddBytes(context)
|
||||
})
|
||||
out := make([]byte, length)
|
||||
n, err := hkdf.Expand(hash.New, secret, hkdfLabel.BytesOrPanic()).Read(out)
|
||||
n, err := hkdf.Expand(c.hash.New, secret, hkdfLabel.BytesOrPanic()).Read(out)
|
||||
if err != nil || n != length {
|
||||
panic("tls: HKDF-Expand-Label invocation failed unexpectedly")
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// expandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1.
|
||||
func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []byte, length int) []byte {
|
||||
return hkdfExpandLabel(c.hash, secret, context, label, length)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@@ -78,7 +60,10 @@ func (c *cipherSuiteTLS13) deriveSecret(secret []byte, label string, transcript
|
||||
|
||||
// extract implements HKDF-Extract with the cipher suite hash.
|
||||
func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte {
|
||||
return HkdfExtract(c.hash, newSecret, currentSecret)
|
||||
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,
|
||||
|
6
vendor/github.com/marten-seemann/qtls-go1-17/README.md
generated
vendored
Normal file
6
vendor/github.com/marten-seemann/qtls-go1-17/README.md
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# qtls
|
||||
|
||||
[](https://pkg.go.dev/github.com/marten-seemann/qtls-go1-17)
|
||||
[](https://github.com/marten-seemann/qtls-go1-17/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/lucas-clemente/quic-go).
|
@@ -13,11 +13,12 @@ import (
|
||||
"crypto/rc4"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"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
|
||||
@@ -46,10 +47,10 @@ var (
|
||||
// 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.
|
||||
// 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_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, false},
|
||||
{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},
|
||||
@@ -61,7 +62,6 @@ func CipherSuites() []*CipherSuite {
|
||||
|
||||
{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_3DES_EDE_CBC_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_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},
|
||||
@@ -79,13 +79,15 @@ func CipherSuites() []*CipherSuite {
|
||||
// Most applications should not use the cipher suites in this list, and should
|
||||
// only use those returned by CipherSuites.
|
||||
func InsecureCipherSuites() []*CipherSuite {
|
||||
// RC4 suites are broken because RC4 is.
|
||||
// CBC-SHA256 suites have no Lucky13 countermeasures.
|
||||
// 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},
|
||||
}
|
||||
@@ -108,25 +110,6 @@ func CipherSuiteName(id uint16) string {
|
||||
return fmt.Sprintf("0x%04X", id)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
const (
|
||||
// suiteECDHE indicates that the cipher suite involves elliptic curve
|
||||
// Diffie-Hellman. This means that it should only be selected when the
|
||||
@@ -144,12 +127,10 @@ const (
|
||||
// suiteSHA384 indicates that the cipher suite uses SHA384 as the
|
||||
// handshake hash.
|
||||
suiteSHA384
|
||||
// suiteDefaultOff indicates that this cipher suite is not included by
|
||||
// default.
|
||||
suiteDefaultOff
|
||||
)
|
||||
|
||||
// A cipherSuite is a specific combination of key agreement, cipher and MAC function.
|
||||
// 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.
|
||||
@@ -160,41 +141,37 @@ type cipherSuite struct {
|
||||
// flags is a bitmask of the suite* values, above.
|
||||
flags int
|
||||
cipher func(key, iv []byte, isRead bool) interface{}
|
||||
mac func(version uint16, macKey []byte) macFunction
|
||||
mac func(key []byte) hash.Hash
|
||||
aead func(key, fixedNonce []byte) aead
|
||||
}
|
||||
|
||||
var cipherSuites = []*cipherSuite{
|
||||
// Ciphersuite order is chosen so that ECDHE comes before plain RSA and
|
||||
// AEADs are the top preference.
|
||||
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 | suiteDefaultOff, cipherAES, macSHA256, nil},
|
||||
{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 | suiteDefaultOff, cipherAES, macSHA256, 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 | suiteDefaultOff, cipherAES, macSHA256, nil},
|
||||
{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},
|
||||
|
||||
// RC4-based cipher suites are disabled by default.
|
||||
{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil},
|
||||
{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteDefaultOff, cipherRC4, macSHA1, nil},
|
||||
{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteDefaultOff, cipherRC4, 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 cipher suite from ids which is also in
|
||||
// supportedIDs and passes the ok filter.
|
||||
// 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)
|
||||
@@ -231,12 +208,208 @@ func (c *CipherSuiteTLS13) IVLen() int {
|
||||
return aeadNonceLength
|
||||
}
|
||||
|
||||
var cipherSuitesTLS13 = []*cipherSuiteTLS13{
|
||||
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) interface{} {
|
||||
cipher, _ := rc4.NewCipher(key)
|
||||
return cipher
|
||||
@@ -258,24 +431,15 @@ func cipherAES(key, iv []byte, isRead bool) interface{} {
|
||||
return cipher.NewCBCEncrypter(block, iv)
|
||||
}
|
||||
|
||||
// macSHA1 returns a macFunction for the given protocol version.
|
||||
func macSHA1(version uint16, key []byte) macFunction {
|
||||
return tls10MAC{h: hmac.New(newConstantTimeHash(sha1.New), key)}
|
||||
// macSHA1 returns a SHA-1 based constant time MAC.
|
||||
func macSHA1(key []byte) hash.Hash {
|
||||
return hmac.New(newConstantTimeHash(sha1.New), key)
|
||||
}
|
||||
|
||||
// macSHA256 returns a SHA-256 based MAC. These are only supported in TLS 1.2
|
||||
// so the given version is ignored.
|
||||
func macSHA256(version uint16, key []byte) macFunction {
|
||||
return tls10MAC{h: hmac.New(sha256.New, key)}
|
||||
}
|
||||
|
||||
type macFunction interface {
|
||||
// Size returns the length of the MAC.
|
||||
Size() int
|
||||
// MAC appends the MAC of (seq, header, data) to out. The extra data is fed
|
||||
// into the MAC after obtaining the result to normalize timing. The result
|
||||
// is only valid until the next invocation of MAC as the buffer is reused.
|
||||
MAC(seq, header, data, extra []byte) []byte
|
||||
// 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 {
|
||||
@@ -428,26 +592,14 @@ func newConstantTimeHash(h func() hash.Hash) func() hash.Hash {
|
||||
}
|
||||
|
||||
// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, Section 6.2.3.
|
||||
type tls10MAC struct {
|
||||
h hash.Hash
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (s tls10MAC) Size() int {
|
||||
return s.h.Size()
|
||||
}
|
||||
|
||||
// MAC is guaranteed to take constant time, as long as
|
||||
// len(seq)+len(header)+len(data)+len(extra) is constant. extra is not fed into
|
||||
// the MAC, but is only provided to make the timing profile constant.
|
||||
func (s tls10MAC) MAC(seq, header, data, extra []byte) []byte {
|
||||
s.h.Reset()
|
||||
s.h.Write(seq)
|
||||
s.h.Write(header)
|
||||
s.h.Write(data)
|
||||
res := s.h.Sum(s.buf[:0])
|
||||
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 {
|
||||
s.h.Write(extra)
|
||||
h.Write(extra)
|
||||
}
|
||||
return res
|
||||
}
|
@@ -7,6 +7,7 @@ package qtls
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
@@ -23,8 +24,6 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/cpu"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -241,9 +240,6 @@ type connectionState struct {
|
||||
CipherSuite uint16
|
||||
|
||||
// NegotiatedProtocol is the application protocol negotiated with ALPN.
|
||||
//
|
||||
// Note that on the client side, this is currently not guaranteed to be from
|
||||
// Config.NextProtos.
|
||||
NegotiatedProtocol string
|
||||
|
||||
// NegotiatedProtocolIsMutual used to indicate a mutual NPN negotiation.
|
||||
@@ -349,7 +345,7 @@ type clientSessionState struct {
|
||||
// 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.
|
||||
//go:generate sh -c "mockgen -package qtls -destination mock_client_session_cache_test.go github.com/marten-seemann/qtls-go1-15 ClientSessionCache"
|
||||
//go:generate sh -c "mockgen -package qtls -destination mock_client_session_cache_test.go github.com/marten-seemann/qtls-go1-17 ClientSessionCache"
|
||||
type ClientSessionCache = tls.ClientSessionCache
|
||||
|
||||
// SignatureScheme is a tls.SignatureScheme
|
||||
@@ -430,6 +426,16 @@ type clientHelloInfo struct {
|
||||
// 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
|
||||
@@ -437,6 +443,31 @@ type clientHelloInfo struct {
|
||||
// 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
|
||||
@@ -573,7 +604,11 @@ type config struct {
|
||||
RootCAs *x509.CertPool
|
||||
|
||||
// NextProtos is a list of supported application level protocols, in
|
||||
// order of preference.
|
||||
// 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
|
||||
@@ -599,17 +634,21 @@ type config struct {
|
||||
// testing or in combination with VerifyConnection or VerifyPeerCertificate.
|
||||
InsecureSkipVerify bool
|
||||
|
||||
// CipherSuites is a list of supported cipher suites for TLS versions up to
|
||||
// TLS 1.2. If CipherSuites is nil, a default list of secure cipher suites
|
||||
// is used, with a preference order based on hardware performance. The
|
||||
// default cipher suites might change over Go versions. Note that TLS 1.3
|
||||
// ciphersuites are not configurable.
|
||||
// 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 controls whether the server selects the
|
||||
// client's most preferred ciphersuite, or the server's most preferred
|
||||
// ciphersuite. If true then the server's preference, as expressed in
|
||||
// the order of elements in CipherSuites, is used.
|
||||
// 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.
|
||||
//
|
||||
// Deprected: PreferServerCipherSuites is ignored.
|
||||
PreferServerCipherSuites bool
|
||||
|
||||
// SessionTicketsDisabled may be set to true to disable session ticket and
|
||||
@@ -806,9 +845,12 @@ func (c *config) ticketKeyFromBytes(b [32]byte) (key ticketKey) {
|
||||
// ticket, and the lifetime we set for tickets we send.
|
||||
const maxSessionTicketLifetime = 7 * 24 * time.Hour
|
||||
|
||||
// Clone returns a shallow clone of c. It is safe to clone a Config that is
|
||||
// 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{
|
||||
@@ -986,11 +1028,10 @@ func (c *config) time() time.Time {
|
||||
}
|
||||
|
||||
func (c *config) cipherSuites() []uint16 {
|
||||
s := c.CipherSuites
|
||||
if s == nil {
|
||||
s = defaultCipherSuites()
|
||||
if c.CipherSuites != nil {
|
||||
return c.CipherSuites
|
||||
}
|
||||
return s
|
||||
return defaultCipherSuites
|
||||
}
|
||||
|
||||
var supportedVersions = []uint16{
|
||||
@@ -1292,7 +1333,9 @@ func (c *config) BuildNameToCertificate() {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if len(x509Cert.Subject.CommonName) > 0 {
|
||||
// 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 {
|
||||
@@ -1428,89 +1471,6 @@ func defaultConfig() *Config {
|
||||
return &emptyConfig
|
||||
}
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
varDefaultCipherSuites []uint16
|
||||
varDefaultCipherSuitesTLS13 []uint16
|
||||
)
|
||||
|
||||
func defaultCipherSuites() []uint16 {
|
||||
once.Do(initDefaultCipherSuites)
|
||||
return varDefaultCipherSuites
|
||||
}
|
||||
|
||||
func defaultCipherSuitesTLS13() []uint16 {
|
||||
once.Do(initDefaultCipherSuites)
|
||||
return varDefaultCipherSuitesTLS13
|
||||
}
|
||||
|
||||
func initDefaultCipherSuites() {
|
||||
var topCipherSuites []uint16
|
||||
|
||||
// Check the cpu flags for each platform that has optimized GCM implementations.
|
||||
// Worst case, these variables will just all be false.
|
||||
var (
|
||||
hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ
|
||||
hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
|
||||
// Keep in sync with crypto/aes/cipher_s390x.go.
|
||||
// TODO: check for s390
|
||||
// hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)
|
||||
hasGCMAsmS390X = false
|
||||
|
||||
hasGCMAsm = hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X
|
||||
)
|
||||
|
||||
if hasGCMAsm {
|
||||
// If AES-GCM hardware is provided then prioritise AES-GCM
|
||||
// cipher suites.
|
||||
topCipherSuites = []uint16{
|
||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||
}
|
||||
varDefaultCipherSuitesTLS13 = []uint16{
|
||||
TLS_AES_128_GCM_SHA256,
|
||||
TLS_CHACHA20_POLY1305_SHA256,
|
||||
TLS_AES_256_GCM_SHA384,
|
||||
}
|
||||
} else {
|
||||
// Without AES-GCM hardware, we put the ChaCha20-Poly1305
|
||||
// cipher suites first.
|
||||
topCipherSuites = []uint16{
|
||||
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
}
|
||||
varDefaultCipherSuitesTLS13 = []uint16{
|
||||
TLS_CHACHA20_POLY1305_SHA256,
|
||||
TLS_AES_128_GCM_SHA256,
|
||||
TLS_AES_256_GCM_SHA384,
|
||||
}
|
||||
}
|
||||
|
||||
varDefaultCipherSuites = make([]uint16, 0, len(cipherSuites))
|
||||
varDefaultCipherSuites = append(varDefaultCipherSuites, topCipherSuites...)
|
||||
|
||||
NextCipherSuite:
|
||||
for _, suite := range cipherSuites {
|
||||
if suite.flags&suiteDefaultOff != 0 {
|
||||
continue
|
||||
}
|
||||
for _, existing := range varDefaultCipherSuites {
|
||||
if existing == suite.id {
|
||||
continue NextCipherSuite
|
||||
}
|
||||
}
|
||||
varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id)
|
||||
}
|
||||
}
|
||||
|
||||
func unexpectedMessageError(wanted, got interface{}) error {
|
||||
return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted)
|
||||
}
|
@@ -8,11 +8,13 @@ package qtls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/cipher"
|
||||
"crypto/subtle"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
@@ -26,7 +28,7 @@ type Conn struct {
|
||||
// constant
|
||||
conn net.Conn
|
||||
isClient bool
|
||||
handshakeFn func() error // (*Conn).clientHandshake or serverHandshake
|
||||
handshakeFn func(context.Context) error // (*Conn).clientHandshake or serverHandshake
|
||||
|
||||
// handshakeStatus is 1 if the connection is currently transferring
|
||||
// application data (i.e. is not currently processing a handshake).
|
||||
@@ -93,15 +95,14 @@ type Conn struct {
|
||||
clientFinished [12]byte
|
||||
serverFinished [12]byte
|
||||
|
||||
clientProtocol string
|
||||
clientProtocolFallback bool
|
||||
// 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
|
||||
outBuf []byte // scratch buffer used by out.encrypt
|
||||
buffering bool // whether records are buffered in sendBuf
|
||||
sendBuf []byte // a buffer of records waiting to be sent
|
||||
|
||||
@@ -164,33 +165,34 @@ func (c *Conn) SetWriteDeadline(t time.Time) error {
|
||||
type halfConn struct {
|
||||
sync.Mutex
|
||||
|
||||
err error // first permanent error
|
||||
version uint16 // protocol version
|
||||
cipher interface{} // cipher algorithm
|
||||
mac macFunction
|
||||
seq [8]byte // 64-bit sequence number
|
||||
additionalData [13]byte // to avoid allocs; interface method args escape
|
||||
err error // first permanent error
|
||||
version uint16 // protocol version
|
||||
cipher interface{} // cipher algorithm
|
||||
mac hash.Hash
|
||||
seq [8]byte // 64-bit sequence number
|
||||
|
||||
scratchBuf [13]byte // to avoid allocs; interface method args escape
|
||||
|
||||
nextCipher interface{} // next encryption state
|
||||
nextMac macFunction // next MAC algorithm
|
||||
nextMac hash.Hash // next MAC algorithm
|
||||
|
||||
trafficSecret []byte // current TLS 1.3 traffic secret
|
||||
|
||||
setKeyCallback func(encLevel EncryptionLevel, suite *CipherSuiteTLS13, trafficSecret []byte)
|
||||
}
|
||||
|
||||
type permamentError struct {
|
||||
type permanentError struct {
|
||||
err net.Error
|
||||
}
|
||||
|
||||
func (e *permamentError) Error() string { return e.err.Error() }
|
||||
func (e *permamentError) Unwrap() error { return e.err }
|
||||
func (e *permamentError) Timeout() bool { return e.err.Timeout() }
|
||||
func (e *permamentError) Temporary() bool { return false }
|
||||
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 = &permamentError{err: e}
|
||||
hc.err = &permanentError{err: e}
|
||||
} else {
|
||||
hc.err = err
|
||||
}
|
||||
@@ -199,7 +201,7 @@ func (hc *halfConn) setErrorLocked(err error) error {
|
||||
|
||||
// prepareCipherSpec sets the encryption and MAC states
|
||||
// that a subsequent changeCipherSpec will use.
|
||||
func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) {
|
||||
func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac hash.Hash) {
|
||||
hc.version = version
|
||||
hc.nextCipher = cipher
|
||||
hc.nextMac = mac
|
||||
@@ -373,15 +375,14 @@ func (hc *halfConn) decrypt(record []byte) ([]byte, recordType, error) {
|
||||
}
|
||||
payload = payload[explicitNonceLen:]
|
||||
|
||||
additionalData := hc.additionalData[:]
|
||||
var additionalData []byte
|
||||
if hc.version == VersionTLS13 {
|
||||
additionalData = record[:recordHeaderLen]
|
||||
} else {
|
||||
copy(additionalData, hc.seq[:])
|
||||
copy(additionalData[8:], record[:3])
|
||||
additionalData = append(hc.scratchBuf[:0], hc.seq[:]...)
|
||||
additionalData = append(additionalData, record[:3]...)
|
||||
n := len(payload) - c.Overhead()
|
||||
additionalData[11] = byte(n >> 8)
|
||||
additionalData[12] = byte(n)
|
||||
additionalData = append(additionalData, byte(n>>8), byte(n))
|
||||
}
|
||||
|
||||
var err error
|
||||
@@ -447,7 +448,7 @@ func (hc *halfConn) decrypt(record []byte) ([]byte, recordType, error) {
|
||||
record[3] = byte(n >> 8)
|
||||
record[4] = byte(n)
|
||||
remoteMAC := payload[n : n+macSize]
|
||||
localMAC := hc.mac.MAC(hc.seq[0:], record[:recordHeaderLen], payload[:n], payload[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
|
||||
@@ -490,7 +491,7 @@ func sliceForAppend(in []byte, n int) (head, tail []byte) {
|
||||
}
|
||||
|
||||
// encrypt encrypts payload, adding the appropriate nonce and/or MAC, and
|
||||
// appends it to record, which contains the record header.
|
||||
// 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
|
||||
@@ -507,7 +508,7 @@ func (hc *halfConn) encrypt(record, payload []byte, rand io.Reader) ([]byte, err
|
||||
// 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 simlarly small block size
|
||||
// collision is reached first due to its similarly small block size
|
||||
// (see the Sweet32 attack).
|
||||
copy(explicitNonce, hc.seq[:])
|
||||
} else {
|
||||
@@ -517,14 +518,10 @@ func (hc *halfConn) encrypt(record, payload []byte, rand io.Reader) ([]byte, err
|
||||
}
|
||||
}
|
||||
|
||||
var mac []byte
|
||||
if hc.mac != nil {
|
||||
mac = hc.mac.MAC(hc.seq[:], record[:recordHeaderLen], payload, nil)
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -548,11 +545,12 @@ func (hc *halfConn) encrypt(record, payload []byte, rand io.Reader) ([]byte, err
|
||||
record = c.Seal(record[:recordHeaderLen],
|
||||
nonce, record[recordHeaderLen:], record[:recordHeaderLen])
|
||||
} else {
|
||||
copy(hc.additionalData[:], hc.seq[:])
|
||||
copy(hc.additionalData[8:], record)
|
||||
record = c.Seal(record, nonce, payload, hc.additionalData[:])
|
||||
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
|
||||
@@ -963,9 +961,28 @@ func (c *Conn) flush() (int, error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// outBufPool pools the record-sized scratch buffers used by writeRecordLocked.
|
||||
var outBufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
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) {
|
||||
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)
|
||||
@@ -973,8 +990,8 @@ func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) {
|
||||
m = maxPayload
|
||||
}
|
||||
|
||||
_, c.outBuf = sliceForAppend(c.outBuf[:0], recordHeaderLen)
|
||||
c.outBuf[0] = byte(typ)
|
||||
_, outBuf = sliceForAppend(outBuf[:0], recordHeaderLen)
|
||||
outBuf[0] = byte(typ)
|
||||
vers := c.vers
|
||||
if vers == 0 {
|
||||
// Some TLS servers fail if the record version is
|
||||
@@ -985,17 +1002,17 @@ func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) {
|
||||
// See RFC 8446, Section 5.1.
|
||||
vers = VersionTLS12
|
||||
}
|
||||
c.outBuf[1] = byte(vers >> 8)
|
||||
c.outBuf[2] = byte(vers)
|
||||
c.outBuf[3] = byte(m >> 8)
|
||||
c.outBuf[4] = byte(m)
|
||||
outBuf[1] = byte(vers >> 8)
|
||||
outBuf[2] = byte(vers)
|
||||
outBuf[3] = byte(m >> 8)
|
||||
outBuf[4] = byte(m)
|
||||
|
||||
var err error
|
||||
c.outBuf, err = c.out.encrypt(c.outBuf, data[:m], c.config.rand())
|
||||
outBuf, err = c.out.encrypt(outBuf, data[:m], c.config.rand())
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
if _, err := c.write(c.outBuf); err != nil {
|
||||
if _, err := c.write(outBuf); err != nil {
|
||||
return n, err
|
||||
}
|
||||
n += m
|
||||
@@ -1121,17 +1138,21 @@ func (c *Conn) readHandshake() (interface{}, error) {
|
||||
}
|
||||
|
||||
var (
|
||||
errClosed = errors.New("tls: use of closed connection")
|
||||
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 := atomic.LoadInt32(&c.activeCall)
|
||||
if x&1 != 0 {
|
||||
return 0, errClosed
|
||||
return 0, net.ErrClosed
|
||||
}
|
||||
if atomic.CompareAndSwapInt32(&c.activeCall, x, x+2) {
|
||||
break
|
||||
@@ -1221,7 +1242,7 @@ func (c *Conn) handleRenegotiation() error {
|
||||
defer c.handshakeMutex.Unlock()
|
||||
|
||||
atomic.StoreUint32(&c.handshakeStatus, 0)
|
||||
if c.handshakeErr = c.clientHandshake(); c.handshakeErr == nil {
|
||||
if c.handshakeErr = c.clientHandshake(context.Background()); c.handshakeErr == nil {
|
||||
c.handshakes++
|
||||
}
|
||||
return c.handshakeErr
|
||||
@@ -1288,8 +1309,12 @@ func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read can be made to time out and return a net.Error with Timeout() == true
|
||||
// after a fixed time limit; see SetDeadline and SetReadDeadline.
|
||||
// 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
|
||||
@@ -1340,7 +1365,7 @@ func (c *Conn) Close() error {
|
||||
for {
|
||||
x = atomic.LoadInt32(&c.activeCall)
|
||||
if x&1 != 0 {
|
||||
return errClosed
|
||||
return net.ErrClosed
|
||||
}
|
||||
if atomic.CompareAndSwapInt32(&c.activeCall, x, x|1) {
|
||||
break
|
||||
@@ -1357,9 +1382,10 @@ func (c *Conn) Close() error {
|
||||
}
|
||||
|
||||
var alertErr error
|
||||
|
||||
if c.handshakeComplete() {
|
||||
alertErr = c.closeNotify()
|
||||
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 {
|
||||
@@ -1386,8 +1412,12 @@ func (c *Conn) closeNotify() error {
|
||||
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
|
||||
}
|
||||
@@ -1399,8 +1429,61 @@ func (c *Conn) closeNotify() error {
|
||||
// first Read or Write will call it automatically.
|
||||
//
|
||||
// For control over canceling or setting a timeout on a handshake, use
|
||||
// the Dialer's DialContext method.
|
||||
// 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) {
|
||||
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()
|
||||
|
||||
// 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.
|
||||
if ctx.Done() != nil {
|
||||
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()
|
||||
|
||||
@@ -1414,7 +1497,7 @@ func (c *Conn) Handshake() error {
|
||||
c.in.Lock()
|
||||
defer c.in.Unlock()
|
||||
|
||||
c.handshakeErr = c.handshakeFn()
|
||||
c.handshakeErr = c.handshakeFn(handshakeCtx)
|
||||
if c.handshakeErr == nil {
|
||||
c.handshakes++
|
||||
} else {
|
||||
@@ -1453,7 +1536,7 @@ func (c *Conn) connectionStateLocked() ConnectionState {
|
||||
state.Version = c.vers
|
||||
state.NegotiatedProtocol = c.clientProtocol
|
||||
state.DidResume = c.didResume
|
||||
state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
|
||||
state.NegotiatedProtocolIsMutual = true
|
||||
state.ServerName = c.serverName
|
||||
state.CipherSuite = c.cipherSuite
|
||||
state.PeerCertificates = c.peerCertificates
|
10
vendor/github.com/marten-seemann/qtls-go1-17/go.mod
generated
vendored
Normal file
10
vendor/github.com/marten-seemann/qtls-go1-17/go.mod
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
module github.com/marten-seemann/qtls-go1-17
|
||||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.4 // indirect
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007
|
||||
)
|
34
vendor/github.com/marten-seemann/qtls-go1-17/go.sum
generated
vendored
Normal file
34
vendor/github.com/marten-seemann/qtls-go1-17/go.sum
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.4 h1:RehYMOyRW8hPVEja1KBVsFVNSm35Jj9Mvs5yNoZZ28A=
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
@@ -6,6 +6,7 @@ package qtls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
@@ -27,6 +29,7 @@ const clientSessionStateVersion = 1
|
||||
|
||||
type clientHandshakeState struct {
|
||||
c *Conn
|
||||
ctx context.Context
|
||||
serverHello *serverHelloMsg
|
||||
hello *clientHelloMsg
|
||||
suite *cipherSuite
|
||||
@@ -95,25 +98,24 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
|
||||
hello.secureRenegotiation = c.clientFinished[:]
|
||||
}
|
||||
|
||||
possibleCipherSuites := config.cipherSuites()
|
||||
hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
|
||||
preferenceOrder := cipherSuitesPreferenceOrder
|
||||
if !hasAESGCMHardwareSupport {
|
||||
preferenceOrder = cipherSuitesPreferenceOrderNoAES
|
||||
}
|
||||
configCipherSuites := config.cipherSuites()
|
||||
hello.cipherSuites = make([]uint16, 0, len(configCipherSuites))
|
||||
|
||||
// add non-TLS 1.3 cipher suites
|
||||
if c.config.MinVersion <= VersionTLS12 {
|
||||
for _, suiteId := range possibleCipherSuites {
|
||||
for _, suite := range cipherSuites {
|
||||
if suite.id != suiteId {
|
||||
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 {
|
||||
break
|
||||
}
|
||||
hello.cipherSuites = append(hello.cipherSuites, suiteId)
|
||||
break
|
||||
}
|
||||
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)
|
||||
@@ -137,18 +139,22 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
|
||||
|
||||
var params ecdheParameters
|
||||
if hello.supportedVersions[0] == VersionTLS13 {
|
||||
var hasTLS13CipherSuite bool
|
||||
// add TLS 1.3 cipher suites
|
||||
for _, suiteID := range possibleCipherSuites {
|
||||
var suites []uint16
|
||||
for _, suiteID := range configCipherSuites {
|
||||
for _, suite := range cipherSuitesTLS13 {
|
||||
if suite.id == suiteID {
|
||||
hasTLS13CipherSuite = true
|
||||
hello.cipherSuites = append(hello.cipherSuites, suiteID)
|
||||
suites = append(suites, suiteID)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hasTLS13CipherSuite {
|
||||
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13()...)
|
||||
if len(suites) > 0 {
|
||||
hello.cipherSuites = suites
|
||||
} else {
|
||||
if hasAESGCMHardwareSupport {
|
||||
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...)
|
||||
} else {
|
||||
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...)
|
||||
}
|
||||
}
|
||||
|
||||
curveID := config.curvePreferences()[0]
|
||||
@@ -169,7 +175,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
|
||||
return hello, params, nil
|
||||
}
|
||||
|
||||
func (c *Conn) clientHandshake() (err error) {
|
||||
func (c *Conn) clientHandshake(ctx context.Context) (err error) {
|
||||
if c.config == nil {
|
||||
c.config = fromConfig(defaultConfig())
|
||||
}
|
||||
@@ -253,6 +259,7 @@ func (c *Conn) clientHandshake() (err error) {
|
||||
if c.vers == VersionTLS13 {
|
||||
hs := &clientHandshakeStateTLS13{
|
||||
c: c,
|
||||
ctx: ctx,
|
||||
serverHello: serverHello,
|
||||
hello: hello,
|
||||
ecdheParams: ecdheParams,
|
||||
@@ -267,6 +274,7 @@ func (c *Conn) clientHandshake() (err error) {
|
||||
|
||||
hs := &clientHandshakeState{
|
||||
c: c,
|
||||
ctx: ctx,
|
||||
serverHello: serverHello,
|
||||
hello: hello,
|
||||
session: session,
|
||||
@@ -640,7 +648,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
||||
certRequested = true
|
||||
hs.finishedHash.Write(certReq.marshal())
|
||||
|
||||
cri := certificateRequestInfoFromMsg(c.vers, certReq)
|
||||
cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq)
|
||||
if chainToSend, err = c.getClientCertificate(cri); err != nil {
|
||||
c.sendAlert(alertInternalError)
|
||||
return err
|
||||
@@ -748,12 +756,12 @@ func (hs *clientHandshakeState) establishKeys() error {
|
||||
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 interface{}
|
||||
var clientHash, serverHash macFunction
|
||||
var clientHash, serverHash hash.Hash
|
||||
if hs.suite.cipher != nil {
|
||||
clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
|
||||
clientHash = hs.suite.mac(c.vers, clientMAC)
|
||||
clientHash = hs.suite.mac(clientMAC)
|
||||
serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
|
||||
serverHash = hs.suite.mac(c.vers, serverMAC)
|
||||
serverHash = hs.suite.mac(serverMAC)
|
||||
} else {
|
||||
clientCipher = hs.suite.aead(clientKey, clientIV)
|
||||
serverCipher = hs.suite.aead(serverKey, serverIV)
|
||||
@@ -801,18 +809,12 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
clientDidALPN := len(hs.hello.alpnProtocols) > 0
|
||||
serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
|
||||
|
||||
if !clientDidALPN && serverHasALPN {
|
||||
c.sendAlert(alertHandshakeFailure)
|
||||
return false, errors.New("tls: server advertised unrequested ALPN extension")
|
||||
if err := checkALPN(hs.hello.alpnProtocols, hs.serverHello.alpnProtocol); err != nil {
|
||||
c.sendAlert(alertUnsupportedExtension)
|
||||
return false, err
|
||||
}
|
||||
c.clientProtocol = hs.serverHello.alpnProtocol
|
||||
|
||||
if serverHasALPN {
|
||||
c.clientProtocol = hs.serverHello.alpnProtocol
|
||||
c.clientProtocolFallback = false
|
||||
}
|
||||
c.scts = hs.serverHello.scts
|
||||
|
||||
if !hs.serverResumedSession() {
|
||||
@@ -843,6 +845,23 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
|
||||
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) error {
|
||||
if serverProto == "" {
|
||||
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
|
||||
|
||||
@@ -980,10 +999,11 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
|
||||
|
||||
// certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS
|
||||
// <= 1.2 CertificateRequest, making an effort to fill in missing information.
|
||||
func certificateRequestInfoFromMsg(vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo {
|
||||
cri := &CertificateRequestInfo{
|
||||
func certificateRequestInfoFromMsg(ctx context.Context, vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo {
|
||||
cri := &certificateRequestInfo{
|
||||
AcceptableCAs: certReq.certificateAuthorities,
|
||||
Version: vers,
|
||||
ctx: ctx,
|
||||
}
|
||||
|
||||
var rsaAvail, ecAvail bool
|
||||
@@ -1017,7 +1037,7 @@ func certificateRequestInfoFromMsg(vers uint16, certReq *certificateRequestMsg)
|
||||
ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512,
|
||||
}
|
||||
}
|
||||
return cri
|
||||
return toCertificateRequestInfo(cri)
|
||||
}
|
||||
|
||||
// Filter the signature schemes based on the certificate types.
|
||||
@@ -1040,7 +1060,7 @@ func certificateRequestInfoFromMsg(vers uint16, certReq *certificateRequestMsg)
|
||||
}
|
||||
}
|
||||
|
||||
return cri
|
||||
return toCertificateRequestInfo(cri)
|
||||
}
|
||||
|
||||
func (c *Conn) getClientCertificate(cri *CertificateRequestInfo) (*Certificate, error) {
|
||||
@@ -1070,22 +1090,6 @@ func clientSessionCacheKey(serverAddr net.Addr, config *config) string {
|
||||
return clientSessionCacheKeyPrefix + serverAddr.String()
|
||||
}
|
||||
|
||||
// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
|
||||
// given list of possible protocols and a list of the preference order. The
|
||||
// first list must not be empty. It returns the resulting protocol and flag
|
||||
// indicating if the fallback case was reached.
|
||||
func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
|
||||
for _, s := range preferenceProtos {
|
||||
for _, c := range protos {
|
||||
if s == c {
|
||||
return s, false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return protos[0], true
|
||||
}
|
||||
|
||||
// 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.
|
@@ -6,12 +6,12 @@ package qtls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/hmac"
|
||||
"crypto/rsa"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
type clientHandshakeStateTLS13 struct {
|
||||
c *Conn
|
||||
ctx context.Context
|
||||
serverHello *serverHelloMsg
|
||||
hello *clientHelloMsg
|
||||
ecdheParams ecdheParameters
|
||||
@@ -413,23 +414,19 @@ func (hs *clientHandshakeStateTLS13) readServerParameters() error {
|
||||
}
|
||||
hs.transcript.Write(encryptedExtensions.marshal())
|
||||
|
||||
if len(encryptedExtensions.alpnProtocol) != 0 && len(hs.hello.alpnProtocols) == 0 {
|
||||
if err := checkALPN(hs.hello.alpnProtocols, encryptedExtensions.alpnProtocol); err != nil {
|
||||
c.sendAlert(alertUnsupportedExtension)
|
||||
return errors.New("tls: server advertised unrequested ALPN extension")
|
||||
return err
|
||||
}
|
||||
c.clientProtocol = encryptedExtensions.alpnProtocol
|
||||
|
||||
if c.extraConfig != nil && c.extraConfig.EnforceNextProtoSelection {
|
||||
if len(encryptedExtensions.alpnProtocol) == 0 {
|
||||
// the server didn't select an ALPN
|
||||
c.sendAlert(alertNoApplicationProtocol)
|
||||
return errors.New("ALPN negotiation failed. Server didn't offer any protocols")
|
||||
}
|
||||
if _, fallback := mutualProtocol([]string{encryptedExtensions.alpnProtocol}, hs.c.config.NextProtos); fallback {
|
||||
// the protocol selected by the server was not offered
|
||||
c.sendAlert(alertNoApplicationProtocol)
|
||||
return fmt.Errorf("ALPN negotiation failed. Server offered: %q", encryptedExtensions.alpnProtocol)
|
||||
}
|
||||
}
|
||||
c.clientProtocol = encryptedExtensions.alpnProtocol
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -576,11 +573,12 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
cert, err := c.getClientCertificate(&CertificateRequestInfo{
|
||||
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
|
||||
}
|
@@ -5,6 +5,7 @@
|
||||
package qtls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -22,6 +24,7 @@ import (
|
||||
// It's discarded once the handshake has completed.
|
||||
type serverHandshakeState struct {
|
||||
c *Conn
|
||||
ctx context.Context
|
||||
clientHello *clientHelloMsg
|
||||
hello *serverHelloMsg
|
||||
suite *cipherSuite
|
||||
@@ -36,10 +39,10 @@ type serverHandshakeState struct {
|
||||
}
|
||||
|
||||
// serverHandshake performs a TLS handshake as a server.
|
||||
func (c *Conn) serverHandshake() error {
|
||||
func (c *Conn) serverHandshake(ctx context.Context) error {
|
||||
c.setAlternativeRecordLayer()
|
||||
|
||||
clientHello, err := c.readClientHello()
|
||||
clientHello, err := c.readClientHello(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -47,6 +50,7 @@ func (c *Conn) serverHandshake() error {
|
||||
if c.vers == VersionTLS13 {
|
||||
hs := serverHandshakeStateTLS13{
|
||||
c: c,
|
||||
ctx: ctx,
|
||||
clientHello: clientHello,
|
||||
}
|
||||
return hs.handshake()
|
||||
@@ -60,6 +64,7 @@ func (c *Conn) serverHandshake() error {
|
||||
|
||||
hs := serverHandshakeState{
|
||||
c: c,
|
||||
ctx: ctx,
|
||||
clientHello: clientHello,
|
||||
}
|
||||
return hs.handshake()
|
||||
@@ -131,7 +136,7 @@ func (hs *serverHandshakeState) handshake() error {
|
||||
}
|
||||
|
||||
// readClientHello reads a ClientHello message and selects the protocol version.
|
||||
func (c *Conn) readClientHello() (*clientHelloMsg, error) {
|
||||
func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) {
|
||||
msg, err := c.readHandshake()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -145,7 +150,7 @@ func (c *Conn) readClientHello() (*clientHelloMsg, error) {
|
||||
var configForClient *config
|
||||
originalConfig := c.config
|
||||
if c.config.GetConfigForClient != nil {
|
||||
chi := newClientHelloInfo(c, clientHello)
|
||||
chi := newClientHelloInfo(ctx, c, clientHello)
|
||||
if cfc, err := c.config.GetConfigForClient(chi); err != nil {
|
||||
c.sendAlert(alertInternalError)
|
||||
return nil, err
|
||||
@@ -242,14 +247,15 @@ func (hs *serverHandshakeState) processClientHello() error {
|
||||
c.serverName = hs.clientHello.serverName
|
||||
}
|
||||
|
||||
if len(hs.clientHello.alpnProtocols) > 0 {
|
||||
if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
|
||||
hs.hello.alpnProtocol = selectedProto
|
||||
c.clientProtocol = selectedProto
|
||||
}
|
||||
selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols)
|
||||
if err != nil {
|
||||
c.sendAlert(alertNoApplicationProtocol)
|
||||
return err
|
||||
}
|
||||
hs.hello.alpnProtocol = selectedProto
|
||||
c.clientProtocol = selectedProto
|
||||
|
||||
hs.cert, err = c.config.getCertificate(newClientHelloInfo(c, hs.clientHello))
|
||||
hs.cert, err = c.config.getCertificate(newClientHelloInfo(hs.ctx, c, hs.clientHello))
|
||||
if err != nil {
|
||||
if err == errNoCertificates {
|
||||
c.sendAlert(alertUnrecognizedName)
|
||||
@@ -299,6 +305,34 @@ func (hs *serverHandshakeState) processClientHello() error {
|
||||
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) (string, error) {
|
||||
if len(serverProtos) == 0 || len(clientProtos) == 0 {
|
||||
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 {
|
||||
@@ -324,16 +358,23 @@ func supportsECDHE(c *config, supportedCurves []CurveID, supportedPoints []uint8
|
||||
func (hs *serverHandshakeState) pickCipherSuite() error {
|
||||
c := hs.c
|
||||
|
||||
var preferenceList, supportedList []uint16
|
||||
if c.config.PreferServerCipherSuites {
|
||||
preferenceList = c.config.cipherSuites()
|
||||
supportedList = hs.clientHello.cipherSuites
|
||||
} else {
|
||||
preferenceList = hs.clientHello.cipherSuites
|
||||
supportedList = c.config.cipherSuites()
|
||||
preferenceOrder := cipherSuitesPreferenceOrder
|
||||
if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) {
|
||||
preferenceOrder = cipherSuitesPreferenceOrderNoAES
|
||||
}
|
||||
|
||||
hs.suite = selectCipherSuite(preferenceList, supportedList, hs.cipherSuiteOk)
|
||||
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")
|
||||
@@ -671,13 +712,13 @@ func (hs *serverHandshakeState) establishKeys() error {
|
||||
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 interface{}
|
||||
var clientHash, serverHash macFunction
|
||||
var clientHash, serverHash hash.Hash
|
||||
|
||||
if hs.suite.aead == nil {
|
||||
clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
|
||||
clientHash = hs.suite.mac(c.vers, clientMAC)
|
||||
clientHash = hs.suite.mac(clientMAC)
|
||||
serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
|
||||
serverHash = hs.suite.mac(c.vers, serverMAC)
|
||||
serverHash = hs.suite.mac(serverMAC)
|
||||
} else {
|
||||
clientCipher = hs.suite.aead(clientKey, clientIV)
|
||||
serverCipher = hs.suite.aead(serverKey, serverIV)
|
||||
@@ -843,7 +884,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newClientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
|
||||
func newClientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
|
||||
supportedVersions := clientHello.supportedVersions
|
||||
if len(clientHello.supportedVersions) == 0 {
|
||||
supportedVersions = supportedVersionsFromMax(clientHello.vers)
|
||||
@@ -859,5 +900,6 @@ func newClientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
|
||||
SupportedVersions: supportedVersions,
|
||||
Conn: c.conn,
|
||||
config: toConfig(c.config),
|
||||
ctx: ctx,
|
||||
})
|
||||
}
|
@@ -6,11 +6,11 @@ package qtls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/hmac"
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"sync/atomic"
|
||||
@@ -24,8 +24,10 @@ const maxClientPSKIdentities = 5
|
||||
|
||||
type serverHandshakeStateTLS13 struct {
|
||||
c *Conn
|
||||
ctx context.Context
|
||||
clientHello *clientHelloMsg
|
||||
hello *serverHelloMsg
|
||||
alpnNegotiationErr error
|
||||
encryptedExtensions *encryptedExtensionsMsg
|
||||
sentDummyCCS bool
|
||||
usingPSK bool
|
||||
@@ -139,28 +141,27 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error {
|
||||
hs.hello.sessionId = hs.clientHello.sessionId
|
||||
hs.hello.compressionMethod = compressionNone
|
||||
|
||||
var preferenceList, supportedList, ourList []uint16
|
||||
for _, suiteID := range c.config.CipherSuites {
|
||||
for _, suite := range cipherSuitesTLS13 {
|
||||
if suite.id == suiteID {
|
||||
ourList = append(ourList, suiteID)
|
||||
if hs.suite == nil {
|
||||
var preferenceList []uint16
|
||||
for _, suiteID := range c.config.CipherSuites {
|
||||
for _, suite := range cipherSuitesTLS13 {
|
||||
if suite.id == suiteID {
|
||||
preferenceList = append(preferenceList, suiteID)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(ourList) == 0 {
|
||||
ourList = defaultCipherSuitesTLS13()
|
||||
}
|
||||
if c.config.PreferServerCipherSuites {
|
||||
preferenceList = ourList
|
||||
supportedList = hs.clientHello.cipherSuites
|
||||
} else {
|
||||
preferenceList = hs.clientHello.cipherSuites
|
||||
supportedList = ourList
|
||||
}
|
||||
for _, suiteID := range preferenceList {
|
||||
hs.suite = mutualCipherSuiteTLS13(supportedList, suiteID)
|
||||
if hs.suite != nil {
|
||||
break
|
||||
if len(preferenceList) == 0 {
|
||||
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 {
|
||||
@@ -227,12 +228,12 @@ GroupSelection:
|
||||
c.extraConfig.ReceivedExtensions(typeClientHello, hs.clientHello.additionalExtensions)
|
||||
}
|
||||
|
||||
if len(hs.clientHello.alpnProtocols) > 0 {
|
||||
if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
|
||||
hs.encryptedExtensions.alpnProtocol = selectedProto
|
||||
c.clientProtocol = selectedProto
|
||||
}
|
||||
selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols)
|
||||
if err != nil {
|
||||
hs.alpnNegotiationErr = err
|
||||
}
|
||||
hs.encryptedExtensions.alpnProtocol = selectedProto
|
||||
c.clientProtocol = selectedProto
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -283,7 +284,7 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error {
|
||||
return errors.New("tls: client sent unexpected early data")
|
||||
}
|
||||
|
||||
if sessionState.alpn == c.clientProtocol &&
|
||||
if hs.alpnNegotiationErr == nil && sessionState.alpn == c.clientProtocol &&
|
||||
c.extraConfig != nil && c.extraConfig.MaxEarlyData > 0 &&
|
||||
c.extraConfig.Accept0RTT != nil && c.extraConfig.Accept0RTT(sessionState.appData) {
|
||||
hs.encryptedExtensions.earlyData = true
|
||||
@@ -400,7 +401,7 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error {
|
||||
return c.sendAlert(alertMissingExtension)
|
||||
}
|
||||
|
||||
certificate, err := c.config.getCertificate(newClientHelloInfo(c, hs.clientHello))
|
||||
certificate, err := c.config.getCertificate(newClientHelloInfo(hs.ctx, c, hs.clientHello))
|
||||
if err != nil {
|
||||
if err == errNoCertificates {
|
||||
c.sendAlert(alertUnrecognizedName)
|
||||
@@ -559,11 +560,6 @@ func illegalClientHelloChange(ch, ch1 *clientHelloMsg) bool {
|
||||
func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
|
||||
c := hs.c
|
||||
|
||||
if c.extraConfig != nil && c.extraConfig.EnforceNextProtoSelection && len(c.clientProtocol) == 0 {
|
||||
c.sendAlert(alertNoApplicationProtocol)
|
||||
return fmt.Errorf("ALPN negotiation failed. Client offered: %q", hs.clientHello.alpnProtocols)
|
||||
}
|
||||
|
||||
hs.transcript.Write(hs.clientHello.marshal())
|
||||
hs.transcript.Write(hs.hello.marshal())
|
||||
if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
|
||||
@@ -601,6 +597,10 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if hs.alpnNegotiationErr != nil {
|
||||
c.sendAlert(alertNoApplicationProtocol)
|
||||
return hs.alpnNegotiationErr
|
||||
}
|
||||
if hs.c.extraConfig != nil && hs.c.extraConfig.GetExtensions != nil {
|
||||
hs.encryptedExtensions.additionalExtensions = hs.c.extraConfig.GetExtensions(typeEncryptedExtensions)
|
||||
}
|
@@ -15,6 +15,25 @@ import (
|
||||
"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")
|
||||
|
||||
@@ -67,7 +86,11 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *config, clientHello
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
|
||||
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
|
||||
}
|
@@ -5,7 +5,6 @@
|
||||
package qtls
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/elliptic"
|
||||
"crypto/hmac"
|
||||
"errors"
|
||||
@@ -32,20 +31,8 @@ const (
|
||||
trafficUpdateLabel = "traffic upd"
|
||||
)
|
||||
|
||||
// HkdfExtract generates a pseudorandom key for use with Expand from an input secret and an optional independent salt.
|
||||
func HkdfExtract(hash crypto.Hash, newSecret, currentSecret []byte) []byte {
|
||||
if newSecret == nil {
|
||||
newSecret = make([]byte, hash.Size())
|
||||
}
|
||||
return hkdf.Extract(hash.New, newSecret, currentSecret)
|
||||
}
|
||||
|
||||
// HkdfExpandLabel HKDF expands a label
|
||||
func HkdfExpandLabel(hash crypto.Hash, secret, hashValue []byte, label string, L int) []byte {
|
||||
return hkdfExpandLabel(hash, secret, hashValue, label, L)
|
||||
}
|
||||
|
||||
func hkdfExpandLabel(hash crypto.Hash, secret, context []byte, label string, length int) []byte {
|
||||
// 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) {
|
||||
@@ -56,18 +43,13 @@ func hkdfExpandLabel(hash crypto.Hash, secret, context []byte, label string, len
|
||||
b.AddBytes(context)
|
||||
})
|
||||
out := make([]byte, length)
|
||||
n, err := hkdf.Expand(hash.New, secret, hkdfLabel.BytesOrPanic()).Read(out)
|
||||
n, err := hkdf.Expand(c.hash.New, secret, hkdfLabel.BytesOrPanic()).Read(out)
|
||||
if err != nil || n != length {
|
||||
panic("tls: HKDF-Expand-Label invocation failed unexpectedly")
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// expandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1.
|
||||
func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []byte, length int) []byte {
|
||||
return hkdfExpandLabel(c.hash, secret, context, label, length)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@@ -78,7 +60,10 @@ func (c *cipherSuiteTLS13) deriveSecret(secret []byte, label string, transcript
|
||||
|
||||
// extract implements HKDF-Extract with the cipher suite hash.
|
||||
func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte {
|
||||
return HkdfExtract(c.hash, newSecret, currentSecret)
|
||||
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,
|
@@ -22,10 +22,9 @@ import (
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Server returns a new TLS server side connection
|
||||
@@ -115,33 +114,24 @@ func (timeoutError) Temporary() bool { return true }
|
||||
//
|
||||
// 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, extraConfig *ExtraConfig) (*Conn, error) {
|
||||
return dial(context.Background(), dialer, network, addr, config, extraConfig)
|
||||
}
|
||||
|
||||
func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config, extraConfig *ExtraConfig) (*Conn, error) {
|
||||
// We want the Timeout and Deadline values from dialer to cover the
|
||||
// whole process: TCP connection and TLS handshake. This means that we
|
||||
// also need to start our own timers now.
|
||||
timeout := netDialer.Timeout
|
||||
if netDialer.Timeout != 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, netDialer.Timeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
if !netDialer.Deadline.IsZero() {
|
||||
deadlineTimeout := time.Until(netDialer.Deadline)
|
||||
if timeout == 0 || deadlineTimeout < timeout {
|
||||
timeout = deadlineTimeout
|
||||
}
|
||||
}
|
||||
|
||||
// hsErrCh is non-nil if we might not wait for Handshake to complete.
|
||||
var hsErrCh chan error
|
||||
if timeout != 0 || ctx.Done() != nil {
|
||||
hsErrCh = make(chan error, 2)
|
||||
}
|
||||
if timeout != 0 {
|
||||
timer := time.AfterFunc(timeout, func() {
|
||||
hsErrCh <- timeoutError{}
|
||||
})
|
||||
defer timer.Stop()
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithDeadline(ctx, netDialer.Deadline)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
rawConn, err := netDialer.DialContext(ctx, network, addr)
|
||||
@@ -168,34 +158,10 @@ func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, conf
|
||||
}
|
||||
|
||||
conn := Client(rawConn, config, extraConfig)
|
||||
|
||||
if hsErrCh == nil {
|
||||
err = conn.Handshake()
|
||||
} else {
|
||||
go func() {
|
||||
hsErrCh <- conn.Handshake()
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
err = ctx.Err()
|
||||
case err = <-hsErrCh:
|
||||
if err != nil {
|
||||
// If the error was due to the context
|
||||
// closing, prefer the context's error, rather
|
||||
// than some random network teardown error.
|
||||
if e := ctx.Err(); e != nil {
|
||||
err = e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if err := conn.HandshakeContext(ctx); err != nil {
|
||||
rawConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
@@ -230,6 +196,9 @@ type Dialer struct {
|
||||
// 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)
|
||||
}
|
||||
@@ -265,11 +234,11 @@ func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Con
|
||||
// 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 := ioutil.ReadFile(certFile)
|
||||
certPEMBlock, err := os.ReadFile(certFile)
|
||||
if err != nil {
|
||||
return Certificate{}, err
|
||||
}
|
||||
keyPEMBlock, err := ioutil.ReadFile(keyFile)
|
||||
keyPEMBlock, err := os.ReadFile(keyFile)
|
||||
if err != nil {
|
||||
return Certificate{}, err
|
||||
}
|
@@ -13,6 +13,9 @@ func init() {
|
||||
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")
|
||||
}
|
||||
@@ -33,6 +36,10 @@ 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))
|
||||
}
|
Reference in New Issue
Block a user