From 4b76abf7c3d68eacb59ebac6085fcccc8b1fb2d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Jun 2023 14:50:40 +0000 Subject: [PATCH 001/146] Update module golang.org/x/crypto to v0.10.0 Generated by renovateBot --- go.mod | 4 ++-- go.sum | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 9d0d65615..2bb8d8637 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v2 v2.2.1 - golang.org/x/crypto v0.8.0 - golang.org/x/net v0.9.0 + golang.org/x/crypto v0.10.0 + golang.org/x/net v0.10.0 ) go 1.13 diff --git a/go.sum b/go.sum index 8144e06dd..78d00bea1 100644 --- a/go.sum +++ b/go.sum @@ -17,16 +17,17 @@ github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -37,15 +38,20 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= From 4fc3d8fc73005f3971d674a9c02415d7251cec4c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Jun 2023 16:44:59 +0000 Subject: [PATCH 002/146] Update module golang.org/x/net to v0.11.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 2bb8d8637..a086b0af5 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v2 v2.2.1 golang.org/x/crypto v0.10.0 - golang.org/x/net v0.10.0 + golang.org/x/net v0.11.0 ) go 1.13 diff --git a/go.sum b/go.sum index 78d00bea1..583ab9f46 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 8a11cf240b99f6ba7564066c9201c3ae11072bdb Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Mon, 26 Jun 2023 15:09:13 -0400 Subject: [PATCH 003/146] Remove extraneous error checks in handshaker Removes extraneous checks for flight error after alert error occurs. If we are sending alert then we already know that a flight error occurred. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- handshaker.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/handshaker.go b/handshaker.go index 1c6d58fe9..721fb77cf 100644 --- a/handshaker.go +++ b/handshaker.go @@ -263,9 +263,7 @@ func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, parse, errFlight := s.currentFlight.getFlightParser() if errFlight != nil { if alertErr := c.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil { - if errFlight != nil { - return handshakeErrored, alertErr - } + return handshakeErrored, alertErr } return handshakeErrored, errFlight } @@ -311,9 +309,7 @@ func (s *handshakeFSM) finish(ctx context.Context, c flightConn) (handshakeState parse, errFlight := s.currentFlight.getFlightParser() if errFlight != nil { if alertErr := c.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil { - if errFlight != nil { - return handshakeErrored, alertErr - } + return handshakeErrored, alertErr } return handshakeErrored, errFlight } From 159122f517a3846cd417618a8269bdef094c6810 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Thu, 29 Jun 2023 16:16:21 -0400 Subject: [PATCH 004/146] Update e2e Go image to 1.20 Updates the e2e Go base image to 1.20. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- e2e/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/Dockerfile b/e2e/Dockerfile index 68440e526..7df99615a 100644 --- a/e2e/Dockerfile +++ b/e2e/Dockerfile @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> # SPDX-License-Identifier: MIT -FROM docker.io/library/golang:1.18-bullseye +FROM docker.io/library/golang:1.20-bullseye COPY . /go/src/github.com/pion/dtls WORKDIR /go/src/github.com/pion/dtls/e2e From d7303d00133584b7cbd21ba55a458fbe5f941778 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Thu, 29 Jun 2023 16:17:03 -0400 Subject: [PATCH 005/146] Wait for OpenSSL server shutdown in e2e test Updates e2e tests to wait until server shutdown before completing to ensure that we do not trigger errors due to leaked watchCtx goroutine, which was added to os/exec.Command in Go 1.20. We do so by moving from implicit shutdown via context cancellation to explicit shutdown. https://tip.golang.org/doc/go1.20 Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- e2e/e2e_openssl_test.go | 8 ++++++-- e2e/e2e_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/e2e/e2e_openssl_test.go b/e2e/e2e_openssl_test.go index 25bffb35a..dbcda4a07 100644 --- a/e2e/e2e_openssl_test.go +++ b/e2e/e2e_openssl_test.go @@ -78,7 +78,7 @@ func serverOpenSSL(c *comm) { // launch command // #nosec G204 - cmd := exec.CommandContext(c.ctx, "openssl", args...) + cmd := exec.Command("openssl", args...) var inner net.Conn inner, c.serverConn = net.Pipe() cmd.Stdin = inner @@ -95,6 +95,8 @@ func serverOpenSSL(c *comm) { c.serverReady <- struct{}{} simpleReadWrite(c.errChan, c.serverChan, c.serverConn, c.messageRecvCount) + c.serverDone <- cmd.Process.Kill() + close(c.serverDone) }() } @@ -155,7 +157,7 @@ func clientOpenSSL(c *comm) { // launch command // #nosec G204 - cmd := exec.CommandContext(c.ctx, "openssl", args...) + cmd := exec.Command("openssl", args...) var inner net.Conn inner, c.clientConn = net.Pipe() cmd.Stdin = inner @@ -168,6 +170,8 @@ func clientOpenSSL(c *comm) { } simpleReadWrite(c.errChan, c.clientChan, c.clientConn, c.messageRecvCount) + c.clientDone <- cmd.Process.Kill() + close(c.clientDone) } func ciphersOpenSSL(cfg *dtls.Config) string { diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 25514eff8..736987ea4 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -85,10 +85,12 @@ type comm struct { messageRecvCount *uint64 // Counter to make sure both sides got a message clientMutex *sync.Mutex clientConn net.Conn + clientDone chan error serverMutex *sync.Mutex serverConn net.Conn serverListener net.Listener serverReady chan struct{} + serverDone chan error errChan chan error clientChan chan string serverChan chan string @@ -107,6 +109,8 @@ func newComm(ctx context.Context, clientConfig, serverConfig *dtls.Config, serve clientMutex: &sync.Mutex{}, serverMutex: &sync.Mutex{}, serverReady: make(chan struct{}), + serverDone: make(chan error), + clientDone: make(chan error), errChan: make(chan error), clientChan: make(chan string), serverChan: make(chan string), @@ -172,6 +176,32 @@ func (c *comm) assert(t *testing.T) { }() } +func (c *comm) cleanup(t *testing.T) { + clientDone, serverDone := false, false + for { + select { + case err := <-c.clientDone: + if err != nil { + t.Fatal(err) + } + clientDone = true + if clientDone && serverDone { + return + } + case err := <-c.serverDone: + if err != nil { + t.Fatal(err) + } + serverDone = true + if clientDone && serverDone { + return + } + case <-time.After(testTimeLimit): + t.Fatalf("Test timeout waiting for server shutdown") + } + } +} + func clientPion(c *comm) { select { case <-c.serverReady: @@ -194,6 +224,8 @@ func clientPion(c *comm) { } simpleReadWrite(c.errChan, c.clientChan, c.clientConn, c.messageRecvCount) + c.clientDone <- nil + close(c.clientDone) } func serverPion(c *comm) { @@ -217,6 +249,8 @@ func serverPion(c *comm) { } simpleReadWrite(c.errChan, c.serverChan, c.serverConn, c.messageRecvCount) + c.serverDone <- nil + close(c.serverDone) } /* @@ -254,6 +288,7 @@ func testPionE2ESimple(t *testing.T, server, client func(*comm)) { } serverPort := randomPort(t) comm := newComm(ctx, cfg, cfg, serverPort, server, client) + defer comm.cleanup(t) comm.assert(t) }) } @@ -287,6 +322,7 @@ func testPionE2ESimplePSK(t *testing.T, server, client func(*comm)) { } serverPort := randomPort(t) comm := newComm(ctx, cfg, cfg, serverPort, server, client) + defer comm.cleanup(t) comm.assert(t) }) } @@ -322,6 +358,7 @@ func testPionE2EMTUs(t *testing.T, server, client func(*comm)) { } serverPort := randomPort(t) comm := newComm(ctx, cfg, cfg, serverPort, server, client) + defer comm.cleanup(t) comm.assert(t) }) } @@ -362,6 +399,7 @@ func testPionE2ESimpleED25519(t *testing.T, server, client func(*comm)) { } serverPort := randomPort(t) comm := newComm(ctx, cfg, cfg, serverPort, server, client) + defer comm.cleanup(t) comm.assert(t) }) } @@ -407,6 +445,7 @@ func testPionE2ESimpleED25519ClientCert(t *testing.T, server, client func(*comm) } serverPort := randomPort(t) comm := newComm(ctx, ccfg, scfg, serverPort, server, client) + defer comm.cleanup(t) comm.assert(t) } @@ -450,6 +489,7 @@ func testPionE2ESimpleECDSAClientCert(t *testing.T, server, client func(*comm)) } serverPort := randomPort(t) comm := newComm(ctx, ccfg, scfg, serverPort, server, client) + defer comm.cleanup(t) comm.assert(t) } @@ -493,6 +533,7 @@ func testPionE2ESimpleRSAClientCert(t *testing.T, server, client func(*comm)) { } serverPort := randomPort(t) comm := newComm(ctx, ccfg, scfg, serverPort, server, client) + defer comm.cleanup(t) comm.assert(t) } From 265bf118a44195fecdce5a30b53b374d80ce9272 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Thu, 6 Jul 2023 09:44:54 -0400 Subject: [PATCH 006/146] Enable Elliptic Curve Supported Point Formats Enables parsing the elliptic curve supported points format extension. https://www.rfc-editor.org/rfc/rfc8422.html#section-5.1.2 Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- pkg/protocol/extension/extension.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/protocol/extension/extension.go b/pkg/protocol/extension/extension.go index 5173a5863..ad59d57d3 100644 --- a/pkg/protocol/extension/extension.go +++ b/pkg/protocol/extension/extension.go @@ -64,6 +64,8 @@ func Unmarshal(buf []byte) ([]Extension, error) { err = unmarshalAndAppend(buf[offset:], &ServerName{}) case SupportedEllipticCurvesTypeValue: err = unmarshalAndAppend(buf[offset:], &SupportedEllipticCurves{}) + case SupportedPointFormatsTypeValue: + err = unmarshalAndAppend(buf[offset:], &SupportedPointFormats{}) case UseSRTPTypeValue: err = unmarshalAndAppend(buf[offset:], &UseSRTP{}) case ALPNTypeValue: From cabe5b8528941cec5aa45ac1fcb19937ad3cf768 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Thu, 6 Jul 2023 09:52:48 -0400 Subject: [PATCH 007/146] Enable Supported Signature Algorithms Enables parsing the supported signature algorithms extension. https://datatracker.ietf.org/doc/html/rfc5246#autoid-39 Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- pkg/protocol/extension/extension.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/protocol/extension/extension.go b/pkg/protocol/extension/extension.go index ad59d57d3..a931f4427 100644 --- a/pkg/protocol/extension/extension.go +++ b/pkg/protocol/extension/extension.go @@ -66,6 +66,8 @@ func Unmarshal(buf []byte) ([]Extension, error) { err = unmarshalAndAppend(buf[offset:], &SupportedEllipticCurves{}) case SupportedPointFormatsTypeValue: err = unmarshalAndAppend(buf[offset:], &SupportedPointFormats{}) + case SupportedSignatureAlgorithmsTypeValue: + err = unmarshalAndAppend(buf[offset:], &SupportedSignatureAlgorithms{}) case UseSRTPTypeValue: err = unmarshalAndAppend(buf[offset:], &UseSRTP{}) case ALPNTypeValue: From 93704b3dc9e42cd9f75eff352441c631d67c7227 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Thu, 6 Jul 2023 09:57:59 -0400 Subject: [PATCH 008/146] Add Daniel Mangum to AUTHORS.txt Adds Daniel Mangum to AUTHORS.txt. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index e14fae4c0..7b3d2ae2b 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -15,6 +15,7 @@ Carson Hoffman <c@rsonhoffman.com> Cecylia Bocovich <cohosh@torproject.org> Chris Hiszpanski <thinkski@users.noreply.github.com> cnderrauber <zengjie9004@gmail.com> +Daniel Mangum <georgedanielmangum@gmail.com> Daniele Sluijters <daenney@users.noreply.github.com> folbrich <frank.olbricht@gmail.com> Hayden James <hayden.james@gmail.com> From 0736d456559b18c0e4443d9ce321fc0ff53727c1 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Thu, 6 Jul 2023 11:05:39 -0400 Subject: [PATCH 009/146] Fix parsing supported EC point formats Fixes error in parsing supported elliptic curve point formats extension. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- pkg/protocol/extension/supported_point_formats.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/protocol/extension/supported_point_formats.go b/pkg/protocol/extension/supported_point_formats.go index 9c2543e6e..5ed0f347f 100644 --- a/pkg/protocol/extension/supported_point_formats.go +++ b/pkg/protocol/extension/supported_point_formats.go @@ -44,12 +44,14 @@ func (s *SupportedPointFormats) Marshal() ([]byte, error) { func (s *SupportedPointFormats) Unmarshal(data []byte) error { if len(data) <= supportedPointFormatsSize { return errBufferTooSmall - } else if TypeValue(binary.BigEndian.Uint16(data)) != s.TypeValue() { + } + + if TypeValue(binary.BigEndian.Uint16(data)) != s.TypeValue() { return errInvalidExtensionType } - pointFormatCount := int(binary.BigEndian.Uint16(data[4:])) - if supportedGroupsHeaderSize+(pointFormatCount) > len(data) { + pointFormatCount := int(data[4]) + if supportedPointFormatsSize+pointFormatCount > len(data) { return errLengthMismatch } From b905606b3fcc1a186a8d245a799c0a2ffb7014e4 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Thu, 6 Jul 2023 12:34:11 -0400 Subject: [PATCH 010/146] Add unmarshal unit tests for extensions Adds missing unmarshal unit tests for extensions that did not have them. These ensure that marshal / unmarshal is round-trippable. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- pkg/protocol/extension/supported_elliptic_curves_test.go | 7 +++++++ pkg/protocol/extension/supported_point_formats_test.go | 7 +++++++ .../extension/supported_signature_algorithms_test.go | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/pkg/protocol/extension/supported_elliptic_curves_test.go b/pkg/protocol/extension/supported_elliptic_curves_test.go index c00554be1..3f7098bdd 100644 --- a/pkg/protocol/extension/supported_elliptic_curves_test.go +++ b/pkg/protocol/extension/supported_elliptic_curves_test.go @@ -22,4 +22,11 @@ func TestExtensionSupportedGroups(t *testing.T) { } else if !reflect.DeepEqual(raw, rawSupportedGroups) { t.Errorf("extensionSupportedGroups marshal: got %#v, want %#v", raw, rawSupportedGroups) } + + roundtrip := &SupportedEllipticCurves{} + if err := roundtrip.Unmarshal(raw); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(roundtrip, parsedSupportedGroups) { + t.Errorf("extensionSupportedGroups unmarshal: got %#v, want %#v", roundtrip, parsedSupportedGroups) + } } diff --git a/pkg/protocol/extension/supported_point_formats_test.go b/pkg/protocol/extension/supported_point_formats_test.go index 7db3f0135..d01ea5992 100644 --- a/pkg/protocol/extension/supported_point_formats_test.go +++ b/pkg/protocol/extension/supported_point_formats_test.go @@ -22,4 +22,11 @@ func TestExtensionSupportedPointFormats(t *testing.T) { } else if !reflect.DeepEqual(raw, rawExtensionSupportedPointFormats) { t.Errorf("extensionSupportedPointFormats marshal: got %#v, want %#v", raw, rawExtensionSupportedPointFormats) } + + roundtrip := &SupportedPointFormats{} + if err := roundtrip.Unmarshal(raw); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(roundtrip, parsedExtensionSupportedPointFormats) { + t.Errorf("extensionSupportedPointFormats unmarshal: got %#v, want %#v", roundtrip, parsedExtensionSupportedPointFormats) + } } diff --git a/pkg/protocol/extension/supported_signature_algorithms_test.go b/pkg/protocol/extension/supported_signature_algorithms_test.go index dbea9c126..fbaa55022 100644 --- a/pkg/protocol/extension/supported_signature_algorithms_test.go +++ b/pkg/protocol/extension/supported_signature_algorithms_test.go @@ -35,4 +35,11 @@ func TestExtensionSupportedSignatureAlgorithms(t *testing.T) { } else if !reflect.DeepEqual(raw, rawExtensionSupportedSignatureAlgorithms) { t.Errorf("extensionSupportedSignatureAlgorithms marshal: got %#v, want %#v", raw, rawExtensionSupportedSignatureAlgorithms) } + + roundtrip := &SupportedSignatureAlgorithms{} + if err := roundtrip.Unmarshal(raw); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(roundtrip, parsedExtensionSupportedSignatureAlgorithms) { + t.Errorf("extensionSupportedSignatureAlgorithms unmarshal: got %#v, want %#v", roundtrip, parsedExtensionSupportedSignatureAlgorithms) + } } From 7307f627e106e7c22384c7b528dd3af654ef7f0d Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Mon, 10 Jul 2023 21:21:50 -0400 Subject: [PATCH 011/146] Fix return of nil alertErrors Fixes two cases where nil alert errors were being returned rather than the underlying error. Calling methods on these nil alert errors can lead to panics. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- conn.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conn.go b/conn.go index 2b7585108..a84e878e9 100644 --- a/conn.go +++ b/conn.go @@ -615,7 +615,7 @@ func (c *Conn) readAndBuffer(ctx context.Context) error { return e } } else if err != nil { - return e + return err } } if hasHandshake { @@ -650,7 +650,7 @@ func (c *Conn) handleQueuedPackets(ctx context.Context) error { return e } } else if err != nil { - return e + return err } } return nil From b03384756911d44587ed17daac271e97bfaf6e90 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Mon, 10 Jul 2023 21:33:18 -0400 Subject: [PATCH 012/146] Clean up unneccessary nested logic Cleans up a few unneccessary else blocks and nested if statements. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- conn.go | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/conn.go b/conn.go index a84e878e9..4194129ba 100644 --- a/conn.go +++ b/conn.go @@ -605,18 +605,17 @@ func (c *Conn) readAndBuffer(ctx context.Context) error { } } } - if hs { - hasHandshake = true - } var e *alertError - if errors.As(err, &e) { - if e.IsFatalOrCloseNotify() { - return e - } - } else if err != nil { + if errors.As(err, &e) && e.IsFatalOrCloseNotify() { + return e + } + if err != nil { return err } + if hs { + hasHandshake = true + } } if hasHandshake { done := make(chan struct{}) @@ -645,11 +644,10 @@ func (c *Conn) handleQueuedPackets(ctx context.Context) error { } } var e *alertError - if errors.As(err, &e) { - if e.IsFatalOrCloseNotify() { - return e - } - } else if err != nil { + if errors.As(err, &e) && e.IsFatalOrCloseNotify() { + return e + } + if err != nil { return err } } From c9eb5f202d7d9f72e1d61f9cd73e757d23e2a261 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 05:00:32 +0000 Subject: [PATCH 013/146] Update module golang.org/x/net to v0.12.0 Generated by renovateBot --- go.mod | 4 ++-- go.sum | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index a086b0af5..8c28e29bf 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v2 v2.2.1 - golang.org/x/crypto v0.10.0 - golang.org/x/net v0.11.0 + golang.org/x/crypto v0.11.0 + golang.org/x/net v0.12.0 ) go 1.13 diff --git a/go.sum b/go.sum index 583ab9f46..cf26a2155 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -27,8 +27,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= -golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -40,19 +40,19 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= From eb34e7d39490ed1ff00afe9aa5cf439554fe5af7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 22:36:35 +0000 Subject: [PATCH 014/146] Update module golang.org/x/net to v0.13.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8c28e29bf..36abd6c0b 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v2 v2.2.1 golang.org/x/crypto v0.11.0 - golang.org/x/net v0.12.0 + golang.org/x/net v0.13.0 ) go 1.13 diff --git a/go.sum b/go.sum index cf26a2155..3ac5e3e1d 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= +golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From a6eca6cb3219d7386b8fed429fcbebde6a94a93f Mon Sep 17 00:00:00 2001 From: Pion <59523206+pionbot@users.noreply.github.com> Date: Sat, 5 Aug 2023 17:45:38 +0000 Subject: [PATCH 015/146] Update CI configs to v0.10.11 Update lint scripts and CI configs. --- .reuse/dep5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.reuse/dep5 b/.reuse/dep5 index c8b3dfa09..717f0c1c2 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -2,7 +2,7 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Pion Source: https://github.com/pion/ -Files: README.md DESIGN.md **/README.md AUTHORS.txt renovate.json go.mod go.sum .eslintrc.json package.json examples/examples.json +Files: README.md DESIGN.md **/README.md AUTHORS.txt renovate.json go.mod go.sum **/go.mod **/go.sum .eslintrc.json package.json examples/examples.json Copyright: 2023 The Pion community <https://pion.ly> License: MIT From a1d270fc5f1878664adf60e7ee653e4aafbdfc04 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 5 Aug 2023 21:43:32 +0000 Subject: [PATCH 016/146] Update module golang.org/x/crypto to v0.12.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 36abd6c0b..cef651caf 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v2 v2.2.1 - golang.org/x/crypto v0.11.0 + golang.org/x/crypto v0.12.0 golang.org/x/net v0.13.0 ) diff --git a/go.sum b/go.sum index 3ac5e3e1d..948a48245 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,9 @@ github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -41,18 +42,21 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= From e9b3ce0059b4ce200e8953d360d5a4394f95200e Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:31:16 -0400 Subject: [PATCH 017/146] Update pion/transport to latest Updates pion/transport to v2.2.2-0.20230802201558-f2dffd80896b to consume the new netctx packages and the replaydetector updates. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- go.mod | 2 +- go.sum | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index cef651caf..b35260c67 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 - github.com/pion/transport/v2 v2.2.1 + github.com/pion/transport/v2 v2.2.2-0.20230802201558-f2dffd80896b golang.org/x/crypto v0.12.0 golang.org/x/net v0.13.0 ) diff --git a/go.sum b/go.sum index 948a48245..b73379cfc 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= -github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v2 v2.2.2-0.20230802201558-f2dffd80896b h1:g/axuqY9eU5L6YeAQSq+yW4CU5fPqOb90EaWI+8xeiI= +github.com/pion/transport/v2 v2.2.2-0.20230802201558-f2dffd80896b/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -12,8 +12,8 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -26,7 +26,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= @@ -39,14 +38,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= From 9e4a4e7262f2533c67e0bfead96a54786c58ba72 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:33:57 -0400 Subject: [PATCH 018/146] Add DTLS connection ID extension Adds the DTLS 1.2 connection ID extension to supported handshake extensions. Connection ID uses 54 as its identifier and includes a potentially empty connection ID. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- pkg/protocol/extension/connection_id.go | 59 +++++++++++++++++++ pkg/protocol/extension/connection_id_test.go | 30 ++++++++++ pkg/protocol/extension/errors.go | 1 + pkg/protocol/extension/extension.go | 3 + .../supported_elliptic_curves_test.go | 4 +- .../extension/supported_point_formats_test.go | 4 +- .../supported_signature_algorithms_test.go | 4 +- 7 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 pkg/protocol/extension/connection_id.go create mode 100644 pkg/protocol/extension/connection_id_test.go diff --git a/pkg/protocol/extension/connection_id.go b/pkg/protocol/extension/connection_id.go new file mode 100644 index 000000000..b3fe1640f --- /dev/null +++ b/pkg/protocol/extension/connection_id.go @@ -0,0 +1,59 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +package extension + +import ( + "golang.org/x/crypto/cryptobyte" +) + +// ConnectionID is a DTLS extension that provides an alternative to IP address +// and port for session association. +// +// https://tools.ietf.org/html/rfc9146 +type ConnectionID struct { + // A zero-length connection ID indicates for a client or server that + // negotiated connection IDs from the peer will be sent but there is no need + // to respond with one + CID []byte // variable length +} + +// TypeValue returns the extension TypeValue +func (c ConnectionID) TypeValue() TypeValue { + return ConnectionIDTypeValue +} + +// Marshal encodes the extension +func (c *ConnectionID) Marshal() ([]byte, error) { + var b cryptobyte.Builder + b.AddUint16(uint16(c.TypeValue())) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(c.CID) + }) + }) + return b.Bytes() +} + +// Unmarshal populates the extension from encoded data +func (c *ConnectionID) Unmarshal(data []byte) error { + val := cryptobyte.String(data) + var extension uint16 + val.ReadUint16(&extension) + if TypeValue(extension) != c.TypeValue() { + return errInvalidExtensionType + } + + var extData cryptobyte.String + val.ReadUint16LengthPrefixed(&extData) + + var cid cryptobyte.String + if !extData.ReadUint8LengthPrefixed(&cid) { + return errInvalidCIDFormat + } + c.CID = make([]byte, len(cid)) + if !cid.CopyBytes(c.CID) { + return errInvalidCIDFormat + } + return nil +} diff --git a/pkg/protocol/extension/connection_id_test.go b/pkg/protocol/extension/connection_id_test.go new file mode 100644 index 000000000..e9736172d --- /dev/null +++ b/pkg/protocol/extension/connection_id_test.go @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +package extension + +import ( + "reflect" + "testing" +) + +func TestExtensionConnectionID(t *testing.T) { + rawExtensionConnectionID := []byte{1, 6, 8, 3, 88, 12, 2, 47} + parsedExtensionConnectionID := &ConnectionID{ + CID: rawExtensionConnectionID, + } + + raw, err := parsedExtensionConnectionID.Marshal() + if err != nil { + t.Fatal(err) + } + + roundtrip := &ConnectionID{} + if err := roundtrip.Unmarshal(raw); err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(roundtrip, parsedExtensionConnectionID) { + t.Errorf("parsedExtensionConnectionID unmarshal: got %#v, want %#v", roundtrip, parsedExtensionConnectionID) + } +} diff --git a/pkg/protocol/extension/errors.go b/pkg/protocol/extension/errors.go index c5e954ce5..39431206f 100644 --- a/pkg/protocol/extension/errors.go +++ b/pkg/protocol/extension/errors.go @@ -16,5 +16,6 @@ var ( errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 errInvalidExtensionType = &protocol.FatalError{Err: errors.New("invalid extension type")} //nolint:goerr113 errInvalidSNIFormat = &protocol.FatalError{Err: errors.New("invalid server name format")} //nolint:goerr113 + errInvalidCIDFormat = &protocol.FatalError{Err: errors.New("invalid connection ID format")} //nolint:goerr113 errLengthMismatch = &protocol.InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113 ) diff --git a/pkg/protocol/extension/extension.go b/pkg/protocol/extension/extension.go index a931f4427..e4df859f8 100644 --- a/pkg/protocol/extension/extension.go +++ b/pkg/protocol/extension/extension.go @@ -20,6 +20,7 @@ const ( UseSRTPTypeValue TypeValue = 14 ALPNTypeValue TypeValue = 16 UseExtendedMasterSecretTypeValue TypeValue = 23 + ConnectionIDTypeValue TypeValue = 54 RenegotiationInfoTypeValue TypeValue = 65281 ) @@ -76,6 +77,8 @@ func Unmarshal(buf []byte) ([]Extension, error) { err = unmarshalAndAppend(buf[offset:], &UseExtendedMasterSecret{}) case RenegotiationInfoTypeValue: err = unmarshalAndAppend(buf[offset:], &RenegotiationInfo{}) + case ConnectionIDTypeValue: + err = unmarshalAndAppend(buf[offset:], &ConnectionID{}) default: } if err != nil { diff --git a/pkg/protocol/extension/supported_elliptic_curves_test.go b/pkg/protocol/extension/supported_elliptic_curves_test.go index 3f7098bdd..dc6c6c502 100644 --- a/pkg/protocol/extension/supported_elliptic_curves_test.go +++ b/pkg/protocol/extension/supported_elliptic_curves_test.go @@ -18,9 +18,9 @@ func TestExtensionSupportedGroups(t *testing.T) { raw, err := parsedSupportedGroups.Marshal() if err != nil { - t.Error(err) + t.Fatal(err) } else if !reflect.DeepEqual(raw, rawSupportedGroups) { - t.Errorf("extensionSupportedGroups marshal: got %#v, want %#v", raw, rawSupportedGroups) + t.Fatalf("extensionSupportedGroups marshal: got %#v, want %#v", raw, rawSupportedGroups) } roundtrip := &SupportedEllipticCurves{} diff --git a/pkg/protocol/extension/supported_point_formats_test.go b/pkg/protocol/extension/supported_point_formats_test.go index d01ea5992..81862679a 100644 --- a/pkg/protocol/extension/supported_point_formats_test.go +++ b/pkg/protocol/extension/supported_point_formats_test.go @@ -18,9 +18,9 @@ func TestExtensionSupportedPointFormats(t *testing.T) { raw, err := parsedExtensionSupportedPointFormats.Marshal() if err != nil { - t.Error(err) + t.Fatal(err) } else if !reflect.DeepEqual(raw, rawExtensionSupportedPointFormats) { - t.Errorf("extensionSupportedPointFormats marshal: got %#v, want %#v", raw, rawExtensionSupportedPointFormats) + t.Fatalf("extensionSupportedPointFormats marshal: got %#v, want %#v", raw, rawExtensionSupportedPointFormats) } roundtrip := &SupportedPointFormats{} diff --git a/pkg/protocol/extension/supported_signature_algorithms_test.go b/pkg/protocol/extension/supported_signature_algorithms_test.go index fbaa55022..16fce4793 100644 --- a/pkg/protocol/extension/supported_signature_algorithms_test.go +++ b/pkg/protocol/extension/supported_signature_algorithms_test.go @@ -31,9 +31,9 @@ func TestExtensionSupportedSignatureAlgorithms(t *testing.T) { raw, err := parsedExtensionSupportedSignatureAlgorithms.Marshal() if err != nil { - t.Error(err) + t.Fatal(err) } else if !reflect.DeepEqual(raw, rawExtensionSupportedSignatureAlgorithms) { - t.Errorf("extensionSupportedSignatureAlgorithms marshal: got %#v, want %#v", raw, rawExtensionSupportedSignatureAlgorithms) + t.Fatalf("extensionSupportedSignatureAlgorithms marshal: got %#v, want %#v", raw, rawExtensionSupportedSignatureAlgorithms) } roundtrip := &SupportedSignatureAlgorithms{} From 20051350b7fc1562a3ad6cf7fdee6f74b82237ec Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:36:02 -0400 Subject: [PATCH 019/146] Add support for parsing CID records Adds support for parsing CID records, which wrap an internal in inner plaintext. Consumers of ContentAwareUnpackDatagram must specify the CID length. The HeaderSize of 13 is now referred to as FixedHeaderSize to indicate that CID records will have variable sized headers. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- pkg/protocol/recordlayer/fuzz_test.go | 7 +-- pkg/protocol/recordlayer/header.go | 29 +++++++++-- pkg/protocol/recordlayer/inner_plaintext.go | 47 +++++++++++++++++ pkg/protocol/recordlayer/recordlayer.go | 57 ++++++++++++++++++--- 4 files changed, 126 insertions(+), 14 deletions(-) create mode 100644 pkg/protocol/recordlayer/inner_plaintext.go diff --git a/pkg/protocol/recordlayer/fuzz_test.go b/pkg/protocol/recordlayer/fuzz_test.go index 6379d9d17..716b5c8a2 100644 --- a/pkg/protocol/recordlayer/fuzz_test.go +++ b/pkg/protocol/recordlayer/fuzz_test.go @@ -4,13 +4,14 @@ package recordlayer import ( + "reflect" "testing" ) -func partialHeaderMismatch(a, b Header) bool { +func headerMismatch(a, b Header) bool { // Ignoring content length for now. a.ContentLen = b.ContentLen - return a != b + return !reflect.DeepEqual(a, b) } func FuzzRecordLayer(f *testing.F) { @@ -34,7 +35,7 @@ func FuzzRecordLayer(f *testing.F) { t.Fatal(err) } - if partialHeaderMismatch(nr.Header, r.Header) { + if headerMismatch(nr.Header, r.Header) { t.Fatalf("Header mismatch: %+v != %+v", nr.Header, r.Header) } }) diff --git a/pkg/protocol/recordlayer/header.go b/pkg/protocol/recordlayer/header.go index 92252502b..66a1be810 100644 --- a/pkg/protocol/recordlayer/header.go +++ b/pkg/protocol/recordlayer/header.go @@ -17,11 +17,16 @@ type Header struct { Version protocol.Version Epoch uint16 SequenceNumber uint64 // uint48 in spec + + // Optional Fields + ConnectionID []byte } // RecordLayer enums const ( - HeaderSize = 13 + // FixedHeaderSize is the size of a DTLS record header when connection IDs + // are not in use. + FixedHeaderSize = 13 MaxSequenceNumber = 0x0000FFFFFFFFFFFF ) @@ -31,22 +36,33 @@ func (h *Header) Marshal() ([]byte, error) { return nil, errSequenceNumberOverflow } - out := make([]byte, HeaderSize) + hs := FixedHeaderSize + len(h.ConnectionID) + + out := make([]byte, hs) out[0] = byte(h.ContentType) out[1] = h.Version.Major out[2] = h.Version.Minor binary.BigEndian.PutUint16(out[3:], h.Epoch) util.PutBigEndianUint48(out[5:], h.SequenceNumber) - binary.BigEndian.PutUint16(out[HeaderSize-2:], h.ContentLen) + copy(out[11:11+len(h.ConnectionID)], h.ConnectionID) + binary.BigEndian.PutUint16(out[hs-2:], h.ContentLen) return out, nil } // Unmarshal populates a TLS RecordLayer Header from binary func (h *Header) Unmarshal(data []byte) error { - if len(data) < HeaderSize { + if len(data) < FixedHeaderSize { return errBufferTooSmall } h.ContentType = protocol.ContentType(data[0]) + if h.ContentType == protocol.ContentTypeConnectionID { + // If a CID was expected the ConnectionID should have been initialized. + if len(data) < FixedHeaderSize+len(h.ConnectionID) { + return errBufferTooSmall + } + h.ConnectionID = data[11 : 11+len(h.ConnectionID)] + } + h.Version.Major = data[1] h.Version.Minor = data[2] h.Epoch = binary.BigEndian.Uint16(data[3:]) @@ -62,3 +78,8 @@ func (h *Header) Unmarshal(data []byte) error { return nil } + +// Size returns the total size of the header. +func (h *Header) Size() int { + return FixedHeaderSize + len(h.ConnectionID) +} diff --git a/pkg/protocol/recordlayer/inner_plaintext.go b/pkg/protocol/recordlayer/inner_plaintext.go new file mode 100644 index 000000000..bbc94dd80 --- /dev/null +++ b/pkg/protocol/recordlayer/inner_plaintext.go @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +package recordlayer + +import ( + "github.com/pion/dtls/v2/pkg/protocol" + "golang.org/x/crypto/cryptobyte" +) + +// InnerPlaintext implements DTLSInnerPlaintext +// +// https://datatracker.ietf.org/doc/html/rfc9146#name-record-layer-extensions +type InnerPlaintext struct { + Content []byte + RealType protocol.ContentType + Zeros uint +} + +// Marshal encodes a DTLS InnerPlaintext to binary +func (p *InnerPlaintext) Marshal() ([]byte, error) { + var out cryptobyte.Builder + out.AddBytes(p.Content) + out.AddUint8(uint8(p.RealType)) + out.AddBytes(make([]byte, p.Zeros)) + return out.Bytes() +} + +// Unmarshal populates a DTLS InnerPlaintext from binary +func (p *InnerPlaintext) Unmarshal(data []byte) error { + // Process in reverse + i := len(data) - 1 + for i >= 0 { + if data[i] != 0 { + p.Zeros = uint(len(data) - 1 - i) + break + } + i-- + } + if i == 0 { + return errBufferTooSmall + } + p.RealType = protocol.ContentType(data[i]) + p.Content = append([]byte{}, data[:i]...) + + return nil +} diff --git a/pkg/protocol/recordlayer/recordlayer.go b/pkg/protocol/recordlayer/recordlayer.go index 02325fd2d..213a7976a 100644 --- a/pkg/protocol/recordlayer/recordlayer.go +++ b/pkg/protocol/recordlayer/recordlayer.go @@ -11,6 +11,23 @@ import ( "github.com/pion/dtls/v2/pkg/protocol/handshake" ) +// DTLS fixed size record layer header when Connection IDs are not in-use. + +// --------------------------------- +// | Type | Version | Epoch | +// --------------------------------- +// | Epoch | Sequence Number | +// --------------------------------- +// | Sequence Number | Length | +// --------------------------------- +// | Length | Fragment... | +// --------------------------------- + +// fixedHeaderLenIdx is the index at which the record layer content length is +// specified in a fixed length header (i.e. one that does not include a +// Connection ID). +const fixedHeaderLenIdx = 11 + // RecordLayer which handles all data transport. // The record layer is assumed to sit directly on top of some // reliable transport such as TCP. The record layer can carry four types of content: @@ -51,14 +68,11 @@ func (r *RecordLayer) Marshal() ([]byte, error) { // Unmarshal populates the RecordLayer from binary func (r *RecordLayer) Unmarshal(data []byte) error { - if len(data) < HeaderSize { - return errBufferTooSmall - } if err := r.Header.Unmarshal(data); err != nil { return err } - switch protocol.ContentType(data[0]) { + switch r.Header.ContentType { case protocol.ContentTypeChangeCipherSpec: r.Content = &protocol.ChangeCipherSpec{} case protocol.ContentTypeAlert: @@ -71,7 +85,7 @@ func (r *RecordLayer) Unmarshal(data []byte) error { return errInvalidContentType } - return r.Content.Unmarshal(data[HeaderSize:]) + return r.Content.Unmarshal(data[r.Header.Size()+len(r.Header.ConnectionID):]) } // UnpackDatagram extracts all RecordLayer messages from a single datagram. @@ -85,11 +99,40 @@ func UnpackDatagram(buf []byte) ([][]byte, error) { out := [][]byte{} for offset := 0; len(buf) != offset; { - if len(buf)-offset <= HeaderSize { + if len(buf)-offset <= FixedHeaderSize { + return nil, errInvalidPacketLength + } + + pktLen := (FixedHeaderSize + int(binary.BigEndian.Uint16(buf[offset+11:]))) + if offset+pktLen > len(buf) { + return nil, errInvalidPacketLength + } + + out = append(out, buf[offset:offset+pktLen]) + offset += pktLen + } + + return out, nil +} + +// ContentAwareUnpackDatagram is the same as UnpackDatagram but considers the +// presence of a connection identifier if the record is of content type +// tls12_cid. +func ContentAwareUnpackDatagram(buf []byte, cidLength int) ([][]byte, error) { + out := [][]byte{} + + for offset := 0; len(buf) != offset; { + headerSize := FixedHeaderSize + lenIdx := fixedHeaderLenIdx + if protocol.ContentType(buf[offset]) == protocol.ContentTypeConnectionID { + headerSize += cidLength + lenIdx += cidLength + } + if len(buf)-offset <= headerSize { return nil, errInvalidPacketLength } - pktLen := (HeaderSize + int(binary.BigEndian.Uint16(buf[offset+11:]))) + pktLen := (headerSize + int(binary.BigEndian.Uint16(buf[offset+lenIdx:]))) if offset+pktLen > len(buf) { return nil, errInvalidPacketLength } From b7b1e445670f7b0699824f462e0b4d5a6e9bbfd6 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:39:23 -0400 Subject: [PATCH 020/146] Add support for CID related generators ConnectionIDGenerator generates connection identifiers that should be sent by the remote party if it supports the DTLS Connection Identifier extension, as determined during the handshake. Generated connection identifiers must always have the same length. Returning a zero-length connection identifier indicates that the local party supports sending connection identifiers but does not require the remote party to send them. A nil ConnectionIDGenerator indicates that connection identifiers are not supported. https://datatracker.ietf.org/doc/html/rfc9146 PaddingLengthGenerator generates the number of padding bytes used to inflate ciphertext size in order to obscure content size from observers. The length of the content is passed to the generator such that both deterministic and random padding schemes can be applied while not exceeding maximum record size. If no PaddingLengthGenerator is specified, padding will not be applied. https://datatracker.ietf.org/doc/html/rfc9146#section-4 Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- config.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/config.go b/config.go index fbc3ee247..604a4d575 100644 --- a/config.go +++ b/config.go @@ -176,6 +176,26 @@ type Config struct { // skip hello verify phase and receive ServerHello after initial ClientHello. // This have implication on DoS attack resistance. InsecureSkipVerifyHello bool + + // ConnectionIDGenerator generates connection identifiers that should be + // sent by the remote party if it supports the DTLS Connection Identifier + // extension, as determined during the handshake. Generated connection + // identifiers must always have the same length. Returning a zero-length + // connection identifier indicates that the local party supports sending + // connection identifiers but does not require the remote party to send + // them. A nil ConnectionIDGenerator indicates that connection identifiers + // are not supported. + // https://datatracker.ietf.org/doc/html/rfc9146 + ConnectionIDGenerator func() []byte + + // PaddingLengthGenerator generates the number of padding bytes used to + // inflate ciphertext size in order to obscure content size from observers. + // The length of the content is passed to the generator such that both + // deterministic and random padding schemes can be applied while not + // exceeding maximum record size. + // If no PaddingLengthGenerator is specified, padding will not be applied. + // https://datatracker.ietf.org/doc/html/rfc9146#section-4 + PaddingLengthGenerator func(uint) uint } func defaultConnectContextMaker() (context.Context, func()) { From 6af61b1f2be1e228b014bfb741cdfe881c21838c Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:42:43 -0400 Subject: [PATCH 021/146] Allow packets to specify CID wrapped Updates the packet structure to allow for specifying the a given packet should be stuffed in the inner plaintext of a CID record. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- packet.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packet.go b/packet.go index 55d6272ee..052c33a19 100644 --- a/packet.go +++ b/packet.go @@ -3,10 +3,13 @@ package dtls -import "github.com/pion/dtls/v2/pkg/protocol/recordlayer" +import ( + "github.com/pion/dtls/v2/pkg/protocol/recordlayer" +) type packet struct { record *recordlayer.RecordLayer shouldEncrypt bool + shouldWrapCID bool resetLocalSequenceNumber bool } From 1ce6f273df4165dee10dfa5b0764e931510a0e6f Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:44:12 -0400 Subject: [PATCH 022/146] Add CID content type Adds the connection ID content type, which used 25 as identifier. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- pkg/protocol/content.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/protocol/content.go b/pkg/protocol/content.go index 92c9db2bf..154005e2c 100644 --- a/pkg/protocol/content.go +++ b/pkg/protocol/content.go @@ -14,6 +14,7 @@ const ( ContentTypeAlert ContentType = 21 ContentTypeHandshake ContentType = 22 ContentTypeApplicationData ContentType = 23 + ContentTypeConnectionID ContentType = 25 ) // Content is the top level distinguisher for a DTLS Datagram From 9a37bfd5d0e93800c458d0cb0bdbf571065cc180 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:45:23 -0400 Subject: [PATCH 023/146] Implement AddUint48 utility Adds the AddUint48 utility used to handle sequence numbers in DTLS records. This should be removed when https://github.com/golang/crypto/pull/265 is implemented. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- internal/util/util.go | 9 ++++++ internal/util/util_test.go | 63 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 internal/util/util_test.go diff --git a/internal/util/util.go b/internal/util/util.go index 685910fc2..382a0e1cd 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -6,6 +6,8 @@ package util import ( "encoding/binary" + + "golang.org/x/crypto/cryptobyte" ) // BigEndianUint24 returns the value of a big endian uint24 @@ -40,3 +42,10 @@ func Max(a, b int) int { } return b } + +// AddUint48 appends a big-endian, 48-bit value to the byte string. +// Remove if / when https://github.com/golang/crypto/pull/265 is merged +// upstream. +func AddUint48(b *cryptobyte.Builder, v uint64) { + b.AddBytes([]byte{byte(v >> 40), byte(v >> 32), byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}) +} diff --git a/internal/util/util_test.go b/internal/util/util_test.go new file mode 100644 index 000000000..c247f68bb --- /dev/null +++ b/internal/util/util_test.go @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +package util + +import ( + "bytes" + "testing" + + "golang.org/x/crypto/cryptobyte" +) + +func TestAddUint48(t *testing.T) { + cases := map[string]struct { + reason string + builder *cryptobyte.Builder + postAdd func(*cryptobyte.Builder) + in uint64 + want []byte + }{ + "OnlyUint48": { + reason: "Adding only a 48-bit unsigned integer should yield expected result.", + builder: &cryptobyte.Builder{}, + in: 0xfefcff3cfdfc, + want: []byte{254, 252, 255, 60, 253, 252}, + }, + "ExistingAddUint48": { + reason: "Adding a 48-bit unsigned integer to a builder with existing bytes should yield expected result.", + builder: func() *cryptobyte.Builder { + var b cryptobyte.Builder + b.AddUint64(0xffffffffffffffff) + return &b + }(), + in: 0xfefcff3cfdfc, + want: []byte{255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 255, 60, 253, 252}, + }, + "ExistingAddUint48AndMore": { + reason: "Adding a 48-bit unsigned integer to a builder with existing bytes, then adding more bytes, should yield expected result.", + builder: func() *cryptobyte.Builder { + var b cryptobyte.Builder + b.AddUint64(0xffffffffffffffff) + return &b + }(), + postAdd: func(b *cryptobyte.Builder) { + b.AddUint32(0xffffffff) + }, + in: 0xfefcff3cfdfc, + want: []byte{255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 255, 60, 253, 252, 255, 255, 255, 255}, + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + AddUint48(tc.builder, tc.in) + if tc.postAdd != nil { + tc.postAdd(tc.builder) + } + got := tc.builder.BytesOrPanic() + if !bytes.Equal(got, tc.want) { + t.Errorf("Bytes() = %v, want %v", got, tc.want) + } + }) + } +} From 27fd1317c52f3f9077e35f7030402d11151dd9fb Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:46:23 -0400 Subject: [PATCH 024/146] Add local and remote CID to state Adds local and remote CID to state, but does not serialize them. CIDs should be renogotiated on session resumption. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- state.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/state.go b/state.go index e9f86a80b..26bfb747d 100644 --- a/state.go +++ b/state.go @@ -27,6 +27,20 @@ type State struct { IdentityHint []byte SessionID []byte + // Connection Identifiers must be negotiated afresh on session resumption. + // https://datatracker.ietf.org/doc/html/rfc9146#name-the-connection_id-extension + + // localConnectionID is the locally generated connection ID that is expected + // to be received from the remote endpoint. + // For a server, this is the connection ID sent in ServerHello. + // For a client, this is the connection ID sent in the ClientHello. + localConnectionID []byte + // remoteConnectionID is the connection ID that the remote endpoint + // specifies should be sent. + // For a server, this is the connection ID received in the ClientHello. + // For a client, this is the connection ID received in the ServerHello. + remoteConnectionID []byte + isClient bool preMasterSecret []byte From 8ba47cb63e6e61f39e995a453a6f4536205858cf Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:47:58 -0400 Subject: [PATCH 025/146] Implement AEAD additional data with CID Implements AEAD additional data generation when using connection IDs as described in https://datatracker.ietf.org/doc/html/rfc9146#name-aead-ciphers. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- pkg/crypto/ciphersuite/ciphersuite.go | 28 +++++++++++ pkg/crypto/ciphersuite/ciphersuite_test.go | 55 ++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 pkg/crypto/ciphersuite/ciphersuite_test.go diff --git a/pkg/crypto/ciphersuite/ciphersuite.go b/pkg/crypto/ciphersuite/ciphersuite.go index 9d9fb7418..a3130be12 100644 --- a/pkg/crypto/ciphersuite/ciphersuite.go +++ b/pkg/crypto/ciphersuite/ciphersuite.go @@ -8,8 +8,16 @@ import ( "encoding/binary" "errors" + "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/protocol" "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "golang.org/x/crypto/cryptobyte" +) + +const ( + // 8 bytes of 0xff. + // https://datatracker.ietf.org/doc/html/rfc9146#name-record-payload-protection + seqNumPlaceholder = 0xffffffffffffffff ) var ( @@ -21,6 +29,7 @@ var ( func generateAEADAdditionalData(h *recordlayer.Header, payloadLen int) []byte { var additionalData [13]byte + // SequenceNumber MUST be set first // we only want uint48, clobbering an extra 2 (using uint64, Golang doesn't have uint48) binary.BigEndian.PutUint64(additionalData[:], h.SequenceNumber) @@ -33,6 +42,25 @@ func generateAEADAdditionalData(h *recordlayer.Header, payloadLen int) []byte { return additionalData[:] } +// generateAEADAdditionalDataCID generates additional data for AEAD ciphers +// according to https://datatracker.ietf.org/doc/html/rfc9146#name-aead-ciphers +func generateAEADAdditionalDataCID(h *recordlayer.Header, payloadLen int) []byte { + var b cryptobyte.Builder + + b.AddUint64(seqNumPlaceholder) + b.AddUint8(uint8(protocol.ContentTypeConnectionID)) + b.AddUint8(uint8(len(h.ConnectionID))) + b.AddUint8(uint8(protocol.ContentTypeConnectionID)) + b.AddUint8(h.Version.Major) + b.AddUint8(h.Version.Minor) + b.AddUint16(h.Epoch) + util.AddUint48(&b, h.SequenceNumber) + b.AddBytes(h.ConnectionID) + b.AddUint16(uint16(payloadLen)) + + return b.BytesOrPanic() +} + // examinePadding returns, in constant time, the length of the padding to remove // from the end of payload. It also returns a byte which is equal to 255 if the // padding was valid and 0 otherwise. See RFC 2246, Section 6.2.3.2. diff --git a/pkg/crypto/ciphersuite/ciphersuite_test.go b/pkg/crypto/ciphersuite/ciphersuite_test.go new file mode 100644 index 000000000..0c2652f79 --- /dev/null +++ b/pkg/crypto/ciphersuite/ciphersuite_test.go @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +// Package ciphersuite provides the crypto operations needed for a DTLS CipherSuite +package ciphersuite + +import ( + "bytes" + "testing" + + "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v2/pkg/protocol/recordlayer" +) + +func TestGenerateAEADAdditionalDataCID(t *testing.T) { + cases := map[string]struct { + reason string + header *recordlayer.Header + payloadLen int + expected []byte + }{ + "WithConnectionID": { + reason: "Should successfully generate additional data with valid header", + header: &recordlayer.Header{ + ContentType: protocol.ContentTypeConnectionID, + ConnectionID: []byte{1, 2, 3, 4, 5, 6, 7, 8}, + Version: protocol.Version1_2, + Epoch: 2, + SequenceNumber: 277, + }, + payloadLen: 1784, + expected: []byte{255, 255, 255, 255, 255, 255, 255, 255, 25, 8, 25, 254, 253, 0, 2, 0, 0, 0, 0, 1, 21, 1, 2, 3, 4, 5, 6, 7, 8, 6, 248}, + }, + "IgnoreContentType": { + reason: "Should use Connection ID content type regardless of header content type.", + header: &recordlayer.Header{ + ContentType: protocol.ContentTypeAlert, + ConnectionID: []byte{1, 2, 3, 4, 5, 6, 7, 8}, + Version: protocol.Version1_2, + Epoch: 2, + SequenceNumber: 277, + }, + payloadLen: 1784, + expected: []byte{255, 255, 255, 255, 255, 255, 255, 255, 25, 8, 25, 254, 253, 0, 2, 0, 0, 0, 0, 1, 21, 1, 2, 3, 4, 5, 6, 7, 8, 6, 248}, + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + data := generateAEADAdditionalDataCID(tc.header, tc.payloadLen) + if !bytes.Equal(data, tc.expected) { + t.Errorf("%s\nUnexpected additional data\nwant: %v\ngot: %v", tc.reason, tc.expected, data) + } + }) + } +} From 89228790e7990e37559bea9f5d6df773558b0604 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:49:15 -0400 Subject: [PATCH 026/146] Update ciphersuites to support CIDs Updates ciphersuites to add support for handling connection ID records. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- internal/ciphersuite/aes_ccm.go | 4 +- ...tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go | 4 +- .../tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go | 4 +- .../tls_ecdhe_psk_with_aes_128_cbc_sha256.go | 4 +- .../tls_psk_with_aes_128_cbc_sha256.go | 4 +- pkg/crypto/ciphersuite/cbc.go | 82 +++++++++++++++---- pkg/crypto/ciphersuite/ccm.go | 38 +++++---- pkg/crypto/ciphersuite/gcm.go | 31 ++++--- 8 files changed, 120 insertions(+), 51 deletions(-) diff --git a/internal/ciphersuite/aes_ccm.go b/internal/ciphersuite/aes_ccm.go index dc5119823..ee3cca903 100644 --- a/internal/ciphersuite/aes_ccm.go +++ b/internal/ciphersuite/aes_ccm.go @@ -103,11 +103,11 @@ func (c *AesCcm) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, erro } // Decrypt decrypts a single TLS RecordLayer -func (c *AesCcm) Decrypt(raw []byte) ([]byte, error) { +func (c *AesCcm) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.ccm.Load().(*ciphersuite.CCM) if !ok { return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit) } - return cipherSuite.Decrypt(raw) + return cipherSuite.Decrypt(h, raw) } diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go index 0c919fe47..362370b98 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go @@ -98,11 +98,11 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) Encrypt(pkt *recordlayer.RecordLayer, } // Decrypt decrypts a single TLS RecordLayer -func (c *TLSEcdheEcdsaWithAes128GcmSha256) Decrypt(raw []byte) ([]byte, error) { +func (c *TLSEcdheEcdsaWithAes128GcmSha256) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.gcm.Load().(*ciphersuite.GCM) if !ok { return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit) } - return cipherSuite.Decrypt(raw) + return cipherSuite.Decrypt(h, raw) } diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go index 577192c89..07ad66fd1 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go @@ -104,11 +104,11 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) Encrypt(pkt *recordlayer.RecordLayer, ra } // Decrypt decrypts a single TLS RecordLayer -func (c *TLSEcdheEcdsaWithAes256CbcSha) Decrypt(raw []byte) ([]byte, error) { +func (c *TLSEcdheEcdsaWithAes256CbcSha) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit) } - return cipherSuite.Decrypt(raw) + return cipherSuite.Decrypt(h, raw) } diff --git a/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go b/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go index 75a25633a..10cc58c0b 100644 --- a/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go +++ b/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go @@ -108,11 +108,11 @@ func (c *TLSEcdhePskWithAes128CbcSha256) Encrypt(pkt *recordlayer.RecordLayer, r } // Decrypt decrypts a single TLS RecordLayer -func (c *TLSEcdhePskWithAes128CbcSha256) Decrypt(raw []byte) ([]byte, error) { +func (c *TLSEcdhePskWithAes128CbcSha256) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { // !c.isInitialized() return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit) } - return cipherSuite.Decrypt(raw) + return cipherSuite.Decrypt(h, raw) } diff --git a/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go b/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go index 7336ad946..dea0dfc75 100644 --- a/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go +++ b/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go @@ -103,11 +103,11 @@ func (c *TLSPskWithAes128CbcSha256) Encrypt(pkt *recordlayer.RecordLayer, raw [] } // Decrypt decrypts a single TLS RecordLayer -func (c *TLSPskWithAes128CbcSha256) Decrypt(raw []byte) ([]byte, error) { +func (c *TLSPskWithAes128CbcSha256) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit) } - return cipherSuite.Decrypt(raw) + return cipherSuite.Decrypt(h, raw) } diff --git a/pkg/crypto/ciphersuite/cbc.go b/pkg/crypto/ciphersuite/cbc.go index 460fb1437..008a8365b 100644 --- a/pkg/crypto/ciphersuite/cbc.go +++ b/pkg/crypto/ciphersuite/cbc.go @@ -15,6 +15,7 @@ import ( //nolint:gci "github.com/pion/dtls/v2/pkg/crypto/prf" "github.com/pion/dtls/v2/pkg/protocol" "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "golang.org/x/crypto/cryptobyte" ) // block ciphers using cipher block chaining. @@ -64,18 +65,24 @@ func NewCBC(localKey, localWriteIV, localMac, remoteKey, remoteWriteIV, remoteMa // Encrypt encrypt a DTLS RecordLayer message func (c *CBC) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { - payload := raw[recordlayer.HeaderSize:] - raw = raw[:recordlayer.HeaderSize] + payload := raw[pkt.Header.Size():] + raw = raw[:pkt.Header.Size()] blockSize := c.writeCBC.BlockSize() // Generate + Append MAC h := pkt.Header - MAC, err := c.hmac(h.Epoch, h.SequenceNumber, h.ContentType, h.Version, payload, c.writeMac, c.h) + var err error + var mac []byte + if h.ContentType == protocol.ContentTypeConnectionID { + mac, err = c.hmacCID(h.Epoch, h.SequenceNumber, h.Version, payload, c.writeMac, c.h, h.ConnectionID) + } else { + mac, err = c.hmac(h.Epoch, h.SequenceNumber, h.ContentType, h.Version, payload, c.writeMac, c.h) + } if err != nil { return nil, err } - payload = append(payload, MAC...) + payload = append(payload, mac...) // Generate + Append padding padding := make([]byte, blockSize-len(payload)%blockSize) @@ -96,26 +103,26 @@ func (c *CBC) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) c.writeCBC.CryptBlocks(payload, payload) payload = append(iv, payload...) - // Prepend unencrypte header with encrypted payload + // Prepend unencrypted header with encrypted payload raw = append(raw, payload...) // Update recordLayer size to include IV+MAC+Padding - binary.BigEndian.PutUint16(raw[recordlayer.HeaderSize-2:], uint16(len(raw)-recordlayer.HeaderSize)) + binary.BigEndian.PutUint16(raw[pkt.Header.Size()-2:], uint16(len(raw)-pkt.Header.Size())) return raw, nil } // Decrypt decrypts a DTLS RecordLayer message -func (c *CBC) Decrypt(in []byte) ([]byte, error) { - body := in[recordlayer.HeaderSize:] +func (c *CBC) Decrypt(h recordlayer.Header, in []byte) ([]byte, error) { blockSize := c.readCBC.BlockSize() mac := c.h() - var h recordlayer.Header - err := h.Unmarshal(in) - switch { - case err != nil: + if err := h.Unmarshal(in); err != nil { return nil, err + } + body := in[h.Size():] + + switch { case h.ContentType == protocol.ContentTypeChangeCipherSpec: // Nothing to encrypt with ChangeCipherSpec return in, nil @@ -145,14 +152,19 @@ func (c *CBC) Decrypt(in []byte) ([]byte, error) { dataEnd := len(body) - macSize - paddingLen expectedMAC := body[dataEnd : dataEnd+macSize] - actualMAC, err := c.hmac(h.Epoch, h.SequenceNumber, h.ContentType, h.Version, body[:dataEnd], c.readMac, c.h) - + var err error + var actualMAC []byte + if h.ContentType == protocol.ContentTypeConnectionID { + actualMAC, err = c.hmacCID(h.Epoch, h.SequenceNumber, h.Version, body[:dataEnd], c.readMac, c.h, h.ConnectionID) + } else { + actualMAC, err = c.hmac(h.Epoch, h.SequenceNumber, h.ContentType, h.Version, body[:dataEnd], c.readMac, c.h) + } // Compute Local MAC and compare if err != nil || !hmac.Equal(actualMAC, expectedMAC) { return nil, errInvalidMAC } - return append(in[:recordlayer.HeaderSize], body[:dataEnd]...), nil + return append(in[:h.Size()], body[:dataEnd]...), nil } func (c *CBC) hmac(epoch uint16, sequenceNumber uint64, contentType protocol.ContentType, protocolVersion protocol.Version, payload []byte, key []byte, hf func() hash.Hash) ([]byte, error) { @@ -169,7 +181,45 @@ func (c *CBC) hmac(epoch uint16, sequenceNumber uint64, contentType protocol.Con if _, err := h.Write(msg); err != nil { return nil, err - } else if _, err := h.Write(payload); err != nil { + } + if _, err := h.Write(payload); err != nil { + return nil, err + } + + return h.Sum(nil), nil +} + +// hmacCID calculates a MAC according to +// https://datatracker.ietf.org/doc/html/rfc9146#section-5.1 +func (c *CBC) hmacCID(epoch uint16, sequenceNumber uint64, protocolVersion protocol.Version, payload []byte, key []byte, hf func() hash.Hash, cid []byte) ([]byte, error) { + // Must unmarshal inner plaintext in orde to perform MAC. + ip := &recordlayer.InnerPlaintext{} + if err := ip.Unmarshal(payload); err != nil { + return nil, err + } + + h := hmac.New(hf, key) + + var msg cryptobyte.Builder + + msg.AddUint64(seqNumPlaceholder) + msg.AddUint8(uint8(protocol.ContentTypeConnectionID)) + msg.AddUint8(uint8(len(cid))) + msg.AddUint8(uint8(protocol.ContentTypeConnectionID)) + msg.AddUint8(protocolVersion.Major) + msg.AddUint8(protocolVersion.Minor) + msg.AddUint16(epoch) + util.AddUint48(&msg, sequenceNumber) + msg.AddBytes(cid) + msg.AddUint16(uint16(len(payload))) + msg.AddBytes(ip.Content) + msg.AddUint8(uint8(ip.RealType)) + msg.AddBytes(make([]byte, ip.Zeros)) + + if _, err := h.Write(msg.BytesOrPanic()); err != nil { + return nil, err + } + if _, err := h.Write(payload); err != nil { return nil, err } diff --git a/pkg/crypto/ciphersuite/ccm.go b/pkg/crypto/ciphersuite/ccm.go index 24050dc92..6fb185d85 100644 --- a/pkg/crypto/ciphersuite/ccm.go +++ b/pkg/crypto/ciphersuite/ccm.go @@ -62,46 +62,56 @@ func NewCCM(tagLen CCMTagLen, localKey, localWriteIV, remoteKey, remoteWriteIV [ // Encrypt encrypt a DTLS RecordLayer message func (c *CCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { - payload := raw[recordlayer.HeaderSize:] - raw = raw[:recordlayer.HeaderSize] + payload := raw[pkt.Header.Size():] + raw = raw[:pkt.Header.Size()] nonce := append(append([]byte{}, c.localWriteIV[:4]...), make([]byte, 8)...) if _, err := rand.Read(nonce[4:]); err != nil { return nil, err } - additionalData := generateAEADAdditionalData(&pkt.Header, len(payload)) + var additionalData []byte + if pkt.Header.ContentType == protocol.ContentTypeConnectionID { + additionalData = generateAEADAdditionalDataCID(&pkt.Header, len(payload)) + } else { + additionalData = generateAEADAdditionalData(&pkt.Header, len(payload)) + } encryptedPayload := c.localCCM.Seal(nil, nonce, payload, additionalData) encryptedPayload = append(nonce[4:], encryptedPayload...) raw = append(raw, encryptedPayload...) // Update recordLayer size to include explicit nonce - binary.BigEndian.PutUint16(raw[recordlayer.HeaderSize-2:], uint16(len(raw)-recordlayer.HeaderSize)) + binary.BigEndian.PutUint16(raw[pkt.Header.Size()-2:], uint16(len(raw)-pkt.Header.Size())) return raw, nil } // Decrypt decrypts a DTLS RecordLayer message -func (c *CCM) Decrypt(in []byte) ([]byte, error) { - var h recordlayer.Header - err := h.Unmarshal(in) - switch { - case err != nil: +func (c *CCM) Decrypt(h recordlayer.Header, in []byte) ([]byte, error) { + if err := h.Unmarshal(in); err != nil { return nil, err + } + switch { case h.ContentType == protocol.ContentTypeChangeCipherSpec: // Nothing to encrypt with ChangeCipherSpec return in, nil - case len(in) <= (8 + recordlayer.HeaderSize): + case len(in) <= (8 + h.Size()): return nil, errNotEnoughRoomForNonce } - nonce := append(append([]byte{}, c.remoteWriteIV[:4]...), in[recordlayer.HeaderSize:recordlayer.HeaderSize+8]...) - out := in[recordlayer.HeaderSize+8:] + nonce := append(append([]byte{}, c.remoteWriteIV[:4]...), in[h.Size():h.Size()+8]...) + out := in[h.Size()+8:] - additionalData := generateAEADAdditionalData(&h, len(out)-int(c.tagLen)) + var additionalData []byte + if h.ContentType == protocol.ContentTypeConnectionID { + additionalData = generateAEADAdditionalDataCID(&h, len(out)-int(c.tagLen)) + } else { + additionalData = generateAEADAdditionalData(&h, len(out)-int(c.tagLen)) + } + var err error out, err = c.remoteCCM.Open(out[:0], nonce, out, additionalData) if err != nil { return nil, fmt.Errorf("%w: %v", errDecryptPacket, err) //nolint:errorlint } - return append(in[:recordlayer.HeaderSize], out...), nil + return append(in[:h.Size()], out...), nil } diff --git a/pkg/crypto/ciphersuite/gcm.go b/pkg/crypto/ciphersuite/gcm.go index c0fd1f76f..1d09c8eb9 100644 --- a/pkg/crypto/ciphersuite/gcm.go +++ b/pkg/crypto/ciphersuite/gcm.go @@ -55,8 +55,8 @@ func NewGCM(localKey, localWriteIV, remoteKey, remoteWriteIV []byte) (*GCM, erro // Encrypt encrypt a DTLS RecordLayer message func (g *GCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { - payload := raw[recordlayer.HeaderSize:] - raw = raw[:recordlayer.HeaderSize] + payload := raw[pkt.Header.Size():] + raw = raw[:pkt.Header.Size()] nonce := make([]byte, gcmNonceLength) copy(nonce, g.localWriteIV[:4]) @@ -64,7 +64,12 @@ func (g *GCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) return nil, err } - additionalData := generateAEADAdditionalData(&pkt.Header, len(payload)) + var additionalData []byte + if pkt.Header.ContentType == protocol.ContentTypeConnectionID { + additionalData = generateAEADAdditionalDataCID(&pkt.Header, len(payload)) + } else { + additionalData = generateAEADAdditionalData(&pkt.Header, len(payload)) + } encryptedPayload := g.localGCM.Seal(nil, nonce, payload, additionalData) r := make([]byte, len(raw)+len(nonce[4:])+len(encryptedPayload)) copy(r, raw) @@ -72,13 +77,12 @@ func (g *GCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) copy(r[len(raw)+len(nonce[4:]):], encryptedPayload) // Update recordLayer size to include explicit nonce - binary.BigEndian.PutUint16(r[recordlayer.HeaderSize-2:], uint16(len(r)-recordlayer.HeaderSize)) + binary.BigEndian.PutUint16(r[pkt.Header.Size()-2:], uint16(len(r)-pkt.Header.Size())) return r, nil } // Decrypt decrypts a DTLS RecordLayer message -func (g *GCM) Decrypt(in []byte) ([]byte, error) { - var h recordlayer.Header +func (g *GCM) Decrypt(h recordlayer.Header, in []byte) ([]byte, error) { err := h.Unmarshal(in) switch { case err != nil: @@ -86,18 +90,23 @@ func (g *GCM) Decrypt(in []byte) ([]byte, error) { case h.ContentType == protocol.ContentTypeChangeCipherSpec: // Nothing to encrypt with ChangeCipherSpec return in, nil - case len(in) <= (8 + recordlayer.HeaderSize): + case len(in) <= (8 + h.Size()): return nil, errNotEnoughRoomForNonce } nonce := make([]byte, 0, gcmNonceLength) - nonce = append(append(nonce, g.remoteWriteIV[:4]...), in[recordlayer.HeaderSize:recordlayer.HeaderSize+8]...) - out := in[recordlayer.HeaderSize+8:] + nonce = append(append(nonce, g.remoteWriteIV[:4]...), in[h.Size():h.Size()+8]...) + out := in[h.Size()+8:] - additionalData := generateAEADAdditionalData(&h, len(out)-gcmTagLength) + var additionalData []byte + if h.ContentType == protocol.ContentTypeConnectionID { + additionalData = generateAEADAdditionalDataCID(&h, len(out)-gcmTagLength) + } else { + additionalData = generateAEADAdditionalData(&h, len(out)-gcmTagLength) + } out, err = g.remoteGCM.Open(out[:0], nonce, out, additionalData) if err != nil { return nil, fmt.Errorf("%w: %v", errDecryptPacket, err) //nolint:errorlint } - return append(in[:recordlayer.HeaderSize], out...), nil + return append(in[:h.Size()], out...), nil } From e5420de15e44ff7c599f3bad3089a52cd9bd9348 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:50:16 -0400 Subject: [PATCH 027/146] Update handshaker to handle CID extension Updates handshaker to handle negotiating CIDs. Local connection ID is only set if the local party generates one and the remote indicates support. Remote connection id is only set if remote generates one and connection IDs are supported locally Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- flight0handler.go | 12 ++++++++++++ flight1handler.go | 8 ++++++++ flight3handler.go | 18 ++++++++++++++++++ flight4handler.go | 11 ++++++++++- flight5handler.go | 1 + flight6handler.go | 1 + fragment_buffer.go | 2 +- handshaker.go | 1 + handshaker_test.go | 2 +- 9 files changed, 53 insertions(+), 3 deletions(-) diff --git a/flight0handler.go b/flight0handler.go index ec766ddff..27e991551 100644 --- a/flight0handler.go +++ b/flight0handler.go @@ -69,9 +69,21 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak state.serverName = e.ServerName // remote server name case *extension.ALPN: state.peerSupportedProtocols = e.ProtocolNameList + case *extension.ConnectionID: + // Only set connection ID to be sent if server supports connection + // IDs. + if cfg.connectionIDGenerator != nil { + state.remoteConnectionID = e.CID + } } } + // If the client doesn't support connection IDs, the server should not + // expect one to be sent. + if state.remoteConnectionID == nil { + state.localConnectionID = nil + } + if cfg.extendedMasterSecret == RequireExtendedMasterSecret && !state.extendedMasterSecret { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errServerRequiredButNoClientEMS } diff --git a/flight1handler.go b/flight1handler.go index 94fdc222d..cafb36d0b 100644 --- a/flight1handler.go +++ b/flight1handler.go @@ -118,6 +118,14 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha } } + // If we have a connection ID generator, use it. The CID may be zero length, + // in which case we are just requesting that the server send us a CID to + // use. + if cfg.connectionIDGenerator != nil { + state.localConnectionID = cfg.connectionIDGenerator() + extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) + } + return []*packet{ { record: &recordlayer.RecordLayer{ diff --git a/flight3handler.go b/flight3handler.go index 5a763dc08..b17a7986c 100644 --- a/flight3handler.go +++ b/flight3handler.go @@ -66,8 +66,20 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, extension.ErrALPNInvalidFormat // Meh, internal error? } state.NegotiatedProtocol = e.ProtocolNameList[0] + case *extension.ConnectionID: + // Only set connection ID to be sent if client supports connection + // IDs. + if cfg.connectionIDGenerator != nil { + state.remoteConnectionID = e.CID + } } } + // If the server doesn't support connection IDs, the client should not + // expect one to be sent. + if state.remoteConnectionID == nil { + state.localConnectionID = nil + } + if cfg.extendedMasterSecret == RequireExtendedMasterSecret && !state.extendedMasterSecret { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errClientRequiredButNoServerEMS } @@ -268,6 +280,12 @@ func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha extensions = append(extensions, &extension.ALPN{ProtocolNameList: cfg.supportedProtocols}) } + // If we sent a connection ID on the first ClientHello, send it on the + // second. + if state.localConnectionID != nil { + extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) + } + return []*packet{ { record: &recordlayer.RecordLayer{ diff --git a/flight4handler.go b/flight4handler.go index 67a486461..52568139f 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -218,7 +218,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return flight6, nil, nil } -func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit extensions := []extension.Extension{&extension.RenegotiationInfo{ RenegotiatedConnection: 0, }} @@ -250,6 +250,15 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha state.NegotiatedProtocol = selectedProto } + // If we have a connection ID generator, we are willing to use connection + // IDs. We already know whether the client supports connection IDs from + // parsing the ClientHello, so avoid setting local connection ID if the + // client won't send it. + if cfg.connectionIDGenerator != nil && state.remoteConnectionID != nil { + state.localConnectionID = cfg.connectionIDGenerator() + extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) + } + var pkts []*packet cipherSuiteID := uint16(state.cipherSuite.ID()) diff --git a/flight5handler.go b/flight5handler.go index e8adf4f36..33965417f 100644 --- a/flight5handler.go +++ b/flight5handler.go @@ -277,6 +277,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han }, }, }, + shouldWrapCID: len(state.remoteConnectionID) > 0, shouldEncrypt: true, resetLocalSequenceNumber: true, }) diff --git a/flight6handler.go b/flight6handler.go index 57ac14360..c03890425 100644 --- a/flight6handler.go +++ b/flight6handler.go @@ -77,6 +77,7 @@ func flight6Generate(_ flightConn, state *State, cache *handshakeCache, cfg *han }, }, }, + shouldWrapCID: len(state.remoteConnectionID) > 0, shouldEncrypt: true, resetLocalSequenceNumber: true, }, diff --git a/fragment_buffer.go b/fragment_buffer.go index f20033758..fb5af6c3d 100644 --- a/fragment_buffer.go +++ b/fragment_buffer.go @@ -58,7 +58,7 @@ func (f *fragmentBuffer) push(buf []byte) (bool, error) { return false, nil } - for buf = buf[recordlayer.HeaderSize:]; len(buf) != 0; frag = new(fragment) { + for buf = buf[recordlayer.FixedHeaderSize:]; len(buf) != 0; frag = new(fragment) { if err := frag.handshakeHeader.Unmarshal(buf); err != nil { return false, err } diff --git a/handshaker.go b/handshaker.go index 721fb77cf..46fbd38bd 100644 --- a/handshaker.go +++ b/handshaker.go @@ -113,6 +113,7 @@ type handshakeConfig struct { customCipherSuites func() []CipherSuite ellipticCurves []elliptic.Curve insecureSkipHelloVerify bool + connectionIDGenerator func() []byte onFlightState func(flightVal, handshakeState) log logging.LeveledLogger diff --git a/handshaker_test.go b/handshaker_test.go index 6cf7cd3cf..6d307aeea 100644 --- a/handshaker_test.go +++ b/handshaker_test.go @@ -409,7 +409,7 @@ func (c *flightTestConn) writePackets(_ context.Context, pkts []*packet) error { return err } - c.handshakeCache.push(handshakeRaw[recordlayer.HeaderSize:], p.record.Header.Epoch, h.Header.MessageSequence, h.Header.Type, c.state.isClient) + c.handshakeCache.push(handshakeRaw[recordlayer.FixedHeaderSize:], p.record.Header.Epoch, h.Header.MessageSequence, h.Header.Type, c.state.isClient) content, err := h.Message.Marshal() if err != nil { From d082911fe6657a9f22490e26c79b17032a7dfe15 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:52:42 -0400 Subject: [PATCH 028/146] Add Conn to PacketConn utility Adds a utility used to translate net.Conn's to net.PacketConn's for use in DTLS package. This utility may be promoted to a public package in the future if consumers require using net.Conn, particularly if they are using connected UDP sockets. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- internal/util/net.go | 57 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 internal/util/net.go diff --git a/internal/util/net.go b/internal/util/net.go new file mode 100644 index 000000000..5a94dcf2a --- /dev/null +++ b/internal/util/net.go @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +// Package util contains small helpers used across the repo +package util + +import ( + "net" + "time" +) + +// packetConn wraps a net.Conn with methods that satisfy net.PacketConn. +type packetConn struct { + conn net.Conn +} + +// FromConn converts a net.Conn into a net.PacketConn. +func FromConn(conn net.Conn) net.PacketConn { + return &packetConn{conn} +} + +// ReadFrom reads from the underlying net.Conn and returns its remote address. +func (cp *packetConn) ReadFrom(b []byte) (int, net.Addr, error) { + n, err := cp.conn.Read(b) + return n, cp.conn.RemoteAddr(), err +} + +// WriteTo writes to the underlying net.Conn. +func (cp *packetConn) WriteTo(b []byte, _ net.Addr) (int, error) { + n, err := cp.conn.Write(b) + return n, err +} + +// Close closes the underlying net.Conn. +func (cp *packetConn) Close() error { + return cp.conn.Close() +} + +// LocalAddr returns the local address of the underlying net.Conn. +func (cp *packetConn) LocalAddr() net.Addr { + return cp.conn.LocalAddr() +} + +// SetDeadline sets the deadline on the underlying net.Conn. +func (cp *packetConn) SetDeadline(t time.Time) error { + return cp.conn.SetDeadline(t) +} + +// SetReadDeadline sets the read deadline on the underlying net.Conn. +func (cp *packetConn) SetReadDeadline(t time.Time) error { + return cp.conn.SetReadDeadline(t) +} + +// SetWriteDeadline sets the write deadline on the underlying net.Conn. +func (cp *packetConn) SetWriteDeadline(t time.Time) error { + return cp.conn.SetWriteDeadline(t) +} From afb61f1d98271bbdb015800a8e9b25f4ed488221 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:55:57 -0400 Subject: [PATCH 029/146] Update DTLS Conn to use PacketConn and CID Updates DTLS Conn to take a net.PacketConn and support connection IDs. Moving to net.PacketConn allows for updating the remote address when utilizing connection IDs, alleviating the need to re-handshake every time an IP address or port changes. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- conn.go | 267 +++++++++++++++++++++++++++++++++++++----------- conn_go_test.go | 9 +- conn_test.go | 211 +++++++++++++++++++++++++++++--------- 3 files changed, 375 insertions(+), 112 deletions(-) diff --git a/conn.go b/conn.go index 4194129ba..8d7799add 100644 --- a/conn.go +++ b/conn.go @@ -4,6 +4,7 @@ package dtls import ( + "bytes" "context" "errors" "fmt" @@ -21,8 +22,8 @@ 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/v2/connctx" "github.com/pion/transport/v2/deadline" + "github.com/pion/transport/v2/netctx" "github.com/pion/transport/v2/replaydetector" ) @@ -45,21 +46,27 @@ func invalidKeyingLabels() map[string]bool { } } +type addrPkt struct { + rAddr net.Addr + data []byte +} + // Conn represents a DTLS connection type Conn struct { - lock sync.RWMutex // Internal lock (must not be public) - nextConn connctx.ConnCtx // Embedded Conn, typically a udpconn we read/write from - fragmentBuffer *fragmentBuffer // out-of-order and missing fragment handling - handshakeCache *handshakeCache // caching of handshake messages for verifyData generation - decrypted chan interface{} // Decrypted Application Data or error, pull by calling `Read` - - state State // Internal state + lock sync.RWMutex // Internal lock (must not be public) + nextConn netctx.PacketConn // Embedded Conn, typically a udpconn we read/write from + fragmentBuffer *fragmentBuffer // out-of-order and missing fragment handling + handshakeCache *handshakeCache // caching of handshake messages for verifyData generation + decrypted chan interface{} // Decrypted Application Data or error, pull by calling `Read` + rAddr net.Addr + state State // Internal state maximumTransmissionUnit int + paddingLengthGenerator func(uint) uint handshakeCompletedSuccessfully atomic.Value - encryptedPackets [][]byte + encryptedPackets []addrPkt connectionClosedByUser bool closeLock sync.Mutex @@ -81,9 +88,8 @@ type Conn struct { replayProtectionWindow uint } -func createConn(ctx context.Context, nextConn net.Conn, config *Config, isClient bool, initialState *State) (*Conn, error) { - err := validateConfig(config) - if err != nil { +func createConn(ctx context.Context, nextConn net.PacketConn, rAddr net.Addr, config *Config, isClient bool, initialState *State) (*Conn, error) { + if err := validateConfig(config); err != nil { return nil, err } @@ -123,11 +129,18 @@ func createConn(ctx context.Context, nextConn net.Conn, config *Config, isClient replayProtectionWindow = defaultReplayProtectionWindow } + paddingLengthGenerator := config.PaddingLengthGenerator + if paddingLengthGenerator == nil { + paddingLengthGenerator = func(uint) uint { return 0 } + } + c := &Conn{ - nextConn: connctx.New(nextConn), + rAddr: rAddr, + nextConn: netctx.NewPacketConn(nextConn), fragmentBuffer: newFragmentBuffer(), handshakeCache: newHandshakeCache(), maximumTransmissionUnit: mtu, + paddingLengthGenerator: paddingLengthGenerator, decrypted: make(chan interface{}, 1), log: logger, @@ -188,6 +201,7 @@ func createConn(ctx context.Context, nextConn net.Conn, config *Config, isClient localGetCertificate: config.GetCertificate, localGetClientCertificate: config.GetClientCertificate, insecureSkipHelloVerify: config.InsecureSkipVerifyHello, + connectionIDGenerator: config.ConnectionIDGenerator, } // rfc5246#section-7.4.3 @@ -234,44 +248,49 @@ func createConn(ctx context.Context, nextConn net.Conn, config *Config, isClient // Dial connects to the given network address and establishes a DTLS connection on top. // Connection handshake will timeout using ConnectContextMaker in the Config. // If you want to specify the timeout duration, use DialWithContext() instead. -func Dial(network string, raddr *net.UDPAddr, config *Config) (*Conn, error) { +func Dial(network string, rAddr *net.UDPAddr, config *Config) (*Conn, error) { ctx, cancel := config.connectContextMaker() defer cancel() - return DialWithContext(ctx, network, raddr, config) + return DialWithContext(ctx, network, rAddr, config) } // Client establishes a DTLS connection over an existing connection. // Connection handshake will timeout using ConnectContextMaker in the Config. // If you want to specify the timeout duration, use ClientWithContext() instead. -func Client(conn net.Conn, config *Config) (*Conn, error) { +func Client(conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { ctx, cancel := config.connectContextMaker() defer cancel() - return ClientWithContext(ctx, conn, config) + return ClientWithContext(ctx, conn, rAddr, config) } // Server listens for incoming DTLS connections. // Connection handshake will timeout using ConnectContextMaker in the Config. // If you want to specify the timeout duration, use ServerWithContext() instead. -func Server(conn net.Conn, config *Config) (*Conn, error) { +func Server(conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { ctx, cancel := config.connectContextMaker() defer cancel() - return ServerWithContext(ctx, conn, config) + return ServerWithContext(ctx, conn, rAddr, config) } -// DialWithContext connects to the given network address and establishes a DTLS connection on top. -func DialWithContext(ctx context.Context, network string, raddr *net.UDPAddr, config *Config) (*Conn, error) { - pConn, err := net.DialUDP(network, nil, raddr) +// DialWithContext connects to the given network address and establishes a DTLS +// connection on top. +func DialWithContext(ctx context.Context, network string, rAddr *net.UDPAddr, config *Config) (*Conn, error) { + // net.ListenUDP is used rather than net.DialUDP as the latter prevents the + // use of net.PacketConn.WriteTo. + // https://github.com/golang/go/blob/ce5e37ec21442c6eb13a43e68ca20129102ebac0/src/net/udpsock_posix.go#L115 + pConn, err := net.ListenUDP(network, nil) if err != nil { return nil, err } - return ClientWithContext(ctx, pConn, config) + + return ClientWithContext(ctx, pConn, rAddr, config) } // ClientWithContext establishes a DTLS connection over an existing connection. -func ClientWithContext(ctx context.Context, conn net.Conn, config *Config) (*Conn, error) { +func ClientWithContext(ctx context.Context, conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { switch { case config == nil: return nil, errNoConfigProvided @@ -279,16 +298,16 @@ func ClientWithContext(ctx context.Context, conn net.Conn, config *Config) (*Con return nil, errPSKAndIdentityMustBeSetForClient } - return createConn(ctx, conn, config, true, nil) + return createConn(ctx, conn, rAddr, config, true, nil) } // ServerWithContext listens for incoming DTLS connections. -func ServerWithContext(ctx context.Context, conn net.Conn, config *Config) (*Conn, error) { +func ServerWithContext(ctx context.Context, conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { if config == nil { return nil, errNoConfigProvided } - return createConn(ctx, conn, config, false, nil) + return createConn(ctx, conn, rAddr, config, false, nil) } // Read reads data from the connection. @@ -352,6 +371,7 @@ func (c *Conn) Write(p []byte) (int, error) { Data: p, }, }, + shouldWrapCID: len(c.state.remoteConnectionID) > 0, shouldEncrypt: true, }, }) @@ -400,7 +420,8 @@ func (c *Conn) writePackets(ctx context.Context, pkts []*packet) error { c.log.Tracef("[handshake:%v] -> %s (epoch: %d, seq: %d)", srvCliStr(c.state.isClient), h.Header.Type.String(), p.record.Header.Epoch, h.Header.MessageSequence) - c.handshakeCache.push(handshakeRaw[recordlayer.HeaderSize:], p.record.Header.Epoch, h.Header.MessageSequence, h.Header.Type, c.state.isClient) + + c.handshakeCache.push(handshakeRaw[recordlayer.FixedHeaderSize:], p.record.Header.Epoch, h.Header.MessageSequence, h.Header.Type, c.state.isClient) rawHandshakePackets, err := c.processHandshakePacket(p, h) if err != nil { @@ -421,7 +442,7 @@ func (c *Conn) writePackets(ctx context.Context, pkts []*packet) error { compactedRawPackets := c.compactRawPackets(rawPackets) for _, compactedRawPackets := range compactedRawPackets { - if _, err := c.nextConn.WriteContext(ctx, compactedRawPackets); err != nil { + if _, err := c.nextConn.WriteToContext(ctx, compactedRawPackets, c.rAddr); err != nil { return netError(err) } } @@ -465,9 +486,44 @@ func (c *Conn) processPacket(p *packet) ([]byte, error) { } p.record.Header.SequenceNumber = seq - rawPacket, err := p.record.Marshal() - if err != nil { - return nil, err + var rawPacket []byte + if p.shouldWrapCID { + // Record must be marshaled to populate fields used in inner plaintext. + if _, err := p.record.Marshal(); err != nil { + return nil, err + } + content, err := p.record.Content.Marshal() + if err != nil { + return nil, err + } + inner := &recordlayer.InnerPlaintext{ + Content: content, + RealType: p.record.Header.ContentType, + } + rawInner, err := inner.Marshal() //nolint:govet + if err != nil { + return nil, err + } + cidHeader := &recordlayer.Header{ + Version: p.record.Header.Version, + ContentType: protocol.ContentTypeConnectionID, + Epoch: p.record.Header.Epoch, + ContentLen: uint16(len(rawInner)), + ConnectionID: c.state.remoteConnectionID, + SequenceNumber: p.record.Header.SequenceNumber, + } + rawPacket, err = cidHeader.Marshal() + if err != nil { + return nil, err + } + p.record.Header = *cidHeader + rawPacket = append(rawPacket, rawInner...) + } else { + var err error + rawPacket, err = p.record.Marshal() + if err != nil { + return nil, err + } } if p.shouldEncrypt { @@ -499,22 +555,49 @@ func (c *Conn) processHandshakePacket(p *packet, h *handshake.Handshake) ([][]by return nil, errSequenceNumberOverflow } - recordlayerHeader := &recordlayer.Header{ - Version: p.record.Header.Version, - ContentType: p.record.Header.ContentType, - ContentLen: uint16(len(handshakeFragment)), - Epoch: p.record.Header.Epoch, - SequenceNumber: seq, - } + var rawPacket []byte + if p.shouldWrapCID { + inner := &recordlayer.InnerPlaintext{ + Content: handshakeFragment, + RealType: protocol.ContentTypeHandshake, + Zeros: c.paddingLengthGenerator(uint(len(handshakeFragment))), + } + rawInner, err := inner.Marshal() //nolint:govet + if err != nil { + return nil, err + } + cidHeader := &recordlayer.Header{ + Version: p.record.Header.Version, + ContentType: protocol.ContentTypeConnectionID, + Epoch: p.record.Header.Epoch, + ContentLen: uint16(len(rawInner)), + ConnectionID: c.state.remoteConnectionID, + SequenceNumber: p.record.Header.SequenceNumber, + } + rawPacket, err = cidHeader.Marshal() + if err != nil { + return nil, err + } + p.record.Header = *cidHeader + rawPacket = append(rawPacket, rawInner...) + } else { + recordlayerHeader := &recordlayer.Header{ + Version: p.record.Header.Version, + ContentType: p.record.Header.ContentType, + ContentLen: uint16(len(handshakeFragment)), + Epoch: p.record.Header.Epoch, + SequenceNumber: seq, + } - rawPacket, err := recordlayerHeader.Marshal() - if err != nil { - return nil, err - } + rawPacket, err = recordlayerHeader.Marshal() + if err != nil { + return nil, err + } - p.record.Header = *recordlayerHeader + p.record.Header = *recordlayerHeader + rawPacket = append(rawPacket, handshakeFragment...) + } - rawPacket = append(rawPacket, handshakeFragment...) if p.shouldEncrypt { var err error rawPacket, err = c.state.cipherSuite.Encrypt(p.record, rawPacket) @@ -585,19 +668,19 @@ func (c *Conn) readAndBuffer(ctx context.Context) error { defer poolReadBuffer.Put(bufptr) b := *bufptr - i, err := c.nextConn.ReadContext(ctx, b) + i, rAddr, err := c.nextConn.ReadFromContext(ctx, b) if err != nil { return netError(err) } - pkts, err := recordlayer.UnpackDatagram(b[:i]) + pkts, err := recordlayer.ContentAwareUnpackDatagram(b[:i], len(c.state.localConnectionID)) if err != nil { return err } var hasHandshake bool for _, p := range pkts { - hs, alert, err := c.handleIncomingPacket(ctx, p, true) + hs, alert, err := c.handleIncomingPacket(ctx, p, rAddr, true) if alert != nil { if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { if err == nil { @@ -635,7 +718,7 @@ func (c *Conn) handleQueuedPackets(ctx context.Context) error { c.encryptedPackets = nil for _, p := range pkts { - _, alert, err := c.handleIncomingPacket(ctx, p, false) // don't re-enqueue + _, alert, err := c.handleIncomingPacket(ctx, p.data, p.rAddr, false) // don't re-enqueue if alert != nil { if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { if err == nil { @@ -654,8 +737,13 @@ func (c *Conn) handleQueuedPackets(ctx context.Context) error { return nil } -func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, enqueue bool) (bool, *alert.Alert, error) { //nolint:gocognit +func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.Addr, enqueue bool) (bool, *alert.Alert, error) { //nolint:gocognit h := &recordlayer.Header{} + // Set connection ID size so that records of content type tls12_cid will + // be parsed correctly. + if len(c.state.localConnectionID) > 0 { + h.ConnectionID = make([]byte, len(c.state.localConnectionID)) + } if err := h.Unmarshal(buf); err != nil { // Decode error must be silently discarded // [RFC6347 Section-4.1.2.7] @@ -674,7 +762,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, enqueue boo } if enqueue { c.log.Debug("received packet of next epoch, queuing packet") - c.encryptedPackets = append(c.encryptedPackets, buf) + c.encryptedPackets = append(c.encryptedPackets, addrPkt{rAddr, buf}) } return false, nil, nil } @@ -693,22 +781,66 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, enqueue boo return false, nil, nil } + // originalCID indicates whether the original record had content type + // Connection ID. + originalCID := false + // Decrypt if h.Epoch != 0 { if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { if enqueue { - c.encryptedPackets = append(c.encryptedPackets, buf) + c.encryptedPackets = append(c.encryptedPackets, addrPkt{rAddr, buf}) c.log.Debug("handshake not finished, queuing packet") } return false, nil, nil } + // If a connection identifier had been negotiated and encryption is + // enabled, the connection identifier MUST be sent. + if len(c.state.localConnectionID) > 0 && h.ContentType != protocol.ContentTypeConnectionID { + c.log.Debug("discarded packet missing connection ID after value negotiated") + return false, nil, nil + } + var err error - buf, err = c.state.cipherSuite.Decrypt(buf) + var hdr recordlayer.Header + if h.ContentType == protocol.ContentTypeConnectionID { + hdr.ConnectionID = make([]byte, len(c.state.localConnectionID)) + } + buf, err = c.state.cipherSuite.Decrypt(hdr, buf) if err != nil { c.log.Debugf("%s: decrypt failed: %s", srvCliStr(c.state.isClient), err) return false, nil, nil } + // If this is a connection ID record, make it look like a normal record for + // further processing. + if h.ContentType == protocol.ContentTypeConnectionID { + originalCID = true + ip := &recordlayer.InnerPlaintext{} + if err := ip.Unmarshal(buf[h.Size():]); err != nil { //nolint:govet + c.log.Debugf("unpacking inner plaintext failed: %s", err) + return false, nil, nil + } + unpacked := &recordlayer.Header{ + ContentType: ip.RealType, + ContentLen: uint16(len(ip.Content)), + Version: h.Version, + Epoch: h.Epoch, + SequenceNumber: h.SequenceNumber, + } + buf, err = unpacked.Marshal() + if err != nil { + c.log.Debugf("converting CID record to inner plaintext failed: %s", err) + return false, nil, nil + } + buf = append(buf, ip.Content...) + } + + // If connection ID does not match discard the packet. + if !bytes.Equal(c.state.localConnectionID, h.ConnectionID) { + c.log.Debug("unexpected connection ID") + return false, nil, nil + } } isHandshake, err := c.fragmentBuffer.push(append([]byte{}, buf...)) @@ -736,6 +868,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, enqueue boo return false, &alert.Alert{Level: alert.Fatal, Description: alert.DecodeError}, err } + isLatestSeqNum := false switch content := r.Content.(type) { case *alert.Alert: c.log.Tracef("%s: <- %s", srvCliStr(c.state.isClient), content.String()) @@ -744,12 +877,12 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, enqueue boo // Respond with a close_notify [RFC5246 Section 7.2.1] a = &alert.Alert{Level: alert.Warning, Description: alert.CloseNotify} } - markPacketAsValid() + _ = markPacketAsValid() return false, a, &alertError{content} case *protocol.ChangeCipherSpec: if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { if enqueue { - c.encryptedPackets = append(c.encryptedPackets, buf) + c.encryptedPackets = append(c.encryptedPackets, addrPkt{rAddr, buf}) c.log.Debugf("CipherSuite not initialized, queuing packet") } return false, nil, nil @@ -760,14 +893,14 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, enqueue boo if c.state.getRemoteEpoch()+1 == newRemoteEpoch { c.setRemoteEpoch(newRemoteEpoch) - markPacketAsValid() + isLatestSeqNum = markPacketAsValid() } case *protocol.ApplicationData: if h.Epoch == 0 { return false, &alert.Alert{Level: alert.Fatal, Description: alert.UnexpectedMessage}, errApplicationDataEpochZero } - markPacketAsValid() + isLatestSeqNum = markPacketAsValid() select { case c.decrypted <- content.Data: @@ -778,6 +911,18 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, enqueue boo default: return false, &alert.Alert{Level: alert.Fatal, Description: alert.UnexpectedMessage}, fmt.Errorf("%w: %d", errUnhandledContextType, content.ContentType()) } + + // Any valid connection ID record is a candidate for updating the remote + // address if it is the latest record received. + // https://datatracker.ietf.org/doc/html/rfc9146#peer-address-update + if originalCID && isLatestSeqNum { + if rAddr != c.RemoteAddr() { + c.lock.Lock() + c.rAddr = rAddr + c.lock.Unlock() + } + } + return false, nil, nil } @@ -881,7 +1026,7 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh } } else { switch { - case errors.Is(err, context.DeadlineExceeded), errors.Is(err, context.Canceled), errors.Is(err, io.EOF): + case errors.Is(err, context.DeadlineExceeded), errors.Is(err, context.Canceled), errors.Is(err, io.EOF), errors.Is(err, net.ErrClosed): default: if c.isHandshakeCompletedSuccessfully() { // Keep read loop and pass the read error to Read() @@ -995,7 +1140,9 @@ func (c *Conn) LocalAddr() net.Addr { // RemoteAddr implements net.Conn.RemoteAddr func (c *Conn) RemoteAddr() net.Addr { - return c.nextConn.RemoteAddr() + c.lock.RLock() + defer c.lock.RUnlock() + return c.rAddr } func (c *Conn) sessionKey() []byte { @@ -1003,7 +1150,7 @@ func (c *Conn) sessionKey() []byte { // As ServerName can be like 0.example.com, it's better to add // delimiter character which is not allowed to be in // neither address or domain name. - return []byte(c.nextConn.RemoteAddr().String() + "_" + c.fsm.cfg.serverName) + return []byte(c.rAddr.String() + "_" + c.fsm.cfg.serverName) } return c.state.SessionID } diff --git a/conn_go_test.go b/conn_go_test.go index 99e6f74c4..2978eb340 100644 --- a/conn_go_test.go +++ b/conn_go_test.go @@ -15,6 +15,7 @@ import ( "testing" "time" + "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/crypto/selfsign" "github.com/pion/transport/v2/dpipe" "github.com/pion/transport/v2/test" @@ -85,7 +86,7 @@ func TestContextConfig(t *testing.T) { f: func() (func() (net.Conn, error), func()) { ca, _ := dpipe.Pipe() return func() (net.Conn, error) { - return Client(ca, config) + return Client(util.FromConn(ca), ca.RemoteAddr(), config) }, func() { _ = ca.Close() } @@ -97,7 +98,7 @@ func TestContextConfig(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond) ca, _ := dpipe.Pipe() return func() (net.Conn, error) { - return ClientWithContext(ctx, ca, config) + return ClientWithContext(ctx, util.FromConn(ca), ca.RemoteAddr(), config) }, func() { cancel() _ = ca.Close() @@ -109,7 +110,7 @@ func TestContextConfig(t *testing.T) { f: func() (func() (net.Conn, error), func()) { ca, _ := dpipe.Pipe() return func() (net.Conn, error) { - return Server(ca, config) + return Server(util.FromConn(ca), ca.RemoteAddr(), config) }, func() { _ = ca.Close() } @@ -121,7 +122,7 @@ func TestContextConfig(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond) ca, _ := dpipe.Pipe() return func() (net.Conn, error) { - return ServerWithContext(ctx, ca, config) + return ServerWithContext(ctx, util.FromConn(ca), ca.RemoteAddr(), config) }, func() { cancel() _ = ca.Close() diff --git a/conn_test.go b/conn_test.go index 946e4ab43..4ec47571b 100644 --- a/conn_test.go +++ b/conn_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/pion/dtls/v2/internal/ciphersuite" + "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/crypto/elliptic" "github.com/pion/dtls/v2/pkg/crypto/hash" "github.com/pion/dtls/v2/pkg/crypto/selfsign" @@ -265,12 +266,12 @@ func pipeConn(ca, cb net.Conn) (*Conn, *Conn, error) { // Setup client go func() { - client, err := testClient(ctx, ca, &Config{SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}}, true) + client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}}, true) c <- result{client, err} }() // Setup server - server, err := testServer(ctx, cb, &Config{SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}}, true) + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}}, true) if err != nil { return nil, nil, err } @@ -285,7 +286,7 @@ func pipeConn(ca, cb net.Conn) (*Conn, *Conn, error) { return res.c, server, nil } -func testClient(ctx context.Context, c net.Conn, cfg *Config, generateCertificate bool) (*Conn, error) { +func testClient(ctx context.Context, c net.PacketConn, rAddr net.Addr, cfg *Config, generateCertificate bool) (*Conn, error) { if generateCertificate { clientCert, err := selfsign.GenerateSelfSigned() if err != nil { @@ -294,10 +295,10 @@ func testClient(ctx context.Context, c net.Conn, cfg *Config, generateCertificat cfg.Certificates = []tls.Certificate{clientCert} } cfg.InsecureSkipVerify = true - return ClientWithContext(ctx, c, cfg) + return ClientWithContext(ctx, c, rAddr, cfg) } -func testServer(ctx context.Context, c net.Conn, cfg *Config, generateCertificate bool) (*Conn, error) { +func testServer(ctx context.Context, c net.PacketConn, rAddr net.Addr, cfg *Config, generateCertificate bool) (*Conn, error) { if generateCertificate { serverCert, err := selfsign.GenerateSelfSigned() if err != nil { @@ -305,7 +306,7 @@ func testServer(ctx context.Context, c net.Conn, cfg *Config, generateCertificat } cfg.Certificates = []tls.Certificate{serverCert} } - return ServerWithContext(ctx, c, cfg) + return ServerWithContext(ctx, c, rAddr, cfg) } func sendClientHello(cookie []byte, ca net.Conn, sequenceNumber uint64, extensions []extension.Extension) error { @@ -384,11 +385,11 @@ func TestHandshakeWithAlert(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - _, err := testClient(ctx, ca, testCase.configClient, true) + _, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), testCase.configClient, true) clientErr <- err }() - _, errServer := testServer(ctx, cb, testCase.configServer, true) + _, errServer := testServer(ctx, util.FromConn(cb), ca.RemoteAddr(), testCase.configServer, true) if !errors.Is(errServer, testCase.errServer) { t.Fatalf("Server error exp(%v) failed(%v)", testCase.errServer, errServer) } @@ -551,7 +552,7 @@ func TestPSK(t *testing.T) { VerifyConnection: test.ClientVerifyConnection, } - c, err := testClient(ctx, ca, conf, false) + c, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), conf, false) clientRes <- result{c, err} }() @@ -567,7 +568,7 @@ func TestPSK(t *testing.T) { VerifyConnection: test.ServerVerifyConnection, } - server, err := testServer(ctx, cb, config, false) + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, false) if test.WantFail { res := <-clientRes if err == nil || !strings.Contains(err.Error(), test.ExpectedServerErr) { @@ -626,7 +627,7 @@ func TestPSKHintFail(t *testing.T) { CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, } - _, err := testClient(ctx, ca, conf, false) + _, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), conf, false) clientErr <- err }() @@ -638,7 +639,7 @@ func TestPSKHintFail(t *testing.T) { CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, } - if _, err := testServer(ctx, cb, config, false); !errors.Is(err, serverAlertError) { + if _, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, false); !errors.Is(err, serverAlertError) { t.Fatalf("TestPSK: Server error exp(%v) failed(%v)", serverAlertError, err) } @@ -665,7 +666,7 @@ func TestClientTimeout(t *testing.T) { go func() { conf := &Config{} - c, err := testClient(ctx, ca, conf, true) + c, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), conf, true) if err == nil { _ = c.Close() //nolint:contextcheck } @@ -753,11 +754,11 @@ func TestSRTPConfiguration(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, ca, &Config{SRTPProtectionProfiles: test.ClientSRTP}, true) + client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ClientSRTP}, true) c <- result{client, err} }() - server, err := testServer(ctx, cb, &Config{SRTPProtectionProfiles: test.ServerSRTP}, true) + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ServerSRTP}, true) if !errors.Is(err, test.WantServerError) { t.Errorf("TestSRTPConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantServerError, err) } @@ -961,11 +962,11 @@ func TestClientCertificate(t *testing.T) { c := make(chan result) go func() { - client, err := Client(ca, tt.clientCfg) + client, err := Client(util.FromConn(ca), ca.RemoteAddr(), tt.clientCfg) c <- result{client, err} }() - server, err := Server(cb, tt.serverCfg) + server, err := Server(util.FromConn(cb), cb.RemoteAddr(), tt.serverCfg) res := <-c defer func() { if err == nil { @@ -1041,6 +1042,120 @@ func TestClientCertificate(t *testing.T) { }) } +func TestConnectionID(t *testing.T) { + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + clientCID := []byte{5, 77, 33, 24, 93, 27, 45, 81} + serverCID := []byte{64, 24, 73, 2, 17, 96, 38, 59} + cidEcho := func(echo []byte) func() []byte { + return func() []byte { + return echo + } + } + tests := map[string]struct { + clientCfg *Config + serverCfg *Config + clientConnectionID []byte + serverConnectionID []byte + }{ + "BidirectionalConnectionIDs": { + clientCfg: &Config{ + ConnectionIDGenerator: cidEcho(clientCID), + }, + serverCfg: &Config{ + ConnectionIDGenerator: cidEcho(serverCID), + }, + clientConnectionID: clientCID, + serverConnectionID: serverCID, + }, + "BothSupportOnlyClientSends": { + clientCfg: &Config{ + ConnectionIDGenerator: cidEcho(nil), + }, + serverCfg: &Config{ + ConnectionIDGenerator: cidEcho(serverCID), + }, + serverConnectionID: serverCID, + }, + "BothSupportOnlyServerSends": { + clientCfg: &Config{ + ConnectionIDGenerator: cidEcho(clientCID), + }, + serverCfg: &Config{ + ConnectionIDGenerator: cidEcho(nil), + }, + clientConnectionID: clientCID, + }, + "ClientDoesNotSupport": { + clientCfg: &Config{}, + serverCfg: &Config{ + ConnectionIDGenerator: cidEcho(serverCID), + }, + }, + "ServerDoesNotSupport": { + clientCfg: &Config{ + ConnectionIDGenerator: cidEcho(clientCID), + }, + serverCfg: &Config{}, + }, + "NeitherSupport": { + clientCfg: &Config{}, + serverCfg: &Config{}, + }, + } + for name, tt := range tests { + tt := tt + t.Run(name, func(t *testing.T) { + 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, util.FromConn(ca), ca.RemoteAddr(), tt.clientCfg, true) + c <- result{client, err} + }() + + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), tt.serverCfg, true) + if err != nil { + t.Fatalf("Unexpected server error: %v", err) + } + res := <-c + if res.err != nil { + t.Fatalf("Unexpected client error: %v", res.err) + } + defer func() { + if err == nil { + _ = server.Close() + } + if res.err == nil { + _ = res.c.Close() + } + }() + + if !bytes.Equal(res.c.state.localConnectionID, tt.clientConnectionID) { + t.Errorf("Unexpected client local connection ID\nwant: %v\ngot:%v", tt.clientConnectionID, res.c.state.localConnectionID) + } + if !bytes.Equal(res.c.state.remoteConnectionID, tt.serverConnectionID) { + t.Errorf("Unexpected client remote connection ID\nwant: %v\ngot:%v", tt.serverConnectionID, res.c.state.remoteConnectionID) + } + if !bytes.Equal(server.state.localConnectionID, tt.serverConnectionID) { + t.Errorf("Unexpected server local connection ID\nwant: %v\ngot:%v", tt.serverConnectionID, server.state.localConnectionID) + } + if !bytes.Equal(server.state.remoteConnectionID, tt.clientConnectionID) { + t.Errorf("Unexpected server remote connection ID\nwant: %v\ngot:%v", tt.clientConnectionID, server.state.remoteConnectionID) + } + }) + } +} + func TestExtendedMasterSecret(t *testing.T) { // Check for leaking routines report := test.CheckRoutines(t) @@ -1157,11 +1272,11 @@ func TestExtendedMasterSecret(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, ca, tt.clientCfg, true) + client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), tt.clientCfg, true) c <- result{client, err} }() - server, err := testServer(ctx, cb, tt.serverCfg, true) + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), tt.serverCfg, true) res := <-c defer func() { if err == nil { @@ -1267,11 +1382,11 @@ func TestServerCertificate(t *testing.T) { } srvCh := make(chan result) go func() { - s, err := Server(cb, tt.serverCfg) + s, err := Server(util.FromConn(cb), cb.RemoteAddr(), tt.serverCfg) srvCh <- result{s, err} }() - cli, err := Client(ca, tt.clientCfg) + cli, err := Client(util.FromConn(ca), ca.RemoteAddr(), tt.clientCfg) if err == nil { _ = cli.Close() } @@ -1371,11 +1486,11 @@ func TestCipherSuiteConfiguration(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, ca, &Config{CipherSuites: test.ClientCipherSuites}, true) + client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: test.ClientCipherSuites}, true) c <- result{client, err} }() - server, err := testServer(ctx, cb, &Config{CipherSuites: test.ServerCipherSuites}, true) + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{CipherSuites: test.ServerCipherSuites}, true) if err == nil { defer func() { _ = server.Close() @@ -1440,7 +1555,7 @@ func TestCertificateAndPSKServer(t *testing.T) { config.CipherSuites = []CipherSuiteID{TLS_PSK_WITH_AES_128_GCM_SHA256} } - client, err := testClient(ctx, ca, config, false) + client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), config, false) c <- result{client, err} }() @@ -1451,7 +1566,7 @@ func TestCertificateAndPSKServer(t *testing.T) { }, } - server, err := testServer(ctx, cb, config, true) + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true) if err == nil { defer func() { _ = server.Close() @@ -1543,11 +1658,11 @@ func TestPSKConfiguration(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, ca, &Config{PSK: test.ClientPSK, PSKIdentityHint: test.ClientPSKIdentity}, test.ClientHasCertificate) + client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{PSK: test.ClientPSK, PSKIdentityHint: test.ClientPSKIdentity}, test.ClientHasCertificate) c <- result{client, err} }() - _, err := testServer(ctx, cb, &Config{PSK: test.ServerPSK, PSKIdentityHint: test.ServerPSKIdentity}, test.ServerHasCertificate) + _, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{PSK: test.ServerPSK, PSKIdentityHint: test.ServerPSKIdentity}, test.ServerHasCertificate) if err != nil || test.WantServerError != nil { if !(err != nil && test.WantServerError != nil && err.Error() == test.WantServerError.Error()) { t.Fatalf("TestPSKConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantServerError, err) @@ -1677,7 +1792,7 @@ func TestServerTimeout(t *testing.T) { FlightInterval: 100 * time.Millisecond, } - _, serverErr := testServer(ctx, cb, config, true) + _, serverErr := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true) var netErr net.Error if !errors.As(serverErr, &netErr) || !netErr.Timeout() { t.Fatalf("Client error exp(Temporary network error) failed(%v)", serverErr) @@ -1792,7 +1907,7 @@ func TestProtocolVersionValidation(t *testing.T) { defer wg.Wait() go func() { defer wg.Done() - if _, err := testServer(ctx, cb, config, true); !errors.Is(err, errUnsupportedProtocolVersion) { + if _, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true); !errors.Is(err, errUnsupportedProtocolVersion) { t.Errorf("Client error exp(%v) failed(%v)", errUnsupportedProtocolVersion, err) } }() @@ -1882,7 +1997,7 @@ func TestProtocolVersionValidation(t *testing.T) { defer wg.Wait() go func() { defer wg.Done() - if _, err := testClient(ctx, cb, config, true); !errors.Is(err, errUnsupportedProtocolVersion) { + if _, err := testClient(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true); !errors.Is(err, errUnsupportedProtocolVersion) { t.Errorf("Server error exp(%v) failed(%v)", errUnsupportedProtocolVersion, err) } }() @@ -1980,7 +2095,7 @@ func TestMultipleHelloVerifyRequest(t *testing.T) { defer wg.Wait() go func() { defer wg.Done() - _, _ = testClient(ctx, ca, &Config{}, false) + _, _ = testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{}, false) }() for i, cookie := range cookies { @@ -2052,7 +2167,7 @@ func TestRenegotationInfo(t *testing.T) { defer cancel() go func() { - if _, err := testServer(ctx, cb, &Config{}, true); !errors.Is(err, context.Canceled) { + if _, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{}, true); !errors.Is(err, context.Canceled) { t.Error(err) } }() @@ -2164,7 +2279,7 @@ func TestServerNameIndicationExtension(t *testing.T) { ServerName: test.ServerName, } - _, _ = testClient(ctx, ca, conf, false) + _, _ = testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), conf, false) }() // Receive ClientHello @@ -2282,7 +2397,7 @@ func TestALPNExtension(t *testing.T) { conf := &Config{ SupportedProtocols: test.ClientProtocolNameList, } - _, _ = testClient(ctx, ca, conf, false) + _, _ = testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), conf, false) }() // Receive ClientHello @@ -2300,7 +2415,7 @@ func TestALPNExtension(t *testing.T) { conf := &Config{ SupportedProtocols: test.ServerProtocolNameList, } - if _, err2 := testServer(ctx2, cb2, conf, true); !errors.Is(err2, context.Canceled) { + if _, err2 := testServer(ctx2, util.FromConn(cb2), cb2.RemoteAddr(), conf, true); !errors.Is(err2, context.Canceled) { if test.ExpectAlertFromServer { //nolint // Assert the error type? } else { @@ -2447,7 +2562,7 @@ func TestSupportedGroupsExtension(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - if _, err := testServer(ctx, cb, &Config{}, true); !errors.Is(err, context.Canceled) { + if _, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{}, true); !errors.Is(err, context.Canceled) { t.Error(err) } }() @@ -2556,7 +2671,7 @@ func TestSessionResume(t *testing.T) { SessionStore: ss, MTU: 100, } - c, err := testClient(ctx, ca, config, false) + c, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), config, false) clientRes <- result{c, err} }() @@ -2566,7 +2681,7 @@ func TestSessionResume(t *testing.T) { SessionStore: ss, MTU: 100, } - server, err := testServer(ctx, cb, config, true) + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true) if err != nil { t.Fatalf("TestSessionResume: Server failed(%v)", err) } @@ -2610,14 +2725,14 @@ func TestSessionResume(t *testing.T) { ServerName: "example.com", SessionStore: s1, } - c, err := testClient(ctx, ca, config, false) + c, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), config, false) clientRes <- result{c, err} }() config := &Config{ SessionStore: s2, } - server, err := testServer(ctx, cb, config, true) + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true) if err != nil { t.Fatalf("TestSessionResumetion: Server failed(%v)", err) } @@ -2715,7 +2830,7 @@ func TestCipherSuiteMatchesCertificateType(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - c, err := testClient(context.TODO(), ca, &Config{CipherSuites: test.cipherList}, false) + c, err := testClient(context.TODO(), util.FromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: test.cipherList}, false) clientErr <- err client <- c }() @@ -2740,7 +2855,7 @@ func TestCipherSuiteMatchesCertificateType(t *testing.T) { t.Fatal(err) } - if s, err := testServer(context.TODO(), cb, &Config{ + if s, err := testServer(context.TODO(), util.FromConn(cb), cb.RemoteAddr(), &Config{ CipherSuites: test.cipherList, Certificates: []tls.Certificate{serverCert}, }, false); err != nil { @@ -2805,7 +2920,7 @@ func TestMultipleServerCertificates(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - c, err := testClient(context.TODO(), ca, &Config{ + c, err := testClient(context.TODO(), util.FromConn(ca), ca.RemoteAddr(), &Config{ RootCAs: caPool, ServerName: test.RequestServerName, VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { @@ -2825,7 +2940,7 @@ func TestMultipleServerCertificates(t *testing.T) { client <- c }() - if s, err := testServer(context.TODO(), cb, &Config{Certificates: []tls.Certificate{fooCert, barCert}}, false); err != nil { + if s, err := testServer(context.TODO(), util.FromConn(cb), cb.RemoteAddr(), &Config{Certificates: []tls.Certificate{fooCert, barCert}}, false); err != nil { t.Fatal(err) } else if err = s.Close(); err != nil { t.Fatal(err) @@ -2877,11 +2992,11 @@ func TestEllipticCurveConfiguration(t *testing.T) { 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) + client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &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) + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, EllipticCurves: test.ConfigCurves}, true) if err != nil { t.Fatalf("Server error: %v", err) } @@ -2933,7 +3048,7 @@ func TestSkipHelloVerify(t *testing.T) { gotHello := make(chan struct{}) go func() { - server, sErr := testServer(ctx, cb, &Config{ + server, sErr := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{ Certificates: []tls.Certificate{certificate}, LoggerFactory: logging.NewDefaultLoggerFactory(), InsecureSkipVerifyHello: true, @@ -2952,7 +3067,7 @@ func TestSkipHelloVerify(t *testing.T) { } }() - client, err := testClient(ctx, ca, &Config{ + client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{ LoggerFactory: logging.NewDefaultLoggerFactory(), InsecureSkipVerify: true, }, false) From f960a37453d5fc98493be2368cb42188b8d56bfc Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:58:20 -0400 Subject: [PATCH 030/146] Wrap net.Conn in DTLS listener Wraps the net.Conn returned from the UDP listener in the DTLS listener. The underlying UDP listener will be adapted in the future to support returning net.PacketConn. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- listener.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/listener.go b/listener.go index 190d236c7..0d281fc4d 100644 --- a/listener.go +++ b/listener.go @@ -6,6 +6,7 @@ package dtls import ( "net" + "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/protocol" "github.com/pion/dtls/v2/pkg/protocol/recordlayer" "github.com/pion/transport/v2/udp" @@ -67,7 +68,7 @@ func (l *listener) Accept() (net.Conn, error) { if err != nil { return nil, err } - return Server(c, l.config) + return Server(util.FromConn(c), c.RemoteAddr(), l.config) } // Close closes the listener. From ee041419dc9340101ffa8c6d546262357deaba9d Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 14:59:39 -0400 Subject: [PATCH 031/146] Update tests to wrap net.Conn Updates tests that use net.Conn to wrap in net.PacketConn so that new Client / Server constructors may be used. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- bench_test.go | 9 +++++---- cipher_suite.go | 2 +- cipher_suite_test.go | 5 +++-- resume.go | 4 ++-- resume_test.go | 9 +++++---- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/bench_test.go b/bench_test.go index abec5a5d7..9f27bb71b 100644 --- a/bench_test.go +++ b/bench_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/crypto/selfsign" "github.com/pion/logging" "github.com/pion/transport/v2/dpipe" @@ -30,7 +31,7 @@ func TestSimpleReadWrite(t *testing.T) { gotHello := make(chan struct{}) go func() { - server, sErr := testServer(ctx, cb, &Config{ + server, sErr := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{ Certificates: []tls.Certificate{certificate}, LoggerFactory: logging.NewDefaultLoggerFactory(), }, false) @@ -48,7 +49,7 @@ func TestSimpleReadWrite(t *testing.T) { } }() - client, err := testClient(ctx, ca, &Config{ + client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{ LoggerFactory: logging.NewDefaultLoggerFactory(), InsecureSkipVerify: true, }, false) @@ -78,7 +79,7 @@ func benchmarkConn(b *testing.B, n int64) { certificate, err := selfsign.GenerateSelfSigned() server := make(chan *Conn) go func() { - s, sErr := testServer(ctx, cb, &Config{ + s, sErr := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{ Certificates: []tls.Certificate{certificate}, }, false) if err != nil { @@ -94,7 +95,7 @@ func benchmarkConn(b *testing.B, n int64) { b.ReportAllocs() b.SetBytes(int64(len(hw))) go func() { - client, cErr := testClient(ctx, ca, &Config{InsecureSkipVerify: true}, false) + client, cErr := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{InsecureSkipVerify: true}, false) if cErr != nil { b.Error(err) } diff --git a/cipher_suite.go b/cipher_suite.go index 7a5bb4a58..6f7015c02 100644 --- a/cipher_suite.go +++ b/cipher_suite.go @@ -95,7 +95,7 @@ type CipherSuite interface { Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error IsInitialized() bool Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) - Decrypt(in []byte) ([]byte, error) + Decrypt(h recordlayer.Header, in []byte) ([]byte, error) } // CipherSuiteName provides the same functionality as tls.CipherSuiteName diff --git a/cipher_suite_test.go b/cipher_suite_test.go index 655fe6717..0d2d83d09 100644 --- a/cipher_suite_test.go +++ b/cipher_suite_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/pion/dtls/v2/internal/ciphersuite" + "github.com/pion/dtls/v2/internal/util" "github.com/pion/transport/v2/dpipe" "github.com/pion/transport/v2/test" ) @@ -70,14 +71,14 @@ func TestCustomCipherSuite(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, ca, &Config{ + client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{ CipherSuites: []CipherSuiteID{}, CustomCipherSuites: cipherFactory, }, true) c <- result{client, err} }() - server, err := testServer(ctx, cb, &Config{ + server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{ CipherSuites: []CipherSuiteID{}, CustomCipherSuites: cipherFactory, }, true) diff --git a/resume.go b/resume.go index c470d856b..9e8a2ae42 100644 --- a/resume.go +++ b/resume.go @@ -9,11 +9,11 @@ import ( ) // Resume imports an already established dtls connection using a specific dtls state -func Resume(state *State, conn net.Conn, config *Config) (*Conn, error) { +func Resume(state *State, conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { if err := state.initCipherSuite(); err != nil { return nil, err } - c, err := createConn(context.Background(), conn, config, state.isClient, state) + c, err := createConn(context.Background(), conn, rAddr, config, state.isClient, state) if err != nil { return nil, err } diff --git a/resume_test.go b/resume_test.go index c8c231b86..740a44e6d 100644 --- a/resume_test.go +++ b/resume_test.go @@ -13,6 +13,7 @@ import ( "testing" "time" + "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/crypto/selfsign" "github.com/pion/transport/v2/test" ) @@ -32,7 +33,7 @@ func fatal(t *testing.T, errChan chan error, err error) { t.Fatal(err) } -func DoTestResume(t *testing.T, newLocal, newRemote func(net.Conn, *Config) (*Conn, error)) { +func DoTestResume(t *testing.T, newLocal, newRemote func(net.PacketConn, net.Addr, *Config) (*Conn, error)) { // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -67,7 +68,7 @@ func DoTestResume(t *testing.T, newLocal, newRemote func(net.Conn, *Config) (*Co go func() { var remote *Conn var errR error - remote, errR = newRemote(remoteConn, config) + remote, errR = newRemote(util.FromConn(remoteConn), remoteConn.RemoteAddr(), config) if errR != nil { errChan <- errR } @@ -89,7 +90,7 @@ func DoTestResume(t *testing.T, newLocal, newRemote func(net.Conn, *Config) (*Co }() var local *Conn - local, err = newLocal(localConn1, config) + local, err = newLocal(util.FromConn(localConn1), localConn1.RemoteAddr(), config) if err != nil { fatal(t, errChan, err) } @@ -132,7 +133,7 @@ func DoTestResume(t *testing.T, newLocal, newRemote func(net.Conn, *Config) (*Co // Resume dtls connection var resumed net.Conn - resumed, err = Resume(deserialized, localConn2, config) + resumed, err = Resume(deserialized, util.FromConn(localConn2), localConn2.RemoteAddr(), config) if err != nil { fatal(t, errChan, err) } From 2f2bc8d81563f8bbe1adc800694f3033da172c66 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 15:00:20 -0400 Subject: [PATCH 032/146] Add e2e CID tests Adds e2e tests for connection ID support. OpenSSL does not currently support connection IDs, so tests are only run between pion/dtls client and server. Support for other libraries, such as californium and mbedTLS will be added in the future. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- e2e/e2e_lossy_test.go | 5 +-- e2e/e2e_test.go | 74 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/e2e/e2e_lossy_test.go b/e2e/e2e_lossy_test.go index 2789ec3e9..c694287da 100644 --- a/e2e/e2e_lossy_test.go +++ b/e2e/e2e_lossy_test.go @@ -11,6 +11,7 @@ import ( "time" "github.com/pion/dtls/v2" + "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/crypto/selfsign" transportTest "github.com/pion/transport/v2/test" ) @@ -144,7 +145,7 @@ func TestPionE2ELossy(t *testing.T) { cfg.Certificates = []tls.Certificate{clientCert} } - client, startupErr := dtls.Client(br.GetConn0(), cfg) + client, startupErr := dtls.Client(util.FromConn(br.GetConn0()), br.GetConn0().RemoteAddr(), cfg) clientDone <- runResult{client, startupErr} }() @@ -159,7 +160,7 @@ func TestPionE2ELossy(t *testing.T) { cfg.ClientAuth = dtls.RequireAnyClientCert } - server, startupErr := dtls.Server(br.GetConn1(), cfg) + server, startupErr := dtls.Server(util.FromConn(br.GetConn1()), br.GetConn1().RemoteAddr(), cfg) serverDone <- runResult{server, startupErr} }() diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 736987ea4..955f82990 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -253,13 +253,21 @@ func serverPion(c *comm) { close(c.serverDone) } +type dtlsConfOpts func(*dtls.Config) + +func withConnectionIDGenerator(g func() []byte) dtlsConfOpts { + return func(c *dtls.Config) { + c.ConnectionIDGenerator = g + } +} + /* 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)) { +func testPionE2ESimple(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -286,6 +294,9 @@ func testPionE2ESimple(t *testing.T, server, client func(*comm)) { CipherSuites: []dtls.CipherSuiteID{cipherSuite}, InsecureSkipVerify: true, } + for _, o := range opts { + o(cfg) + } serverPort := randomPort(t) comm := newComm(ctx, cfg, cfg, serverPort, server, client) defer comm.cleanup(t) @@ -294,7 +305,7 @@ func testPionE2ESimple(t *testing.T, server, client func(*comm)) { } } -func testPionE2ESimplePSK(t *testing.T, server, client func(*comm)) { +func testPionE2ESimplePSK(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -320,6 +331,9 @@ func testPionE2ESimplePSK(t *testing.T, server, client func(*comm)) { PSKIdentityHint: []byte{0x01, 0x02, 0x03, 0x04, 0x05}, CipherSuites: []dtls.CipherSuiteID{cipherSuite}, } + for _, o := range opts { + o(cfg) + } serverPort := randomPort(t) comm := newComm(ctx, cfg, cfg, serverPort, server, client) defer comm.cleanup(t) @@ -328,7 +342,7 @@ func testPionE2ESimplePSK(t *testing.T, server, client func(*comm)) { } } -func testPionE2EMTUs(t *testing.T, server, client func(*comm)) { +func testPionE2EMTUs(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -356,6 +370,9 @@ func testPionE2EMTUs(t *testing.T, server, client func(*comm)) { InsecureSkipVerify: true, MTU: mtu, } + for _, o := range opts { + o(cfg) + } serverPort := randomPort(t) comm := newComm(ctx, cfg, cfg, serverPort, server, client) defer comm.cleanup(t) @@ -364,7 +381,7 @@ func testPionE2EMTUs(t *testing.T, server, client func(*comm)) { } } -func testPionE2ESimpleED25519(t *testing.T, server, client func(*comm)) { +func testPionE2ESimpleED25519(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -397,6 +414,9 @@ func testPionE2ESimpleED25519(t *testing.T, server, client func(*comm)) { CipherSuites: []dtls.CipherSuiteID{cipherSuite}, InsecureSkipVerify: true, } + for _, o := range opts { + o(cfg) + } serverPort := randomPort(t) comm := newComm(ctx, cfg, cfg, serverPort, server, client) defer comm.cleanup(t) @@ -405,7 +425,7 @@ func testPionE2ESimpleED25519(t *testing.T, server, client func(*comm)) { } } -func testPionE2ESimpleED25519ClientCert(t *testing.T, server, client func(*comm)) { +func testPionE2ESimpleED25519ClientCert(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -443,13 +463,17 @@ func testPionE2ESimpleED25519ClientCert(t *testing.T, server, client func(*comm) CipherSuites: []dtls.CipherSuiteID{dtls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, InsecureSkipVerify: true, } + for _, o := range opts { + o(scfg) + o(ccfg) + } serverPort := randomPort(t) comm := newComm(ctx, ccfg, scfg, serverPort, server, client) defer comm.cleanup(t) comm.assert(t) } -func testPionE2ESimpleECDSAClientCert(t *testing.T, server, client func(*comm)) { +func testPionE2ESimpleECDSAClientCert(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -487,13 +511,17 @@ func testPionE2ESimpleECDSAClientCert(t *testing.T, server, client func(*comm)) CipherSuites: []dtls.CipherSuiteID{dtls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, InsecureSkipVerify: true, } + for _, o := range opts { + o(scfg) + o(ccfg) + } serverPort := randomPort(t) comm := newComm(ctx, ccfg, scfg, serverPort, server, client) defer comm.cleanup(t) comm.assert(t) } -func testPionE2ESimpleRSAClientCert(t *testing.T, server, client func(*comm)) { +func testPionE2ESimpleRSAClientCert(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -531,6 +559,10 @@ func testPionE2ESimpleRSAClientCert(t *testing.T, server, client func(*comm)) { CipherSuites: []dtls.CipherSuiteID{dtls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, InsecureSkipVerify: true, } + for _, o := range opts { + o(scfg) + o(ccfg) + } serverPort := randomPort(t) comm := newComm(ctx, ccfg, scfg, serverPort, server, client) defer comm.cleanup(t) @@ -564,3 +596,31 @@ func TestPionE2ESimpleECDSAClientCert(t *testing.T) { func TestPionE2ESimpleRSAClientCert(t *testing.T) { testPionE2ESimpleRSAClientCert(t, serverPion, clientPion) } + +func TestPionE2ESimpleCID(t *testing.T) { + testPionE2ESimple(t, serverPion, clientPion, withConnectionIDGenerator(dtls.RandomCIDGenerator(8))) +} + +func TestPionE2ESimplePSKCID(t *testing.T) { + testPionE2ESimplePSK(t, serverPion, clientPion, withConnectionIDGenerator(dtls.RandomCIDGenerator(8))) +} + +func TestPionE2EMTUsCID(t *testing.T) { + testPionE2EMTUs(t, serverPion, clientPion, withConnectionIDGenerator(dtls.RandomCIDGenerator(8))) +} + +func TestPionE2ESimpleED25519CID(t *testing.T) { + testPionE2ESimpleED25519(t, serverPion, clientPion, withConnectionIDGenerator(dtls.RandomCIDGenerator(8))) +} + +func TestPionE2ESimpleED25519ClientCertCID(t *testing.T) { + testPionE2ESimpleED25519ClientCert(t, serverPion, clientPion, withConnectionIDGenerator(dtls.RandomCIDGenerator(8))) +} + +func TestPionE2ESimpleECDSAClientCertCID(t *testing.T) { + testPionE2ESimpleECDSAClientCert(t, serverPion, clientPion, withConnectionIDGenerator(dtls.RandomCIDGenerator(8))) +} + +func TestPionE2ESimpleRSAClientCertCID(t *testing.T) { + testPionE2ESimpleRSAClientCert(t, serverPion, clientPion, withConnectionIDGenerator(dtls.RandomCIDGenerator(8))) +} From d29c6f07a304a0e030e0871174461b13fe29b017 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 9 Aug 2023 15:01:27 -0400 Subject: [PATCH 033/146] Add basic connection ID generators Adds simple connection ID generators that can be used to generate random connection IDs of a given length, or indicate support for connection IDs without requiring the remote to send one. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- connection_id.go | 28 ++++++++++++++++++++++++++ connection_id_test.go | 46 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 connection_id.go create mode 100644 connection_id_test.go diff --git a/connection_id.go b/connection_id.go new file mode 100644 index 000000000..564d17184 --- /dev/null +++ b/connection_id.go @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +package dtls + +import "crypto/rand" + +// RandomCIDGenerator is a random Connection ID generator where CID is the +// specified size. Specifying a size of 0 will indicate to peers that sending a +// Connection ID is not necessary. +func RandomCIDGenerator(size int) func() []byte { + return func() []byte { + cid := make([]byte, size) + if _, err := rand.Read(cid); err != nil { + panic(err) //nolint -- nonrecoverable + } + return cid + } +} + +// OnlySendCIDGenerator enables sending Connection IDs negotiated with a peer, +// but indicates to the peer that sending Connection IDs in return is not +// necessary. +func OnlySendCIDGenerator() func() []byte { + return func() []byte { + return nil + } +} diff --git a/connection_id_test.go b/connection_id_test.go new file mode 100644 index 000000000..b9f65d3f7 --- /dev/null +++ b/connection_id_test.go @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +package dtls + +import "testing" + +func TestRandomConnectionIDGenerator(t *testing.T) { + cases := map[string]struct { + reason string + size int + }{ + "LengthMatch": { + reason: "Zero size should match length of generated CID.", + size: 0, + }, + "LengthMatchSome": { + reason: "Non-zero size should match length of generated CID with non-zero.", + size: 8, + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + if cidLen := len(RandomCIDGenerator(tc.size)()); cidLen != tc.size { + t.Errorf("%s\nRandomCIDGenerator: expected CID length %d, but got %d.", tc.reason, tc.size, cidLen) + } + }) + } +} + +func TestOnlySendCIDGenerator(t *testing.T) { + cases := map[string]struct { + reason string + }{ + "LengthMatch": { + reason: "CID length should always be zero.", + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + if cidLen := len(OnlySendCIDGenerator()()); cidLen != 0 { + t.Errorf("%s\nOnlySendCIDGenerator: expected CID length %d, but got %d.", tc.reason, 0, cidLen) + } + }) + } +} From 818feb8828c17f0ec2831814295296ae27ca39ca Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Thu, 10 Aug 2023 11:58:06 -0400 Subject: [PATCH 034/146] Set timeout to 10 minutes on e2e workflow Sets the timeout to 10 minutes on the e2e workflow. Previously, if the workflow did not terminate, it would run for the default of 360 minutes. See https://docs.github.com/en/actions/using-workflows for more information. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- .github/workflows/e2e.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 51809cbf3..e9e89daa5 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -14,6 +14,7 @@ jobs: e2e-test: name: Test runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: checkout uses: actions/checkout@v2 From 83b125485ec0277011ba97d26c2c5578ea96d8a7 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Mon, 14 Aug 2023 08:32:03 -0400 Subject: [PATCH 035/146] Fix name of cipher suite initialization function Fixes misspelling in name of cipher suite initialization function. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- flight5handler.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flight5handler.go b/flight5handler.go index 33965417f..e1cca6238 100644 --- a/flight5handler.go +++ b/flight5handler.go @@ -173,7 +173,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han merged = append(merged, raw...) } - if alertPtr, err := initalizeCipherSuite(state, cache, cfg, serverKeyExchange, merged); err != nil { + if alertPtr, err := initializeCipherSuite(state, cache, cfg, serverKeyExchange, merged); err != nil { return nil, alertPtr, err } @@ -285,7 +285,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han return pkts, nil, nil } -func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeConfig, h *handshake.MessageServerKeyExchange, sendingPlainText []byte) (*alert.Alert, error) { //nolint:gocognit +func initializeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeConfig, h *handshake.MessageServerKeyExchange, sendingPlainText []byte) (*alert.Alert, error) { //nolint:gocognit if state.cipherSuite.IsInitialized() { return nil, nil //nolint } From 30823132c17fdf1681fd2beced220f93e8a69857 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Tue, 22 Aug 2023 17:39:21 -0400 Subject: [PATCH 036/146] Convert nil CIDs to empty byte slice Adds a check on the generated CID in flight 1 to convert to an empty byte slice if the CID is nil. This allows us to distinguish not supporting CIDs to only suppporting sending CIDs in the second ClientHello in flight 3. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- flight1handler.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/flight1handler.go b/flight1handler.go index cafb36d0b..48bc88213 100644 --- a/flight1handler.go +++ b/flight1handler.go @@ -123,6 +123,13 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha // use. if cfg.connectionIDGenerator != nil { state.localConnectionID = cfg.connectionIDGenerator() + // The presence of a generator indicates support for connection IDs. We + // use the presence of a non-nil local CID in flight 3 to determine + // whether we send a CID in the second ClientHello, so we convert any + // nil CID returned by a generator to []byte{}. + if state.localConnectionID == nil { + state.localConnectionID = []byte{} + } extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) } From f1d8b0a0fa884a7260d68e5065736b7e8bbab558 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Wed, 23 Aug 2023 15:46:06 -0400 Subject: [PATCH 037/146] Wrap Alerts when CID is negotiated Updates to conditionally wrap Alert messages when a non-zero length connection ID has been negotiated. From the DTLS 1.2 Connection ID RFC: If DTLS peers have negotiated the use of a non-zero-length CID for a given direction, then once encryption is enabled, they MUST send with the record format defined in Figure 3 (see Section 4) with the new Message Authentication Code (MAC) computation defined in Section 5 and the content type tls12_cid. Plaintext payloads never use the new record format or the CID content type. https://datatracker.ietf.org/doc/html/rfc9146#section-3 Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- conn.go | 1 + 1 file changed, 1 insertion(+) diff --git a/conn.go b/conn.go index 8d7799add..e09f4b20a 100644 --- a/conn.go +++ b/conn.go @@ -953,6 +953,7 @@ func (c *Conn) notify(ctx context.Context, level alert.Level, desc alert.Descrip Description: desc, }, }, + shouldWrapCID: len(c.state.remoteConnectionID) > 0, shouldEncrypt: c.isHandshakeCompletedSuccessfully(), }, }) From 4f53ce190613301cceb169c84d1f1aa038c030f9 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:12:49 -0400 Subject: [PATCH 038/146] Introduce net package Introduces a new net package, which defines networking interfaces used throughout the pion/dtls code base, as well as utilities to help consumers convert standard library net types into pion/dtls compatible ones. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- internal/util/net.go | 57 ----------------------- pkg/net/net.go | 108 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 57 deletions(-) delete mode 100644 internal/util/net.go create mode 100644 pkg/net/net.go diff --git a/internal/util/net.go b/internal/util/net.go deleted file mode 100644 index 5a94dcf2a..000000000 --- a/internal/util/net.go +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> -// SPDX-License-Identifier: MIT - -// Package util contains small helpers used across the repo -package util - -import ( - "net" - "time" -) - -// packetConn wraps a net.Conn with methods that satisfy net.PacketConn. -type packetConn struct { - conn net.Conn -} - -// FromConn converts a net.Conn into a net.PacketConn. -func FromConn(conn net.Conn) net.PacketConn { - return &packetConn{conn} -} - -// ReadFrom reads from the underlying net.Conn and returns its remote address. -func (cp *packetConn) ReadFrom(b []byte) (int, net.Addr, error) { - n, err := cp.conn.Read(b) - return n, cp.conn.RemoteAddr(), err -} - -// WriteTo writes to the underlying net.Conn. -func (cp *packetConn) WriteTo(b []byte, _ net.Addr) (int, error) { - n, err := cp.conn.Write(b) - return n, err -} - -// Close closes the underlying net.Conn. -func (cp *packetConn) Close() error { - return cp.conn.Close() -} - -// LocalAddr returns the local address of the underlying net.Conn. -func (cp *packetConn) LocalAddr() net.Addr { - return cp.conn.LocalAddr() -} - -// SetDeadline sets the deadline on the underlying net.Conn. -func (cp *packetConn) SetDeadline(t time.Time) error { - return cp.conn.SetDeadline(t) -} - -// SetReadDeadline sets the read deadline on the underlying net.Conn. -func (cp *packetConn) SetReadDeadline(t time.Time) error { - return cp.conn.SetReadDeadline(t) -} - -// SetWriteDeadline sets the write deadline on the underlying net.Conn. -func (cp *packetConn) SetWriteDeadline(t time.Time) error { - return cp.conn.SetWriteDeadline(t) -} diff --git a/pkg/net/net.go b/pkg/net/net.go new file mode 100644 index 000000000..e76daf56a --- /dev/null +++ b/pkg/net/net.go @@ -0,0 +1,108 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +// Package net defines packet-oriented primitives that are compatible with net +// in the standard library. +package net + +import ( + "net" + "time" +) + +// A PacketListener is the same as net.Listener but returns a net.PacketConn on +// Accept() rather than a net.Conn. +// +// Multiple goroutines may invoke methods on a PacketListener simultaneously. +type PacketListener interface { + // Accept waits for and returns the next connection to the listener. + Accept() (net.PacketConn, net.Addr, error) + + // Close closes the listener. + // Any blocked Accept operations will be unblocked and return errors. + Close() error + + // Addr returns the listener's network address. + Addr() net.Addr +} + +// PacketListenerFromListener converts a net.Listener into a +// dtlsnet.PacketListener. +func PacketListenerFromListener(l net.Listener) PacketListener { + return &packetListenerWrapper{ + l: l, + } +} + +// packetListenerWrapper wraps a net.Listener and implements +// dtlsnet.PacketListener. +type packetListenerWrapper struct { + l net.Listener +} + +// Accept calls Accept on the underlying net.Listener and converts the returned +// net.Conn into a net.PacketConn. +func (p *packetListenerWrapper) Accept() (net.PacketConn, net.Addr, error) { + c, err := p.l.Accept() + if err != nil { + return PacketConnFromConn(c), nil, err + } + return PacketConnFromConn(c), c.RemoteAddr(), nil +} + +// Close closes the underlying net.Listener. +func (p *packetListenerWrapper) Close() error { + return p.l.Close() +} + +// Addr returns the address of the underlying net.Listener. +func (p *packetListenerWrapper) Addr() net.Addr { + return p.l.Addr() +} + +// PacketConnFromConn converts a net.Conn into a net.PacketConn. +func PacketConnFromConn(conn net.Conn) net.PacketConn { + return &packetConnWrapper{conn} +} + +// packetConnWrapper wraps a net.Conn and implements net.PacketConn. +type packetConnWrapper struct { + conn net.Conn +} + +// ReadFrom reads from the underlying net.Conn and returns its remote address. +func (p *packetConnWrapper) ReadFrom(b []byte) (int, net.Addr, error) { + n, err := p.conn.Read(b) + return n, p.conn.RemoteAddr(), err +} + +// WriteTo writes to the underlying net.Conn. +func (p *packetConnWrapper) WriteTo(b []byte, _ net.Addr) (int, error) { + n, err := p.conn.Write(b) + return n, err +} + +// Close closes the underlying net.Conn. +func (p *packetConnWrapper) Close() error { + return p.conn.Close() +} + +// LocalAddr returns the local address of the underlying net.Conn. +func (p *packetConnWrapper) LocalAddr() net.Addr { + return p.conn.LocalAddr() +} + +// SetDeadline sets the deadline on the underlying net.Conn. +func (p *packetConnWrapper) SetDeadline(t time.Time) error { + return p.conn.SetDeadline(t) +} + +// SetReadDeadline sets the read deadline on the underlying net.Conn. +func (p *packetConnWrapper) SetReadDeadline(t time.Time) error { + return p.conn.SetReadDeadline(t) +} + +// SetWriteDeadline sets the write deadline on the underlying net.Conn. +func (p *packetConnWrapper) SetWriteDeadline(t time.Time) error { + return p.conn.SetWriteDeadline(t) +} From 703da0cd768a65dd35a8e5e4b49dd4eb717e14fa Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:17:24 -0400 Subject: [PATCH 039/146] Consume net package in tests Updates unit and e2e tests to consume new utilities from the dtls net package. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- bench_test.go | 10 ++--- cipher_suite_test.go | 6 +-- conn_go_test.go | 10 ++--- conn_test.go | 94 +++++++++++++++++++++---------------------- e2e/e2e_lossy_test.go | 6 +-- resume_test.go | 8 ++-- 6 files changed, 67 insertions(+), 67 deletions(-) diff --git a/bench_test.go b/bench_test.go index 9f27bb71b..08b6c3c7b 100644 --- a/bench_test.go +++ b/bench_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/crypto/selfsign" + dtlsnet "github.com/pion/dtls/v2/pkg/net" "github.com/pion/logging" "github.com/pion/transport/v2/dpipe" "github.com/pion/transport/v2/test" @@ -31,7 +31,7 @@ func TestSimpleReadWrite(t *testing.T) { gotHello := make(chan struct{}) go func() { - server, sErr := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{ + server, sErr := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ Certificates: []tls.Certificate{certificate}, LoggerFactory: logging.NewDefaultLoggerFactory(), }, false) @@ -49,7 +49,7 @@ func TestSimpleReadWrite(t *testing.T) { } }() - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{ + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ LoggerFactory: logging.NewDefaultLoggerFactory(), InsecureSkipVerify: true, }, false) @@ -79,7 +79,7 @@ func benchmarkConn(b *testing.B, n int64) { certificate, err := selfsign.GenerateSelfSigned() server := make(chan *Conn) go func() { - s, sErr := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{ + s, sErr := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ Certificates: []tls.Certificate{certificate}, }, false) if err != nil { @@ -95,7 +95,7 @@ func benchmarkConn(b *testing.B, n int64) { b.ReportAllocs() b.SetBytes(int64(len(hw))) go func() { - client, cErr := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{InsecureSkipVerify: true}, false) + client, cErr := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{InsecureSkipVerify: true}, false) if cErr != nil { b.Error(err) } diff --git a/cipher_suite_test.go b/cipher_suite_test.go index 0d2d83d09..38bfd516e 100644 --- a/cipher_suite_test.go +++ b/cipher_suite_test.go @@ -9,7 +9,7 @@ import ( "time" "github.com/pion/dtls/v2/internal/ciphersuite" - "github.com/pion/dtls/v2/internal/util" + dtlsnet "github.com/pion/dtls/v2/pkg/net" "github.com/pion/transport/v2/dpipe" "github.com/pion/transport/v2/test" ) @@ -71,14 +71,14 @@ func TestCustomCipherSuite(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{ + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ CipherSuites: []CipherSuiteID{}, CustomCipherSuites: cipherFactory, }, true) c <- result{client, err} }() - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{ + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ CipherSuites: []CipherSuiteID{}, CustomCipherSuites: cipherFactory, }, true) diff --git a/conn_go_test.go b/conn_go_test.go index 2978eb340..cfd0e32f4 100644 --- a/conn_go_test.go +++ b/conn_go_test.go @@ -15,8 +15,8 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/crypto/selfsign" + dtlsnet "github.com/pion/dtls/v2/pkg/net" "github.com/pion/transport/v2/dpipe" "github.com/pion/transport/v2/test" ) @@ -86,7 +86,7 @@ func TestContextConfig(t *testing.T) { f: func() (func() (net.Conn, error), func()) { ca, _ := dpipe.Pipe() return func() (net.Conn, error) { - return Client(util.FromConn(ca), ca.RemoteAddr(), config) + return Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) }, func() { _ = ca.Close() } @@ -98,7 +98,7 @@ func TestContextConfig(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond) ca, _ := dpipe.Pipe() return func() (net.Conn, error) { - return ClientWithContext(ctx, util.FromConn(ca), ca.RemoteAddr(), config) + return ClientWithContext(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) }, func() { cancel() _ = ca.Close() @@ -110,7 +110,7 @@ func TestContextConfig(t *testing.T) { f: func() (func() (net.Conn, error), func()) { ca, _ := dpipe.Pipe() return func() (net.Conn, error) { - return Server(util.FromConn(ca), ca.RemoteAddr(), config) + return Server(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) }, func() { _ = ca.Close() } @@ -122,7 +122,7 @@ func TestContextConfig(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond) ca, _ := dpipe.Pipe() return func() (net.Conn, error) { - return ServerWithContext(ctx, util.FromConn(ca), ca.RemoteAddr(), config) + return ServerWithContext(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) }, func() { cancel() _ = ca.Close() diff --git a/conn_test.go b/conn_test.go index 4ec47571b..447526841 100644 --- a/conn_test.go +++ b/conn_test.go @@ -25,12 +25,12 @@ import ( "time" "github.com/pion/dtls/v2/internal/ciphersuite" - "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/crypto/elliptic" "github.com/pion/dtls/v2/pkg/crypto/hash" "github.com/pion/dtls/v2/pkg/crypto/selfsign" "github.com/pion/dtls/v2/pkg/crypto/signature" "github.com/pion/dtls/v2/pkg/crypto/signaturehash" + dtlsnet "github.com/pion/dtls/v2/pkg/net" "github.com/pion/dtls/v2/pkg/protocol" "github.com/pion/dtls/v2/pkg/protocol/alert" "github.com/pion/dtls/v2/pkg/protocol/extension" @@ -266,12 +266,12 @@ func pipeConn(ca, cb net.Conn) (*Conn, *Conn, error) { // Setup client go func() { - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}}, true) + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}}, true) c <- result{client, err} }() // Setup server - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}}, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}}, true) if err != nil { return nil, nil, err } @@ -385,11 +385,11 @@ func TestHandshakeWithAlert(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - _, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), testCase.configClient, true) + _, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), testCase.configClient, true) clientErr <- err }() - _, errServer := testServer(ctx, util.FromConn(cb), ca.RemoteAddr(), testCase.configServer, true) + _, errServer := testServer(ctx, dtlsnet.PacketConnFromConn(cb), ca.RemoteAddr(), testCase.configServer, true) if !errors.Is(errServer, testCase.errServer) { t.Fatalf("Server error exp(%v) failed(%v)", testCase.errServer, errServer) } @@ -552,7 +552,7 @@ func TestPSK(t *testing.T) { VerifyConnection: test.ClientVerifyConnection, } - c, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), conf, false) + c, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), conf, false) clientRes <- result{c, err} }() @@ -568,7 +568,7 @@ func TestPSK(t *testing.T) { VerifyConnection: test.ServerVerifyConnection, } - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, false) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, false) if test.WantFail { res := <-clientRes if err == nil || !strings.Contains(err.Error(), test.ExpectedServerErr) { @@ -627,7 +627,7 @@ func TestPSKHintFail(t *testing.T) { CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, } - _, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), conf, false) + _, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), conf, false) clientErr <- err }() @@ -639,7 +639,7 @@ func TestPSKHintFail(t *testing.T) { CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, } - if _, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, false); !errors.Is(err, serverAlertError) { + if _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, false); !errors.Is(err, serverAlertError) { t.Fatalf("TestPSK: Server error exp(%v) failed(%v)", serverAlertError, err) } @@ -666,7 +666,7 @@ func TestClientTimeout(t *testing.T) { go func() { conf := &Config{} - c, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), conf, true) + c, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), conf, true) if err == nil { _ = c.Close() //nolint:contextcheck } @@ -754,11 +754,11 @@ func TestSRTPConfiguration(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ClientSRTP}, true) + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ClientSRTP}, true) c <- result{client, err} }() - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ServerSRTP}, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ServerSRTP}, true) if !errors.Is(err, test.WantServerError) { t.Errorf("TestSRTPConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantServerError, err) } @@ -962,11 +962,11 @@ func TestClientCertificate(t *testing.T) { c := make(chan result) go func() { - client, err := Client(util.FromConn(ca), ca.RemoteAddr(), tt.clientCfg) + client, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), tt.clientCfg) c <- result{client, err} }() - server, err := Server(util.FromConn(cb), cb.RemoteAddr(), tt.serverCfg) + server, err := Server(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), tt.serverCfg) res := <-c defer func() { if err == nil { @@ -1119,11 +1119,11 @@ func TestConnectionID(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), tt.clientCfg, true) + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), tt.clientCfg, true) c <- result{client, err} }() - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), tt.serverCfg, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), tt.serverCfg, true) if err != nil { t.Fatalf("Unexpected server error: %v", err) } @@ -1272,11 +1272,11 @@ func TestExtendedMasterSecret(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), tt.clientCfg, true) + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), tt.clientCfg, true) c <- result{client, err} }() - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), tt.serverCfg, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), tt.serverCfg, true) res := <-c defer func() { if err == nil { @@ -1382,11 +1382,11 @@ func TestServerCertificate(t *testing.T) { } srvCh := make(chan result) go func() { - s, err := Server(util.FromConn(cb), cb.RemoteAddr(), tt.serverCfg) + s, err := Server(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), tt.serverCfg) srvCh <- result{s, err} }() - cli, err := Client(util.FromConn(ca), ca.RemoteAddr(), tt.clientCfg) + cli, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), tt.clientCfg) if err == nil { _ = cli.Close() } @@ -1486,11 +1486,11 @@ func TestCipherSuiteConfiguration(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: test.ClientCipherSuites}, true) + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: test.ClientCipherSuites}, true) c <- result{client, err} }() - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{CipherSuites: test.ServerCipherSuites}, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{CipherSuites: test.ServerCipherSuites}, true) if err == nil { defer func() { _ = server.Close() @@ -1555,7 +1555,7 @@ func TestCertificateAndPSKServer(t *testing.T) { config.CipherSuites = []CipherSuiteID{TLS_PSK_WITH_AES_128_GCM_SHA256} } - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), config, false) + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config, false) c <- result{client, err} }() @@ -1566,7 +1566,7 @@ func TestCertificateAndPSKServer(t *testing.T) { }, } - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, true) if err == nil { defer func() { _ = server.Close() @@ -1658,11 +1658,11 @@ func TestPSKConfiguration(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{PSK: test.ClientPSK, PSKIdentityHint: test.ClientPSKIdentity}, test.ClientHasCertificate) + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{PSK: test.ClientPSK, PSKIdentityHint: test.ClientPSKIdentity}, test.ClientHasCertificate) c <- result{client, err} }() - _, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{PSK: test.ServerPSK, PSKIdentityHint: test.ServerPSKIdentity}, test.ServerHasCertificate) + _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{PSK: test.ServerPSK, PSKIdentityHint: test.ServerPSKIdentity}, test.ServerHasCertificate) if err != nil || test.WantServerError != nil { if !(err != nil && test.WantServerError != nil && err.Error() == test.WantServerError.Error()) { t.Fatalf("TestPSKConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantServerError, err) @@ -1792,7 +1792,7 @@ func TestServerTimeout(t *testing.T) { FlightInterval: 100 * time.Millisecond, } - _, serverErr := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true) + _, serverErr := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, true) var netErr net.Error if !errors.As(serverErr, &netErr) || !netErr.Timeout() { t.Fatalf("Client error exp(Temporary network error) failed(%v)", serverErr) @@ -1907,7 +1907,7 @@ func TestProtocolVersionValidation(t *testing.T) { defer wg.Wait() go func() { defer wg.Done() - if _, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true); !errors.Is(err, errUnsupportedProtocolVersion) { + if _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, true); !errors.Is(err, errUnsupportedProtocolVersion) { t.Errorf("Client error exp(%v) failed(%v)", errUnsupportedProtocolVersion, err) } }() @@ -1997,7 +1997,7 @@ func TestProtocolVersionValidation(t *testing.T) { defer wg.Wait() go func() { defer wg.Done() - if _, err := testClient(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true); !errors.Is(err, errUnsupportedProtocolVersion) { + if _, err := testClient(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, true); !errors.Is(err, errUnsupportedProtocolVersion) { t.Errorf("Server error exp(%v) failed(%v)", errUnsupportedProtocolVersion, err) } }() @@ -2095,7 +2095,7 @@ func TestMultipleHelloVerifyRequest(t *testing.T) { defer wg.Wait() go func() { defer wg.Done() - _, _ = testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{}, false) + _, _ = testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{}, false) }() for i, cookie := range cookies { @@ -2167,7 +2167,7 @@ func TestRenegotationInfo(t *testing.T) { defer cancel() go func() { - if _, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{}, true); !errors.Is(err, context.Canceled) { + if _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{}, true); !errors.Is(err, context.Canceled) { t.Error(err) } }() @@ -2279,7 +2279,7 @@ func TestServerNameIndicationExtension(t *testing.T) { ServerName: test.ServerName, } - _, _ = testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), conf, false) + _, _ = testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), conf, false) }() // Receive ClientHello @@ -2397,7 +2397,7 @@ func TestALPNExtension(t *testing.T) { conf := &Config{ SupportedProtocols: test.ClientProtocolNameList, } - _, _ = testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), conf, false) + _, _ = testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), conf, false) }() // Receive ClientHello @@ -2415,7 +2415,7 @@ func TestALPNExtension(t *testing.T) { conf := &Config{ SupportedProtocols: test.ServerProtocolNameList, } - if _, err2 := testServer(ctx2, util.FromConn(cb2), cb2.RemoteAddr(), conf, true); !errors.Is(err2, context.Canceled) { + if _, err2 := testServer(ctx2, dtlsnet.PacketConnFromConn(cb2), cb2.RemoteAddr(), conf, true); !errors.Is(err2, context.Canceled) { if test.ExpectAlertFromServer { //nolint // Assert the error type? } else { @@ -2562,7 +2562,7 @@ func TestSupportedGroupsExtension(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - if _, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{}, true); !errors.Is(err, context.Canceled) { + if _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{}, true); !errors.Is(err, context.Canceled) { t.Error(err) } }() @@ -2671,7 +2671,7 @@ func TestSessionResume(t *testing.T) { SessionStore: ss, MTU: 100, } - c, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), config, false) + c, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config, false) clientRes <- result{c, err} }() @@ -2681,7 +2681,7 @@ func TestSessionResume(t *testing.T) { SessionStore: ss, MTU: 100, } - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, true) if err != nil { t.Fatalf("TestSessionResume: Server failed(%v)", err) } @@ -2725,14 +2725,14 @@ func TestSessionResume(t *testing.T) { ServerName: "example.com", SessionStore: s1, } - c, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), config, false) + c, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config, false) clientRes <- result{c, err} }() config := &Config{ SessionStore: s2, } - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), config, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, true) if err != nil { t.Fatalf("TestSessionResumetion: Server failed(%v)", err) } @@ -2830,7 +2830,7 @@ func TestCipherSuiteMatchesCertificateType(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - c, err := testClient(context.TODO(), util.FromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: test.cipherList}, false) + c, err := testClient(context.TODO(), dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: test.cipherList}, false) clientErr <- err client <- c }() @@ -2855,7 +2855,7 @@ func TestCipherSuiteMatchesCertificateType(t *testing.T) { t.Fatal(err) } - if s, err := testServer(context.TODO(), util.FromConn(cb), cb.RemoteAddr(), &Config{ + if s, err := testServer(context.TODO(), dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ CipherSuites: test.cipherList, Certificates: []tls.Certificate{serverCert}, }, false); err != nil { @@ -2920,7 +2920,7 @@ func TestMultipleServerCertificates(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - c, err := testClient(context.TODO(), util.FromConn(ca), ca.RemoteAddr(), &Config{ + c, err := testClient(context.TODO(), dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ RootCAs: caPool, ServerName: test.RequestServerName, VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { @@ -2940,7 +2940,7 @@ func TestMultipleServerCertificates(t *testing.T) { client <- c }() - if s, err := testServer(context.TODO(), util.FromConn(cb), cb.RemoteAddr(), &Config{Certificates: []tls.Certificate{fooCert, barCert}}, false); err != nil { + if s, err := testServer(context.TODO(), dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{Certificates: []tls.Certificate{fooCert, barCert}}, false); err != nil { t.Fatal(err) } else if err = s.Close(); err != nil { t.Fatal(err) @@ -2992,11 +2992,11 @@ func TestEllipticCurveConfiguration(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, EllipticCurves: test.ConfigCurves}, true) + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, EllipticCurves: test.ConfigCurves}, true) c <- result{client, err} }() - server, err := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, EllipticCurves: test.ConfigCurves}, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, EllipticCurves: test.ConfigCurves}, true) if err != nil { t.Fatalf("Server error: %v", err) } @@ -3048,7 +3048,7 @@ func TestSkipHelloVerify(t *testing.T) { gotHello := make(chan struct{}) go func() { - server, sErr := testServer(ctx, util.FromConn(cb), cb.RemoteAddr(), &Config{ + server, sErr := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ Certificates: []tls.Certificate{certificate}, LoggerFactory: logging.NewDefaultLoggerFactory(), InsecureSkipVerifyHello: true, @@ -3067,7 +3067,7 @@ func TestSkipHelloVerify(t *testing.T) { } }() - client, err := testClient(ctx, util.FromConn(ca), ca.RemoteAddr(), &Config{ + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ LoggerFactory: logging.NewDefaultLoggerFactory(), InsecureSkipVerify: true, }, false) diff --git a/e2e/e2e_lossy_test.go b/e2e/e2e_lossy_test.go index c694287da..59231e893 100644 --- a/e2e/e2e_lossy_test.go +++ b/e2e/e2e_lossy_test.go @@ -11,8 +11,8 @@ import ( "time" "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/crypto/selfsign" + dtlsnet "github.com/pion/dtls/v2/pkg/net" transportTest "github.com/pion/transport/v2/test" ) @@ -145,7 +145,7 @@ func TestPionE2ELossy(t *testing.T) { cfg.Certificates = []tls.Certificate{clientCert} } - client, startupErr := dtls.Client(util.FromConn(br.GetConn0()), br.GetConn0().RemoteAddr(), cfg) + client, startupErr := dtls.Client(dtlsnet.PacketConnFromConn(br.GetConn0()), br.GetConn0().RemoteAddr(), cfg) clientDone <- runResult{client, startupErr} }() @@ -160,7 +160,7 @@ func TestPionE2ELossy(t *testing.T) { cfg.ClientAuth = dtls.RequireAnyClientCert } - server, startupErr := dtls.Server(util.FromConn(br.GetConn1()), br.GetConn1().RemoteAddr(), cfg) + server, startupErr := dtls.Server(dtlsnet.PacketConnFromConn(br.GetConn1()), br.GetConn1().RemoteAddr(), cfg) serverDone <- runResult{server, startupErr} }() diff --git a/resume_test.go b/resume_test.go index 740a44e6d..fe78e22e2 100644 --- a/resume_test.go +++ b/resume_test.go @@ -13,8 +13,8 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/crypto/selfsign" + dtlsnet "github.com/pion/dtls/v2/pkg/net" "github.com/pion/transport/v2/test" ) @@ -68,7 +68,7 @@ func DoTestResume(t *testing.T, newLocal, newRemote func(net.PacketConn, net.Add go func() { var remote *Conn var errR error - remote, errR = newRemote(util.FromConn(remoteConn), remoteConn.RemoteAddr(), config) + remote, errR = newRemote(dtlsnet.PacketConnFromConn(remoteConn), remoteConn.RemoteAddr(), config) if errR != nil { errChan <- errR } @@ -90,7 +90,7 @@ func DoTestResume(t *testing.T, newLocal, newRemote func(net.PacketConn, net.Add }() var local *Conn - local, err = newLocal(util.FromConn(localConn1), localConn1.RemoteAddr(), config) + local, err = newLocal(dtlsnet.PacketConnFromConn(localConn1), localConn1.RemoteAddr(), config) if err != nil { fatal(t, errChan, err) } @@ -133,7 +133,7 @@ func DoTestResume(t *testing.T, newLocal, newRemote func(net.PacketConn, net.Add // Resume dtls connection var resumed net.Conn - resumed, err = Resume(deserialized, util.FromConn(localConn2), localConn2.RemoteAddr(), config) + resumed, err = Resume(deserialized, dtlsnet.PacketConnFromConn(localConn2), localConn2.RemoteAddr(), config) if err != nil { fatal(t, errChan, err) } From eb305b11ed4fab49f0c2a1efe1ff48e1f09cdbc7 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:20:16 -0400 Subject: [PATCH 040/146] Introduce net PacketBuffer Introduce a network PacketBuffer which maintains a ring buffer of network packets constituted of the packet payload and the remote address from which it was received. This package borrows heavily from the bytes based ring buffer in pion/transport/packetio. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- internal/net/buffer.go | 235 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 internal/net/buffer.go diff --git a/internal/net/buffer.go b/internal/net/buffer.go new file mode 100644 index 000000000..9f101d454 --- /dev/null +++ b/internal/net/buffer.go @@ -0,0 +1,235 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +// Package net implements DTLS specific networking primitives. +// NOTE: this package is an adaption of pion/transport/packetio that allows for +// storing a remote address alongside each packet in the buffer and implements +// relevant methods of net.PacketConn. If possible, the updates made in this +// repository will be reflected back upstream. If not, it is likely that this +// will be moved to a public package in this repository. +// +// This package was migrated from pion/transport/packetio at +// https://github.com/pion/transport/commit/6890c795c807a617c054149eee40a69d7fdfbfdb +package net + +import ( + "bytes" + "errors" + "io" + "net" + "sync" + "time" + + "github.com/pion/transport/v2/deadline" +) + +// ErrTimeout indicates that deadline was reached before operation could be +// completed. +var ErrTimeout = errors.New("buffer: i/o timeout") + +// AddrPacket is a packet payload and the associated remote address from which +// it was received. +type AddrPacket struct { + addr net.Addr + data bytes.Buffer +} + +// PacketBuffer is a circular buffer for network packets. Each slot in the +// buffer contains the remote address from which the packet was received, as +// well as the packet data. +type PacketBuffer struct { + mutex sync.Mutex + + packets []AddrPacket + write, read int + + // full indicates whether the buffer is full, which is needed to distinguish + // when the write pointer and read pointer are at the same index. + full bool + + notify chan struct{} + closed bool + + readDeadline *deadline.Deadline +} + +// NewPacketBuffer creates a new PacketBuffer. +func NewPacketBuffer() *PacketBuffer { + return &PacketBuffer{ + readDeadline: deadline.New(), + // In the narrow context in which this package is currently used, there + // will always be at least one packet written to the buffer. Therefore, + // we opt to allocate with size of 1 during construction, rather than + // waiting until that first packet is written. + packets: make([]AddrPacket, 1), + full: false, + } +} + +// WriteTo writes a single packet to the buffer. The supplied address will +// remain associated with the packet. +func (b *PacketBuffer) WriteTo(p []byte, addr net.Addr) (int, error) { + b.mutex.Lock() + + if b.closed { + b.mutex.Unlock() + return 0, io.ErrClosedPipe + } + + var notify chan struct{} + if b.notify != nil { + notify = b.notify + b.notify = nil + } + + // Check to see if we are full. + if b.full { + // If so, grow AddrPacket buffer. + var newSize int + if len(b.packets) < 128 { + // Double the number of packets. + newSize = len(b.packets) * 2 + } else { + // Increase the number of packets by 25%. + newSize = 5 * len(b.packets) / 4 + } + newBuf := make([]AddrPacket, newSize) + var n int + if b.read < b.write { + n = copy(newBuf, b.packets[b.read:b.write]) + } else { + n = copy(newBuf, b.packets[b.read:]) + n += copy(newBuf[n:], b.packets[:b.write]) + } + + b.packets = newBuf + + // Update write pointer to point to new location and mark buffer as not + // full. + b.write = n + b.full = false + } + + // Store the packet at the write pointer. + packet := &b.packets[b.write] + packet.data.Reset() + n, err := packet.data.Write(p) + if err != nil { + b.mutex.Unlock() + return n, err + } + packet.addr = addr + + // Increment write pointer. + b.write++ + + // If the write pointer is equal to the length of the buffer, wrap around. + if len(b.packets) == b.write { + b.write = 0 + } + + // If a write resulted in making write and read pointers equivalent, then we + // are full. + if b.write == b.read { + b.full = true + } + + b.mutex.Unlock() + + if notify != nil { + close(notify) + } + + return n, nil +} + +// ReadFrom reads a single packet from the buffer, or blocks until one is +// available. +func (b *PacketBuffer) ReadFrom(packet []byte) (n int, addr net.Addr, err error) { + select { + case <-b.readDeadline.Done(): + return 0, nil, ErrTimeout + default: + } + + for { + b.mutex.Lock() + + if b.read != b.write || b.full { + ap := b.packets[b.read] + if len(packet) < ap.data.Len() { + b.mutex.Unlock() + return 0, nil, io.ErrShortBuffer + } + + // Copy packet data from buffer. + n, err := ap.data.Read(packet) + if err != nil { + b.mutex.Unlock() + return n, nil, err + } + + // Advance read pointer. + b.read++ + if len(b.packets) == b.read { + b.read = 0 + } + + // If we were full before reading and have successfully read, we are + // no longer full. + if b.full { + b.full = false + } + + b.mutex.Unlock() + + return n, ap.addr, nil + } + + if b.closed { + b.mutex.Unlock() + return 0, nil, io.EOF + } + + if b.notify == nil { + b.notify = make(chan struct{}) + } + notify := b.notify + b.mutex.Unlock() + + select { + case <-b.readDeadline.Done(): + return 0, nil, ErrTimeout + case <-notify: + } + } +} + +// Close closes the buffer, allowing unread packets to be read, but erroring on +// any new writes. +func (b *PacketBuffer) Close() (err error) { + b.mutex.Lock() + + if b.closed { + b.mutex.Unlock() + return nil + } + + notify := b.notify + b.notify = nil + b.closed = true + + b.mutex.Unlock() + + if notify != nil { + close(notify) + } + + return nil +} + +// SetReadDeadline sets the read deadline for the buffer. +func (b *PacketBuffer) SetReadDeadline(t time.Time) error { + b.readDeadline.Set(t) + return nil +} From 3afeb7df87fb7bd8c92ec785b9b9c4914e8f2eef Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:21:28 -0400 Subject: [PATCH 041/146] Add PacketBuffer unit tests Adds PacketBuffer unit tests. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- internal/net/buffer_test.go | 345 ++++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 internal/net/buffer_test.go diff --git a/internal/net/buffer_test.go b/internal/net/buffer_test.go new file mode 100644 index 000000000..8a9cd6180 --- /dev/null +++ b/internal/net/buffer_test.go @@ -0,0 +1,345 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +// Package net implements DTLS specific networking primitives. +package net + +import ( + "bytes" + "errors" + "io" + "net" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestBuffer(t *testing.T) { + assert := assert.New(t) + + buffer := NewPacketBuffer() + packet := make([]byte, 4) + addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") + assert.NoError(err) + + // Write once. + n, err := buffer.WriteTo([]byte{0, 1}, addr) + assert.NoError(err) + assert.Equal(2, n) + + // Read once. + var raddr net.Addr + n, raddr, err = buffer.ReadFrom(packet) + assert.NoError(err) + assert.Equal(2, n) + assert.Equal([]byte{0, 1}, packet[:n]) + assert.Equal(addr, raddr) + + // Read deadline. + err = buffer.SetReadDeadline(time.Unix(0, 1)) + assert.NoError(err) + n, raddr, err = buffer.ReadFrom(packet) + assert.EqualError(err, ErrTimeout.Error()) + assert.Equal(0, n) + assert.Equal(nil, raddr) + + // Reset deadline. + err = buffer.SetReadDeadline(time.Time{}) + assert.NoError(err) + + // Write twice. + n, err = buffer.WriteTo([]byte{2, 3, 4}, addr) + assert.NoError(err) + assert.Equal(3, n) + + n, err = buffer.WriteTo([]byte{5, 6, 7}, addr) + assert.NoError(err) + assert.Equal(3, n) + + // Read twice. + n, raddr, err = buffer.ReadFrom(packet) + assert.NoError(err) + assert.Equal(3, n) + assert.Equal([]byte{2, 3, 4}, packet[:n]) + assert.Equal(addr, raddr) + + n, raddr, err = buffer.ReadFrom(packet) + assert.NoError(err) + assert.Equal(3, n) + assert.Equal([]byte{5, 6, 7}, packet[:n]) + assert.Equal(addr, raddr) + + // Write once prior to close. + _, err = buffer.WriteTo([]byte{3}, addr) + assert.NoError(err) + + // Close. + assert.NoError(buffer.Close()) + + // Future writes will error. + _, err = buffer.WriteTo([]byte{4}, addr) + assert.Error(err) + + // But we can read the remaining data. + n, raddr, err = buffer.ReadFrom(packet) + assert.NoError(err) + assert.Equal(1, n) + assert.Equal([]byte{3}, packet[:n]) + assert.Equal(addr, raddr) + + // Until EOF. + _, _, err = buffer.ReadFrom(packet) + assert.Equal(io.EOF, err) +} + +func TestShortBuffer(t *testing.T) { + assert := assert.New(t) + + buffer := NewPacketBuffer() + addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") + assert.NoError(err) + + // Write once. + n, err := buffer.WriteTo([]byte{0, 1, 2, 3}, addr) + assert.NoError(err) + assert.Equal(4, n) + + // Try to read with a short buffer. + packet := make([]byte, 3) + var raddr net.Addr + n, raddr, err = buffer.ReadFrom(packet) + assert.Equal(io.ErrShortBuffer, err) + assert.Equal(nil, raddr) + assert.Equal(0, n) + + // Close. + assert.NoError(buffer.Close()) + + // Make sure you can Close twice. + assert.NoError(buffer.Close()) +} + +func TestWraparound(t *testing.T) { + assert := assert.New(t) + + buffer := NewPacketBuffer() + addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") + assert.NoError(err) + + // Write multiple. + n, err := buffer.WriteTo([]byte{0, 1, 2, 3}, addr) + assert.NoError(err) + assert.Equal(4, n) + + n, err = buffer.WriteTo([]byte{4, 5}, addr) + assert.NoError(err) + assert.Equal(2, n) + + n, err = buffer.WriteTo([]byte{6, 7, 8}, addr) + assert.NoError(err) + assert.Equal(3, n) + + // Verify underlying buffer length. + // Packet 1: buffer does not grow. + // Packet 2: buffer doubles from 1 to 2. + // Packet 3: buffer doubles from 2 to 4. + assert.Equal(4, len(buffer.packets)) + + // Read once. + packet := make([]byte, 4) + var raddr net.Addr + n, raddr, err = buffer.ReadFrom(packet) + assert.NoError(err) + assert.Equal(4, n) + assert.Equal([]byte{0, 1, 2, 3}, packet[:n]) + assert.Equal(addr, raddr) + + // Write again. + n, err = buffer.WriteTo([]byte{9, 10, 11}, addr) + assert.NoError(err) + assert.Equal(3, n) + + // Verify underlying buffer length. + // No change in buffer size. + assert.Equal(4, len(buffer.packets)) + + // Write again and verify buffer grew. + n, err = buffer.WriteTo([]byte{12, 13, 14, 15, 16, 17, 18, 19}, addr) + assert.NoError(err) + assert.Equal(8, n) + assert.Equal(4, len(buffer.packets)) + + // Close. + assert.NoError(buffer.Close()) +} + +func TestBufferAsync(t *testing.T) { + assert := assert.New(t) + + buffer := NewPacketBuffer() + addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") + assert.NoError(err) + + // Start up a goroutine to start a blocking read. + done := make(chan struct{}) + go func() { + packet := make([]byte, 4) + + n, raddr, rErr := buffer.ReadFrom(packet) + assert.NoError(rErr) + assert.Equal(2, n) + assert.Equal([]byte{0, 1}, packet[:n]) + assert.Equal(addr, raddr) + + _, _, err = buffer.ReadFrom(packet) + assert.Equal(io.EOF, err) + + close(done) + }() + + // Wait for the reader to start reading. + time.Sleep(time.Millisecond) + + // Write once + n, err := buffer.WriteTo([]byte{0, 1}, addr) + assert.NoError(err) + assert.Equal(2, n) + + // Wait for the reader to start reading again. + time.Sleep(time.Millisecond) + + // Close will unblock the reader. + assert.NoError(buffer.Close()) + + <-done +} + +func benchmarkBufferWR(b *testing.B, size int64, write bool, grow int) { // nolint:unparam + addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") + if err != nil { + b.Fatalf("net.ResolveUDPAddr: %v", err) + } + buffer := NewPacketBuffer() + packet := make([]byte, size) + + // Grow the buffer first + pad := make([]byte, 1022) + for len(buffer.packets) < grow { + if _, err := buffer.WriteTo(pad, addr); err != nil { + b.Fatalf("Write: %v", err) + } + } + for buffer.read != buffer.write { + if _, _, err := buffer.ReadFrom(pad); err != nil { + b.Fatalf("ReadFrom: %v", err) + } + } + + if write { + if _, err := buffer.WriteTo(packet, addr); err != nil { + b.Fatalf("Write: %v", err) + } + } + + b.SetBytes(size) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + if _, err := buffer.WriteTo(packet, addr); err != nil { + b.Fatalf("Write: %v", err) + } + if _, _, err := buffer.ReadFrom(packet); err != nil { + b.Fatalf("Write: %v", err) + } + } +} + +// In this benchmark, the buffer is often empty, which is hopefully +// typical of real usage. +func BenchmarkBufferWR14(b *testing.B) { + benchmarkBufferWR(b, 14, false, 128) +} + +func BenchmarkBufferWR140(b *testing.B) { + benchmarkBufferWR(b, 140, false, 128) +} + +func BenchmarkBufferWR1400(b *testing.B) { + benchmarkBufferWR(b, 1400, false, 128) +} + +// Here, the buffer never becomes empty, which forces wraparound +func BenchmarkBufferWWR14(b *testing.B) { + benchmarkBufferWR(b, 14, true, 128) +} + +func BenchmarkBufferWWR140(b *testing.B) { + benchmarkBufferWR(b, 140, true, 128) +} + +func BenchmarkBufferWWR1400(b *testing.B) { + benchmarkBufferWR(b, 1400, true, 128) +} + +func benchmarkBuffer(b *testing.B, size int64) { + addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") + if err != nil { + b.Fatalf("net.ResolveUDPAddr: %v", err) + } + buffer := NewPacketBuffer() + b.SetBytes(size) + + done := make(chan struct{}) + go func() { + packet := make([]byte, size) + + for { + _, _, err := buffer.ReadFrom(packet) + if errors.Is(err, io.EOF) { + break + } else if err != nil { + b.Error(err) + break + } + } + + close(done) + }() + + packet := make([]byte, size) + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + var err error + for { + _, err = buffer.WriteTo(packet, addr) + if !errors.Is(err, bytes.ErrTooLarge) { + break + } + time.Sleep(time.Microsecond) + } + if err != nil { + b.Fatal(err) + } + } + + if err := buffer.Close(); err != nil { + b.Fatal(err) + } + + <-done +} + +func BenchmarkBuffer14(b *testing.B) { + benchmarkBuffer(b, 14) +} + +func BenchmarkBuffer140(b *testing.B) { + benchmarkBuffer(b, 140) +} + +func BenchmarkBuffer1400(b *testing.B) { + benchmarkBuffer(b, 1400) +} From 71db42bb7dee6ce23d6e59b4de69b525b4dafd9d Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:21:55 -0400 Subject: [PATCH 042/146] Introduce UDP net.PacketListener Introduces a UDP based net.PacketListener that allows for routing UDP datagrams based on remote address _or_ an alternate identifier. It is configured by the DatagramRouter and ConnectionIdentifier functions, which are provided by the caller. The former introspects outgoing datagrams for potential connection identifiers, while the latter routes incoming datagrams by introspecting their contents. This package borrows heavily from pion/transport/udp. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- internal/net/udp/packet_conn.go | 407 ++++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 internal/net/udp/packet_conn.go diff --git a/internal/net/udp/packet_conn.go b/internal/net/udp/packet_conn.go new file mode 100644 index 000000000..b32306c5a --- /dev/null +++ b/internal/net/udp/packet_conn.go @@ -0,0 +1,407 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +// Package udp implements DTLS specific UDP networking primitives. +// NOTE: this package is an adaption of pion/transport/udp that allows for +// routing datagrams based on identifiers other than the remote address. The +// primary use case for this functionality is routing based on DTLS connection +// IDs. In order to allow for consumers of this package to treat connections as +// generic net.PackageConn, routing and identitier establishment is based on +// custom introspecion of datagrams, rather than direct intervention by +// consumers. If possible, the updates made in this repository will be reflected +// back upstream. If not, it is likely that this will be moved to a public +// package in this repository. +// +// This package was migrated from pion/transport/udp at +// https://github.com/pion/transport/commit/6890c795c807a617c054149eee40a69d7fdfbfdb +package udp + +import ( + "context" + "errors" + "net" + "sync" + "sync/atomic" + "time" + + idtlsnet "github.com/pion/dtls/v2/internal/net" + dtlsnet "github.com/pion/dtls/v2/pkg/net" + "github.com/pion/transport/v2/deadline" +) + +const ( + receiveMTU = 8192 + defaultListenBacklog = 128 // same as Linux default +) + +// Typed errors +var ( + ErrClosedListener = errors.New("udp: listener closed") + ErrListenQueueExceeded = errors.New("udp: listen queue exceeded") +) + +// listener augments a connection-oriented Listener over a UDP PacketConn +type listener struct { + pConn *net.UDPConn + + accepting atomic.Value // bool + acceptCh chan *PacketConn + doneCh chan struct{} + doneOnce sync.Once + acceptFilter func([]byte) bool + datagramRouter func([]byte) (string, bool) + connIdentifier func([]byte) (string, bool) + + connLock sync.Mutex + conns map[string]*PacketConn + connWG sync.WaitGroup + + readWG sync.WaitGroup + errClose atomic.Value // error + + readDoneCh chan struct{} + errRead atomic.Value // error +} + +// Accept waits for and returns the next connection to the listener. +func (l *listener) Accept() (net.PacketConn, net.Addr, error) { + select { + case c := <-l.acceptCh: + l.connWG.Add(1) + return c, c.raddr, nil + + case <-l.readDoneCh: + err, _ := l.errRead.Load().(error) + return nil, nil, err + + case <-l.doneCh: + return nil, nil, ErrClosedListener + } +} + +// Close closes the listener. +// Any blocked Accept operations will be unblocked and return errors. +func (l *listener) Close() error { + var err error + l.doneOnce.Do(func() { + l.accepting.Store(false) + close(l.doneCh) + + l.connLock.Lock() + // Close unaccepted connections + lclose: + for { + select { + case c := <-l.acceptCh: + close(c.doneCh) + // If we have an alternate identifier, remove it from the connection + // map. + if id := c.id.Load(); id != nil { + delete(l.conns, id.(string)) //nolint:forcetypeassert + } + // If we haven't already removed the remote address, remove it + // from the connection map. + if !c.rmraddr.Load() { + delete(l.conns, c.raddr.String()) + c.rmraddr.Store(true) + } + default: + break lclose + } + } + nConns := len(l.conns) + l.connLock.Unlock() + + l.connWG.Done() + + if nConns == 0 { + // Wait if this is the final connection. + l.readWG.Wait() + if errClose, ok := l.errClose.Load().(error); ok { + err = errClose + } + } else { + err = nil + } + }) + + return err +} + +// Addr returns the listener's network address. +func (l *listener) Addr() net.Addr { + return l.pConn.LocalAddr() +} + +// ListenConfig stores options for listening to an address. +type ListenConfig struct { + // Backlog defines the maximum length of the queue of pending + // connections. It is equivalent of the backlog argument of + // POSIX listen function. + // If a connection request arrives when the queue is full, + // the request will be silently discarded, unlike TCP. + // Set zero to use default value 128 which is same as Linux default. + Backlog int + + // AcceptFilter determines whether the new conn should be made for + // the incoming packet. If not set, any packet creates new conn. + AcceptFilter func([]byte) bool + + // DatagramRouter routes an incoming datagram to a connection by extracting + // an identifier from the its paylod + DatagramRouter func([]byte) (string, bool) + + // ConnectionIdentifier extracts an identifier from an outgoing packet. If + // the identifier is not already associated with the connection, it will be + // added. + ConnectionIdentifier func([]byte) (string, bool) +} + +// Listen creates a new listener based on the ListenConfig. +func (lc *ListenConfig) Listen(network string, laddr *net.UDPAddr) (dtlsnet.PacketListener, error) { + if lc.Backlog == 0 { + lc.Backlog = defaultListenBacklog + } + + conn, err := net.ListenUDP(network, laddr) + if err != nil { + return nil, err + } + + l := &listener{ + pConn: conn, + acceptCh: make(chan *PacketConn, lc.Backlog), + conns: make(map[string]*PacketConn), + doneCh: make(chan struct{}), + acceptFilter: lc.AcceptFilter, + datagramRouter: lc.DatagramRouter, + connIdentifier: lc.ConnectionIdentifier, + readDoneCh: make(chan struct{}), + } + + l.accepting.Store(true) + l.connWG.Add(1) + l.readWG.Add(2) // wait readLoop and Close execution routine + + go l.readLoop() + go func() { + l.connWG.Wait() + if err := l.pConn.Close(); err != nil { + l.errClose.Store(err) + } + l.readWG.Done() + }() + + return l, nil +} + +// Listen creates a new listener using default ListenConfig. +func Listen(network string, laddr *net.UDPAddr) (dtlsnet.PacketListener, error) { + return (&ListenConfig{}).Listen(network, laddr) +} + +// readLoop dispatches packets to the proper connection, creating a new one if +// necessary, until all connections are closed. +func (l *listener) readLoop() { + defer l.readWG.Done() + defer close(l.readDoneCh) + + buf := make([]byte, receiveMTU) + + for { + n, raddr, err := l.pConn.ReadFrom(buf) + if err != nil { + l.errRead.Store(err) + return + } + conn, ok, err := l.getConn(raddr, buf[:n]) + if err != nil { + continue + } + if ok { + _, _ = conn.buffer.WriteTo(buf[:n], raddr) + } + } +} + +// getConn gets an existing connection or creates a new one. +func (l *listener) getConn(raddr net.Addr, buf []byte) (*PacketConn, bool, error) { + l.connLock.Lock() + defer l.connLock.Unlock() + // If we have a custom resolver, use it. + if l.datagramRouter != nil { + if id, ok := l.datagramRouter(buf); ok { + if conn, ok := l.conns[id]; ok { + return conn, true, nil + } + } + } + + // If we don't have a custom resolver, or we were unable to find an + // associated connection, fall back to remote address. + conn, ok := l.conns[raddr.String()] + if !ok { + if isAccepting, ok := l.accepting.Load().(bool); !isAccepting || !ok { + return nil, false, ErrClosedListener + } + if l.acceptFilter != nil { + if !l.acceptFilter(buf) { + return nil, false, nil + } + } + conn = l.newPacketConn(raddr) + select { + case l.acceptCh <- conn: + l.conns[raddr.String()] = conn + default: + return nil, false, ErrListenQueueExceeded + } + } + return conn, true, nil +} + +// PacketConn is a net.PacketConn implementation that is able to dictate its +// routing ID via an alternate identifier from its remote address. Internal +// buffering is performed for reads, and writes are passed through to the +// underlying net.PacketConn. +type PacketConn struct { + listener *listener + + raddr net.Addr + rmraddr atomic.Bool + id atomic.Value + + buffer *idtlsnet.PacketBuffer + + doneCh chan struct{} + doneOnce sync.Once + + writeDeadline *deadline.Deadline +} + +// newPacketConn constructs a new PacketConn. +func (l *listener) newPacketConn(raddr net.Addr) *PacketConn { + return &PacketConn{ + listener: l, + raddr: raddr, + buffer: idtlsnet.NewPacketBuffer(), + doneCh: make(chan struct{}), + writeDeadline: deadline.New(), + } +} + +// ReadFrom reads a single packet payload and its associated remote address from +// the underlying buffer. +func (c *PacketConn) ReadFrom(p []byte) (int, net.Addr, error) { + return c.buffer.ReadFrom(p) +} + +// WriteTo writes len(p) bytes from p to the specified address. +func (c *PacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { + // If we have a connection identifier, check to see if the outgoing packet + // sets it. + if c.listener.connIdentifier != nil { + id := c.id.Load() + // Only update establish identifier if we haven't already done so. + if id == nil { + candidate, ok := c.listener.connIdentifier(p) + // If we have an identifier, add entry to connection map. + if ok { + c.listener.connLock.Lock() + c.listener.conns[candidate] = c + c.listener.connLock.Unlock() + c.id.Store(candidate) + } + } + // If we are writing to a remote address that differs from the initial, + // we have an alternate identifier established, and we haven't already + // freed the remote address, free the remote address to be used by + // another connection. + // Note: this strategy results in holding onto a remote address after it + // is potentially no longer in use by the client. However, releasing + // earlier means that we could miss some packets that should have been + // routed to this connection. Ideally, we would drop the connection + // entry for the remote address as soon as the client starts sending + // using an alternate identifier, but in practice this proves + // challenging because any client could spoof a connection identifier, + // resulting in the remote address entry being dropped prior to the + // "real" client transitioning to sending using the alternate + // identifier. + if id != nil && !c.rmraddr.Load() && addr.String() != c.raddr.String() { + c.listener.connLock.Lock() + delete(c.listener.conns, c.raddr.String()) + c.rmraddr.Store(true) + c.listener.connLock.Unlock() + } + } + + select { + case <-c.writeDeadline.Done(): + return 0, context.DeadlineExceeded + default: + } + return c.listener.pConn.WriteTo(p, addr) +} + +// Close closes the conn and releases any Read calls +func (c *PacketConn) Close() error { + var err error + c.doneOnce.Do(func() { + c.listener.connWG.Done() + close(c.doneCh) + c.listener.connLock.Lock() + // If we have an alternate identifier, remove it from the connection + // map. + if id := c.id.Load(); id != nil { + delete(c.listener.conns, id.(string)) //nolint:forcetypeassert + } + // If we haven't already removed the remote address, remove it from the + // connection map. + if !c.rmraddr.Load() { + delete(c.listener.conns, c.raddr.String()) + c.rmraddr.Store(true) + } + nConns := len(c.listener.conns) + c.listener.connLock.Unlock() + + if isAccepting, ok := c.listener.accepting.Load().(bool); nConns == 0 && !isAccepting && ok { + // Wait if this is the final connection + c.listener.readWG.Wait() + if errClose, ok := c.listener.errClose.Load().(error); ok { + err = errClose + } + } else { + err = nil + } + + if errBuf := c.buffer.Close(); errBuf != nil && err == nil { + err = errBuf + } + }) + + return err +} + +// LocalAddr implements net.PacketConn.LocalAddr. +func (c *PacketConn) LocalAddr() net.Addr { + return c.listener.pConn.LocalAddr() +} + +// SetDeadline implements net.PacketConn.SetDeadline. +func (c *PacketConn) SetDeadline(t time.Time) error { + c.writeDeadline.Set(t) + return c.SetReadDeadline(t) +} + +// SetReadDeadline implements net.PacketConn.SetReadDeadline. +func (c *PacketConn) SetReadDeadline(t time.Time) error { + return c.buffer.SetReadDeadline(t) +} + +// SetWriteDeadline implements net.PacketConn.SetWriteDeadline. +func (c *PacketConn) SetWriteDeadline(t time.Time) error { + c.writeDeadline.Set(t) + // Write deadline of underlying connection should not be changed + // since the connection can be shared. + return nil +} From a8998af42b9c7222b860ef9964498b24c449c8de Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:24:03 -0400 Subject: [PATCH 043/146] Add UDP net.PacketListener unit tests Adds unit tests for UDP net.PacketListener. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- internal/net/udp/packet_conn_test.go | 713 +++++++++++++++++++++++++++ 1 file changed, 713 insertions(+) create mode 100644 internal/net/udp/packet_conn_test.go diff --git a/internal/net/udp/packet_conn_test.go b/internal/net/udp/packet_conn_test.go new file mode 100644 index 000000000..1bb34da9f --- /dev/null +++ b/internal/net/udp/packet_conn_test.go @@ -0,0 +1,713 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +//go:build !js +// +build !js + +// Package udp implements DTLS specific UDP networking primitives. +package udp + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "net" + "sync" + "testing" + "time" + + dtlsnet "github.com/pion/dtls/v2/pkg/net" + "github.com/pion/transport/v2/test" +) + +var errHandshakeFailed = errors.New("handshake failed") + +func TestStressDuplex(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(time.Second * 20) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + // Run the test + stressDuplex(t) +} + +type rw struct { + p net.PacketConn + raddr net.Addr +} + +func fromPC(p net.PacketConn, raddr net.Addr) *rw { + return &rw{ + p: p, + raddr: raddr, + } +} + +func (r *rw) Read(p []byte) (int, error) { + n, _, err := r.p.ReadFrom(p) + return n, err +} + +func (r *rw) Write(p []byte) (int, error) { + return r.p.WriteTo(p, r.raddr) +} + +func stressDuplex(t *testing.T) { + listener, ca, cb, err := pipe() + if err != nil { + t.Fatal(err) + } + + defer func() { + if ca.Close() != nil { + t.Fatal(err) + } + if cb.Close() != nil { + t.Fatal(err) + } + if listener.Close() != nil { + t.Fatal(err) + } + }() + + opt := test.Options{ + MsgSize: 2048, + MsgCount: 1, // Can't rely on UDP message order in CI + } + + if err := test.StressDuplex(fromPC(ca, cb.LocalAddr()), cb, opt); err != nil { + t.Fatal(err) + } +} + +func TestListenerCloseTimeout(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(time.Second * 5) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + listener, ca, _, err := pipe() + if err != nil { + t.Fatal(err) + } + + err = listener.Close() + if err != nil { + t.Fatal(err) + } + + // Close client after server closes to cleanup + err = ca.Close() + if err != nil { + t.Fatal(err) + } +} + +func TestListenerCloseUnaccepted(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(time.Second * 20) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + const backlog = 2 + + network, addr := getConfig() + listener, err := (&ListenConfig{ + Backlog: backlog, + }).Listen(network, addr) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < backlog; i++ { + conn, dErr := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) + if dErr != nil { + t.Error(dErr) + continue + } + if _, wErr := conn.Write([]byte{byte(i)}); wErr != nil { + t.Error(wErr) + } + if cErr := conn.Close(); cErr != nil { + t.Error(cErr) + } + } + + time.Sleep(100 * time.Millisecond) // Wait all packets being processed by readLoop + + // Unaccepted connections must be closed by listener.Close() + if err = listener.Close(); err != nil { + t.Fatal(err) + } +} + +func TestListenerAcceptFilter(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(time.Second * 20) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + testCases := map[string]struct { + packet []byte + accept bool + }{ + "CreateConn": { + packet: []byte{0xAA}, + accept: true, + }, + "Discarded": { + packet: []byte{0x00}, + accept: false, + }, + } + + for name, testCase := range testCases { + testCase := testCase + t.Run(name, func(t *testing.T) { + network, addr := getConfig() + listener, err := (&ListenConfig{ + AcceptFilter: func(pkt []byte) bool { + return pkt[0] == 0xAA + }, + }).Listen(network, addr) + if err != nil { + t.Fatal(err) + } + + var wgAcceptLoop sync.WaitGroup + wgAcceptLoop.Add(1) + defer func() { + if lErr := listener.Close(); lErr != nil { + t.Fatal(lErr) + } + wgAcceptLoop.Wait() + }() + + conn, err := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) + if err != nil { + t.Fatal(err) + } + if _, err := conn.Write(testCase.packet); err != nil { + t.Fatal(err) + } + defer func() { + if err := conn.Close(); err != nil { + t.Error(err) + } + }() + + chAccepted := make(chan struct{}) + go func() { + defer wgAcceptLoop.Done() + + conn, _, aArr := listener.Accept() + if aArr != nil { + if !errors.Is(aArr, ErrClosedListener) { + t.Error(aArr) + } + return + } + close(chAccepted) + if err := conn.Close(); err != nil { + t.Error(err) + } + }() + + var accepted bool + select { + case <-chAccepted: + accepted = true + case <-time.After(10 * time.Millisecond): + } + + if accepted != testCase.accept { + if testCase.accept { + t.Error("Packet should create new conn") + } else { + t.Error("Packet should not create new conn") + } + } + }) + } +} + +func TestListenerConcurrent(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(time.Second * 20) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + const backlog = 2 + + network, addr := getConfig() + listener, err := (&ListenConfig{ + Backlog: backlog, + }).Listen(network, addr) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < backlog+1; i++ { + conn, dErr := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) + if dErr != nil { + t.Error(dErr) + continue + } + if _, wErr := conn.Write([]byte{byte(i)}); wErr != nil { + t.Error(wErr) + } + if cErr := conn.Close(); cErr != nil { + t.Error(cErr) + } + } + + time.Sleep(100 * time.Millisecond) // Wait all packets being processed by readLoop + + for i := 0; i < backlog; i++ { + conn, _, lErr := listener.Accept() + if lErr != nil { + t.Error(lErr) + continue + } + b := make([]byte, 1) + n, _, lErr := conn.ReadFrom(b) + if lErr != nil { + t.Error(lErr) + } else if !bytes.Equal([]byte{byte(i)}, b[:n]) { + t.Errorf("Packet from connection %d is wrong, expected: [%d], got: %v", i, i, b[:n]) + } + if lErr = conn.Close(); lErr != nil { + t.Error(lErr) + } + } + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + if conn, _, lErr := listener.Accept(); !errors.Is(lErr, ErrClosedListener) { + t.Errorf("Connection exceeding backlog limit must be discarded: %v", lErr) + if lErr == nil { + _ = conn.Close() + } + } + }() + + time.Sleep(100 * time.Millisecond) // Last Accept should be discarded + err = listener.Close() + if err != nil { + t.Fatal(err) + } + + wg.Wait() +} + +func pipe() (dtlsnet.PacketListener, net.PacketConn, *net.UDPConn, error) { + // Start listening + network, addr := getConfig() + listener, err := Listen(network, addr) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to listen: %w", err) + } + + // Open a connection + var dConn *net.UDPConn + dConn, err = net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to dial: %w", err) + } + + // Write to the connection to initiate it + handshake := "hello" + _, err = dConn.Write([]byte(handshake)) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to write to dialed Conn: %w", err) + } + + // Accept the connection + var lConn net.PacketConn + lConn, _, err = listener.Accept() + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to accept Conn: %w", err) + } + + var n int + buf := make([]byte, len(handshake)) + if n, _, err = lConn.ReadFrom(buf); err != nil { + return nil, nil, nil, fmt.Errorf("failed to read handshake: %w", err) + } + + result := string(buf[:n]) + if handshake != result { + return nil, nil, nil, fmt.Errorf("%w: %s != %s", errHandshakeFailed, handshake, result) + } + + return listener, lConn, dConn, nil +} + +func getConfig() (string, *net.UDPAddr) { + return "udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 0} +} + +func TestConnClose(t *testing.T) { + lim := test.TimeOut(time.Second * 5) + defer lim.Stop() + + t.Run("Close", func(t *testing.T) { + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + l, ca, cb, errPipe := pipe() + if errPipe != nil { + t.Fatal(errPipe) + } + if err := ca.Close(); err != nil { + t.Errorf("Failed to close A side: %v", err) + } + if err := cb.Close(); err != nil { + t.Errorf("Failed to close B side: %v", err) + } + if err := l.Close(); err != nil { + t.Errorf("Failed to close listener: %v", err) + } + }) + t.Run("CloseError1", func(t *testing.T) { + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + l, ca, cb, errPipe := pipe() + if errPipe != nil { + t.Fatal(errPipe) + } + // Close l.pConn to inject error. + if err := l.(*listener).pConn.Close(); err != nil { //nolint:forcetypeassert + t.Error(err) + } + + if err := cb.Close(); err != nil { + t.Errorf("Failed to close A side: %v", err) + } + if err := ca.Close(); err != nil { + t.Errorf("Failed to close B side: %v", err) + } + if err := l.Close(); err == nil { + t.Errorf("Error is not propagated to Listener.Close") + } + }) + t.Run("CloseError2", func(t *testing.T) { + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + l, ca, cb, errPipe := pipe() + if errPipe != nil { + t.Fatal(errPipe) + } + // Close l.pConn to inject error. + if err := l.(*listener).pConn.Close(); err != nil { //nolint:forcetypeassert + t.Error(err) + } + + if err := cb.Close(); err != nil { + t.Errorf("Failed to close A side: %v", err) + } + if err := l.Close(); err != nil { + t.Errorf("Failed to close listener: %v", err) + } + if err := ca.Close(); err == nil { + t.Errorf("Error is not propagated to Conn.Close") + } + }) + t.Run("CancelRead", func(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(time.Second * 5) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + l, ca, cb, errPipe := pipe() + if errPipe != nil { + t.Fatal(errPipe) + } + + errC := make(chan error, 1) + go func() { + buf := make([]byte, 1024) + // This read will block because we don't write on the other side. + // Calling Close must unblock the call. + _, _, err := ca.ReadFrom(buf) + errC <- err + }() + + if err := ca.Close(); err != nil { // Trigger Read cancellation. + t.Errorf("Failed to close B side: %v", err) + } + + // Main test condition, Read should return + // after ca.Close() by closing the buffer. + if err := <-errC; !errors.Is(err, io.EOF) { + t.Errorf("expected err to be io.EOF but got %v", err) + } + + if err := cb.Close(); err != nil { + t.Errorf("Failed to close A side: %v", err) + } + if err := l.Close(); err != nil { + t.Errorf("Failed to close listener: %v", err) + } + }) +} + +func TestListenerCustomConnIDs(t *testing.T) { + const helloPayload, setPayload = "hello", "set" + const serverCount, clientCount = 5, 20 + // Limit runtime in case of deadlocks. + lim := test.TimeOut(time.Second * 20) + defer lim.Stop() + + // Check for leaking routines. + report := test.CheckRoutines(t) + defer report() + + type pkt struct { + ID int + Payload string + } + network, addr := getConfig() + listener, err := (&ListenConfig{ + // For all datagrams other than the initial "hello" packet, use the ID + // to route. + DatagramRouter: func(buf []byte) (string, bool) { + var p pkt + if err := json.Unmarshal(buf, &p); err != nil { + return "", false + } + if p.Payload == helloPayload { + return "", false + } + return fmt.Sprint(p.ID), true + }, + // Use the outgoing "set" payload to add an identifier for a connection. + ConnectionIdentifier: func(buf []byte) (string, bool) { + var p pkt + if err := json.Unmarshal(buf, &p); err != nil { + return "", false + } + if p.Payload == setPayload { + return fmt.Sprint(p.ID), true + } + return "", false + }, + }).Listen(network, addr) + if err != nil { + t.Fatal(err) + } + + var clientWg sync.WaitGroup + var phaseOne [5]chan struct{} + for i := range phaseOne { + phaseOne[i] = make(chan struct{}) + } + var serverWg sync.WaitGroup + clientMap := map[string]struct{}{} + var clientMapMu sync.Mutex + // Start servers. + for i := 0; i < serverCount; i++ { + serverWg.Add(1) + go func() { + defer serverWg.Done() + // The first payload from the accepted connection should inform + // which connection this server is. + conn, _, err := listener.Accept() + if err != nil { + t.Error(err) + return + } + buf := make([]byte, 100) + n, raddr, rErr := conn.ReadFrom(buf) + if rErr != nil { + t.Error(err) + return + } + var p pkt + if uErr := json.Unmarshal(buf[:n], &p); uErr != nil { + t.Error(err) + return + } + // First message should be a hello and custom connection + // ID function will use remote address as identifier. + if p.Payload != helloPayload { + t.Error("Expected hello message") + return + } + connID := p.ID + + // Send set message to associate ID with this connection. + buf, err = json.Marshal(&pkt{ + ID: connID, + Payload: "set", + }) + if err != nil { + t.Error(err) + return + } + if _, wErr := conn.WriteTo(buf, raddr); wErr != nil { + t.Error(wErr) + return + } + // Signal to the corresponding clients that connection ID has been + // set. + close(phaseOne[connID]) + // Receive packets, ensuring that each one came from a different + // client remote address and has a unique payload. + for j := 0; j < clientCount/serverCount; j++ { + buf := make([]byte, 100) + n, _, err := conn.ReadFrom(buf) + if err != nil { + t.Error(err) + return + } + var p pkt + if err := json.Unmarshal(buf[:n], &p); err != nil { + t.Error(err) + return + } + if p.ID != connID { + t.Errorf("Expected connection ID %d, but got %d", connID, p.ID) + return + } + // Ensure we only ever receive one message from + // a given client. + clientMapMu.Lock() + if _, ok := clientMap[p.Payload]; ok { + t.Errorf("Multiple messages from single client %s", p.Payload) + return + } + clientMap[p.Payload] = struct{}{} + clientMapMu.Unlock() + } + if err := conn.Close(); err != nil { + t.Error(err) + } + }() + } + + // Start a client per server to send initial "hello" message and receive a + // "set" message. + for i := 0; i < serverCount; i++ { + clientWg.Add(1) + go func(connID int) { + defer clientWg.Done() + conn, dErr := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) + if dErr != nil { + t.Error(dErr) + return + } + hbuf, err := json.Marshal(&pkt{ + ID: connID, + Payload: helloPayload, + }) + if err != nil { + t.Error(err) + return + } + if _, wErr := conn.Write(hbuf); wErr != nil { + t.Error(wErr) + return + } + + var p pkt + buf := make([]byte, 100) + n, err := conn.Read(buf) + if err != nil { + t.Error(err) + return + } + if err := json.Unmarshal(buf[:n], &p); err != nil { + t.Error(err) + return + } + // Second message should be a set and custom connection identifier + // function will update the connection ID from remote address to the + // supplied ID. + if p.Payload != "set" { + t.Error("Expected set message") + return + } + // Ensure the connection ID matches what the "hello" message + // indicated. + if p.ID != connID { + t.Errorf("Expected connection ID %d, but got %d", connID, p.ID) + return + } + // Close connection. We will reconnect from a different remote + // address using the same connection ID. + if cErr := conn.Close(); cErr != nil { + t.Error(cErr) + } + }(i) + } + + // Spawn clients sending to server connections. + for i := 1; i <= clientCount; i++ { + clientWg.Add(1) + go func(connID int) { + defer clientWg.Done() + // Ensure that we are using a connection ID for packet + // routing prior to sending any messages. + <-phaseOne[connID] + conn, dErr := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) + if dErr != nil { + t.Error(dErr) + return + } + // Send a packet with a connection ID and this client's local + // address. The latter is used to identify this client as unique. + buf, err := json.Marshal(&pkt{ + ID: connID, + Payload: conn.LocalAddr().String(), + }) + if err != nil { + t.Error(err) + return + } + if _, wErr := conn.Write(buf); wErr != nil { + t.Error(wErr) + return + } + if cErr := conn.Close(); cErr != nil { + t.Error(cErr) + } + }(i % serverCount) + } + + // Wait for clients to exit. + clientWg.Wait() + // Wait for servers to exit. + serverWg.Wait() + if err := listener.Close(); err != nil { + t.Fatal(err) + } +} From 9db84b5ca7eb1737153c4016fe69412d12bfc71a Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:24:44 -0400 Subject: [PATCH 044/146] Add CID based datagram routing Adds functions to route datagrams and identify connections by DTLS 1.2 Connection IDs. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- connection_id.go | 75 +++++++++++++++++++++++++++++++++++++++++++++++- go.mod | 1 + 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/connection_id.go b/connection_id.go index 564d17184..b2fbbd7a8 100644 --- a/connection_id.go +++ b/connection_id.go @@ -3,7 +3,14 @@ package dtls -import "crypto/rand" +import ( + "crypto/rand" + + "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v2/pkg/protocol/extension" + "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v2/pkg/protocol/recordlayer" +) // RandomCIDGenerator is a random Connection ID generator where CID is the // specified size. Specifying a size of 0 will indicate to peers that sending a @@ -26,3 +33,69 @@ func OnlySendCIDGenerator() func() []byte { return nil } } + +// cidDatagramRouter extracts connection IDs from incoming datagram payloads and +// uses them to route to the proper connection. +// NOTE: properly routing datagrams based on connection IDs requires using +// constant size connection IDs. +func cidDatagramRouter(size int) func([]byte) (string, bool) { + return func(packet []byte) (string, bool) { + pkts, err := recordlayer.ContentAwareUnpackDatagram(packet, size) + if err != nil || len(pkts) < 1 { + return "", false + } + for _, pkt := range pkts { + h := &recordlayer.Header{ + ConnectionID: make([]byte, size), + } + if err := h.Unmarshal(pkt); err != nil { + continue + } + if h.ContentType != protocol.ContentTypeConnectionID { + continue + } + return string(h.ConnectionID), true + } + return "", false + } +} + +// cidConnIdentifier extracts connection IDs from outgoing ServerHello records +// and associates them with the associated connection. +// NOTE: a ServerHello should always be the first record in a datagram if +// multiple are present, so we avoid iterating through all packets if the first +// is not a ServerHello. +func cidConnIdentifier() func([]byte) (string, bool) { + return func(packet []byte) (string, bool) { + pkts, err := recordlayer.UnpackDatagram(packet) + if err != nil || len(pkts) < 1 { + return "", false + } + var h recordlayer.Header + if hErr := h.Unmarshal(pkts[0]); hErr != nil { + return "", false + } + if h.ContentType != protocol.ContentTypeHandshake { + return "", false + } + var hh handshake.Header + var sh handshake.MessageServerHello + for _, pkt := range pkts { + if hhErr := hh.Unmarshal(pkt[recordlayer.FixedHeaderSize:]); hhErr != nil { + continue + } + if err = sh.Unmarshal(pkt[recordlayer.FixedHeaderSize+handshake.HeaderLength:]); err == nil { + break + } + } + if err != nil { + return "", false + } + for _, ext := range sh.Extensions { + if e, ok := ext.(*extension.ConnectionID); ok { + return string(e.CID), true + } + } + return "", false + } +} diff --git a/go.mod b/go.mod index b35260c67..7fa3fc769 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v2 v2.2.2-0.20230802201558-f2dffd80896b + github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.12.0 golang.org/x/net v0.13.0 ) From e663309aab3718c7bb0d7e49531e0433c62e8f92 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:25:29 -0400 Subject: [PATCH 045/146] Add CID routing unit tests Adds unit tests for CID routing functions. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- connection_id_test.go | 239 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 238 insertions(+), 1 deletion(-) diff --git a/connection_id_test.go b/connection_id_test.go index b9f65d3f7..bc9a991d1 100644 --- a/connection_id_test.go +++ b/connection_id_test.go @@ -3,7 +3,15 @@ package dtls -import "testing" +import ( + "testing" + "time" + + "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v2/pkg/protocol/extension" + "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v2/pkg/protocol/recordlayer" +) func TestRandomConnectionIDGenerator(t *testing.T) { cases := map[string]struct { @@ -44,3 +52,232 @@ func TestOnlySendCIDGenerator(t *testing.T) { }) } } + +func TestCIDDatagramRouter(t *testing.T) { + cid := []byte("abcd1234") + cidLen := 8 + appRecord, err := (&recordlayer.RecordLayer{ + Header: recordlayer.Header{ + Epoch: 1, + Version: protocol.Version1_2, + }, + Content: &protocol.ApplicationData{ + Data: []byte("application data"), + }, + }).Marshal() + if err != nil { + t.Fatal(err) + } + appData, err := (&protocol.ApplicationData{ + Data: []byte("some data"), + }).Marshal() + if err != nil { + t.Fatal(err) + } + inner, err := (&recordlayer.InnerPlaintext{ + Content: appData, + RealType: protocol.ContentTypeApplicationData, + }).Marshal() + if err != nil { + t.Fatal(err) + } + cidHeader, err := (&recordlayer.Header{ + Epoch: 1, + Version: protocol.Version1_2, + ContentType: protocol.ContentTypeConnectionID, + ContentLen: uint16(len(inner)), + ConnectionID: cid, + SequenceNumber: 1, + }).Marshal() + if err != nil { + t.Fatal(err) + } + cases := map[string]struct { + reason string + size int + datagram []byte + ok bool + want string + }{ + "EmptyDatagram": { + reason: "If datagram is empty, we cannot extract an identifier", + size: cidLen, + datagram: []byte{}, + ok: false, + want: "", + }, + "NotADTLSRecord": { + reason: "If datagram is not a DTLS record, we cannot extract an identifier", + size: cidLen, + datagram: []byte("not a DTLS record"), + ok: false, + want: "", + }, + "NotAConnectionIDDatagram": { + reason: "If datagram does not contain any Connection ID records, we cannot extract an identifier", + size: cidLen, + datagram: appRecord, + ok: false, + want: "", + }, + "OneRecordConnectionID": { + reason: "If datagram contains one Connection ID record, we should be able to extract it.", + size: cidLen, + datagram: append(cidHeader, inner...), + ok: true, + want: string(cid), + }, + "OneRecordConnectionIDAltLength": { + reason: "If datagram contains one Connection ID record, but it has the wrong length we should not be able to extract it.", + size: cidLen, + datagram: func() []byte { + altCIDHeader, err := (&recordlayer.Header{ + Epoch: 1, + Version: protocol.Version1_2, + ContentType: protocol.ContentTypeConnectionID, + ContentLen: uint16(len(inner)), + ConnectionID: []byte("abcd"), + SequenceNumber: 1, + }).Marshal() + if err != nil { + t.Fatal(err) + } + return append(altCIDHeader, inner...) + }(), + ok: false, + want: "", + }, + "MultipleRecordOneConnectionID": { + reason: "If datagram contains multiple records and one is a Connection ID record, we should be able to extract it.", + size: 8, + datagram: append(append(appRecord, cidHeader...), inner...), + ok: true, + want: string(cid), + }, + "MultipleRecordMultipleConnectionID": { + reason: "If datagram contains multiple records and multiple are Connection ID records, we should extract the first one.", + size: 8, + datagram: append(append(append(appRecord, func() []byte { + altCIDHeader, err := (&recordlayer.Header{ + Epoch: 1, + Version: protocol.Version1_2, + ContentType: protocol.ContentTypeConnectionID, + ContentLen: uint16(len(inner)), + ConnectionID: []byte("1234abcd"), + SequenceNumber: 1, + }).Marshal() + if err != nil { + t.Fatal(err) + } + return append(altCIDHeader, inner...) + }()...), cidHeader...), inner...), + ok: true, + want: "1234abcd", + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + cid, ok := cidDatagramRouter(tc.size)(tc.datagram) + if ok != tc.ok { + t.Errorf("%s\ncidDatagramRouter: expected ok %t, but got %t.", tc.reason, tc.ok, ok) + } + if cid != tc.want { + t.Errorf("%s\ncidDatagramRouter: expected CID %s, but got %s.", tc.reason, tc.want, cid) + } + }) + } +} + +func TestCIDConnIdentifier(t *testing.T) { + cid := []byte("abcd1234") + cs := uint16(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + sh, err := (&recordlayer.RecordLayer{ + Header: recordlayer.Header{ + Epoch: 0, + Version: protocol.Version1_2, + }, + Content: &handshake.Handshake{ + Message: &handshake.MessageServerHello{ + Version: protocol.Version1_2, + Random: handshake.Random{GMTUnixTime: time.Unix(500, 0), RandomBytes: [28]byte{}}, + SessionID: []byte("hello"), + CipherSuiteID: &cs, + CompressionMethod: defaultCompressionMethods()[0], + Extensions: []extension.Extension{ + &extension.ConnectionID{ + CID: cid, + }, + }, + }, + }, + }).Marshal() + if err != nil { + t.Fatal(err) + } + appRecord, err := (&recordlayer.RecordLayer{ + Header: recordlayer.Header{ + Epoch: 1, + Version: protocol.Version1_2, + }, + Content: &protocol.ApplicationData{ + Data: []byte("application data"), + }, + }).Marshal() + if err != nil { + t.Fatal(err) + } + cases := map[string]struct { + reason string + datagram []byte + ok bool + want string + }{ + "EmptyDatagram": { + reason: "If datagram is empty, we cannot extract an identifier", + datagram: []byte{}, + ok: false, + want: "", + }, + "NotADTLSRecord": { + reason: "If datagram is not a DTLS record, we cannot extract an identifier", + datagram: []byte("not a DTLS record"), + ok: false, + want: "", + }, + "NotAServerhelloDatagram": { + reason: "If datagram does not contain any ServerHello record, we cannot extract an identifier", + datagram: appRecord, + ok: false, + want: "", + }, + "OneRecordServerHello": { + reason: "If datagram contains one ServerHello record, we should be able to extract an identifier.", + datagram: sh, + ok: true, + want: string(cid), + }, + "MultipleRecordFirstServerHello": { + reason: "If datagram contains multiple records and the first is a ServerHello record, we should be able to extract an identifier.", + datagram: append(sh, appRecord...), + ok: true, + want: string(cid), + }, + "MultipleRecordNotFirstServerHello": { + reason: "If datagram contains multiple records and the first is not a ServerHello record, we should not be able to extract an identifier.", + datagram: append(appRecord, sh...), + ok: false, + want: "", + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + cid, ok := cidConnIdentifier()(tc.datagram) + if ok != tc.ok { + t.Errorf("%s\ncidConnIdentifier: expected ok %t, but got %t.", tc.reason, tc.ok, ok) + } + if cid != tc.want { + t.Errorf("%s\ncidConnIdentifier: expected CID %s, but got %s.", tc.reason, tc.want, cid) + } + }) + } +} From f5875c11130a74359706e87e199921b071b74d20 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:25:51 -0400 Subject: [PATCH 046/146] Set UDP routing if CID is enabled Sets UDP routing functions in the default DTLS listener if a connection ID generator is provided. Also updates to accept a dtls net.PacketListener when a caller wishes to provide their own. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- listener.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/listener.go b/listener.go index 0d281fc4d..90dbbb427 100644 --- a/listener.go +++ b/listener.go @@ -6,10 +6,10 @@ package dtls import ( "net" - "github.com/pion/dtls/v2/internal/util" + "github.com/pion/dtls/v2/internal/net/udp" + dtlsnet "github.com/pion/dtls/v2/pkg/net" "github.com/pion/dtls/v2/pkg/protocol" "github.com/pion/dtls/v2/pkg/protocol/recordlayer" - "github.com/pion/transport/v2/udp" ) // Listen creates a DTLS listener @@ -31,6 +31,12 @@ func Listen(network string, laddr *net.UDPAddr, config *Config) (net.Listener, e return h.ContentType == protocol.ContentTypeHandshake }, } + // If connection ID support is enabled, then they must be supported in + // routing. + if config.ConnectionIDGenerator != nil { + lc.DatagramRouter = cidDatagramRouter(len(config.ConnectionIDGenerator())) + lc.ConnectionIdentifier = cidConnIdentifier() + } parent, err := lc.Listen(network, laddr) if err != nil { return nil, err @@ -42,7 +48,7 @@ func Listen(network string, laddr *net.UDPAddr, config *Config) (net.Listener, e } // NewListener creates a DTLS listener which accepts connections from an inner Listener. -func NewListener(inner net.Listener, config *Config) (net.Listener, error) { +func NewListener(inner dtlsnet.PacketListener, config *Config) (net.Listener, error) { if err := validateConfig(config); err != nil { return nil, err } @@ -56,7 +62,7 @@ func NewListener(inner net.Listener, config *Config) (net.Listener, error) { // listener represents a DTLS listener type listener struct { config *Config - parent net.Listener + parent dtlsnet.PacketListener } // Accept waits for and returns the next connection to the listener. @@ -64,11 +70,11 @@ type listener struct { // Connection handshake will timeout using ConnectContextMaker in the Config. // If you want to specify the timeout duration, set ConnectContextMaker. func (l *listener) Accept() (net.Conn, error) { - c, err := l.parent.Accept() + c, raddr, err := l.parent.Accept() if err != nil { return nil, err } - return Server(util.FromConn(c), c.RemoteAddr(), l.config) + return Server(c, raddr, l.config) } // Close closes the listener. From 6df50a63bef6d4352f802dbf54d4c6c5b8fb4f71 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:27:04 -0400 Subject: [PATCH 047/146] Add CID listener example Adds an example for setting up a CID-enabled DTLS listener. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- examples/listen/cid/main.go | 77 +++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 examples/listen/cid/main.go diff --git a/examples/listen/cid/main.go b/examples/listen/cid/main.go new file mode 100644 index 000000000..5c85fe81b --- /dev/null +++ b/examples/listen/cid/main.go @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +// Package main implements a DTLS server using a pre-shared key. +package main + +import ( + "context" + "fmt" + "net" + "time" + + "github.com/pion/dtls/v2" + "github.com/pion/dtls/v2/examples/util" +) + +func main() { + // Prepare the IP to connect to + addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444} + + // Create parent context to cleanup handshaking connections on exit. + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // + // Everything below is the pion-DTLS API! Thanks for using it ❤️. + // + + // Prepare the configuration of the DTLS connection + config := &dtls.Config{ + PSK: func(hint []byte) ([]byte, error) { + fmt.Printf("Client's hint: %s \n", hint) + return []byte{0xAB, 0xC1, 0x23}, nil + }, + PSKIdentityHint: []byte("Pion DTLS Client"), + CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8}, + ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, + // Create timeout context for accepted connection. + ConnectContextMaker: func() (context.Context, func()) { + return context.WithTimeout(ctx, 30*time.Second) + }, + ConnectionIDGenerator: dtls.RandomCIDGenerator(8), + } + + // Connect to a DTLS server + listener, err := dtls.Listen("udp", addr, config) + util.Check(err) + defer func() { + util.Check(listener.Close()) + }() + + fmt.Println("Listening") + + // Simulate a chat session + hub := util.NewHub() + + go func() { + for { + // Wait for a connection. + conn, err := listener.Accept() + util.Check(err) + // defer conn.Close() // TODO: graceful shutdown + + // `conn` is of type `net.Conn` but may be casted to `dtls.Conn` + // using `dtlsConn := conn.(*dtls.Conn)` in order to to expose + // functions like `ConnectionState` etc. + + // Register the connection with the chat hub + if err == nil { + hub.Register(conn) + } + } + }() + + // Start chatting + hub.Chat() +} From 37fbc04a1b1adcedaefa1fec7d830a24b1d10bef Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Sun, 27 Aug 2023 15:27:40 -0400 Subject: [PATCH 048/146] Add CID send only client example Adds an example for a client that only sends connection IDs (i.e. does not request to received them). This is the most common scenario for DTLS clients. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- examples/dial/cid/main.go | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 examples/dial/cid/main.go diff --git a/examples/dial/cid/main.go b/examples/dial/cid/main.go new file mode 100644 index 000000000..0ab8f4b78 --- /dev/null +++ b/examples/dial/cid/main.go @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +// Package main implements an example DTLS client using a pre-shared key. +package main + +import ( + "context" + "fmt" + "net" + "time" + + "github.com/pion/dtls/v2" + "github.com/pion/dtls/v2/examples/util" +) + +func main() { + // Prepare the IP to connect to + addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444} + + // + // Everything below is the pion-DTLS API! Thanks for using it ❤️. + // + + // Prepare the configuration of the DTLS connection + config := &dtls.Config{ + PSK: func(hint []byte) ([]byte, error) { + fmt.Printf("Server's hint: %s \n", hint) + return []byte{0xAB, 0xC1, 0x23}, nil + }, + PSKIdentityHint: []byte("Pion DTLS Server"), + CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8}, + ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, + ConnectionIDGenerator: dtls.OnlySendCIDGenerator(), + } + + // Connect to a DTLS server + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + dtlsConn, err := dtls.DialWithContext(ctx, "udp", addr, config) + util.Check(err) + defer func() { + util.Check(dtlsConn.Close()) + }() + + fmt.Println("Connected; type 'exit' to shutdown gracefully") + + // Simulate a chat session + util.Chat(dtlsConn) +} From e142ee18da547071c6dbfd5b728bf8c2513509db Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Mon, 28 Aug 2023 09:26:19 -0400 Subject: [PATCH 049/146] Serialize CIDs in state Updates state serialization and deserialization to include connection IDs if they were negotiated. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- state.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/state.go b/state.go index 26bfb747d..fbbfd5ee1 100644 --- a/state.go +++ b/state.go @@ -76,6 +76,8 @@ type serializedState struct { PeerCertificates [][]byte IdentityHint []byte SessionID []byte + LocalConnectionID []byte + RemoteConnectionID []byte IsClient bool } @@ -105,6 +107,8 @@ func (s *State) serialize() *serializedState { PeerCertificates: s.PeerCertificates, IdentityHint: s.IdentityHint, SessionID: s.SessionID, + LocalConnectionID: s.localConnectionID, + RemoteConnectionID: s.remoteConnectionID, IsClient: s.isClient, } } @@ -141,7 +145,13 @@ func (s *State) deserialize(serialized serializedState) { // Set remote certificate s.PeerCertificates = serialized.PeerCertificates + s.IdentityHint = serialized.IdentityHint + + // Set local and remote connection IDs + s.localConnectionID = serialized.LocalConnectionID + s.remoteConnectionID = serialized.RemoteConnectionID + s.SessionID = serialized.SessionID } From 609e5bee6eb0269574fed9f5d50127fdb360b846 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Mon, 28 Aug 2023 09:27:07 -0400 Subject: [PATCH 050/146] Clear CIDs on potential session resumption Updates the flight0handler to clear connection IDs in the event the client is attempting to resume an existing session. If connection IDs are to be used in the resumed session, they should be negotiated afresh. https://datatracker.ietf.org/doc/html/rfc9146#section-3 Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- flight0handler.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flight0handler.go b/flight0handler.go index 27e991551..648c52883 100644 --- a/flight0handler.go +++ b/flight0handler.go @@ -22,6 +22,12 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak // No valid message received. Keep reading return 0, nil, nil } + + // Connection Identifiers must be negotiated afresh on session resumption. + // https://datatracker.ietf.org/doc/html/rfc9146#name-the-connection_id-extension + state.localConnectionID = nil + state.remoteConnectionID = nil + state.handshakeRecvSequence = seq var clientHello *handshake.MessageClientHello From 7bf18f8dfcec11ccc0b84c6547387e4e92a65617 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 01:56:40 +0000 Subject: [PATCH 051/146] Update module golang.org/x/net to v0.14.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 7fa3fc769..f3823449c 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/pion/transport/v2 v2.2.2-0.20230802201558-f2dffd80896b github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.12.0 - golang.org/x/net v0.13.0 + golang.org/x/net v0.14.0 ) go 1.13 diff --git a/go.sum b/go.sum index b73379cfc..bbab2a3f7 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From e85f10622f717f771195ed20bf9c941ad46211e7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 03:21:16 +0000 Subject: [PATCH 052/146] Update module github.com/pion/transport/v2 to v2.2.2 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f3823449c..c0319620a 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 - github.com/pion/transport/v2 v2.2.2-0.20230802201558-f2dffd80896b + github.com/pion/transport/v2 v2.2.2 github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.12.0 golang.org/x/net v0.14.0 diff --git a/go.sum b/go.sum index bbab2a3f7..a912df593 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport/v2 v2.2.2-0.20230802201558-f2dffd80896b h1:g/axuqY9eU5L6YeAQSq+yW4CU5fPqOb90EaWI+8xeiI= -github.com/pion/transport/v2 v2.2.2-0.20230802201558-f2dffd80896b/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc= +github.com/pion/transport/v2 v2.2.2 h1:yv+EKSU2dpmInuCebQ1rsBFCYL7p+aV90xIlshSBO+A= +github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From a681f67cd527340bfea4241e9e5d9c33c63e55e6 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Fri, 1 Sep 2023 14:25:00 -0400 Subject: [PATCH 053/146] Correctly identify client and server with PSK ID Updates the PSK ID hints on the client and server examples to match the type of endpoint they represent. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- examples/dial/cid/main.go | 2 +- examples/dial/psk/main.go | 2 +- examples/listen/cid/main.go | 2 +- examples/listen/psk/main.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/dial/cid/main.go b/examples/dial/cid/main.go index 0ab8f4b78..10e547706 100644 --- a/examples/dial/cid/main.go +++ b/examples/dial/cid/main.go @@ -28,7 +28,7 @@ func main() { fmt.Printf("Server's hint: %s \n", hint) return []byte{0xAB, 0xC1, 0x23}, nil }, - PSKIdentityHint: []byte("Pion DTLS Server"), + PSKIdentityHint: []byte("Pion DTLS Client"), CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8}, ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, ConnectionIDGenerator: dtls.OnlySendCIDGenerator(), diff --git a/examples/dial/psk/main.go b/examples/dial/psk/main.go index 1f4440d41..492ecdd61 100644 --- a/examples/dial/psk/main.go +++ b/examples/dial/psk/main.go @@ -28,7 +28,7 @@ func main() { fmt.Printf("Server's hint: %s \n", hint) return []byte{0xAB, 0xC1, 0x23}, nil }, - PSKIdentityHint: []byte("Pion DTLS Server"), + PSKIdentityHint: []byte("Pion DTLS Client"), CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8}, ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, } diff --git a/examples/listen/cid/main.go b/examples/listen/cid/main.go index 5c85fe81b..770bbcfa4 100644 --- a/examples/listen/cid/main.go +++ b/examples/listen/cid/main.go @@ -32,7 +32,7 @@ func main() { fmt.Printf("Client's hint: %s \n", hint) return []byte{0xAB, 0xC1, 0x23}, nil }, - PSKIdentityHint: []byte("Pion DTLS Client"), + PSKIdentityHint: []byte("Pion DTLS Server"), CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8}, ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, // Create timeout context for accepted connection. diff --git a/examples/listen/psk/main.go b/examples/listen/psk/main.go index ff45b7d86..66f099693 100644 --- a/examples/listen/psk/main.go +++ b/examples/listen/psk/main.go @@ -32,7 +32,7 @@ func main() { fmt.Printf("Client's hint: %s \n", hint) return []byte{0xAB, 0xC1, 0x23}, nil }, - PSKIdentityHint: []byte("Pion DTLS Client"), + PSKIdentityHint: []byte("Pion DTLS Server"), CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8}, ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, // Create timeout context for accepted connection. From dbc7fd998e6d2616f8304927bbaf0c4286a64d51 Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@pion.ly> Date: Sat, 2 Sep 2023 14:08:16 -0400 Subject: [PATCH 054/146] Update module github.com/pion/transport/v3 to v3.0.0 --- bench_test.go | 4 ++-- cipher_suite_test.go | 4 ++-- conn.go | 6 +++--- conn_go_test.go | 4 ++-- conn_test.go | 4 ++-- e2e/e2e_lossy_test.go | 2 +- e2e/e2e_test.go | 2 +- flight4handler_test.go | 2 +- go.mod | 2 +- go.sum | 9 ++------- handshaker_test.go | 2 +- internal/net/buffer.go | 2 +- internal/net/udp/packet_conn.go | 2 +- internal/net/udp/packet_conn_test.go | 2 +- nettest_test.go | 2 +- replayprotection_test.go | 4 ++-- resume_test.go | 2 +- state.go | 2 +- 18 files changed, 26 insertions(+), 31 deletions(-) diff --git a/bench_test.go b/bench_test.go index 08b6c3c7b..7b236f6d8 100644 --- a/bench_test.go +++ b/bench_test.go @@ -13,8 +13,8 @@ import ( "github.com/pion/dtls/v2/pkg/crypto/selfsign" dtlsnet "github.com/pion/dtls/v2/pkg/net" "github.com/pion/logging" - "github.com/pion/transport/v2/dpipe" - "github.com/pion/transport/v2/test" + "github.com/pion/transport/v3/dpipe" + "github.com/pion/transport/v3/test" ) func TestSimpleReadWrite(t *testing.T) { diff --git a/cipher_suite_test.go b/cipher_suite_test.go index 38bfd516e..c04220dee 100644 --- a/cipher_suite_test.go +++ b/cipher_suite_test.go @@ -10,8 +10,8 @@ import ( "github.com/pion/dtls/v2/internal/ciphersuite" dtlsnet "github.com/pion/dtls/v2/pkg/net" - "github.com/pion/transport/v2/dpipe" - "github.com/pion/transport/v2/test" + "github.com/pion/transport/v3/dpipe" + "github.com/pion/transport/v3/test" ) func TestCipherSuiteName(t *testing.T) { diff --git a/conn.go b/conn.go index e09f4b20a..9d1da84cb 100644 --- a/conn.go +++ b/conn.go @@ -22,9 +22,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/v2/deadline" - "github.com/pion/transport/v2/netctx" - "github.com/pion/transport/v2/replaydetector" + "github.com/pion/transport/v3/deadline" + "github.com/pion/transport/v3/netctx" + "github.com/pion/transport/v3/replaydetector" ) const ( diff --git a/conn_go_test.go b/conn_go_test.go index cfd0e32f4..d9ca6e187 100644 --- a/conn_go_test.go +++ b/conn_go_test.go @@ -17,8 +17,8 @@ import ( "github.com/pion/dtls/v2/pkg/crypto/selfsign" dtlsnet "github.com/pion/dtls/v2/pkg/net" - "github.com/pion/transport/v2/dpipe" - "github.com/pion/transport/v2/test" + "github.com/pion/transport/v3/dpipe" + "github.com/pion/transport/v3/test" ) func TestContextConfig(t *testing.T) { diff --git a/conn_test.go b/conn_test.go index 447526841..755897bd9 100644 --- a/conn_test.go +++ b/conn_test.go @@ -37,8 +37,8 @@ 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/v2/dpipe" - "github.com/pion/transport/v2/test" + "github.com/pion/transport/v3/dpipe" + "github.com/pion/transport/v3/test" ) var ( diff --git a/e2e/e2e_lossy_test.go b/e2e/e2e_lossy_test.go index 59231e893..f646557cd 100644 --- a/e2e/e2e_lossy_test.go +++ b/e2e/e2e_lossy_test.go @@ -13,7 +13,7 @@ import ( "github.com/pion/dtls/v2" "github.com/pion/dtls/v2/pkg/crypto/selfsign" dtlsnet "github.com/pion/dtls/v2/pkg/net" - transportTest "github.com/pion/transport/v2/test" + transportTest "github.com/pion/transport/v3/test" ) const ( diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 955f82990..4a8dd5d54 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -24,7 +24,7 @@ import ( "github.com/pion/dtls/v2" "github.com/pion/dtls/v2/pkg/crypto/selfsign" - "github.com/pion/transport/v2/test" + "github.com/pion/transport/v3/test" ) const ( diff --git a/flight4handler_test.go b/flight4handler_test.go index 318a05826..304c82eff 100644 --- a/flight4handler_test.go +++ b/flight4handler_test.go @@ -11,7 +11,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/v2/test" + "github.com/pion/transport/v3/test" ) type flight4TestMockFlightConn struct{} diff --git a/go.mod b/go.mod index c0319620a..a49a0d4cd 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 - github.com/pion/transport/v2 v2.2.2 + github.com/pion/transport/v3 v3.0.0 github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.12.0 golang.org/x/net v0.14.0 diff --git a/go.sum b/go.sum index a912df593..32ad7105e 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport/v2 v2.2.2 h1:yv+EKSU2dpmInuCebQ1rsBFCYL7p+aV90xIlshSBO+A= -github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc= +github.com/pion/transport/v3 v3.0.0 h1:xNe+VCuPjpilJH5t7qMSAte7B1N3V1FbtIsDJW3YYsk= +github.com/pion/transport/v3 v3.0.0/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -17,7 +17,6 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -27,7 +26,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -40,20 +38,17 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/handshaker_test.go b/handshaker_test.go index 6d307aeea..f869959d2 100644 --- a/handshaker_test.go +++ b/handshaker_test.go @@ -18,7 +18,7 @@ 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/v2/test" + "github.com/pion/transport/v3/test" ) const nonZeroRetransmitInterval = 100 * time.Millisecond diff --git a/internal/net/buffer.go b/internal/net/buffer.go index 9f101d454..9ab290e4c 100644 --- a/internal/net/buffer.go +++ b/internal/net/buffer.go @@ -20,7 +20,7 @@ import ( "sync" "time" - "github.com/pion/transport/v2/deadline" + "github.com/pion/transport/v3/deadline" ) // ErrTimeout indicates that deadline was reached before operation could be diff --git a/internal/net/udp/packet_conn.go b/internal/net/udp/packet_conn.go index b32306c5a..7ddde13d3 100644 --- a/internal/net/udp/packet_conn.go +++ b/internal/net/udp/packet_conn.go @@ -26,7 +26,7 @@ import ( idtlsnet "github.com/pion/dtls/v2/internal/net" dtlsnet "github.com/pion/dtls/v2/pkg/net" - "github.com/pion/transport/v2/deadline" + "github.com/pion/transport/v3/deadline" ) const ( diff --git a/internal/net/udp/packet_conn_test.go b/internal/net/udp/packet_conn_test.go index 1bb34da9f..cb239b3e0 100644 --- a/internal/net/udp/packet_conn_test.go +++ b/internal/net/udp/packet_conn_test.go @@ -19,7 +19,7 @@ import ( "time" dtlsnet "github.com/pion/dtls/v2/pkg/net" - "github.com/pion/transport/v2/test" + "github.com/pion/transport/v3/test" ) var errHandshakeFailed = errors.New("handshake failed") diff --git a/nettest_test.go b/nettest_test.go index e3cb4eb35..dc245b28d 100644 --- a/nettest_test.go +++ b/nettest_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "github.com/pion/transport/v2/test" + "github.com/pion/transport/v3/test" "golang.org/x/net/nettest" ) diff --git a/replayprotection_test.go b/replayprotection_test.go index 3f3a8b4f0..725e05239 100644 --- a/replayprotection_test.go +++ b/replayprotection_test.go @@ -12,8 +12,8 @@ import ( "testing" "time" - "github.com/pion/transport/v2/dpipe" - "github.com/pion/transport/v2/test" + "github.com/pion/transport/v3/dpipe" + "github.com/pion/transport/v3/test" ) func TestReplayProtection(t *testing.T) { diff --git a/resume_test.go b/resume_test.go index fe78e22e2..00b291788 100644 --- a/resume_test.go +++ b/resume_test.go @@ -15,7 +15,7 @@ import ( "github.com/pion/dtls/v2/pkg/crypto/selfsign" dtlsnet "github.com/pion/dtls/v2/pkg/net" - "github.com/pion/transport/v2/test" + "github.com/pion/transport/v3/test" ) var errMessageMissmatch = errors.New("messages missmatch") diff --git a/state.go b/state.go index fbbfd5ee1..cd6945573 100644 --- a/state.go +++ b/state.go @@ -11,7 +11,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/v2/replaydetector" + "github.com/pion/transport/v3/replaydetector" ) // State holds the dtls connection state and implements both encoding.BinaryMarshaler and encoding.BinaryUnmarshaler From 7e5003a9d4632d35170e1c7a38d66792bbbe7d14 Mon Sep 17 00:00:00 2001 From: Sean <sean@pion.ly> Date: Sat, 2 Sep 2023 18:09:11 +0000 Subject: [PATCH 055/146] Update AUTHORS.txt --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 7b3d2ae2b..8cf11cb7e 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -44,6 +44,7 @@ Ryan Gordon <ryan.gordon@getcruise.com> Sam Lancia <sam.lancia@motorolasolutions.com> Sean DuBois <duboisea@justin.tv> Sean DuBois <seaduboi@amazon.com> +Sean DuBois <sean@pion.ly> Sean DuBois <sean@siobud.com> Shelikhoo <xiaokangwang@outlook.com> Stefan Tatschner <stefan@rumpelsepp.org> From ef50d6b2f8d7524903d85ef257a4357c0042bcdc Mon Sep 17 00:00:00 2001 From: Sean <sean@pion.ly> Date: Sat, 2 Sep 2023 18:09:55 +0000 Subject: [PATCH 056/146] Update AUTHORS.txt --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 8cf11cb7e..fbaf97711 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -42,6 +42,7 @@ Rachel Chen <rachel@chens.email> Robert Eperjesi <eperjesi@uber.com> Ryan Gordon <ryan.gordon@getcruise.com> Sam Lancia <sam.lancia@motorolasolutions.com> +Sean <sean@pion.ly> Sean DuBois <duboisea@justin.tv> Sean DuBois <seaduboi@amazon.com> Sean DuBois <sean@pion.ly> From 60064c6543dd2b864ded02149a61f32842eec6bd Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@pion.ly> Date: Sun, 3 Sep 2023 23:14:56 -0400 Subject: [PATCH 057/146] Update module github.com/pion/transport/v3 to v3.0.1 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a49a0d4cd..e6b46094c 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 - github.com/pion/transport/v3 v3.0.0 + github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.12.0 golang.org/x/net v0.14.0 diff --git a/go.sum b/go.sum index 32ad7105e..68b0b76fa 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport/v3 v3.0.0 h1:xNe+VCuPjpilJH5t7qMSAte7B1N3V1FbtIsDJW3YYsk= -github.com/pion/transport/v3 v3.0.0/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 70caf303d66f123a406bba94973477cbb99db5fc Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Tue, 5 Sep 2023 07:50:53 -0400 Subject: [PATCH 058/146] Use atomic.Value to maintain Go 1.13 compatibility Updates to use atomic.Value in place of atomic.Bool such that older Go versions can continue to be supported. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- internal/net/udp/packet_conn.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/net/udp/packet_conn.go b/internal/net/udp/packet_conn.go index 7ddde13d3..58e685fd7 100644 --- a/internal/net/udp/packet_conn.go +++ b/internal/net/udp/packet_conn.go @@ -101,7 +101,7 @@ func (l *listener) Close() error { } // If we haven't already removed the remote address, remove it // from the connection map. - if !c.rmraddr.Load() { + if c.rmraddr.Load() == nil { delete(l.conns, c.raddr.String()) c.rmraddr.Store(true) } @@ -268,7 +268,7 @@ type PacketConn struct { listener *listener raddr net.Addr - rmraddr atomic.Bool + rmraddr atomic.Value // bool id atomic.Value buffer *idtlsnet.PacketBuffer @@ -327,7 +327,7 @@ func (c *PacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { // resulting in the remote address entry being dropped prior to the // "real" client transitioning to sending using the alternate // identifier. - if id != nil && !c.rmraddr.Load() && addr.String() != c.raddr.String() { + if id != nil && c.rmraddr.Load() == nil && addr.String() != c.raddr.String() { c.listener.connLock.Lock() delete(c.listener.conns, c.raddr.String()) c.rmraddr.Store(true) @@ -357,7 +357,7 @@ func (c *PacketConn) Close() error { } // If we haven't already removed the remote address, remove it from the // connection map. - if !c.rmraddr.Load() { + if c.rmraddr.Load() == nil { delete(c.listener.conns, c.raddr.String()) c.rmraddr.Store(true) } From 2b584af66577b91eb5dd67208782b5eafbc78fb4 Mon Sep 17 00:00:00 2001 From: Daniel Mangum <georgedanielmangum@gmail.com> Date: Tue, 5 Sep 2023 07:52:23 -0400 Subject: [PATCH 059/146] Specifying underlying type of conn ID atomic.Value Adds comment to indicate that conn ID should always be a string. Signed-off-by: Daniel Mangum <georgedanielmangum@gmail.com> --- internal/net/udp/packet_conn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/net/udp/packet_conn.go b/internal/net/udp/packet_conn.go index 58e685fd7..7dafbe23e 100644 --- a/internal/net/udp/packet_conn.go +++ b/internal/net/udp/packet_conn.go @@ -269,7 +269,7 @@ type PacketConn struct { raddr net.Addr rmraddr atomic.Value // bool - id atomic.Value + id atomic.Value // string buffer *idtlsnet.PacketBuffer From 744e27a38f208e465de597d9da1644b66224ffc9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:15:50 +0000 Subject: [PATCH 060/146] Update actions/checkout action to v4 Generated by renovateBot --- .github/workflows/e2e.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index e9e89daa5..52a90f173 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -17,7 +17,7 @@ jobs: timeout-minutes: 10 steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: test run: | docker build -t pion-dtls-e2e -f e2e/Dockerfile . From 8401874423359c8c0a42b2534115d8eaf9c26e41 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 00:09:37 +0000 Subject: [PATCH 061/146] Update module golang.org/x/crypto to v0.13.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index e6b46094c..f69e96dc6 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.8.4 - golang.org/x/crypto v0.12.0 + golang.org/x/crypto v0.13.0 golang.org/x/net v0.14.0 ) diff --git a/go.sum b/go.sum index 68b0b76fa..56bf15f36 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,9 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -39,17 +40,20 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= From 28431d988e01072dcea0990ddabab37db39e82d3 Mon Sep 17 00:00:00 2001 From: Xinjun Ma <xinjun.ma@qq.com> Date: Sat, 23 Sep 2023 00:11:48 +0800 Subject: [PATCH 062/146] Export CipherSuiteID in connection State --- state.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/state.go b/state.go index cd6945573..cbc287b42 100644 --- a/state.go +++ b/state.go @@ -21,6 +21,7 @@ type State struct { localRandom, remoteRandom handshake.Random masterSecret []byte cipherSuite CipherSuite // nil if a cipherSuite hasn't been chosen + CipherSuiteID CipherSuiteID srtpProtectionProfile SRTPProtectionProfile // Negotiated SRTPProtectionProfile PeerCertificates [][]byte @@ -138,7 +139,8 @@ func (s *State) deserialize(serialized serializedState) { s.masterSecret = serialized.MasterSecret // Set cipher suite - s.cipherSuite = cipherSuiteForID(CipherSuiteID(serialized.CipherSuiteID), nil) + s.CipherSuiteID = CipherSuiteID(serialized.CipherSuiteID) + s.cipherSuite = cipherSuiteForID(s.CipherSuiteID, nil) atomic.StoreUint64(&s.localSequenceNumber[epoch], serialized.SequenceNumber) s.srtpProtectionProfile = SRTPProtectionProfile(serialized.SRTPProtectionProfile) From c8645455edb4e920e66c525478dde89ddaa7248e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 11:31:05 +0000 Subject: [PATCH 063/146] Update module golang.org/x/net to v0.15.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index f69e96dc6..b954547f0 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.13.0 - golang.org/x/net v0.14.0 + golang.org/x/net v0.15.0 ) go 1.13 diff --git a/go.sum b/go.sum index 56bf15f36..9d1a8b4d8 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 7faf25fe70226dac81e98983d7a11f7d191049c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 00:19:23 +0000 Subject: [PATCH 064/146] Update module golang.org/x/net to v0.17.0 [SECURITY] Generated by renovateBot --- go.mod | 4 ++-- go.sum | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index b954547f0..4b1daafaa 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.8.4 - golang.org/x/crypto v0.13.0 - golang.org/x/net v0.15.0 + golang.org/x/crypto v0.14.0 + golang.org/x/net v0.17.0 ) go 1.13 diff --git a/go.sum b/go.sum index 9d1a8b4d8..e0d0f2652 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -28,8 +28,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -41,13 +41,13 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= From 9cc3df9c336960fc2bc1e3cc85644ba02c00ba60 Mon Sep 17 00:00:00 2001 From: mschexnaydre <mschex@viasat.com> Date: Tue, 17 Oct 2023 22:13:40 +0000 Subject: [PATCH 065/146] Respect Algorithm value in CertificateRequest Before it was hardcoded to always use SHA256. This change stores the HASH algorithm from the CertificateRequest message in the State object so that we can reference these later when generating the CertificateVerify message. Removed hard-coded usage of SHA-256 in generateCertificateVerify, now uses the Digest method of the passed in algorithm. Resolves #418 --- AUTHORS.txt | 2 ++ conn_test.go | 8 ++++++++ crypto.go | 7 +------ flight3handler.go | 3 ++- flight5handler.go | 3 ++- state.go | 2 ++ 6 files changed, 17 insertions(+), 8 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index fbaf97711..d80ca9973 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -38,6 +38,7 @@ Lukas Lihotzki <lukas@lihotzki.de> ManuelBk <26275612+ManuelBk@users.noreply.github.com> Michael Zabka <zabka.michael@gmail.com> Michiel De Backker <mail@backkem.me> +mschexnaydre <mschex@viasat.com> Rachel Chen <rachel@chens.email> Robert Eperjesi <eperjesi@uber.com> Ryan Gordon <ryan.gordon@getcruise.com> @@ -53,6 +54,7 @@ Steffen Vogel <post@steffenvogel.de> Vadim <fffilimonov@yandex.ru> Vadim Filimonov <fffilimonov@yandex.ru> wmiao <wu.miao@viasat.com> +Xinjun Ma <xinjun.ma@qq.com> ZHENK <chengzhenyang@gmail.com> 吕海涛 <hi@taoshu.in> diff --git a/conn_test.go b/conn_test.go index 755897bd9..d3226d876 100644 --- a/conn_test.go +++ b/conn_test.go @@ -864,6 +864,14 @@ func TestClientCertificate(t *testing.T) { ClientAuth: RequireAnyClientCert, }, }, + "RequestClientCert_cert_sigscheme": { // specify signature algorithm + clientCfg: &Config{RootCAs: srvCAPool, Certificates: []tls.Certificate{cert}}, + serverCfg: &Config{ + SignatureSchemes: []tls.SignatureScheme{tls.ECDSAWithP521AndSHA512}, + Certificates: []tls.Certificate{srvCert}, + ClientAuth: RequestClientCert, + }, + }, "RequestClientCert_cert": { clientCfg: &Config{RootCAs: srvCAPool, Certificates: []tls.Certificate{cert}}, serverCfg: &Config{ diff --git a/crypto.go b/crypto.go index 968910c7e..7b01002f3 100644 --- a/crypto.go +++ b/crypto.go @@ -9,7 +9,6 @@ import ( "crypto/ed25519" "crypto/rand" "crypto/rsa" - "crypto/sha256" "crypto/x509" "encoding/asn1" "encoding/binary" @@ -118,11 +117,7 @@ func generateCertificateVerify(handshakeBodies []byte, privateKey crypto.Private return p.Sign(rand.Reader, handshakeBodies, crypto.Hash(0)) } - h := sha256.New() - if _, err := h.Write(handshakeBodies); err != nil { - return nil, err - } - hashed := h.Sum(nil) + hashed := hashAlgorithm.Digest(handshakeBodies) switch p := privateKey.(type) { case *ecdsa.PrivateKey: diff --git a/flight3handler.go b/flight3handler.go index b17a7986c..920ee73bd 100644 --- a/flight3handler.go +++ b/flight3handler.go @@ -153,7 +153,8 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh } } - if _, ok := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok { + if creq, ok := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok { + state.remoteCertRequestAlgs = creq.SignatureHashAlgorithms state.remoteRequestedCertificate = true } diff --git a/flight5handler.go b/flight5handler.go index e1cca6238..14ad66e53 100644 --- a/flight5handler.go +++ b/flight5handler.go @@ -193,7 +193,8 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han ), merged...) // Find compatible signature scheme - signatureHashAlgo, err := signaturehash.SelectSignatureScheme(cfg.localSignatureSchemes, privateKey) + + signatureHashAlgo, err := signaturehash.SelectSignatureScheme(state.remoteCertRequestAlgs, privateKey) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, err } diff --git a/state.go b/state.go index cbc287b42..a65d426bc 100644 --- a/state.go +++ b/state.go @@ -10,6 +10,7 @@ import ( "github.com/pion/dtls/v2/pkg/crypto/elliptic" "github.com/pion/dtls/v2/pkg/crypto/prf" + "github.com/pion/dtls/v2/pkg/crypto/signaturehash" "github.com/pion/dtls/v2/pkg/protocol/handshake" "github.com/pion/transport/v3/replaydetector" ) @@ -53,6 +54,7 @@ type State struct { handshakeSendSequence int handshakeRecvSequence int serverName string + remoteCertRequestAlgs []signaturehash.Algorithm remoteRequestedCertificate bool // Did we get a CertificateRequest localCertificatesVerify []byte // cache CertificateVerify localVerifyData []byte // cached VerifyData From a8f7062654375423f477d92e4fae96effb90d3df Mon Sep 17 00:00:00 2001 From: boks1971 <raja.gobi@tutanota.com> Date: Wed, 15 Nov 2023 09:47:37 +0530 Subject: [PATCH 066/146] Use atomic to avoid stale SRTP protection profile `state` is acccessed without lock in the FSM. In some cases, that leads to stale values. For example, `srtpProtectionProfile` is set in flight handlers (differnt flight handlers in client and server). But, when it is accessed via the API `SelectedSRTPProtectionProfile`, it gets a stale value as it appears that the two goroutines are out-of-sync on that piece of shared memory. This is a larger concern for use of `state`. Ideally, either - `state` should have a lock internally and all fields are accessed through methods. - carefully split fields of `state` to ensure process access/sync. Doing the smaller change here to address one field that has seen stale value. --- conn.go | 8 +++----- flight0handler.go | 2 +- flight3handler.go | 4 ++-- flight4bhandler.go | 4 ++-- flight4handler.go | 4 ++-- state.go | 18 +++++++++++++++--- 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/conn.go b/conn.go index 9d1da84cb..b0d8cde4f 100644 --- a/conn.go +++ b/conn.go @@ -394,14 +394,12 @@ func (c *Conn) ConnectionState() State { // SelectedSRTPProtectionProfile returns the selected SRTPProtectionProfile func (c *Conn) SelectedSRTPProtectionProfile() (SRTPProtectionProfile, bool) { - c.lock.RLock() - defer c.lock.RUnlock() - - if c.state.srtpProtectionProfile == 0 { + profile := c.state.getSRTPProtectionProfile() + if profile == 0 { return 0, false } - return c.state.srtpProtectionProfile, true + return profile, true } func (c *Conn) writePackets(ctx context.Context, pkts []*packet) error { diff --git a/flight0handler.go b/flight0handler.go index 648c52883..0a45c58d4 100644 --- a/flight0handler.go +++ b/flight0handler.go @@ -66,7 +66,7 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak if !ok { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errServerNoMatchingSRTPProfile } - state.srtpProtectionProfile = profile + state.setSRTPProtectionProfile(profile) case *extension.UseExtendedMasterSecret: if cfg.extendedMasterSecret != DisableExtendedMasterSecret { state.extendedMasterSecret = true diff --git a/flight3handler.go b/flight3handler.go index 920ee73bd..90dc1a6e3 100644 --- a/flight3handler.go +++ b/flight3handler.go @@ -56,7 +56,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh if !found { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, errClientNoMatchingSRTPProfile } - state.srtpProtectionProfile = profile + state.setSRTPProtectionProfile(profile) case *extension.UseExtendedMasterSecret: if cfg.extendedMasterSecret != DisableExtendedMasterSecret { state.extendedMasterSecret = true @@ -83,7 +83,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh if cfg.extendedMasterSecret == RequireExtendedMasterSecret && !state.extendedMasterSecret { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errClientRequiredButNoServerEMS } - if len(cfg.localSRTPProtectionProfiles) > 0 && state.srtpProtectionProfile == 0 { + if len(cfg.localSRTPProtectionProfiles) > 0 && state.getSRTPProtectionProfile() == 0 { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errRequestedButNoSRTPExtension } diff --git a/flight4bhandler.go b/flight4bhandler.go index 6bbbc5972..6b1b90469 100644 --- a/flight4bhandler.go +++ b/flight4bhandler.go @@ -59,9 +59,9 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha Supported: true, }) } - if state.srtpProtectionProfile != 0 { + if state.getSRTPProtectionProfile() != 0 { extensions = append(extensions, &extension.UseSRTP{ - ProtectionProfiles: []SRTPProtectionProfile{state.srtpProtectionProfile}, + ProtectionProfiles: []SRTPProtectionProfile{state.getSRTPProtectionProfile()}, }) } diff --git a/flight4handler.go b/flight4handler.go index 52568139f..cd8f2884a 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -228,9 +228,9 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha Supported: true, }) } - if state.srtpProtectionProfile != 0 { + if state.getSRTPProtectionProfile() != 0 { extensions = append(extensions, &extension.UseSRTP{ - ProtectionProfiles: []SRTPProtectionProfile{state.srtpProtectionProfile}, + ProtectionProfiles: []SRTPProtectionProfile{state.getSRTPProtectionProfile()}, }) } if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate { diff --git a/state.go b/state.go index a65d426bc..b04045ac9 100644 --- a/state.go +++ b/state.go @@ -24,7 +24,7 @@ type State struct { cipherSuite CipherSuite // nil if a cipherSuite hasn't been chosen CipherSuiteID CipherSuiteID - srtpProtectionProfile SRTPProtectionProfile // Negotiated SRTPProtectionProfile + srtpProtectionProfile atomic.Value // Negotiated SRTPProtectionProfile PeerCertificates [][]byte IdentityHint []byte SessionID []byte @@ -106,7 +106,7 @@ func (s *State) serialize() *serializedState { SequenceNumber: atomic.LoadUint64(&s.localSequenceNumber[epoch]), LocalRandom: localRnd, RemoteRandom: remoteRnd, - SRTPProtectionProfile: uint16(s.srtpProtectionProfile), + SRTPProtectionProfile: uint16(s.getSRTPProtectionProfile()), PeerCertificates: s.PeerCertificates, IdentityHint: s.IdentityHint, SessionID: s.SessionID, @@ -145,7 +145,7 @@ func (s *State) deserialize(serialized serializedState) { s.cipherSuite = cipherSuiteForID(s.CipherSuiteID, nil) atomic.StoreUint64(&s.localSequenceNumber[epoch], serialized.SequenceNumber) - s.srtpProtectionProfile = SRTPProtectionProfile(serialized.SRTPProtectionProfile) + s.setSRTPProtectionProfile(SRTPProtectionProfile(serialized.SRTPProtectionProfile)) // Set remote certificate s.PeerCertificates = serialized.PeerCertificates @@ -242,3 +242,15 @@ func (s *State) getLocalEpoch() uint16 { } return 0 } + +func (s *State) setSRTPProtectionProfile(profile SRTPProtectionProfile) { + s.srtpProtectionProfile.Store(profile) +} + +func (s *State) getSRTPProtectionProfile() SRTPProtectionProfile { + if val, ok := s.srtpProtectionProfile.Load().(SRTPProtectionProfile); ok { + return val + } + + return 0 +} From 3f3d83352fe612f5ab4176a7e4e5ac75f9487c65 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Dec 2023 01:14:06 +0000 Subject: [PATCH 067/146] Update module golang.org/x/crypto to v0.16.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 4b1daafaa..1756e72dd 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.8.4 - golang.org/x/crypto v0.14.0 + golang.org/x/crypto v0.16.0 golang.org/x/net v0.17.0 ) diff --git a/go.sum b/go.sum index e0d0f2652..7f774a5d2 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,9 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -42,12 +43,14 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -55,6 +58,7 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= From dc751e3b2df9f2bcfa04793fccc3b7df6aa670b8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Dec 2023 04:19:29 +0000 Subject: [PATCH 068/146] Update module golang.org/x/net to v0.19.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 1756e72dd..b1d6007f5 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.16.0 - golang.org/x/net v0.17.0 + golang.org/x/net v0.19.0 ) go 1.13 diff --git a/go.sum b/go.sum index 7f774a5d2..d407f9fb3 100644 --- a/go.sum +++ b/go.sum @@ -18,7 +18,6 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -29,8 +28,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -42,14 +41,12 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -57,7 +54,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= From 3e8a7d7ceff5cdcec0e7f71fbea6e8ba4dc3ac3f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 01:01:36 +0000 Subject: [PATCH 069/146] Update module golang.org/x/crypto to v0.17.0 [SECURITY] Generated by renovateBot --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index b1d6007f5..be9c26abe 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.8.4 - golang.org/x/crypto v0.16.0 + golang.org/x/crypto v0.17.0 golang.org/x/net v0.19.0 ) diff --git a/go.sum b/go.sum index d407f9fb3..224879b1f 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,9 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From 9ffd96c827fe61080545d986b417f21825f0e2c0 Mon Sep 17 00:00:00 2001 From: cnderrauber <zengjie9004@gmail.com> Date: Tue, 2 Jan 2024 10:52:08 +0800 Subject: [PATCH 070/146] Drop invalid record silently during handshake Fix issue: invalid record in handshake staging cause readloop exited then handshake failed. --- conn.go | 4 + conn_test.go | 79 +++++++++++++++++++- pkg/protocol/recordlayer/errors.go | 12 +-- pkg/protocol/recordlayer/recordlayer.go | 8 +- pkg/protocol/recordlayer/recordlayer_test.go | 4 +- 5 files changed, 95 insertions(+), 12 deletions(-) diff --git a/conn.go b/conn.go index b0d8cde4f..b1f552537 100644 --- a/conn.go +++ b/conn.go @@ -1026,6 +1026,10 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh } else { switch { case errors.Is(err, context.DeadlineExceeded), errors.Is(err, context.Canceled), errors.Is(err, io.EOF), errors.Is(err, net.ErrClosed): + case errors.Is(err, recordlayer.ErrInvalidPacketLength): + // Decode error must be silently discarded + // [RFC6347 Section-4.1.2.7] + continue default: if c.isHandshakeCompletedSuccessfully() { // Keep read loop and pass the read error to Read() diff --git a/conn_test.go b/conn_test.go index d3226d876..f0264df15 100644 --- a/conn_test.go +++ b/conn_test.go @@ -389,7 +389,7 @@ func TestHandshakeWithAlert(t *testing.T) { clientErr <- err }() - _, errServer := testServer(ctx, dtlsnet.PacketConnFromConn(cb), ca.RemoteAddr(), testCase.configServer, true) + _, errServer := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), testCase.configServer, true) if !errors.Is(errServer, testCase.errServer) { t.Fatalf("Server error exp(%v) failed(%v)", testCase.errServer, errServer) } @@ -402,6 +402,71 @@ func TestHandshakeWithAlert(t *testing.T) { } } +func TestHandshakeWithInvalidRecord(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(time.Second * 20) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + type result struct { + c *Conn + err error + } + clientErr := make(chan result, 1) + ca, cb := dpipe.Pipe() + caWithInvalidRecord := &connWithCallback{Conn: ca} + + var msgSeq atomic.Int32 + // Send invalid record after first message + caWithInvalidRecord.onWrite = func(b []byte) { + if msgSeq.Add(1) == 2 { + if _, err := ca.Write([]byte{0x01, 0x02}); err != nil { + t.Fatal(err) + } + } + } + go func() { + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(caWithInvalidRecord), caWithInvalidRecord.RemoteAddr(), &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + }, true) + clientErr <- result{client, err} + }() + + server, errServer := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + }, true) + + errClient := <-clientErr + + defer func() { + if server != nil { + if err := server.Close(); err != nil { + t.Fatal(err) + } + } + + if errClient.c != nil { + if err := errClient.c.Close(); err != nil { + t.Fatal(err) + } + } + }() + + if errServer != nil { + t.Fatalf("Server failed(%v)", errServer) + } + + if errClient.err != nil { + t.Fatalf("Client failed(%v)", errClient.err) + } +} + func TestExportKeyingMaterial(t *testing.T) { // Check for leaking routines report := test.CheckRoutines(t) @@ -3096,3 +3161,15 @@ func TestSkipHelloVerify(t *testing.T) { t.Error(err) } } + +type connWithCallback struct { + net.Conn + onWrite func([]byte) +} + +func (c *connWithCallback) Write(b []byte) (int, error) { + if c.onWrite != nil { + c.onWrite(b) + } + return c.Conn.Write(b) +} diff --git a/pkg/protocol/recordlayer/errors.go b/pkg/protocol/recordlayer/errors.go index cd4cb60a5..1c1898844 100644 --- a/pkg/protocol/recordlayer/errors.go +++ b/pkg/protocol/recordlayer/errors.go @@ -11,9 +11,11 @@ import ( ) var ( - errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 - errInvalidPacketLength = &protocol.TemporaryError{Err: errors.New("packet length and declared length do not match")} //nolint:goerr113 - errSequenceNumberOverflow = &protocol.InternalError{Err: errors.New("sequence number overflow")} //nolint:goerr113 - errUnsupportedProtocolVersion = &protocol.FatalError{Err: errors.New("unsupported protocol version")} //nolint:goerr113 - errInvalidContentType = &protocol.TemporaryError{Err: errors.New("invalid content type")} //nolint:goerr113 + // ErrInvalidPacketLength is returned when the packet length too small or declared length do not match + ErrInvalidPacketLength = &protocol.TemporaryError{Err: errors.New("packet length and declared length do not match")} //nolint:goerr113 + + errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 + errSequenceNumberOverflow = &protocol.InternalError{Err: errors.New("sequence number overflow")} //nolint:goerr113 + errUnsupportedProtocolVersion = &protocol.FatalError{Err: errors.New("unsupported protocol version")} //nolint:goerr113 + errInvalidContentType = &protocol.TemporaryError{Err: errors.New("invalid content type")} //nolint:goerr113 ) diff --git a/pkg/protocol/recordlayer/recordlayer.go b/pkg/protocol/recordlayer/recordlayer.go index 213a7976a..4acacf074 100644 --- a/pkg/protocol/recordlayer/recordlayer.go +++ b/pkg/protocol/recordlayer/recordlayer.go @@ -100,12 +100,12 @@ func UnpackDatagram(buf []byte) ([][]byte, error) { for offset := 0; len(buf) != offset; { if len(buf)-offset <= FixedHeaderSize { - return nil, errInvalidPacketLength + return nil, ErrInvalidPacketLength } pktLen := (FixedHeaderSize + int(binary.BigEndian.Uint16(buf[offset+11:]))) if offset+pktLen > len(buf) { - return nil, errInvalidPacketLength + return nil, ErrInvalidPacketLength } out = append(out, buf[offset:offset+pktLen]) @@ -129,12 +129,12 @@ func ContentAwareUnpackDatagram(buf []byte, cidLength int) ([][]byte, error) { lenIdx += cidLength } if len(buf)-offset <= headerSize { - return nil, errInvalidPacketLength + return nil, ErrInvalidPacketLength } pktLen := (headerSize + int(binary.BigEndian.Uint16(buf[offset+lenIdx:]))) if offset+pktLen > len(buf) { - return nil, errInvalidPacketLength + return nil, ErrInvalidPacketLength } out = append(out, buf[offset:offset+pktLen]) diff --git a/pkg/protocol/recordlayer/recordlayer_test.go b/pkg/protocol/recordlayer/recordlayer_test.go index 2e16c0104..760a73040 100644 --- a/pkg/protocol/recordlayer/recordlayer_test.go +++ b/pkg/protocol/recordlayer/recordlayer_test.go @@ -39,12 +39,12 @@ func TestUDPDecode(t *testing.T) { { Name: "Invalid packet length", Data: []byte{0x14, 0xfe}, - WantError: errInvalidPacketLength, + WantError: ErrInvalidPacketLength, }, { Name: "Packet declared invalid length", Data: []byte{0x14, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xFF, 0x01}, - WantError: errInvalidPacketLength, + WantError: ErrInvalidPacketLength, }, } { dtlsPkts, err := UnpackDatagram(test.Data) From b4a403c9d455518467390c634f9ff78115bb2b84 Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Tue, 2 Jan 2024 11:41:43 -0500 Subject: [PATCH 071/146] Remove 'Generate Authors' workflow pion/.goassets#185 --- .github/workflows/generate-authors.yml | 23 ---------- AUTHORS.txt | 62 -------------------------- 2 files changed, 85 deletions(-) delete mode 100644 .github/workflows/generate-authors.yml delete mode 100644 AUTHORS.txt diff --git a/.github/workflows/generate-authors.yml b/.github/workflows/generate-authors.yml deleted file mode 100644 index ec7446c84..000000000 --- a/.github/workflows/generate-authors.yml +++ /dev/null @@ -1,23 +0,0 @@ -# -# 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. -# -# SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> -# SPDX-License-Identifier: MIT - -name: Generate Authors - -on: - pull_request: - -jobs: - generate: - uses: pion/.goassets/.github/workflows/generate-authors.reusable.yml@master - secrets: - token: ${{ secrets.PIONBOT_PRIVATE_KEY }} diff --git a/AUTHORS.txt b/AUTHORS.txt deleted file mode 100644 index d80ca9973..000000000 --- a/AUTHORS.txt +++ /dev/null @@ -1,62 +0,0 @@ -# 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 https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -Aleksandr Razumov <ar@gortc.io> -alvarowolfx <alvarowolfx@gmail.com> -Arlo Breault <arlolra@gmail.com> -Atsushi Watanabe <atsushi.w@ieee.org> -backkem <mail@backkem.me> -bjdgyc <bjdgyc@163.com> -boks1971 <raja.gobi@tutanota.com> -Bragadeesh <bragboy@gmail.com> -Carson Hoffman <c@rsonhoffman.com> -Cecylia Bocovich <cohosh@torproject.org> -Chris Hiszpanski <thinkski@users.noreply.github.com> -cnderrauber <zengjie9004@gmail.com> -Daniel Mangum <georgedanielmangum@gmail.com> -Daniele Sluijters <daenney@users.noreply.github.com> -folbrich <frank.olbricht@gmail.com> -Hayden James <hayden.james@gmail.com> -Hugo Arregui <hugo.arregui@gmail.com> -Hugo Arregui <hugo@decentraland.org> -igolaizola <11333576+igolaizola@users.noreply.github.com> -Jeffrey Stoke <me@arhat.dev> -Jeroen de Bruijn <vidavidorra+jdbruijn@gmail.com> -Jeroen de Bruijn <vidavidorra@gmail.com> -Jim Wert <jimwert@gmail.com> -jinleileiking <jinleileiking@gmail.com> -Jozef Kralik <jojo.lwin@gmail.com> -Julien Salleyron <julien.salleyron@gmail.com> -Juliusz Chroboczek <jch@irif.fr> -Kegan Dougal <kegan@matrix.org> -Kevin Wang <kevmo314@gmail.com> -Lander Noterman <lander.noterman@basalte.be> -Len <len@hpcnt.com> -Lukas Lihotzki <lukas@lihotzki.de> -ManuelBk <26275612+ManuelBk@users.noreply.github.com> -Michael Zabka <zabka.michael@gmail.com> -Michiel De Backker <mail@backkem.me> -mschexnaydre <mschex@viasat.com> -Rachel Chen <rachel@chens.email> -Robert Eperjesi <eperjesi@uber.com> -Ryan Gordon <ryan.gordon@getcruise.com> -Sam Lancia <sam.lancia@motorolasolutions.com> -Sean <sean@pion.ly> -Sean DuBois <duboisea@justin.tv> -Sean DuBois <seaduboi@amazon.com> -Sean DuBois <sean@pion.ly> -Sean DuBois <sean@siobud.com> -Shelikhoo <xiaokangwang@outlook.com> -Stefan Tatschner <stefan@rumpelsepp.org> -Steffen Vogel <post@steffenvogel.de> -Vadim <fffilimonov@yandex.ru> -Vadim Filimonov <fffilimonov@yandex.ru> -wmiao <wu.miao@viasat.com> -Xinjun Ma <xinjun.ma@qq.com> -ZHENK <chengzhenyang@gmail.com> -吕海涛 <hi@taoshu.in> - -# List of contributors not appearing in Git history - From cfa868ce119cafe9d5c9833b2a147659a076943d Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Tue, 2 Jan 2024 12:39:47 -0500 Subject: [PATCH 072/146] Remove 'AUTHORS.txt' from README.md Relates to pion/.goassets#185 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c0659593..aa0bbc787 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ We are always looking to support **your projects**. Please reach out if you have If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt) +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text From 520d84c38b87bfc18e61c089ca52a8a88e4f3230 Mon Sep 17 00:00:00 2001 From: Pion <59523206+pionbot@users.noreply.github.com> Date: Tue, 2 Jan 2024 19:13:58 +0000 Subject: [PATCH 073/146] Update CI configs to v0.11.0 Update lint scripts and CI configs. --- .golangci.yml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 4e3eddf42..6dd80c805 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -29,7 +29,6 @@ linters: - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - 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()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together @@ -63,7 +62,6 @@ linters: - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - noctx # noctx finds sending http request without context.Context @@ -81,6 +79,7 @@ linters: - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages - containedctx # containedctx is a linter that detects struct contained context.Context field - cyclop # checks function and package cyclomatic complexity - exhaustivestruct # Checks if all struct's fields are initialized @@ -94,6 +93,7 @@ linters: - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - maligned # Tool to detect Go structs that would take less memory if their fields were sorted + - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - nolintlint # Reports ill-formed or insufficient nolint directives @@ -111,22 +111,11 @@ linters: issues: exclude-use-default: false exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) linters: - - gocognit - forbidigo - - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" - linters: - gocognit - - # Allow forbidden identifiers in examples - - path: examples - linters: - - forbidigo # Allow forbidden identifiers in CLI commands - path: cmd From ba72fba742a7e5f89aef415aa6042bc9c84971ed Mon Sep 17 00:00:00 2001 From: Pion <59523206+pionbot@users.noreply.github.com> Date: Fri, 5 Jan 2024 00:02:41 +0000 Subject: [PATCH 074/146] Update CI configs to v0.11.3 Update lint scripts and CI configs. --- .github/workflows/test.yaml | 4 ++-- .github/workflows/tidy-check.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 31aada4af..c8294ef1f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -23,7 +23,7 @@ jobs: uses: pion/.goassets/.github/workflows/test.reusable.yml@master strategy: matrix: - go: ['1.20', '1.19'] # auto-update/supported-go-version-list + go: ['1.21', '1.20'] # auto-update/supported-go-version-list fail-fast: false with: go-version: ${{ matrix.go }} @@ -32,7 +32,7 @@ jobs: uses: pion/.goassets/.github/workflows/test-i386.reusable.yml@master strategy: matrix: - go: ['1.20', '1.19'] # auto-update/supported-go-version-list + go: ['1.21', '1.20'] # auto-update/supported-go-version-list fail-fast: false with: go-version: ${{ matrix.go }} diff --git a/.github/workflows/tidy-check.yaml b/.github/workflows/tidy-check.yaml index 4d346d4fd..33d6b507c 100644 --- a/.github/workflows/tidy-check.yaml +++ b/.github/workflows/tidy-check.yaml @@ -22,4 +22,4 @@ jobs: tidy: uses: pion/.goassets/.github/workflows/tidy-check.reusable.yml@master with: - go-version: '1.20' # auto-update/latest-go-version + go-version: '1.21' # auto-update/latest-go-version From 798b32a0050573e8e65bdfe700038d68484a1384 Mon Sep 17 00:00:00 2001 From: minlpli <minlpli@tencent.com> Date: Wed, 6 Dec 2023 17:10:49 +0800 Subject: [PATCH 075/146] Fix flight1parse processing exception --- flight1handler_test.go | 283 +++++++++++++++++++++++++++++++++++++++++ handshake_cache.go | 4 +- 2 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 flight1handler_test.go diff --git a/flight1handler_test.go b/flight1handler_test.go new file mode 100644 index 000000000..80c8ec770 --- /dev/null +++ b/flight1handler_test.go @@ -0,0 +1,283 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +package dtls + +import ( + "context" + "testing" + "time" + + "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/logging" + "github.com/pion/transport/v3/test" +) + +type flight1TestMockFlightConn struct{} + +func (f *flight1TestMockFlightConn) notify(context.Context, alert.Level, alert.Description) error { + return nil +} +func (f *flight1TestMockFlightConn) writePackets(context.Context, []*packet) error { return nil } +func (f *flight1TestMockFlightConn) recvHandshake() <-chan chan struct{} { return nil } +func (f *flight1TestMockFlightConn) setLocalEpoch(uint16) {} +func (f *flight1TestMockFlightConn) handleQueuedPackets(context.Context) error { return nil } +func (f *flight1TestMockFlightConn) sessionKey() []byte { return nil } + +type flight1TestMockCipherSuite struct { + ciphersuite.TLSEcdheEcdsaWithAes128GcmSha256 + + t *testing.T +} + +func (f *flight1TestMockCipherSuite) IsInitialized() bool { + f.t.Fatal("IsInitialized called with Certificate but not CertificateVerify") + return true +} + +// When "server hello" arrives later than "certificate", +// "server key exchange", "certificate request", "server hello done", +// is it normal for the flight1Parse method to handle it +func TestFlight1_Process_ServerHelloLateArrival(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(5 * time.Second) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + mockConn := &flight1TestMockFlightConn{} + state := &State{ + cipherSuite: &flight1TestMockCipherSuite{t: t}, + } + cache := newHandshakeCache() + cfg := &handshakeConfig{ + localSRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AEAD_AES_128_GCM}, + localCipherSuites: []CipherSuite{}, + } + cfg.localCipherSuites = []CipherSuite{cipherSuiteForID(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, nil)} + cfg.log = logging.NewDefaultLoggerFactory().NewLogger("dtls") + + serverHello := []byte{ + 0x02, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x62, 0xfe, 0xfd, 0x07, 0x46, 0xb7, 0xbf, 0xde, 0x78, + 0xab, 0x38, 0x69, 0x36, 0x74, 0x10, 0xa6, 0x50, 0x67, 0x7b, + 0x4b, 0x85, 0xdf, 0x71, 0x71, 0x62, 0x3a, 0xb1, 0xd7, 0xa4, + 0x79, 0x6a, 0x38, 0x13, 0x5e, 0xa1, 0x20, 0xbd, 0x64, 0xaf, + 0xb3, 0x36, 0x77, 0x73, 0x8a, 0x62, 0x75, 0xb2, 0x64, 0xbe, + 0xf6, 0x2a, 0xb1, 0x6e, 0x7b, 0xf6, 0x00, 0xd6, 0x24, 0xd5, + 0xb1, 0x1e, 0x54, 0xa3, 0x76, 0xb3, 0xac, 0x76, 0x8f, 0xc0, + 0x2f, 0x00, 0x00, 0x1a, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, + 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x00, 0x0e, 0x00, + 0x05, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x17, 0x00, 0x00, + } + certificate1 := []byte{0x0b, 0x00, 0x05, 0x5b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x04, 0xe4, 0x00, 0x05, 0x58, 0x00, 0x05, 0x55, 0x30, 0x82, + 0x05, 0x51, 0x30, 0x82, 0x04, 0x39, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x0c, 0x56, 0x8b, 0xb4, 0x68, 0xed, 0x70, 0xce, + 0xb6, 0x8d, 0x44, 0x65, 0x4b, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, + 0x30, 0x66, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x47, 0x6c, 0x6f, 0x62, + 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x6e, 0x76, 0x2d, + 0x73, 0x61, 0x31, 0x3c, 0x30, 0x3a, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x33, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, + 0x69, 0x67, 0x6e, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x41, + 0x20, 0x2d, 0x20, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x20, + 0x2d, 0x20, 0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, + 0x30, 0x34, 0x32, 0x30, 0x31, 0x31, 0x31, 0x39, 0x35, 0x39, + 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x34, 0x32, 0x31, 0x31, + 0x31, 0x31, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0x84, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x43, 0x4e, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x09, 0x67, 0x75, 0x61, 0x6e, 0x67, 0x64, 0x6f, + 0x6e, 0x67, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x08, 0x73, 0x68, 0x65, 0x6e, 0x7a, 0x68, 0x65, + 0x6e, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x13, 0x2d, 0x54, 0x65, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x20, + 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, + 0x20, 0x28, 0x53, 0x68, 0x65, 0x6e, 0x7a, 0x68, 0x65, 0x6e, + 0x29, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, 0x77, 0x65, + 0x62, 0x72, 0x74, 0x63, 0x2e, 0x71, 0x71, 0x2e, 0x63, 0x6f, + 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, + 0x82, 0x01, 0x01, 0x00, 0xb6, 0x00, 0xa7, 0x09, 0x0a, 0xc4, + 0x96, 0x24, 0x72, 0xa0, 0x09, 0xda, 0xac, 0x63, 0xe4, 0x9a, + 0xfe, 0x8b, 0x9b, 0x99, 0x8c, 0xe3, 0xab, 0x4b, 0x7c, 0xbd, + 0x4f, 0x31, 0x1e, 0x2f, 0xff, 0x34, 0x54, 0xb5, 0xb0, 0x99, + 0xcd, 0x00, 0x7c, 0x5b, 0x12, 0x96, 0xfa, 0x9b, 0x6b, 0x79, + 0xc7, 0xfb, 0x00, 0x53, 0xaf, 0xb6, 0x00, 0x45, 0x46, 0x20, + 0x7d, 0x95, 0xca, 0x86, 0xcc, 0x4b, 0xe8, 0x25, 0x52, 0x5b, + 0x9c, 0xe7, 0x58, 0xcd, 0xd0, 0x8f, 0x4a, 0xd8, 0x77, 0x7d, + 0x45, 0xa0, 0x70, 0xe8, 0x16, 0x45, 0x23, 0xfb, 0xbc, 0x43, + 0x36, 0xdd, 0x5b, 0x8f, 0x01, 0xc3, 0xc0, 0xa2, 0xab, 0x80, + 0xf1, 0x97, 0x72, 0x38, 0xab, 0x6f, 0xa1, 0x28, 0x09, 0xdd, + 0x31, 0x7e, 0x50, 0xc8, 0x51, 0xde, 0x8d, 0x05, 0xbc, 0x72, + 0x79, 0x94, 0x6e, 0xd4, 0xb7, 0xf0, 0x97, 0xd0, 0x76, 0x9c, + 0x9d, 0xb4, 0x34, 0xf1, 0x8a, 0x82, 0x20, 0x9b, 0x24, 0x4b, + 0x38, 0xc9, 0x63, 0xe6, 0x02, 0xf5, 0xb2, 0x9b, 0x70, 0xa4, + 0x97, 0x9f, 0xaa, 0x1f, 0x36, 0x9c, 0xfd, 0x81, 0x93, 0x81, + 0xd7, 0x4e, 0xca, 0xd2, 0xa7, 0x7c, 0x29, 0x9d, 0x28, 0xf2, + 0x3e, 0x3b, 0xea, 0xe6, 0x22, 0x51, 0x8f, 0x0b, 0xe7, 0x65, + 0xa1, 0x28, 0xdd, 0x55, 0x6a, 0x59, 0x53, 0x67, 0xb6, 0xb3, + 0xd2, 0x4c, 0x90, 0x69, 0xd1, 0x1e, 0x62, 0xab, 0x33, 0x47, + 0x29, 0x45, 0x18, 0x1f, 0xeb, 0x6d, 0x13, 0xb4, 0x61, 0xf5, + 0x15, 0x03, 0xf7, 0x4f, 0x9c, 0x4c, 0x2c, 0xae, 0x5e, 0xde, + 0xd2, 0x11, 0x32, 0xb5, 0x17, 0xb5, 0xe8, 0xa3, 0xb2, 0x1f, + 0xc3, 0x9f, 0x78, 0xa1, 0xf5, 0x80, 0xb4, 0x96, 0x90, 0x6b, + 0x77, 0x9e, 0xe9, 0x39, 0x61, 0x2c, 0x18, 0xf5, 0x7b, 0xab, + 0x1e, 0x09, 0x88, 0x7d, 0xc3, 0x75, 0x5e, 0x4d, 0xcf, 0xf3, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xde, 0x30, + 0x82, 0x01, 0xda, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, + 0x81, 0xa0, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x01, 0x01, 0x04, 0x81, 0x93, 0x30, 0x81, 0x90, 0x30, 0x4d, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, + 0x86, 0x41, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73, + 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x67, 0x6c, 0x6f, 0x62, + 0x61, 0x6c, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74, 0x2f, 0x67, 0x73, + 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x76, 0x61, 0x6c, 0x73, 0x68, 0x61, 0x32, 0x67, + 0x32, 0x72, 0x31, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x3f, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, + 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, + 0x73, 0x70, 0x32, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, + 0x73, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x76, 0x61, 0x6c, 0x73, 0x68, 0x61, 0x32, + 0x67, 0x32, 0x30, 0x56, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, + 0x4f, 0x30, 0x4d, 0x30, 0x41, 0x06, 0x09, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0xa0, 0x32, 0x01, 0x14, 0x30, 0x34, 0x30, 0x32, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, + 0x16, 0x26, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, + 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, + 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01, 0x02, 0x02, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, + 0x00, 0x30, 0x49, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x42, + 0x30, 0x40, 0x30, 0x3e, 0xa0, 0x3c, 0xa0, 0x3a, 0x86, 0x38, + 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, + 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x73, 0x2f, 0x67, + 0x73, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x76, 0x61, 0x6c, 0x73, 0x68, 0x61, 0x32, + 0x67, 0x32, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x1d, 0x11, 0x04, 0x11, 0x30, 0x0f, 0x82, 0x0d, 0x77, + 0x65, 0x62, 0x72, 0x74, 0x63, 0x2e, 0x71, 0x71, 0x2e, 0x63, + 0x6f, 0x6d, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, + 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x03, 0x02, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, + 0x04, 0x16, 0x04, 0x14, 0x28, 0xff, 0xe2, 0x97, 0xf3, 0x6f, + 0x2a, 0xef, 0x0f, 0xbc, 0x4c, 0x61, 0x9b, 0xd9, 0x23, 0x7b, + 0x3a, 0xef, 0xc2, 0xe7, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x96, 0xde, 0x61, + 0xf1, 0xbd, 0x1c, 0x16, 0x29, 0x53, 0x1c, 0xc0, 0xcc, 0x7d, + 0x3b, 0x83, 0x00, 0x40, 0xe6, 0x1a, 0x7c, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x30, 0xc1, 0xcc, + 0xd6, 0x97, 0xf7, 0xf5, 0xa7, 0x93, 0xa5, 0x78, 0xc8, 0xcb, + 0x81, 0x44, 0xd4, 0x1f, 0x2a, 0xa6, 0xc1, 0x48, 0xa8, 0x1a, + 0xbd, 0x17, 0x10, 0x0e, 0xdf, 0x21, 0xea, 0x02, 0x3e, 0xb3, + 0xbd, 0x45, 0x1e, 0x64, 0x85, 0x3f, 0x04, 0x9a, 0xc0, 0x78, + 0xf4, 0x81, 0x2e, 0x38, 0x39, 0x3a, 0x04, 0x2d, 0x5f, 0xec, + 0xc4, 0x10, 0x57, 0xfb, 0x1b, 0x32, 0xe0, 0x8e, 0xfc, 0xe3, + 0x6d, 0x4b, 0xc6, 0xf0, 0x07, 0xb7, 0xc6, 0x19, 0xd7, 0x99, + 0x93, 0xbd, 0x60, 0x58, 0xad, 0xbb, 0x94, 0xcf, 0xd8, 0x05, + 0x5c, 0x14, 0x70, 0xec, 0x2e, 0xb7, 0x60, 0x52, 0x3c, 0xd3, + 0x03, 0xf8, 0xcd, 0xe5, 0x4e, 0x84, 0xcf, 0xef, 0x2f, 0x12, + 0xdd, 0x74, 0xfd, 0x95, 0x9d, 0x03, 0xa9, 0x81, 0x18, 0x3a, + 0x6e, 0xe6, 0xc2, 0xdd, 0x07, 0x1e, 0xea, 0x8c, 0xe6, 0xd9, + 0x31, 0x72, 0x63, 0x25, 0xcd, 0xf2, 0x19, 0xf2, 0x4e, 0x3c, + 0x18, 0xfb, 0xb2, 0x74, + } + certificate2 := []byte{ + 0x0b, 0x00, 0x05, 0x5b, 0x00, 0x01, 0x00, 0x04, 0xe4, 0x00, + 0x00, 0x77, 0xc1, 0x6b, 0x67, 0xec, 0x34, 0x05, 0xe8, 0x63, + 0xfc, 0x74, 0x4b, 0x11, 0x3f, 0x3a, 0xe4, 0x4e, 0x06, 0x89, + 0x96, 0x24, 0x3c, 0x15, 0x83, 0xc5, 0x1d, 0xeb, 0xc0, 0x19, + 0x71, 0x35, 0x6c, 0xfa, 0xf1, 0x51, 0x06, 0x0e, 0x8e, 0xfb, + 0x9b, 0x4e, 0xaa, 0x50, 0x24, 0x77, 0xac, 0x86, 0x14, 0x50, + 0x52, 0x35, 0x68, 0x15, 0x9b, 0xdd, 0x8b, 0xdb, 0x83, 0x1d, + 0xed, 0x45, 0x05, 0x78, 0x53, 0xd6, 0xc4, 0x21, 0xaf, 0x68, + 0x45, 0x91, 0xe7, 0x30, 0x36, 0x4c, 0xb1, 0xfb, 0xf1, 0x65, + 0x9a, 0xe4, 0x49, 0x90, 0x1c, 0x0c, 0xa8, 0x63, 0xe9, 0x04, + 0xe3, 0x17, 0x61, 0x8d, 0x20, 0x29, 0xca, 0x41, 0xa6, 0x8b, + 0x32, 0x53, 0xa5, 0x84, 0x29, 0x5a, 0x62, 0xe7, 0x84, 0x38, + 0x32, 0x56, 0xbb, 0x8b, 0xbc, 0x25, 0xc7, 0xa3, 0x28, 0x3b, + 0x35, + } + serverKeyExchange := []byte{ + 0x0c, 0x00, 0x01, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x28, 0x03, 0x00, 0x1d, 0x20, 0x59, 0xa2, 0x0f, 0xc4, + 0x7b, 0xd8, 0x03, 0xf6, 0xb0, 0xcf, 0x5d, 0xf0, 0x45, 0x7f, + 0x7e, 0xf2, 0x98, 0xab, 0xc0, 0x24, 0xf1, 0xdf, 0xba, 0x63, + 0x3e, 0xfb, 0xe5, 0x02, 0x31, 0xcf, 0xd1, 0x05, 0x04, 0x01, + 0x01, 0x00, 0x7b, 0x52, 0x9c, 0xe7, 0x54, 0x8b, 0xb0, 0xc9, + 0xfd, 0xaf, 0xe2, 0x91, 0x19, 0x9d, 0x6c, 0xb8, 0xbe, 0xa5, + 0xe1, 0x48, 0xa0, 0xfd, 0xc5, 0x76, 0x62, 0x47, 0xf2, 0xd1, + 0x35, 0x76, 0x4e, 0x33, 0xf4, 0xa1, 0xf1, 0x58, 0xdc, 0xd5, + 0x45, 0x3f, 0x76, 0x64, 0x40, 0xba, 0x32, 0xe3, 0x07, 0xb7, + 0x4b, 0xbe, 0xe2, 0x77, 0x99, 0xad, 0x11, 0x73, 0x54, 0xe6, + 0xbb, 0xfb, 0xd4, 0xb1, 0x83, 0x9f, 0xc6, 0x50, 0xc6, 0xd8, + 0xbb, 0x92, 0x0d, 0x93, 0xf9, 0x63, 0x29, 0xf9, 0xc3, 0xce, + 0x24, 0x40, 0x29, 0x95, 0x43, 0xf0, 0x32, 0x00, 0x21, 0xde, + 0xdf, 0x64, 0xfe, 0xb6, 0x11, 0xa0, 0x11, 0x44, 0x12, 0x2a, + 0x1c, 0x96, 0x44, 0x4b, 0x79, 0x31, 0x23, 0x46, 0x4e, 0xe8, + 0x16, 0x5b, 0xf5, 0x9a, 0x5f, 0x51, 0x10, 0x5b, 0x11, 0xa3, + 0xb8, 0x1f, 0xb7, 0xf1, 0x11, 0xad, 0x05, 0x82, 0x2b, 0xc3, + 0x65, 0x8c, 0x41, 0xb4, 0x8e, 0x60, 0x42, 0x89, 0x92, 0xd1, + 0x83, 0x73, 0xe7, 0x35, 0xb4, 0xc9, 0xd1, 0xbc, 0x5c, 0x84, + 0x5b, 0xdb, 0x44, 0x34, 0xea, 0xd8, 0x06, 0xe4, 0xfb, 0xbd, + 0x40, 0x35, 0x18, 0x60, 0x33, 0xb6, 0xed, 0xbc, 0x9b, 0x3a, + 0xff, 0x2f, 0xa1, 0xe8, 0x5d, 0x5c, 0xbb, 0xe8, 0xe1, 0xa6, + 0xbb, 0x84, 0x0f, 0x50, 0x51, 0x0d, 0xa5, 0x8f, 0x96, 0xb6, + 0x35, 0x37, 0x7b, 0x58, 0xaf, 0x4f, 0x77, 0x9d, 0x5d, 0xb2, + 0xff, 0x5f, 0xd6, 0xb8, 0x82, 0x64, 0x5f, 0x79, 0xd0, 0x06, + 0x44, 0x6d, 0x3a, 0x82, 0x25, 0x21, 0xca, 0xbb, 0xa0, 0x79, + 0xdd, 0x6e, 0x15, 0xb6, 0x57, 0x9b, 0x04, 0x84, 0x63, 0x88, + 0x1d, 0x41, 0xff, 0xe1, 0x20, 0x61, 0xd5, 0x3f, 0xc7, 0xca, + 0x0c, 0xd9, 0xe0, 0x74, 0x86, 0x78, 0xed, 0x60, 0x18, 0x2d, + 0x9e, 0x69, 0x66, 0x77, 0xf7, 0xd0, 0xe9, 0x9c, + } + certificateRequest := []byte{ + 0x0d, 0x00, 0x00, 0x26, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x26, 0x03, 0x01, 0x02, 0x40, 0x00, 0x1e, 0x06, 0x01, + 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05, 0x02, 0x05, 0x03, + 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, + 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00, + } + serverHelloDone := []byte{ + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + } + cache.push(certificate2, 0, 2, handshake.TypeCertificate, false) + cache.push(serverKeyExchange, 0, 3, handshake.TypeServerKeyExchange, false) + cache.push(certificateRequest, 0, 4, handshake.TypeCertificateRequest, false) + cache.push(serverHelloDone, 0, 5, handshake.TypeServerHelloDone, false) + + if _, alt, err := flight1Parse(context.TODO(), mockConn, state, cache, cfg); err != nil { + t.Fatal(err) + } else if alt != nil { + t.Fatal(alt.String()) + } + + cache.push(serverHello, 0, 0, handshake.TypeServerHello, false) + cache.push(certificate1, 0, 1, handshake.TypeCertificate, false) + if _, alt, err := flight1Parse(context.TODO(), mockConn, state, cache, cfg); err != nil { + t.Fatal(err) + } else if alt != nil { + t.Fatal(alt.String()) + } +} diff --git a/handshake_cache.go b/handshake_cache.go index 8d5960568..3566f2fe4 100644 --- a/handshake_cache.go +++ b/handshake_cache.go @@ -97,6 +97,7 @@ func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rule } out := make(map[handshake.Type]handshake.Message) seq := startSeq + ok := false for _, r := range rules { t := r.typ i := ci[t] @@ -118,9 +119,10 @@ func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rule return startSeq, nil, false } seq++ + ok = true out[t] = rawHandshake.Message } - return seq, out, true + return seq, out, ok } // pullAndMerge calls pull and then merges the results, ignoring any null entries From 34278191427beb2631c9c5b1f5d5f0abfbc23b96 Mon Sep 17 00:00:00 2001 From: minlpli <minlpli@tencent.com> Date: Wed, 6 Dec 2023 23:51:57 +0800 Subject: [PATCH 076/146] Format code --- flight1handler_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flight1handler_test.go b/flight1handler_test.go index 80c8ec770..2d590dcc9 100644 --- a/flight1handler_test.go +++ b/flight1handler_test.go @@ -74,7 +74,8 @@ func TestFlight1_Process_ServerHelloLateArrival(t *testing.T) { 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x00, 0x0e, 0x00, 0x05, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x17, 0x00, 0x00, } - certificate1 := []byte{0x0b, 0x00, 0x05, 0x5b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + certificate1 := []byte{ + 0x0b, 0x00, 0x05, 0x5b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0xe4, 0x00, 0x05, 0x58, 0x00, 0x05, 0x55, 0x30, 0x82, 0x05, 0x51, 0x30, 0x82, 0x04, 0x39, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0c, 0x56, 0x8b, 0xb4, 0x68, 0xed, 0x70, 0xce, From bb54a30e67830ba54cb500293af2bcab3b7d5d5a Mon Sep 17 00:00:00 2001 From: minlpli <minlpli@tencent.com> Date: Tue, 2 Jan 2024 19:31:56 +0800 Subject: [PATCH 077/146] If not found in the cache return nil --- handshake_cache.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/handshake_cache.go b/handshake_cache.go index 3566f2fe4..85c87e640 100644 --- a/handshake_cache.go +++ b/handshake_cache.go @@ -122,7 +122,10 @@ func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rule ok = true out[t] = rawHandshake.Message } - return seq, out, ok + if !ok { + return seq, nil, false + } + return seq, out, true } // pullAndMerge calls pull and then merges the results, ignoring any null entries From 42b677298b10d25c6b27dbbfcf7177c8b7ff2408 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 01:11:16 +0000 Subject: [PATCH 078/146] Update module golang.org/x/crypto to v0.18.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index be9c26abe..3896fb2a8 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.8.4 - golang.org/x/crypto v0.17.0 + golang.org/x/crypto v0.18.0 golang.org/x/net v0.19.0 ) diff --git a/go.sum b/go.sum index 224879b1f..38fc0d00f 100644 --- a/go.sum +++ b/go.sum @@ -19,8 +19,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -43,12 +43,14 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= From 2597464081c866b6d36d40ed30aefd89f299e125 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 03:23:14 +0000 Subject: [PATCH 079/146] Update module golang.org/x/net to v0.20.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3896fb2a8..043091f22 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.18.0 - golang.org/x/net v0.19.0 + golang.org/x/net v0.20.0 ) go 1.13 diff --git a/go.sum b/go.sum index 38fc0d00f..be00e338b 100644 --- a/go.sum +++ b/go.sum @@ -18,7 +18,6 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -29,8 +28,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -42,14 +41,12 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 96b8c2993ac4eceffd5483fd05b3819ac7a8ea65 Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Fri, 15 Mar 2024 22:08:44 -0400 Subject: [PATCH 080/146] Fix linter errors golangci-lint upgrade to v1.56.2 added more checks Relates to .goassets/#201 --- certificate_test.go | 2 +- cipher_suite_test.go | 4 ++-- config_test.go | 10 ++++---- conn.go | 2 +- conn_test.go | 24 +++++++++---------- crypto_test.go | 1 + handshaker_test.go | 4 ++-- .../message_server_key_exchange_test.go | 4 ++-- 8 files changed, 26 insertions(+), 25 deletions(-) diff --git a/certificate_test.go b/certificate_test.go index 5f2e87bb4..8c0868f45 100644 --- a/certificate_test.go +++ b/certificate_test.go @@ -77,7 +77,7 @@ func TestGetCertificate(t *testing.T) { }, { desc: "Get certificate from callback", - getCertificate: func(info *ClientHelloInfo) (*tls.Certificate, error) { + getCertificate: func(*ClientHelloInfo) (*tls.Certificate, error) { return &certificateTest, nil }, expectedCertificate: certificateTest, diff --git a/cipher_suite_test.go b/cipher_suite_test.go index c04220dee..3aa4c8fe6 100644 --- a/cipher_suite_test.go +++ b/cipher_suite_test.go @@ -98,13 +98,13 @@ func TestCustomCipherSuite(t *testing.T) { } } - t.Run("Custom ID", func(t *testing.T) { + t.Run("Custom ID", func(*testing.T) { runTest(func() []CipherSuite { return []CipherSuite{&testCustomCipherSuite{authenticationType: CipherSuiteAuthenticationTypeCertificate}} }) }) - t.Run("Anonymous Cipher", func(t *testing.T) { + t.Run("Anonymous Cipher", func(*testing.T) { runTest(func() []CipherSuite { return []CipherSuite{&testCustomCipherSuite{authenticationType: CipherSuiteAuthenticationTypeAnonymous}} }) diff --git a/config_test.go b/config_test.go index 811427a0c..806d66929 100644 --- a/config_test.go +++ b/config_test.go @@ -47,7 +47,7 @@ func TestValidateConfig(t *testing.T) { "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) { + PSK: func([]byte) ([]byte, error) { return nil, nil }, Certificates: []tls.Certificate{cert}, @@ -56,7 +56,7 @@ func TestValidateConfig(t *testing.T) { "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) { + PSK: func([]byte) ([]byte, error) { return nil, nil }, Certificates: []tls.Certificate{cert}, @@ -66,7 +66,7 @@ func TestValidateConfig(t *testing.T) { "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) { + PSK: func([]byte) ([]byte, error) { return nil, nil }, Certificates: []tls.Certificate{cert}, @@ -108,7 +108,7 @@ func TestValidateConfig(t *testing.T) { "Valid config with get certificate": { config: &Config{ CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, - GetCertificate: func(chi *ClientHelloInfo) (*tls.Certificate, error) { + GetCertificate: func(*ClientHelloInfo) (*tls.Certificate, error) { return &tls.Certificate{Certificate: cert.Certificate, PrivateKey: rsaPrivateKey}, nil }, }, @@ -116,7 +116,7 @@ func TestValidateConfig(t *testing.T) { "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) { + GetClientCertificate: func(*CertificateRequestInfo) (*tls.Certificate, error) { return &tls.Certificate{Certificate: cert.Certificate, PrivateKey: rsaPrivateKey}, nil }, }, diff --git a/conn.go b/conn.go index b1f552537..d4259f9e8 100644 --- a/conn.go +++ b/conn.go @@ -972,7 +972,7 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh done := make(chan struct{}) ctxRead, cancelRead := context.WithCancel(context.Background()) c.cancelHandshakeReader = cancelRead - cfg.onFlightState = func(f flightVal, s handshakeState) { + cfg.onFlightState = func(_ flightVal, s handshakeState) { if s == handshakeFinished && !c.isHandshakeCompletedSuccessfully() { c.setHandshakeCompletedSuccessfully() close(done) diff --git a/conn_test.go b/conn_test.go index f0264df15..f0a961afc 100644 --- a/conn_test.go +++ b/conn_test.go @@ -424,7 +424,7 @@ func TestHandshakeWithInvalidRecord(t *testing.T) { var msgSeq atomic.Int32 // Send invalid record after first message - caWithInvalidRecord.onWrite = func(b []byte) { + caWithInvalidRecord.onWrite = func([]byte) { if msgSeq.Add(1) == 2 { if _, err := ca.Write([]byte{0x01, 0x02}); err != nil { t.Fatal(err) @@ -556,7 +556,7 @@ func TestPSK(t *testing.T) { 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 { + ServerVerifyConnection: func(*State) error { return errExample }, WantFail: true, @@ -567,7 +567,7 @@ func TestPSK(t *testing.T) { 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 { + ClientVerifyConnection: func(*State) error { return errExample }, WantFail: true, @@ -685,7 +685,7 @@ func TestPSKHintFail(t *testing.T) { ca, cb := dpipe.Pipe() go func() { conf := &Config{ - PSK: func(hint []byte) ([]byte, error) { + PSK: func([]byte) ([]byte, error) { return nil, pskRejected }, PSKIdentityHint: []byte{}, @@ -697,7 +697,7 @@ func TestPSKHintFail(t *testing.T) { }() config := &Config{ - PSK: func(hint []byte) ([]byte, error) { + PSK: func([]byte) ([]byte, error) { return nil, pskRejected }, PSKIdentityHint: []byte{}, @@ -905,14 +905,14 @@ func TestClientCertificate(t *testing.T) { Certificates: []tls.Certificate{srvCert}, ClientAuth: NoClientCert, ClientCAs: caPool, - VerifyConnection: func(s *State) error { + VerifyConnection: func(*State) error { return errExample }, }, wantErr: true, }, "NoClientCert_ClientVerifyConnectionFails": { - clientCfg: &Config{RootCAs: srvCAPool, VerifyConnection: func(s *State) error { + clientCfg: &Config{RootCAs: srvCAPool, VerifyConnection: func(*State) error { return errExample }}, serverCfg: &Config{ @@ -1014,10 +1014,10 @@ func TestClientCertificate(t *testing.T) { clientCfg: &Config{ RootCAs: srvCAPool, // Certificates: []tls.Certificate{cert}, - GetClientCertificate: func(cri *CertificateRequestInfo) (*tls.Certificate, error) { return &cert, nil }, + GetClientCertificate: func(*CertificateRequestInfo) (*tls.Certificate, error) { return &cert, nil }, }, serverCfg: &Config{ - GetCertificate: func(chi *ClientHelloInfo) (*tls.Certificate, error) { return &srvCert, nil }, + GetCertificate: func(*ClientHelloInfo) (*tls.Certificate, error) { return &srvCert, nil }, // Certificates: []tls.Certificate{srvCert}, ClientAuth: RequireAndVerifyClientCert, ClientCAs: caPool, @@ -1408,7 +1408,7 @@ func TestServerCertificate(t *testing.T) { }, "good_ca_skip_verify_custom_verify_peer": { clientCfg: &Config{RootCAs: caPool, Certificates: []tls.Certificate{cert}}, - serverCfg: &Config{Certificates: []tls.Certificate{cert}, ClientAuth: RequireAnyClientCert, VerifyPeerCertificate: func(cert [][]byte, chain [][]*x509.Certificate) error { + serverCfg: &Config{Certificates: []tls.Certificate{cert}, ClientAuth: RequireAnyClientCert, VerifyPeerCertificate: func(_ [][]byte, chain [][]*x509.Certificate) error { if len(chain) != 0 { return errNotExpectedChain } @@ -1417,7 +1417,7 @@ func TestServerCertificate(t *testing.T) { }, "good_ca_verify_custom_verify_peer": { clientCfg: &Config{RootCAs: caPool, Certificates: []tls.Certificate{cert}}, - serverCfg: &Config{ClientCAs: caPool, Certificates: []tls.Certificate{cert}, ClientAuth: RequireAndVerifyClientCert, VerifyPeerCertificate: func(cert [][]byte, chain [][]*x509.Certificate) error { + serverCfg: &Config{ClientCAs: caPool, Certificates: []tls.Certificate{cert}, ClientAuth: RequireAndVerifyClientCert, VerifyPeerCertificate: func(_ [][]byte, chain [][]*x509.Certificate) error { if len(chain) == 0 { return errExpecedChain } @@ -2996,7 +2996,7 @@ func TestMultipleServerCertificates(t *testing.T) { c, err := testClient(context.TODO(), dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ RootCAs: caPool, ServerName: test.RequestServerName, - VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + VerifyPeerCertificate: func(rawCerts [][]byte, _ [][]*x509.Certificate) error { certificate, err := x509.ParseCertificate(rawCerts[0]) if err != nil { return err diff --git a/crypto_test.go b/crypto_test.go index 771ea3afa..3b88fccee 100644 --- a/crypto_test.go +++ b/crypto_test.go @@ -13,6 +13,7 @@ import ( "github.com/pion/dtls/v2/pkg/crypto/hash" ) +// nolint: gosec const rawPrivateKey = ` -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAxIA2BrrnR2sIlATsp7aRBD/3krwZ7vt9dNeoDQAee0s6SuYP diff --git a/handshaker_test.go b/handshaker_test.go index f869959d2..9bbca6f50 100644 --- a/handshaker_test.go +++ b/handshaker_test.go @@ -271,7 +271,7 @@ func TestHandshaker(t *testing.T) { localSignatureSchemes: signaturehash.Algorithms(), insecureSkipVerify: true, log: logger, - onFlightState: func(f flightVal, s handshakeState) { + onFlightState: func(_ flightVal, s handshakeState) { if s == handshakeFinished { if clientEndpoint.OnFinished != nil { clientEndpoint.OnFinished() @@ -304,7 +304,7 @@ func TestHandshaker(t *testing.T) { localSignatureSchemes: signaturehash.Algorithms(), insecureSkipVerify: true, log: logger, - onFlightState: func(f flightVal, s handshakeState) { + onFlightState: func(_ flightVal, s handshakeState) { if s == handshakeFinished { if serverEndpoint.OnFinished != nil { serverEndpoint.OnFinished() diff --git a/pkg/protocol/handshake/message_server_key_exchange_test.go b/pkg/protocol/handshake/message_server_key_exchange_test.go index acfc17964..7e960ce03 100644 --- a/pkg/protocol/handshake/message_server_key_exchange_test.go +++ b/pkg/protocol/handshake/message_server_key_exchange_test.go @@ -32,7 +32,7 @@ func TestHandshakeMessageServerKeyExchange(t *testing.T) { } } - t.Run("Hash+Signature", func(t *testing.T) { + t.Run("Hash+Signature", func(*testing.T) { rawServerKeyExchange := []byte{ 0x03, 0x00, 0x1d, 0x41, 0x04, 0x0c, 0xb9, 0xa3, 0xb9, 0x90, 0x71, 0x35, 0x4a, 0x08, 0x66, 0xaf, 0xd6, 0x88, 0x58, 0x29, 0x69, 0x98, 0xf1, 0x87, 0x0f, 0xb5, 0xa8, 0xcd, 0x92, 0xf6, 0x2b, 0x08, @@ -57,7 +57,7 @@ func TestHandshakeMessageServerKeyExchange(t *testing.T) { test(rawServerKeyExchange, parsedServerKeyExchange) }) - t.Run("Anonymous", func(t *testing.T) { + t.Run("Anonymous", func(*testing.T) { rawServerKeyExchange := []byte{ 0x03, 0x00, 0x1d, 0x41, 0x04, 0x0c, 0xb9, 0xa3, 0xb9, 0x90, 0x71, 0x35, 0x4a, 0x08, 0x66, 0xaf, 0xd6, 0x88, 0x58, 0x29, 0x69, 0x98, 0xf1, 0x87, 0x0f, 0xb5, 0xa8, 0xcd, 0x92, 0xf6, 0x2b, 0x08, From 35a00d3f93df9b90a01c2d8e0ca0b2ee10d964f8 Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Fri, 15 Mar 2024 22:27:28 -0400 Subject: [PATCH 081/146] Fix linter errors golangci-lint upgrade to v1.56.2 added more checks Relates to pion/.goassets#201 --- e2e/e2e_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 4a8dd5d54..e0ca90977 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -325,7 +325,7 @@ func testPionE2ESimplePSK(t *testing.T, server, client func(*comm), opts ...dtls defer cancel() cfg := &dtls.Config{ - PSK: func(hint []byte) ([]byte, error) { + PSK: func([]byte) ([]byte, error) { return []byte{0xAB, 0xC1, 0x23}, nil }, PSKIdentityHint: []byte{0x01, 0x02, 0x03, 0x04, 0x05}, From 5e95b5c8bbda9f0e1ee906c00ce37600fc26643c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 16 Mar 2024 02:28:24 +0000 Subject: [PATCH 082/146] Update module github.com/stretchr/testify to v1.9.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 043091f22..92f271052 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.1 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.18.0 golang.org/x/net v0.20.0 ) diff --git a/go.sum b/go.sum index be00e338b..b8384e299 100644 --- a/go.sum +++ b/go.sum @@ -10,10 +10,12 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= From a2457276a95559ab33e219494dfe50bcf87ff5d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 16 Mar 2024 04:12:34 +0000 Subject: [PATCH 083/146] Update module golang.org/x/crypto to v0.21.0 Generated by renovateBot --- go.mod | 4 ++-- go.sum | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 92f271052..c5791fa75 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.9.0 - golang.org/x/crypto v0.18.0 - golang.org/x/net v0.20.0 + golang.org/x/crypto v0.21.0 + golang.org/x/net v0.21.0 ) go 1.13 diff --git a/go.sum b/go.sum index b8384e299..78eb5b32e 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,9 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -30,8 +31,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -43,13 +44,15 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= From 38e39e4a6c95b5279144ee49c264d18a9ac2f423 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 16 Mar 2024 07:07:19 +0000 Subject: [PATCH 084/146] Update module golang.org/x/net to v0.22.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index c5791fa75..be28802a5 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/pion/transport/v3 v3.0.1 github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.21.0 - golang.org/x/net v0.21.0 + golang.org/x/net v0.22.0 ) go 1.13 diff --git a/go.sum b/go.sum index 78eb5b32e..72d67fc94 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,9 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 8a93e0eb6561396d2a464caa3e8fa0fa06c048e3 Mon Sep 17 00:00:00 2001 From: Yutaka Takeda <yt0916@gmail.com> Date: Mon, 25 Mar 2024 00:14:06 -0700 Subject: [PATCH 085/146] Fix TestErrorsTemporary Fixes #614 --- errors_errno_test.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/errors_errno_test.go b/errors_errno_test.go index 5b4b209d1..e2957a691 100644 --- a/errors_errno_test.go +++ b/errors_errno_test.go @@ -16,18 +16,32 @@ import ( ) func TestErrorsTemporary(t *testing.T) { - addrListen, errListen := net.ResolveUDPAddr("udp", "localhost:0") - if errListen != nil { - t.Fatalf("Unexpected error: %v", errListen) + // Allocate a UDP port no one is listening on. + addrListen, err := net.ResolveUDPAddr("udp", "localhost:0") + if err != nil { + t.Fatalf("Unexpected failure to resolve: %v", err) } + listener, err := net.ListenUDP("udp", addrListen) + if err != nil { + t.Fatalf("Unexpected failure to listen: %v", err) + } + raddr, ok := listener.LocalAddr().(*net.UDPAddr) + if !ok { + t.Fatal("Unexpedted type assertion error") + } + err = listener.Close() + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + // Server is not listening. - conn, errDial := net.DialUDP("udp", nil, addrListen) + conn, errDial := net.DialUDP("udp", nil, raddr) if errDial != nil { t.Fatalf("Unexpected error: %v", errDial) } _, _ = conn.Write([]byte{0x00}) // trigger - _, err := conn.Read(make([]byte, 10)) + _, err = conn.Read(make([]byte, 10)) _ = conn.Close() if err == nil { From 0ad9cfddb4868974cbf0cd565c9f061482536746 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Mar 2024 16:07:10 +0000 Subject: [PATCH 086/146] Update module github.com/pion/transport/v3 to v3.0.2 Generated by renovateBot --- go.mod | 2 +- go.sum | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index be28802a5..0fb16fe3d 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 - github.com/pion/transport/v3 v3.0.1 + github.com/pion/transport/v3 v3.0.2 github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.21.0 golang.org/x/net v0.22.0 diff --git a/go.sum b/go.sum index 72d67fc94..6159ee85b 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= -github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4= +github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -19,7 +19,6 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= @@ -30,7 +29,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= @@ -44,14 +42,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -59,7 +55,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= From 8244c4570c013b064e46a2431eaf0336686f76e1 Mon Sep 17 00:00:00 2001 From: Pion <59523206+pionbot@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:57:19 +0000 Subject: [PATCH 087/146] Update CI configs to v0.11.4 Update lint scripts and CI configs. --- .github/workflows/api.yaml | 20 ++++++++++++++++++++ .github/workflows/release.yml | 2 +- .github/workflows/test.yaml | 6 +++--- .github/workflows/tidy-check.yaml | 2 +- 4 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/api.yaml diff --git a/.github/workflows/api.yaml b/.github/workflows/api.yaml new file mode 100644 index 000000000..1032179e3 --- /dev/null +++ b/.github/workflows/api.yaml @@ -0,0 +1,20 @@ +# +# 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. +# +# SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +# SPDX-License-Identifier: MIT + +name: API +on: + pull_request: + +jobs: + check: + uses: pion/.goassets/.github/workflows/api.reusable.yml@master diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 01227e2a5..0e72ea4d3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,4 +21,4 @@ jobs: release: uses: pion/.goassets/.github/workflows/release.reusable.yml@master with: - go-version: '1.20' # auto-update/latest-go-version + go-version: "1.22" # auto-update/latest-go-version diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c8294ef1f..ad6eb90ff 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -23,7 +23,7 @@ jobs: uses: pion/.goassets/.github/workflows/test.reusable.yml@master strategy: matrix: - go: ['1.21', '1.20'] # auto-update/supported-go-version-list + go: ["1.22", "1.21"] # auto-update/supported-go-version-list fail-fast: false with: go-version: ${{ matrix.go }} @@ -32,7 +32,7 @@ jobs: uses: pion/.goassets/.github/workflows/test-i386.reusable.yml@master strategy: matrix: - go: ['1.21', '1.20'] # auto-update/supported-go-version-list + go: ["1.22", "1.21"] # auto-update/supported-go-version-list fail-fast: false with: go-version: ${{ matrix.go }} @@ -40,4 +40,4 @@ jobs: test-wasm: uses: pion/.goassets/.github/workflows/test-wasm.reusable.yml@master with: - go-version: '1.20' # auto-update/latest-go-version + go-version: "1.22" # auto-update/latest-go-version diff --git a/.github/workflows/tidy-check.yaml b/.github/workflows/tidy-check.yaml index 33d6b507c..417e730a5 100644 --- a/.github/workflows/tidy-check.yaml +++ b/.github/workflows/tidy-check.yaml @@ -22,4 +22,4 @@ jobs: tidy: uses: pion/.goassets/.github/workflows/tidy-check.reusable.yml@master with: - go-version: '1.21' # auto-update/latest-go-version + go-version: "1.22" # auto-update/latest-go-version From ae51db9d270ca7ae49c2ae5d78a9d7e80b95d404 Mon Sep 17 00:00:00 2001 From: Pion <59523206+pionbot@users.noreply.github.com> Date: Tue, 2 Apr 2024 16:40:41 +0000 Subject: [PATCH 088/146] Update CI configs to v0.11.7 Update lint scripts and CI configs. --- .golangci.yml | 7 +++---- .reuse/dep5 | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 6dd80c805..e06de4d3c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -3,7 +3,8 @@ linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -110,6 +111,7 @@ linters: issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: # Allow complex tests and examples, better to be self contained - path: (examples|main\.go|_test\.go) @@ -121,6 +123,3 @@ issues: - path: cmd linters: - forbidigo - -run: - skip-dirs-use-default: false diff --git a/.reuse/dep5 b/.reuse/dep5 index 717f0c1c2..eb7fac2fc 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -2,7 +2,7 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Pion Source: https://github.com/pion/ -Files: README.md DESIGN.md **/README.md AUTHORS.txt renovate.json go.mod go.sum **/go.mod **/go.sum .eslintrc.json package.json examples/examples.json +Files: README.md DESIGN.md **/README.md AUTHORS.txt renovate.json go.mod go.sum **/go.mod **/go.sum .eslintrc.json package.json examples.json sfu-ws/flutter/.gitignore sfu-ws/flutter/pubspec.yaml c-data-channels/webrtc.h examples/examples.json Copyright: 2023 The Pion community <https://pion.ly> License: MIT From 3e667b0ffb48a139109ca316fcaa70bf13955ff7 Mon Sep 17 00:00:00 2001 From: Eric Daniels <eric@erdaniels.com> Date: Tue, 2 Apr 2024 14:08:48 -0400 Subject: [PATCH 089/146] Update go.mod version to 1.19 Relates to pion/webrtc#2292 --- go.mod | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0fb16fe3d..48cb1e8ba 100644 --- a/go.mod +++ b/go.mod @@ -8,4 +8,10 @@ require ( golang.org/x/net v0.22.0 ) -go 1.13 +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +go 1.19 From e008bc446392e21acf990a79e414314c5c1330f2 Mon Sep 17 00:00:00 2001 From: Pion <59523206+pionbot@users.noreply.github.com> Date: Tue, 9 Apr 2024 03:08:48 +0000 Subject: [PATCH 090/146] Update CI configs to v0.11.12 Update lint scripts and CI configs. --- .github/workflows/test.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ad6eb90ff..08e4272a8 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -27,6 +27,7 @@ jobs: fail-fast: false with: go-version: ${{ matrix.go }} + secrets: inherit test-i386: uses: pion/.goassets/.github/workflows/test-i386.reusable.yml@master @@ -41,3 +42,4 @@ jobs: uses: pion/.goassets/.github/workflows/test-wasm.reusable.yml@master with: go-version: "1.22" # auto-update/latest-go-version + secrets: inherit From f6f666ef5ee7337ba6a2cb2225a12f731d683b98 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 15:04:24 +0000 Subject: [PATCH 091/146] Update module golang.org/x/net to v0.23.0 [SECURITY] Generated by renovateBot --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 48cb1e8ba..02fdca4a3 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/pion/transport/v3 v3.0.2 github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.21.0 - golang.org/x/net v0.22.0 + golang.org/x/net v0.23.0 ) require ( diff --git a/go.sum b/go.sum index 6159ee85b..9ec371a83 100644 --- a/go.sum +++ b/go.sum @@ -30,8 +30,9 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From d606c79032edf02d8b1078172cf54f6ce15b9b94 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 01:09:04 +0000 Subject: [PATCH 092/146] Update module golang.org/x/crypto to v0.22.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 02fdca4a3..4e20920c7 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.2 github.com/stretchr/testify v1.9.0 - golang.org/x/crypto v0.21.0 + golang.org/x/crypto v0.22.0 golang.org/x/net v0.23.0 ) diff --git a/go.sum b/go.sum index 9ec371a83..5a988532a 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,9 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From 2c36d63320a0312adc9589442ac8014f4fecb9fc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 03:30:35 +0000 Subject: [PATCH 093/146] Update module golang.org/x/net to v0.24.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4e20920c7..bd6ae9f9e 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/pion/transport/v3 v3.0.2 github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.22.0 - golang.org/x/net v0.23.0 + golang.org/x/net v0.24.0 ) require ( diff --git a/go.sum b/go.sum index 5a988532a..80be07f33 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 8738ce19f77e598a194c2d1d87dc9d72e5c2e948 Mon Sep 17 00:00:00 2001 From: theodorsm <theodor@midtlien.com> Date: Sat, 4 May 2024 13:33:45 +0200 Subject: [PATCH 094/146] Add handshake hooking Hooking for client/server hello and certificate request messages --- config.go | 18 ++++++ conn.go | 55 +++++++++--------- e2e/e2e_test.go | 126 ++++++++++++++++++++++++++++++++++++++++- flight1handler.go | 30 ++++++---- flight3handler.go | 30 ++++++---- flight4bhandler.go | 26 +++++---- flight4handler.go | 51 +++++++++++------ flight4handler_test.go | 68 ++++++++++++++++++++++ handshaker.go | 4 ++ state.go | 4 ++ 10 files changed, 336 insertions(+), 76 deletions(-) diff --git a/config.go b/config.go index 604a4d575..d765ecd91 100644 --- a/config.go +++ b/config.go @@ -14,6 +14,7 @@ import ( "time" "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v2/pkg/protocol/handshake" "github.com/pion/logging" ) @@ -196,6 +197,23 @@ type Config struct { // If no PaddingLengthGenerator is specified, padding will not be applied. // https://datatracker.ietf.org/doc/html/rfc9146#section-4 PaddingLengthGenerator func(uint) uint + + // Handshake hooks: hooks can be used for testing invalid messages, + // mimicking other implementations or randomizing fields, which is valuable + // for applications that need censorship-resistance by making + // fingerprinting more difficult. + + // ClientHelloMessageHook, if not nil, is called when a Client Hello message is sent + // from a client. The returned handshake message replaces the original message. + ClientHelloMessageHook func(handshake.MessageClientHello) handshake.Message + + // ServerHelloMessageHook, if not nil, is called when a Server Hello message is sent + // from a server. The returned handshake message replaces the original message. + ServerHelloMessageHook func(handshake.MessageServerHello) handshake.Message + + // CertificateRequestMessageHook, if not nil, is called when a Certificate Request + // message is sent from a server. The returned handshake message replaces the original message. + CertificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message } func defaultConnectContextMaker() (context.Context, func()) { diff --git a/conn.go b/conn.go index d4259f9e8..1ddc70963 100644 --- a/conn.go +++ b/conn.go @@ -176,32 +176,35 @@ func createConn(ctx context.Context, nextConn net.PacketConn, rAddr net.Addr, co } hsCfg := &handshakeConfig{ - localPSKCallback: config.PSK, - localPSKIdentityHint: config.PSKIdentityHint, - localCipherSuites: cipherSuites, - localSignatureSchemes: signatureSchemes, - extendedMasterSecret: config.ExtendedMasterSecret, - localSRTPProtectionProfiles: config.SRTPProtectionProfiles, - serverName: serverName, - supportedProtocols: config.SupportedProtocols, - clientAuth: config.ClientAuth, - localCertificates: config.Certificates, - insecureSkipVerify: config.InsecureSkipVerify, - verifyPeerCertificate: config.VerifyPeerCertificate, - verifyConnection: config.VerifyConnection, - rootCAs: config.RootCAs, - clientCAs: config.ClientCAs, - customCipherSuites: config.CustomCipherSuites, - retransmitInterval: workerInterval, - log: logger, - initialEpoch: 0, - keyLogWriter: config.KeyLogWriter, - sessionStore: config.SessionStore, - ellipticCurves: curves, - localGetCertificate: config.GetCertificate, - localGetClientCertificate: config.GetClientCertificate, - insecureSkipHelloVerify: config.InsecureSkipVerifyHello, - connectionIDGenerator: config.ConnectionIDGenerator, + localPSKCallback: config.PSK, + localPSKIdentityHint: config.PSKIdentityHint, + localCipherSuites: cipherSuites, + localSignatureSchemes: signatureSchemes, + extendedMasterSecret: config.ExtendedMasterSecret, + localSRTPProtectionProfiles: config.SRTPProtectionProfiles, + serverName: serverName, + supportedProtocols: config.SupportedProtocols, + clientAuth: config.ClientAuth, + localCertificates: config.Certificates, + insecureSkipVerify: config.InsecureSkipVerify, + verifyPeerCertificate: config.VerifyPeerCertificate, + verifyConnection: config.VerifyConnection, + rootCAs: config.RootCAs, + clientCAs: config.ClientCAs, + customCipherSuites: config.CustomCipherSuites, + retransmitInterval: workerInterval, + log: logger, + initialEpoch: 0, + keyLogWriter: config.KeyLogWriter, + sessionStore: config.SessionStore, + ellipticCurves: curves, + localGetCertificate: config.GetCertificate, + localGetClientCertificate: config.GetClientCertificate, + insecureSkipHelloVerify: config.InsecureSkipVerifyHello, + connectionIDGenerator: config.ConnectionIDGenerator, + clientHelloMessageHook: config.ClientHelloMessageHook, + serverHelloMessageHook: config.ServerHelloMessageHook, + certificateRequestMessageHook: config.CertificateRequestMessageHook, } // rfc5246#section-7.4.3 diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index e0ca90977..ec1253ec8 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -24,6 +24,8 @@ import ( "github.com/pion/dtls/v2" "github.com/pion/dtls/v2/pkg/crypto/selfsign" + "github.com/pion/dtls/v2/pkg/protocol/extension" + "github.com/pion/dtls/v2/pkg/protocol/handshake" "github.com/pion/transport/v3/test" ) @@ -33,7 +35,11 @@ const ( messageRetry = 200 * time.Millisecond ) -var errServerTimeout = errors.New("waiting on serverReady err: timeout") +var ( + errServerTimeout = errors.New("waiting on serverReady err: timeout") + errHookCiphersFailed = errors.New("hook failed to modify cipherlist") + errHookAPLNFailed = errors.New("hook failed to modify APLN extension") +) func randomPort(t testing.TB) int { t.Helper() @@ -569,6 +575,116 @@ func testPionE2ESimpleRSAClientCert(t *testing.T, server, client func(*comm), op comm.assert(t) } +func testPionE2ESimpleClientHelloHook(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { + lim := test.TimeOut(time.Second * 30) + defer lim.Stop() + + report := test.CheckRoutines(t) + defer report() + + t.Run("ClientHello hook", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + cert, err := selfsign.GenerateSelfSignedWithDNS("localhost") + if err != nil { + t.Fatal(err) + } + + modifiedCipher := dtls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + supportedList := []dtls.CipherSuiteID{ + dtls.TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + modifiedCipher, + } + + ccfg := &dtls.Config{ + Certificates: []tls.Certificate{cert}, + VerifyConnection: func(s *dtls.State) error { + if s.CipherSuiteID != modifiedCipher { + return errHookCiphersFailed + } + return nil + }, + CipherSuites: supportedList, + ClientHelloMessageHook: func(ch handshake.MessageClientHello) handshake.Message { + ch.CipherSuiteIDs = []uint16{uint16(modifiedCipher)} + return &ch + }, + InsecureSkipVerify: true, + } + + scfg := &dtls.Config{ + Certificates: []tls.Certificate{cert}, + CipherSuites: supportedList, + InsecureSkipVerify: true, + } + + for _, o := range opts { + o(ccfg) + o(scfg) + } + serverPort := randomPort(t) + comm := newComm(ctx, ccfg, scfg, serverPort, server, client) + defer comm.cleanup(t) + comm.assert(t) + }) +} + +func testPionE2ESimpleServerHelloHook(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { + lim := test.TimeOut(time.Second * 30) + defer lim.Stop() + + report := test.CheckRoutines(t) + defer report() + + t.Run("ServerHello hook", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + cert, err := selfsign.GenerateSelfSignedWithDNS("localhost") + if err != nil { + t.Fatal(err) + } + + supportedList := []dtls.CipherSuiteID{dtls.TLS_ECDHE_ECDSA_WITH_AES_128_CCM} + + apln := "APLN" + + ccfg := &dtls.Config{ + Certificates: []tls.Certificate{cert}, + VerifyConnection: func(s *dtls.State) error { + if s.NegotiatedProtocol != apln { + return errHookAPLNFailed + } + return nil + }, + CipherSuites: supportedList, + InsecureSkipVerify: true, + } + + scfg := &dtls.Config{ + Certificates: []tls.Certificate{cert}, + CipherSuites: supportedList, + ServerHelloMessageHook: func(sh handshake.MessageServerHello) handshake.Message { + sh.Extensions = append(sh.Extensions, &extension.ALPN{ + ProtocolNameList: []string{apln}, + }) + return &sh + }, + InsecureSkipVerify: true, + } + + for _, o := range opts { + o(ccfg) + o(scfg) + } + serverPort := randomPort(t) + comm := newComm(ctx, ccfg, scfg, serverPort, server, client) + defer comm.cleanup(t) + comm.assert(t) + }) +} + func TestPionE2ESimple(t *testing.T) { testPionE2ESimple(t, serverPion, clientPion) } @@ -624,3 +740,11 @@ func TestPionE2ESimpleECDSAClientCertCID(t *testing.T) { func TestPionE2ESimpleRSAClientCertCID(t *testing.T) { testPionE2ESimpleRSAClientCert(t, serverPion, clientPion, withConnectionIDGenerator(dtls.RandomCIDGenerator(8))) } + +func TestPionE2ESimpleClientHelloHook(t *testing.T) { + testPionE2ESimpleClientHelloHook(t, serverPion, clientPion) +} + +func TestPionE2ESimpleServerHelloHook(t *testing.T) { + testPionE2ESimpleServerHelloHook(t, serverPion, clientPion) +} diff --git a/flight1handler.go b/flight1handler.go index 48bc88213..08a8f3921 100644 --- a/flight1handler.go +++ b/flight1handler.go @@ -133,23 +133,31 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) } + clientHello := &handshake.MessageClientHello{ + Version: protocol.Version1_2, + SessionID: state.SessionID, + Cookie: state.cookie, + Random: state.localRandom, + CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites), + CompressionMethods: defaultCompressionMethods(), + Extensions: extensions, + } + + var content handshake.Handshake + + if cfg.clientHelloMessageHook != nil { + content = handshake.Handshake{Message: cfg.clientHelloMessageHook(*clientHello)} + } else { + content = handshake.Handshake{Message: clientHello} + } + return []*packet{ { record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ Version: protocol.Version1_2, }, - Content: &handshake.Handshake{ - Message: &handshake.MessageClientHello{ - Version: protocol.Version1_2, - SessionID: state.SessionID, - Cookie: state.cookie, - Random: state.localRandom, - CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites), - CompressionMethods: defaultCompressionMethods(), - Extensions: extensions, - }, - }, + Content: &content, }, }, }, nil, nil diff --git a/flight3handler.go b/flight3handler.go index 90dc1a6e3..08549fb76 100644 --- a/flight3handler.go +++ b/flight3handler.go @@ -287,23 +287,31 @@ func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) } + clientHello := &handshake.MessageClientHello{ + Version: protocol.Version1_2, + SessionID: state.SessionID, + Cookie: state.cookie, + Random: state.localRandom, + CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites), + CompressionMethods: defaultCompressionMethods(), + Extensions: extensions, + } + + var content handshake.Handshake + + if cfg.clientHelloMessageHook != nil { + content = handshake.Handshake{Message: cfg.clientHelloMessageHook(*clientHello)} + } else { + content = handshake.Handshake{Message: clientHello} + } + return []*packet{ { record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ Version: protocol.Version1_2, }, - Content: &handshake.Handshake{ - Message: &handshake.MessageClientHello{ - Version: protocol.Version1_2, - SessionID: state.SessionID, - Cookie: state.cookie, - Random: state.localRandom, - CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites), - CompressionMethods: defaultCompressionMethods(), - Extensions: extensions, - }, - }, + Content: &content, }, }, }, nil, nil diff --git a/flight4bhandler.go b/flight4bhandler.go index 6b1b90469..d653f4d94 100644 --- a/flight4bhandler.go +++ b/flight4bhandler.go @@ -77,15 +77,21 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha } cipherSuiteID := uint16(state.cipherSuite.ID()) - serverHello := &handshake.Handshake{ - Message: &handshake.MessageServerHello{ - Version: protocol.Version1_2, - Random: state.localRandom, - SessionID: state.SessionID, - CipherSuiteID: &cipherSuiteID, - CompressionMethod: defaultCompressionMethods()[0], - Extensions: extensions, - }, + var serverHello handshake.Handshake + + serverHelloMessage := &handshake.MessageServerHello{ + Version: protocol.Version1_2, + Random: state.localRandom, + SessionID: state.SessionID, + CipherSuiteID: &cipherSuiteID, + CompressionMethod: defaultCompressionMethods()[0], + Extensions: extensions, + } + + if cfg.serverHelloMessageHook != nil { + serverHello = handshake.Handshake{Message: cfg.serverHelloMessageHook(*serverHelloMessage)} + } else { + serverHello = handshake.Handshake{Message: serverHelloMessage} } serverHello.Header.MessageSequence = uint16(state.handshakeSendSequence) @@ -112,7 +118,7 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha Header: recordlayer.Header{ Version: protocol.Version1_2, }, - Content: serverHello, + Content: &serverHello, }, }, &packet{ diff --git a/flight4handler.go b/flight4handler.go index cd8f2884a..86f21464b 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -269,21 +269,29 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha } } + serverHello := &handshake.MessageServerHello{ + Version: protocol.Version1_2, + Random: state.localRandom, + SessionID: state.SessionID, + CipherSuiteID: &cipherSuiteID, + CompressionMethod: defaultCompressionMethods()[0], + Extensions: extensions, + } + + var content handshake.Handshake + + if cfg.serverHelloMessageHook != nil { + content = handshake.Handshake{Message: cfg.serverHelloMessageHook(*serverHello)} + } else { + content = handshake.Handshake{Message: serverHello} + } + pkts = append(pkts, &packet{ record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ Version: protocol.Version1_2, }, - Content: &handshake.Handshake{ - Message: &handshake.MessageServerHello{ - Version: protocol.Version1_2, - Random: state.localRandom, - SessionID: state.SessionID, - CipherSuiteID: &cipherSuiteID, - CompressionMethod: defaultCompressionMethods()[0], - Extensions: extensions, - }, - }, + Content: &content, }, }) @@ -354,18 +362,27 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha // 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() } + + certReq := &handshake.MessageCertificateRequest{ + CertificateTypes: []clientcertificate.Type{clientcertificate.RSASign, clientcertificate.ECDSASign}, + SignatureHashAlgorithms: cfg.localSignatureSchemes, + CertificateAuthoritiesNames: certificateAuthorities, + } + + var content handshake.Handshake + + if cfg.certificateRequestMessageHook != nil { + content = handshake.Handshake{Message: cfg.certificateRequestMessageHook(*certReq)} + } else { + content = handshake.Handshake{Message: certReq} + } + pkts = append(pkts, &packet{ record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ Version: protocol.Version1_2, }, - Content: &handshake.Handshake{ - Message: &handshake.MessageCertificateRequest{ - CertificateTypes: []clientcertificate.Type{clientcertificate.RSASign, clientcertificate.ECDSASign}, - SignatureHashAlgorithms: cfg.localSignatureSchemes, - CertificateAuthoritiesNames: certificateAuthorities, - }, - }, + Content: &content, }, }) } diff --git a/flight4handler_test.go b/flight4handler_test.go index 304c82eff..f4446c40b 100644 --- a/flight4handler_test.go +++ b/flight4handler_test.go @@ -5,10 +5,15 @@ package dtls import ( "context" + "crypto/tls" + "errors" "testing" "time" "github.com/pion/dtls/v2/internal/ciphersuite" + "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v2/pkg/crypto/selfsign" + "github.com/pion/dtls/v2/pkg/crypto/signaturehash" "github.com/pion/dtls/v2/pkg/protocol/alert" "github.com/pion/dtls/v2/pkg/protocol/handshake" "github.com/pion/transport/v3/test" @@ -16,6 +21,8 @@ import ( type flight4TestMockFlightConn struct{} +var errHookCertReqFailed = errors.New("hook failed to modify SignatureHashAlgorithms") + func (f *flight4TestMockFlightConn) notify(context.Context, alert.Level, alert.Description) error { return nil } @@ -117,3 +124,64 @@ func TestFlight4_Process_CertificateVerify(t *testing.T) { t.Fatal(err) } } + +func TestFlight4_CertificateRequestHook(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(5 * time.Second) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + localKeypair, err := elliptic.GenerateKeypair(elliptic.P256) + if err != nil { + t.Fatal(err) + } + + mockConn := &flight4TestMockFlightConn{} + state := &State{ + cipherSuite: &flight4TestMockCipherSuite{t: t}, + localKeypair: localKeypair, + } + + cert, err := selfsign.GenerateSelfSignedWithDNS("localhost") + if err != nil { + t.Fatal(err) + } + + cfg := &handshakeConfig{ + localCertificates: []tls.Certificate{cert}, + localSignatureSchemes: signaturehash.Algorithms(), + clientAuth: 1, + certificateRequestMessageHook: func(mcr handshake.MessageCertificateRequest) handshake.Message { + mcr.SignatureHashAlgorithms = []signaturehash.Algorithm{} + return &mcr + }, + } + + pkts, _, err := flight4Generate(mockConn, state, nil, cfg) + if err != nil { + t.Fatal(err) + } + + for _, p := range pkts { + if h, ok := p.record.Content.(*handshake.Handshake); ok { + if h.Message.Type() == handshake.TypeCertificateRequest { + mcr := &handshake.MessageCertificateRequest{} + msg, err := h.Message.Marshal() + if err != nil { + t.Fatal(err) + } + err = mcr.Unmarshal(msg) + if err != nil { + t.Fatal(err) + } + if len(mcr.SignatureHashAlgorithms) == 0 { + return + } + } + } + } + t.Fatal(errHookCertReqFailed) +} diff --git a/handshaker.go b/handshaker.go index 46fbd38bd..317cb4e4e 100644 --- a/handshaker.go +++ b/handshaker.go @@ -125,6 +125,10 @@ type handshakeConfig struct { initialEpoch uint16 mu sync.Mutex + + clientHelloMessageHook func(handshake.MessageClientHello) handshake.Message + serverHelloMessageHook func(handshake.MessageServerHello) handshake.Message + certificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message } type flightConn interface { diff --git a/state.go b/state.go index b04045ac9..35a5b64fb 100644 --- a/state.go +++ b/state.go @@ -82,6 +82,7 @@ type serializedState struct { LocalConnectionID []byte RemoteConnectionID []byte IsClient bool + NegotiatedProtocol string } func (s *State) clone() *State { @@ -113,6 +114,7 @@ func (s *State) serialize() *serializedState { LocalConnectionID: s.localConnectionID, RemoteConnectionID: s.remoteConnectionID, IsClient: s.isClient, + NegotiatedProtocol: s.NegotiatedProtocol, } } @@ -157,6 +159,8 @@ func (s *State) deserialize(serialized serializedState) { s.remoteConnectionID = serialized.RemoteConnectionID s.SessionID = serialized.SessionID + + s.NegotiatedProtocol = serialized.NegotiatedProtocol } func (s *State) initCipherSuite() error { From adec94a6d39af67c3111b71033ddfa46416d92fb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 01:29:04 +0000 Subject: [PATCH 095/146] Update golang Docker tag to v1.22 Generated by renovateBot --- e2e/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/Dockerfile b/e2e/Dockerfile index 7df99615a..0df773d91 100644 --- a/e2e/Dockerfile +++ b/e2e/Dockerfile @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> # SPDX-License-Identifier: MIT -FROM docker.io/library/golang:1.20-bullseye +FROM docker.io/library/golang:1.22-bullseye COPY . /go/src/github.com/pion/dtls WORKDIR /go/src/github.com/pion/dtls/e2e From 494c1a3ca87beedc7958ff8769b6d2a451c605c4 Mon Sep 17 00:00:00 2001 From: Sean DuBois <duboisea@amazon.com> Date: Thu, 30 May 2024 23:31:29 -0400 Subject: [PATCH 096/146] Remove testify dependency --- go.mod | 7 - go.sum | 5 - internal/net/buffer_test.go | 262 ++++++++++++++++++++++-------------- 3 files changed, 164 insertions(+), 110 deletions(-) diff --git a/go.mod b/go.mod index bd6ae9f9e..f0c16f9d5 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,8 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.2 - github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.22.0 golang.org/x/net v0.24.0 ) -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) - go 1.19 diff --git a/go.sum b/go.sum index 80be07f33..8dd49ba60 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,9 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4= github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -14,7 +12,6 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -63,8 +60,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/net/buffer_test.go b/internal/net/buffer_test.go index 8a9cd6180..cf90d270f 100644 --- a/internal/net/buffer_test.go +++ b/internal/net/buffer_test.go @@ -7,195 +7,255 @@ package net import ( "bytes" "errors" + "fmt" "io" "net" "testing" "time" - - "github.com/stretchr/testify/assert" ) -func TestBuffer(t *testing.T) { - assert := assert.New(t) +func equalInt(t *testing.T, expected, actual int) { + if expected != actual { + t.Errorf("Expected %d got %d", expected, actual) + } +} +func equalUDPAddr(t *testing.T, expected, actual net.Addr) { + if expected == nil && actual == nil { + return + } + if expected.String() != actual.String() { + t.Errorf("Expected %v got %v", expected, actual) + } +} + +func equalBytes(t *testing.T, expected, actual []byte) { + if !bytes.Equal(expected, actual) { + t.Errorf("Expected %v got %v", expected, actual) + } +} + +func TestBuffer(t *testing.T) { buffer := NewPacketBuffer() packet := make([]byte, 4) addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") - assert.NoError(err) + if err != nil { + t.Fatal(err) + } // Write once. n, err := buffer.WriteTo([]byte{0, 1}, addr) - assert.NoError(err) - assert.Equal(2, n) + if err != nil { + t.Fatal(err) + } + equalInt(t, 2, n) // Read once. var raddr net.Addr - n, raddr, err = buffer.ReadFrom(packet) - assert.NoError(err) - assert.Equal(2, n) - assert.Equal([]byte{0, 1}, packet[:n]) - assert.Equal(addr, raddr) + if n, raddr, err = buffer.ReadFrom(packet); err != nil { + t.Fatal(err) + } + equalInt(t, 2, n) + equalBytes(t, []byte{0, 1}, packet[:n]) + equalUDPAddr(t, addr, raddr) // Read deadline. - err = buffer.SetReadDeadline(time.Unix(0, 1)) - assert.NoError(err) + if err = buffer.SetReadDeadline(time.Unix(0, 1)); err != nil { + t.Fatal(err) + } n, raddr, err = buffer.ReadFrom(packet) - assert.EqualError(err, ErrTimeout.Error()) - assert.Equal(0, n) - assert.Equal(nil, raddr) + if !errors.Is(ErrTimeout, err) { + t.Fatalf("Unexpected err %v wanted ErrTimeout", err) + } + equalInt(t, 0, n) + equalUDPAddr(t, nil, raddr) // Reset deadline. - err = buffer.SetReadDeadline(time.Time{}) - assert.NoError(err) + if err = buffer.SetReadDeadline(time.Time{}); err != nil { + t.Fatal(err) + } // Write twice. - n, err = buffer.WriteTo([]byte{2, 3, 4}, addr) - assert.NoError(err) - assert.Equal(3, n) + if n, err = buffer.WriteTo([]byte{2, 3, 4}, addr); err != nil { + t.Fatal(err) + } + equalInt(t, 3, n) - n, err = buffer.WriteTo([]byte{5, 6, 7}, addr) - assert.NoError(err) - assert.Equal(3, n) + if n, err = buffer.WriteTo([]byte{5, 6, 7}, addr); err != nil { + t.Fatal(err) + } + equalInt(t, 3, n) // Read twice. - n, raddr, err = buffer.ReadFrom(packet) - assert.NoError(err) - assert.Equal(3, n) - assert.Equal([]byte{2, 3, 4}, packet[:n]) - assert.Equal(addr, raddr) + if n, raddr, err = buffer.ReadFrom(packet); err != nil { + t.Fatal(err) + } + equalInt(t, 3, n) + equalBytes(t, []byte{2, 3, 4}, packet[:n]) + equalUDPAddr(t, addr, raddr) - n, raddr, err = buffer.ReadFrom(packet) - assert.NoError(err) - assert.Equal(3, n) - assert.Equal([]byte{5, 6, 7}, packet[:n]) - assert.Equal(addr, raddr) + if n, raddr, err = buffer.ReadFrom(packet); err != nil { + t.Fatal(err) + } + equalInt(t, 3, n) + equalBytes(t, []byte{5, 6, 7}, packet[:n]) + equalUDPAddr(t, addr, raddr) // Write once prior to close. - _, err = buffer.WriteTo([]byte{3}, addr) - assert.NoError(err) + if _, err = buffer.WriteTo([]byte{3}, addr); err != nil { + t.Fatal(err) + } // Close. - assert.NoError(buffer.Close()) + if err = buffer.Close(); err != nil { + t.Fatal(err) + } // Future writes will error. - _, err = buffer.WriteTo([]byte{4}, addr) - assert.Error(err) + if _, err = buffer.WriteTo([]byte{4}, addr); err == nil { + t.Fatal("Expected error") + } // But we can read the remaining data. - n, raddr, err = buffer.ReadFrom(packet) - assert.NoError(err) - assert.Equal(1, n) - assert.Equal([]byte{3}, packet[:n]) - assert.Equal(addr, raddr) + if n, raddr, err = buffer.ReadFrom(packet); err != nil { + t.Fatal(err) + } + equalInt(t, 1, n) + equalBytes(t, []byte{3}, packet[:n]) + equalUDPAddr(t, addr, raddr) // Until EOF. - _, _, err = buffer.ReadFrom(packet) - assert.Equal(io.EOF, err) + if _, _, err = buffer.ReadFrom(packet); !errors.Is(io.EOF, err) { + t.Fatalf("Unexpected err %v wanted io.EOF", err) + } } func TestShortBuffer(t *testing.T) { - assert := assert.New(t) - buffer := NewPacketBuffer() addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") - assert.NoError(err) + if err != nil { + t.Fatal(err) + } // Write once. n, err := buffer.WriteTo([]byte{0, 1, 2, 3}, addr) - assert.NoError(err) - assert.Equal(4, n) + if err != nil { + t.Fatal(err) + } + equalInt(t, 4, n) // Try to read with a short buffer. packet := make([]byte, 3) var raddr net.Addr n, raddr, err = buffer.ReadFrom(packet) - assert.Equal(io.ErrShortBuffer, err) - assert.Equal(nil, raddr) - assert.Equal(0, n) + if !errors.Is(io.ErrShortBuffer, err) { + t.Fatalf("Unexpected err %v wanted io.ErrShortBuffer", err) + } + equalUDPAddr(t, nil, raddr) + equalInt(t, 0, n) // Close. - assert.NoError(buffer.Close()) + if err = buffer.Close(); err != nil { + t.Fatal(err) + } // Make sure you can Close twice. - assert.NoError(buffer.Close()) + if err = buffer.Close(); err != nil { + t.Fatal(err) + } } func TestWraparound(t *testing.T) { - assert := assert.New(t) - buffer := NewPacketBuffer() addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") - assert.NoError(err) + if err != nil { + t.Fatal(err) + } // Write multiple. n, err := buffer.WriteTo([]byte{0, 1, 2, 3}, addr) - assert.NoError(err) - assert.Equal(4, n) + if err != nil { + t.Fatal(err) + } + equalInt(t, 4, n) - n, err = buffer.WriteTo([]byte{4, 5}, addr) - assert.NoError(err) - assert.Equal(2, n) + if n, err = buffer.WriteTo([]byte{4, 5}, addr); err != nil { + t.Fatal(err) + } + equalInt(t, 2, n) - n, err = buffer.WriteTo([]byte{6, 7, 8}, addr) - assert.NoError(err) - assert.Equal(3, n) + if n, err = buffer.WriteTo([]byte{6, 7, 8}, addr); err != nil { + t.Fatal(err) + } + equalInt(t, 3, n) // Verify underlying buffer length. // Packet 1: buffer does not grow. // Packet 2: buffer doubles from 1 to 2. // Packet 3: buffer doubles from 2 to 4. - assert.Equal(4, len(buffer.packets)) + equalInt(t, 4, len(buffer.packets)) // Read once. packet := make([]byte, 4) var raddr net.Addr - n, raddr, err = buffer.ReadFrom(packet) - assert.NoError(err) - assert.Equal(4, n) - assert.Equal([]byte{0, 1, 2, 3}, packet[:n]) - assert.Equal(addr, raddr) + if n, raddr, err = buffer.ReadFrom(packet); err != nil { + t.Fatal(err) + } + equalInt(t, 4, n) + equalBytes(t, []byte{0, 1, 2, 3}, packet[:n]) + equalUDPAddr(t, addr, raddr) // Write again. - n, err = buffer.WriteTo([]byte{9, 10, 11}, addr) - assert.NoError(err) - assert.Equal(3, n) + if n, err = buffer.WriteTo([]byte{9, 10, 11}, addr); err != nil { + t.Fatal(err) + } + equalInt(t, 3, n) // Verify underlying buffer length. // No change in buffer size. - assert.Equal(4, len(buffer.packets)) + equalInt(t, 4, len(buffer.packets)) // Write again and verify buffer grew. - n, err = buffer.WriteTo([]byte{12, 13, 14, 15, 16, 17, 18, 19}, addr) - assert.NoError(err) - assert.Equal(8, n) - assert.Equal(4, len(buffer.packets)) + if n, err = buffer.WriteTo([]byte{12, 13, 14, 15, 16, 17, 18, 19}, addr); err != nil { + t.Fatal(err) + } + equalInt(t, 8, n) + equalInt(t, 4, len(buffer.packets)) // Close. - assert.NoError(buffer.Close()) + if err = buffer.Close(); err != nil { + t.Fatal(err) + } } func TestBufferAsync(t *testing.T) { - assert := assert.New(t) - buffer := NewPacketBuffer() addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") - assert.NoError(err) + if err != nil { + t.Fatal(err) + } // Start up a goroutine to start a blocking read. - done := make(chan struct{}) + done := make(chan string) go func() { packet := make([]byte, 4) n, raddr, rErr := buffer.ReadFrom(packet) - assert.NoError(rErr) - assert.Equal(2, n) - assert.Equal([]byte{0, 1}, packet[:n]) - assert.Equal(addr, raddr) + if rErr != nil { + done <- rErr.Error() + return + } - _, _, err = buffer.ReadFrom(packet) - assert.Equal(io.EOF, err) + equalInt(t, 2, n) + equalBytes(t, []byte{0, 1}, packet[:n]) + equalUDPAddr(t, addr, raddr) - close(done) + _, _, readErr := buffer.ReadFrom(packet) + if !errors.Is(io.EOF, readErr) { + done <- fmt.Sprintf("Unexpected err %v wanted io.EOF", readErr) + } else { + close(done) + } }() // Wait for the reader to start reading. @@ -203,16 +263,22 @@ func TestBufferAsync(t *testing.T) { // Write once n, err := buffer.WriteTo([]byte{0, 1}, addr) - assert.NoError(err) - assert.Equal(2, n) + if err != nil { + t.Fatal(err) + } + equalInt(t, 2, n) // Wait for the reader to start reading again. time.Sleep(time.Millisecond) // Close will unblock the reader. - assert.NoError(buffer.Close()) + if err = buffer.Close(); err != nil { + t.Fatal(err) + } - <-done + if routineFail, ok := <-done; ok { + t.Fatal(routineFail) + } } func benchmarkBufferWR(b *testing.B, size int64, write bool, grow int) { // nolint:unparam From cb62aac052f2e2fc3f1dd97b5976e33a861e76b7 Mon Sep 17 00:00:00 2001 From: Sean DuBois <duboisea@amazon.com> Date: Fri, 31 May 2024 11:15:42 -0400 Subject: [PATCH 097/146] Fix typo in test HadnshakeCurves -> HandshakeCurves --- conn_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/conn_test.go b/conn_test.go index f0a961afc..7f6ff1d43 100644 --- a/conn_test.go +++ b/conn_test.go @@ -3036,22 +3036,22 @@ func TestEllipticCurveConfiguration(t *testing.T) { for _, test := range []struct { Name string ConfigCurves []elliptic.Curve - HadnshakeCurves []elliptic.Curve + HandshakeCurves []elliptic.Curve }{ { Name: "Curve defaulting", ConfigCurves: nil, - HadnshakeCurves: defaultCurves, + HandshakeCurves: defaultCurves, }, { Name: "Single curve", ConfigCurves: []elliptic.Curve{elliptic.X25519}, - HadnshakeCurves: []elliptic.Curve{elliptic.X25519}, + HandshakeCurves: []elliptic.Curve{elliptic.X25519}, }, { Name: "Multiple curves", ConfigCurves: []elliptic.Curve{elliptic.P384, elliptic.X25519}, - HadnshakeCurves: []elliptic.Curve{elliptic.P384, elliptic.X25519}, + HandshakeCurves: []elliptic.Curve{elliptic.P384, elliptic.X25519}, }, } { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) @@ -3074,13 +3074,13 @@ func TestEllipticCurveConfiguration(t *testing.T) { 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 && len(test.HandshakeCurves) != len(server.fsm.cfg.ellipticCurves) { + t.Fatalf("Failed to default Elliptic curves, expected %d, got: %d", len(test.HandshakeCurves), 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)) + if len(test.HandshakeCurves) != len(server.fsm.cfg.ellipticCurves) { + t.Fatalf("Failed to configure Elliptic curves, expect %d, got %d", len(test.HandshakeCurves), len(server.fsm.cfg.ellipticCurves)) } for i, c := range test.ConfigCurves { if c != server.fsm.cfg.ellipticCurves[i] { From efd6737dc408e5b1219c3ecb8b172213f720938d Mon Sep 17 00:00:00 2001 From: Sean DuBois <duboisea@amazon.com> Date: Fri, 31 May 2024 14:24:58 -0400 Subject: [PATCH 098/146] Add test for PSK and Identity * Assert that ServerKeyExchange is only sent with PSKIdentityHint is set on the server side. * Assert that a empty PSKIdentityHint can be used for clients. Resolves #389 --- conn.go | 2 +- conn_test.go | 118 ++++++++++++++++++++++++++++++++++++-- examples/dial/psk/main.go | 2 +- examples/util/util.go | 3 +- 4 files changed, 115 insertions(+), 10 deletions(-) diff --git a/conn.go b/conn.go index 1ddc70963..332d9a211 100644 --- a/conn.go +++ b/conn.go @@ -969,7 +969,7 @@ func (c *Conn) isHandshakeCompletedSuccessfully() bool { return boolean.bool } -func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFlight flightVal, initialState handshakeState) error { //nolint:gocognit +func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFlight flightVal, initialState handshakeState) error { //nolint:gocognit,contextcheck c.fsm = newHandshakeFSM(&c.state, c.handshakeCache, cfg, initialFlight) done := make(chan struct{}) diff --git a/conn_test.go b/conn_test.go index 7f6ff1d43..90d1b004e 100644 --- a/conn_test.go +++ b/conn_test.go @@ -539,6 +539,7 @@ func TestPSK(t *testing.T) { for _, test := range []struct { Name string + ClientIdentity []byte ServerIdentity []byte CipherSuites []CipherSuiteID ClientVerifyConnection func(*State) error @@ -550,11 +551,13 @@ func TestPSK(t *testing.T) { { Name: "Server identity specified", ServerIdentity: []byte("Test Identity"), + ClientIdentity: []byte("Client Identity"), CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, }, { Name: "Server identity specified - Server verify connection fails", ServerIdentity: []byte("Test Identity"), + ClientIdentity: []byte("Client Identity"), CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, ServerVerifyConnection: func(*State) error { return errExample @@ -566,6 +569,7 @@ func TestPSK(t *testing.T) { { Name: "Server identity specified - Client verify connection fails", ServerIdentity: []byte("Test Identity"), + ClientIdentity: []byte("Client Identity"), CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, ClientVerifyConnection: func(*State) error { return errExample @@ -577,25 +581,33 @@ func TestPSK(t *testing.T) { { Name: "Server identity nil", ServerIdentity: nil, + ClientIdentity: []byte("Client Identity"), CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, }, { Name: "TLS_PSK_WITH_AES_128_CBC_SHA256", ServerIdentity: nil, + ClientIdentity: []byte("Client Identity"), CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CBC_SHA256}, }, { Name: "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", ServerIdentity: nil, + ClientIdentity: []byte("Client Identity"), CipherSuites: []CipherSuiteID{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256}, }, + { + Name: "Client identity empty", + ServerIdentity: nil, + ClientIdentity: []byte{}, + CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, + }, } { test := test t.Run(test.Name, func(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - clientIdentity := []byte("Client Identity") type result struct { c *Conn err error @@ -612,7 +624,7 @@ func TestPSK(t *testing.T) { return []byte{0xAB, 0xC1, 0x23}, nil }, - PSKIdentityHint: clientIdentity, + PSKIdentityHint: test.ClientIdentity, CipherSuites: test.CipherSuites, VerifyConnection: test.ClientVerifyConnection, } @@ -623,8 +635,9 @@ func TestPSK(t *testing.T) { config := &Config{ PSK: func(hint []byte) ([]byte, error) { - if !bytes.Equal(clientIdentity, hint) { - return nil, fmt.Errorf("%w: expected(% 02x) actual(% 02x)", errTestPSKInvalidIdentity, clientIdentity, hint) + fmt.Println(hint) + if !bytes.Equal(test.ClientIdentity, hint) { + return nil, fmt.Errorf("%w: expected(% 02x) actual(% 02x)", errTestPSKInvalidIdentity, test.ClientIdentity, hint) } return []byte{0xAB, 0xC1, 0x23}, nil }, @@ -649,8 +662,8 @@ func TestPSK(t *testing.T) { } actualPSKIdentityHint := server.ConnectionState().IdentityHint - if !bytes.Equal(actualPSKIdentityHint, clientIdentity) { - t.Errorf("TestPSK: Server ClientPSKIdentity Mismatch '%s': expected(%v) actual(%v)", test.Name, clientIdentity, actualPSKIdentityHint) + if !bytes.Equal(actualPSKIdentityHint, test.ClientIdentity) { + t.Errorf("TestPSK: Server ClientPSKIdentity Mismatch '%s': expected(%v) actual(%v)", test.Name, test.ClientIdentity, actualPSKIdentityHint) } defer func() { @@ -713,6 +726,99 @@ func TestPSKHintFail(t *testing.T) { } } +// Assert that ServerKeyExchange is only sent if Identity is set on server side +func TestPSKServerKeyExchange(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(time.Second * 20) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + for _, test := range []struct { + Name string + SetIdentity bool + }{ + { + Name: "Server Identity Set", + SetIdentity: true, + }, + { + Name: "Server Not Identity Set", + SetIdentity: false, + }, + } { + test := test + t.Run(test.Name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + gotServerKeyExchange := false + + clientErr := make(chan error, 1) + ca, cb := dpipe.Pipe() + cbAnalyzer := &connWithCallback{Conn: cb} + cbAnalyzer.onWrite = func(in []byte) { + messages, err := recordlayer.UnpackDatagram(in) + if err != nil { + t.Fatal(err) + } + + for i := range messages { + h := &handshake.Handshake{} + _ = h.Unmarshal(messages[i][recordlayer.FixedHeaderSize:]) + + if h.Header.Type == handshake.TypeServerKeyExchange { + gotServerKeyExchange = true + } + } + } + + go func() { + conf := &Config{ + PSK: func([]byte) ([]byte, error) { + return []byte{0xAB, 0xC1, 0x23}, nil + }, + PSKIdentityHint: []byte{0xAB, 0xC1, 0x23}, + CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, + } + + if client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), conf, false); err != nil { + clientErr <- err + } else { + clientErr <- client.Close() //nolint + } + }() + + config := &Config{ + PSK: func([]byte) ([]byte, error) { + return []byte{0xAB, 0xC1, 0x23}, nil + }, + CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, + } + if test.SetIdentity { + config.PSKIdentityHint = []byte{0xAB, 0xC1, 0x23} + } + + if server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cbAnalyzer), cbAnalyzer.RemoteAddr(), config, false); err != nil { + t.Fatalf("TestPSK: Server error %v", err) + } else { + if err = server.Close(); err != nil { + t.Fatal(err) + } + } + + if err := <-clientErr; err != nil { + t.Fatalf("TestPSK: Client error %v", err) + } + + if gotServerKeyExchange != test.SetIdentity { + t.Fatalf("Mismatch between setting Identity and getting a ServerKeyExchange exp(%t) actual(%t)", test.SetIdentity, gotServerKeyExchange) + } + }) + } +} + func TestClientTimeout(t *testing.T) { // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) diff --git a/examples/dial/psk/main.go b/examples/dial/psk/main.go index 492ecdd61..b70efdcc3 100644 --- a/examples/dial/psk/main.go +++ b/examples/dial/psk/main.go @@ -28,7 +28,7 @@ func main() { fmt.Printf("Server's hint: %s \n", hint) return []byte{0xAB, 0xC1, 0x23}, nil }, - PSKIdentityHint: []byte("Pion DTLS Client"), + PSKIdentityHint: []byte{}, CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8}, ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, } diff --git a/examples/util/util.go b/examples/util/util.go index f6a9642c0..e15a2f360 100644 --- a/examples/util/util.go +++ b/examples/util/util.go @@ -11,7 +11,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "os" "path/filepath" @@ -70,7 +69,7 @@ func LoadKeyAndCertificate(keyPath string, certificatePath string) (tls.Certific // LoadCertificate Load/read certificate(s) from file func LoadCertificate(path string) (*tls.Certificate, error) { - rawData, err := ioutil.ReadFile(filepath.Clean(path)) + rawData, err := os.ReadFile(filepath.Clean(path)) if err != nil { return nil, err } From fbbdf6674312a471a701d05c7ba68ab7a4a79935 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 00:29:47 +0000 Subject: [PATCH 099/146] Update module golang.org/x/net to v0.25.0 Generated by renovateBot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index f0c16f9d5..dfaff6fe3 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.2 - golang.org/x/crypto v0.22.0 - golang.org/x/net v0.24.0 + golang.org/x/crypto v0.23.0 + golang.org/x/net v0.25.0 ) go 1.19 diff --git a/go.sum b/go.sum index 8dd49ba60..b6153ae9d 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -29,8 +29,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From edc7ad02205ffc42622cdff7d04eba4970116eee Mon Sep 17 00:00:00 2001 From: Sukun <sukunrt@gmail.com> Date: Mon, 4 Mar 2024 19:49:52 +0530 Subject: [PATCH 100/146] Limit size of encrypted packet queue Before we would queue unbounded encrypted data until the handshake finished/timed out. This sets a limit of 100 packets until the handshake completes. --- conn.go | 94 ++++++++++++++++++++++++++++++++++------------------ conn_test.go | 84 ++++++++++++++++++++++++++++++++++++++++++++++ resume.go | 6 +++- 3 files changed, 150 insertions(+), 34 deletions(-) diff --git a/conn.go b/conn.go index 332d9a211..e65163cf7 100644 --- a/conn.go +++ b/conn.go @@ -35,6 +35,9 @@ const ( inboundBufferSize = 8192 // Default replay protection window is specified by RFC 6347 Section 4.1.2.6 defaultReplayProtectionWindow = 64 + // maxAppDataPacketQueueSize is the maximum number of app data packets we will + // enqueue before the handshake is completed + maxAppDataPacketQueueSize = 100 ) func invalidKeyingLabels() map[string]bool { @@ -88,7 +91,7 @@ type Conn struct { replayProtectionWindow uint } -func createConn(ctx context.Context, nextConn net.PacketConn, rAddr net.Addr, config *Config, isClient bool, initialState *State) (*Conn, error) { +func createConn(nextConn net.PacketConn, rAddr net.Addr, config *Config, isClient bool) (*Conn, error) { if err := validateConfig(config); err != nil { return nil, err } @@ -97,21 +100,6 @@ func createConn(ctx context.Context, nextConn net.PacketConn, rAddr net.Addr, co return nil, errNilNextConn } - cipherSuites, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil) - if err != nil { - return nil, err - } - - signatureSchemes, err := signaturehash.ParseSignatureSchemes(config.SignatureSchemes, config.InsecureHashes) - if err != nil { - return nil, err - } - - workerInterval := initialTickerInterval - if config.FlightInterval != 0 { - workerInterval = config.FlightInterval - } - loggerFactory := config.LoggerFactory if loggerFactory == nil { loggerFactory = logging.NewDefaultLoggerFactory() @@ -162,6 +150,28 @@ func createConn(ctx context.Context, nextConn net.PacketConn, rAddr net.Addr, co c.setRemoteEpoch(0) c.setLocalEpoch(0) + return c, nil +} + +func handshakeConn(ctx context.Context, conn *Conn, config *Config, isClient bool, initialState *State) (*Conn, error) { + if conn == nil { + return nil, errNilNextConn + } + + cipherSuites, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil) + if err != nil { + return nil, err + } + + signatureSchemes, err := signaturehash.ParseSignatureSchemes(config.SignatureSchemes, config.InsecureHashes) + if err != nil { + return nil, err + } + + workerInterval := initialTickerInterval + if config.FlightInterval != 0 { + workerInterval = config.FlightInterval + } serverName := config.ServerName // Do not allow the use of an IP address literal as an SNI value. @@ -193,7 +203,7 @@ func createConn(ctx context.Context, nextConn net.PacketConn, rAddr net.Addr, co clientCAs: config.ClientCAs, customCipherSuites: config.CustomCipherSuites, retransmitInterval: workerInterval, - log: logger, + log: conn.log, initialEpoch: 0, keyLogWriter: config.KeyLogWriter, sessionStore: config.SessionStore, @@ -222,16 +232,16 @@ func createConn(ctx context.Context, nextConn net.PacketConn, rAddr net.Addr, co var initialFSMState handshakeState if initialState != nil { - if c.state.isClient { + if conn.state.isClient { initialFlight = flight5 } else { initialFlight = flight6 } initialFSMState = handshakeFinished - c.state = *initialState + conn.state = *initialState } else { - if c.state.isClient { + if conn.state.isClient { initialFlight = flight1 } else { initialFlight = flight0 @@ -239,13 +249,13 @@ func createConn(ctx context.Context, nextConn net.PacketConn, rAddr net.Addr, co initialFSMState = handshakePreparing } // Do handshake - if err := c.handshake(ctx, hsCfg, initialFlight, initialFSMState); err != nil { + if err := conn.handshake(ctx, hsCfg, initialFlight, initialFSMState); err != nil { return nil, err } - c.log.Trace("Handshake Completed") + conn.log.Trace("Handshake Completed") - return c, nil + return conn, nil } // Dial connects to the given network address and establishes a DTLS connection on top. @@ -301,7 +311,12 @@ func ClientWithContext(ctx context.Context, conn net.PacketConn, rAddr net.Addr, return nil, errPSKAndIdentityMustBeSetForClient } - return createConn(ctx, conn, rAddr, config, true, nil) + dconn, err := createConn(conn, rAddr, config, true) + if err != nil { + return nil, err + } + + return handshakeConn(ctx, dconn, config, true, nil) } // ServerWithContext listens for incoming DTLS connections. @@ -309,8 +324,11 @@ func ServerWithContext(ctx context.Context, conn net.PacketConn, rAddr net.Addr, if config == nil { return nil, errNoConfigProvided } - - return createConn(ctx, conn, rAddr, config, false, nil) + dconn, err := createConn(conn, rAddr, config, false) + if err != nil { + return nil, err + } + return handshakeConn(ctx, dconn, config, false, nil) } // Read reads data from the connection. @@ -738,6 +756,14 @@ func (c *Conn) handleQueuedPackets(ctx context.Context) error { return nil } +func (c *Conn) enqueueEncryptedPackets(packet addrPkt) bool { + if len(c.encryptedPackets) < maxAppDataPacketQueueSize { + c.encryptedPackets = append(c.encryptedPackets, packet) + return true + } + return false +} + func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.Addr, enqueue bool) (bool, *alert.Alert, error) { //nolint:gocognit h := &recordlayer.Header{} // Set connection ID size so that records of content type tls12_cid will @@ -751,7 +777,6 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A c.log.Debugf("discarded broken packet: %v", err) return false, nil, nil } - // Validate epoch remoteEpoch := c.state.getRemoteEpoch() if h.Epoch > remoteEpoch { @@ -762,8 +787,9 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A return false, nil, nil } if enqueue { - c.log.Debug("received packet of next epoch, queuing packet") - c.encryptedPackets = append(c.encryptedPackets, addrPkt{rAddr, buf}) + if ok := c.enqueueEncryptedPackets(addrPkt{rAddr, buf}); ok { + c.log.Debug("received packet of next epoch, queuing packet") + } } return false, nil, nil } @@ -790,8 +816,9 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A if h.Epoch != 0 { if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { if enqueue { - c.encryptedPackets = append(c.encryptedPackets, addrPkt{rAddr, buf}) - c.log.Debug("handshake not finished, queuing packet") + if ok := c.enqueueEncryptedPackets(addrPkt{rAddr, buf}); ok { + c.log.Debug("handshake not finished, queuing packet") + } } return false, nil, nil } @@ -883,8 +910,9 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A case *protocol.ChangeCipherSpec: if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { if enqueue { - c.encryptedPackets = append(c.encryptedPackets, addrPkt{rAddr, buf}) - c.log.Debugf("CipherSuite not initialized, queuing packet") + if ok := c.enqueueEncryptedPackets(addrPkt{rAddr, buf}); ok { + c.log.Debugf("CipherSuite not initialized, queuing packet") + } } return false, nil, nil } diff --git a/conn_test.go b/conn_test.go index 90d1b004e..17eb932f0 100644 --- a/conn_test.go +++ b/conn_test.go @@ -3279,3 +3279,87 @@ func (c *connWithCallback) Write(b []byte) (int, error) { } return c.Conn.Write(b) } + +func TestApplicationDataQueueLimited(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(time.Second * 20) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + ca, cb := dpipe.Pipe() + defer ca.Close() //nolint:errcheck + defer cb.Close() //nolint:errcheck + + done := make(chan struct{}) + go func() { + serverCert, err := selfsign.GenerateSelfSigned() + if err != nil { + t.Error(err) + return + } + cfg := &Config{} + cfg.Certificates = []tls.Certificate{serverCert} + + dconn, err := createConn(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), cfg, false) + if err != nil { + t.Error(err) + return + } + go func() { + for i := 0; i < 5; i++ { + dconn.lock.RLock() + qlen := len(dconn.encryptedPackets) + dconn.lock.RUnlock() + if qlen > maxAppDataPacketQueueSize { + t.Error("too many encrypted packets enqueued", len(dconn.encryptedPackets)) + } + t.Log(qlen) + time.Sleep(1 * time.Second) + } + }() + if _, err := handshakeConn(ctx, dconn, cfg, false, nil); err == nil { + t.Error("expected handshake to fail") + } + close(done) + }() + extensions := []extension.Extension{} + + time.Sleep(50 * time.Millisecond) + + err := sendClientHello([]byte{}, ca, 0, extensions) + if err != nil { + t.Fatal(err) + } + + time.Sleep(50 * time.Millisecond) + + for i := 0; i < 1000; i++ { + // Send an application data packet + packet, err := (&recordlayer.RecordLayer{ + Header: recordlayer.Header{ + Version: protocol.Version1_2, + SequenceNumber: uint64(3), + Epoch: 1, // use an epoch greater than 0 + }, + Content: &protocol.ApplicationData{ + Data: []byte{1, 2, 3, 4}, + }, + }).Marshal() + if err != nil { + t.Fatal(err) + } + ca.Write(packet) // nolint + if i%100 == 0 { + time.Sleep(10 * time.Millisecond) + } + } + time.Sleep(1 * time.Second) + ca.Close() // nolint + <-done +} diff --git a/resume.go b/resume.go index 9e8a2ae42..6cd1c5a69 100644 --- a/resume.go +++ b/resume.go @@ -13,7 +13,11 @@ func Resume(state *State, conn net.PacketConn, rAddr net.Addr, config *Config) ( if err := state.initCipherSuite(); err != nil { return nil, err } - c, err := createConn(context.Background(), conn, rAddr, config, state.isClient, state) + dconn, err := createConn(conn, rAddr, config, state.isClient) + if err != nil { + return nil, err + } + c, err := handshakeConn(context.Background(), dconn, config, state.isClient, state) if err != nil { return nil, err } From eddca226ba5e5b09fb7ad361ae0b2531cde22370 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 23:16:11 +0000 Subject: [PATCH 101/146] Update module golang.org/x/crypto to v0.24.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dfaff6fe3..7c2232390 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.2 - golang.org/x/crypto v0.23.0 + golang.org/x/crypto v0.24.0 golang.org/x/net v0.25.0 ) diff --git a/go.sum b/go.sum index b6153ae9d..a77b47cb2 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From 61b346641ead1eeff98d42c397c1b8db7e9583f6 Mon Sep 17 00:00:00 2001 From: Mingye Chen <mingyechen82@gmail.com> Date: Sun, 10 Sep 2023 21:47:03 -0400 Subject: [PATCH 102/146] Add ability to select cert based on ch rand bytes --- certificate.go | 5 ++++ config.go | 3 ++ conn.go | 1 + conn_test.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++ flight1handler.go | 4 +++ flight4handler.go | 1 + handshaker.go | 1 + state.go | 5 ++++ 8 files changed, 93 insertions(+) diff --git a/certificate.go b/certificate.go index 519fc875f..e8dd2b83f 100644 --- a/certificate.go +++ b/certificate.go @@ -9,6 +9,8 @@ import ( "crypto/x509" "fmt" "strings" + + "github.com/pion/dtls/v2/pkg/protocol/handshake" ) // ClientHelloInfo contains information from a ClientHello message in order to @@ -22,6 +24,9 @@ type ClientHelloInfo struct { // CipherSuites lists the CipherSuites supported by the client (e.g. // TLS_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256). CipherSuites []CipherSuiteID + + // RandomBytes stores the client hello random bytes + RandomBytes [handshake.RandomBytesLength]byte } // CertificateRequestInfo contains information from a server's diff --git a/config.go b/config.go index d765ecd91..3cb9ab07f 100644 --- a/config.go +++ b/config.go @@ -198,6 +198,9 @@ type Config struct { // https://datatracker.ietf.org/doc/html/rfc9146#section-4 PaddingLengthGenerator func(uint) uint + // HelloRandomBytesGenerator generates custom client hello random bytes. + HelloRandomBytesGenerator func() [handshake.RandomBytesLength]byte + // Handshake hooks: hooks can be used for testing invalid messages, // mimicking other implementations or randomizing fields, which is valuable // for applications that need censorship-resistance by making diff --git a/conn.go b/conn.go index e65163cf7..1c670cc2c 100644 --- a/conn.go +++ b/conn.go @@ -212,6 +212,7 @@ func handshakeConn(ctx context.Context, conn *Conn, config *Config, isClient boo localGetClientCertificate: config.GetClientCertificate, insecureSkipHelloVerify: config.InsecureSkipVerifyHello, connectionIDGenerator: config.ConnectionIDGenerator, + helloRandomBytesGenerator: config.HelloRandomBytesGenerator, clientHelloMessageHook: config.ClientHelloMessageHook, serverHelloMessageHook: config.ServerHelloMessageHook, certificateRequestMessageHook: config.CertificateRequestMessageHook, diff --git a/conn_test.go b/conn_test.go index 17eb932f0..960118327 100644 --- a/conn_test.go +++ b/conn_test.go @@ -3363,3 +3363,76 @@ func TestApplicationDataQueueLimited(t *testing.T) { ca.Close() // nolint <-done } + +func TestHelloRandom(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{}) + + chRandom := [handshake.RandomBytesLength]byte{} + _, err = rand.Read(chRandom[:]) + if err != nil { + t.Fatal(err) + } + + go func() { + server, sErr := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ + GetCertificate: func(chi *ClientHelloInfo) (*tls.Certificate, error) { + if len(chi.CipherSuites) == 0 { + return &certificate, nil + } + + if !bytes.Equal(chi.RandomBytes[:], chRandom[:]) { + t.Error("client hello random differs") + } + + return &certificate, nil + }, + LoggerFactory: logging.NewDefaultLoggerFactory(), + }, 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, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ + LoggerFactory: logging.NewDefaultLoggerFactory(), + HelloRandomBytesGenerator: func() [handshake.RandomBytesLength]byte { + return chRandom + }, + 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/flight1handler.go b/flight1handler.go index 08a8f3921..6448fef79 100644 --- a/flight1handler.go +++ b/flight1handler.go @@ -57,6 +57,10 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha return nil, nil, err } + if cfg.helloRandomBytesGenerator != nil { + state.localRandom.RandomBytes = cfg.helloRandomBytesGenerator() + } + extensions := []extension.Extension{ &extension.SupportedSignatureAlgorithms{ SignatureHashAlgorithms: cfg.localSignatureSchemes, diff --git a/flight4handler.go b/flight4handler.go index 86f21464b..840a24f15 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -300,6 +300,7 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha certificate, err := cfg.getCertificate(&ClientHelloInfo{ ServerName: state.serverName, CipherSuites: []ciphersuite.ID{state.cipherSuite.ID()}, + RandomBytes: state.remoteRandom.RandomBytes, }) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, err diff --git a/handshaker.go b/handshaker.go index 317cb4e4e..09c6b4e3b 100644 --- a/handshaker.go +++ b/handshaker.go @@ -114,6 +114,7 @@ type handshakeConfig struct { ellipticCurves []elliptic.Curve insecureSkipHelloVerify bool connectionIDGenerator func() []byte + helloRandomBytesGenerator func() [handshake.RandomBytesLength]byte onFlightState func(flightVal, handshakeState) log logging.LeveledLogger diff --git a/state.go b/state.go index 35a5b64fb..bc93bdf0c 100644 --- a/state.go +++ b/state.go @@ -258,3 +258,8 @@ func (s *State) getSRTPProtectionProfile() SRTPProtectionProfile { return 0 } + +// RemoteRandomBytes returns the remote client hello random bytes +func (s *State) RemoteRandomBytes() [handshake.RandomBytesLength]byte { + return s.remoteRandom.RandomBytes +} From a5d1fac9900f1453716496731650ec20bfcf6cf5 Mon Sep 17 00:00:00 2001 From: Vladislav Yarmak <vladislav-ex-src@vm-0.com> Date: Sat, 30 Sep 2023 23:59:50 +0300 Subject: [PATCH 103/146] Flight3: respect curves configuration Reuse logic from Flight1 to ensure correct behaviour. Signed-off-by: Vladislav Yarmak <vladislav-ex-src@vm-0.com> --- flight3handler.go | 3 +- flight3handler_test.go | 109 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 flight3handler_test.go diff --git a/flight3handler.go b/flight3handler.go index 08549fb76..b3f82fe76 100644 --- a/flight3handler.go +++ b/flight3handler.go @@ -249,10 +249,11 @@ func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha RenegotiatedConnection: 0, }, } + if state.namedCurve != 0 { 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/flight3handler_test.go b/flight3handler_test.go new file mode 100644 index 000000000..537e206db --- /dev/null +++ b/flight3handler_test.go @@ -0,0 +1,109 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +package dtls + +import ( + "context" + "math/rand" + "testing" + "time" + + "github.com/pion/dtls/v2/pkg/crypto/elliptic" + dtlsnet "github.com/pion/dtls/v2/pkg/net" + "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/v3/dpipe" + "github.com/pion/transport/v3/test" +) + +// Assert that SupportedEllipticCurves is only sent when a ECC CipherSuite is available +func TestSupportedEllipticCurves(t *testing.T) { + // Limit runtime in case of deadlocks + lim := test.TimeOut(time.Second * 20) + defer lim.Stop() + + // Check for leaking routines + report := test.CheckRoutines(t) + defer report() + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + expectedCurves := defaultCurves + var actualCurves []elliptic.Curve + + rand.Shuffle(len(expectedCurves), func(i, j int) { + expectedCurves[i], expectedCurves[j] = expectedCurves[j], expectedCurves[i] + }) + + clientErr := make(chan error, 1) + ca, cb := dpipe.Pipe() + caAnalyzer := &connWithCallback{Conn: ca} + caAnalyzer.onWrite = func(in []byte) { + messages, err := recordlayer.UnpackDatagram(in) + if err != nil { + t.Fatal(err) + } + + for i := range messages { + h := &handshake.Handshake{} + _ = h.Unmarshal(messages[i][recordlayer.FixedHeaderSize:]) + + if h.Header.Type == handshake.TypeClientHello { + clientHello := &handshake.MessageClientHello{} + msg, err := h.Message.Marshal() + + if err != nil { + t.Fatal(err) + } else if err = clientHello.Unmarshal(msg); err != nil { + t.Fatal(err) + } + + for _, e := range clientHello.Extensions { + if e.TypeValue() == extension.SupportedEllipticCurvesTypeValue { + if c, ok := e.(*extension.SupportedEllipticCurves); ok { + actualCurves = c.EllipticCurves + } + } + } + } + } + } + + go func() { + conf := &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + EllipticCurves: expectedCurves, + } + + if client, err := testClient(ctx, dtlsnet.PacketConnFromConn(caAnalyzer), caAnalyzer.RemoteAddr(), conf, false); err != nil { + clientErr <- err + } else { + clientErr <- client.Close() //nolint + } + }() + + config := &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + } + + if server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, true); err != nil { + t.Fatalf("Server error %v", err) + } else { + if err = server.Close(); err != nil { + t.Fatal(err) + } + } + + if err := <-clientErr; err != nil { + t.Fatalf("Client error %v", err) + } + + for i := range expectedCurves { + if expectedCurves[i] != actualCurves[i] { + t.Fatal("List of curves in SupportedEllipticCurves does not match config") + } + } +} From 45e16a098c4753d01d3515750eae1bfd2b5aa58f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 00:57:44 +0000 Subject: [PATCH 104/146] Update module golang.org/x/net to v0.26.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7c2232390..d709d7b60 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.2 golang.org/x/crypto v0.24.0 - golang.org/x/net v0.25.0 + golang.org/x/net v0.26.0 ) go 1.19 diff --git a/go.sum b/go.sum index a77b47cb2..913ee4e43 100644 --- a/go.sum +++ b/go.sum @@ -29,8 +29,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 48d67487d931b456de0d7dbaca0c8b68f5498f4c Mon Sep 17 00:00:00 2001 From: Anonymous <anonymous@github.com> Date: Thu, 14 Apr 2022 16:13:21 +0100 Subject: [PATCH 105/146] Implement retransmit backoff according to 4.2.4.1 --- config.go | 4 ++++ conn.go | 3 ++- conn_test.go | 1 - e2e/e2e_lossy_test.go | 16 +++++++------ handshaker.go | 52 ++++++++++++++++++++++++++++++------------- handshaker_test.go | 12 +++++----- 6 files changed, 58 insertions(+), 30 deletions(-) diff --git a/config.go b/config.go index 3cb9ab07f..5763ce530 100644 --- a/config.go +++ b/config.go @@ -57,6 +57,10 @@ type Config struct { // defaults to time.Second FlightInterval time.Duration + // DisableRetransmitBackoff can be used to the disable the backoff feature + // when sending outbound messages as specified in RFC 4347 4.2.4.1 + DisableRetransmitBackoff bool + // PSK sets the pre-shared key used by this DTLS connection // If PSK is non-nil only PSK CipherSuites will be used PSK PSKCallback diff --git a/conn.go b/conn.go index 1c670cc2c..5d0d86fdb 100644 --- a/conn.go +++ b/conn.go @@ -202,7 +202,8 @@ func handshakeConn(ctx context.Context, conn *Conn, config *Config, isClient boo rootCAs: config.RootCAs, clientCAs: config.ClientCAs, customCipherSuites: config.CustomCipherSuites, - retransmitInterval: workerInterval, + initialRetransmitInterval: workerInterval, + disableRetransmitBackoff: config.DisableRetransmitBackoff, log: conn.log, initialEpoch: 0, keyLogWriter: config.KeyLogWriter, diff --git a/conn_test.go b/conn_test.go index 960118327..3b30b23fc 100644 --- a/conn_test.go +++ b/conn_test.go @@ -3319,7 +3319,6 @@ func TestApplicationDataQueueLimited(t *testing.T) { if qlen > maxAppDataPacketQueueSize { t.Error("too many encrypted packets enqueued", len(dconn.encryptedPackets)) } - t.Log(qlen) time.Sleep(1 * time.Second) } }() diff --git a/e2e/e2e_lossy_test.go b/e2e/e2e_lossy_test.go index f646557cd..3e03037ba 100644 --- a/e2e/e2e_lossy_test.go +++ b/e2e/e2e_lossy_test.go @@ -135,10 +135,11 @@ func TestPionE2ELossy(t *testing.T) { go func() { cfg := &dtls.Config{ - FlightInterval: flightInterval, - CipherSuites: test.CipherSuites, - InsecureSkipVerify: true, - MTU: test.MTU, + FlightInterval: flightInterval, + CipherSuites: test.CipherSuites, + InsecureSkipVerify: true, + MTU: test.MTU, + DisableRetransmitBackoff: true, } if test.DoClientAuth { @@ -151,9 +152,10 @@ func TestPionE2ELossy(t *testing.T) { go func() { cfg := &dtls.Config{ - Certificates: []tls.Certificate{serverCert}, - FlightInterval: flightInterval, - MTU: test.MTU, + Certificates: []tls.Certificate{serverCert}, + FlightInterval: flightInterval, + MTU: test.MTU, + DisableRetransmitBackoff: true, } if test.DoClientAuth { diff --git a/handshaker.go b/handshaker.go index 09c6b4e3b..4e0f1ad95 100644 --- a/handshaker.go +++ b/handshaker.go @@ -82,13 +82,14 @@ func (s handshakeState) String() string { } type handshakeFSM struct { - currentFlight flightVal - flights []*packet - retransmit bool - state *State - cache *handshakeCache - cfg *handshakeConfig - closed chan struct{} + currentFlight flightVal + flights []*packet + retransmit bool + retransmitInterval time.Duration + state *State + cache *handshakeCache + cfg *handshakeConfig + closed chan struct{} } type handshakeConfig struct { @@ -109,7 +110,8 @@ type handshakeConfig struct { sessionStore SessionStore rootCAs *x509.CertPool clientCAs *x509.CertPool - retransmitInterval time.Duration + initialRetransmitInterval time.Duration + disableRetransmitBackoff bool customCipherSuites func() []CipherSuite ellipticCurves []elliptic.Curve insecureSkipHelloVerify bool @@ -165,11 +167,12 @@ func newHandshakeFSM( initialFlight flightVal, ) *handshakeFSM { return &handshakeFSM{ - currentFlight: initialFlight, - state: s, - cache: cache, - cfg: cfg, - closed: make(chan struct{}), + currentFlight: initialFlight, + state: s, + cache: cache, + cfg: cfg, + retransmitInterval: cfg.initialRetransmitInterval, + closed: make(chan struct{}), } } @@ -274,11 +277,12 @@ func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, return handshakeErrored, errFlight } - retransmitTimer := time.NewTimer(s.cfg.retransmitInterval) + retransmitTimer := time.NewTimer(s.retransmitInterval) for { select { case done := <-c.recvHandshake(): nextFlight, alert, err := parse(ctx, c, s.state, s.cache, s.cfg) + s.retransmitInterval = s.cfg.initialRetransmitInterval close(done) if alert != nil { if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { @@ -304,8 +308,19 @@ func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, if !s.retransmit { return handshakeWaiting, nil } + + // RFC 4347 4.2.4.1: + // Implementations SHOULD use an initial timer value of 1 second (the minimum defined in RFC 2988 [RFC2988]) + // and double the value at each retransmission, up to no less than the RFC 2988 maximum of 60 seconds. + if !s.cfg.disableRetransmitBackoff { + s.retransmitInterval *= 2 + } + if s.retransmitInterval > time.Second*60 { + s.retransmitInterval = time.Second * 60 + } return handshakeSending, nil case <-ctx.Done(): + s.retransmitInterval = s.cfg.initialRetransmitInterval return handshakeErrored, ctx.Err() } } @@ -320,11 +335,12 @@ func (s *handshakeFSM) finish(ctx context.Context, c flightConn) (handshakeState return handshakeErrored, errFlight } - retransmitTimer := time.NewTimer(s.cfg.retransmitInterval) + retransmitTimer := time.NewTimer(s.retransmitInterval) select { case done := <-c.recvHandshake(): nextFlight, alert, err := parse(ctx, c, s.state, s.cache, s.cfg) close(done) + s.retransmitInterval = s.cfg.initialRetransmitInterval if alert != nil { if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { if err != nil { @@ -342,10 +358,16 @@ func (s *handshakeFSM) finish(ctx context.Context, c flightConn) (handshakeState return handshakeFinished, nil } <-retransmitTimer.C + // RFC 4347 4.2.4.1 + s.retransmitInterval *= 2 + if s.retransmitInterval > time.Second*60 { + s.retransmitInterval = time.Second * 60 + } // Retransmit last flight return handshakeSending, nil case <-ctx.Done(): + s.retransmitInterval = s.cfg.initialRetransmitInterval return handshakeErrored, ctx.Err() } return handshakeFinished, nil diff --git a/handshaker_test.go b/handshaker_test.go index 9bbca6f50..b2bd4443d 100644 --- a/handshaker_test.go +++ b/handshaker_test.go @@ -216,10 +216,10 @@ func TestHandshaker(t *testing.T) { } report := func(t *testing.T) { - // with one second server delay and 100 ms retransmit, there should be close to 10 `Finished` from client - // using a range of 9 - 11 for checking - if cntClientFinished < 8 || cntClientFinished > 11 { - t.Errorf("Number of client finished is wrong, expected: %d - %d times, got: %d times", 9, 11, cntClientFinished) + // with one second server delay and 100 ms retransmit (+ exponential backoff), there should be close to 4 `Finished` from client + // using a range of 3 - 5 for checking + if cntClientFinished < 3 || cntClientFinished > 5 { + t.Errorf("Number of client finished is wrong, expected: %d - %d times, got: %d times", 3, 5, cntClientFinished) } if !isClientFinished { t.Errorf("Client is not finished") @@ -281,7 +281,7 @@ func TestHandshaker(t *testing.T) { }) } }, - retransmitInterval: nonZeroRetransmitInterval, + initialRetransmitInterval: nonZeroRetransmitInterval, } fsm := newHandshakeFSM(&ca.state, ca.handshakeCache, cfg, flight1) @@ -314,7 +314,7 @@ func TestHandshaker(t *testing.T) { }) } }, - retransmitInterval: nonZeroRetransmitInterval, + initialRetransmitInterval: nonZeroRetransmitInterval, } fsm := newHandshakeFSM(&cb.state, cb.handshakeCache, cfg, flight0) From a6d96409c74d75c7547252b310eefdeefd50ab8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toni=20Sol=C3=A9?= <toni.sole@manusa.com> Date: Tue, 4 Jun 2024 11:18:32 +0200 Subject: [PATCH 106/146] Add OnConnectionAttempt to Config Convenience callback that can be fired for Servers with the net.Addr of the remote --- config.go | 7 + conn.go | 5 + conn_test.go | 47 +++++++ .../verify-brute-force-protection/main.go | 132 ++++++++++++++++++ 4 files changed, 191 insertions(+) create mode 100644 examples/listen/verify-brute-force-protection/main.go diff --git a/config.go b/config.go index 5763ce530..0f6813d24 100644 --- a/config.go +++ b/config.go @@ -11,6 +11,7 @@ import ( "crypto/tls" "crypto/x509" "io" + "net" "time" "github.com/pion/dtls/v2/pkg/crypto/elliptic" @@ -221,6 +222,12 @@ type Config struct { // CertificateRequestMessageHook, if not nil, is called when a Certificate Request // message is sent from a server. The returned handshake message replaces the original message. CertificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message + + // OnConnectionAttempt is fired Whenever a connection attempt is made, the server or application can call this callback function. + // The callback function can then implement logic to handle the connection attempt, such as logging the attempt, + // checking against a list of blocked IPs, or counting the attempts to prevent brute force attacks. + // If the callback function returns an error, the connection attempt will be aborted. + OnConnectionAttempt func(net.Addr) error } func defaultConnectContextMaker() (context.Context, func()) { diff --git a/conn.go b/conn.go index 5d0d86fdb..d82228f31 100644 --- a/conn.go +++ b/conn.go @@ -326,6 +326,11 @@ func ServerWithContext(ctx context.Context, conn net.PacketConn, rAddr net.Addr, if config == nil { return nil, errNoConfigProvided } + if config.OnConnectionAttempt != nil { + if err := config.OnConnectionAttempt(rAddr); err != nil { + return nil, err + } + } dconn, err := createConn(conn, rAddr, config, false) if err != nil { return nil, err diff --git a/conn_test.go b/conn_test.go index 3b30b23fc..5560edc3a 100644 --- a/conn_test.go +++ b/conn_test.go @@ -3435,3 +3435,50 @@ func TestHelloRandom(t *testing.T) { t.Error(err) } } + +func TestOnConnectionAttempt(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*20) + defer cancel() + + var clientOnConnectionAttempt, serverOnConnectionAttempt atomic.Int32 + + ca, cb := dpipe.Pipe() + clientErr := make(chan error, 1) + go func() { + _, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ + OnConnectionAttempt: func(in net.Addr) error { + clientOnConnectionAttempt.Store(1) + if in == nil { + t.Fatal("net.Addr is nil") //nolint: govet + } + return nil + }, + }, true) + clientErr <- err + }() + + expectedErr := &FatalError{} + if _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ + OnConnectionAttempt: func(in net.Addr) error { + serverOnConnectionAttempt.Store(1) + if in == nil { + t.Fatal("net.Addr is nil") //nolint: govet + } + return expectedErr + }, + }, true); !errors.Is(err, expectedErr) { + t.Fatal(err) + } + + if err := <-clientErr; err == nil { + t.Fatal(err) + } + + if v := serverOnConnectionAttempt.Load(); v != 1 { + t.Fatal("OnConnectionAttempt did not fire for server") + } + + if v := clientOnConnectionAttempt.Load(); v != 0 { + t.Fatal("OnConnectionAttempt fired for client") + } +} diff --git a/examples/listen/verify-brute-force-protection/main.go b/examples/listen/verify-brute-force-protection/main.go new file mode 100644 index 000000000..b5fb82c42 --- /dev/null +++ b/examples/listen/verify-brute-force-protection/main.go @@ -0,0 +1,132 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +// Package main implements an example DTLS server which verifies client certificates. +// It also implements a basic Brute Force Attack protection. +package main + +import ( + "context" + "crypto/tls" + "crypto/x509" + "fmt" + "net" + "sync" + "time" + + "github.com/pion/dtls/v2" + "github.com/pion/dtls/v2/examples/util" +) + +func main() { + // Prepare the IP to connect to + addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444} + + // Create parent context to cleanup handshaking connections on exit. + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // + // Everything below is the pion-DTLS API! Thanks for using it ❤️. + // + + // ************ Variables used to implement a basic Brute Force Attack protection ************* + var attempts = make(map[string]int) // Map of attempts for each IP address. + var attemptsMutex sync.Mutex // Mutex for the map of attempts. + var attemptsCleaner = time.Now() // Time to be able to clean the map of attempts every X minutes. + + certificate, err := util.LoadKeyAndCertificate("examples/certificates/server.pem", + "examples/certificates/server.pub.pem") + util.Check(err) + + rootCertificate, err := util.LoadCertificate("examples/certificates/server.pub.pem") + util.Check(err) + certPool := x509.NewCertPool() + cert, err := x509.ParseCertificate(rootCertificate.Certificate[0]) + util.Check(err) + certPool.AddCert(cert) + + // Prepare the configuration of the DTLS connection + config := &dtls.Config{ + Certificates: []tls.Certificate{certificate}, + ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, + ClientAuth: dtls.RequireAndVerifyClientCert, + ClientCAs: certPool, + // Create timeout context for accepted connection. + ConnectContextMaker: func() (context.Context, func()) { + return context.WithTimeout(ctx, 30*time.Second) + }, + // This function will be called on each connection attempt. + OnConnectionAttempt: func(addr net.Addr) error { + // *************** Brute Force Attack protection *************** + // Check if the IP address is in the map, and if the IP address has exceeded the limit + attemptsMutex.Lock() + defer attemptsMutex.Unlock() + // Here I implement a time cleaner for the map of attempts, every 5 minutes I will + // decrement by 1 the number of attempts for each IP address. + if time.Now().After(attemptsCleaner.Add(time.Minute * 5)) { + attemptsCleaner = time.Now() + for k, v := range attempts { + if v > 0 { + attempts[k]-- + } + if attempts[k] == 0 { + delete(attempts, k) + } + } + } + // Check if the IP address is in the map, and the IP address has exceeded the limit (Brute Force Attack protection) + attemptIP := addr.(*net.UDPAddr).IP.String() + if attempts[attemptIP] > 10 { + return fmt.Errorf("too many attempts from this IP address") + } + // Here I increment the number of attempts for this IP address (Brute Force Attack protection) + attempts[attemptIP]++ + // *************** END Brute Force Attack protection END *************** + return nil + }, + } + + // Connect to a DTLS server + listener, err := dtls.Listen("udp", addr, config) + util.Check(err) + defer func() { + util.Check(listener.Close()) + }() + + fmt.Println("Listening") + + // Simulate a chat session + hub := util.NewHub() + + go func() { + for { + // Wait for a connection. + conn, err := listener.Accept() + util.Check(err) + // defer conn.Close() // TODO: graceful shutdown + + // `conn` is of type `net.Conn` but may be casted to `dtls.Conn` + // using `dtlsConn := conn.(*dtls.Conn)` in order to to expose + // functions like `ConnectionState` etc. + + // *************** Brute Force Attack protection *************** + // Here I decrease the number of attempts for this IP address + attemptsMutex.Lock() + attemptIP := conn.(*dtls.Conn).RemoteAddr().(*net.UDPAddr).IP.String() + attempts[attemptIP]-- + // If the number of attempts for this IP address is 0, I delete the IP address from the map + if attempts[attemptIP] == 0 { + delete(attempts, attemptIP) + } + attemptsMutex.Unlock() + // *************** END Brute Force Attack protection END *************** + + // Register the connection with the chat hub + hub.Register(conn) + } + }() + + // Start chatting + hub.Chat() +} From 0a1b73ae1d4a6991fcaf5a06ab6da74466529e93 Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Thu, 11 Jul 2024 22:15:42 -0400 Subject: [PATCH 107/146] Respect disableRetransmitBackoff 48d67487d9 only enabled it in sending, not finish --- handshaker.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/handshaker.go b/handshaker.go index 4e0f1ad95..ce3be24c3 100644 --- a/handshaker.go +++ b/handshaker.go @@ -358,8 +358,11 @@ func (s *handshakeFSM) finish(ctx context.Context, c flightConn) (handshakeState return handshakeFinished, nil } <-retransmitTimer.C + // RFC 4347 4.2.4.1 - s.retransmitInterval *= 2 + if !s.cfg.disableRetransmitBackoff { + s.retransmitInterval *= 2 + } if s.retransmitInterval > time.Second*60 { s.retransmitInterval = time.Second * 60 } From 602dc71bb729b0a5a0fb9008bb41a08cd7fb8af7 Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Fri, 12 Jul 2024 15:32:53 -0400 Subject: [PATCH 108/146] Make localConnectionID thread safe Resolves #647 --- conn.go | 12 ++++++------ conn_test.go | 4 ++-- flight0handler.go | 4 ++-- flight1handler.go | 8 ++++---- flight3handler.go | 6 +++--- flight4handler.go | 4 ++-- state.go | 18 +++++++++++++++--- 7 files changed, 34 insertions(+), 22 deletions(-) diff --git a/conn.go b/conn.go index d82228f31..50213652c 100644 --- a/conn.go +++ b/conn.go @@ -699,7 +699,7 @@ func (c *Conn) readAndBuffer(ctx context.Context) error { return netError(err) } - pkts, err := recordlayer.ContentAwareUnpackDatagram(b[:i], len(c.state.localConnectionID)) + pkts, err := recordlayer.ContentAwareUnpackDatagram(b[:i], len(c.state.getLocalConnectionID())) if err != nil { return err } @@ -775,8 +775,8 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A h := &recordlayer.Header{} // Set connection ID size so that records of content type tls12_cid will // be parsed correctly. - if len(c.state.localConnectionID) > 0 { - h.ConnectionID = make([]byte, len(c.state.localConnectionID)) + if len(c.state.getLocalConnectionID()) > 0 { + h.ConnectionID = make([]byte, len(c.state.getLocalConnectionID())) } if err := h.Unmarshal(buf); err != nil { // Decode error must be silently discarded @@ -832,7 +832,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A // If a connection identifier had been negotiated and encryption is // enabled, the connection identifier MUST be sent. - if len(c.state.localConnectionID) > 0 && h.ContentType != protocol.ContentTypeConnectionID { + if len(c.state.getLocalConnectionID()) > 0 && h.ContentType != protocol.ContentTypeConnectionID { c.log.Debug("discarded packet missing connection ID after value negotiated") return false, nil, nil } @@ -840,7 +840,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A var err error var hdr recordlayer.Header if h.ContentType == protocol.ContentTypeConnectionID { - hdr.ConnectionID = make([]byte, len(c.state.localConnectionID)) + hdr.ConnectionID = make([]byte, len(c.state.getLocalConnectionID())) } buf, err = c.state.cipherSuite.Decrypt(hdr, buf) if err != nil { @@ -872,7 +872,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A } // If connection ID does not match discard the packet. - if !bytes.Equal(c.state.localConnectionID, h.ConnectionID) { + if !bytes.Equal(c.state.getLocalConnectionID(), h.ConnectionID) { c.log.Debug("unexpected connection ID") return false, nil, nil } diff --git a/conn_test.go b/conn_test.go index 5560edc3a..a4f234e10 100644 --- a/conn_test.go +++ b/conn_test.go @@ -1319,13 +1319,13 @@ func TestConnectionID(t *testing.T) { } }() - if !bytes.Equal(res.c.state.localConnectionID, tt.clientConnectionID) { + if !bytes.Equal(res.c.state.getLocalConnectionID(), tt.clientConnectionID) { t.Errorf("Unexpected client local connection ID\nwant: %v\ngot:%v", tt.clientConnectionID, res.c.state.localConnectionID) } if !bytes.Equal(res.c.state.remoteConnectionID, tt.serverConnectionID) { t.Errorf("Unexpected client remote connection ID\nwant: %v\ngot:%v", tt.serverConnectionID, res.c.state.remoteConnectionID) } - if !bytes.Equal(server.state.localConnectionID, tt.serverConnectionID) { + if !bytes.Equal(server.state.getLocalConnectionID(), tt.serverConnectionID) { t.Errorf("Unexpected server local connection ID\nwant: %v\ngot:%v", tt.serverConnectionID, server.state.localConnectionID) } if !bytes.Equal(server.state.remoteConnectionID, tt.clientConnectionID) { diff --git a/flight0handler.go b/flight0handler.go index 0a45c58d4..c965fd0b5 100644 --- a/flight0handler.go +++ b/flight0handler.go @@ -25,7 +25,7 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak // Connection Identifiers must be negotiated afresh on session resumption. // https://datatracker.ietf.org/doc/html/rfc9146#name-the-connection_id-extension - state.localConnectionID = nil + state.setLocalConnectionID(nil) state.remoteConnectionID = nil state.handshakeRecvSequence = seq @@ -87,7 +87,7 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak // If the client doesn't support connection IDs, the server should not // expect one to be sent. if state.remoteConnectionID == nil { - state.localConnectionID = nil + state.setLocalConnectionID(nil) } if cfg.extendedMasterSecret == RequireExtendedMasterSecret && !state.extendedMasterSecret { diff --git a/flight1handler.go b/flight1handler.go index 6448fef79..bcbddc3ec 100644 --- a/flight1handler.go +++ b/flight1handler.go @@ -126,15 +126,15 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha // in which case we are just requesting that the server send us a CID to // use. if cfg.connectionIDGenerator != nil { - state.localConnectionID = cfg.connectionIDGenerator() + state.setLocalConnectionID(cfg.connectionIDGenerator()) // The presence of a generator indicates support for connection IDs. We // use the presence of a non-nil local CID in flight 3 to determine // whether we send a CID in the second ClientHello, so we convert any // nil CID returned by a generator to []byte{}. - if state.localConnectionID == nil { - state.localConnectionID = []byte{} + if state.getLocalConnectionID() == nil { + state.setLocalConnectionID([]byte{}) } - extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) + extensions = append(extensions, &extension.ConnectionID{CID: state.getLocalConnectionID()}) } clientHello := &handshake.MessageClientHello{ diff --git a/flight3handler.go b/flight3handler.go index b3f82fe76..678b1e5a7 100644 --- a/flight3handler.go +++ b/flight3handler.go @@ -77,7 +77,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh // If the server doesn't support connection IDs, the client should not // expect one to be sent. if state.remoteConnectionID == nil { - state.localConnectionID = nil + state.setLocalConnectionID(nil) } if cfg.extendedMasterSecret == RequireExtendedMasterSecret && !state.extendedMasterSecret { @@ -284,8 +284,8 @@ func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha // If we sent a connection ID on the first ClientHello, send it on the // second. - if state.localConnectionID != nil { - extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) + if state.getLocalConnectionID() != nil { + extensions = append(extensions, &extension.ConnectionID{CID: state.getLocalConnectionID()}) } clientHello := &handshake.MessageClientHello{ diff --git a/flight4handler.go b/flight4handler.go index 840a24f15..b1ff6c3ff 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -255,8 +255,8 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha // parsing the ClientHello, so avoid setting local connection ID if the // client won't send it. if cfg.connectionIDGenerator != nil && state.remoteConnectionID != nil { - state.localConnectionID = cfg.connectionIDGenerator() - extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) + state.setLocalConnectionID(cfg.connectionIDGenerator()) + extensions = append(extensions, &extension.ConnectionID{CID: state.getLocalConnectionID()}) } var pkts []*packet diff --git a/state.go b/state.go index bc93bdf0c..178d937ea 100644 --- a/state.go +++ b/state.go @@ -36,7 +36,7 @@ type State struct { // to be received from the remote endpoint. // For a server, this is the connection ID sent in ServerHello. // For a client, this is the connection ID sent in the ClientHello. - localConnectionID []byte + localConnectionID atomic.Value // remoteConnectionID is the connection ID that the remote endpoint // specifies should be sent. // For a server, this is the connection ID received in the ClientHello. @@ -111,7 +111,7 @@ func (s *State) serialize() *serializedState { PeerCertificates: s.PeerCertificates, IdentityHint: s.IdentityHint, SessionID: s.SessionID, - LocalConnectionID: s.localConnectionID, + LocalConnectionID: s.getLocalConnectionID(), RemoteConnectionID: s.remoteConnectionID, IsClient: s.isClient, NegotiatedProtocol: s.NegotiatedProtocol, @@ -155,7 +155,7 @@ func (s *State) deserialize(serialized serializedState) { s.IdentityHint = serialized.IdentityHint // Set local and remote connection IDs - s.localConnectionID = serialized.LocalConnectionID + s.setLocalConnectionID(serialized.LocalConnectionID) s.remoteConnectionID = serialized.RemoteConnectionID s.SessionID = serialized.SessionID @@ -259,6 +259,18 @@ func (s *State) getSRTPProtectionProfile() SRTPProtectionProfile { return 0 } +func (s *State) getLocalConnectionID() []byte { + if val, ok := s.localConnectionID.Load().([]byte); ok { + return val + } + + return nil +} + +func (s *State) setLocalConnectionID(v []byte) { + s.localConnectionID.Store(v) +} + // RemoteRandomBytes returns the remote client hello random bytes func (s *State) RemoteRandomBytes() [handshake.RandomBytesLength]byte { return s.remoteRandom.RandomBytes From ec76652f161d0116e85db57af95768639688accb Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Thu, 11 Jul 2024 22:33:04 -0400 Subject: [PATCH 109/146] Retransmit last flight when in finished When FSM is in finished and sees a handshake message re-send the last flight again. --- handshaker.go | 40 ---------------------------------------- handshaker_test.go | 4 ++-- 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/handshaker.go b/handshaker.go index ce3be24c3..a7125f8d9 100644 --- a/handshaker.go +++ b/handshaker.go @@ -327,51 +327,11 @@ func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, } func (s *handshakeFSM) finish(ctx context.Context, c flightConn) (handshakeState, error) { - parse, errFlight := s.currentFlight.getFlightParser() - if errFlight != nil { - if alertErr := c.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil { - return handshakeErrored, alertErr - } - return handshakeErrored, errFlight - } - - retransmitTimer := time.NewTimer(s.retransmitInterval) select { case done := <-c.recvHandshake(): - nextFlight, alert, err := parse(ctx, c, s.state, s.cache, s.cfg) close(done) - s.retransmitInterval = s.cfg.initialRetransmitInterval - if alert != nil { - if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { - if err != nil { - err = alertErr - } - } - } - if err != nil { - return handshakeErrored, err - } - if nextFlight == 0 { - break - } - if nextFlight.isLastRecvFlight() && s.currentFlight == nextFlight { - return handshakeFinished, nil - } - <-retransmitTimer.C - - // RFC 4347 4.2.4.1 - if !s.cfg.disableRetransmitBackoff { - s.retransmitInterval *= 2 - } - if s.retransmitInterval > time.Second*60 { - s.retransmitInterval = time.Second * 60 - } - // Retransmit last flight return handshakeSending, nil - case <-ctx.Done(): - s.retransmitInterval = s.cfg.initialRetransmitInterval return handshakeErrored, ctx.Err() } - return handshakeFinished, nil } diff --git a/handshaker_test.go b/handshaker_test.go index b2bd4443d..b7d4f1bff 100644 --- a/handshaker_test.go +++ b/handshaker_test.go @@ -225,8 +225,8 @@ func TestHandshaker(t *testing.T) { t.Errorf("Client is not finished") } // there should be no `Finished` last retransmit from client - if cntClientFinishedLastRetransmit != 0 { - t.Errorf("Number of client finished last retransmit is wrong, expected: %d times, got: %d times", 0, cntClientFinishedLastRetransmit) + if cntClientFinishedLastRetransmit != 4 { + t.Errorf("Number of client finished last retransmit is wrong, expected: %d times, got: %d times", 4, cntClientFinishedLastRetransmit) } if cntServerFinished < 1 { t.Errorf("Number of server finished is wrong, expected: at least %d times, got: %d times", 1, cntServerFinished) From d013d0c2f9a366c6fa24bc3f4ba848e2f6a1219b Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Fri, 12 Jul 2024 11:44:10 -0400 Subject: [PATCH 110/146] On Read Retransmit send FSM to SENDING RFC6347 Section-4.2.4 states ``` The implementation reads a retransmitted flight from the peer: the implementation transitions to the SENDING state, where it retransmits the flight, resets the retransmit timer, and returns to the WAITING state. The rationale here is that the receipt of a duplicate message is the likely result of timer expiry on the peer and therefore suggests that part of one's previous flight was lost. ``` Resolves #478 --- conn.go | 70 ++++++++++++++++++++++++----------------- conn_test.go | 21 +++++++++++++ e2e/e2e_lossy_test.go | 31 +++++++++++++++--- flight1handler_test.go | 2 +- flight4handler_test.go | 2 +- fragment_buffer.go | 15 +++++---- fragment_buffer_test.go | 6 ++-- handshaker.go | 15 ++++++--- handshaker_test.go | 12 +++---- 9 files changed, 119 insertions(+), 55 deletions(-) diff --git a/conn.go b/conn.go index 50213652c..0ca5090d2 100644 --- a/conn.go +++ b/conn.go @@ -54,6 +54,11 @@ type addrPkt struct { data []byte } +type recvHandshakeState struct { + done chan struct{} + isRetransmit bool +} + // Conn represents a DTLS connection type Conn struct { lock sync.RWMutex // Internal lock (must not be public) @@ -82,7 +87,7 @@ type Conn struct { log logging.LeveledLogger reading chan struct{} - handshakeRecv chan chan struct{} + handshakeRecv chan recvHandshakeState cancelHandshaker func() cancelHandshakeReader func() @@ -137,7 +142,7 @@ func createConn(nextConn net.PacketConn, rAddr net.Addr, config *Config, isClien writeDeadline: deadline.New(), reading: make(chan struct{}, 1), - handshakeRecv: make(chan chan struct{}), + handshakeRecv: make(chan recvHandshakeState), closed: closer.NewCloser(), cancelHandshaker: func() {}, @@ -704,9 +709,9 @@ func (c *Conn) readAndBuffer(ctx context.Context) error { return err } - var hasHandshake bool + var hasHandshake, isRetransmit bool for _, p := range pkts { - hs, alert, err := c.handleIncomingPacket(ctx, p, rAddr, true) + hs, rtx, alert, err := c.handleIncomingPacket(ctx, p, rAddr, true) if alert != nil { if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { if err == nil { @@ -725,14 +730,20 @@ func (c *Conn) readAndBuffer(ctx context.Context) error { if hs { hasHandshake = true } + if rtx { + isRetransmit = true + } } if hasHandshake { - done := make(chan struct{}) + s := recvHandshakeState{ + done: make(chan struct{}), + isRetransmit: isRetransmit, + } select { - case c.handshakeRecv <- done: + case c.handshakeRecv <- s: // If the other party may retransmit the flight, // we should respond even if it not a new message. - <-done + <-s.done case <-c.fsm.Done(): } } @@ -744,7 +755,7 @@ func (c *Conn) handleQueuedPackets(ctx context.Context) error { c.encryptedPackets = nil for _, p := range pkts { - _, alert, err := c.handleIncomingPacket(ctx, p.data, p.rAddr, false) // don't re-enqueue + _, _, alert, err := c.handleIncomingPacket(ctx, p.data, p.rAddr, false) // don't re-enqueue if alert != nil { if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { if err == nil { @@ -771,7 +782,7 @@ func (c *Conn) enqueueEncryptedPackets(packet addrPkt) bool { return false } -func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.Addr, enqueue bool) (bool, *alert.Alert, error) { //nolint:gocognit +func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.Addr, enqueue bool) (bool, bool, *alert.Alert, error) { //nolint:gocognit h := &recordlayer.Header{} // Set connection ID size so that records of content type tls12_cid will // be parsed correctly. @@ -782,7 +793,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A // Decode error must be silently discarded // [RFC6347 Section-4.1.2.7] c.log.Debugf("discarded broken packet: %v", err) - return false, nil, nil + return false, false, nil, nil } // Validate epoch remoteEpoch := c.state.getRemoteEpoch() @@ -791,14 +802,14 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A c.log.Debugf("discarded future packet (epoch: %d, seq: %d)", h.Epoch, h.SequenceNumber, ) - return false, nil, nil + return false, false, nil, nil } if enqueue { if ok := c.enqueueEncryptedPackets(addrPkt{rAddr, buf}); ok { c.log.Debug("received packet of next epoch, queuing packet") } } - return false, nil, nil + return false, false, nil, nil } // Anti-replay protection @@ -812,7 +823,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A c.log.Debugf("discarded duplicated packet (epoch: %d, seq: %d)", h.Epoch, h.SequenceNumber, ) - return false, nil, nil + return false, false, nil, nil } // originalCID indicates whether the original record had content type @@ -827,14 +838,14 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A c.log.Debug("handshake not finished, queuing packet") } } - return false, nil, nil + return false, false, nil, nil } // If a connection identifier had been negotiated and encryption is // enabled, the connection identifier MUST be sent. if len(c.state.getLocalConnectionID()) > 0 && h.ContentType != protocol.ContentTypeConnectionID { c.log.Debug("discarded packet missing connection ID after value negotiated") - return false, nil, nil + return false, false, nil, nil } var err error @@ -845,7 +856,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A buf, err = c.state.cipherSuite.Decrypt(hdr, buf) if err != nil { c.log.Debugf("%s: decrypt failed: %s", srvCliStr(c.state.isClient), err) - return false, nil, nil + return false, false, nil, nil } // If this is a connection ID record, make it look like a normal record for // further processing. @@ -854,7 +865,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A ip := &recordlayer.InnerPlaintext{} if err := ip.Unmarshal(buf[h.Size():]); err != nil { //nolint:govet c.log.Debugf("unpacking inner plaintext failed: %s", err) - return false, nil, nil + return false, false, nil, nil } unpacked := &recordlayer.Header{ ContentType: ip.RealType, @@ -866,7 +877,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A buf, err = unpacked.Marshal() if err != nil { c.log.Debugf("converting CID record to inner plaintext failed: %s", err) - return false, nil, nil + return false, false, nil, nil } buf = append(buf, ip.Content...) } @@ -874,18 +885,19 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A // If connection ID does not match discard the packet. if !bytes.Equal(c.state.getLocalConnectionID(), h.ConnectionID) { c.log.Debug("unexpected connection ID") - return false, nil, nil + return false, false, nil, nil } } - isHandshake, err := c.fragmentBuffer.push(append([]byte{}, buf...)) + isHandshake, isRetransmit, err := c.fragmentBuffer.push(append([]byte{}, buf...)) if err != nil { // Decode error must be silently discarded // [RFC6347 Section-4.1.2.7] c.log.Debugf("defragment failed: %s", err) - return false, nil, nil + return false, false, nil, nil } else if isHandshake { markPacketAsValid() + for out, epoch := c.fragmentBuffer.pop(); out != nil; out, epoch = c.fragmentBuffer.pop() { header := &handshake.Header{} if err := header.Unmarshal(out); err != nil { @@ -895,12 +907,12 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A c.handshakeCache.push(out, epoch, header.MessageSequence, header.Type, !c.state.isClient) } - return true, nil, nil + return true, isRetransmit, nil, nil } r := &recordlayer.RecordLayer{} if err := r.Unmarshal(buf); err != nil { - return false, &alert.Alert{Level: alert.Fatal, Description: alert.DecodeError}, err + return false, false, &alert.Alert{Level: alert.Fatal, Description: alert.DecodeError}, err } isLatestSeqNum := false @@ -913,7 +925,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A a = &alert.Alert{Level: alert.Warning, Description: alert.CloseNotify} } _ = markPacketAsValid() - return false, a, &alertError{content} + return false, false, a, &alertError{content} case *protocol.ChangeCipherSpec: if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { if enqueue { @@ -921,7 +933,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A c.log.Debugf("CipherSuite not initialized, queuing packet") } } - return false, nil, nil + return false, false, nil, nil } newRemoteEpoch := h.Epoch + 1 @@ -933,7 +945,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A } case *protocol.ApplicationData: if h.Epoch == 0 { - return false, &alert.Alert{Level: alert.Fatal, Description: alert.UnexpectedMessage}, errApplicationDataEpochZero + return false, false, &alert.Alert{Level: alert.Fatal, Description: alert.UnexpectedMessage}, errApplicationDataEpochZero } isLatestSeqNum = markPacketAsValid() @@ -945,7 +957,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A } default: - return false, &alert.Alert{Level: alert.Fatal, Description: alert.UnexpectedMessage}, fmt.Errorf("%w: %d", errUnhandledContextType, content.ContentType()) + return false, false, &alert.Alert{Level: alert.Fatal, Description: alert.UnexpectedMessage}, fmt.Errorf("%w: %d", errUnhandledContextType, content.ContentType()) } // Any valid connection ID record is a candidate for updating the remote @@ -959,10 +971,10 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A } } - return false, nil, nil + return false, false, nil, nil } -func (c *Conn) recvHandshake() <-chan chan struct{} { +func (c *Conn) recvHandshake() <-chan recvHandshakeState { return c.handshakeRecv } diff --git a/conn_test.go b/conn_test.go index a4f234e10..3d4b3ab47 100644 --- a/conn_test.go +++ b/conn_test.go @@ -3482,3 +3482,24 @@ func TestOnConnectionAttempt(t *testing.T) { t.Fatal("OnConnectionAttempt fired for client") } } + +func TestFragmentBuffer_Retransmission(t *testing.T) { + fragmentBuffer := newFragmentBuffer() + frag := []byte{0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x30, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x01, 0x01} + + if _, isRetransmission, err := fragmentBuffer.push(frag); err != nil { + t.Fatal(err) + } else if isRetransmission { + t.Fatal("fragment should not be retransmission") + } + + if v, _ := fragmentBuffer.pop(); v == nil { + t.Fatal("Failed to pop fragment") + } + + if _, isRetransmission, err := fragmentBuffer.push(frag); err != nil { + t.Fatal(err) + } else if !isRetransmission { + t.Fatal("fragment should be retransmission") + } +} diff --git a/e2e/e2e_lossy_test.go b/e2e/e2e_lossy_test.go index 3e03037ba..a306584bb 100644 --- a/e2e/e2e_lossy_test.go +++ b/e2e/e2e_lossy_test.go @@ -45,10 +45,11 @@ func TestPionE2ELossy(t *testing.T) { } for _, test := range []struct { - LossChanceRange int - DoClientAuth bool - CipherSuites []dtls.CipherSuiteID - MTU int + LossChanceRange int + DoClientAuth bool + CipherSuites []dtls.CipherSuiteID + MTU int + DisableServerFlightInterval bool }{ { LossChanceRange: 0, @@ -109,6 +110,20 @@ func TestPionE2ELossy(t *testing.T) { MTU: 100, DoClientAuth: true, }, + // Incoming retransmitted handshakes should cause us to retransmit. Disabling the FlightInterval on one side + // means that a incoming re-transmissions causes the retransmission to be fired + { + LossChanceRange: 10, + DisableServerFlightInterval: true, + }, + { + LossChanceRange: 20, + DisableServerFlightInterval: true, + }, + { + LossChanceRange: 50, + DisableServerFlightInterval: true, + }, } { name := fmt.Sprintf("Loss%d_MTU%d", test.LossChanceRange, test.MTU) if test.DoClientAuth { @@ -117,6 +132,10 @@ func TestPionE2ELossy(t *testing.T) { for _, ciph := range test.CipherSuites { name += "_With" + ciph.String() } + if test.DisableServerFlightInterval { + name += "_WithNoServerFlightInterval" + } + test := test t.Run(name, func(t *testing.T) { // Limit runtime in case of deadlocks @@ -162,6 +181,10 @@ func TestPionE2ELossy(t *testing.T) { cfg.ClientAuth = dtls.RequireAnyClientCert } + if test.DisableServerFlightInterval { + cfg.FlightInterval = time.Hour + } + server, startupErr := dtls.Server(dtlsnet.PacketConnFromConn(br.GetConn1()), br.GetConn1().RemoteAddr(), cfg) serverDone <- runResult{server, startupErr} }() diff --git a/flight1handler_test.go b/flight1handler_test.go index 2d590dcc9..461ef7cf6 100644 --- a/flight1handler_test.go +++ b/flight1handler_test.go @@ -21,7 +21,7 @@ func (f *flight1TestMockFlightConn) notify(context.Context, alert.Level, alert.D return nil } func (f *flight1TestMockFlightConn) writePackets(context.Context, []*packet) error { return nil } -func (f *flight1TestMockFlightConn) recvHandshake() <-chan chan struct{} { return nil } +func (f *flight1TestMockFlightConn) recvHandshake() <-chan recvHandshakeState { return nil } func (f *flight1TestMockFlightConn) setLocalEpoch(uint16) {} func (f *flight1TestMockFlightConn) handleQueuedPackets(context.Context) error { return nil } func (f *flight1TestMockFlightConn) sessionKey() []byte { return nil } diff --git a/flight4handler_test.go b/flight4handler_test.go index f4446c40b..bf99a160e 100644 --- a/flight4handler_test.go +++ b/flight4handler_test.go @@ -27,7 +27,7 @@ func (f *flight4TestMockFlightConn) notify(context.Context, alert.Level, alert.D return nil } func (f *flight4TestMockFlightConn) writePackets(context.Context, []*packet) error { return nil } -func (f *flight4TestMockFlightConn) recvHandshake() <-chan chan struct{} { return nil } +func (f *flight4TestMockFlightConn) recvHandshake() <-chan recvHandshakeState { return nil } func (f *flight4TestMockFlightConn) setLocalEpoch(uint16) {} func (f *flight4TestMockFlightConn) handleQueuedPackets(context.Context) error { return nil } func (f *flight4TestMockFlightConn) sessionKey() []byte { return nil } diff --git a/fragment_buffer.go b/fragment_buffer.go index fb5af6c3d..f7785ec32 100644 --- a/fragment_buffer.go +++ b/fragment_buffer.go @@ -43,26 +43,29 @@ func (f *fragmentBuffer) size() int { // Attempts to push a DTLS packet to the fragmentBuffer // when it returns true it means the fragmentBuffer has inserted and the buffer shouldn't be handled // when an error returns it is fatal, and the DTLS connection should be stopped -func (f *fragmentBuffer) push(buf []byte) (bool, error) { +func (f *fragmentBuffer) push(buf []byte) (isHandshake, isRetransmit bool, err error) { if f.size()+len(buf) >= fragmentBufferMaxSize { - return false, errFragmentBufferOverflow + return false, false, errFragmentBufferOverflow } frag := new(fragment) if err := frag.recordLayerHeader.Unmarshal(buf); err != nil { - return false, err + return false, false, err } // fragment isn't a handshake, we don't need to handle it if frag.recordLayerHeader.ContentType != protocol.ContentTypeHandshake { - return false, nil + return false, false, nil } for buf = buf[recordlayer.FixedHeaderSize:]; len(buf) != 0; frag = new(fragment) { if err := frag.handshakeHeader.Unmarshal(buf); err != nil { - return false, err + return false, false, err } + // Fragment is a retransmission. We have already assembled it before successfully + isRetransmit = frag.handshakeHeader.FragmentOffset == 0 && frag.handshakeHeader.MessageSequence < f.currentMessageSequenceNumber + if _, ok := f.cache[frag.handshakeHeader.MessageSequence]; !ok { f.cache[frag.handshakeHeader.MessageSequence] = []*fragment{} } @@ -80,7 +83,7 @@ func (f *fragmentBuffer) push(buf []byte) (bool, error) { buf = buf[end:] } - return true, nil + return true, isRetransmit, nil } func (f *fragmentBuffer) pop() (content []byte, epoch uint16) { diff --git a/fragment_buffer_test.go b/fragment_buffer_test.go index ad8834e71..2b2f62c7e 100644 --- a/fragment_buffer_test.go +++ b/fragment_buffer_test.go @@ -94,7 +94,7 @@ func TestFragmentBuffer(t *testing.T) { } { fragmentBuffer := newFragmentBuffer() for _, frag := range test.In { - status, err := fragmentBuffer.push(frag) + status, _, err := fragmentBuffer.push(frag) if err != nil { t.Error(err) } else if !status { @@ -122,13 +122,13 @@ func TestFragmentBuffer_Overflow(t *testing.T) { fragmentBuffer := newFragmentBuffer() // Push a buffer that doesn't exceed size limits - if _, err := fragmentBuffer.push([]byte{0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00}); err != nil { + if _, _, err := fragmentBuffer.push([]byte{0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00}); err != nil { t.Fatal(err) } // Allocate a buffer that exceeds cache size largeBuffer := make([]byte, fragmentBufferMaxSize) - if _, err := fragmentBuffer.push(largeBuffer); !errors.Is(err, errFragmentBufferOverflow) { + if _, _, err := fragmentBuffer.push(largeBuffer); !errors.Is(err, errFragmentBufferOverflow) { t.Fatalf("Pushing a large buffer returned (%s) expected(%s)", err, errFragmentBufferOverflow) } } diff --git a/handshaker.go b/handshaker.go index a7125f8d9..a585c3db8 100644 --- a/handshaker.go +++ b/handshaker.go @@ -137,7 +137,7 @@ type handshakeConfig struct { type flightConn interface { notify(ctx context.Context, level alert.Level, desc alert.Description) error writePackets(context.Context, []*packet) error - recvHandshake() <-chan chan struct{} + recvHandshake() <-chan recvHandshakeState setLocalEpoch(epoch uint16) handleQueuedPackets(context.Context) error sessionKey() []byte @@ -280,10 +280,15 @@ func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, retransmitTimer := time.NewTimer(s.retransmitInterval) for { select { - case done := <-c.recvHandshake(): + case state := <-c.recvHandshake(): + if state.isRetransmit { + close(state.done) + return handshakeSending, nil + } + nextFlight, alert, err := parse(ctx, c, s.state, s.cache, s.cfg) s.retransmitInterval = s.cfg.initialRetransmitInterval - close(done) + close(state.done) if alert != nil { if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { if err != nil { @@ -328,8 +333,8 @@ func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, func (s *handshakeFSM) finish(ctx context.Context, c flightConn) (handshakeState, error) { select { - case done := <-c.recvHandshake(): - close(done) + case state := <-c.recvHandshake(): + close(state.done) return handshakeSending, nil case <-ctx.Done(): return handshakeErrored, ctx.Err() diff --git a/handshaker_test.go b/handshaker_test.go index b7d4f1bff..b814fc90b 100644 --- a/handshaker_test.go +++ b/handshaker_test.go @@ -349,8 +349,8 @@ type TestEndpoint struct { func flightTestPipe(ctx context.Context, clientEndpoint TestEndpoint, serverEndpoint TestEndpoint) (*flightTestConn, *flightTestConn) { ca := newHandshakeCache() cb := newHandshakeCache() - chA := make(chan chan struct{}) - chB := make(chan chan struct{}) + chA := make(chan recvHandshakeState) + chB := make(chan recvHandshakeState) return &flightTestConn{ handshakeCache: ca, otherEndCache: cb, @@ -373,7 +373,7 @@ func flightTestPipe(ctx context.Context, clientEndpoint TestEndpoint, serverEndp type flightTestConn struct { state State handshakeCache *handshakeCache - recv chan chan struct{} + recv chan recvHandshakeState done <-chan struct{} epoch uint16 @@ -382,10 +382,10 @@ type flightTestConn struct { delay time.Duration otherEndCache *handshakeCache - otherEndRecv chan chan struct{} + otherEndRecv chan recvHandshakeState } -func (c *flightTestConn) recvHandshake() <-chan chan struct{} { +func (c *flightTestConn) recvHandshake() <-chan recvHandshakeState { return c.recv } @@ -427,7 +427,7 @@ func (c *flightTestConn) writePackets(_ context.Context, pkts []*packet) error { } go func() { select { - case c.otherEndRecv <- make(chan struct{}): + case c.otherEndRecv <- recvHandshakeState{done: make(chan struct{})}: case <-c.done: } }() From bc3159a9539cb48f83fdb58ec5741b93c39277ad Mon Sep 17 00:00:00 2001 From: sirzooro <daniel@poradnik-webmastera.com> Date: Sat, 13 Jul 2024 21:06:00 +0200 Subject: [PATCH 111/146] Added DTLS-SRTP IDs for NULL and AES256CM ciphers --- pkg/protocol/extension/srtp_protection_profile.go | 4 ++++ srtp_protection_profile.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/pkg/protocol/extension/srtp_protection_profile.go b/pkg/protocol/extension/srtp_protection_profile.go index 2966966dd..131ae5328 100644 --- a/pkg/protocol/extension/srtp_protection_profile.go +++ b/pkg/protocol/extension/srtp_protection_profile.go @@ -10,6 +10,10 @@ type SRTPProtectionProfile uint16 const ( SRTP_AES128_CM_HMAC_SHA1_80 SRTPProtectionProfile = 0x0001 // nolint SRTP_AES128_CM_HMAC_SHA1_32 SRTPProtectionProfile = 0x0002 // nolint + SRTP_AES256_CM_SHA1_80 SRTPProtectionProfile = 0x0003 // nolint + SRTP_AES256_CM_SHA1_32 SRTPProtectionProfile = 0x0004 // nolint + SRTP_NULL_HMAC_SHA1_80 SRTPProtectionProfile = 0x0005 // nolint + SRTP_NULL_HMAC_SHA1_32 SRTPProtectionProfile = 0x0006 // nolint SRTP_AEAD_AES_128_GCM SRTPProtectionProfile = 0x0007 // nolint SRTP_AEAD_AES_256_GCM SRTPProtectionProfile = 0x0008 // nolint ) diff --git a/srtp_protection_profile.go b/srtp_protection_profile.go index e306e9e6a..8b7e471f3 100644 --- a/srtp_protection_profile.go +++ b/srtp_protection_profile.go @@ -12,6 +12,10 @@ type SRTPProtectionProfile = extension.SRTPProtectionProfile const ( SRTP_AES128_CM_HMAC_SHA1_80 SRTPProtectionProfile = extension.SRTP_AES128_CM_HMAC_SHA1_80 // nolint:revive,stylecheck SRTP_AES128_CM_HMAC_SHA1_32 SRTPProtectionProfile = extension.SRTP_AES128_CM_HMAC_SHA1_32 // nolint:revive,stylecheck + SRTP_AES256_CM_SHA1_80 SRTPProtectionProfile = extension.SRTP_AES256_CM_SHA1_80 // nolint:revive,stylecheck + SRTP_AES256_CM_SHA1_32 SRTPProtectionProfile = extension.SRTP_AES256_CM_SHA1_32 // nolint:revive,stylecheck + SRTP_NULL_HMAC_SHA1_80 SRTPProtectionProfile = extension.SRTP_NULL_HMAC_SHA1_80 // nolint:revive,stylecheck + SRTP_NULL_HMAC_SHA1_32 SRTPProtectionProfile = extension.SRTP_NULL_HMAC_SHA1_32 // nolint:revive,stylecheck SRTP_AEAD_AES_128_GCM SRTPProtectionProfile = extension.SRTP_AEAD_AES_128_GCM // nolint:revive,stylecheck SRTP_AEAD_AES_256_GCM SRTPProtectionProfile = extension.SRTP_AEAD_AES_256_GCM // nolint:revive,stylecheck ) From 6178064b9f001cb10dc80d99bd66254fe273bac8 Mon Sep 17 00:00:00 2001 From: sirzooro <daniel@poradnik-webmastera.com> Date: Sat, 20 Jul 2024 11:57:35 +0200 Subject: [PATCH 112/146] Mark NULL and AES256CM SRTP ciphers as supported DTLS server checks this list during handshake. Without this change new NULL and AES256CM SRTP ciphers were ignored. --- pkg/protocol/extension/srtp_protection_profile.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/protocol/extension/srtp_protection_profile.go b/pkg/protocol/extension/srtp_protection_profile.go index 131ae5328..75a8c2ee3 100644 --- a/pkg/protocol/extension/srtp_protection_profile.go +++ b/pkg/protocol/extension/srtp_protection_profile.go @@ -22,6 +22,10 @@ func srtpProtectionProfiles() map[SRTPProtectionProfile]bool { return map[SRTPProtectionProfile]bool{ SRTP_AES128_CM_HMAC_SHA1_80: true, SRTP_AES128_CM_HMAC_SHA1_32: true, + SRTP_AES256_CM_SHA1_80: true, + SRTP_AES256_CM_SHA1_32: true, + SRTP_NULL_HMAC_SHA1_80: true, + SRTP_NULL_HMAC_SHA1_32: true, SRTP_AEAD_AES_128_GCM: true, SRTP_AEAD_AES_256_GCM: true, } From e4064683d277f946e5d1a4b359ca4e552c23131c Mon Sep 17 00:00:00 2001 From: Kevin Wang <kevmo314@gmail.com> Date: Sat, 20 Jul 2024 00:37:07 -0400 Subject: [PATCH 113/146] Perform handshake on first read/write Updates the connection to perform a handshake on first read/write instead of on accept. Closes https://github.com/pion/dtls/issues/279. --- bench_test.go | 2 +- config.go | 21 -- conn.go | 195 +++++++++--------- conn_go_test.go | 64 ++---- conn_test.go | 42 ++-- e2e/e2e_test.go | 18 +- examples/dial/cid/main.go | 7 +- examples/dial/psk/main.go | 7 +- examples/dial/selfsign/main.go | 7 +- examples/dial/verify/main.go | 7 +- examples/listen/cid/main.go | 23 +-- examples/listen/psk/main.go | 17 +- examples/listen/selfsign/main.go | 17 +- .../verify-brute-force-protection/main.go | 16 +- examples/listen/verify/main.go | 17 +- handshaker.go | 2 + listener.go | 2 - resume.go | 12 +- 18 files changed, 227 insertions(+), 249 deletions(-) diff --git a/bench_test.go b/bench_test.go index 7b236f6d8..885b311f2 100644 --- a/bench_test.go +++ b/bench_test.go @@ -40,7 +40,7 @@ func TestSimpleReadWrite(t *testing.T) { return } buf := make([]byte, 1024) - if _, sErr = server.Read(buf); sErr != nil { + if _, sErr = server.Read(buf); sErr != nil { //nolint:contextcheck t.Error(sErr) } gotHello <- struct{}{} diff --git a/config.go b/config.go index 0f6813d24..f97930294 100644 --- a/config.go +++ b/config.go @@ -4,7 +4,6 @@ package dtls import ( - "context" "crypto/ecdsa" "crypto/ed25519" "crypto/rsa" @@ -118,15 +117,6 @@ type Config struct { LoggerFactory logging.LoggerFactory - // ConnectContextMaker is a function to make a context used in Dial(), - // Client(), Server(), and Accept(). If nil, the default ConnectContextMaker - // is used. It can be implemented as following. - // - // func ConnectContextMaker() (context.Context, func()) { - // return context.WithTimeout(context.Background(), 30*time.Second) - // } - ConnectContextMaker func() (context.Context, func()) - // MTU is the length at which handshake messages will be fragmented to // fit within the maximum transmission unit (default is 1200 bytes) MTU int @@ -230,17 +220,6 @@ type Config struct { OnConnectionAttempt func(net.Addr) error } -func defaultConnectContextMaker() (context.Context, func()) { - return context.WithTimeout(context.Background(), 30*time.Second) -} - -func (c *Config) connectContextMaker() (context.Context, func()) { - if c.ConnectContextMaker == nil { - return defaultConnectContextMaker() - } - return c.ConnectContextMaker() -} - func (c *Config) includeCertificateSuites() bool { return c.PSK == nil || len(c.Certificates) > 0 || c.GetCertificate != nil || c.GetClientCertificate != nil } diff --git a/conn.go b/conn.go index 0ca5090d2..0d8896550 100644 --- a/conn.go +++ b/conn.go @@ -73,6 +73,7 @@ type Conn struct { paddingLengthGenerator func(uint) uint handshakeCompletedSuccessfully atomic.Value + handshakeMutex sync.Mutex encryptedPackets []addrPkt @@ -94,9 +95,11 @@ type Conn struct { fsm *handshakeFSM replayProtectionWindow uint + + handshakeConfig *handshakeConfig } -func createConn(nextConn net.PacketConn, rAddr net.Addr, config *Config, isClient bool) (*Conn, error) { +func createConn(nextConn net.PacketConn, rAddr net.Addr, config *Config, isClient bool, resumeState *State) (*Conn, error) { if err := validateConfig(config); err != nil { return nil, err } @@ -127,42 +130,6 @@ func createConn(nextConn net.PacketConn, rAddr net.Addr, config *Config, isClien paddingLengthGenerator = func(uint) uint { return 0 } } - c := &Conn{ - rAddr: rAddr, - nextConn: netctx.NewPacketConn(nextConn), - fragmentBuffer: newFragmentBuffer(), - handshakeCache: newHandshakeCache(), - maximumTransmissionUnit: mtu, - paddingLengthGenerator: paddingLengthGenerator, - - decrypted: make(chan interface{}, 1), - log: logger, - - readDeadline: deadline.New(), - writeDeadline: deadline.New(), - - reading: make(chan struct{}, 1), - handshakeRecv: make(chan recvHandshakeState), - closed: closer.NewCloser(), - cancelHandshaker: func() {}, - - replayProtectionWindow: uint(replayProtectionWindow), - - state: State{ - isClient: isClient, - }, - } - - c.setRemoteEpoch(0) - c.setLocalEpoch(0) - return c, nil -} - -func handshakeConn(ctx context.Context, conn *Conn, config *Config, isClient bool, initialState *State) (*Conn, error) { - if conn == nil { - return nil, errNilNextConn - } - cipherSuites, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil) if err != nil { return nil, err @@ -190,7 +157,7 @@ func handshakeConn(ctx context.Context, conn *Conn, config *Config, isClient boo curves = defaultCurves } - hsCfg := &handshakeConfig{ + handshakeConfig := &handshakeConfig{ localPSKCallback: config.PSK, localPSKIdentityHint: config.PSKIdentityHint, localCipherSuites: cipherSuites, @@ -209,7 +176,7 @@ func handshakeConn(ctx context.Context, conn *Conn, config *Config, isClient boo customCipherSuites: config.CustomCipherSuites, initialRetransmitInterval: workerInterval, disableRetransmitBackoff: config.DisableRetransmitBackoff, - log: conn.log, + log: logger, initialEpoch: 0, keyLogWriter: config.KeyLogWriter, sessionStore: config.SessionStore, @@ -222,33 +189,97 @@ func handshakeConn(ctx context.Context, conn *Conn, config *Config, isClient boo clientHelloMessageHook: config.ClientHelloMessageHook, serverHelloMessageHook: config.ServerHelloMessageHook, certificateRequestMessageHook: config.CertificateRequestMessageHook, + resumeState: resumeState, + } + + c := &Conn{ + rAddr: rAddr, + nextConn: netctx.NewPacketConn(nextConn), + handshakeConfig: handshakeConfig, + fragmentBuffer: newFragmentBuffer(), + handshakeCache: newHandshakeCache(), + maximumTransmissionUnit: mtu, + paddingLengthGenerator: paddingLengthGenerator, + + decrypted: make(chan interface{}, 1), + log: logger, + + readDeadline: deadline.New(), + writeDeadline: deadline.New(), + + reading: make(chan struct{}, 1), + handshakeRecv: make(chan recvHandshakeState), + closed: closer.NewCloser(), + cancelHandshaker: func() {}, + cancelHandshakeReader: func() {}, + + replayProtectionWindow: uint(replayProtectionWindow), + + state: State{ + isClient: isClient, + }, + } + + c.setRemoteEpoch(0) + c.setLocalEpoch(0) + return c, nil +} + +// Handshake runs the client or server DTLS handshake +// protocol if it has not yet been run. +// +// Most uses of this package need not call Handshake explicitly: the +// first [Conn.Read] or [Conn.Write] will call it automatically. +// +// For control over canceling or setting a timeout on a handshake, use +// [Conn.HandshakeContext]. +func (c *Conn) Handshake() error { + return c.HandshakeContext(context.Background()) +} + +// HandshakeContext runs the client or server DTLS handshake +// protocol if it has not yet been run. +// +// The provided Context must be non-nil. If the context is canceled before +// the handshake is complete, the handshake is interrupted and an error is returned. +// Once the handshake has completed, cancellation of the context will not affect the +// connection. +// +// Most uses of this package need not call HandshakeContext explicitly: the +// first [Conn.Read] or [Conn.Write] will call it automatically. +func (c *Conn) HandshakeContext(ctx context.Context) error { + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + + if c.isHandshakeCompletedSuccessfully() { + return nil } // 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(&ClientHelloInfo{}) + if !c.state.isClient { + cert, err := c.handshakeConfig.getCertificate(&ClientHelloInfo{}) if err != nil && !errors.Is(err, errNoCertificates) { - return nil, err + return err } - hsCfg.localCipherSuites = filterCipherSuitesForCertificate(cert, cipherSuites) + c.handshakeConfig.localCipherSuites = filterCipherSuitesForCertificate(cert, c.handshakeConfig.localCipherSuites) } var initialFlight flightVal var initialFSMState handshakeState - if initialState != nil { - if conn.state.isClient { + if c.handshakeConfig.resumeState != nil { + if c.state.isClient { initialFlight = flight5 } else { initialFlight = flight6 } initialFSMState = handshakeFinished - conn.state = *initialState + c.state = *c.handshakeConfig.resumeState } else { - if conn.state.isClient { + if c.state.isClient { initialFlight = flight1 } else { initialFlight = flight0 @@ -256,48 +287,17 @@ func handshakeConn(ctx context.Context, conn *Conn, config *Config, isClient boo initialFSMState = handshakePreparing } // Do handshake - if err := conn.handshake(ctx, hsCfg, initialFlight, initialFSMState); err != nil { - return nil, err + if err := c.handshake(ctx, c.handshakeConfig, initialFlight, initialFSMState); err != nil { + return err } - conn.log.Trace("Handshake Completed") + c.log.Trace("Handshake Completed") - return conn, nil + return nil } // Dial connects to the given network address and establishes a DTLS connection on top. -// Connection handshake will timeout using ConnectContextMaker in the Config. -// If you want to specify the timeout duration, use DialWithContext() instead. func Dial(network string, rAddr *net.UDPAddr, config *Config) (*Conn, error) { - ctx, cancel := config.connectContextMaker() - defer cancel() - - return DialWithContext(ctx, network, rAddr, config) -} - -// Client establishes a DTLS connection over an existing connection. -// Connection handshake will timeout using ConnectContextMaker in the Config. -// If you want to specify the timeout duration, use ClientWithContext() instead. -func Client(conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { - ctx, cancel := config.connectContextMaker() - defer cancel() - - return ClientWithContext(ctx, conn, rAddr, config) -} - -// Server listens for incoming DTLS connections. -// Connection handshake will timeout using ConnectContextMaker in the Config. -// If you want to specify the timeout duration, use ServerWithContext() instead. -func Server(conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { - ctx, cancel := config.connectContextMaker() - defer cancel() - - return ServerWithContext(ctx, conn, rAddr, config) -} - -// DialWithContext connects to the given network address and establishes a DTLS -// connection on top. -func DialWithContext(ctx context.Context, network string, rAddr *net.UDPAddr, config *Config) (*Conn, error) { // net.ListenUDP is used rather than net.DialUDP as the latter prevents the // use of net.PacketConn.WriteTo. // https://github.com/golang/go/blob/ce5e37ec21442c6eb13a43e68ca20129102ebac0/src/net/udpsock_posix.go#L115 @@ -306,11 +306,11 @@ func DialWithContext(ctx context.Context, network string, rAddr *net.UDPAddr, co return nil, err } - return ClientWithContext(ctx, pConn, rAddr, config) + return Client(pConn, rAddr, config) } -// ClientWithContext establishes a DTLS connection over an existing connection. -func ClientWithContext(ctx context.Context, conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { +// Client establishes a DTLS connection over an existing connection. +func Client(conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { switch { case config == nil: return nil, errNoConfigProvided @@ -318,16 +318,11 @@ func ClientWithContext(ctx context.Context, conn net.PacketConn, rAddr net.Addr, return nil, errPSKAndIdentityMustBeSetForClient } - dconn, err := createConn(conn, rAddr, config, true) - if err != nil { - return nil, err - } - - return handshakeConn(ctx, dconn, config, true, nil) + return createConn(conn, rAddr, config, true, nil) } -// ServerWithContext listens for incoming DTLS connections. -func ServerWithContext(ctx context.Context, conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { +// Server listens for incoming DTLS connections. +func Server(conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { if config == nil { return nil, errNoConfigProvided } @@ -336,17 +331,13 @@ func ServerWithContext(ctx context.Context, conn net.PacketConn, rAddr net.Addr, return nil, err } } - dconn, err := createConn(conn, rAddr, config, false) - if err != nil { - return nil, err - } - return handshakeConn(ctx, dconn, config, false, nil) + return createConn(conn, rAddr, config, false, nil) } // Read reads data from the connection. func (c *Conn) Read(p []byte) (n int, err error) { - if !c.isHandshakeCompletedSuccessfully() { - return 0, errHandshakeInProgress + if err := c.Handshake(); err != nil { + return 0, err } select { @@ -389,8 +380,8 @@ func (c *Conn) Write(p []byte) (int, error) { default: } - if !c.isHandshakeCompletedSuccessfully() { - return 0, errHandshakeInProgress + if err := c.Handshake(); err != nil { + return 0, err } return len(p), c.writePackets(c.writeDeadline, []*packet{ diff --git a/conn_go_test.go b/conn_go_test.go index d9ca6e187..bd542f27d 100644 --- a/conn_go_test.go +++ b/conn_go_test.go @@ -52,9 +52,6 @@ func TestContextConfig(t *testing.T) { t.Fatalf("Unexpected error: %v", err) } config := &Config{ - ConnectContextMaker: func() (context.Context, func()) { - return context.WithTimeout(context.Background(), 40*time.Millisecond) - }, Certificates: []tls.Certificate{cert}, } @@ -64,71 +61,52 @@ func TestContextConfig(t *testing.T) { }{ "Dial": { f: func() (func() (net.Conn, error), func()) { + ctx, cancel := context.WithTimeout(context.Background(), 40*time.Millisecond) return func() (net.Conn, error) { - return Dial("udp", addr, config) - }, func() { - } - }, - order: []byte{0, 1, 2}, - }, - "DialWithContext": { - f: func() (func() (net.Conn, error), func()) { - ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond) - return func() (net.Conn, error) { - return DialWithContext(ctx, "udp", addr, config) + conn, err := Dial("udp", addr, config) + if err != nil { + return nil, err + } + return conn, conn.HandshakeContext(ctx) }, func() { cancel() } }, - order: []byte{0, 2, 1}, + order: []byte{0, 1, 2}, }, "Client": { f: func() (func() (net.Conn, error), func()) { ca, _ := dpipe.Pipe() + ctx, cancel := context.WithTimeout(context.Background(), 40*time.Millisecond) return func() (net.Conn, error) { - return Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) + conn, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) + if err != nil { + return nil, err + } + return conn, conn.HandshakeContext(ctx) }, func() { _ = ca.Close() - } - }, - order: []byte{0, 1, 2}, - }, - "ClientWithContext": { - f: func() (func() (net.Conn, error), func()) { - ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond) - ca, _ := dpipe.Pipe() - return func() (net.Conn, error) { - return ClientWithContext(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) - }, func() { cancel() - _ = ca.Close() } }, - order: []byte{0, 2, 1}, + order: []byte{0, 1, 2}, }, "Server": { f: func() (func() (net.Conn, error), func()) { ca, _ := dpipe.Pipe() + ctx, cancel := context.WithTimeout(context.Background(), 40*time.Millisecond) return func() (net.Conn, error) { - return Server(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) + conn, err := Server(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) + if err != nil { + return nil, err + } + return conn, conn.HandshakeContext(ctx) }, func() { _ = ca.Close() - } - }, - order: []byte{0, 1, 2}, - }, - "ServerWithContext": { - f: func() (func() (net.Conn, error), func()) { - ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond) - ca, _ := dpipe.Pipe() - return func() (net.Conn, error) { - return ServerWithContext(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) - }, func() { cancel() - _ = ca.Close() } }, - order: []byte{0, 2, 1}, + order: []byte{0, 1, 2}, }, } diff --git a/conn_test.go b/conn_test.go index 3d4b3ab47..83a90f2d2 100644 --- a/conn_test.go +++ b/conn_test.go @@ -295,7 +295,11 @@ func testClient(ctx context.Context, c net.PacketConn, rAddr net.Addr, cfg *Conf cfg.Certificates = []tls.Certificate{clientCert} } cfg.InsecureSkipVerify = true - return ClientWithContext(ctx, c, rAddr, cfg) + conn, err := Client(c, rAddr, cfg) + if err != nil { + return nil, err + } + return conn, conn.HandshakeContext(ctx) } func testServer(ctx context.Context, c net.PacketConn, rAddr net.Addr, cfg *Config, generateCertificate bool) (*Conn, error) { @@ -306,7 +310,11 @@ func testServer(ctx context.Context, c net.PacketConn, rAddr net.Addr, cfg *Conf } cfg.Certificates = []tls.Certificate{serverCert} } - return ServerWithContext(ctx, c, rAddr, cfg) + conn, err := Server(c, rAddr, cfg) + if err != nil { + return nil, err + } + return conn, conn.HandshakeContext(ctx) } func sendClientHello(cookie []byte, ca net.Conn, sequenceNumber uint64, extensions []extension.Extension) error { @@ -1135,17 +1143,18 @@ func TestClientCertificate(t *testing.T) { t.Run(name, func(t *testing.T) { ca, cb := dpipe.Pipe() type result struct { - c *Conn - err error + c *Conn + err, hserr error } c := make(chan result) go func() { client, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), tt.clientCfg) - c <- result{client, err} + c <- result{client, err, client.Handshake()} }() server, err := Server(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), tt.serverCfg) + hserr := server.Handshake() res := <-c defer func() { if err == nil { @@ -1157,7 +1166,7 @@ func TestClientCertificate(t *testing.T) { }() if tt.wantErr { - if err != nil { + if err != nil || hserr != nil { // Error expected, test succeeded return } @@ -1556,23 +1565,24 @@ func TestServerCertificate(t *testing.T) { ca, cb := dpipe.Pipe() type result struct { - c *Conn - err error + c *Conn + err, hserr error } srvCh := make(chan result) go func() { s, err := Server(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), tt.serverCfg) - srvCh <- result{s, err} + srvCh <- result{s, err, s.Handshake()} }() cli, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), tt.clientCfg) + hserr := cli.Handshake() if err == nil { _ = cli.Close() } - if !tt.wantErr && err != nil { - t.Errorf("Client failed(%v)", err) + if !tt.wantErr && (err != nil || hserr != nil) { + t.Errorf("Client failed(%v, %v)", err, hserr) } - if tt.wantErr && err == nil { + if tt.wantErr && err == nil && hserr == nil { t.Fatal("Error expected") } @@ -3237,7 +3247,7 @@ func TestSkipHelloVerify(t *testing.T) { return } buf := make([]byte, 1024) - if _, sErr = server.Read(buf); sErr != nil { + if _, sErr = server.Read(buf); sErr != nil { //nolint:contextcheck t.Error(sErr) } gotHello <- struct{}{} @@ -3306,7 +3316,7 @@ func TestApplicationDataQueueLimited(t *testing.T) { cfg := &Config{} cfg.Certificates = []tls.Certificate{serverCert} - dconn, err := createConn(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), cfg, false) + dconn, err := createConn(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), cfg, false, nil) if err != nil { t.Error(err) return @@ -3322,7 +3332,7 @@ func TestApplicationDataQueueLimited(t *testing.T) { time.Sleep(1 * time.Second) } }() - if _, err := handshakeConn(ctx, dconn, cfg, false, nil); err == nil { + if err := dconn.HandshakeContext(ctx); err == nil { t.Error("expected handshake to fail") } close(done) @@ -3402,7 +3412,7 @@ func TestHelloRandom(t *testing.T) { return } buf := make([]byte, 1024) - if _, sErr = server.Read(buf); sErr != nil { + if _, sErr = server.Read(buf); sErr != nil { //nolint:contextcheck t.Error(sErr) } gotHello <- struct{}{} diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index ec1253ec8..0d8ba35bc 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -219,8 +219,7 @@ func clientPion(c *comm) { c.clientMutex.Lock() defer c.clientMutex.Unlock() - var err error - c.clientConn, err = dtls.DialWithContext(c.ctx, "udp", + conn, err := dtls.Dial("udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: c.serverPort}, c.clientConfig, ) @@ -229,6 +228,13 @@ func clientPion(c *comm) { return } + if err := conn.HandshakeContext(c.ctx); err != nil { + c.errChan <- err + return + } + + c.clientConn = conn + simpleReadWrite(c.errChan, c.clientChan, c.clientConn, c.messageRecvCount) c.clientDone <- nil close(c.clientDone) @@ -254,6 +260,14 @@ func serverPion(c *comm) { return } + dtlsConn, ok := c.serverConn.(*dtls.Conn) + if ok { + if err := dtlsConn.HandshakeContext(c.ctx); err != nil { + c.errChan <- err + return + } + } + simpleReadWrite(c.errChan, c.serverChan, c.serverConn, c.messageRecvCount) c.serverDone <- nil close(c.serverDone) diff --git a/examples/dial/cid/main.go b/examples/dial/cid/main.go index 10e547706..4859e72b1 100644 --- a/examples/dial/cid/main.go +++ b/examples/dial/cid/main.go @@ -37,12 +37,17 @@ func main() { // Connect to a DTLS server ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - dtlsConn, err := dtls.DialWithContext(ctx, "udp", addr, config) + dtlsConn, err := dtls.Dial("udp", addr, config) util.Check(err) defer func() { util.Check(dtlsConn.Close()) }() + if err := dtlsConn.HandshakeContext(ctx); err != nil { + fmt.Printf("Failed to handshake with server: %v\n", err) + return + } + fmt.Println("Connected; type 'exit' to shutdown gracefully") // Simulate a chat session diff --git a/examples/dial/psk/main.go b/examples/dial/psk/main.go index b70efdcc3..94731e93a 100644 --- a/examples/dial/psk/main.go +++ b/examples/dial/psk/main.go @@ -36,12 +36,17 @@ func main() { // Connect to a DTLS server ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - dtlsConn, err := dtls.DialWithContext(ctx, "udp", addr, config) + dtlsConn, err := dtls.Dial("udp", addr, config) util.Check(err) defer func() { util.Check(dtlsConn.Close()) }() + if err := dtlsConn.HandshakeContext(ctx); err != nil { + fmt.Printf("Failed to handshake with server: %v\n", err) + return + } + fmt.Println("Connected; type 'exit' to shutdown gracefully") // Simulate a chat session diff --git a/examples/dial/selfsign/main.go b/examples/dial/selfsign/main.go index 5fa25a923..b3be5a8f8 100644 --- a/examples/dial/selfsign/main.go +++ b/examples/dial/selfsign/main.go @@ -38,12 +38,17 @@ func main() { // Connect to a DTLS server ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - dtlsConn, err := dtls.DialWithContext(ctx, "udp", addr, config) + dtlsConn, err := dtls.Dial("udp", addr, config) util.Check(err) defer func() { util.Check(dtlsConn.Close()) }() + if err := dtlsConn.HandshakeContext(ctx); err != nil { + fmt.Printf("Failed to handshake with server: %v\n", err) + return + } + fmt.Println("Connected; type 'exit' to shutdown gracefully") // Simulate a chat session diff --git a/examples/dial/verify/main.go b/examples/dial/verify/main.go index 07501954d..ed5352dd5 100644 --- a/examples/dial/verify/main.go +++ b/examples/dial/verify/main.go @@ -45,12 +45,17 @@ func main() { // Connect to a DTLS server ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - dtlsConn, err := dtls.DialWithContext(ctx, "udp", addr, config) + dtlsConn, err := dtls.Dial("udp", addr, config) util.Check(err) defer func() { util.Check(dtlsConn.Close()) }() + if err := dtlsConn.HandshakeContext(ctx); err != nil { + fmt.Printf("Failed to handshake with server: %v\n", err) + return + } + fmt.Println("Connected; type 'exit' to shutdown gracefully") // Simulate a chat session diff --git a/examples/listen/cid/main.go b/examples/listen/cid/main.go index 770bbcfa4..11be4bc21 100644 --- a/examples/listen/cid/main.go +++ b/examples/listen/cid/main.go @@ -8,7 +8,6 @@ import ( "context" "fmt" "net" - "time" "github.com/pion/dtls/v2" "github.com/pion/dtls/v2/examples/util" @@ -18,10 +17,6 @@ func main() { // Prepare the IP to connect to addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444} - // Create parent context to cleanup handshaking connections on exit. - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - // // Everything below is the pion-DTLS API! Thanks for using it ❤️. // @@ -32,13 +27,9 @@ func main() { fmt.Printf("Client's hint: %s \n", hint) return []byte{0xAB, 0xC1, 0x23}, nil }, - PSKIdentityHint: []byte("Pion DTLS Server"), - CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8}, - ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, - // Create timeout context for accepted connection. - ConnectContextMaker: func() (context.Context, func()) { - return context.WithTimeout(ctx, 30*time.Second) - }, + PSKIdentityHint: []byte("Pion DTLS Server"), + CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8}, + ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, ConnectionIDGenerator: dtls.RandomCIDGenerator(8), } @@ -65,6 +56,14 @@ func main() { // using `dtlsConn := conn.(*dtls.Conn)` in order to to expose // functions like `ConnectionState` etc. + // Perform the handshake with a 30-second timeout + ctx, cancel := context.WithTimeout(context.Background(), 30) + dtlsConn, ok := conn.(*dtls.Conn) + if ok { + util.Check(dtlsConn.HandshakeContext(ctx)) + } + cancel() + // Register the connection with the chat hub if err == nil { hub.Register(conn) diff --git a/examples/listen/psk/main.go b/examples/listen/psk/main.go index 66f099693..e6c16514c 100644 --- a/examples/listen/psk/main.go +++ b/examples/listen/psk/main.go @@ -8,7 +8,6 @@ import ( "context" "fmt" "net" - "time" "github.com/pion/dtls/v2" "github.com/pion/dtls/v2/examples/util" @@ -18,10 +17,6 @@ func main() { // Prepare the IP to connect to addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444} - // Create parent context to cleanup handshaking connections on exit. - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - // // Everything below is the pion-DTLS API! Thanks for using it ❤️. // @@ -35,10 +30,6 @@ func main() { PSKIdentityHint: []byte("Pion DTLS Server"), CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8}, ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, - // Create timeout context for accepted connection. - ConnectContextMaker: func() (context.Context, func()) { - return context.WithTimeout(ctx, 30*time.Second) - }, } // Connect to a DTLS server @@ -64,6 +55,14 @@ func main() { // using `dtlsConn := conn.(*dtls.Conn)` in order to to expose // functions like `ConnectionState` etc. + // Perform the handshake with a 30-second timeout + ctx, cancel := context.WithTimeout(context.Background(), 30) + dtlsConn, ok := conn.(*dtls.Conn) + if ok { + util.Check(dtlsConn.HandshakeContext(ctx)) + } + cancel() + // Register the connection with the chat hub if err == nil { hub.Register(conn) diff --git a/examples/listen/selfsign/main.go b/examples/listen/selfsign/main.go index 025b667e4..af1010102 100644 --- a/examples/listen/selfsign/main.go +++ b/examples/listen/selfsign/main.go @@ -9,7 +9,6 @@ import ( "crypto/tls" "fmt" "net" - "time" "github.com/pion/dtls/v2" "github.com/pion/dtls/v2/examples/util" @@ -24,10 +23,6 @@ func main() { certificate, genErr := selfsign.GenerateSelfSigned() util.Check(genErr) - // Create parent context to cleanup handshaking connections on exit. - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - // // Everything below is the pion-DTLS API! Thanks for using it ❤️. // @@ -36,10 +31,6 @@ func main() { config := &dtls.Config{ Certificates: []tls.Certificate{certificate}, ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, - // Create timeout context for accepted connection. - ConnectContextMaker: func() (context.Context, func()) { - return context.WithTimeout(ctx, 30*time.Second) - }, } // Connect to a DTLS server @@ -65,6 +56,14 @@ func main() { // using `dtlsConn := conn.(*dtls.Conn)` in order to to expose // functions like `ConnectionState` etc. + // Perform the handshake with a 30-second timeout + ctx, cancel := context.WithTimeout(context.Background(), 30) + dtlsConn, ok := conn.(*dtls.Conn) + if ok { + util.Check(dtlsConn.HandshakeContext(ctx)) + } + cancel() + // Register the connection with the chat hub if err == nil { hub.Register(conn) diff --git a/examples/listen/verify-brute-force-protection/main.go b/examples/listen/verify-brute-force-protection/main.go index b5fb82c42..bcb518164 100644 --- a/examples/listen/verify-brute-force-protection/main.go +++ b/examples/listen/verify-brute-force-protection/main.go @@ -22,10 +22,6 @@ func main() { // Prepare the IP to connect to addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444} - // Create parent context to cleanup handshaking connections on exit. - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - // // Everything below is the pion-DTLS API! Thanks for using it ❤️. // @@ -52,10 +48,6 @@ func main() { ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, ClientAuth: dtls.RequireAndVerifyClientCert, ClientCAs: certPool, - // Create timeout context for accepted connection. - ConnectContextMaker: func() (context.Context, func()) { - return context.WithTimeout(ctx, 30*time.Second) - }, // This function will be called on each connection attempt. OnConnectionAttempt: func(addr net.Addr) error { // *************** Brute Force Attack protection *************** @@ -122,6 +114,14 @@ func main() { attemptsMutex.Unlock() // *************** END Brute Force Attack protection END *************** + // Perform the handshake with a 30-second timeout + ctx, cancel := context.WithTimeout(context.Background(), 30) + dtlsConn, ok := conn.(*dtls.Conn) + if ok { + util.Check(dtlsConn.HandshakeContext(ctx)) + } + cancel() + // Register the connection with the chat hub hub.Register(conn) } diff --git a/examples/listen/verify/main.go b/examples/listen/verify/main.go index a02211e15..5ef6e038f 100644 --- a/examples/listen/verify/main.go +++ b/examples/listen/verify/main.go @@ -10,7 +10,6 @@ import ( "crypto/x509" "fmt" "net" - "time" "github.com/pion/dtls/v2" "github.com/pion/dtls/v2/examples/util" @@ -20,10 +19,6 @@ func main() { // Prepare the IP to connect to addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444} - // Create parent context to cleanup handshaking connections on exit. - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - // // Everything below is the pion-DTLS API! Thanks for using it ❤️. // @@ -45,10 +40,6 @@ func main() { ExtendedMasterSecret: dtls.RequireExtendedMasterSecret, ClientAuth: dtls.RequireAndVerifyClientCert, ClientCAs: certPool, - // Create timeout context for accepted connection. - ConnectContextMaker: func() (context.Context, func()) { - return context.WithTimeout(ctx, 30*time.Second) - }, } // Connect to a DTLS server @@ -74,6 +65,14 @@ func main() { // using `dtlsConn := conn.(*dtls.Conn)` in order to to expose // functions like `ConnectionState` etc. + // Perform the handshake with a 30-second timeout + ctx, cancel := context.WithTimeout(context.Background(), 30) + dtlsConn, ok := conn.(*dtls.Conn) + if ok { + util.Check(dtlsConn.HandshakeContext(ctx)) + } + cancel() + // Register the connection with the chat hub hub.Register(conn) } diff --git a/handshaker.go b/handshaker.go index a585c3db8..62a4bf6e8 100644 --- a/handshaker.go +++ b/handshaker.go @@ -132,6 +132,8 @@ type handshakeConfig struct { clientHelloMessageHook func(handshake.MessageClientHello) handshake.Message serverHelloMessageHook func(handshake.MessageServerHello) handshake.Message certificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message + + resumeState *State } type flightConn interface { diff --git a/listener.go b/listener.go index 90dbbb427..cb75d4143 100644 --- a/listener.go +++ b/listener.go @@ -67,8 +67,6 @@ type listener struct { // Accept waits for and returns the next connection to the listener. // You have to either close or read on all connection that are created. -// Connection handshake will timeout using ConnectContextMaker in the Config. -// If you want to specify the timeout duration, set ConnectContextMaker. func (l *listener) Accept() (net.Conn, error) { c, raddr, err := l.parent.Accept() if err != nil { diff --git a/resume.go b/resume.go index 6cd1c5a69..0b76314a5 100644 --- a/resume.go +++ b/resume.go @@ -4,7 +4,6 @@ package dtls import ( - "context" "net" ) @@ -13,14 +12,5 @@ func Resume(state *State, conn net.PacketConn, rAddr net.Addr, config *Config) ( if err := state.initCipherSuite(); err != nil { return nil, err } - dconn, err := createConn(conn, rAddr, config, state.isClient) - if err != nil { - return nil, err - } - c, err := handshakeConn(context.Background(), dconn, config, state.isClient, state) - if err != nil { - return nil, err - } - - return c, nil + return createConn(conn, rAddr, config, state.isClient, state) } From b6fd38ec67a340b0c41b000e8e1f9b1966172392 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 05:57:34 +0000 Subject: [PATCH 114/146] Update module github.com/pion/transport/v3 to v3.0.5 Generated by renovateBot --- go.mod | 2 +- go.sum | 61 ++-------------------------------------------------------- 2 files changed, 3 insertions(+), 60 deletions(-) diff --git a/go.mod b/go.mod index d709d7b60..8313206c9 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/pion/dtls/v2 require ( github.com/pion/logging v0.2.2 - github.com/pion/transport/v3 v3.0.2 + github.com/pion/transport/v3 v3.0.5 golang.org/x/crypto v0.24.0 golang.org/x/net v0.26.0 ) diff --git a/go.sum b/go.sum index 913ee4e43..f34fc2e62 100644 --- a/go.sum +++ b/go.sum @@ -1,65 +1,8 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4= -github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +github.com/pion/transport/v3 v3.0.5 h1:ofVrcbPNqVPuKaTO5AMFnFuJ1ZX7ElYiWzC5PCf9YVQ= +github.com/pion/transport/v3 v3.0.5/go.mod h1:HvJr2N/JwNJAfipsRleqwFoR3t/pWyHeZUs89v3+t5s= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 0a8d8382e8fcc2e93e470d16a2ea3bf64b7b0ee7 Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Wed, 24 Jul 2024 22:21:58 -0400 Subject: [PATCH 115/146] Prepare /v3 Update go.mod and imports for /v3 --- bench_test.go | 4 ++-- certificate.go | 2 +- certificate_test.go | 2 +- cipher_suite.go | 6 ++--- cipher_suite_test.go | 4 ++-- compression_method.go | 2 +- config.go | 4 ++-- config_test.go | 2 +- conn.go | 14 +++++------ conn_go_test.go | 4 ++-- conn_test.go | 24 +++++++++---------- connection_id.go | 8 +++---- connection_id_test.go | 8 +++---- crypto.go | 4 ++-- crypto_test.go | 4 ++-- e2e/e2e_lossy_test.go | 6 ++--- e2e/e2e_openssl_test.go | 2 +- e2e/e2e_test.go | 8 +++---- errors.go | 4 ++-- examples/dial/cid/main.go | 4 ++-- examples/dial/psk/main.go | 4 ++-- examples/dial/selfsign/main.go | 6 ++--- examples/dial/verify/main.go | 4 ++-- examples/listen/cid/main.go | 4 ++-- examples/listen/psk/main.go | 4 ++-- examples/listen/selfsign/main.go | 6 ++--- .../verify-brute-force-protection/main.go | 4 ++-- examples/listen/verify/main.go | 4 ++-- flight0handler.go | 10 ++++---- flight1handler.go | 12 +++++----- flight1handler_test.go | 6 ++--- flight2handler.go | 8 +++---- flight3handler.go | 16 ++++++------- flight3handler_test.go | 10 ++++---- flight4bhandler.go | 12 +++++----- flight4handler.go | 20 ++++++++-------- flight4handler_test.go | 12 +++++----- flight5bhandler.go | 10 ++++---- flight5handler.go | 12 +++++----- flight6handler.go | 10 ++++---- flighthandler.go | 2 +- fragment_buffer.go | 6 ++--- go.mod | 2 +- handshake_cache.go | 4 ++-- handshake_cache_test.go | 4 ++-- handshake_test.go | 6 ++--- handshaker.go | 8 +++---- handshaker_test.go | 10 ++++---- internal/ciphersuite/aes_128_ccm.go | 4 ++-- internal/ciphersuite/aes_256_ccm.go | 4 ++-- internal/ciphersuite/aes_ccm.go | 8 +++---- internal/ciphersuite/ciphersuite.go | 4 ++-- .../tls_ecdhe_ecdsa_with_aes_128_ccm.go | 4 ++-- .../tls_ecdhe_ecdsa_with_aes_128_ccm8.go | 4 ++-- ...tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go | 8 +++---- .../tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go | 8 +++---- .../tls_ecdhe_psk_with_aes_128_cbc_sha256.go | 8 +++---- .../tls_ecdhe_rsa_with_aes_128_gcm_sha256.go | 2 +- .../tls_ecdhe_rsa_with_aes_256_cbc_sha.go | 2 +- .../tls_ecdhe_rsa_with_aes_256_gcm_sha384.go | 2 +- .../tls_psk_with_aes_128_cbc_sha256.go | 8 +++---- .../ciphersuite/tls_psk_with_aes_128_ccm.go | 4 ++-- .../ciphersuite/tls_psk_with_aes_128_ccm8.go | 4 ++-- .../tls_psk_with_aes_128_gcm_sha256.go | 2 +- .../ciphersuite/tls_psk_with_aes_256_ccm8.go | 4 ++-- internal/net/udp/packet_conn.go | 4 ++-- internal/net/udp/packet_conn_test.go | 2 +- listener.go | 8 +++---- packet.go | 2 +- pkg/crypto/ciphersuite/cbc.go | 8 +++---- pkg/crypto/ciphersuite/ccm.go | 6 ++--- pkg/crypto/ciphersuite/ciphersuite.go | 6 ++--- pkg/crypto/ciphersuite/ciphersuite_test.go | 4 ++-- pkg/crypto/ciphersuite/gcm.go | 4 ++-- pkg/crypto/hash/hash_test.go | 2 +- pkg/crypto/prf/prf.go | 4 ++-- pkg/crypto/prf/prf_test.go | 2 +- pkg/crypto/signaturehash/signaturehash.go | 4 ++-- .../signaturehash/signaturehash_test.go | 4 ++-- pkg/protocol/alert/alert.go | 2 +- pkg/protocol/extension/errors.go | 2 +- .../extension/supported_elliptic_curves.go | 2 +- .../supported_elliptic_curves_test.go | 2 +- .../extension/supported_point_formats.go | 2 +- .../extension/supported_point_formats_test.go | 2 +- .../supported_signature_algorithms.go | 6 ++--- .../supported_signature_algorithms_test.go | 6 ++--- pkg/protocol/handshake/errors.go | 2 +- pkg/protocol/handshake/handshake.go | 6 ++--- pkg/protocol/handshake/header.go | 2 +- pkg/protocol/handshake/message_certificate.go | 2 +- .../handshake/message_certificate_request.go | 8 +++---- .../message_certificate_request_test.go | 8 +++---- .../handshake/message_certificate_verify.go | 4 ++-- .../message_certificate_verify_test.go | 4 ++-- .../handshake/message_client_hello.go | 4 ++-- .../handshake/message_client_hello_test.go | 6 ++--- .../handshake/message_client_key_exchange.go | 2 +- .../message_client_key_exchange_test.go | 2 +- .../handshake/message_hello_verify_request.go | 2 +- .../message_hello_verify_request_test.go | 2 +- .../handshake/message_server_hello.go | 4 ++-- .../handshake/message_server_hello_test.go | 4 ++-- .../handshake/message_server_key_exchange.go | 8 +++---- .../message_server_key_exchange_test.go | 8 +++---- pkg/protocol/recordlayer/errors.go | 2 +- pkg/protocol/recordlayer/header.go | 4 ++-- pkg/protocol/recordlayer/inner_plaintext.go | 2 +- pkg/protocol/recordlayer/recordlayer.go | 6 ++--- pkg/protocol/recordlayer/recordlayer_test.go | 2 +- resume_test.go | 4 ++-- srtp_protection_profile.go | 2 +- state.go | 8 +++---- 113 files changed, 302 insertions(+), 302 deletions(-) diff --git a/bench_test.go b/bench_test.go index 885b311f2..57fe93ff1 100644 --- a/bench_test.go +++ b/bench_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" - dtlsnet "github.com/pion/dtls/v2/pkg/net" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" + dtlsnet "github.com/pion/dtls/v3/pkg/net" "github.com/pion/logging" "github.com/pion/transport/v3/dpipe" "github.com/pion/transport/v3/test" diff --git a/certificate.go b/certificate.go index e8dd2b83f..7e184dfd5 100644 --- a/certificate.go +++ b/certificate.go @@ -10,7 +10,7 @@ import ( "fmt" "strings" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/handshake" ) // ClientHelloInfo contains information from a ClientHello message in order to diff --git a/certificate_test.go b/certificate_test.go index 8c0868f45..37598a639 100644 --- a/certificate_test.go +++ b/certificate_test.go @@ -8,7 +8,7 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" ) func TestGetCertificate(t *testing.T) { diff --git a/cipher_suite.go b/cipher_suite.go index 6f7015c02..af95dec2e 100644 --- a/cipher_suite.go +++ b/cipher_suite.go @@ -11,9 +11,9 @@ import ( "fmt" "hash" - "github.com/pion/dtls/v2/internal/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/internal/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) // CipherSuiteID is an ID for our supported CipherSuites diff --git a/cipher_suite_test.go b/cipher_suite_test.go index 3aa4c8fe6..bd1f803ec 100644 --- a/cipher_suite_test.go +++ b/cipher_suite_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/internal/ciphersuite" - dtlsnet "github.com/pion/dtls/v2/pkg/net" + "github.com/pion/dtls/v3/internal/ciphersuite" + dtlsnet "github.com/pion/dtls/v3/pkg/net" "github.com/pion/transport/v3/dpipe" "github.com/pion/transport/v3/test" ) diff --git a/compression_method.go b/compression_method.go index 7e44de009..49b11c718 100644 --- a/compression_method.go +++ b/compression_method.go @@ -3,7 +3,7 @@ package dtls -import "github.com/pion/dtls/v2/pkg/protocol" +import "github.com/pion/dtls/v3/pkg/protocol" func defaultCompressionMethods() []*protocol.CompressionMethod { return []*protocol.CompressionMethod{ diff --git a/config.go b/config.go index f97930294..2fb241959 100644 --- a/config.go +++ b/config.go @@ -13,8 +13,8 @@ import ( "net" "time" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/protocol/handshake" "github.com/pion/logging" ) diff --git a/config_test.go b/config_test.go index 806d66929..99e25a4c2 100644 --- a/config_test.go +++ b/config_test.go @@ -11,7 +11,7 @@ import ( "errors" "testing" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" ) func TestValidateConfig(t *testing.T) { diff --git a/conn.go b/conn.go index 0d8896550..ce3234731 100644 --- a/conn.go +++ b/conn.go @@ -14,13 +14,13 @@ import ( "sync/atomic" "time" - "github.com/pion/dtls/v2/internal/closer" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/internal/closer" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" "github.com/pion/logging" "github.com/pion/transport/v3/deadline" "github.com/pion/transport/v3/netctx" diff --git a/conn_go_test.go b/conn_go_test.go index bd542f27d..6b05d8d76 100644 --- a/conn_go_test.go +++ b/conn_go_test.go @@ -15,8 +15,8 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" - dtlsnet "github.com/pion/dtls/v2/pkg/net" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" + dtlsnet "github.com/pion/dtls/v3/pkg/net" "github.com/pion/transport/v3/dpipe" "github.com/pion/transport/v3/test" ) diff --git a/conn_test.go b/conn_test.go index 83a90f2d2..7192178a8 100644 --- a/conn_test.go +++ b/conn_test.go @@ -24,18 +24,18 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/internal/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" - "github.com/pion/dtls/v2/pkg/crypto/signature" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - dtlsnet "github.com/pion/dtls/v2/pkg/net" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "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/dtls/v3/internal/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" + "github.com/pion/dtls/v3/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + dtlsnet "github.com/pion/dtls/v3/pkg/net" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" "github.com/pion/logging" "github.com/pion/transport/v3/dpipe" "github.com/pion/transport/v3/test" diff --git a/connection_id.go b/connection_id.go index b2fbbd7a8..f0e94631b 100644 --- a/connection_id.go +++ b/connection_id.go @@ -6,10 +6,10 @@ package dtls import ( "crypto/rand" - "github.com/pion/dtls/v2/pkg/protocol" - "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/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) // RandomCIDGenerator is a random Connection ID generator where CID is the diff --git a/connection_id_test.go b/connection_id_test.go index bc9a991d1..8936aba98 100644 --- a/connection_id_test.go +++ b/connection_id_test.go @@ -7,10 +7,10 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/pkg/protocol" - "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/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) func TestRandomConnectionIDGenerator(t *testing.T) { diff --git a/crypto.go b/crypto.go index 7b01002f3..beddb40a8 100644 --- a/crypto.go +++ b/crypto.go @@ -15,8 +15,8 @@ import ( "math/big" "time" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/hash" ) type ecdsaSignature struct { diff --git a/crypto_test.go b/crypto_test.go index 3b88fccee..e3f572eb5 100644 --- a/crypto_test.go +++ b/crypto_test.go @@ -9,8 +9,8 @@ import ( "encoding/pem" "testing" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/hash" ) // nolint: gosec diff --git a/e2e/e2e_lossy_test.go b/e2e/e2e_lossy_test.go index a306584bb..5be97eb4c 100644 --- a/e2e/e2e_lossy_test.go +++ b/e2e/e2e_lossy_test.go @@ -10,9 +10,9 @@ import ( "testing" "time" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" - dtlsnet "github.com/pion/dtls/v2/pkg/net" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" + dtlsnet "github.com/pion/dtls/v3/pkg/net" transportTest "github.com/pion/transport/v3/test" ) diff --git a/e2e/e2e_openssl_test.go b/e2e/e2e_openssl_test.go index dbcda4a07..97da68e88 100644 --- a/e2e/e2e_openssl_test.go +++ b/e2e/e2e_openssl_test.go @@ -20,7 +20,7 @@ import ( "testing" "time" - "github.com/pion/dtls/v2" + "github.com/pion/dtls/v3" ) func serverOpenSSL(c *comm) { diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 0d8ba35bc..06f9b78fb 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -22,10 +22,10 @@ import ( "testing" "time" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" - "github.com/pion/dtls/v2/pkg/protocol/extension" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" "github.com/pion/transport/v3/test" ) diff --git a/errors.go b/errors.go index 025d8645e..f03fb11c0 100644 --- a/errors.go +++ b/errors.go @@ -11,8 +11,8 @@ import ( "net" "os" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" ) // Typed errors diff --git a/examples/dial/cid/main.go b/examples/dial/cid/main.go index 4859e72b1..b52631f1a 100644 --- a/examples/dial/cid/main.go +++ b/examples/dial/cid/main.go @@ -10,8 +10,8 @@ import ( "net" "time" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/examples/util" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/examples/util" ) func main() { diff --git a/examples/dial/psk/main.go b/examples/dial/psk/main.go index 94731e93a..112826bbc 100644 --- a/examples/dial/psk/main.go +++ b/examples/dial/psk/main.go @@ -10,8 +10,8 @@ import ( "net" "time" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/examples/util" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/examples/util" ) func main() { diff --git a/examples/dial/selfsign/main.go b/examples/dial/selfsign/main.go index b3be5a8f8..7d86adf13 100644 --- a/examples/dial/selfsign/main.go +++ b/examples/dial/selfsign/main.go @@ -11,9 +11,9 @@ import ( "net" "time" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/examples/util" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/examples/util" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" ) func main() { diff --git a/examples/dial/verify/main.go b/examples/dial/verify/main.go index ed5352dd5..e572aec2d 100644 --- a/examples/dial/verify/main.go +++ b/examples/dial/verify/main.go @@ -12,8 +12,8 @@ import ( "net" "time" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/examples/util" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/examples/util" ) func main() { diff --git a/examples/listen/cid/main.go b/examples/listen/cid/main.go index 11be4bc21..25cc3287d 100644 --- a/examples/listen/cid/main.go +++ b/examples/listen/cid/main.go @@ -9,8 +9,8 @@ import ( "fmt" "net" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/examples/util" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/examples/util" ) func main() { diff --git a/examples/listen/psk/main.go b/examples/listen/psk/main.go index e6c16514c..4fdcc838f 100644 --- a/examples/listen/psk/main.go +++ b/examples/listen/psk/main.go @@ -9,8 +9,8 @@ import ( "fmt" "net" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/examples/util" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/examples/util" ) func main() { diff --git a/examples/listen/selfsign/main.go b/examples/listen/selfsign/main.go index af1010102..a73b1479c 100644 --- a/examples/listen/selfsign/main.go +++ b/examples/listen/selfsign/main.go @@ -10,9 +10,9 @@ import ( "fmt" "net" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/examples/util" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/examples/util" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" ) func main() { diff --git a/examples/listen/verify-brute-force-protection/main.go b/examples/listen/verify-brute-force-protection/main.go index bcb518164..aaa1a90ad 100644 --- a/examples/listen/verify-brute-force-protection/main.go +++ b/examples/listen/verify-brute-force-protection/main.go @@ -14,8 +14,8 @@ import ( "sync" "time" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/examples/util" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/examples/util" ) func main() { diff --git a/examples/listen/verify/main.go b/examples/listen/verify/main.go index 5ef6e038f..cb19ee605 100644 --- a/examples/listen/verify/main.go +++ b/examples/listen/verify/main.go @@ -11,8 +11,8 @@ import ( "fmt" "net" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/examples/util" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/examples/util" ) func main() { diff --git a/flight0handler.go b/flight0handler.go index c965fd0b5..77d403276 100644 --- a/flight0handler.go +++ b/flight0handler.go @@ -7,11 +7,11 @@ import ( "context" "crypto/rand" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/extension" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" ) func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { diff --git a/flight1handler.go b/flight1handler.go index bcbddc3ec..69019c91c 100644 --- a/flight1handler.go +++ b/flight1handler.go @@ -6,12 +6,12 @@ package dtls import ( "context" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "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/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { diff --git a/flight1handler_test.go b/flight1handler_test.go index 461ef7cf6..f6dc46c3e 100644 --- a/flight1handler_test.go +++ b/flight1handler_test.go @@ -8,9 +8,9 @@ import ( "testing" "time" - "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/dtls/v3/internal/ciphersuite" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" "github.com/pion/logging" "github.com/pion/transport/v3/test" ) diff --git a/flight2handler.go b/flight2handler.go index 26e57d2f2..0af457c35 100644 --- a/flight2handler.go +++ b/flight2handler.go @@ -7,10 +7,10 @@ import ( "bytes" "context" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) func flight2Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { diff --git a/flight3handler.go b/flight3handler.go index 678b1e5a7..39d9380cb 100644 --- a/flight3handler.go +++ b/flight3handler.go @@ -7,14 +7,14 @@ import ( "bytes" "context" - "github.com/pion/dtls/v2/internal/ciphersuite/types" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "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/dtls/v3/internal/ciphersuite/types" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { //nolint:gocognit diff --git a/flight3handler_test.go b/flight3handler_test.go index 537e206db..e801be00a 100644 --- a/flight3handler_test.go +++ b/flight3handler_test.go @@ -9,11 +9,11 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - dtlsnet "github.com/pion/dtls/v2/pkg/net" - "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/dtls/v3/pkg/crypto/elliptic" + dtlsnet "github.com/pion/dtls/v3/pkg/net" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" "github.com/pion/transport/v3/dpipe" "github.com/pion/transport/v3/test" ) diff --git a/flight4bhandler.go b/flight4bhandler.go index d653f4d94..71e7044cb 100644 --- a/flight4bhandler.go +++ b/flight4bhandler.go @@ -7,12 +7,12 @@ import ( "bytes" "context" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "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/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) func flight4bParse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { diff --git a/flight4handler.go b/flight4handler.go index b1ff6c3ff..af8cf6b4b 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -8,16 +8,16 @@ 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" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "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/dtls/v3/internal/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { //nolint:gocognit diff --git a/flight4handler_test.go b/flight4handler_test.go index bf99a160e..20e9d2253 100644 --- a/flight4handler_test.go +++ b/flight4handler_test.go @@ -10,12 +10,12 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/internal/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/internal/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" "github.com/pion/transport/v3/test" ) diff --git a/flight5bhandler.go b/flight5bhandler.go index ddd37324c..27a05cc21 100644 --- a/flight5bhandler.go +++ b/flight5bhandler.go @@ -6,11 +6,11 @@ package dtls import ( "context" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) func flight5bParse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { diff --git a/flight5handler.go b/flight5handler.go index 14ad66e53..2f6e7b3ee 100644 --- a/flight5handler.go +++ b/flight5handler.go @@ -9,12 +9,12 @@ import ( "crypto" "crypto/x509" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { diff --git a/flight6handler.go b/flight6handler.go index c03890425..576dc551b 100644 --- a/flight6handler.go +++ b/flight6handler.go @@ -6,11 +6,11 @@ package dtls import ( "context" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) func flight6Parse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { diff --git a/flighthandler.go b/flighthandler.go index ceb4a992b..651ff17e0 100644 --- a/flighthandler.go +++ b/flighthandler.go @@ -6,7 +6,7 @@ package dtls import ( "context" - "github.com/pion/dtls/v2/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/alert" ) // Parse received handshakes and return next flightVal diff --git a/fragment_buffer.go b/fragment_buffer.go index f7785ec32..37223ab07 100644 --- a/fragment_buffer.go +++ b/fragment_buffer.go @@ -4,9 +4,9 @@ package dtls import ( - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) // 2 megabytes diff --git a/go.mod b/go.mod index 8313206c9..6ddc83232 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/pion/dtls/v2 +module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.2 diff --git a/handshake_cache.go b/handshake_cache.go index 85c87e640..285c71331 100644 --- a/handshake_cache.go +++ b/handshake_cache.go @@ -6,8 +6,8 @@ package dtls import ( "sync" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/handshake" ) type handshakeCacheItem struct { diff --git a/handshake_cache_test.go b/handshake_cache_test.go index 44a15b587..647a3f35e 100644 --- a/handshake_cache_test.go +++ b/handshake_cache_test.go @@ -7,8 +7,8 @@ import ( "bytes" "testing" - "github.com/pion/dtls/v2/internal/ciphersuite" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/internal/ciphersuite" + "github.com/pion/dtls/v3/pkg/protocol/handshake" ) func TestHandshakeCacheSinglePush(t *testing.T) { diff --git a/handshake_test.go b/handshake_test.go index 5bba7f812..4cadb610f 100644 --- a/handshake_test.go +++ b/handshake_test.go @@ -8,9 +8,9 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/extension" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" ) func TestHandshakeMessage(t *testing.T) { diff --git a/handshaker.go b/handshaker.go index 62a4bf6e8..0c2a43643 100644 --- a/handshaker.go +++ b/handshaker.go @@ -12,10 +12,10 @@ import ( "sync" "time" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" "github.com/pion/logging" ) diff --git a/handshaker_test.go b/handshaker_test.go index b814fc90b..39b7ff20c 100644 --- a/handshaker_test.go +++ b/handshaker_test.go @@ -12,11 +12,11 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" "github.com/pion/logging" "github.com/pion/transport/v3/test" ) diff --git a/internal/ciphersuite/aes_128_ccm.go b/internal/ciphersuite/aes_128_ccm.go index f78b6dc2c..0877c2c18 100644 --- a/internal/ciphersuite/aes_128_ccm.go +++ b/internal/ciphersuite/aes_128_ccm.go @@ -4,8 +4,8 @@ package ciphersuite import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) // Aes128Ccm is a base class used by multiple AES-CCM Ciphers diff --git a/internal/ciphersuite/aes_256_ccm.go b/internal/ciphersuite/aes_256_ccm.go index bb8128627..bbdf06d81 100644 --- a/internal/ciphersuite/aes_256_ccm.go +++ b/internal/ciphersuite/aes_256_ccm.go @@ -4,8 +4,8 @@ package ciphersuite import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) // Aes256Ccm is a base class used by multiple AES-CCM Ciphers diff --git a/internal/ciphersuite/aes_ccm.go b/internal/ciphersuite/aes_ccm.go index ee3cca903..54eafcf80 100644 --- a/internal/ciphersuite/aes_ccm.go +++ b/internal/ciphersuite/aes_ccm.go @@ -9,10 +9,10 @@ import ( "hash" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) // AesCcm is a base class used by multiple AES-CCM Ciphers diff --git a/internal/ciphersuite/ciphersuite.go b/internal/ciphersuite/ciphersuite.go index f44f29fd3..4778be72a 100644 --- a/internal/ciphersuite/ciphersuite.go +++ b/internal/ciphersuite/ciphersuite.go @@ -8,8 +8,8 @@ import ( "errors" "fmt" - "github.com/pion/dtls/v2/internal/ciphersuite/types" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/internal/ciphersuite/types" + "github.com/pion/dtls/v3/pkg/protocol" ) var errCipherSuiteNotInit = &protocol.TemporaryError{Err: errors.New("CipherSuite has not been initialized")} //nolint:goerr113 diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go index 8367b2c6d..e55290799 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go @@ -4,8 +4,8 @@ package ciphersuite import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) // NewTLSEcdheEcdsaWithAes128Ccm constructs a TLS_ECDHE_ECDSA_WITH_AES_128_CCM Cipher diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go index 11b687327..a423a13f1 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go @@ -4,8 +4,8 @@ package ciphersuite import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) // NewTLSEcdheEcdsaWithAes128Ccm8 creates a new TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuite diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go index 362370b98..9f7b27788 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go @@ -9,10 +9,10 @@ import ( "hash" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) // TLSEcdheEcdsaWithAes128GcmSha256 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go index 07ad66fd1..87f5ef395 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go @@ -10,10 +10,10 @@ import ( "hash" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) // TLSEcdheEcdsaWithAes256CbcSha represents a TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuite diff --git a/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go b/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go index 10cc58c0b..87b80f421 100644 --- a/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go +++ b/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go @@ -9,10 +9,10 @@ import ( "hash" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) // TLSEcdhePskWithAes128CbcSha256 implements the TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuite diff --git a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go index 478a2e0dc..5ac17ed97 100644 --- a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go +++ b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go @@ -3,7 +3,7 @@ package ciphersuite -import "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" +import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" // TLSEcdheRsaWithAes128GcmSha256 implements the TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuite type TLSEcdheRsaWithAes128GcmSha256 struct { diff --git a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go index 8e88ee639..545c2e46f 100644 --- a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go +++ b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go @@ -3,7 +3,7 @@ package ciphersuite -import "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" +import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" // TLSEcdheRsaWithAes256CbcSha implements the TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuite type TLSEcdheRsaWithAes256CbcSha struct { diff --git a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go index 752fb529c..5750cc386 100644 --- a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go +++ b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go @@ -3,7 +3,7 @@ package ciphersuite -import "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" +import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" // TLSEcdheRsaWithAes256GcmSha384 implements the TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuite type TLSEcdheRsaWithAes256GcmSha384 struct { diff --git a/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go b/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go index dea0dfc75..dc485c46b 100644 --- a/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go +++ b/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go @@ -9,10 +9,10 @@ import ( "hash" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) // TLSPskWithAes128CbcSha256 implements the TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuite diff --git a/internal/ciphersuite/tls_psk_with_aes_128_ccm.go b/internal/ciphersuite/tls_psk_with_aes_128_ccm.go index 1ded09b88..6344f11fb 100644 --- a/internal/ciphersuite/tls_psk_with_aes_128_ccm.go +++ b/internal/ciphersuite/tls_psk_with_aes_128_ccm.go @@ -4,8 +4,8 @@ package ciphersuite import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) // NewTLSPskWithAes128Ccm returns the TLS_PSK_WITH_AES_128_CCM CipherSuite diff --git a/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go b/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go index 478197074..4b0827533 100644 --- a/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go +++ b/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go @@ -4,8 +4,8 @@ package ciphersuite import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) // NewTLSPskWithAes128Ccm8 returns the TLS_PSK_WITH_AES_128_CCM_8 CipherSuite diff --git a/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go b/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go index 8ab5b89a8..3a5e7e753 100644 --- a/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go +++ b/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go @@ -3,7 +3,7 @@ package ciphersuite -import "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" +import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" // TLSPskWithAes128GcmSha256 implements the TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuite type TLSPskWithAes128GcmSha256 struct { diff --git a/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go b/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go index 32d503018..211bdae03 100644 --- a/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go +++ b/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go @@ -4,8 +4,8 @@ package ciphersuite import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) // NewTLSPskWithAes256Ccm8 returns the TLS_PSK_WITH_AES_256_CCM_8 CipherSuite diff --git a/internal/net/udp/packet_conn.go b/internal/net/udp/packet_conn.go index 7dafbe23e..da5b6fae8 100644 --- a/internal/net/udp/packet_conn.go +++ b/internal/net/udp/packet_conn.go @@ -24,8 +24,8 @@ import ( "sync/atomic" "time" - idtlsnet "github.com/pion/dtls/v2/internal/net" - dtlsnet "github.com/pion/dtls/v2/pkg/net" + idtlsnet "github.com/pion/dtls/v3/internal/net" + dtlsnet "github.com/pion/dtls/v3/pkg/net" "github.com/pion/transport/v3/deadline" ) diff --git a/internal/net/udp/packet_conn_test.go b/internal/net/udp/packet_conn_test.go index cb239b3e0..2e9f4a063 100644 --- a/internal/net/udp/packet_conn_test.go +++ b/internal/net/udp/packet_conn_test.go @@ -18,7 +18,7 @@ import ( "testing" "time" - dtlsnet "github.com/pion/dtls/v2/pkg/net" + dtlsnet "github.com/pion/dtls/v3/pkg/net" "github.com/pion/transport/v3/test" ) diff --git a/listener.go b/listener.go index cb75d4143..22e56ce52 100644 --- a/listener.go +++ b/listener.go @@ -6,10 +6,10 @@ package dtls import ( "net" - "github.com/pion/dtls/v2/internal/net/udp" - dtlsnet "github.com/pion/dtls/v2/pkg/net" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/internal/net/udp" + dtlsnet "github.com/pion/dtls/v3/pkg/net" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) // Listen creates a DTLS listener diff --git a/packet.go b/packet.go index 052c33a19..c224eff1b 100644 --- a/packet.go +++ b/packet.go @@ -4,7 +4,7 @@ package dtls import ( - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) type packet struct { diff --git a/pkg/crypto/ciphersuite/cbc.go b/pkg/crypto/ciphersuite/cbc.go index 008a8365b..68a080d5d 100644 --- a/pkg/crypto/ciphersuite/cbc.go +++ b/pkg/crypto/ciphersuite/cbc.go @@ -11,10 +11,10 @@ import ( //nolint:gci "encoding/binary" "hash" - "github.com/pion/dtls/v2/internal/util" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/internal/util" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" "golang.org/x/crypto/cryptobyte" ) diff --git a/pkg/crypto/ciphersuite/ccm.go b/pkg/crypto/ciphersuite/ccm.go index 6fb185d85..4c296e2bb 100644 --- a/pkg/crypto/ciphersuite/ccm.go +++ b/pkg/crypto/ciphersuite/ccm.go @@ -9,9 +9,9 @@ import ( "encoding/binary" "fmt" - "github.com/pion/dtls/v2/pkg/crypto/ccm" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ccm" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) // CCMTagLen is the length of Authentication Tag diff --git a/pkg/crypto/ciphersuite/ciphersuite.go b/pkg/crypto/ciphersuite/ciphersuite.go index a3130be12..90ddf6105 100644 --- a/pkg/crypto/ciphersuite/ciphersuite.go +++ b/pkg/crypto/ciphersuite/ciphersuite.go @@ -8,9 +8,9 @@ import ( "encoding/binary" "errors" - "github.com/pion/dtls/v2/internal/util" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/internal/util" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" "golang.org/x/crypto/cryptobyte" ) diff --git a/pkg/crypto/ciphersuite/ciphersuite_test.go b/pkg/crypto/ciphersuite/ciphersuite_test.go index 0c2652f79..100d718d9 100644 --- a/pkg/crypto/ciphersuite/ciphersuite_test.go +++ b/pkg/crypto/ciphersuite/ciphersuite_test.go @@ -8,8 +8,8 @@ import ( "bytes" "testing" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) func TestGenerateAEADAdditionalDataCID(t *testing.T) { diff --git a/pkg/crypto/ciphersuite/gcm.go b/pkg/crypto/ciphersuite/gcm.go index 1d09c8eb9..a7f828246 100644 --- a/pkg/crypto/ciphersuite/gcm.go +++ b/pkg/crypto/ciphersuite/gcm.go @@ -10,8 +10,8 @@ import ( "encoding/binary" "fmt" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) const ( diff --git a/pkg/crypto/hash/hash_test.go b/pkg/crypto/hash/hash_test.go index e6711c69e..d6660254b 100644 --- a/pkg/crypto/hash/hash_test.go +++ b/pkg/crypto/hash/hash_test.go @@ -6,7 +6,7 @@ package hash import ( "testing" - "github.com/pion/dtls/v2/pkg/crypto/fingerprint" + "github.com/pion/dtls/v3/pkg/crypto/fingerprint" ) func TestHashAlgorithm_StringRoundtrip(t *testing.T) { diff --git a/pkg/crypto/prf/prf.go b/pkg/crypto/prf/prf.go index 6e7b3ecba..b5ac19f79 100644 --- a/pkg/crypto/prf/prf.go +++ b/pkg/crypto/prf/prf.go @@ -13,8 +13,8 @@ import ( //nolint:gci "hash" "math" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/protocol" "golang.org/x/crypto/curve25519" ) diff --git a/pkg/crypto/prf/prf_test.go b/pkg/crypto/prf/prf_test.go index bd375b9aa..fa9b32510 100644 --- a/pkg/crypto/prf/prf_test.go +++ b/pkg/crypto/prf/prf_test.go @@ -9,7 +9,7 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" ) func TestPreMasterSecret(t *testing.T) { diff --git a/pkg/crypto/signaturehash/signaturehash.go b/pkg/crypto/signaturehash/signaturehash.go index 2561accd1..38587768b 100644 --- a/pkg/crypto/signaturehash/signaturehash.go +++ b/pkg/crypto/signaturehash/signaturehash.go @@ -12,8 +12,8 @@ import ( "crypto/tls" "fmt" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" ) // Algorithm is a signature/hash algorithm pairs which may be used in diff --git a/pkg/crypto/signaturehash/signaturehash_test.go b/pkg/crypto/signaturehash/signaturehash_test.go index 6df4dbcab..54afce324 100644 --- a/pkg/crypto/signaturehash/signaturehash_test.go +++ b/pkg/crypto/signaturehash/signaturehash_test.go @@ -9,8 +9,8 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" ) func TestParseSignatureSchemes(t *testing.T) { diff --git a/pkg/protocol/alert/alert.go b/pkg/protocol/alert/alert.go index 91e9f4d60..0a9e0a215 100644 --- a/pkg/protocol/alert/alert.go +++ b/pkg/protocol/alert/alert.go @@ -8,7 +8,7 @@ import ( "errors" "fmt" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol" ) var errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 diff --git a/pkg/protocol/extension/errors.go b/pkg/protocol/extension/errors.go index 39431206f..6b4c9229b 100644 --- a/pkg/protocol/extension/errors.go +++ b/pkg/protocol/extension/errors.go @@ -6,7 +6,7 @@ package extension import ( "errors" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol" ) var ( diff --git a/pkg/protocol/extension/supported_elliptic_curves.go b/pkg/protocol/extension/supported_elliptic_curves.go index dd9b54f0d..e83b5ccb8 100644 --- a/pkg/protocol/extension/supported_elliptic_curves.go +++ b/pkg/protocol/extension/supported_elliptic_curves.go @@ -6,7 +6,7 @@ package extension import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" ) const ( diff --git a/pkg/protocol/extension/supported_elliptic_curves_test.go b/pkg/protocol/extension/supported_elliptic_curves_test.go index dc6c6c502..620246a81 100644 --- a/pkg/protocol/extension/supported_elliptic_curves_test.go +++ b/pkg/protocol/extension/supported_elliptic_curves_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" ) func TestExtensionSupportedGroups(t *testing.T) { diff --git a/pkg/protocol/extension/supported_point_formats.go b/pkg/protocol/extension/supported_point_formats.go index 5ed0f347f..ec877aff2 100644 --- a/pkg/protocol/extension/supported_point_formats.go +++ b/pkg/protocol/extension/supported_point_formats.go @@ -6,7 +6,7 @@ package extension import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" ) const ( diff --git a/pkg/protocol/extension/supported_point_formats_test.go b/pkg/protocol/extension/supported_point_formats_test.go index 81862679a..eecbd5c82 100644 --- a/pkg/protocol/extension/supported_point_formats_test.go +++ b/pkg/protocol/extension/supported_point_formats_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" ) func TestExtensionSupportedPointFormats(t *testing.T) { diff --git a/pkg/protocol/extension/supported_signature_algorithms.go b/pkg/protocol/extension/supported_signature_algorithms.go index 2ff4b90b6..396b9ae38 100644 --- a/pkg/protocol/extension/supported_signature_algorithms.go +++ b/pkg/protocol/extension/supported_signature_algorithms.go @@ -6,9 +6,9 @@ package extension import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" ) const ( diff --git a/pkg/protocol/extension/supported_signature_algorithms_test.go b/pkg/protocol/extension/supported_signature_algorithms_test.go index 16fce4793..80b5692e3 100644 --- a/pkg/protocol/extension/supported_signature_algorithms_test.go +++ b/pkg/protocol/extension/supported_signature_algorithms_test.go @@ -7,9 +7,9 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" ) func TestExtensionSupportedSignatureAlgorithms(t *testing.T) { diff --git a/pkg/protocol/handshake/errors.go b/pkg/protocol/handshake/errors.go index 1354300c4..4f007198f 100644 --- a/pkg/protocol/handshake/errors.go +++ b/pkg/protocol/handshake/errors.go @@ -6,7 +6,7 @@ package handshake import ( "errors" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol" ) // Typed errors diff --git a/pkg/protocol/handshake/handshake.go b/pkg/protocol/handshake/handshake.go index b1f682bf5..6f0eb9c71 100644 --- a/pkg/protocol/handshake/handshake.go +++ b/pkg/protocol/handshake/handshake.go @@ -5,9 +5,9 @@ package handshake import ( - "github.com/pion/dtls/v2/internal/ciphersuite/types" - "github.com/pion/dtls/v2/internal/util" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/internal/ciphersuite/types" + "github.com/pion/dtls/v3/internal/util" + "github.com/pion/dtls/v3/pkg/protocol" ) // Type is the unique identifier for each handshake message diff --git a/pkg/protocol/handshake/header.go b/pkg/protocol/handshake/header.go index 4f9a96287..619fd2bdb 100644 --- a/pkg/protocol/handshake/header.go +++ b/pkg/protocol/handshake/header.go @@ -6,7 +6,7 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/internal/util" + "github.com/pion/dtls/v3/internal/util" ) // HeaderLength msg_len for Handshake messages assumes an extra diff --git a/pkg/protocol/handshake/message_certificate.go b/pkg/protocol/handshake/message_certificate.go index d5c861d90..54b0bfddb 100644 --- a/pkg/protocol/handshake/message_certificate.go +++ b/pkg/protocol/handshake/message_certificate.go @@ -4,7 +4,7 @@ package handshake import ( - "github.com/pion/dtls/v2/internal/util" + "github.com/pion/dtls/v3/internal/util" ) // MessageCertificate is a DTLS Handshake Message diff --git a/pkg/protocol/handshake/message_certificate_request.go b/pkg/protocol/handshake/message_certificate_request.go index 11a44d440..5c3ac63c5 100644 --- a/pkg/protocol/handshake/message_certificate_request.go +++ b/pkg/protocol/handshake/message_certificate_request.go @@ -6,10 +6,10 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" ) /* diff --git a/pkg/protocol/handshake/message_certificate_request_test.go b/pkg/protocol/handshake/message_certificate_request_test.go index 99b360f80..78bcb5b41 100644 --- a/pkg/protocol/handshake/message_certificate_request_test.go +++ b/pkg/protocol/handshake/message_certificate_request_test.go @@ -8,10 +8,10 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" ) func TestHandshakeMessageCertificateRequest(t *testing.T) { diff --git a/pkg/protocol/handshake/message_certificate_verify.go b/pkg/protocol/handshake/message_certificate_verify.go index 9e02a9c11..9d09b31ca 100644 --- a/pkg/protocol/handshake/message_certificate_verify.go +++ b/pkg/protocol/handshake/message_certificate_verify.go @@ -6,8 +6,8 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" ) // MessageCertificateVerify provide explicit verification of a diff --git a/pkg/protocol/handshake/message_certificate_verify_test.go b/pkg/protocol/handshake/message_certificate_verify_test.go index ea9cdce7c..3144e5c78 100644 --- a/pkg/protocol/handshake/message_certificate_verify_test.go +++ b/pkg/protocol/handshake/message_certificate_verify_test.go @@ -7,8 +7,8 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" ) func TestHandshakeMessageCertificateVerify(t *testing.T) { diff --git a/pkg/protocol/handshake/message_client_hello.go b/pkg/protocol/handshake/message_client_hello.go index bea6dd969..c651718e5 100644 --- a/pkg/protocol/handshake/message_client_hello.go +++ b/pkg/protocol/handshake/message_client_hello.go @@ -6,8 +6,8 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/extension" ) /* diff --git a/pkg/protocol/handshake/message_client_hello_test.go b/pkg/protocol/handshake/message_client_hello_test.go index eeb73b81e..d46567691 100644 --- a/pkg/protocol/handshake/message_client_hello_test.go +++ b/pkg/protocol/handshake/message_client_hello_test.go @@ -9,9 +9,9 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/extension" ) func TestHandshakeMessageClientHello(t *testing.T) { diff --git a/pkg/protocol/handshake/message_client_key_exchange.go b/pkg/protocol/handshake/message_client_key_exchange.go index 2abcd5bf7..626361c6c 100644 --- a/pkg/protocol/handshake/message_client_key_exchange.go +++ b/pkg/protocol/handshake/message_client_key_exchange.go @@ -6,7 +6,7 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/internal/ciphersuite/types" + "github.com/pion/dtls/v3/internal/ciphersuite/types" ) // MessageClientKeyExchange is a DTLS Handshake Message diff --git a/pkg/protocol/handshake/message_client_key_exchange_test.go b/pkg/protocol/handshake/message_client_key_exchange_test.go index 88f31af8b..c7d569542 100644 --- a/pkg/protocol/handshake/message_client_key_exchange_test.go +++ b/pkg/protocol/handshake/message_client_key_exchange_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/internal/ciphersuite/types" + "github.com/pion/dtls/v3/internal/ciphersuite/types" ) func TestHandshakeMessageClientKeyExchange(t *testing.T) { diff --git a/pkg/protocol/handshake/message_hello_verify_request.go b/pkg/protocol/handshake/message_hello_verify_request.go index 398e59cc3..98960400c 100644 --- a/pkg/protocol/handshake/message_hello_verify_request.go +++ b/pkg/protocol/handshake/message_hello_verify_request.go @@ -4,7 +4,7 @@ package handshake import ( - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol" ) // MessageHelloVerifyRequest is as follows: diff --git a/pkg/protocol/handshake/message_hello_verify_request_test.go b/pkg/protocol/handshake/message_hello_verify_request_test.go index 3513fc8ee..82252566e 100644 --- a/pkg/protocol/handshake/message_hello_verify_request_test.go +++ b/pkg/protocol/handshake/message_hello_verify_request_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol" ) func TestHandshakeMessageHelloVerifyRequest(t *testing.T) { diff --git a/pkg/protocol/handshake/message_server_hello.go b/pkg/protocol/handshake/message_server_hello.go index caf186da8..a1e86e1b2 100644 --- a/pkg/protocol/handshake/message_server_hello.go +++ b/pkg/protocol/handshake/message_server_hello.go @@ -6,8 +6,8 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/extension" ) // MessageServerHello is sent in response to a ClientHello diff --git a/pkg/protocol/handshake/message_server_hello_test.go b/pkg/protocol/handshake/message_server_hello_test.go index 14b713fcd..c4d6683a5 100644 --- a/pkg/protocol/handshake/message_server_hello_test.go +++ b/pkg/protocol/handshake/message_server_hello_test.go @@ -9,8 +9,8 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/extension" ) func TestHandshakeMessageServerHello(t *testing.T) { diff --git a/pkg/protocol/handshake/message_server_key_exchange.go b/pkg/protocol/handshake/message_server_key_exchange.go index 82abbe0d4..1edac45f9 100644 --- a/pkg/protocol/handshake/message_server_key_exchange.go +++ b/pkg/protocol/handshake/message_server_key_exchange.go @@ -6,10 +6,10 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/internal/ciphersuite/types" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" + "github.com/pion/dtls/v3/internal/ciphersuite/types" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" ) // MessageServerKeyExchange supports ECDH and PSK diff --git a/pkg/protocol/handshake/message_server_key_exchange_test.go b/pkg/protocol/handshake/message_server_key_exchange_test.go index 7e960ce03..fc4573cf3 100644 --- a/pkg/protocol/handshake/message_server_key_exchange_test.go +++ b/pkg/protocol/handshake/message_server_key_exchange_test.go @@ -7,10 +7,10 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/internal/ciphersuite/types" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" + "github.com/pion/dtls/v3/internal/ciphersuite/types" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" ) func TestHandshakeMessageServerKeyExchange(t *testing.T) { diff --git a/pkg/protocol/recordlayer/errors.go b/pkg/protocol/recordlayer/errors.go index 1c1898844..ba2b396b8 100644 --- a/pkg/protocol/recordlayer/errors.go +++ b/pkg/protocol/recordlayer/errors.go @@ -7,7 +7,7 @@ package recordlayer import ( "errors" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol" ) var ( diff --git a/pkg/protocol/recordlayer/header.go b/pkg/protocol/recordlayer/header.go index 66a1be810..0899d5a22 100644 --- a/pkg/protocol/recordlayer/header.go +++ b/pkg/protocol/recordlayer/header.go @@ -6,8 +6,8 @@ package recordlayer import ( "encoding/binary" - "github.com/pion/dtls/v2/internal/util" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/internal/util" + "github.com/pion/dtls/v3/pkg/protocol" ) // Header implements a TLS RecordLayer header diff --git a/pkg/protocol/recordlayer/inner_plaintext.go b/pkg/protocol/recordlayer/inner_plaintext.go index bbc94dd80..296475a6c 100644 --- a/pkg/protocol/recordlayer/inner_plaintext.go +++ b/pkg/protocol/recordlayer/inner_plaintext.go @@ -4,7 +4,7 @@ package recordlayer import ( - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol" "golang.org/x/crypto/cryptobyte" ) diff --git a/pkg/protocol/recordlayer/recordlayer.go b/pkg/protocol/recordlayer/recordlayer.go index 4acacf074..61e25a563 100644 --- a/pkg/protocol/recordlayer/recordlayer.go +++ b/pkg/protocol/recordlayer/recordlayer.go @@ -6,9 +6,9 @@ package recordlayer import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" ) // DTLS fixed size record layer header when Connection IDs are not in-use. diff --git a/pkg/protocol/recordlayer/recordlayer_test.go b/pkg/protocol/recordlayer/recordlayer_test.go index 760a73040..c568c9147 100644 --- a/pkg/protocol/recordlayer/recordlayer_test.go +++ b/pkg/protocol/recordlayer/recordlayer_test.go @@ -8,7 +8,7 @@ import ( "reflect" "testing" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol" ) func TestUDPDecode(t *testing.T) { diff --git a/resume_test.go b/resume_test.go index 00b291788..fa4ca0a4c 100644 --- a/resume_test.go +++ b/resume_test.go @@ -13,8 +13,8 @@ import ( "testing" "time" - "github.com/pion/dtls/v2/pkg/crypto/selfsign" - dtlsnet "github.com/pion/dtls/v2/pkg/net" + "github.com/pion/dtls/v3/pkg/crypto/selfsign" + dtlsnet "github.com/pion/dtls/v3/pkg/net" "github.com/pion/transport/v3/test" ) diff --git a/srtp_protection_profile.go b/srtp_protection_profile.go index 8b7e471f3..bc242095b 100644 --- a/srtp_protection_profile.go +++ b/srtp_protection_profile.go @@ -3,7 +3,7 @@ package dtls -import "github.com/pion/dtls/v2/pkg/protocol/extension" +import "github.com/pion/dtls/v3/pkg/protocol/extension" // SRTPProtectionProfile defines the parameters and options that are in effect for the SRTP processing // https://tools.ietf.org/html/rfc5764#section-4.1.2 diff --git a/state.go b/state.go index 178d937ea..27b1ebb31 100644 --- a/state.go +++ b/state.go @@ -8,10 +8,10 @@ import ( "encoding/gob" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol/handshake" "github.com/pion/transport/v3/replaydetector" ) From 2ed7caa12678227ea7d7fa6518d0194c182b447a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 22:55:45 +0000 Subject: [PATCH 116/146] Update module github.com/pion/transport/v3 to v3.0.6 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6ddc83232..1e48e6493 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.2 - github.com/pion/transport/v3 v3.0.5 + github.com/pion/transport/v3 v3.0.6 golang.org/x/crypto v0.24.0 golang.org/x/net v0.26.0 ) diff --git a/go.sum b/go.sum index f34fc2e62..9c20c4538 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport/v3 v3.0.5 h1:ofVrcbPNqVPuKaTO5AMFnFuJ1ZX7ElYiWzC5PCf9YVQ= -github.com/pion/transport/v3 v3.0.5/go.mod h1:HvJr2N/JwNJAfipsRleqwFoR3t/pWyHeZUs89v3+t5s= +github.com/pion/transport/v3 v3.0.6 h1:k1mQU06bmmX143qSWgXFqSH1KUJceQvIUuVH/K5ELWw= +github.com/pion/transport/v3 v3.0.6/go.mod h1:HvJr2N/JwNJAfipsRleqwFoR3t/pWyHeZUs89v3+t5s= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= From 7139e0e694277cf20f78e7528c4ce157ecd4ef88 Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Mon, 29 Jul 2024 09:45:27 -0400 Subject: [PATCH 117/146] Fix time units in example WithTimeout should be seconds not nanoseconds --- examples/listen/cid/main.go | 3 ++- examples/listen/psk/main.go | 3 ++- examples/listen/selfsign/main.go | 3 ++- examples/listen/verify-brute-force-protection/main.go | 2 +- examples/listen/verify/main.go | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/examples/listen/cid/main.go b/examples/listen/cid/main.go index 25cc3287d..7418d895b 100644 --- a/examples/listen/cid/main.go +++ b/examples/listen/cid/main.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "net" + "time" "github.com/pion/dtls/v3" "github.com/pion/dtls/v3/examples/util" @@ -57,7 +58,7 @@ func main() { // functions like `ConnectionState` etc. // Perform the handshake with a 30-second timeout - ctx, cancel := context.WithTimeout(context.Background(), 30) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) dtlsConn, ok := conn.(*dtls.Conn) if ok { util.Check(dtlsConn.HandshakeContext(ctx)) diff --git a/examples/listen/psk/main.go b/examples/listen/psk/main.go index 4fdcc838f..041b1fb4e 100644 --- a/examples/listen/psk/main.go +++ b/examples/listen/psk/main.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "net" + "time" "github.com/pion/dtls/v3" "github.com/pion/dtls/v3/examples/util" @@ -56,7 +57,7 @@ func main() { // functions like `ConnectionState` etc. // Perform the handshake with a 30-second timeout - ctx, cancel := context.WithTimeout(context.Background(), 30) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) dtlsConn, ok := conn.(*dtls.Conn) if ok { util.Check(dtlsConn.HandshakeContext(ctx)) diff --git a/examples/listen/selfsign/main.go b/examples/listen/selfsign/main.go index a73b1479c..2243d722e 100644 --- a/examples/listen/selfsign/main.go +++ b/examples/listen/selfsign/main.go @@ -9,6 +9,7 @@ import ( "crypto/tls" "fmt" "net" + "time" "github.com/pion/dtls/v3" "github.com/pion/dtls/v3/examples/util" @@ -57,7 +58,7 @@ func main() { // functions like `ConnectionState` etc. // Perform the handshake with a 30-second timeout - ctx, cancel := context.WithTimeout(context.Background(), 30) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) dtlsConn, ok := conn.(*dtls.Conn) if ok { util.Check(dtlsConn.HandshakeContext(ctx)) diff --git a/examples/listen/verify-brute-force-protection/main.go b/examples/listen/verify-brute-force-protection/main.go index aaa1a90ad..9bf950467 100644 --- a/examples/listen/verify-brute-force-protection/main.go +++ b/examples/listen/verify-brute-force-protection/main.go @@ -115,7 +115,7 @@ func main() { // *************** END Brute Force Attack protection END *************** // Perform the handshake with a 30-second timeout - ctx, cancel := context.WithTimeout(context.Background(), 30) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) dtlsConn, ok := conn.(*dtls.Conn) if ok { util.Check(dtlsConn.HandshakeContext(ctx)) diff --git a/examples/listen/verify/main.go b/examples/listen/verify/main.go index cb19ee605..7d7067a27 100644 --- a/examples/listen/verify/main.go +++ b/examples/listen/verify/main.go @@ -10,6 +10,7 @@ import ( "crypto/x509" "fmt" "net" + "time" "github.com/pion/dtls/v3" "github.com/pion/dtls/v3/examples/util" @@ -66,7 +67,7 @@ func main() { // functions like `ConnectionState` etc. // Perform the handshake with a 30-second timeout - ctx, cancel := context.WithTimeout(context.Background(), 30) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) dtlsConn, ok := conn.(*dtls.Conn) if ok { util.Check(dtlsConn.HandshakeContext(ctx)) From 7ab74fbfb566de0101334848016ff7cc2d2b0298 Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Mon, 29 Jul 2024 13:28:27 -0400 Subject: [PATCH 118/146] Add support for MKI in use_srtp Resolves #650 --- config.go | 4 ++ conn.go | 10 ++++ conn_test.go | 42 +++++++++----- flight0handler.go | 1 + flight1handler.go | 3 +- flight3handler.go | 1 + flight4bhandler.go | 3 +- flight4handler.go | 3 +- handshaker.go | 49 ++++++++-------- pkg/protocol/extension/errors.go | 15 ++--- pkg/protocol/extension/use_srtp.go | 27 +++++++-- pkg/protocol/extension/use_srtp_test.go | 74 +++++++++++++++++++++---- state.go | 10 ++-- 13 files changed, 174 insertions(+), 68 deletions(-) diff --git a/config.go b/config.go index 2fb241959..54a86c0ee 100644 --- a/config.go +++ b/config.go @@ -45,6 +45,10 @@ type Config struct { // Servers will assert that clients send one of these profiles and will respond as needed SRTPProtectionProfiles []SRTPProtectionProfile + // SRTPMasterKeyIdentifier value (if any) is sent via the use_srtp + // extension for Clients and Servers + SRTPMasterKeyIdentifier []byte + // ClientAuth determines the server's policy for // TLS Client Authentication. The default is NoClientCert. ClientAuth ClientAuthType diff --git a/conn.go b/conn.go index ce3234731..459cdcf59 100644 --- a/conn.go +++ b/conn.go @@ -164,6 +164,7 @@ func createConn(nextConn net.PacketConn, rAddr net.Addr, config *Config, isClien localSignatureSchemes: signatureSchemes, extendedMasterSecret: config.ExtendedMasterSecret, localSRTPProtectionProfiles: config.SRTPProtectionProfiles, + localSRTPMasterKeyIdentifier: config.SRTPMasterKeyIdentifier, serverName: serverName, supportedProtocols: config.SupportedProtocols, clientAuth: config.ClientAuth, @@ -426,6 +427,15 @@ func (c *Conn) SelectedSRTPProtectionProfile() (SRTPProtectionProfile, bool) { return profile, true } +// RemoteSRTPMasterKeyIdentifier returns the MasterKeyIdentifier value from the use_srtp +func (c *Conn) RemoteSRTPMasterKeyIdentifier() ([]byte, bool) { + if profile := c.state.getSRTPProtectionProfile(); profile == 0 { + return nil, false + } + + return c.state.remoteSRTPMasterKeyIdentifier, true +} + func (c *Conn) writePackets(ctx context.Context, pkts []*packet) error { c.lock.Lock() defer c.lock.Unlock() diff --git a/conn_test.go b/conn_test.go index 7192178a8..c66e03810 100644 --- a/conn_test.go +++ b/conn_test.go @@ -866,12 +866,14 @@ func TestSRTPConfiguration(t *testing.T) { defer report() for _, test := range []struct { - Name string - ClientSRTP []SRTPProtectionProfile - ServerSRTP []SRTPProtectionProfile - ExpectedProfile SRTPProtectionProfile - WantClientError error - WantServerError error + Name string + ClientSRTP []SRTPProtectionProfile + ServerSRTP []SRTPProtectionProfile + ClientSRTPMasterKeyIdentifier []byte + ServerSRTPMasterKeyIdentifier []byte + ExpectedProfile SRTPProtectionProfile + WantClientError error + WantServerError error }{ { Name: "No SRTP in use", @@ -882,12 +884,14 @@ func TestSRTPConfiguration(t *testing.T) { WantServerError: nil, }, { - Name: "SRTP both ends", - ClientSRTP: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}, - ServerSRTP: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}, - ExpectedProfile: SRTP_AES128_CM_HMAC_SHA1_80, - WantClientError: nil, - WantServerError: nil, + Name: "SRTP both ends", + ClientSRTP: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}, + ServerSRTP: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}, + ExpectedProfile: SRTP_AES128_CM_HMAC_SHA1_80, + ClientSRTPMasterKeyIdentifier: []byte("ClientSRTPMKI"), + ServerSRTPMasterKeyIdentifier: []byte("ServerSRTPMKI"), + WantClientError: nil, + WantServerError: nil, }, { Name: "SRTP client only", @@ -933,11 +937,11 @@ func TestSRTPConfiguration(t *testing.T) { c := make(chan result) go func() { - client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ClientSRTP}, true) + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ClientSRTP, SRTPMasterKeyIdentifier: test.ServerSRTPMasterKeyIdentifier}, true) c <- result{client, err} }() - server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ServerSRTP}, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ServerSRTP, SRTPMasterKeyIdentifier: test.ClientSRTPMasterKeyIdentifier}, true) if !errors.Is(err, test.WantServerError) { t.Errorf("TestSRTPConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantServerError, err) } @@ -969,6 +973,16 @@ func TestSRTPConfiguration(t *testing.T) { if actualServerSRTP != test.ExpectedProfile { t.Errorf("TestSRTPConfiguration: Server SRTPProtectionProfile Mismatch '%s': expected(%v) actual(%v)", test.Name, test.ExpectedProfile, actualServerSRTP) } + + actualServerMKI, _ := server.RemoteSRTPMasterKeyIdentifier() + if !bytes.Equal(actualServerMKI, test.ServerSRTPMasterKeyIdentifier) { + t.Errorf("TestSRTPConfiguration: Server SRTPMKI Mismatch '%s': expected(%v) actual(%v)", test.Name, test.ServerSRTPMasterKeyIdentifier, actualServerMKI) + } + + actualClientMKI, _ := res.c.RemoteSRTPMasterKeyIdentifier() + if !bytes.Equal(actualClientMKI, test.ClientSRTPMasterKeyIdentifier) { + t.Errorf("TestSRTPConfiguration: Client SRTPMKI Mismatch '%s': expected(%v) actual(%v)", test.Name, test.ClientSRTPMasterKeyIdentifier, actualClientMKI) + } } } diff --git a/flight0handler.go b/flight0handler.go index 77d403276..7bb528f1a 100644 --- a/flight0handler.go +++ b/flight0handler.go @@ -67,6 +67,7 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errServerNoMatchingSRTPProfile } state.setSRTPProtectionProfile(profile) + state.remoteSRTPMasterKeyIdentifier = e.MasterKeyIdentifier case *extension.UseExtendedMasterSecret: if cfg.extendedMasterSecret != DisableExtendedMasterSecret { state.extendedMasterSecret = true diff --git a/flight1handler.go b/flight1handler.go index 69019c91c..60215c084 100644 --- a/flight1handler.go +++ b/flight1handler.go @@ -91,7 +91,8 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha if len(cfg.localSRTPProtectionProfiles) > 0 { extensions = append(extensions, &extension.UseSRTP{ - ProtectionProfiles: cfg.localSRTPProtectionProfiles, + ProtectionProfiles: cfg.localSRTPProtectionProfiles, + MasterKeyIdentifier: cfg.localSRTPMasterKeyIdentifier, }) } diff --git a/flight3handler.go b/flight3handler.go index 39d9380cb..f27c01a7e 100644 --- a/flight3handler.go +++ b/flight3handler.go @@ -57,6 +57,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, errClientNoMatchingSRTPProfile } state.setSRTPProtectionProfile(profile) + state.remoteSRTPMasterKeyIdentifier = e.MasterKeyIdentifier case *extension.UseExtendedMasterSecret: if cfg.extendedMasterSecret != DisableExtendedMasterSecret { state.extendedMasterSecret = true diff --git a/flight4bhandler.go b/flight4bhandler.go index 71e7044cb..d87a1feee 100644 --- a/flight4bhandler.go +++ b/flight4bhandler.go @@ -61,7 +61,8 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha } if state.getSRTPProtectionProfile() != 0 { extensions = append(extensions, &extension.UseSRTP{ - ProtectionProfiles: []SRTPProtectionProfile{state.getSRTPProtectionProfile()}, + ProtectionProfiles: []SRTPProtectionProfile{state.getSRTPProtectionProfile()}, + MasterKeyIdentifier: cfg.localSRTPMasterKeyIdentifier, }) } diff --git a/flight4handler.go b/flight4handler.go index af8cf6b4b..5f8676888 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -230,7 +230,8 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha } if state.getSRTPProtectionProfile() != 0 { extensions = append(extensions, &extension.UseSRTP{ - ProtectionProfiles: []SRTPProtectionProfile{state.getSRTPProtectionProfile()}, + ProtectionProfiles: []SRTPProtectionProfile{state.getSRTPProtectionProfile()}, + MasterKeyIdentifier: cfg.localSRTPMasterKeyIdentifier, }) } if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate { diff --git a/handshaker.go b/handshaker.go index 0c2a43643..946cf4bcd 100644 --- a/handshaker.go +++ b/handshaker.go @@ -93,30 +93,31 @@ type handshakeFSM struct { } type handshakeConfig struct { - localPSKCallback PSKCallback - localPSKIdentityHint []byte - localCipherSuites []CipherSuite // Available CipherSuites - localSignatureSchemes []signaturehash.Algorithm // Available signature schemes - extendedMasterSecret ExtendedMasterSecretType // Policy for the Extended Master Support extension - localSRTPProtectionProfiles []SRTPProtectionProfile // Available SRTPProtectionProfiles, if empty no SRTP support - serverName string - supportedProtocols []string - clientAuth ClientAuthType // If we are a client should we request a client certificate - localCertificates []tls.Certificate - nameToCertificate map[string]*tls.Certificate - insecureSkipVerify bool - verifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error - verifyConnection func(*State) error - sessionStore SessionStore - rootCAs *x509.CertPool - clientCAs *x509.CertPool - initialRetransmitInterval time.Duration - disableRetransmitBackoff bool - customCipherSuites func() []CipherSuite - ellipticCurves []elliptic.Curve - insecureSkipHelloVerify bool - connectionIDGenerator func() []byte - helloRandomBytesGenerator func() [handshake.RandomBytesLength]byte + localPSKCallback PSKCallback + localPSKIdentityHint []byte + localCipherSuites []CipherSuite // Available CipherSuites + localSignatureSchemes []signaturehash.Algorithm // Available signature schemes + extendedMasterSecret ExtendedMasterSecretType // Policy for the Extended Master Support extension + localSRTPProtectionProfiles []SRTPProtectionProfile // Available SRTPProtectionProfiles, if empty no SRTP support + localSRTPMasterKeyIdentifier []byte + serverName string + supportedProtocols []string + clientAuth ClientAuthType // If we are a client should we request a client certificate + localCertificates []tls.Certificate + nameToCertificate map[string]*tls.Certificate + insecureSkipVerify bool + verifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error + verifyConnection func(*State) error + sessionStore SessionStore + rootCAs *x509.CertPool + clientCAs *x509.CertPool + initialRetransmitInterval time.Duration + disableRetransmitBackoff bool + customCipherSuites func() []CipherSuite + ellipticCurves []elliptic.Curve + insecureSkipHelloVerify bool + connectionIDGenerator func() []byte + helloRandomBytesGenerator func() [handshake.RandomBytesLength]byte onFlightState func(flightVal, handshakeState) log logging.LeveledLogger diff --git a/pkg/protocol/extension/errors.go b/pkg/protocol/extension/errors.go index 6b4c9229b..5999c96fe 100644 --- a/pkg/protocol/extension/errors.go +++ b/pkg/protocol/extension/errors.go @@ -11,11 +11,12 @@ import ( var ( // ErrALPNInvalidFormat is raised when the ALPN format is invalid - ErrALPNInvalidFormat = &protocol.FatalError{Err: errors.New("invalid alpn format")} //nolint:goerr113 - errALPNNoAppProto = &protocol.FatalError{Err: errors.New("no application protocol")} //nolint:goerr113 - errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 - errInvalidExtensionType = &protocol.FatalError{Err: errors.New("invalid extension type")} //nolint:goerr113 - errInvalidSNIFormat = &protocol.FatalError{Err: errors.New("invalid server name format")} //nolint:goerr113 - errInvalidCIDFormat = &protocol.FatalError{Err: errors.New("invalid connection ID format")} //nolint:goerr113 - errLengthMismatch = &protocol.InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113 + ErrALPNInvalidFormat = &protocol.FatalError{Err: errors.New("invalid alpn format")} //nolint:goerr113 + errALPNNoAppProto = &protocol.FatalError{Err: errors.New("no application protocol")} //nolint:goerr113 + errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 + errInvalidExtensionType = &protocol.FatalError{Err: errors.New("invalid extension type")} //nolint:goerr113 + errInvalidSNIFormat = &protocol.FatalError{Err: errors.New("invalid server name format")} //nolint:goerr113 + errInvalidCIDFormat = &protocol.FatalError{Err: errors.New("invalid connection ID format")} //nolint:goerr113 + errLengthMismatch = &protocol.InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113 + errMasterKeyIdentifierTooLarge = &protocol.FatalError{Err: errors.New("master key identifier is over 255 bytes")} //nolint:goerr113 ) diff --git a/pkg/protocol/extension/use_srtp.go b/pkg/protocol/extension/use_srtp.go index ea9f10872..6d5f54b23 100644 --- a/pkg/protocol/extension/use_srtp.go +++ b/pkg/protocol/extension/use_srtp.go @@ -3,7 +3,9 @@ package extension -import "encoding/binary" +import ( + "encoding/binary" +) const ( useSRTPHeaderSize = 6 @@ -14,7 +16,8 @@ const ( // // https://tools.ietf.org/html/rfc8422 type UseSRTP struct { - ProtectionProfiles []SRTPProtectionProfile + ProtectionProfiles []SRTPProtectionProfile + MasterKeyIdentifier []byte } // TypeValue returns the extension TypeValue @@ -27,15 +30,20 @@ func (u *UseSRTP) Marshal() ([]byte, error) { out := make([]byte, useSRTPHeaderSize) binary.BigEndian.PutUint16(out, uint16(u.TypeValue())) - binary.BigEndian.PutUint16(out[2:], uint16(2+(len(u.ProtectionProfiles)*2)+ /* MKI Length */ 1)) + binary.BigEndian.PutUint16(out[2:], uint16(2+(len(u.ProtectionProfiles)*2)+ /* MKI Length */ 1+len(u.MasterKeyIdentifier))) binary.BigEndian.PutUint16(out[4:], uint16(len(u.ProtectionProfiles)*2)) for _, v := range u.ProtectionProfiles { out = append(out, []byte{0x00, 0x00}...) binary.BigEndian.PutUint16(out[len(out)-2:], uint16(v)) } + if len(u.MasterKeyIdentifier) > 255 { + return nil, errMasterKeyIdentifierTooLarge + } + + out = append(out, byte(len(u.MasterKeyIdentifier))) + out = append(out, u.MasterKeyIdentifier...) - out = append(out, 0x00) /* MKI Length */ return out, nil } @@ -48,7 +56,8 @@ func (u *UseSRTP) Unmarshal(data []byte) error { } profileCount := int(binary.BigEndian.Uint16(data[4:]) / 2) - if supportedGroupsHeaderSize+(profileCount*2) > len(data) { + masterKeyIdentifierIndex := supportedGroupsHeaderSize + (profileCount * 2) + if masterKeyIdentifierIndex+1 > len(data) { return errLengthMismatch } @@ -58,5 +67,13 @@ func (u *UseSRTP) Unmarshal(data []byte) error { u.ProtectionProfiles = append(u.ProtectionProfiles, supportedProfile) } } + + masterKeyIdentifierLen := int(data[masterKeyIdentifierIndex]) + if masterKeyIdentifierIndex+masterKeyIdentifierLen >= len(data) { + return errLengthMismatch + } + + u.MasterKeyIdentifier = append([]byte{}, data[masterKeyIdentifierIndex+1:masterKeyIdentifierIndex+1+masterKeyIdentifierLen]...) + return nil } diff --git a/pkg/protocol/extension/use_srtp_test.go b/pkg/protocol/extension/use_srtp_test.go index 25b7b9e12..36e284cd4 100644 --- a/pkg/protocol/extension/use_srtp_test.go +++ b/pkg/protocol/extension/use_srtp_test.go @@ -4,20 +4,72 @@ package extension import ( + "errors" "reflect" "testing" ) func TestExtensionUseSRTP(t *testing.T) { - rawUseSRTP := []byte{0x00, 0x0e, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00} - parsedUseSRTP := &UseSRTP{ - ProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}, - } - - raw, err := parsedUseSRTP.Marshal() - if err != nil { - t.Error(err) - } else if !reflect.DeepEqual(raw, rawUseSRTP) { - t.Errorf("extensionUseSRTP marshal: got %#v, want %#v", raw, rawUseSRTP) - } + t.Run("No MasterKeyIdentifier", func(t *testing.T) { + rawUseSRTP := []byte{0x00, 0x0e, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00} + parsedUseSRTP := &UseSRTP{ + ProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}, + MasterKeyIdentifier: []byte{}, + } + + marshaled, err := parsedUseSRTP.Marshal() + if err != nil { + t.Error(err) + } else if !reflect.DeepEqual(marshaled, rawUseSRTP) { + t.Errorf("extensionUseSRTP marshal: got %#v, want %#v", marshaled, rawUseSRTP) + } + + unmarshaled := &UseSRTP{} + if err := unmarshaled.Unmarshal(rawUseSRTP); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(unmarshaled, parsedUseSRTP) { + t.Errorf("extensionUseSRTP unmarshal: got %#v, want %#v", unmarshaled, parsedUseSRTP) + } + }) + + t.Run("With MasterKeyIdentifier", func(t *testing.T) { + rawUseSRTP := []byte{0x00, 0x0e, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x01, 0x05, 0xA, 0xB, 0xC, 0xD, 0xE} + parsedUseSRTP := &UseSRTP{ + ProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}, + MasterKeyIdentifier: []byte{0xA, 0xB, 0xC, 0xD, 0xE}, + } + + marshaled, err := parsedUseSRTP.Marshal() + if err != nil { + t.Error(err) + } else if !reflect.DeepEqual(marshaled, rawUseSRTP) { + t.Errorf("extensionUseSRTP marshal: got %#v, want %#v", marshaled, rawUseSRTP) + } + + unmarshaled := &UseSRTP{} + if err := unmarshaled.Unmarshal(rawUseSRTP); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(unmarshaled, parsedUseSRTP) { + t.Errorf("extensionUseSRTP unmarshal: got %#v, want %#v", unmarshaled, parsedUseSRTP) + } + }) + + t.Run("Invalid Lengths", func(t *testing.T) { + unmarshaled := &UseSRTP{} + + if err := unmarshaled.Unmarshal([]byte{0x00, 0x0e, 0x00, 0x05, 0x00, 0x04, 0x00, 0x01, 0x00}); !errors.Is(errLengthMismatch, err) { + t.Error(err) + } + + if err := unmarshaled.Unmarshal([]byte{0x00, 0x0e, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x01, 0x01}); !errors.Is(errLengthMismatch, err) { + t.Error(err) + } + + if _, err := (&UseSRTP{ + ProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}, + MasterKeyIdentifier: make([]byte, 500), + }).Marshal(); !errors.Is(errMasterKeyIdentifierTooLarge, err) { + panic(err) + } + }) } diff --git a/state.go b/state.go index 27b1ebb31..f2d6df6f8 100644 --- a/state.go +++ b/state.go @@ -24,10 +24,12 @@ type State struct { cipherSuite CipherSuite // nil if a cipherSuite hasn't been chosen CipherSuiteID CipherSuiteID - srtpProtectionProfile atomic.Value // Negotiated SRTPProtectionProfile - PeerCertificates [][]byte - IdentityHint []byte - SessionID []byte + srtpProtectionProfile atomic.Value // Negotiated SRTPProtectionProfile + remoteSRTPMasterKeyIdentifier []byte + + PeerCertificates [][]byte + IdentityHint []byte + SessionID []byte // Connection Identifiers must be negotiated afresh on session resumption. // https://datatracker.ietf.org/doc/html/rfc9146#name-the-connection_id-extension From 23674bda0777e95e7349627c543dbaeae030a4a5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 00:08:53 +0000 Subject: [PATCH 119/146] Update module golang.org/x/crypto to v0.25.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1e48e6493..21a4ced7d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.6 - golang.org/x/crypto v0.24.0 + golang.org/x/crypto v0.25.0 golang.org/x/net v0.26.0 ) diff --git a/go.sum b/go.sum index 9c20c4538..89c5ca58d 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,7 @@ github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/transport/v3 v3.0.6 h1:k1mQU06bmmX143qSWgXFqSH1KUJceQvIUuVH/K5ELWw= github.com/pion/transport/v3 v3.0.6/go.mod h1:HvJr2N/JwNJAfipsRleqwFoR3t/pWyHeZUs89v3+t5s= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= From c5ab822f4a5869a18c42354ae75e1757513c3796 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:12:33 +0000 Subject: [PATCH 120/146] Update module golang.org/x/net to v0.27.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 21a4ced7d..f30378fc7 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.6 golang.org/x/crypto v0.25.0 - golang.org/x/net v0.26.0 + golang.org/x/net v0.27.0 ) go 1.19 diff --git a/go.sum b/go.sum index 89c5ca58d..507794a03 100644 --- a/go.sum +++ b/go.sum @@ -4,5 +4,5 @@ github.com/pion/transport/v3 v3.0.6 h1:k1mQU06bmmX143qSWgXFqSH1KUJceQvIUuVH/K5EL github.com/pion/transport/v3 v3.0.6/go.mod h1:HvJr2N/JwNJAfipsRleqwFoR3t/pWyHeZUs89v3+t5s= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= From 5a72b122c9e7a9c3feaf331dd133c3fb3fbe3a31 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:48:31 +0000 Subject: [PATCH 121/146] Update module github.com/pion/transport/v3 to v3.0.7 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f30378fc7..f9b061e70 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.2 - github.com/pion/transport/v3 v3.0.6 + github.com/pion/transport/v3 v3.0.7 golang.org/x/crypto v0.25.0 golang.org/x/net v0.27.0 ) diff --git a/go.sum b/go.sum index 507794a03..1437e4eea 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport/v3 v3.0.6 h1:k1mQU06bmmX143qSWgXFqSH1KUJceQvIUuVH/K5ELWw= -github.com/pion/transport/v3 v3.0.6/go.mod h1:HvJr2N/JwNJAfipsRleqwFoR3t/pWyHeZUs89v3+t5s= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= From f3e8a9e5489612d7add31cf6585661926bccf084 Mon Sep 17 00:00:00 2001 From: Daniel Adam <daniel.adam1922@protonmail.com> Date: Fri, 2 Aug 2024 16:15:21 +0200 Subject: [PATCH 122/146] Fix segfault in State::serialize method The method gets invoked from public API function Conn::ConnectionState but the cipherSuite pointer member might not have been initialized yet. Invoking ConnectionState too early causes a segfault. Issue is fixed by changing the return type of Conn::ConnectionState from State to (State, bool) and returning (State{}, false) if the cipherSuite has not been set. --- conn.go | 8 +++- conn_test.go | 115 ++++++++++++++++++++++++++++++++++++++++------ flight4handler.go | 12 ++++- flight5handler.go | 8 +++- resume_test.go | 10 +++- state.go | 28 ++++++++--- 6 files changed, 152 insertions(+), 29 deletions(-) diff --git a/conn.go b/conn.go index 459cdcf59..09fb5741a 100644 --- a/conn.go +++ b/conn.go @@ -411,10 +411,14 @@ func (c *Conn) Close() error { // ConnectionState returns basic DTLS details about the connection. // Note that this replaced the `Export` function of v1. -func (c *Conn) ConnectionState() State { +func (c *Conn) ConnectionState() (State, bool) { c.lock.RLock() defer c.lock.RUnlock() - return *c.state.clone() + stateClone, err := c.state.clone() + if err != nil { + return State{}, false + } + return *stateClone, true } // SelectedSRTPProtectionProfile returns the selected SRTPProtectionProfile diff --git a/conn_test.go b/conn_test.go index c66e03810..283021ffe 100644 --- a/conn_test.go +++ b/conn_test.go @@ -497,28 +497,40 @@ func TestExportKeyingMaterial(t *testing.T) { c.setLocalEpoch(0) c.setRemoteEpoch(0) - state := c.ConnectionState() + state, ok := c.ConnectionState() + if !ok { + t.Fatal("ConnectionState failed") + } _, err := state.ExportKeyingMaterial(exportLabel, nil, 0) if !errors.Is(err, errHandshakeInProgress) { t.Errorf("ExportKeyingMaterial when epoch == 0: expected '%s' actual '%s'", errHandshakeInProgress, err) } c.setLocalEpoch(1) - state = c.ConnectionState() + state, ok = c.ConnectionState() + if !ok { + t.Fatal("ConnectionState failed") + } _, err = state.ExportKeyingMaterial(exportLabel, []byte{0x00}, 0) if !errors.Is(err, errContextUnsupported) { t.Errorf("ExportKeyingMaterial with context: expected '%s' actual '%s'", errContextUnsupported, err) } for k := range invalidKeyingLabels() { - state = c.ConnectionState() + state, ok = c.ConnectionState() + if !ok { + t.Fatal("ConnectionState failed") + } _, err = state.ExportKeyingMaterial(k, nil, 0) if !errors.Is(err, errReservedExportKeyingMaterial) { t.Errorf("ExportKeyingMaterial reserved label: expected '%s' actual '%s'", errReservedExportKeyingMaterial, err) } } - state = c.ConnectionState() + state, ok = c.ConnectionState() + if !ok { + t.Fatal("ConnectionState failed") + } keyingMaterial, err := state.ExportKeyingMaterial(exportLabel, nil, 10) if err != nil { t.Errorf("ExportKeyingMaterial as server: unexpected error '%s'", err) @@ -527,7 +539,10 @@ func TestExportKeyingMaterial(t *testing.T) { } c.state.isClient = true - state = c.ConnectionState() + state, ok = c.ConnectionState() + if !ok { + t.Fatal("ConnectionState failed") + } keyingMaterial, err = state.ExportKeyingMaterial(exportLabel, nil, 10) if err != nil { t.Errorf("ExportKeyingMaterial as server: unexpected error '%s'", err) @@ -669,7 +684,11 @@ func TestPSK(t *testing.T) { t.Fatalf("TestPSK: Server failed(%v)", err) } - actualPSKIdentityHint := server.ConnectionState().IdentityHint + state, ok := server.ConnectionState() + if !ok { + t.Fatalf("TestPSK: Server ConnectionState failed") + } + actualPSKIdentityHint := state.IdentityHint if !bytes.Equal(actualPSKIdentityHint, test.ClientIdentity) { t.Errorf("TestPSK: Server ClientPSKIdentity Mismatch '%s': expected(%v) actual(%v)", test.Name, test.ClientIdentity, actualPSKIdentityHint) } @@ -1194,7 +1213,11 @@ func TestClientCertificate(t *testing.T) { t.Errorf("Client failed(%v)", res.err) } - actualClientCert := server.ConnectionState().PeerCertificates + state, ok := server.ConnectionState() + if !ok { + t.Error("Server connection state not available") + } + actualClientCert := state.PeerCertificates if tt.serverCfg.ClientAuth == RequireAnyClientCert || tt.serverCfg.ClientAuth == RequireAndVerifyClientCert { if actualClientCert == nil { t.Errorf("Client did not provide a certificate") @@ -1221,7 +1244,11 @@ func TestClientCertificate(t *testing.T) { } } - actualServerCert := res.c.ConnectionState().PeerCertificates + clientState, ok := res.c.ConnectionState() + if !ok { + t.Error("Client connection state not available") + } + actualServerCert := clientState.PeerCertificates if actualServerCert == nil { t.Errorf("Server did not provide a certificate") } @@ -2889,8 +2916,12 @@ func TestSessionResume(t *testing.T) { t.Fatalf("TestSessionResume: Server failed(%v)", err) } - actualSessionID := server.ConnectionState().SessionID - actualMasterSecret := server.ConnectionState().masterSecret + state, ok := server.ConnectionState() + if !ok { + t.Fatal("TestSessionResume: ConnectionState failed") + } + actualSessionID := state.SessionID + actualMasterSecret := state.masterSecret if !bytes.Equal(actualSessionID, id) { t.Errorf("TestSessionResumetion: SessionID Mismatch: expected(%v) actual(%v)", id, actualSessionID) } @@ -2940,8 +2971,12 @@ func TestSessionResume(t *testing.T) { t.Fatalf("TestSessionResumetion: Server failed(%v)", err) } - actualSessionID := server.ConnectionState().SessionID - actualMasterSecret := server.ConnectionState().masterSecret + state, ok := server.ConnectionState() + if !ok { + t.Fatal("TestSessionResumetion: ConnectionState failed") + } + actualSessionID := state.SessionID + actualMasterSecret := state.masterSecret ss, _ := s2.Get(actualSessionID) if !bytes.Equal(actualMasterSecret, ss.Secret) { t.Errorf("TestSessionResumetion: masterSecret Mismatch: expected(%v) actual(%v)", ss.Secret, actualMasterSecret) @@ -3071,8 +3106,8 @@ func TestCipherSuiteMatchesCertificateType(t *testing.T) { t.Fatal(err) } else if err := c.Close(); err != nil { t.Fatal(err) - } else if c.ConnectionState().cipherSuite.ID() != test.expectedCipher { - t.Fatalf("Expected(%s) and Actual(%s) CipherSuite do not match", test.expectedCipher, c.ConnectionState().cipherSuite.ID()) + } else if state, ok := c.ConnectionState(); !ok || state.cipherSuite.ID() != test.expectedCipher { + t.Fatalf("Expected(%s) and Actual(%s) CipherSuite do not match", test.expectedCipher, state.cipherSuite.ID()) } }) } @@ -3527,3 +3562,55 @@ func TestFragmentBuffer_Retransmission(t *testing.T) { t.Fatal("fragment should be retransmission") } } + +func TestConnectionState(t *testing.T) { + ca, cb := dpipe.Pipe() + + // Setup client + clientCfg := &Config{} + clientCert, err := selfsign.GenerateSelfSigned() + if err != nil { + t.Fatal(err) + } + clientCfg.Certificates = []tls.Certificate{clientCert} + clientCfg.InsecureSkipVerify = true + client, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), clientCfg) + if err != nil { + t.Fatal(err) + } + defer func() { + _ = client.Close() + }() + + _, ok := client.ConnectionState() + if ok { + t.Fatal("ConnectionState should be nil") + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + c := make(chan error) + go func() { + errC := client.HandshakeContext(ctx) + c <- errC + }() + + // Setup server + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{}, true) + if err != nil { + t.Fatal(err) + } + defer func() { + _ = server.Close() + }() + + err = <-c + if err != nil { + t.Fatal(err) + } + + _, ok = client.ConnectionState() + if !ok { + t.Fatal("ConnectionState should not be nil") + } +} diff --git a/flight4handler.go b/flight4handler.go index 5f8676888..7e4ae12f1 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -183,7 +183,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 { + stateClone, err := state.clone() + if err != nil { + return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err + } + if err := cfg.verifyConnection(stateClone); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err } } @@ -210,7 +214,11 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh // go to flight6 } if cfg.verifyConnection != nil { - if err := cfg.verifyConnection(state.clone()); err != nil { + stateClone, err := state.clone() + if err != nil { + return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err + } + if err := cfg.verifyConnection(stateClone); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err } } diff --git a/flight5handler.go b/flight5handler.go index 2f6e7b3ee..7e940cdc9 100644 --- a/flight5handler.go +++ b/flight5handler.go @@ -344,8 +344,12 @@ func initializeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCo } } if cfg.verifyConnection != nil { - if err = cfg.verifyConnection(state.clone()); err != nil { - return &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err + stateClone, errC := state.clone() + if errC != nil { + return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errC + } + if errC = cfg.verifyConnection(stateClone); errC != nil { + return &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, errC } } diff --git a/resume_test.go b/resume_test.go index fa4ca0a4c..4f79adb3f 100644 --- a/resume_test.go +++ b/resume_test.go @@ -18,7 +18,10 @@ import ( "github.com/pion/transport/v3/test" ) -var errMessageMissmatch = errors.New("messages missmatch") +var ( + errMessageMissmatch = errors.New("messages missmatch") + errInvalidConnectionState = errors.New("failed to get connection state") +) func TestResumeClient(t *testing.T) { DoTestResume(t, Client, Server) @@ -120,7 +123,10 @@ func DoTestResume(t *testing.T, newLocal, newRemote func(net.PacketConn, net.Add } // Serialize and deserialize state - state := local.ConnectionState() + state, ok := local.ConnectionState() + if !ok { + fatal(t, errChan, errInvalidConnectionState) + } var b []byte b, err = state.MarshalBinary() if err != nil { diff --git a/state.go b/state.go index f2d6df6f8..f1afb857d 100644 --- a/state.go +++ b/state.go @@ -6,6 +6,7 @@ package dtls import ( "bytes" "encoding/gob" + "errors" "sync/atomic" "github.com/pion/dtls/v3/pkg/crypto/elliptic" @@ -87,15 +88,25 @@ type serializedState struct { NegotiatedProtocol string } -func (s *State) clone() *State { - serialized := s.serialize() +var errCipherSuiteNotSet = &InternalError{Err: errors.New("cipher suite not set")} //nolint:goerr113 + +func (s *State) clone() (*State, error) { + serialized, err := s.serialize() + if err != nil { + return nil, err + } state := &State{} state.deserialize(*serialized) - return state + return state, err } -func (s *State) serialize() *serializedState { +func (s *State) serialize() (*serializedState, error) { + if s.cipherSuite == nil { + return nil, errCipherSuiteNotSet + } + cipherSuiteID := uint16(s.cipherSuite.ID()) + // Marshal random values localRnd := s.localRandom.MarshalFixed() remoteRnd := s.remoteRandom.MarshalFixed() @@ -104,7 +115,7 @@ func (s *State) serialize() *serializedState { return &serializedState{ LocalEpoch: s.getLocalEpoch(), RemoteEpoch: s.getRemoteEpoch(), - CipherSuiteID: uint16(s.cipherSuite.ID()), + CipherSuiteID: cipherSuiteID, MasterSecret: s.masterSecret, SequenceNumber: atomic.LoadUint64(&s.localSequenceNumber[epoch]), LocalRandom: localRnd, @@ -117,7 +128,7 @@ func (s *State) serialize() *serializedState { RemoteConnectionID: s.remoteConnectionID, IsClient: s.isClient, NegotiatedProtocol: s.NegotiatedProtocol, - } + }, nil } func (s *State) deserialize(serialized serializedState) { @@ -187,7 +198,10 @@ func (s *State) initCipherSuite() error { // MarshalBinary is a binary.BinaryMarshaler.MarshalBinary implementation func (s *State) MarshalBinary() ([]byte, error) { - serialized := s.serialize() + serialized, err := s.serialize() + if err != nil { + return nil, err + } var buf bytes.Buffer enc := gob.NewEncoder(&buf) From e20b1620594ce408a20636f455b00ed9a3d69512 Mon Sep 17 00:00:00 2001 From: Daniel Adam <daniel.adam1922@protonmail.com> Date: Tue, 6 Aug 2024 17:06:12 +0200 Subject: [PATCH 123/146] Fix multiple calls to Handshake Handshake are synchronized by a mutex, but there is a panicing scenario when the first handshake fails. --- conn.go | 8 ++-- conn_test.go | 48 +++++++++++++++++++ .../verify-brute-force-protection/main.go | 14 +++--- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/conn.go b/conn.go index 09fb5741a..c0c340731 100644 --- a/conn.go +++ b/conn.go @@ -1055,9 +1055,11 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh }() go func() { defer func() { - // Escaping read loop. - // It's safe to close decrypted channnel now. - close(c.decrypted) + if c.isHandshakeCompletedSuccessfully() { + // Escaping read loop. + // It's safe to close decrypted channnel now. + close(c.decrypted) + } // Force stop handshaker when the underlying connection is closed. cancel() diff --git a/conn_test.go b/conn_test.go index 283021ffe..44fddbdb8 100644 --- a/conn_test.go +++ b/conn_test.go @@ -3614,3 +3614,51 @@ func TestConnectionState(t *testing.T) { t.Fatal("ConnectionState should not be nil") } } + +func TestMultiHandshake(t *testing.T) { + defer test.CheckRoutines(t)() + defer test.TimeOut(time.Second * 10).Stop() + + ca, cb := dpipe.Pipe() + serverCert, err := selfsign.GenerateSelfSigned() + if err != nil { + t.Fatal(err) + } + server, err := Server(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ + Certificates: []tls.Certificate{serverCert}, + }) + if err != nil { + t.Fatal(err) + } + + go func() { + _ = server.Handshake() + }() + + clientCert, err := selfsign.GenerateSelfSigned() + if err != nil { + t.Fatal(err) + } + client, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ + Certificates: []tls.Certificate{clientCert}, + }) + if err != nil { + t.Fatal(err) + } + + if err = client.Handshake(); err == nil { + t.Fatal(err) + } + + if err = client.Handshake(); err == nil { + t.Fatal(err) + } + + if err = server.Close(); err != nil { + t.Fatal(err) + } + + if err = client.Close(); err != nil { + t.Fatal(err) + } +} diff --git a/examples/listen/verify-brute-force-protection/main.go b/examples/listen/verify-brute-force-protection/main.go index 9bf950467..606179b34 100644 --- a/examples/listen/verify-brute-force-protection/main.go +++ b/examples/listen/verify-brute-force-protection/main.go @@ -27,9 +27,11 @@ func main() { // // ************ Variables used to implement a basic Brute Force Attack protection ************* - var attempts = make(map[string]int) // Map of attempts for each IP address. - var attemptsMutex sync.Mutex // Mutex for the map of attempts. - var attemptsCleaner = time.Now() // Time to be able to clean the map of attempts every X minutes. + var ( + attempts = make(map[string]int) // Map of attempts for each IP address. + attemptsMutex sync.Mutex // Mutex for the map of attempts. + attemptsCleaner = time.Now() // Time to be able to clean the map of attempts every X minutes. + ) certificate, err := util.LoadKeyAndCertificate("examples/certificates/server.pem", "examples/certificates/server.pub.pem") @@ -68,9 +70,9 @@ func main() { } } // Check if the IP address is in the map, and the IP address has exceeded the limit (Brute Force Attack protection) - attemptIP := addr.(*net.UDPAddr).IP.String() + attemptIP := addr.(*net.UDPAddr).IP.String() //nolint if attempts[attemptIP] > 10 { - return fmt.Errorf("too many attempts from this IP address") + return fmt.Errorf("too many attempts from this IP address") //nolint } // Here I increment the number of attempts for this IP address (Brute Force Attack protection) attempts[attemptIP]++ @@ -105,7 +107,7 @@ func main() { // *************** Brute Force Attack protection *************** // Here I decrease the number of attempts for this IP address attemptsMutex.Lock() - attemptIP := conn.(*dtls.Conn).RemoteAddr().(*net.UDPAddr).IP.String() + attemptIP := conn.(*dtls.Conn).RemoteAddr().(*net.UDPAddr).IP.String() //nolint attempts[attemptIP]-- // If the number of attempts for this IP address is 0, I delete the IP address from the map if attempts[attemptIP] == 0 { From fd18984005d282752cfc8b0a654a67aac82fe331 Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Mon, 12 Aug 2024 11:45:29 -0400 Subject: [PATCH 124/146] Fix pkg.go.dev link New major version --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index aa0bbc787..fa00c95d8 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ <a href="https://pion.ly/slack"><img src="https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen" alt="Slack Widget"></a> <br> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/pion/dtls/test.yaml"> - <a href="https://pkg.go.dev/github.com/pion/dtls/v2"><img src="https://pkg.go.dev/badge/github.com/pion/dtls/v2.svg" alt="Go Reference"></a> + <a href="https://pkg.go.dev/github.com/pion/dtls/v3"><img src="https://pkg.go.dev/badge/github.com/pion/dtls/v3.svg" alt="Go Reference"></a> <a href="https://codecov.io/gh/pion/dtls"><img src="https://codecov.io/gh/pion/dtls/branch/master/graph/badge.svg" alt="Coverage Status"></a> - <a href="https://goreportcard.com/report/github.com/pion/dtls/v2"><img src="https://goreportcard.com/badge/github.com/pion/dtls/v2" alt="Go Report Card"></a> + <a href="https://goreportcard.com/report/github.com/pion/dtls/v3"><img src="https://goreportcard.com/badge/github.com/pion/dtls/v3" alt="Go Report Card"></a> <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a> </p> <br> From f6ecbc2b1621b17f4ecc44e08401ad55df1df71d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 22:13:34 +0000 Subject: [PATCH 125/146] Update docker.io/library/golang Docker tag to v1.23 Generated by renovateBot --- e2e/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/Dockerfile b/e2e/Dockerfile index 0df773d91..9ad4b00ee 100644 --- a/e2e/Dockerfile +++ b/e2e/Dockerfile @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> # SPDX-License-Identifier: MIT -FROM docker.io/library/golang:1.22-bullseye +FROM docker.io/library/golang:1.23-bullseye COPY . /go/src/github.com/pion/dtls WORKDIR /go/src/github.com/pion/dtls/e2e From 032d60cd97a035a0231940557da954a0b6444725 Mon Sep 17 00:00:00 2001 From: Pion <59523206+pionbot@users.noreply.github.com> Date: Fri, 16 Aug 2024 15:16:28 +0000 Subject: [PATCH 126/146] Update CI configs to v0.11.15 Update lint scripts and CI configs. --- .github/workflows/test.yaml | 6 +++--- .golangci.yml | 8 ++++---- internal/net/buffer_test.go | 6 +++--- pkg/crypto/ccm/ccm.go | 10 +++++----- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 08e4272a8..b02428931 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -23,7 +23,7 @@ jobs: uses: pion/.goassets/.github/workflows/test.reusable.yml@master strategy: matrix: - go: ["1.22", "1.21"] # auto-update/supported-go-version-list + go: ["1.23", "1.22"] # auto-update/supported-go-version-list fail-fast: false with: go-version: ${{ matrix.go }} @@ -33,7 +33,7 @@ jobs: uses: pion/.goassets/.github/workflows/test-i386.reusable.yml@master strategy: matrix: - go: ["1.22", "1.21"] # auto-update/supported-go-version-list + go: ["1.23", "1.22"] # auto-update/supported-go-version-list fail-fast: false with: go-version: ${{ matrix.go }} @@ -41,5 +41,5 @@ jobs: test-wasm: uses: pion/.goassets/.github/workflows/test-wasm.reusable.yml@master with: - go-version: "1.22" # auto-update/latest-go-version + go-version: "1.23" # auto-update/latest-go-version secrets: inherit diff --git a/.golangci.yml b/.golangci.yml index e06de4d3c..a3235bec2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,6 +1,9 @@ # SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> # SPDX-License-Identifier: MIT +run: + timeout: 5m + linters-settings: govet: enable: @@ -48,7 +51,7 @@ linters: - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions + - err113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern @@ -83,17 +86,14 @@ linters: - depguard # Go linter that checks if package imports are in a list of acceptable packages - containedctx # containedctx is a linter that detects struct contained context.Context field - cyclop # checks function and package cyclomatic complexity - - exhaustivestruct # Checks if all struct's fields are initialized - funlen # Tool for detection of long functions - gocyclo # Computes and checks the cyclomatic complexity of functions - godot # Check if comments end in a period - gomnd # An analyzer to detect magic numbers. - - ifshort # Checks that your code uses short syntax for if-statements whenever possible - ireturn # Accept Interfaces, Return Concrete Types - lll # Reports long lines - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity diff --git a/internal/net/buffer_test.go b/internal/net/buffer_test.go index cf90d270f..e416dde53 100644 --- a/internal/net/buffer_test.go +++ b/internal/net/buffer_test.go @@ -125,7 +125,7 @@ func TestBuffer(t *testing.T) { equalUDPAddr(t, addr, raddr) // Until EOF. - if _, _, err = buffer.ReadFrom(packet); !errors.Is(io.EOF, err) { + if _, _, err = buffer.ReadFrom(packet); !errors.Is(err, io.EOF) { t.Fatalf("Unexpected err %v wanted io.EOF", err) } } @@ -148,7 +148,7 @@ func TestShortBuffer(t *testing.T) { packet := make([]byte, 3) var raddr net.Addr n, raddr, err = buffer.ReadFrom(packet) - if !errors.Is(io.ErrShortBuffer, err) { + if !errors.Is(err, io.ErrShortBuffer) { t.Fatalf("Unexpected err %v wanted io.ErrShortBuffer", err) } equalUDPAddr(t, nil, raddr) @@ -251,7 +251,7 @@ func TestBufferAsync(t *testing.T) { equalUDPAddr(t, addr, raddr) _, _, readErr := buffer.ReadFrom(packet) - if !errors.Is(io.EOF, readErr) { + if !errors.Is(readErr, io.EOF) { done <- fmt.Sprintf("Unexpected err %v wanted io.EOF", readErr) } else { close(done) diff --git a/pkg/crypto/ccm/ccm.go b/pkg/crypto/ccm/ccm.go index d6e6fc479..73476f219 100644 --- a/pkg/crypto/ccm/ccm.go +++ b/pkg/crypto/ccm/ccm.go @@ -74,14 +74,14 @@ func (c *ccm) Overhead() int { return int(c.M) } func (c *ccm) MaxLength() int { return maxlen(c.L, c.Overhead()) } func maxlen(l uint8, tagsize int) int { - max := (uint64(1) << (8 * l)) - 1 - if m64 := uint64(math.MaxInt64) - uint64(tagsize); l > 8 || max > m64 { - max = m64 // The maximum lentgh on a 64bit arch + mLen := (uint64(1) << (8 * l)) - 1 + if m64 := uint64(math.MaxInt64) - uint64(tagsize); l > 8 || mLen > m64 { + mLen = m64 // The maximum lentgh on a 64bit arch } - if max != uint64(int(max)) { + if mLen != uint64(int(mLen)) { return math.MaxInt32 - tagsize // We have only 32bit int's } - return int(max) + return int(mLen) } // MaxNonceLength returns the maximum nonce length for a given plaintext length. From 1a023506fc9e0de3f5078aee5225c21063e775e4 Mon Sep 17 00:00:00 2001 From: Daniel Adam <daniel.adam1922@protonmail.com> Date: Wed, 21 Aug 2024 10:11:21 +0200 Subject: [PATCH 127/146] Fix race between Conn.Close and Conn.Handshake --- conn.go | 40 ++++++++++++++++++++++++++++++---------- conn_test.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/conn.go b/conn.go index c0c340731..26c56f2e0 100644 --- a/conn.go +++ b/conn.go @@ -74,13 +74,13 @@ type Conn struct { handshakeCompletedSuccessfully atomic.Value handshakeMutex sync.Mutex + handshakeDone chan struct{} encryptedPackets []addrPkt connectionClosedByUser bool closeLock sync.Mutex closed *closer.Closer - handshakeLoopsFinished sync.WaitGroup readDeadline *deadline.Deadline writeDeadline *deadline.Deadline @@ -256,6 +256,12 @@ func (c *Conn) HandshakeContext(ctx context.Context) error { return nil } + handshakeDone := make(chan struct{}) + defer close(handshakeDone) + c.closeLock.Lock() + c.handshakeDone = handshakeDone + c.closeLock.Unlock() + // 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. @@ -405,7 +411,12 @@ func (c *Conn) Write(p []byte) (int, error) { // Close closes the connection. func (c *Conn) Close() error { err := c.close(true) //nolint:contextcheck - c.handshakeLoopsFinished.Wait() + c.closeLock.Lock() + handshakeDone := c.handshakeDone + c.closeLock.Unlock() + if handshakeDone != nil { + <-handshakeDone + } return err } @@ -1026,7 +1037,6 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh done := make(chan struct{}) ctxRead, cancelRead := context.WithCancel(context.Background()) - c.cancelHandshakeReader = cancelRead cfg.onFlightState = func(_ flightVal, s handshakeState) { if s == handshakeFinished && !c.isHandshakeCompletedSuccessfully() { c.setHandshakeCompletedSuccessfully() @@ -1035,16 +1045,21 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh } ctxHs, cancel := context.WithCancel(context.Background()) + + c.closeLock.Lock() c.cancelHandshaker = cancel + c.cancelHandshakeReader = cancelRead + c.closeLock.Unlock() firstErr := make(chan error, 1) - c.handshakeLoopsFinished.Add(2) + var handshakeLoopsFinished sync.WaitGroup + handshakeLoopsFinished.Add(2) // Handshake routine should be live until close. // The other party may request retransmission of the last flight to cope with packet drop. go func() { - defer c.handshakeLoopsFinished.Done() + defer handshakeLoopsFinished.Done() err := c.fsm.Run(ctxHs, c, initialState) if !errors.Is(err, context.Canceled) { select { @@ -1064,7 +1079,7 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh // Force stop handshaker when the underlying connection is closed. cancel() }() - defer c.handshakeLoopsFinished.Done() + defer handshakeLoopsFinished.Done() for { if err := c.readAndBuffer(ctxRead); err != nil { var e *alertError @@ -1123,12 +1138,12 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh case err := <-firstErr: cancelRead() cancel() - c.handshakeLoopsFinished.Wait() + handshakeLoopsFinished.Wait() return c.translateHandshakeCtxError(err) case <-ctx.Done(): cancelRead() cancel() - c.handshakeLoopsFinished.Wait() + handshakeLoopsFinished.Wait() return c.translateHandshakeCtxError(ctx.Err()) case <-done: return nil @@ -1146,8 +1161,13 @@ func (c *Conn) translateHandshakeCtxError(err error) error { } func (c *Conn) close(byUser bool) error { - c.cancelHandshaker() - c.cancelHandshakeReader() + c.closeLock.Lock() + cancelHandshaker := c.cancelHandshaker + cancelHandshakeReader := c.cancelHandshakeReader + c.closeLock.Unlock() + + cancelHandshaker() + cancelHandshakeReader() if c.isHandshakeCompletedSuccessfully() && byUser { // Discard error from notify() to return non-error on the first user call of Close() diff --git a/conn_test.go b/conn_test.go index 44fddbdb8..9edb3aee0 100644 --- a/conn_test.go +++ b/conn_test.go @@ -3662,3 +3662,54 @@ func TestMultiHandshake(t *testing.T) { t.Fatal(err) } } + +func TestCloseDuringHandshake(t *testing.T) { + defer test.CheckRoutines(t)() + defer test.TimeOut(time.Second * 10).Stop() + + serverCert, err := selfsign.GenerateSelfSigned() + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 100; i++ { + _, cb := dpipe.Pipe() + server, err := Server(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ + Certificates: []tls.Certificate{serverCert}, + }) + if err != nil { + t.Fatal(err) + } + + waitChan := make(chan struct{}) + go func() { + close(waitChan) + _ = server.Handshake() + }() + + <-waitChan + if err = server.Close(); err != nil { + t.Fatal(err) + } + } +} + +func TestCloseWithoutHandshake(t *testing.T) { + defer test.CheckRoutines(t)() + defer test.TimeOut(time.Second * 10).Stop() + + serverCert, err := selfsign.GenerateSelfSigned() + if err != nil { + t.Fatal(err) + } + _, cb := dpipe.Pipe() + server, err := Server(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ + Certificates: []tls.Certificate{serverCert}, + }) + if err != nil { + t.Fatal(err) + } + if err = server.Close(); err != nil { + t.Fatal(err) + } +} From e193dc2e8ad58190d396122230f067da0e6c22cc Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Mon, 26 Aug 2024 11:28:11 -0400 Subject: [PATCH 128/146] Update go.mod version to 1.20 Relates to pion/webrtc#2869 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index f9b061e70..0bafa07f1 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,4 @@ require ( golang.org/x/net v0.27.0 ) -go 1.19 +go 1.20 From f13eec1209dec3135f7e8f32e7cfd51c587106f4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 00:02:15 +0000 Subject: [PATCH 129/146] Update module golang.org/x/crypto to v0.26.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0bafa07f1..f0576efcd 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.7 - golang.org/x/crypto v0.25.0 + golang.org/x/crypto v0.26.0 golang.org/x/net v0.27.0 ) diff --git a/go.sum b/go.sum index 1437e4eea..5f2b0c0a5 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,7 @@ github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= From 07903697a77065b5ccd75e4ff8821a7799e9d23f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 02:22:08 +0000 Subject: [PATCH 130/146] Update module golang.org/x/net to v0.28.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f0576efcd..6ee427d9e 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.7 golang.org/x/crypto v0.26.0 - golang.org/x/net v0.27.0 + golang.org/x/net v0.28.0 ) go 1.20 diff --git a/go.sum b/go.sum index 5f2b0c0a5..4ef939d86 100644 --- a/go.sum +++ b/go.sum @@ -4,5 +4,5 @@ github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1 github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= From 0be603adb705d3c95d7a0377585ecaf1b19a9cc7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:45:10 +0000 Subject: [PATCH 131/146] Update module golang.org/x/crypto to v0.27.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6ee427d9e..e0a90ae3d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.7 - golang.org/x/crypto v0.26.0 + golang.org/x/crypto v0.27.0 golang.org/x/net v0.28.0 ) diff --git a/go.sum b/go.sum index 4ef939d86..d3304399e 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,7 @@ github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= From d7f5fee0dff3d752088ccb09f5c23aab828db18b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 03:55:06 +0000 Subject: [PATCH 132/146] Update module golang.org/x/net to v0.29.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e0a90ae3d..a730cba71 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.7 golang.org/x/crypto v0.27.0 - golang.org/x/net v0.28.0 + golang.org/x/net v0.29.0 ) go 1.20 diff --git a/go.sum b/go.sum index d3304399e..e39c9f483 100644 --- a/go.sum +++ b/go.sum @@ -4,5 +4,5 @@ github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1 github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= From 98a05d681d3affae2d055a70d3273cbb35425b5a Mon Sep 17 00:00:00 2001 From: Sean DuBois <sean@siobud.com> Date: Sat, 5 Oct 2024 23:35:34 -0400 Subject: [PATCH 133/146] Fix incorrect client retransmissions introduced by ec76652f161d0. If Client has gone to finished we know that server sent Finished. No reason to ever re-send messages. Resolves pion/webrtc#2909 --- handshaker.go | 6 +++++- handshaker_test.go | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/handshaker.go b/handshaker.go index 946cf4bcd..5e16808a9 100644 --- a/handshaker.go +++ b/handshaker.go @@ -338,7 +338,11 @@ func (s *handshakeFSM) finish(ctx context.Context, c flightConn) (handshakeState select { case state := <-c.recvHandshake(): close(state.done) - return handshakeSending, nil + if s.state.isClient { + return handshakeFinished, nil + } else { + return handshakeSending, nil + } case <-ctx.Done(): return handshakeErrored, ctx.Err() } diff --git a/handshaker_test.go b/handshaker_test.go index 39b7ff20c..de82a571a 100644 --- a/handshaker_test.go +++ b/handshaker_test.go @@ -225,8 +225,8 @@ func TestHandshaker(t *testing.T) { t.Errorf("Client is not finished") } // there should be no `Finished` last retransmit from client - if cntClientFinishedLastRetransmit != 4 { - t.Errorf("Number of client finished last retransmit is wrong, expected: %d times, got: %d times", 4, cntClientFinishedLastRetransmit) + if cntClientFinishedLastRetransmit != 0 { + t.Errorf("Number of client finished last retransmit is wrong, expected: %d times, got: %d times", 0, cntClientFinishedLastRetransmit) } if cntServerFinished < 1 { t.Errorf("Number of server finished is wrong, expected: at least %d times, got: %d times", 1, cntServerFinished) From d7964378674c5a64b6a7f9222f1ff6a8209885dc Mon Sep 17 00:00:00 2001 From: Arjun Singh <ajsinghyadav00@gmail.com> Date: Wed, 11 Oct 2023 14:28:09 +0530 Subject: [PATCH 134/146] Improve fuzzing Add seed, new target and remove bloat Signed-off-by: Arjun Singh <ajsinghyadav00@gmail.com> --- .reuse/dep5 | 2 +- fuzz_test.go | 27 ++++++++++ pkg/protocol/extension/fuzz_test.go | 19 +++++++ pkg/protocol/handshake/fuzz_test.go | 69 ++++++++++++++++++++++---- pkg/protocol/recordlayer/fuzz_test.go | 50 ++++++++----------- testdata/seed/TestResumeClient.raw | Bin 0 -> 948 bytes testdata/seed/TestResumeServer.raw | 1 + 7 files changed, 128 insertions(+), 40 deletions(-) create mode 100644 fuzz_test.go create mode 100644 pkg/protocol/extension/fuzz_test.go create mode 100644 testdata/seed/TestResumeClient.raw create mode 100644 testdata/seed/TestResumeServer.raw diff --git a/.reuse/dep5 b/.reuse/dep5 index eb7fac2fc..4ce056940 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -6,6 +6,6 @@ Files: README.md DESIGN.md **/README.md AUTHORS.txt renovate.json go.mod go.sum Copyright: 2023 The Pion community <https://pion.ly> License: MIT -Files: testdata/fuzz/* **/testdata/fuzz/* api/*.txt +Files: testdata/seed/* testdata/fuzz/* **/testdata/fuzz/* api/*.txt Copyright: 2023 The Pion community <https://pion.ly> License: CC0-1.0 diff --git a/fuzz_test.go b/fuzz_test.go new file mode 100644 index 000000000..c91ec2d5e --- /dev/null +++ b/fuzz_test.go @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT +package dtls + +import ( + "os" + "testing" +) + +func FuzzUnmarshalBinary(f *testing.F) { + TestResumeClient, err := os.ReadFile("testdata/seed/TestResumeClient.raw") + if err != nil { + return + } + f.Add(TestResumeClient) + + TestResumeServer, err := os.ReadFile("testdata/seed/TestResumeServer.raw") + if err != nil { + return + } + f.Add(TestResumeServer) + + f.Fuzz(func(_ *testing.T, data []byte) { + deserialized := &State{} + _ = deserialized.UnmarshalBinary(data) + }) +} diff --git a/pkg/protocol/extension/fuzz_test.go b/pkg/protocol/extension/fuzz_test.go new file mode 100644 index 000000000..9266a8031 --- /dev/null +++ b/pkg/protocol/extension/fuzz_test.go @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> +// SPDX-License-Identifier: MIT + +package extension + +import "testing" + +func FuzzUnmarshal(f *testing.F) { + f.Add([]byte{0x00}) + f.Add([]byte{1, 6, 8, 3, 88, 12, 2, 47}) + f.Add([]byte{0x0, 0xa, 0x0, 0x4, 0x0, 0x2, 0x0, 0x1d}) + f.Add([]byte{0x00, 0x0b, 0x00, 0x02, 0x01, 0x00}) + f.Add([]byte{0x00, 0x0d, 0x00, 0x08, 0x00, 0x06, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03}) + f.Add([]byte{0x00, 0x0e, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00}) + + f.Fuzz(func(_ *testing.T, data []byte) { + _, _ = Unmarshal(data) + }) +} diff --git a/pkg/protocol/handshake/fuzz_test.go b/pkg/protocol/handshake/fuzz_test.go index 837459f85..bce66ff3d 100644 --- a/pkg/protocol/handshake/fuzz_test.go +++ b/pkg/protocol/handshake/fuzz_test.go @@ -8,17 +8,64 @@ import ( ) func FuzzDtlsHandshake(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { + 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, + } + rawCertificateVerify := []byte{ + 0x04, 0x03, 0x00, 0x47, 0x30, 0x45, 0x02, 0x20, 0x6b, 0x63, 0x17, 0xad, 0xbe, 0xb7, 0x7b, 0x0f, + 0x86, 0x73, 0x39, 0x1e, 0xba, 0xb3, 0x50, 0x9c, 0xce, 0x9c, 0xe4, 0x8b, 0xe5, 0x13, 0x07, 0x59, + 0x18, 0x1f, 0xe5, 0xa0, 0x2b, 0xca, 0xa6, 0xad, 0x02, 0x21, 0x00, 0xd3, 0xb5, 0x01, 0xbe, 0x87, + 0x6c, 0x04, 0xa1, 0xdc, 0x28, 0xaa, 0x5f, 0xf7, 0x1e, 0x9c, 0xc0, 0x1e, 0x00, 0x2c, 0xe5, 0x94, + 0xbb, 0x03, 0x0e, 0xf1, 0xcb, 0x28, 0x22, 0x33, 0x23, 0x88, 0xad, + } + rawClientHello := []byte{ + 0xfe, 0xfd, 0xb6, 0x2f, 0xce, 0x5c, 0x42, 0x54, 0xff, 0x86, 0xe1, 0x24, 0x41, 0x91, 0x42, + 0x62, 0x15, 0xad, 0x16, 0xc9, 0x15, 0x8d, 0x95, 0x71, 0x8a, 0xbb, 0x22, 0xd7, 0x47, 0xec, + 0xd8, 0x3d, 0xdc, 0x4b, 0x00, 0x14, 0xe6, 0x14, 0x3a, 0x1b, 0x04, 0xea, 0x9e, 0x7a, 0x14, + 0xd6, 0x6c, 0x57, 0xd0, 0x0e, 0x32, 0x85, 0x76, 0x18, 0xde, 0xd8, 0x00, 0x04, 0xc0, 0x2b, + 0xc0, 0x0a, 0x01, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x02, 0x00, 0x1d, + } + rawClientKeyExchange := []byte{ + 0x20, 0x26, 0x78, 0x4a, 0x78, 0x70, 0xc1, 0xf9, 0x71, 0xea, 0x50, 0x4a, 0xb5, 0xbb, 0x00, 0x76, + 0x02, 0x05, 0xda, 0xf7, 0xd0, 0x3f, 0xe3, 0xf7, 0x4e, 0x8a, 0x14, 0x6f, 0xb7, 0xe0, 0xc0, 0xff, + 0x54, + } + rawFinished := []byte{ + 0x01, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + } + rawHelloVerifyRequest := []byte{ + 0xfe, 0xff, 0x14, 0x25, 0xfb, 0xee, 0xb3, 0x7c, 0x95, 0xcf, 0x00, + 0xeb, 0xad, 0xe2, 0xef, 0xc7, 0xfd, 0xbb, 0xed, 0xf7, 0x1f, 0x6c, 0xcd, + } + rawServerHello := []byte{ + 0xfe, 0xfd, 0x21, 0x63, 0x32, 0x21, 0x81, 0x0e, 0x98, 0x6c, + 0x85, 0x3d, 0xa4, 0x39, 0xaf, 0x5f, 0xd6, 0x5c, 0xcc, 0x20, + 0x7f, 0x7c, 0x78, 0xf1, 0x5f, 0x7e, 0x1c, 0xb7, 0xa1, 0x1e, + 0xcf, 0x63, 0x84, 0x28, 0x00, 0xc0, 0x2b, 0x00, 0x00, 0x00, + } + rawServerKeyExchange := []byte{ + 0x03, 0x00, 0x1d, 0x41, 0x04, 0x0c, 0xb9, 0xa3, 0xb9, 0x90, 0x71, 0x35, 0x4a, 0x08, 0x66, 0xaf, + 0xd6, 0x88, 0x58, 0x29, 0x69, 0x98, 0xf1, 0x87, 0x0f, 0xb5, 0xa8, 0xcd, 0x92, 0xf6, 0x2b, 0x08, + 0x0c, 0xd4, 0x16, 0x5b, 0xcc, 0x81, 0xf2, 0x58, 0x91, 0x8e, 0x62, 0xdf, 0xc1, 0xec, 0x72, 0xe8, + 0x47, 0x24, 0x42, 0x96, 0xb8, 0x7b, 0xee, 0xe7, 0x0d, 0xdc, 0x44, 0xec, 0xf3, 0x97, 0x6b, 0x1b, + 0x45, 0x28, 0xac, 0x3f, 0x35, 0x02, 0x03, 0x00, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xb2, 0x0b, + 0x22, 0x95, 0x3d, 0x56, 0x57, 0x6a, 0x3f, 0x85, 0x30, 0x6f, 0x55, 0xc3, 0xf4, 0x24, 0x1b, 0x21, + 0x07, 0xe5, 0xdf, 0xba, 0x24, 0x02, 0x68, 0x95, 0x1f, 0x6e, 0x13, 0xbd, 0x9f, 0xaa, 0x02, 0x20, + 0x49, 0x9c, 0x9d, 0xdf, 0x84, 0x60, 0x33, 0x27, 0x96, 0x9e, 0x58, 0x6d, 0x72, 0x13, 0xe7, 0x3a, + 0xe8, 0xdf, 0x43, 0x75, 0xc7, 0xb9, 0x37, 0x6e, 0x90, 0xe5, 0x3b, 0x81, 0xd4, 0xda, 0x68, 0xcd, + } + f.Add(rawCertificateRequest) + f.Add(rawCertificateVerify) + f.Add(rawClientHello) + f.Add(rawClientKeyExchange) + f.Add(rawFinished) + f.Add(rawHelloVerifyRequest) + f.Add(rawServerHello) + f.Add(rawServerKeyExchange) + + f.Fuzz(func(_ *testing.T, data []byte) { h := &Handshake{} - if err := h.Unmarshal(data); err != nil { - return - } - buf, err := h.Marshal() - if err != nil { - t.Fatal(err) - } - if len(buf) == 0 { - t.Fatal("Zero buff") - } + _ = h.Unmarshal(data) }) } diff --git a/pkg/protocol/recordlayer/fuzz_test.go b/pkg/protocol/recordlayer/fuzz_test.go index 716b5c8a2..24918d2ee 100644 --- a/pkg/protocol/recordlayer/fuzz_test.go +++ b/pkg/protocol/recordlayer/fuzz_test.go @@ -4,39 +4,33 @@ package recordlayer import ( - "reflect" "testing" ) -func headerMismatch(a, b Header) bool { - // Ignoring content length for now. - a.ContentLen = b.ContentLen - return !reflect.DeepEqual(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 - } + Data := []byte{ + 0x14, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x01, + } + f.Add(Data) - if len(buf) == 0 { - t.Fatal("Zero buff") - } - - var nr RecordLayer - if err = nr.Unmarshal(data); err != nil { - t.Fatal(err) - } + f.Fuzz(func(_ *testing.T, data []byte) { + var r RecordLayer + _ = r.Unmarshal(data) + }) +} - if headerMismatch(nr.Header, r.Header) { - t.Fatalf("Header mismatch: %+v != %+v", nr.Header, r.Header) - } +func FuzzUnpackDatagram(f *testing.F) { + Datasingle := []byte{ + 0x14, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x01, + } + Datamulti := []byte{ + 0x14, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x01, + 0x14, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x01, + } + f.Add(Datasingle) + f.Add(Datamulti) + + f.Fuzz(func(_ *testing.T, data []byte) { + _, _ = UnpackDatagram(data) }) } diff --git a/testdata/seed/TestResumeClient.raw b/testdata/seed/TestResumeClient.raw new file mode 100644 index 0000000000000000000000000000000000000000..c2f9cb04e773fbdd906fae4819a6e0dcbe33a181 GIT binary patch literal 948 zcmaJ;?MstU6z|YKpmRD@6l*AyNq4@Kgr+tp8@{x*{Gg&S_gwXf?U`-Q@CC`&tVo0e zG15w~f)e~tU?aa6CYFWR3uIQB1ZJg@QgcFiy3Zc9DConz_nhB3=XZYR+zp7t#+?A* zqE6mo<7+8r7A+zLY+@ilj>BrP=_(!83cqWjc85qe{T-WOlSSYhcEA>vA}9QbX!*(t z>NLA~ks31nB)Jxs$Pj9EQqd2X=_xlAtTfMUFQrZi3O1XL8;wrZ%PR5?fmvm|jY^RK zBc)C)b&7l$Z)HMVfUOKRa8wX^u}04eTbwQztCU*?`p3{Z1VQGLQH3n_Zx{?Nt&L}N zQacF6X6Y$Ph%a_C?qqpPNC!~i8God>Xe%NK0oZ_&&E-YWm|UE+ariPVCl#OIW5VI> zLt$0efxUTl{E1z7S&ct}@fO8(>;pL;*Q&DII9ZTm#8rG1lA$X>#AhWzi8zZMR=R*! zv0)!Jpbs{NV}Xo3uU!lq9`HJ5>Uf>GXYx~urqisi82g$FS>6Mg5hvSJaqZlt3#IS8 zKIqEdBWt`zn&2)w1-*XJfe>Bedyx$=<nDy0)dOe05Qgt<)la0dmxOCVi3%VeASl2^ zZDnyTzFeSOl$Cu1iBv&+f`(``<Y0UfNi6icnr-+0#RVkjcc1Nsa0Fm(tgwE5|AV2p zLZ7-orPzJt;#{cX`gt`pH)t|)r+trBzona&MMe1R(J7_D+i03tQhziYTk0Oqo}xGE zoBB?ZI%$af2zDVm04;>s`4Q0&LX-fpeoVTyEIFMCV(F5Nay~!^C<VGUmmCY8!w=U# zIQvh$Zi7KJ376;sK}i%%|L%nmY%LJ<Ky<JRCdU;$(e-J8Rc~YXYwz!PlB&O-<Jw0@ t->i5H!Jo_LAu1z%WM(|5dm$iY@V*z8+itE*Lq9AiI+C>GzQq|y?Jue|O9%h} literal 0 HcmV?d00001 diff --git a/testdata/seed/TestResumeServer.raw b/testdata/seed/TestResumeServer.raw new file mode 100644 index 000000000..29b6f4d00 --- /dev/null +++ b/testdata/seed/TestResumeServer.raw @@ -0,0 +1 @@ +���serializedState��LocalEpochRemoteEpochLocalRandom��RemoteRandom��CipherSuiteIDMasterSecretSequenceNumberSRTPProtectionProfilePeerCertificates��IdentityHintSessionIDLocalConnectionIDRemoteConnectionIDIsClient��[32]uint8��@��[][]uint8������ e&M����K��'����/��kZO6g��MP��I����������} e&M����������@��Cs.=��5Z��{����rg:[����Le����+0y���*��[�\B�GEv�5�ٕ=�u�CwP9�r�48r�y��;k.E \ No newline at end of file From 3f61fd2edd35ab7ff45dac4f9d3b95d179698821 Mon Sep 17 00:00:00 2001 From: Donald Chan <hoiho.chan@gmail.com> Date: Fri, 1 Nov 2024 20:28:47 -0700 Subject: [PATCH 135/146] Fix RSA signature verification issue Both verifyKeySignature() and verifyCertificateVerify() has a bug when handling RSA signature as it looks at the signature algorithm of the certificate to determine whether to verify with RSA PKCSv1.5. This will cause issues if the certificate's issuing CA uses something other than RSA (e.g. ECDSA) to sign the certificate. Since DTLS v1.2 does not support RSA-PSS [1], we can just use RSA PKCSv1.5 verification directly if the public key of the certificate is RSA. [1] https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml --- crypto.go | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/crypto.go b/crypto.go index beddb40a8..25b2a1f9f 100644 --- a/crypto.go +++ b/crypto.go @@ -89,13 +89,11 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A } return nil case *rsa.PublicKey: - switch certificate.SignatureAlgorithm { - case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA: - hashed := hashAlgorithm.Digest(message) - return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature) - default: - return errKeySignatureVerifyUnimplemented + hashed := hashAlgorithm.Digest(message) + if rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature) != nil { + return errKeySignatureMismatch } + return nil } return errKeySignatureVerifyUnimplemented @@ -158,13 +156,11 @@ func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorith } return nil case *rsa.PublicKey: - switch certificate.SignatureAlgorithm { - case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA: - hash := hashAlgorithm.Digest(handshakeBodies) - return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hash, remoteKeySignature) - default: - return errKeySignatureVerifyUnimplemented + hash := hashAlgorithm.Digest(handshakeBodies) + if rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hash, remoteKeySignature) != nil { + return errKeySignatureMismatch } + return nil } return errKeySignatureVerifyUnimplemented From b3e02c4ba7e207c6dfce4e490f30fe09c8c926be Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:14:27 +0000 Subject: [PATCH 136/146] Update module golang.org/x/net to v0.30.0 Generated by renovateBot --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index a730cba71..53de83263 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.7 - golang.org/x/crypto v0.27.0 - golang.org/x/net v0.29.0 + golang.org/x/crypto v0.28.0 + golang.org/x/net v0.30.0 ) go 1.20 diff --git a/go.sum b/go.sum index e39c9f483..ac6a8e071 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,7 @@ github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= From 02434c73b48f63397b58dc1f7615b62575f0e93e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:37:09 +0000 Subject: [PATCH 137/146] Update module golang.org/x/crypto to v0.29.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 53de83263..eff393f32 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.7 - golang.org/x/crypto v0.28.0 + golang.org/x/crypto v0.29.0 golang.org/x/net v0.30.0 ) diff --git a/go.sum b/go.sum index ac6a8e071..8ef5060e9 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,7 @@ github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= From 4e34db5ca6566b816295c74f5e547fc260a69749 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 04:41:51 +0000 Subject: [PATCH 138/146] Update module golang.org/x/net to v0.31.0 Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eff393f32..047422d1a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.7 golang.org/x/crypto v0.29.0 - golang.org/x/net v0.30.0 + golang.org/x/net v0.31.0 ) go 1.20 diff --git a/go.sum b/go.sum index 8ef5060e9..73f0d3963 100644 --- a/go.sum +++ b/go.sum @@ -4,5 +4,5 @@ github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1 github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= From ceb84588accbb1b0ca0a51e807cc0062278c6d38 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 03:18:39 +0000 Subject: [PATCH 139/146] Update module golang.org/x/crypto to v0.31.0 [SECURITY] Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 047422d1a..e06a9f23d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.7 - golang.org/x/crypto v0.29.0 + golang.org/x/crypto v0.31.0 golang.org/x/net v0.31.0 ) diff --git a/go.sum b/go.sum index 73f0d3963..bbd91997f 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,7 @@ github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= From 1e4ae60e28516c475e999b389bcbe96a168c4470 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:22:36 +0000 Subject: [PATCH 140/146] Update module golang.org/x/net to v0.33.0 [SECURITY] Generated by renovateBot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e06a9f23d..13deb95c2 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/pion/logging v0.2.2 github.com/pion/transport/v3 v3.0.7 golang.org/x/crypto v0.31.0 - golang.org/x/net v0.31.0 + golang.org/x/net v0.33.0 ) go 1.20 diff --git a/go.sum b/go.sum index bbd91997f..556fd0315 100644 --- a/go.sum +++ b/go.sum @@ -4,5 +4,5 @@ github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1 github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= From 1c0df61a228f240c27d3ef69b3eeea679de70d2c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 Jan 2025 05:39:24 +0000 Subject: [PATCH 141/146] Update module github.com/pion/logging to v0.2.3 (#691) Generated by renovateBot Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 13deb95c2..192a98c5f 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/pion/dtls/v3 require ( - github.com/pion/logging v0.2.2 + github.com/pion/logging v0.2.3 github.com/pion/transport/v3 v3.0.7 golang.org/x/crypto v0.31.0 golang.org/x/net v0.33.0 diff --git a/go.sum b/go.sum index 556fd0315..be68fd590 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI= +github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= From 8eb9a91be4fd045f3ac20728db4d353a494f2d3c Mon Sep 17 00:00:00 2001 From: Joe Turki <git@joeturki.com> Date: Thu, 23 Jan 2025 18:30:21 -0600 Subject: [PATCH 142/146] Upgrade golangci-lint, more linters Introduces new linters, upgrade golangci-lint to version (v1.63.4) --- .golangci.yml | 47 +- bench_test.go | 14 +- certificate.go | 9 +- cipher_suite.go | 75 ++- cipher_suite_go114.go | 6 +- cipher_suite_go114_test.go | 22 +- cipher_suite_test.go | 10 +- config.go | 18 +- config_test.go | 6 +- conn.go | 285 ++++++---- conn_go_test.go | 9 +- conn_test.go | 504 ++++++++++++------ connection_id.go | 6 +- connection_id_test.go | 13 +- crypto.go | 61 ++- crypto_test.go | 41 +- e2e/e2e_lossy_test.go | 25 +- e2e/e2e_test.go | 74 ++- errors.go | 168 ++++-- errors_test.go | 22 +- examples/dial/cid/main.go | 2 + examples/dial/psk/main.go | 2 + examples/dial/selfsign/main.go | 1 + examples/dial/verify/main.go | 1 + examples/listen/cid/main.go | 1 + examples/listen/psk/main.go | 1 + examples/util/hub.go | 9 +- examples/util/util.go | 8 +- flight.go | 2 +- flight0handler.go | 40 +- flight1handler.go | 22 +- flight1handler_test.go | 5 +- flight2handler.go | 17 +- flight3handler.go | 91 +++- flight3handler_test.go | 14 +- flight4bhandler.go | 18 +- flight4handler.go | 73 ++- flight4handler_test.go | 6 +- flight5bhandler.go | 15 +- flight5handler.go | 72 ++- flight6handler.go | 16 +- flighthandler.go | 16 +- fragment_buffer.go | 13 +- fragment_buffer_test.go | 55 +- handshake_cache.go | 30 +- handshake_cache_test.go | 20 +- handshake_test.go | 5 +- handshaker.go | 55 +- handshaker_test.go | 80 ++- internal/ciphersuite/aes_128_ccm.go | 14 +- internal/ciphersuite/aes_256_ccm.go | 14 +- internal/ciphersuite/aes_ccm.go | 35 +- internal/ciphersuite/ciphersuite.go | 24 +- .../tls_ecdhe_ecdsa_with_aes_128_ccm.go | 11 +- .../tls_ecdhe_ecdsa_with_aes_128_ccm8.go | 11 +- ...tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go | 34 +- .../tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go | 26 +- ...tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go | 8 +- .../tls_ecdhe_psk_with_aes_128_cbc_sha256.go | 26 +- .../tls_ecdhe_rsa_with_aes_128_gcm_sha256.go | 6 +- .../tls_ecdhe_rsa_with_aes_256_cbc_sha.go | 6 +- .../tls_ecdhe_rsa_with_aes_256_gcm_sha384.go | 6 +- .../tls_psk_with_aes_128_cbc_sha256.go | 26 +- .../ciphersuite/tls_psk_with_aes_128_ccm.go | 11 +- .../ciphersuite/tls_psk_with_aes_128_ccm8.go | 11 +- .../tls_psk_with_aes_128_gcm_sha256.go | 10 +- .../ciphersuite/tls_psk_with_aes_256_ccm8.go | 11 +- .../ciphersuite/types/authentication_type.go | 4 +- .../types/key_exchange_algorithm.go | 2 +- internal/closer/closer.go | 16 +- internal/net/buffer.go | 13 +- internal/net/buffer_test.go | 18 +- internal/net/udp/packet_conn.go | 46 +- internal/net/udp/packet_conn_test.go | 83 ++- internal/util/util.go | 10 +- internal/util/util_test.go | 3 + listener.go | 7 +- nettest_test.go | 1 + pkg/crypto/ccm/ccm.go | 29 +- pkg/crypto/ccm/ccm_test.go | 148 +++-- pkg/crypto/ciphersuite/cbc.go | 81 ++- pkg/crypto/ciphersuite/ccm.go | 36 +- pkg/crypto/ciphersuite/ciphersuite.go | 51 +- pkg/crypto/ciphersuite/ciphersuite_test.go | 10 +- pkg/crypto/ciphersuite/gcm.go | 32 +- .../clientcertificate/client_certificate.go | 4 +- pkg/crypto/elliptic/elliptic.go | 16 +- pkg/crypto/fingerprint/fingerprint.go | 2 +- pkg/crypto/fingerprint/fingerprint_test.go | 41 +- pkg/crypto/fingerprint/hash.go | 4 +- pkg/crypto/fingerprint/hash_test.go | 3 +- pkg/crypto/hash/hash.go | 17 +- pkg/crypto/hash/hash_test.go | 5 +- pkg/crypto/prf/prf.go | 38 +- pkg/crypto/prf/prf_test.go | 192 ++++++- pkg/crypto/selfsign/selfsign.go | 8 +- pkg/crypto/signature/signature.go | 4 +- pkg/crypto/signaturehash/signaturehash.go | 3 +- pkg/net/net.go | 3 + pkg/protocol/alert/alert.go | 17 +- pkg/protocol/application_data.go | 7 +- pkg/protocol/change_cipher_spec.go | 6 +- pkg/protocol/compression_method.go | 12 +- pkg/protocol/content.go | 4 +- pkg/protocol/errors.go | 25 +- pkg/protocol/extension/alpn.go | 19 +- pkg/protocol/extension/alpn_test.go | 12 +- pkg/protocol/extension/connection_id.go | 8 +- pkg/protocol/extension/errors.go | 34 +- pkg/protocol/extension/extension.go | 15 +- pkg/protocol/extension/renegotiation_info.go | 7 +- .../extension/renegotiation_info_test.go | 5 +- pkg/protocol/extension/server_name.go | 10 +- .../extension/supported_elliptic_curves.go | 13 +- .../extension/supported_point_formats.go | 12 +- .../extension/supported_point_formats_test.go | 5 +- .../supported_signature_algorithms.go | 12 +- .../supported_signature_algorithms_test.go | 10 +- pkg/protocol/extension/use_master_secret.go | 7 +- pkg/protocol/extension/use_srtp.go | 25 +- pkg/protocol/extension/use_srtp_test.go | 10 +- pkg/protocol/handshake/cipher_suite.go | 4 +- pkg/protocol/handshake/errors.go | 58 +- pkg/protocol/handshake/handshake.go | 22 +- pkg/protocol/handshake/header.go | 8 +- pkg/protocol/handshake/message_certificate.go | 17 +- .../handshake/message_certificate_request.go | 15 +- .../handshake/message_certificate_test.go | 10 +- .../handshake/message_certificate_verify.go | 10 +- .../handshake/message_client_hello.go | 23 +- .../handshake/message_client_hello_test.go | 10 +- .../handshake/message_client_key_exchange.go | 8 +- pkg/protocol/handshake/message_finished.go | 7 +- .../handshake/message_hello_verify_request.go | 7 +- .../message_hello_verify_request_test.go | 5 +- .../handshake/message_server_hello.go | 18 +- .../handshake/message_server_hello_done.go | 8 +- .../handshake/message_server_hello_test.go | 5 +- .../handshake/message_server_key_exchange.go | 18 +- pkg/protocol/handshake/random.go | 10 +- pkg/protocol/recordlayer/errors.go | 7 +- pkg/protocol/recordlayer/header.go | 9 +- pkg/protocol/recordlayer/inner_plaintext.go | 8 +- pkg/protocol/recordlayer/recordlayer.go | 6 +- pkg/protocol/version.go | 4 +- replayprotection_test.go | 5 +- resume.go | 3 +- resume_test.go | 15 +- session.go | 2 +- state.go | 17 +- util.go | 2 + 151 files changed, 2676 insertions(+), 1265 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a3235bec2..88cb4fbf9 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,17 +25,32 @@ linters-settings: - ^os.Exit$ - ^panic$ - ^print(ln)?$ + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte linters: enable: - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers - bidichk # Checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully + - containedctx # containedctx is a linter that detects struct contained context.Context field - contextcheck # check the function whether use a non-inherited context + - cyclop # checks function and package cyclomatic complexity - decorder # check declaration order and count of types, constants, variables and functions - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. @@ -46,18 +61,17 @@ linters: - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - gochecknoglobals # Checks that no globals are present in Go code - - gochecknoinits # Checks that no init functions are present in Go code - gocognit # Computes and checks the cognitive complexity of functions - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period - godox # Tool for detection of FIXME, TODO and other comment keywords - - err113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - goprintffuncname # Checks that printf-like functions are named with `f` at the end - gosec # Inspects source code for security problems - gosimple # Linter for Go source code that specializes in simplifying a code @@ -65,9 +79,15 @@ linters: - grouper # An analyzer to analyze expression groups. - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length - misspell # Finds commonly misspelled English words in comments + - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - noctx # noctx finds sending http request without context.Context - predeclared # find code that shadows one of Go's predeclared identifiers - revive # golint replacement, finds style mistakes @@ -75,28 +95,22 @@ linters: - 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 - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types + - varnamelen # checks that the length of a variable's name matches its scope - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: - depguard # Go linter that checks if package imports are in a list of acceptable packages - - containedctx # containedctx is a linter that detects struct contained context.Context field - - cyclop # checks function and package cyclomatic complexity - funlen # Tool for detection of long functions - - gocyclo # Computes and checks the cyclomatic complexity of functions - - godot # Check if comments end in a period - - gomnd # An analyzer to detect magic numbers. + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. - ireturn # Accept Interfaces, Return Concrete Types - - lll # Reports long lines - - maintidx # maintidx measures the maintainability index of each function. - - makezero # Finds slice declarations with non-zero initial length - - nakedret # Finds naked returns in functions greater than a specified function length - - nestif # Reports deeply nested if statements - - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - mnd # An analyzer to detect magic numbers - nolintlint # Reports ill-formed or insufficient nolint directives - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - prealloc # Finds slice declarations that could potentially be preallocated @@ -104,8 +118,7 @@ linters: - rowserrcheck # checks whether Err of rows is checked successfully - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - testpackage # linter that makes you use a separate _test package - - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - - varnamelen # checks that the length of a variable's name matches its scope + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - wrapcheck # Checks that errors returned from external packages are wrapped - wsl # Whitespace Linter - Forces you to use empty lines! diff --git a/bench_test.go b/bench_test.go index 57fe93ff1..8d90786cb 100644 --- a/bench_test.go +++ b/bench_test.go @@ -37,6 +37,7 @@ func TestSimpleReadWrite(t *testing.T) { }, false) if sErr != nil { t.Error(sErr) + return } buf := make([]byte, 1024) @@ -71,8 +72,10 @@ func TestSimpleReadWrite(t *testing.T) { } } -func benchmarkConn(b *testing.B, n int64) { - b.Run(fmt.Sprintf("%d", n), func(b *testing.B) { +func benchmarkConn(b *testing.B, payloadSize int64) { + b.Helper() + + b.Run(fmt.Sprintf("%d", payloadSize), func(b *testing.B) { ctx := context.Background() ca, cb := dpipe.Pipe() @@ -84,6 +87,7 @@ func benchmarkConn(b *testing.B, n int64) { }, false) if err != nil { b.Error(sErr) + return } server <- s @@ -91,11 +95,13 @@ func benchmarkConn(b *testing.B, n int64) { if err != nil { b.Fatal(err) } - hw := make([]byte, n) + hw := make([]byte, payloadSize) b.ReportAllocs() b.SetBytes(int64(len(hw))) go func() { - client, cErr := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{InsecureSkipVerify: true}, false) + client, cErr := testClient( + ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{InsecureSkipVerify: true}, false, + ) if cErr != nil { b.Error(err) } diff --git a/certificate.go b/certificate.go index 7e184dfd5..524b8e063 100644 --- a/certificate.go +++ b/certificate.go @@ -43,7 +43,8 @@ type CertificateRequestInfo struct { // 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 +// 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 @@ -66,6 +67,7 @@ func (cri *CertificateRequestInfo) SupportsCertificate(c *tls.Certificate) error } } } + return errNotAcceptableCertificateChain } @@ -91,6 +93,7 @@ func (c *handshakeConfig) setNameToCertificateLocked() { c.nameToCertificate = nameToCertificate } +//nolint:cyclop func (c *handshakeConfig) getCertificate(clientHelloInfo *ClientHelloInfo) (*tls.Certificate, error) { c.mu.Lock() defer c.mu.Unlock() @@ -141,7 +144,8 @@ func (c *handshakeConfig) getCertificate(clientHelloInfo *ClientHelloInfo) (*tls return &c.localCertificates[0], nil } -// NOTE: original src: https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/handshake_client.go#L974 +// 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() @@ -154,6 +158,7 @@ func (c *handshakeConfig) getClientCertificate(cri *CertificateRequestInfo) (*tl if err := cri.SupportsCertificate(&chain); err != nil { continue } + return &chain, nil } diff --git a/cipher_suite.go b/cipher_suite.go index af95dec2e..0a40918e0 100644 --- a/cipher_suite.go +++ b/cipher_suite.go @@ -16,49 +16,63 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// CipherSuiteID is an ID for our supported CipherSuites +// CipherSuiteID is an ID for our supported CipherSuites. type CipherSuiteID = ciphersuite.ID -// Supported Cipher Suites +// Supported Cipher Suites. const ( // AES-128-CCM - TLS_ECDHE_ECDSA_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM //nolint:revive,stylecheck - TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 //nolint:revive,stylecheck + //nolint:revive,stylecheck + TLS_ECDHE_ECDSA_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM + //nolint:revive,stylecheck + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 // AES-128-GCM-SHA256 - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 //nolint:revive,stylecheck - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 //nolint:revive,stylecheck + //nolint:revive,stylecheck + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + //nolint:revive,stylecheck + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 //nolint:revive,stylecheck - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 //nolint:revive,stylecheck + //nolint:revive,stylecheck + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + //nolint:revive,stylecheck + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // AES-256-CBC-SHA - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA //nolint:revive,stylecheck - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA //nolint:revive,stylecheck - - TLS_PSK_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM //nolint:revive,stylecheck - TLS_PSK_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM_8 //nolint:revive,stylecheck - TLS_PSK_WITH_AES_256_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_256_CCM_8 //nolint:revive,stylecheck - TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_GCM_SHA256 //nolint:revive,stylecheck - TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CBC_SHA256 //nolint:revive,stylecheck - - TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 //nolint:revive,stylecheck + //nolint:revive,stylecheck + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + //nolint:revive,stylecheck + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + + //nolint:revive,stylecheck + TLS_PSK_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM + //nolint:revive,stylecheck + TLS_PSK_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM_8 + //nolint:revive,stylecheck + TLS_PSK_WITH_AES_256_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_256_CCM_8 + //nolint:revive,stylecheck + TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_GCM_SHA256 + //nolint:revive,stylecheck + TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CBC_SHA256 + + //nolint:revive,stylecheck + TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 ) -// CipherSuiteAuthenticationType controls what authentication method is using during the handshake for a CipherSuite +// CipherSuiteAuthenticationType controls what authentication method is using during the handshake for a CipherSuite. type CipherSuiteAuthenticationType = ciphersuite.AuthenticationType -// AuthenticationType Enums +// AuthenticationType Enums. const ( CipherSuiteAuthenticationTypeCertificate CipherSuiteAuthenticationType = ciphersuite.AuthenticationTypeCertificate CipherSuiteAuthenticationTypePreSharedKey CipherSuiteAuthenticationType = ciphersuite.AuthenticationTypePreSharedKey CipherSuiteAuthenticationTypeAnonymous CipherSuiteAuthenticationType = ciphersuite.AuthenticationTypeAnonymous ) -// CipherSuiteKeyExchangeAlgorithm controls what exchange algorithm is using during the handshake for a CipherSuite +// CipherSuiteKeyExchangeAlgorithm controls what exchange algorithm is using during the handshake for a CipherSuite. type CipherSuiteKeyExchangeAlgorithm = ciphersuite.KeyExchangeAlgorithm -// CipherSuiteKeyExchangeAlgorithm Bitmask +// CipherSuiteKeyExchangeAlgorithm Bitmask. const ( CipherSuiteKeyExchangeAlgorithmNone CipherSuiteKeyExchangeAlgorithm = ciphersuite.KeyExchangeAlgorithmNone CipherSuiteKeyExchangeAlgorithmPsk CipherSuiteKeyExchangeAlgorithm = ciphersuite.KeyExchangeAlgorithmPsk @@ -67,7 +81,7 @@ const ( var _ = allCipherSuites() // Necessary until this function isn't only used by Go 1.14 -// CipherSuite is an interface that all DTLS CipherSuites must satisfy +// CipherSuite is an interface that all DTLS CipherSuites must satisfy. type CipherSuite interface { // String of CipherSuite, only used for logging String() string @@ -108,13 +122,14 @@ func CipherSuiteName(id CipherSuiteID) string { if suite != nil { return suite.String() } + return fmt.Sprintf("0x%04X", uint16(id)) } // Taken from https://www.iana.org/assignments/tls-parameters/tls-parameters.xml // A cipherSuite is a specific combination of key agreement, cipher and MAC // function. -func cipherSuiteForID(id CipherSuiteID, customCiphers func() []CipherSuite) CipherSuite { +func cipherSuiteForID(id CipherSuiteID, customCiphers func() []CipherSuite) CipherSuite { //nolint:cyclop switch id { //nolint:exhaustive case TLS_ECDHE_ECDSA_WITH_AES_128_CCM: return ciphersuite.NewTLSEcdheEcdsaWithAes128Ccm() @@ -157,7 +172,7 @@ func cipherSuiteForID(id CipherSuiteID, customCiphers func() []CipherSuite) Ciph return nil } -// CipherSuites we support in order of preference +// CipherSuites we support in order of preference. func defaultCipherSuites() []CipherSuite { return []CipherSuite{ &ciphersuite.TLSEcdheEcdsaWithAes128GcmSha256{}, @@ -191,10 +206,16 @@ func cipherSuiteIDs(cipherSuites []CipherSuite) []uint16 { for _, c := range cipherSuites { rtrn = append(rtrn, uint16(c.ID())) } + return rtrn } -func parseCipherSuites(userSelectedSuites []CipherSuiteID, customCipherSuites func() []CipherSuite, includeCertificateSuites, includePSKSuites bool) ([]CipherSuite, error) { +//nolint:cyclop +func parseCipherSuites( + userSelectedSuites []CipherSuiteID, + customCipherSuites func() []CipherSuite, + includeCertificateSuites, includePSKSuites bool, +) ([]CipherSuite, error) { cipherSuitesForIDs := func(ids []CipherSuiteID) ([]CipherSuite, error) { cipherSuites := []CipherSuite{} for _, id := range ids { @@ -204,6 +225,7 @@ func parseCipherSuites(userSelectedSuites []CipherSuiteID, customCipherSuites fu } cipherSuites = append(cipherSuites, c) } + return cipherSuites, nil } @@ -272,5 +294,6 @@ func filterCipherSuitesForCertificate(cert *tls.Certificate, cipherSuites []Ciph filtered = append(filtered, c) } } + return filtered } diff --git a/cipher_suite_go114.go b/cipher_suite_go114.go index fd46d7bd9..e7a324147 100644 --- a/cipher_suite_go114.go +++ b/cipher_suite_go114.go @@ -11,10 +11,10 @@ import ( ) // VersionDTLS12 is the DTLS version in the same style as -// VersionTLSXX from crypto/tls +// VersionTLSXX from crypto/tls. const VersionDTLS12 = 0xfefd -// Convert from our cipherSuite interface to a tls.CipherSuite struct +// Convert from our cipherSuite interface to a tls.CipherSuite struct. func toTLSCipherSuite(c CipherSuite) *tls.CipherSuite { return &tls.CipherSuite{ ID: uint16(c.ID()), @@ -33,6 +33,7 @@ func CipherSuites() []*tls.CipherSuite { for i, c := range suites { res[i] = toTLSCipherSuite(c) } + return res } @@ -40,5 +41,6 @@ func CipherSuites() []*tls.CipherSuite { // this package and which have security issues. func InsecureCipherSuites() []*tls.CipherSuite { var res []*tls.CipherSuite + return res } diff --git a/cipher_suite_go114_test.go b/cipher_suite_go114_test.go index 35c4b1ef6..e93b760c5 100644 --- a/cipher_suite_go114_test.go +++ b/cipher_suite_go114_test.go @@ -30,25 +30,25 @@ func TestCipherSuites(t *testing.T) { i := i s := s t.Run(s.String(), func(t *testing.T) { - c := theirs[i] - if c.ID != uint16(s.ID()) { - t.Fatalf("Expected ID: 0x%04X, got 0x%04X", s.ID(), c.ID) + cipher := theirs[i] + if cipher.ID != uint16(s.ID()) { + t.Fatalf("Expected ID: 0x%04X, got 0x%04X", s.ID(), cipher.ID) } - if c.Name != s.String() { - t.Fatalf("Expected Name: %s, got %s", s.String(), c.Name) + if cipher.Name != s.String() { + t.Fatalf("Expected Name: %s, got %s", s.String(), cipher.Name) } - if len(c.SupportedVersions) != 1 { - t.Fatalf("Expected %d SupportedVersion, got %d", 1, len(c.SupportedVersions)) + if len(cipher.SupportedVersions) != 1 { + t.Fatalf("Expected %d SupportedVersion, got %d", 1, len(cipher.SupportedVersions)) } - if c.SupportedVersions[0] != VersionDTLS12 { - t.Fatalf("Expected SupportedVersions 0x%04X, got 0x%04X", VersionDTLS12, c.SupportedVersions[0]) + if cipher.SupportedVersions[0] != VersionDTLS12 { + t.Fatalf("Expected SupportedVersions 0x%04X, got 0x%04X", VersionDTLS12, cipher.SupportedVersions[0]) } - if c.Insecure { - t.Fatalf("Expected Insecure %t, got %t", false, c.Insecure) + if cipher.Insecure { + t.Fatalf("Expected Insecure %t, got %t", false, cipher.Insecure) } }) } diff --git a/cipher_suite_test.go b/cipher_suite_test.go index bd1f803ec..c4fd4840a 100644 --- a/cipher_suite_test.go +++ b/cipher_suite_test.go @@ -38,7 +38,7 @@ func TestAllCipherSuites(t *testing.T) { } } -// CustomCipher that is just used to assert Custom IDs work +// CustomCipher that is just used to assert Custom IDs work. type testCustomCipherSuite struct { ciphersuite.TLSEcdheEcdsaWithAes128GcmSha256 authenticationType CipherSuiteAuthenticationType @@ -52,7 +52,7 @@ func (t *testCustomCipherSuite) AuthenticationType() CipherSuiteAuthenticationTy return t.authenticationType } -// Assert that two connections that pass in a CipherSuite with a CustomID works +// Assert that two connections that pass in a CipherSuite with a CustomID works. func TestCustomCipherSuite(t *testing.T) { type result struct { c *Conn @@ -68,14 +68,14 @@ func TestCustomCipherSuite(t *testing.T) { defer cancel() ca, cb := dpipe.Pipe() - c := make(chan result) + resultCh := make(chan result) go func() { client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ CipherSuites: []CipherSuiteID{}, CustomCipherSuites: cipherFactory, }, true) - c <- result{client, err} + resultCh <- result{client, err} }() server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ @@ -83,7 +83,7 @@ func TestCustomCipherSuite(t *testing.T) { CustomCipherSuites: cipherFactory, }, true) - clientResult := <-c + clientResult := <-resultCh if err != nil { t.Error(err) diff --git a/config.go b/config.go index 54a86c0ee..39b5cc38c 100644 --- a/config.go +++ b/config.go @@ -217,7 +217,8 @@ type Config struct { // message is sent from a server. The returned handshake message replaces the original message. CertificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message - // OnConnectionAttempt is fired Whenever a connection attempt is made, the server or application can call this callback function. + // OnConnectionAttempt is fired Whenever a connection attempt is made, + // the server or application can call this callback function. // The callback function can then implement logic to handle the connection attempt, such as logging the attempt, // checking against a list of blocked IPs, or counting the attempts to prevent brute force attacks. // If the callback function returns an error, the connection attempt will be aborted. @@ -233,14 +234,14 @@ 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 +// If the remote provided none it will be nil. type PSKCallback func([]byte) ([]byte, error) // ClientAuthType declares the policy the server will follow for // TLS Client Authentication. type ClientAuthType int -// ClientAuthType enums +// ClientAuthType enums. const ( NoClientCert ClientAuthType = iota RequestClientCert @@ -250,17 +251,17 @@ const ( ) // ExtendedMasterSecretType declares the policy the client and server -// will follow for the Extended Master Secret extension +// will follow for the Extended Master Secret extension. type ExtendedMasterSecretType int -// ExtendedMasterSecretType enums +// ExtendedMasterSecretType enums. const ( RequestExtendedMasterSecret ExtendedMasterSecretType = iota RequireExtendedMasterSecret DisableExtendedMasterSecret ) -func validateConfig(config *Config) error { +func validateConfig(config *Config) error { //nolint:cyclop switch { case config == nil: return errNoConfigProvided @@ -283,6 +284,9 @@ func validateConfig(config *Config) error { } } - _, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), 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 99e25a4c2..b01de1442 100644 --- a/config_test.go +++ b/config_test.go @@ -14,26 +14,30 @@ import ( "github.com/pion/dtls/v3/pkg/crypto/selfsign" ) -func TestValidateConfig(t *testing.T) { +func TestValidateConfig(t *testing.T) { //nolint:cyclop cert, err := selfsign.GenerateSelfSigned() if err != nil { t.Fatalf("TestValidateConfig: Config validation error(%v), self signed certificate not generated", err) + return } dsaPrivateKey := &dsa.PrivateKey{} err = dsa.GenerateParameters(&dsaPrivateKey.Parameters, rand.Reader, dsa.L1024N160) if err != nil { t.Fatalf("TestValidateConfig: Config validation error(%v), DSA parameters not generated", err) + return } err = dsa.GenerateKey(dsaPrivateKey, rand.Reader) if err != nil { t.Fatalf("TestValidateConfig: Config validation error(%v), DSA private key not generated", err) + return } rsaPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { t.Fatalf("TestValidateConfig: Config validation error(%v), RSA private key not generated", err) + return } cases := map[string]struct { diff --git a/conn.go b/conn.go index 26c56f2e0..c7cd9a3cb 100644 --- a/conn.go +++ b/conn.go @@ -33,10 +33,10 @@ const ( sessionLength = 32 defaultNamedCurve = elliptic.X25519 inboundBufferSize = 8192 - // Default replay protection window is specified by RFC 6347 Section 4.1.2.6 + // Default replay protection window is specified by RFC 6347 Section 4.1.2.6. defaultReplayProtectionWindow = 64 - // maxAppDataPacketQueueSize is the maximum number of app data packets we will - // enqueue before the handshake is completed + // maxAppDataPacketQueueSize is the maximum number of app data packets we will. + // enqueue before the handshake is completed. maxAppDataPacketQueueSize = 100 ) @@ -59,7 +59,7 @@ type recvHandshakeState struct { isRetransmit bool } -// Conn represents a DTLS connection +// Conn represents a DTLS connection. type Conn struct { lock sync.RWMutex // Internal lock (must not be public) nextConn netctx.PacketConn // Embedded Conn, typically a udpconn we read/write from @@ -99,7 +99,14 @@ type Conn struct { handshakeConfig *handshakeConfig } -func createConn(nextConn net.PacketConn, rAddr net.Addr, config *Config, isClient bool, resumeState *State) (*Conn, error) { +//nolint:cyclop +func createConn( + nextConn net.PacketConn, + rAddr net.Addr, + config *Config, + isClient bool, + resumeState *State, +) (*Conn, error) { if err := validateConfig(config); err != nil { return nil, err } @@ -130,7 +137,12 @@ func createConn(nextConn net.PacketConn, rAddr net.Addr, config *Config, isClien paddingLengthGenerator = func(uint) uint { return 0 } } - cipherSuites, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil) + cipherSuites, err := parseCipherSuites( + config.CipherSuites, + config.CustomCipherSuites, + config.includeCertificateSuites(), + config.PSK != nil, + ) if err != nil { return nil, err } @@ -193,7 +205,7 @@ func createConn(nextConn net.PacketConn, rAddr net.Addr, config *Config, isClien resumeState: resumeState, } - c := &Conn{ + conn := &Conn{ rAddr: rAddr, nextConn: netctx.NewPacketConn(nextConn), handshakeConfig: handshakeConfig, @@ -214,16 +226,17 @@ func createConn(nextConn net.PacketConn, rAddr net.Addr, config *Config, isClien cancelHandshaker: func() {}, cancelHandshakeReader: func() {}, - replayProtectionWindow: uint(replayProtectionWindow), + replayProtectionWindow: uint(replayProtectionWindow), //nolint:gosec // G115 state: State{ isClient: isClient, }, } - c.setRemoteEpoch(0) - c.setLocalEpoch(0) - return c, nil + conn.setRemoteEpoch(0) + conn.setLocalEpoch(0) + + return conn, nil } // Handshake runs the client or server DTLS handshake @@ -276,7 +289,7 @@ func (c *Conn) HandshakeContext(ctx context.Context) error { var initialFlight flightVal var initialFSMState handshakeState - if c.handshakeConfig.resumeState != nil { + if c.handshakeConfig.resumeState != nil { //nolint:nestif if c.state.isClient { initialFlight = flight5 } else { @@ -338,11 +351,12 @@ func Server(conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) return nil, err } } + return createConn(conn, rAddr, config, false, nil) } // Read reads data from the connection. -func (c *Conn) Read(p []byte) (n int, err error) { +func (c *Conn) Read(buff []byte) (n int, err error) { //nolint:cyclop if err := c.Handshake(); err != nil { return 0, err } @@ -363,10 +377,11 @@ func (c *Conn) Read(p []byte) (n int, err error) { } switch val := out.(type) { case ([]byte): - if len(p) < len(val) { + if len(buff) < len(val) { return 0, errBufferTooSmall } - copy(p, val) + copy(buff, val) + return len(val), nil case (error): return 0, val @@ -375,8 +390,8 @@ func (c *Conn) Read(p []byte) (n int, err error) { } } -// Write writes len(p) bytes from p to the DTLS connection -func (c *Conn) Write(p []byte) (int, error) { +// Write writes len(payload) bytes from payload to the DTLS connection. +func (c *Conn) Write(payload []byte) (int, error) { if c.isConnectionClosed() { return 0, ErrConnClosed } @@ -391,7 +406,7 @@ func (c *Conn) Write(p []byte) (int, error) { return 0, err } - return len(p), c.writePackets(c.writeDeadline, []*packet{ + return len(payload), c.writePackets(c.writeDeadline, []*packet{ { record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ @@ -399,7 +414,7 @@ func (c *Conn) Write(p []byte) (int, error) { Version: protocol.Version1_2, }, Content: &protocol.ApplicationData{ - Data: p, + Data: payload, }, }, shouldWrapCID: len(c.state.remoteConnectionID) > 0, @@ -417,6 +432,7 @@ func (c *Conn) Close() error { if handshakeDone != nil { <-handshakeDone } + return err } @@ -429,10 +445,11 @@ func (c *Conn) ConnectionState() (State, bool) { if err != nil { return State{}, false } + return *stateClone, true } -// SelectedSRTPProtectionProfile returns the selected SRTPProtectionProfile +// SelectedSRTPProtectionProfile returns the selected SRTPProtectionProfile. func (c *Conn) SelectedSRTPProtectionProfile() (SRTPProtectionProfile, bool) { profile := c.state.getSRTPProtectionProfile() if profile == 0 { @@ -442,7 +459,7 @@ func (c *Conn) SelectedSRTPProtectionProfile() (SRTPProtectionProfile, bool) { return profile, true } -// RemoteSRTPMasterKeyIdentifier returns the MasterKeyIdentifier value from the use_srtp +// RemoteSRTPMasterKeyIdentifier returns the MasterKeyIdentifier value from the use_srtp. func (c *Conn) RemoteSRTPMasterKeyIdentifier() ([]byte, bool) { if profile := c.state.getSRTPProtectionProfile(); profile == 0 { return nil, false @@ -457,26 +474,32 @@ func (c *Conn) writePackets(ctx context.Context, pkts []*packet) error { var rawPackets [][]byte - for _, p := range pkts { - if h, ok := p.record.Content.(*handshake.Handshake); ok { - handshakeRaw, err := p.record.Marshal() + for _, pkt := range pkts { + if dtlsHandshake, ok := pkt.record.Content.(*handshake.Handshake); ok { + handshakeRaw, err := pkt.record.Marshal() if err != nil { return err } c.log.Tracef("[handshake:%v] -> %s (epoch: %d, seq: %d)", - srvCliStr(c.state.isClient), h.Header.Type.String(), - p.record.Header.Epoch, h.Header.MessageSequence) - - c.handshakeCache.push(handshakeRaw[recordlayer.FixedHeaderSize:], p.record.Header.Epoch, h.Header.MessageSequence, h.Header.Type, c.state.isClient) + srvCliStr(c.state.isClient), dtlsHandshake.Header.Type.String(), + pkt.record.Header.Epoch, dtlsHandshake.Header.MessageSequence) + + c.handshakeCache.push( + handshakeRaw[recordlayer.FixedHeaderSize:], + pkt.record.Header.Epoch, + dtlsHandshake.Header.MessageSequence, + dtlsHandshake.Header.Type, + c.state.isClient, + ) - rawHandshakePackets, err := c.processHandshakePacket(p, h) + rawHandshakePackets, err := c.processHandshakePacket(pkt, dtlsHandshake) if err != nil { return err } rawPackets = append(rawPackets, rawHandshakePackets...) } else { - rawPacket, err := c.processPacket(p) + rawPacket, err := c.processPacket(pkt) if err != nil { return err } @@ -519,8 +542,8 @@ func (c *Conn) compactRawPackets(rawPackets [][]byte) [][]byte { return combinedRawPackets } -func (c *Conn) processPacket(p *packet) ([]byte, error) { - epoch := p.record.Header.Epoch +func (c *Conn) processPacket(pkt *packet) ([]byte, error) { //nolint:cyclop + epoch := pkt.record.Header.Epoch for len(c.state.localSequenceNumber) <= int(epoch) { c.state.localSequenceNumber = append(c.state.localSequenceNumber, uint64(0)) } @@ -531,51 +554,51 @@ func (c *Conn) processPacket(p *packet) ([]byte, error) { // prior to allowing the sequence number to wrap. return nil, errSequenceNumberOverflow } - p.record.Header.SequenceNumber = seq + pkt.record.Header.SequenceNumber = seq var rawPacket []byte - if p.shouldWrapCID { + if pkt.shouldWrapCID { //nolint:nestif // Record must be marshaled to populate fields used in inner plaintext. - if _, err := p.record.Marshal(); err != nil { + if _, err := pkt.record.Marshal(); err != nil { return nil, err } - content, err := p.record.Content.Marshal() + content, err := pkt.record.Content.Marshal() if err != nil { return nil, err } inner := &recordlayer.InnerPlaintext{ Content: content, - RealType: p.record.Header.ContentType, + RealType: pkt.record.Header.ContentType, } rawInner, err := inner.Marshal() //nolint:govet if err != nil { return nil, err } cidHeader := &recordlayer.Header{ - Version: p.record.Header.Version, + Version: pkt.record.Header.Version, ContentType: protocol.ContentTypeConnectionID, - Epoch: p.record.Header.Epoch, - ContentLen: uint16(len(rawInner)), + Epoch: pkt.record.Header.Epoch, + ContentLen: uint16(len(rawInner)), //nolint:gosec //G115 ConnectionID: c.state.remoteConnectionID, - SequenceNumber: p.record.Header.SequenceNumber, + SequenceNumber: pkt.record.Header.SequenceNumber, } rawPacket, err = cidHeader.Marshal() if err != nil { return nil, err } - p.record.Header = *cidHeader + pkt.record.Header = *cidHeader rawPacket = append(rawPacket, rawInner...) } else { var err error - rawPacket, err = p.record.Marshal() + rawPacket, err = pkt.record.Marshal() if err != nil { return nil, err } } - if p.shouldEncrypt { + if pkt.shouldEncrypt { var err error - rawPacket, err = c.state.cipherSuite.Encrypt(p.record, rawPacket) + rawPacket, err = c.state.cipherSuite.Encrypt(pkt.record, rawPacket) if err != nil { return nil, err } @@ -584,14 +607,15 @@ func (c *Conn) processPacket(p *packet) ([]byte, error) { return rawPacket, nil } -func (c *Conn) processHandshakePacket(p *packet, h *handshake.Handshake) ([][]byte, error) { +//nolint:cyclop +func (c *Conn) processHandshakePacket(pkt *packet, dtlsHandshake *handshake.Handshake) ([][]byte, error) { rawPackets := make([][]byte, 0) - handshakeFragments, err := c.fragmentHandshake(h) + handshakeFragments, err := c.fragmentHandshake(dtlsHandshake) if err != nil { return nil, err } - epoch := p.record.Header.Epoch + epoch := pkt.record.Header.Epoch for len(c.state.localSequenceNumber) <= int(epoch) { c.state.localSequenceNumber = append(c.state.localSequenceNumber, uint64(0)) } @@ -603,7 +627,7 @@ func (c *Conn) processHandshakePacket(p *packet, h *handshake.Handshake) ([][]by } var rawPacket []byte - if p.shouldWrapCID { + if pkt.shouldWrapCID { inner := &recordlayer.InnerPlaintext{ Content: handshakeFragment, RealType: protocol.ContentTypeHandshake, @@ -614,25 +638,25 @@ func (c *Conn) processHandshakePacket(p *packet, h *handshake.Handshake) ([][]by return nil, err } cidHeader := &recordlayer.Header{ - Version: p.record.Header.Version, + Version: pkt.record.Header.Version, ContentType: protocol.ContentTypeConnectionID, - Epoch: p.record.Header.Epoch, - ContentLen: uint16(len(rawInner)), + Epoch: pkt.record.Header.Epoch, + ContentLen: uint16(len(rawInner)), //nolint:gosec //G115 ConnectionID: c.state.remoteConnectionID, - SequenceNumber: p.record.Header.SequenceNumber, + SequenceNumber: pkt.record.Header.SequenceNumber, } rawPacket, err = cidHeader.Marshal() if err != nil { return nil, err } - p.record.Header = *cidHeader + pkt.record.Header = *cidHeader rawPacket = append(rawPacket, rawInner...) } else { recordlayerHeader := &recordlayer.Header{ - Version: p.record.Header.Version, - ContentType: p.record.Header.ContentType, - ContentLen: uint16(len(handshakeFragment)), - Epoch: p.record.Header.Epoch, + Version: pkt.record.Header.Version, + ContentType: pkt.record.Header.ContentType, + ContentLen: uint16(len(handshakeFragment)), //nolint:gosec // G115 + Epoch: pkt.record.Header.Epoch, SequenceNumber: seq, } @@ -641,13 +665,13 @@ func (c *Conn) processHandshakePacket(p *packet, h *handshake.Handshake) ([][]by return nil, err } - p.record.Header = *recordlayerHeader + pkt.record.Header = *recordlayerHeader rawPacket = append(rawPacket, handshakeFragment...) } - if p.shouldEncrypt { + if pkt.shouldEncrypt { var err error - rawPacket, err = c.state.cipherSuite.Encrypt(p.record, rawPacket) + rawPacket, err = c.state.cipherSuite.Encrypt(pkt.record, rawPacket) if err != nil { return nil, err } @@ -659,8 +683,8 @@ func (c *Conn) processHandshakePacket(p *packet, h *handshake.Handshake) ([][]by return rawPackets, nil } -func (c *Conn) fragmentHandshake(h *handshake.Handshake) ([][]byte, error) { - content, err := h.Message.Marshal() +func (c *Conn) fragmentHandshake(dtlsHandshake *handshake.Handshake) ([][]byte, error) { + content, err := dtlsHandshake.Message.Marshal() if err != nil { return nil, err } @@ -679,11 +703,11 @@ func (c *Conn) fragmentHandshake(h *handshake.Handshake) ([][]byte, error) { contentFragmentLen := len(contentFragment) headerFragment := &handshake.Header{ - Type: h.Header.Type, - Length: h.Header.Length, - MessageSequence: h.Header.MessageSequence, - FragmentOffset: uint32(offset), - FragmentLength: uint32(contentFragmentLen), + Type: dtlsHandshake.Header.Type, + Length: dtlsHandshake.Header.Length, + MessageSequence: dtlsHandshake.Header.MessageSequence, + FragmentOffset: uint32(offset), //nolint:gosec // G115 + FragmentLength: uint32(contentFragmentLen), //nolint:gosec // G115 } offset += contentFragmentLen @@ -703,11 +727,12 @@ func (c *Conn) fragmentHandshake(h *handshake.Handshake) ([][]byte, error) { var poolReadBuffer = sync.Pool{ //nolint:gochecknoglobals New: func() interface{} { b := make([]byte, inboundBufferSize) + return &b }, } -func (c *Conn) readAndBuffer(ctx context.Context) error { +func (c *Conn) readAndBuffer(ctx context.Context) error { //nolint:cyclop bufptr, ok := poolReadBuffer.Get().(*[]byte) if !ok { return errFailedToAccessPoolReadBuffer @@ -763,6 +788,7 @@ func (c *Conn) readAndBuffer(ctx context.Context) error { case <-c.fsm.Done(): } } + return nil } @@ -787,37 +813,48 @@ func (c *Conn) handleQueuedPackets(ctx context.Context) error { return err } } + return nil } func (c *Conn) enqueueEncryptedPackets(packet addrPkt) bool { if len(c.encryptedPackets) < maxAppDataPacketQueueSize { c.encryptedPackets = append(c.encryptedPackets, packet) + return true } + return false } -func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.Addr, enqueue bool) (bool, bool, *alert.Alert, error) { //nolint:gocognit - h := &recordlayer.Header{} +//nolint:gocognit,gocyclo,cyclop,maintidx +func (c *Conn) handleIncomingPacket( + ctx context.Context, + buf []byte, + rAddr net.Addr, + enqueue bool, +) (bool, bool, *alert.Alert, error) { + header := &recordlayer.Header{} // Set connection ID size so that records of content type tls12_cid will // be parsed correctly. if len(c.state.getLocalConnectionID()) > 0 { - h.ConnectionID = make([]byte, len(c.state.getLocalConnectionID())) + header.ConnectionID = make([]byte, len(c.state.getLocalConnectionID())) } - if err := h.Unmarshal(buf); err != nil { + if err := header.Unmarshal(buf); err != nil { // Decode error must be silently discarded // [RFC6347 Section-4.1.2.7] c.log.Debugf("discarded broken packet: %v", err) + return false, false, nil, nil } // Validate epoch remoteEpoch := c.state.getRemoteEpoch() - if h.Epoch > remoteEpoch { - if h.Epoch > remoteEpoch+1 { + if header.Epoch > remoteEpoch { + if header.Epoch > remoteEpoch+1 { c.log.Debugf("discarded future packet (epoch: %d, seq: %d)", - h.Epoch, h.SequenceNumber, + header.Epoch, header.SequenceNumber, ) + return false, false, nil, nil } if enqueue { @@ -825,20 +862,22 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A c.log.Debug("received packet of next epoch, queuing packet") } } + return false, false, nil, nil } // Anti-replay protection - for len(c.state.replayDetector) <= int(h.Epoch) { + for len(c.state.replayDetector) <= int(header.Epoch) { c.state.replayDetector = append(c.state.replayDetector, replaydetector.New(c.replayProtectionWindow, recordlayer.MaxSequenceNumber), ) } - markPacketAsValid, ok := c.state.replayDetector[int(h.Epoch)].Check(h.SequenceNumber) + markPacketAsValid, ok := c.state.replayDetector[int(header.Epoch)].Check(header.SequenceNumber) if !ok { c.log.Debugf("discarded duplicated packet (epoch: %d, seq: %d)", - h.Epoch, h.SequenceNumber, + header.Epoch, header.SequenceNumber, ) + return false, false, nil, nil } @@ -847,60 +886,66 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A originalCID := false // Decrypt - if h.Epoch != 0 { + if header.Epoch != 0 { //nolint:nestif if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { if enqueue { if ok := c.enqueueEncryptedPackets(addrPkt{rAddr, buf}); ok { c.log.Debug("handshake not finished, queuing packet") } } + return false, false, nil, nil } // If a connection identifier had been negotiated and encryption is // enabled, the connection identifier MUST be sent. - if len(c.state.getLocalConnectionID()) > 0 && h.ContentType != protocol.ContentTypeConnectionID { + if len(c.state.getLocalConnectionID()) > 0 && header.ContentType != protocol.ContentTypeConnectionID { c.log.Debug("discarded packet missing connection ID after value negotiated") + return false, false, nil, nil } var err error var hdr recordlayer.Header - if h.ContentType == protocol.ContentTypeConnectionID { + if header.ContentType == protocol.ContentTypeConnectionID { hdr.ConnectionID = make([]byte, len(c.state.getLocalConnectionID())) } buf, err = c.state.cipherSuite.Decrypt(hdr, buf) if err != nil { c.log.Debugf("%s: decrypt failed: %s", srvCliStr(c.state.isClient), err) + return false, false, nil, nil } // If this is a connection ID record, make it look like a normal record for // further processing. - if h.ContentType == protocol.ContentTypeConnectionID { + if header.ContentType == protocol.ContentTypeConnectionID { originalCID = true ip := &recordlayer.InnerPlaintext{} - if err := ip.Unmarshal(buf[h.Size():]); err != nil { //nolint:govet + if err := ip.Unmarshal(buf[header.Size():]); err != nil { //nolint:govet c.log.Debugf("unpacking inner plaintext failed: %s", err) + return false, false, nil, nil } unpacked := &recordlayer.Header{ ContentType: ip.RealType, - ContentLen: uint16(len(ip.Content)), - Version: h.Version, - Epoch: h.Epoch, - SequenceNumber: h.SequenceNumber, + ContentLen: uint16(len(ip.Content)), //nolint:gosec // G115 + Version: header.Version, + Epoch: header.Epoch, + SequenceNumber: header.SequenceNumber, } buf, err = unpacked.Marshal() if err != nil { c.log.Debugf("converting CID record to inner plaintext failed: %s", err) + return false, false, nil, nil } buf = append(buf, ip.Content...) } // If connection ID does not match discard the packet. - if !bytes.Equal(c.state.getLocalConnectionID(), h.ConnectionID) { + if !bytes.Equal(c.state.getLocalConnectionID(), header.ConnectionID) { c.log.Debug("unexpected connection ID") + return false, false, nil, nil } } @@ -910,6 +955,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A // Decode error must be silently discarded // [RFC6347 Section-4.1.2.7] c.log.Debugf("defragment failed: %s", err) + return false, false, nil, nil } else if isHandshake { markPacketAsValid() @@ -918,6 +964,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A header := &handshake.Header{} if err := header.Unmarshal(out); err != nil { c.log.Debugf("%s: handshake parse failed: %s", srvCliStr(c.state.isClient), err) + continue } c.handshakeCache.push(out, epoch, header.MessageSequence, header.Type, !c.state.isClient) @@ -941,6 +988,7 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A a = &alert.Alert{Level: alert.Warning, Description: alert.CloseNotify} } _ = markPacketAsValid() + return false, false, a, &alertError{content} case *protocol.ChangeCipherSpec: if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { @@ -949,10 +997,11 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A c.log.Debugf("CipherSuite not initialized, queuing packet") } } + return false, false, nil, nil } - newRemoteEpoch := h.Epoch + 1 + newRemoteEpoch := header.Epoch + 1 c.log.Tracef("%s: <- ChangeCipherSpec (epoch: %d)", srvCliStr(c.state.isClient), newRemoteEpoch) if c.state.getRemoteEpoch()+1 == newRemoteEpoch { @@ -960,8 +1009,10 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A isLatestSeqNum = markPacketAsValid() } case *protocol.ApplicationData: - if h.Epoch == 0 { - return false, false, &alert.Alert{Level: alert.Fatal, Description: alert.UnexpectedMessage}, errApplicationDataEpochZero + if header.Epoch == 0 { + return false, false, &alert.Alert{ + Level: alert.Fatal, Description: alert.UnexpectedMessage, + }, errApplicationDataEpochZero } isLatestSeqNum = markPacketAsValid() @@ -973,7 +1024,9 @@ func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, rAddr net.A } default: - return false, false, &alert.Alert{Level: alert.Fatal, Description: alert.UnexpectedMessage}, fmt.Errorf("%w: %d", errUnhandledContextType, content.ContentType()) + return false, false, &alert.Alert{ + Level: alert.Fatal, Description: alert.UnexpectedMessage, + }, fmt.Errorf("%w: %d", errUnhandledContextType, content.ContentType()) } // Any valid connection ID record is a candidate for updating the remote @@ -1005,6 +1058,7 @@ func (c *Conn) notify(ctx context.Context, level alert.Level, desc alert.Descrip } } } + return c.writePackets(ctx, []*packet{ { record: &recordlayer.RecordLayer{ @@ -1029,10 +1083,17 @@ func (c *Conn) setHandshakeCompletedSuccessfully() { func (c *Conn) isHandshakeCompletedSuccessfully() bool { boolean, _ := c.handshakeCompletedSuccessfully.Load().(struct{ bool }) + return boolean.bool } -func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFlight flightVal, initialState handshakeState) error { //nolint:gocognit,contextcheck +//nolint:cyclop,gocognit,contextcheck +func (c *Conn) handshake( + ctx context.Context, + cfg *handshakeConfig, + initialFlight flightVal, + initialState handshakeState, +) error { c.fsm = newHandshakeFSM(&c.state, c.handshakeCache, cfg, initialFlight) done := make(chan struct{}) @@ -1081,10 +1142,10 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh }() defer handshakeLoopsFinished.Done() for { - if err := c.readAndBuffer(ctxRead); err != nil { - var e *alertError - if errors.As(err, &e) { - if !e.IsFatalOrCloseNotify() { + if err := c.readAndBuffer(ctxRead); err != nil { //nolint:nestif + var alertErr *alertError + if errors.As(err, &alertErr) { + if !alertErr.IsFatalOrCloseNotify() { if c.isHandshakeCompletedSuccessfully() { // Pass the error to Read() select { @@ -1093,11 +1154,15 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh case <-ctxRead.Done(): } } + continue // non-fatal alert must not stop read loop } } else { switch { - case errors.Is(err, context.DeadlineExceeded), errors.Is(err, context.Canceled), errors.Is(err, io.EOF), errors.Is(err, net.ErrClosed): + case errors.Is(err, context.DeadlineExceeded), + errors.Is(err, context.Canceled), + errors.Is(err, io.EOF), + errors.Is(err, net.ErrClosed): case errors.Is(err, recordlayer.ErrInvalidPacketLength): // Decode error must be silently discarded // [RFC6347 Section-4.1.2.7] @@ -1110,6 +1175,7 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh case <-c.closed.Done(): case <-ctxRead.Done(): } + continue // non-fatal alert must not stop read loop } } @@ -1120,8 +1186,8 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh default: } - if e != nil { - if e.IsFatalOrCloseNotify() { + if alertErr != nil { + if alertErr.IsFatalOrCloseNotify() { _ = c.close(false) //nolint:contextcheck } } @@ -1129,6 +1195,7 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh c.log.Trace("handshake timeouts - closing underline connection") _ = c.close(false) //nolint:contextcheck } + return } } @@ -1139,11 +1206,13 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh cancelRead() cancel() handshakeLoopsFinished.Wait() + return c.translateHandshakeCtxError(err) case <-ctx.Done(): cancelRead() cancel() handshakeLoopsFinished.Wait() + return c.translateHandshakeCtxError(ctx.Err()) case <-done: return nil @@ -1157,6 +1226,7 @@ func (c *Conn) translateHandshakeCtxError(err error) error { if errors.Is(err, context.Canceled) && c.isHandshakeCompletedSuccessfully() { return nil } + return &HandshakeError{Err: err} } @@ -1213,15 +1283,16 @@ func (c *Conn) setRemoteEpoch(epoch uint16) { c.state.remoteEpoch.Store(epoch) } -// LocalAddr implements net.Conn.LocalAddr +// LocalAddr implements net.Conn.LocalAddr. func (c *Conn) LocalAddr() net.Addr { return c.nextConn.LocalAddr() } -// RemoteAddr implements net.Conn.RemoteAddr +// RemoteAddr implements net.Conn.RemoteAddr. func (c *Conn) RemoteAddr() net.Addr { c.lock.RLock() defer c.lock.RUnlock() + return c.rAddr } @@ -1232,16 +1303,18 @@ func (c *Conn) sessionKey() []byte { // neither address or domain name. return []byte(c.rAddr.String() + "_" + c.fsm.cfg.serverName) } + return c.state.SessionID } -// SetDeadline implements net.Conn.SetDeadline +// SetDeadline implements net.Conn.SetDeadline. func (c *Conn) SetDeadline(t time.Time) error { c.readDeadline.Set(t) + return c.SetWriteDeadline(t) } -// SetReadDeadline implements net.Conn.SetReadDeadline +// SetReadDeadline implements net.Conn.SetReadDeadline. func (c *Conn) SetReadDeadline(t time.Time) error { c.readDeadline.Set(t) // Read deadline is fully managed by this layer. @@ -1249,7 +1322,7 @@ func (c *Conn) SetReadDeadline(t time.Time) error { return nil } -// SetWriteDeadline implements net.Conn.SetWriteDeadline +// SetWriteDeadline implements net.Conn.SetWriteDeadline. func (c *Conn) SetWriteDeadline(t time.Time) error { c.writeDeadline.Set(t) // Write deadline is also fully managed by this layer. diff --git a/conn_go_test.go b/conn_go_test.go index 6b05d8d76..b22e7c71e 100644 --- a/conn_go_test.go +++ b/conn_go_test.go @@ -21,7 +21,7 @@ import ( "github.com/pion/transport/v3/test" ) -func TestContextConfig(t *testing.T) { +func TestContextConfig(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -62,11 +62,13 @@ func TestContextConfig(t *testing.T) { "Dial": { f: func() (func() (net.Conn, error), func()) { ctx, cancel := context.WithTimeout(context.Background(), 40*time.Millisecond) + return func() (net.Conn, error) { conn, err := Dial("udp", addr, config) if err != nil { return nil, err } + return conn, conn.HandshakeContext(ctx) }, func() { cancel() @@ -78,11 +80,13 @@ func TestContextConfig(t *testing.T) { f: func() (func() (net.Conn, error), func()) { ca, _ := dpipe.Pipe() ctx, cancel := context.WithTimeout(context.Background(), 40*time.Millisecond) + return func() (net.Conn, error) { conn, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) if err != nil { return nil, err } + return conn, conn.HandshakeContext(ctx) }, func() { _ = ca.Close() @@ -95,11 +99,13 @@ func TestContextConfig(t *testing.T) { f: func() (func() (net.Conn, error), func()) { ca, _ := dpipe.Pipe() ctx, cancel := context.WithTimeout(context.Background(), 40*time.Millisecond) + return func() (net.Conn, error) { conn, err := Server(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config) if err != nil { return nil, err } + return conn, conn.HandshakeContext(ctx) }, func() { _ = ca.Close() @@ -123,6 +129,7 @@ func TestContextConfig(t *testing.T) { if !errors.As(err, &netError) || !netError.Temporary() { //nolint:staticcheck t.Errorf("Client error exp(Temporary network error) failed(%v)", err) close(done) + return } done <- struct{}{} diff --git a/conn_test.go b/conn_test.go index 9edb3aee0..47538a80a 100644 --- a/conn_test.go +++ b/conn_test.go @@ -63,6 +63,8 @@ func TestStressDuplex(t *testing.T) { } func stressDuplex(t *testing.T) { + t.Helper() + ca, cb, err := pipeMemory() if err != nil { t.Fatal(err) @@ -117,7 +119,7 @@ func TestRoutineLeakOnClose(t *testing.T) { // inboundLoop routine should not be leaked. } -func TestReadWriteDeadline(t *testing.T) { +func TestReadWriteDeadline(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(5 * time.Second) defer lim.Stop() @@ -126,7 +128,7 @@ func TestReadWriteDeadline(t *testing.T) { report := test.CheckRoutines(t) defer report() - var e net.Error + var netErr net.Error ca, cb, err := pipeMemory() if err != nil { @@ -137,22 +139,22 @@ func TestReadWriteDeadline(t *testing.T) { t.Fatal(err) } _, werr := ca.Write(make([]byte, 100)) - if errors.As(werr, &e) { - if !e.Timeout() { + if errors.As(werr, &netErr) { + if !netErr.Timeout() { t.Error("Deadline exceeded Write must return Timeout error") } - if !e.Temporary() { //nolint:staticcheck + if !netErr.Temporary() { //nolint:staticcheck t.Error("Deadline exceeded Write must return Temporary error") } } else { t.Error("Write must return net.Error error") } _, rerr := ca.Read(make([]byte, 100)) - if errors.As(rerr, &e) { - if !e.Timeout() { + if errors.As(rerr, &netErr) { + if !netErr.Timeout() { t.Error("Deadline exceeded Read must return Timeout error") } - if !e.Temporary() { //nolint:staticcheck + if !netErr.Temporary() { //nolint:staticcheck t.Error("Deadline exceeded Read must return Temporary error") } } else { @@ -251,6 +253,7 @@ func TestSequenceNumberOverflow(t *testing.T) { func pipeMemory() (*Conn, *Conn, error) { // In memory pipe ca, cb := dpipe.Pipe() + return pipeConn(ca, cb) } @@ -260,33 +263,44 @@ func pipeConn(ca, cb net.Conn) (*Conn, *Conn, error) { err error } - c := make(chan result) + resultCh := make(chan result) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() // Setup client go func() { - client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}}, true) - c <- result{client, err} + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ + SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}, + }, true) + resultCh <- result{client, err} }() // Setup server - server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}}, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ + SRTPProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80}, + }, true) if err != nil { return nil, nil, err } // Receive client - res := <-c + res := <-resultCh if res.err != nil { _ = server.Close() + return nil, nil, res.err } return res.c, server, nil } -func testClient(ctx context.Context, c net.PacketConn, rAddr net.Addr, cfg *Config, generateCertificate bool) (*Conn, error) { +func testClient( + ctx context.Context, + pktConn net.PacketConn, + rAddr net.Addr, + cfg *Config, + generateCertificate bool, +) (*Conn, error) { if generateCertificate { clientCert, err := selfsign.GenerateSelfSigned() if err != nil { @@ -295,14 +309,21 @@ func testClient(ctx context.Context, c net.PacketConn, rAddr net.Addr, cfg *Conf cfg.Certificates = []tls.Certificate{clientCert} } cfg.InsecureSkipVerify = true - conn, err := Client(c, rAddr, cfg) + conn, err := Client(pktConn, rAddr, cfg) if err != nil { return nil, err } + return conn, conn.HandshakeContext(ctx) } -func testServer(ctx context.Context, c net.PacketConn, rAddr net.Addr, cfg *Config, generateCertificate bool) (*Conn, error) { +func testServer( + ctx context.Context, + c net.PacketConn, + rAddr net.Addr, + cfg *Config, + generateCertificate bool, +) (*Conn, error) { if generateCertificate { serverCert, err := selfsign.GenerateSelfSigned() if err != nil { @@ -314,6 +335,7 @@ func testServer(ctx context.Context, c net.PacketConn, rAddr net.Addr, cfg *Conf if err != nil { return nil, err } + return conn, conn.HandshakeContext(ctx) } @@ -325,7 +347,7 @@ func sendClientHello(cookie []byte, ca net.Conn, sequenceNumber uint64, extensio }, Content: &handshake.Handshake{ Header: handshake.Header{ - MessageSequence: uint16(sequenceNumber), + MessageSequence: uint16(sequenceNumber), //nolint:gosec // G115 }, Message: &handshake.MessageClientHello{ Version: protocol.Version1_2, @@ -343,6 +365,7 @@ func sendClientHello(cookie []byte, ca net.Conn, sequenceNumber uint64, extensio if _, err = ca.Write(packet); err != nil { return err } + return nil } @@ -440,9 +463,13 @@ func TestHandshakeWithInvalidRecord(t *testing.T) { } } go func() { - client, err := testClient(ctx, dtlsnet.PacketConnFromConn(caWithInvalidRecord), caWithInvalidRecord.RemoteAddr(), &Config{ - CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, - }, true) + client, err := testClient( + ctx, + dtlsnet.PacketConnFromConn(caWithInvalidRecord), + caWithInvalidRecord.RemoteAddr(), + &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}}, + true, + ) clientErr <- result{client, err} }() @@ -475,7 +502,7 @@ func TestHandshakeWithInvalidRecord(t *testing.T) { } } -func TestExportKeyingMaterial(t *testing.T) { +func TestExportKeyingMaterial(t *testing.T) { //nolint:cyclop // Check for leaking routines report := test.CheckRoutines(t) defer report() @@ -486,7 +513,7 @@ func TestExportKeyingMaterial(t *testing.T) { expectedServerKey := []byte{0x61, 0x09, 0x9d, 0x7d, 0xcb, 0x08, 0x52, 0x2c, 0xe7, 0x7b} expectedClientKey := []byte{0x87, 0xf0, 0x40, 0x02, 0xf6, 0x1c, 0xf1, 0xfe, 0x8c, 0x77} - c := &Conn{ + conn := &Conn{ state: State{ localRandom: handshake.Random{GMTUnixTime: time.Unix(500, 0), RandomBytes: rand}, remoteRandom: handshake.Random{GMTUnixTime: time.Unix(1000, 0), RandomBytes: rand}, @@ -494,10 +521,10 @@ func TestExportKeyingMaterial(t *testing.T) { cipherSuite: &ciphersuite.TLSEcdheEcdsaWithAes128GcmSha256{}, }, } - c.setLocalEpoch(0) - c.setRemoteEpoch(0) + conn.setLocalEpoch(0) + conn.setRemoteEpoch(0) - state, ok := c.ConnectionState() + state, ok := conn.ConnectionState() if !ok { t.Fatal("ConnectionState failed") } @@ -506,8 +533,8 @@ func TestExportKeyingMaterial(t *testing.T) { t.Errorf("ExportKeyingMaterial when epoch == 0: expected '%s' actual '%s'", errHandshakeInProgress, err) } - c.setLocalEpoch(1) - state, ok = c.ConnectionState() + conn.setLocalEpoch(1) + state, ok = conn.ConnectionState() if !ok { t.Fatal("ConnectionState failed") } @@ -517,7 +544,7 @@ func TestExportKeyingMaterial(t *testing.T) { } for k := range invalidKeyingLabels() { - state, ok = c.ConnectionState() + state, ok = conn.ConnectionState() if !ok { t.Fatal("ConnectionState failed") } @@ -527,7 +554,7 @@ func TestExportKeyingMaterial(t *testing.T) { } } - state, ok = c.ConnectionState() + state, ok = conn.ConnectionState() if !ok { t.Fatal("ConnectionState failed") } @@ -538,8 +565,8 @@ func TestExportKeyingMaterial(t *testing.T) { t.Errorf("ExportKeyingMaterial client export: expected (% 02x) actual (% 02x)", expectedServerKey, keyingMaterial) } - c.state.isClient = true - state, ok = c.ConnectionState() + conn.state.isClient = true + state, ok = conn.ConnectionState() if !ok { t.Fatal("ConnectionState failed") } @@ -551,7 +578,7 @@ func TestExportKeyingMaterial(t *testing.T) { } } -func TestPSK(t *testing.T) { +func TestPSK(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -642,7 +669,10 @@ func TestPSK(t *testing.T) { conf := &Config{ PSK: func(hint []byte) ([]byte, error) { if !bytes.Equal(test.ServerIdentity, hint) { - return nil, fmt.Errorf("TestPSK: Client got invalid identity expected(% 02x) actual(% 02x)", test.ServerIdentity, hint) //nolint:goerr113 + return nil, fmt.Errorf( //nolint:goerr113 + "TestPSK: Client got invalid identity expected(% 02x) actual(% 02x)", + test.ServerIdentity, hint, + ) } return []byte{0xAB, 0xC1, 0x23}, nil @@ -662,6 +692,7 @@ func TestPSK(t *testing.T) { if !bytes.Equal(test.ClientIdentity, hint) { return nil, fmt.Errorf("%w: expected(% 02x) actual(% 02x)", errTestPSKInvalidIdentity, test.ClientIdentity, hint) } + return []byte{0xAB, 0xC1, 0x23}, nil }, PSKIdentityHint: test.ServerIdentity, @@ -678,6 +709,7 @@ func TestPSK(t *testing.T) { 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 { @@ -690,7 +722,10 @@ func TestPSK(t *testing.T) { } actualPSKIdentityHint := state.IdentityHint if !bytes.Equal(actualPSKIdentityHint, test.ClientIdentity) { - t.Errorf("TestPSK: Server ClientPSKIdentity Mismatch '%s': expected(%v) actual(%v)", test.Name, test.ClientIdentity, actualPSKIdentityHint) + t.Errorf( + "TestPSK: Server ClientPSKIdentity Mismatch '%s': expected(%v) actual(%v)", + test.Name, test.ClientIdentity, actualPSKIdentityHint, + ) } defer func() { @@ -744,7 +779,9 @@ func TestPSKHintFail(t *testing.T) { CipherSuites: []CipherSuiteID{TLS_PSK_WITH_AES_128_CCM_8}, } - if _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, false); !errors.Is(err, serverAlertError) { + if _, err := testServer( + ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, false, + ); !errors.Is(err, serverAlertError) { t.Fatalf("TestPSK: Server error exp(%v) failed(%v)", serverAlertError, err) } @@ -753,8 +790,8 @@ func TestPSKHintFail(t *testing.T) { } } -// Assert that ServerKeyExchange is only sent if Identity is set on server side -func TestPSKServerKeyExchange(t *testing.T) { +// Assert that ServerKeyExchange is only sent if Identity is set on server side. +func TestPSKServerKeyExchange(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -827,7 +864,9 @@ func TestPSKServerKeyExchange(t *testing.T) { config.PSKIdentityHint = []byte{0xAB, 0xC1, 0x23} } - if server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cbAnalyzer), cbAnalyzer.RemoteAddr(), config, false); err != nil { + if server, err := testServer( + ctx, dtlsnet.PacketConnFromConn(cbAnalyzer), cbAnalyzer.RemoteAddr(), config, false, + ); err != nil { t.Fatalf("TestPSK: Server error %v", err) } else { if err = server.Close(); err != nil { @@ -840,7 +879,10 @@ func TestPSKServerKeyExchange(t *testing.T) { } if gotServerKeyExchange != test.SetIdentity { - t.Fatalf("Mismatch between setting Identity and getting a ServerKeyExchange exp(%t) actual(%t)", test.SetIdentity, gotServerKeyExchange) + t.Fatalf( + "Mismatch between setting Identity and getting a ServerKeyExchange exp(%t) actual(%t)", + test.SetIdentity, gotServerKeyExchange, + ) } }) } @@ -879,7 +921,7 @@ func TestClientTimeout(t *testing.T) { } } -func TestSRTPConfiguration(t *testing.T) { +func TestSRTPConfiguration(t *testing.T) { //nolint:cyclop // Check for leaking routines report := test.CheckRoutines(t) defer report() @@ -953,16 +995,23 @@ func TestSRTPConfiguration(t *testing.T) { c *Conn err error } - c := make(chan result) + resultCh := make(chan result) go func() { - client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ClientSRTP, SRTPMasterKeyIdentifier: test.ServerSRTPMasterKeyIdentifier}, true) - c <- result{client, err} + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ + SRTPProtectionProfiles: test.ClientSRTP, SRTPMasterKeyIdentifier: test.ServerSRTPMasterKeyIdentifier, + }, true) + resultCh <- result{client, err} }() - server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{SRTPProtectionProfiles: test.ServerSRTP, SRTPMasterKeyIdentifier: test.ClientSRTPMasterKeyIdentifier}, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ + SRTPProtectionProfiles: test.ServerSRTP, SRTPMasterKeyIdentifier: test.ClientSRTPMasterKeyIdentifier, + }, true) if !errors.Is(err, test.WantServerError) { - t.Errorf("TestSRTPConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantServerError, err) + t.Errorf( + "TestSRTPConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", + test.Name, test.WantServerError, err, + ) } if err == nil { defer func() { @@ -970,14 +1019,17 @@ func TestSRTPConfiguration(t *testing.T) { }() } - res := <-c + res := <-resultCh if res.err == nil { defer func() { _ = res.c.Close() }() } if !errors.Is(res.err, test.WantClientError) { - t.Fatalf("TestSRTPConfiguration: Client Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantClientError, res.err) + t.Fatalf( + "TestSRTPConfiguration: Client Error Mismatch '%s': expected(%v) actual(%v)", + test.Name, test.WantClientError, res.err, + ) } if res.c == nil { return @@ -985,27 +1037,39 @@ func TestSRTPConfiguration(t *testing.T) { actualClientSRTP, _ := res.c.SelectedSRTPProtectionProfile() if actualClientSRTP != test.ExpectedProfile { - t.Errorf("TestSRTPConfiguration: Client SRTPProtectionProfile Mismatch '%s': expected(%v) actual(%v)", test.Name, test.ExpectedProfile, actualClientSRTP) + t.Errorf( + "TestSRTPConfiguration: Client SRTPProtectionProfile Mismatch '%s': expected(%v) actual(%v)", + test.Name, test.ExpectedProfile, actualClientSRTP, + ) } actualServerSRTP, _ := server.SelectedSRTPProtectionProfile() if actualServerSRTP != test.ExpectedProfile { - t.Errorf("TestSRTPConfiguration: Server SRTPProtectionProfile Mismatch '%s': expected(%v) actual(%v)", test.Name, test.ExpectedProfile, actualServerSRTP) + t.Errorf( + "TestSRTPConfiguration: Server SRTPProtectionProfile Mismatch '%s': expected(%v) actual(%v)", + test.Name, test.ExpectedProfile, actualServerSRTP, + ) } actualServerMKI, _ := server.RemoteSRTPMasterKeyIdentifier() if !bytes.Equal(actualServerMKI, test.ServerSRTPMasterKeyIdentifier) { - t.Errorf("TestSRTPConfiguration: Server SRTPMKI Mismatch '%s': expected(%v) actual(%v)", test.Name, test.ServerSRTPMasterKeyIdentifier, actualServerMKI) + t.Errorf( + "TestSRTPConfiguration: Server SRTPMKI Mismatch '%s': expected(%v) actual(%v)", + test.Name, test.ServerSRTPMasterKeyIdentifier, actualServerMKI, + ) } actualClientMKI, _ := res.c.RemoteSRTPMasterKeyIdentifier() if !bytes.Equal(actualClientMKI, test.ClientSRTPMasterKeyIdentifier) { - t.Errorf("TestSRTPConfiguration: Client SRTPMKI Mismatch '%s': expected(%v) actual(%v)", test.Name, test.ClientSRTPMasterKeyIdentifier, actualClientMKI) + t.Errorf( + "TestSRTPConfiguration: Client SRTPMKI Mismatch '%s': expected(%v) actual(%v)", + test.Name, test.ClientSRTPMasterKeyIdentifier, actualClientMKI, + ) } } } -func TestClientCertificate(t *testing.T) { +func TestClientCertificate(t *testing.T) { //nolint:gocyclo,cyclop,maintidx // Check for leaking routines report := test.CheckRoutines(t) defer report() @@ -1139,12 +1203,17 @@ func TestClientCertificate(t *testing.T) { wantErr: true, }, "RequireAndVerifyClientCert": { - 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 - }}, + 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, @@ -1153,6 +1222,7 @@ func TestClientCertificate(t *testing.T) { if ok := bytes.Equal(s.PeerCertificates[0], certificate.Raw); !ok { return errExample } + return nil }, }, @@ -1218,7 +1288,9 @@ func TestClientCertificate(t *testing.T) { t.Error("Server connection state not available") } actualClientCert := state.PeerCertificates - if tt.serverCfg.ClientAuth == RequireAnyClientCert || tt.serverCfg.ClientAuth == RequireAndVerifyClientCert { + //nolint:nestif + if tt.serverCfg.ClientAuth == RequireAnyClientCert || + tt.serverCfg.ClientAuth == RequireAndVerifyClientCert { if actualClientCert == nil { t.Errorf("Client did not provide a certificate") } @@ -1370,16 +1442,28 @@ func TestConnectionID(t *testing.T) { }() if !bytes.Equal(res.c.state.getLocalConnectionID(), tt.clientConnectionID) { - t.Errorf("Unexpected client local connection ID\nwant: %v\ngot:%v", tt.clientConnectionID, res.c.state.localConnectionID) + t.Errorf( + "Unexpected client local connection ID\nwant: %v\ngot:%v", + tt.clientConnectionID, res.c.state.localConnectionID, + ) } if !bytes.Equal(res.c.state.remoteConnectionID, tt.serverConnectionID) { - t.Errorf("Unexpected client remote connection ID\nwant: %v\ngot:%v", tt.serverConnectionID, res.c.state.remoteConnectionID) + t.Errorf( + "Unexpected client remote connection ID\nwant: %v\ngot:%v", + tt.serverConnectionID, res.c.state.remoteConnectionID, + ) } if !bytes.Equal(server.state.getLocalConnectionID(), tt.serverConnectionID) { - t.Errorf("Unexpected server local connection ID\nwant: %v\ngot:%v", tt.serverConnectionID, server.state.localConnectionID) + t.Errorf( + "Unexpected server local connection ID\nwant: %v\ngot:%v", + tt.serverConnectionID, server.state.localConnectionID, + ) } if !bytes.Equal(server.state.remoteConnectionID, tt.clientConnectionID) { - t.Errorf("Unexpected server remote connection ID\nwant: %v\ngot:%v", tt.clientConnectionID, server.state.remoteConnectionID) + t.Errorf( + "Unexpected server remote connection ID\nwant: %v\ngot:%v", + tt.clientConnectionID, server.state.remoteConnectionID, + ) } }) } @@ -1527,7 +1611,7 @@ func TestExtendedMasterSecret(t *testing.T) { } } -func TestServerCertificate(t *testing.T) { +func TestServerCertificate(t *testing.T) { //nolint:cyclop // Check for leaking routines report := test.CheckRoutines(t) defer report() @@ -1564,21 +1648,32 @@ func TestServerCertificate(t *testing.T) { }, "good_ca_skip_verify_custom_verify_peer": { clientCfg: &Config{RootCAs: caPool, Certificates: []tls.Certificate{cert}}, - serverCfg: &Config{Certificates: []tls.Certificate{cert}, ClientAuth: RequireAnyClientCert, VerifyPeerCertificate: func(_ [][]byte, chain [][]*x509.Certificate) error { - if len(chain) != 0 { - return errNotExpectedChain - } - return nil - }}, + serverCfg: &Config{ + Certificates: []tls.Certificate{cert}, + ClientAuth: RequireAnyClientCert, + VerifyPeerCertificate: func(_ [][]byte, chain [][]*x509.Certificate) error { + if len(chain) != 0 { + return errNotExpectedChain + } + + return nil + }, + }, }, "good_ca_verify_custom_verify_peer": { clientCfg: &Config{RootCAs: caPool, Certificates: []tls.Certificate{cert}}, - serverCfg: &Config{ClientCAs: caPool, Certificates: []tls.Certificate{cert}, ClientAuth: RequireAndVerifyClientCert, VerifyPeerCertificate: func(_ [][]byte, chain [][]*x509.Certificate) error { - if len(chain) == 0 { - return errExpecedChain - } - return nil - }}, + serverCfg: &Config{ + ClientCAs: caPool, + Certificates: []tls.Certificate{cert}, + ClientAuth: RequireAndVerifyClientCert, + VerifyPeerCertificate: func(_ [][]byte, chain [][]*x509.Certificate) error { + if len(chain) == 0 { + return errExpecedChain + } + + return nil + }, + }, }, "good_ca_custom_verify_peer": { clientCfg: &Config{ @@ -1695,8 +1790,10 @@ func TestCipherSuiteConfiguration(t *testing.T) { WantSelectedCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, }, { - Name: "Server supports subset of client suites", - ClientCipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, + Name: "Server supports subset of client suites", + ClientCipherSuites: []CipherSuiteID{ + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + }, ServerCipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, WantClientError: nil, WantServerError: nil, @@ -1713,33 +1810,46 @@ func TestCipherSuiteConfiguration(t *testing.T) { c *Conn err error } - c := make(chan result) + resultCh := make(chan result) go func() { - client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: test.ClientCipherSuites}, true) - c <- result{client, err} + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ + CipherSuites: test.ClientCipherSuites, + }, true) + resultCh <- result{client, err} }() - server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{CipherSuites: test.ServerCipherSuites}, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ + CipherSuites: test.ServerCipherSuites, + }, true) if err == nil { defer func() { _ = server.Close() }() } if !errors.Is(err, test.WantServerError) { - t.Errorf("TestCipherSuiteConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantServerError, err) + t.Errorf( + "TestCipherSuiteConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", + test.Name, test.WantServerError, err, + ) } - res := <-c + res := <-resultCh 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) + t.Errorf( + "TestSRTPConfiguration: Client Error Mismatch '%s': expected(%v) actual(%v)", + test.Name, test.WantClientError, res.err, + ) } if test.WantSelectedCipherSuite != 0x00 && res.c.state.cipherSuite.ID() != test.WantSelectedCipherSuite { - t.Errorf("TestCipherSuiteConfiguration: Server Selected Bad Cipher Suite '%s': expected(%v) actual(%v)", test.Name, test.WantSelectedCipherSuite, res.c.state.cipherSuite.ID()) + t.Errorf( + "TestCipherSuiteConfiguration: Server Selected Bad Cipher Suite '%s': expected(%v) actual(%v)", + test.Name, test.WantSelectedCipherSuite, res.c.state.cipherSuite.ID(), + ) } }) } @@ -1773,7 +1883,7 @@ func TestCertificateAndPSKServer(t *testing.T) { c *Conn err error } - c := make(chan result) + resultCh := make(chan result) go func() { config := &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}} @@ -1786,7 +1896,7 @@ func TestCertificateAndPSKServer(t *testing.T) { } client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), config, false) - c <- result{client, err} + resultCh <- result{client, err} }() config := &Config{ @@ -1805,18 +1915,21 @@ func TestCertificateAndPSKServer(t *testing.T) { t.Errorf("TestCertificateAndPSKServer: Server Error Mismatch '%s': expected(%v) actual(%v)", test.Name, nil, err) } - res := <-c + res := <-resultCh 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) + t.Errorf( + "TestCertificateAndPSKServer: Client Error Mismatch '%s': expected(%v) actual(%v)", + test.Name, nil, res.err, + ) } }) } } -func TestPSKConfiguration(t *testing.T) { +func TestPSKConfiguration(t *testing.T) { //nolint:cyclop // Check for leaking routines report := test.CheckRoutines(t) defer report() @@ -1885,30 +1998,50 @@ func TestPSKConfiguration(t *testing.T) { c *Conn err error } - c := make(chan result) + resultCh := make(chan result) go func() { - client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{PSK: test.ClientPSK, PSKIdentityHint: test.ClientPSKIdentity}, test.ClientHasCertificate) - c <- result{client, err} + client, err := testClient( + ctx, + dtlsnet.PacketConnFromConn(ca), + ca.RemoteAddr(), + &Config{PSK: test.ClientPSK, PSKIdentityHint: test.ClientPSKIdentity}, + test.ClientHasCertificate, + ) + resultCh <- result{client, err} }() - _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{PSK: test.ServerPSK, PSKIdentityHint: test.ServerPSKIdentity}, test.ServerHasCertificate) + _, err := testServer( + ctx, + dtlsnet.PacketConnFromConn(cb), + cb.RemoteAddr(), + &Config{PSK: test.ServerPSK, PSKIdentityHint: test.ServerPSKIdentity}, + test.ServerHasCertificate, + ) if err != nil || test.WantServerError != nil { if !(err != nil && test.WantServerError != nil && err.Error() == test.WantServerError.Error()) { - t.Fatalf("TestPSKConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantServerError, err) + t.Fatalf( + "TestPSKConfiguration: Server Error Mismatch '%s': expected(%v) actual(%v)", + test.Name, test.WantServerError, err, + ) } } - res := <-c + res := <-resultCh if res.err != nil || test.WantClientError != nil { if !(res.err != nil && test.WantClientError != nil && res.err.Error() == test.WantClientError.Error()) { - t.Fatalf("TestPSKConfiguration: Client Error Mismatch '%s': expected(%v) actual(%v)", test.Name, test.WantClientError, res.err) + t.Fatalf( + "TestPSKConfiguration: Client Error Mismatch '%s': expected(%v) actual(%v)", + test.Name, + test.WantClientError, + res.err, + ) } } } } -func TestServerTimeout(t *testing.T) { +func TestServerTimeout(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -2037,7 +2170,7 @@ func TestServerTimeout(t *testing.T) { } } -func TestProtocolVersionValidation(t *testing.T) { +func TestProtocolVersionValidation(t *testing.T) { //nolint:cyclop,maintidx // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -2118,8 +2251,8 @@ func TestProtocolVersionValidation(t *testing.T) { }, }, } - for name, c := range serverCases { - c := c + for name, serverCase := range serverCases { + serverCase := serverCase t.Run(name, func(t *testing.T) { ca, cb := dpipe.Pipe() defer func() { @@ -2137,7 +2270,13 @@ func TestProtocolVersionValidation(t *testing.T) { defer wg.Wait() go func() { defer wg.Done() - if _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, true); !errors.Is(err, errUnsupportedProtocolVersion) { + if _, err := testServer( + ctx, + dtlsnet.PacketConnFromConn(cb), + cb.RemoteAddr(), + config, + true, + ); !errors.Is(err, errUnsupportedProtocolVersion) { t.Errorf("Client error exp(%v) failed(%v)", errUnsupportedProtocolVersion, err) } }() @@ -2145,7 +2284,7 @@ func TestProtocolVersionValidation(t *testing.T) { time.Sleep(50 * time.Millisecond) resp := make([]byte, 1024) - for _, record := range c.records { + for _, record := range serverCase.records { packet, err := record.Marshal() if err != nil { t.Fatal(err) @@ -2198,9 +2337,13 @@ func TestProtocolVersionValidation(t *testing.T) { MessageSequence: 1, }, Message: &handshake.MessageServerHello{ - Version: protocol.Version{Major: 0xfe, Minor: 0xff}, // try to downgrade - Random: random, - CipherSuiteID: func() *uint16 { id := uint16(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256); return &id }(), + Version: protocol.Version{Major: 0xfe, Minor: 0xff}, // try to downgrade + Random: random, + CipherSuiteID: func() *uint16 { + id := uint16(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + + return &id + }(), CompressionMethod: defaultCompressionMethods()[0], }, }, @@ -2208,8 +2351,8 @@ func TestProtocolVersionValidation(t *testing.T) { }, }, } - for name, c := range clientCases { - c := c + for name, clientCase := range clientCases { + clientCase := clientCase t.Run(name, func(t *testing.T) { ca, cb := dpipe.Pipe() defer func() { @@ -2227,14 +2370,16 @@ func TestProtocolVersionValidation(t *testing.T) { defer wg.Wait() go func() { defer wg.Done() - if _, err := testClient(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, true); !errors.Is(err, errUnsupportedProtocolVersion) { + if _, err := testClient(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), config, true); !errors.Is( + err, errUnsupportedProtocolVersion, + ) { t.Errorf("Server error exp(%v) failed(%v)", errUnsupportedProtocolVersion, err) } }() time.Sleep(50 * time.Millisecond) - for _, record := range c.records { + for _, record := range clientCase.records { if _, err := ca.Read(make([]byte, 1024)); err != nil { t.Fatal(err) } @@ -2266,7 +2411,7 @@ func TestProtocolVersionValidation(t *testing.T) { }) } -func TestMultipleHelloVerifyRequest(t *testing.T) { +func TestMultipleHelloVerifyRequest(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -2294,7 +2439,7 @@ func TestMultipleHelloVerifyRequest(t *testing.T) { }, Content: &handshake.Handshake{ Header: handshake.Header{ - MessageSequence: uint16(i), + MessageSequence: uint16(i), //nolint:gosec // G115 }, Message: &handshake.MessageHelloVerifyRequest{ Version: protocol.Version1_2, @@ -2359,8 +2504,8 @@ func TestMultipleHelloVerifyRequest(t *testing.T) { } // Assert that a DTLS Server always responds with RenegotiationInfo if -// a ClientHello contained that extension or not -func TestRenegotationInfo(t *testing.T) { +// a ClientHello contained that extension or not. +func TestRenegotationInfo(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(10 * time.Second) defer lim.Stop() @@ -2397,7 +2542,13 @@ func TestRenegotationInfo(t *testing.T) { defer cancel() go func() { - if _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{}, true); !errors.Is(err, context.Canceled) { + if _, err := testServer( + ctx, + dtlsnet.PacketConnFromConn(cb), + cb.RemoteAddr(), + &Config{}, + true, + ); !errors.Is(err, context.Canceled) { t.Error(err) } }() @@ -2418,12 +2569,12 @@ func TestRenegotationInfo(t *testing.T) { if err != nil { t.Fatal(err) } - r := &recordlayer.RecordLayer{} - if err = r.Unmarshal(resp[:n]); err != nil { + record := &recordlayer.RecordLayer{} + if err = record.Unmarshal(resp[:n]); err != nil { t.Fatal(err) } - helloVerifyRequest, ok := r.Content.(*handshake.Handshake).Message.(*handshake.MessageHelloVerifyRequest) + helloVerifyRequest, ok := record.Content.(*handshake.Handshake).Message.(*handshake.MessageHelloVerifyRequest) if !ok { t.Fatal("Failed to cast MessageHelloVerifyRequest") } @@ -2441,11 +2592,11 @@ func TestRenegotationInfo(t *testing.T) { t.Fatal(err) } - if err := r.Unmarshal(messages[0]); err != nil { + if err := record.Unmarshal(messages[0]); err != nil { t.Fatal(err) } - serverHello, ok := r.Content.(*handshake.Handshake).Message.(*handshake.MessageServerHello) + serverHello, ok := record.Content.(*handshake.Handshake).Message.(*handshake.MessageServerHello) if !ok { t.Fatal("Failed to cast MessageServerHello") } @@ -2553,7 +2704,7 @@ func TestServerNameIndicationExtension(t *testing.T) { } } -func TestALPNExtension(t *testing.T) { +func TestALPNExtension(t *testing.T) { //nolint:cyclop,maintidx // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -2645,7 +2796,9 @@ func TestALPNExtension(t *testing.T) { conf := &Config{ SupportedProtocols: test.ServerProtocolNameList, } - if _, err2 := testServer(ctx2, dtlsnet.PacketConnFromConn(cb2), cb2.RemoteAddr(), conf, true); !errors.Is(err2, context.Canceled) { + if _, err2 := testServer(ctx2, dtlsnet.PacketConnFromConn(cb2), cb2.RemoteAddr(), conf, true); !errors.Is( + err2, context.Canceled, + ) { if test.ExpectAlertFromServer { //nolint // Assert the error type? } else { @@ -2697,13 +2850,13 @@ func TestALPNExtension(t *testing.T) { t.Fatal(err) } - r := &recordlayer.RecordLayer{} - if err := r.Unmarshal(messages[0]); err != nil { + record := &recordlayer.RecordLayer{} + if err := record.Unmarshal(messages[0]); err != nil { t.Fatal(err) } - if test.ExpectAlertFromServer { - a, ok := r.Content.(*alert.Alert) + if test.ExpectAlertFromServer { //nolint:nestif + a, ok := record.Content.(*alert.Alert) if !ok { t.Fatal("Failed to cast alert.Alert") } @@ -2712,7 +2865,7 @@ func TestALPNExtension(t *testing.T) { t.Errorf("ALPN %v: expected(%v) actual(%v)", test.Name, test.Alert, a.Description) } } else { - serverHello, ok := r.Content.(*handshake.Handshake).Message.(*handshake.MessageServerHello) + serverHello, ok := record.Content.(*handshake.Handshake).Message.(*handshake.MessageServerHello) if !ok { t.Fatal("Failed to cast handshake.MessageServerHello") } @@ -2738,7 +2891,7 @@ func TestALPNExtension(t *testing.T) { t.Errorf("ALPN %v: expected(%v) actual(%v)", test.Name, test.ExpectedProtocol, negotiatedProtocol) } - s, err := r.Marshal() + s, err := record.Marshal() if err != nil { t.Fatal(err) } @@ -2776,8 +2929,8 @@ func TestALPNExtension(t *testing.T) { } } -// Make sure the supported_groups extension is not included in the ServerHello -func TestSupportedGroupsExtension(t *testing.T) { +// Make sure the supported_groups extension is not included in the ServerHello. +func TestSupportedGroupsExtension(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -2792,7 +2945,9 @@ func TestSupportedGroupsExtension(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - if _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{}, true); !errors.Is(err, context.Canceled) { + if _, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{}, true); !errors.Is( + err, context.Canceled, + ) { t.Error(err) } }() @@ -2818,12 +2973,12 @@ func TestSupportedGroupsExtension(t *testing.T) { if err != nil { t.Fatal(err) } - r := &recordlayer.RecordLayer{} - if err = r.Unmarshal(resp[:n]); err != nil { + record := &recordlayer.RecordLayer{} + if err = record.Unmarshal(resp[:n]); err != nil { t.Fatal(err) } - helloVerifyRequest, ok := r.Content.(*handshake.Handshake).Message.(*handshake.MessageHelloVerifyRequest) + helloVerifyRequest, ok := record.Content.(*handshake.Handshake).Message.(*handshake.MessageHelloVerifyRequest) if !ok { t.Fatal("Failed to cast MessageHelloVerifyRequest") } @@ -2841,11 +2996,11 @@ func TestSupportedGroupsExtension(t *testing.T) { t.Fatal(err) } - if err := r.Unmarshal(messages[0]); err != nil { + if err := record.Unmarshal(messages[0]); err != nil { t.Fatal(err) } - serverHello, ok := r.Content.(*handshake.Handshake).Message.(*handshake.MessageServerHello) + serverHello, ok := record.Content.(*handshake.Handshake).Message.(*handshake.MessageServerHello) if !ok { t.Fatal("Failed to cast MessageServerHello") } @@ -2863,7 +3018,7 @@ func TestSupportedGroupsExtension(t *testing.T) { }) } -func TestSessionResume(t *testing.T) { +func TestSessionResume(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -2885,7 +3040,9 @@ func TestSessionResume(t *testing.T) { ss := &memSessStore{} id, _ := hex.DecodeString("9b9fc92255634d9fb109febed42166717bb8ded8c738ba71bc7f2a0d9dae0306") - secret, _ := hex.DecodeString("2e942a37aca5241deb2295b5fcedac221c7078d2503d2b62aeb48c880d7da73c001238b708559686b9da6e829c05ead7") + secret, _ := hex.DecodeString( + "2e942a37aca5241deb2295b5fcedac221c7078d2503d2b62aeb48c880d7da73c001238b708559686b9da6e829c05ead7", + ) s := Session{ID: id, Secret: secret} @@ -3034,7 +3191,8 @@ func (ms *memSessStore) Del(key []byte) error { // Assert that the server only uses CipherSuites with a hash+signature that matches // the certificate. As specified in rfc5246#section-7.4.3 -func TestCipherSuiteMatchesCertificateType(t *testing.T) { +// . +func TestCipherSuiteMatchesCertificateType(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -3068,7 +3226,9 @@ func TestCipherSuiteMatchesCertificateType(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - c, err := testClient(context.TODO(), dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: test.cipherList}, false) + c, err := testClient(context.TODO(), dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ + CipherSuites: test.cipherList, + }, false) clientErr <- err client <- c }() @@ -3113,8 +3273,8 @@ func TestCipherSuiteMatchesCertificateType(t *testing.T) { } } -// Test that we return the proper certificate if we are serving multiple ServerNames on a single Server -func TestMultipleServerCertificates(t *testing.T) { +// Test that we return the proper certificate if we are serving multiple ServerNames on a single Server. +func TestMultipleServerCertificates(t *testing.T) { //nolint:cyclop fooCert, err := selfsign.GenerateSelfSignedWithDNS("foo") if err != nil { t.Fatal(err) @@ -3158,7 +3318,7 @@ func TestMultipleServerCertificates(t *testing.T) { ca, cb := dpipe.Pipe() go func() { - c, err := testClient(context.TODO(), dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ + clientConn, err := testClient(context.TODO(), dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ RootCAs: caPool, ServerName: test.RequestServerName, VerifyPeerCertificate: func(rawCerts [][]byte, _ [][]*x509.Certificate) error { @@ -3175,10 +3335,12 @@ func TestMultipleServerCertificates(t *testing.T) { }, }, false) clientErr <- err - client <- c + client <- clientConn }() - if s, err := testServer(context.TODO(), dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{Certificates: []tls.Certificate{fooCert, barCert}}, false); err != nil { + if s, err := testServer(context.TODO(), dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{ + Certificates: []tls.Certificate{fooCert, barCert}, + }, false); err != nil { t.Fatal(err) } else if err = s.Close(); err != nil { t.Fatal(err) @@ -3193,7 +3355,7 @@ func TestMultipleServerCertificates(t *testing.T) { } } -func TestEllipticCurveConfiguration(t *testing.T) { +func TestEllipticCurveConfiguration(t *testing.T) { //nolint:cyclop // Check for leaking routines report := test.CheckRoutines(t) defer report() @@ -3227,25 +3389,39 @@ func TestEllipticCurveConfiguration(t *testing.T) { c *Conn err error } - c := make(chan result) + resultCh := make(chan result) go func() { - client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, EllipticCurves: test.ConfigCurves}, true) - c <- result{client, err} + client, err := testClient(ctx, dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{ + CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + EllipticCurves: test.ConfigCurves, + }, true) + resultCh <- result{client, err} }() - server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, EllipticCurves: test.ConfigCurves}, true) + server, err := testServer(ctx, dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &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.HandshakeCurves) != len(server.fsm.cfg.ellipticCurves) { - t.Fatalf("Failed to default Elliptic curves, expected %d, got: %d", len(test.HandshakeCurves), len(server.fsm.cfg.ellipticCurves)) + t.Fatalf( + "Failed to default Elliptic curves, expected %d, got: %d", + len(test.HandshakeCurves), + len(server.fsm.cfg.ellipticCurves), + ) } if len(test.ConfigCurves) != 0 { if len(test.HandshakeCurves) != len(server.fsm.cfg.ellipticCurves) { - t.Fatalf("Failed to configure Elliptic curves, expect %d, got %d", len(test.HandshakeCurves), len(server.fsm.cfg.ellipticCurves)) + t.Fatalf( + "Failed to configure Elliptic curves, expect %d, got %d", + len(test.HandshakeCurves), + len(server.fsm.cfg.ellipticCurves), + ) } for i, c := range test.ConfigCurves { if c != server.fsm.cfg.ellipticCurves[i] { @@ -3254,7 +3430,7 @@ func TestEllipticCurveConfiguration(t *testing.T) { } } - res := <-c + res := <-resultCh if res.err != nil { t.Fatalf("Client error; %v", err) } @@ -3293,6 +3469,7 @@ func TestSkipHelloVerify(t *testing.T) { }, false) if sErr != nil { t.Error(sErr) + return } buf := make([]byte, 1024) @@ -3336,6 +3513,7 @@ func (c *connWithCallback) Write(b []byte) (int, error) { if c.onWrite != nil { c.onWrite(b) } + return c.Conn.Write(b) } @@ -3360,6 +3538,7 @@ func TestApplicationDataQueueLimited(t *testing.T) { serverCert, err := selfsign.GenerateSelfSigned() if err != nil { t.Error(err) + return } cfg := &Config{} @@ -3368,6 +3547,7 @@ func TestApplicationDataQueueLimited(t *testing.T) { dconn, err := createConn(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), cfg, false, nil) if err != nil { t.Error(err) + return } go func() { @@ -3422,7 +3602,7 @@ func TestApplicationDataQueueLimited(t *testing.T) { <-done } -func TestHelloRandom(t *testing.T) { +func TestHelloRandom(t *testing.T) { //nolint:cyclop report := test.CheckRoutines(t) defer report() ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) @@ -3458,6 +3638,7 @@ func TestHelloRandom(t *testing.T) { }, false) if sErr != nil { t.Error(sErr) + return } buf := make([]byte, 1024) @@ -3510,6 +3691,7 @@ func TestOnConnectionAttempt(t *testing.T) { if in == nil { t.Fatal("net.Addr is nil") //nolint: govet } + return nil }, }, true) @@ -3523,6 +3705,7 @@ func TestOnConnectionAttempt(t *testing.T) { if in == nil { t.Fatal("net.Addr is nil") //nolint: govet } + return expectedErr }, }, true); !errors.Is(err, expectedErr) { @@ -3544,7 +3727,10 @@ func TestOnConnectionAttempt(t *testing.T) { func TestFragmentBuffer_Retransmission(t *testing.T) { fragmentBuffer := newFragmentBuffer() - frag := []byte{0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x30, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x01, 0x01} + frag := []byte{ + 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x30, 0x03, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x01, 0x01, + } if _, isRetransmission, err := fragmentBuffer.push(frag); err != nil { t.Fatal(err) @@ -3589,10 +3775,10 @@ func TestConnectionState(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - c := make(chan error) + errorChannel := make(chan error) go func() { errC := client.HandshakeContext(ctx) - c <- errC + errorChannel <- errC }() // Setup server @@ -3604,7 +3790,7 @@ func TestConnectionState(t *testing.T) { _ = server.Close() }() - err = <-c + err = <-errorChannel if err != nil { t.Fatal(err) } diff --git a/connection_id.go b/connection_id.go index f0e94631b..c590499b4 100644 --- a/connection_id.go +++ b/connection_id.go @@ -21,6 +21,7 @@ func RandomCIDGenerator(size int) func() []byte { if _, err := rand.Read(cid); err != nil { panic(err) //nolint -- nonrecoverable } + return cid } } @@ -54,8 +55,10 @@ func cidDatagramRouter(size int) func([]byte) (string, bool) { if h.ContentType != protocol.ContentTypeConnectionID { continue } + return string(h.ConnectionID), true } + return "", false } } @@ -65,7 +68,7 @@ func cidDatagramRouter(size int) func([]byte) (string, bool) { // NOTE: a ServerHello should always be the first record in a datagram if // multiple are present, so we avoid iterating through all packets if the first // is not a ServerHello. -func cidConnIdentifier() func([]byte) (string, bool) { +func cidConnIdentifier() func([]byte) (string, bool) { //nolint:cyclop return func(packet []byte) (string, bool) { pkts, err := recordlayer.UnpackDatagram(packet) if err != nil || len(pkts) < 1 { @@ -96,6 +99,7 @@ func cidConnIdentifier() func([]byte) (string, bool) { return string(e.CID), true } } + return "", false } } diff --git a/connection_id_test.go b/connection_id_test.go index 8936aba98..aba5f72d0 100644 --- a/connection_id_test.go +++ b/connection_id_test.go @@ -85,7 +85,7 @@ func TestCIDDatagramRouter(t *testing.T) { Epoch: 1, Version: protocol.Version1_2, ContentType: protocol.ContentTypeConnectionID, - ContentLen: uint16(len(inner)), + ContentLen: uint16(len(inner)), //nolint:gosec // G115 ConnectionID: cid, SequenceNumber: 1, }).Marshal() @@ -128,6 +128,7 @@ func TestCIDDatagramRouter(t *testing.T) { want: string(cid), }, "OneRecordConnectionIDAltLength": { + //nolint:lll reason: "If datagram contains one Connection ID record, but it has the wrong length we should not be able to extract it.", size: cidLen, datagram: func() []byte { @@ -135,19 +136,21 @@ func TestCIDDatagramRouter(t *testing.T) { Epoch: 1, Version: protocol.Version1_2, ContentType: protocol.ContentTypeConnectionID, - ContentLen: uint16(len(inner)), + ContentLen: uint16(len(inner)), //nolint:gosec // G115 ConnectionID: []byte("abcd"), SequenceNumber: 1, }).Marshal() if err != nil { t.Fatal(err) } + return append(altCIDHeader, inner...) }(), ok: false, want: "", }, "MultipleRecordOneConnectionID": { + //nolint:lll reason: "If datagram contains multiple records and one is a Connection ID record, we should be able to extract it.", size: 8, datagram: append(append(appRecord, cidHeader...), inner...), @@ -155,6 +158,7 @@ func TestCIDDatagramRouter(t *testing.T) { want: string(cid), }, "MultipleRecordMultipleConnectionID": { + //nolint:lll reason: "If datagram contains multiple records and multiple are Connection ID records, we should extract the first one.", size: 8, datagram: append(append(append(appRecord, func() []byte { @@ -162,13 +166,14 @@ func TestCIDDatagramRouter(t *testing.T) { Epoch: 1, Version: protocol.Version1_2, ContentType: protocol.ContentTypeConnectionID, - ContentLen: uint16(len(inner)), + ContentLen: uint16(len(inner)), //nolint:gosec // G115 ConnectionID: []byte("1234abcd"), SequenceNumber: 1, }).Marshal() if err != nil { t.Fatal(err) } + return append(altCIDHeader, inner...) }()...), cidHeader...), inner...), ok: true, @@ -257,12 +262,14 @@ func TestCIDConnIdentifier(t *testing.T) { want: string(cid), }, "MultipleRecordFirstServerHello": { + //nolint:lll reason: "If datagram contains multiple records and the first is a ServerHello record, we should be able to extract an identifier.", datagram: append(sh, appRecord...), ok: true, want: string(cid), }, "MultipleRecordNotFirstServerHello": { + //nolint:lll reason: "If datagram contains multiple records and the first is not a ServerHello record, we should not be able to extract an identifier.", datagram: append(appRecord, sh...), ok: false, diff --git a/crypto.go b/crypto.go index 25b2a1f9f..04b39d442 100644 --- a/crypto.go +++ b/crypto.go @@ -43,7 +43,12 @@ func valueKeyMessage(clientRandom, serverRandom, publicKey []byte, namedCurve el // hash/signature algorithm pair that appears in that extension // // https://tools.ietf.org/html/rfc5246#section-7.4.2 -func generateKeySignature(clientRandom, serverRandom, publicKey []byte, namedCurve elliptic.Curve, privateKey crypto.PrivateKey, hashAlgorithm hash.Algorithm) ([]byte, error) { +func generateKeySignature( + clientRandom, serverRandom, publicKey []byte, + namedCurve elliptic.Curve, + privateKey crypto.PrivateKey, + hashAlgorithm hash.Algorithm, +) ([]byte, error) { msg := valueKeyMessage(clientRandom, serverRandom, publicKey, namedCurve) switch p := privateKey.(type) { case ed25519.PrivateKey: @@ -51,16 +56,23 @@ func generateKeySignature(clientRandom, serverRandom, publicKey []byte, namedCur return p.Sign(rand.Reader, msg, crypto.Hash(0)) case *ecdsa.PrivateKey: hashed := hashAlgorithm.Digest(msg) + return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) case *rsa.PrivateKey: hashed := hashAlgorithm.Digest(msg) + return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) } return nil, errKeySignatureGenerateUnimplemented } -func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.Algorithm, rawCertificates [][]byte) error { //nolint:dupl +//nolint:dupl,cyclop +func verifyKeySignature( + message, remoteKeySignature []byte, + hashAlgorithm hash.Algorithm, + rawCertificates [][]byte, +) error { if len(rawCertificates) == 0 { return errLengthMismatch } @@ -69,11 +81,12 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A return err } - switch p := certificate.PublicKey.(type) { + switch pubKey := certificate.PublicKey.(type) { case ed25519.PublicKey: - if ok := ed25519.Verify(p, message, remoteKeySignature); !ok { + if ok := ed25519.Verify(pubKey, message, remoteKeySignature); !ok { return errKeySignatureMismatch } + return nil case *ecdsa.PublicKey: ecdsaSig := &ecdsaSignature{} @@ -84,15 +97,17 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A return errInvalidECDSASignature } hashed := hashAlgorithm.Digest(message) - if !ecdsa.Verify(p, hashed, ecdsaSig.R, ecdsaSig.S) { + if !ecdsa.Verify(pubKey, hashed, ecdsaSig.R, ecdsaSig.S) { return errKeySignatureMismatch } + return nil case *rsa.PublicKey: hashed := hashAlgorithm.Digest(message) - if rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature) != nil { + if rsa.VerifyPKCS1v15(pubKey, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature) != nil { return errKeySignatureMismatch } + return nil } @@ -107,7 +122,11 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A // CertificateVerify message is sent to explicitly verify possession of // the private key in the certificate. // https://tools.ietf.org/html/rfc5246#section-7.3 -func generateCertificateVerify(handshakeBodies []byte, privateKey crypto.PrivateKey, hashAlgorithm hash.Algorithm) ([]byte, error) { +func generateCertificateVerify( + handshakeBodies []byte, + privateKey crypto.PrivateKey, + hashAlgorithm hash.Algorithm, +) ([]byte, error) { if p, ok := privateKey.(ed25519.PrivateKey); ok { // https://pkg.go.dev/crypto/ed25519#PrivateKey.Sign // Sign signs the given message with priv. Ed25519 performs two passes over @@ -127,7 +146,13 @@ func generateCertificateVerify(handshakeBodies []byte, privateKey crypto.Private return nil, errInvalidSignatureAlgorithm } -func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorithm, remoteKeySignature []byte, rawCertificates [][]byte) error { //nolint:dupl +//nolint:dupl,cyclop +func verifyCertificateVerify( + handshakeBodies []byte, + hashAlgorithm hash.Algorithm, + remoteKeySignature []byte, + rawCertificates [][]byte, +) error { if len(rawCertificates) == 0 { return errLengthMismatch } @@ -136,11 +161,12 @@ func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorith return err } - switch p := certificate.PublicKey.(type) { + switch pubKey := certificate.PublicKey.(type) { case ed25519.PublicKey: - if ok := ed25519.Verify(p, handshakeBodies, remoteKeySignature); !ok { + if ok := ed25519.Verify(pubKey, handshakeBodies, remoteKeySignature); !ok { return errKeySignatureMismatch } + return nil case *ecdsa.PublicKey: ecdsaSig := &ecdsaSignature{} @@ -151,15 +177,17 @@ func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorith return errInvalidECDSASignature } hash := hashAlgorithm.Digest(handshakeBodies) - if !ecdsa.Verify(p, hash, ecdsaSig.R, ecdsaSig.S) { + if !ecdsa.Verify(pubKey, hash, ecdsaSig.R, ecdsaSig.S) { return errKeySignatureMismatch } + return nil case *rsa.PublicKey: hash := hashAlgorithm.Digest(handshakeBodies) - if rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hash, remoteKeySignature) != nil { + if rsa.VerifyPKCS1v15(pubKey, hashAlgorithm.CryptoHash(), hash, remoteKeySignature) != nil { return errKeySignatureMismatch } + return nil } @@ -179,6 +207,7 @@ func loadCerts(rawCertificates [][]byte) ([]*x509.Certificate, error) { } certs = append(certs, cert) } + return certs, nil } @@ -197,10 +226,15 @@ func verifyClientCert(rawCertificates [][]byte, roots *x509.CertPool) (chains [] Intermediates: intermediateCAPool, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, } + return certificate[0].Verify(opts) } -func verifyServerCert(rawCertificates [][]byte, roots *x509.CertPool, serverName string) (chains [][]*x509.Certificate, err error) { +func verifyServerCert( + rawCertificates [][]byte, + roots *x509.CertPool, + serverName string, +) (chains [][]*x509.Certificate, err error) { certificate, err := loadCerts(rawCertificates) if err != nil { return nil, err @@ -215,5 +249,6 @@ func verifyServerCert(rawCertificates [][]byte, roots *x509.CertPool, serverName DNSName: serverName, Intermediates: intermediateCAPool, } + return certificate[0].Verify(opts) } diff --git a/crypto_test.go b/crypto_test.go index e3f572eb5..249ca2cdc 100644 --- a/crypto_test.go +++ b/crypto_test.go @@ -51,21 +51,34 @@ func TestGenerateKeySignature(t *testing.T) { t.Error(err) } - clientRandom := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f} - serverRandom := []byte{0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f} - publicKey := []byte{0x20, 0x9f, 0xd7, 0xad, 0x6d, 0xcf, 0xf4, 0x29, 0x8d, 0xd3, 0xf9, 0x6d, 0x5b, 0x1b, 0x2a, 0xf9, 0x10, 0xa0, 0x53, 0x5b, 0x14, 0x88, 0xd7, 0xf8, 0xfa, 0xbb, 0x34, 0x9a, 0x98, 0x28, 0x80, 0xb6, 0x15} + clientRandom := []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + } + serverRandom := []byte{ + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + } + publicKey := []byte{ + 0x20, 0x9f, 0xd7, 0xad, 0x6d, 0xcf, 0xf4, 0x29, 0x8d, 0xd3, 0xf9, 0x6d, 0x5b, 0x1b, 0x2a, 0xf9, 0x10, + 0xa0, 0x53, 0x5b, 0x14, 0x88, 0xd7, 0xf8, 0xfa, 0xbb, 0x34, 0x9a, 0x98, 0x28, 0x80, 0xb6, 0x15, + } expectedSignature := []byte{ - 0x6f, 0x47, 0x97, 0x85, 0xcc, 0x76, 0x50, 0x93, 0xbd, 0xe2, 0x6a, 0x69, 0x0b, 0xc3, 0x03, 0xd1, 0xb7, 0xe4, 0xab, 0x88, 0x7b, 0xa6, 0x52, 0x80, 0xdf, - 0xaa, 0x25, 0x7a, 0xdb, 0x29, 0x32, 0xe4, 0xd8, 0x28, 0x28, 0xb3, 0xe8, 0x04, 0x3c, 0x38, 0x16, 0xfc, 0x78, 0xe9, 0x15, 0x7b, 0xc5, 0xbd, 0x7d, 0xfc, - 0xcd, 0x83, 0x00, 0x57, 0x4a, 0x3c, 0x23, 0x85, 0x75, 0x6b, 0x37, 0xd5, 0x89, 0x72, 0x73, 0xf0, 0x44, 0x8c, 0x00, 0x70, 0x1f, 0x6e, 0xa2, 0x81, 0xd0, - 0x09, 0xc5, 0x20, 0x36, 0xab, 0x23, 0x09, 0x40, 0x1f, 0x4d, 0x45, 0x96, 0x62, 0xbb, 0x81, 0xb0, 0x30, 0x72, 0xad, 0x3a, 0x0a, 0xac, 0x31, 0x63, 0x40, - 0x52, 0x0a, 0x27, 0xf3, 0x34, 0xde, 0x27, 0x7d, 0xb7, 0x54, 0xff, 0x0f, 0x9f, 0x5a, 0xfe, 0x07, 0x0f, 0x4e, 0x9f, 0x53, 0x04, 0x34, 0x62, 0xf4, 0x30, - 0x74, 0x83, 0x35, 0xfc, 0xe4, 0x7e, 0xbf, 0x5a, 0xc4, 0x52, 0xd0, 0xea, 0xf9, 0x61, 0x4e, 0xf5, 0x1c, 0x0e, 0x58, 0x02, 0x71, 0xfb, 0x1f, 0x34, 0x55, - 0xe8, 0x36, 0x70, 0x3c, 0xc1, 0xcb, 0xc9, 0xb7, 0xbb, 0xb5, 0x1c, 0x44, 0x9a, 0x6d, 0x88, 0x78, 0x98, 0xd4, 0x91, 0x2e, 0xeb, 0x98, 0x81, 0x23, 0x30, - 0x73, 0x39, 0x43, 0xd5, 0xbb, 0x70, 0x39, 0xba, 0x1f, 0xdb, 0x70, 0x9f, 0x91, 0x83, 0x56, 0xc2, 0xde, 0xed, 0x17, 0x6d, 0x2c, 0x3e, 0x21, 0xea, 0x36, - 0xb4, 0x91, 0xd8, 0x31, 0x05, 0x60, 0x90, 0xfd, 0xc6, 0x74, 0xa9, 0x7b, 0x18, 0xfc, 0x1c, 0x6a, 0x1c, 0x6e, 0xec, 0xd3, 0xc1, 0xc0, 0x0d, 0x11, 0x25, - 0x48, 0x37, 0x3d, 0x45, 0x11, 0xa2, 0x31, 0x14, 0x0a, 0x66, 0x9f, 0xd8, 0xac, 0x74, 0xa2, 0xcd, 0xc8, 0x79, 0xb3, 0x9e, 0xc6, 0x66, 0x25, 0xcf, 0x2c, - 0x87, 0x5e, 0x5c, 0x36, 0x75, 0x86, + 0x6f, 0x47, 0x97, 0x85, 0xcc, 0x76, 0x50, 0x93, 0xbd, 0xe2, 0x6a, 0x69, 0x0b, 0xc3, 0x03, 0xd1, 0xb7, 0xe4, + 0xab, 0x88, 0x7b, 0xa6, 0x52, 0x80, 0xdf, 0xaa, 0x25, 0x7a, 0xdb, 0x29, 0x32, 0xe4, 0xd8, 0x28, 0x28, 0xb3, + 0xe8, 0x04, 0x3c, 0x38, 0x16, 0xfc, 0x78, 0xe9, 0x15, 0x7b, 0xc5, 0xbd, 0x7d, 0xfc, 0xcd, 0x83, 0x00, 0x57, + 0x4a, 0x3c, 0x23, 0x85, 0x75, 0x6b, 0x37, 0xd5, 0x89, 0x72, 0x73, 0xf0, 0x44, 0x8c, 0x00, 0x70, 0x1f, 0x6e, + 0xa2, 0x81, 0xd0, 0x09, 0xc5, 0x20, 0x36, 0xab, 0x23, 0x09, 0x40, 0x1f, 0x4d, 0x45, 0x96, 0x62, 0xbb, 0x81, + 0xb0, 0x30, 0x72, 0xad, 0x3a, 0x0a, 0xac, 0x31, 0x63, 0x40, 0x52, 0x0a, 0x27, 0xf3, 0x34, 0xde, 0x27, 0x7d, + 0xb7, 0x54, 0xff, 0x0f, 0x9f, 0x5a, 0xfe, 0x07, 0x0f, 0x4e, 0x9f, 0x53, 0x04, 0x34, 0x62, 0xf4, 0x30, 0x74, + 0x83, 0x35, 0xfc, 0xe4, 0x7e, 0xbf, 0x5a, 0xc4, 0x52, 0xd0, 0xea, 0xf9, 0x61, 0x4e, 0xf5, 0x1c, 0x0e, 0x58, + 0x02, 0x71, 0xfb, 0x1f, 0x34, 0x55, 0xe8, 0x36, 0x70, 0x3c, 0xc1, 0xcb, 0xc9, 0xb7, 0xbb, 0xb5, 0x1c, 0x44, + 0x9a, 0x6d, 0x88, 0x78, 0x98, 0xd4, 0x91, 0x2e, 0xeb, 0x98, 0x81, 0x23, 0x30, 0x73, 0x39, 0x43, 0xd5, 0xbb, + 0x70, 0x39, 0xba, 0x1f, 0xdb, 0x70, 0x9f, 0x91, 0x83, 0x56, 0xc2, 0xde, 0xed, 0x17, 0x6d, 0x2c, 0x3e, 0x21, + 0xea, 0x36, 0xb4, 0x91, 0xd8, 0x31, 0x05, 0x60, 0x90, 0xfd, 0xc6, 0x74, 0xa9, 0x7b, 0x18, 0xfc, 0x1c, 0x6a, + 0x1c, 0x6e, 0xec, 0xd3, 0xc1, 0xc0, 0x0d, 0x11, 0x25, 0x48, 0x37, 0x3d, 0x45, 0x11, 0xa2, 0x31, 0x14, 0x0a, + 0x66, 0x9f, 0xd8, 0xac, 0x74, 0xa2, 0xcd, 0xc8, 0x79, 0xb3, 0x9e, 0xc6, 0x66, 0x25, 0xcf, 0x2c, 0x87, 0x5e, + 0x5c, 0x36, 0x75, 0x86, } signature, err := generateKeySignature(clientRandom, serverRandom, publicKey, elliptic.X25519, key, hash.SHA256) diff --git a/e2e/e2e_lossy_test.go b/e2e/e2e_lossy_test.go index 5be97eb4c..e70130cdc 100644 --- a/e2e/e2e_lossy_test.go +++ b/e2e/e2e_lossy_test.go @@ -21,10 +21,9 @@ const ( lossyTestTimeout = 30 * time.Second ) -/* -DTLS Client/Server over a lossy transport, just asserts it can handle at increasing increments -*/ -func TestPionE2ELossy(t *testing.T) { +// DTLS Client/Server over a lossy transport, just asserts it can handle at increasing increments + +func TestPionE2ELossy(t *testing.T) { //nolint:cyclop // Check for leaking routines report := transportTest.CheckRoutines(t) defer report() @@ -213,20 +212,32 @@ func TestPionE2ELossy(t *testing.T) { select { case serverResult := <-serverDone: if serverResult.err != nil { - t.Errorf("Fail, serverError: clientComplete(%t) serverComplete(%t) LossChance(%d) error(%v)", clientConn != nil, serverConn != nil, chosenLoss, serverResult.err) + t.Errorf( + "Fail, serverError: clientComplete(%t) serverComplete(%t) LossChance(%d) error(%v)", + clientConn != nil, serverConn != nil, chosenLoss, serverResult.err, + ) + return } serverConn = serverResult.dtlsConn case clientResult := <-clientDone: if clientResult.err != nil { - t.Errorf("Fail, clientError: clientComplete(%t) serverComplete(%t) LossChance(%d) error(%v)", clientConn != nil, serverConn != nil, chosenLoss, clientResult.err) + t.Errorf( + "Fail, clientError: clientComplete(%t) serverComplete(%t) LossChance(%d) error(%v)", + clientConn != nil, serverConn != nil, chosenLoss, clientResult.err, + ) + return } clientConn = clientResult.dtlsConn case <-testTimer.C: - t.Errorf("Test expired: clientComplete(%t) serverComplete(%t) LossChance(%d)", clientConn != nil, serverConn != nil, chosenLoss) + t.Errorf( + "Test expired: clientComplete(%t) serverComplete(%t) LossChance(%d)", + clientConn != nil, serverConn != nil, chosenLoss, + ) + return case <-time.After(10 * time.Millisecond): } diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 06f9b78fb..f02d1507f 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -41,11 +41,11 @@ var ( errHookAPLNFailed = errors.New("hook failed to modify APLN extension") ) -func randomPort(t testing.TB) int { - t.Helper() +func randomPort(tb testing.TB) int { + tb.Helper() conn, err := net.ListenPacket("udp4", "127.0.0.1:0") if err != nil { - t.Fatalf("failed to pickPort: %v", err) + tb.Fatalf("failed to pickPort: %v", err) } defer func() { _ = conn.Close() @@ -54,7 +54,8 @@ func randomPort(t testing.TB) int { case *net.UDPAddr: return addr.Port default: - t.Fatalf("unknown addr type %T", addr) + tb.Fatalf("unknown addr type %T", addr) + return 0 } } @@ -65,6 +66,7 @@ func simpleReadWrite(errChan chan error, outChan chan string, conn io.ReadWriter n, err := conn.Read(buffer) if err != nil { errChan <- err + return } @@ -77,6 +79,7 @@ func simpleReadWrite(errChan chan error, outChan chan string, conn io.ReadWriter break } else if _, err := conn.Write([]byte(testMessage)); err != nil { errChan <- err + break } @@ -85,7 +88,7 @@ func simpleReadWrite(errChan chan error, outChan chan string, conn io.ReadWriter } type comm struct { - ctx context.Context + ctx context.Context //nolint:containedctx clientConfig, serverConfig *dtls.Config serverPort int messageRecvCount *uint64 // Counter to make sure both sides got a message @@ -104,9 +107,15 @@ type comm struct { server func(*comm) } -func newComm(ctx context.Context, clientConfig, serverConfig *dtls.Config, serverPort int, server, client func(*comm)) *comm { +func newComm( + ctx context.Context, + clientConfig, serverConfig *dtls.Config, + serverPort int, + server, client func(*comm), +) *comm { messageRecvCount := uint64(0) - c := &comm{ + + com := &comm{ ctx: ctx, clientConfig: clientConfig, serverConfig: serverConfig, @@ -123,10 +132,13 @@ func newComm(ctx context.Context, clientConfig, serverConfig *dtls.Config, serve server: server, client: client, } - return c + + return com } -func (c *comm) assert(t *testing.T) { +func (c *comm) assert(t *testing.T) { //nolint:cyclop + t.Helper() + // DTLS Client go c.client(c) @@ -182,7 +194,9 @@ func (c *comm) assert(t *testing.T) { }() } -func (c *comm) cleanup(t *testing.T) { +func (c *comm) cleanup(t *testing.T) { //nolint:cyclop + t.Helper() + clientDone, serverDone := false, false for { select { @@ -208,7 +222,7 @@ func (c *comm) cleanup(t *testing.T) { } } -func clientPion(c *comm) { +func clientPion(c *comm) { //nolint:varnamelen select { case <-c.serverReady: // OK @@ -225,11 +239,13 @@ func clientPion(c *comm) { ) if err != nil { c.errChan <- err + return } if err := conn.HandshakeContext(c.ctx); err != nil { c.errChan <- err + return } @@ -240,7 +256,7 @@ func clientPion(c *comm) { close(c.clientDone) } -func serverPion(c *comm) { +func serverPion(c *comm) { //nolint:varnamelen c.serverMutex.Lock() defer c.serverMutex.Unlock() @@ -251,12 +267,14 @@ func serverPion(c *comm) { ) if err != nil { c.errChan <- err + return } c.serverReady <- struct{}{} c.serverConn, err = c.serverListener.Accept() if err != nil { c.errChan <- err + return } @@ -264,6 +282,7 @@ func serverPion(c *comm) { if ok { if err := dtlsConn.HandshakeContext(c.ctx); err != nil { c.errChan <- err + return } } @@ -281,13 +300,12 @@ func withConnectionIDGenerator(g func() []byte) dtlsConfOpts { } } -/* - 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), opts ...dtlsConfOpts) { + t.Helper() lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -326,6 +344,8 @@ func testPionE2ESimple(t *testing.T, server, client func(*comm), opts ...dtlsCon } func testPionE2ESimplePSK(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { + t.Helper() + lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -363,6 +383,8 @@ func testPionE2ESimplePSK(t *testing.T, server, client func(*comm), opts ...dtls } func testPionE2EMTUs(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { + t.Helper() + lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -402,6 +424,8 @@ func testPionE2EMTUs(t *testing.T, server, client func(*comm), opts ...dtlsConfO } func testPionE2ESimpleED25519(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { + t.Helper() + lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -446,6 +470,8 @@ func testPionE2ESimpleED25519(t *testing.T, server, client func(*comm), opts ... } func testPionE2ESimpleED25519ClientCert(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { + t.Helper() + lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -494,6 +520,8 @@ func testPionE2ESimpleED25519ClientCert(t *testing.T, server, client func(*comm) } func testPionE2ESimpleECDSAClientCert(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { + t.Helper() + lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -542,6 +570,8 @@ func testPionE2ESimpleECDSAClientCert(t *testing.T, server, client func(*comm), } func testPionE2ESimpleRSAClientCert(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { + t.Helper() + lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -590,6 +620,8 @@ func testPionE2ESimpleRSAClientCert(t *testing.T, server, client func(*comm), op } func testPionE2ESimpleClientHelloHook(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { + t.Helper() + lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -617,11 +649,13 @@ func testPionE2ESimpleClientHelloHook(t *testing.T, server, client func(*comm), if s.CipherSuiteID != modifiedCipher { return errHookCiphersFailed } + return nil }, CipherSuites: supportedList, ClientHelloMessageHook: func(ch handshake.MessageClientHello) handshake.Message { ch.CipherSuiteIDs = []uint16{uint16(modifiedCipher)} + return &ch }, InsecureSkipVerify: true, @@ -645,6 +679,8 @@ func testPionE2ESimpleClientHelloHook(t *testing.T, server, client func(*comm), } func testPionE2ESimpleServerHelloHook(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { + t.Helper() + lim := test.TimeOut(time.Second * 30) defer lim.Stop() @@ -670,6 +706,7 @@ func testPionE2ESimpleServerHelloHook(t *testing.T, server, client func(*comm), if s.NegotiatedProtocol != apln { return errHookAPLNFailed } + return nil }, CipherSuites: supportedList, @@ -683,6 +720,7 @@ func testPionE2ESimpleServerHelloHook(t *testing.T, server, client func(*comm), sh.Extensions = append(sh.Extensions, &extension.ALPN{ ProtocolNameList: []string{apln}, }) + return &sh }, InsecureSkipVerify: true, diff --git a/errors.go b/errors.go index f03fb11c0..b7f93b7b4 100644 --- a/errors.go +++ b/errors.go @@ -15,65 +15,133 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/alert" ) -// Typed errors +// Typed errors. var ( ErrConnClosed = &FatalError{Err: errors.New("conn is closed")} //nolint:goerr113 errDeadlineExceeded = &TimeoutError{Err: fmt.Errorf("read/write timeout: %w", context.DeadlineExceeded)} errInvalidContentType = &TemporaryError{Err: errors.New("invalid content type")} //nolint:goerr113 - errBufferTooSmall = &TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 - errContextUnsupported = &TemporaryError{Err: errors.New("context is not supported for ExportKeyingMaterial")} //nolint:goerr113 - errHandshakeInProgress = &TemporaryError{Err: errors.New("handshake is in progress")} //nolint:goerr113 - errReservedExportKeyingMaterial = &TemporaryError{Err: errors.New("ExportKeyingMaterial can not be used with a reserved label")} //nolint:goerr113 - errApplicationDataEpochZero = &TemporaryError{Err: errors.New("ApplicationData with epoch of 0")} //nolint:goerr113 - errUnhandledContextType = &TemporaryError{Err: errors.New("unhandled contentType")} //nolint:goerr113 - - errCertificateVerifyNoCertificate = &FatalError{Err: errors.New("client sent certificate verify but we have no certificate to verify")} //nolint:goerr113 - errCipherSuiteNoIntersection = &FatalError{Err: errors.New("client+server do not support any shared cipher suites")} //nolint:goerr113 - errClientCertificateNotVerified = &FatalError{Err: errors.New("client sent certificate but did not verify it")} //nolint:goerr113 - errClientCertificateRequired = &FatalError{Err: errors.New("server required client verification, but got none")} //nolint:goerr113 - errClientNoMatchingSRTPProfile = &FatalError{Err: errors.New("server responded with SRTP Profile we do not support")} //nolint:goerr113 - errClientRequiredButNoServerEMS = &FatalError{Err: errors.New("client required Extended Master Secret extension, but server does not support it")} //nolint:goerr113 - errCookieMismatch = &FatalError{Err: errors.New("client+server cookie does not match")} //nolint:goerr113 - errIdentityNoPSK = &FatalError{Err: errors.New("PSK Identity Hint provided but PSK is nil")} //nolint:goerr113 - errInvalidCertificate = &FatalError{Err: errors.New("no certificate provided")} //nolint:goerr113 - errInvalidCipherSuite = &FatalError{Err: errors.New("invalid or unknown cipher suite")} //nolint:goerr113 - errInvalidECDSASignature = &FatalError{Err: errors.New("ECDSA signature contained zero or negative values")} //nolint:goerr113 - errInvalidPrivateKey = &FatalError{Err: errors.New("invalid private key type")} //nolint:goerr113 - errInvalidSignatureAlgorithm = &FatalError{Err: errors.New("invalid signature algorithm")} //nolint:goerr113 - errKeySignatureMismatch = &FatalError{Err: errors.New("expected and actual key signature do not match")} //nolint:goerr113 - errNilNextConn = &FatalError{Err: errors.New("Conn can not be created with a nil nextConn")} //nolint:goerr113 - errNoAvailableCipherSuites = &FatalError{Err: errors.New("connection can not be created, no CipherSuites satisfy this Config")} //nolint:goerr113 - errNoAvailablePSKCipherSuite = &FatalError{Err: errors.New("connection can not be created, pre-shared key present but no compatible CipherSuite")} //nolint:goerr113 - errNoAvailableCertificateCipherSuite = &FatalError{Err: errors.New("connection can not be created, certificate present but no compatible CipherSuite")} //nolint:goerr113 - errNoAvailableSignatureSchemes = &FatalError{Err: errors.New("connection can not be created, no SignatureScheme satisfy this Config")} //nolint:goerr113 - errNoCertificates = &FatalError{Err: errors.New("no certificates configured")} //nolint:goerr113 - errNoConfigProvided = &FatalError{Err: errors.New("no config provided")} //nolint:goerr113 - errNoSupportedEllipticCurves = &FatalError{Err: errors.New("client requested zero or more elliptic curves that are not supported by the server")} //nolint:goerr113 - errUnsupportedProtocolVersion = &FatalError{Err: errors.New("unsupported protocol version")} //nolint:goerr113 - errPSKAndIdentityMustBeSetForClient = &FatalError{Err: errors.New("PSK and PSK Identity Hint must both be set for client")} //nolint:goerr113 - errRequestedButNoSRTPExtension = &FatalError{Err: errors.New("SRTP support was requested but server did not respond with use_srtp extension")} //nolint:goerr113 - 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 - errKeySignatureVerifyUnimplemented = &InternalError{Err: errors.New("unable to verify key signature, unimplemented")} //nolint:goerr113 - errLengthMismatch = &InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113 - errSequenceNumberOverflow = &InternalError{Err: errors.New("sequence number overflow")} //nolint:goerr113 - errInvalidFSMTransition = &InternalError{Err: errors.New("invalid state machine transition")} //nolint:goerr113 - errFailedToAccessPoolReadBuffer = &InternalError{Err: errors.New("failed to access pool read buffer")} //nolint:goerr113 - errFragmentBufferOverflow = &InternalError{Err: errors.New("fragment buffer overflow")} //nolint:goerr113 + //nolint:goerr113 + errBufferTooSmall = &TemporaryError{Err: errors.New("buffer is too small")} + //nolint:goerr113 + errContextUnsupported = &TemporaryError{Err: errors.New("context is not supported for ExportKeyingMaterial")} + //nolint:goerr113 + errHandshakeInProgress = &TemporaryError{Err: errors.New("handshake is in progress")} + //nolint:goerr113 + errReservedExportKeyingMaterial = &TemporaryError{ + Err: errors.New("ExportKeyingMaterial can not be used with a reserved label"), + } + //nolint:goerr113 + errApplicationDataEpochZero = &TemporaryError{Err: errors.New("ApplicationData with epoch of 0")} + //nolint:goerr113 + errUnhandledContextType = &TemporaryError{Err: errors.New("unhandled contentType")} + + //nolint:goerr113 + errCertificateVerifyNoCertificate = &FatalError{ + Err: errors.New("client sent certificate verify but we have no certificate to verify"), + } + //nolint:goerr113 + errCipherSuiteNoIntersection = &FatalError{Err: errors.New("client+server do not support any shared cipher suites")} + //nolint:goerr113 + errClientCertificateNotVerified = &FatalError{Err: errors.New("client sent certificate but did not verify it")} + //nolint:goerr113 + errClientCertificateRequired = &FatalError{Err: errors.New("server required client verification, but got none")} + //nolint:goerr113 + errClientNoMatchingSRTPProfile = &FatalError{Err: errors.New("server responded with SRTP Profile we do not support")} + //nolint:goerr113 + errClientRequiredButNoServerEMS = &FatalError{ + Err: errors.New("client required Extended Master Secret extension, but server does not support it"), + } + //nolint:goerr113 + errCookieMismatch = &FatalError{Err: errors.New("client+server cookie does not match")} + //nolint:goerr113 + errIdentityNoPSK = &FatalError{Err: errors.New("PSK Identity Hint provided but PSK is nil")} + //nolint:goerr113 + errInvalidCertificate = &FatalError{Err: errors.New("no certificate provided")} + //nolint:goerr113 + errInvalidCipherSuite = &FatalError{Err: errors.New("invalid or unknown cipher suite")} + //nolint:goerr113 + errInvalidECDSASignature = &FatalError{Err: errors.New("ECDSA signature contained zero or negative values")} + //nolint:goerr113 + errInvalidPrivateKey = &FatalError{Err: errors.New("invalid private key type")} + //nolint:goerr113 + errInvalidSignatureAlgorithm = &FatalError{Err: errors.New("invalid signature algorithm")} + //nolint:goerr113 + errKeySignatureMismatch = &FatalError{Err: errors.New("expected and actual key signature do not match")} + //nolint:goerr113 + errNilNextConn = &FatalError{Err: errors.New("Conn can not be created with a nil nextConn")} + //nolint:goerr113 + errNoAvailableCipherSuites = &FatalError{ + Err: errors.New("connection can not be created, no CipherSuites satisfy this Config"), + } + //nolint:goerr113 + errNoAvailablePSKCipherSuite = &FatalError{ + Err: errors.New("connection can not be created, pre-shared key present but no compatible CipherSuite"), + } + //nolint:goerr113 + errNoAvailableCertificateCipherSuite = &FatalError{ + Err: errors.New("connection can not be created, certificate present but no compatible CipherSuite"), + } + //nolint:goerr113 + errNoAvailableSignatureSchemes = &FatalError{ + Err: errors.New("connection can not be created, no SignatureScheme satisfy this Config"), + } + //nolint:goerr113 + errNoCertificates = &FatalError{Err: errors.New("no certificates configured")} + //nolint:goerr113 + errNoConfigProvided = &FatalError{Err: errors.New("no config provided")} + //nolint:goerr113 + errNoSupportedEllipticCurves = &FatalError{ + Err: errors.New("client requested zero or more elliptic curves that are not supported by the server"), + } + //nolint:goerr113 + errUnsupportedProtocolVersion = &FatalError{Err: errors.New("unsupported protocol version")} + //nolint:goerr113 + errPSKAndIdentityMustBeSetForClient = &FatalError{ + Err: errors.New("PSK and PSK Identity Hint must both be set for client"), + } + //nolint:goerr113 + errRequestedButNoSRTPExtension = &FatalError{ + Err: errors.New("SRTP support was requested but server did not respond with use_srtp extension"), + } + //nolint:goerr113 + 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 + errKeySignatureVerifyUnimplemented = &InternalError{Err: errors.New("unable to verify key signature, unimplemented")} + //nolint:goerr113 + errLengthMismatch = &InternalError{Err: errors.New("data length and declared length do not match")} + //nolint:goerr113 + errSequenceNumberOverflow = &InternalError{Err: errors.New("sequence number overflow")} + //nolint:goerr113 + errInvalidFSMTransition = &InternalError{Err: errors.New("invalid state machine transition")} + //nolint:goerr113 + errFailedToAccessPoolReadBuffer = &InternalError{Err: errors.New("failed to access pool read buffer")} + //nolint:goerr113 + errFragmentBufferOverflow = &InternalError{Err: errors.New("fragment buffer overflow")} ) // FatalError indicates that the DTLS connection is no longer available. // It is mainly caused by wrong configuration of server or client. type FatalError = protocol.FatalError -// InternalError indicates and internal error caused by the implementation, and the DTLS connection is no longer available. +// InternalError indicates and internal error caused by the implementation, +// and the DTLS connection is no longer available. // It is mainly caused by bugs or tried to use unimplemented features. type InternalError = protocol.InternalError @@ -100,10 +168,11 @@ func (e *invalidCipherSuiteError) Is(err error) bool { if errors.As(err, &other) { return e.id == other.id } + return false } -// errAlert wraps DTLS alert notification as an error +// errAlert wraps DTLS alert notification as an error. type alertError struct { *alert.Alert } @@ -121,6 +190,7 @@ func (e *alertError) Is(err error) bool { if errors.As(err, &other) { return e.Level == other.Level && e.Description == other.Description } + return false } @@ -138,7 +208,7 @@ func netError(err error) error { se *os.SyscallError ) - if errors.As(err, &opError) { + if errors.As(err, &opError) { //nolint:nestif if errors.As(opError, &se) { if se.Timeout() { return &TimeoutError{Err: err} diff --git a/errors_test.go b/errors_test.go index 05c2c2745..db3bffc59 100644 --- a/errors_test.go +++ b/errors_test.go @@ -65,21 +65,21 @@ func TestErrorNetError(t *testing.T) { {&HandshakeError{Err: errExample}, "handshake error: an example error", false, false}, {&HandshakeError{Err: &TimeoutError{Err: errExample}}, "handshake error: dtls timeout: an example error", true, true}, } - for _, c := range cases { - c := c - t.Run(fmt.Sprintf("%T", c.err), func(t *testing.T) { + for _, testCase := range cases { + testCase := testCase + t.Run(fmt.Sprintf("%T", testCase.err), func(t *testing.T) { var ne net.Error - if !errors.As(c.err, &ne) { - t.Fatalf("%T doesn't implement net.Error", c.err) + if !errors.As(testCase.err, &ne) { + t.Fatalf("%T doesn't implement net.Error", testCase.err) } - if ne.Timeout() != c.timeout { - t.Errorf("%T.Timeout() should be %v", c.err, c.timeout) + if ne.Timeout() != testCase.timeout { + t.Errorf("%T.Timeout() should be %v", testCase.err, testCase.timeout) } - if ne.Temporary() != c.temporary { //nolint:staticcheck - t.Errorf("%T.Temporary() should be %v", c.err, c.temporary) + if ne.Temporary() != testCase.temporary { //nolint:staticcheck + t.Errorf("%T.Temporary() should be %v", testCase.err, testCase.temporary) } - if ne.Error() != c.str { - t.Errorf("%T.Error() should be %v", c.err, c.str) + if ne.Error() != testCase.str { + t.Errorf("%T.Error() should be %v", testCase.err, testCase.str) } }) } diff --git a/examples/dial/cid/main.go b/examples/dial/cid/main.go index b52631f1a..15f316137 100644 --- a/examples/dial/cid/main.go +++ b/examples/dial/cid/main.go @@ -26,6 +26,7 @@ func main() { config := &dtls.Config{ PSK: func(hint []byte) ([]byte, error) { fmt.Printf("Server's hint: %s \n", hint) + return []byte{0xAB, 0xC1, 0x23}, nil }, PSKIdentityHint: []byte("Pion DTLS Client"), @@ -45,6 +46,7 @@ func main() { if err := dtlsConn.HandshakeContext(ctx); err != nil { fmt.Printf("Failed to handshake with server: %v\n", err) + return } diff --git a/examples/dial/psk/main.go b/examples/dial/psk/main.go index 112826bbc..2847d40c7 100644 --- a/examples/dial/psk/main.go +++ b/examples/dial/psk/main.go @@ -26,6 +26,7 @@ func main() { config := &dtls.Config{ PSK: func(hint []byte) ([]byte, error) { fmt.Printf("Server's hint: %s \n", hint) + return []byte{0xAB, 0xC1, 0x23}, nil }, PSKIdentityHint: []byte{}, @@ -44,6 +45,7 @@ func main() { if err := dtlsConn.HandshakeContext(ctx); err != nil { fmt.Printf("Failed to handshake with server: %v\n", err) + return } diff --git a/examples/dial/selfsign/main.go b/examples/dial/selfsign/main.go index 7d86adf13..66ff80a70 100644 --- a/examples/dial/selfsign/main.go +++ b/examples/dial/selfsign/main.go @@ -46,6 +46,7 @@ func main() { if err := dtlsConn.HandshakeContext(ctx); err != nil { fmt.Printf("Failed to handshake with server: %v\n", err) + return } diff --git a/examples/dial/verify/main.go b/examples/dial/verify/main.go index e572aec2d..32992a9d1 100644 --- a/examples/dial/verify/main.go +++ b/examples/dial/verify/main.go @@ -53,6 +53,7 @@ func main() { if err := dtlsConn.HandshakeContext(ctx); err != nil { fmt.Printf("Failed to handshake with server: %v\n", err) + return } diff --git a/examples/listen/cid/main.go b/examples/listen/cid/main.go index 7418d895b..2c0b41ee6 100644 --- a/examples/listen/cid/main.go +++ b/examples/listen/cid/main.go @@ -26,6 +26,7 @@ func main() { config := &dtls.Config{ PSK: func(hint []byte) ([]byte, error) { fmt.Printf("Client's hint: %s \n", hint) + return []byte{0xAB, 0xC1, 0x23}, nil }, PSKIdentityHint: []byte("Pion DTLS Server"), diff --git a/examples/listen/psk/main.go b/examples/listen/psk/main.go index 041b1fb4e..4098e0dfe 100644 --- a/examples/listen/psk/main.go +++ b/examples/listen/psk/main.go @@ -26,6 +26,7 @@ func main() { config := &dtls.Config{ PSK: func(hint []byte) ([]byte, error) { fmt.Printf("Client's hint: %s \n", hint) + return []byte{0xAB, 0xC1, 0x23}, nil }, PSKIdentityHint: []byte("Pion DTLS Server"), diff --git a/examples/util/hub.go b/examples/util/hub.go index 19e33db0c..4e656a21f 100644 --- a/examples/util/hub.go +++ b/examples/util/hub.go @@ -12,18 +12,18 @@ import ( "sync" ) -// Hub is a helper to handle one to many chat +// Hub is a helper to handle one to many chat. type Hub struct { conns map[string]net.Conn lock sync.RWMutex } -// NewHub builds a new hub +// NewHub builds a new hub. func NewHub() *Hub { return &Hub{conns: make(map[string]net.Conn)} } -// Register adds a new conn to the Hub +// Register adds a new conn to the Hub. func (h *Hub) Register(conn net.Conn) { fmt.Printf("Connected to %s\n", conn.RemoteAddr()) h.lock.Lock() @@ -40,6 +40,7 @@ func (h *Hub) readLoop(conn net.Conn) { n, err := conn.Read(b) if err != nil { h.unregister(conn) + return } fmt.Printf("Got message: %s\n", string(b[:n])) @@ -69,7 +70,7 @@ func (h *Hub) broadcast(msg []byte) { } } -// Chat starts the stdin readloop to dispatch messages to the hub +// Chat starts the stdin readloop to dispatch messages to the hub. func (h *Hub) Chat() { reader := bufio.NewReader(os.Stdin) for { diff --git a/examples/util/util.go b/examples/util/util.go index e15a2f360..e3a85cb0e 100644 --- a/examples/util/util.go +++ b/examples/util/util.go @@ -24,7 +24,7 @@ var ( errNoCertificateFound = errors.New("no certificate found, unable to load certificates") ) -// Chat simulates a simple text chat session over the connection +// Chat simulates a simple text chat session over the connection. func Chat(conn io.ReadWriter) { go func() { b := make([]byte, bufSize) @@ -51,7 +51,7 @@ func Chat(conn io.ReadWriter) { } } -// Check is a helper to throw errors in the examples +// Check is a helper to throw errors in the examples. func Check(err error) { var netError net.Error if errors.As(err, &netError) && netError.Temporary() { //nolint:staticcheck @@ -62,12 +62,12 @@ func Check(err error) { } } -// LoadKeyAndCertificate reads certificates or key from file +// LoadKeyAndCertificate reads certificates or key from file. func LoadKeyAndCertificate(keyPath string, certificatePath string) (tls.Certificate, error) { return tls.LoadX509KeyPair(certificatePath, keyPath) } -// LoadCertificate Load/read certificate(s) from file +// LoadCertificate Load/read certificate(s) from file. func LoadCertificate(path string) (*tls.Certificate, error) { rawData, err := os.ReadFile(filepath.Clean(path)) if err != nil { diff --git a/flight.go b/flight.go index cfa58c574..7ecc9489d 100644 --- a/flight.go +++ b/flight.go @@ -70,7 +70,7 @@ const ( flight6 ) -func (f flightVal) String() string { +func (f flightVal) String() string { //nolint:cyclop switch f { case flight0: return "Flight 0" diff --git a/flight0handler.go b/flight0handler.go index 7bb528f1a..ce6ad2031 100644 --- a/flight0handler.go +++ b/flight0handler.go @@ -14,7 +14,14 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/handshake" ) -func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +//nolint:cyclop +func flight0Parse( + _ context.Context, + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { seq, msgs, ok := cache.fullPullMap(0, state.cipherSuite, handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false}, ) @@ -55,32 +62,32 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak } for _, val := range clientHello.Extensions { - switch e := val.(type) { + switch ext := val.(type) { case *extension.SupportedEllipticCurves: - if len(e.EllipticCurves) == 0 { + if len(ext.EllipticCurves) == 0 { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errNoSupportedEllipticCurves } - state.namedCurve = e.EllipticCurves[0] + state.namedCurve = ext.EllipticCurves[0] case *extension.UseSRTP: - profile, ok := findMatchingSRTPProfile(e.ProtectionProfiles, cfg.localSRTPProtectionProfiles) + profile, ok := findMatchingSRTPProfile(ext.ProtectionProfiles, cfg.localSRTPProtectionProfiles) if !ok { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errServerNoMatchingSRTPProfile } state.setSRTPProtectionProfile(profile) - state.remoteSRTPMasterKeyIdentifier = e.MasterKeyIdentifier + state.remoteSRTPMasterKeyIdentifier = ext.MasterKeyIdentifier case *extension.UseExtendedMasterSecret: if cfg.extendedMasterSecret != DisableExtendedMasterSecret { state.extendedMasterSecret = true } case *extension.ServerName: - state.serverName = e.ServerName // remote server name + state.serverName = ext.ServerName // remote server name case *extension.ALPN: - state.peerSupportedProtocols = e.ProtocolNameList + state.peerSupportedProtocols = ext.ProtocolNameList case *extension.ConnectionID: // Only set connection ID to be sent if server supports connection // IDs. if cfg.connectionIDGenerator != nil { - state.remoteConnectionID = e.CID + state.remoteConnectionID = ext.CID } } } @@ -112,7 +119,12 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak return handleHelloResume(clientHello.SessionID, state, cfg, nextFlight) } -func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, next flightVal) (flightVal, *alert.Alert, error) { +func handleHelloResume( + sessionID []byte, + state *State, + cfg *handshakeConfig, + next flightVal, +) (flightVal, *alert.Alert, error) { if len(sessionID) > 0 && cfg.sessionStore != nil { if s, err := cfg.sessionStore.Get(sessionID); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err @@ -132,10 +144,16 @@ func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, nex return flight4b, nil, nil } } + return next, nil, nil } -func flight0Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +func flight0Generate( + _ flightConn, + state *State, + _ *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { // Initialize if !cfg.insecureSkipHelloVerify { state.cookie = make([]byte, cookieLength) diff --git a/flight1handler.go b/flight1handler.go index 60215c084..6c55a6430 100644 --- a/flight1handler.go +++ b/flight1handler.go @@ -14,7 +14,13 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight1Parse( + ctx context.Context, + conn flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { // HelloVerifyRequest can be skipped by the server, // so allow ServerHello during flight1 also seq, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite, @@ -29,7 +35,7 @@ func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handsh if _, ok := msgs[handshake.TypeServerHello]; ok { // Flight1 and flight2 were skipped. // Parse as flight3. - return flight3Parse(ctx, c, state, cache, cfg) + return flight3Parse(ctx, conn, state, cache, cfg) } if h, ok := msgs[handshake.TypeHelloVerifyRequest].(*handshake.MessageHelloVerifyRequest); ok { @@ -40,13 +46,20 @@ func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handsh } state.cookie = append([]byte{}, h.Cookie...) state.handshakeRecvSequence = seq + return flight3, nil, nil } return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, nil } -func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +//nolint:cyclop +func flight1Generate( + conn flightConn, + state *State, + _ *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { var zeroEpoch uint16 state.localEpoch.Store(zeroEpoch) state.remoteEpoch.Store(zeroEpoch) @@ -74,6 +87,7 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha for _, c := range cfg.localCipherSuites { if c.ECC() { setEllipticCurveCryptographyClientHelloExtensions = true + break } } @@ -113,7 +127,7 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha if cfg.sessionStore != nil { cfg.log.Tracef("[handshake] try to resume session") - if s, err := cfg.sessionStore.Get(c.sessionKey()); err != nil { + if s, err := cfg.sessionStore.Get(conn.sessionKey()); err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } else if s.ID != nil { cfg.log.Tracef("[handshake] get saved session: %x", s.ID) diff --git a/flight1handler_test.go b/flight1handler_test.go index f6dc46c3e..457ee413b 100644 --- a/flight1handler_test.go +++ b/flight1handler_test.go @@ -34,13 +34,14 @@ type flight1TestMockCipherSuite struct { func (f *flight1TestMockCipherSuite) IsInitialized() bool { f.t.Fatal("IsInitialized called with Certificate but not CertificateVerify") + return true } // When "server hello" arrives later than "certificate", // "server key exchange", "certificate request", "server hello done", -// is it normal for the flight1Parse method to handle it -func TestFlight1_Process_ServerHelloLateArrival(t *testing.T) { +// is it normal for the flight1Parse method to handle it. +func TestFlight1_Process_ServerHelloLateArrival(t *testing.T) { //nolint:maintidx // Limit runtime in case of deadlocks lim := test.TimeOut(5 * time.Second) defer lim.Stop() diff --git a/flight2handler.go b/flight2handler.go index 0af457c35..8d50befba 100644 --- a/flight2handler.go +++ b/flight2handler.go @@ -13,7 +13,13 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight2Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight2Parse( + ctx context.Context, + c flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { seq, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite, handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false}, ) @@ -41,11 +47,18 @@ func flight2Parse(ctx context.Context, c flightConn, state *State, cache *handsh if !bytes.Equal(state.cookie, clientHello.Cookie) { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.AccessDenied}, errCookieMismatch } + return flight4, nil, nil } -func flight2Generate(_ flightConn, state *State, _ *handshakeCache, _ *handshakeConfig) ([]*packet, *alert.Alert, error) { +func flight2Generate( + _ flightConn, + state *State, + _ *handshakeCache, + _ *handshakeConfig, +) ([]*packet, *alert.Alert, error) { state.handshakeSendSequence = 0 + return []*packet{ { record: &recordlayer.RecordLayer{ diff --git a/flight3handler.go b/flight3handler.go index f27c01a7e..7301e34b6 100644 --- a/flight3handler.go +++ b/flight3handler.go @@ -17,7 +17,14 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { //nolint:gocognit +//nolint:gocognit,gocyclo,maintidx,cyclop +func flight3Parse( + ctx context.Context, + conn flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { // Clients may receive multiple HelloVerifyRequest messages with different cookies. // Clients SHOULD handle this by sending a new ClientHello with a cookie in response // to the new HelloVerifyRequest. RFC 6347 Section 4.2.1 @@ -33,6 +40,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh } state.cookie = append([]byte{}, h.Cookie...) state.handshakeRecvSequence = seq + return flight3, nil, nil } } @@ -45,33 +53,36 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, nil, nil } - if h, msgOk := msgs[handshake.TypeServerHello].(*handshake.MessageServerHello); msgOk { - if !h.Version.Equal(protocol.Version1_2) { + if serverHelloMsg, msgOk := msgs[handshake.TypeServerHello].(*handshake.MessageServerHello); msgOk { //nolint:nestif + if !serverHelloMsg.Version.Equal(protocol.Version1_2) { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.ProtocolVersion}, errUnsupportedProtocolVersion } - for _, v := range h.Extensions { - switch e := v.(type) { + for _, v := range serverHelloMsg.Extensions { + switch ext := v.(type) { case *extension.UseSRTP: - profile, found := findMatchingSRTPProfile(e.ProtectionProfiles, cfg.localSRTPProtectionProfiles) + profile, found := findMatchingSRTPProfile(ext.ProtectionProfiles, cfg.localSRTPProtectionProfiles) if !found { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, errClientNoMatchingSRTPProfile } state.setSRTPProtectionProfile(profile) - state.remoteSRTPMasterKeyIdentifier = e.MasterKeyIdentifier + state.remoteSRTPMasterKeyIdentifier = ext.MasterKeyIdentifier case *extension.UseExtendedMasterSecret: if cfg.extendedMasterSecret != DisableExtendedMasterSecret { state.extendedMasterSecret = true } case *extension.ALPN: - if len(e.ProtocolNameList) > 1 { // This should be exactly 1, the zero case is handle when unmarshalling - return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, extension.ErrALPNInvalidFormat // Meh, internal error? + if len(ext.ProtocolNameList) > 1 { // This should be exactly 1, the zero case is handle when unmarshalling + return 0, &alert.Alert{ + Level: alert.Fatal, + Description: alert.InternalError, + }, extension.ErrALPNInvalidFormat // Meh, internal error? } - state.NegotiatedProtocol = e.ProtocolNameList[0] + state.NegotiatedProtocol = ext.ProtocolNameList[0] case *extension.ConnectionID: // Only set connection ID to be sent if client supports connection // IDs. if cfg.connectionIDGenerator != nil { - state.remoteConnectionID = e.CID + state.remoteConnectionID = ext.CID } } } @@ -88,7 +99,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errRequestedButNoSRTPExtension } - remoteCipherSuite := cipherSuiteForID(CipherSuiteID(*h.CipherSuiteID), cfg.customCipherSuites) + remoteCipherSuite := cipherSuiteForID(CipherSuiteID(*serverHelloMsg.CipherSuiteID), cfg.customCipherSuites) if remoteCipherSuite == nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errCipherSuiteNoIntersection } @@ -99,11 +110,11 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh } state.cipherSuite = selectedCipherSuite - state.remoteRandom = h.Random + state.remoteRandom = serverHelloMsg.Random cfg.log.Tracef("[handshake] use cipher suite: %s", selectedCipherSuite.String()) - if len(h.SessionID) > 0 && bytes.Equal(state.SessionID, h.SessionID) { - return handleResumption(ctx, c, state, cache, cfg) + if len(serverHelloMsg.SessionID) > 0 && bytes.Equal(state.SessionID, serverHelloMsg.SessionID) { + return handleResumption(ctx, conn, state, cache, cfg) } if len(state.SessionID) > 0 { @@ -116,7 +127,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh if cfg.sessionStore == nil { state.SessionID = []byte{} } else { - state.SessionID = h.SessionID + state.SessionID = serverHelloMsg.SessionID } state.masterSecret = []byte{} @@ -148,7 +159,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh } if h, ok := msgs[handshake.TypeServerKeyExchange].(*handshake.MessageServerKeyExchange); ok { - alertPtr, err := handleServerKeyExchange(c, state, cfg, h) + alertPtr, err := handleServerKeyExchange(conn, state, cfg, h) if err != nil { return 0, alertPtr, err } @@ -162,7 +173,13 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh return flight5, nil, nil } -func handleResumption(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func handleResumption( + ctx context.Context, + c flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { if err := state.initCipherSuite(); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -203,25 +220,36 @@ func handleResumption(ctx context.Context, c flightConn, state *State, cache *ha return flight5b, nil, nil } -func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h *handshake.MessageServerKeyExchange) (*alert.Alert, error) { +//nolint:cyclop +func handleServerKeyExchange( + _ flightConn, + state *State, + cfg *handshakeConfig, + keyExchangeMessage *handshake.MessageServerKeyExchange, +) (*alert.Alert, error) { var err error if state.cipherSuite == nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errInvalidCipherSuite } - if cfg.localPSKCallback != nil { + if cfg.localPSKCallback != nil { //nolint:nestif var psk []byte - if psk, err = cfg.localPSKCallback(h.IdentityHint); err != nil { + if psk, err = cfg.localPSKCallback(keyExchangeMessage.IdentityHint); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } - state.IdentityHint = h.IdentityHint + state.IdentityHint = keyExchangeMessage.IdentityHint switch state.cipherSuite.KeyExchangeAlgorithm() { case types.KeyExchangeAlgorithmPsk: state.preMasterSecret = prf.PSKPreMasterSecret(psk) case (types.KeyExchangeAlgorithmEcdhe | types.KeyExchangeAlgorithmPsk): - if state.localKeypair, err = elliptic.GenerateKeypair(h.NamedCurve); err != nil { + if state.localKeypair, err = elliptic.GenerateKeypair(keyExchangeMessage.NamedCurve); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } - state.preMasterSecret, err = prf.EcdhePSKPreMasterSecret(psk, h.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve) + state.preMasterSecret, err = prf.EcdhePSKPreMasterSecret( + psk, + keyExchangeMessage.PublicKey, + state.localKeypair.PrivateKey, + state.localKeypair.Curve, + ) if err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -229,11 +257,15 @@ func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h return &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errInvalidCipherSuite } } else { - if state.localKeypair, err = elliptic.GenerateKeypair(h.NamedCurve); err != nil { + if state.localKeypair, err = elliptic.GenerateKeypair(keyExchangeMessage.NamedCurve); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } - if state.preMasterSecret, err = prf.PreMasterSecret(h.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve); err != nil { + if state.preMasterSecret, err = prf.PreMasterSecret( + keyExchangeMessage.PublicKey, + state.localKeypair.PrivateKey, + state.localKeypair.Curve, + ); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } } @@ -241,7 +273,12 @@ func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h return nil, nil //nolint:nilnil } -func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +func flight3Generate( + _ flightConn, + state *State, + _ *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { extensions := []extension.Extension{ &extension.SupportedSignatureAlgorithms{ SignatureHashAlgorithms: cfg.localSignatureSchemes, diff --git a/flight3handler_test.go b/flight3handler_test.go index e801be00a..af7374d6d 100644 --- a/flight3handler_test.go +++ b/flight3handler_test.go @@ -18,8 +18,8 @@ import ( "github.com/pion/transport/v3/test" ) -// Assert that SupportedEllipticCurves is only sent when a ECC CipherSuite is available -func TestSupportedEllipticCurves(t *testing.T) { +// Assert that SupportedEllipticCurves is only sent when a ECC CipherSuite is available. +func TestSupportedEllipticCurves(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -51,7 +51,7 @@ func TestSupportedEllipticCurves(t *testing.T) { h := &handshake.Handshake{} _ = h.Unmarshal(messages[i][recordlayer.FixedHeaderSize:]) - if h.Header.Type == handshake.TypeClientHello { + if h.Header.Type == handshake.TypeClientHello { //nolint:nestif clientHello := &handshake.MessageClientHello{} msg, err := h.Message.Marshal() @@ -78,7 +78,13 @@ func TestSupportedEllipticCurves(t *testing.T) { EllipticCurves: expectedCurves, } - if client, err := testClient(ctx, dtlsnet.PacketConnFromConn(caAnalyzer), caAnalyzer.RemoteAddr(), conf, false); err != nil { + if client, err := testClient( + ctx, + dtlsnet.PacketConnFromConn(caAnalyzer), + caAnalyzer.RemoteAddr(), + conf, + false, + ); err != nil { clientErr <- err } else { clientErr <- client.Close() //nolint diff --git a/flight4bhandler.go b/flight4bhandler.go index d87a1feee..681533b0e 100644 --- a/flight4bhandler.go +++ b/flight4bhandler.go @@ -15,7 +15,13 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight4bParse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight4bParse( + _ context.Context, + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite, handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, true, false}, ) @@ -47,7 +53,13 @@ func flight4bParse(_ context.Context, _ flightConn, state *State, cache *handsha return flight4b, nil, nil } -func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +//nolint:cyclop +func flight4bGenerate( + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { var pkts []*packet extensions := []extension.Extension{&extension.RenegotiationInfo{ @@ -95,7 +107,7 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha serverHello = handshake.Handshake{Message: serverHelloMessage} } - serverHello.Header.MessageSequence = uint16(state.handshakeSendSequence) + serverHello.Header.MessageSequence = uint16(state.handshakeSendSequence) //nolint:gosec // G115 if len(state.localVerifyData) == 0 { plainText := cache.pullAndMerge( diff --git a/flight4handler.go b/flight4handler.go index 7e4ae12f1..75e2e8b1a 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -20,7 +20,14 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { //nolint:gocognit +//nolint:gocognit,gocyclo,lll,cyclop,maintidx +func flight4Parse( + ctx context.Context, + conn flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { seq, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite, handshakeCachePullRule{handshake.TypeCertificate, cfg.initialEpoch, true, true}, handshakeCachePullRule{handshake.TypeClientKeyExchange, cfg.initialEpoch, true, false}, @@ -47,7 +54,8 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh state.SessionID = nil } - if h, hasCertVerify := msgs[handshake.TypeCertificateVerify].(*handshake.MessageCertificateVerify); hasCertVerify { + //nolint:nestif + if verify, hasVerify := msgs[handshake.TypeCertificateVerify].(*handshake.MessageCertificateVerify); hasVerify { if state.PeerCertificates == nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.NoCertificate}, errCertificateVerifyNoCertificate } @@ -66,8 +74,9 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh // Verify that the pair of hash algorithm and signiture is listed. var validSignatureScheme bool for _, ss := range cfg.localSignatureSchemes { - if ss.Hash == h.HashAlgorithm && ss.Signature == h.SignatureAlgorithm { + if ss.Hash == verify.HashAlgorithm && ss.Signature == verify.SignatureAlgorithm { validSignatureScheme = true + break } } @@ -75,7 +84,12 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errNoAvailableSignatureSchemes } - if err := verifyCertificateVerify(plainText, h.HashAlgorithm, h.Signature, state.PeerCertificates); err != nil { + if err := verifyCertificateVerify( + plainText, + verify.HashAlgorithm, + verify.Signature, + state.PeerCertificates, + ); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err } var chains [][]*x509.Certificate @@ -99,7 +113,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, nil, nil } - if !state.cipherSuite.IsInitialized() { + if !state.cipherSuite.IsInitialized() { //nolint:nestif serverRandom := state.localRandom.MarshalFixed() clientRandom := state.remoteRandom.MarshalFixed() @@ -115,14 +129,23 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh case CipherSuiteKeyExchangeAlgorithmPsk: preMasterSecret = prf.PSKPreMasterSecret(psk) case (CipherSuiteKeyExchangeAlgorithmPsk | CipherSuiteKeyExchangeAlgorithmEcdhe): - if preMasterSecret, err = prf.EcdhePSKPreMasterSecret(psk, clientKeyExchange.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve); err != nil { + if preMasterSecret, err = prf.EcdhePSKPreMasterSecret( + psk, + clientKeyExchange.PublicKey, + state.localKeypair.PrivateKey, + state.localKeypair.Curve, + ); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } default: return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errInvalidCipherSuite } } else { - preMasterSecret, err = prf.PreMasterSecret(clientKeyExchange.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve) + preMasterSecret, err = prf.PreMasterSecret( + clientKeyExchange.PublicKey, + state.localKeypair.PrivateKey, + state.localKeypair.Curve, + ) if err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, err } @@ -140,7 +163,12 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } } else { - state.masterSecret, err = prf.MasterSecret(preMasterSecret, clientRandom[:], serverRandom[:], state.cipherSuite.HashFunc()) + state.masterSecret, err = prf.MasterSecret( + preMasterSecret, + clientRandom[:], + serverRandom[:], + state.cipherSuite.HashFunc(), + ) if err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -164,7 +192,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh } // Now, encrypted packets can be handled - if err := c.handleQueuedPackets(ctx); err != nil { + if err := conn.handleQueuedPackets(ctx); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -181,7 +209,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, nil } - if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeAnonymous { + if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeAnonymous { //nolint:nestif if cfg.verifyConnection != nil { stateClone, err := state.clone() if err != nil { @@ -191,6 +219,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err } } + return flight6, nil, nil } @@ -226,7 +255,13 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return flight6, nil, nil } -func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit +//nolint:gocognit,cyclop,maintidx +func flight4Generate( + _ flightConn, + state *State, + _ *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { extensions := []extension.Extension{&extension.RenegotiationInfo{ RenegotiatedConnection: 0, }} @@ -337,7 +372,14 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, err } - signature, err := generateKeySignature(clientRandom[:], serverRandom[:], state.localKeypair.PublicKey, state.namedCurve, certificate.PrivateKey, signatureHashAlgo.Hash) + signature, err := generateKeySignature( + clientRandom[:], + serverRandom[:], + state.localKeypair.PublicKey, + state.namedCurve, + certificate.PrivateKey, + signatureHashAlgo.Hash, + ) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -369,7 +411,9 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha // 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. + // 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() } @@ -396,7 +440,8 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha }, }) } - case cfg.localPSKIdentityHint != nil || state.cipherSuite.KeyExchangeAlgorithm().Has(CipherSuiteKeyExchangeAlgorithmEcdhe): + case cfg.localPSKIdentityHint != nil || + state.cipherSuite.KeyExchangeAlgorithm().Has(CipherSuiteKeyExchangeAlgorithmEcdhe): // To help the client in selecting which identity to use, the server // can provide a "PSK identity hint" in the ServerKeyExchange message. // If no hint is provided and cipher suite doesn't use elliptic curve, diff --git a/flight4handler_test.go b/flight4handler_test.go index 20e9d2253..458292b69 100644 --- a/flight4handler_test.go +++ b/flight4handler_test.go @@ -40,13 +40,14 @@ type flight4TestMockCipherSuite struct { func (f *flight4TestMockCipherSuite) IsInitialized() bool { f.t.Fatal("IsInitialized called with Certificate but not CertificateVerify") + return true } // Assert that if a Client sends a certificate they // must also send a CertificateVerify message. // The flight4handler must not interact with the CipherSuite -// if the CertificateVerify is missing +// if the CertificateVerify is missing. func TestFlight4_Process_CertificateVerify(t *testing.T) { // Limit runtime in case of deadlocks lim := test.TimeOut(5 * time.Second) @@ -156,6 +157,7 @@ func TestFlight4_CertificateRequestHook(t *testing.T) { clientAuth: 1, certificateRequestMessageHook: func(mcr handshake.MessageCertificateRequest) handshake.Message { mcr.SignatureHashAlgorithms = []signaturehash.Algorithm{} + return &mcr }, } @@ -166,7 +168,7 @@ func TestFlight4_CertificateRequestHook(t *testing.T) { } for _, p := range pkts { - if h, ok := p.record.Content.(*handshake.Handshake); ok { + if h, ok := p.record.Content.(*handshake.Handshake); ok { //nolint:nestif if h.Message.Type() == handshake.TypeCertificateRequest { mcr := &handshake.MessageCertificateRequest{} msg, err := h.Message.Marshal() diff --git a/flight5bhandler.go b/flight5bhandler.go index 27a05cc21..db6de367c 100644 --- a/flight5bhandler.go +++ b/flight5bhandler.go @@ -13,7 +13,13 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight5bParse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight5bParse( + _ context.Context, + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-1, state.cipherSuite, handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, false, false}, ) @@ -30,7 +36,12 @@ func flight5bParse(_ context.Context, _ flightConn, state *State, cache *handsha return flight5b, nil, nil } -func flight5bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit +func flight5bGenerate( + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { //nolint:gocognit var pkts []*packet pkts = append(pkts, diff --git a/flight5handler.go b/flight5handler.go index 7e940cdc9..95f2466c5 100644 --- a/flight5handler.go +++ b/flight5handler.go @@ -17,7 +17,13 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight5Parse( + _ context.Context, + conn flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite, handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, false, false}, ) @@ -57,7 +63,7 @@ func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshak Secret: state.masterSecret, } cfg.log.Tracef("[handshake] save new session: %x", s.ID) - if err := cfg.sessionStore.Set(c.sessionKey(), s); err != nil { + if err := cfg.sessionStore.Set(conn.sessionKey(), s); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } } @@ -65,10 +71,16 @@ func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshak return flight5, nil, nil } -func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit +//nolint:gocognit,cyclop,maintidx +func flight5Generate( + conn flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { var privateKey crypto.PrivateKey var pkts []*packet - if state.remoteRequestedCertificate { + if state.remoteRequestedCertificate { //nolint:nestif _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-2, state.cipherSuite, handshakeCachePullRule{handshake.TypeCertificateRequest, cfg.initialEpoch, false, false}) if !ok { @@ -135,7 +147,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han // handshakeMessageServerKeyExchange is optional for PSK if len(serverKeyExchangeData) == 0 { - alertPtr, err := handleServerKeyExchange(c, state, cfg, &handshake.MessageServerKeyExchange{}) + alertPtr, err := handleServerKeyExchange(conn, state, cfg, &handshake.MessageServerKeyExchange{}) if err != nil { return nil, alertPtr, err } @@ -158,7 +170,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han // Append not-yet-sent packets merged := []byte{} - seqPred := uint16(state.handshakeSendSequence) + seqPred := uint16(state.handshakeSendSequence) //nolint:gosec // G115 for _, p := range pkts { h, ok := p.record.Content.(*handshake.Handshake) if !ok { @@ -205,7 +217,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han } state.localCertificatesVerify = certVerify - p := &packet{ + pkt := &packet{ record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ Version: protocol.Version1_2, @@ -219,9 +231,9 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han }, }, } - pkts = append(pkts, p) + pkts = append(pkts, pkt) - h, ok := p.record.Content.(*handshake.Handshake) + h, ok := pkt.record.Content.(*handshake.Handshake) if !ok { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errInvalidContentType } @@ -259,7 +271,11 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han ) var err error - state.localVerifyData, err = prf.VerifyDataClient(state.masterSecret, append(plainText, merged...), state.cipherSuite.HashFunc()) + state.localVerifyData, err = prf.VerifyDataClient( + state.masterSecret, + append(plainText, merged...), + state.cipherSuite.HashFunc(), + ) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -286,7 +302,14 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han return pkts, nil, nil } -func initializeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeConfig, h *handshake.MessageServerKeyExchange, sendingPlainText []byte) (*alert.Alert, error) { //nolint:gocognit +//nolint:gocognit,cyclop +func initializeCipherSuite( + state *State, + cache *handshakeCache, + cfg *handshakeConfig, + handshakeKeyExchange *handshake.MessageServerKeyExchange, + sendingPlainText []byte, +) (*alert.Alert, error) { if state.cipherSuite.IsInitialized() { return nil, nil //nolint } @@ -308,18 +331,24 @@ func initializeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCo return &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, err } } else { - state.masterSecret, err = prf.MasterSecret(state.preMasterSecret, clientRandom[:], serverRandom[:], state.cipherSuite.HashFunc()) + state.masterSecret, err = prf.MasterSecret( + state.preMasterSecret, + clientRandom[:], + serverRandom[:], + state.cipherSuite.HashFunc(), + ) if err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } } - if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate { + if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate { //nolint:nestif // Verify that the pair of hash algorithm and signiture is listed. var validSignatureScheme bool for _, ss := range cfg.localSignatureSchemes { - if ss.Hash == h.HashAlgorithm && ss.Signature == h.SignatureAlgorithm { + if ss.Hash == handshakeKeyExchange.HashAlgorithm && ss.Signature == handshakeKeyExchange.SignatureAlgorithm { validSignatureScheme = true + break } } @@ -327,8 +356,19 @@ func initializeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCo return &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errNoAvailableSignatureSchemes } - expectedMsg := valueKeyMessage(clientRandom[:], serverRandom[:], h.PublicKey, h.NamedCurve) - if err = verifyKeySignature(expectedMsg, h.Signature, h.HashAlgorithm, state.PeerCertificates); err != nil { + expectedMsg := valueKeyMessage( + clientRandom[:], + serverRandom[:], + handshakeKeyExchange.PublicKey, + handshakeKeyExchange.NamedCurve, + ) + if err = verifyKeySignature( + expectedMsg, + handshakeKeyExchange. + Signature, + handshakeKeyExchange.HashAlgorithm, + state.PeerCertificates, + ); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err } var chains [][]*x509.Certificate diff --git a/flight6handler.go b/flight6handler.go index 576dc551b..d7828e749 100644 --- a/flight6handler.go +++ b/flight6handler.go @@ -13,7 +13,13 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight6Parse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight6Parse( + _ context.Context, + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-1, state.cipherSuite, handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, true, false}, ) @@ -30,7 +36,12 @@ func flight6Parse(_ context.Context, _ flightConn, state *State, cache *handshak return flight6, nil, nil } -func flight6Generate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +func flight6Generate( + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { var pkts []*packet pkts = append(pkts, @@ -82,5 +93,6 @@ func flight6Generate(_ flightConn, state *State, cache *handshakeCache, cfg *han resetLocalSequenceNumber: true, }, ) + return pkts, nil, nil } diff --git a/flighthandler.go b/flighthandler.go index 651ff17e0..b90cebd3b 100644 --- a/flighthandler.go +++ b/flighthandler.go @@ -9,13 +9,19 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/alert" ) -// Parse received handshakes and return next flightVal -type flightParser func(context.Context, flightConn, *State, *handshakeCache, *handshakeConfig) (flightVal, *alert.Alert, error) +// Parse received handshakes and return next flightVal. +type flightParser func( + context.Context, + flightConn, + *State, + *handshakeCache, + *handshakeConfig, +) (flightVal, *alert.Alert, error) -// Generate flights +// Generate flights. type flightGenerator func(flightConn, *State, *handshakeCache, *handshakeConfig) ([]*packet, *alert.Alert, error) -func (f flightVal) getFlightParser() (flightParser, error) { +func (f flightVal) getFlightParser() (flightParser, error) { //nolint:cyclop switch f { case flight0: return flight0Parse, nil @@ -40,7 +46,7 @@ func (f flightVal) getFlightParser() (flightParser, error) { } } -func (f flightVal) getFlightGenerator() (gen flightGenerator, retransmit bool, err error) { +func (f flightVal) getFlightGenerator() (gen flightGenerator, retransmit bool, err error) { //nolint:cyclop switch f { case flight0: return flight0Generate, true, nil diff --git a/fragment_buffer.go b/fragment_buffer.go index 37223ab07..497d97107 100644 --- a/fragment_buffer.go +++ b/fragment_buffer.go @@ -9,7 +9,7 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// 2 megabytes +// 2 megabytes. const fragmentBufferMaxSize = 2000000 type fragment struct { @@ -29,7 +29,7 @@ func newFragmentBuffer() *fragmentBuffer { return &fragmentBuffer{cache: map[uint16][]*fragment{}} } -// current total size of buffer +// current total size of buffer. func (f *fragmentBuffer) size() int { size := 0 for i := range f.cache { @@ -37,12 +37,13 @@ func (f *fragmentBuffer) size() int { size += len(f.cache[i][j].data) } } + return size } // Attempts to push a DTLS packet to the fragmentBuffer // when it returns true it means the fragmentBuffer has inserted and the buffer shouldn't be handled -// when an error returns it is fatal, and the DTLS connection should be stopped +// when an error returns it is fatal, and the DTLS connection should be stopped. func (f *fragmentBuffer) push(buf []byte) (isHandshake, isRetransmit bool, err error) { if f.size()+len(buf) >= fragmentBufferMaxSize { return false, false, errFragmentBufferOverflow @@ -64,7 +65,8 @@ func (f *fragmentBuffer) push(buf []byte) (isHandshake, isRetransmit bool, err e } // Fragment is a retransmission. We have already assembled it before successfully - isRetransmit = frag.handshakeHeader.FragmentOffset == 0 && frag.handshakeHeader.MessageSequence < f.currentMessageSequenceNumber + isRetransmit = frag.handshakeHeader.FragmentOffset == 0 && + frag.handshakeHeader.MessageSequence < f.currentMessageSequenceNumber if _, ok := f.cache[frag.handshakeHeader.MessageSequence]; !ok { f.cache[frag.handshakeHeader.MessageSequence] = []*fragment{} @@ -107,9 +109,11 @@ func (f *fragmentBuffer) pop() (content []byte, epoch uint16) { } rawMessage = append(f.data, rawMessage...) + return true } } + return false } @@ -131,5 +135,6 @@ func (f *fragmentBuffer) pop() (content []byte, epoch uint16) { delete(f.cache, f.currentMessageSequenceNumber) f.currentMessageSequenceNumber++ + return append(rawHeader, rawMessage...), messageEpoch } diff --git a/fragment_buffer_test.go b/fragment_buffer_test.go index 2b2f62c7e..9e842b0a2 100644 --- a/fragment_buffer_test.go +++ b/fragment_buffer_test.go @@ -19,7 +19,10 @@ func TestFragmentBuffer(t *testing.T) { { Name: "Single Fragment", In: [][]byte{ - {0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00}, + { + 0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00, + }, }, Expected: [][]byte{ {0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00}, @@ -29,7 +32,10 @@ func TestFragmentBuffer(t *testing.T) { { Name: "Single Fragment Epoch 3", In: [][]byte{ - {0x16, 0xfe, 0xff, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00}, + { + 0x16, 0xfe, 0xff, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00, + }, }, Expected: [][]byte{ {0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00}, @@ -39,24 +45,48 @@ func TestFragmentBuffer(t *testing.T) { { Name: "Multiple Fragments", In: [][]byte{ - {0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04}, - {0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09}, - {0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x05, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E}, + { + 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, + }, + { + 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, + }, + { + 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x05, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + }, }, Expected: [][]byte{ - {0x0b, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e}, + { + 0x0b, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + }, }, Epoch: 0, }, { Name: "Multiple Unordered Fragments", In: [][]byte{ - {0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04}, - {0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x05, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E}, - {0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09}, + { + 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, + }, + { + 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x05, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + }, + { + 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x81, 0x0b, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, + }, }, Expected: [][]byte{ - {0x0b, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e}, + { + 0x0b, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + }, }, Epoch: 0, }, @@ -122,7 +152,10 @@ func TestFragmentBuffer_Overflow(t *testing.T) { fragmentBuffer := newFragmentBuffer() // Push a buffer that doesn't exceed size limits - if _, _, err := fragmentBuffer.push([]byte{0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00}); err != nil { + if _, _, err := fragmentBuffer.push([]byte{ + 0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00, + }); err != nil { t.Fatal(err) } diff --git a/handshake_cache.go b/handshake_cache.go index 285c71331..95f20953f 100644 --- a/handshake_cache.go +++ b/handshake_cache.go @@ -49,7 +49,7 @@ func (h *handshakeCache) push(data []byte, epoch, messageSequence uint16, typ ha // returns a list handshakes that match the requested rules // the list will contain null entries for rules that can't be satisfied -// multiple entries may match a rule, but only the last match is returned (ie ClientHello with cookies) +// multiple entries may match a rule, but only the last match is returned (ie ClientHello with cookies). func (h *handshakeCache) pull(rules ...handshakeCachePullRule) []*handshakeCacheItem { h.mu.Lock() defer h.mu.Unlock() @@ -72,15 +72,21 @@ func (h *handshakeCache) pull(rules ...handshakeCachePullRule) []*handshakeCache } // fullPullMap pulls all handshakes between rules[0] to rules[len(rules)-1] as map. -func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rules ...handshakeCachePullRule) (int, map[handshake.Type]handshake.Message, bool) { +// +//nolint:cyclop +func (h *handshakeCache) fullPullMap( + startSeq int, + cipherSuite CipherSuite, + rules ...handshakeCachePullRule, +) (int, map[handshake.Type]handshake.Message, bool) { h.mu.Lock() defer h.mu.Unlock() ci := make(map[handshake.Type]*handshakeCacheItem) - for _, r := range rules { + for _, rule := range rules { var item *handshakeCacheItem for _, c := range h.cache { - if c.typ == r.typ && c.isClient == r.isClient && c.epoch == r.epoch { + if c.typ == rule.typ && c.isClient == rule.isClient && c.epoch == rule.epoch { switch { case item == nil: item = c @@ -89,18 +95,18 @@ func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rule } } } - if !r.optional && item == nil { + if !rule.optional && item == nil { // Missing mandatory message. return startSeq, nil, false } - ci[r.typ] = item + ci[rule.typ] = item } out := make(map[handshake.Type]handshake.Message) seq := startSeq ok := false for _, r := range rules { - t := r.typ - i := ci[t] + typ := r.typ + i := ci[typ] if i == nil { continue } @@ -114,21 +120,22 @@ func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rule if err := rawHandshake.Unmarshal(i.data); err != nil { return startSeq, nil, false } - if uint16(seq) != rawHandshake.Header.MessageSequence { + if uint16(seq) != rawHandshake.Header.MessageSequence { //nolint:gosec // G115 // There is a gap. Some messages are not arrived. return startSeq, nil, false } seq++ ok = true - out[t] = rawHandshake.Message + out[typ] = rawHandshake.Message } if !ok { return seq, nil, false } + return seq, out, true } -// pullAndMerge calls pull and then merges the results, ignoring any null entries +// pullAndMerge calls pull and then merges the results, ignoring any null entries. func (h *handshakeCache) pullAndMerge(rules ...handshakeCachePullRule) []byte { merged := []byte{} @@ -137,6 +144,7 @@ func (h *handshakeCache) pullAndMerge(rules ...handshakeCachePullRule) []byte { merged = append(merged, p.data...) } } + return merged } diff --git a/handshake_cache_test.go b/handshake_cache_test.go index 647a3f35e..b655ac166 100644 --- a/handshake_cache_test.go +++ b/handshake_cache_test.go @@ -144,7 +144,10 @@ func TestHandshakeCacheSessionHash(t *testing.T) { {handshake.TypeServerHelloDone, false, 0, 4, []byte{0x04}}, {handshake.TypeClientKeyExchange, true, 0, 5, []byte{0x05}}, }, - Expected: []byte{0x17, 0xe8, 0x8d, 0xb1, 0x87, 0xaf, 0xd6, 0x2c, 0x16, 0xe5, 0xde, 0xbf, 0x3e, 0x65, 0x27, 0xcd, 0x00, 0x6b, 0xc0, 0x12, 0xbc, 0x90, 0xb5, 0x1a, 0x81, 0x0c, 0xd8, 0x0c, 0x2d, 0x51, 0x1f, 0x43}, + Expected: []byte{ + 0x17, 0xe8, 0x8d, 0xb1, 0x87, 0xaf, 0xd6, 0x2c, 0x16, 0xe5, 0xde, 0xbf, 0x3e, 0x65, 0x27, 0xcd, + 0x00, 0x6b, 0xc0, 0x12, 0xbc, 0x90, 0xb5, 0x1a, 0x81, 0x0c, 0xd8, 0x0c, 0x2d, 0x51, 0x1f, 0x43, + }, }, { Name: "Handshake With Client Cert Request", @@ -157,7 +160,10 @@ func TestHandshakeCacheSessionHash(t *testing.T) { {handshake.TypeServerHelloDone, false, 0, 5, []byte{0x05}}, {handshake.TypeClientKeyExchange, true, 0, 6, []byte{0x06}}, }, - Expected: []byte{0x57, 0x35, 0x5a, 0xc3, 0x30, 0x3c, 0x14, 0x8f, 0x11, 0xae, 0xf7, 0xcb, 0x17, 0x94, 0x56, 0xb9, 0x23, 0x2c, 0xde, 0x33, 0xa8, 0x18, 0xdf, 0xda, 0x2c, 0x2f, 0xcb, 0x93, 0x25, 0x74, 0x9a, 0x6b}, + Expected: []byte{ + 0x57, 0x35, 0x5a, 0xc3, 0x30, 0x3c, 0x14, 0x8f, 0x11, 0xae, 0xf7, 0xcb, 0x17, 0x94, 0x56, 0xb9, + 0x23, 0x2c, 0xde, 0x33, 0xa8, 0x18, 0xdf, 0xda, 0x2c, 0x2f, 0xcb, 0x93, 0x25, 0x74, 0x9a, 0x6b, + }, }, { Name: "Handshake Ignores after ClientKeyExchange", @@ -173,7 +179,10 @@ func TestHandshakeCacheSessionHash(t *testing.T) { {handshake.TypeFinished, true, 1, 7, []byte{0x08}}, {handshake.TypeFinished, false, 1, 7, []byte{0x09}}, }, - Expected: []byte{0x57, 0x35, 0x5a, 0xc3, 0x30, 0x3c, 0x14, 0x8f, 0x11, 0xae, 0xf7, 0xcb, 0x17, 0x94, 0x56, 0xb9, 0x23, 0x2c, 0xde, 0x33, 0xa8, 0x18, 0xdf, 0xda, 0x2c, 0x2f, 0xcb, 0x93, 0x25, 0x74, 0x9a, 0x6b}, + Expected: []byte{ + 0x57, 0x35, 0x5a, 0xc3, 0x30, 0x3c, 0x14, 0x8f, 0x11, 0xae, 0xf7, 0xcb, 0x17, 0x94, 0x56, 0xb9, + 0x23, 0x2c, 0xde, 0x33, 0xa8, 0x18, 0xdf, 0xda, 0x2c, 0x2f, 0xcb, 0x93, 0x25, 0x74, 0x9a, 0x6b, + }, }, { Name: "Handshake Ignores wrong epoch", @@ -193,7 +202,10 @@ func TestHandshakeCacheSessionHash(t *testing.T) { {handshake.TypeFinished, true, 0, 7, []byte{0xf0}}, {handshake.TypeFinished, false, 0, 7, []byte{0xf1}}, }, - Expected: []byte{0x57, 0x35, 0x5a, 0xc3, 0x30, 0x3c, 0x14, 0x8f, 0x11, 0xae, 0xf7, 0xcb, 0x17, 0x94, 0x56, 0xb9, 0x23, 0x2c, 0xde, 0x33, 0xa8, 0x18, 0xdf, 0xda, 0x2c, 0x2f, 0xcb, 0x93, 0x25, 0x74, 0x9a, 0x6b}, + Expected: []byte{ + 0x57, 0x35, 0x5a, 0xc3, 0x30, 0x3c, 0x14, 0x8f, 0x11, 0xae, 0xf7, 0xcb, 0x17, 0x94, 0x56, 0xb9, + 0x23, 0x2c, 0xde, 0x33, 0xa8, 0x18, 0xdf, 0xda, 0x2c, 0x2f, 0xcb, 0x93, 0x25, 0x74, 0x9a, 0x6b, + }, }, } { h := newHandshakeCache() diff --git a/handshake_test.go b/handshake_test.go index 4cadb610f..8c97d20b2 100644 --- a/handshake_test.go +++ b/handshake_test.go @@ -30,7 +30,10 @@ func TestHandshakeMessage(t *testing.T) { Version: protocol.Version{Major: 0xFE, Minor: 0xFD}, Random: handshake.Random{ GMTUnixTime: time.Unix(3056586332, 0), - RandomBytes: [28]byte{0x42, 0x54, 0xff, 0x86, 0xe1, 0x24, 0x41, 0x91, 0x42, 0x62, 0x15, 0xad, 0x16, 0xc9, 0x15, 0x8d, 0x95, 0x71, 0x8a, 0xbb, 0x22, 0xd7, 0x47, 0xec, 0xd8, 0x3d, 0xdc, 0x4b}, + RandomBytes: [28]byte{ + 0x42, 0x54, 0xff, 0x86, 0xe1, 0x24, 0x41, 0x91, 0x42, 0x62, 0x15, 0xad, 0x16, 0xc9, + 0x15, 0x8d, 0x95, 0x71, 0x8a, 0xbb, 0x22, 0xd7, 0x47, 0xec, 0xd8, 0x3d, 0xdc, 0x4b, + }, }, SessionID: []byte{}, Cookie: []byte{}, diff --git a/handshaker.go b/handshaker.go index 5e16808a9..e8b09b6c4 100644 --- a/handshaker.go +++ b/handshaker.go @@ -162,6 +162,7 @@ func srvCliStr(isClient bool) string { if isClient { return "client" } + return "server" } @@ -179,7 +180,7 @@ func newHandshakeFSM( } } -func (s *handshakeFSM) Run(ctx context.Context, c flightConn, initialState handshakeState) error { +func (s *handshakeFSM) Run(ctx context.Context, conn flightConn, initialState handshakeState) error { state := initialState defer func() { close(s.closed) @@ -192,13 +193,13 @@ func (s *handshakeFSM) Run(ctx context.Context, c flightConn, initialState hands var err error switch state { case handshakePreparing: - state, err = s.prepare(ctx, c) + state, err = s.prepare(ctx, conn) case handshakeSending: - state, err = s.send(ctx, c) + state, err = s.send(ctx, conn) case handshakeWaiting: - state, err = s.wait(ctx, c) + state, err = s.wait(ctx, conn) case handshakeFinished: - state, err = s.finish(ctx, c) + state, err = s.finish(ctx, conn) default: return errInvalidFSMTransition } @@ -212,24 +213,24 @@ func (s *handshakeFSM) Done() <-chan struct{} { return s.closed } -func (s *handshakeFSM) prepare(ctx context.Context, c flightConn) (handshakeState, error) { +func (s *handshakeFSM) prepare(ctx context.Context, conn flightConn) (handshakeState, error) { s.flights = nil // Prepare flights var ( - a *alert.Alert - err error - pkts []*packet + dtlsAlert *alert.Alert + err error + pkts []*packet ) gen, retransmit, errFlight := s.currentFlight.getFlightGenerator() if errFlight != nil { err = errFlight - a = &alert.Alert{Level: alert.Fatal, Description: alert.InternalError} + dtlsAlert = &alert.Alert{Level: alert.Fatal, Description: alert.InternalError} } else { - pkts, a, err = gen(c, s.state, s.cache, s.cfg) + pkts, dtlsAlert, err = gen(conn, s.state, s.cache, s.cfg) s.retransmit = retransmit } - if a != nil { - if alertErr := c.notify(ctx, a.Level, a.Description); alertErr != nil { + if dtlsAlert != nil { + if alertErr := conn.notify(ctx, dtlsAlert.Level, dtlsAlert.Description); alertErr != nil { if err != nil { err = alertErr } @@ -248,14 +249,15 @@ func (s *handshakeFSM) prepare(ctx context.Context, c flightConn) (handshakeStat nextEpoch = p.record.Header.Epoch } if h, ok := p.record.Content.(*handshake.Handshake); ok { - h.Header.MessageSequence = uint16(s.state.handshakeSendSequence) + h.Header.MessageSequence = uint16(s.state.handshakeSendSequence) //nolint:gosec // G115 s.state.handshakeSendSequence++ } } if epoch != nextEpoch { s.cfg.log.Tracef("[handshake:%s] -> changeCipherSpec (epoch: %d)", srvCliStr(s.state.isClient), nextEpoch) - c.setLocalEpoch(nextEpoch) + conn.setLocalEpoch(nextEpoch) } + return handshakeSending, nil } @@ -268,32 +270,35 @@ func (s *handshakeFSM) send(ctx context.Context, c flightConn) (handshakeState, if s.currentFlight.isLastSendFlight() { return handshakeFinished, nil } + return handshakeWaiting, nil } -func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, error) { //nolint:gocognit +func (s *handshakeFSM) wait(ctx context.Context, conn flightConn) (handshakeState, error) { //nolint:gocognit,cyclop parse, errFlight := s.currentFlight.getFlightParser() if errFlight != nil { - if alertErr := c.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil { + if alertErr := conn.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil { return handshakeErrored, alertErr } + return handshakeErrored, errFlight } retransmitTimer := time.NewTimer(s.retransmitInterval) for { select { - case state := <-c.recvHandshake(): + case state := <-conn.recvHandshake(): if state.isRetransmit { close(state.done) + return handshakeSending, nil } - nextFlight, alert, err := parse(ctx, c, s.state, s.cache, s.cfg) + nextFlight, alert, err := parse(ctx, conn, s.state, s.cache, s.cfg) s.retransmitInterval = s.cfg.initialRetransmitInterval close(state.done) if alert != nil { - if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { + if alertErr := conn.notify(ctx, alert.Level, alert.Description); alertErr != nil { if err != nil { err = alertErr } @@ -305,11 +310,17 @@ func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, if nextFlight == 0 { break } - s.cfg.log.Tracef("[handshake:%s] %s -> %s", srvCliStr(s.state.isClient), s.currentFlight.String(), nextFlight.String()) + s.cfg.log.Tracef( + "[handshake:%s] %s -> %s", + srvCliStr(s.state.isClient), + s.currentFlight.String(), + nextFlight.String(), + ) if nextFlight.isLastRecvFlight() && s.currentFlight == nextFlight { return handshakeFinished, nil } s.currentFlight = nextFlight + return handshakePreparing, nil case <-retransmitTimer.C: @@ -326,9 +337,11 @@ func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, if s.retransmitInterval > time.Second*60 { s.retransmitInterval = time.Second * 60 } + return handshakeSending, nil case <-ctx.Done(): s.retransmitInterval = s.cfg.initialRetransmitInterval + return handshakeErrored, ctx.Err() } } diff --git a/handshaker_test.go b/handshaker_test.go index de82a571a..88e69ee0c 100644 --- a/handshaker_test.go +++ b/handshaker_test.go @@ -44,7 +44,7 @@ func TestWriteKeyLog(t *testing.T) { cfg.writeKeyLog("LABEL", []byte{0xAA, 0xBB, 0xCC}, []byte{0xDD, 0xEE, 0xFF}) } -func TestHandshaker(t *testing.T) { +func TestHandshaker(t *testing.T) { //nolint:gocyclo,cyclop,maintidx // Check for leaking routines report := test.CheckRoutines(t) defer report() @@ -84,6 +84,7 @@ func TestHandshaker(t *testing.T) { cntClientHelloNoCookie++ } } + return true }, } @@ -96,17 +97,26 @@ func TestHandshaker(t *testing.T) { } if _, ok := h.Message.(*handshake.MessageHelloVerifyRequest); ok { cntHelloVerifyRequest++ + return cntHelloVerifyRequest > helloVerifyDrop } + return true }, } report := func(t *testing.T) { + t.Helper() + if cntHelloVerifyRequest != helloVerifyDrop+1 { - t.Errorf("Number of HelloVerifyRequest retransmit is wrong, expected: %d times, got: %d times", helloVerifyDrop+1, cntHelloVerifyRequest) + t.Errorf( + "Number of HelloVerifyRequest retransmit is wrong, expected: %d times, got: %d times", + helloVerifyDrop+1, + cntHelloVerifyRequest, + ) } if cntClientHelloNoCookie != cntHelloVerifyRequest { + ///nolint:lll t.Errorf( "HelloVerifyRequest must be triggered only by ClientHello, but HelloVerifyRequest was sent %d times and ClientHello was sent %d times", cntHelloVerifyRequest, cntClientHelloNoCookie, @@ -132,6 +142,7 @@ func TestHandshaker(t *testing.T) { if _, ok := h.Message.(*handshake.MessageFinished); ok { cntClientFinished++ } + return true }, } @@ -145,11 +156,14 @@ func TestHandshaker(t *testing.T) { if _, ok := h.Message.(*handshake.MessageFinished); ok { cntServerFinished++ } + return true }, } report := func(t *testing.T) { + t.Helper() + if cntClientFinished != 1 { t.Errorf("Number of client finished is wrong, expected: %d times, got: %d times", 1, cntClientFinished) } @@ -184,6 +198,7 @@ func TestHandshaker(t *testing.T) { cntClientFinished++ } } + return true }, Delay: 0, @@ -206,6 +221,7 @@ func TestHandshaker(t *testing.T) { cntServerFinished++ } } + return true }, Delay: 1000 * time.Millisecond, @@ -216,8 +232,11 @@ func TestHandshaker(t *testing.T) { } report := func(t *testing.T) { - // with one second server delay and 100 ms retransmit (+ exponential backoff), there should be close to 4 `Finished` from client - // using a range of 3 - 5 for checking + t.Helper() + + // with one second server delay and 100 ms retransmit (+ exponential backoff), + // there should be close to 4 `Finished` from client + // using a range of 3 - 5 for checking. if cntClientFinished < 3 || cntClientFinished > 5 { t.Errorf("Number of client finished is wrong, expected: %d - %d times, got: %d times", 3, 5, cntClientFinished) } @@ -226,7 +245,11 @@ func TestHandshaker(t *testing.T) { } // there should be no `Finished` last retransmit from client if cntClientFinishedLastRetransmit != 0 { - t.Errorf("Number of client finished last retransmit is wrong, expected: %d times, got: %d times", 0, cntClientFinishedLastRetransmit) + t.Errorf( + "Number of client finished last retransmit is wrong, expected: %d times, got: %d times", + 0, + cntClientFinishedLastRetransmit, + ) } if cntServerFinished < 1 { t.Errorf("Number of server finished is wrong, expected: at least %d times, got: %d times", 1, cntServerFinished) @@ -234,9 +257,14 @@ func TestHandshaker(t *testing.T) { if !isServerFinished { t.Errorf("Server is not finished") } - // there should be `Finished` last retransmit from server. Because of slow server, client would have sent several `Finished`. + // there should be `Finished` last retransmit from server. + // Because of slow server, client would have sent several `Finished`. if cntServerFinishedLastRetransmit < 1 { - t.Errorf("Number of server finished last retransmit is wrong, expected: at least %d times, got: %d times", 1, cntServerFinishedLastRetransmit) + t.Errorf( + "Number of server finished last retransmit is wrong, expected: at least %d times, got: %d times", + 1, + cntServerFinishedLastRetransmit, + ) } } @@ -346,11 +374,16 @@ type TestEndpoint struct { FinishWait time.Duration } -func flightTestPipe(ctx context.Context, clientEndpoint TestEndpoint, serverEndpoint TestEndpoint) (*flightTestConn, *flightTestConn) { +func flightTestPipe( + ctx context.Context, + clientEndpoint TestEndpoint, + serverEndpoint TestEndpoint, +) (*flightTestConn, *flightTestConn) { ca := newHandshakeCache() cb := newHandshakeCache() chA := make(chan recvHandshakeState) chB := make(chan recvHandshakeState) + return &flightTestConn{ handshakeCache: ca, otherEndCache: cb, @@ -399,30 +432,41 @@ func (c *flightTestConn) notify(context.Context, alert.Level, alert.Description) func (c *flightTestConn) writePackets(_ context.Context, pkts []*packet) error { time.Sleep(c.delay) - for _, p := range pkts { - if c.filter != nil && !c.filter(p) { + for _, pkt := range pkts { + if c.filter != nil && !c.filter(pkt) { continue } - if h, ok := p.record.Content.(*handshake.Handshake); ok { - handshakeRaw, err := p.record.Marshal() + if handshake, ok := pkt.record.Content.(*handshake.Handshake); ok { + handshakeRaw, err := pkt.record.Marshal() if err != nil { return err } - c.handshakeCache.push(handshakeRaw[recordlayer.FixedHeaderSize:], p.record.Header.Epoch, h.Header.MessageSequence, h.Header.Type, c.state.isClient) + c.handshakeCache.push( + handshakeRaw[recordlayer.FixedHeaderSize:], + pkt.record.Header.Epoch, + handshake.Header.MessageSequence, + handshake.Header.Type, + c.state.isClient, + ) - content, err := h.Message.Marshal() + content, err := handshake.Message.Marshal() if err != nil { return err } - h.Header.Length = uint32(len(content)) - h.Header.FragmentLength = uint32(len(content)) - hdr, err := h.Header.Marshal() + handshake.Header.Length = uint32(len(content)) //nolint:gosec // G115 + handshake.Header.FragmentLength = uint32(len(content)) //nolint:gosec // G115 + hdr, err := handshake.Header.Marshal() if err != nil { return err } c.otherEndCache.push( - append(hdr, content...), p.record.Header.Epoch, h.Header.MessageSequence, h.Header.Type, c.state.isClient) + append(hdr, content...), + pkt.record.Header.Epoch, + handshake.Header.MessageSequence, + handshake.Header.Type, + c.state.isClient, + ) } } go func() { diff --git a/internal/ciphersuite/aes_128_ccm.go b/internal/ciphersuite/aes_128_ccm.go index 0877c2c18..9805f36e8 100644 --- a/internal/ciphersuite/aes_128_ccm.go +++ b/internal/ciphersuite/aes_128_ccm.go @@ -8,12 +8,19 @@ import ( "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) -// Aes128Ccm is a base class used by multiple AES-CCM Ciphers +// Aes128Ccm is a base class used by multiple AES-CCM Ciphers. type Aes128Ccm struct { AesCcm } -func newAes128Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool, cryptoCCMTagLen ciphersuite.CCMTagLen, keyExchangeAlgorithm KeyExchangeAlgorithm, ecc bool) *Aes128Ccm { +func newAes128Ccm( + clientCertificateType clientcertificate.Type, + id ID, + psk bool, + cryptoCCMTagLen ciphersuite.CCMTagLen, + keyExchangeAlgorithm KeyExchangeAlgorithm, + ecc bool, +) *Aes128Ccm { return &Aes128Ccm{ AesCcm: AesCcm{ clientCertificateType: clientCertificateType, @@ -26,8 +33,9 @@ func newAes128Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool, } } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *Aes128Ccm) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const prfKeyLen = 16 + return c.AesCcm.Init(masterSecret, clientRandom, serverRandom, isClient, prfKeyLen) } diff --git a/internal/ciphersuite/aes_256_ccm.go b/internal/ciphersuite/aes_256_ccm.go index bbdf06d81..58d5e0cee 100644 --- a/internal/ciphersuite/aes_256_ccm.go +++ b/internal/ciphersuite/aes_256_ccm.go @@ -8,12 +8,19 @@ import ( "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) -// Aes256Ccm is a base class used by multiple AES-CCM Ciphers +// Aes256Ccm is a base class used by multiple AES-CCM Ciphers. type Aes256Ccm struct { AesCcm } -func newAes256Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool, cryptoCCMTagLen ciphersuite.CCMTagLen, keyExchangeAlgorithm KeyExchangeAlgorithm, ecc bool) *Aes256Ccm { +func newAes256Ccm( + clientCertificateType clientcertificate.Type, + id ID, + psk bool, + cryptoCCMTagLen ciphersuite.CCMTagLen, + keyExchangeAlgorithm KeyExchangeAlgorithm, + ecc bool, +) *Aes256Ccm { return &Aes256Ccm{ AesCcm: AesCcm{ clientCertificateType: clientCertificateType, @@ -26,8 +33,9 @@ func newAes256Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool, } } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *Aes256Ccm) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const prfKeyLen = 32 + return c.AesCcm.Init(masterSecret, clientRandom, serverRandom, isClient, prfKeyLen) } diff --git a/internal/ciphersuite/aes_ccm.go b/internal/ciphersuite/aes_ccm.go index 54eafcf80..ddda1c8e7 100644 --- a/internal/ciphersuite/aes_ccm.go +++ b/internal/ciphersuite/aes_ccm.go @@ -15,7 +15,7 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// AesCcm is a base class used by multiple AES-CCM Ciphers +// AesCcm is a base class used by multiple AES-CCM Ciphers. type AesCcm struct { ccm atomic.Value // *cryptoCCM clientCertificateType clientcertificate.Type @@ -26,12 +26,12 @@ type AesCcm struct { ecc bool } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *AesCcm) CertificateType() clientcertificate.Type { return c.clientCertificateType } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *AesCcm) ID() ID { return c.id } @@ -40,59 +40,66 @@ func (c *AesCcm) String() string { return c.id.String() } -// ECC uses Elliptic Curve Cryptography +// ECC uses Elliptic Curve Cryptography. func (c *AesCcm) ECC() bool { return c.ecc } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *AesCcm) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return c.keyExchangeAlgorithm } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *AesCcm) HashFunc() func() hash.Hash { return sha256.New } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *AesCcm) AuthenticationType() AuthenticationType { if c.psk { return AuthenticationTypePreSharedKey } + return AuthenticationTypeCertificate } // IsInitialized returns if the CipherSuite has keying material and can -// encrypt/decrypt packets +// encrypt/decrypt packets. func (c *AesCcm) IsInitialized() bool { return c.ccm.Load() != nil } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *AesCcm) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool, prfKeyLen int) error { const ( prfMacLen = 0 prfIvLen = 4 ) - keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc()) + keys, err := prf.GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc(), + ) if err != nil { return err } var ccm *ciphersuite.CCM if isClient { - ccm, err = ciphersuite.NewCCM(c.cryptoCCMTagLen, keys.ClientWriteKey, keys.ClientWriteIV, keys.ServerWriteKey, keys.ServerWriteIV) + ccm, err = ciphersuite.NewCCM( + c.cryptoCCMTagLen, keys.ClientWriteKey, keys.ClientWriteIV, keys.ServerWriteKey, keys.ServerWriteIV, + ) } else { - ccm, err = ciphersuite.NewCCM(c.cryptoCCMTagLen, keys.ServerWriteKey, keys.ServerWriteIV, keys.ClientWriteKey, keys.ClientWriteIV) + ccm, err = ciphersuite.NewCCM( + c.cryptoCCMTagLen, keys.ServerWriteKey, keys.ServerWriteIV, keys.ClientWriteKey, keys.ClientWriteIV, + ) } c.ccm.Store(ccm) return err } -// Encrypt encrypts a single TLS RecordLayer +// Encrypt encrypts a single TLS RecordLayer. func (c *AesCcm) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { cipherSuite, ok := c.ccm.Load().(*ciphersuite.CCM) if !ok { @@ -102,7 +109,7 @@ func (c *AesCcm) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, erro return cipherSuite.Encrypt(pkt, raw) } -// Decrypt decrypts a single TLS RecordLayer +// Decrypt decrypts a single TLS RecordLayer. func (c *AesCcm) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.ccm.Load().(*ciphersuite.CCM) if !ok { diff --git a/internal/ciphersuite/ciphersuite.go b/internal/ciphersuite/ciphersuite.go index 4778be72a..27b7d57ce 100644 --- a/internal/ciphersuite/ciphersuite.go +++ b/internal/ciphersuite/ciphersuite.go @@ -1,7 +1,8 @@ // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> // SPDX-License-Identifier: MIT -// Package ciphersuite provides TLS Ciphers as registered with the IANA https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 +// Package ciphersuite provides TLS Ciphers as registered with the IANA +// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 package ciphersuite import ( @@ -12,12 +13,13 @@ import ( "github.com/pion/dtls/v3/pkg/protocol" ) -var errCipherSuiteNotInit = &protocol.TemporaryError{Err: errors.New("CipherSuite has not been initialized")} //nolint:goerr113 +//nolint:goerr113 +var errCipherSuiteNotInit = &protocol.TemporaryError{Err: errors.New("CipherSuite has not been initialized")} -// ID is an ID for our supported CipherSuites +// ID is an ID for our supported CipherSuites. type ID uint16 -func (i ID) String() string { +func (i ID) String() string { //nolint:cyclop switch i { case TLS_ECDHE_ECDSA_WITH_AES_128_CCM: return "TLS_ECDHE_ECDSA_WITH_AES_128_CCM" @@ -52,19 +54,19 @@ func (i ID) String() string { } } -// Supported Cipher Suites +// Supported Cipher Suites. const ( - // AES-128-CCM + // AES-128-CCM. TLS_ECDHE_ECDSA_WITH_AES_128_CCM ID = 0xc0ac //nolint:revive,stylecheck TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ID = 0xc0ae //nolint:revive,stylecheck - // AES-128-GCM-SHA256 + // AES-128-GCM-SHA256. TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ID = 0xc02b //nolint:revive,stylecheck TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ID = 0xc02f //nolint:revive,stylecheck TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ID = 0xc02c //nolint:revive,stylecheck TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ID = 0xc030 //nolint:revive,stylecheck - // AES-256-CBC-SHA + // AES-256-CBC-SHA. TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ID = 0xc00a //nolint:revive,stylecheck TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ID = 0xc014 //nolint:revive,stylecheck @@ -77,10 +79,10 @@ const ( TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 ID = 0xC037 //nolint:revive,stylecheck ) -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. type AuthenticationType = types.AuthenticationType -// AuthenticationType Enums +// AuthenticationType Enums. const ( AuthenticationTypeCertificate AuthenticationType = types.AuthenticationTypeCertificate AuthenticationTypePreSharedKey AuthenticationType = types.AuthenticationTypePreSharedKey @@ -90,7 +92,7 @@ const ( // KeyExchangeAlgorithm controls what exchange algorithm was chosen. type KeyExchangeAlgorithm = types.KeyExchangeAlgorithm -// KeyExchangeAlgorithm Bitmask +// KeyExchangeAlgorithm Bitmask. const ( KeyExchangeAlgorithmNone KeyExchangeAlgorithm = types.KeyExchangeAlgorithmNone KeyExchangeAlgorithmPsk KeyExchangeAlgorithm = types.KeyExchangeAlgorithmPsk diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go index e55290799..04a6ca40d 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go @@ -8,7 +8,14 @@ import ( "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) -// NewTLSEcdheEcdsaWithAes128Ccm constructs a TLS_ECDHE_ECDSA_WITH_AES_128_CCM Cipher +// NewTLSEcdheEcdsaWithAes128Ccm constructs a TLS_ECDHE_ECDSA_WITH_AES_128_CCM Cipher. func NewTLSEcdheEcdsaWithAes128Ccm() *Aes128Ccm { - return newAes128Ccm(clientcertificate.ECDSASign, TLS_ECDHE_ECDSA_WITH_AES_128_CCM, false, ciphersuite.CCMTagLength, KeyExchangeAlgorithmEcdhe, true) + return newAes128Ccm( + clientcertificate.ECDSASign, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + false, + ciphersuite.CCMTagLength, + KeyExchangeAlgorithmEcdhe, + true, + ) } diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go index a423a13f1..38a166fad 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go @@ -8,7 +8,14 @@ import ( "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) -// NewTLSEcdheEcdsaWithAes128Ccm8 creates a new TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuite +// NewTLSEcdheEcdsaWithAes128Ccm8 creates a new TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuite. func NewTLSEcdheEcdsaWithAes128Ccm8() *Aes128Ccm { - return newAes128Ccm(clientcertificate.ECDSASign, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, false, ciphersuite.CCMTagLength8, KeyExchangeAlgorithmEcdhe, true) + return newAes128Ccm( + clientcertificate.ECDSASign, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + false, + ciphersuite.CCMTagLength8, + KeyExchangeAlgorithmEcdhe, + true, + ) } diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go index 9f7b27788..f47a67497 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go @@ -15,27 +15,27 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// TLSEcdheEcdsaWithAes128GcmSha256 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite +// TLSEcdheEcdsaWithAes128GcmSha256 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite. type TLSEcdheEcdsaWithAes128GcmSha256 struct { gcm atomic.Value // *cryptoGCM } -// CertificateType returns what type of certficate this CipherSuite exchanges +// CertificateType returns what type of certficate this CipherSuite exchanges. func (c *TLSEcdheEcdsaWithAes128GcmSha256) CertificateType() clientcertificate.Type { return clientcertificate.ECDSASign } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *TLSEcdheEcdsaWithAes128GcmSha256) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return KeyExchangeAlgorithmEcdhe } -// ECC uses Elliptic Curve Cryptography +// ECC uses Elliptic Curve Cryptography. func (c *TLSEcdheEcdsaWithAes128GcmSha256) ECC() bool { return true } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheEcdsaWithAes128GcmSha256) ID() ID { return TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 } @@ -44,24 +44,31 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) String() string { return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *TLSEcdheEcdsaWithAes128GcmSha256) HashFunc() func() hash.Hash { return sha256.New } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *TLSEcdheEcdsaWithAes128GcmSha256) AuthenticationType() AuthenticationType { return AuthenticationTypeCertificate } // IsInitialized returns if the CipherSuite has keying material and can -// encrypt/decrypt packets +// encrypt/decrypt packets. func (c *TLSEcdheEcdsaWithAes128GcmSha256) IsInitialized() bool { return c.gcm.Load() != nil } -func (c *TLSEcdheEcdsaWithAes128GcmSha256) init(masterSecret, clientRandom, serverRandom []byte, isClient bool, prfMacLen, prfKeyLen, prfIvLen int, hashFunc func() hash.Hash) error { - keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, hashFunc) +func (c *TLSEcdheEcdsaWithAes128GcmSha256) init( + masterSecret, clientRandom, serverRandom []byte, + isClient bool, + prfMacLen, prfKeyLen, prfIvLen int, + hashFunc func() hash.Hash, +) error { + keys, err := prf.GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, hashFunc, + ) if err != nil { return err } @@ -73,10 +80,11 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) init(masterSecret, clientRandom, serv gcm, err = ciphersuite.NewGCM(keys.ServerWriteKey, keys.ServerWriteIV, keys.ClientWriteKey, keys.ClientWriteIV) } c.gcm.Store(gcm) + return err } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *TLSEcdheEcdsaWithAes128GcmSha256) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const ( prfMacLen = 0 @@ -87,7 +95,7 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) Init(masterSecret, clientRandom, serv return c.init(masterSecret, clientRandom, serverRandom, isClient, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc()) } -// Encrypt encrypts a single TLS RecordLayer +// Encrypt encrypts a single TLS RecordLayer. func (c *TLSEcdheEcdsaWithAes128GcmSha256) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { cipherSuite, ok := c.gcm.Load().(*ciphersuite.GCM) if !ok { @@ -97,7 +105,7 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) Encrypt(pkt *recordlayer.RecordLayer, return cipherSuite.Encrypt(pkt, raw) } -// Decrypt decrypts a single TLS RecordLayer +// Decrypt decrypts a single TLS RecordLayer. func (c *TLSEcdheEcdsaWithAes128GcmSha256) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.gcm.Load().(*ciphersuite.GCM) if !ok { diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go index 87f5ef395..6eeb91811 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go @@ -16,27 +16,27 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// TLSEcdheEcdsaWithAes256CbcSha represents a TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuite +// TLSEcdheEcdsaWithAes256CbcSha represents a TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuite. type TLSEcdheEcdsaWithAes256CbcSha struct { cbc atomic.Value // *cryptoCBC } -// CertificateType returns what type of certficate this CipherSuite exchanges +// CertificateType returns what type of certficate this CipherSuite exchanges. func (c *TLSEcdheEcdsaWithAes256CbcSha) CertificateType() clientcertificate.Type { return clientcertificate.ECDSASign } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *TLSEcdheEcdsaWithAes256CbcSha) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return KeyExchangeAlgorithmEcdhe } -// ECC uses Elliptic Curve Cryptography +// ECC uses Elliptic Curve Cryptography. func (c *TLSEcdheEcdsaWithAes256CbcSha) ECC() bool { return true } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheEcdsaWithAes256CbcSha) ID() ID { return TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA } @@ -45,23 +45,23 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) String() string { return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *TLSEcdheEcdsaWithAes256CbcSha) HashFunc() func() hash.Hash { return sha256.New } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *TLSEcdheEcdsaWithAes256CbcSha) AuthenticationType() AuthenticationType { return AuthenticationTypeCertificate } // IsInitialized returns if the CipherSuite has keying material and can -// encrypt/decrypt packets +// encrypt/decrypt packets. func (c *TLSEcdheEcdsaWithAes256CbcSha) IsInitialized() bool { return c.cbc.Load() != nil } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *TLSEcdheEcdsaWithAes256CbcSha) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const ( prfMacLen = 20 @@ -69,7 +69,9 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) Init(masterSecret, clientRandom, serverR prfIvLen = 16 ) - keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc()) + keys, err := prf.GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc(), + ) if err != nil { return err } @@ -93,7 +95,7 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) Init(masterSecret, clientRandom, serverR return err } -// Encrypt encrypts a single TLS RecordLayer +// Encrypt encrypts a single TLS RecordLayer. func (c *TLSEcdheEcdsaWithAes256CbcSha) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { @@ -103,7 +105,7 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) Encrypt(pkt *recordlayer.RecordLayer, ra return cipherSuite.Encrypt(pkt, raw) } -// Decrypt decrypts a single TLS RecordLayer +// Decrypt decrypts a single TLS RecordLayer. func (c *TLSEcdheEcdsaWithAes256CbcSha) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { diff --git a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go index 2a3cfa4f5..bf6f6c444 100644 --- a/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go +++ b/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go @@ -8,12 +8,12 @@ import ( "hash" ) -// TLSEcdheEcdsaWithAes256GcmSha384 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite +// TLSEcdheEcdsaWithAes256GcmSha384 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite. type TLSEcdheEcdsaWithAes256GcmSha384 struct { TLSEcdheEcdsaWithAes128GcmSha256 } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheEcdsaWithAes256GcmSha384) ID() ID { return TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 } @@ -22,12 +22,12 @@ func (c *TLSEcdheEcdsaWithAes256GcmSha384) String() string { return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *TLSEcdheEcdsaWithAes256GcmSha384) HashFunc() func() hash.Hash { return sha512.New384 } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *TLSEcdheEcdsaWithAes256GcmSha384) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const ( prfMacLen = 0 diff --git a/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go b/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go index 87b80f421..24f51e1eb 100644 --- a/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go +++ b/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go @@ -15,7 +15,7 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// TLSEcdhePskWithAes128CbcSha256 implements the TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuite +// TLSEcdhePskWithAes128CbcSha256 implements the TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuite. type TLSEcdhePskWithAes128CbcSha256 struct { cbc atomic.Value // *cryptoCBC } @@ -25,22 +25,22 @@ func NewTLSEcdhePskWithAes128CbcSha256() *TLSEcdhePskWithAes128CbcSha256 { return &TLSEcdhePskWithAes128CbcSha256{} } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSEcdhePskWithAes128CbcSha256) CertificateType() clientcertificate.Type { return clientcertificate.Type(0) } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *TLSEcdhePskWithAes128CbcSha256) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return (KeyExchangeAlgorithmPsk | KeyExchangeAlgorithmEcdhe) } -// ECC uses Elliptic Curve Cryptography +// ECC uses Elliptic Curve Cryptography. func (c *TLSEcdhePskWithAes128CbcSha256) ECC() bool { return true } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdhePskWithAes128CbcSha256) ID() ID { return TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 } @@ -49,23 +49,23 @@ func (c *TLSEcdhePskWithAes128CbcSha256) String() string { return "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256" } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *TLSEcdhePskWithAes128CbcSha256) HashFunc() func() hash.Hash { return sha256.New } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *TLSEcdhePskWithAes128CbcSha256) AuthenticationType() AuthenticationType { return AuthenticationTypePreSharedKey } // IsInitialized returns if the CipherSuite has keying material and can -// encrypt/decrypt packets +// encrypt/decrypt packets. func (c *TLSEcdhePskWithAes128CbcSha256) IsInitialized() bool { return c.cbc.Load() != nil } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *TLSEcdhePskWithAes128CbcSha256) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const ( prfMacLen = 32 @@ -73,7 +73,9 @@ func (c *TLSEcdhePskWithAes128CbcSha256) Init(masterSecret, clientRandom, server prfIvLen = 16 ) - keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc()) + keys, err := prf.GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc(), + ) if err != nil { return err } @@ -97,7 +99,7 @@ func (c *TLSEcdhePskWithAes128CbcSha256) Init(masterSecret, clientRandom, server return err } -// Encrypt encrypts a single TLS RecordLayer +// Encrypt encrypts a single TLS RecordLayer. func (c *TLSEcdhePskWithAes128CbcSha256) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { // !c.isInitialized() @@ -107,7 +109,7 @@ func (c *TLSEcdhePskWithAes128CbcSha256) Encrypt(pkt *recordlayer.RecordLayer, r return cipherSuite.Encrypt(pkt, raw) } -// Decrypt decrypts a single TLS RecordLayer +// Decrypt decrypts a single TLS RecordLayer. func (c *TLSEcdhePskWithAes128CbcSha256) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { // !c.isInitialized() diff --git a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go index 5ac17ed97..b78969111 100644 --- a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go +++ b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go @@ -5,17 +5,17 @@ package ciphersuite import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" -// TLSEcdheRsaWithAes128GcmSha256 implements the TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuite +// TLSEcdheRsaWithAes128GcmSha256 implements the TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuite. type TLSEcdheRsaWithAes128GcmSha256 struct { TLSEcdheEcdsaWithAes128GcmSha256 } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSEcdheRsaWithAes128GcmSha256) CertificateType() clientcertificate.Type { return clientcertificate.RSASign } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheRsaWithAes128GcmSha256) ID() ID { return TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } diff --git a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go index 545c2e46f..deb20dd94 100644 --- a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go +++ b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go @@ -5,17 +5,17 @@ package ciphersuite import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" -// TLSEcdheRsaWithAes256CbcSha implements the TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuite +// TLSEcdheRsaWithAes256CbcSha implements the TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuite. type TLSEcdheRsaWithAes256CbcSha struct { TLSEcdheEcdsaWithAes256CbcSha } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSEcdheRsaWithAes256CbcSha) CertificateType() clientcertificate.Type { return clientcertificate.RSASign } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheRsaWithAes256CbcSha) ID() ID { return TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA } diff --git a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go index 5750cc386..f7d7049a8 100644 --- a/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go +++ b/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go @@ -5,17 +5,17 @@ package ciphersuite import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" -// TLSEcdheRsaWithAes256GcmSha384 implements the TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuite +// TLSEcdheRsaWithAes256GcmSha384 implements the TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuite. type TLSEcdheRsaWithAes256GcmSha384 struct { TLSEcdheEcdsaWithAes256GcmSha384 } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSEcdheRsaWithAes256GcmSha384) CertificateType() clientcertificate.Type { return clientcertificate.RSASign } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheRsaWithAes256GcmSha384) ID() ID { return TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 } diff --git a/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go b/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go index dc485c46b..32507cdc3 100644 --- a/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go +++ b/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go @@ -15,27 +15,27 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// TLSPskWithAes128CbcSha256 implements the TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuite +// TLSPskWithAes128CbcSha256 implements the TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuite. type TLSPskWithAes128CbcSha256 struct { cbc atomic.Value // *cryptoCBC } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSPskWithAes128CbcSha256) CertificateType() clientcertificate.Type { return clientcertificate.Type(0) } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *TLSPskWithAes128CbcSha256) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return KeyExchangeAlgorithmPsk } -// ECC uses Elliptic Curve Cryptography +// ECC uses Elliptic Curve Cryptography. func (c *TLSPskWithAes128CbcSha256) ECC() bool { return false } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSPskWithAes128CbcSha256) ID() ID { return TLS_PSK_WITH_AES_128_CBC_SHA256 } @@ -44,23 +44,23 @@ func (c *TLSPskWithAes128CbcSha256) String() string { return "TLS_PSK_WITH_AES_128_CBC_SHA256" } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *TLSPskWithAes128CbcSha256) HashFunc() func() hash.Hash { return sha256.New } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *TLSPskWithAes128CbcSha256) AuthenticationType() AuthenticationType { return AuthenticationTypePreSharedKey } // IsInitialized returns if the CipherSuite has keying material and can -// encrypt/decrypt packets +// encrypt/decrypt packets. func (c *TLSPskWithAes128CbcSha256) IsInitialized() bool { return c.cbc.Load() != nil } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *TLSPskWithAes128CbcSha256) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const ( prfMacLen = 32 @@ -68,7 +68,9 @@ func (c *TLSPskWithAes128CbcSha256) Init(masterSecret, clientRandom, serverRando prfIvLen = 16 ) - keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc()) + keys, err := prf.GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc(), + ) if err != nil { return err } @@ -92,7 +94,7 @@ func (c *TLSPskWithAes128CbcSha256) Init(masterSecret, clientRandom, serverRando return err } -// Encrypt encrypts a single TLS RecordLayer +// Encrypt encrypts a single TLS RecordLayer. func (c *TLSPskWithAes128CbcSha256) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { @@ -102,7 +104,7 @@ func (c *TLSPskWithAes128CbcSha256) Encrypt(pkt *recordlayer.RecordLayer, raw [] return cipherSuite.Encrypt(pkt, raw) } -// Decrypt decrypts a single TLS RecordLayer +// Decrypt decrypts a single TLS RecordLayer. func (c *TLSPskWithAes128CbcSha256) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { diff --git a/internal/ciphersuite/tls_psk_with_aes_128_ccm.go b/internal/ciphersuite/tls_psk_with_aes_128_ccm.go index 6344f11fb..0b802fc8c 100644 --- a/internal/ciphersuite/tls_psk_with_aes_128_ccm.go +++ b/internal/ciphersuite/tls_psk_with_aes_128_ccm.go @@ -8,7 +8,14 @@ import ( "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) -// NewTLSPskWithAes128Ccm returns the TLS_PSK_WITH_AES_128_CCM CipherSuite +// NewTLSPskWithAes128Ccm returns the TLS_PSK_WITH_AES_128_CCM CipherSuite. func NewTLSPskWithAes128Ccm() *Aes128Ccm { - return newAes128Ccm(clientcertificate.Type(0), TLS_PSK_WITH_AES_128_CCM, true, ciphersuite.CCMTagLength, KeyExchangeAlgorithmPsk, false) + return newAes128Ccm( + clientcertificate.Type(0), + TLS_PSK_WITH_AES_128_CCM, + true, + ciphersuite.CCMTagLength, + KeyExchangeAlgorithmPsk, + false, + ) } diff --git a/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go b/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go index 4b0827533..c6bf6dc59 100644 --- a/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go +++ b/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go @@ -8,7 +8,14 @@ import ( "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) -// NewTLSPskWithAes128Ccm8 returns the TLS_PSK_WITH_AES_128_CCM_8 CipherSuite +// NewTLSPskWithAes128Ccm8 returns the TLS_PSK_WITH_AES_128_CCM_8 CipherSuite. func NewTLSPskWithAes128Ccm8() *Aes128Ccm { - return newAes128Ccm(clientcertificate.Type(0), TLS_PSK_WITH_AES_128_CCM_8, true, ciphersuite.CCMTagLength8, KeyExchangeAlgorithmPsk, false) + return newAes128Ccm( + clientcertificate.Type(0), + TLS_PSK_WITH_AES_128_CCM_8, + true, + ciphersuite.CCMTagLength8, + KeyExchangeAlgorithmPsk, + false, + ) } diff --git a/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go b/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go index 3a5e7e753..bc50d562b 100644 --- a/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go +++ b/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go @@ -5,22 +5,22 @@ package ciphersuite import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" -// TLSPskWithAes128GcmSha256 implements the TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuite +// TLSPskWithAes128GcmSha256 implements the TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuite. type TLSPskWithAes128GcmSha256 struct { TLSEcdheEcdsaWithAes128GcmSha256 } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSPskWithAes128GcmSha256) CertificateType() clientcertificate.Type { return clientcertificate.Type(0) } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *TLSPskWithAes128GcmSha256) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return KeyExchangeAlgorithmPsk } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSPskWithAes128GcmSha256) ID() ID { return TLS_PSK_WITH_AES_128_GCM_SHA256 } @@ -29,7 +29,7 @@ func (c *TLSPskWithAes128GcmSha256) String() string { return "TLS_PSK_WITH_AES_128_GCM_SHA256" } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *TLSPskWithAes128GcmSha256) AuthenticationType() AuthenticationType { return AuthenticationTypePreSharedKey } diff --git a/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go b/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go index 211bdae03..771a1d42e 100644 --- a/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go +++ b/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go @@ -8,7 +8,14 @@ import ( "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) -// NewTLSPskWithAes256Ccm8 returns the TLS_PSK_WITH_AES_256_CCM_8 CipherSuite +// NewTLSPskWithAes256Ccm8 returns the TLS_PSK_WITH_AES_256_CCM_8 CipherSuite. func NewTLSPskWithAes256Ccm8() *Aes256Ccm { - return newAes256Ccm(clientcertificate.Type(0), TLS_PSK_WITH_AES_256_CCM_8, true, ciphersuite.CCMTagLength8, KeyExchangeAlgorithmPsk, false) + return newAes256Ccm( + clientcertificate.Type(0), + TLS_PSK_WITH_AES_256_CCM_8, + true, + ciphersuite.CCMTagLength8, + KeyExchangeAlgorithmPsk, + false, + ) } diff --git a/internal/ciphersuite/types/authentication_type.go b/internal/ciphersuite/types/authentication_type.go index 2da21e642..09681cec5 100644 --- a/internal/ciphersuite/types/authentication_type.go +++ b/internal/ciphersuite/types/authentication_type.go @@ -3,10 +3,10 @@ package types -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. type AuthenticationType int -// AuthenticationType Enums +// AuthenticationType Enums. const ( AuthenticationTypeCertificate AuthenticationType = iota + 1 AuthenticationTypePreSharedKey diff --git a/internal/ciphersuite/types/key_exchange_algorithm.go b/internal/ciphersuite/types/key_exchange_algorithm.go index c2c39113a..5b59f2410 100644 --- a/internal/ciphersuite/types/key_exchange_algorithm.go +++ b/internal/ciphersuite/types/key_exchange_algorithm.go @@ -7,7 +7,7 @@ package types // KeyExchangeAlgorithm controls what exchange algorithm was chosen. type KeyExchangeAlgorithm int -// KeyExchangeAlgorithm Bitmask +// KeyExchangeAlgorithm Bitmask. const ( KeyExchangeAlgorithmNone KeyExchangeAlgorithm = 0 KeyExchangeAlgorithmPsk KeyExchangeAlgorithm = iota << 1 diff --git a/internal/closer/closer.go b/internal/closer/closer.go index bfa171cda..a1c25f379 100644 --- a/internal/closer/closer.go +++ b/internal/closer/closer.go @@ -8,41 +8,43 @@ import ( "context" ) -// Closer allows for each signaling a channel for shutdown +// Closer allows for each signaling a channel for shutdown. type Closer struct { - ctx context.Context + ctx context.Context //nolint:containedctx closeFunc func() } -// NewCloser creates a new instance of Closer +// NewCloser creates a new instance of Closer. func NewCloser() *Closer { ctx, closeFunc := context.WithCancel(context.Background()) + return &Closer{ ctx: ctx, closeFunc: closeFunc, } } -// NewCloserWithParent creates a new instance of Closer with a parent context +// NewCloserWithParent creates a new instance of Closer with a parent context. func NewCloserWithParent(ctx context.Context) *Closer { ctx, closeFunc := context.WithCancel(ctx) + return &Closer{ ctx: ctx, closeFunc: closeFunc, } } -// Done returns a channel signaling when it is done +// Done returns a channel signaling when it is done. func (c *Closer) Done() <-chan struct{} { return c.ctx.Done() } -// Err returns an error of the context +// Err returns an error of the context. func (c *Closer) Err() error { return c.ctx.Err() } -// Close sends a signal to trigger the ctx done channel +// Close sends a signal to trigger the ctx done channel. func (c *Closer) Close() { c.closeFunc() } diff --git a/internal/net/buffer.go b/internal/net/buffer.go index 9ab290e4c..c763f15e4 100644 --- a/internal/net/buffer.go +++ b/internal/net/buffer.go @@ -68,11 +68,12 @@ func NewPacketBuffer() *PacketBuffer { // WriteTo writes a single packet to the buffer. The supplied address will // remain associated with the packet. -func (b *PacketBuffer) WriteTo(p []byte, addr net.Addr) (int, error) { +func (b *PacketBuffer) WriteTo(pkt []byte, addr net.Addr) (int, error) { b.mutex.Lock() if b.closed { b.mutex.Unlock() + return 0, io.ErrClosedPipe } @@ -113,9 +114,10 @@ func (b *PacketBuffer) WriteTo(p []byte, addr net.Addr) (int, error) { // Store the packet at the write pointer. packet := &b.packets[b.write] packet.data.Reset() - n, err := packet.data.Write(p) + n, err := packet.data.Write(pkt) if err != nil { b.mutex.Unlock() + return n, err } packet.addr = addr @@ -145,7 +147,7 @@ func (b *PacketBuffer) WriteTo(p []byte, addr net.Addr) (int, error) { // ReadFrom reads a single packet from the buffer, or blocks until one is // available. -func (b *PacketBuffer) ReadFrom(packet []byte) (n int, addr net.Addr, err error) { +func (b *PacketBuffer) ReadFrom(packet []byte) (n int, addr net.Addr, err error) { //nolint:cyclop select { case <-b.readDeadline.Done(): return 0, nil, ErrTimeout @@ -159,6 +161,7 @@ func (b *PacketBuffer) ReadFrom(packet []byte) (n int, addr net.Addr, err error) ap := b.packets[b.read] if len(packet) < ap.data.Len() { b.mutex.Unlock() + return 0, nil, io.ErrShortBuffer } @@ -166,6 +169,7 @@ func (b *PacketBuffer) ReadFrom(packet []byte) (n int, addr net.Addr, err error) n, err := ap.data.Read(packet) if err != nil { b.mutex.Unlock() + return n, nil, err } @@ -188,6 +192,7 @@ func (b *PacketBuffer) ReadFrom(packet []byte) (n int, addr net.Addr, err error) if b.closed { b.mutex.Unlock() + return 0, nil, io.EOF } @@ -212,6 +217,7 @@ func (b *PacketBuffer) Close() (err error) { if b.closed { b.mutex.Unlock() + return nil } @@ -231,5 +237,6 @@ func (b *PacketBuffer) Close() (err error) { // SetReadDeadline sets the read deadline for the buffer. func (b *PacketBuffer) SetReadDeadline(t time.Time) error { b.readDeadline.Set(t) + return nil } diff --git a/internal/net/buffer_test.go b/internal/net/buffer_test.go index e416dde53..87a2a6ce1 100644 --- a/internal/net/buffer_test.go +++ b/internal/net/buffer_test.go @@ -15,12 +15,16 @@ import ( ) func equalInt(t *testing.T, expected, actual int) { + t.Helper() + if expected != actual { t.Errorf("Expected %d got %d", expected, actual) } } func equalUDPAddr(t *testing.T, expected, actual net.Addr) { + t.Helper() + if expected == nil && actual == nil { return } @@ -30,12 +34,14 @@ func equalUDPAddr(t *testing.T, expected, actual net.Addr) { } func equalBytes(t *testing.T, expected, actual []byte) { + t.Helper() + if !bytes.Equal(expected, actual) { t.Errorf("Expected %v got %v", expected, actual) } } -func TestBuffer(t *testing.T) { +func TestBuffer(t *testing.T) { //nolint:cyclop buffer := NewPacketBuffer() packet := make([]byte, 4) addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") @@ -243,6 +249,7 @@ func TestBufferAsync(t *testing.T) { n, raddr, rErr := buffer.ReadFrom(packet) if rErr != nil { done <- rErr.Error() + return } @@ -281,7 +288,9 @@ func TestBufferAsync(t *testing.T) { } } -func benchmarkBufferWR(b *testing.B, size int64, write bool, grow int) { // nolint:unparam +func benchmarkBufferWR(b *testing.B, size int64, write bool, grow int) { // nolint:unparam,cyclop + b.Helper() + addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") if err != nil { b.Fatalf("net.ResolveUDPAddr: %v", err) @@ -335,7 +344,7 @@ func BenchmarkBufferWR1400(b *testing.B) { benchmarkBufferWR(b, 1400, false, 128) } -// Here, the buffer never becomes empty, which forces wraparound +// Here, the buffer never becomes empty, which forces wraparound. func BenchmarkBufferWWR14(b *testing.B) { benchmarkBufferWR(b, 14, true, 128) } @@ -349,6 +358,8 @@ func BenchmarkBufferWWR1400(b *testing.B) { } func benchmarkBuffer(b *testing.B, size int64) { + b.Helper() + addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5684") if err != nil { b.Fatalf("net.ResolveUDPAddr: %v", err) @@ -366,6 +377,7 @@ func benchmarkBuffer(b *testing.B, size int64) { break } else if err != nil { b.Error(err) + break } } diff --git a/internal/net/udp/packet_conn.go b/internal/net/udp/packet_conn.go index da5b6fae8..e3e214ce9 100644 --- a/internal/net/udp/packet_conn.go +++ b/internal/net/udp/packet_conn.go @@ -34,13 +34,13 @@ const ( defaultListenBacklog = 128 // same as Linux default ) -// Typed errors +// Typed errors. var ( ErrClosedListener = errors.New("udp: listener closed") ErrListenQueueExceeded = errors.New("udp: listen queue exceeded") ) -// listener augments a connection-oriented Listener over a UDP PacketConn +// listener augments a connection-oriented Listener over a UDP PacketConn. type listener struct { pConn *net.UDPConn @@ -68,10 +68,12 @@ func (l *listener) Accept() (net.PacketConn, net.Addr, error) { select { case c := <-l.acceptCh: l.connWG.Add(1) + return c, c.raddr, nil case <-l.readDoneCh: err, _ := l.errRead.Load().(error) + return nil, nil, err case <-l.doneCh: @@ -168,7 +170,7 @@ func (lc *ListenConfig) Listen(network string, laddr *net.UDPAddr) (dtlsnet.Pack return nil, err } - l := &listener{ + packetListener := &listener{ pConn: conn, acceptCh: make(chan *PacketConn, lc.Backlog), conns: make(map[string]*PacketConn), @@ -179,20 +181,20 @@ func (lc *ListenConfig) Listen(network string, laddr *net.UDPAddr) (dtlsnet.Pack readDoneCh: make(chan struct{}), } - l.accepting.Store(true) - l.connWG.Add(1) - l.readWG.Add(2) // wait readLoop and Close execution routine + packetListener.accepting.Store(true) + packetListener.connWG.Add(1) + packetListener.readWG.Add(2) // wait readLoop and Close execution routine - go l.readLoop() + go packetListener.readLoop() go func() { - l.connWG.Wait() - if err := l.pConn.Close(); err != nil { - l.errClose.Store(err) + packetListener.connWG.Wait() + if err := packetListener.pConn.Close(); err != nil { + packetListener.errClose.Store(err) } - l.readWG.Done() + packetListener.readWG.Done() }() - return l, nil + return packetListener, nil } // Listen creates a new listener using default ListenConfig. @@ -212,6 +214,7 @@ func (l *listener) readLoop() { n, raddr, err := l.pConn.ReadFrom(buf) if err != nil { l.errRead.Store(err) + return } conn, ok, err := l.getConn(raddr, buf[:n]) @@ -225,7 +228,7 @@ func (l *listener) readLoop() { } // getConn gets an existing connection or creates a new one. -func (l *listener) getConn(raddr net.Addr, buf []byte) (*PacketConn, bool, error) { +func (l *listener) getConn(raddr net.Addr, buf []byte) (*PacketConn, bool, error) { //nolint:cyclop l.connLock.Lock() defer l.connLock.Unlock() // If we have a custom resolver, use it. @@ -257,6 +260,7 @@ func (l *listener) getConn(raddr net.Addr, buf []byte) (*PacketConn, bool, error return nil, false, ErrListenQueueExceeded } } + return conn, true, nil } @@ -292,19 +296,19 @@ func (l *listener) newPacketConn(raddr net.Addr) *PacketConn { // ReadFrom reads a single packet payload and its associated remote address from // the underlying buffer. -func (c *PacketConn) ReadFrom(p []byte) (int, net.Addr, error) { - return c.buffer.ReadFrom(p) +func (c *PacketConn) ReadFrom(buff []byte) (int, net.Addr, error) { + return c.buffer.ReadFrom(buff) } -// WriteTo writes len(p) bytes from p to the specified address. -func (c *PacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { +// WriteTo writes len(payload) bytes from payload to the specified address. +func (c *PacketConn) WriteTo(payload []byte, addr net.Addr) (n int, err error) { // If we have a connection identifier, check to see if the outgoing packet // sets it. if c.listener.connIdentifier != nil { id := c.id.Load() // Only update establish identifier if we haven't already done so. if id == nil { - candidate, ok := c.listener.connIdentifier(p) + candidate, ok := c.listener.connIdentifier(payload) // If we have an identifier, add entry to connection map. if ok { c.listener.connLock.Lock() @@ -340,10 +344,11 @@ func (c *PacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { return 0, context.DeadlineExceeded default: } - return c.listener.pConn.WriteTo(p, addr) + + return c.listener.pConn.WriteTo(payload, addr) } -// Close closes the conn and releases any Read calls +// Close closes the conn and releases any Read calls. func (c *PacketConn) Close() error { var err error c.doneOnce.Do(func() { @@ -390,6 +395,7 @@ func (c *PacketConn) LocalAddr() net.Addr { // SetDeadline implements net.PacketConn.SetDeadline. func (c *PacketConn) SetDeadline(t time.Time) error { c.writeDeadline.Set(t) + return c.SetReadDeadline(t) } diff --git a/internal/net/udp/packet_conn_test.go b/internal/net/udp/packet_conn_test.go index 2e9f4a063..53b3c06d5 100644 --- a/internal/net/udp/packet_conn_test.go +++ b/internal/net/udp/packet_conn_test.go @@ -51,6 +51,7 @@ func fromPC(p net.PacketConn, raddr net.Addr) *rw { func (r *rw) Read(p []byte) (int, error) { n, _, err := r.p.ReadFrom(p) + return n, err } @@ -59,6 +60,8 @@ func (r *rw) Write(p []byte) (int, error) { } func stressDuplex(t *testing.T) { + t.Helper() + listener, ca, cb, err := pipe() if err != nil { t.Fatal(err) @@ -135,6 +138,7 @@ func TestListenerCloseUnaccepted(t *testing.T) { conn, dErr := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) if dErr != nil { t.Error(dErr) + continue } if _, wErr := conn.Write([]byte{byte(i)}); wErr != nil { @@ -153,7 +157,7 @@ func TestListenerCloseUnaccepted(t *testing.T) { } } -func TestListenerAcceptFilter(t *testing.T) { +func TestListenerAcceptFilter(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -220,6 +224,7 @@ func TestListenerAcceptFilter(t *testing.T) { if !errors.Is(aArr, ErrClosedListener) { t.Error(aArr) } + return } close(chAccepted) @@ -246,7 +251,7 @@ func TestListenerAcceptFilter(t *testing.T) { } } -func TestListenerConcurrent(t *testing.T) { +func TestListenerConcurrent(t *testing.T) { //nolint:gocyclo,cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -269,6 +274,7 @@ func TestListenerConcurrent(t *testing.T) { conn, dErr := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) if dErr != nil { t.Error(dErr) + continue } if _, wErr := conn.Write([]byte{byte(i)}); wErr != nil { @@ -285,6 +291,7 @@ func TestListenerConcurrent(t *testing.T) { conn, _, lErr := listener.Accept() if lErr != nil { t.Error(lErr) + continue } b := make([]byte, 1) @@ -367,7 +374,7 @@ func getConfig() (string, *net.UDPAddr) { return "udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 0} } -func TestConnClose(t *testing.T) { +func TestConnClose(t *testing.T) { //nolint:cyclop lim := test.TimeOut(time.Second * 5) defer lim.Stop() @@ -376,7 +383,7 @@ func TestConnClose(t *testing.T) { report := test.CheckRoutines(t) defer report() - l, ca, cb, errPipe := pipe() + udpListener, ca, cb, errPipe := pipe() if errPipe != nil { t.Fatal(errPipe) } @@ -386,7 +393,7 @@ func TestConnClose(t *testing.T) { if err := cb.Close(); err != nil { t.Errorf("Failed to close B side: %v", err) } - if err := l.Close(); err != nil { + if err := udpListener.Close(); err != nil { t.Errorf("Failed to close listener: %v", err) } }) @@ -395,12 +402,12 @@ func TestConnClose(t *testing.T) { report := test.CheckRoutines(t) defer report() - l, ca, cb, errPipe := pipe() + udpListener, ca, cb, errPipe := pipe() if errPipe != nil { t.Fatal(errPipe) } // Close l.pConn to inject error. - if err := l.(*listener).pConn.Close(); err != nil { //nolint:forcetypeassert + if err := udpListener.(*listener).pConn.Close(); err != nil { //nolint:forcetypeassert t.Error(err) } @@ -410,7 +417,7 @@ func TestConnClose(t *testing.T) { if err := ca.Close(); err != nil { t.Errorf("Failed to close B side: %v", err) } - if err := l.Close(); err == nil { + if err := udpListener.Close(); err == nil { t.Errorf("Error is not propagated to Listener.Close") } }) @@ -447,7 +454,7 @@ func TestConnClose(t *testing.T) { report := test.CheckRoutines(t) defer report() - l, ca, cb, errPipe := pipe() + listener, ca, cb, errPipe := pipe() if errPipe != nil { t.Fatal(errPipe) } @@ -474,13 +481,13 @@ func TestConnClose(t *testing.T) { if err := cb.Close(); err != nil { t.Errorf("Failed to close A side: %v", err) } - if err := l.Close(); err != nil { + if err := listener.Close(); err != nil { t.Errorf("Failed to close listener: %v", err) } }) } -func TestListenerCustomConnIDs(t *testing.T) { +func TestListenerCustomConnIDs(t *testing.T) { //nolint:gocyclo,cyclop,maintidx const helloPayload, setPayload = "hello", "set" const serverCount, clientCount = 5, 20 // Limit runtime in case of deadlocks. @@ -507,6 +514,7 @@ func TestListenerCustomConnIDs(t *testing.T) { if p.Payload == helloPayload { return "", false } + return fmt.Sprint(p.ID), true }, // Use the outgoing "set" payload to add an identifier for a connection. @@ -518,6 +526,7 @@ func TestListenerCustomConnIDs(t *testing.T) { if p.Payload == setPayload { return fmt.Sprint(p.ID), true } + return "", false }, }).Listen(network, addr) @@ -543,26 +552,30 @@ func TestListenerCustomConnIDs(t *testing.T) { conn, _, err := listener.Accept() if err != nil { t.Error(err) + return } buf := make([]byte, 100) n, raddr, rErr := conn.ReadFrom(buf) if rErr != nil { t.Error(err) + return } - var p pkt - if uErr := json.Unmarshal(buf[:n], &p); uErr != nil { + var udpPkt pkt + if uErr := json.Unmarshal(buf[:n], &udpPkt); uErr != nil { t.Error(err) + return } // First message should be a hello and custom connection // ID function will use remote address as identifier. - if p.Payload != helloPayload { + if udpPkt.Payload != helloPayload { t.Error("Expected hello message") + return } - connID := p.ID + connID := udpPkt.ID // Send set message to associate ID with this connection. buf, err = json.Marshal(&pkt{ @@ -571,10 +584,12 @@ func TestListenerCustomConnIDs(t *testing.T) { }) if err != nil { t.Error(err) + return } if _, wErr := conn.WriteTo(buf, raddr); wErr != nil { t.Error(wErr) + return } // Signal to the corresponding clients that connection ID has been @@ -587,25 +602,29 @@ func TestListenerCustomConnIDs(t *testing.T) { n, _, err := conn.ReadFrom(buf) if err != nil { t.Error(err) + return } - var p pkt - if err := json.Unmarshal(buf[:n], &p); err != nil { + var udpPkt pkt + if err := json.Unmarshal(buf[:n], &udpPkt); err != nil { t.Error(err) + return } - if p.ID != connID { - t.Errorf("Expected connection ID %d, but got %d", connID, p.ID) + if udpPkt.ID != connID { + t.Errorf("Expected connection ID %d, but got %d", connID, udpPkt.ID) + return } // Ensure we only ever receive one message from // a given client. clientMapMu.Lock() - if _, ok := clientMap[p.Payload]; ok { - t.Errorf("Multiple messages from single client %s", p.Payload) + if _, ok := clientMap[udpPkt.Payload]; ok { + t.Errorf("Multiple messages from single client %s", udpPkt.Payload) + return } - clientMap[p.Payload] = struct{}{} + clientMap[udpPkt.Payload] = struct{}{} clientMapMu.Unlock() } if err := conn.Close(); err != nil { @@ -623,6 +642,7 @@ func TestListenerCustomConnIDs(t *testing.T) { conn, dErr := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) if dErr != nil { t.Error(dErr) + return } hbuf, err := json.Marshal(&pkt{ @@ -631,35 +651,41 @@ func TestListenerCustomConnIDs(t *testing.T) { }) if err != nil { t.Error(err) + return } if _, wErr := conn.Write(hbuf); wErr != nil { t.Error(wErr) + return } - var p pkt + var udpPacket pkt buf := make([]byte, 100) n, err := conn.Read(buf) if err != nil { t.Error(err) + return } - if err := json.Unmarshal(buf[:n], &p); err != nil { + if err := json.Unmarshal(buf[:n], &udpPacket); err != nil { t.Error(err) + return } // Second message should be a set and custom connection identifier // function will update the connection ID from remote address to the // supplied ID. - if p.Payload != "set" { + if udpPacket.Payload != "set" { t.Error("Expected set message") + return } // Ensure the connection ID matches what the "hello" message // indicated. - if p.ID != connID { - t.Errorf("Expected connection ID %d, but got %d", connID, p.ID) + if udpPacket.ID != connID { + t.Errorf("Expected connection ID %d, but got %d", connID, udpPacket.ID) + return } // Close connection. We will reconnect from a different remote @@ -681,6 +707,7 @@ func TestListenerCustomConnIDs(t *testing.T) { conn, dErr := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) if dErr != nil { t.Error(dErr) + return } // Send a packet with a connection ID and this client's local @@ -691,10 +718,12 @@ func TestListenerCustomConnIDs(t *testing.T) { }) if err != nil { t.Error(err) + return } if _, wErr := conn.Write(buf); wErr != nil { t.Error(wErr) + return } if cErr := conn.Close(); cErr != nil { diff --git a/internal/util/util.go b/internal/util/util.go index 382a0e1cd..8ebbcd44f 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -10,7 +10,7 @@ import ( "golang.org/x/crypto/cryptobyte" ) -// BigEndianUint24 returns the value of a big endian uint24 +// BigEndianUint24 returns the value of a big endian uint24. func BigEndianUint24(raw []byte) uint32 { if len(raw) < 3 { return 0 @@ -18,28 +18,30 @@ func BigEndianUint24(raw []byte) uint32 { rawCopy := make([]byte, 4) copy(rawCopy[1:], raw) + return binary.BigEndian.Uint32(rawCopy) } -// PutBigEndianUint24 encodes a uint24 and places into out +// PutBigEndianUint24 encodes a uint24 and places into out. func PutBigEndianUint24(out []byte, in uint32) { tmp := make([]byte, 4) binary.BigEndian.PutUint32(tmp, in) copy(out, tmp[1:]) } -// PutBigEndianUint48 encodes a uint64 and places into out +// PutBigEndianUint48 encodes a uint64 and places into out. func PutBigEndianUint48(out []byte, in uint64) { tmp := make([]byte, 8) binary.BigEndian.PutUint64(tmp, in) copy(out, tmp[2:]) } -// Max returns the larger value +// Max returns the larger value. func Max(a, b int) int { if a > b { return a } + return b } diff --git a/internal/util/util_test.go b/internal/util/util_test.go index c247f68bb..41127c0b8 100644 --- a/internal/util/util_test.go +++ b/internal/util/util_test.go @@ -29,16 +29,19 @@ func TestAddUint48(t *testing.T) { builder: func() *cryptobyte.Builder { var b cryptobyte.Builder b.AddUint64(0xffffffffffffffff) + return &b }(), in: 0xfefcff3cfdfc, want: []byte{255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 255, 60, 253, 252}, }, "ExistingAddUint48AndMore": { + //nolint:lll reason: "Adding a 48-bit unsigned integer to a builder with existing bytes, then adding more bytes, should yield expected result.", builder: func() *cryptobyte.Builder { var b cryptobyte.Builder b.AddUint64(0xffffffffffffffff) + return &b }(), postAdd: func(b *cryptobyte.Builder) { diff --git a/listener.go b/listener.go index 22e56ce52..3583d0308 100644 --- a/listener.go +++ b/listener.go @@ -12,7 +12,7 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// Listen creates a DTLS listener +// Listen creates a DTLS listener. func Listen(network string, laddr *net.UDPAddr, config *Config) (net.Listener, error) { if err := validateConfig(config); err != nil { return nil, err @@ -28,6 +28,7 @@ func Listen(network string, laddr *net.UDPAddr, config *Config) (net.Listener, e if err := h.Unmarshal(pkts[0]); err != nil { return false } + return h.ContentType == protocol.ContentTypeHandshake }, } @@ -41,6 +42,7 @@ func Listen(network string, laddr *net.UDPAddr, config *Config) (net.Listener, e if err != nil { return nil, err } + return &listener{ config: config, parent: parent, @@ -59,7 +61,7 @@ func NewListener(inner dtlsnet.PacketListener, config *Config) (net.Listener, er }, nil } -// listener represents a DTLS listener +// listener represents a DTLS listener. type listener struct { config *Config parent dtlsnet.PacketListener @@ -72,6 +74,7 @@ func (l *listener) Accept() (net.Conn, error) { if err != nil { return nil, err } + return Server(c, raddr, l.config) } diff --git a/nettest_test.go b/nettest_test.go index dc245b28d..3a712434f 100644 --- a/nettest_test.go +++ b/nettest_test.go @@ -28,6 +28,7 @@ func TestNetTest(t *testing.T) { _ = c1.Close() _ = c2.Close() } + return }) } diff --git a/pkg/crypto/ccm/ccm.go b/pkg/crypto/ccm/ccm.go index 73476f219..bc268deeb 100644 --- a/pkg/crypto/ccm/ccm.go +++ b/pkg/crypto/ccm/ccm.go @@ -65,7 +65,8 @@ func NewCCM(b cipher.Block, tagsize, noncesize int) (CCM, error) { if lensize < 2 || lensize > 8 { return nil, errInvalidNonceSize } - c := &ccm{b: b, M: uint8(tagsize), L: uint8(lensize)} + c := &ccm{b: b, M: uint8(tagsize), L: uint8(lensize)} //nolint:gosec // G114 + return c, nil } @@ -75,13 +76,14 @@ func (c *ccm) MaxLength() int { return maxlen(c.L, c.Overhead()) } func maxlen(l uint8, tagsize int) int { mLen := (uint64(1) << (8 * l)) - 1 - if m64 := uint64(math.MaxInt64) - uint64(tagsize); l > 8 || mLen > m64 { + if m64 := uint64(math.MaxInt64) - uint64(tagsize); l > 8 || mLen > m64 { //nolint:gosec // G114 mLen = m64 // The maximum lentgh on a 64bit arch } - if mLen != uint64(int(mLen)) { + if mLen != uint64(int(mLen)) { //nolint:gosec // G114 return math.MaxInt32 - tagsize // We have only 32bit int's } - return int(mLen) + + return int(mLen) //nolint:gosec // G114 } // MaxNonceLength returns the maximum nonce length for a given plaintext length. @@ -90,10 +92,11 @@ func maxlen(l uint8, tagsize int) int { func MaxNonceLength(pdatalen int) int { const tagsize = 16 for L := 2; L <= 8; L++ { - if maxlen(uint8(L), tagsize) >= pdatalen { + if maxlen(uint8(L), tagsize) >= pdatalen { //nolint:gosec // G115 return 15 - L } } + return 0 } @@ -137,20 +140,20 @@ func (c *ccm) tag(nonce, plaintext, adata []byte) ([]byte, error) { c.b.Encrypt(mac[:], mac[:]) var block [ccmBlockSize]byte - if n := uint64(len(adata)); n > 0 { + if adataLength := uint64(len(adata)); adataLength > 0 { //nolint:nestif // First adata block includes adata length i := 2 - if n <= 0xfeff { - binary.BigEndian.PutUint16(block[:i], uint16(n)) + if adataLength <= 0xfeff { + binary.BigEndian.PutUint16(block[:i], uint16(adataLength)) } else { block[0] = 0xfe block[1] = 0xff - if n < uint64(1<<32) { + if adataLength < uint64(1<<32) { i = 2 + 4 - binary.BigEndian.PutUint32(block[2:i], uint32(n)) + binary.BigEndian.PutUint32(block[2:i], uint32(adataLength)) //nolint:gosec // G115 } else { i = 2 + 8 - binary.BigEndian.PutUint64(block[2:i], n) + binary.BigEndian.PutUint64(block[2:i], adataLength) } } i = copy(block[i:], adata) @@ -170,6 +173,7 @@ func (c *ccm) tag(nonce, plaintext, adata []byte) ([]byte, error) { // second slice that aliases into it and contains only the extra bytes. If the // original slice has sufficient capacity then no allocation is performed. // From crypto/cipher/gcm.go +// . func sliceForAppend(in []byte, n int) (head, tail []byte) { if total := len(in) + n; cap(in) >= total { head = in[:total] @@ -178,6 +182,7 @@ func sliceForAppend(in []byte, n int) (head, tail []byte) { copy(head, in) } tail = head[len(in):] + return } @@ -207,6 +212,7 @@ func (c *ccm) Seal(dst, nonce, plaintext, adata []byte) []byte { ret, out := sliceForAppend(dst, len(plaintext)+int(c.M)) stream.XORKeyStream(out, plaintext) copy(out[len(plaintext):], tag) + return ret } @@ -250,5 +256,6 @@ func (c *ccm) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) { if subtle.ConstantTimeCompare(tag, expectedTag) != 1 { return nil, errOpen } + return append(dst, plaintext...), nil } diff --git a/pkg/crypto/ccm/ccm_test.go b/pkg/crypto/ccm/ccm_test.go index da88f2a05..c8056c721 100644 --- a/pkg/crypto/ccm/ccm_test.go +++ b/pkg/crypto/ccm/ccm_test.go @@ -19,6 +19,7 @@ func mustHexDecode(s string) []byte { if err != nil { panic(err) } + return r } @@ -32,7 +33,7 @@ var ( // ClearHeaderOctets: Input with X cleartext header octets // Data: Input with X cleartext header octets // M: length(CBC-MAC) -// Nonce: Nonce +// Nonce: Nonce. type vector struct { AESKey []byte CipherText []byte @@ -42,7 +43,7 @@ type vector struct { Nonce []byte } -func TestRFC3610Vectors(t *testing.T) { +func TestRFC3610Vectors(t *testing.T) { //nolint:maintidx cases := []vector{ // Vectors 1-12 { @@ -62,8 +63,10 @@ func TestRFC3610Vectors(t *testing.T) { Nonce: mustHexDecode("00000004030201a0a1a2a3a4a5"), }, { - AESKey: aesKey1to12, - CipherText: mustHexDecode("000102030405060751b1e5f44a197d1da46b0f8e2d282ae871e838bb64da8596574adaa76fbd9fb0c5"), + AESKey: aesKey1to12, + CipherText: mustHexDecode( + "000102030405060751b1e5f44a197d1da46b0f8e2d282ae871e838bb64da8596574adaa76fbd9fb0c5", + ), ClearHeaderOctets: 8, Data: mustHexDecode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), M: 8, @@ -86,56 +89,70 @@ func TestRFC3610Vectors(t *testing.T) { Nonce: mustHexDecode("00000007060504a0a1a2a3a4a5"), }, { - AESKey: aesKey1to12, - CipherText: mustHexDecode("000102030405060708090a0b6fc1b011f006568b5171a42d953d469b2570a4bd87405a0443ac91cb94"), + AESKey: aesKey1to12, + CipherText: mustHexDecode( + "000102030405060708090a0b6fc1b011f006568b5171a42d953d469b2570a4bd87405a0443ac91cb94", + ), ClearHeaderOctets: 12, Data: mustHexDecode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), M: 8, Nonce: mustHexDecode("00000008070605a0a1a2a3a4a5"), }, { - AESKey: aesKey1to12, - CipherText: mustHexDecode("00010203040506070135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c048c56602c97acbb7490"), + AESKey: aesKey1to12, + CipherText: mustHexDecode( + "00010203040506070135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c048c56602c97acbb7490", + ), ClearHeaderOctets: 8, Data: mustHexDecode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e"), M: 10, Nonce: mustHexDecode("00000009080706a0a1a2a3a4a5"), }, { - AESKey: aesKey1to12, - CipherText: mustHexDecode("00010203040506077b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24c17b4433f434963f34b4"), + AESKey: aesKey1to12, + CipherText: mustHexDecode( + "00010203040506077b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24c17b4433f434963f34b4", + ), ClearHeaderOctets: 8, Data: mustHexDecode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), M: 10, Nonce: mustHexDecode("0000000a090807a0a1a2a3a4a5"), }, { - AESKey: aesKey1to12, - CipherText: mustHexDecode("000102030405060782531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197ea9c07e56b5eb17e5f4e"), + AESKey: aesKey1to12, + CipherText: mustHexDecode( + "000102030405060782531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197ea9c07e56b5eb17e5f4e", + ), ClearHeaderOctets: 8, Data: mustHexDecode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), M: 10, Nonce: mustHexDecode("0000000b0a0908a0a1a2a3a4a5"), }, { - AESKey: aesKey1to12, - CipherText: mustHexDecode("000102030405060708090a0b07342594157785152b074098330abb141b947b566aa9406b4d999988dd"), + AESKey: aesKey1to12, + CipherText: mustHexDecode( + "000102030405060708090a0b07342594157785152b074098330abb141b947b566aa9406b4d999988dd", + ), ClearHeaderOctets: 12, Data: mustHexDecode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e"), M: 10, Nonce: mustHexDecode("0000000c0b0a09a0a1a2a3a4a5"), }, { - AESKey: aesKey1to12, - CipherText: mustHexDecode("000102030405060708090a0b676bb20380b0e301e8ab79590a396da78b834934f53aa2e9107a8b6c022c"), + AESKey: aesKey1to12, + CipherText: mustHexDecode( + "000102030405060708090a0b676bb20380b0e301e8ab79590a396da78b834934f53aa2e9107a8b6c022c", + ), ClearHeaderOctets: 12, Data: mustHexDecode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), M: 10, Nonce: mustHexDecode("0000000d0c0b0aa0a1a2a3a4a5"), }, { - AESKey: aesKey1to12, - CipherText: mustHexDecode("000102030405060708090a0bc0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43cd1aa31662e7ad65d6db"), + AESKey: aesKey1to12, + CipherText: mustHexDecode( + "000102030405060708090a0bc0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43cd1aa31662e7ad65d6db", + ), ClearHeaderOctets: 12, Data: mustHexDecode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), M: 10, @@ -159,8 +176,10 @@ func TestRFC3610Vectors(t *testing.T) { Nonce: mustHexDecode("0033568ef7b2633c9696766cfa"), }, { - AESKey: aesKey13to24, - CipherText: mustHexDecode("aa6cfa36cae86b40b1d23a2220ddc0ac900d9aa03c61fcf4a559a4417767089708a776796edb723506"), + AESKey: aesKey13to24, + CipherText: mustHexDecode( + "aa6cfa36cae86b40b1d23a2220ddc0ac900d9aa03c61fcf4a559a4417767089708a776796edb723506", + ), ClearHeaderOctets: 8, Data: mustHexDecode("aa6cfa36cae86b40b916e0eacc1c00d7dcec68ec0b3bbb1a02de8a2d1aa346132e"), M: 8, @@ -183,56 +202,70 @@ func TestRFC3610Vectors(t *testing.T) { Nonce: mustHexDecode("00f8b678094e3b3c9696766cfa"), }, { - AESKey: aesKey13to24, - CipherText: mustHexDecode("cd9044d2b71fdb8120ea60c0009769ecabdf48625594c59251e6035722675e04c847099e5ae0704551"), + AESKey: aesKey13to24, + CipherText: mustHexDecode( + "cd9044d2b71fdb8120ea60c0009769ecabdf48625594c59251e6035722675e04c847099e5ae0704551", + ), ClearHeaderOctets: 12, Data: mustHexDecode("cd9044d2b71fdb8120ea60c06435acbafb11a82e2f071d7ca4a5ebd93a803ba87f"), M: 8, Nonce: mustHexDecode("00d560912d3f703c9696766cfa"), }, { - AESKey: aesKey13to24, - CipherText: mustHexDecode("d85bc7e69f944fb8bc218daa947427b6db386a99ac1aef23ade0b52939cb6a637cf9bec2408897c6ba"), + AESKey: aesKey13to24, + CipherText: mustHexDecode( + "d85bc7e69f944fb8bc218daa947427b6db386a99ac1aef23ade0b52939cb6a637cf9bec2408897c6ba", + ), ClearHeaderOctets: 8, Data: mustHexDecode("d85bc7e69f944fb88a19b950bcf71a018e5e6701c91787659809d67dbedd18"), M: 10, Nonce: mustHexDecode("0042fff8f1951c3c9696766cfa"), }, { - AESKey: aesKey13to24, - CipherText: mustHexDecode("74a0ebc9069f5b375810e6fd25874022e80361a478e3e9cf484ab04f447efff6f0a477cc2fc9bf548944"), + AESKey: aesKey13to24, + CipherText: mustHexDecode( + "74a0ebc9069f5b375810e6fd25874022e80361a478e3e9cf484ab04f447efff6f0a477cc2fc9bf548944", + ), ClearHeaderOctets: 8, Data: mustHexDecode("74a0ebc9069f5b371761433c37c5a35fc1f39f406302eb907c6163be38c98437"), M: 10, Nonce: mustHexDecode("00920f40e56cdc3c9696766cfa"), }, { - AESKey: aesKey13to24, - CipherText: mustHexDecode("44a3aa3aae6475caf2beed7bc5098e83feb5b31608f8e29c38819a89c8e776f1544d4151a4ed3a8b87b9ce"), + AESKey: aesKey13to24, + CipherText: mustHexDecode( + "44a3aa3aae6475caf2beed7bc5098e83feb5b31608f8e29c38819a89c8e776f1544d4151a4ed3a8b87b9ce", + ), ClearHeaderOctets: 8, Data: mustHexDecode("44a3aa3aae6475caa434a8e58500c6e41530538862d686ea9e81301b5ae4226bfa"), M: 10, Nonce: mustHexDecode("0027ca0c7120bc3c9696766cfa"), }, { - AESKey: aesKey13to24, - CipherText: mustHexDecode("ec46bb63b02520c33c49fd7031d750a09da3ed7fddd49a2032aabf17ec8ebf7d22c8088c666be5c197"), + AESKey: aesKey13to24, + CipherText: mustHexDecode( + "ec46bb63b02520c33c49fd7031d750a09da3ed7fddd49a2032aabf17ec8ebf7d22c8088c666be5c197", + ), ClearHeaderOctets: 12, Data: mustHexDecode("ec46bb63b02520c33c49fd70b96b49e21d621741632875db7f6c9243d2d7c2"), M: 10, Nonce: mustHexDecode("005b8ccbcd9af83c9696766cfa"), }, { - AESKey: aesKey13to24, - CipherText: mustHexDecode("47a65ac78b3d594227e85e71e882f1dbd38ce3eda7c23f04dd65071eb41342acdf7e00dccec7ae52987d"), + AESKey: aesKey13to24, + CipherText: mustHexDecode( + "47a65ac78b3d594227e85e71e882f1dbd38ce3eda7c23f04dd65071eb41342acdf7e00dccec7ae52987d", + ), ClearHeaderOctets: 12, Data: mustHexDecode("47a65ac78b3d594227e85e71e2fcfbb880442c731bf95167c8ffd7895e337076"), M: 10, Nonce: mustHexDecode("003ebe94044b9a3c9696766cfa"), }, { - AESKey: aesKey13to24, - CipherText: mustHexDecode("6e37a6ef546d955d34ab6059f32905b88a641b04b9c9ffb58cc390900f3da12ab16dce9e82efa16da62059"), + AESKey: aesKey13to24, + CipherText: mustHexDecode( + "6e37a6ef546d955d34ab6059f32905b88a641b04b9c9ffb58cc390900f3da12ab16dce9e82efa16da62059", + ), ClearHeaderOctets: 12, Data: mustHexDecode("6e37a6ef546d955d34ab6059abf21c0b02feb88f856df4a37381bce3cc128517d4"), M: 10, @@ -245,37 +278,47 @@ func TestRFC3610Vectors(t *testing.T) { t.FailNow() //nolint:revive } - for idx, c := range cases { - c := c + for idx, testCase := range cases { + testCase := testCase t.Run(fmt.Sprintf("packet vector #%d", idx+1), func(t *testing.T) { - blk, err := aes.NewCipher(c.AESKey) + blk, err := aes.NewCipher(testCase.AESKey) if err != nil { t.Fatalf("could not initialize AES block cipher from key: %v", err) } - lccm, err := NewCCM(blk, c.M, len(c.Nonce)) + lccm, err := NewCCM(blk, testCase.M, len(testCase.Nonce)) if err != nil { t.Fatalf("could not create CCM: %v", err) } t.Run("seal", func(t *testing.T) { var dst []byte - dst = lccm.Seal(dst, c.Nonce, c.Data[c.ClearHeaderOctets:], c.Data[:c.ClearHeaderOctets]) - if !bytes.Equal(c.CipherText[c.ClearHeaderOctets:], dst) { + dst = lccm.Seal( + dst, + testCase.Nonce, + testCase.Data[testCase.ClearHeaderOctets:], + testCase.Data[:testCase.ClearHeaderOctets], + ) + if !bytes.Equal(testCase.CipherText[testCase.ClearHeaderOctets:], dst) { t.Fatalf("ciphertext does not match, wanted %v, got %v", - c.CipherText[c.ClearHeaderOctets:], dst) + testCase.CipherText[testCase.ClearHeaderOctets:], dst) } }) t.Run("open", func(t *testing.T) { var dst []byte - dst, err = lccm.Open(dst, c.Nonce, c.CipherText[c.ClearHeaderOctets:], c.CipherText[:c.ClearHeaderOctets]) + dst, err = lccm.Open( + dst, + testCase.Nonce, + testCase.CipherText[testCase.ClearHeaderOctets:], + testCase.CipherText[:testCase.ClearHeaderOctets], + ) if err != nil { t.Fatalf("failed to unseal: %v", err) } - if !bytes.Equal(c.Data[c.ClearHeaderOctets:], dst) { + if !bytes.Equal(testCase.Data[testCase.ClearHeaderOctets:], dst) { t.Fatalf("plaintext does not match, wanted %v, got %v", - c.Data[c.ClearHeaderOctets:], dst) + testCase.Data[testCase.ClearHeaderOctets:], dst) } }) }) @@ -363,21 +406,26 @@ func TestSealError(t *testing.T) { t.Fatalf("could not create CCM: %v", err) } - for name, c := range cases { - c := c + for name, testCase := range cases { + testCase := testCase t.Run(name, func(t *testing.T) { defer func() { err, ok := recover().(error) if !ok { - t.Errorf("expected panic '%v', got '%v'", c.err, err) + t.Errorf("expected panic '%v', got '%v'", testCase.err, err) } - if !errors.Is(err, c.err) { - t.Errorf("expected panic '%v', got '%v'", c.err, err) + if !errors.Is(err, testCase.err) { + t.Errorf("expected panic '%v', got '%v'", testCase.err, err) } }() var dst []byte - _ = lccm.Seal(dst, c.Nonce, c.Data[c.ClearHeaderOctets:], c.Data[:c.ClearHeaderOctets]) + _ = lccm.Seal( + dst, + testCase.Nonce, + testCase.Data[testCase.ClearHeaderOctets:], + testCase.Data[:testCase.ClearHeaderOctets], + ) }) } } diff --git a/pkg/crypto/ciphersuite/cbc.go b/pkg/crypto/ciphersuite/cbc.go index 68a080d5d..ab2588f9f 100644 --- a/pkg/crypto/ciphersuite/cbc.go +++ b/pkg/crypto/ciphersuite/cbc.go @@ -24,15 +24,18 @@ type cbcMode interface { SetIV([]byte) } -// CBC Provides an API to Encrypt/Decrypt DTLS 1.2 Packets +// CBC Provides an API to Encrypt/Decrypt DTLS 1.2 Packets. type CBC struct { writeCBC, readCBC cbcMode writeMac, readMac []byte h prf.HashFunc } -// NewCBC creates a DTLS CBC Cipher -func NewCBC(localKey, localWriteIV, localMac, remoteKey, remoteWriteIV, remoteMac []byte, h prf.HashFunc) (*CBC, error) { +// NewCBC creates a DTLS CBC Cipher. +func NewCBC( + localKey, localWriteIV, localMac, remoteKey, remoteWriteIV, remoteMac []byte, + hashFunc prf.HashFunc, +) (*CBC, error) { writeBlock, err := aes.NewCipher(localKey) if err != nil { return nil, err @@ -59,11 +62,11 @@ func NewCBC(localKey, localWriteIV, localMac, remoteKey, remoteWriteIV, remoteMa readCBC: readCBC, readMac: remoteMac, - h: h, + h: hashFunc, }, nil } -// Encrypt encrypt a DTLS RecordLayer message +// Encrypt encrypt a DTLS RecordLayer message. func (c *CBC) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { payload := raw[pkt.Header.Size():] raw = raw[:pkt.Header.Size()] @@ -101,29 +104,29 @@ func (c *CBC) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) // Set IV + Encrypt + Prepend IV c.writeCBC.SetIV(iv) c.writeCBC.CryptBlocks(payload, payload) - payload = append(iv, payload...) + payload = append(iv, payload...) //nolint:makezero // todo: FIX // Prepend unencrypted header with encrypted payload raw = append(raw, payload...) // Update recordLayer size to include IV+MAC+Padding - binary.BigEndian.PutUint16(raw[pkt.Header.Size()-2:], uint16(len(raw)-pkt.Header.Size())) + binary.BigEndian.PutUint16(raw[pkt.Header.Size()-2:], uint16(len(raw)-pkt.Header.Size())) //nolint:gosec //G115 return raw, nil } -// Decrypt decrypts a DTLS RecordLayer message -func (c *CBC) Decrypt(h recordlayer.Header, in []byte) ([]byte, error) { +// Decrypt decrypts a DTLS RecordLayer message. +func (c *CBC) Decrypt(header recordlayer.Header, in []byte) ([]byte, error) { blockSize := c.readCBC.BlockSize() mac := c.h() - if err := h.Unmarshal(in); err != nil { + if err := header.Unmarshal(in); err != nil { return nil, err } - body := in[h.Size():] + body := in[header.Size():] switch { - case h.ContentType == protocol.ContentTypeChangeCipherSpec: + case header.ContentType == protocol.ContentTypeChangeCipherSpec: // Nothing to encrypt with ChangeCipherSpec return in, nil case len(body)%blockSize != 0 || len(body) < blockSize+util.Max(mac.Size()+1, blockSize): @@ -154,21 +157,33 @@ func (c *CBC) Decrypt(h recordlayer.Header, in []byte) ([]byte, error) { expectedMAC := body[dataEnd : dataEnd+macSize] var err error var actualMAC []byte - if h.ContentType == protocol.ContentTypeConnectionID { - actualMAC, err = c.hmacCID(h.Epoch, h.SequenceNumber, h.Version, body[:dataEnd], c.readMac, c.h, h.ConnectionID) + if header.ContentType == protocol.ContentTypeConnectionID { + actualMAC, err = c.hmacCID( + header.Epoch, header.SequenceNumber, header.Version, body[:dataEnd], c.readMac, c.h, header.ConnectionID, + ) } else { - actualMAC, err = c.hmac(h.Epoch, h.SequenceNumber, h.ContentType, h.Version, body[:dataEnd], c.readMac, c.h) + actualMAC, err = c.hmac( + header.Epoch, header.SequenceNumber, header.ContentType, header.Version, body[:dataEnd], c.readMac, c.h, + ) } // Compute Local MAC and compare if err != nil || !hmac.Equal(actualMAC, expectedMAC) { return nil, errInvalidMAC } - return append(in[:h.Size()], body[:dataEnd]...), nil + return append(in[:header.Size()], body[:dataEnd]...), nil } -func (c *CBC) hmac(epoch uint16, sequenceNumber uint64, contentType protocol.ContentType, protocolVersion protocol.Version, payload []byte, key []byte, hf func() hash.Hash) ([]byte, error) { - h := hmac.New(hf, key) +func (c *CBC) hmac( + epoch uint16, + sequenceNumber uint64, + contentType protocol.ContentType, + protocolVersion protocol.Version, + payload []byte, + key []byte, + hf func() hash.Hash, +) ([]byte, error) { + hmacHash := hmac.New(hf, key) msg := make([]byte, 13) @@ -177,51 +192,59 @@ func (c *CBC) hmac(epoch uint16, sequenceNumber uint64, contentType protocol.Con msg[8] = byte(contentType) msg[9] = protocolVersion.Major msg[10] = protocolVersion.Minor - binary.BigEndian.PutUint16(msg[11:], uint16(len(payload))) + binary.BigEndian.PutUint16(msg[11:], uint16(len(payload))) //nolint:gosec //G115 - if _, err := h.Write(msg); err != nil { + if _, err := hmacHash.Write(msg); err != nil { return nil, err } - if _, err := h.Write(payload); err != nil { + if _, err := hmacHash.Write(payload); err != nil { return nil, err } - return h.Sum(nil), nil + return hmacHash.Sum(nil), nil } // hmacCID calculates a MAC according to // https://datatracker.ietf.org/doc/html/rfc9146#section-5.1 -func (c *CBC) hmacCID(epoch uint16, sequenceNumber uint64, protocolVersion protocol.Version, payload []byte, key []byte, hf func() hash.Hash, cid []byte) ([]byte, error) { +func (c *CBC) hmacCID( + epoch uint16, + sequenceNumber uint64, + protocolVersion protocol.Version, + payload []byte, + key []byte, + hf func() hash.Hash, + cid []byte, +) ([]byte, error) { // Must unmarshal inner plaintext in orde to perform MAC. ip := &recordlayer.InnerPlaintext{} if err := ip.Unmarshal(payload); err != nil { return nil, err } - h := hmac.New(hf, key) + hmacHash := hmac.New(hf, key) var msg cryptobyte.Builder msg.AddUint64(seqNumPlaceholder) msg.AddUint8(uint8(protocol.ContentTypeConnectionID)) - msg.AddUint8(uint8(len(cid))) + msg.AddUint8(uint8(len(cid))) //nolint:gosec //G115 msg.AddUint8(uint8(protocol.ContentTypeConnectionID)) msg.AddUint8(protocolVersion.Major) msg.AddUint8(protocolVersion.Minor) msg.AddUint16(epoch) util.AddUint48(&msg, sequenceNumber) msg.AddBytes(cid) - msg.AddUint16(uint16(len(payload))) + msg.AddUint16(uint16(len(payload))) //nolint:gosec //G115 msg.AddBytes(ip.Content) msg.AddUint8(uint8(ip.RealType)) msg.AddBytes(make([]byte, ip.Zeros)) - if _, err := h.Write(msg.BytesOrPanic()); err != nil { + if _, err := hmacHash.Write(msg.BytesOrPanic()); err != nil { return nil, err } - if _, err := h.Write(payload); err != nil { + if _, err := hmacHash.Write(payload); err != nil { return nil, err } - return h.Sum(nil), nil + return hmacHash.Sum(nil), nil } diff --git a/pkg/crypto/ciphersuite/ccm.go b/pkg/crypto/ciphersuite/ccm.go index 4c296e2bb..9a40cae8f 100644 --- a/pkg/crypto/ciphersuite/ccm.go +++ b/pkg/crypto/ciphersuite/ccm.go @@ -14,24 +14,24 @@ import ( "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// CCMTagLen is the length of Authentication Tag +// CCMTagLen is the length of Authentication Tag. type CCMTagLen int -// CCM Enums +// CCM Enums. const ( CCMTagLength8 CCMTagLen = 8 CCMTagLength CCMTagLen = 16 ccmNonceLength = 12 ) -// CCM Provides an API to Encrypt/Decrypt DTLS 1.2 Packets +// CCM Provides an API to Encrypt/Decrypt DTLS 1.2 Packets. type CCM struct { localCCM, remoteCCM ccm.CCM localWriteIV, remoteWriteIV []byte tagLen CCMTagLen } -// NewCCM creates a DTLS GCM Cipher +// NewCCM creates a DTLS GCM Cipher. func NewCCM(tagLen CCMTagLen, localKey, localWriteIV, remoteKey, remoteWriteIV []byte) (*CCM, error) { localBlock, err := aes.NewCipher(localKey) if err != nil { @@ -60,7 +60,7 @@ func NewCCM(tagLen CCMTagLen, localKey, localWriteIV, remoteKey, remoteWriteIV [ }, nil } -// Encrypt encrypt a DTLS RecordLayer message +// Encrypt encrypt a DTLS RecordLayer message. func (c *CCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { payload := raw[pkt.Header.Size():] raw = raw[:pkt.Header.Size()] @@ -82,36 +82,38 @@ func (c *CCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) raw = append(raw, encryptedPayload...) // Update recordLayer size to include explicit nonce - binary.BigEndian.PutUint16(raw[pkt.Header.Size()-2:], uint16(len(raw)-pkt.Header.Size())) + binary.BigEndian.PutUint16(raw[pkt.Header.Size()-2:], uint16(len(raw)-pkt.Header.Size())) //nolint:gosec //G115 + return raw, nil } -// Decrypt decrypts a DTLS RecordLayer message -func (c *CCM) Decrypt(h recordlayer.Header, in []byte) ([]byte, error) { - if err := h.Unmarshal(in); err != nil { +// Decrypt decrypts a DTLS RecordLayer message. +func (c *CCM) Decrypt(header recordlayer.Header, in []byte) ([]byte, error) { + if err := header.Unmarshal(in); err != nil { return nil, err } switch { - case h.ContentType == protocol.ContentTypeChangeCipherSpec: + case header.ContentType == protocol.ContentTypeChangeCipherSpec: // Nothing to encrypt with ChangeCipherSpec return in, nil - case len(in) <= (8 + h.Size()): + case len(in) <= (8 + header.Size()): return nil, errNotEnoughRoomForNonce } - nonce := append(append([]byte{}, c.remoteWriteIV[:4]...), in[h.Size():h.Size()+8]...) - out := in[h.Size()+8:] + nonce := append(append([]byte{}, c.remoteWriteIV[:4]...), in[header.Size():header.Size()+8]...) + out := in[header.Size()+8:] var additionalData []byte - if h.ContentType == protocol.ContentTypeConnectionID { - additionalData = generateAEADAdditionalDataCID(&h, len(out)-int(c.tagLen)) + if header.ContentType == protocol.ContentTypeConnectionID { + additionalData = generateAEADAdditionalDataCID(&header, len(out)-int(c.tagLen)) } else { - additionalData = generateAEADAdditionalData(&h, len(out)-int(c.tagLen)) + additionalData = generateAEADAdditionalData(&header, len(out)-int(c.tagLen)) } var err error out, err = c.remoteCCM.Open(out[:0], nonce, out, additionalData) if err != nil { return nil, fmt.Errorf("%w: %v", errDecryptPacket, err) //nolint:errorlint } - return append(in[:h.Size()], out...), nil + + return append(in[:header.Size()], out...), nil } diff --git a/pkg/crypto/ciphersuite/ciphersuite.go b/pkg/crypto/ciphersuite/ciphersuite.go index 90ddf6105..5c01de580 100644 --- a/pkg/crypto/ciphersuite/ciphersuite.go +++ b/pkg/crypto/ciphersuite/ciphersuite.go @@ -21,10 +21,14 @@ const ( ) var ( - errNotEnoughRoomForNonce = &protocol.InternalError{Err: errors.New("buffer not long enough to contain nonce")} //nolint:goerr113 - errDecryptPacket = &protocol.TemporaryError{Err: errors.New("failed to decrypt packet")} //nolint:goerr113 - errInvalidMAC = &protocol.TemporaryError{Err: errors.New("invalid mac")} //nolint:goerr113 - errFailedToCast = &protocol.FatalError{Err: errors.New("failed to cast")} //nolint:goerr113 + //nolint:goerr113 + errNotEnoughRoomForNonce = &protocol.InternalError{Err: errors.New("buffer not long enough to contain nonce")} + //nolint:goerr113 + errDecryptPacket = &protocol.TemporaryError{Err: errors.New("failed to decrypt packet")} + //nolint:goerr113 + errInvalidMAC = &protocol.TemporaryError{Err: errors.New("invalid mac")} + //nolint:goerr113 + errFailedToCast = &protocol.FatalError{Err: errors.New("failed to cast")} ) func generateAEADAdditionalData(h *recordlayer.Header, payloadLen int) []byte { @@ -37,6 +41,7 @@ func generateAEADAdditionalData(h *recordlayer.Header, payloadLen int) []byte { additionalData[8] = byte(h.ContentType) additionalData[9] = h.Version.Major additionalData[10] = h.Version.Minor + //nolint:gosec //G115 binary.BigEndian.PutUint16(additionalData[len(additionalData)-2:], uint16(payloadLen)) return additionalData[:] @@ -45,20 +50,20 @@ func generateAEADAdditionalData(h *recordlayer.Header, payloadLen int) []byte { // generateAEADAdditionalDataCID generates additional data for AEAD ciphers // according to https://datatracker.ietf.org/doc/html/rfc9146#name-aead-ciphers func generateAEADAdditionalDataCID(h *recordlayer.Header, payloadLen int) []byte { - var b cryptobyte.Builder - - b.AddUint64(seqNumPlaceholder) - b.AddUint8(uint8(protocol.ContentTypeConnectionID)) - b.AddUint8(uint8(len(h.ConnectionID))) - b.AddUint8(uint8(protocol.ContentTypeConnectionID)) - b.AddUint8(h.Version.Major) - b.AddUint8(h.Version.Minor) - b.AddUint16(h.Epoch) - util.AddUint48(&b, h.SequenceNumber) - b.AddBytes(h.ConnectionID) - b.AddUint16(uint16(payloadLen)) - - return b.BytesOrPanic() + var builder cryptobyte.Builder + + builder.AddUint64(seqNumPlaceholder) + builder.AddUint8(uint8(protocol.ContentTypeConnectionID)) + builder.AddUint8(uint8(len(h.ConnectionID))) //nolint:gosec //G115 + builder.AddUint8(uint8(protocol.ContentTypeConnectionID)) + builder.AddUint8(h.Version.Major) + builder.AddUint8(h.Version.Minor) + builder.AddUint16(h.Epoch) + util.AddUint48(&builder, h.SequenceNumber) + builder.AddBytes(h.ConnectionID) + builder.AddUint16(uint16(payloadLen)) //nolint:gosec //G115 + + return builder.BytesOrPanic() } // examinePadding returns, in constant time, the length of the padding to remove @@ -72,9 +77,9 @@ func examinePadding(payload []byte) (toRemove int, good byte) { } paddingLen := payload[len(payload)-1] - t := uint(len(payload)-1) - uint(paddingLen) + t := uint(len(payload)-1) - uint(paddingLen) //nolint:gosec //G115 // if len(payload) >= (paddingLen - 1) then the MSB of t is zero - good = byte(int32(^t) >> 31) + good = byte(int32(^t) >> 31) //nolint:gosec //G115 // The maximum possible padding length plus the actual length field toCheck := 256 @@ -84,9 +89,9 @@ func examinePadding(payload []byte) (toRemove int, good byte) { } for i := 0; i < toCheck; i++ { - t := uint(paddingLen) - uint(i) + t := uint(paddingLen) - uint(i) //nolint:gosec //G115 // if i <= paddingLen then the MSB of t is zero - mask := byte(int32(^t) >> 31) + mask := byte(int32(^t) >> 31) //nolint:gosec //G115 b := payload[len(payload)-1-i] good &^= mask&paddingLen ^ mask&b } @@ -96,7 +101,7 @@ func examinePadding(payload []byte) (toRemove int, good byte) { good &= good << 4 good &= good << 2 good &= good << 1 - good = uint8(int8(good) >> 7) + good = uint8(int8(good) >> 7) //nolint:gosec //G115 toRemove = int(paddingLen) + 1 diff --git a/pkg/crypto/ciphersuite/ciphersuite_test.go b/pkg/crypto/ciphersuite/ciphersuite_test.go index 100d718d9..3767d9661 100644 --- a/pkg/crypto/ciphersuite/ciphersuite_test.go +++ b/pkg/crypto/ciphersuite/ciphersuite_test.go @@ -29,7 +29,10 @@ func TestGenerateAEADAdditionalDataCID(t *testing.T) { SequenceNumber: 277, }, payloadLen: 1784, - expected: []byte{255, 255, 255, 255, 255, 255, 255, 255, 25, 8, 25, 254, 253, 0, 2, 0, 0, 0, 0, 1, 21, 1, 2, 3, 4, 5, 6, 7, 8, 6, 248}, + expected: []byte{ + 255, 255, 255, 255, 255, 255, 255, 255, 25, 8, 25, 254, 253, + 0, 2, 0, 0, 0, 0, 1, 21, 1, 2, 3, 4, 5, 6, 7, 8, 6, 248, + }, }, "IgnoreContentType": { reason: "Should use Connection ID content type regardless of header content type.", @@ -41,7 +44,10 @@ func TestGenerateAEADAdditionalDataCID(t *testing.T) { SequenceNumber: 277, }, payloadLen: 1784, - expected: []byte{255, 255, 255, 255, 255, 255, 255, 255, 25, 8, 25, 254, 253, 0, 2, 0, 0, 0, 0, 1, 21, 1, 2, 3, 4, 5, 6, 7, 8, 6, 248}, + expected: []byte{ + 255, 255, 255, 255, 255, 255, 255, 255, 25, 8, 25, 254, 253, + 0, 2, 0, 0, 0, 0, 1, 21, 1, 2, 3, 4, 5, 6, 7, 8, 6, 248, + }, }, } for name, tc := range cases { diff --git a/pkg/crypto/ciphersuite/gcm.go b/pkg/crypto/ciphersuite/gcm.go index a7f828246..1c50dd967 100644 --- a/pkg/crypto/ciphersuite/gcm.go +++ b/pkg/crypto/ciphersuite/gcm.go @@ -19,13 +19,13 @@ const ( gcmNonceLength = 12 ) -// GCM Provides an API to Encrypt/Decrypt DTLS 1.2 Packets +// GCM Provides an API to Encrypt/Decrypt DTLS 1.2 Packets. type GCM struct { localGCM, remoteGCM cipher.AEAD localWriteIV, remoteWriteIV []byte } -// NewGCM creates a DTLS GCM Cipher +// NewGCM creates a DTLS GCM Cipher. func NewGCM(localKey, localWriteIV, remoteKey, remoteWriteIV []byte) (*GCM, error) { localBlock, err := aes.NewCipher(localKey) if err != nil { @@ -53,7 +53,7 @@ func NewGCM(localKey, localWriteIV, remoteKey, remoteWriteIV []byte) (*GCM, erro }, nil } -// Encrypt encrypt a DTLS RecordLayer message +// Encrypt encrypt a DTLS RecordLayer message. func (g *GCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { payload := raw[pkt.Header.Size():] raw = raw[:pkt.Header.Size()] @@ -77,36 +77,38 @@ func (g *GCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) copy(r[len(raw)+len(nonce[4:]):], encryptedPayload) // Update recordLayer size to include explicit nonce - binary.BigEndian.PutUint16(r[pkt.Header.Size()-2:], uint16(len(r)-pkt.Header.Size())) + binary.BigEndian.PutUint16(r[pkt.Header.Size()-2:], uint16(len(r)-pkt.Header.Size())) //nolint:gosec //G115 + return r, nil } -// Decrypt decrypts a DTLS RecordLayer message -func (g *GCM) Decrypt(h recordlayer.Header, in []byte) ([]byte, error) { - err := h.Unmarshal(in) +// Decrypt decrypts a DTLS RecordLayer message. +func (g *GCM) Decrypt(header recordlayer.Header, in []byte) ([]byte, error) { + err := header.Unmarshal(in) switch { case err != nil: return nil, err - case h.ContentType == protocol.ContentTypeChangeCipherSpec: + case header.ContentType == protocol.ContentTypeChangeCipherSpec: // Nothing to encrypt with ChangeCipherSpec return in, nil - case len(in) <= (8 + h.Size()): + case len(in) <= (8 + header.Size()): return nil, errNotEnoughRoomForNonce } nonce := make([]byte, 0, gcmNonceLength) - nonce = append(append(nonce, g.remoteWriteIV[:4]...), in[h.Size():h.Size()+8]...) - out := in[h.Size()+8:] + nonce = append(append(nonce, g.remoteWriteIV[:4]...), in[header.Size():header.Size()+8]...) + out := in[header.Size()+8:] var additionalData []byte - if h.ContentType == protocol.ContentTypeConnectionID { - additionalData = generateAEADAdditionalDataCID(&h, len(out)-gcmTagLength) + if header.ContentType == protocol.ContentTypeConnectionID { + additionalData = generateAEADAdditionalDataCID(&header, len(out)-gcmTagLength) } else { - additionalData = generateAEADAdditionalData(&h, len(out)-gcmTagLength) + additionalData = generateAEADAdditionalData(&header, len(out)-gcmTagLength) } out, err = g.remoteGCM.Open(out[:0], nonce, out, additionalData) if err != nil { return nil, fmt.Errorf("%w: %v", errDecryptPacket, err) //nolint:errorlint } - return append(in[:h.Size()], out...), nil + + return append(in[:header.Size()], out...), nil } diff --git a/pkg/crypto/clientcertificate/client_certificate.go b/pkg/crypto/clientcertificate/client_certificate.go index ddfa39ebe..0a510d4d4 100644 --- a/pkg/crypto/clientcertificate/client_certificate.go +++ b/pkg/crypto/clientcertificate/client_certificate.go @@ -10,13 +10,13 @@ package clientcertificate // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-2 type Type byte -// ClientCertificateType enums +// ClientCertificateType enums. const ( RSASign Type = 1 ECDSASign Type = 64 ) -// Types returns all valid ClientCertificate Types +// Types returns all valid ClientCertificate Types. func Types() map[Type]bool { return map[Type]bool{ RSASign: true, diff --git a/pkg/crypto/elliptic/elliptic.go b/pkg/crypto/elliptic/elliptic.go index 126523872..b98fb4f9c 100644 --- a/pkg/crypto/elliptic/elliptic.go +++ b/pkg/crypto/elliptic/elliptic.go @@ -20,12 +20,12 @@ var errInvalidNamedCurve = errors.New("invalid named curve") // https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 type CurvePointFormat byte -// CurvePointFormat enums +// CurvePointFormat enums. const ( CurvePointFormatUncompressed CurvePointFormat = 0 ) -// Keypair is a Curve with a Private/Public Keypair +// Keypair is a Curve with a Private/Public Keypair. type Keypair struct { Curve Curve PublicKey []byte @@ -37,12 +37,12 @@ type Keypair struct { // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-10 type CurveType byte -// CurveType enums +// CurveType enums. const ( CurveTypeNamedCurve CurveType = 0x03 ) -// CurveTypes returns all known curves +// CurveTypes returns all known curves. func CurveTypes() map[CurveType]struct{} { return map[CurveType]struct{}{ CurveTypeNamedCurve: {}, @@ -54,7 +54,7 @@ func CurveTypes() map[CurveType]struct{} { // https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 type Curve uint16 -// Curve enums +// Curve enums. const ( P256 Curve = 0x0017 P384 Curve = 0x0018 @@ -70,10 +70,11 @@ func (c Curve) String() string { case X25519: return "X25519" } + return fmt.Sprintf("%#x", uint16(c)) } -// Curves returns all curves we implement +// Curves returns all curves we implement. func Curves() map[Curve]bool { return map[Curve]bool{ X25519: true, @@ -82,7 +83,7 @@ func Curves() map[Curve]bool { } } -// GenerateKeypair generates a keypair for the given Curve +// GenerateKeypair generates a keypair for the given Curve. func GenerateKeypair(c Curve) (*Keypair, error) { switch c { //nolint:revive case X25519: @@ -95,6 +96,7 @@ func GenerateKeypair(c Curve) (*Keypair, error) { copy(private[:], tmp) curve25519.ScalarBaseMult(&public, &private) + return &Keypair{X25519, public[:], private[:]}, nil case P256: return ellipticCurveKeypair(P256, elliptic.P256(), elliptic.P256()) diff --git a/pkg/crypto/fingerprint/fingerprint.go b/pkg/crypto/fingerprint/fingerprint.go index 7c66265c7..43d4a4000 100644 --- a/pkg/crypto/fingerprint/fingerprint.go +++ b/pkg/crypto/fingerprint/fingerprint.go @@ -16,7 +16,7 @@ var ( errInvalidFingerprintLength = errors.New("fingerprint: invalid fingerprint length") ) -// Fingerprint creates a fingerprint for a certificate using the specified hash algorithm +// Fingerprint creates a fingerprint for a certificate using the specified hash algorithm. func Fingerprint(cert *x509.Certificate, algo crypto.Hash) (string, error) { if !algo.Available() { return "", errHashUnavailable diff --git a/pkg/crypto/fingerprint/fingerprint_test.go b/pkg/crypto/fingerprint/fingerprint_test.go index 3266d1153..0a22d8b6c 100644 --- a/pkg/crypto/fingerprint/fingerprint_test.go +++ b/pkg/crypto/fingerprint/fingerprint_test.go @@ -12,23 +12,29 @@ import ( func TestFingerprint(t *testing.T) { rawCertificate := []byte{ - 0x30, 0x82, 0x01, 0x98, 0x30, 0x82, 0x01, 0x3d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, 0xa9, 0x91, 0x76, 0x0a, 0xcd, 0x97, 0x4c, 0x36, 0xba, - 0xc9, 0xc2, 0x66, 0x91, 0x47, 0x6c, 0xac, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x27, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x31, 0x31, 0x30, 0x30, - 0x39, 0x30, 0x34, 0x32, 0x33, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x32, 0x31, 0x30, 0x30, 0x39, 0x30, 0x34, 0x32, 0x33, 0x5a, 0x30, 0x2b, 0x31, 0x29, - 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, - 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x9c, 0x12, 0x8e, 0xb5, 0x21, 0x23, 0x9f, - 0x35, 0x5d, 0x39, 0x64, 0xc3, 0x75, 0x81, 0xa4, 0xc8, 0xc8, 0x08, 0x8a, 0xa8, 0x42, 0x30, 0x30, 0x65, 0xb8, 0xb1, 0x3e, 0x4a, 0x51, 0x86, 0xeb, 0xad, - 0x03, 0x02, 0x35, 0x83, 0xc4, 0x19, 0x3a, 0x5b, 0x79, 0x83, 0xec, 0x59, 0x0e, 0x4f, 0x99, 0xb1, 0xd2, 0xf0, 0x50, 0xfa, 0xb8, 0x5f, 0xfc, 0x88, 0xf3, - 0x15, 0xed, 0xb8, 0x14, 0xf0, 0xba, 0xcd, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, - 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, - 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xcd, 0x44, 0xb1, 0xf2, 0x09, - 0xe5, 0xf1, 0xf4, 0xc9, 0x26, 0x95, 0x9a, 0x2d, 0x6d, 0xf3, 0x0c, 0xb8, 0xeb, 0x27, 0x2d, 0x81, 0x19, 0xe9, 0x51, 0xf7, 0xad, 0x64, 0x7d, 0x42, 0x32, - 0x9e, 0xf8, 0x02, 0x21, 0x00, 0xee, 0xad, 0x96, 0x41, 0xf1, 0x12, 0xd0, 0x6b, 0xcd, 0x09, 0xf0, 0x3c, 0x67, 0xb3, 0xdd, 0xed, 0x0a, 0xf1, 0xd8, 0x41, - 0x4f, 0x61, 0xfd, 0x53, 0x1d, 0xf5, 0x27, 0xbe, 0x6d, 0x0b, 0xe2, 0x0d, + 0x30, 0x82, 0x01, 0x98, 0x30, 0x82, 0x01, 0x3d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, 0xa9, 0x91, + 0x76, 0x0a, 0xcd, 0x97, 0x4c, 0x36, 0xba, 0xc9, 0xc2, 0x66, 0x91, 0x47, 0x6c, 0xac, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x31, 0x31, 0x30, 0x30, 0x39, 0x30, 0x34, 0x32, 0x33, 0x5a, 0x17, 0x0d, + 0x31, 0x39, 0x31, 0x32, 0x31, 0x30, 0x30, 0x39, 0x30, 0x34, 0x32, 0x33, 0x5a, 0x30, 0x2b, 0x31, 0x29, 0x30, + 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x9c, 0x12, 0x8e, 0xb5, 0x21, + 0x23, 0x9f, 0x35, 0x5d, 0x39, 0x64, 0xc3, 0x75, 0x81, 0xa4, 0xc8, 0xc8, 0x08, 0x8a, 0xa8, 0x42, 0x30, 0x30, + 0x65, 0xb8, 0xb1, 0x3e, 0x4a, 0x51, 0x86, 0xeb, 0xad, 0x03, 0x02, 0x35, 0x83, 0xc4, 0x19, 0x3a, 0x5b, 0x79, + 0x83, 0xec, 0x59, 0x0e, 0x4f, 0x99, 0xb1, 0xd2, 0xf0, 0x50, 0xfa, 0xb8, 0x5f, 0xfc, 0x88, 0xf3, 0x15, 0xed, + 0xb8, 0x14, 0xf0, 0xba, 0xcd, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, + 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x03, 0x01, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, + 0x02, 0x21, 0x00, 0xcd, 0x44, 0xb1, 0xf2, 0x09, 0xe5, 0xf1, 0xf4, 0xc9, 0x26, 0x95, 0x9a, 0x2d, 0x6d, 0xf3, + 0x0c, 0xb8, 0xeb, 0x27, 0x2d, 0x81, 0x19, 0xe9, 0x51, 0xf7, 0xad, 0x64, 0x7d, 0x42, 0x32, 0x9e, 0xf8, 0x02, + 0x21, 0x00, 0xee, 0xad, 0x96, 0x41, 0xf1, 0x12, 0xd0, 0x6b, 0xcd, 0x09, 0xf0, 0x3c, 0x67, 0xb3, 0xdd, 0xed, + 0x0a, 0xf1, 0xd8, 0x41, 0x4f, 0x61, 0xfd, 0x53, 0x1d, 0xf5, 0x27, 0xbe, 0x6d, 0x0b, 0xe2, 0x0d, } cert, err := x509.ParseCertificate(rawCertificate) @@ -36,6 +42,7 @@ func TestFingerprint(t *testing.T) { t.Fatal(err) } + //nolint:lll const expectedSHA256 = "60:ef:f5:79:ad:8d:3e:d7:e8:4d:5a:5a:d6:1e:71:2d:47:52:a5:cb:df:34:37:87:10:a5:4e:d7:2a:2c:37:34" actualSHA256, err := Fingerprint(cert, crypto.SHA256) if err != nil { diff --git a/pkg/crypto/fingerprint/hash.go b/pkg/crypto/fingerprint/hash.go index 3f988ffb7..8aacd673d 100644 --- a/pkg/crypto/fingerprint/hash.go +++ b/pkg/crypto/fingerprint/hash.go @@ -22,11 +22,12 @@ func nameToHash() map[string]crypto.Hash { } } -// HashFromString allows looking up a hash algorithm by it's string representation +// HashFromString allows looking up a hash algorithm by it's string representation. func HashFromString(s string) (crypto.Hash, error) { if h, ok := nameToHash()[strings.ToLower(s)]; ok { return h, nil } + return 0, errInvalidHashAlgorithm } @@ -37,5 +38,6 @@ func StringFromHash(hash crypto.Hash) (string, error) { return s, nil } } + return "", errInvalidHashAlgorithm } diff --git a/pkg/crypto/fingerprint/hash_test.go b/pkg/crypto/fingerprint/hash_test.go index b71a7a363..51a29bfce 100644 --- a/pkg/crypto/fingerprint/hash_test.go +++ b/pkg/crypto/fingerprint/hash_test.go @@ -22,7 +22,7 @@ func TestHashFromString(t *testing.T) { t.Fatalf("Unexpected error for valid hash name, got '%v'", err) } if h != crypto.SHA512 { - t.Errorf("Expected hash ID of %d, got %d", int(crypto.SHA512), int(h)) + t.Errorf("Expected hash ID of %d, got %d", int(crypto.SHA512), int(h)) //nolint:gosec //G115 } }) t.Run("ValidCaseInsensitiveHashAlgorithm", func(t *testing.T) { @@ -31,6 +31,7 @@ func TestHashFromString(t *testing.T) { t.Fatalf("Unexpected error for valid hash name, got '%v'", err) } if h != crypto.SHA512 { + //nolint:gosec // G115 t.Errorf("Expected hash ID of %d, got %d", int(crypto.SHA512), int(h)) } }) diff --git a/pkg/crypto/hash/hash.go b/pkg/crypto/hash/hash.go index 9966626e3..a390170fe 100644 --- a/pkg/crypto/hash/hash.go +++ b/pkg/crypto/hash/hash.go @@ -16,7 +16,7 @@ import ( //nolint:gci // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18 type Algorithm uint16 -// Supported hash algorithms +// Supported hash algorithms. const ( None Algorithm = 0 // Blacklisted MD5 Algorithm = 1 // Blacklisted @@ -28,7 +28,7 @@ const ( Ed25519 Algorithm = 8 ) -// String makes hashAlgorithm printable +// String makes hashAlgorithm printable. func (a Algorithm) String() string { switch a { case None: @@ -52,28 +52,34 @@ func (a Algorithm) String() string { } } -// Digest performs a digest on the passed value +// Digest performs a digest on the passed value. func (a Algorithm) Digest(b []byte) []byte { switch a { case None: return nil case MD5: hash := md5.Sum(b) // #nosec + return hash[:] case SHA1: hash := sha1.Sum(b) // #nosec + return hash[:] case SHA224: hash := sha256.Sum224(b) + return hash[:] case SHA256: hash := sha256.Sum256(b) + return hash[:] case SHA384: hash := sha512.Sum384(b) + return hash[:] case SHA512: hash := sha512.Sum512(b) + return hash[:] default: return nil @@ -81,6 +87,7 @@ func (a Algorithm) Digest(b []byte) []byte { } // Insecure returns if the given HashAlgorithm is considered secure in DTLS 1.2 +// . func (a Algorithm) Insecure() bool { switch a { case None, MD5, SHA1: @@ -90,7 +97,7 @@ func (a Algorithm) Insecure() bool { } } -// CryptoHash returns the crypto.Hash implementation for the given HashAlgorithm +// CryptoHash returns the crypto.Hash implementation for the given HashAlgorithm. func (a Algorithm) CryptoHash() crypto.Hash { switch a { case None: @@ -114,7 +121,7 @@ func (a Algorithm) CryptoHash() crypto.Hash { } } -// Algorithms returns all the supported Hash Algorithms +// Algorithms returns all the supported Hash Algorithms. func Algorithms() map[Algorithm]struct{} { return map[Algorithm]struct{}{ None: {}, diff --git a/pkg/crypto/hash/hash_test.go b/pkg/crypto/hash/hash_test.go index d6660254b..c6ba906ae 100644 --- a/pkg/crypto/hash/hash_test.go +++ b/pkg/crypto/hash/hash_test.go @@ -22,7 +22,10 @@ func TestHashAlgorithm_StringRoundtrip(t *testing.T) { t.Fatalf("fingerprint.HashFromString failed: %v", err) } if hash1 != hash2 { - t.Errorf("Hash algorithm mismatch, input: %d, after roundtrip: %d", int(hash1), int(hash2)) + t.Errorf( + "Hash algorithm mismatch, input: %d, after roundtrip: %d", + int(hash1), int(hash2), //nolint:gosec // G115 + ) } } } diff --git a/pkg/crypto/prf/prf.go b/pkg/crypto/prf/prf.go index b5ac19f79..9eace83b7 100644 --- a/pkg/crypto/prf/prf.go +++ b/pkg/crypto/prf/prf.go @@ -26,10 +26,10 @@ const ( verifyDataServerLabel = "server finished" ) -// HashFunc allows callers to decide what hash is used in PRF +// HashFunc allows callers to decide what hash is used in PRF. type HashFunc func() hash.Hash -// EncryptionKeys is all the state needed for a TLS CipherSuite +// EncryptionKeys is all the state needed for a TLS CipherSuite. type EncryptionKeys struct { MasterSecret []byte ClientMACKey []byte @@ -68,7 +68,7 @@ func (e *EncryptionKeys) String() string { // // https://tools.ietf.org/html/rfc4279#section-2 func PSKPreMasterSecret(psk []byte) []byte { - pskLen := uint16(len(psk)) + pskLen := uint16(len(psk)) //nolint:gosec // G115 out := append(make([]byte, 2+pskLen+2), psk...) binary.BigEndian.PutUint16(out, pskLen) @@ -89,7 +89,7 @@ func EcdhePSKPreMasterSecret(psk, publicKey, privateKey []byte, curve elliptic.C // write preMasterSecret length offset := 0 - binary.BigEndian.PutUint16(out[offset:], uint16(len(preMasterSecret))) + binary.BigEndian.PutUint16(out[offset:], uint16(len(preMasterSecret))) //nolint:gosec // G115 offset += 2 // write preMasterSecret @@ -97,15 +97,16 @@ func EcdhePSKPreMasterSecret(psk, publicKey, privateKey []byte, curve elliptic.C offset += len(preMasterSecret) // write psk length - binary.BigEndian.PutUint16(out[offset:], uint16(len(psk))) + binary.BigEndian.PutUint16(out[offset:], uint16(len(psk))) //nolint:gosec // G115 offset += 2 // write psk copy(out[offset:], psk) + return out, nil } -// PreMasterSecret implements TLS 1.2 Premaster Secret generation given a keypair and a curve +// PreMasterSecret implements TLS 1.2 Premaster Secret generation given a keypair and a curve. func PreMasterSecret(publicKey, privateKey []byte, curve elliptic.Curve) ([]byte, error) { switch curve { case elliptic.X25519: @@ -129,6 +130,7 @@ func ellipticCurvePreMasterSecret(publicKey, privateKey []byte, c1, c2 ellipticS preMasterSecret := make([]byte, (c2.Params().BitSize+7)>>3) resultBytes := result.Bytes() copy(preMasterSecret[len(preMasterSecret)-len(resultBytes):], resultBytes) + return preMasterSecret, nil } @@ -155,12 +157,13 @@ func ellipticCurvePreMasterSecret(publicKey, privateKey []byte, c1, c2 ellipticS // output data. // // https://tools.ietf.org/html/rfc4346w -func PHash(secret, seed []byte, requestedLength int, h HashFunc) ([]byte, error) { +func PHash(secret, seed []byte, requestedLength int, hashFunc HashFunc) ([]byte, error) { hmacSHA256 := func(key, data []byte) ([]byte, error) { - mac := hmac.New(h, key) + mac := hmac.New(hashFunc, key) if _, err := mac.Write(data); err != nil { return nil, err } + return mac.Sum(nil), nil } @@ -168,7 +171,7 @@ func PHash(secret, seed []byte, requestedLength int, h HashFunc) ([]byte, error) lastRound := seed out := []byte{} - iterations := int(math.Ceil(float64(requestedLength) / float64(h().Size()))) + iterations := int(math.Ceil(float64(requestedLength) / float64(hashFunc().Size()))) for i := 0; i < iterations; i++ { lastRound, err = hmacSHA256(secret, lastRound) if err != nil { @@ -188,18 +191,24 @@ func PHash(secret, seed []byte, requestedLength int, h HashFunc) ([]byte, error) // https://tools.ietf.org/html/rfc7627 func ExtendedMasterSecret(preMasterSecret, sessionHash []byte, h HashFunc) ([]byte, error) { seed := append([]byte(extendedMasterSecretLabel), sessionHash...) + return PHash(preMasterSecret, seed, 48, h) } -// MasterSecret generates a TLS 1.2 MasterSecret +// MasterSecret generates a TLS 1.2 MasterSecret. func MasterSecret(preMasterSecret, clientRandom, serverRandom []byte, h HashFunc) ([]byte, error) { seed := append(append([]byte(masterSecretLabel), clientRandom...), serverRandom...) + return PHash(preMasterSecret, seed, 48, h) } // GenerateEncryptionKeys is the final step TLS 1.2 PRF. Given all state generated so far generates -// the final keys need for encryption -func GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int, h HashFunc) (*EncryptionKeys, error) { +// the final keys need for encryption. +func GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom []byte, + macLen, keyLen, ivLen int, + h HashFunc, +) (*EncryptionKeys, error) { seed := append(append([]byte(keyExpansionLabel), serverRandom...), clientRandom...) keyMaterial, err := PHash(masterSecret, seed, (2*macLen)+(2*keyLen)+(2*ivLen), h) if err != nil { @@ -241,15 +250,16 @@ func prfVerifyData(masterSecret, handshakeBodies []byte, label string, hashFunc } seed := append([]byte(label), h.Sum(nil)...) + return PHash(masterSecret, seed, 12, hashFunc) } -// VerifyDataClient is caled on the Client Side to either verify or generate the VerifyData message +// VerifyDataClient is caled on the Client Side to either verify or generate the VerifyData message. func VerifyDataClient(masterSecret, handshakeBodies []byte, h HashFunc) ([]byte, error) { return prfVerifyData(masterSecret, handshakeBodies, verifyDataClientLabel, h) } -// VerifyDataServer is caled on the Server Side to either verify or generate the VerifyData message +// VerifyDataServer is caled on the Server Side to either verify or generate the VerifyData message. func VerifyDataServer(masterSecret, handshakeBodies []byte, h HashFunc) ([]byte, error) { return prfVerifyData(masterSecret, handshakeBodies, verifyDataServerLabel, h) } diff --git a/pkg/crypto/prf/prf_test.go b/pkg/crypto/prf/prf_test.go index fa9b32510..9d2f90451 100644 --- a/pkg/crypto/prf/prf_test.go +++ b/pkg/crypto/prf/prf_test.go @@ -13,9 +13,18 @@ import ( ) func TestPreMasterSecret(t *testing.T) { - privateKey := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f} - publicKey := []byte{0x9f, 0xd7, 0xad, 0x6d, 0xcf, 0xf4, 0x29, 0x8d, 0xd3, 0xf9, 0x6d, 0x5b, 0x1b, 0x2a, 0xf9, 0x10, 0xa0, 0x53, 0x5b, 0x14, 0x88, 0xd7, 0xf8, 0xfa, 0xbb, 0x34, 0x9a, 0x98, 0x28, 0x80, 0xb6, 0x15} - expectedPreMasterSecret := []byte{0xdf, 0x4a, 0x29, 0x1b, 0xaa, 0x1e, 0xb7, 0xcf, 0xa6, 0x93, 0x4b, 0x29, 0xb4, 0x74, 0xba, 0xad, 0x26, 0x97, 0xe2, 0x9f, 0x1f, 0x92, 0x0d, 0xcc, 0x77, 0xc8, 0xa0, 0xa0, 0x88, 0x44, 0x76, 0x24} + privateKey := []byte{ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + } + publicKey := []byte{ + 0x9f, 0xd7, 0xad, 0x6d, 0xcf, 0xf4, 0x29, 0x8d, 0xd3, 0xf9, 0x6d, 0x5b, 0x1b, 0x2a, 0xf9, 0x10, + 0xa0, 0x53, 0x5b, 0x14, 0x88, 0xd7, 0xf8, 0xfa, 0xbb, 0x34, 0x9a, 0x98, 0x28, 0x80, 0xb6, 0x15, + } + expectedPreMasterSecret := []byte{ + 0xdf, 0x4a, 0x29, 0x1b, 0xaa, 0x1e, 0xb7, 0xcf, 0xa6, 0x93, 0x4b, 0x29, 0xb4, 0x74, 0xba, 0xad, + 0x26, 0x97, 0xe2, 0x9f, 0x1f, 0x92, 0x0d, 0xcc, 0x77, 0xc8, 0xa0, 0xa0, 0x88, 0x44, 0x76, 0x24, + } preMasterSecret, err := PreMasterSecret(publicKey, privateKey, elliptic.X25519) if err != nil { @@ -26,10 +35,23 @@ func TestPreMasterSecret(t *testing.T) { } func TestMasterSecret(t *testing.T) { - preMasterSecret := []byte{0xdf, 0x4a, 0x29, 0x1b, 0xaa, 0x1e, 0xb7, 0xcf, 0xa6, 0x93, 0x4b, 0x29, 0xb4, 0x74, 0xba, 0xad, 0x26, 0x97, 0xe2, 0x9f, 0x1f, 0x92, 0x0d, 0xcc, 0x77, 0xc8, 0xa0, 0xa0, 0x88, 0x44, 0x76, 0x24} - clientRandom := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f} - serverRandom := []byte{0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f} - expectedMasterSecret := []byte{0x91, 0x6a, 0xbf, 0x9d, 0xa5, 0x59, 0x73, 0xe1, 0x36, 0x14, 0xae, 0x0a, 0x3f, 0x5d, 0x3f, 0x37, 0xb0, 0x23, 0xba, 0x12, 0x9a, 0xee, 0x02, 0xcc, 0x91, 0x34, 0x33, 0x81, 0x27, 0xcd, 0x70, 0x49, 0x78, 0x1c, 0x8e, 0x19, 0xfc, 0x1e, 0xb2, 0xa7, 0x38, 0x7a, 0xc0, 0x6a, 0xe2, 0x37, 0x34, 0x4c} + preMasterSecret := []byte{ + 0xdf, 0x4a, 0x29, 0x1b, 0xaa, 0x1e, 0xb7, 0xcf, 0xa6, 0x93, 0x4b, 0x29, 0xb4, 0x74, 0xba, 0xad, + 0x26, 0x97, 0xe2, 0x9f, 0x1f, 0x92, 0x0d, 0xcc, 0x77, 0xc8, 0xa0, 0xa0, 0x88, 0x44, 0x76, 0x24, + } + clientRandom := []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + } + serverRandom := []byte{ + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + } + expectedMasterSecret := []byte{ + 0x91, 0x6a, 0xbf, 0x9d, 0xa5, 0x59, 0x73, 0xe1, 0x36, 0x14, 0xae, 0x0a, 0x3f, 0x5d, 0x3f, 0x37, + 0xb0, 0x23, 0xba, 0x12, 0x9a, 0xee, 0x02, 0xcc, 0x91, 0x34, 0x33, 0x81, 0x27, 0xcd, 0x70, 0x49, + 0x78, 0x1c, 0x8e, 0x19, 0xfc, 0x1e, 0xb2, 0xa7, 0x38, 0x7a, 0xc0, 0x6a, 0xe2, 0x37, 0x34, 0x4c, + } masterSecret, err := MasterSecret(preMasterSecret, clientRandom, serverRandom, sha256.New) if err != nil { @@ -40,18 +62,32 @@ func TestMasterSecret(t *testing.T) { } func TestEncryptionKeys(t *testing.T) { - clientRandom := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f} - serverRandom := []byte{0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f} - masterSecret := []byte{0x91, 0x6a, 0xbf, 0x9d, 0xa5, 0x59, 0x73, 0xe1, 0x36, 0x14, 0xae, 0x0a, 0x3f, 0x5d, 0x3f, 0x37, 0xb0, 0x23, 0xba, 0x12, 0x9a, 0xee, 0x02, 0xcc, 0x91, 0x34, 0x33, 0x81, 0x27, 0xcd, 0x70, 0x49, 0x78, 0x1c, 0x8e, 0x19, 0xfc, 0x1e, 0xb2, 0xa7, 0x38, 0x7a, 0xc0, 0x6a, 0xe2, 0x37, 0x34, 0x4c} + clientRandom := []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + } + serverRandom := []byte{ + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + } + masterSecret := []byte{ + 0x91, 0x6a, 0xbf, 0x9d, 0xa5, 0x59, 0x73, 0xe1, 0x36, 0x14, 0xae, 0x0a, 0x3f, 0x5d, 0x3f, 0x37, + 0xb0, 0x23, 0xba, 0x12, 0x9a, 0xee, 0x02, 0xcc, 0x91, 0x34, 0x33, 0x81, 0x27, 0xcd, 0x70, 0x49, + 0x78, 0x1c, 0x8e, 0x19, 0xfc, 0x1e, 0xb2, 0xa7, 0x38, 0x7a, 0xc0, 0x6a, 0xe2, 0x37, 0x34, 0x4c, + } expectedEncryptionKeys := &EncryptionKeys{ - MasterSecret: masterSecret, - ClientMACKey: []byte{}, - ServerMACKey: []byte{}, - ClientWriteKey: []byte{0x1b, 0x7d, 0x11, 0x7c, 0x7d, 0x5f, 0x69, 0x0b, 0xc2, 0x63, 0xca, 0xe8, 0xef, 0x60, 0xaf, 0x0f}, - ServerWriteKey: []byte{0x18, 0x78, 0xac, 0xc2, 0x2a, 0xd8, 0xbd, 0xd8, 0xc6, 0x01, 0xa6, 0x17, 0x12, 0x6f, 0x63, 0x54}, - ClientWriteIV: []byte{0x0e, 0xb2, 0x09, 0x06}, - ServerWriteIV: []byte{0xf7, 0x81, 0xfa, 0xd2}, + MasterSecret: masterSecret, + ClientMACKey: []byte{}, + ServerMACKey: []byte{}, + ClientWriteKey: []byte{ + 0x1b, 0x7d, 0x11, 0x7c, 0x7d, 0x5f, 0x69, 0x0b, 0xc2, 0x63, 0xca, 0xe8, 0xef, 0x60, 0xaf, 0x0f, + }, + ServerWriteKey: []byte{ + 0x18, 0x78, 0xac, 0xc2, 0x2a, 0xd8, 0xbd, 0xd8, 0xc6, 0x01, 0xa6, 0x17, 0x12, 0x6f, 0x63, 0x54, + }, + ClientWriteIV: []byte{0x0e, 0xb2, 0x09, 0x06}, + ServerWriteIV: []byte{0xf7, 0x81, 0xfa, 0xd2}, } keys, err := GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, 0, 16, 4, sha256.New) @@ -63,15 +99,123 @@ func TestEncryptionKeys(t *testing.T) { } func TestVerifyData(t *testing.T) { - clientHello := []byte{0x01, 0x00, 0x00, 0xa1, 0x03, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x00, 0x20, 0xcc, 0xa8, 0xcc, 0xa9, 0xc0, 0x2f, 0xc0, 0x30, 0xc0, 0x2b, 0xc0, 0x2c, 0xc0, 0x13, 0xc0, 0x09, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x35, 0xc0, 0x12, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x18, 0x00, 0x16, 0x00, 0x00, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x10, 0x04, 0x01, 0x04, 0x03, 0x05, 0x01, 0x05, 0x03, 0x06, 0x01, 0x06, 0x03, 0x02, 0x01, 0x02, 0x03, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00, 0x00} - serverHello := []byte{0x02, 0x00, 0x00, 0x2d, 0x03, 0x03, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x00, 0xc0, 0x13, 0x00, 0x00, 0x05, 0xff, 0x01, 0x00, 0x01, 0x00} - serverCertificate := []byte{0x0b, 0x00, 0x03, 0x2b, 0x00, 0x03, 0x28, 0x00, 0x03, 0x25, 0x30, 0x82, 0x03, 0x21, 0x30, 0x82, 0x02, 0x09, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x15, 0x5a, 0x92, 0xad, 0xc2, 0x04, 0x8f, 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, 0x38, 0x31, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, 0x38, 0x31, 0x37, 0x5a, 0x30, 0x2b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0x80, 0x36, 0x06, 0xba, 0xe7, 0x47, 0x6b, 0x08, 0x94, 0x04, 0xec, 0xa7, 0xb6, 0x91, 0x04, 0x3f, 0xf7, 0x92, 0xbc, 0x19, 0xee, 0xfb, 0x7d, 0x74, 0xd7, 0xa8, 0x0d, 0x00, 0x1e, 0x7b, 0x4b, 0x3a, 0x4a, 0xe6, 0x0f, 0xe8, 0xc0, 0x71, 0xfc, 0x73, 0xe7, 0x02, 0x4c, 0x0d, 0xbc, 0xf4, 0xbd, 0xd1, 0x1d, 0x39, 0x6b, 0xba, 0x70, 0x46, 0x4a, 0x13, 0xe9, 0x4a, 0xf8, 0x3d, 0xf3, 0xe1, 0x09, 0x59, 0x54, 0x7b, 0xc9, 0x55, 0xfb, 0x41, 0x2d, 0xa3, 0x76, 0x52, 0x11, 0xe1, 0xf3, 0xdc, 0x77, 0x6c, 0xaa, 0x53, 0x37, 0x6e, 0xca, 0x3a, 0xec, 0xbe, 0xc3, 0xaa, 0xb7, 0x3b, 0x31, 0xd5, 0x6c, 0xb6, 0x52, 0x9c, 0x80, 0x98, 0xbc, 0xc9, 0xe0, 0x28, 0x18, 0xe2, 0x0b, 0xf7, 0xf8, 0xa0, 0x3a, 0xfd, 0x17, 0x04, 0x50, 0x9e, 0xce, 0x79, 0xbd, 0x9f, 0x39, 0xf1, 0xea, 0x69, 0xec, 0x47, 0x97, 0x2e, 0x83, 0x0f, 0xb5, 0xca, 0x95, 0xde, 0x95, 0xa1, 0xe6, 0x04, 0x22, 0xd5, 0xee, 0xbe, 0x52, 0x79, 0x54, 0xa1, 0xe7, 0xbf, 0x8a, 0x86, 0xf6, 0x46, 0x6d, 0x0d, 0x9f, 0x16, 0x95, 0x1a, 0x4c, 0xf7, 0xa0, 0x46, 0x92, 0x59, 0x5c, 0x13, 0x52, 0xf2, 0x54, 0x9e, 0x5a, 0xfb, 0x4e, 0xbf, 0xd7, 0x7a, 0x37, 0x95, 0x01, 0x44, 0xe4, 0xc0, 0x26, 0x87, 0x4c, 0x65, 0x3e, 0x40, 0x7d, 0x7d, 0x23, 0x07, 0x44, 0x01, 0xf4, 0x84, 0xff, 0xd0, 0x8f, 0x7a, 0x1f, 0xa0, 0x52, 0x10, 0xd1, 0xf4, 0xf0, 0xd5, 0xce, 0x79, 0x70, 0x29, 0x32, 0xe2, 0xca, 0xbe, 0x70, 0x1f, 0xdf, 0xad, 0x6b, 0x4b, 0xb7, 0x11, 0x01, 0xf4, 0x4b, 0xad, 0x66, 0x6a, 0x11, 0x13, 0x0f, 0xe2, 0xee, 0x82, 0x9e, 0x4d, 0x02, 0x9d, 0xc9, 0x1c, 0xdd, 0x67, 0x16, 0xdb, 0xb9, 0x06, 0x18, 0x86, 0xed, 0xc1, 0xba, 0x94, 0x21, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x52, 0x30, 0x50, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x89, 0x4f, 0xde, 0x5b, 0xcc, 0x69, 0xe2, 0x52, 0xcf, 0x3e, 0xa3, 0x00, 0xdf, 0xb1, 0x97, 0xb8, 0x1d, 0xe1, 0xc1, 0x46, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x59, 0x16, 0x45, 0xa6, 0x9a, 0x2e, 0x37, 0x79, 0xe4, 0xf6, 0xdd, 0x27, 0x1a, 0xba, 0x1c, 0x0b, 0xfd, 0x6c, 0xd7, 0x55, 0x99, 0xb5, 0xe7, 0xc3, 0x6e, 0x53, 0x3e, 0xff, 0x36, 0x59, 0x08, 0x43, 0x24, 0xc9, 0xe7, 0xa5, 0x04, 0x07, 0x9d, 0x39, 0xe0, 0xd4, 0x29, 0x87, 0xff, 0xe3, 0xeb, 0xdd, 0x09, 0xc1, 0xcf, 0x1d, 0x91, 0x44, 0x55, 0x87, 0x0b, 0x57, 0x1d, 0xd1, 0x9b, 0xdf, 0x1d, 0x24, 0xf8, 0xbb, 0x9a, 0x11, 0xfe, 0x80, 0xfd, 0x59, 0x2b, 0xa0, 0x39, 0x8c, 0xde, 0x11, 0xe2, 0x65, 0x1e, 0x61, 0x8c, 0xe5, 0x98, 0xfa, 0x96, 0xe5, 0x37, 0x2e, 0xef, 0x3d, 0x24, 0x8a, 0xfd, 0xe1, 0x74, 0x63, 0xeb, 0xbf, 0xab, 0xb8, 0xe4, 0xd1, 0xab, 0x50, 0x2a, 0x54, 0xec, 0x00, 0x64, 0xe9, 0x2f, 0x78, 0x19, 0x66, 0x0d, 0x3f, 0x27, 0xcf, 0x20, 0x9e, 0x66, 0x7f, 0xce, 0x5a, 0xe2, 0xe4, 0xac, 0x99, 0xc7, 0xc9, 0x38, 0x18, 0xf8, 0xb2, 0x51, 0x07, 0x22, 0xdf, 0xed, 0x97, 0xf3, 0x2e, 0x3e, 0x93, 0x49, 0xd4, 0xc6, 0x6c, 0x9e, 0xa6, 0x39, 0x6d, 0x74, 0x44, 0x62, 0xa0, 0x6b, 0x42, 0xc6, 0xd5, 0xba, 0x68, 0x8e, 0xac, 0x3a, 0x01, 0x7b, 0xdd, 0xfc, 0x8e, 0x2c, 0xfc, 0xad, 0x27, 0xcb, 0x69, 0xd3, 0xcc, 0xdc, 0xa2, 0x80, 0x41, 0x44, 0x65, 0xd3, 0xae, 0x34, 0x8c, 0xe0, 0xf3, 0x4a, 0xb2, 0xfb, 0x9c, 0x61, 0x83, 0x71, 0x31, 0x2b, 0x19, 0x10, 0x41, 0x64, 0x1c, 0x23, 0x7f, 0x11, 0xa5, 0xd6, 0x5c, 0x84, 0x4f, 0x04, 0x04, 0x84, 0x99, 0x38, 0x71, 0x2b, 0x95, 0x9e, 0xd6, 0x85, 0xbc, 0x5c, 0x5d, 0xd6, 0x45, 0xed, 0x19, 0x90, 0x94, 0x73, 0x40, 0x29, 0x26, 0xdc, 0xb4, 0x0e, 0x34, 0x69, 0xa1, 0x59, 0x41, 0xe8, 0xe2, 0xcc, 0xa8, 0x4b, 0xb6, 0x08, 0x46, 0x36, 0xa0} - serverKeyExchange := []byte{0x0c, 0x00, 0x01, 0x28, 0x03, 0x00, 0x1d, 0x20, 0x9f, 0xd7, 0xad, 0x6d, 0xcf, 0xf4, 0x29, 0x8d, 0xd3, 0xf9, 0x6d, 0x5b, 0x1b, 0x2a, 0xf9, 0x10, 0xa0, 0x53, 0x5b, 0x14, 0x88, 0xd7, 0xf8, 0xfa, 0xbb, 0x34, 0x9a, 0x98, 0x28, 0x80, 0xb6, 0x15, 0x04, 0x01, 0x01, 0x00, 0x04, 0x02, 0xb6, 0x61, 0xf7, 0xc1, 0x91, 0xee, 0x59, 0xbe, 0x45, 0x37, 0x66, 0x39, 0xbd, 0xc3, 0xd4, 0xbb, 0x81, 0xe1, 0x15, 0xca, 0x73, 0xc8, 0x34, 0x8b, 0x52, 0x5b, 0x0d, 0x23, 0x38, 0xaa, 0x14, 0x46, 0x67, 0xed, 0x94, 0x31, 0x02, 0x14, 0x12, 0xcd, 0x9b, 0x84, 0x4c, 0xba, 0x29, 0x93, 0x4a, 0xaa, 0xcc, 0xe8, 0x73, 0x41, 0x4e, 0xc1, 0x1c, 0xb0, 0x2e, 0x27, 0x2d, 0x0a, 0xd8, 0x1f, 0x76, 0x7d, 0x33, 0x07, 0x67, 0x21, 0xf1, 0x3b, 0xf3, 0x60, 0x20, 0xcf, 0x0b, 0x1f, 0xd0, 0xec, 0xb0, 0x78, 0xde, 0x11, 0x28, 0xbe, 0xba, 0x09, 0x49, 0xeb, 0xec, 0xe1, 0xa1, 0xf9, 0x6e, 0x20, 0x9d, 0xc3, 0x6e, 0x4f, 0xff, 0xd3, 0x6b, 0x67, 0x3a, 0x7d, 0xdc, 0x15, 0x97, 0xad, 0x44, 0x08, 0xe4, 0x85, 0xc4, 0xad, 0xb2, 0xc8, 0x73, 0x84, 0x12, 0x49, 0x37, 0x25, 0x23, 0x80, 0x9e, 0x43, 0x12, 0xd0, 0xc7, 0xb3, 0x52, 0x2e, 0xf9, 0x83, 0xca, 0xc1, 0xe0, 0x39, 0x35, 0xff, 0x13, 0xa8, 0xe9, 0x6b, 0xa6, 0x81, 0xa6, 0x2e, 0x40, 0xd3, 0xe7, 0x0a, 0x7f, 0xf3, 0x58, 0x66, 0xd3, 0xd9, 0x99, 0x3f, 0x9e, 0x26, 0xa6, 0x34, 0xc8, 0x1b, 0x4e, 0x71, 0x38, 0x0f, 0xcd, 0xd6, 0xf4, 0xe8, 0x35, 0xf7, 0x5a, 0x64, 0x09, 0xc7, 0xdc, 0x2c, 0x07, 0x41, 0x0e, 0x6f, 0x87, 0x85, 0x8c, 0x7b, 0x94, 0xc0, 0x1c, 0x2e, 0x32, 0xf2, 0x91, 0x76, 0x9e, 0xac, 0xca, 0x71, 0x64, 0x3b, 0x8b, 0x98, 0xa9, 0x63, 0xdf, 0x0a, 0x32, 0x9b, 0xea, 0x4e, 0xd6, 0x39, 0x7e, 0x8c, 0xd0, 0x1a, 0x11, 0x0a, 0xb3, 0x61, 0xac, 0x5b, 0xad, 0x1c, 0xcd, 0x84, 0x0a, 0x6c, 0x8a, 0x6e, 0xaa, 0x00, 0x1a, 0x9d, 0x7d, 0x87, 0xdc, 0x33, 0x18, 0x64, 0x35, 0x71, 0x22, 0x6c, 0x4d, 0xd2, 0xc2, 0xac, 0x41, 0xfb} + clientHello := []byte{ + 0x01, 0x00, 0x00, 0xa1, 0x03, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x00, 0x20, 0xcc, 0xa8, 0xcc, 0xa9, 0xc0, 0x2f, 0xc0, + 0x30, 0xc0, 0x2b, 0xc0, 0x2c, 0xc0, 0x13, 0xc0, 0x09, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9c, 0x00, + 0x9d, 0x00, 0x2f, 0x00, 0x35, 0xc0, 0x12, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x16, 0x00, 0x00, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, + 0x66, 0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, + 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x10, 0x04, 0x01, 0x04, 0x03, + 0x05, 0x01, 0x05, 0x03, 0x06, 0x01, 0x06, 0x03, 0x02, 0x01, 0x02, 0x03, 0xff, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x12, 0x00, 0x00, + } + serverHello := []byte{ + 0x02, 0x00, 0x00, 0x2d, 0x03, 0x03, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x00, 0xc0, 0x13, 0x00, 0x00, 0x05, 0xff, 0x01, 0x00, 0x01, + 0x00, + } + serverCertificate := []byte{ + 0x0b, 0x00, 0x03, 0x2b, 0x00, 0x03, 0x28, 0x00, 0x03, 0x25, 0x30, 0x82, 0x03, 0x21, 0x30, 0x82, + 0x02, 0x09, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x15, 0x5a, 0x92, 0xad, 0xc2, 0x04, 0x8f, + 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, + 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, + 0x33, 0x38, 0x31, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, + 0x38, 0x31, 0x37, 0x5a, 0x30, 0x2b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x78, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e, 0x65, + 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xc4, 0x80, 0x36, 0x06, 0xba, 0xe7, 0x47, 0x6b, 0x08, 0x94, 0x04, 0xec, 0xa7, 0xb6, + 0x91, 0x04, 0x3f, 0xf7, 0x92, 0xbc, 0x19, 0xee, 0xfb, 0x7d, 0x74, 0xd7, 0xa8, 0x0d, 0x00, 0x1e, + 0x7b, 0x4b, 0x3a, 0x4a, 0xe6, 0x0f, 0xe8, 0xc0, 0x71, 0xfc, 0x73, 0xe7, 0x02, 0x4c, 0x0d, 0xbc, + 0xf4, 0xbd, 0xd1, 0x1d, 0x39, 0x6b, 0xba, 0x70, 0x46, 0x4a, 0x13, 0xe9, 0x4a, 0xf8, 0x3d, 0xf3, + 0xe1, 0x09, 0x59, 0x54, 0x7b, 0xc9, 0x55, 0xfb, 0x41, 0x2d, 0xa3, 0x76, 0x52, 0x11, 0xe1, 0xf3, + 0xdc, 0x77, 0x6c, 0xaa, 0x53, 0x37, 0x6e, 0xca, 0x3a, 0xec, 0xbe, 0xc3, 0xaa, 0xb7, 0x3b, 0x31, + 0xd5, 0x6c, 0xb6, 0x52, 0x9c, 0x80, 0x98, 0xbc, 0xc9, 0xe0, 0x28, 0x18, 0xe2, 0x0b, 0xf7, 0xf8, + 0xa0, 0x3a, 0xfd, 0x17, 0x04, 0x50, 0x9e, 0xce, 0x79, 0xbd, 0x9f, 0x39, 0xf1, 0xea, 0x69, 0xec, + 0x47, 0x97, 0x2e, 0x83, 0x0f, 0xb5, 0xca, 0x95, 0xde, 0x95, 0xa1, 0xe6, 0x04, 0x22, 0xd5, 0xee, + 0xbe, 0x52, 0x79, 0x54, 0xa1, 0xe7, 0xbf, 0x8a, 0x86, 0xf6, 0x46, 0x6d, 0x0d, 0x9f, 0x16, 0x95, + 0x1a, 0x4c, 0xf7, 0xa0, 0x46, 0x92, 0x59, 0x5c, 0x13, 0x52, 0xf2, 0x54, 0x9e, 0x5a, 0xfb, 0x4e, + 0xbf, 0xd7, 0x7a, 0x37, 0x95, 0x01, 0x44, 0xe4, 0xc0, 0x26, 0x87, 0x4c, 0x65, 0x3e, 0x40, 0x7d, + 0x7d, 0x23, 0x07, 0x44, 0x01, 0xf4, 0x84, 0xff, 0xd0, 0x8f, 0x7a, 0x1f, 0xa0, 0x52, 0x10, 0xd1, + 0xf4, 0xf0, 0xd5, 0xce, 0x79, 0x70, 0x29, 0x32, 0xe2, 0xca, 0xbe, 0x70, 0x1f, 0xdf, 0xad, 0x6b, + 0x4b, 0xb7, 0x11, 0x01, 0xf4, 0x4b, 0xad, 0x66, 0x6a, 0x11, 0x13, 0x0f, 0xe2, 0xee, 0x82, 0x9e, + 0x4d, 0x02, 0x9d, 0xc9, 0x1c, 0xdd, 0x67, 0x16, 0xdb, 0xb9, 0x06, 0x18, 0x86, 0xed, 0xc1, 0xba, + 0x94, 0x21, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x52, 0x30, 0x50, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x89, 0x4f, 0xde, 0x5b, 0xcc, 0x69, 0xe2, 0x52, 0xcf, + 0x3e, 0xa3, 0x00, 0xdf, 0xb1, 0x97, 0xb8, 0x1d, 0xe1, 0xc1, 0x46, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x59, + 0x16, 0x45, 0xa6, 0x9a, 0x2e, 0x37, 0x79, 0xe4, 0xf6, 0xdd, 0x27, 0x1a, 0xba, 0x1c, 0x0b, 0xfd, + 0x6c, 0xd7, 0x55, 0x99, 0xb5, 0xe7, 0xc3, 0x6e, 0x53, 0x3e, 0xff, 0x36, 0x59, 0x08, 0x43, 0x24, + 0xc9, 0xe7, 0xa5, 0x04, 0x07, 0x9d, 0x39, 0xe0, 0xd4, 0x29, 0x87, 0xff, 0xe3, 0xeb, 0xdd, 0x09, + 0xc1, 0xcf, 0x1d, 0x91, 0x44, 0x55, 0x87, 0x0b, 0x57, 0x1d, 0xd1, 0x9b, 0xdf, 0x1d, 0x24, 0xf8, + 0xbb, 0x9a, 0x11, 0xfe, 0x80, 0xfd, 0x59, 0x2b, 0xa0, 0x39, 0x8c, 0xde, 0x11, 0xe2, 0x65, 0x1e, + 0x61, 0x8c, 0xe5, 0x98, 0xfa, 0x96, 0xe5, 0x37, 0x2e, 0xef, 0x3d, 0x24, 0x8a, 0xfd, 0xe1, 0x74, + 0x63, 0xeb, 0xbf, 0xab, 0xb8, 0xe4, 0xd1, 0xab, 0x50, 0x2a, 0x54, 0xec, 0x00, 0x64, 0xe9, 0x2f, + 0x78, 0x19, 0x66, 0x0d, 0x3f, 0x27, 0xcf, 0x20, 0x9e, 0x66, 0x7f, 0xce, 0x5a, 0xe2, 0xe4, 0xac, + 0x99, 0xc7, 0xc9, 0x38, 0x18, 0xf8, 0xb2, 0x51, 0x07, 0x22, 0xdf, 0xed, 0x97, 0xf3, 0x2e, 0x3e, + 0x93, 0x49, 0xd4, 0xc6, 0x6c, 0x9e, 0xa6, 0x39, 0x6d, 0x74, 0x44, 0x62, 0xa0, 0x6b, 0x42, 0xc6, + 0xd5, 0xba, 0x68, 0x8e, 0xac, 0x3a, 0x01, 0x7b, 0xdd, 0xfc, 0x8e, 0x2c, 0xfc, 0xad, 0x27, 0xcb, + 0x69, 0xd3, 0xcc, 0xdc, 0xa2, 0x80, 0x41, 0x44, 0x65, 0xd3, 0xae, 0x34, 0x8c, 0xe0, 0xf3, 0x4a, + 0xb2, 0xfb, 0x9c, 0x61, 0x83, 0x71, 0x31, 0x2b, 0x19, 0x10, 0x41, 0x64, 0x1c, 0x23, 0x7f, 0x11, + 0xa5, 0xd6, 0x5c, 0x84, 0x4f, 0x04, 0x04, 0x84, 0x99, 0x38, 0x71, 0x2b, 0x95, 0x9e, 0xd6, 0x85, + 0xbc, 0x5c, 0x5d, 0xd6, 0x45, 0xed, 0x19, 0x90, 0x94, 0x73, 0x40, 0x29, 0x26, 0xdc, 0xb4, 0x0e, + 0x34, 0x69, 0xa1, 0x59, 0x41, 0xe8, 0xe2, 0xcc, 0xa8, 0x4b, 0xb6, 0x08, 0x46, 0x36, 0xa0, + } + serverKeyExchange := []byte{ + 0x0c, 0x00, 0x01, 0x28, 0x03, 0x00, 0x1d, 0x20, 0x9f, 0xd7, 0xad, 0x6d, 0xcf, 0xf4, 0x29, 0x8d, + 0xd3, 0xf9, 0x6d, 0x5b, 0x1b, 0x2a, 0xf9, 0x10, 0xa0, 0x53, 0x5b, 0x14, 0x88, 0xd7, 0xf8, 0xfa, + 0xbb, 0x34, 0x9a, 0x98, 0x28, 0x80, 0xb6, 0x15, 0x04, 0x01, 0x01, 0x00, 0x04, 0x02, 0xb6, 0x61, + 0xf7, 0xc1, 0x91, 0xee, 0x59, 0xbe, 0x45, 0x37, 0x66, 0x39, 0xbd, 0xc3, 0xd4, 0xbb, 0x81, 0xe1, + 0x15, 0xca, 0x73, 0xc8, 0x34, 0x8b, 0x52, 0x5b, 0x0d, 0x23, 0x38, 0xaa, 0x14, 0x46, 0x67, 0xed, + 0x94, 0x31, 0x02, 0x14, 0x12, 0xcd, 0x9b, 0x84, 0x4c, 0xba, 0x29, 0x93, 0x4a, 0xaa, 0xcc, 0xe8, + 0x73, 0x41, 0x4e, 0xc1, 0x1c, 0xb0, 0x2e, 0x27, 0x2d, 0x0a, 0xd8, 0x1f, 0x76, 0x7d, 0x33, 0x07, + 0x67, 0x21, 0xf1, 0x3b, 0xf3, 0x60, 0x20, 0xcf, 0x0b, 0x1f, 0xd0, 0xec, 0xb0, 0x78, 0xde, 0x11, + 0x28, 0xbe, 0xba, 0x09, 0x49, 0xeb, 0xec, 0xe1, 0xa1, 0xf9, 0x6e, 0x20, 0x9d, 0xc3, 0x6e, 0x4f, + 0xff, 0xd3, 0x6b, 0x67, 0x3a, 0x7d, 0xdc, 0x15, 0x97, 0xad, 0x44, 0x08, 0xe4, 0x85, 0xc4, 0xad, + 0xb2, 0xc8, 0x73, 0x84, 0x12, 0x49, 0x37, 0x25, 0x23, 0x80, 0x9e, 0x43, 0x12, 0xd0, 0xc7, 0xb3, + 0x52, 0x2e, 0xf9, 0x83, 0xca, 0xc1, 0xe0, 0x39, 0x35, 0xff, 0x13, 0xa8, 0xe9, 0x6b, 0xa6, 0x81, + 0xa6, 0x2e, 0x40, 0xd3, 0xe7, 0x0a, 0x7f, 0xf3, 0x58, 0x66, 0xd3, 0xd9, 0x99, 0x3f, 0x9e, 0x26, + 0xa6, 0x34, 0xc8, 0x1b, 0x4e, 0x71, 0x38, 0x0f, 0xcd, 0xd6, 0xf4, 0xe8, 0x35, 0xf7, 0x5a, 0x64, + 0x09, 0xc7, 0xdc, 0x2c, 0x07, 0x41, 0x0e, 0x6f, 0x87, 0x85, 0x8c, 0x7b, 0x94, 0xc0, 0x1c, 0x2e, + 0x32, 0xf2, 0x91, 0x76, 0x9e, 0xac, 0xca, 0x71, 0x64, 0x3b, 0x8b, 0x98, 0xa9, 0x63, 0xdf, 0x0a, + 0x32, 0x9b, 0xea, 0x4e, 0xd6, 0x39, 0x7e, 0x8c, 0xd0, 0x1a, 0x11, 0x0a, 0xb3, 0x61, 0xac, 0x5b, + 0xad, 0x1c, 0xcd, 0x84, 0x0a, 0x6c, 0x8a, 0x6e, 0xaa, 0x00, 0x1a, 0x9d, 0x7d, 0x87, 0xdc, 0x33, + 0x18, 0x64, 0x35, 0x71, 0x22, 0x6c, 0x4d, 0xd2, 0xc2, 0xac, 0x41, 0xfb, + } serverHelloDone := []byte{0x0e, 0x00, 0x00, 0x00} - clientKeyExchange := []byte{0x10, 0x00, 0x00, 0x21, 0x20, 0x35, 0x80, 0x72, 0xd6, 0x36, 0x58, 0x80, 0xd1, 0xae, 0xea, 0x32, 0x9a, 0xdf, 0x91, 0x21, 0x38, 0x38, 0x51, 0xed, 0x21, 0xa2, 0x8e, 0x3b, 0x75, 0xe9, 0x65, 0xd0, 0xd2, 0xcd, 0x16, 0x62, 0x54} + clientKeyExchange := []byte{ + 0x10, 0x00, 0x00, 0x21, 0x20, 0x35, 0x80, 0x72, 0xd6, 0x36, 0x58, 0x80, 0xd1, 0xae, 0xea, + 0x32, 0x9a, 0xdf, 0x91, 0x21, 0x38, 0x38, 0x51, 0xed, 0x21, 0xa2, 0x8e, 0x3b, 0x75, 0xe9, + 0x65, 0xd0, 0xd2, 0xcd, 0x16, 0x62, 0x54, + } - finalMsg := append(append(append(append(append(clientHello, serverHello...), serverCertificate...), serverKeyExchange...), serverHelloDone...), clientKeyExchange...) - masterSecret := []byte{0x91, 0x6a, 0xbf, 0x9d, 0xa5, 0x59, 0x73, 0xe1, 0x36, 0x14, 0xae, 0x0a, 0x3f, 0x5d, 0x3f, 0x37, 0xb0, 0x23, 0xba, 0x12, 0x9a, 0xee, 0x02, 0xcc, 0x91, 0x34, 0x33, 0x81, 0x27, 0xcd, 0x70, 0x49, 0x78, 0x1c, 0x8e, 0x19, 0xfc, 0x1e, 0xb2, 0xa7, 0x38, 0x7a, 0xc0, 0x6a, 0xe2, 0x37, 0x34, 0x4c} + finalMsg := append( + append( + append( + append( + append( + clientHello, serverHello..., + ), serverCertificate..., + ), serverKeyExchange..., + ), serverHelloDone..., + ), clientKeyExchange..., + ) + masterSecret := []byte{ + 0x91, 0x6a, 0xbf, 0x9d, 0xa5, 0x59, 0x73, 0xe1, 0x36, 0x14, 0xae, 0x0a, 0x3f, 0x5d, 0x3f, + 0x37, 0xb0, 0x23, 0xba, 0x12, 0x9a, 0xee, 0x02, 0xcc, 0x91, 0x34, 0x33, 0x81, 0x27, 0xcd, + 0x70, 0x49, 0x78, 0x1c, 0x8e, 0x19, 0xfc, 0x1e, 0xb2, 0xa7, 0x38, 0x7a, 0xc0, 0x6a, 0xe2, + 0x37, 0x34, 0x4c, + } expectedVerifyData := []byte{0xcf, 0x91, 0x96, 0x26, 0xf1, 0x36, 0x0c, 0x53, 0x6a, 0xaa, 0xd7, 0x3a} verifyData, err := VerifyDataClient(masterSecret, finalMsg, sha256.New) diff --git a/pkg/crypto/selfsign/selfsign.go b/pkg/crypto/selfsign/selfsign.go index 6ef016724..fd238b18a 100644 --- a/pkg/crypto/selfsign/selfsign.go +++ b/pkg/crypto/selfsign/selfsign.go @@ -21,7 +21,7 @@ import ( var errInvalidPrivateKey = errors.New("selfsign: invalid private key type") -// GenerateSelfSigned creates a self-signed certificate +// GenerateSelfSigned creates a self-signed certificate. func GenerateSelfSigned() (tls.Certificate, error) { priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { @@ -31,7 +31,7 @@ func GenerateSelfSigned() (tls.Certificate, error) { return SelfSign(priv) } -// GenerateSelfSignedWithDNS creates a self-signed certificate +// GenerateSelfSignedWithDNS creates a self-signed certificate. func GenerateSelfSignedWithDNS(cn string, sans ...string) (tls.Certificate, error) { priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { @@ -41,12 +41,12 @@ func GenerateSelfSignedWithDNS(cn string, sans ...string) (tls.Certificate, erro return WithDNS(priv, cn, sans...) } -// SelfSign creates a self-signed certificate from a elliptic curve key +// SelfSign creates a self-signed certificate from a elliptic curve key. func SelfSign(key crypto.PrivateKey) (tls.Certificate, error) { return WithDNS(key, "self-signed cert") } -// WithDNS creates a self-signed certificate from a elliptic curve key +// WithDNS creates a self-signed certificate from a elliptic curve key. func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate, error) { var ( pubKey crypto.PublicKey diff --git a/pkg/crypto/signature/signature.go b/pkg/crypto/signature/signature.go index fec7fba3b..53fb7c952 100644 --- a/pkg/crypto/signature/signature.go +++ b/pkg/crypto/signature/signature.go @@ -8,7 +8,7 @@ package signature // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16 type Algorithm uint16 -// SignatureAlgorithm enums +// SignatureAlgorithm enums. const ( Anonymous Algorithm = 0 RSA Algorithm = 1 @@ -16,7 +16,7 @@ const ( Ed25519 Algorithm = 7 ) -// Algorithms returns all implemented Signature Algorithms +// Algorithms returns all implemented Signature Algorithms. func Algorithms() map[Algorithm]struct{} { return map[Algorithm]struct{}{ Anonymous: {}, diff --git a/pkg/crypto/signaturehash/signaturehash.go b/pkg/crypto/signaturehash/signaturehash.go index 38587768b..b036fdbfc 100644 --- a/pkg/crypto/signaturehash/signaturehash.go +++ b/pkg/crypto/signaturehash/signaturehash.go @@ -25,7 +25,7 @@ type Algorithm struct { Signature signature.Algorithm } -// Algorithms are all the know SignatureHash Algorithms +// Algorithms are all the know SignatureHash Algorithms. func Algorithms() []Algorithm { return []Algorithm{ {hash.SHA256, signature.ECDSA}, @@ -45,6 +45,7 @@ func SelectSignatureScheme(sigs []Algorithm, privateKey crypto.PrivateKey) (Algo return ss, nil } } + return Algorithm{}, errNoAvailableSignatureSchemes } diff --git a/pkg/net/net.go b/pkg/net/net.go index e76daf56a..3db604777 100644 --- a/pkg/net/net.go +++ b/pkg/net/net.go @@ -47,6 +47,7 @@ func (p *packetListenerWrapper) Accept() (net.PacketConn, net.Addr, error) { if err != nil { return PacketConnFromConn(c), nil, err } + return PacketConnFromConn(c), c.RemoteAddr(), nil } @@ -73,12 +74,14 @@ type packetConnWrapper struct { // ReadFrom reads from the underlying net.Conn and returns its remote address. func (p *packetConnWrapper) ReadFrom(b []byte) (int, net.Addr, error) { n, err := p.conn.Read(b) + return n, p.conn.RemoteAddr(), err } // WriteTo writes to the underlying net.Conn. func (p *packetConnWrapper) WriteTo(b []byte, _ net.Addr) (int, error) { n, err := p.conn.Write(b) + return n, err } diff --git a/pkg/protocol/alert/alert.go b/pkg/protocol/alert/alert.go index 0a9e0a215..8fac65962 100644 --- a/pkg/protocol/alert/alert.go +++ b/pkg/protocol/alert/alert.go @@ -13,10 +13,10 @@ import ( var errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 -// Level is the level of the TLS Alert +// Level is the level of the TLS Alert. type Level byte -// Level enums +// Level enums. const ( Warning Level = 1 Fatal Level = 2 @@ -33,10 +33,10 @@ func (l Level) String() string { } } -// Description is the extended info of the TLS Alert +// Description is the extended info of the TLS Alert. type Description byte -// Description enums +// Description enums. const ( CloseNotify Description = 0 UnexpectedMessage Description = 10 @@ -66,7 +66,7 @@ const ( NoApplicationProtocol Description = 120 ) -func (d Description) String() string { +func (d Description) String() string { //nolint:cyclop switch d { case CloseNotify: return "CloseNotify" @@ -140,17 +140,17 @@ type Alert struct { Description Description } -// ContentType returns the ContentType of this Content +// ContentType returns the ContentType of this Content. func (a Alert) ContentType() protocol.ContentType { return protocol.ContentTypeAlert } -// Marshal returns the encoded alert +// Marshal returns the encoded alert. func (a *Alert) Marshal() ([]byte, error) { return []byte{byte(a.Level), byte(a.Description)}, nil } -// Unmarshal populates the alert from binary data +// Unmarshal populates the alert from binary data. func (a *Alert) Unmarshal(data []byte) error { if len(data) != 2 { return errBufferTooSmall @@ -158,6 +158,7 @@ func (a *Alert) Unmarshal(data []byte) error { a.Level = Level(data[0]) a.Description = Description(data[1]) + return nil } diff --git a/pkg/protocol/application_data.go b/pkg/protocol/application_data.go index f42211511..f478c4231 100644 --- a/pkg/protocol/application_data.go +++ b/pkg/protocol/application_data.go @@ -12,18 +12,19 @@ type ApplicationData struct { Data []byte } -// ContentType returns the ContentType of this content +// ContentType returns the ContentType of this content. func (a ApplicationData) ContentType() ContentType { return ContentTypeApplicationData } -// Marshal encodes the ApplicationData to binary +// Marshal encodes the ApplicationData to binary. func (a *ApplicationData) Marshal() ([]byte, error) { return append([]byte{}, a.Data...), nil } -// Unmarshal populates the ApplicationData from binary +// Unmarshal populates the ApplicationData from binary. func (a *ApplicationData) Unmarshal(data []byte) error { a.Data = append([]byte{}, data...) + return nil } diff --git a/pkg/protocol/change_cipher_spec.go b/pkg/protocol/change_cipher_spec.go index 87f28bc37..4813cd564 100644 --- a/pkg/protocol/change_cipher_spec.go +++ b/pkg/protocol/change_cipher_spec.go @@ -10,17 +10,17 @@ package protocol // https://tools.ietf.org/html/rfc5246#section-7.1 type ChangeCipherSpec struct{} -// ContentType returns the ContentType of this content +// ContentType returns the ContentType of this content. func (c ChangeCipherSpec) ContentType() ContentType { return ContentTypeChangeCipherSpec } -// Marshal encodes the ChangeCipherSpec to binary +// Marshal encodes the ChangeCipherSpec to binary. func (c *ChangeCipherSpec) Marshal() ([]byte, error) { return []byte{0x01}, nil } -// Unmarshal populates the ChangeCipherSpec from binary +// Unmarshal populates the ChangeCipherSpec from binary. func (c *ChangeCipherSpec) Unmarshal(data []byte) error { if len(data) == 1 && data[0] == 0x01 { return nil diff --git a/pkg/protocol/compression_method.go b/pkg/protocol/compression_method.go index 3478ee38c..0fb99a51b 100644 --- a/pkg/protocol/compression_method.go +++ b/pkg/protocol/compression_method.go @@ -3,26 +3,26 @@ package protocol -// CompressionMethodID is the ID for a CompressionMethod +// CompressionMethodID is the ID for a CompressionMethod. type CompressionMethodID byte const ( compressionMethodNull CompressionMethodID = 0 ) -// CompressionMethod represents a TLS Compression Method +// CompressionMethod represents a TLS Compression Method. type CompressionMethod struct { ID CompressionMethodID } -// CompressionMethods returns all supported CompressionMethods +// CompressionMethods returns all supported CompressionMethods. func CompressionMethods() map[CompressionMethodID]*CompressionMethod { return map[CompressionMethodID]*CompressionMethod{ compressionMethodNull: {ID: compressionMethodNull}, } } -// DecodeCompressionMethods the given compression methods +// DecodeCompressionMethods the given compression methods. func DecodeCompressionMethods(buf []byte) ([]*CompressionMethod, error) { if len(buf) < 1 { return nil, errBufferTooSmall @@ -38,14 +38,16 @@ func DecodeCompressionMethods(buf []byte) ([]*CompressionMethod, error) { c = append(c, compressionMethod) } } + return c, nil } -// EncodeCompressionMethods the given compression methods +// EncodeCompressionMethods the given compression methods. func EncodeCompressionMethods(c []*CompressionMethod) []byte { out := []byte{byte(len(c))} for i := len(c); i > 0; i-- { out = append(out, byte(c[i-1].ID)) } + return out } diff --git a/pkg/protocol/content.go b/pkg/protocol/content.go index 154005e2c..9b6daa51f 100644 --- a/pkg/protocol/content.go +++ b/pkg/protocol/content.go @@ -8,7 +8,7 @@ package protocol // https://tools.ietf.org/html/rfc4346#section-6.2.1 type ContentType uint8 -// ContentType enums +// ContentType enums. const ( ContentTypeChangeCipherSpec ContentType = 20 ContentTypeAlert ContentType = 21 @@ -17,7 +17,7 @@ const ( ContentTypeConnectionID ContentType = 25 ) -// Content is the top level distinguisher for a DTLS Datagram +// Content is the top level distinguisher for a DTLS Datagram. type Content interface { ContentType() ContentType Marshal() ([]byte, error) diff --git a/pkg/protocol/errors.go b/pkg/protocol/errors.go index d87aff7fb..dc091bff3 100644 --- a/pkg/protocol/errors.go +++ b/pkg/protocol/errors.go @@ -20,7 +20,8 @@ type FatalError struct { Err error } -// InternalError indicates and internal error caused by the implementation, and the DTLS connection is no longer available. +// InternalError indicates and internal error caused by the implementation, +// and the DTLS connection is no longer available. // It is mainly caused by bugs or tried to use unimplemented features. type InternalError struct { Err error @@ -41,10 +42,10 @@ type HandshakeError struct { Err error } -// Timeout implements net.Error.Timeout() +// Timeout implements net.Error.Timeout(). func (*FatalError) Timeout() bool { return false } -// Temporary implements net.Error.Temporary() +// Temporary implements net.Error.Temporary(). func (*FatalError) Temporary() bool { return false } // Unwrap implements Go1.13 error unwrapper. @@ -52,10 +53,10 @@ func (e *FatalError) Unwrap() error { return e.Err } func (e *FatalError) Error() string { return fmt.Sprintf("dtls fatal: %v", e.Err) } -// Timeout implements net.Error.Timeout() +// Timeout implements net.Error.Timeout(). func (*InternalError) Timeout() bool { return false } -// Temporary implements net.Error.Temporary() +// Temporary implements net.Error.Temporary(). func (*InternalError) Temporary() bool { return false } // Unwrap implements Go1.13 error unwrapper. @@ -63,10 +64,10 @@ func (e *InternalError) Unwrap() error { return e.Err } func (e *InternalError) Error() string { return fmt.Sprintf("dtls internal: %v", e.Err) } -// Timeout implements net.Error.Timeout() +// Timeout implements net.Error.Timeout(). func (*TemporaryError) Timeout() bool { return false } -// Temporary implements net.Error.Temporary() +// Temporary implements net.Error.Temporary(). func (*TemporaryError) Temporary() bool { return true } // Unwrap implements Go1.13 error unwrapper. @@ -74,10 +75,10 @@ func (e *TemporaryError) Unwrap() error { return e.Err } func (e *TemporaryError) Error() string { return fmt.Sprintf("dtls temporary: %v", e.Err) } -// Timeout implements net.Error.Timeout() +// Timeout implements net.Error.Timeout(). func (*TimeoutError) Timeout() bool { return true } -// Temporary implements net.Error.Temporary() +// Temporary implements net.Error.Temporary(). func (*TimeoutError) Temporary() bool { return true } // Unwrap implements Go1.13 error unwrapper. @@ -85,21 +86,23 @@ func (e *TimeoutError) Unwrap() error { return e.Err } func (e *TimeoutError) Error() string { return fmt.Sprintf("dtls timeout: %v", e.Err) } -// Timeout implements net.Error.Timeout() +// Timeout implements net.Error.Timeout(). func (e *HandshakeError) Timeout() bool { var netErr net.Error if errors.As(e.Err, &netErr) { return netErr.Timeout() } + return false } -// Temporary implements net.Error.Temporary() +// Temporary implements net.Error.Temporary(). func (e *HandshakeError) Temporary() bool { var netErr net.Error if errors.As(e.Err, &netErr) { return netErr.Temporary() //nolint } + return false } diff --git a/pkg/protocol/extension/alpn.go b/pkg/protocol/extension/alpn.go index e780dc9e1..719428601 100644 --- a/pkg/protocol/extension/alpn.go +++ b/pkg/protocol/extension/alpn.go @@ -15,16 +15,16 @@ type ALPN struct { ProtocolNameList []string } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (a ALPN) TypeValue() TypeValue { return ALPNTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (a *ALPN) Marshal() ([]byte, error) { - var b cryptobyte.Builder - b.AddUint16(uint16(a.TypeValue())) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + var builder cryptobyte.Builder + builder.AddUint16(uint16(a.TypeValue())) + builder.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { for _, proto := range a.ProtocolNameList { p := proto // Satisfy range scope lint @@ -34,10 +34,11 @@ func (a *ALPN) Marshal() ([]byte, error) { } }) }) - return b.Bytes() + + return builder.Bytes() } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (a *ALPN) Unmarshal(data []byte) error { val := cryptobyte.String(data) @@ -61,10 +62,11 @@ func (a *ALPN) Unmarshal(data []byte) error { } a.ProtocolNameList = append(a.ProtocolNameList, string(proto)) } + return nil } -// ALPNProtocolSelection negotiates a shared protocol according to #3.2 of rfc7301 +// ALPNProtocolSelection negotiates a shared protocol according to #3.2 of rfc7301. func ALPNProtocolSelection(supportedProtocols, peerSupportedProtocols []string) (string, error) { if len(supportedProtocols) == 0 || len(peerSupportedProtocols) == 0 { return "", nil @@ -76,5 +78,6 @@ func ALPNProtocolSelection(supportedProtocols, peerSupportedProtocols []string) } } } + return "", errALPNNoAppProto } diff --git a/pkg/protocol/extension/alpn_test.go b/pkg/protocol/extension/alpn_test.go index 6b12af0f7..11468fac0 100644 --- a/pkg/protocol/extension/alpn_test.go +++ b/pkg/protocol/extension/alpn_test.go @@ -31,22 +31,22 @@ func TestALPN(t *testing.T) { } func TestALPNProtocolSelection(t *testing.T) { - s, err := ALPNProtocolSelection([]string{"http/1.1", "spd/1"}, []string{"spd/1"}) + selectedProtocol, err := ALPNProtocolSelection([]string{"http/1.1", "spd/1"}, []string{"spd/1"}) if err != nil { t.Fatal(err) } - if s != "spd/1" { - t.Errorf("expected: spd/1, got: %v", s) + if selectedProtocol != "spd/1" { + t.Errorf("expected: spd/1, got: %v", selectedProtocol) } _, err = ALPNProtocolSelection([]string{"http/1.1"}, []string{"spd/1"}) if !errors.Is(err, errALPNNoAppProto) { t.Fatal("expected to fail negotiating an application protocol") } - s, err = ALPNProtocolSelection([]string{"http/1.1", "spd/1"}, []string{}) + selectedProtocol, err = ALPNProtocolSelection([]string{"http/1.1", "spd/1"}, []string{}) if err != nil { t.Fatal(err) } - if s != "" { - t.Errorf("expected not to negotiate a protocol, got: %v", s) + if selectedProtocol != "" { + t.Errorf("expected not to negotiate a protocol, got: %v", selectedProtocol) } } diff --git a/pkg/protocol/extension/connection_id.go b/pkg/protocol/extension/connection_id.go index b3fe1640f..6c8a7f566 100644 --- a/pkg/protocol/extension/connection_id.go +++ b/pkg/protocol/extension/connection_id.go @@ -18,12 +18,12 @@ type ConnectionID struct { CID []byte // variable length } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (c ConnectionID) TypeValue() TypeValue { return ConnectionIDTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (c *ConnectionID) Marshal() ([]byte, error) { var b cryptobyte.Builder b.AddUint16(uint16(c.TypeValue())) @@ -32,10 +32,11 @@ func (c *ConnectionID) Marshal() ([]byte, error) { b.AddBytes(c.CID) }) }) + return b.Bytes() } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (c *ConnectionID) Unmarshal(data []byte) error { val := cryptobyte.String(data) var extension uint16 @@ -55,5 +56,6 @@ func (c *ConnectionID) Unmarshal(data []byte) error { if !cid.CopyBytes(c.CID) { return errInvalidCIDFormat } + return nil } diff --git a/pkg/protocol/extension/errors.go b/pkg/protocol/extension/errors.go index 5999c96fe..424ae5b1a 100644 --- a/pkg/protocol/extension/errors.go +++ b/pkg/protocol/extension/errors.go @@ -10,13 +10,29 @@ import ( ) var ( - // ErrALPNInvalidFormat is raised when the ALPN format is invalid - ErrALPNInvalidFormat = &protocol.FatalError{Err: errors.New("invalid alpn format")} //nolint:goerr113 - errALPNNoAppProto = &protocol.FatalError{Err: errors.New("no application protocol")} //nolint:goerr113 - errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 - errInvalidExtensionType = &protocol.FatalError{Err: errors.New("invalid extension type")} //nolint:goerr113 - errInvalidSNIFormat = &protocol.FatalError{Err: errors.New("invalid server name format")} //nolint:goerr113 - errInvalidCIDFormat = &protocol.FatalError{Err: errors.New("invalid connection ID format")} //nolint:goerr113 - errLengthMismatch = &protocol.InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113 - errMasterKeyIdentifierTooLarge = &protocol.FatalError{Err: errors.New("master key identifier is over 255 bytes")} //nolint:goerr113 + // ErrALPNInvalidFormat is raised when the ALPN format is invalid. + ErrALPNInvalidFormat = &protocol.FatalError{ + Err: errors.New("invalid alpn format"), //nolint:goerr113 + } + errALPNNoAppProto = &protocol.FatalError{ + Err: errors.New("no application protocol"), //nolint:goerr113 + } + errBufferTooSmall = &protocol.TemporaryError{ + Err: errors.New("buffer is too small"), //nolint:goerr113 + } + errInvalidExtensionType = &protocol.FatalError{ + Err: errors.New("invalid extension type"), //nolint:goerr113 + } + errInvalidSNIFormat = &protocol.FatalError{ + Err: errors.New("invalid server name format"), //nolint:goerr113 + } + errInvalidCIDFormat = &protocol.FatalError{ + Err: errors.New("invalid connection ID format"), //nolint:goerr113 + } + errLengthMismatch = &protocol.InternalError{ + Err: errors.New("data length and declared length do not match"), //nolint:goerr113 + } + errMasterKeyIdentifierTooLarge = &protocol.FatalError{ + Err: errors.New("master key identifier is over 255 bytes"), //nolint:goerr113 + } ) diff --git a/pkg/protocol/extension/extension.go b/pkg/protocol/extension/extension.go index e4df859f8..ba82beea3 100644 --- a/pkg/protocol/extension/extension.go +++ b/pkg/protocol/extension/extension.go @@ -11,7 +11,7 @@ import "encoding/binary" // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml type TypeValue uint16 -// TypeValue constants +// TypeValue constants. const ( ServerNameTypeValue TypeValue = 0 SupportedEllipticCurvesTypeValue TypeValue = 10 @@ -24,15 +24,15 @@ const ( RenegotiationInfoTypeValue TypeValue = 65281 ) -// Extension represents a single TLS extension +// Extension represents a single TLS extension. type Extension interface { Marshal() ([]byte, error) Unmarshal(data []byte) error TypeValue() TypeValue } -// Unmarshal many extensions at once -func Unmarshal(buf []byte) ([]Extension, error) { +// Unmarshal many extensions at once. +func Unmarshal(buf []byte) ([]Extension, error) { //nolint:cyclop switch { case len(buf) == 0: return []Extension{}, nil @@ -52,6 +52,7 @@ func Unmarshal(buf []byte) ([]Extension, error) { return err } extensions = append(extensions, e) + return nil } @@ -90,10 +91,11 @@ func Unmarshal(buf []byte) ([]Extension, error) { extensionLength := binary.BigEndian.Uint16(buf[offset+2:]) offset += (4 + int(extensionLength)) } + return extensions, nil } -// Marshal many extensions at once +// Marshal many extensions at once. func Marshal(e []Extension) ([]byte, error) { extensions := []byte{} for _, e := range e { @@ -104,6 +106,7 @@ func Marshal(e []Extension) ([]byte, error) { extensions = append(extensions, raw...) } out := []byte{0x00, 0x00} - binary.BigEndian.PutUint16(out, uint16(len(extensions))) + binary.BigEndian.PutUint16(out, uint16(len(extensions))) //nolint:gosec // G115 + return append(out, extensions...), nil } diff --git a/pkg/protocol/extension/renegotiation_info.go b/pkg/protocol/extension/renegotiation_info.go index c5092a7db..57432fd0b 100644 --- a/pkg/protocol/extension/renegotiation_info.go +++ b/pkg/protocol/extension/renegotiation_info.go @@ -17,22 +17,23 @@ type RenegotiationInfo struct { RenegotiatedConnection uint8 } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (r RenegotiationInfo) TypeValue() TypeValue { return RenegotiationInfoTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (r *RenegotiationInfo) Marshal() ([]byte, error) { out := make([]byte, renegotiationInfoHeaderSize) binary.BigEndian.PutUint16(out, uint16(r.TypeValue())) binary.BigEndian.PutUint16(out[2:], uint16(1)) // length out[4] = r.RenegotiatedConnection + return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (r *RenegotiationInfo) Unmarshal(data []byte) error { if len(data) < renegotiationInfoHeaderSize { return errBufferTooSmall diff --git a/pkg/protocol/extension/renegotiation_info_test.go b/pkg/protocol/extension/renegotiation_info_test.go index 63b9609d1..252144332 100644 --- a/pkg/protocol/extension/renegotiation_info_test.go +++ b/pkg/protocol/extension/renegotiation_info_test.go @@ -20,6 +20,9 @@ func TestRenegotiationInfo(t *testing.T) { } if newExtension.RenegotiatedConnection != extension.RenegotiatedConnection { - t.Errorf("extensionRenegotiationInfo marshal: got %d expected %d", newExtension.RenegotiatedConnection, extension.RenegotiatedConnection) + t.Errorf( + "extensionRenegotiationInfo marshal: got %d expected %d", + newExtension.RenegotiatedConnection, extension.RenegotiatedConnection, + ) } } diff --git a/pkg/protocol/extension/server_name.go b/pkg/protocol/extension/server_name.go index 183e08e6e..31e6327d3 100644 --- a/pkg/protocol/extension/server_name.go +++ b/pkg/protocol/extension/server_name.go @@ -20,12 +20,12 @@ type ServerName struct { ServerName string } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (s ServerName) TypeValue() TypeValue { return ServerNameTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (s *ServerName) Marshal() ([]byte, error) { var b cryptobyte.Builder b.AddUint16(uint16(s.TypeValue())) @@ -37,11 +37,12 @@ func (s *ServerName) Marshal() ([]byte, error) { }) }) }) + return b.Bytes() } -// Unmarshal populates the extension from encoded data -func (s *ServerName) Unmarshal(data []byte) error { +// Unmarshal populates the extension from encoded data. +func (s *ServerName) Unmarshal(data []byte) error { //nolint:cyclop val := cryptobyte.String(data) var extension uint16 val.ReadUint16(&extension) @@ -77,5 +78,6 @@ func (s *ServerName) Unmarshal(data []byte) error { return errInvalidSNIFormat } } + return nil } diff --git a/pkg/protocol/extension/supported_elliptic_curves.go b/pkg/protocol/extension/supported_elliptic_curves.go index e83b5ccb8..e3e87634b 100644 --- a/pkg/protocol/extension/supported_elliptic_curves.go +++ b/pkg/protocol/extension/supported_elliptic_curves.go @@ -21,28 +21,28 @@ type SupportedEllipticCurves struct { EllipticCurves []elliptic.Curve } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (s SupportedEllipticCurves) TypeValue() TypeValue { return SupportedEllipticCurvesTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (s *SupportedEllipticCurves) Marshal() ([]byte, error) { out := make([]byte, supportedGroupsHeaderSize) binary.BigEndian.PutUint16(out, uint16(s.TypeValue())) - binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.EllipticCurves)*2))) - binary.BigEndian.PutUint16(out[4:], uint16(len(s.EllipticCurves)*2)) + binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.EllipticCurves)*2))) //nolint:gosec // G115 + binary.BigEndian.PutUint16(out[4:], uint16(len(s.EllipticCurves)*2)) //nolint:gosec // G115 for _, v := range s.EllipticCurves { - out = append(out, []byte{0x00, 0x00}...) + out = append(out, []byte{0x00, 0x00}...) //nolint:makezero // todo: fix binary.BigEndian.PutUint16(out[len(out)-2:], uint16(v)) } return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (s *SupportedEllipticCurves) Unmarshal(data []byte) error { if len(data) <= supportedGroupsHeaderSize { return errBufferTooSmall @@ -61,5 +61,6 @@ func (s *SupportedEllipticCurves) Unmarshal(data []byte) error { s.EllipticCurves = append(s.EllipticCurves, supportedGroupID) } } + return nil } diff --git a/pkg/protocol/extension/supported_point_formats.go b/pkg/protocol/extension/supported_point_formats.go index ec877aff2..77dc4fd50 100644 --- a/pkg/protocol/extension/supported_point_formats.go +++ b/pkg/protocol/extension/supported_point_formats.go @@ -21,26 +21,27 @@ type SupportedPointFormats struct { PointFormats []elliptic.CurvePointFormat } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (s SupportedPointFormats) TypeValue() TypeValue { return SupportedPointFormatsTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (s *SupportedPointFormats) Marshal() ([]byte, error) { out := make([]byte, supportedPointFormatsSize) binary.BigEndian.PutUint16(out, uint16(s.TypeValue())) - binary.BigEndian.PutUint16(out[2:], uint16(1+(len(s.PointFormats)))) + binary.BigEndian.PutUint16(out[2:], uint16(1+(len(s.PointFormats)))) //nolint:gosec // G115 out[4] = byte(len(s.PointFormats)) for _, v := range s.PointFormats { - out = append(out, byte(v)) + out = append(out, byte(v)) //nolint:makezero // todo: fix } + return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (s *SupportedPointFormats) Unmarshal(data []byte) error { if len(data) <= supportedPointFormatsSize { return errBufferTooSmall @@ -63,5 +64,6 @@ func (s *SupportedPointFormats) Unmarshal(data []byte) error { default: } } + return nil } diff --git a/pkg/protocol/extension/supported_point_formats_test.go b/pkg/protocol/extension/supported_point_formats_test.go index eecbd5c82..f57bdd0ca 100644 --- a/pkg/protocol/extension/supported_point_formats_test.go +++ b/pkg/protocol/extension/supported_point_formats_test.go @@ -27,6 +27,9 @@ func TestExtensionSupportedPointFormats(t *testing.T) { if err := roundtrip.Unmarshal(raw); err != nil { t.Error(err) } else if !reflect.DeepEqual(roundtrip, parsedExtensionSupportedPointFormats) { - t.Errorf("extensionSupportedPointFormats unmarshal: got %#v, want %#v", roundtrip, parsedExtensionSupportedPointFormats) + t.Errorf( + "extensionSupportedPointFormats unmarshal: got %#v, want %#v", + roundtrip, parsedExtensionSupportedPointFormats, + ) } } diff --git a/pkg/protocol/extension/supported_signature_algorithms.go b/pkg/protocol/extension/supported_signature_algorithms.go index 396b9ae38..e7ad0d422 100644 --- a/pkg/protocol/extension/supported_signature_algorithms.go +++ b/pkg/protocol/extension/supported_signature_algorithms.go @@ -23,20 +23,20 @@ type SupportedSignatureAlgorithms struct { SignatureHashAlgorithms []signaturehash.Algorithm } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (s SupportedSignatureAlgorithms) TypeValue() TypeValue { return SupportedSignatureAlgorithmsTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (s *SupportedSignatureAlgorithms) Marshal() ([]byte, error) { out := make([]byte, supportedSignatureAlgorithmsHeaderSize) binary.BigEndian.PutUint16(out, uint16(s.TypeValue())) - binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.SignatureHashAlgorithms)*2))) - binary.BigEndian.PutUint16(out[4:], uint16(len(s.SignatureHashAlgorithms)*2)) + binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.SignatureHashAlgorithms)*2))) //nolint:gosec // G115 + binary.BigEndian.PutUint16(out[4:], uint16(len(s.SignatureHashAlgorithms)*2)) //nolint:gosec // G115 for _, v := range s.SignatureHashAlgorithms { - out = append(out, []byte{0x00, 0x00}...) + out = append(out, []byte{0x00, 0x00}...) //nolint:makezero // todo: fix out[len(out)-2] = byte(v.Hash) out[len(out)-1] = byte(v.Signature) } @@ -44,7 +44,7 @@ func (s *SupportedSignatureAlgorithms) Marshal() ([]byte, error) { return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (s *SupportedSignatureAlgorithms) Unmarshal(data []byte) error { if len(data) <= supportedSignatureAlgorithmsHeaderSize { return errBufferTooSmall diff --git a/pkg/protocol/extension/supported_signature_algorithms_test.go b/pkg/protocol/extension/supported_signature_algorithms_test.go index 80b5692e3..653d4b558 100644 --- a/pkg/protocol/extension/supported_signature_algorithms_test.go +++ b/pkg/protocol/extension/supported_signature_algorithms_test.go @@ -33,13 +33,19 @@ func TestExtensionSupportedSignatureAlgorithms(t *testing.T) { if err != nil { t.Fatal(err) } else if !reflect.DeepEqual(raw, rawExtensionSupportedSignatureAlgorithms) { - t.Fatalf("extensionSupportedSignatureAlgorithms marshal: got %#v, want %#v", raw, rawExtensionSupportedSignatureAlgorithms) + t.Fatalf( + "extensionSupportedSignatureAlgorithms marshal: got %#v, want %#v", + raw, rawExtensionSupportedSignatureAlgorithms, + ) } roundtrip := &SupportedSignatureAlgorithms{} if err := roundtrip.Unmarshal(raw); err != nil { t.Error(err) } else if !reflect.DeepEqual(roundtrip, parsedExtensionSupportedSignatureAlgorithms) { - t.Errorf("extensionSupportedSignatureAlgorithms unmarshal: got %#v, want %#v", roundtrip, parsedExtensionSupportedSignatureAlgorithms) + t.Errorf( + "extensionSupportedSignatureAlgorithms unmarshal: got %#v, want %#v", + roundtrip, parsedExtensionSupportedSignatureAlgorithms, + ) } } diff --git a/pkg/protocol/extension/use_master_secret.go b/pkg/protocol/extension/use_master_secret.go index d0b70cafb..fcf5dd289 100644 --- a/pkg/protocol/extension/use_master_secret.go +++ b/pkg/protocol/extension/use_master_secret.go @@ -16,12 +16,12 @@ type UseExtendedMasterSecret struct { Supported bool } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (u UseExtendedMasterSecret) TypeValue() TypeValue { return UseExtendedMasterSecretTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (u *UseExtendedMasterSecret) Marshal() ([]byte, error) { if !u.Supported { return []byte{}, nil @@ -31,10 +31,11 @@ func (u *UseExtendedMasterSecret) Marshal() ([]byte, error) { binary.BigEndian.PutUint16(out, uint16(u.TypeValue())) binary.BigEndian.PutUint16(out[2:], uint16(0)) // length + return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (u *UseExtendedMasterSecret) Unmarshal(data []byte) error { if len(data) < useExtendedMasterSecretHeaderSize { return errBufferTooSmall diff --git a/pkg/protocol/extension/use_srtp.go b/pkg/protocol/extension/use_srtp.go index 6d5f54b23..4e0410cae 100644 --- a/pkg/protocol/extension/use_srtp.go +++ b/pkg/protocol/extension/use_srtp.go @@ -20,34 +20,38 @@ type UseSRTP struct { MasterKeyIdentifier []byte } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (u UseSRTP) TypeValue() TypeValue { return UseSRTPTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (u *UseSRTP) Marshal() ([]byte, error) { out := make([]byte, useSRTPHeaderSize) binary.BigEndian.PutUint16(out, uint16(u.TypeValue())) - binary.BigEndian.PutUint16(out[2:], uint16(2+(len(u.ProtectionProfiles)*2)+ /* MKI Length */ 1+len(u.MasterKeyIdentifier))) - binary.BigEndian.PutUint16(out[4:], uint16(len(u.ProtectionProfiles)*2)) + //nolint:gosec // G115 + binary.BigEndian.PutUint16( + out[2:], + uint16(2+(len(u.ProtectionProfiles)*2)+ /* MKI Length */ 1+len(u.MasterKeyIdentifier)), + ) + binary.BigEndian.PutUint16(out[4:], uint16(len(u.ProtectionProfiles)*2)) //nolint:gosec // G115 for _, v := range u.ProtectionProfiles { - out = append(out, []byte{0x00, 0x00}...) + out = append(out, []byte{0x00, 0x00}...) //nolint:makezero // todo: fix binary.BigEndian.PutUint16(out[len(out)-2:], uint16(v)) } if len(u.MasterKeyIdentifier) > 255 { return nil, errMasterKeyIdentifierTooLarge } - out = append(out, byte(len(u.MasterKeyIdentifier))) - out = append(out, u.MasterKeyIdentifier...) + out = append(out, byte(len(u.MasterKeyIdentifier))) //nolint:makezero // todo: fix + out = append(out, u.MasterKeyIdentifier...) //nolint:makezero // todo: fix return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (u *UseSRTP) Unmarshal(data []byte) error { if len(data) <= useSRTPHeaderSize { return errBufferTooSmall @@ -73,7 +77,10 @@ func (u *UseSRTP) Unmarshal(data []byte) error { return errLengthMismatch } - u.MasterKeyIdentifier = append([]byte{}, data[masterKeyIdentifierIndex+1:masterKeyIdentifierIndex+1+masterKeyIdentifierLen]...) + u.MasterKeyIdentifier = append( + []byte{}, + data[masterKeyIdentifierIndex+1:masterKeyIdentifierIndex+1+masterKeyIdentifierLen]..., + ) return nil } diff --git a/pkg/protocol/extension/use_srtp_test.go b/pkg/protocol/extension/use_srtp_test.go index 36e284cd4..c88c61c15 100644 --- a/pkg/protocol/extension/use_srtp_test.go +++ b/pkg/protocol/extension/use_srtp_test.go @@ -9,7 +9,7 @@ import ( "testing" ) -func TestExtensionUseSRTP(t *testing.T) { +func TestExtensionUseSRTP(t *testing.T) { //nolint:cyclop t.Run("No MasterKeyIdentifier", func(t *testing.T) { rawUseSRTP := []byte{0x00, 0x0e, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00} parsedUseSRTP := &UseSRTP{ @@ -57,11 +57,15 @@ func TestExtensionUseSRTP(t *testing.T) { t.Run("Invalid Lengths", func(t *testing.T) { unmarshaled := &UseSRTP{} - if err := unmarshaled.Unmarshal([]byte{0x00, 0x0e, 0x00, 0x05, 0x00, 0x04, 0x00, 0x01, 0x00}); !errors.Is(errLengthMismatch, err) { + if err := unmarshaled.Unmarshal( + []byte{0x00, 0x0e, 0x00, 0x05, 0x00, 0x04, 0x00, 0x01, 0x00}, + ); !errors.Is(errLengthMismatch, err) { t.Error(err) } - if err := unmarshaled.Unmarshal([]byte{0x00, 0x0e, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x01, 0x01}); !errors.Is(errLengthMismatch, err) { + if err := unmarshaled.Unmarshal( + []byte{0x00, 0x0e, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x01, 0x01}, + ); !errors.Is(errLengthMismatch, err) { t.Error(err) } diff --git a/pkg/protocol/handshake/cipher_suite.go b/pkg/protocol/handshake/cipher_suite.go index b29629717..49d2b7407 100644 --- a/pkg/protocol/handshake/cipher_suite.go +++ b/pkg/protocol/handshake/cipher_suite.go @@ -18,15 +18,17 @@ func decodeCipherSuiteIDs(buf []byte) ([]uint16, error) { rtrn[i] = binary.BigEndian.Uint16(buf[(i*2)+2:]) } + return rtrn, nil } func encodeCipherSuiteIDs(cipherSuiteIDs []uint16) []byte { out := []byte{0x00, 0x00} - binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(cipherSuiteIDs)*2)) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(cipherSuiteIDs)*2)) //nolint:gosec // G115 for _, id := range cipherSuiteIDs { out = append(out, []byte{0x00, 0x00}...) binary.BigEndian.PutUint16(out[len(out)-2:], id) } + return out } diff --git a/pkg/protocol/handshake/errors.go b/pkg/protocol/handshake/errors.go index 4f007198f..20794f78c 100644 --- a/pkg/protocol/handshake/errors.go +++ b/pkg/protocol/handshake/errors.go @@ -9,20 +9,48 @@ import ( "github.com/pion/dtls/v3/pkg/protocol" ) -// Typed errors +// Typed errors. var ( - errUnableToMarshalFragmented = &protocol.InternalError{Err: errors.New("unable to marshal fragmented handshakes")} //nolint:goerr113 - errHandshakeMessageUnset = &protocol.InternalError{Err: errors.New("handshake message unset, unable to marshal")} //nolint:goerr113 - errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 - errLengthMismatch = &protocol.InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113 - errInvalidClientKeyExchange = &protocol.FatalError{Err: errors.New("unable to determine if ClientKeyExchange is a public key or PSK Identity")} //nolint:goerr113 - errInvalidHashAlgorithm = &protocol.FatalError{Err: errors.New("invalid hash algorithm")} //nolint:goerr113 - errInvalidSignatureAlgorithm = &protocol.FatalError{Err: errors.New("invalid signature algorithm")} //nolint:goerr113 - errCookieTooLong = &protocol.FatalError{Err: errors.New("cookie must not be longer then 255 bytes")} //nolint:goerr113 - errInvalidEllipticCurveType = &protocol.FatalError{Err: errors.New("invalid or unknown elliptic curve type")} //nolint:goerr113 - errInvalidNamedCurve = &protocol.FatalError{Err: errors.New("invalid named curve")} //nolint:goerr113 - errCipherSuiteUnset = &protocol.FatalError{Err: errors.New("server hello can not be created without a cipher suite")} //nolint:goerr113 - errCompressionMethodUnset = &protocol.FatalError{Err: errors.New("server hello can not be created without a compression method")} //nolint:goerr113 - errInvalidCompressionMethod = &protocol.FatalError{Err: errors.New("invalid or unknown compression method")} //nolint:goerr113 - errNotImplemented = &protocol.InternalError{Err: errors.New("feature has not been implemented yet")} //nolint:goerr113 + errUnableToMarshalFragmented = &protocol.InternalError{ + Err: errors.New("unable to marshal fragmented handshakes"), //nolint:err113 + } + errHandshakeMessageUnset = &protocol.InternalError{ + Err: errors.New("handshake message unset, unable to marshal"), //nolint:err113 + } + errBufferTooSmall = &protocol.TemporaryError{ + Err: errors.New("buffer is too small"), //nolint:err113 + } + errLengthMismatch = &protocol.InternalError{ + Err: errors.New("data length and declared length do not match"), //nolint:err113 + } + errInvalidClientKeyExchange = &protocol.FatalError{ + Err: errors.New("unable to determine if ClientKeyExchange is a public key or PSK Identity"), //nolint:err113 + } + errInvalidHashAlgorithm = &protocol.FatalError{ + Err: errors.New("invalid hash algorithm"), //nolint:err113 + } + errInvalidSignatureAlgorithm = &protocol.FatalError{ + Err: errors.New("invalid signature algorithm"), //nolint:err113 + } + errCookieTooLong = &protocol.FatalError{ + Err: errors.New("cookie must not be longer then 255 bytes"), //nolint:err113 + } + errInvalidEllipticCurveType = &protocol.FatalError{ + Err: errors.New("invalid or unknown elliptic curve type"), //nolint:err113 + } + errInvalidNamedCurve = &protocol.FatalError{ + Err: errors.New("invalid named curve"), //nolint:err113 + } + errCipherSuiteUnset = &protocol.FatalError{ + Err: errors.New("server hello can not be created without a cipher suite"), //nolint:err113 + } + errCompressionMethodUnset = &protocol.FatalError{ + Err: errors.New("server hello can not be created without a compression method"), //nolint:err113 + } + errInvalidCompressionMethod = &protocol.FatalError{ + Err: errors.New("invalid or unknown compression method"), //nolint:err113 + } + errNotImplemented = &protocol.InternalError{ + Err: errors.New("feature has not been implemented yet"), //nolint:err113 + } ) diff --git a/pkg/protocol/handshake/handshake.go b/pkg/protocol/handshake/handshake.go index 6f0eb9c71..9c6187711 100644 --- a/pkg/protocol/handshake/handshake.go +++ b/pkg/protocol/handshake/handshake.go @@ -14,7 +14,7 @@ import ( // https://tools.ietf.org/html/rfc5246#section-7.4 type Type uint8 -// Types of DTLS Handshake messages we know about +// Types of DTLS Handshake messages we know about. const ( TypeHelloRequest Type = 0 TypeClientHello Type = 1 @@ -29,8 +29,8 @@ const ( TypeFinished Type = 20 ) -// String returns the string representation of this type -func (t Type) String() string { +// String returns the string representation of this type. +func (t Type) String() string { //nolint:cyclop switch t { case TypeHelloRequest: return "HelloRequest" @@ -55,10 +55,11 @@ func (t Type) String() string { case TypeFinished: return "Finished" } + return "" } -// Message is the body of a Handshake datagram +// Message is the body of a Handshake datagram. type Message interface { Marshal() ([]byte, error) Unmarshal(data []byte) error @@ -78,12 +79,12 @@ type Handshake struct { KeyExchangeAlgorithm types.KeyExchangeAlgorithm } -// ContentType returns what kind of content this message is carying +// ContentType returns what kind of content this message is carying. func (h Handshake) ContentType() protocol.ContentType { return protocol.ContentTypeHandshake } -// Marshal encodes a handshake into a binary message +// Marshal encodes a handshake into a binary message. func (h *Handshake) Marshal() ([]byte, error) { if h.Message == nil { return nil, errHandshakeMessageUnset @@ -96,7 +97,7 @@ func (h *Handshake) Marshal() ([]byte, error) { return nil, err } - h.Header.Length = uint32(len(msg)) + h.Header.Length = uint32(len(msg)) //nolint:gosec // G115 h.Header.FragmentLength = h.Header.Length h.Header.Type = h.Message.Type() header, err := h.Header.Marshal() @@ -107,14 +108,14 @@ func (h *Handshake) Marshal() ([]byte, error) { return append(header, msg...), nil } -// Unmarshal decodes a handshake from a binary message -func (h *Handshake) Unmarshal(data []byte) error { +// Unmarshal decodes a handshake from a binary message. +func (h *Handshake) Unmarshal(data []byte) error { //nolint:cyclop if err := h.Header.Unmarshal(data); err != nil { return err } reportedLen := util.BigEndianUint24(data[1:]) - if uint32(len(data)-HeaderLength) != reportedLen { + if uint32(len(data)-HeaderLength) != reportedLen { //nolint:gosec // G115 return errLengthMismatch } else if reportedLen != h.Header.FragmentLength { return errLengthMismatch @@ -146,5 +147,6 @@ func (h *Handshake) Unmarshal(data []byte) error { default: return errNotImplemented } + return h.Message.Unmarshal(data[HeaderLength:]) } diff --git a/pkg/protocol/handshake/header.go b/pkg/protocol/handshake/header.go index 619fd2bdb..4e909de54 100644 --- a/pkg/protocol/handshake/header.go +++ b/pkg/protocol/handshake/header.go @@ -10,7 +10,7 @@ import ( ) // HeaderLength msg_len for Handshake messages assumes an extra -// 12 bytes for sequence, fragment and version information vs TLS +// 12 bytes for sequence, fragment and version information vs TLS. const HeaderLength = 12 // Header is the static first 12 bytes of each RecordLayer @@ -26,7 +26,7 @@ type Header struct { FragmentLength uint32 // uint24 in spec } -// Marshal encodes the Header +// Marshal encodes the Header. func (h *Header) Marshal() ([]byte, error) { out := make([]byte, HeaderLength) @@ -35,10 +35,11 @@ func (h *Header) Marshal() ([]byte, error) { binary.BigEndian.PutUint16(out[4:], h.MessageSequence) util.PutBigEndianUint24(out[6:], h.FragmentOffset) util.PutBigEndianUint24(out[9:], h.FragmentLength) + return out, nil } -// Unmarshal populates the header from encoded data +// Unmarshal populates the header from encoded data. func (h *Header) Unmarshal(data []byte) error { if len(data) < HeaderLength { return errBufferTooSmall @@ -49,5 +50,6 @@ func (h *Header) Unmarshal(data []byte) error { h.MessageSequence = binary.BigEndian.Uint16(data[4:]) h.FragmentOffset = util.BigEndianUint24(data[6:]) h.FragmentLength = util.BigEndianUint24(data[9:]) + return nil } diff --git a/pkg/protocol/handshake/message_certificate.go b/pkg/protocol/handshake/message_certificate.go index 54b0bfddb..27d2ea99a 100644 --- a/pkg/protocol/handshake/message_certificate.go +++ b/pkg/protocol/handshake/message_certificate.go @@ -15,7 +15,7 @@ type MessageCertificate struct { Certificate [][]byte } -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageCertificate) Type() Type { return TypeCertificate } @@ -24,31 +24,36 @@ const ( handshakeMessageCertificateLengthFieldSize = 3 ) -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageCertificate) Marshal() ([]byte, error) { out := make([]byte, handshakeMessageCertificateLengthFieldSize) for _, r := range m.Certificate { // Certificate Length + //nolint:makezero // todo: fix out = append(out, make([]byte, handshakeMessageCertificateLengthFieldSize)...) + //nolint:gosec // G115 util.PutBigEndianUint24(out[len(out)-handshakeMessageCertificateLengthFieldSize:], uint32(len(r))) // Certificate body - out = append(out, append([]byte{}, r...)...) + out = append(out, append([]byte{}, r...)...) //nolint:makezero // todo: fix } // Total Payload Size - util.PutBigEndianUint24(out[0:], uint32(len(out[handshakeMessageCertificateLengthFieldSize:]))) + util.PutBigEndianUint24(out[0:], uint32(len(out[handshakeMessageCertificateLengthFieldSize:]))) //nolint:gosec //G115 + return out, nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageCertificate) Unmarshal(data []byte) error { if len(data) < handshakeMessageCertificateLengthFieldSize { return errBufferTooSmall } - if certificateBodyLen := int(util.BigEndianUint24(data)); certificateBodyLen+handshakeMessageCertificateLengthFieldSize != len(data) { + if certificateBodyLen := int(util.BigEndianUint24( + data, + )); certificateBodyLen+handshakeMessageCertificateLengthFieldSize != len(data) { return errLengthMismatch } diff --git a/pkg/protocol/handshake/message_certificate_request.go b/pkg/protocol/handshake/message_certificate_request.go index 5c3ac63c5..28dabf35a 100644 --- a/pkg/protocol/handshake/message_certificate_request.go +++ b/pkg/protocol/handshake/message_certificate_request.go @@ -31,12 +31,12 @@ const ( messageCertificateRequestMinLength = 5 ) -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageCertificateRequest) Type() Type { return TypeCertificateRequest } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageCertificateRequest) Marshal() ([]byte, error) { out := []byte{byte(len(m.CertificateTypes))} for _, v := range m.CertificateTypes { @@ -44,7 +44,7 @@ func (m *MessageCertificateRequest) Marshal() ([]byte, error) { } out = append(out, []byte{0x00, 0x00}...) - binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.SignatureHashAlgorithms)*2)) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.SignatureHashAlgorithms)*2)) //nolint:gosec //G115 for _, v := range m.SignatureHashAlgorithms { out = append(out, byte(v.Hash)) out = append(out, byte(v.Signature)) @@ -56,19 +56,20 @@ func (m *MessageCertificateRequest) Marshal() ([]byte, error) { casLength += len(ca) + 2 } out = append(out, []byte{0x00, 0x00}...) - binary.BigEndian.PutUint16(out[len(out)-2:], uint16(casLength)) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(casLength)) //nolint:gosec //G115 if casLength > 0 { for _, ca := range m.CertificateAuthoritiesNames { out = append(out, []byte{0x00, 0x00}...) - binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(ca))) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(ca))) //nolint:gosec //G115 out = append(out, ca...) } } + return out, nil } -// Unmarshal populates the message from encoded data -func (m *MessageCertificateRequest) Unmarshal(data []byte) error { +// Unmarshal populates the message from encoded data. +func (m *MessageCertificateRequest) Unmarshal(data []byte) error { //nolint:cyclop if len(data) < messageCertificateRequestMinLength { return errBufferTooSmall } diff --git a/pkg/protocol/handshake/message_certificate_test.go b/pkg/protocol/handshake/message_certificate_test.go index 760d5efdf..8abe42578 100644 --- a/pkg/protocol/handshake/message_certificate_test.go +++ b/pkg/protocol/handshake/message_certificate_test.go @@ -60,21 +60,21 @@ func TestHandshakeMessageCertificate(t *testing.T) { Version: 1, } - c := &MessageCertificate{} - if err := c.Unmarshal(rawCertificate); err != nil { + certMessage := &MessageCertificate{} + if err := certMessage.Unmarshal(rawCertificate); err != nil { t.Error(err) } else { - certificate, err := x509.ParseCertificate(c.Certificate[0]) + certificate, err := x509.ParseCertificate(certMessage.Certificate[0]) if err != nil { t.Error(err) } copyCertificatePrivateMembers(certificate, parsedCertificate) if !reflect.DeepEqual(certificate, parsedCertificate) { - t.Errorf("handshakeMessageCertificate unmarshal: got %#v, want %#v", c, parsedCertificate) + t.Errorf("handshakeMessageCertificate unmarshal: got %#v, want %#v", certMessage, parsedCertificate) } } - raw, err := c.Marshal() + raw, err := certMessage.Marshal() if err != nil { t.Error(err) } else if !reflect.DeepEqual(raw, rawCertificate) { diff --git a/pkg/protocol/handshake/message_certificate_verify.go b/pkg/protocol/handshake/message_certificate_verify.go index 9d09b31ca..d10ffa035 100644 --- a/pkg/protocol/handshake/message_certificate_verify.go +++ b/pkg/protocol/handshake/message_certificate_verify.go @@ -22,23 +22,24 @@ type MessageCertificateVerify struct { const handshakeMessageCertificateVerifyMinLength = 4 -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageCertificateVerify) Type() Type { return TypeCertificateVerify } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageCertificateVerify) Marshal() ([]byte, error) { out := make([]byte, 1+1+2+len(m.Signature)) out[0] = byte(m.HashAlgorithm) out[1] = byte(m.SignatureAlgorithm) - binary.BigEndian.PutUint16(out[2:], uint16(len(m.Signature))) + binary.BigEndian.PutUint16(out[2:], uint16(len(m.Signature))) //nolint:gosec // G115 copy(out[4:], m.Signature) + return out, nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageCertificateVerify) Unmarshal(data []byte) error { if len(data) < handshakeMessageCertificateVerifyMinLength { return errBufferTooSmall @@ -60,5 +61,6 @@ func (m *MessageCertificateVerify) Unmarshal(data []byte) error { } m.Signature = append([]byte{}, data[4:]...) + return nil } diff --git a/pkg/protocol/handshake/message_client_hello.go b/pkg/protocol/handshake/message_client_hello.go index c651718e5..e7aa5e397 100644 --- a/pkg/protocol/handshake/message_client_hello.go +++ b/pkg/protocol/handshake/message_client_hello.go @@ -31,12 +31,12 @@ type MessageClientHello struct { const handshakeMessageClientHelloVariableWidthStart = 34 -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageClientHello) Type() Type { return TypeClientHello } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageClientHello) Marshal() ([]byte, error) { if len(m.Cookie) > 255 { return nil, errCookieTooLong @@ -49,24 +49,24 @@ func (m *MessageClientHello) Marshal() ([]byte, error) { rand := m.Random.MarshalFixed() copy(out[2:], rand[:]) - out = append(out, byte(len(m.SessionID))) - out = append(out, m.SessionID...) + out = append(out, byte(len(m.SessionID))) //nolint:makezero // todo: fix + out = append(out, m.SessionID...) //nolint:makezero // todo: fix - out = append(out, byte(len(m.Cookie))) - out = append(out, m.Cookie...) - out = append(out, encodeCipherSuiteIDs(m.CipherSuiteIDs)...) - out = append(out, protocol.EncodeCompressionMethods(m.CompressionMethods)...) + out = append(out, byte(len(m.Cookie))) //nolint:makezero // todo: fix + out = append(out, m.Cookie...) //nolint:makezero // todo: fix + out = append(out, encodeCipherSuiteIDs(m.CipherSuiteIDs)...) //nolint:makezero // todo: fix + out = append(out, protocol.EncodeCompressionMethods(m.CompressionMethods)...) //nolint:makezero // todo: fix extensions, err := extension.Marshal(m.Extensions) if err != nil { return nil, err } - return append(out, extensions...), nil + return append(out, extensions...), nil //nolint:makezero // todo: fix } -// Unmarshal populates the message from encoded data -func (m *MessageClientHello) Unmarshal(data []byte) error { +// Unmarshal populates the message from encoded data. +func (m *MessageClientHello) Unmarshal(data []byte) error { //nolint:cyclop if len(data) < 2+RandomLength { return errBufferTooSmall } @@ -137,5 +137,6 @@ func (m *MessageClientHello) Unmarshal(data []byte) error { return err } m.Extensions = extensions + return nil } diff --git a/pkg/protocol/handshake/message_client_hello_test.go b/pkg/protocol/handshake/message_client_hello_test.go index d46567691..f32fe1dff 100644 --- a/pkg/protocol/handshake/message_client_hello_test.go +++ b/pkg/protocol/handshake/message_client_hello_test.go @@ -26,10 +26,16 @@ func TestHandshakeMessageClientHello(t *testing.T) { Version: protocol.Version{Major: 0xFE, Minor: 0xFD}, Random: Random{ GMTUnixTime: time.Unix(3056586332, 0), - RandomBytes: [28]byte{0x42, 0x54, 0xff, 0x86, 0xe1, 0x24, 0x41, 0x91, 0x42, 0x62, 0x15, 0xad, 0x16, 0xc9, 0x15, 0x8d, 0x95, 0x71, 0x8a, 0xbb, 0x22, 0xd7, 0x47, 0xec, 0xd8, 0x3d, 0xdc, 0x4b}, + RandomBytes: [28]byte{ + 0x42, 0x54, 0xff, 0x86, 0xe1, 0x24, 0x41, 0x91, 0x42, 0x62, 0x15, 0xad, 0x16, 0xc9, + 0x15, 0x8d, 0x95, 0x71, 0x8a, 0xbb, 0x22, 0xd7, 0x47, 0xec, 0xd8, 0x3d, 0xdc, 0x4b, + }, }, SessionID: []byte{}, - Cookie: []byte{0xe6, 0x14, 0x3a, 0x1b, 0x04, 0xea, 0x9e, 0x7a, 0x14, 0xd6, 0x6c, 0x57, 0xd0, 0x0e, 0x32, 0x85, 0x76, 0x18, 0xde, 0xd8}, + Cookie: []byte{ + 0xe6, 0x14, 0x3a, 0x1b, 0x04, 0xea, 0x9e, 0x7a, 0x14, 0xd6, + 0x6c, 0x57, 0xd0, 0x0e, 0x32, 0x85, 0x76, 0x18, 0xde, 0xd8, + }, CipherSuiteIDs: []uint16{ 0xc02b, 0xc00a, diff --git a/pkg/protocol/handshake/message_client_key_exchange.go b/pkg/protocol/handshake/message_client_key_exchange.go index 626361c6c..60361a94a 100644 --- a/pkg/protocol/handshake/message_client_key_exchange.go +++ b/pkg/protocol/handshake/message_client_key_exchange.go @@ -24,12 +24,12 @@ type MessageClientKeyExchange struct { KeyExchangeAlgorithm types.KeyExchangeAlgorithm } -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageClientKeyExchange) Type() Type { return TypeClientKeyExchange } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageClientKeyExchange) Marshal() (out []byte, err error) { if m.IdentityHint == nil && m.PublicKey == nil { return nil, errInvalidClientKeyExchange @@ -37,7 +37,7 @@ func (m *MessageClientKeyExchange) Marshal() (out []byte, err error) { if m.IdentityHint != nil { out = append([]byte{0x00, 0x00}, m.IdentityHint...) - binary.BigEndian.PutUint16(out, uint16(len(out)-2)) + binary.BigEndian.PutUint16(out, uint16(len(out)-2)) //nolint:gosec // G115 } if m.PublicKey != nil { @@ -48,7 +48,7 @@ func (m *MessageClientKeyExchange) Marshal() (out []byte, err error) { return out, nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageClientKeyExchange) Unmarshal(data []byte) error { switch { case len(data) < 2: diff --git a/pkg/protocol/handshake/message_finished.go b/pkg/protocol/handshake/message_finished.go index 255aedd7e..f7187d88a 100644 --- a/pkg/protocol/handshake/message_finished.go +++ b/pkg/protocol/handshake/message_finished.go @@ -13,18 +13,19 @@ type MessageFinished struct { VerifyData []byte } -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageFinished) Type() Type { return TypeFinished } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageFinished) Marshal() ([]byte, error) { return append([]byte{}, m.VerifyData...), nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageFinished) Unmarshal(data []byte) error { m.VerifyData = append([]byte{}, data...) + return nil } diff --git a/pkg/protocol/handshake/message_hello_verify_request.go b/pkg/protocol/handshake/message_hello_verify_request.go index 98960400c..7f5bc95aa 100644 --- a/pkg/protocol/handshake/message_hello_verify_request.go +++ b/pkg/protocol/handshake/message_hello_verify_request.go @@ -27,12 +27,12 @@ type MessageHelloVerifyRequest struct { Cookie []byte } -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageHelloVerifyRequest) Type() Type { return TypeHelloVerifyRequest } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageHelloVerifyRequest) Marshal() ([]byte, error) { if len(m.Cookie) > 255 { return nil, errCookieTooLong @@ -47,7 +47,7 @@ func (m *MessageHelloVerifyRequest) Marshal() ([]byte, error) { return out, nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageHelloVerifyRequest) Unmarshal(data []byte) error { if len(data) < 3 { return errBufferTooSmall @@ -61,5 +61,6 @@ func (m *MessageHelloVerifyRequest) Unmarshal(data []byte) error { m.Cookie = make([]byte, cookieLength) copy(m.Cookie, data[3:3+cookieLength]) + return nil } diff --git a/pkg/protocol/handshake/message_hello_verify_request_test.go b/pkg/protocol/handshake/message_hello_verify_request_test.go index 82252566e..0cfd24b70 100644 --- a/pkg/protocol/handshake/message_hello_verify_request_test.go +++ b/pkg/protocol/handshake/message_hello_verify_request_test.go @@ -17,7 +17,10 @@ func TestHandshakeMessageHelloVerifyRequest(t *testing.T) { } parsedHelloVerifyRequest := &MessageHelloVerifyRequest{ Version: protocol.Version{Major: 0xFE, Minor: 0xFF}, - Cookie: []byte{0x25, 0xfb, 0xee, 0xb3, 0x7c, 0x95, 0xcf, 0x00, 0xeb, 0xad, 0xe2, 0xef, 0xc7, 0xfd, 0xbb, 0xed, 0xf7, 0x1f, 0x6c, 0xcd}, + Cookie: []byte{ + 0x25, 0xfb, 0xee, 0xb3, 0x7c, 0x95, 0xcf, 0x00, 0xeb, 0xad, + 0xe2, 0xef, 0xc7, 0xfd, 0xbb, 0xed, 0xf7, 0x1f, 0x6c, 0xcd, + }, } h := &MessageHelloVerifyRequest{} diff --git a/pkg/protocol/handshake/message_server_hello.go b/pkg/protocol/handshake/message_server_hello.go index a1e86e1b2..e2f19c1d9 100644 --- a/pkg/protocol/handshake/message_server_hello.go +++ b/pkg/protocol/handshake/message_server_hello.go @@ -29,12 +29,12 @@ type MessageServerHello struct { const messageServerHelloVariableWidthStart = 2 + RandomLength -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageServerHello) Type() Type { return TypeServerHello } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageServerHello) Marshal() ([]byte, error) { if m.CipherSuiteID == nil { return nil, errCipherSuiteUnset @@ -49,23 +49,23 @@ func (m *MessageServerHello) Marshal() ([]byte, error) { rand := m.Random.MarshalFixed() copy(out[2:], rand[:]) - out = append(out, byte(len(m.SessionID))) - out = append(out, m.SessionID...) + out = append(out, byte(len(m.SessionID))) //nolint:makezero // todo: fix + out = append(out, m.SessionID...) //nolint:makezero // todo: fix - out = append(out, []byte{0x00, 0x00}...) + out = append(out, []byte{0x00, 0x00}...) //nolint:makezero // todo: fix binary.BigEndian.PutUint16(out[len(out)-2:], *m.CipherSuiteID) - out = append(out, byte(m.CompressionMethod.ID)) + out = append(out, byte(m.CompressionMethod.ID)) //nolint:makezero // todo: fix extensions, err := extension.Marshal(m.Extensions) if err != nil { return nil, err } - return append(out, extensions...), nil + return append(out, extensions...), nil //nolint:makezero // todo: fix } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageServerHello) Unmarshal(data []byte) error { if len(data) < 2+RandomLength { return errBufferTooSmall @@ -110,6 +110,7 @@ func (m *MessageServerHello) Unmarshal(data []byte) error { if len(data) <= currOffset { m.Extensions = []extension.Extension{} + return nil } @@ -118,5 +119,6 @@ func (m *MessageServerHello) Unmarshal(data []byte) error { return err } m.Extensions = extensions + return nil } diff --git a/pkg/protocol/handshake/message_server_hello_done.go b/pkg/protocol/handshake/message_server_hello_done.go index b187dd417..49a830c2a 100644 --- a/pkg/protocol/handshake/message_server_hello_done.go +++ b/pkg/protocol/handshake/message_server_hello_done.go @@ -5,20 +5,20 @@ package handshake // MessageServerHelloDone is final non-encrypted message from server // this communicates server has sent all its handshake messages and next -// should be MessageFinished +// should be MessageFinished. type MessageServerHelloDone struct{} -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageServerHelloDone) Type() Type { return TypeServerHelloDone } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageServerHelloDone) Marshal() ([]byte, error) { return []byte{}, nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageServerHelloDone) Unmarshal([]byte) error { return nil } diff --git a/pkg/protocol/handshake/message_server_hello_test.go b/pkg/protocol/handshake/message_server_hello_test.go index c4d6683a5..810dcd348 100644 --- a/pkg/protocol/handshake/message_server_hello_test.go +++ b/pkg/protocol/handshake/message_server_hello_test.go @@ -27,7 +27,10 @@ func TestHandshakeMessageServerHello(t *testing.T) { Version: protocol.Version{Major: 0xFE, Minor: 0xFD}, Random: Random{ GMTUnixTime: time.Unix(560149025, 0), - RandomBytes: [28]byte{0x81, 0x0e, 0x98, 0x6c, 0x85, 0x3d, 0xa4, 0x39, 0xaf, 0x5f, 0xd6, 0x5c, 0xcc, 0x20, 0x7f, 0x7c, 0x78, 0xf1, 0x5f, 0x7e, 0x1c, 0xb7, 0xa1, 0x1e, 0xcf, 0x63, 0x84, 0x28}, + RandomBytes: [28]byte{ + 0x81, 0x0e, 0x98, 0x6c, 0x85, 0x3d, 0xa4, 0x39, 0xaf, 0x5f, 0xd6, 0x5c, 0xcc, 0x20, + 0x7f, 0x7c, 0x78, 0xf1, 0x5f, 0x7e, 0x1c, 0xb7, 0xa1, 0x1e, 0xcf, 0x63, 0x84, 0x28, + }, }, SessionID: []byte{}, CipherSuiteID: &cipherSuiteID, diff --git a/pkg/protocol/handshake/message_server_key_exchange.go b/pkg/protocol/handshake/message_server_key_exchange.go index 1edac45f9..59a5392f3 100644 --- a/pkg/protocol/handshake/message_server_key_exchange.go +++ b/pkg/protocol/handshake/message_server_key_exchange.go @@ -12,7 +12,7 @@ import ( "github.com/pion/dtls/v3/pkg/crypto/signature" ) -// MessageServerKeyExchange supports ECDH and PSK +// MessageServerKeyExchange supports ECDH and PSK. type MessageServerKeyExchange struct { IdentityHint []byte @@ -27,17 +27,17 @@ type MessageServerKeyExchange struct { KeyExchangeAlgorithm types.KeyExchangeAlgorithm } -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageServerKeyExchange) Type() Type { return TypeServerKeyExchange } -// Marshal encodes the Handshake -func (m *MessageServerKeyExchange) Marshal() ([]byte, error) { +// Marshal encodes the Handshake. +func (m *MessageServerKeyExchange) Marshal() ([]byte, error) { //nolint:cyclop var out []byte if m.IdentityHint != nil { out = append([]byte{0x00, 0x00}, m.IdentityHint...) - binary.BigEndian.PutUint16(out, uint16(len(out)-2)) + binary.BigEndian.PutUint16(out, uint16(len(out)-2)) //nolint:gosec //G115 } if m.EllipticCurveType == 0 || len(m.PublicKey) == 0 { @@ -60,14 +60,14 @@ func (m *MessageServerKeyExchange) Marshal() ([]byte, error) { } out = append(out, []byte{byte(m.HashAlgorithm), byte(m.SignatureAlgorithm), 0x00, 0x00}...) - binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.Signature))) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.Signature))) //nolint:gosec // G115 out = append(out, m.Signature...) return out, nil } -// Unmarshal populates the message from encoded data -func (m *MessageServerKeyExchange) Unmarshal(data []byte) error { +// Unmarshal populates the message from encoded data. +func (m *MessageServerKeyExchange) Unmarshal(data []byte) error { //nolint:cyclop switch { case len(data) < 2: return errBufferTooSmall @@ -84,6 +84,7 @@ func (m *MessageServerKeyExchange) Unmarshal(data []byte) error { if len(data) == 0 { return nil } + return errLengthMismatch } @@ -144,5 +145,6 @@ func (m *MessageServerKeyExchange) Unmarshal(data []byte) error { return errBufferTooSmall } m.Signature = append([]byte{}, data[offset:offset+signatureLength]...) + return nil } diff --git a/pkg/protocol/handshake/random.go b/pkg/protocol/handshake/random.go index 56f37569b..6eb2815f4 100644 --- a/pkg/protocol/handshake/random.go +++ b/pkg/protocol/handshake/random.go @@ -9,7 +9,7 @@ import ( "time" ) -// Consts for Random in Handshake +// Consts for Random in Handshake. const ( RandomBytesLength = 28 RandomLength = RandomBytesLength + 4 @@ -23,24 +23,24 @@ type Random struct { RandomBytes [RandomBytesLength]byte } -// MarshalFixed encodes the Handshake +// MarshalFixed encodes the Handshake. func (r *Random) MarshalFixed() [RandomLength]byte { var out [RandomLength]byte - binary.BigEndian.PutUint32(out[0:], uint32(r.GMTUnixTime.Unix())) + binary.BigEndian.PutUint32(out[0:], uint32(r.GMTUnixTime.Unix())) //nolint:gosec // G115 copy(out[4:], r.RandomBytes[:]) return out } -// UnmarshalFixed populates the message from encoded data +// UnmarshalFixed populates the message from encoded data. func (r *Random) UnmarshalFixed(data [RandomLength]byte) { r.GMTUnixTime = time.Unix(int64(binary.BigEndian.Uint32(data[0:])), 0) copy(r.RandomBytes[:], data[4:]) } // Populate fills the handshakeRandom with random values -// may be called multiple times +// may be called multiple times. func (r *Random) Populate() error { r.GMTUnixTime = time.Now() diff --git a/pkg/protocol/recordlayer/errors.go b/pkg/protocol/recordlayer/errors.go index ba2b396b8..09599249b 100644 --- a/pkg/protocol/recordlayer/errors.go +++ b/pkg/protocol/recordlayer/errors.go @@ -11,8 +11,11 @@ import ( ) var ( - // ErrInvalidPacketLength is returned when the packet length too small or declared length do not match - ErrInvalidPacketLength = &protocol.TemporaryError{Err: errors.New("packet length and declared length do not match")} //nolint:goerr113 + // ErrInvalidPacketLength is returned when the packet length too small + // or declared length do not match. + ErrInvalidPacketLength = &protocol.TemporaryError{ + Err: errors.New("packet length and declared length do not match"), //nolint:goerr113 + } errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 errSequenceNumberOverflow = &protocol.InternalError{Err: errors.New("sequence number overflow")} //nolint:goerr113 diff --git a/pkg/protocol/recordlayer/header.go b/pkg/protocol/recordlayer/header.go index 0899d5a22..47af855df 100644 --- a/pkg/protocol/recordlayer/header.go +++ b/pkg/protocol/recordlayer/header.go @@ -10,7 +10,7 @@ import ( "github.com/pion/dtls/v3/pkg/protocol" ) -// Header implements a TLS RecordLayer header +// Header implements a TLS RecordLayer header. type Header struct { ContentType protocol.ContentType ContentLen uint16 @@ -22,7 +22,7 @@ type Header struct { ConnectionID []byte } -// RecordLayer enums +// RecordLayer enums. const ( // FixedHeaderSize is the size of a DTLS record header when connection IDs // are not in use. @@ -30,7 +30,7 @@ const ( MaxSequenceNumber = 0x0000FFFFFFFFFFFF ) -// Marshal encodes a TLS RecordLayer Header to binary +// Marshal encodes a TLS RecordLayer Header to binary. func (h *Header) Marshal() ([]byte, error) { if h.SequenceNumber > MaxSequenceNumber { return nil, errSequenceNumberOverflow @@ -46,10 +46,11 @@ func (h *Header) Marshal() ([]byte, error) { util.PutBigEndianUint48(out[5:], h.SequenceNumber) copy(out[11:11+len(h.ConnectionID)], h.ConnectionID) binary.BigEndian.PutUint16(out[hs-2:], h.ContentLen) + return out, nil } -// Unmarshal populates a TLS RecordLayer Header from binary +// Unmarshal populates a TLS RecordLayer Header from binary. func (h *Header) Unmarshal(data []byte) error { if len(data) < FixedHeaderSize { return errBufferTooSmall diff --git a/pkg/protocol/recordlayer/inner_plaintext.go b/pkg/protocol/recordlayer/inner_plaintext.go index 296475a6c..2c67c86f2 100644 --- a/pkg/protocol/recordlayer/inner_plaintext.go +++ b/pkg/protocol/recordlayer/inner_plaintext.go @@ -17,22 +17,24 @@ type InnerPlaintext struct { Zeros uint } -// Marshal encodes a DTLS InnerPlaintext to binary +// Marshal encodes a DTLS InnerPlaintext to binary. func (p *InnerPlaintext) Marshal() ([]byte, error) { var out cryptobyte.Builder out.AddBytes(p.Content) out.AddUint8(uint8(p.RealType)) out.AddBytes(make([]byte, p.Zeros)) + return out.Bytes() } -// Unmarshal populates a DTLS InnerPlaintext from binary +// Unmarshal populates a DTLS InnerPlaintext from binary. func (p *InnerPlaintext) Unmarshal(data []byte) error { // Process in reverse i := len(data) - 1 for i >= 0 { if data[i] != 0 { - p.Zeros = uint(len(data) - 1 - i) + p.Zeros = uint(len(data) - 1 - i) //nolint:gosec // G115 + break } i-- diff --git a/pkg/protocol/recordlayer/recordlayer.go b/pkg/protocol/recordlayer/recordlayer.go index 61e25a563..95113da4f 100644 --- a/pkg/protocol/recordlayer/recordlayer.go +++ b/pkg/protocol/recordlayer/recordlayer.go @@ -48,14 +48,14 @@ type RecordLayer struct { Content protocol.Content } -// Marshal encodes the RecordLayer to binary +// Marshal encodes the RecordLayer to binary. func (r *RecordLayer) Marshal() ([]byte, error) { contentRaw, err := r.Content.Marshal() if err != nil { return nil, err } - r.Header.ContentLen = uint16(len(contentRaw)) + r.Header.ContentLen = uint16(len(contentRaw)) //nolint:gosec // G115 r.Header.ContentType = r.Content.ContentType() headerRaw, err := r.Header.Marshal() @@ -66,7 +66,7 @@ func (r *RecordLayer) Marshal() ([]byte, error) { return append(headerRaw, contentRaw...), nil } -// Unmarshal populates the RecordLayer from binary +// Unmarshal populates the RecordLayer from binary. func (r *RecordLayer) Unmarshal(data []byte) error { if err := r.Header.Unmarshal(data); err != nil { return err diff --git a/pkg/protocol/version.go b/pkg/protocol/version.go index c4d94ac3a..3943c1504 100644 --- a/pkg/protocol/version.go +++ b/pkg/protocol/version.go @@ -4,7 +4,7 @@ // Package protocol provides the DTLS wire format package protocol -// Version enums +// Version enums. var ( Version1_0 = Version{Major: 0xfe, Minor: 0xff} //nolint:gochecknoglobals Version1_2 = Version{Major: 0xfe, Minor: 0xfd} //nolint:gochecknoglobals @@ -18,7 +18,7 @@ type Version struct { Major, Minor uint8 } -// Equal determines if two protocol versions are equal +// Equal determines if two protocol versions are equal. func (v Version) Equal(x Version) bool { return v.Major == x.Major && v.Minor == x.Minor } diff --git a/replayprotection_test.go b/replayprotection_test.go index 725e05239..e0984ef62 100644 --- a/replayprotection_test.go +++ b/replayprotection_test.go @@ -16,7 +16,7 @@ import ( "github.com/pion/transport/v3/test" ) -func TestReplayProtection(t *testing.T) { +func TestReplayProtection(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(5 * time.Second) defer lim.Stop() @@ -52,6 +52,7 @@ func TestReplayProtection(t *testing.T) { } if _, werr := cb.Write(b[:n]); werr != nil { t.Error(werr) + return } @@ -109,10 +110,12 @@ func TestReplayProtection(t *testing.T) { sent = append(sent, data) if _, werr := ca.Write(data); werr != nil { t.Error(werr) + return } if _, werr := cb.Write(data); werr != nil { t.Error(werr) + return } } diff --git a/resume.go b/resume.go index 0b76314a5..954907dd0 100644 --- a/resume.go +++ b/resume.go @@ -7,10 +7,11 @@ import ( "net" ) -// Resume imports an already established dtls connection using a specific dtls state +// Resume imports an already established dtls connection using a specific dtls state. func Resume(state *State, conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { if err := state.initCipherSuite(); err != nil { return nil, err } + return createConn(conn, rAddr, config, state.isClient, state) } diff --git a/resume_test.go b/resume_test.go index 4f79adb3f..a3ce26cec 100644 --- a/resume_test.go +++ b/resume_test.go @@ -32,11 +32,20 @@ func TestResumeServer(t *testing.T) { } func fatal(t *testing.T, errChan chan error, err error) { + t.Helper() + close(errChan) t.Fatal(err) } -func DoTestResume(t *testing.T, newLocal, newRemote func(net.PacketConn, net.Addr, *Config) (*Conn, error)) { +//nolint:cyclop +func DoTestResume( + t *testing.T, + newLocal, + newRemote func(net.PacketConn, net.Addr, *Config) (*Conn, error), +) { + t.Helper() + // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -176,8 +185,10 @@ func (b *backupConn) Read(data []byte) (n int, err error) { b.curr = b.next b.next = nil b.mux.Unlock() + return b.Read(data) } + return n, err } @@ -188,8 +199,10 @@ func (b *backupConn) Write(data []byte) (n int, err error) { b.curr = b.next b.next = nil b.mux.Unlock() + return b.Write(data) } + return n, err } diff --git a/session.go b/session.go index 99bf5a499..912a5997a 100644 --- a/session.go +++ b/session.go @@ -3,7 +3,7 @@ package dtls -// Session store data needed in resumption +// Session store data needed in resumption. type Session struct { // ID store session id ID []byte diff --git a/state.go b/state.go index f1afb857d..364f7dcc1 100644 --- a/state.go +++ b/state.go @@ -16,7 +16,8 @@ import ( "github.com/pion/transport/v3/replaydetector" ) -// State holds the dtls connection state and implements both encoding.BinaryMarshaler and encoding.BinaryUnmarshaler +// State holds the dtls connection state and implements both encoding.BinaryMarshaler and +// encoding.BinaryUnmarshaler. type State struct { localEpoch, remoteEpoch atomic.Value localSequenceNumber []uint64 // uint48 @@ -112,6 +113,7 @@ func (s *State) serialize() (*serializedState, error) { remoteRnd := s.remoteRandom.MarshalFixed() epoch := s.getLocalEpoch() + return &serializedState{ LocalEpoch: s.getLocalEpoch(), RemoteEpoch: s.getRemoteEpoch(), @@ -193,10 +195,11 @@ func (s *State) initCipherSuite() error { if err != nil { return err } + return nil } -// MarshalBinary is a binary.BinaryMarshaler.MarshalBinary implementation +// MarshalBinary is a binary.BinaryMarshaler.MarshalBinary implementation. func (s *State) MarshalBinary() ([]byte, error) { serialized, err := s.serialize() if err != nil { @@ -208,10 +211,11 @@ func (s *State) MarshalBinary() ([]byte, error) { if err := enc.Encode(*serialized); err != nil { return nil, err } + return buf.Bytes(), nil } -// UnmarshalBinary is a binary.BinaryUnmarshaler.UnmarshalBinary implementation +// UnmarshalBinary is a binary.BinaryUnmarshaler.UnmarshalBinary implementation. func (s *State) UnmarshalBinary(data []byte) error { enc := gob.NewDecoder(bytes.NewBuffer(data)) var serialized serializedState @@ -227,7 +231,7 @@ func (s *State) UnmarshalBinary(data []byte) error { // ExportKeyingMaterial returns length bytes of exported key material in a new // slice as defined in RFC 5705. // This allows protocols to use DTLS for key establishment, but -// then use some of the keying material for their own purposes +// then use some of the keying material for their own purposes. func (s *State) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) { if s.getLocalEpoch() == 0 { return nil, errHandshakeInProgress @@ -246,6 +250,7 @@ func (s *State) ExportKeyingMaterial(label string, context []byte, length int) ( } else { seed = append(append(seed, remoteRandom[:]...), localRandom[:]...) } + return prf.PHash(s.masterSecret, seed, length, s.cipherSuite.HashFunc()) } @@ -253,6 +258,7 @@ func (s *State) getRemoteEpoch() uint16 { if remoteEpoch, ok := s.remoteEpoch.Load().(uint16); ok { return remoteEpoch } + return 0 } @@ -260,6 +266,7 @@ func (s *State) getLocalEpoch() uint16 { if localEpoch, ok := s.localEpoch.Load().(uint16); ok { return localEpoch } + return 0 } @@ -287,7 +294,7 @@ func (s *State) setLocalConnectionID(v []byte) { s.localConnectionID.Store(v) } -// RemoteRandomBytes returns the remote client hello random bytes +// RemoteRandomBytes returns the remote client hello random bytes. func (s *State) RemoteRandomBytes() [handshake.RandomBytesLength]byte { return s.remoteRandom.RandomBytes } diff --git a/util.go b/util.go index 663c4437c..3d9b0bc85 100644 --- a/util.go +++ b/util.go @@ -11,6 +11,7 @@ func findMatchingSRTPProfile(a, b []SRTPProtectionProfile) (SRTPProtectionProfil } } } + return 0, false } @@ -22,6 +23,7 @@ func findMatchingCipherSuite(a, b []CipherSuite) (CipherSuite, bool) { } } } + return nil, false } From 16d630638a22ed42fa5881a88a00e6357c822f48 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 1 Feb 2025 22:04:54 +0000 Subject: [PATCH 143/146] Update module golang.org/x/net to v0.34.0 (#693) Generated by renovateBot Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 192a98c5f..0d974fc9d 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.3 github.com/pion/transport/v3 v3.0.7 - golang.org/x/crypto v0.31.0 - golang.org/x/net v0.33.0 + golang.org/x/crypto v0.32.0 + golang.org/x/net v0.34.0 ) go 1.20 diff --git a/go.sum b/go.sum index be68fd590..fb83dd618 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,7 @@ github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI= github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= From 3a0f50af7df4355fd3107f874446e64309c9b019 Mon Sep 17 00:00:00 2001 From: Donald Chan <hoiho.chan@gmail.com> Date: Tue, 11 Mar 2025 07:40:16 -0700 Subject: [PATCH 144/146] Use crypto.Signer whenever possible (#681) For certificate-based authentication, it is possible that the private key resides in hardware such as Trusted Platform Module (TPM) and the only way in Golang to access it via the crypto.Signer interface. Any code paths that deal with a private key should use the crypto.Signer interface which comes with a function called Public() and it can be used to determine the type of key used. Fixes #524 --- cipher_suite.go | 12 ++++++--- config.go | 13 ++++++--- conn_test.go | 10 +++---- crypto.go | 32 +++++++++++------------ e2e/e2e_lossy_test.go | 1 - flight4handler.go | 10 +++++-- flight5handler.go | 15 ++++++----- pkg/crypto/selfsign/selfsign.go | 25 +++++++++++------- pkg/crypto/signaturehash/errors.go | 1 + pkg/crypto/signaturehash/signaturehash.go | 16 +++++++----- 10 files changed, 82 insertions(+), 53 deletions(-) diff --git a/cipher_suite.go b/cipher_suite.go index 0a40918e0..2b29bf238 100644 --- a/cipher_suite.go +++ b/cipher_suite.go @@ -4,6 +4,7 @@ package dtls import ( + "crypto" "crypto/ecdsa" "crypto/ed25519" "crypto/rsa" @@ -280,11 +281,16 @@ func filterCipherSuitesForCertificate(cert *tls.Certificate, cipherSuites []Ciph if cert == nil || cert.PrivateKey == nil { return cipherSuites } + signer, ok := cert.PrivateKey.(crypto.Signer) + if !ok { + return cipherSuites + } + var certType clientcertificate.Type - switch cert.PrivateKey.(type) { - case ed25519.PrivateKey, *ecdsa.PrivateKey: + switch signer.Public().(type) { + case ed25519.PublicKey, *ecdsa.PublicKey: certType = clientcertificate.ECDSASign - case *rsa.PrivateKey: + case *rsa.PublicKey: certType = clientcertificate.RSASign } diff --git a/config.go b/config.go index 39b5cc38c..722335139 100644 --- a/config.go +++ b/config.go @@ -4,6 +4,7 @@ package dtls import ( + "crypto" "crypto/ecdsa" "crypto/ed25519" "crypto/rsa" @@ -274,10 +275,14 @@ func validateConfig(config *Config) error { //nolint:cyclop return errInvalidCertificate } if cert.PrivateKey != nil { - switch cert.PrivateKey.(type) { - case ed25519.PrivateKey: - case *ecdsa.PrivateKey: - case *rsa.PrivateKey: + signer, ok := cert.PrivateKey.(crypto.Signer) + if !ok { + return errInvalidPrivateKey + } + switch signer.Public().(type) { + case ed25519.PublicKey: + case *ecdsa.PublicKey: + case *rsa.PublicKey: default: return errInvalidPrivateKey } diff --git a/conn_test.go b/conn_test.go index 47538a80a..ed821a57c 100644 --- a/conn_test.go +++ b/conn_test.go @@ -3234,21 +3234,21 @@ func TestCipherSuiteMatchesCertificateType(t *testing.T) { //nolint:cyclop }() var ( - priv crypto.PrivateKey - err error + signer crypto.Signer + err error ) if test.generateRSA { - if priv, err = rsa.GenerateKey(rand.Reader, 2048); err != nil { + if signer, err = rsa.GenerateKey(rand.Reader, 2048); err != nil { t.Fatal(err) } } else { - if priv, err = ecdsa.GenerateKey(cryptoElliptic.P256(), rand.Reader); err != nil { + if signer, err = ecdsa.GenerateKey(cryptoElliptic.P256(), rand.Reader); err != nil { t.Fatal(err) } } - serverCert, err := selfsign.SelfSign(priv) + serverCert, err := selfsign.SelfSign(signer) if err != nil { t.Fatal(err) } diff --git a/crypto.go b/crypto.go index 04b39d442..dae47731c 100644 --- a/crypto.go +++ b/crypto.go @@ -46,22 +46,22 @@ func valueKeyMessage(clientRandom, serverRandom, publicKey []byte, namedCurve el func generateKeySignature( clientRandom, serverRandom, publicKey []byte, namedCurve elliptic.Curve, - privateKey crypto.PrivateKey, + signer crypto.Signer, hashAlgorithm hash.Algorithm, ) ([]byte, error) { msg := valueKeyMessage(clientRandom, serverRandom, publicKey, namedCurve) - switch p := privateKey.(type) { - case ed25519.PrivateKey: + switch signer.Public().(type) { + case ed25519.PublicKey: // https://crypto.stackexchange.com/a/55483 - return p.Sign(rand.Reader, msg, crypto.Hash(0)) - case *ecdsa.PrivateKey: + return signer.Sign(rand.Reader, msg, crypto.Hash(0)) + case *ecdsa.PublicKey: hashed := hashAlgorithm.Digest(msg) - return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) - case *rsa.PrivateKey: + return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) + case *rsa.PublicKey: hashed := hashAlgorithm.Digest(msg) - return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) + return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) } return nil, errKeySignatureGenerateUnimplemented @@ -124,23 +124,23 @@ func verifyKeySignature( // https://tools.ietf.org/html/rfc5246#section-7.3 func generateCertificateVerify( handshakeBodies []byte, - privateKey crypto.PrivateKey, + signer crypto.Signer, hashAlgorithm hash.Algorithm, ) ([]byte, error) { - if p, ok := privateKey.(ed25519.PrivateKey); ok { + if _, ok := signer.Public().(ed25519.PublicKey); ok { // https://pkg.go.dev/crypto/ed25519#PrivateKey.Sign // Sign signs the given message with priv. Ed25519 performs two passes over // messages to be signed and therefore cannot handle pre-hashed messages. - return p.Sign(rand.Reader, handshakeBodies, crypto.Hash(0)) + return signer.Sign(rand.Reader, handshakeBodies, crypto.Hash(0)) } hashed := hashAlgorithm.Digest(handshakeBodies) - switch p := privateKey.(type) { - case *ecdsa.PrivateKey: - return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) - case *rsa.PrivateKey: - return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) + switch signer.Public().(type) { + case *ecdsa.PublicKey: + return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) + case *rsa.PublicKey: + return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) } return nil, errInvalidSignatureAlgorithm diff --git a/e2e/e2e_lossy_test.go b/e2e/e2e_lossy_test.go index e70130cdc..f49cb78f4 100644 --- a/e2e/e2e_lossy_test.go +++ b/e2e/e2e_lossy_test.go @@ -141,7 +141,6 @@ func TestPionE2ELossy(t *testing.T) { //nolint:cyclop lim := transportTest.TimeOut(lossyTestTimeout + time.Second) defer lim.Stop() - rand.Seed(time.Now().UTC().UnixNano()) chosenLoss := rand.Intn(9) + test.LossChanceRange //nolint:gosec serverDone := make(chan runResult) clientDone := make(chan runResult) diff --git a/flight4handler.go b/flight4handler.go index 75e2e8b1a..f75373fc2 100644 --- a/flight4handler.go +++ b/flight4handler.go @@ -5,6 +5,7 @@ package dtls import ( "context" + "crypto" "crypto/rand" "crypto/x509" @@ -366,8 +367,13 @@ func flight4Generate( serverRandom := state.localRandom.MarshalFixed() clientRandom := state.remoteRandom.MarshalFixed() + signer, ok := certificate.PrivateKey.(crypto.Signer) + if !ok { + return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errInvalidPrivateKey + } + // Find compatible signature scheme - signatureHashAlgo, err := signaturehash.SelectSignatureScheme(cfg.localSignatureSchemes, certificate.PrivateKey) + signatureHashAlgo, err := signaturehash.SelectSignatureScheme(cfg.localSignatureSchemes, signer) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, err } @@ -377,7 +383,7 @@ func flight4Generate( serverRandom[:], state.localKeypair.PublicKey, state.namedCurve, - certificate.PrivateKey, + signer, signatureHashAlgo.Hash, ) if err != nil { diff --git a/flight5handler.go b/flight5handler.go index 95f2466c5..1b85b06b9 100644 --- a/flight5handler.go +++ b/flight5handler.go @@ -78,7 +78,7 @@ func flight5Generate( cache *handshakeCache, cfg *handshakeConfig, ) ([]*packet, *alert.Alert, error) { - var privateKey crypto.PrivateKey + var signer crypto.Signer var pkts []*packet if state.remoteRequestedCertificate { //nolint:nestif _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-2, state.cipherSuite, @@ -87,7 +87,7 @@ func flight5Generate( return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errClientCertificateRequired } reqInfo := CertificateRequestInfo{} - if r, ok := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok { + if r, ok2 := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok2 { reqInfo.AcceptableCAs = r.CertificateAuthoritiesNames } else { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errClientCertificateRequired @@ -100,7 +100,10 @@ func flight5Generate( return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errNotAcceptableCertificateChain } if certificate.Certificate != nil { - privateKey = certificate.PrivateKey + signer, ok = certificate.PrivateKey.(crypto.Signer) + if !ok { + return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errInvalidPrivateKey + } } pkts = append(pkts, &packet{ @@ -192,7 +195,7 @@ func flight5Generate( // 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 && privateKey != nil { + if state.remoteRequestedCertificate && signer != nil { plainText := append(cache.pullAndMerge( handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false}, handshakeCachePullRule{handshake.TypeServerHello, cfg.initialEpoch, false, false}, @@ -206,12 +209,12 @@ func flight5Generate( // Find compatible signature scheme - signatureHashAlgo, err := signaturehash.SelectSignatureScheme(state.remoteCertRequestAlgs, privateKey) + signatureHashAlgo, err := signaturehash.SelectSignatureScheme(state.remoteCertRequestAlgs, signer) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, err } - certVerify, err := generateCertificateVerify(plainText, privateKey, signatureHashAlgo.Hash) + certVerify, err := generateCertificateVerify(plainText, signer, signatureHashAlgo.Hash) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } diff --git a/pkg/crypto/selfsign/selfsign.go b/pkg/crypto/selfsign/selfsign.go index fd238b18a..b3bf850a4 100644 --- a/pkg/crypto/selfsign/selfsign.go +++ b/pkg/crypto/selfsign/selfsign.go @@ -53,13 +53,18 @@ func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate, maxBigInt = new(big.Int) // Max random value, a 130-bits integer, i.e 2^130 - 1 ) - switch k := key.(type) { - case ed25519.PrivateKey: - pubKey = k.Public() - case *ecdsa.PrivateKey: - pubKey = k.Public() - case *rsa.PrivateKey: - pubKey = k.Public() + signer, ok := key.(crypto.Signer) + if !ok { + return tls.Certificate{}, errInvalidPrivateKey + } + + switch k := signer.Public().(type) { + case ed25519.PublicKey: + pubKey = k + case *ecdsa.PublicKey: + pubKey = k + case *rsa.PublicKey: + pubKey = k default: return tls.Certificate{}, errInvalidPrivateKey } @@ -76,7 +81,7 @@ func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate, names = append(names, sans...) keyUsage := x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign - if _, isRSA := key.(*rsa.PrivateKey); isRSA { + if _, isRSA := signer.Public().(*rsa.PublicKey); isRSA { keyUsage |= x509.KeyUsageKeyEncipherment } @@ -98,7 +103,7 @@ func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate, }, } - raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey, key) + raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey, signer) if err != nil { return tls.Certificate{}, err } @@ -110,7 +115,7 @@ func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate, return tls.Certificate{ Certificate: [][]byte{raw}, - PrivateKey: key, + PrivateKey: signer, Leaf: leaf, }, nil } diff --git a/pkg/crypto/signaturehash/errors.go b/pkg/crypto/signaturehash/errors.go index 4aeb3e40a..2e2b72bb8 100644 --- a/pkg/crypto/signaturehash/errors.go +++ b/pkg/crypto/signaturehash/errors.go @@ -9,4 +9,5 @@ var ( errNoAvailableSignatureSchemes = errors.New("connection can not be created, no SignatureScheme satisfy this Config") errInvalidSignatureAlgorithm = errors.New("invalid signature algorithm") errInvalidHashAlgorithm = errors.New("invalid hash algorithm") + errInvalidPrivateKey = errors.New("invalid private key type") ) diff --git a/pkg/crypto/signaturehash/signaturehash.go b/pkg/crypto/signaturehash/signaturehash.go index b036fdbfc..2c72f8ca8 100644 --- a/pkg/crypto/signaturehash/signaturehash.go +++ b/pkg/crypto/signaturehash/signaturehash.go @@ -40,8 +40,12 @@ func Algorithms() []Algorithm { // SelectSignatureScheme returns most preferred and compatible scheme. func SelectSignatureScheme(sigs []Algorithm, privateKey crypto.PrivateKey) (Algorithm, error) { + signer, ok := privateKey.(crypto.Signer) + if !ok { + return Algorithm{}, errInvalidPrivateKey + } for _, ss := range sigs { - if ss.isCompatible(privateKey) { + if ss.isCompatible(signer) { return ss, nil } } @@ -50,13 +54,13 @@ func SelectSignatureScheme(sigs []Algorithm, privateKey crypto.PrivateKey) (Algo } // isCompatible checks that given private key is compatible with the signature scheme. -func (a *Algorithm) isCompatible(privateKey crypto.PrivateKey) bool { - switch privateKey.(type) { - case ed25519.PrivateKey: +func (a *Algorithm) isCompatible(signer crypto.Signer) bool { + switch signer.Public().(type) { + case ed25519.PublicKey: return a.Signature == signature.Ed25519 - case *ecdsa.PrivateKey: + case *ecdsa.PublicKey: return a.Signature == signature.ECDSA - case *rsa.PrivateKey: + case *rsa.PublicKey: return a.Signature == signature.RSA default: return false From 13b929b076c4503b206c9cfa7d118472b55006e6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 10:40:52 -0400 Subject: [PATCH 145/146] Update module golang.org/x/net to v0.37.0 (#697) Generated by renovateBot Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- go.mod | 8 +++++--- go.sum | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 0d974fc9d..6c9fd66ee 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,10 @@ module github.com/pion/dtls/v3 require ( github.com/pion/logging v0.2.3 github.com/pion/transport/v3 v3.0.7 - golang.org/x/crypto v0.32.0 - golang.org/x/net v0.34.0 + golang.org/x/crypto v0.36.0 + golang.org/x/net v0.37.0 ) -go 1.20 +go 1.23.0 + +toolchain go1.24.1 diff --git a/go.sum b/go.sum index fb83dd618..dfb9901d2 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,7 @@ github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI= github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= From fbc7bae955bde9270dca5e0c5595896cfe9c4b2d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 10:41:23 -0400 Subject: [PATCH 146/146] Update docker.io/library/golang Docker tag to v1.24 (#694) Generated by renovateBot Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- e2e/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/Dockerfile b/e2e/Dockerfile index 9ad4b00ee..a6f9eedce 100644 --- a/e2e/Dockerfile +++ b/e2e/Dockerfile @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> # SPDX-License-Identifier: MIT -FROM docker.io/library/golang:1.23-bullseye +FROM docker.io/library/golang:1.24-bullseye COPY . /go/src/github.com/pion/dtls WORKDIR /go/src/github.com/pion/dtls/e2e