serverHandshakeState::readClientHello was setting selected ALPN protocol
always on hs.hello.alpnProtocol, which is specific to TLS 1.2 and older.
Because of that server was marshalling ALPN to SH instead of EE.
It's sufficient to pass in the *tls.Certificate (resp.
*x509.Certificate) to the server functions (resp. client funcctions),
but not necessary; the existing keyAgreement implementations only makes
use of the private key (resp. public key). Moreover, this change is
necessary for implementing the delegated credentials extension, which
replaces the private key (resp. public key) used in the handshake.
Send/Skip CCS, set legacy record version to 3,3 and echo session ID.
CCS must be ignored while the handshake is running, but not thereafter:
https://tools.ietf.org/html/draft-ietf-tls-tls13-22#section-5
Unconditionally send CCS as server because bogo requires it, even if no
session ID is included in the Client Hello. TLS 1.3 clients MUST ignore
it anyway, so it should not hurt.
Fixes interop with boringssl and openssl and passes bogo.
ServerKeyExchange and CertificateVerify can share the same logic for
picking a signature algorithm (based on the certificate public key and
advertised algorithms), selecting a hash algorithm (depending on TLS
version) and signature verification.
Refactor the code to achieve code reuse, have common error checking
(especially for intersecting supported signature algorithms) and to
prepare for addition of new signature algorithms. Code should be easier
to read since version-dependent logic is concentrated at one place.
Change-Id: I978dec3815d28e33c3cfbc85f0c704b1894c25a3
Disable 0.5-RTT as it has weaker security properties than 1-RTT. The
same security considerations from TLS False Start (RFC 7918) apply.
Currently the server Handshake method returns as soon as it has sent its
parameters, but it does not wait for the client to authenticate the
handshake via a Finished message. This broke a test that assumed that
the Handshake message performs a full handshake and also
(unintentionally?) enabled the server to send application data before
the handshake is complete ("0.5-RTT data").
Fix this by moving the implicit Finished message check in the handshake
message reader to the server handshake itself (previously readRecord
would process the Finished message as a side-effect of requesting
recordTypeApplicationData). And in the special case where 0-RTT data is
actually desired, process the Finished message in the ConfirmHandshake
and Read functions.
NOTE: 0.5-RTT is not disabled when the server enables 0-RTT. It is the
server responsibility to use ConfirmHandshake before writing anything.
Explicitly panic when ConfirmHandshake is used for client connections,
this is not the intended use of that API.
Merge serverHelloMsg13 into serverHelloMsg in preparation for draft 22.
This will also simplify the client implementation since only one
structure has to be checked.
Also fixed potential out-of-bounds access with keyShare unmarshal.
Merge upstream go post-1.9 crypto/tls changes from master:
d8ee5d11e5 crypto/tls: limit number of consecutive warning alerts
96cd66b266 crypto/tls: advertise support for SHA-512 signatures in 1.2
f265f5db5d archive/zip, crypto/tls: use rand.Read instead of casting ints to bytes
54d04c2fcb crypto/tls: remove bookkeeping code from pHash function
d1bbdbe760 crypto/tls: replace signatureAndHash by SignatureScheme.
cb3b345209 crypto/tls: fix first byte test for 255 CBC padding bytes
d153df8e4b all: revert "all: prefer strings.LastIndexByte over strings.LastIndex"
5e42658fc0 all: prefer bytes.IndexByte over bytes.Index
d2826d3e06 all: prefer strings.LastIndexByte over strings.LastIndex
5a986eca86 all: fix article typos
0f9a2cf2c4 crypto/tls: fix clientHelloMsg fuzzer not to generate the RI SCSV
e7d46cee2f crypto/tls: fix and expand TestVerifyPeerCertificate and TestGetClientCertificate
85deaf6077 crypto/tls: fix docstring of Config.ClientSessionCache
4a5f85babb crypto/tls: disallow handshake messages fragmented across CCS
b3465646ff crypto/tls: add BenchmarkHandshakeServer
d38d357c78 crypto/tls: don't check whether an ec point is on a curve twice
e085a891f0 crypto/tls: split clientHandshake into multiple methods
Conflicts:
* handshake_client.go: conflict between our ("crypto/tls: allow client to
pick TLS 1.3, do not enable it by default.") and upstream
("crypto/tls: split clientHandshake into multiple methods"), resolve
by applying the mutualVersion->pickVersion change in pickTLSVersion.
* handshake_server.go: trivial conflict due to upstreamed patch
("crypto/tls: replace signatureAndHash by SignatureScheme.") and
("crypto/tls: implement TLS 1.3 server 0-RTT") which added pskBinder.
Other merge changes:
* tls13.go: signatureAndHashes as added in ("crypto/tls: implement TLS
1.3 minimal server") was renamed as required by ("crypto/tls: replace
signatureAndHash by SignatureScheme.").
* handshake_client.go: moved check from ("crypto/tls: check that client
cipher suite matches version") to pickCipherSuite as required by
("crypto/tls: split clientHandshake into multiple methods").
Consolidate the signature and hash fields (SignatureAndHashAlgorithm in
TLS 1.2) into a single uint16 (SignatureScheme in TLS 1.3 draft 21).
This makes it easier to add RSASSA-PSS for TLS 1.2 in the future.
Fields were named like "signatureAlgorithm" rather than
"signatureScheme" since that name is also used throughout the 1.3 draft.
The only new public symbol is ECDSAWithSHA1, other than that this is an
internal change with no new functionality.
Change-Id: Iba63d262ab1af895420583ac9e302d9705a7e0f0
Reviewed-on: https://go-review.googlesource.com/62210
Reviewed-by: Adam Langley <agl@golang.org>
To allow clients to advertise both TLS 1.2 and TLS 1.3 cipher suites,
remove the distinction between both suites. TLS 1.3 suites are now
always included in the default cipher list (and the client will send it
if MaxVersion allows for it).
Since TLS 1.3 is expected to become the default MaxVersion and
applications might have set only TLS 1.2 cipher suites in their
configuration, TLS 1.3 cipher suites are added when none are present.
Alternatively, I considered disallowing overriding the TLS 1.3 suites,
but that requires more complexity and has not much benefits. Provide a
mechanism and do not dictate policy, application developers might want
to fix a cipher suite for testing other implementations for example.
Fixes https://github.com/cloudflare/tls-tris/pull/22
Use the new keySchedule13 type instead of hash.Hash to avoid tracking
the hashContext and intermediate secrets manually.
checkPSK is modified not to return the calculated early secret, this is
internal to keySchedule13 now. The caller just learns whether it was
resumed using a PSK or not.
There should be no data in the Handshake buffer on encryption state
changes (including implicit 1.3 transitions). Checking that also blocks
all Handshake messages fragmented across CCS.
BoGo: PartialClientFinishedWithClientHello
Phase should only be accessed under in.Mutex. Handshake and all Read
operations obtain that lock. However, many functions checking for
handshakeRunning only obtain handshakeMutex: reintroduce
handshakeCompleted for them. ConnectionState and Close check for
handshakeConfirmed, introduce an atomic flag for them.
I opted for adding a separate TLS13CipherSuites field to the Config
because library users that did not set Config.MaxVersion are
supposed to get TLS 1.3 support automatically, like it has been for
HTTP/2, but having set CipherSuites would effectively disable it.
Updates #9671
Change-Id: I26a2776b68374d6f5ee45629da09f9494fe723ad
The SignatureAndHashAlgorithm from TLS 1.2[1] is being changed to
SignatureScheme in TLS 1.3[2]. (The actual values are compatible
however.)
Since we expect to support TLS 1.3 in the future, we're already using
the name and style of SignatureScheme in the recently augmented
ClientHelloInfo. As this is public API, it seems that SignatureScheme
should have its own type and exported values, which is implemented in
this change.
[1] https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
[2] https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.3
Change-Id: I0482755d02bb9a04eaf075c012696103eb806645
Reviewed-on: https://go-review.googlesource.com/32119
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
VerifyPeerCertificate returns an error if the peer should not be
trusted. It will be called after the initial handshake and before
any other verification checks on the cert or chain are performed.
This provides the callee an opportunity to augment the certificate
verification.
If VerifyPeerCertificate is not nil and returns an error,
then the handshake will fail.
Fixes#16363
Change-Id: I6a22f199f0e81b6f5d5f37c54d85ab878216bb22
Reviewed-on: https://go-review.googlesource.com/26654
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
GetConfigForClient allows the tls.Config to be updated on a per-client
basis.
Fixes#16066.
Fixes#15707.
Fixes#15699.
Change-Id: I2c675a443d557f969441226729f98502b38901ea
Reviewed-on: https://go-review.googlesource.com/30790
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Add support for writing TLS client random and master secret
in NSS key log format.
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
Normally this is enabled by a developer debugging TLS based
applications, especially HTTP/2, by setting the KeyLogWriter
to an open file. The keys negotiated in handshake are then
logged and can be used to decrypt TLS sessions e.g. in Wireshark.
Applications may choose to add support similar to NSS where this
is enabled by environment variable, but no such mechanism is
built in to Go. Instead each application must explicitly enable.
Fixes#13057.
Change-Id: If6edd2d58999903e8390b1674ba4257ecc747ae1
Reviewed-on: https://go-review.googlesource.com/27434
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This change causes TLS handshake messages to be buffered and written in
a single Write to the underlying net.Conn.
There are two reasons to want to do this:
Firstly, it's slightly preferable to do this in order to save sending
several, small packets over the network where a single one will do.
Secondly, since 37c28759ca46cf381a466e32168a793165d9c9e9 errors from
Write have been returned from a handshake. This means that, if a peer
closes the connection during a handshake, a “broken pipe” error may
result from tls.Conn.Handshake(). This can mask any, more detailed,
fatal alerts that the peer may have sent because a read will never
happen.
Buffering handshake messages means that the peer will not receive, and
possibly reject, any of a flow while it's still being written.
Fixes#15709
Change-Id: I38dcff1abecc06e52b2de647ea98713ce0fb9a21
Reviewed-on: https://go-review.googlesource.com/23609
Reviewed-by: Andrew Gerrand <adg@golang.org>
Run-TryBot: Andrew Gerrand <adg@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Instead, decline the session and do a full handshake. The semantics of
cross-version resume are unclear, and all major client implementations
treat this as a fatal error. (This doesn't come up very much, mostly if
the client does the browser version fallback without sharding the
session cache.)
See BoringSSL's bdf5e72f50e25f0e45e825c156168766d8442dde and OpenSSL's
9e189b9dc10786c755919e6792e923c584c918a1.
Change-Id: I51ca95ac1691870dd0c148fd967739e2d4f58824
Reviewed-on: https://go-review.googlesource.com/21152
Reviewed-by: Adam Langley <agl@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This change adds Config.Renegotiation which controls whether a TLS
client will accept renegotiation requests from a server. This is used,
for example, by some web servers that wish to “add” a client certificate
to an HTTPS connection.
This is disabled by default because it significantly complicates the
state machine.
Originally, handshakeMutex was taken before locking either Conn.in or
Conn.out. However, if renegotiation is permitted then a handshake may
be triggered during a Read() call. If Conn.in were unlocked before
taking handshakeMutex then a concurrent Read() call could see an
intermediate state and trigger an error. Thus handshakeMutex is now
locked after Conn.in and the handshake functions assume that Conn.in is
locked for the duration of the handshake.
Additionally, handshakeMutex used to protect Conn.out also. With the
possibility of renegotiation that's no longer viable and so
writeRecordLocked has been split off.
Fixes#5742.
Change-Id: I935914db1f185d507ff39bba8274c148d756a1c8
Reviewed-on: https://go-review.googlesource.com/22475
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
Error strings in this package were all over the place: some were
prefixed with “tls:”, some with “crypto/tls:” and some didn't have a
prefix.
This change makes everything use the prefix “tls:”.
Change-Id: Ie8b073c897764b691140412ecd6613da8c4e33a2
Reviewed-on: https://go-review.googlesource.com/21893
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
This promotes a connection hang during TLS handshake to a proper error.
This doesn't fully address #14539 because the error reported in that
case is a write-on-socket-not-connected error, which implies that an
earlier error during connection setup is not being checked, but it is
an improvement over the current behaviour.
Updates #14539.
Change-Id: I0571a752d32d5303db48149ab448226868b19495
Reviewed-on: https://go-review.googlesource.com/19990
Reviewed-by: Adam Langley <agl@golang.org>
The tree's pretty inconsistent about single space vs double space
after a period in documentation. Make it consistently a single space,
per earlier decisions. This means contributors won't be confused by
misleading precedence.
This CL doesn't use go/doc to parse. It only addresses // comments.
It was generated with:
$ perl -i -npe 's,^(\s*// .+[a-z]\.) +([A-Z]),$1 $2,' $(git grep -l -E '^\s*//(.+\.) +([A-Z])')
$ go test go/doc -update
Change-Id: Iccdb99c37c797ef1f804a94b22ba5ee4b500c4f7
Reviewed-on: https://go-review.googlesource.com/20022
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Dave Day <djd@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Previously we enforced both that the extended key usages of a client
certificate chain allowed for client authentication, and that the
client-auth EKU was in the leaf certificate.
This change removes the latter requirement. It's still the case that the
chain must be compatible with the client-auth EKU (i.e. that a parent
certificate isn't limited to another usage, like S/MIME), but we'll now
accept a leaf certificate with no EKUs for client-auth.
While it would be nice if all client certificates were explicit in their
intended purpose, I no longer feel that this battle is worthwhile.
Fixes#11087.
Change-Id: I777e695101cbeba069b730163533e2977f4dc1fc
Reviewed-on: https://go-review.googlesource.com/10806
Reviewed-by: Andrew Gerrand <adg@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
Prior to TLS 1.2, the handshake had a pleasing property that one could
incrementally hash it and, from that, get the needed hashes for both
the CertificateVerify and Finished messages.
TLS 1.2 introduced negotiation for the signature and hash and it became
possible for the handshake hash to be, say, SHA-384, but for the
CertificateVerify to sign the handshake with SHA-1. The problem is that
one doesn't know in advance which hashes will be needed and thus the
handshake needs to be buffered.
Go ignored this, always kept a single handshake hash, and any signatures
over the handshake had to use that hash.
However, there are a set of servers that inspect the client's offered
signature hash functions and will abort the handshake if one of the
server's certificates is signed with a hash function outside of that
set. https://robertsspaceindustries.com/ is an example of such a server.
Clearly not a lot of thought happened when that server code was written,
but its out there and we have to deal with it.
This change decouples the handshake hash from the CertificateVerify
hash. This lays the groundwork for advertising support for SHA-384 but
doesn't actually make that change in the interests of reviewability.
Updating the advertised hash functions will cause changes in many of the
testdata/ files and some errors might get lost in the noise. This change
only needs to update four testdata/ files: one because a SHA-384-based
handshake is now being signed with SHA-256 and the others because the
TLS 1.2 CertificateRequest message now includes SHA-1.
This change also has the effect of adding support for
client-certificates in SSLv3 servers. However, SSLv3 is now disabled by
default so this should be moot.
It would be possible to avoid much of this change and just support
SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces
and SKX params (a design mistake in TLS). However, that would leave Go
in the odd situation where it advertised support for SHA-384, but would
only use the handshake hash when signing client certificates. I fear
that'll just cause problems in the future.
Much of this code was written by davidben@ for the purposes of testing
BoringSSL.
Partly addresses #9757
Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485
Reviewed-on: https://go-review.googlesource.com/9415
Run-TryBot: Adam Langley <agl@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
This change causes the GetCertificate callback to be called if
Certificates is empty. Previously this configuration would result in an
error.
This allows people to have servers that depend entirely on dynamic
certificate selection, even when the client doesn't send SNI.
Fixes#9208.
Change-Id: I2f5a5551215958b88b154c64a114590300dfc461
Reviewed-on: https://go-review.googlesource.com/8792
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
This change adds a new method to tls.Config, SetSessionTicketKeys, that
changes the key used to encrypt session tickets while the server is
running. Additional keys may be provided that will be used to maintain
continuity while rotating keys. If a ticket encrypted with an old key is
provided by the client, the server will resume the session and provide
the client with a ticket encrypted using the new key.
Fixes#9994
Change-Id: Idbc16b10ff39616109a51ed39a6fa208faad5b4e
Reviewed-on: https://go-review.googlesource.com/9072
Reviewed-by: Jonathan Rudenberg <jonathan@titanous.com>
Reviewed-by: Adam Langley <agl@golang.org>