Repository: pion/dtls
Pull request #187 (2020-02-08 14:11:33)

Mirror new exported functions from crypto/tls in Go 1.14

daenney: The annoying bit here is that due to `// +build go1.14` CI isn't running the new tests. They pass locally for me with Go 1.14rc1.

We'll need to keep that build tag while we support Go 1.13 and Go 1.14, but at least once Go 1.14 is out we can have CI test this too. Once Go 1.15 hits and we move over we can merge the files together and remove the build constraint.
codecov-io: # [Codecov](https://codecov.io/gh/pion/dtls/pull/187?src=pr&el=h1) Report
> Merging [#187](https://codecov.io/gh/pion/dtls/pull/187?src=pr&el=desc) into [master](https://codecov.io/gh/pion/dtls/commit/5abf71da54bc268c6d30b7c6fca9145d393c0fb4?src=pr&el=desc) will **decrease** coverage by `0.19%`.
> The diff coverage is `31.25%`.

[![Impacted file tree graph](https://codecov.io/gh/pion/dtls/pull/187/graphs/tree.svg?width=650&token=bcCB2jB88I&height=150&src=pr)](https://codecov.io/gh/pion/dtls/pull/187?src=pr&el=tree)

```diff
@@           Coverage Diff            @@
##           master    #187     +/-   ##
========================================
- Coverage   73.99%   73.8%   -0.2%     
========================================
  Files          62      62             
  Lines        3423    3439     +16     
========================================
+ Hits         2533    2538      +5     
- Misses        599     610     +11     
  Partials      291     291
```

| Flag | Coverage Δ | |
|---|---|---|
| #go | `73.68% <31.25%> (-0.32%)` | :arrow_down: |
| #wasm | `69.99% <31.25%> (-0.19%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pion/dtls/pull/187?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [cipher\_suite.go](https://codecov.io/gh/pion/dtls/pull/187/diff?src=pr&el=tree#diff-Y2lwaGVyX3N1aXRlLmdv) | `80% <31.25%> (-7.88%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pion/dtls/pull/187?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pion/dtls/pull/187?src=pr&el=footer). Last update [5abf71d...29489b2](https://codecov.io/gh/pion/dtls/pull/187?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

daenney: @at-wat Thanks for the review! I think I managed to address all of the comments.

Patch:
diff --git a/cipher_suite.go b/cipher_suite.go
index e99ac1d..bf31487 100644
--- a/cipher_suite.go
+++ b/cipher_suite.go
@@ -28,6 +28,10 @@ const (
 	TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuiteID = 0x00a8
 )
 
+var (
+	_ = allCipherSuites() // Necessary until this function isn't only used by Go 1.14
+)
+
 func (c CipherSuiteID) String() string {
 	switch c {
 	case TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
@@ -68,6 +72,19 @@ type cipherSuite interface {
 	decrypt(in []byte) ([]byte, error)
 }
 
+// CipherSuiteName provides the same functionality as tls.CipherSuiteName
+// that appeared first in Go 1.14.
+//
+// Our implementation differs slightly in that it takes in a CiperSuiteID,
+// like the rest of our library, instead of a uint16 like crypto/tls.
+func CipherSuiteName(id CipherSuiteID) string {
+	suite := cipherSuiteForID(id)
+	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.
@@ -107,6 +124,20 @@ func defaultCipherSuites() []cipherSuite {
 	}
 }
 
+func allCipherSuites() []cipherSuite {
+	return []cipherSuite{
+		newCipherSuiteTLSEcdheEcdsaWithAes128Ccm(),
+		newCipherSuiteTLSEcdheEcdsaWithAes128Ccm8(),
+		&cipherSuiteTLSEcdheEcdsaWithAes128GcmSha256{},
+		&cipherSuiteTLSEcdheRsaWithAes128GcmSha256{},
+		&cipherSuiteTLSEcdheEcdsaWithAes256CbcSha{},
+		&cipherSuiteTLSEcdheRsaWithAes256CbcSha{},
+		newCipherSuiteTLSPskWithAes128Ccm(),
+		newCipherSuiteTLSPskWithAes128Ccm8(),
+		&cipherSuiteTLSPskWithAes128GcmSha256{},
+	}
+}
+
 func decodeCipherSuites(buf []byte) ([]cipherSuite, error) {
 	if len(buf) < 2 {
 		return nil, errDTLSPacketInvalidLength
diff --git a/cipher_suite_go114.go b/cipher_suite_go114.go
new file mode 100644
index 0000000..54824db
--- /dev/null
+++ b/cipher_suite_go114.go
@@ -0,0 +1,36 @@
+// +build go1.14
+
+package dtls
+
+import (
+	"crypto/tls"
+)
+
+// Convert from our cipherSuite interface to a tls.CipherSuite struct
+func toTLSCipherSuite(c cipherSuite) *tls.CipherSuite {
+	return &tls.CipherSuite{
+		ID:                uint16(c.ID()),
+		Name:              c.String(),
+		SupportedVersions: []uint16{VersionDTLS12},
+		Insecure:          false,
+	}
+}
+
+// CipherSuites returns a list of cipher suites currently implemented by this
+// package, excluding those with security issues, which are returned by
+// InsecureCipherSuites.
+func CipherSuites() []*tls.CipherSuite {
+	suites := allCipherSuites()
+	res := make([]*tls.CipherSuite, len(suites))
+	for i, c := range suites {
+		res[i] = toTLSCipherSuite(c)
+	}
+	return res
+}
+
+// InsecureCipherSuites returns a list of cipher suites currently implemented by
+// this package and which have security issues.
+func InsecureCipherSuites() []*tls.CipherSuite {
+	var res []*tls.CipherSuite
+	return res
+}
diff --git a/record_layer_header.go b/record_layer_header.go
index 07e4b3c..954cd4a 100644
--- a/record_layer_header.go
+++ b/record_layer_header.go
@@ -17,6 +17,10 @@ const (
 
 	dtls1_2Major = 0xfe
 	dtls1_2Minor = 0xfd
+
+	// VersionDTLS12 is the DTLS version in the same style as
+	// VersionTLSXX from crypto/tls
+	VersionDTLS12 = 0xfefd
 )
 
 var protocolVersion1_2 = protocolVersion{dtls1_2Major, dtls1_2Minor}


Test patch:
diff --git a/cipher_suite_go114_test.go b/cipher_suite_go114_test.go
new file mode 100644
index 0000000..57c64d4
--- /dev/null
+++ b/cipher_suite_go114_test.go
@@ -0,0 +1,51 @@
+// +build go1.14
+
+package dtls
+
+import (
+	"testing"
+)
+
+func TestInsecureCipherSuites(t *testing.T) {
+	r := InsecureCipherSuites()
+
+	if len(r) != 0 {
+		t.Fatalf("Expected no insecure ciphersuites, got %d", len(r))
+	}
+}
+
+func TestCipherSuites(t *testing.T) {
+	ours := allCipherSuites()
+	theirs := CipherSuites()
+
+	if len(ours) != len(theirs) {
+		t.Fatalf("Expected %d CipherSuites, got %d", len(ours), len(theirs))
+	}
+
+	for i, s := range ours {
+		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)
+			}
+
+			if c.Name != s.String() {
+				t.Fatalf("Expected Name: %s, got %s", s.String(), c.Name)
+			}
+
+			if len(c.SupportedVersions) != 1 {
+				t.Fatalf("Expected %d SupportedVersion, got %d", 1, len(c.SupportedVersions))
+			}
+
+			if c.SupportedVersions[0] != VersionDTLS12 {
+				t.Fatalf("Expected SupportedVersions 0x%04X, got 0x%04X", VersionDTLS12, c.SupportedVersions[0])
+			}
+
+			if c.Insecure {
+				t.Fatalf("Expected Insecure %t, got %t", false, c.Insecure)
+			}
+		})
+	}
+}
diff --git a/cipher_suite_test.go b/cipher_suite_test.go
index 1e295d5..ade6772 100644
--- a/cipher_suite_test.go
+++ b/cipher_suite_test.go
@@ -21,3 +21,27 @@ func TestDecodeCipherSuites(t *testing.T) {
 		// todo: compare result
 	}
 }
+
+func TestCipherSuiteName(t *testing.T) {
+	testCases := []struct {
+		suite    CipherSuiteID
+		expected string
+	}{
+		{TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM"},
+		{CipherSuiteID(0x0000), "0x0000"},
+	}
+
+	for _, testCase := range testCases {
+		res := CipherSuiteName(testCase.suite)
+		if res != testCase.expected {
+			t.Fatalf("Expected: %s, got %s", testCase.expected, res)
+		}
+	}
+}
+
+func TestAllCipherSuites(t *testing.T) {
+	actual := len(allCipherSuites())
+	if actual == 0 {
+		t.Fatal()
+	}
+}