diff --git a/.github/workflows/cross-compile.sh b/.github/workflows/cross-compile.sh index 1b7f0dcb6..c58fa7967 100755 --- a/.github/workflows/cross-compile.sh +++ b/.github/workflows/cross-compile.sh @@ -11,7 +11,10 @@ for dist in $(go tool dist list); do if [[ "$goos" == "darwin" && $goarch == "arm64" ]]; then continue; fi # ... darwin/arm64 neither if [[ $GOVERSION == "1.14" && $goos == "darwin" && $goarch == "arm" ]]; then continue; fi # Go 1.14 lacks syscall.IPV6_RECVTCLASS + cgo=0 + if [[ "$goos" == "ios" ]]; then cgo=1; fi # iOS builds require CGO, see https://github.com/golang/go/issues/43343 + echo "$dist" - GOOS=$goos GOARCH=$goarch go build -o main example/main.go + GOOS=$goos GOARCH=$goarch CGO_ENABLED=$cgo go build -o main example/main.go rm main done diff --git a/.github/workflows/cross-compile.yml b/.github/workflows/cross-compile.yml index f3216f6b0..f8a127034 100644 --- a/.github/workflows/cross-compile.yml +++ b/.github/workflows/cross-compile.yml @@ -3,13 +3,14 @@ jobs: crosscompile: strategy: matrix: - go: [ "1.14.x", "1.15.x" ] + go: [ "1.14.x", "1.15.x", "1.16.0-beta1" ] runs-on: ubuntu-latest name: "Cross Compilation (Go ${{matrix.go}})" steps: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: + stable: !contains(${{ matrix.go }}, "beta") && !contains(${{ matrix.go }}, "rc") go-version: ${{ matrix.go }} - name: Install build utils run: sudo apt-get install -y gcc-multilib diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 1cb99520b..ae3d1ad72 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -4,13 +4,14 @@ jobs: unit: strategy: matrix: - go: [ "1.14", "1.15" ] + go: [ "1.14.x", "1.15.x", "1.16.0-beta1" ] runs-on: ubuntu-latest name: Integration Tests, Go ${{ matrix.go }}) steps: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: + stable: !contains(${{ matrix.go }}, "beta") && !contains(${{ matrix.go }}, "rc") go-version: ${{ matrix.go }} - run: go version - name: Install Ginkgo diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 11d7600ad..957fdb84e 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -7,13 +7,14 @@ jobs: fail-fast: false matrix: os: [ "ubuntu", "windows", "macos" ] - go: [ "1.14", "1.15" ] + go: [ "1.14.x", "1.15.x", "1.16.0-beta1" ] runs-on: ${{ matrix.os }}-latest name: Unit tests (${{ matrix.os}}, Go ${{ matrix.go }}) steps: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 - with: + with: + stable: !contains(${{ matrix.go }}, "beta") && !contains(${{ matrix.go }}, "rc") go-version: ${{ matrix.go }} - run: go version - name: Install test tools diff --git a/go.mod b/go.mod index 15d7e7f41..56d69fd2d 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/marten-seemann/qpack v0.2.1 github.com/marten-seemann/qtls v0.10.0 github.com/marten-seemann/qtls-go1-15 v0.1.1 + github.com/marten-seemann/qtls-go1-16 v0.1.0-beta.1.1 github.com/onsi/ginkgo v1.14.0 github.com/onsi/gomega v1.10.1 go.opencensus.io v0.22.2 diff --git a/go.sum b/go.sum index 6a747b040..d3ee689c8 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,8 @@ github.com/marten-seemann/qtls v0.10.0 h1:ECsuYUKalRL240rRD4Ri33ISb7kAQ3qGDlrrl5 github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs= github.com/marten-seemann/qtls-go1-15 v0.1.1 h1:LIH6K34bPVttyXnUWixk0bzH6/N07VxbSabxn5A5gZQ= github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= +github.com/marten-seemann/qtls-go1-16 v0.1.0-beta.1.1 h1:CWVWoLCcdfarQRGgWi2b9ILKhc5v8MXtfs3bz9dmE00= +github.com/marten-seemann/qtls-go1-16 v0.1.0-beta.1.1/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= diff --git a/internal/qtls/go114.go b/internal/qtls/go114.go index c6c6d5133..9b96551a2 100644 --- a/internal/qtls/go114.go +++ b/internal/qtls/go114.go @@ -1,4 +1,5 @@ // +build !go1.15 +// +build !go1.16 package qtls diff --git a/internal/qtls/go114_test.go b/internal/qtls/go114_test.go index 8942a9885..6f8616f69 100644 --- a/internal/qtls/go114_test.go +++ b/internal/qtls/go114_test.go @@ -1,4 +1,5 @@ // +build !go1.15 +// +build !go1.16 package qtls diff --git a/internal/qtls/go115.go b/internal/qtls/go115.go index 72bfb2c83..bd11d0175 100644 --- a/internal/qtls/go115.go +++ b/internal/qtls/go115.go @@ -1,4 +1,5 @@ // +build go1.15 +// +build !go1.16 package qtls diff --git a/internal/qtls/go115_test.go b/internal/qtls/go115_test.go index d5abc550a..7c7920aa5 100644 --- a/internal/qtls/go115_test.go +++ b/internal/qtls/go115_test.go @@ -1,4 +1,5 @@ // +build go1.15 +// +build !go1.16 package qtls diff --git a/internal/qtls/go116.go b/internal/qtls/go116.go new file mode 100644 index 000000000..5e64a6fb6 --- /dev/null +++ b/internal/qtls/go116.go @@ -0,0 +1,114 @@ +// +build go1.16 + +package qtls + +import ( + "crypto" + "crypto/cipher" + "crypto/tls" + "net" + "unsafe" + + qtls "github.com/marten-seemann/qtls-go1-16" +) + +type ( + // Alert is a TLS alert + Alert = qtls.Alert + // A Certificate is qtls.Certificate. + Certificate = qtls.Certificate + // CertificateRequestInfo contains inforamtion about a certificate request. + CertificateRequestInfo = qtls.CertificateRequestInfo + // A CipherSuiteTLS13 is a cipher suite for TLS 1.3 + CipherSuiteTLS13 = qtls.CipherSuiteTLS13 + // ClientHelloInfo contains information about a ClientHello. + ClientHelloInfo = qtls.ClientHelloInfo + // ClientSessionCache is a cache used for session resumption. + ClientSessionCache = qtls.ClientSessionCache + // ClientSessionState is a state needed for session resumption. + ClientSessionState = qtls.ClientSessionState + // A Config is a qtls.Config. + Config = qtls.Config + // A Conn is a qtls.Conn. + Conn = qtls.Conn + // ConnectionState contains information about the state of the connection. + ConnectionState = qtls.ConnectionStateWith0RTT + // EncryptionLevel is the encryption level of a message. + EncryptionLevel = qtls.EncryptionLevel + // Extension is a TLS extension + Extension = qtls.Extension + // ExtraConfig is the qtls.ExtraConfig + ExtraConfig = qtls.ExtraConfig + // RecordLayer is a qtls RecordLayer. + RecordLayer = qtls.RecordLayer +) + +const ( + // EncryptionHandshake is the Handshake encryption level + EncryptionHandshake = qtls.EncryptionHandshake + // Encryption0RTT is the 0-RTT encryption level + Encryption0RTT = qtls.Encryption0RTT + // EncryptionApplication is the application data encryption level + EncryptionApplication = qtls.EncryptionApplication +) + +// CipherSuiteName gets the name of a cipher suite. +func CipherSuiteName(id uint16) string { + return qtls.CipherSuiteName(id) +} + +// 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 { + return qtls.HkdfExtract(hash, newSecret, currentSecret) +} + +// HkdfExpandLabel HKDF expands a label +func HkdfExpandLabel(hash crypto.Hash, secret, hashValue []byte, label string, L int) []byte { + return qtls.HkdfExpandLabel(hash, secret, hashValue, label, L) +} + +// AEADAESGCMTLS13 creates a new AES-GCM AEAD for TLS 1.3 +func AEADAESGCMTLS13(key, fixedNonce []byte) cipher.AEAD { + return qtls.AEADAESGCMTLS13(key, fixedNonce) +} + +// Client returns a new TLS client side connection. +func Client(conn net.Conn, config *Config, extraConfig *ExtraConfig) *Conn { + return qtls.Client(conn, config, extraConfig) +} + +// Server returns a new TLS server side connection. +func Server(conn net.Conn, config *Config, extraConfig *ExtraConfig) *Conn { + return qtls.Server(conn, config, extraConfig) +} + +func GetConnectionState(conn *Conn) ConnectionState { + return conn.ConnectionStateWith0RTT() +} + +// ToTLSConnectionState extracts the tls.ConnectionState +func ToTLSConnectionState(cs ConnectionState) tls.ConnectionState { + return cs.ConnectionState +} + +type cipherSuiteTLS13 struct { + ID uint16 + KeyLen int + AEAD func(key, fixedNonce []byte) cipher.AEAD + Hash crypto.Hash +} + +//go:linkname cipherSuiteTLS13ByID github.com/marten-seemann/qtls-go1-16.cipherSuiteTLS13ByID +func cipherSuiteTLS13ByID(id uint16) *cipherSuiteTLS13 + +// CipherSuiteTLS13ByID gets a TLS 1.3 cipher suite. +func CipherSuiteTLS13ByID(id uint16) *CipherSuiteTLS13 { + val := cipherSuiteTLS13ByID(id) + cs := (*cipherSuiteTLS13)(unsafe.Pointer(val)) + return &qtls.CipherSuiteTLS13{ + ID: cs.ID, + KeyLen: cs.KeyLen, + AEAD: cs.AEAD, + Hash: cs.Hash, + } +} diff --git a/internal/qtls/go116_test.go b/internal/qtls/go116_test.go new file mode 100644 index 000000000..2c1253a8f --- /dev/null +++ b/internal/qtls/go116_test.go @@ -0,0 +1,19 @@ +// +build go1.16 + +package qtls + +import ( + "crypto/tls" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("qtls wrapper", func() { + It("gets cipher suites", func() { + for _, id := range []uint16{tls.TLS_AES_128_GCM_SHA256, tls.TLS_AES_256_GCM_SHA384, tls.TLS_CHACHA20_POLY1305_SHA256} { + cs := CipherSuiteTLS13ByID(id) + Expect(cs.ID).To(Equal(id)) + } + }) +})