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