mirror of
https://github.com/refraction-networking/utls.git
synced 2025-04-01 19:17:36 +03:00
* Merging upstream changes into sync branch (#6)
* [dev.boringcrypto] crypto/sha1,sha256,sha512: use BoringCrypto
Change-Id: I80a764971b41f75c3b699797bfed71f509e3407d
Reviewed-on: https://go-review.googlesource.com/55474
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* [dev.boringcrypto] crypto/aes: use BoringCrypto
Change-Id: If83fdeac31f65aba818bbc7edd2f215b16814021
Reviewed-on: https://go-review.googlesource.com/55476
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* [dev.boringcrypto] crypto/tls: use TLS-specific AES-GCM mode if available
Change-Id: Ide00c40c0ca8d486f3bd8968e1d301c8b0ed6d05
Reviewed-on: https://go-review.googlesource.com/56011
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* [dev.boringcrypto] crypto/tls/fipsonly: new package to force FIPS-allowed TLS settings
Change-Id: I3268cab2de8aed9e2424e9c3bc7667083bc5e1ce
Reviewed-on: https://go-review.googlesource.com/65250
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* [dev.boringcrypto] crypto/tls: restore AES-GCM priority when BoringCrypto is enabled
This patch used to be in crypto/internal/cipherhw.AESGCMSupport which
was removed from the tree. It was meant and documented to affect only
crypto/tls, so move the logic there.
Change-Id: I36ed4f08a5fe2abaab18907910899ae0297d1611
Reviewed-on: https://go-review.googlesource.com/114816
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* [dev.boringcrypto] crypto/tls: test for TLS 1.3 to be disabled in FIPS mode
Change-Id: I32b3e29a3e34f20cccc51666905fd36744ef00b2
Reviewed-on: https://go-review.googlesource.com/c/149602
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: add support for Ed25519 certificates in TLS 1.2 and 1.3
Support for Ed25519 certificates was added in CL 175478, this wires them
up into the TLS stack according to RFC 8422 (TLS 1.2) and RFC 8446 (TLS 1.3).
RFC 8422 also specifies support for TLS 1.0 and 1.1, and I initially
implemented that, but even OpenSSL doesn't take the complexity, so I
just dropped it. It would have required keeping a buffer of the
handshake transcript in order to do the direct Ed25519 signatures. We
effectively need to support TLS 1.2 because it shares ClientHello
signature algorithms with TLS 1.3.
While at it, reordered the advertised signature algorithms in the rough
order we would want to use them, also based on what curves have fast
constant-time implementations.
Client and client auth tests changed because of the change in advertised
signature algorithms in ClientHello and CertificateRequest.
Fixes #25355
Change-Id: I9fdd839afde4fd6b13fcbc5cc7017fd8c35085ee
Reviewed-on: https://go-review.googlesource.com/c/go/+/177698
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: fix TestVerifyHostnameResumed
In TLS 1.3 session tickets are delivered after the handshake, and it
looks like now the Google servers wait until the first flight of data to
send them (or our timeout is too low). Cause some data to be sent so we
can avoid the guessing game.
Fixes #32090
Change-Id: I54af4acb3a89cc70c9e14a5dfe18a44c29a841a7
Reviewed-on: https://go-review.googlesource.com/c/go/+/177877
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
* all: remove PEM-encoded private keys from tests
Gerrit is complaining about pushes that affect these files
and forcing people to use -o nokeycheck, which defeats
the point of the check. Hide the keys from this kind of scan
by marking them explicitly as testing keys.
This is a little annoying but better than training everyone
who ever edits one of these test files to reflexively override
the Gerrit check.
The only remaining keys explicitly marked as private instead
of testing are in examples, and there's not much to do
about those. Hopefully they are not edited as much.
Change-Id: I4431592b5266cb39fe6a80b40e742d97da803a0b
Reviewed-on: https://go-review.googlesource.com/c/go/+/178178
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
* all: shorten some tests
Shorten some of the longest tests that run during all.bash.
Removes 7r 50u 21s from all.bash.
After this change, all.bash is under 5 minutes again on my laptop.
For #26473.
Change-Id: Ie0460aa935808d65460408feaed210fbaa1d5d79
Reviewed-on: https://go-review.googlesource.com/c/go/+/177559
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
* [dev.boringcrypto] crypto: move crypto/internal/boring imports to reduce merge conflicts
As suggested by dmitshur@, move them to their own block so they don't
conflict with changes in the upstream imports.
Change-Id: Id46fb7c766066c406023b0355f4c3c860166f0fe
Reviewed-on: https://go-review.googlesource.com/c/go/+/181277
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
* crypto/tls: disable RSA-PSS in TLS 1.2 again
Signing with RSA-PSS can uncover faulty crypto.Signer implementations,
and it can fail for (broken) small keys. We'll have to take that
breakage eventually, but it would be nice for it to be opt-out at first.
TLS 1.3 requires RSA-PSS and is opt-out in Go 1.13. Instead of making a
TLS 1.3 opt-out influence a TLS 1.2 behavior, let's wait to add RSA-PSS
to TLS 1.2 until TLS 1.3 is on without opt-out.
Note that since the Client Hello is sent before a protocol version is
selected, we have to advertise RSA-PSS there to support TLS 1.3.
That means that we still support RSA-PSS on the client in TLS 1.2 for
verifying server certificates, which is fine, as all issues arise on the
signing side. We have to be careful not to pick (or consider available)
RSA-PSS on the client for client certificates, though.
We'd expect tests to change only in TLS 1.2:
* the server won't pick PSS to sign the key exchange
(Server-TLSv12-* w/ RSA, TestHandshakeServerRSAPSS);
* the server won't advertise PSS in CertificateRequest
(Server-TLSv12-ClientAuthRequested*, TestClientAuth);
* and the client won't pick PSS for its CertificateVerify
(Client-TLSv12-ClientCert-RSA-*, TestHandshakeClientCertRSAPSS,
Client-TLSv12-Renegotiate* because "R" requests a client cert).
Client-TLSv13-ClientCert-RSA-RSAPSS was updated because of a fix in the test.
This effectively reverts 88343530720a52c96b21f2bd5488c8fb607605d7.
Testing was made more complex by the undocumented semantics of OpenSSL's
-[client_]sigalgs (see openssl/openssl#9172).
Updates #32425
Change-Id: Iaddeb2df1f5c75cd090cc8321df2ac8e8e7db349
Reviewed-on: https://go-review.googlesource.com/c/go/+/182339
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: move shared code and resources to handshake_test.go
Removed cross-dependencies between handshake_server_test.go and
handshake_client_test.go; moved all initialization to TestMain; replaced
SSLKEYLOGFILE environment variable with -keylog flag.
Change-Id: Ida6712daa44e01a2c00658e8a1896087ee88bcb0
Reviewed-on: https://go-review.googlesource.com/c/go/+/183057
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: reject low-order Curve25519 points
The RFC recommends checking the X25519 output to ensure it's not the
zero value, to guard against peers trying to remove contributory
behavior.
In TLS there should be enough transcript involvement to mitigate any
attack, and the RSA key exchange would suffer from the same issues by
design, so not proposing a backport.
See #31846
Change-Id: I8e657f8ee8aa72c3f8ca3b124555202638c53f5e
Reviewed-on: https://go-review.googlesource.com/c/go/+/183039
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: deflake localPipe in tests
The localPipe implementation assumes that every successful net.Dial
results in exactly one successful listener.Accept. I don't believe this
is guaranteed by essentially any operating system. For this test, we're
seeing flakes on dragonfly (#29583).
But see also #19519, flakes due to the same assumption on FreeBSD
and macOS in package net's own tests.
This CL rewrites localPipe to try a few times to get a matching pair
of connections on the dial and accept side.
Fixes #29583.
Change-Id: Idb045b18c404eae457f091df20456c5ae879a291
Reviewed-on: https://go-review.googlesource.com/c/go/+/184157
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
* crypto/tls: remove TestVerifyHostnameResumed
Session resumption is not a reliable TLS behavior: the server can decide
to reject a session ticket for a number of reasons, or no reason at all.
This makes this non-hermetic test extremely brittle.
It's currently broken on the builders for both TLS 1.2 and TLS 1.3, and
I could reproduce the issue for TLS 1.3 only. As I was debugging it, it
started passing entirely on my machine.
In practice, it doesn't get us any coverage as resumption is already
tested with the recorded exchange tests, and TestVerifyHostname still
provides a smoke test checking that we can in fact talk TLS.
Fixes #32978
Change-Id: I63505e22ff7704f25ad700d46e4ff14850ba5d3c
Reviewed-on: https://go-review.googlesource.com/c/go/+/186239
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
* crypto/tls: deprecate SSLv3 support
Updates #32716
Change-Id: Ia0c03918e8f2da4d9824c49c6d4cfca1b0787b0a
Reviewed-on: https://go-review.googlesource.com/c/go/+/184102
Reviewed-by: Andrew Bonventre <andybons@golang.org>
* crypto/tls: make SSLv3 again disabled by default
It was mistakenly re-enabled in CL 146217.
Fixes #33837
Change-Id: I8c0e1787114c6232df5888e51e355906622295bc
Reviewed-on: https://go-review.googlesource.com/c/go/+/191877
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
* crypto/tls: remove SSLv3 support
SSLv3 has been irreparably broken since the POODLE attack 5 years ago
and RFC 7568 (f.k.a. draft-ietf-tls-sslv3-diediedie) prohibits its use
in no uncertain terms.
As announced in the Go 1.13 release notes, remove support for it
entirely in Go 1.14.
Updates #32716
Change-Id: Id653557961d8f75f484a01e6afd2e104a4ccceaf
Reviewed-on: https://go-review.googlesource.com/c/go/+/191976
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
* crypto/tls: remove TLS 1.3 opt-out
Fixes #30055
Change-Id: If757c43b52fc7bf62b0afb1c720615329fb5569d
Reviewed-on: https://go-review.googlesource.com/c/go/+/191999
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
* all: fix typos
Use the following (suboptimal) script to obtain a list of possible
typos:
#!/usr/bin/env sh
set -x
git ls-files |\
grep -e '\.\(c\|cc\|go\)$' |\
xargs -n 1\
awk\
'/\/\// { gsub(/.*\/\//, ""); print; } /\/\*/, /\*\// { gsub(/.*\/\*/, ""); gsub(/\*\/.*/, ""); }' |\
hunspell -d en_US -l |\
grep '^[[:upper:]]\{0,1\}[[:lower:]]\{1,\}$' |\
grep -v -e '^.\{1,4\}$' -e '^.\{16,\}$' |\
sort -f |\
uniq -c |\
awk '$1 == 1 { print $2; }'
Then, go through the results manually and fix the most obvious typos in
the non-vendored code.
Change-Id: I3cb5830a176850e1a0584b8a40b47bde7b260eae
Reviewed-on: https://go-review.googlesource.com/c/go/+/193848
Reviewed-by: Robert Griesemer <gri@golang.org>
* crypto/tls: remove NPN support
RELNOTE=yes
Fixes #28362
Change-Id: I43813c0c17bbe6c4cbb4d1f121518c434b3f5aa8
Reviewed-on: https://go-review.googlesource.com/c/go/+/174329
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: consistently use %v for error formatting
We should keep a consistent way of formatting errors
in this file.
Fixes #34848
Change-Id: Ibb75908504f381fccab0281a42e788ef8c716b6f
Reviewed-on: https://go-review.googlesource.com/c/go/+/200679
Run-TryBot: Johan Brandhorst <johan.brandhorst@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
* crypto/tls: retry net.Dial flakes on Dragonfly
localPipe currently flakes in various crypto/tls tests. Since that
function doesn't seem to flake anywhere else, I suspect a kernel bug.
To make the test less flaky, retry the Dial if we suspect that it is
affected. (Worst case, we delay the test by a few seconds before
erroring out as usual.)
Fixes #29583
Change-Id: I357990ffa316edb471bd7d46d6404fa0884da646
Reviewed-on: https://go-review.googlesource.com/c/go/+/202557
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
* crypto/tls: move a defer out of a loop
Rhys Hiltner noted in #14939 that this defer was
syntactically inside a loop, but was only ever
executed once. Now that defer in a loop
is significantly slower, pull this one out.
name old time/op new time/op delta
Throughput/MaxPacket/1MB/TLSv12-8 3.94ms ± 8% 3.93ms ±13% ~ (p=0.967 n=15+15)
Throughput/MaxPacket/1MB/TLSv13-8 4.33ms ± 3% 4.51ms ± 7% +4.00% (p=0.000 n=14+14)
Throughput/MaxPacket/2MB/TLSv12-8 6.80ms ± 6% 7.01ms ± 4% +3.15% (p=0.000 n=14+14)
Throughput/MaxPacket/2MB/TLSv13-8 6.96ms ± 5% 6.80ms ± 5% -2.43% (p=0.006 n=15+14)
Throughput/MaxPacket/4MB/TLSv12-8 12.0ms ± 3% 11.7ms ± 2% -2.88% (p=0.000 n=15+13)
Throughput/MaxPacket/4MB/TLSv13-8 12.1ms ± 3% 11.7ms ± 2% -3.54% (p=0.000 n=13+13)
Throughput/MaxPacket/8MB/TLSv12-8 22.2ms ± 3% 21.6ms ± 3% -2.97% (p=0.000 n=15+15)
Throughput/MaxPacket/8MB/TLSv13-8 22.5ms ± 5% 22.0ms ± 3% -2.34% (p=0.004 n=15+15)
Throughput/MaxPacket/16MB/TLSv12-8 42.4ms ± 3% 41.3ms ± 3% -2.49% (p=0.001 n=15+15)
Throughput/MaxPacket/16MB/TLSv13-8 43.4ms ± 5% 42.3ms ± 3% -2.33% (p=0.006 n=15+14)
Throughput/MaxPacket/32MB/TLSv12-8 83.1ms ± 4% 80.6ms ± 3% -2.98% (p=0.000 n=15+15)
Throughput/MaxPacket/32MB/TLSv13-8 85.2ms ± 8% 82.6ms ± 4% -3.02% (p=0.005 n=15+15)
Throughput/MaxPacket/64MB/TLSv12-8 167ms ± 7% 158ms ± 2% -5.21% (p=0.000 n=15+15)
Throughput/MaxPacket/64MB/TLSv13-8 170ms ± 4% 162ms ± 3% -4.83% (p=0.000 n=15+15)
Throughput/DynamicPacket/1MB/TLSv12-8 4.13ms ± 7% 4.00ms ± 8% ~ (p=0.061 n=15+15)
Throughput/DynamicPacket/1MB/TLSv13-8 4.72ms ± 6% 4.64ms ± 7% ~ (p=0.377 n=14+15)
Throughput/DynamicPacket/2MB/TLSv12-8 7.29ms ± 7% 7.09ms ± 7% ~ (p=0.070 n=15+14)
Throughput/DynamicPacket/2MB/TLSv13-8 7.18ms ± 5% 6.59ms ± 4% -8.34% (p=0.000 n=15+15)
Throughput/DynamicPacket/4MB/TLSv12-8 12.3ms ± 3% 11.9ms ± 4% -3.31% (p=0.000 n=15+14)
Throughput/DynamicPacket/4MB/TLSv13-8 12.2ms ± 4% 12.0ms ± 4% -1.91% (p=0.019 n=15+15)
Throughput/DynamicPacket/8MB/TLSv12-8 22.4ms ± 3% 21.9ms ± 3% -2.18% (p=0.000 n=15+15)
Throughput/DynamicPacket/8MB/TLSv13-8 22.7ms ± 3% 22.2ms ± 3% -2.35% (p=0.000 n=15+15)
Throughput/DynamicPacket/16MB/TLSv12-8 42.3ms ± 3% 42.1ms ± 3% ~ (p=0.505 n=14+15)
Throughput/DynamicPacket/16MB/TLSv13-8 42.7ms ± 3% 43.3ms ± 7% ~ (p=0.123 n=15+14)
Throughput/DynamicPacket/32MB/TLSv12-8 82.8ms ± 3% 81.9ms ± 3% ~ (p=0.112 n=14+15)
Throughput/DynamicPacket/32MB/TLSv13-8 84.6ms ± 6% 83.9ms ± 4% ~ (p=0.624 n=15+15)
Throughput/DynamicPacket/64MB/TLSv12-8 166ms ± 4% 163ms ± 6% ~ (p=0.081 n=15+15)
Throughput/DynamicPacket/64MB/TLSv13-8 165ms ± 3% 168ms ± 3% +1.56% (p=0.029 n=15+15)
Change-Id: I22409b05afe761b8ed1912b15c67fc03f88d3d1f
Reviewed-on: https://go-review.googlesource.com/c/go/+/203481
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
* crypto/tls: improve error messages for invalid certificates and signatures
Also, fix the alert value sent when a signature by a client certificate
is invalid in TLS 1.0-1.2.
Fixes #35190
Change-Id: I2ae1d5593dfd5ee2b4d979664aec74aab4a8a704
Reviewed-on: https://go-review.googlesource.com/c/go/+/204157
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: send ec_points_format extension in ServerHello
Follow the recommandation from RFC 8422, section 5.1.2 of sending back the
ec_points_format extension when requested by the client. This is to fix
some clients declining the handshake if omitted.
Fixes #31943
Change-Id: I7b04dbac6f9af75cda094073defe081e1e9a295d
Reviewed-on: https://go-review.googlesource.com/c/go/+/176418
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Olivier Poitrey <rs@rhapsodyk.net>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
* crypto/tls: make -update only regenerate transcripts for failing tests
Change-Id: Ie68fd4fe2879e6b5417a1a4240971e3d837bf115
Reviewed-on: https://go-review.googlesource.com/c/go/+/204377
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Katie Hockman <katie@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
* crypto/tls: add ExampleConfig_VerifyPeerCertificate
Setting InsecureSkipVerify and VerifyPeerCertificate is the recommended
way to customize and override certificate validation.
However, there is boilerplate involved and it usually requires first
reimplementing the default validation strategy to then customize it.
Provide an example that does the same thing as the default as a starting
point.
Examples of where we directed users to do something similar are in
issues #35467, #31791, #28754, #21971, and #24151.
Fixes #31792
Change-Id: Id033e9fa3cac9dff1f7be05c72dfb34b4f973fd4
Reviewed-on: https://go-review.googlesource.com/c/go/+/193620
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: refactor certificate and signature algorithm logic
This refactors a lot of the certificate support logic to make it cleaner
and reusable where possible. These changes will make the following CLs
much simpler.
In particular, the heavily overloaded pickSignatureAlgorithm is gone.
That function used to cover both signing and verifying side, would work
both for pre-signature_algorithms TLS 1.0/1.1 and TLS 1.2, and returned
sigalg, type and hash.
Now, TLS 1.0/1.1 and 1.2 are differentiated at the caller, as they have
effectively completely different logic. TLS 1.0/1.1 simply use
legacyTypeAndHashFromPublicKey as they employ a fixed hash function and
signature algorithm for each public key type. TLS 1.2 is instead routed
through selectSignatureScheme (on the signing side) or
isSupportedSignatureAlgorithm (on the verifying side) and
typeAndHashFromSignatureScheme, like TLS 1.3.
On the signing side, signatureSchemesForCertificate was already version
aware (for PKCS#1 v1.5 vs PSS support), so selectSignatureScheme just
had to learn the Section 7.4.1.4.1 defaults for a missing
signature_algorithms to replace pickSignatureAlgorithm.
On the verifying side, pickSignatureAlgorithm was also checking the
public key type, while isSupportedSignatureAlgorithm +
typeAndHashFromSignatureScheme are not, but that check was redundant
with the one in verifyHandshakeSignature.
There should be no major change in behavior so far. A few minor changes
came from the refactor: we now correctly require signature_algorithms in
TLS 1.3 when using a certificate; we won't use Ed25519 in TLS 1.2 if the
client didn't send signature_algorithms; and we don't send
ec_points_format in the ServerHello (a compatibility measure) if we are
not doing ECDHE anyway because there are no mutually supported curves.
The tests also got simpler because they test simpler functions. The
caller logic switching between TLS 1.0/1.1 and 1.2 is tested by the
transcript tests.
Updates #32426
Change-Id: Ice9dcaea78d204718f661f8d60efdb408ba41577
Reviewed-on: https://go-review.googlesource.com/c/go/+/205061
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: implement (*ClientHelloInfo).SupportsCertificate
We'll also use this function for a better selection logic from
Config.Certificates in a later CL.
Updates #32426
Change-Id: Ie239574d02eb7fd2cf025ec36721c8c7e082d0bc
Reviewed-on: https://go-review.googlesource.com/c/go/+/205057
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: implement (*CertificateRequestInfo).SupportsCertificate
Also, add Version to CertificateRequestInfo, as the semantics of
SignatureSchemes change based on version: the ECDSA SignatureSchemes are
only constrained to a specific curve in TLS 1.3.
Fixes #32426
Change-Id: I7a551bea864799e98118349ac2476162893d1ffd
Reviewed-on: https://go-review.googlesource.com/c/go/+/205058
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: select only compatible chains from Certificates
Now that we have a full implementation of the logic to check certificate
compatibility, we can let applications just list multiple chains in
Certificates (for example, an RSA and an ECDSA one) and choose the most
appropriate automatically.
NameToCertificate only maps each name to one chain, so simply deprecate
it, and while at it simplify its implementation by not stripping
trailing dots from the SNI (which is specified not to have any, see RFC
6066, Section 3) and by not supporting multi-level wildcards, which are
not a thing in the WebPKI (and in crypto/x509).
The performance of SupportsCertificate without Leaf is poor, but doesn't
affect current users. For now document that, and address it properly in
the next cycle. See #35504.
While cleaning up the Certificates/GetCertificate/GetConfigForClient
behavior, also support leaving Certificates/GetCertificate nil if
GetConfigForClient is set, and send unrecognized_name when there are no
available certificates.
Fixes #29139
Fixes #18377
Change-Id: I26604db48806fe4d608388e55da52f34b7ca4566
Reviewed-on: https://go-review.googlesource.com/c/go/+/205059
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: implement Certificate.SupportedSignatureAlgorithms
This will let applications stop crypto/tls from using a certificate key
with an algorithm that is not supported by its crypto.Signer, like
hardware backed keys that can't do RSA-PSS.
Fixes #28660
Change-Id: I294cc06bddf813fff35c5107540c4a1788e1dace
Reviewed-on: https://go-review.googlesource.com/c/go/+/205062
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: re-enable RSA-PSS in TLS 1.2 again
TLS 1.3, which requires RSA-PSS, is now enabled without a GODEBUG
opt-out, and with the introduction of
Certificate.SupportedSignatureAlgorithms (#28660) there is a
programmatic way to avoid RSA-PSS (disable TLS 1.3 with MaxVersion and
use that field to specify only PKCS#1 v1.5 SignatureSchemes).
This effectively reverts 0b3a57b5374bba3fdf88258e2be4c8be65e6a5de,
although following CL 205061 all of the signing-side logic is
conveniently centralized in signatureSchemesForCertificate.
Fixes #32425
Change-Id: I7c9a8893bb5d518d86eae7db82612b9b2cd257d7
Reviewed-on: https://go-review.googlesource.com/c/go/+/205063
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: add correct names for CHACHA20_POLY1305 cipher suite constants
The cipher suites were apparently renamed late in the standardization
process, and we picked up the legacy name. We can't remove the old
constants, but add correctly named ones.
Fixes #32061
Change-Id: I65ee25c12c10934391af88b76b18565da67453fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/205068
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: add CipherSuites, InsecureCipherSuites and CipherSuiteName
Fixes #30325
Change-Id: I497110224bb73ecfcc4655698a794e7aa4a66925
Reviewed-on: https://go-review.googlesource.com/c/go/+/175517
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
* crypto/tls: take key size into account in signature algorithm selection
Fixes #29793
Change-Id: I6e389d166c2d9a2ba8664a41f4b9569f2481b27f
Reviewed-on: https://go-review.googlesource.com/c/go/+/205177
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: retry ETIMEDOUT flakes in localPipe on dragonfly
Fixes #29583
Change-Id: Ia89433bddd4c9f67ec1f0150b730cde8a7e973ee
Reviewed-on: https://go-review.googlesource.com/c/go/+/206759
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
* src/vendor,crypto/tls: update to latest x/crypto and use new X25519 API
Change-Id: Icd5006e37861d892a5f3d4397c3826179c1b12ad
Reviewed-on: https://go-review.googlesource.com/c/go/+/206657
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* all: fix a bunch of misspellings
Change-Id: I5b909df0fd048cd66c5a27fca1b06466d3bcaac7
GitHub-Last-Rev: 778c5d21311abee09a5fbda2e4005a5fd4cc3f9f
GitHub-Pull-Request: golang/go#35624
Reviewed-on: https://go-review.googlesource.com/c/go/+/207421
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
* crypto/tls: remove leftover extensionNextProtoNeg constant
NPN was removed in CL 174329.
Change-Id: Ic63ad53e7e24872e28673d590727e0300f435619
Reviewed-on: https://go-review.googlesource.com/c/go/+/208224
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
* crypto/tls: fix a typo in TLS handshake comment
Fix a minor typo in the TLS handshake comment.
Change-Id: I0fd243e5440f6c77c97e844e6669a7974a2c8798
GitHub-Last-Rev: 21e91a1a48e8a9200e6fca89a988e1383ded7bb2
GitHub-Pull-Request: golang/go#36030
Reviewed-on: https://go-review.googlesource.com/c/go/+/210289
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
* crypto/tls: stop a timeout timer
I noticed this leak while writing CL 214977.
Change-Id: I7566952b8e4bc58939d23435aea86576fc58ddca
Reviewed-on: https://go-review.googlesource.com/c/go/+/214978
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
* crypto/tls: clarify TLS 1.0/1.1 CertificateRequestInfo.SignatureSchemes
This CL should not change the logic at all, but it took me a while to
figure out why we use these specific SignatureSchemes, so reformulate
the comment.
Change-Id: If519a58264209e6575417be07668e92ead0e772f
Reviewed-on: https://go-review.googlesource.com/c/go/+/208225
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: update ExampleDial with a valid root
When run as a separate program, the code in ExampleDial panicked due to
an expired certificate. Fixed this problem by replacing the expired
certificate with a valid one.
Also added a comment in the certificate to give a hint about why it
might fail in the future.
Fixes #35706
Change-Id: I3d300f7bccae050e4b73ded28b8029aa04b480bd
Reviewed-on: https://go-review.googlesource.com/c/go/+/212601
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: use new ecdsa.VerifyASN1 API
Change-Id: I2a233190bda78ca022ff4074b4553788847d7583
Reviewed-on: https://go-review.googlesource.com/c/go/+/220720
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* all: fix incorrect channel and API usage in some unit tests
This CL changes some unit test functions, making sure that these tests (and goroutines spawned during test) won't block.
Since they are just test functions, I use one CL to fix them all. I hope this won't cause trouble to reviewers and can save time for us.
There are three main categories of incorrect logic fixed by this CL:
1. Use testing.Fatal()/Fatalf() in spawned goroutines, which is forbidden by Go's document.
2. Channels are used in such a way that, when errors or timeout happen, the test will be blocked and never return.
3. Channels are used in such a way that, when errors or timeout happen, the test can return but some spawned goroutines will be leaked, occupying resource until all other tests return and the process is killed.
Change-Id: I3df931ec380794a0cf1404e632c1dd57c65d63e8
Reviewed-on: https://go-review.googlesource.com/c/go/+/219380
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
* crypto/tls: add {SignatureScheme,CurveID,ClientAuthType}.String()
Fixes #35499
Change-Id: Ieb487782f389f6d80e8f68ee980e584d906cb4da
Reviewed-on: https://go-review.googlesource.com/c/go/+/208226
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: update the MITM reference to "machine-in-the-middle"
Changing "man-in-the-middle" references to "machine-in-the-middle",
it's a more inclusive term and still aligns with the MITM acronym.
Change-Id: I81f954cff3d252433443f159ff9edaf59a28ab9d
GitHub-Last-Rev: 3e8f91424a207233b537984747ae90cbc1f03755
GitHub-Pull-Request: golang/go#37918
Reviewed-on: https://go-review.googlesource.com/c/go/+/223897
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: add missing alert values
Fixes #35911
Change-Id: I093d25aa169963769b51c37d2481bce71bd0fd2f
Reviewed-on: https://go-review.googlesource.com/c/go/+/226858
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: failed tls.Conn.Write returns a permanent error
Fixes #29971
Change-Id: I2f1653640c88fafe0ec17a75dcf41d5896c4cb8e
Reviewed-on: https://go-review.googlesource.com/c/go/+/227840
Run-TryBot: Katie Hockman <katie@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
* crypto/tls: help linker remove code when only Client or Server is used
This saves 166 KiB for a tls.Dial hello world program (5382441 to
5212356 to bytes), by permitting the linker to remove TLS server code.
Change-Id: I16610b836bb0802b7d84995ff881d79ec03b6a84
Reviewed-on: https://go-review.googlesource.com/c/go/+/228111
Reviewed-by: Ian Lance Taylor <iant@golang.org>
* crypto/tls: add Dialer
Fixes #18482
Change-Id: I99d65dc5d824c00093ea61e7445fc121314af87f
Reviewed-on: https://go-review.googlesource.com/c/go/+/214977
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
* math/big: add (*Int).FillBytes
Replaced almost every use of Bytes with FillBytes.
Note that the approved proposal was for
func (*Int) FillBytes(buf []byte)
while this implements
func (*Int) FillBytes(buf []byte) []byte
because the latter was far nicer to use in all callsites.
Fixes #35833
Change-Id: Ia912df123e5d79b763845312ea3d9a8051343c0a
Reviewed-on: https://go-review.googlesource.com/c/go/+/230397
Reviewed-by: Robert Griesemer <gri@golang.org>
* crypto/tls: enforce TLS 1.3 (and TLS 1.2) downgrade protection checks
Fixes #37763
Change-Id: Ic6bcc9af0d164966f4ae31087998e5b546540038
Reviewed-on: https://go-review.googlesource.com/c/go/+/231038
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: marshal sessionState using cryptobyte
Change-Id: I95a60b837e19d0c4bf45ea74baa5843a8244a186
Reviewed-on: https://go-review.googlesource.com/c/go/+/231218
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: accept HelloRetryRequest messages with only a cookie
Clients have to reject any HelloRetryRequest message that doesn't lead
to a change in the ClientHello. Instead, we were rejecting any HRR that
didn't select an alternative group, even if it sent a cookie, which
would change the CH.
The good news is that I know of no TLS servers that use or need HRRs
exclusively for cookies (which are mostly useful in DTLS as a way to
verify the source address). The bad news is that we poisoned the
ecosystem as Go 1.12 to 1.14 will reject such HRRs. Oops, hopefully no
one needed this.
No tests because neither Go nor s_server support cookies. This would
presumably get covered once we integrate BoGo.
Fixes #30149
Change-Id: I760fb1ded81148ac3096cf201cbc1e941374b83d
Reviewed-on: https://go-review.googlesource.com/c/go/+/231039
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: fix sessionState marshaling
Change-Id: I2910f322256c521dd03b1dc23d117defdcd0aa54
Reviewed-on: https://go-review.googlesource.com/c/go/+/232662
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: rotate session keys in older TLS versions
Also encode the certificates in a way that's more
consistent with TLS 1.3 (with a 24 byte length prefix).
Note that this will have an additional performance cost
requiring clients to do a full handshake every 7 days
where previously they were able to use the same ticket
indefinitely.
Updates #25256
Change-Id: Ic4d1ba0d92773c490b33b5f6c1320d557cc7347d
Reviewed-on: https://go-review.googlesource.com/c/go/+/231317
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: rotate session ticket keys
Automatically rotate session ticket keys for servers
that don't already have sessionTicketKeys and that
haven't called SetSessionTicketKeys.
Now, session ticket keys will be rotated every 24 hours
with a lifetime of 7 days. This adds a small performance
cost to existing clients that don't provide a session
ticket encrypted with a fresh enough session ticket key,
which would require a full handshake.
Updates #25256
Change-Id: I15b46af7a82aab9a108bceb706bbf66243a1510f
Reviewed-on: https://go-review.googlesource.com/c/go/+/230679
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: add Config.VerifyConnection callback
Since the ConnectionState will now be available during
verification, some code was moved around in order to
initialize and make available as much of the fields on
Conn as possible before the ConnectionState is verified.
Fixes #36736
Change-Id: I0e3efa97565ead7de5c48bb8a87e3ea54fbde140
Reviewed-on: https://go-review.googlesource.com/c/go/+/229122
Run-TryBot: Katie Hockman <katie@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
* crypto/tls: persist the createdAt time when re-wrapping session tickets
Change-Id: I33fcde2d544943fb04c2599810cf7fb773aeba1f
Reviewed-on: https://go-review.googlesource.com/c/go/+/234483
Run-TryBot: Katie Hockman <katie@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
* crypto/tls: remove version check when unmarshaling sessionState
This was causing issues when fuzzing with
TestMarshalUnmarshal since the test would
occassionally set the version to VersionTLS13,
which would fail when unmarshaling. The check
doesn't add much in practice, and there is no
harm in removing it to de-flake the test.
Fixes #38902
Change-Id: I0906c570e9ed69c85fdd2c15f1b52f9e372c62e3
Reviewed-on: https://go-review.googlesource.com/c/go/+/234486
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: fix duplicate calls to VerifyConnection
Also add a test that could reproduce this error and
ensure it doesn't occur in other configurations.
Fixes #39012
Change-Id: If792b5131f312c269fd2c5f08c9ed5c00188d1af
Reviewed-on: https://go-review.googlesource.com/c/go/+/233957
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: test that Clone copies session ticket key fields
Updates #25256
Change-Id: If16c42581f1cf3500fd7fd01c915e487f8025e55
Reviewed-on: https://go-review.googlesource.com/c/go/+/235922
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: set CipherSuite for VerifyConnection
The ConnectionState's CipherSuite was not set prior
to the VerifyConnection callback in TLS 1.2 servers,
both for full handshakes and resumptions.
Change-Id: Iab91783eff84d1b42ca09c8df08e07861e18da30
Reviewed-on: https://go-review.googlesource.com/c/go/+/236558
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: restore OCSP and SCTs during session resumption
Restore previously sent SCTs and stapled OCSP response during session
resumption for both TLS 1.2 and 1.3. This behavior is somewhat
complicated for TLS 1.2 as SCTs are sent during the server hello,
so they override what is saved in ClientSessionState. It is likely
that if the server is sending a different set of SCTs there is probably
a reason for doing so, such as a log being retired, or SCT validation
requirements changing, so it makes sense to defer to the server in
that case.
Fixes #39075
Change-Id: I3c0fa2f69c6bf0247a447c48a1b4c733a882a233
Reviewed-on: https://go-review.googlesource.com/c/go/+/234237
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: fix DialContext docs
Change-Id: I58e3febbf63049bebb4f8ed8893288183c8aaccd
Reviewed-on: https://go-review.googlesource.com/c/go/+/239745
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: expand the ConnectionState docs
Fixes #37572
Change-Id: I493392f535a979ee16609861041da2ecfe21cf77
Reviewed-on: https://go-review.googlesource.com/c/go/+/239744
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: replace VerifyPeerCertificate example with VerifyConnection
Look at how much better it is!
Updates #36736
Change-Id: I53a314a103a42dd869c05823fa50f37d70f9d283
Reviewed-on: https://go-review.googlesource.com/c/go/+/239560
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: create certs w/o KeyEncipherment KU for non-RSA keys in generate_cert.go
Summary
The crypto/tls/generate_cert.go utility should only set the template
x509.Certificate's KeyUsage field to a value with the
x509.KeyUsageKeyEncipherment bits set when the certificate subject
public key is an RSA public key, not an ECDSA or ED25519 public key.
Background
RFC 5480 describes the usage of ECDSA elliptic curve subject keys with
X.509. Unfortunately while Section 3 "Key Usages Bits" indicates which
key usage bits MAY be used with a certificate that indicates
id-ecPublicKey in the SubjectPublicKeyInfo field it doesn't provide
guidance on which usages should *not* be included (e.g. the
keyEncipherment bit, which is particular to RSA key exchange). The same
problem is present in RFC 8410 Section 5 describing Key Usage Bits for
ED25519 elliptic curve subject keys.
There's an update to RFC 5480 in last call stage within the IETF LAMPS
WG, draft-ietf-lamps-5480-ku-clarifications-00. This update is meant
to clarify the allowed Key Usages extension values for certificates with
ECDSA subject public keys by adding:
> If the keyUsage extension is present in a certificate that indicates
> id-ecPublicKey as algorithm of AlgorithmIdentifier [RFC2986] in
> SubjectPublicKeyInfo, then following values MUST NOT be present:
>
> keyEncipherment; and
> dataEncipherment.
I don't believe there is an update for RFC 8410 in the works but I
suspect it will be clarified similarly in the future.
This commit updates generate_cert.go to ensure when the certificate
public key is ECDSA or ED25519 the generated certificate has the
x509.Certificate.KeyUsage field set to a value that doesn't include KUs
specific to RSA. For ECDSA keys this will adhere to the updated RFC 5480
language.
Fixes #36499
Change-Id: Ib1b0757c039b7fe97fc6d1e826fe6b88856c1964
GitHub-Last-Rev: a8f34fb33dde90e09b6f9a27b2598a82b3023abb
GitHub-Pull-Request: golang/go#36500
Reviewed-on: https://go-review.googlesource.com/c/go/+/214337
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
* crypto/tls: relax the docs of InsecureSkipVerify
Fixes #39074
Change-Id: I72ec95f4b190253bb82d52a03a769b0399170b93
Reviewed-on: https://go-review.googlesource.com/c/go/+/239746
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto: fix PKCS space in docs
Change-Id: Iee53acb963a889410f8c6daaa9a7841f1b12c6fb
Reviewed-on: https://go-review.googlesource.com/c/go/+/241497
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: replace errClosed with net.ErrClosed
CL 250357 exported net.ErrClosed to allow more reliable detection
of closed network connection errors. Use that error in crypto/tls
as well.
The error message is changed from "tls: use of closed connection"
to "use of closed network connection", so the code that detected such
errors by looking for that text in the error message will need to be
updated to use errors.Is(err, net.ErrClosed) instead.
Fixes #41066
Change-Id: Ic05c0ed6a4f57af2a0302d53b00851a59200be2e
Reviewed-on: https://go-review.googlesource.com/c/go/+/256897
Reviewed-by: Katie Hockman <katie@golang.org>
Trust: Katie Hockman <katie@golang.org>
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
* crypto/tls: make config.Clone return nil if the source is nil
Fixes #40565
Change-Id: I13a67be193f8cd68df02b8729529e627a73d364b
GitHub-Last-Rev: b03d2c04fd88db909b40dfd7bd08fe13d8994ab9
GitHub-Pull-Request: golang/go#40566
Reviewed-on: https://go-review.googlesource.com/c/go/+/246637
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Trust: Emmanuel Odeke <emm.odeke@gmail.com>
* crypto/tls: fix TestLinkerGC test
A test that checks if "tls.(*Conn)" appears in any symbol's name.
tls.Conn is a type, so the string "tls.(*Conn)" can only appear
in the name of a method of Conn. But the test code doesn't use
any of the methods. Not sure why this needs to be live. In
particular, the linker is now able to prune all methods of Conn.
Remove this requirement. In fact, just drop the only_conn test
case, as simply allocating a type doesn't necessarily bring
anything live.
Change-Id: I754291b75d38e1465b5291b4dea20806615d21b3
Reviewed-on: https://go-review.googlesource.com/c/go/+/257973
Trust: Cherry Zhang <cherryyz@google.com>
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
* crypto/tls: fix typo in spelling of permanentError
Change-Id: I819c121ff388460ec348af773ef94b44416a2ea9
GitHub-Last-Rev: 98dd8fb25cecb73e88d107e0a35e3e63a53dfd09
GitHub-Pull-Request: golang/go#41785
Reviewed-on: https://go-review.googlesource.com/c/go/+/259517
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Trust: Emmanuel Odeke <emm.odeke@gmail.com>
* all: update references to symbols moved from io/ioutil to io
The old ioutil references are still valid, but update our code
to reflect best practices and get used to the new locations.
Code compiled with the bootstrap toolchain
(cmd/asm, cmd/dist, cmd/compile, debug/elf)
must remain Go 1.4-compatible and is excluded.
Also excluded vendored code.
For #41190.
Change-Id: I6d86f2bf7bc37a9d904b6cee3fe0c7af6d94d5b1
Reviewed-on: https://go-review.googlesource.com/c/go/+/263142
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
* crypto/tls: add no-shared to openssl build instructions
This prevents the custom-built version of openssl prefering the system
libraries over the ones compiled with the specified (weak crypto)
options necessary to generate the updates. This difference can lead to
confusing failures when updating the tests.
Fixes #31809
Change-Id: I2dd257f3121d6c6c62c6aeba52e1c74046b3c584
GitHub-Last-Rev: 6d4eeafadf0b4671b7e17c6810f1a66a9fda7d3c
GitHub-Pull-Request: golang/go#41630
Reviewed-on: https://go-review.googlesource.com/c/go/+/257517
Trust: Emmanuel Odeke <emm.odeke@gmail.com>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: document the ClientAuthType consts
Fixes #34023
Change-Id: Ib7552a8873a79a91e8d971f906c6d7283da7a80c
Reviewed-on: https://go-review.googlesource.com/c/go/+/264027
Trust: Roland Shoemaker <roland@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: set Deadline before sending close notify alert
This change also documents the need to set a Deadline before
calling Read or Write.
Fixes #31224
Change-Id: I89d6fe3ecb0a0076b4c61765f61c88056f951406
Reviewed-on: https://go-review.googlesource.com/c/go/+/266037
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: pool Conn's outBuf to reduce memory cost of idle connections
Derived from CL 263277, which includes benchmarks.
Fixes #42035
Co-authored-by: Filippo Valsorda <filippo@golang.org>
Change-Id: I5f28673f95d4568b7d13dbc20e9d4b48d481a93d
Reviewed-on: https://go-review.googlesource.com/c/go/+/267957
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Filippo Valsorda <filippo@golang.org>
Trust: Roland Shoemaker <roland@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Roberto Clapis <roberto@golang.org>
* crypto/tls: don't use CN in BuildNameToCertificate if SANs are present
Change-Id: I18d5b9fc392a6a52fbdd240254d6d9db838073a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/266540
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
* crypto/tls: add HandshakeContext method to Conn
Adds the (*tls.Conn).HandshakeContext method. This allows
us to pass the context provided down the call stack to
eventually reach the tls.ClientHelloInfo and
tls.CertificateRequestInfo structs.
These contexts are exposed to the user as read-only via Context()
methods.
This allows users of (*tls.Config).GetCertificate and
(*tls.Config).GetClientCertificate to use the context for
request scoped parameters and cancellation.
Replace uses of (*tls.Conn).Handshake with (*tls.Conn).HandshakeContext
where appropriate, to propagate existing contexts.
Fixes #32406
Change-Id: I33c228904fe82dcf57683b63627497d3eb841ff2
Reviewed-on: https://go-review.googlesource.com/c/go/+/246338
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Roland Shoemaker <roland@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: drop macFunction abstraction
Since we dropped SSLv3, there is only one MAC scheme, and it doesn't
need any state beyond a keyed HMAC, so we can replace the macFunction
with the hash.Hash it wraps.
Pointed out by mtp@.
Change-Id: I5545be0e6ccb34a3055fad7f6cb5f628ff748e9f
Reviewed-on: https://go-review.googlesource.com/c/go/+/251859
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Trust: Roland Shoemaker <roland@golang.org>
Trust: Filippo Valsorda <filippo@golang.org>
* crypto/tls: ensure the server picked an advertised ALPN protocol
This is a SHALL in RFC 7301, Section 3.2.
Also some more cleanup after NPN, which worked the other way around
(with the possibility that the client could pick a protocol the server
did not suggest).
Change-Id: I83cc43ca1b3c686dfece8315436441c077065d82
Reviewed-on: https://go-review.googlesource.com/c/go/+/239748
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Filippo Valsorda <filippo@golang.org>
Trust: Roland Shoemaker <roland@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
* crypto/tls: de-prioritize AES-GCM ciphers when lacking hardware support
When either the server or client are lacking hardware support for
AES-GCM ciphers, indicated by the server lacking the relevant
instructions and by the client not putting AES-GCM ciphers at the top
of its preference list, reorder the preference list to de-prioritize
AES-GCM based ciphers when they are adjacent to other AEAD ciphers.
Also updates a number of recorded openssl TLS tests which previously
only specified TLS 1.2 cipher preferences (using -cipher), but not
TLS 1.3 cipher preferences (using -ciphersuites), to specify both
preferences, making these tests more predictable.
Fixes #41181.
Change-Id: Ied896c96c095481e755aaff9ff0746fb4cb9568e
Reviewed-on: https://go-review.googlesource.com/c/go/+/262857
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Trust: Roland Shoemaker <roland@golang.org>
Trust: Katie Hockman <katie@golang.org>
* all: update to use os.ReadFile, os.WriteFile, os.CreateTemp, os.MkdirTemp
As part of #42026, these helpers from io/ioutil were moved to os.
(ioutil.TempFile and TempDir became os.CreateTemp and MkdirTemp.)
Update the Go tree to use the preferred names.
As usual, code compiled with the Go 1.4 bootstrap toolchain
and code vendored from other sources is excluded.
ReadDir changes are in a separate CL, because they are not a
simple search and replace.
For #42026.
Change-Id: If318df0216d57e95ea0c4093b89f65e5b0ababb3
Reviewed-on: https://go-review.googlesource.com/c/go/+/266365
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
* crypto/tls: revert "add HandshakeContext method to Conn"
This reverts CL 246338.
Reason for revert: waiting for 1.17 release cycle
Updates #32406
Change-Id: I074379039041e086c62271d689b4b7f442281663
Reviewed-on: https://go-review.googlesource.com/c/go/+/269697
Run-TryBot: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
Trust: Katie Hockman <katie@golang.org>
Trust: Roland Shoemaker <roland@golang.org>
* all: go fmt std cmd (but revert vendor)
Make all our package sources use Go 1.17 gofmt format
(adding //go:build lines).
Part of //go:build change (#41184).
See https://golang.org/design/draft-gobuild
Change-Id: Ia0534360e4957e58cd9a18429c39d0e32a6addb4
Reviewed-on: https://go-review.googlesource.com/c/go/+/294430
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
* docs: fix spelling
Change-Id: Ib689e5793d9cb372e759c4f34af71f004010c822
GitHub-Last-Rev: d63798388e5dcccb984689b0ae39b87453b97393
GitHub-Pull-Request: golang/go#44259
Reviewed-on: https://go-review.googlesource.com/c/go/+/291949
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Trust: Robert Griesemer <gri@golang.org>
* docs: clarify when APIs use context.Background.
The Go standard library retrofitted context support onto existing APIs
using context.Background and later offered variants that directly
supported user-defined context value specification. This commit makes
that behavior clear in documentation and suggests context-aware
alternatives if the user is looking for one.
An example motivation is supporting code for use in systems that expect
APIs to be cancelable for lifecycle correctness or load
shedding/management reasons, as alluded to in
https://blog.golang.org/context-and-structs.
Updates #44143
Change-Id: I2d7f954ddf9b48264d5ebc8d0007058ff9bddf14
Reviewed-on: https://go-review.googlesource.com/c/go/+/296152
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Jean de Klerk <deklerk@google.com>
Trust: Jean de Klerk <deklerk@google.com>
Run-TryBot: Jean de Klerk <deklerk@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
* all: remove duplicate words
Change-Id: Ib0469232a2b69a869e58d5d24990ad74ac96ea56
GitHub-Last-Rev: eb38e049ee1e773392ff3747e1eb2af20dd50dcd
GitHub-Pull-Request: golang/go#44805
Reviewed-on: https://go-review.googlesource.com/c/go/+/299109
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
* crypto/tls: add HandshakeContext method to Conn
Adds the (*tls.Conn).HandshakeContext method. This allows
us to pass the context provided down the call stack to
eventually reach the tls.ClientHelloInfo and
tls.CertificateRequestInfo structs.
These contexts are exposed to the user as read-only via Context()
methods.
This allows users of (*tls.Config).GetCertificate and
(*tls.Config).GetClientCertificate to use the context for
request scoped parameters and cancellation.
Replace uses of (*tls.Conn).Handshake with (*tls.Conn).HandshakeContext
where appropriate, to propagate existing contexts.
Fixes #32406
Change-Id: I259939c744bdc9b805bf51a845a8bc462c042483
Reviewed-on: https://go-review.googlesource.com/c/go/+/295370
Run-TryBot: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Katie Hockman <katie@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: remove flaky cancellation test
This will be reintroduced again once the source of the
flakiness has been determined and fixed.
Fixes #45084
Change-Id: I6677b27fcd71e8c9bb8edbe8e3be70e5a271ebd3
Reviewed-on: https://go-review.googlesource.com/c/go/+/302569
Trust: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
Run-TryBot: Katie Hockman <katie@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
* all: fix spellings
This follows the spelling choices that the Go project has made for English words.
https://github.com/golang/go/wiki/Spelling
Change-Id: Ie7c586d2cf23020cb492cfff58c0831d2d8d3a78
GitHub-Last-Rev: e16a32cd225a275f73d236bcb33703986d110ded
GitHub-Pull-Request: golang/go#45442
Reviewed-on: https://go-review.googlesource.com/c/go/+/308291
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
* crypto/tls: fix flaky handshake cancellation tests
Simplified both tests significantly by removing logic for writing
the client/server side messages. The flake was likely because of a
race between the closing of the local pipe from inside the test
and closing of the pipe from within the handshakeContext goroutine.
Wait to close the local pipe in the test until after the test
has finished running.
Fixes #45106
Fixes #45299
Change-Id: If7ca75aeff7df70cda03c934fa9d8513276d465d
Reviewed-on: https://go-review.googlesource.com/c/go/+/305250
Trust: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
Trust: Katie Hockman <katie@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: enforce ALPN overlap when negotiated on both sides
During the TLS handshake if the server doesn't support any of the
application protocols requested by the client, send the
no_application_protocol alert and abort the handshake on the server
side. This enforces the requirements of RFC 7301.
Change-Id: Iced2bb5c6efc607497de1c40ee3de9c2b393fa5d
Reviewed-on: https://go-review.googlesource.com/c/go/+/289209
Trust: Roland Shoemaker <roland@golang.org>
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* crypto/tls: make cipher suite preference ordering automatic
We now have a (well, two, depending on AES hardware support) universal
cipher suite preference order, based on their security and performance.
Peer and application lists are now treated as filters (and AES hardware
support hints) that are applied to this universal order.
This removes a complex and nuanced decision from the application's
responsibilities, one which we are better equipped to make and which
applications usually don't need to have an opinion about. It also lets
us worry less about what suites we support or enable, because we can be
confident that bad ones won't be selected over good ones.
This also moves 3DES suites to InsecureCipherSuites(), even if they are
not disabled by default. Just because we can keep them as a last resort
it doesn't mean they are secure. Thankfully we had not promised that
Insecure means disabled by default.
Notable test changes:
- TestCipherSuiteCertPreferenceECDSA was testing that we'd pick the
right certificate regardless of CipherSuite ordering, which is now
completely ignored, as tested by TestCipherSuitePreference. Removed.
- The openssl command of TestHandshakeServerExportKeyingMaterial was
broken for TLS 1.0 in CL 262857, but its golden file was not
regenerated, so the test kept passing. It now broke because the
selected suite from the ones in the golden file changed.
- In TestAESCipherReordering, "server strongly prefers AES-GCM" is
removed because there is no way for a server to express a strong
preference anymore; "client prefers AES-GCM and AES-CBC over ChaCha"
switched to ChaCha20 when the server lacks AES hardware; and finally
"client supports multiple AES-GCM" changed to always prefer AES-128
per the universal preference list.
* this is going back on an explicit decision from CL 262857, and
while that client order is weird and does suggest a strong dislike
for ChaCha20, we have a strong dislike for software AES, so it
didn't feel worth making the logic more complex
- All Client-* golden files had to be regenerated because the
ClientHello cipher suites have changed.
(Even when Config.CipherSuites was limited to one suite, the TLS 1.3
default order changed.)
Fixes #45430
Fixes #41476 (as 3DES is now always the last resort)
Change-Id: If5f5d356c0f8d1f1c7542fb06644a478d6bad1e5
Reviewed-on: https://go-review.googlesource.com/c/go/+/314609
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Trust: Filippo Valsorda <filippo@golang.org>
* crypto/tls: fix typo in Config.NextProtos docs
Change-Id: I916df584859595067e5e86c35607869397dbbd8c
Reviewed-on: https://go-review.googlesource.com/c/go/+/325651
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
* crypto/tls: let HTTP/1.1 clients connect to servers with NextProtos "h2"
Fixes #46310
Change-Id: Idd5e30f05c439f736ae6f3904cbb9cc2ba772315
Reviewed-on: https://go-review.googlesource.com/c/go/+/325432
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
* crypto/tls: test key type when casting
When casting the certificate public key in generateClientKeyExchange,
check the type is appropriate. This prevents a panic when a server
agrees to a RSA based key exchange, but then sends an ECDSA (or
other) certificate.
Fixes #47143
Fixes CVE-2021-34558
Thanks to Imre Rad for reporting this issue.
Change-Id: Iabccacca6052769a605cccefa1216a9f7b7f6aea
Reviewed-on: 1116723
Reviewed-by: Filippo Valsorda <valsorda@google.com>
Reviewed-by: Katie Hockman <katiehockman@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/334031
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
* crypto/tls: fix typo in PreferServerCipherSuites comment
Fixing a typo, Deprected -> Deprecated.
Change-Id: Ie0ccc9a57ae6a935b4f67154ac097dba4c3832ec
GitHub-Last-Rev: 57337cc1bfa771111f229e7b899fdfdad3b1655e
GitHub-Pull-Request: golang/go#47745
Reviewed-on: https://go-review.googlesource.com/c/go/+/342791
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
* [dev.boringcrypto] crypto/tls: use correct config in TestBoringClientHello
The existing implementation sets the ClientConfig to specific values to
check, but does no…
* fix: resolve merge incompatibilities (#7)
- Removed anything only build with tag `boringcrypto`
- Defined dummy Boring struct to supply statically defined Boring ENV VAR(s) and functions.
- Adding back removed `extensionNextProtoNeg` extension.
* Update README.md
* chore: fixing comments
- uncomment an occurrence of `boring`
- edited comment for `decryptTicket`/`DecryptTicketWith` to reflect changes made.
Co-authored-by: Russ Cox <rsc@golang.org>
Co-authored-by: Filippo Valsorda <filippo@golang.org>
Co-authored-by: Filippo Valsorda <hi@filippo.io>
Co-authored-by: Katie Hockman <katie@golang.org>
Co-authored-by: Ainar Garipov <gugl.zadolbal@gmail.com>
Co-authored-by: Brad Fitzpatrick <bradfitz@golang.org>
Co-authored-by: fenos <fabri.feno@gmail.com>
Co-authored-by: Bryan C. Mills <bcmills@google.com>
Co-authored-by: Josh Bleecher Snyder <josharian@gmail.com>
Co-authored-by: Olivier Poitrey <rs@netflix.com>
Co-authored-by: Ville Skyttä <ville.skytta@iki.fi>
Co-authored-by: Alex Harford <alex.harford@saucelabs.com>
Co-authored-by: Johan Jansson <johan.jansson@iki.fi>
Co-authored-by: Ziheng Liu <lzhfromustc@gmail.com>
Co-authored-by: Chris Le Roy <brompwnie@users.noreply.github.com>
Co-authored-by: Brad Fitzpatrick <brad@danga.com>
Co-authored-by: Dmitri Shuralyov <dmitshur@golang.org>
Co-authored-by: Roland Shoemaker <rolandshoemaker@gmail.com>
Co-authored-by: Daniel <cpu@letsencrypt.org>
Co-authored-by: Chen.Zhidong <njutczd@gmail.com>
Co-authored-by: Cherry Zhang <cherryyz@google.com>
Co-authored-by: Luca Spiller <luca@stackednotion.com>
Co-authored-by: Thom Wiggers <thom@thomwiggers.nl>
Co-authored-by: cch123 <buaa.cch@gmail.com>
Co-authored-by: Johan Brandhorst <johan.brandhorst@gmail.com>
Co-authored-by: Roland Shoemaker <roland@golang.org>
Co-authored-by: John Bampton <jbampton@gmail.com>
Co-authored-by: Matt T. Proud <matt.proud@gmail.com>
Co-authored-by: Naman Gera <namangera15@gmail.com>
Co-authored-by: vinckr <vincent@ory.sh>
Co-authored-by: Sofía Celi <cherenkovd69@gmail.com>
Co-authored-by: Watson Ladd <watson@cloudflare.com>
Co-authored-by: Agniva De Sarker <agnivade@yahoo.co.in>
Co-authored-by: Heschi Kreinick <heschi@google.com>
Co-authored-by: Chressie Himpel <chressie@google.com>
Co-authored-by: Dan Kortschak <dan@kortschak.io>
Co-authored-by: Nicolas Hillegeer <aktau@google.com>
Co-authored-by: Ian Lance Taylor <iant@golang.org>
Co-authored-by: Lasse Folger <lassefolger@google.com>
Co-authored-by: Daniel Martí <mvdan@mvdan.cc>
Co-authored-by: David Taylor <tinystatemachine@gmail.com>
Co-authored-by: Tatiana Bradley <tatiana@golang.org>
1487 lines
53 KiB
Go
1487 lines
53 KiB
Go
// Copyright 2009 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 (
|
|
"bytes"
|
|
"container/list"
|
|
"context"
|
|
"crypto"
|
|
"crypto/ecdsa"
|
|
"crypto/ed25519"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/sha512"
|
|
"crypto/x509"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
VersionTLS10 = 0x0301
|
|
VersionTLS11 = 0x0302
|
|
VersionTLS12 = 0x0303
|
|
VersionTLS13 = 0x0304
|
|
|
|
// Deprecated: SSLv3 is cryptographically broken, and is no longer
|
|
// supported by this package. See golang.org/issue/32716.
|
|
VersionSSL30 = 0x0300
|
|
)
|
|
|
|
const (
|
|
maxPlaintext = 16384 // maximum plaintext payload length
|
|
maxCiphertext = 16384 + 2048 // maximum ciphertext payload length
|
|
maxCiphertextTLS13 = 16384 + 256 // maximum ciphertext length in TLS 1.3
|
|
recordHeaderLen = 5 // record header length
|
|
maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB)
|
|
maxUselessRecords = 16 // maximum number of consecutive non-advancing records
|
|
)
|
|
|
|
// TLS record types.
|
|
type recordType uint8
|
|
|
|
const (
|
|
recordTypeChangeCipherSpec recordType = 20
|
|
recordTypeAlert recordType = 21
|
|
recordTypeHandshake recordType = 22
|
|
recordTypeApplicationData recordType = 23
|
|
)
|
|
|
|
// TLS handshake message types.
|
|
const (
|
|
typeHelloRequest uint8 = 0
|
|
typeClientHello uint8 = 1
|
|
typeServerHello uint8 = 2
|
|
typeNewSessionTicket uint8 = 4
|
|
typeEndOfEarlyData uint8 = 5
|
|
typeEncryptedExtensions uint8 = 8
|
|
typeCertificate uint8 = 11
|
|
typeServerKeyExchange uint8 = 12
|
|
typeCertificateRequest uint8 = 13
|
|
typeServerHelloDone uint8 = 14
|
|
typeCertificateVerify uint8 = 15
|
|
typeClientKeyExchange uint8 = 16
|
|
typeFinished uint8 = 20
|
|
typeCertificateStatus uint8 = 22
|
|
typeKeyUpdate uint8 = 24
|
|
typeNextProtocol uint8 = 67 // Not IANA assigned
|
|
typeMessageHash uint8 = 254 // synthetic message
|
|
)
|
|
|
|
// TLS compression types.
|
|
const (
|
|
compressionNone uint8 = 0
|
|
)
|
|
|
|
// TLS extension numbers
|
|
const (
|
|
extensionServerName uint16 = 0
|
|
extensionStatusRequest uint16 = 5
|
|
extensionSupportedCurves uint16 = 10 // supported_groups in TLS 1.3, see RFC 8446, Section 4.2.7
|
|
extensionSupportedPoints uint16 = 11
|
|
extensionSignatureAlgorithms uint16 = 13
|
|
extensionALPN uint16 = 16
|
|
extensionSCT uint16 = 18
|
|
extensionDelegatedCredentials uint16 = 34
|
|
extensionSessionTicket uint16 = 35
|
|
extensionPreSharedKey uint16 = 41
|
|
extensionEarlyData uint16 = 42
|
|
extensionSupportedVersions uint16 = 43
|
|
extensionCookie uint16 = 44
|
|
extensionPSKModes uint16 = 45
|
|
extensionCertificateAuthorities uint16 = 47
|
|
extensionSignatureAlgorithmsCert uint16 = 50
|
|
extensionKeyShare uint16 = 51
|
|
extensionNextProtoNeg uint16 = 13172 // not IANA assigned // Pending discussion on whether or not remove this. crypto/tls removed it on Nov 21, 2019.
|
|
extensionRenegotiationInfo uint16 = 0xff01
|
|
)
|
|
|
|
// TLS signaling cipher suite values
|
|
const (
|
|
scsvRenegotiation uint16 = 0x00ff
|
|
)
|
|
|
|
// CurveID is the type of a TLS identifier for an elliptic curve. See
|
|
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8.
|
|
//
|
|
// In TLS 1.3, this type is called NamedGroup, but at this time this library
|
|
// only supports Elliptic Curve based groups. See RFC 8446, Section 4.2.7.
|
|
type CurveID uint16
|
|
|
|
const (
|
|
CurveP256 CurveID = 23
|
|
CurveP384 CurveID = 24
|
|
CurveP521 CurveID = 25
|
|
X25519 CurveID = 29
|
|
)
|
|
|
|
// TLS 1.3 Key Share. See RFC 8446, Section 4.2.8.
|
|
type keyShare struct {
|
|
group CurveID
|
|
data []byte
|
|
}
|
|
|
|
// TLS 1.3 PSK Key Exchange Modes. See RFC 8446, Section 4.2.9.
|
|
const (
|
|
pskModePlain uint8 = 0
|
|
pskModeDHE uint8 = 1
|
|
)
|
|
|
|
// TLS 1.3 PSK Identity. Can be a Session Ticket, or a reference to a saved
|
|
// session. See RFC 8446, Section 4.2.11.
|
|
type pskIdentity struct {
|
|
label []byte
|
|
obfuscatedTicketAge uint32
|
|
}
|
|
|
|
// TLS Elliptic Curve Point Formats
|
|
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
|
|
const (
|
|
pointFormatUncompressed uint8 = 0
|
|
)
|
|
|
|
// TLS CertificateStatusType (RFC 3546)
|
|
const (
|
|
statusTypeOCSP uint8 = 1
|
|
)
|
|
|
|
// Certificate types (for certificateRequestMsg)
|
|
const (
|
|
certTypeRSASign = 1
|
|
certTypeECDSASign = 64 // ECDSA or EdDSA keys, see RFC 8422, Section 3.
|
|
)
|
|
|
|
// Signature algorithms (for internal signaling use). Starting at 225 to avoid overlap with
|
|
// TLS 1.2 codepoints (RFC 5246, Appendix A.4.1), with which these have nothing to do.
|
|
const (
|
|
signaturePKCS1v15 uint8 = iota + 225
|
|
signatureRSAPSS
|
|
signatureECDSA
|
|
signatureEd25519
|
|
)
|
|
|
|
// directSigning is a standard Hash value that signals that no pre-hashing
|
|
// should be performed, and that the input should be signed directly. It is the
|
|
// hash function associated with the Ed25519 signature scheme.
|
|
var directSigning crypto.Hash = 0
|
|
|
|
// defaultSupportedSignatureAlgorithms contains the signature and hash algorithms that
|
|
// the code advertises as supported in a TLS 1.2+ ClientHello and in a TLS 1.2+
|
|
// CertificateRequest. The two fields are merged to match with TLS 1.3.
|
|
// Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc.
|
|
var defaultSupportedSignatureAlgorithms = []SignatureScheme{
|
|
PSSWithSHA256,
|
|
ECDSAWithP256AndSHA256,
|
|
Ed25519,
|
|
PSSWithSHA384,
|
|
PSSWithSHA512,
|
|
PKCS1WithSHA256,
|
|
PKCS1WithSHA384,
|
|
PKCS1WithSHA512,
|
|
ECDSAWithP384AndSHA384,
|
|
ECDSAWithP521AndSHA512,
|
|
PKCS1WithSHA1,
|
|
ECDSAWithSHA1,
|
|
}
|
|
|
|
// helloRetryRequestRandom is set as the Random value of a ServerHello
|
|
// to signal that the message is actually a HelloRetryRequest.
|
|
var helloRetryRequestRandom = []byte{ // See RFC 8446, Section 4.1.3.
|
|
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
|
|
0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
|
|
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
|
|
0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C,
|
|
}
|
|
|
|
const (
|
|
// downgradeCanaryTLS12 or downgradeCanaryTLS11 is embedded in the server
|
|
// random as a downgrade protection if the server would be capable of
|
|
// negotiating a higher version. See RFC 8446, Section 4.1.3.
|
|
downgradeCanaryTLS12 = "DOWNGRD\x01"
|
|
downgradeCanaryTLS11 = "DOWNGRD\x00"
|
|
)
|
|
|
|
// testingOnlyForceDowngradeCanary is set in tests to force the server side to
|
|
// include downgrade canaries even if it's using its highers supported version.
|
|
var testingOnlyForceDowngradeCanary bool
|
|
|
|
// ConnectionState records basic TLS details about the connection.
|
|
type ConnectionState struct {
|
|
// Version is the TLS version used by the connection (e.g. VersionTLS12).
|
|
Version uint16
|
|
|
|
// HandshakeComplete is true if the handshake has concluded.
|
|
HandshakeComplete bool
|
|
|
|
// DidResume is true if this connection was successfully resumed from a
|
|
// previous session with a session ticket or similar mechanism.
|
|
DidResume bool
|
|
|
|
// CipherSuite is the cipher suite negotiated for the connection (e.g.
|
|
// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_AES_128_GCM_SHA256).
|
|
CipherSuite uint16
|
|
|
|
// NegotiatedProtocol is the application protocol negotiated with ALPN.
|
|
NegotiatedProtocol string
|
|
|
|
// NegotiatedProtocolIsMutual used to indicate a mutual NPN negotiation.
|
|
//
|
|
// Deprecated: this value is always true.
|
|
NegotiatedProtocolIsMutual bool
|
|
|
|
// ServerName is the value of the Server Name Indication extension sent by
|
|
// the client. It's available both on the server and on the client side.
|
|
ServerName string
|
|
|
|
// PeerCertificates are the parsed certificates sent by the peer, in the
|
|
// order in which they were sent. The first element is the leaf certificate
|
|
// that the connection is verified against.
|
|
//
|
|
// On the client side, it can't be empty. On the server side, it can be
|
|
// empty if Config.ClientAuth is not RequireAnyClientCert or
|
|
// RequireAndVerifyClientCert.
|
|
PeerCertificates []*x509.Certificate
|
|
|
|
// VerifiedChains is a list of one or more chains where the first element is
|
|
// PeerCertificates[0] and the last element is from Config.RootCAs (on the
|
|
// client side) or Config.ClientCAs (on the server side).
|
|
//
|
|
// On the client side, it's set if Config.InsecureSkipVerify is false. On
|
|
// the server side, it's set if Config.ClientAuth is VerifyClientCertIfGiven
|
|
// (and the peer provided a certificate) or RequireAndVerifyClientCert.
|
|
VerifiedChains [][]*x509.Certificate
|
|
|
|
// SignedCertificateTimestamps is a list of SCTs provided by the peer
|
|
// through the TLS handshake for the leaf certificate, if any.
|
|
SignedCertificateTimestamps [][]byte
|
|
|
|
// OCSPResponse is a stapled Online Certificate Status Protocol (OCSP)
|
|
// response provided by the peer for the leaf certificate, if any.
|
|
OCSPResponse []byte
|
|
|
|
// TLSUnique contains the "tls-unique" channel binding value (see RFC 5929,
|
|
// Section 3). This value will be nil for TLS 1.3 connections and for all
|
|
// resumed connections.
|
|
//
|
|
// Deprecated: there are conditions in which this value might not be unique
|
|
// to a connection. See the Security Considerations sections of RFC 5705 and
|
|
// RFC 7627, and https://mitls.org/pages/attacks/3SHAKE#channelbindings.
|
|
TLSUnique []byte
|
|
|
|
// ekm is a closure exposed via ExportKeyingMaterial.
|
|
ekm func(label string, context []byte, length int) ([]byte, error)
|
|
}
|
|
|
|
// ExportKeyingMaterial returns length bytes of exported key material in a new
|
|
// slice as defined in RFC 5705. If context is nil, it is not used as part of
|
|
// the seed. If the connection was set to allow renegotiation via
|
|
// Config.Renegotiation, this function will return an error.
|
|
func (cs *ConnectionState) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
|
|
return cs.ekm(label, context, length)
|
|
}
|
|
|
|
// ClientAuthType declares the policy the server will follow for
|
|
// TLS Client Authentication.
|
|
type ClientAuthType int
|
|
|
|
const (
|
|
// NoClientCert indicates that no client certificate should be requested
|
|
// during the handshake, and if any certificates are sent they will not
|
|
// be verified.
|
|
NoClientCert ClientAuthType = iota
|
|
// RequestClientCert indicates that a client certificate should be requested
|
|
// during the handshake, but does not require that the client send any
|
|
// certificates.
|
|
RequestClientCert
|
|
// RequireAnyClientCert indicates that a client certificate should be requested
|
|
// during the handshake, and that at least one certificate is required to be
|
|
// sent by the client, but that certificate is not required to be valid.
|
|
RequireAnyClientCert
|
|
// VerifyClientCertIfGiven indicates that a client certificate should be requested
|
|
// during the handshake, but does not require that the client sends a
|
|
// certificate. If the client does send a certificate it is required to be
|
|
// valid.
|
|
VerifyClientCertIfGiven
|
|
// RequireAndVerifyClientCert indicates that a client certificate should be requested
|
|
// during the handshake, and that at least one valid certificate is required
|
|
// to be sent by the client.
|
|
RequireAndVerifyClientCert
|
|
)
|
|
|
|
// requiresClientCert reports whether the ClientAuthType requires a client
|
|
// certificate to be provided.
|
|
func requiresClientCert(c ClientAuthType) bool {
|
|
switch c {
|
|
case RequireAnyClientCert, RequireAndVerifyClientCert:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// ClientSessionState contains the state needed by clients to resume TLS
|
|
// sessions.
|
|
type ClientSessionState struct {
|
|
sessionTicket []uint8 // Encrypted ticket used for session resumption with server
|
|
vers uint16 // TLS version negotiated for the session
|
|
cipherSuite uint16 // Ciphersuite negotiated for the session
|
|
masterSecret []byte // Full handshake MasterSecret, or TLS 1.3 resumption_master_secret
|
|
serverCertificates []*x509.Certificate // Certificate chain presented by the server
|
|
verifiedChains [][]*x509.Certificate // Certificate chains we built for verification
|
|
receivedAt time.Time // When the session ticket was received from the server
|
|
ocspResponse []byte // Stapled OCSP response presented by the server
|
|
scts [][]byte // SCTs presented by the server
|
|
|
|
// TLS 1.3 fields.
|
|
nonce []byte // Ticket nonce sent by the server, to derive PSK
|
|
useBy time.Time // Expiration of the ticket lifetime as set by the server
|
|
ageAdd uint32 // Random obfuscation factor for sending the ticket age
|
|
}
|
|
|
|
// ClientSessionCache is a cache of ClientSessionState objects that can be used
|
|
// by a client to resume a TLS session with a given server. ClientSessionCache
|
|
// implementations should expect to be called concurrently from different
|
|
// goroutines. Up to TLS 1.2, only ticket-based resumption is supported, not
|
|
// SessionID-based resumption. In TLS 1.3 they were merged into PSK modes, which
|
|
// are supported via this interface.
|
|
type ClientSessionCache interface {
|
|
// Get searches for a ClientSessionState associated with the given key.
|
|
// On return, ok is true if one was found.
|
|
Get(sessionKey string) (session *ClientSessionState, ok bool)
|
|
|
|
// Put adds the ClientSessionState to the cache with the given key. It might
|
|
// get called multiple times in a connection if a TLS 1.3 server provides
|
|
// more than one session ticket. If called with a nil *ClientSessionState,
|
|
// it should remove the cache entry.
|
|
Put(sessionKey string, cs *ClientSessionState)
|
|
}
|
|
|
|
//go:generate stringer -type=SignatureScheme,CurveID,ClientAuthType -output=common_string.go
|
|
|
|
// SignatureScheme identifies a signature algorithm supported by TLS. See
|
|
// RFC 8446, Section 4.2.3.
|
|
type SignatureScheme uint16
|
|
|
|
const (
|
|
// RSASSA-PKCS1-v1_5 algorithms.
|
|
PKCS1WithSHA256 SignatureScheme = 0x0401
|
|
PKCS1WithSHA384 SignatureScheme = 0x0501
|
|
PKCS1WithSHA512 SignatureScheme = 0x0601
|
|
|
|
// RSASSA-PSS algorithms with public key OID rsaEncryption.
|
|
PSSWithSHA256 SignatureScheme = 0x0804
|
|
PSSWithSHA384 SignatureScheme = 0x0805
|
|
PSSWithSHA512 SignatureScheme = 0x0806
|
|
|
|
// ECDSA algorithms. Only constrained to a specific curve in TLS 1.3.
|
|
ECDSAWithP256AndSHA256 SignatureScheme = 0x0403
|
|
ECDSAWithP384AndSHA384 SignatureScheme = 0x0503
|
|
ECDSAWithP521AndSHA512 SignatureScheme = 0x0603
|
|
|
|
// EdDSA algorithms.
|
|
Ed25519 SignatureScheme = 0x0807
|
|
|
|
// Legacy signature and hash algorithms for TLS 1.2.
|
|
PKCS1WithSHA1 SignatureScheme = 0x0201
|
|
ECDSAWithSHA1 SignatureScheme = 0x0203
|
|
)
|
|
|
|
// ClientHelloInfo contains information from a ClientHello message in order to
|
|
// guide application logic in the GetCertificate and GetConfigForClient callbacks.
|
|
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 []uint16
|
|
|
|
// ServerName indicates the name of the server requested by the client
|
|
// in order to support virtual hosting. ServerName is only set if the
|
|
// client is using SNI (see RFC 4366, Section 3.1).
|
|
ServerName string
|
|
|
|
// SupportedCurves lists the elliptic curves supported by the client.
|
|
// SupportedCurves is set only if the Supported Elliptic Curves
|
|
// Extension is being used (see RFC 4492, Section 5.1.1).
|
|
SupportedCurves []CurveID
|
|
|
|
// SupportedPoints lists the point formats supported by the client.
|
|
// SupportedPoints is set only if the Supported Point Formats Extension
|
|
// is being used (see RFC 4492, Section 5.1.2).
|
|
SupportedPoints []uint8
|
|
|
|
// SignatureSchemes lists the signature and hash schemes that the client
|
|
// is willing to verify. SignatureSchemes is set only if the Signature
|
|
// Algorithms Extension is being used (see RFC 5246, Section 7.4.1.4.1).
|
|
SignatureSchemes []SignatureScheme
|
|
|
|
// SupportedProtos lists the application protocols supported by the client.
|
|
// SupportedProtos is set only if the Application-Layer Protocol
|
|
// Negotiation Extension is being used (see RFC 7301, Section 3.1).
|
|
//
|
|
// Servers can select a protocol by setting Config.NextProtos in a
|
|
// GetConfigForClient return value.
|
|
SupportedProtos []string
|
|
|
|
// SupportedVersions lists the TLS versions supported by the client.
|
|
// For TLS versions less than 1.3, this is extrapolated from the max
|
|
// version advertised by the client, so values other than the greatest
|
|
// might be rejected if used.
|
|
SupportedVersions []uint16
|
|
|
|
// Conn is the underlying net.Conn for the connection. Do not read
|
|
// from, or write to, this connection; that will cause the TLS
|
|
// connection to fail.
|
|
Conn net.Conn
|
|
|
|
// config is embedded by the GetCertificate or GetConfigForClient caller,
|
|
// for use with SupportsCertificate.
|
|
config *Config
|
|
|
|
// ctx is the context of the handshake that is in progress.
|
|
ctx context.Context
|
|
}
|
|
|
|
// Context returns the context of the handshake that is in progress.
|
|
// This context is a child of the context passed to HandshakeContext,
|
|
// if any, and is canceled when the handshake concludes.
|
|
func (c *ClientHelloInfo) Context() context.Context {
|
|
return c.ctx
|
|
}
|
|
|
|
// CertificateRequestInfo contains information from a server's
|
|
// CertificateRequest message, which is used to demand a certificate and proof
|
|
// of control from a client.
|
|
type CertificateRequestInfo struct {
|
|
// AcceptableCAs contains zero or more, DER-encoded, X.501
|
|
// Distinguished Names. These are the names of root or intermediate CAs
|
|
// that the server wishes the returned certificate to be signed by. An
|
|
// empty slice indicates that the server has no preference.
|
|
AcceptableCAs [][]byte
|
|
|
|
// SignatureSchemes lists the signature schemes that the server is
|
|
// willing to verify.
|
|
SignatureSchemes []SignatureScheme
|
|
|
|
// Version is the TLS version that was negotiated for this connection.
|
|
Version uint16
|
|
|
|
// ctx is the context of the handshake that is in progress.
|
|
ctx context.Context
|
|
}
|
|
|
|
// Context returns the context of the handshake that is in progress.
|
|
// This context is a child of the context passed to HandshakeContext,
|
|
// if any, and is canceled when the handshake concludes.
|
|
func (c *CertificateRequestInfo) Context() context.Context {
|
|
return c.ctx
|
|
}
|
|
|
|
// RenegotiationSupport enumerates the different levels of support for TLS
|
|
// renegotiation. TLS renegotiation is the act of performing subsequent
|
|
// handshakes on a connection after the first. This significantly complicates
|
|
// the state machine and has been the source of numerous, subtle security
|
|
// issues. Initiating a renegotiation is not supported, but support for
|
|
// accepting renegotiation requests may be enabled.
|
|
//
|
|
// Even when enabled, the server may not change its identity between handshakes
|
|
// (i.e. the leaf certificate must be the same). Additionally, concurrent
|
|
// handshake and application data flow is not permitted so renegotiation can
|
|
// only be used with protocols that synchronise with the renegotiation, such as
|
|
// HTTPS.
|
|
//
|
|
// Renegotiation is not defined in TLS 1.3.
|
|
type RenegotiationSupport int
|
|
|
|
const (
|
|
// RenegotiateNever disables renegotiation.
|
|
RenegotiateNever RenegotiationSupport = iota
|
|
|
|
// RenegotiateOnceAsClient allows a remote server to request
|
|
// renegotiation once per connection.
|
|
RenegotiateOnceAsClient
|
|
|
|
// RenegotiateFreelyAsClient allows a remote server to repeatedly
|
|
// request renegotiation.
|
|
RenegotiateFreelyAsClient
|
|
)
|
|
|
|
// A Config structure is used to configure a TLS client or server.
|
|
// After one has been passed to a TLS function it must not be
|
|
// modified. A Config may be reused; the tls package will also not
|
|
// modify it.
|
|
type Config struct {
|
|
// Rand provides the source of entropy for nonces and RSA blinding.
|
|
// If Rand is nil, TLS uses the cryptographic random reader in package
|
|
// crypto/rand.
|
|
// The Reader must be safe for use by multiple goroutines.
|
|
Rand io.Reader
|
|
|
|
// Time returns the current time as the number of seconds since the epoch.
|
|
// If Time is nil, TLS uses time.Now.
|
|
Time func() time.Time
|
|
|
|
// Certificates contains one or more certificate chains to present to the
|
|
// other side of the connection. The first certificate compatible with the
|
|
// peer's requirements is selected automatically.
|
|
//
|
|
// Server configurations must set one of Certificates, GetCertificate or
|
|
// GetConfigForClient. Clients doing client-authentication may set either
|
|
// Certificates or GetClientCertificate.
|
|
//
|
|
// Note: if there are multiple Certificates, and they don't have the
|
|
// optional field Leaf set, certificate selection will incur a significant
|
|
// per-handshake performance cost.
|
|
Certificates []Certificate
|
|
|
|
// NameToCertificate maps from a certificate name to an element of
|
|
// Certificates. Note that a certificate name can be of the form
|
|
// '*.example.com' and so doesn't have to be a domain name as such.
|
|
//
|
|
// Deprecated: NameToCertificate only allows associating a single
|
|
// certificate with a given name. Leave this field nil to let the library
|
|
// select the first compatible chain from Certificates.
|
|
NameToCertificate map[string]*Certificate
|
|
|
|
// GetCertificate returns a Certificate based on the given
|
|
// ClientHelloInfo. It will only be called if the client supplies SNI
|
|
// information or if Certificates is empty.
|
|
//
|
|
// If GetCertificate is nil or returns nil, then the certificate is
|
|
// retrieved from NameToCertificate. If NameToCertificate is nil, the
|
|
// best element of Certificates will be used.
|
|
GetCertificate func(*ClientHelloInfo) (*Certificate, error)
|
|
|
|
// GetClientCertificate, if not nil, is called when a server requests a
|
|
// certificate from a client. If set, the contents of Certificates will
|
|
// be ignored.
|
|
//
|
|
// If GetClientCertificate returns an error, the handshake will be
|
|
// aborted and that error will be returned. Otherwise
|
|
// GetClientCertificate must return a non-nil Certificate. If
|
|
// Certificate.Certificate is empty then no certificate will be sent to
|
|
// the server. If this is unacceptable to the server then it may abort
|
|
// the handshake.
|
|
//
|
|
// GetClientCertificate may be called multiple times for the same
|
|
// connection if renegotiation occurs or if TLS 1.3 is in use.
|
|
GetClientCertificate func(*CertificateRequestInfo) (*Certificate, error)
|
|
|
|
// GetConfigForClient, if not nil, is called after a ClientHello is
|
|
// received from a client. It may return a non-nil Config in order to
|
|
// change the Config that will be used to handle this connection. If
|
|
// the returned Config is nil, the original Config will be used. The
|
|
// Config returned by this callback may not be subsequently modified.
|
|
//
|
|
// If GetConfigForClient is nil, the Config passed to Server() will be
|
|
// used for all connections.
|
|
//
|
|
// If SessionTicketKey was explicitly set on the returned Config, or if
|
|
// SetSessionTicketKeys was called on the returned Config, those keys will
|
|
// be used. Otherwise, the original Config keys will be used (and possibly
|
|
// rotated if they are automatically managed).
|
|
GetConfigForClient func(*ClientHelloInfo) (*Config, error)
|
|
|
|
// VerifyPeerCertificate, if not nil, is called after normal
|
|
// certificate verification by either a TLS client or server. It
|
|
// receives the raw ASN.1 certificates provided by the peer and also
|
|
// any verified chains that normal processing found. If it returns a
|
|
// non-nil error, the handshake is aborted and that error results.
|
|
//
|
|
// If normal verification fails then the handshake will abort before
|
|
// considering this callback. If normal verification is disabled by
|
|
// setting InsecureSkipVerify, or (for a server) when ClientAuth is
|
|
// RequestClientCert or RequireAnyClientCert, then this callback will
|
|
// be considered but the verifiedChains argument will always be nil.
|
|
VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
|
|
|
|
// VerifyConnection, if not nil, is called after normal certificate
|
|
// verification and after VerifyPeerCertificate by either a TLS client
|
|
// or server. If it returns a non-nil error, the handshake is aborted
|
|
// and that error results.
|
|
//
|
|
// If normal verification fails then the handshake will abort before
|
|
// considering this callback. This callback will run for all connections
|
|
// regardless of InsecureSkipVerify or ClientAuth settings.
|
|
VerifyConnection func(ConnectionState) error
|
|
|
|
// RootCAs defines the set of root certificate authorities
|
|
// that clients use when verifying server certificates.
|
|
// If RootCAs is nil, TLS uses the host's root CA set.
|
|
RootCAs *x509.CertPool
|
|
|
|
// NextProtos is a list of supported application level protocols, in
|
|
// order of preference. If both peers support ALPN, the selected
|
|
// protocol will be one from this list, and the connection will fail
|
|
// if there is no mutually supported protocol. If NextProtos is empty
|
|
// or the peer doesn't support ALPN, the connection will succeed and
|
|
// ConnectionState.NegotiatedProtocol will be empty.
|
|
NextProtos []string
|
|
|
|
// ServerName is used to verify the hostname on the returned
|
|
// certificates unless InsecureSkipVerify is given. It is also included
|
|
// in the client's handshake to support virtual hosting unless it is
|
|
// an IP address.
|
|
ServerName string
|
|
|
|
// ClientAuth determines the server's policy for
|
|
// TLS Client Authentication. The default is NoClientCert.
|
|
ClientAuth ClientAuthType
|
|
|
|
// ClientCAs defines the set of root certificate authorities
|
|
// that servers use if required to verify a client certificate
|
|
// by the policy in ClientAuth.
|
|
ClientCAs *x509.CertPool
|
|
|
|
// InsecureSkipVerify controls whether a client verifies the server's
|
|
// certificate chain and host name. If InsecureSkipVerify is true, crypto/tls
|
|
// accepts any certificate presented by the server and any host name in that
|
|
// certificate. In this mode, TLS is susceptible to machine-in-the-middle
|
|
// attacks unless custom verification is used. This should be used only for
|
|
// testing or in combination with VerifyConnection or VerifyPeerCertificate.
|
|
InsecureSkipVerify bool
|
|
|
|
// CipherSuites is a list of enabled TLS 1.0–1.2 cipher suites. The order of
|
|
// the list is ignored. Note that TLS 1.3 ciphersuites are not configurable.
|
|
//
|
|
// If CipherSuites is nil, a safe default list is used. The default cipher
|
|
// suites might change over time.
|
|
CipherSuites []uint16
|
|
|
|
// PreferServerCipherSuites is a legacy field and has no effect.
|
|
//
|
|
// It used to control whether the server would follow the client's or the
|
|
// server's preference. Servers now select the best mutually supported
|
|
// cipher suite based on logic that takes into account inferred client
|
|
// hardware, server hardware, and security.
|
|
//
|
|
// Deprecated: PreferServerCipherSuites is ignored.
|
|
PreferServerCipherSuites bool
|
|
|
|
// SessionTicketsDisabled may be set to true to disable session ticket and
|
|
// PSK (resumption) support. Note that on clients, session ticket support is
|
|
// also disabled if ClientSessionCache is nil.
|
|
SessionTicketsDisabled bool
|
|
|
|
// SessionTicketKey is used by TLS servers to provide session resumption.
|
|
// See RFC 5077 and the PSK mode of RFC 8446. If zero, it will be filled
|
|
// with random data before the first server handshake.
|
|
//
|
|
// Deprecated: if this field is left at zero, session ticket keys will be
|
|
// automatically rotated every day and dropped after seven days. For
|
|
// customizing the rotation schedule or synchronizing servers that are
|
|
// terminating connections for the same host, use SetSessionTicketKeys.
|
|
SessionTicketKey [32]byte
|
|
|
|
// ClientSessionCache is a cache of ClientSessionState entries for TLS
|
|
// session resumption. It is only used by clients.
|
|
ClientSessionCache ClientSessionCache
|
|
|
|
// MinVersion contains the minimum TLS version that is acceptable.
|
|
//
|
|
// By default, TLS 1.2 is currently used as the minimum when acting as a
|
|
// client, and TLS 1.0 when acting as a server. TLS 1.0 is the minimum
|
|
// supported by this package, both as a client and as a server.
|
|
//
|
|
// The client-side default can temporarily be reverted to TLS 1.0 by
|
|
// including the value "x509sha1=1" in the GODEBUG environment variable.
|
|
// Note that this option will be removed in Go 1.19 (but it will still be
|
|
// possible to set this field to VersionTLS10 explicitly).
|
|
MinVersion uint16
|
|
|
|
// MaxVersion contains the maximum TLS version that is acceptable.
|
|
//
|
|
// By default, the maximum version supported by this package is used,
|
|
// which is currently TLS 1.3.
|
|
MaxVersion uint16
|
|
|
|
// CurvePreferences contains the elliptic curves that will be used in
|
|
// an ECDHE handshake, in preference order. If empty, the default will
|
|
// be used. The client will use the first preference as the type for
|
|
// its key share in TLS 1.3. This may change in the future.
|
|
CurvePreferences []CurveID
|
|
|
|
// DynamicRecordSizingDisabled disables adaptive sizing of TLS records.
|
|
// When true, the largest possible TLS record size is always used. When
|
|
// false, the size of TLS records may be adjusted in an attempt to
|
|
// improve latency.
|
|
DynamicRecordSizingDisabled bool
|
|
|
|
// Renegotiation controls what types of renegotiation are supported.
|
|
// The default, none, is correct for the vast majority of applications.
|
|
Renegotiation RenegotiationSupport
|
|
|
|
// KeyLogWriter optionally specifies a destination for TLS master secrets
|
|
// in NSS key log format that can be used to allow external programs
|
|
// such as Wireshark to decrypt TLS connections.
|
|
// See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.
|
|
// Use of KeyLogWriter compromises security and should only be
|
|
// used for debugging.
|
|
KeyLogWriter io.Writer
|
|
|
|
// mutex protects sessionTicketKeys and autoSessionTicketKeys.
|
|
mutex sync.RWMutex
|
|
// sessionTicketKeys contains zero or more ticket keys. If set, it means the
|
|
// the keys were set with SessionTicketKey or SetSessionTicketKeys. The
|
|
// first key is used for new tickets and any subsequent keys can be used to
|
|
// decrypt old tickets. The slice contents are not protected by the mutex
|
|
// and are immutable.
|
|
sessionTicketKeys []ticketKey
|
|
// autoSessionTicketKeys is like sessionTicketKeys but is owned by the
|
|
// auto-rotation logic. See Config.ticketKeys.
|
|
autoSessionTicketKeys []ticketKey
|
|
}
|
|
|
|
const (
|
|
// ticketKeyNameLen is the number of bytes of identifier that is prepended to
|
|
// an encrypted session ticket in order to identify the key used to encrypt it.
|
|
ticketKeyNameLen = 16
|
|
|
|
// ticketKeyLifetime is how long a ticket key remains valid and can be used to
|
|
// resume a client connection.
|
|
ticketKeyLifetime = 7 * 24 * time.Hour // 7 days
|
|
|
|
// ticketKeyRotation is how often the server should rotate the session ticket key
|
|
// that is used for new tickets.
|
|
ticketKeyRotation = 24 * time.Hour
|
|
)
|
|
|
|
// ticketKey is the internal representation of a session ticket key.
|
|
type ticketKey struct {
|
|
// keyName is an opaque byte string that serves to identify the session
|
|
// ticket key. It's exposed as plaintext in every session ticket.
|
|
keyName [ticketKeyNameLen]byte
|
|
aesKey [16]byte
|
|
hmacKey [16]byte
|
|
// created is the time at which this ticket key was created. See Config.ticketKeys.
|
|
created time.Time
|
|
}
|
|
|
|
// ticketKeyFromBytes converts from the external representation of a session
|
|
// ticket key to a ticketKey. Externally, session ticket keys are 32 random
|
|
// bytes and this function expands that into sufficient name and key material.
|
|
func (c *Config) ticketKeyFromBytes(b [32]byte) (key ticketKey) {
|
|
hashed := sha512.Sum512(b[:])
|
|
copy(key.keyName[:], hashed[:ticketKeyNameLen])
|
|
copy(key.aesKey[:], hashed[ticketKeyNameLen:ticketKeyNameLen+16])
|
|
copy(key.hmacKey[:], hashed[ticketKeyNameLen+16:ticketKeyNameLen+32])
|
|
key.created = c.time()
|
|
return key
|
|
}
|
|
|
|
// maxSessionTicketLifetime is the maximum allowed lifetime of a TLS 1.3 session
|
|
// ticket, and the lifetime we set for tickets we send.
|
|
const maxSessionTicketLifetime = 7 * 24 * time.Hour
|
|
|
|
// Clone returns a shallow clone of c or nil if c is nil. It is safe to clone a Config that is
|
|
// being used concurrently by a TLS client or server.
|
|
func (c *Config) Clone() *Config {
|
|
if c == nil {
|
|
return nil
|
|
}
|
|
c.mutex.RLock()
|
|
defer c.mutex.RUnlock()
|
|
return &Config{
|
|
Rand: c.Rand,
|
|
Time: c.Time,
|
|
Certificates: c.Certificates,
|
|
NameToCertificate: c.NameToCertificate,
|
|
GetCertificate: c.GetCertificate,
|
|
GetClientCertificate: c.GetClientCertificate,
|
|
GetConfigForClient: c.GetConfigForClient,
|
|
VerifyPeerCertificate: c.VerifyPeerCertificate,
|
|
VerifyConnection: c.VerifyConnection,
|
|
RootCAs: c.RootCAs,
|
|
NextProtos: c.NextProtos,
|
|
ServerName: c.ServerName,
|
|
ClientAuth: c.ClientAuth,
|
|
ClientCAs: c.ClientCAs,
|
|
InsecureSkipVerify: c.InsecureSkipVerify,
|
|
CipherSuites: c.CipherSuites,
|
|
PreferServerCipherSuites: c.PreferServerCipherSuites,
|
|
SessionTicketsDisabled: c.SessionTicketsDisabled,
|
|
SessionTicketKey: c.SessionTicketKey,
|
|
ClientSessionCache: c.ClientSessionCache,
|
|
MinVersion: c.MinVersion,
|
|
MaxVersion: c.MaxVersion,
|
|
CurvePreferences: c.CurvePreferences,
|
|
DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
|
|
Renegotiation: c.Renegotiation,
|
|
KeyLogWriter: c.KeyLogWriter,
|
|
sessionTicketKeys: c.sessionTicketKeys,
|
|
autoSessionTicketKeys: c.autoSessionTicketKeys,
|
|
}
|
|
}
|
|
|
|
// deprecatedSessionTicketKey is set as the prefix of SessionTicketKey if it was
|
|
// randomized for backwards compatibility but is not in use.
|
|
var deprecatedSessionTicketKey = []byte("DEPRECATED")
|
|
|
|
// initLegacySessionTicketKeyRLocked ensures the legacy SessionTicketKey field is
|
|
// randomized if empty, and that sessionTicketKeys is populated from it otherwise.
|
|
func (c *Config) initLegacySessionTicketKeyRLocked() {
|
|
// Don't write if SessionTicketKey is already defined as our deprecated string,
|
|
// or if it is defined by the user but sessionTicketKeys is already set.
|
|
if c.SessionTicketKey != [32]byte{} &&
|
|
(bytes.HasPrefix(c.SessionTicketKey[:], deprecatedSessionTicketKey) || len(c.sessionTicketKeys) > 0) {
|
|
return
|
|
}
|
|
|
|
// We need to write some data, so get an exclusive lock and re-check any conditions.
|
|
c.mutex.RUnlock()
|
|
defer c.mutex.RLock()
|
|
c.mutex.Lock()
|
|
defer c.mutex.Unlock()
|
|
if c.SessionTicketKey == [32]byte{} {
|
|
if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil {
|
|
panic(fmt.Sprintf("tls: unable to generate random session ticket key: %v", err))
|
|
}
|
|
// Write the deprecated prefix at the beginning so we know we created
|
|
// it. This key with the DEPRECATED prefix isn't used as an actual
|
|
// session ticket key, and is only randomized in case the application
|
|
// reuses it for some reason.
|
|
copy(c.SessionTicketKey[:], deprecatedSessionTicketKey)
|
|
} else if !bytes.HasPrefix(c.SessionTicketKey[:], deprecatedSessionTicketKey) && len(c.sessionTicketKeys) == 0 {
|
|
c.sessionTicketKeys = []ticketKey{c.ticketKeyFromBytes(c.SessionTicketKey)}
|
|
}
|
|
|
|
}
|
|
|
|
// ticketKeys returns the ticketKeys for this connection.
|
|
// If configForClient has explicitly set keys, those will
|
|
// be returned. Otherwise, the keys on c will be used and
|
|
// may be rotated if auto-managed.
|
|
// During rotation, any expired session ticket keys are deleted from
|
|
// c.sessionTicketKeys. If the session ticket key that is currently
|
|
// encrypting tickets (ie. the first ticketKey in c.sessionTicketKeys)
|
|
// is not fresh, then a new session ticket key will be
|
|
// created and prepended to c.sessionTicketKeys.
|
|
func (c *Config) ticketKeys(configForClient *Config) []ticketKey {
|
|
// If the ConfigForClient callback returned a Config with explicitly set
|
|
// keys, use those, otherwise just use the original Config.
|
|
if configForClient != nil {
|
|
configForClient.mutex.RLock()
|
|
if configForClient.SessionTicketsDisabled {
|
|
return nil
|
|
}
|
|
configForClient.initLegacySessionTicketKeyRLocked()
|
|
if len(configForClient.sessionTicketKeys) != 0 {
|
|
ret := configForClient.sessionTicketKeys
|
|
configForClient.mutex.RUnlock()
|
|
return ret
|
|
}
|
|
configForClient.mutex.RUnlock()
|
|
}
|
|
|
|
c.mutex.RLock()
|
|
defer c.mutex.RUnlock()
|
|
if c.SessionTicketsDisabled {
|
|
return nil
|
|
}
|
|
c.initLegacySessionTicketKeyRLocked()
|
|
if len(c.sessionTicketKeys) != 0 {
|
|
return c.sessionTicketKeys
|
|
}
|
|
// Fast path for the common case where the key is fresh enough.
|
|
if len(c.autoSessionTicketKeys) > 0 && c.time().Sub(c.autoSessionTicketKeys[0].created) < ticketKeyRotation {
|
|
return c.autoSessionTicketKeys
|
|
}
|
|
|
|
// autoSessionTicketKeys are managed by auto-rotation.
|
|
c.mutex.RUnlock()
|
|
defer c.mutex.RLock()
|
|
c.mutex.Lock()
|
|
defer c.mutex.Unlock()
|
|
// Re-check the condition in case it changed since obtaining the new lock.
|
|
if len(c.autoSessionTicketKeys) == 0 || c.time().Sub(c.autoSessionTicketKeys[0].created) >= ticketKeyRotation {
|
|
var newKey [32]byte
|
|
if _, err := io.ReadFull(c.rand(), newKey[:]); err != nil {
|
|
panic(fmt.Sprintf("unable to generate random session ticket key: %v", err))
|
|
}
|
|
valid := make([]ticketKey, 0, len(c.autoSessionTicketKeys)+1)
|
|
valid = append(valid, c.ticketKeyFromBytes(newKey))
|
|
for _, k := range c.autoSessionTicketKeys {
|
|
// While rotating the current key, also remove any expired ones.
|
|
if c.time().Sub(k.created) < ticketKeyLifetime {
|
|
valid = append(valid, k)
|
|
}
|
|
}
|
|
c.autoSessionTicketKeys = valid
|
|
}
|
|
return c.autoSessionTicketKeys
|
|
}
|
|
|
|
// SetSessionTicketKeys updates the session ticket keys for a server.
|
|
//
|
|
// The first key will be used when creating new tickets, while all keys can be
|
|
// used for decrypting tickets. It is safe to call this function while the
|
|
// server is running in order to rotate the session ticket keys. The function
|
|
// will panic if keys is empty.
|
|
//
|
|
// Calling this function will turn off automatic session ticket key rotation.
|
|
//
|
|
// If multiple servers are terminating connections for the same host they should
|
|
// all have the same session ticket keys. If the session ticket keys leaks,
|
|
// previously recorded and future TLS connections using those keys might be
|
|
// compromised.
|
|
func (c *Config) SetSessionTicketKeys(keys [][32]byte) {
|
|
if len(keys) == 0 {
|
|
panic("tls: keys must have at least one key")
|
|
}
|
|
|
|
newKeys := make([]ticketKey, len(keys))
|
|
for i, bytes := range keys {
|
|
newKeys[i] = c.ticketKeyFromBytes(bytes)
|
|
}
|
|
|
|
c.mutex.Lock()
|
|
c.sessionTicketKeys = newKeys
|
|
c.mutex.Unlock()
|
|
}
|
|
|
|
func (c *Config) rand() io.Reader {
|
|
r := c.Rand
|
|
if r == nil {
|
|
return rand.Reader
|
|
}
|
|
return r
|
|
}
|
|
|
|
func (c *Config) time() time.Time {
|
|
t := c.Time
|
|
if t == nil {
|
|
t = time.Now
|
|
}
|
|
return t()
|
|
}
|
|
|
|
func (c *Config) cipherSuites() []uint16 {
|
|
if needFIPS() {
|
|
return fipsCipherSuites(c)
|
|
}
|
|
if c.CipherSuites != nil {
|
|
return c.CipherSuites
|
|
}
|
|
return defaultCipherSuites
|
|
}
|
|
|
|
var supportedVersions = []uint16{
|
|
VersionTLS13,
|
|
VersionTLS12,
|
|
VersionTLS11,
|
|
VersionTLS10,
|
|
}
|
|
|
|
// roleClient and roleServer are meant to call supportedVersions and parents
|
|
// with more readability at the callsite.
|
|
const roleClient = true
|
|
const roleServer = false
|
|
|
|
func (c *Config) supportedVersions(isClient bool) []uint16 {
|
|
versions := make([]uint16, 0, len(supportedVersions))
|
|
for _, v := range supportedVersions {
|
|
if needFIPS() && (v < fipsMinVersion(c) || v > fipsMaxVersion(c)) {
|
|
continue
|
|
}
|
|
if (c == nil || c.MinVersion == 0) &&
|
|
isClient && v < VersionTLS12 {
|
|
continue
|
|
}
|
|
if c != nil && c.MinVersion != 0 && v < c.MinVersion {
|
|
continue
|
|
}
|
|
if c != nil && c.MaxVersion != 0 && v > c.MaxVersion {
|
|
continue
|
|
}
|
|
versions = append(versions, v)
|
|
}
|
|
return versions
|
|
}
|
|
|
|
func (c *Config) maxSupportedVersion(isClient bool) uint16 {
|
|
supportedVersions := c.supportedVersions(isClient)
|
|
if len(supportedVersions) == 0 {
|
|
return 0
|
|
}
|
|
return supportedVersions[0]
|
|
}
|
|
|
|
// supportedVersionsFromMax returns a list of supported versions derived from a
|
|
// legacy maximum version value. Note that only versions supported by this
|
|
// library are returned. Any newer peer will use supportedVersions anyway.
|
|
func supportedVersionsFromMax(maxVersion uint16) []uint16 {
|
|
versions := make([]uint16, 0, len(supportedVersions))
|
|
for _, v := range supportedVersions {
|
|
if v > maxVersion {
|
|
continue
|
|
}
|
|
versions = append(versions, v)
|
|
}
|
|
return versions
|
|
}
|
|
|
|
var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521}
|
|
|
|
func (c *Config) curvePreferences() []CurveID {
|
|
if needFIPS() {
|
|
return fipsCurvePreferences(c)
|
|
}
|
|
if c == nil || len(c.CurvePreferences) == 0 {
|
|
return defaultCurvePreferences
|
|
}
|
|
return c.CurvePreferences
|
|
}
|
|
|
|
func (c *Config) supportsCurve(curve CurveID) bool {
|
|
for _, cc := range c.curvePreferences() {
|
|
if cc == curve {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// mutualVersion returns the protocol version to use given the advertised
|
|
// versions of the peer. Priority is given to the peer preference order.
|
|
func (c *Config) mutualVersion(isClient bool, peerVersions []uint16) (uint16, bool) {
|
|
supportedVersions := c.supportedVersions(isClient)
|
|
for _, peerVersion := range peerVersions {
|
|
for _, v := range supportedVersions {
|
|
if v == peerVersion {
|
|
return v, true
|
|
}
|
|
}
|
|
}
|
|
return 0, false
|
|
}
|
|
|
|
var errNoCertificates = errors.New("tls: no certificates configured")
|
|
|
|
// getCertificate returns the best certificate for the given ClientHelloInfo,
|
|
// defaulting to the first element of c.Certificates.
|
|
func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) {
|
|
if c.GetCertificate != nil &&
|
|
(len(c.Certificates) == 0 || len(clientHello.ServerName) > 0) {
|
|
cert, err := c.GetCertificate(clientHello)
|
|
if cert != nil || err != nil {
|
|
return cert, err
|
|
}
|
|
}
|
|
|
|
if len(c.Certificates) == 0 {
|
|
return nil, errNoCertificates
|
|
}
|
|
|
|
if len(c.Certificates) == 1 {
|
|
// There's only one choice, so no point doing any work.
|
|
return &c.Certificates[0], nil
|
|
}
|
|
|
|
if c.NameToCertificate != nil {
|
|
name := strings.ToLower(clientHello.ServerName)
|
|
if cert, ok := c.NameToCertificate[name]; ok {
|
|
return cert, nil
|
|
}
|
|
if len(name) > 0 {
|
|
labels := strings.Split(name, ".")
|
|
labels[0] = "*"
|
|
wildcardName := strings.Join(labels, ".")
|
|
if cert, ok := c.NameToCertificate[wildcardName]; ok {
|
|
return cert, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, cert := range c.Certificates {
|
|
if err := clientHello.SupportsCertificate(&cert); err == nil {
|
|
return &cert, nil
|
|
}
|
|
}
|
|
|
|
// If nothing matches, return the first certificate.
|
|
return &c.Certificates[0], nil
|
|
}
|
|
|
|
// SupportsCertificate returns nil if the provided certificate is supported by
|
|
// the client that sent the ClientHello. Otherwise, it returns an error
|
|
// describing the reason for the incompatibility.
|
|
//
|
|
// If this ClientHelloInfo was passed to a GetConfigForClient or GetCertificate
|
|
// callback, this method will take into account the associated Config. Note that
|
|
// if GetConfigForClient returns a different Config, the change can't be
|
|
// accounted for by this method.
|
|
//
|
|
// This function will call x509.ParseCertificate unless c.Leaf is set, which can
|
|
// incur a significant performance cost.
|
|
func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error {
|
|
// Note we don't currently support certificate_authorities nor
|
|
// signature_algorithms_cert, and don't check the algorithms of the
|
|
// signatures on the chain (which anyway are a SHOULD, see RFC 8446,
|
|
// Section 4.4.2.2).
|
|
|
|
config := chi.config
|
|
if config == nil {
|
|
config = &Config{}
|
|
}
|
|
vers, ok := config.mutualVersion(roleServer, chi.SupportedVersions)
|
|
if !ok {
|
|
return errors.New("no mutually supported protocol versions")
|
|
}
|
|
|
|
// If the client specified the name they are trying to connect to, the
|
|
// certificate needs to be valid for it.
|
|
if chi.ServerName != "" {
|
|
x509Cert, err := c.leaf()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to parse certificate: %w", err)
|
|
}
|
|
if err := x509Cert.VerifyHostname(chi.ServerName); err != nil {
|
|
return fmt.Errorf("certificate is not valid for requested server name: %w", err)
|
|
}
|
|
}
|
|
|
|
// supportsRSAFallback returns nil if the certificate and connection support
|
|
// the static RSA key exchange, and unsupported otherwise. The logic for
|
|
// supporting static RSA is completely disjoint from the logic for
|
|
// supporting signed key exchanges, so we just check it as a fallback.
|
|
supportsRSAFallback := func(unsupported error) error {
|
|
// TLS 1.3 dropped support for the static RSA key exchange.
|
|
if vers == VersionTLS13 {
|
|
return unsupported
|
|
}
|
|
// The static RSA key exchange works by decrypting a challenge with the
|
|
// RSA private key, not by signing, so check the PrivateKey implements
|
|
// crypto.Decrypter, like *rsa.PrivateKey does.
|
|
if priv, ok := c.PrivateKey.(crypto.Decrypter); ok {
|
|
if _, ok := priv.Public().(*rsa.PublicKey); !ok {
|
|
return unsupported
|
|
}
|
|
} else {
|
|
return unsupported
|
|
}
|
|
// Finally, there needs to be a mutual cipher suite that uses the static
|
|
// RSA key exchange instead of ECDHE.
|
|
rsaCipherSuite := selectCipherSuite(chi.CipherSuites, config.cipherSuites(), func(c *cipherSuite) bool {
|
|
if c.flags&suiteECDHE != 0 {
|
|
return false
|
|
}
|
|
if vers < VersionTLS12 && c.flags&suiteTLS12 != 0 {
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
if rsaCipherSuite == nil {
|
|
return unsupported
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// If the client sent the signature_algorithms extension, ensure it supports
|
|
// schemes we can use with this certificate and TLS version.
|
|
if len(chi.SignatureSchemes) > 0 {
|
|
if _, err := selectSignatureScheme(vers, c, chi.SignatureSchemes); err != nil {
|
|
return supportsRSAFallback(err)
|
|
}
|
|
}
|
|
|
|
// In TLS 1.3 we are done because supported_groups is only relevant to the
|
|
// ECDHE computation, point format negotiation is removed, cipher suites are
|
|
// only relevant to the AEAD choice, and static RSA does not exist.
|
|
if vers == VersionTLS13 {
|
|
return nil
|
|
}
|
|
|
|
// The only signed key exchange we support is ECDHE.
|
|
if !supportsECDHE(config, chi.SupportedCurves, chi.SupportedPoints) {
|
|
return supportsRSAFallback(errors.New("client doesn't support ECDHE, can only use legacy RSA key exchange"))
|
|
}
|
|
|
|
var ecdsaCipherSuite bool
|
|
if priv, ok := c.PrivateKey.(crypto.Signer); ok {
|
|
switch pub := priv.Public().(type) {
|
|
case *ecdsa.PublicKey:
|
|
var curve CurveID
|
|
switch pub.Curve {
|
|
case elliptic.P256():
|
|
curve = CurveP256
|
|
case elliptic.P384():
|
|
curve = CurveP384
|
|
case elliptic.P521():
|
|
curve = CurveP521
|
|
default:
|
|
return supportsRSAFallback(unsupportedCertificateError(c))
|
|
}
|
|
var curveOk bool
|
|
for _, c := range chi.SupportedCurves {
|
|
if c == curve && config.supportsCurve(c) {
|
|
curveOk = true
|
|
break
|
|
}
|
|
}
|
|
if !curveOk {
|
|
return errors.New("client doesn't support certificate curve")
|
|
}
|
|
ecdsaCipherSuite = true
|
|
case ed25519.PublicKey:
|
|
if vers < VersionTLS12 || len(chi.SignatureSchemes) == 0 {
|
|
return errors.New("connection doesn't support Ed25519")
|
|
}
|
|
ecdsaCipherSuite = true
|
|
case *rsa.PublicKey:
|
|
default:
|
|
return supportsRSAFallback(unsupportedCertificateError(c))
|
|
}
|
|
} else {
|
|
return supportsRSAFallback(unsupportedCertificateError(c))
|
|
}
|
|
|
|
// Make sure that there is a mutually supported cipher suite that works with
|
|
// this certificate. Cipher suite selection will then apply the logic in
|
|
// reverse to pick it. See also serverHandshakeState.cipherSuiteOk.
|
|
cipherSuite := selectCipherSuite(chi.CipherSuites, config.cipherSuites(), func(c *cipherSuite) bool {
|
|
if c.flags&suiteECDHE == 0 {
|
|
return false
|
|
}
|
|
if c.flags&suiteECSign != 0 {
|
|
if !ecdsaCipherSuite {
|
|
return false
|
|
}
|
|
} else {
|
|
if ecdsaCipherSuite {
|
|
return false
|
|
}
|
|
}
|
|
if vers < VersionTLS12 && c.flags&suiteTLS12 != 0 {
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
if cipherSuite == nil {
|
|
return supportsRSAFallback(errors.New("client doesn't support any cipher suites compatible with the certificate"))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 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.
|
|
func (cri *CertificateRequestInfo) SupportsCertificate(c *Certificate) error {
|
|
if _, err := selectSignatureScheme(cri.Version, c, cri.SignatureSchemes); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(cri.AcceptableCAs) == 0 {
|
|
return nil
|
|
}
|
|
|
|
for j, cert := range c.Certificate {
|
|
x509Cert := c.Leaf
|
|
// Parse the certificate if this isn't the leaf node, or if
|
|
// chain.Leaf was nil.
|
|
if j != 0 || x509Cert == nil {
|
|
var err error
|
|
if x509Cert, err = x509.ParseCertificate(cert); err != nil {
|
|
return fmt.Errorf("failed to parse certificate #%d in the chain: %w", j, err)
|
|
}
|
|
}
|
|
|
|
for _, ca := range cri.AcceptableCAs {
|
|
if bytes.Equal(x509Cert.RawIssuer, ca) {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
return errors.New("chain is not signed by an acceptable CA")
|
|
}
|
|
|
|
// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate
|
|
// from the CommonName and SubjectAlternateName fields of each of the leaf
|
|
// certificates.
|
|
//
|
|
// Deprecated: NameToCertificate only allows associating a single certificate
|
|
// with a given name. Leave that field nil to let the library select the first
|
|
// compatible chain from Certificates.
|
|
func (c *Config) BuildNameToCertificate() {
|
|
c.NameToCertificate = make(map[string]*Certificate)
|
|
for i := range c.Certificates {
|
|
cert := &c.Certificates[i]
|
|
x509Cert, err := cert.leaf()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
// If SANs are *not* present, some clients will consider the certificate
|
|
// valid for the name in the Common Name.
|
|
if x509Cert.Subject.CommonName != "" && len(x509Cert.DNSNames) == 0 {
|
|
c.NameToCertificate[x509Cert.Subject.CommonName] = cert
|
|
}
|
|
for _, san := range x509Cert.DNSNames {
|
|
c.NameToCertificate[san] = cert
|
|
}
|
|
}
|
|
}
|
|
|
|
const (
|
|
keyLogLabelTLS12 = "CLIENT_RANDOM"
|
|
keyLogLabelClientHandshake = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
|
|
keyLogLabelServerHandshake = "SERVER_HANDSHAKE_TRAFFIC_SECRET"
|
|
keyLogLabelClientTraffic = "CLIENT_TRAFFIC_SECRET_0"
|
|
keyLogLabelServerTraffic = "SERVER_TRAFFIC_SECRET_0"
|
|
)
|
|
|
|
func (c *Config) writeKeyLog(label string, clientRandom, secret []byte) error {
|
|
if c.KeyLogWriter == nil {
|
|
return nil
|
|
}
|
|
|
|
logLine := []byte(fmt.Sprintf("%s %x %x\n", label, clientRandom, secret))
|
|
|
|
writerMutex.Lock()
|
|
_, err := c.KeyLogWriter.Write(logLine)
|
|
writerMutex.Unlock()
|
|
|
|
return err
|
|
}
|
|
|
|
// writerMutex protects all KeyLogWriters globally. It is rarely enabled,
|
|
// and is only for debugging, so a global mutex saves space.
|
|
var writerMutex sync.Mutex
|
|
|
|
// A Certificate is a chain of one or more certificates, leaf first.
|
|
type Certificate struct {
|
|
Certificate [][]byte
|
|
// PrivateKey contains the private key corresponding to the public key in
|
|
// Leaf. This must implement crypto.Signer with an RSA, ECDSA or Ed25519 PublicKey.
|
|
// For a server up to TLS 1.2, it can also implement crypto.Decrypter with
|
|
// an RSA PublicKey.
|
|
PrivateKey crypto.PrivateKey
|
|
// SupportedSignatureAlgorithms is an optional list restricting what
|
|
// signature algorithms the PrivateKey can be used for.
|
|
SupportedSignatureAlgorithms []SignatureScheme
|
|
// OCSPStaple contains an optional OCSP response which will be served
|
|
// to clients that request it.
|
|
OCSPStaple []byte
|
|
// SignedCertificateTimestamps contains an optional list of Signed
|
|
// Certificate Timestamps which will be served to clients that request it.
|
|
SignedCertificateTimestamps [][]byte
|
|
// Leaf is the parsed form of the leaf certificate, which may be initialized
|
|
// using x509.ParseCertificate to reduce per-handshake processing. If nil,
|
|
// the leaf certificate will be parsed as needed.
|
|
Leaf *x509.Certificate
|
|
}
|
|
|
|
// leaf returns the parsed leaf certificate, either from c.Leaf or by parsing
|
|
// the corresponding c.Certificate[0].
|
|
func (c *Certificate) leaf() (*x509.Certificate, error) {
|
|
if c.Leaf != nil {
|
|
return c.Leaf, nil
|
|
}
|
|
return x509.ParseCertificate(c.Certificate[0])
|
|
}
|
|
|
|
type handshakeMessage interface {
|
|
marshal() []byte
|
|
unmarshal([]byte) bool
|
|
}
|
|
|
|
// lruSessionCache is a ClientSessionCache implementation that uses an LRU
|
|
// caching strategy.
|
|
type lruSessionCache struct {
|
|
sync.Mutex
|
|
|
|
m map[string]*list.Element
|
|
q *list.List
|
|
capacity int
|
|
}
|
|
|
|
type lruSessionCacheEntry struct {
|
|
sessionKey string
|
|
state *ClientSessionState
|
|
}
|
|
|
|
// NewLRUClientSessionCache returns a ClientSessionCache with the given
|
|
// capacity that uses an LRU strategy. If capacity is < 1, a default capacity
|
|
// is used instead.
|
|
func NewLRUClientSessionCache(capacity int) ClientSessionCache {
|
|
const defaultSessionCacheCapacity = 64
|
|
|
|
if capacity < 1 {
|
|
capacity = defaultSessionCacheCapacity
|
|
}
|
|
return &lruSessionCache{
|
|
m: make(map[string]*list.Element),
|
|
q: list.New(),
|
|
capacity: capacity,
|
|
}
|
|
}
|
|
|
|
// Put adds the provided (sessionKey, cs) pair to the cache. If cs is nil, the entry
|
|
// corresponding to sessionKey is removed from the cache instead.
|
|
func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) {
|
|
c.Lock()
|
|
defer c.Unlock()
|
|
|
|
if elem, ok := c.m[sessionKey]; ok {
|
|
if cs == nil {
|
|
c.q.Remove(elem)
|
|
delete(c.m, sessionKey)
|
|
} else {
|
|
entry := elem.Value.(*lruSessionCacheEntry)
|
|
entry.state = cs
|
|
c.q.MoveToFront(elem)
|
|
}
|
|
return
|
|
}
|
|
|
|
if c.q.Len() < c.capacity {
|
|
entry := &lruSessionCacheEntry{sessionKey, cs}
|
|
c.m[sessionKey] = c.q.PushFront(entry)
|
|
return
|
|
}
|
|
|
|
elem := c.q.Back()
|
|
entry := elem.Value.(*lruSessionCacheEntry)
|
|
delete(c.m, entry.sessionKey)
|
|
entry.sessionKey = sessionKey
|
|
entry.state = cs
|
|
c.q.MoveToFront(elem)
|
|
c.m[sessionKey] = elem
|
|
}
|
|
|
|
// Get returns the ClientSessionState value associated with a given key. It
|
|
// returns (nil, false) if no value is found.
|
|
func (c *lruSessionCache) Get(sessionKey string) (*ClientSessionState, bool) {
|
|
c.Lock()
|
|
defer c.Unlock()
|
|
|
|
if elem, ok := c.m[sessionKey]; ok {
|
|
c.q.MoveToFront(elem)
|
|
return elem.Value.(*lruSessionCacheEntry).state, true
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
var emptyConfig Config
|
|
|
|
func defaultConfig() *Config {
|
|
return &emptyConfig
|
|
}
|
|
|
|
func unexpectedMessageError(wanted, got any) error {
|
|
return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted)
|
|
}
|
|
|
|
func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlgorithms []SignatureScheme) bool {
|
|
for _, s := range supportedSignatureAlgorithms {
|
|
if s == sigAlg {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|