Later CLs will clean up the ClientHello construction a bit (draft-12
avoids computing ClientHelloOuter twice). I suspect the transcript
handling on the client can also be simpler, but I'll see what's
convenient after I've changed how ClientHelloOuter is constructed.
Changes of note between draft-10 and draft-13:
- There is now an ECH confirmation signal in both HRR and SH. We don't
actually make much use of this in our client right now, but it
resolves a bunch of weird issues around HRR, including edge cases if
HRR applies to one ClientHello but not the other.
- The confirmation signal no longer depends on key_share and PSK, so we
don't have to work around a weird ordering issue.
- ech_is_inner is now folded into the main encrypted_client_hello code
point. This works better with some stuff around HRR.
- Padding is moved from the padding extension, computed with
ClientHelloInner, to something we fill in afterwards. This makes it
easier to pad up the whole thing to a multiple of 32. I've accordingly
updated to the latest recommended padding construction, and updated
the GREASE logic to match.
- ech_outer_extensions is much easier to process because the order is
required to be consistent. We were doing that anyway, and now a simple
linear scan works.
- ClientHelloOuterAAD now uses an all zero placeholder payload of the
same length. This lets us simplify the server code, but, for now, I've
kept the client code the same. I'll follow this up with a CL to avoid
computing ClientHelloOuter twice.
- ClientHelloOuterAAD is allowed to contain a placeholder PSK. I haven't
filled that in and will do it in a follow-up CL.
Bug: 275
Change-Id: I7464345125c53968b2fe692f9268e392120fc2eb
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48912
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
The session ID field cannot exceed 32 bytes, and we size various buffers
based on this. Test that our parsers correctly handle this.
Also fix the -wait-for-debugger flag. I broke it recently by removing
the statusShimStarted message.
Change-Id: I29bb177f29a79bb4904fb5ba3cedfb0b6b856061
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48907
Reviewed-by: Adam Langley <agl@google.com>
If a client offers ECH, but the server rejects it, the client completes
the handshake with ClientHelloOuter in order to authenticate retry keys.
Implement this flow. This is largely allowing the existing handshake to
proceed, but with some changes:
- Certificate verification uses the other name. This CL routes this up to
the built-in verifier and adds SSL_get0_ech_name_override for the
callback.
- We need to disable False Start to pick up server Finished in TLS 1.2.
- Client certificates, notably in TLS 1.3 where they're encrypted,
should only be revealed to the true server. Fortunately, not sending
client certs is always an option, so do that.
Channel ID has a similar issue. I've just omitted the extension in
ClientHelloOuter because it's deprecated and is unlikely to be used
with ECH at this point. ALPS may be worth some pondering but, the way
it's currently used, is not sensitive.
(Possibly we should change the draft to terminate the handshake before
even sending that flight...)
- The session is never offered in ClientHelloOuter, but our internal
book-keeping doesn't quite notice.
I had to replace ech_accept with a tri-state ech_status to correctly
handle an edge case in SSL_get0_ech_name_override: when ECH + 0-RTT +
reverify_on_resume are all enabled, the first certificate verification
is for the 0-RTT session and should be against the true name, yet we
have selected_ech_config && !ech_accept. A tri-state tracks when ECH is
actually rejected. I've maintained this on the server as well, though
the server never actually cares.
Bug: 275
Change-Id: Ie55966ca3dc4ffcc8c381479f0fe9bcacd34d0f8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48135
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Some tests run three connections, resuming a renewed ticket.
Particularly the way TLS 1.2 ticket renewal works, the client logic
could accidentally report the old session up to the application. Our
runner tests would not currently notice (though one of the tests in
ssl_tests does).
Make runner tests also check this by cycling ticket keys between
connection attempts. This also makes newSessionsOnResume apply even if
the test did not specify a resumeConfig.
Change-Id: I95375c01adf6ad62de65ecf8aed3c286a0571875
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48131
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Based on an initial implementation by Dan McArdle at
https://boringssl-review.googlesource.com/c/boringssl/+/46784
This CL contains most of a client implementation for
draft-ietf-tls-esni-10. The pieces missing so far, which will be done in
follow-up CLs are:
1. While the ClientHelloInner is padded, the server Certificate message
is not. I'll add that once we resolve the spec discussions on how to
do that. (We were originally going to use TLS record-level padding,
but that doesn't work well with QUIC.)
2. The client should check the public name is a valid DNS name before
copying it into ClientHelloOuter.server_name.
3. The ClientHelloOuter handshake flow is not yet implemented. This CL
can detect when the server selects ClientHelloOuter, but for now the
handshake immediately fails. A follow-up CL will remove that logic
and instead add the APIs and extra checks needed.
Otherwise, this should be complete, including padding and compression.
The main interesting point design-wise is that we run through
ClientHello construction multiple times. We need to construct
ClientHelloInner and ClientHelloOuter. Then each of those has slight
variants: EncodedClientHelloInner is the compressed form, and
ClientHelloOuterAAD just has the ECH extension erased to avoid a
circular dependency.
I've computed ClientHelloInner and EncodedClientHelloInner concurrently
because the compression scheme requires shifting the extensions around
to be contiguous. However, I've computed ClientHelloOuterAAD and
ClientHelloOuter by running through the logic twice. This probably can
be done better, but the next draft revises the construction anyway, so
I'm thinking I'll rework it then. (In the next draft, we use a
placeholder payload of the same length, so we can construct the
ClientHello once and fill in the payload.)
Additionally, now that we have a client available in ssl_test, this adds
a threading test to confirm that SSL_CTX_set1_ech_keys is properly
synchronized. (Confirmed that, if I drop the lock in
SSL_CTX_set1_ech_keys, TSan notices.)
Change-Id: Icaff68b595035bdcc73c468ff638e67c84239ef4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48004
Reviewed-by: Adam Langley <agl@google.com>
While decompression is deterministic, compression is not. New revisions
of the compression algorithm may start using different (hopefully
smaller!) compressions. So this doesn't cause hint mismatches, add a
certificate compression hint. If the shim's Certificate message matches
the handshaker, we'll reuse the already compressed message.
This also adds what appears to be a missing test for when the server
cannot find compression algorithms in common.
Change-Id: Idbedaceb20208463d8f61581ee27971c17fcd126
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48005
Reviewed-by: Adam Langley <agl@google.com>
This implements draft-ietf-tls-esni-10.
This will be used to test the client implementation. While I'm here,
I've switched the setup logic in the server tests to use the new
ServerECHConfig type. I'll probably need to patch in various features
later for testing, but this should be a usable starting point.
Based on an initial implementation by Dan McArdle in
https://boringssl-review.googlesource.com/c/boringssl/+/46786
Bug: 275
Change-Id: I69523cda70c3da2ae505bcab837fd358195fb9e9
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47967
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
The ECH server extension is defined for TLS 1.3 EncryptedExtensions, not
TLS 1.2 ServerHello.
Bug: 275
Change-Id: Ie6e76c238075d70e6a0694ec0192df07da3457d1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47910
Reviewed-by: Adam Langley <agl@google.com>
Also now that it's finalized, flip the default for
SSL_set_quic_use_legacy_codepoint.
Update-Note: QUIC APIs now default to the standard code point rather
than the draft one. QUICHE has already been calling
SSL_set_quic_use_legacy_codepoint, so this should not affect them. Once
callers implementing the draft versions cycle out, we can then drop
SSL_set_quic_use_legacy_codepoint altogether. I've also bumped
BORINGSSL_API_VERSION in case we end up needing an ifdef.
Change-Id: Id2cab66215f4ad4c1e31503d329c0febfdb4603e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47864
Reviewed-by: David Schinazi <dschinazi@google.com>
Reviewed-by: Adam Langley <agl@google.com>
If we ever forget to fill it in the randoms, they'll end up all zero.
Particularly at the ClientHello, that logic is getting increasingly far
away from ClientHello serialization, so add a test to make sure we
notice.
(This will flakily fail with probability 2^-256, which is reasonably
unlikely.)
Change-Id: I81f32fd96dbccf377cb92198a222b557ab66976b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47665
Reviewed-by: Adam Langley <agl@google.com>
We didn't end up deploying this. We also never implemented the final
RFC, so what we do have isn't useful for someone who wishes to deploy
it anyway.
Update-Note: Token binding APIs are removed.
Change-Id: Iecea7c3dcf9d3e2644a3b7afaf61511310b45d5f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47584
Reviewed-by: Adam Langley <agl@google.com>
Bug: 275
Change-Id: I8096070386af7d2b5020875ea09bcc0c04ebc8cd
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47245
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Also generate a corpus to unblock the Chromium roll. The build tools
expect there to be a corresponding directory somewhere.
Bug: 275
Change-Id: I7a061ba6625ec57c10b0ae17e68b6b0159c539d4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46826
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
This CL adds an initial implementation of the ECH server, with pieces of
the client in BoGo as necessary for testing. In particular, the server
supports ClientHelloInner compression with ech_outer_extensions. When
ECH decryption fails, it can send retry_configs back to the client.
This server passes the "ech-accept" and "ech-reject" test cases in
tls-interop-runner[0] when tested against both the cloudflare-go and nss
clients. For reproducibility, I started with the main branch at commit
707604c262d8bcf3e944ed1d5a675077304732ce and updated the endpoint's
script to pass the server's ECHConfig and private key to the boringssl
tool.
Follow-up CLs will update HPKE to the latest draft and catch us up to
draft-10.
[0]: https://github.com/xvzcf/tls-interop-runner
Bug: 275
Change-Id: I49be35af46d1fd5dd9c62252f07d0bae179381ab
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/45285
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
The challenge field, at least per our implementation and OpenSSL, may be
either left-padded or truncated to form the ClientHello random. Test
both cases, as well as an exact match.
Change-Id: Icdedf899ef483225d8ed20580ad15818b5e52e91
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46631
Reviewed-by: Adam Langley <agl@google.com>
This is a remnant of when we had various pre-standard TLS 1.3 variants.
runner's logic is now built-in.
Change-Id: I72a2fcef9a94e82fa39fe4be9d60ddd329d212ce
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46604
Reviewed-by: Adam Langley <agl@google.com>
In early TLS 1.3 drafts, HelloRetryRequest was a dedicated message type.
Our HelloRetryRequest handling in runner is still based on this. Along
the way, remove the SendServerHelloAsHelloRetryRequest test, since
that's just a generic unexpected message type now.
Change-Id: Idd9c54d0ab66d962657af9a53849c3928f78ce5c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46585
Reviewed-by: Adam Langley <agl@google.com>
This avoids looking up and passing around the cipherSuite object
everywhere. We don't serialize ClientSessionState and, if we did, we can
simply do the lookup at parsing time.
Change-Id: Ice06e4da6b23ff32988597100e8aaa11b82f23ad
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46565
Reviewed-by: Adam Langley <agl@google.com>
Omitting the extension means we'll never issue tickets, but if the
client were to offer a ticket anyway, RFC8446 4.2.9 says we MUST reject
the ClientHello. It's not clear on what alert to use, but
missing_extension is probably appropriate.
Thanks to Ben Kaduk for pointing this out.
Change-Id: Ie5c720eac9dd2e1a27ba8a13c59b707c109eaa4e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46464
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
This reverts commit a3437c09c7. There was
a miscommunication and it does not seem like we currently need this. If
that changes later, it's in Git and we can bring it back easily.
Change-Id: Ibbce29df2258a2d893d725ab3ee6fd78c5b6cb00
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46286
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
See draft-davidben-tls13-pkcs1-00. The code point is disabled by default
and must be configured in SSL_set_verify_algorithm_prefs and
SSL_set_signing_algorithm_prefs. It is also only defined for TLS 1.3
client certificates and otherwise ignored.
This required reworking the tests a bit since this is the first
signature algorithm that's disabled by default, and the first algorithm
that behaves differently between client and server.
Change-Id: Iac4aa96a4963cbc33688c252e958a572c5c3b511
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46187
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
This mirrors a change on the C side. Sessions may store the master
secret (main secret as of draft-ietf-tls-rfc8446bis-01) in TLS 1.2 or
the resumption PSK in TLS 1.3, so giving it any description other than
plain 'secret' isn't even accurate.
(Doing this separately from the rfc8446bis names since it's a bit less
mechanical.)
Change-Id: Iaf2b72fe298f17eeb4f4957cfd78b0015c3a9d89
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/45824
Reviewed-by: Adam Langley <agl@google.com>
A linter was complaining about some instance, so just fix the lot of it.
Change-Id: I7e23cbada6e42da887d740b84a05de9f104a86ab
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/45284
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
IETF QUIC draft 33 is replacing the TLS extension
codepoint for QUIC transport parameters from 0xffa5
to 57. To support multiple versions of Chrome, we
need to support both codepoints in BoringSSL. This
CL adds support for the new codepoint in a way that
can be enabled on individual connections.
Note that when BoringSSL is not in QUIC mode, it
will error if it sees the new codepoint as a server
but it will ignore the legacy codepoint as that could
be a different private usage of that codepoint.
Change-Id: I314f8f0b169cedd96eeccc42b44153e97044388c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/44704
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
This CL implements the backend server behavior described in Section 7.2
of draft-ietf-tls-esni-09.
Bug: 275
Change-Id: I2e162673ce564db0cb75fc9b71ef11ed15037f4b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/43924
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
(Original CL by svaldez, reworked by davidben.)
Change-Id: I8570808fa5e96a1c9e6e03c4877039a22e73254f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42404
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
This CL replaces clientHelloMsg's npnAfterAlpn and pskBinderFirst fields
with a new field: prefixExtensions. The extensions in prefixExtensions
are tried first when marshalling clientHelloMsg.
The ability to control extensions' marshalling order will make it
simpler to implement the "outer_extensions" behavior defined in
draft-ietf-tls-esni-07.
Bug: 275
Change-Id: Ib6dcc1e6fa0281f312cb65a9e204415c3f3ef2c6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/43064
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
We have an ad-hoc expectResumeVersion, and I'll want to add one for ALPS
(to confirm changing ALPS on resumption works). We probably could have
done with such a test for ALPN too. Wrap all the ConnectionState
expectations into a struct with an optional resumeExpectations field.
Also move the OCSPResponse() method to ConnectionState for consistency.
Change-Id: Icaabf5571c51e78ed078f57de0e04928d3f3fa8d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/43084
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
This version adds signature algorithms to the extension
Change-Id: I91dc78d33ee81cb7a6221c7bdeefc8ea460a2d6c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42424
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>