diff --git a/.github/.gitignore b/.github/.gitignore new file mode 100644 index 00000000..44d7f86a --- /dev/null +++ b/.github/.gitignore @@ -0,0 +1 @@ +.goassets diff --git a/.github/fetch-scripts.sh b/.github/fetch-scripts.sh new file mode 100755 index 00000000..d7e848b3 --- /dev/null +++ b/.github/fetch-scripts.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# +# DO NOT EDIT THIS FILE +# +# It is automatically copied from https://github.com/pion/.goassets repository. +# +# If you want to update the shared CI config, send a PR to +# https://github.com/pion/.goassets instead of this repository. +# + +set -eu + +SCRIPT_PATH="$(realpath "$(dirname "$0")")" +GOASSETS_PATH="${SCRIPT_PATH}/.goassets" + +GOASSETS_REF=${GOASSETS_REF:-master} + +if [ -d "${GOASSETS_PATH}" ]; then + if ! git -C "${GOASSETS_PATH}" diff --exit-code; then + echo "${GOASSETS_PATH} has uncommitted changes" >&2 + exit 1 + fi + git -C "${GOASSETS_PATH}" fetch origin + git -C "${GOASSETS_PATH}" checkout ${GOASSETS_REF} + git -C "${GOASSETS_PATH}" reset --hard origin/${GOASSETS_REF} +else + git clone -b ${GOASSETS_REF} https://github.com/pion/.goassets.git "${GOASSETS_PATH}" +fi diff --git a/.github/generate-authors.sh b/.github/generate-authors.sh deleted file mode 100755 index 182e4f5e..00000000 --- a/.github/generate-authors.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash - -# -# DO NOT EDIT THIS FILE -# -# It is automatically copied from https://github.com/pion/.goassets repository. -# -# If you want to update the shared CI config, send a PR to -# https://github.com/pion/.goassets instead of this repository. -# - -set -e - -SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) -AUTHORS_PATH="$GITHUB_WORKSPACE/AUTHORS.txt" - -if [ -f ${SCRIPT_PATH}/.ci.conf ] -then - . ${SCRIPT_PATH}/.ci.conf -fi - -# -# DO NOT EDIT THIS -# -EXCLUDED_CONTRIBUTORS+=('John R. Bradley' 'renovate[bot]' 'Renovate Bot' 'Pion Bot' 'pionbot') -# If you want to exclude a name from all repositories, send a PR to -# https://github.com/pion/.goassets instead of this repository. -# If you want to exclude a name only from this repository, -# add EXCLUDED_CONTRIBUTORS=('name') to .github/.ci.conf - -CONTRIBUTORS=() - -shouldBeIncluded () { - for i in "${EXCLUDED_CONTRIBUTORS[@]}" - do - if [[ $1 =~ "$i" ]]; then - return 1 - fi - done - return 0 -} - - -IFS=$'\n' #Only split on newline -for contributor in $(git log --format='%aN <%aE>' | LC_ALL=C.UTF-8 sort -uf) -do - if shouldBeIncluded $contributor; then - CONTRIBUTORS+=("$contributor") - fi -done -unset IFS - -if [ ${#CONTRIBUTORS[@]} -ne 0 ]; then - cat >$AUTHORS_PATH <<-'EOH' -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see `.github/generate-authors.sh` for the scripting -EOH - for i in "${CONTRIBUTORS[@]}" - do - echo "$i" >> $AUTHORS_PATH - done - exit 0 -fi diff --git a/.github/install-hooks.sh b/.github/install-hooks.sh index 73d20a4e..57b77988 100755 --- a/.github/install-hooks.sh +++ b/.github/install-hooks.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # # DO NOT EDIT THIS FILE @@ -9,8 +9,10 @@ # https://github.com/pion/.goassets instead of this repository. # -SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) +SCRIPT_PATH="$(realpath "$(dirname "$0")")" -cp "$SCRIPT_PATH/hooks/commit-msg.sh" "$SCRIPT_PATH/../.git/hooks/commit-msg" -cp "$SCRIPT_PATH/hooks/pre-commit.sh" "$SCRIPT_PATH/../.git/hooks/pre-commit" -cp "$SCRIPT_PATH/hooks/pre-push.sh" "$SCRIPT_PATH/../.git/hooks/pre-push" +. ${SCRIPT_PATH}/fetch-scripts.sh + +cp "${GOASSETS_PATH}/hooks/commit-msg.sh" "${SCRIPT_PATH}/../.git/hooks/commit-msg" +cp "${GOASSETS_PATH}/hooks/pre-commit.sh" "${SCRIPT_PATH}/../.git/hooks/pre-commit" +cp "${GOASSETS_PATH}/hooks/pre-push.sh" "${SCRIPT_PATH}/../.git/hooks/pre-push" diff --git a/.github/lint-commit-message.sh b/.github/lint-commit-message.sh deleted file mode 100755 index 010a3328..00000000 --- a/.github/lint-commit-message.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env bash - -# -# DO NOT EDIT THIS FILE -# -# It is automatically copied from https://github.com/pion/.goassets repository. -# -# If you want to update the shared CI config, send a PR to -# https://github.com/pion/.goassets instead of this repository. -# - -set -e - -display_commit_message_error() { -cat << EndOfMessage -$1 - -------------------------------------------------- -The preceding commit message is invalid -it failed '$2' of the following checks - -* Separate subject from body with a blank line -* Limit the subject line to 50 characters -* Capitalize the subject line -* Do not end the subject line with a period -* Wrap the body at 72 characters -EndOfMessage - - exit 1 -} - -lint_commit_message() { - if [[ "$(echo "$1" | awk 'NR == 2 {print $1;}' | wc -c)" -ne 1 ]]; then - display_commit_message_error "$1" 'Separate subject from body with a blank line' - fi - - if [[ "$(echo "$1" | head -n1 | awk '{print length}')" -gt 50 ]]; then - display_commit_message_error "$1" 'Limit the subject line to 50 characters' - fi - - if [[ ! $1 =~ ^[A-Z] ]]; then - display_commit_message_error "$1" 'Capitalize the subject line' - fi - - if [[ "$(echo "$1" | awk 'NR == 1 {print substr($0,length($0),1)}')" == "." ]]; then - display_commit_message_error "$1" 'Do not end the subject line with a period' - fi - - if [[ "$(echo "$1" | awk '{print length}' | sort -nr | head -1)" -gt 72 ]]; then - display_commit_message_error "$1" 'Wrap the body at 72 characters' - fi -} - -if [ "$#" -eq 1 ]; then - if [ ! -f "$1" ]; then - echo "$0 was passed one argument, but was not a valid file" - exit 1 - fi - lint_commit_message "$(sed -n '/# Please enter the commit message for your changes. Lines starting/q;p' "$1")" -else - for commit in $(git rev-list --no-merges origin/master..); do - lint_commit_message "$(git log --format="%B" -n 1 $commit)" - done -fi diff --git a/.github/lint-disallowed-functions-in-library.sh b/.github/lint-disallowed-functions-in-library.sh deleted file mode 100755 index 8ce5d096..00000000 --- a/.github/lint-disallowed-functions-in-library.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -# -# DO NOT EDIT THIS FILE -# -# It is automatically copied from https://github.com/pion/.goassets repository. -# -# If you want to update the shared CI config, send a PR to -# https://github.com/pion/.goassets instead of this repository. -# - -set -e - -# Disallow usages of functions that cause the program to exit in the library code -SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) -if [ -f ${SCRIPT_PATH}/.ci.conf ] -then - . ${SCRIPT_PATH}/.ci.conf -fi - -EXCLUDE_DIRECTORIES=${DISALLOWED_FUNCTIONS_EXCLUDED_DIRECTORIES:-"examples"} -DISALLOWED_FUNCTIONS=('os.Exit(' 'panic(' 'Fatal(' 'Fatalf(' 'Fatalln(' 'fmt.Println(' 'fmt.Printf(' 'log.Print(' 'log.Println(' 'log.Printf(' 'print(' 'println(') - -files=$( - find "$SCRIPT_PATH/.." -name "*.go" \ - | grep -v -e '^.*_test.go$' \ - | while read file - do - excluded=false - for ex in $EXCLUDE_DIRECTORIES - do - if [[ $file == */$ex/* ]] - then - excluded=true - break - fi - done - $excluded || echo "$file" - done -) - -for disallowedFunction in "${DISALLOWED_FUNCTIONS[@]}" -do - if grep -e "\s$disallowedFunction" $files | grep -v -e 'nolint'; then - echo "$disallowedFunction may only be used in example code" - exit 1 - fi -done diff --git a/.github/lint-filename.sh b/.github/lint-filename.sh deleted file mode 100755 index 81b3f14f..00000000 --- a/.github/lint-filename.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -# -# DO NOT EDIT THIS FILE -# -# It is automatically copied from https://github.com/pion/.goassets repository. -# -# If you want to update the shared CI config, send a PR to -# https://github.com/pion/.goassets instead of this repository. -# - -set -e - -SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) -GO_REGEX="^[a-zA-Z][a-zA-Z0-9_]*\.go$" - -find "$SCRIPT_PATH/.." -name "*.go" | while read fullpath; do - filename=$(basename -- "$fullpath") - - if ! [[ $filename =~ $GO_REGEX ]]; then - echo "$filename is not a valid filename for Go code, only alpha, numbers and underscores are supported" - exit 1 - fi -done diff --git a/.github/lint-no-trailing-newline-in-log-messages.sh b/.github/lint-no-trailing-newline-in-log-messages.sh deleted file mode 100755 index 29cd4a28..00000000 --- a/.github/lint-no-trailing-newline-in-log-messages.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -# -# DO NOT EDIT THIS FILE -# -# It is automatically copied from https://github.com/pion/.goassets repository. -# -# If you want to update the shared CI config, send a PR to -# https://github.com/pion/.goassets instead of this repository. -# - -set -e - -# Disallow usages of functions that cause the program to exit in the library code -SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) -if [ -f ${SCRIPT_PATH}/.ci.conf ] -then - . ${SCRIPT_PATH}/.ci.conf -fi - -files=$( - find "$SCRIPT_PATH/.." -name "*.go" \ - | while read file - do - excluded=false - for ex in $EXCLUDE_DIRECTORIES - do - if [[ $file == */$ex/* ]] - then - excluded=true - break - fi - done - $excluded || echo "$file" - done -) - -if grep -E '\.(Trace|Debug|Info|Warn|Error)f?\("[^"]*\\n"\)?' $files | grep -v -e 'nolint'; then - echo "Log format strings should have trailing new-line" - exit 1 -fi \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..a07c2928 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,22 @@ +# +# DO NOT EDIT THIS FILE +# +# It is automatically copied from https://github.com/pion/.goassets repository. +# If this repository should have package specific CI config, +# remove the repository name from .goassets/.github/workflows/assets-sync.yml. +# +# If you want to update the shared CI config, send a PR to +# https://github.com/pion/.goassets instead of this repository. +# + +name: Release +on: + push: + tags: + - 'v*' + +jobs: + release: + uses: pion/.goassets/.github/workflows/release.reusable.yml@master + with: + go-version: '1.19' # auto-update/latest-go-version diff --git a/.github/workflows/renovate-go-sum-fix.yaml b/.github/workflows/renovate-go-sum-fix.yaml new file mode 100644 index 00000000..5a9af364 --- /dev/null +++ b/.github/workflows/renovate-go-sum-fix.yaml @@ -0,0 +1,22 @@ +# +# DO NOT EDIT THIS FILE +# +# It is automatically copied from https://github.com/pion/.goassets repository. +# If this repository should have package specific CI config, +# remove the repository name from .goassets/.github/workflows/assets-sync.yml. +# +# If you want to update the shared CI config, send a PR to +# https://github.com/pion/.goassets instead of this repository. +# + +name: Fix go.sum +on: + push: + branches: + - renovate/* + +jobs: + fix: + uses: pion/.goassets/.github/workflows/renovate-go-sum-fix.reusable.yml@master + secrets: + token: ${{ secrets.PIONBOT_PRIVATE_KEY }} diff --git a/.golangci.yml b/.golangci.yml index d7a88eca..48696f16 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -18,7 +18,6 @@ linters: - bidichk # Checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - - deadcode # Finds unused code - decorder # check declaration order and count of types, constants, variables and functions - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) @@ -60,7 +59,6 @@ linters: - predeclared # find code that shadows one of Go's predeclared identifiers - revive # golint replacement, finds style mistakes - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks - - structcheck # Finds unused struct fields - stylecheck # Stylecheck is a replacement for golint - tagliatelle # Checks the struct tags. - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 @@ -69,7 +67,6 @@ linters: - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types - - varcheck # Finds unused global variables and constants - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 00000000..2caa5fbd --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,2 @@ +builds: +- skip: true diff --git a/AUTHORS.txt b/AUTHORS.txt index 65ad9ac0..54aaaa69 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -2,7 +2,7 @@ # we would love to have you https://github.com/pion/webrtc/wiki/Contributing # # This file is auto generated, using git to list all individuals contributors. -# see `.github/generate-authors.sh` for the scripting +# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting Aleksandr Razumov alvarowolfx Arlo Breault @@ -29,19 +29,28 @@ Jozef Kralik Julien Salleyron Juliusz Chroboczek Kegan Dougal +Kevin Wang Lander Noterman Len Lukas Lihotzki ManuelBk <26275612+ManuelBk@users.noreply.github.com> Michael Zabka Michiel De Backker +Rachel Chen Robert Eperjesi Ryan Gordon +Sam Lancia +Sean DuBois Sean DuBois Sean DuBois +Shelikhoo Stefan Tatschner +Steffen Vogel Vadim Vadim Filimonov wmiao ZHENK 吕海涛 + +# List of contributors not appearing in Git history + diff --git a/Makefile b/Makefile deleted file mode 100644 index 1df38b22..00000000 --- a/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -fuzz-build-record-layer: fuzz-prepare - go-fuzz-build -tags gofuzz -func FuzzRecordLayer -fuzz-run-record-layer: - go-fuzz -bin dtls-fuzz.zip -workdir fuzz -fuzz-prepare: - @GO111MODULE=on go mod vendor diff --git a/bench_test.go b/bench_test.go index 58e4f38c..8ca67ff9 100644 --- a/bench_test.go +++ b/bench_test.go @@ -10,7 +10,7 @@ import ( "github.com/pion/dtls/v2/internal/net/dpipe" "github.com/pion/dtls/v2/pkg/crypto/selfsign" "github.com/pion/logging" - "github.com/pion/transport/test" + "github.com/pion/transport/v2/test" ) func TestSimpleReadWrite(t *testing.T) { diff --git a/certificate.go b/certificate.go index c99e1c93..7211ae09 100644 --- a/certificate.go +++ b/certificate.go @@ -1,35 +1,102 @@ package dtls import ( + "bytes" "crypto/tls" "crypto/x509" + "fmt" "strings" ) -func (c *handshakeConfig) getCertificate(serverName string) (*tls.Certificate, error) { - c.mu.Lock() - defer c.mu.Unlock() +// ClientHelloInfo contains information from a ClientHello message in order to +// guide application logic in the GetCertificate. +type ClientHelloInfo struct { + // ServerName indicates the name of the server requested by the client + // in order to support virtual hosting. ServerName is only set if the + // client is using SNI (see RFC 4366, Section 3.1). + ServerName string - if c.nameToCertificate == nil { - nameToCertificate := make(map[string]*tls.Certificate) - for i := range c.localCertificates { - cert := &c.localCertificates[i] - x509Cert := cert.Leaf - if x509Cert == nil { - var parseErr error - x509Cert, parseErr = x509.ParseCertificate(cert.Certificate[0]) - if parseErr != nil { - continue - } + // CipherSuites lists the CipherSuites supported by the client (e.g. + // TLS_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256). + CipherSuites []CipherSuiteID +} + +// CertificateRequestInfo contains information from a server's +// CertificateRequest message, which is used to demand a certificate and proof +// of control from a client. +type CertificateRequestInfo 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 +} + +// SupportsCertificate returns nil if the provided certificate is supported by +// the server that sent the CertificateRequest. Otherwise, it returns an error +// describing the reason for the incompatibility. +// NOTE: original src: https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/common.go#L1273 +func (cri *CertificateRequestInfo) SupportsCertificate(c *tls.Certificate) error { + if len(cri.AcceptableCAs) == 0 { + return nil + } + + for j, cert := range c.Certificate { + x509Cert := c.Leaf + // Parse the certificate if this isn't the leaf node, or if + // chain.Leaf was nil. + if j != 0 || x509Cert == nil { + var err error + if x509Cert, err = x509.ParseCertificate(cert); err != nil { + return fmt.Errorf("failed to parse certificate #%d in the chain: %w", j, err) } - if len(x509Cert.Subject.CommonName) > 0 { - nameToCertificate[strings.ToLower(x509Cert.Subject.CommonName)] = cert + } + + for _, ca := range cri.AcceptableCAs { + if bytes.Equal(x509Cert.RawIssuer, ca) { + return nil } - for _, san := range x509Cert.DNSNames { - nameToCertificate[strings.ToLower(san)] = cert + } + } + return errNotAcceptableCertificateChain +} + +func (c *handshakeConfig) setNameToCertificateLocked() { + nameToCertificate := make(map[string]*tls.Certificate) + for i := range c.localCertificates { + cert := &c.localCertificates[i] + x509Cert := cert.Leaf + if x509Cert == nil { + var parseErr error + x509Cert, parseErr = x509.ParseCertificate(cert.Certificate[0]) + if parseErr != nil { + continue } } - c.nameToCertificate = nameToCertificate + if len(x509Cert.Subject.CommonName) > 0 { + nameToCertificate[strings.ToLower(x509Cert.Subject.CommonName)] = cert + } + for _, san := range x509Cert.DNSNames { + nameToCertificate[strings.ToLower(san)] = cert + } + } + c.nameToCertificate = nameToCertificate +} + +func (c *handshakeConfig) getCertificate(clientHelloInfo *ClientHelloInfo) (*tls.Certificate, error) { + c.mu.Lock() + defer c.mu.Unlock() + + if c.localGetCertificate != nil && + (len(c.localCertificates) == 0 || len(clientHelloInfo.ServerName) > 0) { + cert, err := c.localGetCertificate(clientHelloInfo) + if cert != nil || err != nil { + return cert, err + } + } + + if c.nameToCertificate == nil { + c.setNameToCertificateLocked() } if len(c.localCertificates) == 0 { @@ -41,11 +108,11 @@ func (c *handshakeConfig) getCertificate(serverName string) (*tls.Certificate, e return &c.localCertificates[0], nil } - if len(serverName) == 0 { + if len(clientHelloInfo.ServerName) == 0 { return &c.localCertificates[0], nil } - name := strings.TrimRight(strings.ToLower(serverName), ".") + name := strings.TrimRight(strings.ToLower(clientHelloInfo.ServerName), ".") if cert, ok := c.nameToCertificate[name]; ok { return cert, nil @@ -65,3 +132,23 @@ func (c *handshakeConfig) getCertificate(serverName string) (*tls.Certificate, e // If nothing matches, return the first certificate. return &c.localCertificates[0], nil } + +// NOTE: original src: https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/handshake_client.go#L974 +func (c *handshakeConfig) getClientCertificate(cri *CertificateRequestInfo) (*tls.Certificate, error) { + c.mu.Lock() + defer c.mu.Unlock() + if c.localGetClientCertificate != nil { + return c.localGetClientCertificate(cri) + } + + for i := range c.localCertificates { + chain := c.localCertificates[i] + if err := cri.SupportsCertificate(&chain); err != nil { + continue + } + return &chain, nil + } + + // No acceptable certificate found. Don't send a certificate. + return new(tls.Certificate), nil +} diff --git a/certificate_test.go b/certificate_test.go index 694c9471..7557aa24 100644 --- a/certificate_test.go +++ b/certificate_test.go @@ -24,47 +24,71 @@ func TestGetCertificate(t *testing.T) { t.Fatal(err) } - cfg := &handshakeConfig{ - localCertificates: []tls.Certificate{ - certificateRandom, - certificateTest, - certificateWildcard, - }, - } - testCases := []struct { + localCertificates []tls.Certificate desc string serverName string expectedCertificate tls.Certificate + getCertificate func(info *ClientHelloInfo) (*tls.Certificate, error) }{ { - desc: "Simple match in CN", + desc: "Simple match in CN", + localCertificates: []tls.Certificate{ + certificateRandom, + certificateTest, + certificateWildcard, + }, serverName: "test.test", expectedCertificate: certificateTest, }, { - desc: "Simple match in SANs", + desc: "Simple match in SANs", + localCertificates: []tls.Certificate{ + certificateRandom, + certificateTest, + certificateWildcard, + }, serverName: "www.test.test", expectedCertificate: certificateTest, }, { - desc: "Wildcard match", + desc: "Wildcard match", + localCertificates: []tls.Certificate{ + certificateRandom, + certificateTest, + certificateWildcard, + }, serverName: "foo.test.test", expectedCertificate: certificateWildcard, }, { - desc: "No match return first", + desc: "No match return first", + localCertificates: []tls.Certificate{ + certificateRandom, + certificateTest, + certificateWildcard, + }, serverName: "foo.bar", expectedCertificate: certificateRandom, }, + { + desc: "Get certificate from callback", + getCertificate: func(info *ClientHelloInfo) (*tls.Certificate, error) { + return &certificateTest, nil + }, + expectedCertificate: certificateTest, + }, } for _, test := range testCases { test := test - t.Run(test.desc, func(t *testing.T) { - cert, err := cfg.getCertificate(test.serverName) + cfg := &handshakeConfig{ + localCertificates: test.localCertificates, + localGetCertificate: test.getCertificate, + } + cert, err := cfg.getCertificate(&ClientHelloInfo{ServerName: test.serverName}) if err != nil { t.Fatal(err) } diff --git a/cipher_suite_test.go b/cipher_suite_test.go index e0ed6d1b..81ef2384 100644 --- a/cipher_suite_test.go +++ b/cipher_suite_test.go @@ -7,7 +7,7 @@ import ( "github.com/pion/dtls/v2/internal/ciphersuite" "github.com/pion/dtls/v2/internal/net/dpipe" - "github.com/pion/transport/test" + "github.com/pion/transport/v2/test" ) func TestCipherSuiteName(t *testing.T) { diff --git a/config.go b/config.go index 7f68c03b..13a17225 100644 --- a/config.go +++ b/config.go @@ -10,6 +10,7 @@ import ( "io" "time" + "github.com/pion/dtls/v2/pkg/crypto/elliptic" "github.com/pion/logging" ) @@ -82,6 +83,16 @@ type Config struct { // be considered but the verifiedChains will always be nil. VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error + // VerifyConnection, if not nil, is called after normal certificate + // verification/PSK and after VerifyPeerCertificate by either a TLS client + // or server. If it returns a non-nil error, the handshake is aborted + // and that error results. + // + // If normal verification fails then the handshake will abort before + // considering this callback. This callback will run for all connections + // regardless of InsecureSkipVerify or ClientAuth settings. + VerifyConnection func(*State) error + // RootCAs defines the set of root certificate authorities // that one peer uses when verifying the other peer's certificates. // If RootCAs is nil, TLS uses the host's root CA set. @@ -130,6 +141,38 @@ type Config struct { // List of application protocols the peer supports, for ALPN SupportedProtocols []string + + // List of Elliptic Curves to use + // + // If an ECC ciphersuite is configured and EllipticCurves is empty + // it will default to X25519, P-256, P-384 in this specific order. + EllipticCurves []elliptic.Curve + + // GetCertificate returns a Certificate based on the given + // ClientHelloInfo. It will only be called if the client supplies SNI + // information or if Certificates is empty. + // + // If GetCertificate is nil or returns nil, then the certificate is + // retrieved from NameToCertificate. If NameToCertificate is nil, the + // best element of Certificates will be used. + GetCertificate func(*ClientHelloInfo) (*tls.Certificate, error) + + // GetClientCertificate, if not nil, is called when a server requests a + // certificate from a client. If set, the contents of Certificates will + // be ignored. + // + // If GetClientCertificate returns an error, the handshake will be + // aborted and that error will be returned. Otherwise + // GetClientCertificate must return a non-nil Certificate. If + // Certificate.Certificate is empty then no certificate will be sent to + // the server. If this is unacceptable to the server then it may abort + // the handshake. + GetClientCertificate func(*CertificateRequestInfo) (*tls.Certificate, error) + + // InsecureSkipVerifyHello, if true and when acting as server, allow client to + // skip hello verify phase and receive ServerHello after initial ClientHello. + // This have implication on DoS attack resistance. + InsecureSkipVerifyHello bool } func defaultConnectContextMaker() (context.Context, func()) { @@ -143,8 +186,14 @@ func (c *Config) connectContextMaker() (context.Context, func()) { return c.ConnectContextMaker() } +func (c *Config) includeCertificateSuites() bool { + return c.PSK == nil || len(c.Certificates) > 0 || c.GetCertificate != nil || c.GetClientCertificate != nil +} + const defaultMTU = 1200 // bytes +var defaultCurves = []elliptic.Curve{elliptic.X25519, elliptic.P256, elliptic.P384} //nolint:gochecknoglobals + // PSKCallback is called once we have the remote's PSKIdentityHint. // If the remote provided none it will be nil type PSKCallback func([]byte) ([]byte, error) @@ -196,6 +245,6 @@ func validateConfig(config *Config) error { } } - _, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.PSK == nil || len(config.Certificates) > 0, config.PSK != nil) + _, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil) return err } diff --git a/config_test.go b/config_test.go index d9360f3c..b99755ac 100644 --- a/config_test.go +++ b/config_test.go @@ -12,63 +12,11 @@ import ( ) func TestValidateConfig(t *testing.T) { - // Empty config - if err := validateConfig(nil); !errors.Is(err, errNoConfigProvided) { - t.Fatalf("TestValidateConfig: Config validation error exp(%v) failed(%v)", errNoConfigProvided, err) - } - - // PSK and Certificate, valid cipher suites cert, err := selfsign.GenerateSelfSigned() if err != nil { t.Fatalf("TestValidateConfig: Config validation error(%v), self signed certificate not generated", err) return } - config := &Config{ - CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, - PSK: func(hint []byte) ([]byte, error) { - return nil, nil - }, - Certificates: []tls.Certificate{cert}, - } - if err = validateConfig(config); err != nil { - t.Fatalf("TestValidateConfig: Client error exp(%v) failed(%v)", nil, err) - } - - // PSK and Certificate, no PSK cipher suite - config = &Config{ - CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, - PSK: func(hint []byte) ([]byte, error) { - return nil, nil - }, - Certificates: []tls.Certificate{cert}, - } - if err = validateConfig(config); !errors.Is(errNoAvailablePSKCipherSuite, err) { - t.Fatalf("TestValidateConfig: Client error exp(%v) failed(%v)", errNoAvailablePSKCipherSuite, err) - } - - // PSK and Certificate, no non-PSK cipher suite - config = &Config{ - CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, - PSK: func(hint []byte) ([]byte, error) { - return nil, nil - }, - Certificates: []tls.Certificate{cert}, - } - if err = validateConfig(config); !errors.Is(errNoAvailableCertificateCipherSuite, err) { - t.Fatalf("TestValidateConfig: Client error exp(%v) failed(%v)", errNoAvailableCertificateCipherSuite, err) - } - - // PSK identity hint with not PSK - config = &Config{ - CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, - PSK: nil, - PSKIdentityHint: []byte{}, - } - if err = validateConfig(config); !errors.Is(err, errIdentityNoPSK) { - t.Fatalf("TestValidateConfig: Client error exp(%v) failed(%v)", errIdentityNoPSK, err) - } - - // Invalid private key dsaPrivateKey := &dsa.PrivateKey{} err = dsa.GenerateParameters(&dsaPrivateKey.Parameters, rand.Reader, dsa.L1024N160) if err != nil { @@ -80,40 +28,110 @@ func TestValidateConfig(t *testing.T) { t.Fatalf("TestValidateConfig: Config validation error(%v), DSA private key not generated", err) return } - config = &Config{ - CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, - Certificates: []tls.Certificate{{Certificate: cert.Certificate, PrivateKey: dsaPrivateKey}}, - } - if err = validateConfig(config); !errors.Is(err, errInvalidPrivateKey) { - t.Fatalf("TestValidateConfig: Client error exp(%v) failed(%v)", errInvalidPrivateKey, err) - } - - // PrivateKey without Certificate - config = &Config{ - CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, - Certificates: []tls.Certificate{{PrivateKey: cert.PrivateKey}}, - } - if err = validateConfig(config); !errors.Is(err, errInvalidCertificate) { - t.Fatalf("TestValidateConfig: Client error exp(%v) failed(%v)", errInvalidCertificate, err) - } - - // Invalid cipher suites - config = &Config{CipherSuites: []CipherSuiteID{0x0000}} - if err = validateConfig(config); err == nil { - t.Fatal("TestValidateConfig: Client error expected with invalid CipherSuiteID") - } - - // Valid config rsaPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { t.Fatalf("TestValidateConfig: Config validation error(%v), RSA private key not generated", err) return } - config = &Config{ - CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, - Certificates: []tls.Certificate{cert, {Certificate: cert.Certificate, PrivateKey: rsaPrivateKey}}, + cases := map[string]struct { + config *Config + wantAnyErr bool + expErr error + }{ + "Empty config": { + expErr: errNoConfigProvided, + }, + "PSK and Certificate, valid cipher suites": { + config: &Config{ + CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + PSK: func(hint []byte) ([]byte, error) { + return nil, nil + }, + Certificates: []tls.Certificate{cert}, + }, + }, + "PSK and Certificate, no PSK cipher suite": { + config: &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + PSK: func(hint []byte) ([]byte, error) { + return nil, nil + }, + Certificates: []tls.Certificate{cert}, + }, + expErr: errNoAvailablePSKCipherSuite, + }, + "PSK and Certificate, no non-PSK cipher suite": { + config: &Config{ + CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, + PSK: func(hint []byte) ([]byte, error) { + return nil, nil + }, + Certificates: []tls.Certificate{cert}, + }, + expErr: errNoAvailableCertificateCipherSuite, + }, + "PSK identity hint with not PSK": { + config: &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + PSK: nil, + PSKIdentityHint: []byte{}, + }, + expErr: errIdentityNoPSK, + }, + "Invalid private key": { + config: &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + Certificates: []tls.Certificate{{Certificate: cert.Certificate, PrivateKey: dsaPrivateKey}}, + }, + expErr: errInvalidPrivateKey, + }, + "PrivateKey without Certificate": { + config: &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + Certificates: []tls.Certificate{{PrivateKey: cert.PrivateKey}}, + }, + expErr: errInvalidCertificate, + }, + "Invalid cipher suites": { + config: &Config{CipherSuites: []CipherSuiteID{0x0000}}, + wantAnyErr: true, + }, + "Valid config": { + config: &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + Certificates: []tls.Certificate{cert, {Certificate: cert.Certificate, PrivateKey: rsaPrivateKey}}, + }, + }, + "Valid config with get certificate": { + config: &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + GetCertificate: func(chi *ClientHelloInfo) (*tls.Certificate, error) { + return &tls.Certificate{Certificate: cert.Certificate, PrivateKey: rsaPrivateKey}, nil + }, + }, + }, + "Valid config with get client certificate": { + config: &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + GetClientCertificate: func(cri *CertificateRequestInfo) (*tls.Certificate, error) { + return &tls.Certificate{Certificate: cert.Certificate, PrivateKey: rsaPrivateKey}, nil + }, + }, + }, } - if err = validateConfig(config); err != nil { - t.Fatalf("TestValidateConfig: Client error exp(%v) failed(%v)", nil, err) + + for name, testCase := range cases { + testCase := testCase + t.Run(name, func(t *testing.T) { + err := validateConfig(testCase.config) + if testCase.expErr != nil || testCase.wantAnyErr { + if testCase.expErr != nil && !errors.Is(err, testCase.expErr) { + t.Fatalf("TestValidateConfig: Config validation error exp(%v) failed(%v)", testCase.expErr, err) + } + if err == nil { + t.Fatalf("TestValidateConfig: Config validation expected an error") + } + } + }) } } diff --git a/conn.go b/conn.go index aff5a95f..086095a4 100644 --- a/conn.go +++ b/conn.go @@ -18,9 +18,9 @@ import ( "github.com/pion/dtls/v2/pkg/protocol/handshake" "github.com/pion/dtls/v2/pkg/protocol/recordlayer" "github.com/pion/logging" - "github.com/pion/transport/connctx" - "github.com/pion/transport/deadline" - "github.com/pion/transport/replaydetector" + "github.com/pion/transport/v2/connctx" + "github.com/pion/transport/v2/deadline" + "github.com/pion/transport/v2/replaydetector" ) const ( @@ -28,7 +28,7 @@ const ( cookieLength = 20 sessionLength = 32 defaultNamedCurve = elliptic.X25519 - inboundBufferSize = 8192 + inboundBufferSize = 2048 // Default replay protection window is specified by RFC 6347 Section 4.1.2.6 defaultReplayProtectionWindow = 64 ) @@ -88,7 +88,7 @@ func createConn(ctx context.Context, nextConn net.Conn, config *Config, isClient return nil, errNilNextConn } - cipherSuites, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.PSK == nil || len(config.Certificates) > 0, config.PSK != nil) + cipherSuites, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil) if err != nil { return nil, err } @@ -154,6 +154,11 @@ func createConn(ctx context.Context, nextConn net.Conn, config *Config, isClient serverName = "" } + curves := config.EllipticCurves + if len(curves) == 0 { + curves = defaultCurves + } + hsCfg := &handshakeConfig{ localPSKCallback: config.PSK, localPSKIdentityHint: config.PSKIdentityHint, @@ -167,6 +172,7 @@ func createConn(ctx context.Context, nextConn net.Conn, config *Config, isClient localCertificates: config.Certificates, insecureSkipVerify: config.InsecureSkipVerify, verifyPeerCertificate: config.VerifyPeerCertificate, + verifyConnection: config.VerifyConnection, rootCAs: config.RootCAs, clientCAs: config.ClientCAs, customCipherSuites: config.CustomCipherSuites, @@ -175,13 +181,17 @@ func createConn(ctx context.Context, nextConn net.Conn, config *Config, isClient initialEpoch: 0, keyLogWriter: config.KeyLogWriter, sessionStore: config.SessionStore, + ellipticCurves: curves, + localGetCertificate: config.GetCertificate, + localGetClientCertificate: config.GetClientCertificate, + insecureSkipHelloVerify: config.InsecureSkipVerifyHello, } // rfc5246#section-7.4.3 // In addition, the hash and signature algorithms MUST be compatible // with the key in the server's end-entity certificate. if !isClient { - cert, err := hsCfg.getCertificate("") + cert, err := hsCfg.getCertificate(&ClientHelloInfo{}) if err != nil && !errors.Is(err, errNoCertificates) { return nil, err } @@ -567,6 +577,7 @@ func (c *Conn) readAndBuffer(ctx context.Context) error { defer poolReadBuffer.Put(bufptr) b := *bufptr + b = b[128:] i, err := c.nextConn.ReadContext(ctx, b) if err != nil { return netError(err) @@ -889,6 +900,10 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh _ = c.close(false) //nolint:contextcheck } } + if !c.isConnectionClosed() && errors.Is(err, context.Canceled) { + c.log.Trace("handshake timeouts - closing underline connection") + _ = c.close(false) //nolint:contextcheck + } return } } @@ -898,10 +913,12 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh case err := <-firstErr: cancelRead() cancel() + c.handshakeLoopsFinished.Wait() return c.translateHandshakeCtxError(err) case <-ctx.Done(): cancelRead() cancel() + c.handshakeLoopsFinished.Wait() return c.translateHandshakeCtxError(ctx.Err()) case <-done: return nil @@ -934,6 +951,7 @@ func (c *Conn) close(byUser bool) error { if byUser { c.connectionClosedByUser = true } + isClosed := c.isConnectionClosed() c.closed.Close() c.closeLock.Unlock() @@ -941,6 +959,10 @@ func (c *Conn) close(byUser bool) error { return ErrConnClosed } + if isClosed { + return nil + } + return c.nextConn.Close() } diff --git a/conn_go_test.go b/conn_go_test.go index b6d61839..3dd4e938 100644 --- a/conn_go_test.go +++ b/conn_go_test.go @@ -14,7 +14,7 @@ import ( "github.com/pion/dtls/v2/internal/net/dpipe" "github.com/pion/dtls/v2/pkg/crypto/selfsign" - "github.com/pion/transport/test" + "github.com/pion/transport/v2/test" ) func TestContextConfig(t *testing.T) { diff --git a/conn_test.go b/conn_test.go index 9810971f..d9e76860 100644 --- a/conn_test.go +++ b/conn_test.go @@ -15,6 +15,7 @@ import ( "fmt" "io" "net" + "strings" "sync" "sync/atomic" "testing" @@ -32,7 +33,8 @@ import ( "github.com/pion/dtls/v2/pkg/protocol/extension" "github.com/pion/dtls/v2/pkg/protocol/handshake" "github.com/pion/dtls/v2/pkg/protocol/recordlayer" - "github.com/pion/transport/test" + "github.com/pion/logging" + "github.com/pion/transport/v2/test" ) var ( @@ -273,6 +275,7 @@ func pipeConn(ca, cb net.Conn) (*Conn, *Conn, error) { // Receive client res := <-c if res.err != nil { + _ = server.Close() return nil, nil, res.err } @@ -466,15 +469,42 @@ func TestPSK(t *testing.T) { defer report() for _, test := range []struct { - Name string - ServerIdentity []byte - CipherSuites []CipherSuiteID + Name string + ServerIdentity []byte + CipherSuites []CipherSuiteID + ClientVerifyConnection func(*State) error + ServerVerifyConnection func(*State) error + WantFail bool + ExpectedServerErr string + ExpectedClientErr string }{ { Name: "Server identity specified", ServerIdentity: []byte("Test Identity"), CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, }, + { + Name: "Server identity specified - Server verify connection fails", + ServerIdentity: []byte("Test Identity"), + CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, + ServerVerifyConnection: func(s *State) error { + return errExample + }, + WantFail: true, + ExpectedServerErr: errExample.Error(), + ExpectedClientErr: alert.BadCertificate.String(), + }, + { + Name: "Server identity specified - Client verify connection fails", + ServerIdentity: []byte("Test Identity"), + CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, + ClientVerifyConnection: func(s *State) error { + return errExample + }, + WantFail: true, + ExpectedServerErr: alert.BadCertificate.String(), + ExpectedClientErr: errExample.Error(), + }, { Name: "Server identity nil", ServerIdentity: nil, @@ -513,8 +543,9 @@ func TestPSK(t *testing.T) { return []byte{0xAB, 0xC1, 0x23}, nil }, - PSKIdentityHint: clientIdentity, - CipherSuites: test.CipherSuites, + PSKIdentityHint: clientIdentity, + CipherSuites: test.CipherSuites, + VerifyConnection: test.ClientVerifyConnection, } c, err := testClient(ctx, ca, conf, false) @@ -528,11 +559,22 @@ func TestPSK(t *testing.T) { } return []byte{0xAB, 0xC1, 0x23}, nil }, - PSKIdentityHint: test.ServerIdentity, - CipherSuites: test.CipherSuites, + PSKIdentityHint: test.ServerIdentity, + CipherSuites: test.CipherSuites, + VerifyConnection: test.ServerVerifyConnection, } server, err := testServer(ctx, cb, config, false) + if test.WantFail { + res := <-clientRes + if err == nil || !strings.Contains(err.Error(), test.ExpectedServerErr) { + t.Fatalf("TestPSK: Server expected(%v) actual(%v)", test.ExpectedServerErr, err) + } + if res.err == nil || !strings.Contains(res.err.Error(), test.ExpectedClientErr) { + t.Fatalf("TestPSK: Client expected(%v) actual(%v)", test.ExpectedClientErr, res.err) + } + return + } if err != nil { t.Fatalf("TestPSK: Server failed(%v)", err) } @@ -788,6 +830,29 @@ func TestClientCertificate(t *testing.T) { ClientCAs: caPool, }, }, + "NoClientCert_ServerVerifyConnectionFails": { + clientCfg: &Config{RootCAs: srvCAPool}, + serverCfg: &Config{ + Certificates: []tls.Certificate{srvCert}, + ClientAuth: NoClientCert, + ClientCAs: caPool, + VerifyConnection: func(s *State) error { + return errExample + }, + }, + wantErr: true, + }, + "NoClientCert_ClientVerifyConnectionFails": { + clientCfg: &Config{RootCAs: srvCAPool, VerifyConnection: func(s *State) error { + return errExample + }}, + serverCfg: &Config{ + Certificates: []tls.Certificate{srvCert}, + ClientAuth: NoClientCert, + ClientCAs: caPool, + }, + wantErr: true, + }, "NoClientCert_cert": { clientCfg: &Config{RootCAs: srvCAPool, Certificates: []tls.Certificate{cert}}, serverCfg: &Config{ @@ -850,11 +915,35 @@ func TestClientCertificate(t *testing.T) { wantErr: true, }, "RequireAndVerifyClientCert": { - clientCfg: &Config{RootCAs: srvCAPool, Certificates: []tls.Certificate{cert}}, + clientCfg: &Config{RootCAs: srvCAPool, Certificates: []tls.Certificate{cert}, VerifyConnection: func(s *State) error { + if ok := bytes.Equal(s.PeerCertificates[0], srvCertificate.Raw); !ok { + return errExample + } + return nil + }}, serverCfg: &Config{ Certificates: []tls.Certificate{srvCert}, ClientAuth: RequireAndVerifyClientCert, ClientCAs: caPool, + VerifyConnection: func(s *State) error { + if ok := bytes.Equal(s.PeerCertificates[0], certificate.Raw); !ok { + return errExample + } + return nil + }, + }, + }, + "RequireAndVerifyClientCert_callbacks": { + clientCfg: &Config{ + RootCAs: srvCAPool, + // Certificates: []tls.Certificate{cert}, + GetClientCertificate: func(cri *CertificateRequestInfo) (*tls.Certificate, error) { return &cert, nil }, + }, + serverCfg: &Config{ + GetCertificate: func(chi *ClientHelloInfo) (*tls.Certificate, error) { return &srvCert, nil }, + // Certificates: []tls.Certificate{srvCert}, + ClientAuth: RequireAndVerifyClientCert, + ClientCAs: caPool, }, }, } @@ -905,7 +994,18 @@ func TestClientCertificate(t *testing.T) { t.Errorf("Client did not provide a certificate") } - if len(actualClientCert) != len(tt.clientCfg.Certificates[0].Certificate) || !bytes.Equal(tt.clientCfg.Certificates[0].Certificate[0], actualClientCert[0]) { + var cfgCert [][]byte + if len(tt.clientCfg.Certificates) > 0 { + cfgCert = tt.clientCfg.Certificates[0].Certificate + } + if tt.clientCfg.GetClientCertificate != nil { + crt, err := tt.clientCfg.GetClientCertificate(&CertificateRequestInfo{}) + if err != nil { + t.Errorf("Server configuration did not provide a certificate") + } + cfgCert = crt.Certificate + } + if len(cfgCert) == 0 || !bytes.Equal(cfgCert[0], actualClientCert[0]) { t.Errorf("Client certificate was not communicated correctly") } } @@ -919,8 +1019,18 @@ func TestClientCertificate(t *testing.T) { if actualServerCert == nil { t.Errorf("Server did not provide a certificate") } - - if len(actualServerCert) != len(tt.serverCfg.Certificates[0].Certificate) || !bytes.Equal(tt.serverCfg.Certificates[0].Certificate[0], actualServerCert[0]) { + var cfgCert [][]byte + if len(tt.serverCfg.Certificates) > 0 { + cfgCert = tt.serverCfg.Certificates[0].Certificate + } + if tt.serverCfg.GetCertificate != nil { + crt, err := tt.serverCfg.GetCertificate(&ClientHelloInfo{}) + if err != nil { + t.Errorf("Server configuration did not provide a certificate") + } + cfgCert = crt.Certificate + } + if len(cfgCert) == 0 || !bytes.Equal(cfgCert[0], actualServerCert[0]) { t.Errorf("Server certificate was not communicated correctly") } }) @@ -1275,6 +1385,7 @@ func TestCipherSuiteConfiguration(t *testing.T) { res := <-c if res.err == nil { _ = server.Close() + _ = res.c.Close() } if !errors.Is(res.err, test.WantClientError) { t.Errorf("TestSRTPConfiguration: Client Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantClientError, res.err) @@ -1349,6 +1460,7 @@ func TestCertificateAndPSKServer(t *testing.T) { res := <-c if res.err == nil { _ = server.Close() + _ = res.c.Close() } else { t.Errorf("TestCertificateAndPSKServer: Client Error Mismatch '%s': expected(%v) actual(%v)", test.Name, nil, res.err) } @@ -2724,3 +2836,137 @@ func TestMultipleServerCertificates(t *testing.T) { }) } } + +func TestEllipticCurveConfiguration(t *testing.T) { + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + for _, test := range []struct { + Name string + ConfigCurves []elliptic.Curve + HadnshakeCurves []elliptic.Curve + }{ + { + Name: "Curve defaulting", + ConfigCurves: nil, + HadnshakeCurves: defaultCurves, + }, + { + Name: "Single curve", + ConfigCurves: []elliptic.Curve{elliptic.X25519}, + HadnshakeCurves: []elliptic.Curve{elliptic.X25519}, + }, + { + Name: "Multiple curves", + ConfigCurves: []elliptic.Curve{elliptic.P384, elliptic.X25519}, + HadnshakeCurves: []elliptic.Curve{elliptic.P384, elliptic.X25519}, + }, + } { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + ca, cb := dpipe.Pipe() + type result struct { + c *Conn + err error + } + c := make(chan result) + + go func() { + client, err := testClient(ctx, ca, &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, EllipticCurves: test.ConfigCurves}, true) + c <- result{client, err} + }() + + server, err := testServer(ctx, cb, &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, EllipticCurves: test.ConfigCurves}, true) + if err != nil { + t.Fatalf("Server error: %v", err) + } + + if len(test.ConfigCurves) == 0 && len(test.HadnshakeCurves) != len(server.fsm.cfg.ellipticCurves) { + t.Fatalf("Failed to default Elliptic curves, expected %d, got: %d", len(test.HadnshakeCurves), len(server.fsm.cfg.ellipticCurves)) + } + + if len(test.ConfigCurves) != 0 { + if len(test.HadnshakeCurves) != len(server.fsm.cfg.ellipticCurves) { + t.Fatalf("Failed to configure Elliptic curves, expect %d, got %d", len(test.HadnshakeCurves), len(server.fsm.cfg.ellipticCurves)) + } + for i, c := range test.ConfigCurves { + if c != server.fsm.cfg.ellipticCurves[i] { + t.Fatalf("Failed to maintain Elliptic curve order, expected %s, got %s", c, server.fsm.cfg.ellipticCurves[i]) + } + } + } + + res := <-c + if res.err != nil { + t.Fatalf("Client error; %v", err) + } + + defer func() { + err = server.Close() + if err != nil { + t.Fatal(err) + } + err = res.c.Close() + if err != nil { + t.Fatal(err) + } + }() + } +} + +func TestSkipHelloVerify(t *testing.T) { + report := test.CheckRoutines(t) + defer report() + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + ca, cb := dpipe.Pipe() + certificate, err := selfsign.GenerateSelfSigned() + if err != nil { + t.Fatal(err) + } + gotHello := make(chan struct{}) + + go func() { + server, sErr := testServer(ctx, cb, &Config{ + Certificates: []tls.Certificate{certificate}, + LoggerFactory: logging.NewDefaultLoggerFactory(), + InsecureSkipVerifyHello: true, + }, false) + if sErr != nil { + t.Error(sErr) + return + } + buf := make([]byte, 1024) + if _, sErr = server.Read(buf); sErr != nil { + t.Error(sErr) + } + gotHello <- struct{}{} + if sErr = server.Close(); sErr != nil { //nolint:contextcheck + t.Error(sErr) + } + }() + + client, err := testClient(ctx, ca, &Config{ + LoggerFactory: logging.NewDefaultLoggerFactory(), + InsecureSkipVerify: true, + }, false) + if err != nil { + t.Fatal(err) + } + if _, err = client.Write([]byte("hello")); err != nil { + t.Error(err) + } + select { + case <-gotHello: + // OK + case <-time.After(time.Second * 5): + t.Error("timeout") + } + + if err = client.Close(); err != nil { + t.Error(err) + } +} diff --git a/e2e/Dockerfile b/e2e/Dockerfile index aa256b25..7192a5f9 100644 --- a/e2e/Dockerfile +++ b/e2e/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/library/golang:bullseye +FROM docker.io/library/golang:1.18-bullseye COPY . /go/src/github.com/pion/dtls WORKDIR /go/src/github.com/pion/dtls/e2e diff --git a/e2e/e2e_lossy_test.go b/e2e/e2e_lossy_test.go index 92a4074d..4ca9a0c5 100644 --- a/e2e/e2e_lossy_test.go +++ b/e2e/e2e_lossy_test.go @@ -9,7 +9,7 @@ import ( "github.com/pion/dtls/v2" "github.com/pion/dtls/v2/pkg/crypto/selfsign" - transportTest "github.com/pion/transport/test" + transportTest "github.com/pion/transport/v2/test" ) const ( @@ -18,7 +18,7 @@ const ( ) /* - DTLS Client/Server over a lossy transport, just asserts it can handle at increasing increments +DTLS Client/Server over a lossy transport, just asserts it can handle at increasing increments */ func TestPionE2ELossy(t *testing.T) { // Check for leaking routines diff --git a/e2e/e2e_openssl_test.go b/e2e/e2e_openssl_test.go index 804b54f4..a9f0e4dd 100644 --- a/e2e/e2e_openssl_test.go +++ b/e2e/e2e_openssl_test.go @@ -114,7 +114,6 @@ func clientOpenSSL(c *comm) { "-dtls1_2", "-quiet", "-verify_quiet", - "-verify_return_error", "-servername=localhost", fmt.Sprintf("-connect=127.0.0.1:%d", c.serverPort), } @@ -141,12 +140,15 @@ func clientOpenSSL(c *comm) { c.errChan <- err return } - args = append(args, fmt.Sprintf("-CAfile=%s", certPEM)) + args = append(args, fmt.Sprintf("-CAfile=%s", certPEM), fmt.Sprintf("-cert=%s", certPEM), fmt.Sprintf("-key=%s", keyPEM)) defer func() { _ = os.Remove(certPEM) _ = os.Remove(keyPEM) }() } + if !cfg.InsecureSkipVerify { + args = append(args, "-verify_return_error") + } // launch command // #nosec G204 @@ -295,10 +297,31 @@ func TestPionOpenSSLE2ESimpleED25519(t *testing.T) { t.Run("OpenSSLServer", func(t *testing.T) { if !minimumOpenSSLVersion(t) { t.Skip("Cannot use OpenSSL < 3.0 as a DTLS server with ED25519 keys") - testPionE2ESimpleED25519(t, serverOpenSSL, clientPion) } + testPionE2ESimpleED25519(t, serverOpenSSL, clientPion) }) t.Run("OpenSSLClient", func(t *testing.T) { testPionE2ESimpleED25519(t, serverPion, clientOpenSSL) }) } + +func TestPionOpenSSLE2ESimpleED25519ClientCert(t *testing.T) { + t.Run("OpenSSLServer", func(t *testing.T) { + if !minimumOpenSSLVersion(t) { + t.Skip("Cannot use OpenSSL < 3.0 as a DTLS server with ED25519 keys") + } + testPionE2ESimpleED25519ClientCert(t, serverOpenSSL, clientPion) + }) + t.Run("OpenSSLClient", func(t *testing.T) { + testPionE2ESimpleED25519ClientCert(t, serverPion, clientOpenSSL) + }) +} + +func TestPionOpenSSLE2ESimpleECDSAClientCert(t *testing.T) { + t.Run("OpenSSLServer", func(t *testing.T) { + testPionE2ESimpleECDSAClientCert(t, serverOpenSSL, clientPion) + }) + t.Run("OpenSSLClient", func(t *testing.T) { + testPionE2ESimpleECDSAClientCert(t, serverPion, clientOpenSSL) + }) +} diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index f12d76e8..1c6b1a10 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -9,6 +9,7 @@ import ( "crypto/rand" "crypto/rsa" "crypto/tls" + "crypto/x509" "errors" "fmt" "io" @@ -20,7 +21,7 @@ import ( "github.com/pion/dtls/v2" "github.com/pion/dtls/v2/pkg/crypto/selfsign" - "github.com/pion/transport/test" + "github.com/pion/transport/v2/test" ) const ( @@ -216,10 +217,10 @@ func serverPion(c *comm) { } /* - Simple DTLS Client/Server can communicate - - Assert that you can send messages both ways - - Assert that Close() on both ends work - - Assert that no Goroutines are leaked + Simple DTLS Client/Server can communicate + - Assert that you can send messages both ways + - Assert that Close() on both ends work + - Assert that no Goroutines are leaked */ func testPionE2ESimple(t *testing.T, server, client func(*comm)) { lim := test.TimeOut(time.Second * 30) @@ -426,7 +427,15 @@ func testPionE2ESimpleECDSAClientCert(t *testing.T, server, client func(*comm)) t.Fatal(err) } + clientCAs := x509.NewCertPool() + caCert, err := x509.ParseCertificate(ccert.Certificate[0]) + if err != nil { + t.Fatal(err) + } + clientCAs.AddCert(caCert) + scfg := &dtls.Config{ + ClientCAs: clientCAs, Certificates: []tls.Certificate{scert}, CipherSuites: []dtls.CipherSuiteID{dtls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, ClientAuth: dtls.RequireAnyClientCert, diff --git a/errors.go b/errors.go index 09c6ffe9..df16a21d 100644 --- a/errors.go +++ b/errors.go @@ -54,6 +54,7 @@ var ( errServerNoMatchingSRTPProfile = &FatalError{Err: errors.New("client requested SRTP but we have no matching profiles")} //nolint:goerr113 errServerRequiredButNoClientEMS = &FatalError{Err: errors.New("server requires the Extended Master Secret extension, but the client does not support it")} //nolint:goerr113 errVerifyDataMismatch = &FatalError{Err: errors.New("expected and actual verify data does not match")} //nolint:goerr113 + errNotAcceptableCertificateChain = &FatalError{Err: errors.New("certificate chain is not signed by an acceptable CA")} //nolint:goerr113 errInvalidFlight = &InternalError{Err: errors.New("invalid flight number")} //nolint:goerr113 errKeySignatureGenerateUnimplemented = &InternalError{Err: errors.New("unable to generate key signature, unimplemented")} //nolint:goerr113 diff --git a/flight0handler.go b/flight0handler.go index 0b16eb6a..fa4720e0 100644 --- a/flight0handler.go +++ b/flight0handler.go @@ -81,7 +81,13 @@ func flight0Parse(ctx context.Context, c flightConn, state *State, cache *handsh } } - return handleHelloResume(clientHello.SessionID, state, cfg, flight2) + nextFlight := flight2 + + if cfg.insecureSkipHelloVerify { + nextFlight = flight4 + } + + return handleHelloResume(clientHello.SessionID, state, cfg, nextFlight) } func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, next flightVal) (flightVal, *alert.Alert, error) { @@ -109,9 +115,11 @@ func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, nex func flight0Generate(c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { // Initialize - state.cookie = make([]byte, cookieLength) - if _, err := rand.Read(state.cookie); err != nil { - return nil, nil, err + if !cfg.insecureSkipHelloVerify { + state.cookie = make([]byte, cookieLength) + if _, err := rand.Read(state.cookie); err != nil { + return nil, nil, err + } } var zeroEpoch uint16 diff --git a/flight1handler.go b/flight1handler.go index 3e14eddb..7cfcea8f 100644 --- a/flight1handler.go +++ b/flight1handler.go @@ -74,7 +74,7 @@ func flight1Generate(c flightConn, state *State, cache *handshakeCache, cfg *han if setEllipticCurveCryptographyClientHelloExtensions { extensions = append(extensions, []extension.Extension{ &extension.SupportedEllipticCurves{ - EllipticCurves: []elliptic.Curve{elliptic.X25519, elliptic.P256, elliptic.P384}, + EllipticCurves: cfg.ellipticCurves, }, &extension.SupportedPointFormats{ PointFormats: []elliptic.CurvePointFormat{elliptic.CurvePointFormatUncompressed}, diff --git a/flight4handler.go b/flight4handler.go index 5d35f5f5..9792e0a9 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -5,6 +5,7 @@ import ( "crypto/rand" "crypto/x509" + "github.com/pion/dtls/v2/internal/ciphersuite" "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" "github.com/pion/dtls/v2/pkg/crypto/elliptic" "github.com/pion/dtls/v2/pkg/crypto/prf" @@ -91,7 +92,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh state.peerCertificatesVerified = verified } else if state.PeerCertificates != nil { // A certificate was received, but we haven't seen a CertificateVerify - // keep reading until we receieve one + // keep reading until we receive one return 0, nil, nil } @@ -178,6 +179,11 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh } if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeAnonymous { + if cfg.verifyConnection != nil { + if err := cfg.verifyConnection(state.clone()); err != nil { + return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err + } + } return flight6, nil, nil } @@ -198,7 +204,12 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, errClientCertificateNotVerified } case NoClientCert, RequestClientCert: - return flight6, nil, nil + // go to flight6 + } + if cfg.verifyConnection != nil { + if err := cfg.verifyConnection(state.clone()); err != nil { + return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err + } } return flight6, nil, nil @@ -266,7 +277,10 @@ func flight4Generate(c flightConn, state *State, cache *handshakeCache, cfg *han switch { case state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate: - certificate, err := cfg.getCertificate(state.serverName) + certificate, err := cfg.getCertificate(&ClientHelloInfo{ + ServerName: state.serverName, + CipherSuites: []ciphersuite.ID{state.cipherSuite.ID()}, + }) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, err } @@ -318,6 +332,16 @@ func flight4Generate(c flightConn, state *State, cache *handshakeCache, cfg *han }) if cfg.clientAuth > NoClientCert { + // An empty list of certificateAuthorities signals to + // the client that it may send any certificate in response + // to our request. When we know the CAs we trust, then + // we can send them down, so that the client can choose + // an appropriate certificate to give to us. + var certificateAuthorities [][]byte + if cfg.clientCAs != nil { + // nolint:staticcheck // ignoring tlsCert.RootCAs.Subjects is deprecated ERR because cert does not come from SystemCertPool and it's ok if certificate authorities is empty. + certificateAuthorities = cfg.clientCAs.Subjects() + } pkts = append(pkts, &packet{ record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ @@ -325,8 +349,9 @@ func flight4Generate(c flightConn, state *State, cache *handshakeCache, cfg *han }, Content: &handshake.Handshake{ Message: &handshake.MessageCertificateRequest{ - CertificateTypes: []clientcertificate.Type{clientcertificate.RSASign, clientcertificate.ECDSASign}, - SignatureHashAlgorithms: cfg.localSignatureSchemes, + CertificateTypes: []clientcertificate.Type{clientcertificate.RSASign, clientcertificate.ECDSASign}, + SignatureHashAlgorithms: cfg.localSignatureSchemes, + CertificateAuthoritiesNames: certificateAuthorities, }, }, }, diff --git a/flight4handler_test.go b/flight4handler_test.go index c38feaf3..46d3fb7b 100644 --- a/flight4handler_test.go +++ b/flight4handler_test.go @@ -8,7 +8,7 @@ import ( "github.com/pion/dtls/v2/internal/ciphersuite" "github.com/pion/dtls/v2/pkg/protocol/alert" "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/transport/test" + "github.com/pion/transport/v2/test" ) type flight4TestMockFlightConn struct{} diff --git a/flight5handler.go b/flight5handler.go index 86435a53..5a60973d 100644 --- a/flight5handler.go +++ b/flight5handler.go @@ -63,20 +63,30 @@ func flight5Parse(ctx context.Context, c flightConn, state *State, cache *handsh } func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit - var certBytes [][]byte var privateKey crypto.PrivateKey - if len(cfg.localCertificates) > 0 { - certificate, err := cfg.getCertificate(cfg.serverName) + var pkts []*packet + if state.remoteRequestedCertificate { + _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-2, state.cipherSuite, + handshakeCachePullRule{handshake.TypeCertificateRequest, cfg.initialEpoch, false, false}) + if !ok { + return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errClientCertificateRequired + } + reqInfo := CertificateRequestInfo{} + if r, ok := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok { + reqInfo.AcceptableCAs = r.CertificateAuthoritiesNames + } else { + return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errClientCertificateRequired + } + certificate, err := cfg.getClientCertificate(&reqInfo) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, err } - certBytes = certificate.Certificate - privateKey = certificate.PrivateKey - } - - var pkts []*packet - - if state.remoteRequestedCertificate { + if certificate == nil { + return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errNotAcceptableCertificateChain + } + if certificate.Certificate != nil { + privateKey = certificate.PrivateKey + } pkts = append(pkts, &packet{ record: &recordlayer.RecordLayer{ @@ -85,7 +95,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han }, Content: &handshake.Handshake{ Message: &handshake.MessageCertificate{ - Certificate: certBytes, + Certificate: certificate.Certificate, }, }, }, @@ -167,7 +177,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han // If the client has sent a certificate with signing ability, a digitally-signed // CertificateVerify message is sent to explicitly verify possession of the // private key in the certificate. - if state.remoteRequestedCertificate && len(cfg.localCertificates) > 0 { + if state.remoteRequestedCertificate && privateKey != nil { plainText := append(cache.pullAndMerge( handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false}, handshakeCachePullRule{handshake.TypeServerHello, cfg.initialEpoch, false, false}, @@ -328,6 +338,11 @@ func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCon } } } + if cfg.verifyConnection != nil { + if err = cfg.verifyConnection(state.clone()); err != nil { + return &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err + } + } if err = state.cipherSuite.Init(state.masterSecret, clientRandom[:], serverRandom[:], true); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err diff --git a/fuzz.go b/fuzz.go deleted file mode 100644 index d6863241..00000000 --- a/fuzz.go +++ /dev/null @@ -1,39 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package dtls - -import "fmt" - -func partialHeaderMismatch(a, b recordlayer.Header) bool { - // Ignoring content length for now. - a.contentLen = b.contentLen - return a != b -} - -func FuzzRecordLayer(data []byte) int { - var r recordLayer - if err := r.Unmarshal(data); err != nil { - return 0 - } - buf, err := r.Marshal() - if err != nil { - return 1 - } - if len(buf) == 0 { - panic("zero buff") // nolint - } - var nr recordLayer - if err = nr.Unmarshal(data); err != nil { - panic(err) // nolint - } - if partialHeaderMismatch(nr.recordlayer.Header, r.recordlayer.Header) { - panic( // nolint - fmt.Sprintf("header mismatch: %+v != %+v", - nr.recordlayer.Header, r.recordlayer.Header, - ), - ) - } - - return 1 -} diff --git a/fuzz/corpus/012178ca0830b7449ad370598d55873d81b95e40-25 b/fuzz/corpus/012178ca0830b7449ad370598d55873d81b95e40-25 deleted file mode 100644 index f82ac9a1..00000000 Binary files a/fuzz/corpus/012178ca0830b7449ad370598d55873d81b95e40-25 and /dev/null differ diff --git a/fuzz/corpus/01277073b27ccc6925ce4c941527f7b7705c8311-1 b/fuzz/corpus/01277073b27ccc6925ce4c941527f7b7705c8311-1 deleted file mode 100644 index 4756c7aa..00000000 --- a/fuzz/corpus/01277073b27ccc6925ce4c941527f7b7705c8311-1 +++ /dev/null @@ -1 +0,0 @@ -12[A51 \ No newline at end of file diff --git a/fuzz/corpus/039192caed40959ac2f5c3254669312ba2dfbcad-12 b/fuzz/corpus/039192caed40959ac2f5c3254669312ba2dfbcad-12 deleted file mode 100644 index 3580e3c8..00000000 Binary files a/fuzz/corpus/039192caed40959ac2f5c3254669312ba2dfbcad-12 and /dev/null differ diff --git a/fuzz/corpus/03a9bad270cf32520b5c3e99add47c648ba6150f-7 b/fuzz/corpus/03a9bad270cf32520b5c3e99add47c648ba6150f-7 deleted file mode 100644 index f3b959a0..00000000 Binary files a/fuzz/corpus/03a9bad270cf32520b5c3e99add47c648ba6150f-7 and /dev/null differ diff --git a/fuzz/corpus/048fcd45b732d5bed912e6652bc265a0adaf5664-26 b/fuzz/corpus/048fcd45b732d5bed912e6652bc265a0adaf5664-26 deleted file mode 100644 index 40c5ce23..00000000 Binary files a/fuzz/corpus/048fcd45b732d5bed912e6652bc265a0adaf5664-26 and /dev/null differ diff --git a/fuzz/corpus/04a28c0806a91267f0576e11d042400f41dc538b-12 b/fuzz/corpus/04a28c0806a91267f0576e11d042400f41dc538b-12 deleted file mode 100644 index a25e2a6a..00000000 Binary files a/fuzz/corpus/04a28c0806a91267f0576e11d042400f41dc538b-12 and /dev/null differ diff --git a/fuzz/corpus/04d00cfd50deb9ccd9d14be8c58f401a0414dad3-30 b/fuzz/corpus/04d00cfd50deb9ccd9d14be8c58f401a0414dad3-30 deleted file mode 100644 index 53a1acbd..00000000 Binary files a/fuzz/corpus/04d00cfd50deb9ccd9d14be8c58f401a0414dad3-30 and /dev/null differ diff --git a/fuzz/corpus/04e7f402f7d9f6ed2e664190dbd3267eddfddefa-6 b/fuzz/corpus/04e7f402f7d9f6ed2e664190dbd3267eddfddefa-6 deleted file mode 100644 index 3f7dfd3e..00000000 Binary files a/fuzz/corpus/04e7f402f7d9f6ed2e664190dbd3267eddfddefa-6 and /dev/null differ diff --git a/fuzz/corpus/057a8c627dc06c27296c8208265a9f8a32a8d4c2-19 b/fuzz/corpus/057a8c627dc06c27296c8208265a9f8a32a8d4c2-19 deleted file mode 100644 index 50846b2f..00000000 Binary files a/fuzz/corpus/057a8c627dc06c27296c8208265a9f8a32a8d4c2-19 and /dev/null differ diff --git a/fuzz/corpus/05a0d164b8e3ca08dc1bd077ce4aa4559731182b-15 b/fuzz/corpus/05a0d164b8e3ca08dc1bd077ce4aa4559731182b-15 deleted file mode 100644 index aa777997..00000000 Binary files a/fuzz/corpus/05a0d164b8e3ca08dc1bd077ce4aa4559731182b-15 and /dev/null differ diff --git a/fuzz/corpus/06148fe224720cd3a0497fc87f2b6bc5f004484a-30 b/fuzz/corpus/06148fe224720cd3a0497fc87f2b6bc5f004484a-30 deleted file mode 100644 index f80886b5..00000000 Binary files a/fuzz/corpus/06148fe224720cd3a0497fc87f2b6bc5f004484a-30 and /dev/null differ diff --git a/fuzz/corpus/078c2bd97a33002242f9d5ac0a95970c9432124a-31 b/fuzz/corpus/078c2bd97a33002242f9d5ac0a95970c9432124a-31 deleted file mode 100644 index ac541d3c..00000000 Binary files a/fuzz/corpus/078c2bd97a33002242f9d5ac0a95970c9432124a-31 and /dev/null differ diff --git a/fuzz/corpus/07ff33058f3c6732b9439f7d5c2bd50bb46adb31-20 b/fuzz/corpus/07ff33058f3c6732b9439f7d5c2bd50bb46adb31-20 deleted file mode 100644 index dd34c829..00000000 Binary files a/fuzz/corpus/07ff33058f3c6732b9439f7d5c2bd50bb46adb31-20 and /dev/null differ diff --git a/fuzz/corpus/08f2f7719e35261f615174917101cba578892f43-11 b/fuzz/corpus/08f2f7719e35261f615174917101cba578892f43-11 deleted file mode 100644 index c6911cbc..00000000 Binary files a/fuzz/corpus/08f2f7719e35261f615174917101cba578892f43-11 and /dev/null differ diff --git a/fuzz/corpus/09b742837cf0d26ddecb5dbf536d91db6d1e9855-12 b/fuzz/corpus/09b742837cf0d26ddecb5dbf536d91db6d1e9855-12 deleted file mode 100644 index c4190316..00000000 Binary files a/fuzz/corpus/09b742837cf0d26ddecb5dbf536d91db6d1e9855-12 and /dev/null differ diff --git a/fuzz/corpus/0a3bff70743f3cc7ecdc293887c10e14e152dec2-19 b/fuzz/corpus/0a3bff70743f3cc7ecdc293887c10e14e152dec2-19 deleted file mode 100644 index 73bb16ae..00000000 Binary files a/fuzz/corpus/0a3bff70743f3cc7ecdc293887c10e14e152dec2-19 and /dev/null differ diff --git a/fuzz/corpus/11e7b0e2a84f99b2f3f367cf546dde345bba563f-15 b/fuzz/corpus/11e7b0e2a84f99b2f3f367cf546dde345bba563f-15 deleted file mode 100644 index 3f8d0aab..00000000 Binary files a/fuzz/corpus/11e7b0e2a84f99b2f3f367cf546dde345bba563f-15 and /dev/null differ diff --git a/fuzz/corpus/136a342418a743d6167ef2b44e657c82427469b8-35 b/fuzz/corpus/136a342418a743d6167ef2b44e657c82427469b8-35 deleted file mode 100644 index fbfb7c0c..00000000 Binary files a/fuzz/corpus/136a342418a743d6167ef2b44e657c82427469b8-35 and /dev/null differ diff --git a/fuzz/corpus/137e470b38deeeac3586025e0e6e2702117e26e6 b/fuzz/corpus/137e470b38deeeac3586025e0e6e2702117e26e6 deleted file mode 100644 index 7af93492..00000000 --- a/fuzz/corpus/137e470b38deeeac3586025e0e6e2702117e26e6 +++ /dev/null @@ -1 +0,0 @@ -864797660130 \ No newline at end of file diff --git a/fuzz/corpus/156c962d90205b0c4afa3394de42d56967dfc7ee-14 b/fuzz/corpus/156c962d90205b0c4afa3394de42d56967dfc7ee-14 deleted file mode 100644 index aa1f91d7..00000000 Binary files a/fuzz/corpus/156c962d90205b0c4afa3394de42d56967dfc7ee-14 and /dev/null differ diff --git a/fuzz/corpus/17863d02affd5fc60da97a59318b3f7014f93a9f-36 b/fuzz/corpus/17863d02affd5fc60da97a59318b3f7014f93a9f-36 deleted file mode 100644 index 07367202..00000000 Binary files a/fuzz/corpus/17863d02affd5fc60da97a59318b3f7014f93a9f-36 and /dev/null differ diff --git a/fuzz/corpus/1841fb69e960e2d6ce1d19c6264e70b5606bfa39-32 b/fuzz/corpus/1841fb69e960e2d6ce1d19c6264e70b5606bfa39-32 deleted file mode 100644 index 7db3310a..00000000 Binary files a/fuzz/corpus/1841fb69e960e2d6ce1d19c6264e70b5606bfa39-32 and /dev/null differ diff --git a/fuzz/corpus/1a460400f96b0b40872eac2daed7c1db2e8f9843-11 b/fuzz/corpus/1a460400f96b0b40872eac2daed7c1db2e8f9843-11 deleted file mode 100644 index fdcf4dcd..00000000 Binary files a/fuzz/corpus/1a460400f96b0b40872eac2daed7c1db2e8f9843-11 and /dev/null differ diff --git a/fuzz/corpus/1c042652c21f2c6d7ffcb6b6e6be55fdf95a5dbb-30 b/fuzz/corpus/1c042652c21f2c6d7ffcb6b6e6be55fdf95a5dbb-30 deleted file mode 100644 index 7a203469..00000000 Binary files a/fuzz/corpus/1c042652c21f2c6d7ffcb6b6e6be55fdf95a5dbb-30 and /dev/null differ diff --git a/fuzz/corpus/1d09cef95c3269d3e244f0008a4fc6dfefd1e2ad-9 b/fuzz/corpus/1d09cef95c3269d3e244f0008a4fc6dfefd1e2ad-9 deleted file mode 100644 index f7c55237..00000000 Binary files a/fuzz/corpus/1d09cef95c3269d3e244f0008a4fc6dfefd1e2ad-9 and /dev/null differ diff --git a/fuzz/corpus/22e3d3a8748eb152a65ee9ada8834f8a07b247f4-29 b/fuzz/corpus/22e3d3a8748eb152a65ee9ada8834f8a07b247f4-29 deleted file mode 100644 index a8c217e4..00000000 Binary files a/fuzz/corpus/22e3d3a8748eb152a65ee9ada8834f8a07b247f4-29 and /dev/null differ diff --git a/fuzz/corpus/23ce064ef35c0204982d748c34850bfc9433beca-13 b/fuzz/corpus/23ce064ef35c0204982d748c34850bfc9433beca-13 deleted file mode 100644 index 1a992de6..00000000 Binary files a/fuzz/corpus/23ce064ef35c0204982d748c34850bfc9433beca-13 and /dev/null differ diff --git a/fuzz/corpus/23e0e1cbd88637fbb4a19fe44c5665dda52e4c89-1 b/fuzz/corpus/23e0e1cbd88637fbb4a19fe44c5665dda52e4c89-1 deleted file mode 100644 index bf83f493..00000000 --- a/fuzz/corpus/23e0e1cbd88637fbb4a19fe44c5665dda52e4c89-1 +++ /dev/null @@ -1 +0,0 @@ -8647996606130 \ No newline at end of file diff --git a/fuzz/corpus/2403e35492e1dc374b40bb2b4eda453c2e9612f2-21 b/fuzz/corpus/2403e35492e1dc374b40bb2b4eda453c2e9612f2-21 deleted file mode 100644 index 1d206490..00000000 Binary files a/fuzz/corpus/2403e35492e1dc374b40bb2b4eda453c2e9612f2-21 and /dev/null differ diff --git a/fuzz/corpus/2438ed38ea739d8f57018f8de0a52f3e545ac760-18 b/fuzz/corpus/2438ed38ea739d8f57018f8de0a52f3e545ac760-18 deleted file mode 100644 index 6ebc62fd..00000000 Binary files a/fuzz/corpus/2438ed38ea739d8f57018f8de0a52f3e545ac760-18 and /dev/null differ diff --git a/fuzz/corpus/256b14a77bc0439a14908b6fa00afb348dde3af4-17 b/fuzz/corpus/256b14a77bc0439a14908b6fa00afb348dde3af4-17 deleted file mode 100644 index fc08e430..00000000 Binary files a/fuzz/corpus/256b14a77bc0439a14908b6fa00afb348dde3af4-17 and /dev/null differ diff --git a/fuzz/corpus/27702a0157f6eeb426aef4d5789b380d7b23801e-35 b/fuzz/corpus/27702a0157f6eeb426aef4d5789b380d7b23801e-35 deleted file mode 100644 index 64b2027f..00000000 Binary files a/fuzz/corpus/27702a0157f6eeb426aef4d5789b380d7b23801e-35 and /dev/null differ diff --git a/fuzz/corpus/29accdef171829b8dc0dba39d24acf913e13a31f-20 b/fuzz/corpus/29accdef171829b8dc0dba39d24acf913e13a31f-20 deleted file mode 100644 index e0fd446e..00000000 Binary files a/fuzz/corpus/29accdef171829b8dc0dba39d24acf913e13a31f-20 and /dev/null differ diff --git a/fuzz/corpus/2ad24ef4188d2626e363cb12c5242fa96abfa7a3-13 b/fuzz/corpus/2ad24ef4188d2626e363cb12c5242fa96abfa7a3-13 deleted file mode 100644 index 8038d1a4..00000000 Binary files a/fuzz/corpus/2ad24ef4188d2626e363cb12c5242fa96abfa7a3-13 and /dev/null differ diff --git a/fuzz/corpus/2db7497fc9f463803d041365e337cccd7e74111a-18 b/fuzz/corpus/2db7497fc9f463803d041365e337cccd7e74111a-18 deleted file mode 100644 index 558ffdb0..00000000 Binary files a/fuzz/corpus/2db7497fc9f463803d041365e337cccd7e74111a-18 and /dev/null differ diff --git a/fuzz/corpus/30b9805b33c0d67926cbb5ab174508797eb7b7a7-17 b/fuzz/corpus/30b9805b33c0d67926cbb5ab174508797eb7b7a7-17 deleted file mode 100644 index 95b5ea5d..00000000 Binary files a/fuzz/corpus/30b9805b33c0d67926cbb5ab174508797eb7b7a7-17 and /dev/null differ diff --git a/fuzz/corpus/3105d624d1010500139670e332bd50771c112fdd-17 b/fuzz/corpus/3105d624d1010500139670e332bd50771c112fdd-17 deleted file mode 100644 index ac56ddcf..00000000 Binary files a/fuzz/corpus/3105d624d1010500139670e332bd50771c112fdd-17 and /dev/null differ diff --git a/fuzz/corpus/32b051a5ed27cbcb3c1689adbf51c4223e58f9bc-36 b/fuzz/corpus/32b051a5ed27cbcb3c1689adbf51c4223e58f9bc-36 deleted file mode 100644 index f5138d98..00000000 Binary files a/fuzz/corpus/32b051a5ed27cbcb3c1689adbf51c4223e58f9bc-36 and /dev/null differ diff --git a/fuzz/corpus/340161bf9f51d50c47d1853eb5d4fcac06914900-12 b/fuzz/corpus/340161bf9f51d50c47d1853eb5d4fcac06914900-12 deleted file mode 100644 index f832cf5a..00000000 Binary files a/fuzz/corpus/340161bf9f51d50c47d1853eb5d4fcac06914900-12 and /dev/null differ diff --git a/fuzz/corpus/371f95aa3e615531b896c89647e6ce67586e082e-15 b/fuzz/corpus/371f95aa3e615531b896c89647e6ce67586e082e-15 deleted file mode 100644 index 9b658672..00000000 Binary files a/fuzz/corpus/371f95aa3e615531b896c89647e6ce67586e082e-15 and /dev/null differ diff --git a/fuzz/corpus/386d1a6c0d51af038a3b2d3adba6eb15d8e3fe0a-23 b/fuzz/corpus/386d1a6c0d51af038a3b2d3adba6eb15d8e3fe0a-23 deleted file mode 100644 index c5914c7c..00000000 Binary files a/fuzz/corpus/386d1a6c0d51af038a3b2d3adba6eb15d8e3fe0a-23 and /dev/null differ diff --git a/fuzz/corpus/3929563fe81b960a338a68a87a60e1940ac7f14e-34 b/fuzz/corpus/3929563fe81b960a338a68a87a60e1940ac7f14e-34 deleted file mode 100644 index 552a00a7..00000000 Binary files a/fuzz/corpus/3929563fe81b960a338a68a87a60e1940ac7f14e-34 and /dev/null differ diff --git a/fuzz/corpus/3be9ff705b7c6d24ba58057e44fe7f51d0b0aa54-30 b/fuzz/corpus/3be9ff705b7c6d24ba58057e44fe7f51d0b0aa54-30 deleted file mode 100644 index 0a09ce81..00000000 Binary files a/fuzz/corpus/3be9ff705b7c6d24ba58057e44fe7f51d0b0aa54-30 and /dev/null differ diff --git a/fuzz/corpus/3eb3261e52074eceab2d28b5eee628d3ec213a84-14 b/fuzz/corpus/3eb3261e52074eceab2d28b5eee628d3ec213a84-14 deleted file mode 100644 index c1d6dd48..00000000 Binary files a/fuzz/corpus/3eb3261e52074eceab2d28b5eee628d3ec213a84-14 and /dev/null differ diff --git a/fuzz/corpus/3f88c87cc5fe3fff5a45dc1916eed2fdcfe20d57-13 b/fuzz/corpus/3f88c87cc5fe3fff5a45dc1916eed2fdcfe20d57-13 deleted file mode 100644 index 0da0cc33..00000000 Binary files a/fuzz/corpus/3f88c87cc5fe3fff5a45dc1916eed2fdcfe20d57-13 and /dev/null differ diff --git a/fuzz/corpus/3f928478ccaf16b9685071b91f52d5e0e6bc71c1-38 b/fuzz/corpus/3f928478ccaf16b9685071b91f52d5e0e6bc71c1-38 deleted file mode 100644 index c19a284e..00000000 Binary files a/fuzz/corpus/3f928478ccaf16b9685071b91f52d5e0e6bc71c1-38 and /dev/null differ diff --git a/fuzz/corpus/42ab249f3ceb17939f5fcab757894b22d94a86a8-22 b/fuzz/corpus/42ab249f3ceb17939f5fcab757894b22d94a86a8-22 deleted file mode 100644 index 322bf2c0..00000000 Binary files a/fuzz/corpus/42ab249f3ceb17939f5fcab757894b22d94a86a8-22 and /dev/null differ diff --git a/fuzz/corpus/42dbe1a681da3f7e48d18c53ab26b5893f3ea2ac-9 b/fuzz/corpus/42dbe1a681da3f7e48d18c53ab26b5893f3ea2ac-9 deleted file mode 100644 index c7c2bed5..00000000 Binary files a/fuzz/corpus/42dbe1a681da3f7e48d18c53ab26b5893f3ea2ac-9 and /dev/null differ diff --git a/fuzz/corpus/471c2a2e1065b2c0f6040b286eebbca70e3742c6-10 b/fuzz/corpus/471c2a2e1065b2c0f6040b286eebbca70e3742c6-10 deleted file mode 100644 index 1b5fa665..00000000 Binary files a/fuzz/corpus/471c2a2e1065b2c0f6040b286eebbca70e3742c6-10 and /dev/null differ diff --git a/fuzz/corpus/4735f3fc147ee436f8c02c24b9c40b4ee4cb1265-7 b/fuzz/corpus/4735f3fc147ee436f8c02c24b9c40b4ee4cb1265-7 deleted file mode 100644 index 66de70c3..00000000 Binary files a/fuzz/corpus/4735f3fc147ee436f8c02c24b9c40b4ee4cb1265-7 and /dev/null differ diff --git a/fuzz/corpus/48e4ba16b5626f66169cf52fb35054ae32f1037e-27 b/fuzz/corpus/48e4ba16b5626f66169cf52fb35054ae32f1037e-27 deleted file mode 100644 index 6c37949f..00000000 Binary files a/fuzz/corpus/48e4ba16b5626f66169cf52fb35054ae32f1037e-27 and /dev/null differ diff --git a/fuzz/corpus/4be120299b63639b4c203c93da101e2db703839a-26 b/fuzz/corpus/4be120299b63639b4c203c93da101e2db703839a-26 deleted file mode 100644 index f8da2d60..00000000 Binary files a/fuzz/corpus/4be120299b63639b4c203c93da101e2db703839a-26 and /dev/null differ diff --git a/fuzz/corpus/4cdafe201d691c06b529689668d52106a3e98dfa-22 b/fuzz/corpus/4cdafe201d691c06b529689668d52106a3e98dfa-22 deleted file mode 100644 index 2fb9f62b..00000000 Binary files a/fuzz/corpus/4cdafe201d691c06b529689668d52106a3e98dfa-22 and /dev/null differ diff --git a/fuzz/corpus/4d79d6a303e57c882d1d329ad4e3f091dd60e7ff-20 b/fuzz/corpus/4d79d6a303e57c882d1d329ad4e3f091dd60e7ff-20 deleted file mode 100644 index 672fb798..00000000 Binary files a/fuzz/corpus/4d79d6a303e57c882d1d329ad4e3f091dd60e7ff-20 and /dev/null differ diff --git a/fuzz/corpus/509dbda3f391113a75c8309028bf59c0f107ac52-30 b/fuzz/corpus/509dbda3f391113a75c8309028bf59c0f107ac52-30 deleted file mode 100644 index 401db35c..00000000 Binary files a/fuzz/corpus/509dbda3f391113a75c8309028bf59c0f107ac52-30 and /dev/null differ diff --git a/fuzz/corpus/52aecd8762579fcaa1b5f26b152840f899683660-17 b/fuzz/corpus/52aecd8762579fcaa1b5f26b152840f899683660-17 deleted file mode 100644 index 9483584e..00000000 Binary files a/fuzz/corpus/52aecd8762579fcaa1b5f26b152840f899683660-17 and /dev/null differ diff --git a/fuzz/corpus/545ad51188a5d270eafe4733272be18ac1769c21-1 b/fuzz/corpus/545ad51188a5d270eafe4733272be18ac1769c21-1 deleted file mode 100644 index e06cbd90..00000000 --- a/fuzz/corpus/545ad51188a5d270eafe4733272be18ac1769c21-1 +++ /dev/null @@ -1 +0,0 @@ -/ソソY \ No newline at end of file diff --git a/fuzz/corpus/5642ffc103d245461d8e754281bea517ff54ed85-17 b/fuzz/corpus/5642ffc103d245461d8e754281bea517ff54ed85-17 deleted file mode 100644 index f2d2e993..00000000 Binary files a/fuzz/corpus/5642ffc103d245461d8e754281bea517ff54ed85-17 and /dev/null differ diff --git a/fuzz/corpus/57d1652be22f597708e8099e2d23e8e4b00b0f89-33 b/fuzz/corpus/57d1652be22f597708e8099e2d23e8e4b00b0f89-33 deleted file mode 100644 index 620e248f..00000000 Binary files a/fuzz/corpus/57d1652be22f597708e8099e2d23e8e4b00b0f89-33 and /dev/null differ diff --git a/fuzz/corpus/59d6ef268e83be801c670340b2383a5a732308cb-8 b/fuzz/corpus/59d6ef268e83be801c670340b2383a5a732308cb-8 deleted file mode 100644 index 91e28537..00000000 Binary files a/fuzz/corpus/59d6ef268e83be801c670340b2383a5a732308cb-8 and /dev/null differ diff --git a/fuzz/corpus/5b3cbe41487f4f9f5e728a86adce154ebd73fbe0-9 b/fuzz/corpus/5b3cbe41487f4f9f5e728a86adce154ebd73fbe0-9 deleted file mode 100644 index 71470b05..00000000 Binary files a/fuzz/corpus/5b3cbe41487f4f9f5e728a86adce154ebd73fbe0-9 and /dev/null differ diff --git a/fuzz/corpus/5c165fd943bcb6df518c71b149d5aed736237833-16 b/fuzz/corpus/5c165fd943bcb6df518c71b149d5aed736237833-16 deleted file mode 100644 index 31cd9b35..00000000 Binary files a/fuzz/corpus/5c165fd943bcb6df518c71b149d5aed736237833-16 and /dev/null differ diff --git a/fuzz/corpus/5eeaf10bf3fbb5575a63e054fd377645b5f45de5-3 b/fuzz/corpus/5eeaf10bf3fbb5575a63e054fd377645b5f45de5-3 deleted file mode 100644 index 224b46e8..00000000 --- a/fuzz/corpus/5eeaf10bf3fbb5575a63e054fd377645b5f45de5-3 +++ /dev/null @@ -1 +0,0 @@ -}\v/ \ No newline at end of file diff --git a/fuzz/corpus/64c5404b7e07af41448c99eadd4ded3a1572b503-9 b/fuzz/corpus/64c5404b7e07af41448c99eadd4ded3a1572b503-9 deleted file mode 100644 index f887cb37..00000000 Binary files a/fuzz/corpus/64c5404b7e07af41448c99eadd4ded3a1572b503-9 and /dev/null differ diff --git a/fuzz/corpus/6926133d1d407a21e5e57ed4ec71583b8f4650ab-16 b/fuzz/corpus/6926133d1d407a21e5e57ed4ec71583b8f4650ab-16 deleted file mode 100644 index 04d21c8f..00000000 Binary files a/fuzz/corpus/6926133d1d407a21e5e57ed4ec71583b8f4650ab-16 and /dev/null differ diff --git a/fuzz/corpus/6998ed50de84d0a1e2250af37ef989f866392d8e-7 b/fuzz/corpus/6998ed50de84d0a1e2250af37ef989f866392d8e-7 deleted file mode 100644 index 4fcf44dd..00000000 Binary files a/fuzz/corpus/6998ed50de84d0a1e2250af37ef989f866392d8e-7 and /dev/null differ diff --git a/fuzz/corpus/6a823391df6589e83b50fbf6ad7ec4a61edb34c5-35 b/fuzz/corpus/6a823391df6589e83b50fbf6ad7ec4a61edb34c5-35 deleted file mode 100644 index fe27af27..00000000 Binary files a/fuzz/corpus/6a823391df6589e83b50fbf6ad7ec4a61edb34c5-35 and /dev/null differ diff --git a/fuzz/corpus/6af8fabbde43b2d6bb76502831dbd8c0d1dea233-36 b/fuzz/corpus/6af8fabbde43b2d6bb76502831dbd8c0d1dea233-36 deleted file mode 100644 index aacbe8b9..00000000 Binary files a/fuzz/corpus/6af8fabbde43b2d6bb76502831dbd8c0d1dea233-36 and /dev/null differ diff --git a/fuzz/corpus/6b33f20c523b6d32a26863fa65923e66ab555408-3 b/fuzz/corpus/6b33f20c523b6d32a26863fa65923e66ab555408-3 deleted file mode 100644 index e61c359c..00000000 Binary files a/fuzz/corpus/6b33f20c523b6d32a26863fa65923e66ab555408-3 and /dev/null differ diff --git a/fuzz/corpus/6bf06a9be690f993286b45425cb88b8331876fe1-1 b/fuzz/corpus/6bf06a9be690f993286b45425cb88b8331876fe1-1 deleted file mode 100644 index c9231f29..00000000 --- a/fuzz/corpus/6bf06a9be690f993286b45425cb88b8331876fe1-1 +++ /dev/null @@ -1 +0,0 @@ -1 0 { + for _, ca := range m.CertificateAuthoritiesNames { + out = append(out, []byte{0x00, 0x00}...) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(ca))) + out = append(out, ca...) + } + } return out, nil } @@ -96,5 +110,32 @@ func (m *MessageCertificateRequest) Unmarshal(data []byte) error { m.SignatureHashAlgorithms = append(m.SignatureHashAlgorithms, signaturehash.Algorithm{Signature: s, Hash: h}) } + offset += signatureHashAlgorithmsLength + if len(data) < offset+2 { + return errBufferTooSmall + } + casLength := int(binary.BigEndian.Uint16(data[offset:])) + offset += 2 + if (offset + casLength) > len(data) { + return errBufferTooSmall + } + cas := make([]byte, casLength) + copy(cas, data[offset:offset+casLength]) + m.CertificateAuthoritiesNames = nil + for len(cas) > 0 { + if len(cas) < 2 { + return errBufferTooSmall + } + caLen := binary.BigEndian.Uint16(cas) + cas = cas[2:] + + if len(cas) < int(caLen) { + return errBufferTooSmall + } + + m.CertificateAuthoritiesNames = append(m.CertificateAuthoritiesNames, cas[:caLen]) + cas = cas[caLen:] + } + return nil } diff --git a/pkg/protocol/handshake/message_certificate_request_test.go b/pkg/protocol/handshake/message_certificate_request_test.go index 1d73ae5a..e645548a 100644 --- a/pkg/protocol/handshake/message_certificate_request_test.go +++ b/pkg/protocol/handshake/message_certificate_request_test.go @@ -1,6 +1,7 @@ package handshake import ( + "errors" "reflect" "testing" @@ -11,36 +12,82 @@ import ( ) func TestHandshakeMessageCertificateRequest(t *testing.T) { - rawCertificateRequest := []byte{ - 0x02, 0x01, 0x40, 0x00, 0x0C, 0x04, 0x03, 0x04, 0x01, 0x05, - 0x03, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x00, 0x00, - } - parsedCertificateRequest := &MessageCertificateRequest{ - CertificateTypes: []clientcertificate.Type{ - clientcertificate.RSASign, - clientcertificate.ECDSASign, + cases := map[string]struct { + rawCertificateRequest []byte + parsedCertificateRequest *MessageCertificateRequest + expErr error + }{ + "valid - with CertificateAuthoritiesNames": { + rawCertificateRequest: []byte{ + 0x02, 0x01, 0x40, 0x00, 0x0C, 0x04, 0x03, 0x04, 0x01, 0x05, + 0x03, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x00, 0x06, 0x00, + 0x04, 0x74, 0x65, 0x73, 0x74, + }, + parsedCertificateRequest: &MessageCertificateRequest{ + CertificateTypes: []clientcertificate.Type{ + clientcertificate.RSASign, + clientcertificate.ECDSASign, + }, + SignatureHashAlgorithms: []signaturehash.Algorithm{ + {Hash: hash.SHA256, Signature: signature.ECDSA}, + {Hash: hash.SHA256, Signature: signature.RSA}, + {Hash: hash.SHA384, Signature: signature.ECDSA}, + {Hash: hash.SHA384, Signature: signature.RSA}, + {Hash: hash.SHA512, Signature: signature.RSA}, + {Hash: hash.SHA1, Signature: signature.RSA}, + }, + CertificateAuthoritiesNames: [][]byte{[]byte("test")}, + }, }, - SignatureHashAlgorithms: []signaturehash.Algorithm{ - {Hash: hash.SHA256, Signature: signature.ECDSA}, - {Hash: hash.SHA256, Signature: signature.RSA}, - {Hash: hash.SHA384, Signature: signature.ECDSA}, - {Hash: hash.SHA384, Signature: signature.RSA}, - {Hash: hash.SHA512, Signature: signature.RSA}, - {Hash: hash.SHA1, Signature: signature.RSA}, + "valid - without CertificateAuthoritiesNames": { + rawCertificateRequest: []byte{ + 0x02, 0x01, 0x40, 0x00, 0x0C, 0x04, 0x03, 0x04, 0x01, 0x05, + 0x03, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x00, 0x00, + }, + parsedCertificateRequest: &MessageCertificateRequest{ + CertificateTypes: []clientcertificate.Type{ + clientcertificate.RSASign, + clientcertificate.ECDSASign, + }, + SignatureHashAlgorithms: []signaturehash.Algorithm{ + {Hash: hash.SHA256, Signature: signature.ECDSA}, + {Hash: hash.SHA256, Signature: signature.RSA}, + {Hash: hash.SHA384, Signature: signature.ECDSA}, + {Hash: hash.SHA384, Signature: signature.RSA}, + {Hash: hash.SHA512, Signature: signature.RSA}, + {Hash: hash.SHA1, Signature: signature.RSA}, + }, + }, + }, + "invalid - casLength CertificateAuthoritiesNames": { + rawCertificateRequest: []byte{ + 0x02, 0x01, 0x40, 0x00, 0x0C, 0x04, 0x03, 0x04, 0x01, 0x05, + 0x03, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x01, + }, + expErr: errBufferTooSmall, }, } - c := &MessageCertificateRequest{} - if err := c.Unmarshal(rawCertificateRequest); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(c, parsedCertificateRequest) { - t.Errorf("parsedCertificateRequest unmarshal: got %#v, want %#v", c, parsedCertificateRequest) - } - - raw, err := c.Marshal() - if err != nil { - t.Error(err) - } else if !reflect.DeepEqual(raw, rawCertificateRequest) { - t.Errorf("parsedCertificateRequest marshal: got %#v, want %#v", raw, rawCertificateRequest) + for name, testCase := range cases { + testCase := testCase + t.Run(name, func(t *testing.T) { + c := &MessageCertificateRequest{} + if err := c.Unmarshal(testCase.rawCertificateRequest); err != nil { + if testCase.expErr != nil { + if errors.Is(err, testCase.expErr) { + return + } + } + t.Error(err) + } else if !reflect.DeepEqual(c, testCase.parsedCertificateRequest) { + t.Errorf("parsedCertificateRequest unmarshal: got %#v, want %#v", c, testCase.parsedCertificateRequest) + } + raw, err := c.Marshal() + if err != nil { + t.Error(err) + } else if !reflect.DeepEqual(raw, testCase.rawCertificateRequest) { + t.Errorf("parsedCertificateRequest marshal: got %#v, want %#v", raw, testCase.rawCertificateRequest) + } + }) } } diff --git a/pkg/protocol/handshake/message_hello_verify_request.go b/pkg/protocol/handshake/message_hello_verify_request.go index ef834dc8..20c63773 100644 --- a/pkg/protocol/handshake/message_hello_verify_request.go +++ b/pkg/protocol/handshake/message_hello_verify_request.go @@ -51,8 +51,8 @@ func (m *MessageHelloVerifyRequest) Unmarshal(data []byte) error { } m.Version.Major = data[0] m.Version.Minor = data[1] - cookieLength := data[2] - if len(data) < (int(cookieLength) + 3) { + cookieLength := int(data[2]) + if len(data) < cookieLength+3 { return errBufferTooSmall } m.Cookie = make([]byte, cookieLength) diff --git a/pkg/protocol/handshake/message_server_hello.go b/pkg/protocol/handshake/message_server_hello.go index 9c1cc221..b4157e25 100644 --- a/pkg/protocol/handshake/message_server_hello.go +++ b/pkg/protocol/handshake/message_server_hello.go @@ -88,11 +88,14 @@ func (m *MessageServerHello) Unmarshal(data []byte) error { m.SessionID = append([]byte{}, data[currOffset:currOffset+n]...) currOffset += len(m.SessionID) + if len(data) < currOffset+2 { + return errBufferTooSmall + } m.CipherSuiteID = new(uint16) *m.CipherSuiteID = binary.BigEndian.Uint16(data[currOffset:]) currOffset += 2 - if len(data) < currOffset { + if len(data) <= currOffset { return errBufferTooSmall } if compressionMethod, ok := protocol.CompressionMethods()[protocol.CompressionMethodID(data[currOffset])]; ok { diff --git a/pkg/protocol/recordlayer/fuzz_test.go b/pkg/protocol/recordlayer/fuzz_test.go new file mode 100644 index 00000000..7442c7a5 --- /dev/null +++ b/pkg/protocol/recordlayer/fuzz_test.go @@ -0,0 +1,38 @@ +package recordlayer + +import ( + "testing" +) + +func partialHeaderMismatch(a, b Header) bool { + // Ignoring content length for now. + a.ContentLen = b.ContentLen + return a != b +} + +func FuzzRecordLayer(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + var r RecordLayer + if err := r.Unmarshal(data); err != nil { + return + } + + buf, err := r.Marshal() + if err != nil { + return + } + + if len(buf) == 0 { + t.Fatal("Zero buff") + } + + var nr RecordLayer + if err = nr.Unmarshal(data); err != nil { + t.Fatal(err) + } + + if partialHeaderMismatch(nr.Header, r.Header) { + t.Fatalf("Header mismatch: %+v != %+v", nr.Header, r.Header) + } + }) +} diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/03987f803f3e531e0fd490b5904921636c59aa91a2d3307ee5d9adf4debb214d b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/03987f803f3e531e0fd490b5904921636c59aa91a2d3307ee5d9adf4debb214d new file mode 100644 index 00000000..5de16fd9 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/03987f803f3e531e0fd490b5904921636c59aa91a2d3307ee5d9adf4debb214d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7Nl\x01li\x00too \x01\f\x00\x00\x03\xe8\x00 \x01\f\x00\x00\x03\x03\x00\x1d") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/03b7821fddb81be526945e2258d835ad3472d80a9c72363578a6b2d7f6256d94 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/03b7821fddb81be526945e2258d835ad3472d80a9c72363578a6b2d7f6256d94 new file mode 100644 index 00000000..22b58152 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/03b7821fddb81be526945e2258d835ad3472d80a9c72363578a6b2d7f6256d94 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x003552\x7f\x00\x00\x0033\x00\x00@t\x009474452381LittleEnd2\x00\x00\bt\x009\x00\x00\x00\x02\x00\r\x00\x00\bt\x00\x06\x05\xff\x00\x00\x00!\b") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/03e41cdcff69baafb4dd1a7cad2d47696fb55a873336408889fec13f2424705d b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/03e41cdcff69baafb4dd1a7cad2d47696fb55a873336408889fec13f2424705d new file mode 100644 index 00000000..122a31d7 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/03e41cdcff69baafb4dd1a7cad2d47696fb55a873336408889fec13f2424705d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\x01\xbd\xb7\xef\xbfϻ\xbf\x00\x00\x00\x00\f\x00\x00\bt\x80o\xfea\x00\x00\b\x03\x00\x17\x00\xd1\x00\x00\xde") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/05efabbe66819ab1efd3b8d0ffa11abd6eb49c27299ddd9e9103ef1ba967bc9e b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/05efabbe66819ab1efd3b8d0ffa11abd6eb49c27299ddd9e9103ef1ba967bc9e new file mode 100644 index 00000000..a14f0ae8 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/05efabbe66819ab1efd3b8d0ffa11abd6eb49c27299ddd9e9103ef1ba967bc9e @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7NlsNi''oo l\r\x00\x00\bt\x80o\xfea\x00\x00\b\x03\x01\x01@\xbf\xbd*\xde") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/06b503715c6189045b02cd7ed561182fc6a538b495e00a525445fda6fb1b04e1 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/06b503715c6189045b02cd7ed561182fc6a538b495e00a525445fda6fb1b04e1 new file mode 100644 index 00000000..319d2644 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/06b503715c6189045b02cd7ed561182fc6a538b495e00a525445fda6fb1b04e1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x0035\x02\x00\x00\x00\x00\x0033\x00\x00ttlePn445ttleEnd2\x00\x13\bt\x009\x00\x00\x00\x00\x003\x00\r\x00\x00\b\x00\xc0/\xc0+-\x00\xc0\n\xc0\n\xbd\x00\x02") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0a441253acbf17bf235287120ed6ce93c2d92b1be5086e32d56ec378af1076be b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0a441253acbf17bf235287120ed6ce93c2d92b1be5086e32d56ec378af1076be new file mode 100644 index 00000000..9cf10f8c --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0a441253acbf17bf235287120ed6ce93c2d92b1be5086e32d56ec378af1076be @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7Nlsli\x00too l\x0f\x00\x00\x00too l\x00\x00\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0b9eae444bc5ac302312bcf1166db2b93b0bef2ea9d6b342f265daa42f755a08 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0b9eae444bc5ac302312bcf1166db2b93b0bef2ea9d6b342f265daa42f755a08 new file mode 100644 index 00000000..1105c673 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0b9eae444bc5ac302312bcf1166db2b93b0bef2ea9d6b342f265daa42f755a08 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x0035\x02\x00\x00\x00\x00\x0033\x00\x00ttlePn445ttleEnd2\x00\x13\bt\x009\x00\x00\x00\x00\x003\x00\r\x00\x00\b\x00\xc0/\xc0/-\x00\xc0/\xc0/\xc0/-") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0d01c5cc8eb8488d1b2721a5afd36d5d60e4e72470371d8ac59ad4630d681e24 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0d01c5cc8eb8488d1b2721a5afd36d5d60e4e72470371d8ac59ad4630d681e24 new file mode 100644 index 00000000..aa158436 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0d01c5cc8eb8488d1b2721a5afd36d5d60e4e72470371d8ac59ad4630d681e24 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x0035\x02\x00\x00\x00\x00\x0033\x00\x00ttlePn445ttleEnd2\x00\x13\bt\x009\x00\x00\x00\x00\x003\x00\r\x00\x00\b\x00\xc0/\xc0/-\x00\xc0\n\xc0\n\xbd\x00\x02") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0d3b706464ba1475fb74629dc6a0b9f3810bd1855e24fe7634d1c6935684f5cf b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0d3b706464ba1475fb74629dc6a0b9f3810bd1855e24fe7634d1c6935684f5cf new file mode 100644 index 00000000..abc1fc6a --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0d3b706464ba1475fb74629dc6a0b9f3810bd1855e24fe7634d1c6935684f5cf @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x00355\x00\x00\x00\x00\x0033\x00t@t\x0095744\x802381Little\x009574452\x009\x00\x00\x00\x02\x00\r\x00\b\b\x00\x00\x00\x02\x00\x005\x00\x00\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0d65d397a7673cb3d53cd46ccb11bcc00d56b5f503701a0fcf63d75f73d4e666 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0d65d397a7673cb3d53cd46ccb11bcc00d56b5f503701a0fcf63d75f73d4e666 new file mode 100644 index 00000000..4f363a17 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0d65d397a7673cb3d53cd46ccb11bcc00d56b5f503701a0fcf63d75f73d4e666 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7Nlsli\x00too l\x0f\x00\x00\btoo l\x00\x00\b\x01\xbf\xbd�+\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0ec25d176479549cca9330d17192847cdad0f553aef3928df26de02415011a5e b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0ec25d176479549cca9330d17192847cdad0f553aef3928df26de02415011a5e new file mode 100644 index 00000000..61fab691 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0ec25d176479549cca9330d17192847cdad0f553aef3928df26de02415011a5e @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7NlsNi''oo l\r\x00\x00\rt\x00\x00\x00\x00\x00\x00\r\x00\x00\t\x00\t\x01\x01\x01\x01\x01\x01\x01\xde") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0ef1d69b71a15234385291d3d106584e48652843926ca35c284a1114d5c3f868 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0ef1d69b71a15234385291d3d106584e48652843926ca35c284a1114d5c3f868 new file mode 100644 index 00000000..5056f5fb --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0ef1d69b71a15234385291d3d106584e48652843926ca35c284a1114d5c3f868 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7NlsNi''oo l\r\x00\x00\bt\x00\x00\x00\x00\x00\x00\b\x05\x01\x01@\x00@\x00\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0f34180120ab01c88faf62ebb5c50d01e8b349a96275f0afbe49cef0fd51d04e b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0f34180120ab01c88faf62ebb5c50d01e8b349a96275f0afbe49cef0fd51d04e new file mode 100644 index 00000000..9d1ab0b8 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0f34180120ab01c88faf62ebb5c50d01e8b349a96275f0afbe49cef0fd51d04e @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xb7\xef\xbfϻ\xbf\x00\x00\x00\x00\f\x00\x00\bt\x80o\xfea\x00\x00\b\x03\x00\x17\x00\x01\x00\x00\xde") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0f8e2356e693d9c54480329acec8b90481233b9feeb3757e2497ad586a537674 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0f8e2356e693d9c54480329acec8b90481233b9feeb3757e2497ad586a537674 new file mode 100644 index 00000000..b00d2c91 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/0f8e2356e693d9c54480329acec8b90481233b9feeb3757e2497ad586a537674 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x00355\x00\x00\x00\x00\x0033\x00t@t\x0095744\x802381Little\x009074452\x009\x00\x00\x00\x02\x00\r\x00\b\b\x00\x005\x00\x00\x005\x00\x00\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/129d68da1ade96a9e4e310b72ac975cd6024dbee6fac0d67496fccf4e26a3db1 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/129d68da1ade96a9e4e310b72ac975cd6024dbee6fac0d67496fccf4e26a3db1 new file mode 100644 index 00000000..1aad2961 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/129d68da1ade96a9e4e310b72ac975cd6024dbee6fac0d67496fccf4e26a3db1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x00355\x00\x00\x00\x00\x0033\x00\x00@t\x009474452381LittleEnd2\x00\x13\bt\x009\x00\x00\x00\x00\x00\x02\x00\r\x00\x00\b\x00\x0e\xc0\xbd\x00\x02\x00\x01") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/13e41b10c4046c1bde0d26f873c947abf238064a3561cdfb7e19cf769d91a2fc b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/13e41b10c4046c1bde0d26f873c947abf238064a3561cdfb7e19cf769d91a2fc new file mode 100644 index 00000000..948bdb8a --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/13e41b10c4046c1bde0d26f873c947abf238064a3561cdfb7e19cf769d91a2fc @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x00355\x00\x00\x00\x00\x0033\x00t@t\x0095744\x802381Little\x009074452\x009\x00\x00\x00\x02\x00\r\x00\b\b\x00\x005\x005\x005\x00\x00\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/14096a5a580bed7bdbb77ff8cc5459de2a87bf31d61bd17d52b2fcfe7112c701 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/14096a5a580bed7bdbb77ff8cc5459de2a87bf31d61bd17d52b2fcfe7112c701 new file mode 100644 index 00000000..724b9233 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/14096a5a580bed7bdbb77ff8cc5459de2a87bf31d61bd17d52b2fcfe7112c701 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \r\x00\x00355\x00\x00\x00\x00\x003\x00\x000@t\x009574452381Little\x009574452\x009\x00\x00\x00\x02\x00\r\x00\x00\bt\x00\x06\x05\xff\x00\x80\x00\x00\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/14aaac1245bd441d8611916283e88388a581ef35a3ea5ab54f029d269f8c6d80 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/14aaac1245bd441d8611916283e88388a581ef35a3ea5ab54f029d269f8c6d80 new file mode 100644 index 00000000..14ff132a --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/14aaac1245bd441d8611916283e88388a581ef35a3ea5ab54f029d269f8c6d80 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7Nlsli\x00to\x16 l\v\x00\x00\bt \x00\x00\x00\x00\x00\b\x00\x00\x05\x00\x00\x020\"") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/14b7ee96e8dd34dec156fc8a4d76f9d5d37727b054f9b822896e4dae7756878e b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/14b7ee96e8dd34dec156fc8a4d76f9d5d37727b054f9b822896e4dae7756878e new file mode 100644 index 00000000..afa12d48 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/14b7ee96e8dd34dec156fc8a4d76f9d5d37727b054f9b822896e4dae7756878e @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xa6`\xff\xff\xff\n\x14\x00\x00\x00@d\x00\x00\x00\x00\x00\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/150352563014b70fc7ca4b600f35dc18c1a01f426c419ae90dbad5a832a078be b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/150352563014b70fc7ca4b600f35dc18c1a01f426c419ae90dbad5a832a078be new file mode 100644 index 00000000..d2aaf764 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/150352563014b70fc7ca4b600f35dc18c1a01f426c419ae90dbad5a832a078be @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x00\x00\x00\x00\xef\x00d\x00\x00\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/156ac6eb0e4f6afa3336c4cee17b9d867b7f4de82f9f131bf911d2a605faa0ce b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/156ac6eb0e4f6afa3336c4cee17b9d867b7f4de82f9f131bf911d2a605faa0ce new file mode 100644 index 00000000..6af39aae --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/156ac6eb0e4f6afa3336c4cee17b9d867b7f4de82f9f131bf911d2a605faa0ce @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7NlsN\x8b'0oo l\x02\x00\x003552\x7f\x00\x00\x003274\x00699474452381LittleEnd\x00\x00\x01\x00\rt\x00\x00\x00!\x005\x00\x7f\x00\bt\x00\x06\x05\xff\x05@!!\b") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/1be04e0793ce8acabafd1f2eddcbb2069faad2c2acd300e5fbbb88acc5077208 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/1be04e0793ce8acabafd1f2eddcbb2069faad2c2acd300e5fbbb88acc5077208 new file mode 100644 index 00000000..d939a89b --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/1be04e0793ce8acabafd1f2eddcbb2069faad2c2acd300e5fbbb88acc5077208 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x15\xefmd5\xbf\xbd��") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/1c051d05115d4d0e84c6d3c5f1cab62cd4473b46ec1d7d997c63e5a86e554f74 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/1c051d05115d4d0e84c6d3c5f1cab62cd4473b46ec1d7d997c63e5a86e554f74 new file mode 100644 index 00000000..c95baa28 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/1c051d05115d4d0e84c6d3c5f1cab62cd4473b46ec1d7d997c63e5a86e554f74 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7Nl\x80li\x10too l\r\x00\x00\btso\xfea\x00\x00\b\x00\x00\x02\x01\xbf\xbd*\xde") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/21dddbcbb96168a528cca28beb419453d64f61d3db22a2998ddbb1bf581cb9aa b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/21dddbcbb96168a528cca28beb419453d64f61d3db22a2998ddbb1bf581cb9aa new file mode 100644 index 00000000..ce0dc605 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/21dddbcbb96168a528cca28beb419453d64f61d3db22a2998ddbb1bf581cb9aa @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x0035!2\x7f\x00\x00\x0033\x00\x00\bt\x009474452381LittleEnd2\x00\x00\bt\x009\x00\x00\x00\x00\x00\r\x00\x00\bt\x00\x06\x05\xff\x05@\x005\b") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/226aa282492968c6cc959c4023619a854a61baa014a731d71fe97d4ae74554a1 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/226aa282492968c6cc959c4023619a854a61baa014a731d71fe97d4ae74554a1 new file mode 100644 index 00000000..4e0d52ed --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/226aa282492968c6cc959c4023619a854a61baa014a731d71fe97d4ae74554a1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7Nlsli\x00too \x01\f\x00\x00\x03\xe8\x00 \x01\f\x00\x00\x03\x03\xe8\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/229a837762ca3a05681476f143b6ad9ec30bf5e9d3187a9e5a3c17a7decba189 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/229a837762ca3a05681476f143b6ad9ec30bf5e9d3187a9e5a3c17a7decba189 new file mode 100644 index 00000000..a4d119f2 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/229a837762ca3a05681476f143b6ad9ec30bf5e9d3187a9e5a3c17a7decba189 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7Nlsli\x00too l\x14\x00\x00\x00too l\x00\x00\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/22caa86510dd5c23c431c18f0d7886b2784624da0dc581e8caccc3ef5b995b7b b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/22caa86510dd5c23c431c18f0d7886b2784624da0dc581e8caccc3ef5b995b7b new file mode 100644 index 00000000..af881640 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/22caa86510dd5c23c431c18f0d7886b2784624da0dc581e8caccc3ef5b995b7b @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7Nl\x80li\x10\xfeoo l\r\x00\x00\bt \x00\x00\x00\x00\x00\b\x00\x00\x03\x01\xbf\x01\x01\xde") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/23dbfe6a2f0f5a2b7e1da49ec7f3d43e037555b9247390886d42675e46f714ef b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/23dbfe6a2f0f5a2b7e1da49ec7f3d43e037555b9247390886d42675e46f714ef new file mode 100644 index 00000000..10135733 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/23dbfe6a2f0f5a2b7e1da49ec7f3d43e037555b9247390886d42675e46f714ef @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16\xe7Nl\x80li\x10\xfeoo l\r\x00\x00\bt \x00\x00\x00\x00\x00\b\x00\x00\x03\x01\x01\x01\x01\xde") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/2424d8fd4880b69d76df156b5ef079151ad2ffa99ce6edf315bbc9bb4716a4dc b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/2424d8fd4880b69d76df156b5ef079151ad2ffa99ce6edf315bbc9bb4716a4dc new file mode 100644 index 00000000..1d0de4ef --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/2424d8fd4880b69d76df156b5ef079151ad2ffa99ce6edf315bbc9bb4716a4dc @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \x01\x00\x00355\x00\x00\x00\x00\x0033\x00\x00@t\x009474452381LittleEnd2\x00\x13\bt\x009\x00\x00\xfd\x00\x00\x02\x00\r\x00\x00\b\x00\x0e\xc0\xbd\x00\x02\x05\xff") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/25f666a9e3c0b6305ebd9193fda35041a026aa772c876e04a79fc1f6870d9653 b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/25f666a9e3c0b6305ebd9193fda35041a026aa772c876e04a79fc1f6870d9653 new file mode 100644 index 00000000..99230e47 --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/25f666a9e3c0b6305ebd9193fda35041a026aa772c876e04a79fc1f6870d9653 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x16ѽ\xbf\xef\xbfソ\xef\xbf{ \r\x00\x00355\x00\x00\x00\x00\x0030\x00\x00@t\x009574452381Little\x009574452\x009\x00\x00\x00\x02\x00\r\x00\x00\bt\x00\x06\x05\xff\x00\x80\x00\x00\x00") \ No newline at end of file diff --git a/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/279f37884661b8654da271bd28da5d76a942d2a723d16b147e3852198b552d8d b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/279f37884661b8654da271bd28da5d76a942d2a723d16b147e3852198b552d8d new file mode 100644 index 00000000..18d6933e --- /dev/null +++ b/pkg/protocol/recordlayer/testdata/fuzz/FuzzRecordLayer/279f37884661b8654da271bd28da5d76a942d2a723d16b147e3852198b552d8d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x14\xd11pion/renovate-config" ] } diff --git a/replayprotection_test.go b/replayprotection_test.go index 31758951..ce28df88 100644 --- a/replayprotection_test.go +++ b/replayprotection_test.go @@ -10,7 +10,7 @@ import ( "time" "github.com/pion/dtls/v2/internal/net/dpipe" - "github.com/pion/transport/test" + "github.com/pion/transport/v2/test" ) func TestReplayProtection(t *testing.T) { diff --git a/resume_test.go b/resume_test.go index cad3d2db..16624039 100644 --- a/resume_test.go +++ b/resume_test.go @@ -11,7 +11,7 @@ import ( "time" "github.com/pion/dtls/v2/pkg/crypto/selfsign" - "github.com/pion/transport/test" + "github.com/pion/transport/v2/test" ) var errMessageMissmatch = errors.New("messages missmatch") diff --git a/state.go b/state.go index 90afb89c..22c65c74 100644 --- a/state.go +++ b/state.go @@ -8,7 +8,7 @@ import ( "github.com/pion/dtls/v2/pkg/crypto/elliptic" "github.com/pion/dtls/v2/pkg/crypto/prf" "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/transport/replaydetector" + "github.com/pion/transport/v2/replaydetector" ) // State holds the dtls connection state and implements both encoding.BinaryMarshaler and encoding.BinaryUnmarshaler