mirror of
https://github.com/refraction-networking/utls.git
synced 2025-03-31 10:37:36 +03:00
* sync: Go 1.21rc3, QUIC support added (#207) * sync: merge with upstream tag/go-1.21rc3 (#11) * fix: all tests pass * impl: UQUIC Transport * deps: bump up min Go version * new: uquic * fix: add QUICTransportParameter * deprecated: Go 1.19 no longer supported Go 1.19 will fail to build or pass the test once we bump up to the new version. * sync: crypto/tls: restrict RSA keys in certificates to <= 8192 bits (#209) * [release-branch.go1.21] crypto/tls: restrict RSA keys in certificates to <= 8192 bits Extremely large RSA keys in certificate chains can cause a client/server to expend significant CPU time verifying signatures. Limit this by restricting the size of RSA keys transmitted during handshakes to <= 8192 bits. Based on a survey of publicly trusted RSA keys, there are currently only three certificates in circulation with keys larger than this, and all three appear to be test certificates that are not actively deployed. It is possible there are larger keys in use in private PKIs, but we target the web PKI, so causing breakage here in the interests of increasing the default safety of users of crypto/tls seems reasonable. Thanks to Mateusz Poliwczak for reporting this issue. Fixes CVE-2023-29409 * build: [ci skip] boring not included * fix: typo [ci skip] * docs: replenish readme [ci skip] replace old build status badge with new ones, bump up required version noted in docs, update developer contact to reflect current status.
117 lines
2.6 KiB
Go
117 lines
2.6 KiB
Go
// Copyright 2022 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package tls
|
|
|
|
import (
|
|
"encoding/pem"
|
|
"fmt"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestCertCache(t *testing.T) {
|
|
cc := certCache{}
|
|
p, _ := pem.Decode([]byte(rsaCertPEM))
|
|
if p == nil {
|
|
t.Fatal("Failed to decode certificate")
|
|
}
|
|
|
|
certA, err := cc.newCert(p.Bytes)
|
|
if err != nil {
|
|
t.Fatalf("newCert failed: %s", err)
|
|
}
|
|
certB, err := cc.newCert(p.Bytes)
|
|
if err != nil {
|
|
t.Fatalf("newCert failed: %s", err)
|
|
}
|
|
if certA.cert != certB.cert {
|
|
t.Fatal("newCert returned a unique reference for a duplicate certificate")
|
|
}
|
|
|
|
if entry, ok := cc.Load(string(p.Bytes)); !ok {
|
|
t.Fatal("cache does not contain expected entry")
|
|
} else {
|
|
if refs := entry.(*cacheEntry).refs.Load(); refs != 2 {
|
|
t.Fatalf("unexpected number of references: got %d, want 2", refs)
|
|
}
|
|
}
|
|
|
|
timeoutRefCheck := func(t *testing.T, key string, count int64) {
|
|
t.Helper()
|
|
c := time.After(4 * time.Second)
|
|
for {
|
|
select {
|
|
case <-c:
|
|
t.Fatal("timed out waiting for expected ref count")
|
|
default:
|
|
e, ok := cc.Load(key)
|
|
if !ok && count != 0 {
|
|
t.Fatal("cache does not contain expected key")
|
|
} else if count == 0 && !ok {
|
|
return
|
|
}
|
|
|
|
if e.(*cacheEntry).refs.Load() == count {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Keep certA alive until at least now, so that we can
|
|
// purposefully nil it and force the finalizer to be
|
|
// called.
|
|
runtime.KeepAlive(certA)
|
|
certA = nil
|
|
runtime.GC()
|
|
|
|
timeoutRefCheck(t, string(p.Bytes), 1)
|
|
|
|
// Keep certB alive until at least now, so that we can
|
|
// purposefully nil it and force the finalizer to be
|
|
// called.
|
|
runtime.KeepAlive(certB)
|
|
certB = nil
|
|
runtime.GC()
|
|
|
|
timeoutRefCheck(t, string(p.Bytes), 0)
|
|
}
|
|
|
|
func BenchmarkCertCache(b *testing.B) {
|
|
p, _ := pem.Decode([]byte(rsaCertPEM))
|
|
if p == nil {
|
|
b.Fatal("Failed to decode certificate")
|
|
}
|
|
|
|
cc := certCache{}
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
// We expect that calling newCert additional times after
|
|
// the initial call should not cause additional allocations.
|
|
for extra := 0; extra < 4; extra++ {
|
|
b.Run(fmt.Sprint(extra), func(b *testing.B) {
|
|
actives := make([]*activeCert, extra+1)
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
var err error
|
|
actives[0], err = cc.newCert(p.Bytes)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
for j := 0; j < extra; j++ {
|
|
actives[j+1], err = cc.newCert(p.Bytes)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
for j := 0; j < extra+1; j++ {
|
|
actives[j] = nil
|
|
}
|
|
runtime.GC()
|
|
}
|
|
})
|
|
}
|
|
}
|