From 7ee105076aced2c368ee414d78946d0b3fbf1d09 Mon Sep 17 00:00:00 2001 From: Gaukas Wang Date: Thu, 27 Oct 2022 23:32:24 -0600 Subject: [PATCH 1/4] Merging upstream changes into sync branch (#6) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [dev.boringcrypto] crypto/sha1,sha256,sha512: use BoringCrypto Change-Id: I80a764971b41f75c3b699797bfed71f509e3407d Reviewed-on: https://go-review.googlesource.com/55474 Run-TryBot: Russ Cox TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * [dev.boringcrypto] crypto/aes: use BoringCrypto Change-Id: If83fdeac31f65aba818bbc7edd2f215b16814021 Reviewed-on: https://go-review.googlesource.com/55476 Run-TryBot: Russ Cox Reviewed-by: Adam Langley * [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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * [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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * [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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * [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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * 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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * 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 * 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick * 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 TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor * [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 TryBot-Result: Gobot Gobot Reviewed-by: Dmitri Shuralyov * 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 * 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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * 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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * 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 TryBot-Result: Gobot Gobot Reviewed-by: Bryan C. Mills * 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 Reviewed-by: Bryan C. Mills * crypto/tls: deprecate SSLv3 support Updates #32716 Change-Id: Ia0c03918e8f2da4d9824c49c6d4cfca1b0787b0a Reviewed-on: https://go-review.googlesource.com/c/go/+/184102 Reviewed-by: Andrew Bonventre * 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 TryBot-Result: Gobot Gobot Reviewed-by: Dmitri Shuralyov * 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick * 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick * 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 * 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 * 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 TryBot-Result: Gobot Gobot Reviewed-by: Daniel Martí * 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick * 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick * 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 * 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 Reviewed-by: Olivier Poitrey Reviewed-by: Filippo Valsorda TryBot-Result: Gobot Gobot * 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 Run-TryBot: Katie Hockman Reviewed-by: Katie Hockman TryBot-Result: Gobot Gobot * 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 * 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 * 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 * 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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * 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 TryBot-Result: Gobot Gobot Reviewed-by: Katie Hockman * 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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * 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 TryBot-Result: Gobot Gobot Reviewed-by: Katie Hockman Reviewed-by: Adam Langley * 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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * 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 TryBot-Result: Gobot Gobot Reviewed-by: Adam Langley * 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 TryBot-Result: Gobot Gobot Reviewed-by: Katie Hockman * 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 Reviewed-by: Brad Fitzpatrick TryBot-Result: Gobot Gobot * 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 TryBot-Result: Gobot Gobot Reviewed-by: Katie Hockman * 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 TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor * 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick * 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 * 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 TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor * 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 TryBot-Result: Gobot Gobot Reviewed-by: Katie Hockman * 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 TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * crypto/tls: use new ecdsa.VerifyASN1 API Change-Id: I2a233190bda78ca022ff4074b4553788847d7583 Reviewed-on: https://go-review.googlesource.com/c/go/+/220720 Run-TryBot: Katie Hockman TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor * 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 TryBot-Result: Gobot Gobot Reviewed-by: Katie Hockman * 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 * 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 TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 Run-TryBot: Filippo Valsorda Reviewed-by: Filippo Valsorda TryBot-Result: Gobot Gobot * 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 * crypto/tls: add Dialer Fixes #18482 Change-Id: I99d65dc5d824c00093ea61e7445fc121314af87f Reviewed-on: https://go-review.googlesource.com/c/go/+/214977 Run-TryBot: Brad Fitzpatrick Reviewed-by: Ian Lance Taylor * 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 * 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 TryBot-Result: Gobot Gobot Reviewed-by: Katie Hockman * crypto/tls: marshal sessionState using cryptobyte Change-Id: I95a60b837e19d0c4bf45ea74baa5843a8244a186 Reviewed-on: https://go-review.googlesource.com/c/go/+/231218 Run-TryBot: Katie Hockman TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 TryBot-Result: Gobot Gobot Reviewed-by: Katie Hockman * crypto/tls: fix sessionState marshaling Change-Id: I2910f322256c521dd03b1dc23d117defdcd0aa54 Reviewed-on: https://go-review.googlesource.com/c/go/+/232662 Run-TryBot: Katie Hockman TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 Reviewed-by: Filippo Valsorda TryBot-Result: Gobot Gobot * 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 Reviewed-by: Filippo Valsorda TryBot-Result: Gobot Gobot * 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 TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 * crypto/tls: fix DialContext docs Change-Id: I58e3febbf63049bebb4f8ed8893288183c8aaccd Reviewed-on: https://go-review.googlesource.com/c/go/+/239745 Run-TryBot: Filippo Valsorda TryBot-Result: Gobot Gobot Reviewed-by: Katie Hockman * 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 Reviewed-by: Katie Hockman * 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 TryBot-Result: Gobot Gobot Reviewed-by: Katie Hockman * 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 Run-TryBot: Filippo Valsorda TryBot-Result: Gobot Gobot * 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 * crypto: fix PKCS space in docs Change-Id: Iee53acb963a889410f8c6daaa9a7841f1b12c6fb Reviewed-on: https://go-review.googlesource.com/c/go/+/241497 Run-TryBot: Katie Hockman TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda * 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 Trust: Katie Hockman Trust: Ian Lance Taylor Run-TryBot: Katie Hockman TryBot-Result: Go Bot * 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 TryBot-Result: Go Bot Reviewed-by: Filippo Valsorda Reviewed-by: Emmanuel Odeke Trust: Emmanuel Odeke * 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 Trust: Tobias Klauser Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Filippo Valsorda Reviewed-by: Than McIntosh Reviewed-by: Jeremy Faller * 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 TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke Reviewed-by: Filippo Valsorda Trust: Emmanuel Odeke * 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 Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke * 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 Reviewed-by: Filippo Valsorda * crypto/tls: document the ClientAuthType consts Fixes #34023 Change-Id: Ib7552a8873a79a91e8d971f906c6d7283da7a80c Reviewed-on: https://go-review.googlesource.com/c/go/+/264027 Trust: Roland Shoemaker Reviewed-by: Katie Hockman * 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 Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Filippo Valsorda * 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 Change-Id: I5f28673f95d4568b7d13dbc20e9d4b48d481a93d Reviewed-on: https://go-review.googlesource.com/c/go/+/267957 Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Trust: Filippo Valsorda Trust: Roland Shoemaker Reviewed-by: Roland Shoemaker Reviewed-by: Roberto Clapis * 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 Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Katie Hockman * 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 TryBot-Result: Go Bot Trust: Roland Shoemaker Reviewed-by: Filippo Valsorda * 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 TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker Trust: Roland Shoemaker Trust: Filippo Valsorda * 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 TryBot-Result: Go Bot Trust: Filippo Valsorda Trust: Roland Shoemaker Reviewed-by: Roland Shoemaker * 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 TryBot-Result: Go Bot Reviewed-by: Filippo Valsorda Trust: Roland Shoemaker Trust: Katie Hockman * 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 Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor * 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 Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Katie Hockman Trust: Katie Hockman Trust: Roland Shoemaker * 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 Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Jason A. Donenfeld Reviewed-by: Ian Lance Taylor * 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 Reviewed-by: Ian Lance Taylor Trust: Matthew Dempsky Trust: Robert Griesemer * 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 Reviewed-by: Jean de Klerk Trust: Jean de Klerk Run-TryBot: Jean de Klerk TryBot-Result: Go Bot * 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 Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills * 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 TryBot-Result: Go Bot Trust: Katie Hockman Reviewed-by: Filippo Valsorda * 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 Trust: Katie Hockman Run-TryBot: Johan Brandhorst-Satzkorn Run-TryBot: Katie Hockman Reviewed-by: Katie Hockman TryBot-Result: Go Bot * 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 TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Emmanuel Odeke * 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 Trust: Katie Hockman Reviewed-by: Filippo Valsorda * 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 Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Filippo Valsorda * 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 TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker Trust: Filippo Valsorda * crypto/tls: fix typo in Config.NextProtos docs Change-Id: I916df584859595067e5e86c35607869397dbbd8c Reviewed-on: https://go-review.googlesource.com/c/go/+/325651 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Dmitri Shuralyov * 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 Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker * 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: https://team-review.git.corp.google.com/c/golang/go-private/+/1116723 Reviewed-by: Filippo Valsorda Reviewed-by: Katie Hockman Reviewed-on: https://go-review.googlesource.com/c/go/+/334031 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Dmitri Shuralyov * 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 Reviewed-by: Filippo Valsorda * [dev.boringcrypto] crypto/tls: use correct config in TestBoringClientHello The existing implementation sets the ClientConfig to specific values to check, but does not uses it in the actual testing. This commit make the test to actually use it, which can be used to flag bugs in the future. Change-Id: I8d883c11675169705771af3fcca11a303cfeb30f GitHub-Last-Rev: 37841fd3561c95c8c9143c9fa4fff81268e18cdc GitHub-Pull-Request: golang/go#47959 Reviewed-on: https://go-review.googlesource.com/c/go/+/345029 Reviewed-by: Filippo Valsorda Reviewed-by: Dmitri Shuralyov Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Trust: Dmitri Shuralyov * [dev.boringcrypto] crypto/tls: permit P-521 in FIPS mode While BoringCrypto has a certification for P-521, the go code disallows certificates with it. This change permits those certificates to be used. Change-Id: I451c91a845f22ff0e4c3e922eaf8bf82466e80ae Reviewed-on: https://go-review.googlesource.com/c/go/+/343880 Reviewed-by: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Trust: Dmitri Shuralyov * crypto/tls: use cryptobyte.NewFixedBuilder Change-Id: Ia2a9465680e766336dae34f5d2b3cb412185bf1f Reviewed-on: https://go-review.googlesource.com/c/go/+/318131 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker * all: use bytes.Cut, strings.Cut Many uses of Index/IndexByte/IndexRune/Split/SplitN can be written more clearly using the new Cut functions. Do that. Also rewrite to other functions if that's clearer. For #46336. Change-Id: I68d024716ace41a57a8bf74455c62279bde0f448 Reviewed-on: https://go-review.googlesource.com/c/go/+/351711 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor * crypto/tls: add Conn.NetConn method NetConn method gives us access to the underlying net.Conn value. Fixes #29257 Change-Id: I68b2a92ed9dab4be9900807c94184f8c0aeb4f72 Reviewed-on: https://go-review.googlesource.com/c/go/+/325250 Reviewed-by: Filippo Valsorda Trust: Agniva De Sarker Trust: Katie Hockman * all: go fix -fix=buildtag std cmd (except for bootstrap deps, vendor) When these packages are released as part of Go 1.18, Go 1.16 will no longer be supported, so we can remove the +build tags in these files. Ran go fix -fix=buildtag std cmd and then reverted the bootstrapDirs as defined in src/cmd/dist/buildtool.go, which need to continue to build with Go 1.4 for now. Also reverted src/vendor and src/cmd/vendor, which will need to be updated in their own repos first. Manual changes in runtime/pprof/mprof_test.go to adjust line numbers. For #41184. Change-Id: Ic0f93f7091295b6abc76ed5cd6e6746e1280861e Reviewed-on: https://go-review.googlesource.com/c/go/+/344955 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills * crypto/tls: set default minimum client version to TLS 1.2 Updates #45428 Change-Id: I5d70066d4091196ec6f8bfc2edf3d78fdc0520c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/359779 Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Trust: Filippo Valsorda Reviewed-by: Roland Shoemaker * all: gofmt -w -r 'interface{} -> any' src And then revert the bootstrap cmd directories and certain testdata. And adjust tests as needed. Not reverting the changes in std that are bootstrapped, because some of those changes would appear in API docs, and we want to use any consistently. Instead, rewrite 'any' to 'interface{}' in cmd/dist for those directories when preparing the bootstrap copy. A few files changed as a result of running gofmt -w not because of interface{} -> any but because they hadn't been updated for the new //go:build lines. Fixes #49884. Change-Id: Ie8045cba995f65bd79c694ec77a1b3d1fe01bb09 Reviewed-on: https://go-review.googlesource.com/c/go/+/368254 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Robert Griesemer TryBot-Result: Gopher Robot * all: fix some typos Change-Id: I7dfae0fc91c2d70873ec7ec920be7c0a4888153a Reviewed-on: https://go-review.googlesource.com/c/go/+/390175 Reviewed-by: Ian Lance Taylor Reviewed-by: Daniel Martí Trust: Daniel Martí * all: use new "unix" build tag where appropriate For #20322 For #51572 Change-Id: Id0b4799d097d01128e98ba4cc0092298357bca45 Reviewed-on: https://go-review.googlesource.com/c/go/+/389935 Trust: Ian Lance Taylor Reviewed-by: Tobias Klauser * all: remove trailing blank doc comment lines A future change to gofmt will rewrite // Doc comment. // func f() to // Doc comment. func f() Apply that change preemptively to all doc comments. For #51082. Change-Id: I4023e16cfb0729b64a8590f071cd92f17343081d Reviewed-on: https://go-review.googlesource.com/c/go/+/384259 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot * all: consistently use US spelling of present participles It has been agreed that we should prefer the US spelling of words like "canceling" over "cancelling"; for example, see https://go.dev/cl/14526. Fix a few occurrences of the "canceling" inconsistency, as well as: * signaling * tunneling * marshaling Change-Id: I99f3ba0a700a9f0292bc6c1b110af31dd05f1ff0 Reviewed-on: https://go-review.googlesource.com/c/go/+/398734 Trust: Daniel Martí Run-TryBot: Daniel Martí TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor * all: gofmt main repo [This CL is part of a sequence implementing the proposal #51082. The design doc is at https://go.dev/s/godocfmt-design.] Run the updated gofmt, which reformats doc comments, on the main repository. Vendored files are excluded. For #51082. Change-Id: I7332f099b60f716295fb34719c98c04eb1a85407 Reviewed-on: https://go-review.googlesource.com/c/go/+/384268 Reviewed-by: Jonathan Amsterdam Reviewed-by: Ian Lance Taylor * crypto/tls: reject duplicate extensions Does what it says on the tin. Fixes #51088 Change-Id: I12c0fa6bba1c1ce96c1ad31ba387c77a93f801c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/384894 Reviewed-by: Roland Shoemaker Run-TryBot: Roland Shoemaker TryBot-Result: Gopher Robot Reviewed-by: Damien Neil * crypto/tls: remove tls10default GODEBUG flag Updates #45428 Change-Id: Ic2ff459e6a3f1e8ded2a770c11d34067c0b39a8a Reviewed-on: https://go-review.googlesource.com/c/go/+/400974 Reviewed-by: Filippo Valsorda Auto-Submit: Filippo Valsorda TryBot-Result: Gopher Robot Run-TryBot: Filippo Valsorda Reviewed-by: Roland Shoemaker * [dev.boringcrypto] all: add boringcrypto build tags A plain make.bash in this tree will produce a working, standard Go toolchain, not a BoringCrypto-enabled one. The BoringCrypto-enabled one will be created with: GOEXPERIMENT=boringcrypto ./make.bash For #51940. Change-Id: Ia9102ed993242eb1cb7f9b93eca97e81986a27b3 Reviewed-on: https://go-review.googlesource.com/c/go/+/395881 Run-TryBot: Russ Cox Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor * [dev.boringcrypto] crypto/x509: remove VerifyOptions.IsBoring This API was added only for BoringCrypto, never shipped in standard Go. This API is also not compatible with the expected future evolution of crypto/x509, as we move closer to host verifiers on macOS and Windows. If we want to merge BoringCrypto into the main tree, it is best not to have differing API. So instead of a hook set by crypto/tls, move the actual check directly into crypto/x509, eliminating the need for exposed API. For #51940. Change-Id: Ia2ae98c745de818d39501777014ea8166cab0b03 Reviewed-on: https://go-review.googlesource.com/c/go/+/395878 TryBot-Result: Gopher Robot Run-TryBot: Russ Cox Reviewed-by: Roland Shoemaker * crypto/tls: avoid extra allocations in steady-state Handshake calls The Read and Write methods of *tls.Conn call Handshake unconditionally, every time they are called, expecting it to only perform a new handshake if required. However in go 1.17 handshakeContext was extended to set up a cancelable Context, and importantly did so prior to checking if a handshake is required. This thus causes it to allocate on every call, even in those that are no-ops when called in a Read or Write on an established connection, sometimes leading to very large numbers of allocations during reads. This change adds an early return, prior to setting up the context or proceeding into the handshakeMutex and checking the handshake error, if the handshake status atomic indicates handshake is already complete. name old allocs/op new allocs/op delta Throughput/MaxPacket/1MB/TLSv12-10 1.07k ± 0% 0.62k ± 0% -42.16% (p=0.000 n=4+5) Throughput/MaxPacket/1MB/TLSv13-10 1.70k ± 0% 1.25k ± 0% ~ (p=0.079 n=4+5) Throughput/MaxPacket/2MB/TLSv12-10 1.62k ± 0% 0.73k ± 0% -55.18% (p=0.008 n=5+5) Throughput/MaxPacket/2MB/TLSv13-10 2.26k ± 0% 1.36k ± 0% -39.64% (p=0.008 n=5+5) Throughput/MaxPacket/4MB/TLSv12-10 2.74k ± 0% 0.95k ± 0% -65.35% (p=0.008 n=5+5) Throughput/MaxPacket/4MB/TLSv13-10 3.37k ± 0% 1.58k ± 0% -53.15% (p=0.008 n=5+5) Throughput/MaxPacket/8MB/TLSv12-10 4.96k ± 0% 1.39k ± 0% -72.06% (p=0.016 n=4+5) Throughput/MaxPacket/8MB/TLSv13-10 5.60k ± 0% 2.01k ± 0% -64.05% (p=0.008 n=5+5) Throughput/MaxPacket/16MB/TLSv12-10 9.42k ± 0% 2.27k ± 1% -75.92% (p=0.016 n=4+5) Throughput/MaxPacket/16MB/TLSv13-10 10.0k ± 0% 2.9k ± 0% -71.39% (p=0.008 n=5+5) Throughput/MaxPacket/32MB/TLSv12-10 18.3k ± 0% 4.0k ± 0% -77.97% (p=0.008 n=5+5) Throughput/MaxPacket/32MB/TLSv13-10 18.9k ± 0% 4.6k ± 0% -75.62% (p=0.008 n=5+5) Throughput/MaxPacket/64MB/TLSv12-10 36.2k ± 0% 7.5k ± 0% -79.15% (p=0.008 n=5+5) Throughput/MaxPacket/64MB/TLSv13-10 36.7k ± 0% 8.1k ± 0% -78.06% (p=0.008 n=5+5) Throughput/DynamicPacket/1MB/TLSv12-10 1.12k ± 0% 0.63k ± 0% -44.20% (p=0.008 n=5+5) Throughput/DynamicPacket/1MB/TLSv13-10 1.76k ± 0% 1.26k ± 0% -28.22% (p=0.016 n=5+4) Throughput/DynamicPacket/2MB/TLSv12-10 1.68k ± 0% 0.74k ± 0% -56.11% (p=0.008 n=5+5) Throughput/DynamicPacket/2MB/TLSv13-10 2.32k ± 0% 1.37k ± 0% -40.80% (p=0.008 n=5+5) Throughput/DynamicPacket/4MB/TLSv12-10 2.80k ± 0% 0.96k ± 0% -65.81% (p=0.008 n=5+5) Throughput/DynamicPacket/4MB/TLSv13-10 3.43k ± 0% 1.59k ± 0% -53.57% (p=0.008 n=5+5) Throughput/DynamicPacket/8MB/TLSv12-10 5.03k ± 0% 1.39k ± 0% -72.27% (p=0.008 n=5+5) Throughput/DynamicPacket/8MB/TLSv13-10 5.66k ± 0% 2.02k ± 0% -64.27% (p=0.008 n=5+5) Throughput/DynamicPacket/16MB/TLSv12-10 9.48k ± 0% 2.28k ± 1% -75.98% (p=0.008 n=5+5) Throughput/DynamicPacket/16MB/TLSv13-10 10.1k ± 0% 2.9k ± 0% -71.34% (p=0.008 n=5+5) Throughput/DynamicPacket/32MB/TLSv12-10 18.4k ± 0% 4.0k ± 0% -78.13% (p=0.008 n=5+5) Throughput/DynamicPacket/32MB/TLSv13-10 19.0k ± 0% 4.6k ± 0% -75.54% (p=0.008 n=5+5) Throughput/DynamicPacket/64MB/TLSv12-10 36.2k ± 0% 7.6k ± 1% -79.02% (p=0.008 n=5+5) Throughput/DynamicPacket/64MB/TLSv13-10 36.8k ± 0% 8.2k ± 1% -77.76% (p=0.008 n=5+5) Fixes #50657 Change-Id: Iacb1f9bf7802022960d9dbce141b8c0587a614d4 Reviewed-on: https://go-review.googlesource.com/c/go/+/379034 Reviewed-by: David Chase TryBot-Result: Gopher Robot Reviewed-by: Filippo Valsorda Auto-Submit: Filippo Valsorda Run-TryBot: Filippo Valsorda * all: fix spelling Change-Id: I68538a50c22b02cdb5aa2a889f9440fed7b94c54 GitHub-Last-Rev: aaac9e78340ac482e9cd1b506a035f271c29648c GitHub-Pull-Request: golang/go#52944 Reviewed-on: https://go-review.googlesource.com/c/go/+/406835 Reviewed-by: Bryan Mills Reviewed-by: Robert Griesemer TryBot-Result: Gopher Robot Run-TryBot: Bryan Mills Auto-Submit: Bryan Mills * crypto/tls: randomly generate ticket_age_add As required by RFC 8446, section 4.6.1, ticket_age_add now holds a random 32-bit value. Before this change, this value was always set to 0. This change also documents the reasoning for always setting ticket_nonce to 0. The value ticket_nonce must be unique per connection, but we only ever send one ticket per connection. Fixes #52814 Fixes CVE-2022-30629 Change-Id: I6c2fc6ca0376b7b968abd59d6d3d3854c1ab68bb Reviewed-on: https://go-review.googlesource.com/c/go/+/405994 Reviewed-by: Tatiana Bradley Reviewed-by: Roland Shoemaker Run-TryBot: Tatiana Bradley TryBot-Result: Gopher Robot * all: boringcrypto post-merge cleanup This CL addresses the comments on CL 403154. For #51940. Change-Id: I99bb3530916d469077bfbd53095bfcd1d2aa82ef Reviewed-on: https://go-review.googlesource.com/c/go/+/403976 Reviewed-by: Roland Shoemaker TryBot-Result: Gopher Robot Run-TryBot: Russ Cox Reviewed-by: Ian Lance Taylor * [release-branch.go1.19] crypto/tls: support ECDHE when ec_point_formats is missing Updates #49126 Fixes #54643 Change-Id: I9d6f6392b1a6748bdac1d2c6371b22d75829a2b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/425295 Run-TryBot: Filippo Valsorda Auto-Submit: Filippo Valsorda Reviewed-by: Alex Scheel TryBot-Result: Gopher Robot Reviewed-by: Roland Shoemaker Reviewed-by: David Chase (cherry picked from commit 1df2a03b17b4496bddfb482ec45b2a29c20e5249) Reviewed-on: https://go-review.googlesource.com/c/go/+/425635 * run `go mod tidy` Co-authored-by: Russ Cox Co-authored-by: Filippo Valsorda Co-authored-by: Filippo Valsorda Co-authored-by: Katie Hockman Co-authored-by: Ainar Garipov Co-authored-by: Brad Fitzpatrick Co-authored-by: fenos Co-authored-by: Bryan C. Mills Co-authored-by: Josh Bleecher Snyder Co-authored-by: Olivier Poitrey Co-authored-by: Ville Skyttä Co-authored-by: Alex Harford Co-authored-by: Johan Jansson Co-authored-by: Ziheng Liu Co-authored-by: Chris Le Roy Co-authored-by: Brad Fitzpatrick Co-authored-by: Dmitri Shuralyov Co-authored-by: Roland Shoemaker Co-authored-by: Daniel Co-authored-by: Chen.Zhidong Co-authored-by: Cherry Zhang Co-authored-by: Luca Spiller Co-authored-by: Thom Wiggers Co-authored-by: cch123 Co-authored-by: Johan Brandhorst Co-authored-by: Roland Shoemaker Co-authored-by: John Bampton Co-authored-by: Matt T. Proud Co-authored-by: Naman Gera Co-authored-by: vinckr Co-authored-by: Sofía Celi Co-authored-by: Watson Ladd Co-authored-by: Agniva De Sarker Co-authored-by: Heschi Kreinick Co-authored-by: Chressie Himpel Co-authored-by: Dan Kortschak Co-authored-by: Nicolas Hillegeer Co-authored-by: Ian Lance Taylor Co-authored-by: Lasse Folger Co-authored-by: Daniel Martí Co-authored-by: David Taylor Co-authored-by: Tatiana Bradley --- auth.go | 4 + auth_test.go | 2 +- boring.go | 98 ++++++ boring_test.go | 616 +++++++++++++++++++++++++++++++++++++ cipher_suites.go | 25 +- common.go | 22 +- conn.go | 18 +- fipsonly/fipsonly.go | 29 ++ fipsonly/fipsonly_test.go | 18 ++ generate_cert.go | 5 +- go.mod | 13 +- go.sum | 28 +- handshake_client.go | 10 +- handshake_client_test.go | 6 +- handshake_client_tls13.go | 6 +- handshake_messages.go | 12 + handshake_messages_test.go | 31 +- handshake_server.go | 13 +- handshake_server_test.go | 41 +-- handshake_server_tls13.go | 8 +- handshake_unix_test.go | 3 +- notboring.go | 20 ++ ticket.go | 38 ++- 23 files changed, 952 insertions(+), 114 deletions(-) create mode 100644 boring.go create mode 100644 boring_test.go create mode 100644 fipsonly/fipsonly.go create mode 100644 fipsonly/fipsonly_test.go create mode 100644 notboring.go diff --git a/auth.go b/auth.go index a9df0da6..42775e3d 100644 --- a/auth.go +++ b/auth.go @@ -169,6 +169,7 @@ var rsaSignatureSchemes = []struct { // and optionally filtered by its explicit SupportedSignatureAlgorithms. // // This function must be kept in sync with supportedSignatureAlgorithms. +// FIPS filtering is applied in the caller, selectSignatureScheme. func signatureSchemesForCertificate(version uint16, cert *Certificate) []SignatureScheme { priv, ok := cert.PrivateKey.(crypto.Signer) if !ok { @@ -241,6 +242,9 @@ func selectSignatureScheme(vers uint16, c *Certificate, peerAlgs []SignatureSche // Pick signature scheme in the peer's preference order, as our // preference order is not configurable. for _, preferredAlg := range peerAlgs { + // if needFIPS() && !isSupportedSignatureAlgorithm(preferredAlg, fipsSupportedSignatureAlgorithms) { + // continue + // } if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) { return preferredAlg, nil } diff --git a/auth_test.go b/auth_test.go index c42e3491..c23d93f3 100644 --- a/auth_test.go +++ b/auth_test.go @@ -153,7 +153,7 @@ func TestLegacyTypeAndHash(t *testing.T) { // TestSupportedSignatureAlgorithms checks that all supportedSignatureAlgorithms // have valid type and hash information. func TestSupportedSignatureAlgorithms(t *testing.T) { - for _, sigAlg := range supportedSignatureAlgorithms { + for _, sigAlg := range supportedSignatureAlgorithms() { sigType, hash, err := typeAndHashFromSignatureScheme(sigAlg) if err != nil { t.Errorf("%v: unexpected error: %v", sigAlg, err) diff --git a/boring.go b/boring.go new file mode 100644 index 00000000..1827f764 --- /dev/null +++ b/boring.go @@ -0,0 +1,98 @@ +// Copyright 2017 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. + +//go:build boringcrypto + +package tls + +import ( + "crypto/internal/boring/fipstls" +) + +// needFIPS returns fipstls.Required(); it avoids a new import in common.go. +func needFIPS() bool { + return fipstls.Required() +} + +// fipsMinVersion replaces c.minVersion in FIPS-only mode. +func fipsMinVersion(c *Config) uint16 { + // FIPS requires TLS 1.2. + return VersionTLS12 +} + +// fipsMaxVersion replaces c.maxVersion in FIPS-only mode. +func fipsMaxVersion(c *Config) uint16 { + // FIPS requires TLS 1.2. + return VersionTLS12 +} + +// default defaultFIPSCurvePreferences is the FIPS-allowed curves, +// in preference order (most preferable first). +var defaultFIPSCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521} + +// fipsCurvePreferences replaces c.curvePreferences in FIPS-only mode. +func fipsCurvePreferences(c *Config) []CurveID { + if c == nil || len(c.CurvePreferences) == 0 { + return defaultFIPSCurvePreferences + } + var list []CurveID + for _, id := range c.CurvePreferences { + for _, allowed := range defaultFIPSCurvePreferences { + if id == allowed { + list = append(list, id) + break + } + } + } + return list +} + +// defaultCipherSuitesFIPS are the FIPS-allowed cipher suites. +var defaultCipherSuitesFIPS = []uint16{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_256_GCM_SHA384, +} + +// fipsCipherSuites replaces c.cipherSuites in FIPS-only mode. +func fipsCipherSuites(c *Config) []uint16 { + if c == nil || c.CipherSuites == nil { + return defaultCipherSuitesFIPS + } + list := make([]uint16, 0, len(defaultCipherSuitesFIPS)) + for _, id := range c.CipherSuites { + for _, allowed := range defaultCipherSuitesFIPS { + if id == allowed { + list = append(list, id) + break + } + } + } + return list +} + +// fipsSupportedSignatureAlgorithms currently are a subset of +// defaultSupportedSignatureAlgorithms without Ed25519 and SHA-1. +var fipsSupportedSignatureAlgorithms = []SignatureScheme{ + PSSWithSHA256, + PSSWithSHA384, + PSSWithSHA512, + PKCS1WithSHA256, + ECDSAWithP256AndSHA256, + PKCS1WithSHA384, + ECDSAWithP384AndSHA384, + PKCS1WithSHA512, + ECDSAWithP521AndSHA512, +} + +// supportedSignatureAlgorithms returns the supported signature algorithms. +func supportedSignatureAlgorithms() []SignatureScheme { + if !needFIPS() { + return defaultSupportedSignatureAlgorithms + } + return fipsSupportedSignatureAlgorithms +} diff --git a/boring_test.go b/boring_test.go new file mode 100644 index 00000000..f743fc8e --- /dev/null +++ b/boring_test.go @@ -0,0 +1,616 @@ +// Copyright 2017 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. + +//go:build boringcrypto + +package tls + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/internal/boring/fipstls" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "net" + "runtime" + "strings" + "testing" + "time" +) + +func TestBoringServerProtocolVersion(t *testing.T) { + test := func(name string, v uint16, msg string) { + t.Run(name, func(t *testing.T) { + serverConfig := testConfig.Clone() + serverConfig.MinVersion = VersionSSL30 + clientHello := &clientHelloMsg{ + vers: v, + random: make([]byte, 32), + cipherSuites: allCipherSuites(), + compressionMethods: []uint8{compressionNone}, + supportedVersions: []uint16{v}, + } + testClientHelloFailure(t, serverConfig, clientHello, msg) + }) + } + + test("VersionTLS10", VersionTLS10, "") + test("VersionTLS11", VersionTLS11, "") + test("VersionTLS12", VersionTLS12, "") + test("VersionTLS13", VersionTLS13, "") + + fipstls.Force() + defer fipstls.Abandon() + test("VersionSSL30", VersionSSL30, "client offered only unsupported versions") + test("VersionTLS10", VersionTLS10, "client offered only unsupported versions") + test("VersionTLS11", VersionTLS11, "client offered only unsupported versions") + test("VersionTLS12", VersionTLS12, "") + test("VersionTLS13", VersionTLS13, "client offered only unsupported versions") +} + +func isBoringVersion(v uint16) bool { + return v == VersionTLS12 +} + +func isBoringCipherSuite(id uint16) bool { + switch id { + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_256_GCM_SHA384: + return true + } + return false +} + +func isBoringCurve(id CurveID) bool { + switch id { + case CurveP256, CurveP384, CurveP521: + return true + } + return false +} + +func isECDSA(id uint16) bool { + for _, suite := range cipherSuites { + if suite.id == id { + return suite.flags&suiteECSign == suiteECSign + } + } + panic(fmt.Sprintf("unknown cipher suite %#x", id)) +} + +func isBoringSignatureScheme(alg SignatureScheme) bool { + switch alg { + default: + return false + case PKCS1WithSHA256, + ECDSAWithP256AndSHA256, + PKCS1WithSHA384, + ECDSAWithP384AndSHA384, + PKCS1WithSHA512, + ECDSAWithP521AndSHA512, + PSSWithSHA256, + PSSWithSHA384, + PSSWithSHA512: + // ok + } + return true +} + +func TestBoringServerCipherSuites(t *testing.T) { + serverConfig := testConfig.Clone() + serverConfig.CipherSuites = allCipherSuites() + serverConfig.Certificates = make([]Certificate, 1) + + for _, id := range allCipherSuites() { + if isECDSA(id) { + serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} + serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey + } else { + serverConfig.Certificates[0].Certificate = [][]byte{testRSACertificate} + serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey + } + serverConfig.BuildNameToCertificate() + t.Run(fmt.Sprintf("suite=%#x", id), func(t *testing.T) { + clientHello := &clientHelloMsg{ + vers: VersionTLS12, + random: make([]byte, 32), + cipherSuites: []uint16{id}, + compressionMethods: []uint8{compressionNone}, + supportedCurves: defaultCurvePreferences, + supportedPoints: []uint8{pointFormatUncompressed}, + } + + testClientHello(t, serverConfig, clientHello) + t.Run("fipstls", func(t *testing.T) { + fipstls.Force() + defer fipstls.Abandon() + msg := "" + if !isBoringCipherSuite(id) { + msg = "no cipher suite supported by both client and server" + } + testClientHelloFailure(t, serverConfig, clientHello, msg) + }) + }) + } +} + +func TestBoringServerCurves(t *testing.T) { + serverConfig := testConfig.Clone() + serverConfig.Certificates = make([]Certificate, 1) + serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} + serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey + serverConfig.BuildNameToCertificate() + + for _, curveid := range defaultCurvePreferences { + t.Run(fmt.Sprintf("curve=%d", curveid), func(t *testing.T) { + clientHello := &clientHelloMsg{ + vers: VersionTLS12, + random: make([]byte, 32), + cipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + compressionMethods: []uint8{compressionNone}, + supportedCurves: []CurveID{curveid}, + supportedPoints: []uint8{pointFormatUncompressed}, + } + + testClientHello(t, serverConfig, clientHello) + + // With fipstls forced, bad curves should be rejected. + t.Run("fipstls", func(t *testing.T) { + fipstls.Force() + defer fipstls.Abandon() + msg := "" + if !isBoringCurve(curveid) { + msg = "no cipher suite supported by both client and server" + } + testClientHelloFailure(t, serverConfig, clientHello, msg) + }) + }) + } +} + +func boringHandshake(t *testing.T, clientConfig, serverConfig *Config) (clientErr, serverErr error) { + c, s := localPipe(t) + client := Client(c, clientConfig) + server := Server(s, serverConfig) + done := make(chan error, 1) + go func() { + done <- client.Handshake() + c.Close() + }() + serverErr = server.Handshake() + s.Close() + clientErr = <-done + return +} + +func TestBoringServerSignatureAndHash(t *testing.T) { + defer func() { + testingOnlyForceClientHelloSignatureAlgorithms = nil + }() + + for _, sigHash := range defaultSupportedSignatureAlgorithms { + t.Run(fmt.Sprintf("%#x", sigHash), func(t *testing.T) { + serverConfig := testConfig.Clone() + serverConfig.Certificates = make([]Certificate, 1) + + testingOnlyForceClientHelloSignatureAlgorithms = []SignatureScheme{sigHash} + + sigType, _, _ := typeAndHashFromSignatureScheme(sigHash) + switch sigType { + case signaturePKCS1v15, signatureRSAPSS: + serverConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} + serverConfig.Certificates[0].Certificate = [][]byte{testRSA2048Certificate} + serverConfig.Certificates[0].PrivateKey = testRSA2048PrivateKey + case signatureEd25519: + serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256} + serverConfig.Certificates[0].Certificate = [][]byte{testEd25519Certificate} + serverConfig.Certificates[0].PrivateKey = testEd25519PrivateKey + case signatureECDSA: + serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256} + serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} + serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey + } + serverConfig.BuildNameToCertificate() + // PKCS#1 v1.5 signature algorithms can't be used standalone in TLS + // 1.3, and the ECDSA ones bind to the curve used. + serverConfig.MaxVersion = VersionTLS12 + + clientErr, serverErr := boringHandshake(t, testConfig, serverConfig) + if clientErr != nil { + t.Fatalf("expected handshake with %#x to succeed; client error: %v; server error: %v", sigHash, clientErr, serverErr) + } + + // With fipstls forced, bad curves should be rejected. + t.Run("fipstls", func(t *testing.T) { + fipstls.Force() + defer fipstls.Abandon() + clientErr, _ := boringHandshake(t, testConfig, serverConfig) + if isBoringSignatureScheme(sigHash) { + if clientErr != nil { + t.Fatalf("expected handshake with %#x to succeed; err=%v", sigHash, clientErr) + } + } else { + if clientErr == nil { + t.Fatalf("expected handshake with %#x to fail, but it succeeded", sigHash) + } + } + }) + }) + } +} + +func TestBoringClientHello(t *testing.T) { + // Test that no matter what we put in the client config, + // the client does not offer non-FIPS configurations. + fipstls.Force() + defer fipstls.Abandon() + + c, s := net.Pipe() + defer c.Close() + defer s.Close() + + clientConfig := testConfig.Clone() + // All sorts of traps for the client to avoid. + clientConfig.MinVersion = VersionSSL30 + clientConfig.MaxVersion = VersionTLS13 + clientConfig.CipherSuites = allCipherSuites() + clientConfig.CurvePreferences = defaultCurvePreferences + + go Client(c, clientConfig).Handshake() + srv := Server(s, testConfig) + msg, err := srv.readHandshake() + if err != nil { + t.Fatal(err) + } + hello, ok := msg.(*clientHelloMsg) + if !ok { + t.Fatalf("unexpected message type %T", msg) + } + + if !isBoringVersion(hello.vers) { + t.Errorf("client vers=%#x, want %#x (TLS 1.2)", hello.vers, VersionTLS12) + } + for _, v := range hello.supportedVersions { + if !isBoringVersion(v) { + t.Errorf("client offered disallowed version %#x", v) + } + } + for _, id := range hello.cipherSuites { + if !isBoringCipherSuite(id) { + t.Errorf("client offered disallowed suite %#x", id) + } + } + for _, id := range hello.supportedCurves { + if !isBoringCurve(id) { + t.Errorf("client offered disallowed curve %d", id) + } + } + for _, sigHash := range hello.supportedSignatureAlgorithms { + if !isBoringSignatureScheme(sigHash) { + t.Errorf("client offered disallowed signature-and-hash %v", sigHash) + } + } +} + +func TestBoringCertAlgs(t *testing.T) { + // NaCl, arm and wasm time out generating keys. Nothing in this test is architecture-specific, so just don't bother on those. + if runtime.GOOS == "nacl" || runtime.GOARCH == "arm" || runtime.GOOS == "js" { + t.Skipf("skipping on %s/%s because key generation takes too long", runtime.GOOS, runtime.GOARCH) + } + + // Set up some roots, intermediate CAs, and leaf certs with various algorithms. + // X_Y is X signed by Y. + R1 := boringCert(t, "R1", boringRSAKey(t, 2048), nil, boringCertCA|boringCertFIPSOK) + R2 := boringCert(t, "R2", boringRSAKey(t, 4096), nil, boringCertCA) + + M1_R1 := boringCert(t, "M1_R1", boringECDSAKey(t, elliptic.P256()), R1, boringCertCA|boringCertFIPSOK) + M2_R1 := boringCert(t, "M2_R1", boringECDSAKey(t, elliptic.P224()), R1, boringCertCA) + + I_R1 := boringCert(t, "I_R1", boringRSAKey(t, 3072), R1, boringCertCA|boringCertFIPSOK) + I_R2 := boringCert(t, "I_R2", I_R1.key, R2, boringCertCA|boringCertFIPSOK) + I_M1 := boringCert(t, "I_M1", I_R1.key, M1_R1, boringCertCA|boringCertFIPSOK) + I_M2 := boringCert(t, "I_M2", I_R1.key, M2_R1, boringCertCA|boringCertFIPSOK) + + L1_I := boringCert(t, "L1_I", boringECDSAKey(t, elliptic.P384()), I_R1, boringCertLeaf|boringCertFIPSOK) + L2_I := boringCert(t, "L2_I", boringRSAKey(t, 1024), I_R1, boringCertLeaf) + + // client verifying server cert + testServerCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) { + clientConfig := testConfig.Clone() + clientConfig.RootCAs = pool + clientConfig.InsecureSkipVerify = false + clientConfig.ServerName = "example.com" + + serverConfig := testConfig.Clone() + serverConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}} + serverConfig.BuildNameToCertificate() + + clientErr, _ := boringHandshake(t, clientConfig, serverConfig) + + if (clientErr == nil) == ok { + if ok { + t.Logf("%s: accept", desc) + } else { + t.Logf("%s: reject", desc) + } + } else { + if ok { + t.Errorf("%s: BAD reject (%v)", desc, clientErr) + } else { + t.Errorf("%s: BAD accept", desc) + } + } + } + + // server verifying client cert + testClientCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) { + clientConfig := testConfig.Clone() + clientConfig.ServerName = "example.com" + clientConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}} + + serverConfig := testConfig.Clone() + serverConfig.ClientCAs = pool + serverConfig.ClientAuth = RequireAndVerifyClientCert + + _, serverErr := boringHandshake(t, clientConfig, serverConfig) + + if (serverErr == nil) == ok { + if ok { + t.Logf("%s: accept", desc) + } else { + t.Logf("%s: reject", desc) + } + } else { + if ok { + t.Errorf("%s: BAD reject (%v)", desc, serverErr) + } else { + t.Errorf("%s: BAD accept", desc) + } + } + } + + // Run simple basic test with known answers before proceeding to + // exhaustive test with computed answers. + r1pool := x509.NewCertPool() + r1pool.AddCert(R1.cert) + testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true) + testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true) + fipstls.Force() + testServerCert(t, "basic (fips)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false) + testClientCert(t, "basic (fips, client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false) + fipstls.Abandon() + + if t.Failed() { + t.Fatal("basic test failed, skipping exhaustive test") + } + + if testing.Short() { + t.Logf("basic test passed; skipping exhaustive test in -short mode") + return + } + + for l := 1; l <= 2; l++ { + leaf := L1_I + if l == 2 { + leaf = L2_I + } + for i := 0; i < 64; i++ { + reachable := map[string]bool{leaf.parentOrg: true} + reachableFIPS := map[string]bool{leaf.parentOrg: leaf.fipsOK} + list := [][]byte{leaf.der} + listName := leaf.name + addList := func(cond int, c *boringCertificate) { + if cond != 0 { + list = append(list, c.der) + listName += "," + c.name + if reachable[c.org] { + reachable[c.parentOrg] = true + } + if reachableFIPS[c.org] && c.fipsOK { + reachableFIPS[c.parentOrg] = true + } + } + } + addList(i&1, I_R1) + addList(i&2, I_R2) + addList(i&4, I_M1) + addList(i&8, I_M2) + addList(i&16, M1_R1) + addList(i&32, M2_R1) + + for r := 1; r <= 3; r++ { + pool := x509.NewCertPool() + rootName := "," + shouldVerify := false + shouldVerifyFIPS := false + addRoot := func(cond int, c *boringCertificate) { + if cond != 0 { + rootName += "," + c.name + pool.AddCert(c.cert) + if reachable[c.org] { + shouldVerify = true + } + if reachableFIPS[c.org] && c.fipsOK { + shouldVerifyFIPS = true + } + } + } + addRoot(r&1, R1) + addRoot(r&2, R2) + rootName = rootName[1:] // strip leading comma + testServerCert(t, listName+"->"+rootName[1:], pool, leaf.key, list, shouldVerify) + testClientCert(t, listName+"->"+rootName[1:]+"(client cert)", pool, leaf.key, list, shouldVerify) + fipstls.Force() + testServerCert(t, listName+"->"+rootName[1:]+" (fips)", pool, leaf.key, list, shouldVerifyFIPS) + testClientCert(t, listName+"->"+rootName[1:]+" (fips, client cert)", pool, leaf.key, list, shouldVerifyFIPS) + fipstls.Abandon() + } + } + } +} + +const ( + boringCertCA = iota + boringCertLeaf + boringCertFIPSOK = 0x80 +) + +func boringRSAKey(t *testing.T, size int) *rsa.PrivateKey { + k, err := rsa.GenerateKey(rand.Reader, size) + if err != nil { + t.Fatal(err) + } + return k +} + +func boringECDSAKey(t *testing.T, curve elliptic.Curve) *ecdsa.PrivateKey { + k, err := ecdsa.GenerateKey(curve, rand.Reader) + if err != nil { + t.Fatal(err) + } + return k +} + +type boringCertificate struct { + name string + org string + parentOrg string + der []byte + cert *x509.Certificate + key interface{} + fipsOK bool +} + +func boringCert(t *testing.T, name string, key interface{}, parent *boringCertificate, mode int) *boringCertificate { + org := name + parentOrg := "" + if i := strings.Index(org, "_"); i >= 0 { + org = org[:i] + parentOrg = name[i+1:] + } + tmpl := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + Organization: []string{org}, + }, + NotBefore: time.Unix(0, 0), + NotAfter: time.Unix(0, 0), + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + BasicConstraintsValid: true, + } + if mode&^boringCertFIPSOK == boringCertLeaf { + tmpl.DNSNames = []string{"example.com"} + } else { + tmpl.IsCA = true + tmpl.KeyUsage |= x509.KeyUsageCertSign + } + + var pcert *x509.Certificate + var pkey interface{} + if parent != nil { + pcert = parent.cert + pkey = parent.key + } else { + pcert = tmpl + pkey = key + } + + var pub interface{} + switch k := key.(type) { + case *rsa.PrivateKey: + pub = &k.PublicKey + case *ecdsa.PrivateKey: + pub = &k.PublicKey + default: + t.Fatalf("invalid key %T", key) + } + + der, err := x509.CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey) + if err != nil { + t.Fatal(err) + } + cert, err := x509.ParseCertificate(der) + if err != nil { + t.Fatal(err) + } + + fipsOK := mode&boringCertFIPSOK != 0 + return &boringCertificate{name, org, parentOrg, der, cert, key, fipsOK} +} + +// A self-signed test certificate with an RSA key of size 2048, for testing +// RSA-PSS with SHA512. SAN of example.golang. +var ( + testRSA2048Certificate []byte + testRSA2048PrivateKey *rsa.PrivateKey +) + +func init() { + block, _ := pem.Decode([]byte(` +-----BEGIN CERTIFICATE----- +MIIC/zCCAeegAwIBAgIRALHHX/kh4+4zMU9DarzBEcQwDQYJKoZIhvcNAQELBQAw +EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xMTAxMDExNTA0MDVaFw0yMDEyMjkxNTA0 +MDVaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCf8fk0N6ieCBX4IOVIfKitt4kGcOQLeimCfsjqqHcysMIVGEtFSM6E +4Ay141f/7IqdW0UtIqNb4PXhROID7yDxR284xL6XbCuv/t5hP3UcehYc3hmLiyVd +MkZQiZWtfUUJf/1qOtM+ohNg59LRWp4d+6iX0la1JL3EwCIckkNjJ9hQbF7Pb2CS ++ES9Yo55KAap8KOblpcR8MBSN38bqnwjfQdCXvOEOjam2HUxKzEFX5MA+fA0me4C +ioCcCRLWKl+GoN9F8fABfoZ+T+2eal4DLuO95rXR8SrOIVBh3XFOr/RVhjtXcNVF +ZKcvDt6d68V6jAKAYKm5nlj9GPpd4v+rAgMBAAGjUDBOMA4GA1UdDwEB/wQEAwIF +oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBkGA1UdEQQSMBCC +DmV4YW1wbGUuZ29sYW5nMA0GCSqGSIb3DQEBCwUAA4IBAQCOoYsVcFCBhboqe3WH +dC6V7XXXECmnjh01r8h80yv0NR379nSD3cw2M+HKvaXysWqrl5hjGVKw0vtwD81r +V4JzDu7IfIog5m8+QNC+7LqDZsz88vDKOrsoySVOmUCgmCKFXew+LA+eO/iQEJTr +7ensddOeXJEp27Ed5vW+kmWW3Qmglc2Gwy8wFrMDIqnrnOzBA4oCnDEgtXJt0zog +nRwbfEMAWi1aQRy5dT9KA3SP9mo5SeTFSzGGHiE4s4gHUe7jvsAFF2qgtD6+wH6s +z9b6shxnC7g5IlBKhI7SVB/Uqt2ydJ+kH1YbjMcIq6NAM5eNMKgZuJr3+zwsSgwh +GNaE +-----END CERTIFICATE-----`)) + testRSA2048Certificate = block.Bytes + + block, _ = pem.Decode([]byte(` +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAn/H5NDeonggV+CDlSHyorbeJBnDkC3opgn7I6qh3MrDCFRhL +RUjOhOAMteNX/+yKnVtFLSKjW+D14UTiA+8g8UdvOMS+l2wrr/7eYT91HHoWHN4Z +i4slXTJGUImVrX1FCX/9ajrTPqITYOfS0VqeHfuol9JWtSS9xMAiHJJDYyfYUGxe +z29gkvhEvWKOeSgGqfCjm5aXEfDAUjd/G6p8I30HQl7zhDo2pth1MSsxBV+TAPnw +NJnuAoqAnAkS1ipfhqDfRfHwAX6Gfk/tnmpeAy7jvea10fEqziFQYd1xTq/0VYY7 +V3DVRWSnLw7enevFeowCgGCpuZ5Y/Rj6XeL/qwIDAQABAoIBAQCNpMZifd/vg42h +HdCvLuZaYS0R7SunFlpoXEsltGdLFsnp0IfoJZ/ugFQBSAIIfLwMumU6oXA1z7Uv +98aIYV61DePrTCDVDFBsHbNmP8JAo8WtbusEbwd5zyoB7LYG2+clkJklWE73KqUq +rmI+UJeyScl2Gin7ZTxBXz1WPBk9VwcnwkeaXpgASIBW23fhECM9gnYEEwaBez5T +6Me8d1tHtYQv7vsKe7ro9w9/HKrRXejqYKK1LxkhfFriyV+m8LZJZn2nXOa6G3gF +Nb8Qk1Uk5PUBENBmyMFJhT4M/uuSq4YtMrrO2gi8Q+fPhuGzc5SshYKRBp0W4P5r +mtVCtEFRAoGBAMENBIFLrV2+HsGj0xYFasKov/QPe6HSTR1Hh2IZONp+oK4oszWE +jBT4VcnITmpl6tC1Wy4GcrxjNgKIFZAj+1x1LUULdorXkuG8yr0tAhG9zNyfWsSy +PrSovC0UVbzr8Jxxla+kQVxEQQqWQxPlEVuL8kXaIDA6Lyt1Hpua2LvPAoGBANQZ +c6Lq2T7+BxLxNdi2m8kZzej5kgzBp/XdVsbFWRlebIX2KrFHsrHzT9PUk3DE1vZK +M6pzTt94nQhWSkDgCaw1SohElJ3HFIFwcusF1SJAc3pQepd8ug6IYdlpDMLtBj/P +/5P6BVUtgo05E4+I/T3iYatmglQxTtlZ0RkSV2llAoGBALOXkKFX7ahPvf0WksDh +uTfuFOTPoowgQG0EpgW0wRdCxeg/JLic3lSD0gsttQV2WsRecryWcxaelRg10RmO +38BbogmhaF4xvgsSvujOfiZTE8oK1T43M+6NKsIlML3YILbpU/9aJxPWy0s2DqDr +cQJhZrlk+pzjBA7Bnf/URdwxAoGAKR/CNw14D+mrL3YLbbiCXiydqxVwxv5pdZdz +8thi3TNcsWC4iGURdcVqbfUinVPdJiXe/Kac3WGCeRJaFVgbKAOxLti1RB5MkIhg +D8eyupBqk4W1L1gkrxqsdj4TFlxkwMywjl2E2S4YyQ8PBt6V04DoVRZsIKzqz+PF +UionPq0CgYBCYXvqioJhPewkOq/Y5wrDBeZW1FQK5QD9W5M8/5zxd4rdvJtjhbJp +oOrtvMdrl6upy9Hz4BJD3FXwVFiPFE7jqeNqi0F21viLxBPMMD3UODF6LL5EyLiR +9V4xVMS8KXxvg7rxsuqzMPscViaWUL6WNVBhsD2+92dHxSXzz5EJKQ== +-----END RSA PRIVATE KEY-----`)) + var err error + testRSA2048PrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + panic(err) + } +} diff --git a/cipher_suites.go b/cipher_suites.go index 4c8ff49b..b0b6af30 100644 --- a/cipher_suites.go +++ b/cipher_suites.go @@ -141,7 +141,7 @@ type cipherSuite struct { ka func(version uint16) keyAgreement // flags is a bitmask of the suite* values, above. flags int - cipher func(key, iv []byte, isRead bool) interface{} + cipher func(key, iv []byte, isRead bool) any mac func(key []byte) hash.Hash aead func(key, fixedNonce []byte) aead } @@ -399,12 +399,12 @@ func aesgcmPreferred(ciphers []uint16) bool { return false } -func cipherRC4(key, iv []byte, isRead bool) interface{} { +func cipherRC4(key, iv []byte, isRead bool) any { cipher, _ := rc4.NewCipher(key) return cipher } -func cipher3DES(key, iv []byte, isRead bool) interface{} { +func cipher3DES(key, iv []byte, isRead bool) any { block, _ := des.NewTripleDESCipher(key) if isRead { return cipher.NewCBCDecrypter(block, iv) @@ -412,7 +412,7 @@ func cipher3DES(key, iv []byte, isRead bool) interface{} { return cipher.NewCBCEncrypter(block, iv) } -func cipherAES(key, iv []byte, isRead bool) interface{} { +func cipherAES(key, iv []byte, isRead bool) any { block, _ := aes.NewCipher(key) if isRead { return cipher.NewCBCDecrypter(block, iv) @@ -422,7 +422,13 @@ func cipherAES(key, iv []byte, isRead bool) interface{} { // macSHA1 returns a SHA-1 based constant time MAC. func macSHA1(key []byte) hash.Hash { - return hmac.New(newConstantTimeHash(sha1.New), key) + h := sha1.New + // The BoringCrypto SHA1 does not have a constant-time + // checksum function, so don't try to use it. + if !boring.Enabled { + h = newConstantTimeHash(h) + } + return hmac.New(h, key) } // macSHA256 returns a SHA-256 based MAC. This is only supported in TLS 1.2 and @@ -510,7 +516,13 @@ func aeadAESGCM(key, noncePrefix []byte) aead { if err != nil { panic(err) } - aead, err := cipher.NewGCM(aes) + var aead cipher.AEAD + if boring.Enabled { + aead, err = boring.NewGCMTLS(aes) + } else { + boring.Unreachable() + aead, err = cipher.NewGCM(aes) + } if err != nil { panic(err) } @@ -570,6 +582,7 @@ func (c *cthWrapper) Write(p []byte) (int, error) { return c.h.Write(p) } func (c *cthWrapper) Sum(b []byte) []byte { return c.h.ConstantTimeSum(b) } func newConstantTimeHash(h func() hash.Hash) func() hash.Hash { + boring.Unreachable() return func() hash.Hash { return &cthWrapper{h().(constantTimeHash)} } diff --git a/common.go b/common.go index 65308a0f..c7741ef9 100644 --- a/common.go +++ b/common.go @@ -100,7 +100,6 @@ const ( extensionCertificateAuthorities uint16 = 47 extensionSignatureAlgorithmsCert uint16 = 50 extensionKeyShare uint16 = 51 - extensionNextProtoNeg uint16 = 13172 // not IANA assigned extensionRenegotiationInfo uint16 = 0xff01 ) @@ -173,11 +172,11 @@ const ( // hash function associated with the Ed25519 signature scheme. var directSigning crypto.Hash = 0 -// supportedSignatureAlgorithms contains the signature and hash algorithms that +// 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 supportedSignatureAlgorithms = []SignatureScheme{ +var defaultSupportedSignatureAlgorithms = []SignatureScheme{ PSSWithSHA256, ECDSAWithP256AndSHA256, Ed25519, @@ -962,6 +961,9 @@ func (c *Config) time() time.Time { } func (c *Config) cipherSuites() []uint16 { + if needFIPS() { + return fipsCipherSuites(c) + } if c.CipherSuites != nil { return c.CipherSuites } @@ -975,10 +977,6 @@ var supportedVersions = []uint16{ VersionTLS10, } -// debugEnableTLS10 enables TLS 1.0. See issue 45428. -// [uTLS] disabled TLS 1.0 -var debugEnableTLS10 = false - // roleClient and roleServer are meant to call supportedVersions and parents // with more readability at the callsite. const roleClient = true @@ -987,7 +985,10 @@ const roleServer = false func (c *Config) supportedVersions(isClient bool) []uint16 { versions := make([]uint16, 0, len(supportedVersions)) for _, v := range supportedVersions { - if (c == nil || c.MinVersion == 0) && !debugEnableTLS10 && + if needFIPS() && (v < fipsMinVersion(c) || v > fipsMaxVersion(c)) { + continue + } + if (c == nil || c.MinVersion == 0) && isClient && v < VersionTLS12 { continue } @@ -1027,6 +1028,9 @@ func supportedVersionsFromMax(maxVersion uint16) []uint16 { 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 } @@ -1468,7 +1472,7 @@ func defaultConfig() *Config { return &emptyConfig } -func unexpectedMessageError(wanted, got interface{}) error { +func unexpectedMessageError(wanted, got any) error { return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted) } diff --git a/conn.go b/conn.go index 43eed7f2..805354b7 100644 --- a/conn.go +++ b/conn.go @@ -164,16 +164,16 @@ func (c *Conn) NetConn() net.Conn { type halfConn struct { sync.Mutex - err error // first permanent error - version uint16 // protocol version - cipher interface{} // cipher algorithm + err error // first permanent error + version uint16 // protocol version + cipher any // cipher algorithm mac hash.Hash seq [8]byte // 64-bit sequence number scratchBuf [13]byte // to avoid allocs; interface method args escape - nextCipher interface{} // next encryption state - nextMac hash.Hash // next MAC algorithm + nextCipher any // next encryption state + nextMac hash.Hash // next MAC algorithm trafficSecret []byte // current TLS 1.3 traffic secret } @@ -198,7 +198,7 @@ func (hc *halfConn) setErrorLocked(err error) error { // prepareCipherSpec sets the encryption and MAC states // that a subsequent changeCipherSpec will use. -func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac hash.Hash) { +func (hc *halfConn) prepareCipherSpec(version uint16, cipher any, mac hash.Hash) { hc.version = version hc.nextCipher = cipher hc.nextMac = mac @@ -761,7 +761,7 @@ func (c *Conn) readRecordOrCCS(expectChangeCipherSpec bool) error { return nil } -// retryReadRecord recurses into readRecordOrCCS to drop a non-advancing record, like +// retryReadRecord recurs into readRecordOrCCS to drop a non-advancing record, like // a warning alert, empty application_data, or a change_cipher_spec in TLS 1.3. func (c *Conn) retryReadRecord(expectChangeCipherSpec bool) error { c.retryCount++ @@ -938,7 +938,7 @@ func (c *Conn) flush() (int, error) { // outBufPool pools the record-sized scratch buffers used by writeRecordLocked. var outBufPool = sync.Pool{ - New: func() interface{} { + New: func() any { return new([]byte) }, } @@ -1014,7 +1014,7 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (int, error) { // readHandshake reads the next handshake message from // the record layer. -func (c *Conn) readHandshake() (interface{}, error) { +func (c *Conn) readHandshake() (any, error) { for c.hand.Len() < 4 { if err := c.readRecord(); err != nil { return nil, err diff --git a/fipsonly/fipsonly.go b/fipsonly/fipsonly.go new file mode 100644 index 00000000..e5e47835 --- /dev/null +++ b/fipsonly/fipsonly.go @@ -0,0 +1,29 @@ +// Copyright 2017 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. + +//go:build boringcrypto + +// Package fipsonly restricts all TLS configuration to FIPS-approved settings. +// +// The effect is triggered by importing the package anywhere in a program, as in: +// +// import _ "crypto/tls/fipsonly" +// +// This package only exists when using Go compiled with GOEXPERIMENT=boringcrypto. +package fipsonly + +// This functionality is provided as a side effect of an import to make +// it trivial to add to an existing program. It requires only a single line +// added to an existing source file, or it can be done by adding a whole +// new source file and not modifying any existing source files. + +import ( + "crypto/internal/boring/fipstls" + "crypto/internal/boring/sig" +) + +func init() { + fipstls.Force() + sig.FIPSOnly() +} diff --git a/fipsonly/fipsonly_test.go b/fipsonly/fipsonly_test.go new file mode 100644 index 00000000..f8485dc3 --- /dev/null +++ b/fipsonly/fipsonly_test.go @@ -0,0 +1,18 @@ +// Copyright 2017 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. + +//go:build boringcrypto + +package fipsonly + +import ( + "crypto/internal/boring/fipstls" + "testing" +) + +func Test(t *testing.T) { + if !fipstls.Required() { + t.Fatal("fipstls.Required() = false, must be true") + } +} diff --git a/generate_cert.go b/generate_cert.go index 7ea90f8a..74509c9d 100644 --- a/generate_cert.go +++ b/generate_cert.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // Generate a self-signed X.509 certificate for a TLS server. Outputs to // 'cert.pem' and 'key.pem' and will overwrite existing files. @@ -38,7 +37,7 @@ var ( ed25519Key = flag.Bool("ed25519", false, "Generate an Ed25519 key") ) -func publicKey(priv interface{}) interface{} { +func publicKey(priv any) any { switch k := priv.(type) { case *rsa.PrivateKey: return &k.PublicKey @@ -58,7 +57,7 @@ func main() { log.Fatalf("Missing required --host parameter") } - var priv interface{} + var priv any var err error switch *ecdsaCurve { case "": diff --git a/go.mod b/go.mod index 8dcb2619..6d81e07e 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,15 @@ module github.com/refraction-networking/utls -go 1.16 +go 1.19 require ( github.com/andybalholm/brotli v1.0.4 - github.com/klauspost/compress v1.15.9 - golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 - golang.org/x/net v0.0.0-20220909164309-bea034e7d591 + github.com/klauspost/compress v1.15.12 + golang.org/x/crypto v0.1.0 + golang.org/x/net v0.1.0 +) + +require ( + golang.org/x/sys v0.1.0 // indirect + golang.org/x/text v0.4.0 // indirect ) diff --git a/go.sum b/go.sum index 20803ed2..16fe15cd 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,12 @@ github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM= -golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= +github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= diff --git a/handshake_client.go b/handshake_client.go index 96a6bce1..39a3355e 100644 --- a/handshake_client.go +++ b/handshake_client.go @@ -36,6 +36,8 @@ type clientHandshakeState struct { uconn *UConn // [uTLS] } +var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme + func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) { config := c.config if len(config.ServerName) == 0 && !config.InsecureSkipVerify { @@ -119,7 +121,10 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) { } if hello.vers >= VersionTLS12 { - hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms + hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + } + if testingOnlyForceClientHelloSignatureAlgorithms != nil { + hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms } var params ecdheParameters @@ -663,7 +668,7 @@ func (hs *clientHandshakeState) establishKeys() error { clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) - var clientCipher, serverCipher interface{} + var clientCipher, serverCipher any var clientHash, serverHash hash.Hash if hs.suite.cipher != nil { clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) @@ -867,6 +872,7 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error { DNSName: c.config.ServerName, Intermediates: x509.NewCertPool(), } + for _, cert := range certs[1:] { opts.Intermediates.AddCert(cert) } diff --git a/handshake_client_test.go b/handshake_client_test.go index 2158f324..380de9f6 100644 --- a/handshake_client_test.go +++ b/handshake_client_test.go @@ -134,7 +134,7 @@ type clientTest struct { cert []byte // key, if not nil, contains either a *rsa.PrivateKey, ed25519.PrivateKey or // *ecdsa.PrivateKey which is the private key for the reference server. - key interface{} + key any // extensions, if not nil, contains a list of extension data to be returned // from the ServerHello. The data should be in standard TLS format with // a 2-byte uint16 type, 2-byte data length, followed by the extension data. @@ -171,7 +171,7 @@ func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, certPath := tempFile(string(cert)) defer os.Remove(certPath) - var key interface{} = testRSAPrivateKey + var key any = testRSAPrivateKey if test.key != nil { key = test.key } @@ -2564,7 +2564,7 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) { } } -// TestClientHandshakeContextCancellation tests that cancelling +// TestClientHandshakeContextCancellation tests that canceling // the context given to the client side conn.HandshakeContext // interrupts the in-progress handshake. func TestClientHandshakeContextCancellation(t *testing.T) { diff --git a/handshake_client_tls13.go b/handshake_client_tls13.go index 1724f245..47aa2026 100644 --- a/handshake_client_tls13.go +++ b/handshake_client_tls13.go @@ -49,6 +49,10 @@ type clientHandshakeStateTLS13 struct { func (hs *clientHandshakeStateTLS13) handshake() error { c := hs.c + if needFIPS() { + return errors.New("tls: internal error: TLS 1.3 reached in FIPS mode") + } + // The server must not select TLS 1.3 in a renegotiation. See RFC 8446, // sections 4.1.2 and 4.1.3. if c.handshakes > 0 { @@ -564,7 +568,7 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error { } // See RFC 8446, Section 4.4.3. - if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms) { + if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) { c.sendAlert(alertIllegalParameter) return errors.New("tls: certificate used with invalid signature algorithm") } diff --git a/handshake_messages.go b/handshake_messages.go index 55821d17..6daf19c5 100644 --- a/handshake_messages.go +++ b/handshake_messages.go @@ -388,6 +388,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { return false } + seenExts := make(map[uint16]bool) for !extensions.Empty() { var extension uint16 var extData cryptobyte.String @@ -396,6 +397,11 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { return false } + if seenExts[extension] { + return false + } + seenExts[extension] = true + switch extension { case extensionServerName: // RFC 6066, Section 3 @@ -759,6 +765,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { return false } + seenExts := make(map[uint16]bool) for !extensions.Empty() { var extension uint16 var extData cryptobyte.String @@ -767,6 +774,11 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { return false } + if seenExts[extension] { + return false + } + seenExts[extension] = true + switch extension { case extensionStatusRequest: m.ocspStapling = true diff --git a/handshake_messages_test.go b/handshake_messages_test.go index 914a4ed7..93ac1b1c 100644 --- a/handshake_messages_test.go +++ b/handshake_messages_test.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "encoding/hex" "math/rand" "reflect" "strings" @@ -14,7 +15,7 @@ import ( "time" ) -var tests = []interface{}{ +var tests = []any{ &clientHelloMsg{}, &serverHelloMsg{}, &finishedMsg{}, @@ -148,10 +149,10 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value { } } if rand.Intn(10) > 5 { - m.supportedSignatureAlgorithms = supportedSignatureAlgorithms + m.supportedSignatureAlgorithms = supportedSignatureAlgorithms() } if rand.Intn(10) > 5 { - m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms + m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms() } for i := 0; i < rand.Intn(5); i++ { m.alpnProtocols = append(m.alpnProtocols, randomString(rand.Intn(20)+1, rand)) @@ -370,10 +371,10 @@ func (*certificateRequestMsgTLS13) Generate(rand *rand.Rand, size int) reflect.V m.scts = true } if rand.Intn(10) > 5 { - m.supportedSignatureAlgorithms = supportedSignatureAlgorithms + m.supportedSignatureAlgorithms = supportedSignatureAlgorithms() } if rand.Intn(10) > 5 { - m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms + m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms() } if rand.Intn(10) > 5 { m.certificateAuthorities = make([][]byte, 3) @@ -473,3 +474,23 @@ func TestRejectEmptySCT(t *testing.T) { t.Fatal("Unmarshaled ServerHello with zero-length SCT") } } + +func TestRejectDuplicateExtensions(t *testing.T) { + clientHelloBytes, err := hex.DecodeString("010000440303000000000000000000000000000000000000000000000000000000000000000000000000001c0000000a000800000568656c6c6f0000000a000800000568656c6c6f") + if err != nil { + t.Fatalf("failed to decode test ClientHello: %s", err) + } + var clientHelloCopy clientHelloMsg + if clientHelloCopy.unmarshal(clientHelloBytes) { + t.Error("Unmarshaled ClientHello with duplicate extensions") + } + + serverHelloBytes, err := hex.DecodeString("02000030030300000000000000000000000000000000000000000000000000000000000000000000000000080005000000050000") + if err != nil { + t.Fatalf("failed to decode test ServerHello: %s", err) + } + var serverHelloCopy serverHelloMsg + if serverHelloCopy.unmarshal(serverHelloBytes) { + t.Fatal("Unmarshaled ServerHello with duplicate extensions") + } +} diff --git a/handshake_server.go b/handshake_server.go index 5cb15275..92b38cb1 100644 --- a/handshake_server.go +++ b/handshake_server.go @@ -240,7 +240,7 @@ func (hs *serverHandshakeState) processClientHello() error { hs.ecdheOk = supportsECDHE(c.config, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints) - if hs.ecdheOk { + if hs.ecdheOk && len(hs.clientHello.supportedPoints) > 0 { // Although omitting the ec_point_formats extension is permitted, some // old OpenSSL version will refuse to handshake if not present. // @@ -321,6 +321,13 @@ func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8 break } } + // Per RFC 8422, Section 5.1.2, if the Supported Point Formats extension is + // missing, uncompressed points are supported. If supportedPoints is empty, + // the extension must be missing, as an empty extension body is rejected by + // the parser. See https://go.dev/issue/49126. + if len(supportedPoints) == 0 { + supportsPointFormat = true + } return supportsCurve && supportsPointFormat } @@ -541,7 +548,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { } if c.vers >= VersionTLS12 { certReq.hasSignatureAlgorithm = true - certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms + certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() } // An empty list of certificateAuthorities signals to @@ -681,7 +688,7 @@ func (hs *serverHandshakeState) establishKeys() error { clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) - var clientCipher, serverCipher interface{} + var clientCipher, serverCipher any var clientHash, serverHash hash.Hash if hs.suite.aead == nil { diff --git a/handshake_server_test.go b/handshake_server_test.go index 5fb2ebbb..39b65f6d 100644 --- a/handshake_server_test.go +++ b/handshake_server_test.go @@ -249,7 +249,7 @@ func TestTLS12OnlyCipherSuites(t *testing.T) { } c, s := localPipe(t) - replyChan := make(chan interface{}) + replyChan := make(chan any) go func() { cli := Client(c, testConfig) cli.vers = clientHello.vers @@ -281,7 +281,7 @@ func TestTLS12OnlyCipherSuites(t *testing.T) { func TestTLSPointFormats(t *testing.T) { // Test that a Server returns the ec_point_format extension when ECC is - // negotiated, and not returned on RSA handshake. + // negotiated, and not on a RSA handshake or if ec_point_format is missing. tests := []struct { name string cipherSuites []uint16 @@ -289,8 +289,11 @@ func TestTLSPointFormats(t *testing.T) { supportedPoints []uint8 wantSupportedPoints bool }{ - {"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{compressionNone}, true}, + {"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{pointFormatUncompressed}, true}, + {"ECC without ec_point_format", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, nil, false}, + {"ECC with extra values", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{13, 37, pointFormatUncompressed, 42}, true}, {"RSA", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, nil, false}, + {"RSA with ec_point_format", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, []uint8{pointFormatUncompressed}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -304,7 +307,7 @@ func TestTLSPointFormats(t *testing.T) { } c, s := localPipe(t) - replyChan := make(chan interface{}) + replyChan := make(chan any) go func() { cli := Client(c, testConfig) cli.vers = clientHello.vers @@ -330,22 +333,12 @@ func TestTLSPointFormats(t *testing.T) { t.Fatalf("didn't get ServerHello message in reply. Got %v\n", reply) } if tt.wantSupportedPoints { - if len(serverHello.supportedPoints) < 1 { - t.Fatal("missing ec_point_format extension from server") - } - found := false - for _, p := range serverHello.supportedPoints { - if p == pointFormatUncompressed { - found = true - break - } - } - if !found { - t.Fatal("missing uncompressed format in ec_point_format extension from server") + if !bytes.Equal(serverHello.supportedPoints, []uint8{pointFormatUncompressed}) { + t.Fatal("incorrect ec_point_format extension from server") } } else { if len(serverHello.supportedPoints) != 0 { - t.Fatalf("unexcpected ec_point_format extension from server: %v", serverHello.supportedPoints) + t.Fatalf("unexpected ec_point_format extension from server: %v", serverHello.supportedPoints) } } }) @@ -400,16 +393,6 @@ func TestVersion(t *testing.T) { if err == nil { t.Fatalf("expected failure to connect with TLS 1.0/1.1") } - - defer func(old bool) { debugEnableTLS10 = old }(debugEnableTLS10) - debugEnableTLS10 = true - _, _, err = testHandshake(t, clientConfig, serverConfig) - if err != nil { - t.Fatalf("handshake failed: %s", err) - } - if state.Version != VersionTLS11 { - t.Fatalf("incorrect version %x, should be %x", state.Version, VersionTLS11) - } } func TestCipherSuitePreference(t *testing.T) { @@ -600,7 +583,7 @@ func (test *serverTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, return nil, nil, err } - connChan := make(chan interface{}, 1) + connChan := make(chan any, 1) go func() { tcpConn, err := l.Accept() if err != nil { @@ -1944,7 +1927,7 @@ func TestAESCipherReorderingTLS13(t *testing.T) { } } -// TestServerHandshakeContextCancellation tests that cancelling +// TestServerHandshakeContextCancellation tests that canceling // the context given to the server side conn.HandshakeContext // interrupts the in-progress handshake. func TestServerHandshakeContextCancellation(t *testing.T) { diff --git a/handshake_server_tls13.go b/handshake_server_tls13.go index 54e612ae..03a477f7 100644 --- a/handshake_server_tls13.go +++ b/handshake_server_tls13.go @@ -45,6 +45,10 @@ type serverHandshakeStateTLS13 struct { func (hs *serverHandshakeStateTLS13) handshake() error { c := hs.c + if needFIPS() { + return errors.New("tls: internal error: TLS 1.3 reached in FIPS mode") + } + // For an overview of the TLS 1.3 handshake, see RFC 8446, Section 2. if err := hs.processClientHello(); err != nil { return err @@ -584,7 +588,7 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { certReq := new(certificateRequestMsgTLS13) certReq.ocspStapling = true certReq.scts = true - certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms + certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() if c.config.ClientCAs != nil { certReq.certificateAuthorities = c.config.ClientCAs.Subjects() } @@ -816,7 +820,7 @@ func (hs *serverHandshakeStateTLS13) readClientCertificate() error { } // See RFC 8446, Section 4.4.3. - if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms) { + if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) { c.sendAlert(alertIllegalParameter) return errors.New("tls: client certificate used with invalid signature algorithm") } diff --git a/handshake_unix_test.go b/handshake_unix_test.go index 19fc6986..86a48f29 100644 --- a/handshake_unix_test.go +++ b/handshake_unix_test.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build unix package tls diff --git a/notboring.go b/notboring.go new file mode 100644 index 00000000..7d85b39c --- /dev/null +++ b/notboring.go @@ -0,0 +1,20 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !boringcrypto + +package tls + +func needFIPS() bool { return false } + +func supportedSignatureAlgorithms() []SignatureScheme { + return defaultSupportedSignatureAlgorithms +} + +func fipsMinVersion(c *Config) uint16 { panic("fipsMinVersion") } +func fipsMaxVersion(c *Config) uint16 { panic("fipsMaxVersion") } +func fipsCurvePreferences(c *Config) []CurveID { panic("fipsCurvePreferences") } +func fipsCipherSuites(c *Config) []uint16 { panic("fipsCipherSuites") } + +var fipsSupportedSignatureAlgorithms []SignatureScheme diff --git a/ticket.go b/ticket.go index cbe94eab..ba34a51d 100644 --- a/ticket.go +++ b/ticket.go @@ -146,18 +146,6 @@ func (c *Conn) encryptTicket(state []byte) ([]byte, error) { // [uTLS] changed to use exported DecryptTicketWith func below func (c *Conn) decryptTicket(encrypted []byte) (plaintext []byte, usedOldKey bool) { - tks := ticketKeys(c.config.ticketKeys(c.config)).ToPublic() - return DecryptTicketWith(encrypted, tks) -} - -// DecryptTicketWith decrypts an encrypted session ticket -// using a TicketKeys (ie []TicketKey) struct -// -// usedOldKey will be true if the key used for decryption is -// not the first in the []TicketKey slice -// -// [uTLS] changed to be made public and take a TicketKeys instead of use a Conn receiver -func DecryptTicketWith(encrypted []byte, tks TicketKeys) (plaintext []byte, usedOldKey bool) { if len(encrypted) < ticketKeyNameLen+aes.BlockSize+sha256.Size { return nil, false } @@ -168,8 +156,8 @@ func DecryptTicketWith(encrypted []byte, tks TicketKeys) (plaintext []byte, used ciphertext := encrypted[ticketKeyNameLen+aes.BlockSize : len(encrypted)-sha256.Size] keyIndex := -1 - for i, candidateKey := range tks { - if bytes.Equal(keyName, candidateKey.KeyName[:]) { + for i, candidateKey := range c.ticketKeys { + if bytes.Equal(keyName, candidateKey.keyName[:]) { keyIndex = i break } @@ -177,9 +165,9 @@ func DecryptTicketWith(encrypted []byte, tks TicketKeys) (plaintext []byte, used if keyIndex == -1 { return nil, false } - key := &tks[keyIndex] + key := &c.ticketKeys[keyIndex] - mac := hmac.New(sha256.New, key.HmacKey[:]) + mac := hmac.New(sha256.New, key.hmacKey[:]) mac.Write(encrypted[:len(encrypted)-sha256.Size]) expected := mac.Sum(nil) @@ -187,7 +175,7 @@ func DecryptTicketWith(encrypted []byte, tks TicketKeys) (plaintext []byte, used return nil, false } - block, err := aes.NewCipher(key.AesKey[:]) + block, err := aes.NewCipher(key.aesKey[:]) if err != nil { return nil, false } @@ -196,3 +184,19 @@ func DecryptTicketWith(encrypted []byte, tks TicketKeys) (plaintext []byte, used return plaintext, keyIndex > 0 } + +// DecryptTicketWith decrypts an encrypted session ticket +// using a TicketKeys (ie []TicketKey) struct +// +// usedOldKey will be true if the key used for decryption is +// not the first in the []TicketKey slice +// +// [uTLS] changed to be made public and take a TicketKeys instead of use a Conn receiver +func DecryptTicketWith(encrypted []byte, tks TicketKeys) (plaintext []byte, usedOldKey bool) { + // create fake conn + c := &Conn{ + ticketKeys: tks.ToPrivate(), + } + + return c.decryptTicket(encrypted) +} From 82a8255c3e51beb4caec6100a629205f8d2bf448 Mon Sep 17 00:00:00 2001 From: Gaukas Wang Date: Fri, 28 Oct 2022 00:02:30 -0600 Subject: [PATCH 2/4] 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. --- boring.go | 98 -------- boring_test.go | 616 ------------------------------------------------- common.go | 1 + notboring.go | 25 +- 4 files changed, 23 insertions(+), 717 deletions(-) delete mode 100644 boring.go delete mode 100644 boring_test.go diff --git a/boring.go b/boring.go deleted file mode 100644 index 1827f764..00000000 --- a/boring.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2017 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. - -//go:build boringcrypto - -package tls - -import ( - "crypto/internal/boring/fipstls" -) - -// needFIPS returns fipstls.Required(); it avoids a new import in common.go. -func needFIPS() bool { - return fipstls.Required() -} - -// fipsMinVersion replaces c.minVersion in FIPS-only mode. -func fipsMinVersion(c *Config) uint16 { - // FIPS requires TLS 1.2. - return VersionTLS12 -} - -// fipsMaxVersion replaces c.maxVersion in FIPS-only mode. -func fipsMaxVersion(c *Config) uint16 { - // FIPS requires TLS 1.2. - return VersionTLS12 -} - -// default defaultFIPSCurvePreferences is the FIPS-allowed curves, -// in preference order (most preferable first). -var defaultFIPSCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521} - -// fipsCurvePreferences replaces c.curvePreferences in FIPS-only mode. -func fipsCurvePreferences(c *Config) []CurveID { - if c == nil || len(c.CurvePreferences) == 0 { - return defaultFIPSCurvePreferences - } - var list []CurveID - for _, id := range c.CurvePreferences { - for _, allowed := range defaultFIPSCurvePreferences { - if id == allowed { - list = append(list, id) - break - } - } - } - return list -} - -// defaultCipherSuitesFIPS are the FIPS-allowed cipher suites. -var defaultCipherSuitesFIPS = []uint16{ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - TLS_RSA_WITH_AES_128_GCM_SHA256, - TLS_RSA_WITH_AES_256_GCM_SHA384, -} - -// fipsCipherSuites replaces c.cipherSuites in FIPS-only mode. -func fipsCipherSuites(c *Config) []uint16 { - if c == nil || c.CipherSuites == nil { - return defaultCipherSuitesFIPS - } - list := make([]uint16, 0, len(defaultCipherSuitesFIPS)) - for _, id := range c.CipherSuites { - for _, allowed := range defaultCipherSuitesFIPS { - if id == allowed { - list = append(list, id) - break - } - } - } - return list -} - -// fipsSupportedSignatureAlgorithms currently are a subset of -// defaultSupportedSignatureAlgorithms without Ed25519 and SHA-1. -var fipsSupportedSignatureAlgorithms = []SignatureScheme{ - PSSWithSHA256, - PSSWithSHA384, - PSSWithSHA512, - PKCS1WithSHA256, - ECDSAWithP256AndSHA256, - PKCS1WithSHA384, - ECDSAWithP384AndSHA384, - PKCS1WithSHA512, - ECDSAWithP521AndSHA512, -} - -// supportedSignatureAlgorithms returns the supported signature algorithms. -func supportedSignatureAlgorithms() []SignatureScheme { - if !needFIPS() { - return defaultSupportedSignatureAlgorithms - } - return fipsSupportedSignatureAlgorithms -} diff --git a/boring_test.go b/boring_test.go deleted file mode 100644 index f743fc8e..00000000 --- a/boring_test.go +++ /dev/null @@ -1,616 +0,0 @@ -// Copyright 2017 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. - -//go:build boringcrypto - -package tls - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "crypto/internal/boring/fipstls" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "fmt" - "math/big" - "net" - "runtime" - "strings" - "testing" - "time" -) - -func TestBoringServerProtocolVersion(t *testing.T) { - test := func(name string, v uint16, msg string) { - t.Run(name, func(t *testing.T) { - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionSSL30 - clientHello := &clientHelloMsg{ - vers: v, - random: make([]byte, 32), - cipherSuites: allCipherSuites(), - compressionMethods: []uint8{compressionNone}, - supportedVersions: []uint16{v}, - } - testClientHelloFailure(t, serverConfig, clientHello, msg) - }) - } - - test("VersionTLS10", VersionTLS10, "") - test("VersionTLS11", VersionTLS11, "") - test("VersionTLS12", VersionTLS12, "") - test("VersionTLS13", VersionTLS13, "") - - fipstls.Force() - defer fipstls.Abandon() - test("VersionSSL30", VersionSSL30, "client offered only unsupported versions") - test("VersionTLS10", VersionTLS10, "client offered only unsupported versions") - test("VersionTLS11", VersionTLS11, "client offered only unsupported versions") - test("VersionTLS12", VersionTLS12, "") - test("VersionTLS13", VersionTLS13, "client offered only unsupported versions") -} - -func isBoringVersion(v uint16) bool { - return v == VersionTLS12 -} - -func isBoringCipherSuite(id uint16) bool { - switch id { - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - TLS_RSA_WITH_AES_128_GCM_SHA256, - TLS_RSA_WITH_AES_256_GCM_SHA384: - return true - } - return false -} - -func isBoringCurve(id CurveID) bool { - switch id { - case CurveP256, CurveP384, CurveP521: - return true - } - return false -} - -func isECDSA(id uint16) bool { - for _, suite := range cipherSuites { - if suite.id == id { - return suite.flags&suiteECSign == suiteECSign - } - } - panic(fmt.Sprintf("unknown cipher suite %#x", id)) -} - -func isBoringSignatureScheme(alg SignatureScheme) bool { - switch alg { - default: - return false - case PKCS1WithSHA256, - ECDSAWithP256AndSHA256, - PKCS1WithSHA384, - ECDSAWithP384AndSHA384, - PKCS1WithSHA512, - ECDSAWithP521AndSHA512, - PSSWithSHA256, - PSSWithSHA384, - PSSWithSHA512: - // ok - } - return true -} - -func TestBoringServerCipherSuites(t *testing.T) { - serverConfig := testConfig.Clone() - serverConfig.CipherSuites = allCipherSuites() - serverConfig.Certificates = make([]Certificate, 1) - - for _, id := range allCipherSuites() { - if isECDSA(id) { - serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} - serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey - } else { - serverConfig.Certificates[0].Certificate = [][]byte{testRSACertificate} - serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey - } - serverConfig.BuildNameToCertificate() - t.Run(fmt.Sprintf("suite=%#x", id), func(t *testing.T) { - clientHello := &clientHelloMsg{ - vers: VersionTLS12, - random: make([]byte, 32), - cipherSuites: []uint16{id}, - compressionMethods: []uint8{compressionNone}, - supportedCurves: defaultCurvePreferences, - supportedPoints: []uint8{pointFormatUncompressed}, - } - - testClientHello(t, serverConfig, clientHello) - t.Run("fipstls", func(t *testing.T) { - fipstls.Force() - defer fipstls.Abandon() - msg := "" - if !isBoringCipherSuite(id) { - msg = "no cipher suite supported by both client and server" - } - testClientHelloFailure(t, serverConfig, clientHello, msg) - }) - }) - } -} - -func TestBoringServerCurves(t *testing.T) { - serverConfig := testConfig.Clone() - serverConfig.Certificates = make([]Certificate, 1) - serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} - serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey - serverConfig.BuildNameToCertificate() - - for _, curveid := range defaultCurvePreferences { - t.Run(fmt.Sprintf("curve=%d", curveid), func(t *testing.T) { - clientHello := &clientHelloMsg{ - vers: VersionTLS12, - random: make([]byte, 32), - cipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, - compressionMethods: []uint8{compressionNone}, - supportedCurves: []CurveID{curveid}, - supportedPoints: []uint8{pointFormatUncompressed}, - } - - testClientHello(t, serverConfig, clientHello) - - // With fipstls forced, bad curves should be rejected. - t.Run("fipstls", func(t *testing.T) { - fipstls.Force() - defer fipstls.Abandon() - msg := "" - if !isBoringCurve(curveid) { - msg = "no cipher suite supported by both client and server" - } - testClientHelloFailure(t, serverConfig, clientHello, msg) - }) - }) - } -} - -func boringHandshake(t *testing.T, clientConfig, serverConfig *Config) (clientErr, serverErr error) { - c, s := localPipe(t) - client := Client(c, clientConfig) - server := Server(s, serverConfig) - done := make(chan error, 1) - go func() { - done <- client.Handshake() - c.Close() - }() - serverErr = server.Handshake() - s.Close() - clientErr = <-done - return -} - -func TestBoringServerSignatureAndHash(t *testing.T) { - defer func() { - testingOnlyForceClientHelloSignatureAlgorithms = nil - }() - - for _, sigHash := range defaultSupportedSignatureAlgorithms { - t.Run(fmt.Sprintf("%#x", sigHash), func(t *testing.T) { - serverConfig := testConfig.Clone() - serverConfig.Certificates = make([]Certificate, 1) - - testingOnlyForceClientHelloSignatureAlgorithms = []SignatureScheme{sigHash} - - sigType, _, _ := typeAndHashFromSignatureScheme(sigHash) - switch sigType { - case signaturePKCS1v15, signatureRSAPSS: - serverConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} - serverConfig.Certificates[0].Certificate = [][]byte{testRSA2048Certificate} - serverConfig.Certificates[0].PrivateKey = testRSA2048PrivateKey - case signatureEd25519: - serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256} - serverConfig.Certificates[0].Certificate = [][]byte{testEd25519Certificate} - serverConfig.Certificates[0].PrivateKey = testEd25519PrivateKey - case signatureECDSA: - serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256} - serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} - serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey - } - serverConfig.BuildNameToCertificate() - // PKCS#1 v1.5 signature algorithms can't be used standalone in TLS - // 1.3, and the ECDSA ones bind to the curve used. - serverConfig.MaxVersion = VersionTLS12 - - clientErr, serverErr := boringHandshake(t, testConfig, serverConfig) - if clientErr != nil { - t.Fatalf("expected handshake with %#x to succeed; client error: %v; server error: %v", sigHash, clientErr, serverErr) - } - - // With fipstls forced, bad curves should be rejected. - t.Run("fipstls", func(t *testing.T) { - fipstls.Force() - defer fipstls.Abandon() - clientErr, _ := boringHandshake(t, testConfig, serverConfig) - if isBoringSignatureScheme(sigHash) { - if clientErr != nil { - t.Fatalf("expected handshake with %#x to succeed; err=%v", sigHash, clientErr) - } - } else { - if clientErr == nil { - t.Fatalf("expected handshake with %#x to fail, but it succeeded", sigHash) - } - } - }) - }) - } -} - -func TestBoringClientHello(t *testing.T) { - // Test that no matter what we put in the client config, - // the client does not offer non-FIPS configurations. - fipstls.Force() - defer fipstls.Abandon() - - c, s := net.Pipe() - defer c.Close() - defer s.Close() - - clientConfig := testConfig.Clone() - // All sorts of traps for the client to avoid. - clientConfig.MinVersion = VersionSSL30 - clientConfig.MaxVersion = VersionTLS13 - clientConfig.CipherSuites = allCipherSuites() - clientConfig.CurvePreferences = defaultCurvePreferences - - go Client(c, clientConfig).Handshake() - srv := Server(s, testConfig) - msg, err := srv.readHandshake() - if err != nil { - t.Fatal(err) - } - hello, ok := msg.(*clientHelloMsg) - if !ok { - t.Fatalf("unexpected message type %T", msg) - } - - if !isBoringVersion(hello.vers) { - t.Errorf("client vers=%#x, want %#x (TLS 1.2)", hello.vers, VersionTLS12) - } - for _, v := range hello.supportedVersions { - if !isBoringVersion(v) { - t.Errorf("client offered disallowed version %#x", v) - } - } - for _, id := range hello.cipherSuites { - if !isBoringCipherSuite(id) { - t.Errorf("client offered disallowed suite %#x", id) - } - } - for _, id := range hello.supportedCurves { - if !isBoringCurve(id) { - t.Errorf("client offered disallowed curve %d", id) - } - } - for _, sigHash := range hello.supportedSignatureAlgorithms { - if !isBoringSignatureScheme(sigHash) { - t.Errorf("client offered disallowed signature-and-hash %v", sigHash) - } - } -} - -func TestBoringCertAlgs(t *testing.T) { - // NaCl, arm and wasm time out generating keys. Nothing in this test is architecture-specific, so just don't bother on those. - if runtime.GOOS == "nacl" || runtime.GOARCH == "arm" || runtime.GOOS == "js" { - t.Skipf("skipping on %s/%s because key generation takes too long", runtime.GOOS, runtime.GOARCH) - } - - // Set up some roots, intermediate CAs, and leaf certs with various algorithms. - // X_Y is X signed by Y. - R1 := boringCert(t, "R1", boringRSAKey(t, 2048), nil, boringCertCA|boringCertFIPSOK) - R2 := boringCert(t, "R2", boringRSAKey(t, 4096), nil, boringCertCA) - - M1_R1 := boringCert(t, "M1_R1", boringECDSAKey(t, elliptic.P256()), R1, boringCertCA|boringCertFIPSOK) - M2_R1 := boringCert(t, "M2_R1", boringECDSAKey(t, elliptic.P224()), R1, boringCertCA) - - I_R1 := boringCert(t, "I_R1", boringRSAKey(t, 3072), R1, boringCertCA|boringCertFIPSOK) - I_R2 := boringCert(t, "I_R2", I_R1.key, R2, boringCertCA|boringCertFIPSOK) - I_M1 := boringCert(t, "I_M1", I_R1.key, M1_R1, boringCertCA|boringCertFIPSOK) - I_M2 := boringCert(t, "I_M2", I_R1.key, M2_R1, boringCertCA|boringCertFIPSOK) - - L1_I := boringCert(t, "L1_I", boringECDSAKey(t, elliptic.P384()), I_R1, boringCertLeaf|boringCertFIPSOK) - L2_I := boringCert(t, "L2_I", boringRSAKey(t, 1024), I_R1, boringCertLeaf) - - // client verifying server cert - testServerCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) { - clientConfig := testConfig.Clone() - clientConfig.RootCAs = pool - clientConfig.InsecureSkipVerify = false - clientConfig.ServerName = "example.com" - - serverConfig := testConfig.Clone() - serverConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}} - serverConfig.BuildNameToCertificate() - - clientErr, _ := boringHandshake(t, clientConfig, serverConfig) - - if (clientErr == nil) == ok { - if ok { - t.Logf("%s: accept", desc) - } else { - t.Logf("%s: reject", desc) - } - } else { - if ok { - t.Errorf("%s: BAD reject (%v)", desc, clientErr) - } else { - t.Errorf("%s: BAD accept", desc) - } - } - } - - // server verifying client cert - testClientCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) { - clientConfig := testConfig.Clone() - clientConfig.ServerName = "example.com" - clientConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}} - - serverConfig := testConfig.Clone() - serverConfig.ClientCAs = pool - serverConfig.ClientAuth = RequireAndVerifyClientCert - - _, serverErr := boringHandshake(t, clientConfig, serverConfig) - - if (serverErr == nil) == ok { - if ok { - t.Logf("%s: accept", desc) - } else { - t.Logf("%s: reject", desc) - } - } else { - if ok { - t.Errorf("%s: BAD reject (%v)", desc, serverErr) - } else { - t.Errorf("%s: BAD accept", desc) - } - } - } - - // Run simple basic test with known answers before proceeding to - // exhaustive test with computed answers. - r1pool := x509.NewCertPool() - r1pool.AddCert(R1.cert) - testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true) - testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true) - fipstls.Force() - testServerCert(t, "basic (fips)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false) - testClientCert(t, "basic (fips, client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false) - fipstls.Abandon() - - if t.Failed() { - t.Fatal("basic test failed, skipping exhaustive test") - } - - if testing.Short() { - t.Logf("basic test passed; skipping exhaustive test in -short mode") - return - } - - for l := 1; l <= 2; l++ { - leaf := L1_I - if l == 2 { - leaf = L2_I - } - for i := 0; i < 64; i++ { - reachable := map[string]bool{leaf.parentOrg: true} - reachableFIPS := map[string]bool{leaf.parentOrg: leaf.fipsOK} - list := [][]byte{leaf.der} - listName := leaf.name - addList := func(cond int, c *boringCertificate) { - if cond != 0 { - list = append(list, c.der) - listName += "," + c.name - if reachable[c.org] { - reachable[c.parentOrg] = true - } - if reachableFIPS[c.org] && c.fipsOK { - reachableFIPS[c.parentOrg] = true - } - } - } - addList(i&1, I_R1) - addList(i&2, I_R2) - addList(i&4, I_M1) - addList(i&8, I_M2) - addList(i&16, M1_R1) - addList(i&32, M2_R1) - - for r := 1; r <= 3; r++ { - pool := x509.NewCertPool() - rootName := "," - shouldVerify := false - shouldVerifyFIPS := false - addRoot := func(cond int, c *boringCertificate) { - if cond != 0 { - rootName += "," + c.name - pool.AddCert(c.cert) - if reachable[c.org] { - shouldVerify = true - } - if reachableFIPS[c.org] && c.fipsOK { - shouldVerifyFIPS = true - } - } - } - addRoot(r&1, R1) - addRoot(r&2, R2) - rootName = rootName[1:] // strip leading comma - testServerCert(t, listName+"->"+rootName[1:], pool, leaf.key, list, shouldVerify) - testClientCert(t, listName+"->"+rootName[1:]+"(client cert)", pool, leaf.key, list, shouldVerify) - fipstls.Force() - testServerCert(t, listName+"->"+rootName[1:]+" (fips)", pool, leaf.key, list, shouldVerifyFIPS) - testClientCert(t, listName+"->"+rootName[1:]+" (fips, client cert)", pool, leaf.key, list, shouldVerifyFIPS) - fipstls.Abandon() - } - } - } -} - -const ( - boringCertCA = iota - boringCertLeaf - boringCertFIPSOK = 0x80 -) - -func boringRSAKey(t *testing.T, size int) *rsa.PrivateKey { - k, err := rsa.GenerateKey(rand.Reader, size) - if err != nil { - t.Fatal(err) - } - return k -} - -func boringECDSAKey(t *testing.T, curve elliptic.Curve) *ecdsa.PrivateKey { - k, err := ecdsa.GenerateKey(curve, rand.Reader) - if err != nil { - t.Fatal(err) - } - return k -} - -type boringCertificate struct { - name string - org string - parentOrg string - der []byte - cert *x509.Certificate - key interface{} - fipsOK bool -} - -func boringCert(t *testing.T, name string, key interface{}, parent *boringCertificate, mode int) *boringCertificate { - org := name - parentOrg := "" - if i := strings.Index(org, "_"); i >= 0 { - org = org[:i] - parentOrg = name[i+1:] - } - tmpl := &x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{ - Organization: []string{org}, - }, - NotBefore: time.Unix(0, 0), - NotAfter: time.Unix(0, 0), - - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, - BasicConstraintsValid: true, - } - if mode&^boringCertFIPSOK == boringCertLeaf { - tmpl.DNSNames = []string{"example.com"} - } else { - tmpl.IsCA = true - tmpl.KeyUsage |= x509.KeyUsageCertSign - } - - var pcert *x509.Certificate - var pkey interface{} - if parent != nil { - pcert = parent.cert - pkey = parent.key - } else { - pcert = tmpl - pkey = key - } - - var pub interface{} - switch k := key.(type) { - case *rsa.PrivateKey: - pub = &k.PublicKey - case *ecdsa.PrivateKey: - pub = &k.PublicKey - default: - t.Fatalf("invalid key %T", key) - } - - der, err := x509.CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey) - if err != nil { - t.Fatal(err) - } - cert, err := x509.ParseCertificate(der) - if err != nil { - t.Fatal(err) - } - - fipsOK := mode&boringCertFIPSOK != 0 - return &boringCertificate{name, org, parentOrg, der, cert, key, fipsOK} -} - -// A self-signed test certificate with an RSA key of size 2048, for testing -// RSA-PSS with SHA512. SAN of example.golang. -var ( - testRSA2048Certificate []byte - testRSA2048PrivateKey *rsa.PrivateKey -) - -func init() { - block, _ := pem.Decode([]byte(` ------BEGIN CERTIFICATE----- -MIIC/zCCAeegAwIBAgIRALHHX/kh4+4zMU9DarzBEcQwDQYJKoZIhvcNAQELBQAw -EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xMTAxMDExNTA0MDVaFw0yMDEyMjkxNTA0 -MDVaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQCf8fk0N6ieCBX4IOVIfKitt4kGcOQLeimCfsjqqHcysMIVGEtFSM6E -4Ay141f/7IqdW0UtIqNb4PXhROID7yDxR284xL6XbCuv/t5hP3UcehYc3hmLiyVd -MkZQiZWtfUUJf/1qOtM+ohNg59LRWp4d+6iX0la1JL3EwCIckkNjJ9hQbF7Pb2CS -+ES9Yo55KAap8KOblpcR8MBSN38bqnwjfQdCXvOEOjam2HUxKzEFX5MA+fA0me4C -ioCcCRLWKl+GoN9F8fABfoZ+T+2eal4DLuO95rXR8SrOIVBh3XFOr/RVhjtXcNVF -ZKcvDt6d68V6jAKAYKm5nlj9GPpd4v+rAgMBAAGjUDBOMA4GA1UdDwEB/wQEAwIF -oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBkGA1UdEQQSMBCC -DmV4YW1wbGUuZ29sYW5nMA0GCSqGSIb3DQEBCwUAA4IBAQCOoYsVcFCBhboqe3WH -dC6V7XXXECmnjh01r8h80yv0NR379nSD3cw2M+HKvaXysWqrl5hjGVKw0vtwD81r -V4JzDu7IfIog5m8+QNC+7LqDZsz88vDKOrsoySVOmUCgmCKFXew+LA+eO/iQEJTr -7ensddOeXJEp27Ed5vW+kmWW3Qmglc2Gwy8wFrMDIqnrnOzBA4oCnDEgtXJt0zog -nRwbfEMAWi1aQRy5dT9KA3SP9mo5SeTFSzGGHiE4s4gHUe7jvsAFF2qgtD6+wH6s -z9b6shxnC7g5IlBKhI7SVB/Uqt2ydJ+kH1YbjMcIq6NAM5eNMKgZuJr3+zwsSgwh -GNaE ------END CERTIFICATE-----`)) - testRSA2048Certificate = block.Bytes - - block, _ = pem.Decode([]byte(` ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAn/H5NDeonggV+CDlSHyorbeJBnDkC3opgn7I6qh3MrDCFRhL -RUjOhOAMteNX/+yKnVtFLSKjW+D14UTiA+8g8UdvOMS+l2wrr/7eYT91HHoWHN4Z -i4slXTJGUImVrX1FCX/9ajrTPqITYOfS0VqeHfuol9JWtSS9xMAiHJJDYyfYUGxe -z29gkvhEvWKOeSgGqfCjm5aXEfDAUjd/G6p8I30HQl7zhDo2pth1MSsxBV+TAPnw -NJnuAoqAnAkS1ipfhqDfRfHwAX6Gfk/tnmpeAy7jvea10fEqziFQYd1xTq/0VYY7 -V3DVRWSnLw7enevFeowCgGCpuZ5Y/Rj6XeL/qwIDAQABAoIBAQCNpMZifd/vg42h -HdCvLuZaYS0R7SunFlpoXEsltGdLFsnp0IfoJZ/ugFQBSAIIfLwMumU6oXA1z7Uv -98aIYV61DePrTCDVDFBsHbNmP8JAo8WtbusEbwd5zyoB7LYG2+clkJklWE73KqUq -rmI+UJeyScl2Gin7ZTxBXz1WPBk9VwcnwkeaXpgASIBW23fhECM9gnYEEwaBez5T -6Me8d1tHtYQv7vsKe7ro9w9/HKrRXejqYKK1LxkhfFriyV+m8LZJZn2nXOa6G3gF -Nb8Qk1Uk5PUBENBmyMFJhT4M/uuSq4YtMrrO2gi8Q+fPhuGzc5SshYKRBp0W4P5r -mtVCtEFRAoGBAMENBIFLrV2+HsGj0xYFasKov/QPe6HSTR1Hh2IZONp+oK4oszWE -jBT4VcnITmpl6tC1Wy4GcrxjNgKIFZAj+1x1LUULdorXkuG8yr0tAhG9zNyfWsSy -PrSovC0UVbzr8Jxxla+kQVxEQQqWQxPlEVuL8kXaIDA6Lyt1Hpua2LvPAoGBANQZ -c6Lq2T7+BxLxNdi2m8kZzej5kgzBp/XdVsbFWRlebIX2KrFHsrHzT9PUk3DE1vZK -M6pzTt94nQhWSkDgCaw1SohElJ3HFIFwcusF1SJAc3pQepd8ug6IYdlpDMLtBj/P -/5P6BVUtgo05E4+I/T3iYatmglQxTtlZ0RkSV2llAoGBALOXkKFX7ahPvf0WksDh -uTfuFOTPoowgQG0EpgW0wRdCxeg/JLic3lSD0gsttQV2WsRecryWcxaelRg10RmO -38BbogmhaF4xvgsSvujOfiZTE8oK1T43M+6NKsIlML3YILbpU/9aJxPWy0s2DqDr -cQJhZrlk+pzjBA7Bnf/URdwxAoGAKR/CNw14D+mrL3YLbbiCXiydqxVwxv5pdZdz -8thi3TNcsWC4iGURdcVqbfUinVPdJiXe/Kac3WGCeRJaFVgbKAOxLti1RB5MkIhg -D8eyupBqk4W1L1gkrxqsdj4TFlxkwMywjl2E2S4YyQ8PBt6V04DoVRZsIKzqz+PF -UionPq0CgYBCYXvqioJhPewkOq/Y5wrDBeZW1FQK5QD9W5M8/5zxd4rdvJtjhbJp -oOrtvMdrl6upy9Hz4BJD3FXwVFiPFE7jqeNqi0F21viLxBPMMD3UODF6LL5EyLiR -9V4xVMS8KXxvg7rxsuqzMPscViaWUL6WNVBhsD2+92dHxSXzz5EJKQ== ------END RSA PRIVATE KEY-----`)) - var err error - testRSA2048PrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - panic(err) - } -} diff --git a/common.go b/common.go index c7741ef9..b3d7f89b 100644 --- a/common.go +++ b/common.go @@ -100,6 +100,7 @@ const ( 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 ) diff --git a/notboring.go b/notboring.go index 7d85b39c..a8fcdf53 100644 --- a/notboring.go +++ b/notboring.go @@ -1,11 +1,13 @@ // Copyright 2022 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. - -//go:build !boringcrypto - package tls +import ( + "crypto/cipher" + "errors" +) + func needFIPS() bool { return false } func supportedSignatureAlgorithms() []SignatureScheme { @@ -18,3 +20,20 @@ func fipsCurvePreferences(c *Config) []CurveID { panic("fipsCurvePreferences") } func fipsCipherSuites(c *Config) []uint16 { panic("fipsCipherSuites") } var fipsSupportedSignatureAlgorithms []SignatureScheme + +// [uTLS] +// Boring struct is only to be used to record static env variables +// in boring package. We do not implement BoringSSL compatibliity here. +type Boring struct { + Enabled bool +} + +func (*Boring) NewGCMTLS(_ cipher.Block) (cipher.AEAD, error) { + return nil, errors.New("boring not implemented") +} + +func (*Boring) Unreachable() { + // do nothing +} + +var boring Boring \ No newline at end of file From 7edeeded0aacb33e4bad9441689406b95fde6c00 Mon Sep 17 00:00:00 2001 From: Gaukas Wang Date: Fri, 28 Oct 2022 00:19:53 -0600 Subject: [PATCH 3/4] Update README.md --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 97b48b38..ea82b497 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,17 @@ # ![uTLS](logo_small.png) uTLS -[![Build Status](https://travis-ci.org/refraction-networking/utls.svg?branch=master)](https://travis-ci.org/refraction-networking/utls) + [![godoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/refraction-networking/utls#UConn) --- uTLS is a fork of "crypto/tls", which provides ClientHello fingerprinting resistance, low-level access to handshake, fake session tickets and some other features. Handshake is still performed by "crypto/tls", this library merely changes ClientHello part of it and provides low-level access. -Golang 1.11+ is required. -If you have any questions, bug reports or contributions, you are welcome to publish those on GitHub. If you want to do so in private, you can contact one of developers personally via sergey.frolov@colorado.edu +Golang 1.19+ is required. + +If you have any questions, bug reports or contributions, you are welcome to publish those on GitHub. If you want to do so in private, you can contact one of developers personally via sergey.frolov@colorado.edu. Documentation below may not keep up with all the changes and new features at all times, so you are encouraged to use [godoc](https://godoc.org/github.com/refraction-networking/utls#UConn). +*Note: Information provided below in this README.md could be obsolete.* + # Features ## Low-level access to handshake * Read/write access to all bits of client hello message. From e9b8ee123201ac9e274887ff7f8516dd5a9b8b2c Mon Sep 17 00:00:00 2001 From: Gaukas Wang Date: Fri, 28 Oct 2022 00:40:30 -0600 Subject: [PATCH 4/4] chore: fixing comments - uncomment an occurrence of `boring` - edited comment for `decryptTicket`/`DecryptTicketWith` to reflect changes made. --- auth.go | 6 +++--- ticket.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/auth.go b/auth.go index 42775e3d..7c5675c6 100644 --- a/auth.go +++ b/auth.go @@ -242,9 +242,9 @@ func selectSignatureScheme(vers uint16, c *Certificate, peerAlgs []SignatureSche // Pick signature scheme in the peer's preference order, as our // preference order is not configurable. for _, preferredAlg := range peerAlgs { - // if needFIPS() && !isSupportedSignatureAlgorithm(preferredAlg, fipsSupportedSignatureAlgorithms) { - // continue - // } + if needFIPS() && !isSupportedSignatureAlgorithm(preferredAlg, fipsSupportedSignatureAlgorithms) { + continue + } if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) { return preferredAlg, nil } diff --git a/ticket.go b/ticket.go index ba34a51d..9ce14540 100644 --- a/ticket.go +++ b/ticket.go @@ -144,7 +144,7 @@ func (c *Conn) encryptTicket(state []byte) ([]byte, error) { return encrypted, nil } -// [uTLS] changed to use exported DecryptTicketWith func below +// [uTLS] added exported DecryptTicketWith func below func (c *Conn) decryptTicket(encrypted []byte) (plaintext []byte, usedOldKey bool) { if len(encrypted) < ticketKeyNameLen+aes.BlockSize+sha256.Size { return nil, false @@ -191,7 +191,7 @@ func (c *Conn) decryptTicket(encrypted []byte) (plaintext []byte, usedOldKey boo // usedOldKey will be true if the key used for decryption is // not the first in the []TicketKey slice // -// [uTLS] changed to be made public and take a TicketKeys instead of use a Conn receiver +// [uTLS] changed to be made public and take a TicketKeys and use a fake conn receiver func DecryptTicketWith(encrypted []byte, tks TicketKeys) (plaintext []byte, usedOldKey bool) { // create fake conn c := &Conn{