diff options
| author | Neal Patel <nealpatel@google.com> | 2026-04-10 16:57:45 -0400 |
|---|---|---|
| committer | Neal Patel <nealpatel@google.com> | 2026-04-11 08:57:27 -0700 |
| commit | 7599be8e4a8f051fa3e00e2a56471a5e7fb4f73a (patch) | |
| tree | 16876f6e7fbdc538800155e885318c3c63d4e60d | |
| parent | b7db5702b0743209c7bc9fb4e4c8683549325621 (diff) | |
| download | go-7599be8e4a8f051fa3e00e2a56471a5e7fb4f73a.tar.xz | |
crypto/tls: fix ECH SNI encoded length
https://datatracker.ietf.org/doc/html/rfc9849#section-6.1.3
Change-Id: Ifccf7b92f69ddb9ae288991763111bd1f00e61de
Reviewed-on: https://go-review.googlesource.com/c/go/+/765446
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
| -rw-r--r-- | src/crypto/tls/ech.go | 2 | ||||
| -rw-r--r-- | src/crypto/tls/ech_test.go | 54 |
2 files changed, 55 insertions, 1 deletions
diff --git a/src/crypto/tls/ech.go b/src/crypto/tls/ech.go index adeff9e050..7b0f4a0974 100644 --- a/src/crypto/tls/ech.go +++ b/src/crypto/tls/ech.go @@ -207,7 +207,7 @@ func encodeInnerClientHello(inner *clientHelloMsg, maxNameLength int) ([]byte, e } else { paddingLen = maxNameLength + 9 } - paddingLen = 31 - ((len(h) + paddingLen - 1) % 32) + paddingLen += 31 - ((len(h) + paddingLen - 1) % 32) return append(h, make([]byte, paddingLen)...), nil } diff --git a/src/crypto/tls/ech_test.go b/src/crypto/tls/ech_test.go index 5adbb0293d..472ab55519 100644 --- a/src/crypto/tls/ech_test.go +++ b/src/crypto/tls/ech_test.go @@ -6,6 +6,7 @@ package tls import ( "encoding/hex" + "strings" "testing" ) @@ -46,3 +47,56 @@ func TestSkipBadConfigs(t *testing.T) { t.Fatal("pickECHConfig picked an invalid config") } } + +func TestECHPadding(t *testing.T) { + const maxNameLength = 64 + for _, tc := range []struct { + name string + serverName string + }{ + {"Short", "a.test"}, + {"Medium", strings.Repeat("a", 30) + ".test"}, + {"MaxLength", strings.Repeat("a", maxNameLength) + ".test"}, + {"NoSNI", ""}, + } { + t.Run(tc.name, func(t *testing.T) { + inner := &clientHelloMsg{ + vers: VersionTLS13, + random: make([]byte, 32), + serverName: tc.serverName, + cipherSuites: []uint16{TLS_AES_128_GCM_SHA256}, + compressionMethods: []uint8{0}, + supportedVersions: []uint16{VersionTLS13}, + } + encoded, err := encodeInnerClientHello(inner, maxNameLength) + if err != nil { + t.Fatal(err) + } + if len(encoded)%32 != 0 { + t.Errorf("got %d, want multiple of 32", len(encoded)) + } + }) + } + + t.Run("SetSizeReduction", func(t *testing.T) { + sizes := make(map[int]struct{}) + for sniLen := 1; sniLen <= maxNameLength; sniLen++ { + inner := &clientHelloMsg{ + vers: VersionTLS13, + random: make([]byte, 32), + serverName: strings.Repeat("a", sniLen) + ".test", + cipherSuites: []uint16{TLS_AES_128_GCM_SHA256}, + compressionMethods: []uint8{0}, + supportedVersions: []uint16{VersionTLS13}, + } + encoded, err := encodeInnerClientHello(inner, maxNameLength) + if err != nil { + t.Fatal(err) + } + sizes[len(encoded)] = struct{}{} + } + if len(sizes) > 4 { + t.Errorf("got %d distinct encoded sizes for SNI lengths 1..%d, want <= 4", len(sizes), maxNameLength) + } + }) +} |
