1*8fb009dcSAndroid Build Coastguard Worker /* Copyright (C) 1995-1998 Eric Young ([email protected])
2*8fb009dcSAndroid Build Coastguard Worker * All rights reserved.
3*8fb009dcSAndroid Build Coastguard Worker *
4*8fb009dcSAndroid Build Coastguard Worker * This package is an SSL implementation written
5*8fb009dcSAndroid Build Coastguard Worker * by Eric Young ([email protected]).
6*8fb009dcSAndroid Build Coastguard Worker * The implementation was written so as to conform with Netscapes SSL.
7*8fb009dcSAndroid Build Coastguard Worker *
8*8fb009dcSAndroid Build Coastguard Worker * This library is free for commercial and non-commercial use as long as
9*8fb009dcSAndroid Build Coastguard Worker * the following conditions are aheared to. The following conditions
10*8fb009dcSAndroid Build Coastguard Worker * apply to all code found in this distribution, be it the RC4, RSA,
11*8fb009dcSAndroid Build Coastguard Worker * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12*8fb009dcSAndroid Build Coastguard Worker * included with this distribution is covered by the same copyright terms
13*8fb009dcSAndroid Build Coastguard Worker * except that the holder is Tim Hudson ([email protected]).
14*8fb009dcSAndroid Build Coastguard Worker *
15*8fb009dcSAndroid Build Coastguard Worker * Copyright remains Eric Young's, and as such any Copyright notices in
16*8fb009dcSAndroid Build Coastguard Worker * the code are not to be removed.
17*8fb009dcSAndroid Build Coastguard Worker * If this package is used in a product, Eric Young should be given attribution
18*8fb009dcSAndroid Build Coastguard Worker * as the author of the parts of the library used.
19*8fb009dcSAndroid Build Coastguard Worker * This can be in the form of a textual message at program startup or
20*8fb009dcSAndroid Build Coastguard Worker * in documentation (online or textual) provided with the package.
21*8fb009dcSAndroid Build Coastguard Worker *
22*8fb009dcSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
23*8fb009dcSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
24*8fb009dcSAndroid Build Coastguard Worker * are met:
25*8fb009dcSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the copyright
26*8fb009dcSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
27*8fb009dcSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
28*8fb009dcSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
29*8fb009dcSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
30*8fb009dcSAndroid Build Coastguard Worker * 3. All advertising materials mentioning features or use of this software
31*8fb009dcSAndroid Build Coastguard Worker * must display the following acknowledgement:
32*8fb009dcSAndroid Build Coastguard Worker * "This product includes cryptographic software written by
33*8fb009dcSAndroid Build Coastguard Worker * Eric Young ([email protected])"
34*8fb009dcSAndroid Build Coastguard Worker * The word 'cryptographic' can be left out if the rouines from the library
35*8fb009dcSAndroid Build Coastguard Worker * being used are not cryptographic related :-).
36*8fb009dcSAndroid Build Coastguard Worker * 4. If you include any Windows specific code (or a derivative thereof) from
37*8fb009dcSAndroid Build Coastguard Worker * the apps directory (application code) you must include an acknowledgement:
38*8fb009dcSAndroid Build Coastguard Worker * "This product includes software written by Tim Hudson ([email protected])"
39*8fb009dcSAndroid Build Coastguard Worker *
40*8fb009dcSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41*8fb009dcSAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42*8fb009dcSAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43*8fb009dcSAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44*8fb009dcSAndroid Build Coastguard Worker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45*8fb009dcSAndroid Build Coastguard Worker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46*8fb009dcSAndroid Build Coastguard Worker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47*8fb009dcSAndroid Build Coastguard Worker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48*8fb009dcSAndroid Build Coastguard Worker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49*8fb009dcSAndroid Build Coastguard Worker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50*8fb009dcSAndroid Build Coastguard Worker * SUCH DAMAGE.
51*8fb009dcSAndroid Build Coastguard Worker *
52*8fb009dcSAndroid Build Coastguard Worker * The licence and distribution terms for any publically available version or
53*8fb009dcSAndroid Build Coastguard Worker * derivative of this code cannot be changed. i.e. this code cannot simply be
54*8fb009dcSAndroid Build Coastguard Worker * copied and put under another distribution licence
55*8fb009dcSAndroid Build Coastguard Worker * [including the GNU Public Licence.]
56*8fb009dcSAndroid Build Coastguard Worker */
57*8fb009dcSAndroid Build Coastguard Worker /* ====================================================================
58*8fb009dcSAndroid Build Coastguard Worker * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
59*8fb009dcSAndroid Build Coastguard Worker *
60*8fb009dcSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
61*8fb009dcSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
62*8fb009dcSAndroid Build Coastguard Worker * are met:
63*8fb009dcSAndroid Build Coastguard Worker *
64*8fb009dcSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
65*8fb009dcSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
66*8fb009dcSAndroid Build Coastguard Worker *
67*8fb009dcSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
68*8fb009dcSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in
69*8fb009dcSAndroid Build Coastguard Worker * the documentation and/or other materials provided with the
70*8fb009dcSAndroid Build Coastguard Worker * distribution.
71*8fb009dcSAndroid Build Coastguard Worker *
72*8fb009dcSAndroid Build Coastguard Worker * 3. All advertising materials mentioning features or use of this
73*8fb009dcSAndroid Build Coastguard Worker * software must display the following acknowledgment:
74*8fb009dcSAndroid Build Coastguard Worker * "This product includes software developed by the OpenSSL Project
75*8fb009dcSAndroid Build Coastguard Worker * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76*8fb009dcSAndroid Build Coastguard Worker *
77*8fb009dcSAndroid Build Coastguard Worker * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78*8fb009dcSAndroid Build Coastguard Worker * endorse or promote products derived from this software without
79*8fb009dcSAndroid Build Coastguard Worker * prior written permission. For written permission, please contact
80*8fb009dcSAndroid Build Coastguard Worker * [email protected].
81*8fb009dcSAndroid Build Coastguard Worker *
82*8fb009dcSAndroid Build Coastguard Worker * 5. Products derived from this software may not be called "OpenSSL"
83*8fb009dcSAndroid Build Coastguard Worker * nor may "OpenSSL" appear in their names without prior written
84*8fb009dcSAndroid Build Coastguard Worker * permission of the OpenSSL Project.
85*8fb009dcSAndroid Build Coastguard Worker *
86*8fb009dcSAndroid Build Coastguard Worker * 6. Redistributions of any form whatsoever must retain the following
87*8fb009dcSAndroid Build Coastguard Worker * acknowledgment:
88*8fb009dcSAndroid Build Coastguard Worker * "This product includes software developed by the OpenSSL Project
89*8fb009dcSAndroid Build Coastguard Worker * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90*8fb009dcSAndroid Build Coastguard Worker *
91*8fb009dcSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92*8fb009dcSAndroid Build Coastguard Worker * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93*8fb009dcSAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94*8fb009dcSAndroid Build Coastguard Worker * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
95*8fb009dcSAndroid Build Coastguard Worker * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96*8fb009dcSAndroid Build Coastguard Worker * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97*8fb009dcSAndroid Build Coastguard Worker * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98*8fb009dcSAndroid Build Coastguard Worker * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99*8fb009dcSAndroid Build Coastguard Worker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100*8fb009dcSAndroid Build Coastguard Worker * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101*8fb009dcSAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102*8fb009dcSAndroid Build Coastguard Worker * OF THE POSSIBILITY OF SUCH DAMAGE.
103*8fb009dcSAndroid Build Coastguard Worker * ====================================================================
104*8fb009dcSAndroid Build Coastguard Worker *
105*8fb009dcSAndroid Build Coastguard Worker * This product includes cryptographic software written by Eric Young
106*8fb009dcSAndroid Build Coastguard Worker * ([email protected]). This product includes software written by Tim
107*8fb009dcSAndroid Build Coastguard Worker * Hudson ([email protected]). */
108*8fb009dcSAndroid Build Coastguard Worker
109*8fb009dcSAndroid Build Coastguard Worker #include <openssl/ssl.h>
110*8fb009dcSAndroid Build Coastguard Worker
111*8fb009dcSAndroid Build Coastguard Worker #include <assert.h>
112*8fb009dcSAndroid Build Coastguard Worker #include <limits.h>
113*8fb009dcSAndroid Build Coastguard Worker #include <stdlib.h>
114*8fb009dcSAndroid Build Coastguard Worker #include <string.h>
115*8fb009dcSAndroid Build Coastguard Worker
116*8fb009dcSAndroid Build Coastguard Worker #include <algorithm>
117*8fb009dcSAndroid Build Coastguard Worker #include <utility>
118*8fb009dcSAndroid Build Coastguard Worker
119*8fb009dcSAndroid Build Coastguard Worker #include <openssl/aead.h>
120*8fb009dcSAndroid Build Coastguard Worker #include <openssl/bytestring.h>
121*8fb009dcSAndroid Build Coastguard Worker #include <openssl/chacha.h>
122*8fb009dcSAndroid Build Coastguard Worker #include <openssl/curve25519.h>
123*8fb009dcSAndroid Build Coastguard Worker #include <openssl/digest.h>
124*8fb009dcSAndroid Build Coastguard Worker #include <openssl/err.h>
125*8fb009dcSAndroid Build Coastguard Worker #include <openssl/evp.h>
126*8fb009dcSAndroid Build Coastguard Worker #include <openssl/hmac.h>
127*8fb009dcSAndroid Build Coastguard Worker #include <openssl/hpke.h>
128*8fb009dcSAndroid Build Coastguard Worker #include <openssl/mem.h>
129*8fb009dcSAndroid Build Coastguard Worker #include <openssl/nid.h>
130*8fb009dcSAndroid Build Coastguard Worker #include <openssl/rand.h>
131*8fb009dcSAndroid Build Coastguard Worker
132*8fb009dcSAndroid Build Coastguard Worker #include "../crypto/internal.h"
133*8fb009dcSAndroid Build Coastguard Worker #include "internal.h"
134*8fb009dcSAndroid Build Coastguard Worker
135*8fb009dcSAndroid Build Coastguard Worker
136*8fb009dcSAndroid Build Coastguard Worker BSSL_NAMESPACE_BEGIN
137*8fb009dcSAndroid Build Coastguard Worker
138*8fb009dcSAndroid Build Coastguard Worker static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs);
139*8fb009dcSAndroid Build Coastguard Worker static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs);
140*8fb009dcSAndroid Build Coastguard Worker
compare_uint16_t(const void * p1,const void * p2)141*8fb009dcSAndroid Build Coastguard Worker static int compare_uint16_t(const void *p1, const void *p2) {
142*8fb009dcSAndroid Build Coastguard Worker uint16_t u1 = *((const uint16_t *)p1);
143*8fb009dcSAndroid Build Coastguard Worker uint16_t u2 = *((const uint16_t *)p2);
144*8fb009dcSAndroid Build Coastguard Worker if (u1 < u2) {
145*8fb009dcSAndroid Build Coastguard Worker return -1;
146*8fb009dcSAndroid Build Coastguard Worker } else if (u1 > u2) {
147*8fb009dcSAndroid Build Coastguard Worker return 1;
148*8fb009dcSAndroid Build Coastguard Worker } else {
149*8fb009dcSAndroid Build Coastguard Worker return 0;
150*8fb009dcSAndroid Build Coastguard Worker }
151*8fb009dcSAndroid Build Coastguard Worker }
152*8fb009dcSAndroid Build Coastguard Worker
153*8fb009dcSAndroid Build Coastguard Worker // Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
154*8fb009dcSAndroid Build Coastguard Worker // more than one extension of the same type in a ClientHello or ServerHello.
155*8fb009dcSAndroid Build Coastguard Worker // This function does an initial scan over the extensions block to filter those
156*8fb009dcSAndroid Build Coastguard Worker // out.
tls1_check_duplicate_extensions(const CBS * cbs)157*8fb009dcSAndroid Build Coastguard Worker static bool tls1_check_duplicate_extensions(const CBS *cbs) {
158*8fb009dcSAndroid Build Coastguard Worker // First pass: count the extensions.
159*8fb009dcSAndroid Build Coastguard Worker size_t num_extensions = 0;
160*8fb009dcSAndroid Build Coastguard Worker CBS extensions = *cbs;
161*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&extensions) > 0) {
162*8fb009dcSAndroid Build Coastguard Worker uint16_t type;
163*8fb009dcSAndroid Build Coastguard Worker CBS extension;
164*8fb009dcSAndroid Build Coastguard Worker
165*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(&extensions, &type) ||
166*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16_length_prefixed(&extensions, &extension)) {
167*8fb009dcSAndroid Build Coastguard Worker return false;
168*8fb009dcSAndroid Build Coastguard Worker }
169*8fb009dcSAndroid Build Coastguard Worker
170*8fb009dcSAndroid Build Coastguard Worker num_extensions++;
171*8fb009dcSAndroid Build Coastguard Worker }
172*8fb009dcSAndroid Build Coastguard Worker
173*8fb009dcSAndroid Build Coastguard Worker if (num_extensions == 0) {
174*8fb009dcSAndroid Build Coastguard Worker return true;
175*8fb009dcSAndroid Build Coastguard Worker }
176*8fb009dcSAndroid Build Coastguard Worker
177*8fb009dcSAndroid Build Coastguard Worker Array<uint16_t> extension_types;
178*8fb009dcSAndroid Build Coastguard Worker if (!extension_types.Init(num_extensions)) {
179*8fb009dcSAndroid Build Coastguard Worker return false;
180*8fb009dcSAndroid Build Coastguard Worker }
181*8fb009dcSAndroid Build Coastguard Worker
182*8fb009dcSAndroid Build Coastguard Worker // Second pass: gather the extension types.
183*8fb009dcSAndroid Build Coastguard Worker extensions = *cbs;
184*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < extension_types.size(); i++) {
185*8fb009dcSAndroid Build Coastguard Worker CBS extension;
186*8fb009dcSAndroid Build Coastguard Worker
187*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(&extensions, &extension_types[i]) ||
188*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16_length_prefixed(&extensions, &extension)) {
189*8fb009dcSAndroid Build Coastguard Worker // This should not happen.
190*8fb009dcSAndroid Build Coastguard Worker return false;
191*8fb009dcSAndroid Build Coastguard Worker }
192*8fb009dcSAndroid Build Coastguard Worker }
193*8fb009dcSAndroid Build Coastguard Worker assert(CBS_len(&extensions) == 0);
194*8fb009dcSAndroid Build Coastguard Worker
195*8fb009dcSAndroid Build Coastguard Worker // Sort the extensions and make sure there are no duplicates.
196*8fb009dcSAndroid Build Coastguard Worker qsort(extension_types.data(), extension_types.size(), sizeof(uint16_t),
197*8fb009dcSAndroid Build Coastguard Worker compare_uint16_t);
198*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 1; i < num_extensions; i++) {
199*8fb009dcSAndroid Build Coastguard Worker if (extension_types[i - 1] == extension_types[i]) {
200*8fb009dcSAndroid Build Coastguard Worker return false;
201*8fb009dcSAndroid Build Coastguard Worker }
202*8fb009dcSAndroid Build Coastguard Worker }
203*8fb009dcSAndroid Build Coastguard Worker
204*8fb009dcSAndroid Build Coastguard Worker return true;
205*8fb009dcSAndroid Build Coastguard Worker }
206*8fb009dcSAndroid Build Coastguard Worker
is_post_quantum_group(uint16_t id)207*8fb009dcSAndroid Build Coastguard Worker static bool is_post_quantum_group(uint16_t id) {
208*8fb009dcSAndroid Build Coastguard Worker switch (id) {
209*8fb009dcSAndroid Build Coastguard Worker case SSL_GROUP_X25519_KYBER768_DRAFT00:
210*8fb009dcSAndroid Build Coastguard Worker return true;
211*8fb009dcSAndroid Build Coastguard Worker default:
212*8fb009dcSAndroid Build Coastguard Worker return false;
213*8fb009dcSAndroid Build Coastguard Worker }
214*8fb009dcSAndroid Build Coastguard Worker }
215*8fb009dcSAndroid Build Coastguard Worker
ssl_client_hello_init(const SSL * ssl,SSL_CLIENT_HELLO * out,Span<const uint8_t> body)216*8fb009dcSAndroid Build Coastguard Worker bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out,
217*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> body) {
218*8fb009dcSAndroid Build Coastguard Worker CBS cbs = body;
219*8fb009dcSAndroid Build Coastguard Worker if (!ssl_parse_client_hello_with_trailing_data(ssl, &cbs, out) ||
220*8fb009dcSAndroid Build Coastguard Worker CBS_len(&cbs) != 0) {
221*8fb009dcSAndroid Build Coastguard Worker return false;
222*8fb009dcSAndroid Build Coastguard Worker }
223*8fb009dcSAndroid Build Coastguard Worker return true;
224*8fb009dcSAndroid Build Coastguard Worker }
225*8fb009dcSAndroid Build Coastguard Worker
ssl_parse_client_hello_with_trailing_data(const SSL * ssl,CBS * cbs,SSL_CLIENT_HELLO * out)226*8fb009dcSAndroid Build Coastguard Worker bool ssl_parse_client_hello_with_trailing_data(const SSL *ssl, CBS *cbs,
227*8fb009dcSAndroid Build Coastguard Worker SSL_CLIENT_HELLO *out) {
228*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memset(out, 0, sizeof(*out));
229*8fb009dcSAndroid Build Coastguard Worker out->ssl = const_cast<SSL *>(ssl);
230*8fb009dcSAndroid Build Coastguard Worker
231*8fb009dcSAndroid Build Coastguard Worker CBS copy = *cbs;
232*8fb009dcSAndroid Build Coastguard Worker CBS random, session_id;
233*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(cbs, &out->version) ||
234*8fb009dcSAndroid Build Coastguard Worker !CBS_get_bytes(cbs, &random, SSL3_RANDOM_SIZE) ||
235*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u8_length_prefixed(cbs, &session_id) ||
236*8fb009dcSAndroid Build Coastguard Worker CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
237*8fb009dcSAndroid Build Coastguard Worker return false;
238*8fb009dcSAndroid Build Coastguard Worker }
239*8fb009dcSAndroid Build Coastguard Worker
240*8fb009dcSAndroid Build Coastguard Worker out->random = CBS_data(&random);
241*8fb009dcSAndroid Build Coastguard Worker out->random_len = CBS_len(&random);
242*8fb009dcSAndroid Build Coastguard Worker out->session_id = CBS_data(&session_id);
243*8fb009dcSAndroid Build Coastguard Worker out->session_id_len = CBS_len(&session_id);
244*8fb009dcSAndroid Build Coastguard Worker
245*8fb009dcSAndroid Build Coastguard Worker // Skip past DTLS cookie
246*8fb009dcSAndroid Build Coastguard Worker if (SSL_is_dtls(out->ssl)) {
247*8fb009dcSAndroid Build Coastguard Worker CBS cookie;
248*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(cbs, &cookie)) {
249*8fb009dcSAndroid Build Coastguard Worker return false;
250*8fb009dcSAndroid Build Coastguard Worker }
251*8fb009dcSAndroid Build Coastguard Worker }
252*8fb009dcSAndroid Build Coastguard Worker
253*8fb009dcSAndroid Build Coastguard Worker CBS cipher_suites, compression_methods;
254*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(cbs, &cipher_suites) ||
255*8fb009dcSAndroid Build Coastguard Worker CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0 ||
256*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u8_length_prefixed(cbs, &compression_methods) ||
257*8fb009dcSAndroid Build Coastguard Worker CBS_len(&compression_methods) < 1) {
258*8fb009dcSAndroid Build Coastguard Worker return false;
259*8fb009dcSAndroid Build Coastguard Worker }
260*8fb009dcSAndroid Build Coastguard Worker
261*8fb009dcSAndroid Build Coastguard Worker out->cipher_suites = CBS_data(&cipher_suites);
262*8fb009dcSAndroid Build Coastguard Worker out->cipher_suites_len = CBS_len(&cipher_suites);
263*8fb009dcSAndroid Build Coastguard Worker out->compression_methods = CBS_data(&compression_methods);
264*8fb009dcSAndroid Build Coastguard Worker out->compression_methods_len = CBS_len(&compression_methods);
265*8fb009dcSAndroid Build Coastguard Worker
266*8fb009dcSAndroid Build Coastguard Worker // If the ClientHello ends here then it's valid, but doesn't have any
267*8fb009dcSAndroid Build Coastguard Worker // extensions.
268*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(cbs) == 0) {
269*8fb009dcSAndroid Build Coastguard Worker out->extensions = nullptr;
270*8fb009dcSAndroid Build Coastguard Worker out->extensions_len = 0;
271*8fb009dcSAndroid Build Coastguard Worker } else {
272*8fb009dcSAndroid Build Coastguard Worker // Extract extensions and check it is valid.
273*8fb009dcSAndroid Build Coastguard Worker CBS extensions;
274*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(cbs, &extensions) ||
275*8fb009dcSAndroid Build Coastguard Worker !tls1_check_duplicate_extensions(&extensions)) {
276*8fb009dcSAndroid Build Coastguard Worker return false;
277*8fb009dcSAndroid Build Coastguard Worker }
278*8fb009dcSAndroid Build Coastguard Worker out->extensions = CBS_data(&extensions);
279*8fb009dcSAndroid Build Coastguard Worker out->extensions_len = CBS_len(&extensions);
280*8fb009dcSAndroid Build Coastguard Worker }
281*8fb009dcSAndroid Build Coastguard Worker
282*8fb009dcSAndroid Build Coastguard Worker out->client_hello = CBS_data(©);
283*8fb009dcSAndroid Build Coastguard Worker out->client_hello_len = CBS_len(©) - CBS_len(cbs);
284*8fb009dcSAndroid Build Coastguard Worker return true;
285*8fb009dcSAndroid Build Coastguard Worker }
286*8fb009dcSAndroid Build Coastguard Worker
ssl_client_hello_get_extension(const SSL_CLIENT_HELLO * client_hello,CBS * out,uint16_t extension_type)287*8fb009dcSAndroid Build Coastguard Worker bool ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
288*8fb009dcSAndroid Build Coastguard Worker CBS *out, uint16_t extension_type) {
289*8fb009dcSAndroid Build Coastguard Worker CBS extensions;
290*8fb009dcSAndroid Build Coastguard Worker CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
291*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&extensions) != 0) {
292*8fb009dcSAndroid Build Coastguard Worker // Decode the next extension.
293*8fb009dcSAndroid Build Coastguard Worker uint16_t type;
294*8fb009dcSAndroid Build Coastguard Worker CBS extension;
295*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(&extensions, &type) ||
296*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16_length_prefixed(&extensions, &extension)) {
297*8fb009dcSAndroid Build Coastguard Worker return false;
298*8fb009dcSAndroid Build Coastguard Worker }
299*8fb009dcSAndroid Build Coastguard Worker
300*8fb009dcSAndroid Build Coastguard Worker if (type == extension_type) {
301*8fb009dcSAndroid Build Coastguard Worker *out = extension;
302*8fb009dcSAndroid Build Coastguard Worker return true;
303*8fb009dcSAndroid Build Coastguard Worker }
304*8fb009dcSAndroid Build Coastguard Worker }
305*8fb009dcSAndroid Build Coastguard Worker
306*8fb009dcSAndroid Build Coastguard Worker return false;
307*8fb009dcSAndroid Build Coastguard Worker }
308*8fb009dcSAndroid Build Coastguard Worker
309*8fb009dcSAndroid Build Coastguard Worker static const uint16_t kDefaultGroups[] = {
310*8fb009dcSAndroid Build Coastguard Worker SSL_GROUP_X25519,
311*8fb009dcSAndroid Build Coastguard Worker SSL_GROUP_SECP256R1,
312*8fb009dcSAndroid Build Coastguard Worker SSL_GROUP_SECP384R1,
313*8fb009dcSAndroid Build Coastguard Worker };
314*8fb009dcSAndroid Build Coastguard Worker
tls1_get_grouplist(const SSL_HANDSHAKE * hs)315*8fb009dcSAndroid Build Coastguard Worker Span<const uint16_t> tls1_get_grouplist(const SSL_HANDSHAKE *hs) {
316*8fb009dcSAndroid Build Coastguard Worker if (!hs->config->supported_group_list.empty()) {
317*8fb009dcSAndroid Build Coastguard Worker return hs->config->supported_group_list;
318*8fb009dcSAndroid Build Coastguard Worker }
319*8fb009dcSAndroid Build Coastguard Worker return Span<const uint16_t>(kDefaultGroups);
320*8fb009dcSAndroid Build Coastguard Worker }
321*8fb009dcSAndroid Build Coastguard Worker
tls1_get_shared_group(SSL_HANDSHAKE * hs,uint16_t * out_group_id)322*8fb009dcSAndroid Build Coastguard Worker bool tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) {
323*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
324*8fb009dcSAndroid Build Coastguard Worker assert(ssl->server);
325*8fb009dcSAndroid Build Coastguard Worker
326*8fb009dcSAndroid Build Coastguard Worker // Clients are not required to send a supported_groups extension. In this
327*8fb009dcSAndroid Build Coastguard Worker // case, the server is free to pick any group it likes. See RFC 4492,
328*8fb009dcSAndroid Build Coastguard Worker // section 4, paragraph 3.
329*8fb009dcSAndroid Build Coastguard Worker //
330*8fb009dcSAndroid Build Coastguard Worker // However, in the interests of compatibility, we will skip ECDH if the
331*8fb009dcSAndroid Build Coastguard Worker // client didn't send an extension because we can't be sure that they'll
332*8fb009dcSAndroid Build Coastguard Worker // support our favoured group. Thus we do not special-case an emtpy
333*8fb009dcSAndroid Build Coastguard Worker // |peer_supported_group_list|.
334*8fb009dcSAndroid Build Coastguard Worker
335*8fb009dcSAndroid Build Coastguard Worker Span<const uint16_t> groups = tls1_get_grouplist(hs);
336*8fb009dcSAndroid Build Coastguard Worker Span<const uint16_t> pref, supp;
337*8fb009dcSAndroid Build Coastguard Worker if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
338*8fb009dcSAndroid Build Coastguard Worker pref = groups;
339*8fb009dcSAndroid Build Coastguard Worker supp = hs->peer_supported_group_list;
340*8fb009dcSAndroid Build Coastguard Worker } else {
341*8fb009dcSAndroid Build Coastguard Worker pref = hs->peer_supported_group_list;
342*8fb009dcSAndroid Build Coastguard Worker supp = groups;
343*8fb009dcSAndroid Build Coastguard Worker }
344*8fb009dcSAndroid Build Coastguard Worker
345*8fb009dcSAndroid Build Coastguard Worker for (uint16_t pref_group : pref) {
346*8fb009dcSAndroid Build Coastguard Worker for (uint16_t supp_group : supp) {
347*8fb009dcSAndroid Build Coastguard Worker if (pref_group == supp_group &&
348*8fb009dcSAndroid Build Coastguard Worker // Post-quantum key agreements don't fit in the u8-length-prefixed
349*8fb009dcSAndroid Build Coastguard Worker // ECPoint field in TLS 1.2 and below.
350*8fb009dcSAndroid Build Coastguard Worker (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
351*8fb009dcSAndroid Build Coastguard Worker !is_post_quantum_group(pref_group))) {
352*8fb009dcSAndroid Build Coastguard Worker *out_group_id = pref_group;
353*8fb009dcSAndroid Build Coastguard Worker return true;
354*8fb009dcSAndroid Build Coastguard Worker }
355*8fb009dcSAndroid Build Coastguard Worker }
356*8fb009dcSAndroid Build Coastguard Worker }
357*8fb009dcSAndroid Build Coastguard Worker
358*8fb009dcSAndroid Build Coastguard Worker return false;
359*8fb009dcSAndroid Build Coastguard Worker }
360*8fb009dcSAndroid Build Coastguard Worker
tls1_check_group_id(const SSL_HANDSHAKE * hs,uint16_t group_id)361*8fb009dcSAndroid Build Coastguard Worker bool tls1_check_group_id(const SSL_HANDSHAKE *hs, uint16_t group_id) {
362*8fb009dcSAndroid Build Coastguard Worker if (is_post_quantum_group(group_id) &&
363*8fb009dcSAndroid Build Coastguard Worker ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
364*8fb009dcSAndroid Build Coastguard Worker // Post-quantum "groups" require TLS 1.3.
365*8fb009dcSAndroid Build Coastguard Worker return false;
366*8fb009dcSAndroid Build Coastguard Worker }
367*8fb009dcSAndroid Build Coastguard Worker
368*8fb009dcSAndroid Build Coastguard Worker // We internally assume zero is never allocated as a group ID.
369*8fb009dcSAndroid Build Coastguard Worker if (group_id == 0) {
370*8fb009dcSAndroid Build Coastguard Worker return false;
371*8fb009dcSAndroid Build Coastguard Worker }
372*8fb009dcSAndroid Build Coastguard Worker
373*8fb009dcSAndroid Build Coastguard Worker for (uint16_t supported : tls1_get_grouplist(hs)) {
374*8fb009dcSAndroid Build Coastguard Worker if (supported == group_id) {
375*8fb009dcSAndroid Build Coastguard Worker return true;
376*8fb009dcSAndroid Build Coastguard Worker }
377*8fb009dcSAndroid Build Coastguard Worker }
378*8fb009dcSAndroid Build Coastguard Worker
379*8fb009dcSAndroid Build Coastguard Worker return false;
380*8fb009dcSAndroid Build Coastguard Worker }
381*8fb009dcSAndroid Build Coastguard Worker
382*8fb009dcSAndroid Build Coastguard Worker // kVerifySignatureAlgorithms is the default list of accepted signature
383*8fb009dcSAndroid Build Coastguard Worker // algorithms for verifying.
384*8fb009dcSAndroid Build Coastguard Worker static const uint16_t kVerifySignatureAlgorithms[] = {
385*8fb009dcSAndroid Build Coastguard Worker // List our preferred algorithms first.
386*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_ECDSA_SECP256R1_SHA256,
387*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PSS_RSAE_SHA256,
388*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PKCS1_SHA256,
389*8fb009dcSAndroid Build Coastguard Worker
390*8fb009dcSAndroid Build Coastguard Worker // Larger hashes are acceptable.
391*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_ECDSA_SECP384R1_SHA384,
392*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PSS_RSAE_SHA384,
393*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PKCS1_SHA384,
394*8fb009dcSAndroid Build Coastguard Worker
395*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PSS_RSAE_SHA512,
396*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PKCS1_SHA512,
397*8fb009dcSAndroid Build Coastguard Worker
398*8fb009dcSAndroid Build Coastguard Worker // For now, SHA-1 is still accepted but least preferable.
399*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PKCS1_SHA1,
400*8fb009dcSAndroid Build Coastguard Worker };
401*8fb009dcSAndroid Build Coastguard Worker
402*8fb009dcSAndroid Build Coastguard Worker // kSignSignatureAlgorithms is the default list of supported signature
403*8fb009dcSAndroid Build Coastguard Worker // algorithms for signing.
404*8fb009dcSAndroid Build Coastguard Worker static const uint16_t kSignSignatureAlgorithms[] = {
405*8fb009dcSAndroid Build Coastguard Worker // List our preferred algorithms first.
406*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_ED25519,
407*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_ECDSA_SECP256R1_SHA256,
408*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PSS_RSAE_SHA256,
409*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PKCS1_SHA256,
410*8fb009dcSAndroid Build Coastguard Worker
411*8fb009dcSAndroid Build Coastguard Worker // If needed, sign larger hashes.
412*8fb009dcSAndroid Build Coastguard Worker //
413*8fb009dcSAndroid Build Coastguard Worker // TODO(davidben): Determine which of these may be pruned.
414*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_ECDSA_SECP384R1_SHA384,
415*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PSS_RSAE_SHA384,
416*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PKCS1_SHA384,
417*8fb009dcSAndroid Build Coastguard Worker
418*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_ECDSA_SECP521R1_SHA512,
419*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PSS_RSAE_SHA512,
420*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PKCS1_SHA512,
421*8fb009dcSAndroid Build Coastguard Worker
422*8fb009dcSAndroid Build Coastguard Worker // If the peer supports nothing else, sign with SHA-1.
423*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_ECDSA_SHA1,
424*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_RSA_PKCS1_SHA1,
425*8fb009dcSAndroid Build Coastguard Worker };
426*8fb009dcSAndroid Build Coastguard Worker
tls12_get_verify_sigalgs(const SSL_HANDSHAKE * hs)427*8fb009dcSAndroid Build Coastguard Worker static Span<const uint16_t> tls12_get_verify_sigalgs(const SSL_HANDSHAKE *hs) {
428*8fb009dcSAndroid Build Coastguard Worker if (hs->config->verify_sigalgs.empty()) {
429*8fb009dcSAndroid Build Coastguard Worker return Span<const uint16_t>(kVerifySignatureAlgorithms);
430*8fb009dcSAndroid Build Coastguard Worker }
431*8fb009dcSAndroid Build Coastguard Worker return hs->config->verify_sigalgs;
432*8fb009dcSAndroid Build Coastguard Worker }
433*8fb009dcSAndroid Build Coastguard Worker
tls12_add_verify_sigalgs(const SSL_HANDSHAKE * hs,CBB * out)434*8fb009dcSAndroid Build Coastguard Worker bool tls12_add_verify_sigalgs(const SSL_HANDSHAKE *hs, CBB *out) {
435*8fb009dcSAndroid Build Coastguard Worker for (uint16_t sigalg : tls12_get_verify_sigalgs(hs)) {
436*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, sigalg)) {
437*8fb009dcSAndroid Build Coastguard Worker return false;
438*8fb009dcSAndroid Build Coastguard Worker }
439*8fb009dcSAndroid Build Coastguard Worker }
440*8fb009dcSAndroid Build Coastguard Worker return true;
441*8fb009dcSAndroid Build Coastguard Worker }
442*8fb009dcSAndroid Build Coastguard Worker
tls12_check_peer_sigalg(const SSL_HANDSHAKE * hs,uint8_t * out_alert,uint16_t sigalg,EVP_PKEY * pkey)443*8fb009dcSAndroid Build Coastguard Worker bool tls12_check_peer_sigalg(const SSL_HANDSHAKE *hs, uint8_t *out_alert,
444*8fb009dcSAndroid Build Coastguard Worker uint16_t sigalg, EVP_PKEY *pkey) {
445*8fb009dcSAndroid Build Coastguard Worker // The peer must have selected an algorithm that is consistent with its public
446*8fb009dcSAndroid Build Coastguard Worker // key, the TLS version, and what we advertised.
447*8fb009dcSAndroid Build Coastguard Worker Span<const uint16_t> sigalgs = tls12_get_verify_sigalgs(hs);
448*8fb009dcSAndroid Build Coastguard Worker if (std::find(sigalgs.begin(), sigalgs.end(), sigalg) == sigalgs.end() ||
449*8fb009dcSAndroid Build Coastguard Worker !ssl_pkey_supports_algorithm(hs->ssl, pkey, sigalg, /*is_verify=*/true)) {
450*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
451*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
452*8fb009dcSAndroid Build Coastguard Worker return false;
453*8fb009dcSAndroid Build Coastguard Worker }
454*8fb009dcSAndroid Build Coastguard Worker
455*8fb009dcSAndroid Build Coastguard Worker return true;
456*8fb009dcSAndroid Build Coastguard Worker }
457*8fb009dcSAndroid Build Coastguard Worker
458*8fb009dcSAndroid Build Coastguard Worker // tls_extension represents a TLS extension that is handled internally.
459*8fb009dcSAndroid Build Coastguard Worker //
460*8fb009dcSAndroid Build Coastguard Worker // The parse callbacks receive a |CBS| that contains the contents of the
461*8fb009dcSAndroid Build Coastguard Worker // extension (i.e. not including the type and length bytes). If an extension is
462*8fb009dcSAndroid Build Coastguard Worker // not received then the parse callbacks will be called with a NULL CBS so that
463*8fb009dcSAndroid Build Coastguard Worker // they can do any processing needed to handle the absence of an extension.
464*8fb009dcSAndroid Build Coastguard Worker //
465*8fb009dcSAndroid Build Coastguard Worker // The add callbacks receive a |CBB| to which the extension can be appended but
466*8fb009dcSAndroid Build Coastguard Worker // the function is responsible for appending the type and length bytes too.
467*8fb009dcSAndroid Build Coastguard Worker //
468*8fb009dcSAndroid Build Coastguard Worker // |add_clienthello| may be called multiple times and must not mutate |hs|. It
469*8fb009dcSAndroid Build Coastguard Worker // is additionally passed two output |CBB|s. If the extension is the same
470*8fb009dcSAndroid Build Coastguard Worker // independent of the value of |type|, the callback may write to
471*8fb009dcSAndroid Build Coastguard Worker // |out_compressible| instead of |out|. When serializing the ClientHelloInner,
472*8fb009dcSAndroid Build Coastguard Worker // all compressible extensions will be made continguous and replaced with
473*8fb009dcSAndroid Build Coastguard Worker // ech_outer_extensions when encrypted. When serializing the ClientHelloOuter
474*8fb009dcSAndroid Build Coastguard Worker // or not offering ECH, |out| will be equal to |out_compressible|, so writing to
475*8fb009dcSAndroid Build Coastguard Worker // |out_compressible| still works.
476*8fb009dcSAndroid Build Coastguard Worker //
477*8fb009dcSAndroid Build Coastguard Worker // Note the |parse_serverhello| and |add_serverhello| callbacks refer to the
478*8fb009dcSAndroid Build Coastguard Worker // TLS 1.2 ServerHello. In TLS 1.3, these callbacks act on EncryptedExtensions,
479*8fb009dcSAndroid Build Coastguard Worker // with ServerHello extensions handled elsewhere in the handshake.
480*8fb009dcSAndroid Build Coastguard Worker //
481*8fb009dcSAndroid Build Coastguard Worker // All callbacks return true for success and false for error. If a parse
482*8fb009dcSAndroid Build Coastguard Worker // function returns zero then a fatal alert with value |*out_alert| will be
483*8fb009dcSAndroid Build Coastguard Worker // sent. If |*out_alert| isn't set, then a |decode_error| alert will be sent.
484*8fb009dcSAndroid Build Coastguard Worker struct tls_extension {
485*8fb009dcSAndroid Build Coastguard Worker uint16_t value;
486*8fb009dcSAndroid Build Coastguard Worker
487*8fb009dcSAndroid Build Coastguard Worker bool (*add_clienthello)(const SSL_HANDSHAKE *hs, CBB *out,
488*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible, ssl_client_hello_type_t type);
489*8fb009dcSAndroid Build Coastguard Worker bool (*parse_serverhello)(SSL_HANDSHAKE *hs, uint8_t *out_alert,
490*8fb009dcSAndroid Build Coastguard Worker CBS *contents);
491*8fb009dcSAndroid Build Coastguard Worker
492*8fb009dcSAndroid Build Coastguard Worker bool (*parse_clienthello)(SSL_HANDSHAKE *hs, uint8_t *out_alert,
493*8fb009dcSAndroid Build Coastguard Worker CBS *contents);
494*8fb009dcSAndroid Build Coastguard Worker bool (*add_serverhello)(SSL_HANDSHAKE *hs, CBB *out);
495*8fb009dcSAndroid Build Coastguard Worker };
496*8fb009dcSAndroid Build Coastguard Worker
forbid_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)497*8fb009dcSAndroid Build Coastguard Worker static bool forbid_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
498*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
499*8fb009dcSAndroid Build Coastguard Worker if (contents != NULL) {
500*8fb009dcSAndroid Build Coastguard Worker // Servers MUST NOT send this extension.
501*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
502*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
503*8fb009dcSAndroid Build Coastguard Worker return false;
504*8fb009dcSAndroid Build Coastguard Worker }
505*8fb009dcSAndroid Build Coastguard Worker
506*8fb009dcSAndroid Build Coastguard Worker return true;
507*8fb009dcSAndroid Build Coastguard Worker }
508*8fb009dcSAndroid Build Coastguard Worker
ignore_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)509*8fb009dcSAndroid Build Coastguard Worker static bool ignore_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
510*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
511*8fb009dcSAndroid Build Coastguard Worker // This extension from the client is handled elsewhere.
512*8fb009dcSAndroid Build Coastguard Worker return true;
513*8fb009dcSAndroid Build Coastguard Worker }
514*8fb009dcSAndroid Build Coastguard Worker
dont_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)515*8fb009dcSAndroid Build Coastguard Worker static bool dont_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
516*8fb009dcSAndroid Build Coastguard Worker return true;
517*8fb009dcSAndroid Build Coastguard Worker }
518*8fb009dcSAndroid Build Coastguard Worker
519*8fb009dcSAndroid Build Coastguard Worker // Server name indication (SNI).
520*8fb009dcSAndroid Build Coastguard Worker //
521*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc6066#section-3.
522*8fb009dcSAndroid Build Coastguard Worker
ext_sni_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)523*8fb009dcSAndroid Build Coastguard Worker static bool ext_sni_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
524*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
525*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
526*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
527*8fb009dcSAndroid Build Coastguard Worker // If offering ECH, send the public name instead of the configured name.
528*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> hostname;
529*8fb009dcSAndroid Build Coastguard Worker if (type == ssl_client_hello_outer) {
530*8fb009dcSAndroid Build Coastguard Worker hostname = hs->selected_ech_config->public_name;
531*8fb009dcSAndroid Build Coastguard Worker } else {
532*8fb009dcSAndroid Build Coastguard Worker if (ssl->hostname == nullptr) {
533*8fb009dcSAndroid Build Coastguard Worker return true;
534*8fb009dcSAndroid Build Coastguard Worker }
535*8fb009dcSAndroid Build Coastguard Worker hostname =
536*8fb009dcSAndroid Build Coastguard Worker MakeConstSpan(reinterpret_cast<const uint8_t *>(ssl->hostname.get()),
537*8fb009dcSAndroid Build Coastguard Worker strlen(ssl->hostname.get()));
538*8fb009dcSAndroid Build Coastguard Worker }
539*8fb009dcSAndroid Build Coastguard Worker
540*8fb009dcSAndroid Build Coastguard Worker CBB contents, server_name_list, name;
541*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) ||
542*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
543*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &server_name_list) ||
544*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(&server_name_list, TLSEXT_NAMETYPE_host_name) ||
545*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&server_name_list, &name) ||
546*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&name, hostname.data(), hostname.size()) ||
547*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
548*8fb009dcSAndroid Build Coastguard Worker return false;
549*8fb009dcSAndroid Build Coastguard Worker }
550*8fb009dcSAndroid Build Coastguard Worker
551*8fb009dcSAndroid Build Coastguard Worker return true;
552*8fb009dcSAndroid Build Coastguard Worker }
553*8fb009dcSAndroid Build Coastguard Worker
ext_sni_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)554*8fb009dcSAndroid Build Coastguard Worker static bool ext_sni_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
555*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
556*8fb009dcSAndroid Build Coastguard Worker // The server may acknowledge SNI with an empty extension. We check the syntax
557*8fb009dcSAndroid Build Coastguard Worker // but otherwise ignore this signal.
558*8fb009dcSAndroid Build Coastguard Worker return contents == NULL || CBS_len(contents) == 0;
559*8fb009dcSAndroid Build Coastguard Worker }
560*8fb009dcSAndroid Build Coastguard Worker
ext_sni_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)561*8fb009dcSAndroid Build Coastguard Worker static bool ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
562*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
563*8fb009dcSAndroid Build Coastguard Worker // SNI has already been parsed earlier in the handshake. See |extract_sni|.
564*8fb009dcSAndroid Build Coastguard Worker return true;
565*8fb009dcSAndroid Build Coastguard Worker }
566*8fb009dcSAndroid Build Coastguard Worker
ext_sni_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)567*8fb009dcSAndroid Build Coastguard Worker static bool ext_sni_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
568*8fb009dcSAndroid Build Coastguard Worker if (hs->ssl->s3->session_reused ||
569*8fb009dcSAndroid Build Coastguard Worker !hs->should_ack_sni) {
570*8fb009dcSAndroid Build Coastguard Worker return true;
571*8fb009dcSAndroid Build Coastguard Worker }
572*8fb009dcSAndroid Build Coastguard Worker
573*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) ||
574*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out, 0 /* length */)) {
575*8fb009dcSAndroid Build Coastguard Worker return false;
576*8fb009dcSAndroid Build Coastguard Worker }
577*8fb009dcSAndroid Build Coastguard Worker
578*8fb009dcSAndroid Build Coastguard Worker return true;
579*8fb009dcSAndroid Build Coastguard Worker }
580*8fb009dcSAndroid Build Coastguard Worker
581*8fb009dcSAndroid Build Coastguard Worker
582*8fb009dcSAndroid Build Coastguard Worker // Encrypted ClientHello (ECH)
583*8fb009dcSAndroid Build Coastguard Worker //
584*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/draft-ietf-tls-esni-13
585*8fb009dcSAndroid Build Coastguard Worker
ext_ech_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)586*8fb009dcSAndroid Build Coastguard Worker static bool ext_ech_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
587*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
588*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
589*8fb009dcSAndroid Build Coastguard Worker if (type == ssl_client_hello_inner) {
590*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
591*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out, /* length */ 1) ||
592*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(out, ECH_CLIENT_INNER)) {
593*8fb009dcSAndroid Build Coastguard Worker return false;
594*8fb009dcSAndroid Build Coastguard Worker }
595*8fb009dcSAndroid Build Coastguard Worker return true;
596*8fb009dcSAndroid Build Coastguard Worker }
597*8fb009dcSAndroid Build Coastguard Worker
598*8fb009dcSAndroid Build Coastguard Worker if (hs->ech_client_outer.empty()) {
599*8fb009dcSAndroid Build Coastguard Worker return true;
600*8fb009dcSAndroid Build Coastguard Worker }
601*8fb009dcSAndroid Build Coastguard Worker
602*8fb009dcSAndroid Build Coastguard Worker CBB ech_body;
603*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
604*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &ech_body) ||
605*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(&ech_body, ECH_CLIENT_OUTER) ||
606*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&ech_body, hs->ech_client_outer.data(),
607*8fb009dcSAndroid Build Coastguard Worker hs->ech_client_outer.size()) ||
608*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
609*8fb009dcSAndroid Build Coastguard Worker return false;
610*8fb009dcSAndroid Build Coastguard Worker }
611*8fb009dcSAndroid Build Coastguard Worker return true;
612*8fb009dcSAndroid Build Coastguard Worker }
613*8fb009dcSAndroid Build Coastguard Worker
ext_ech_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)614*8fb009dcSAndroid Build Coastguard Worker static bool ext_ech_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
615*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
616*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
617*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
618*8fb009dcSAndroid Build Coastguard Worker return true;
619*8fb009dcSAndroid Build Coastguard Worker }
620*8fb009dcSAndroid Build Coastguard Worker
621*8fb009dcSAndroid Build Coastguard Worker // The ECH extension may not be sent in TLS 1.2 ServerHello, only TLS 1.3
622*8fb009dcSAndroid Build Coastguard Worker // EncryptedExtensions. It also may not be sent in response to an inner ECH
623*8fb009dcSAndroid Build Coastguard Worker // extension.
624*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
625*8fb009dcSAndroid Build Coastguard Worker ssl->s3->ech_status == ssl_ech_accepted) {
626*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
627*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
628*8fb009dcSAndroid Build Coastguard Worker return false;
629*8fb009dcSAndroid Build Coastguard Worker }
630*8fb009dcSAndroid Build Coastguard Worker
631*8fb009dcSAndroid Build Coastguard Worker if (!ssl_is_valid_ech_config_list(*contents)) {
632*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
633*8fb009dcSAndroid Build Coastguard Worker return false;
634*8fb009dcSAndroid Build Coastguard Worker }
635*8fb009dcSAndroid Build Coastguard Worker
636*8fb009dcSAndroid Build Coastguard Worker if (ssl->s3->ech_status == ssl_ech_rejected &&
637*8fb009dcSAndroid Build Coastguard Worker !hs->ech_retry_configs.CopyFrom(*contents)) {
638*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
639*8fb009dcSAndroid Build Coastguard Worker return false;
640*8fb009dcSAndroid Build Coastguard Worker }
641*8fb009dcSAndroid Build Coastguard Worker
642*8fb009dcSAndroid Build Coastguard Worker return true;
643*8fb009dcSAndroid Build Coastguard Worker }
644*8fb009dcSAndroid Build Coastguard Worker
ext_ech_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)645*8fb009dcSAndroid Build Coastguard Worker static bool ext_ech_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
646*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
647*8fb009dcSAndroid Build Coastguard Worker if (contents == nullptr) {
648*8fb009dcSAndroid Build Coastguard Worker return true;
649*8fb009dcSAndroid Build Coastguard Worker }
650*8fb009dcSAndroid Build Coastguard Worker
651*8fb009dcSAndroid Build Coastguard Worker uint8_t type;
652*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8(contents, &type)) {
653*8fb009dcSAndroid Build Coastguard Worker return false;
654*8fb009dcSAndroid Build Coastguard Worker }
655*8fb009dcSAndroid Build Coastguard Worker if (type == ECH_CLIENT_OUTER) {
656*8fb009dcSAndroid Build Coastguard Worker // Outer ECH extensions are handled outside the callback.
657*8fb009dcSAndroid Build Coastguard Worker return true;
658*8fb009dcSAndroid Build Coastguard Worker }
659*8fb009dcSAndroid Build Coastguard Worker if (type != ECH_CLIENT_INNER || CBS_len(contents) != 0) {
660*8fb009dcSAndroid Build Coastguard Worker return false;
661*8fb009dcSAndroid Build Coastguard Worker }
662*8fb009dcSAndroid Build Coastguard Worker
663*8fb009dcSAndroid Build Coastguard Worker hs->ech_is_inner = true;
664*8fb009dcSAndroid Build Coastguard Worker return true;
665*8fb009dcSAndroid Build Coastguard Worker }
666*8fb009dcSAndroid Build Coastguard Worker
ext_ech_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)667*8fb009dcSAndroid Build Coastguard Worker static bool ext_ech_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
668*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
669*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
670*8fb009dcSAndroid Build Coastguard Worker ssl->s3->ech_status == ssl_ech_accepted || //
671*8fb009dcSAndroid Build Coastguard Worker hs->ech_keys == nullptr) {
672*8fb009dcSAndroid Build Coastguard Worker return true;
673*8fb009dcSAndroid Build Coastguard Worker }
674*8fb009dcSAndroid Build Coastguard Worker
675*8fb009dcSAndroid Build Coastguard Worker // Write the list of retry configs to |out|. Note |SSL_CTX_set1_ech_keys|
676*8fb009dcSAndroid Build Coastguard Worker // ensures |ech_keys| contains at least one retry config.
677*8fb009dcSAndroid Build Coastguard Worker CBB body, retry_configs;
678*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
679*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &body) ||
680*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&body, &retry_configs)) {
681*8fb009dcSAndroid Build Coastguard Worker return false;
682*8fb009dcSAndroid Build Coastguard Worker }
683*8fb009dcSAndroid Build Coastguard Worker for (const auto &config : hs->ech_keys->configs) {
684*8fb009dcSAndroid Build Coastguard Worker if (!config->is_retry_config()) {
685*8fb009dcSAndroid Build Coastguard Worker continue;
686*8fb009dcSAndroid Build Coastguard Worker }
687*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_bytes(&retry_configs, config->ech_config().raw.data(),
688*8fb009dcSAndroid Build Coastguard Worker config->ech_config().raw.size())) {
689*8fb009dcSAndroid Build Coastguard Worker return false;
690*8fb009dcSAndroid Build Coastguard Worker }
691*8fb009dcSAndroid Build Coastguard Worker }
692*8fb009dcSAndroid Build Coastguard Worker return CBB_flush(out);
693*8fb009dcSAndroid Build Coastguard Worker }
694*8fb009dcSAndroid Build Coastguard Worker
695*8fb009dcSAndroid Build Coastguard Worker
696*8fb009dcSAndroid Build Coastguard Worker // Renegotiation indication.
697*8fb009dcSAndroid Build Coastguard Worker //
698*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc5746
699*8fb009dcSAndroid Build Coastguard Worker
ext_ri_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)700*8fb009dcSAndroid Build Coastguard Worker static bool ext_ri_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
701*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
702*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
703*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
704*8fb009dcSAndroid Build Coastguard Worker // Renegotiation indication is not necessary in TLS 1.3.
705*8fb009dcSAndroid Build Coastguard Worker if (hs->min_version >= TLS1_3_VERSION ||
706*8fb009dcSAndroid Build Coastguard Worker type == ssl_client_hello_inner) {
707*8fb009dcSAndroid Build Coastguard Worker return true;
708*8fb009dcSAndroid Build Coastguard Worker }
709*8fb009dcSAndroid Build Coastguard Worker
710*8fb009dcSAndroid Build Coastguard Worker assert(ssl->s3->initial_handshake_complete ==
711*8fb009dcSAndroid Build Coastguard Worker (ssl->s3->previous_client_finished_len != 0));
712*8fb009dcSAndroid Build Coastguard Worker
713*8fb009dcSAndroid Build Coastguard Worker CBB contents, prev_finished;
714*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
715*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
716*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8_length_prefixed(&contents, &prev_finished) ||
717*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&prev_finished, ssl->s3->previous_client_finished,
718*8fb009dcSAndroid Build Coastguard Worker ssl->s3->previous_client_finished_len) ||
719*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
720*8fb009dcSAndroid Build Coastguard Worker return false;
721*8fb009dcSAndroid Build Coastguard Worker }
722*8fb009dcSAndroid Build Coastguard Worker
723*8fb009dcSAndroid Build Coastguard Worker return true;
724*8fb009dcSAndroid Build Coastguard Worker }
725*8fb009dcSAndroid Build Coastguard Worker
ext_ri_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)726*8fb009dcSAndroid Build Coastguard Worker static bool ext_ri_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
727*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
728*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
729*8fb009dcSAndroid Build Coastguard Worker if (contents != NULL && ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
730*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
731*8fb009dcSAndroid Build Coastguard Worker return false;
732*8fb009dcSAndroid Build Coastguard Worker }
733*8fb009dcSAndroid Build Coastguard Worker
734*8fb009dcSAndroid Build Coastguard Worker // Servers may not switch between omitting the extension and supporting it.
735*8fb009dcSAndroid Build Coastguard Worker // See RFC 5746, sections 3.5 and 4.2.
736*8fb009dcSAndroid Build Coastguard Worker if (ssl->s3->initial_handshake_complete &&
737*8fb009dcSAndroid Build Coastguard Worker (contents != NULL) != ssl->s3->send_connection_binding) {
738*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_HANDSHAKE_FAILURE;
739*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
740*8fb009dcSAndroid Build Coastguard Worker return false;
741*8fb009dcSAndroid Build Coastguard Worker }
742*8fb009dcSAndroid Build Coastguard Worker
743*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
744*8fb009dcSAndroid Build Coastguard Worker // Strictly speaking, if we want to avoid an attack we should *always* see
745*8fb009dcSAndroid Build Coastguard Worker // RI even on initial ServerHello because the client doesn't see any
746*8fb009dcSAndroid Build Coastguard Worker // renegotiation during an attack. However this would mean we could not
747*8fb009dcSAndroid Build Coastguard Worker // connect to any server which doesn't support RI.
748*8fb009dcSAndroid Build Coastguard Worker //
749*8fb009dcSAndroid Build Coastguard Worker // OpenSSL has |SSL_OP_LEGACY_SERVER_CONNECT| to control this, but in
750*8fb009dcSAndroid Build Coastguard Worker // practical terms every client sets it so it's just assumed here.
751*8fb009dcSAndroid Build Coastguard Worker return true;
752*8fb009dcSAndroid Build Coastguard Worker }
753*8fb009dcSAndroid Build Coastguard Worker
754*8fb009dcSAndroid Build Coastguard Worker const size_t expected_len = ssl->s3->previous_client_finished_len +
755*8fb009dcSAndroid Build Coastguard Worker ssl->s3->previous_server_finished_len;
756*8fb009dcSAndroid Build Coastguard Worker
757*8fb009dcSAndroid Build Coastguard Worker // Check for logic errors
758*8fb009dcSAndroid Build Coastguard Worker assert(!expected_len || ssl->s3->previous_client_finished_len);
759*8fb009dcSAndroid Build Coastguard Worker assert(!expected_len || ssl->s3->previous_server_finished_len);
760*8fb009dcSAndroid Build Coastguard Worker assert(ssl->s3->initial_handshake_complete ==
761*8fb009dcSAndroid Build Coastguard Worker (ssl->s3->previous_client_finished_len != 0));
762*8fb009dcSAndroid Build Coastguard Worker assert(ssl->s3->initial_handshake_complete ==
763*8fb009dcSAndroid Build Coastguard Worker (ssl->s3->previous_server_finished_len != 0));
764*8fb009dcSAndroid Build Coastguard Worker
765*8fb009dcSAndroid Build Coastguard Worker // Parse out the extension contents.
766*8fb009dcSAndroid Build Coastguard Worker CBS renegotiated_connection;
767*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) ||
768*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0) {
769*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR);
770*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
771*8fb009dcSAndroid Build Coastguard Worker return false;
772*8fb009dcSAndroid Build Coastguard Worker }
773*8fb009dcSAndroid Build Coastguard Worker
774*8fb009dcSAndroid Build Coastguard Worker // Check that the extension matches.
775*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(&renegotiated_connection) != expected_len) {
776*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
777*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_HANDSHAKE_FAILURE;
778*8fb009dcSAndroid Build Coastguard Worker return false;
779*8fb009dcSAndroid Build Coastguard Worker }
780*8fb009dcSAndroid Build Coastguard Worker
781*8fb009dcSAndroid Build Coastguard Worker const uint8_t *d = CBS_data(&renegotiated_connection);
782*8fb009dcSAndroid Build Coastguard Worker bool ok = CRYPTO_memcmp(d, ssl->s3->previous_client_finished,
783*8fb009dcSAndroid Build Coastguard Worker ssl->s3->previous_client_finished_len) == 0;
784*8fb009dcSAndroid Build Coastguard Worker #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
785*8fb009dcSAndroid Build Coastguard Worker ok = true;
786*8fb009dcSAndroid Build Coastguard Worker #endif
787*8fb009dcSAndroid Build Coastguard Worker if (!ok) {
788*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
789*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_HANDSHAKE_FAILURE;
790*8fb009dcSAndroid Build Coastguard Worker return false;
791*8fb009dcSAndroid Build Coastguard Worker }
792*8fb009dcSAndroid Build Coastguard Worker d += ssl->s3->previous_client_finished_len;
793*8fb009dcSAndroid Build Coastguard Worker
794*8fb009dcSAndroid Build Coastguard Worker ok = CRYPTO_memcmp(d, ssl->s3->previous_server_finished,
795*8fb009dcSAndroid Build Coastguard Worker ssl->s3->previous_server_finished_len) == 0;
796*8fb009dcSAndroid Build Coastguard Worker #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
797*8fb009dcSAndroid Build Coastguard Worker ok = true;
798*8fb009dcSAndroid Build Coastguard Worker #endif
799*8fb009dcSAndroid Build Coastguard Worker if (!ok) {
800*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
801*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_HANDSHAKE_FAILURE;
802*8fb009dcSAndroid Build Coastguard Worker return false;
803*8fb009dcSAndroid Build Coastguard Worker }
804*8fb009dcSAndroid Build Coastguard Worker ssl->s3->send_connection_binding = true;
805*8fb009dcSAndroid Build Coastguard Worker
806*8fb009dcSAndroid Build Coastguard Worker return true;
807*8fb009dcSAndroid Build Coastguard Worker }
808*8fb009dcSAndroid Build Coastguard Worker
ext_ri_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)809*8fb009dcSAndroid Build Coastguard Worker static bool ext_ri_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
810*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
811*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
812*8fb009dcSAndroid Build Coastguard Worker // Renegotiation isn't supported as a server so this function should never be
813*8fb009dcSAndroid Build Coastguard Worker // called after the initial handshake.
814*8fb009dcSAndroid Build Coastguard Worker assert(!ssl->s3->initial_handshake_complete);
815*8fb009dcSAndroid Build Coastguard Worker
816*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
817*8fb009dcSAndroid Build Coastguard Worker return true;
818*8fb009dcSAndroid Build Coastguard Worker }
819*8fb009dcSAndroid Build Coastguard Worker
820*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
821*8fb009dcSAndroid Build Coastguard Worker return true;
822*8fb009dcSAndroid Build Coastguard Worker }
823*8fb009dcSAndroid Build Coastguard Worker
824*8fb009dcSAndroid Build Coastguard Worker CBS renegotiated_connection;
825*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) ||
826*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0) {
827*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR);
828*8fb009dcSAndroid Build Coastguard Worker return false;
829*8fb009dcSAndroid Build Coastguard Worker }
830*8fb009dcSAndroid Build Coastguard Worker
831*8fb009dcSAndroid Build Coastguard Worker // Check that the extension matches. We do not support renegotiation as a
832*8fb009dcSAndroid Build Coastguard Worker // server, so this must be empty.
833*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(&renegotiated_connection) != 0) {
834*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
835*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_HANDSHAKE_FAILURE;
836*8fb009dcSAndroid Build Coastguard Worker return false;
837*8fb009dcSAndroid Build Coastguard Worker }
838*8fb009dcSAndroid Build Coastguard Worker
839*8fb009dcSAndroid Build Coastguard Worker ssl->s3->send_connection_binding = true;
840*8fb009dcSAndroid Build Coastguard Worker
841*8fb009dcSAndroid Build Coastguard Worker return true;
842*8fb009dcSAndroid Build Coastguard Worker }
843*8fb009dcSAndroid Build Coastguard Worker
ext_ri_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)844*8fb009dcSAndroid Build Coastguard Worker static bool ext_ri_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
845*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
846*8fb009dcSAndroid Build Coastguard Worker // Renegotiation isn't supported as a server so this function should never be
847*8fb009dcSAndroid Build Coastguard Worker // called after the initial handshake.
848*8fb009dcSAndroid Build Coastguard Worker assert(!ssl->s3->initial_handshake_complete);
849*8fb009dcSAndroid Build Coastguard Worker
850*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
851*8fb009dcSAndroid Build Coastguard Worker return true;
852*8fb009dcSAndroid Build Coastguard Worker }
853*8fb009dcSAndroid Build Coastguard Worker
854*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
855*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out, 1 /* length */) ||
856*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(out, 0 /* empty renegotiation info */)) {
857*8fb009dcSAndroid Build Coastguard Worker return false;
858*8fb009dcSAndroid Build Coastguard Worker }
859*8fb009dcSAndroid Build Coastguard Worker
860*8fb009dcSAndroid Build Coastguard Worker return true;
861*8fb009dcSAndroid Build Coastguard Worker }
862*8fb009dcSAndroid Build Coastguard Worker
863*8fb009dcSAndroid Build Coastguard Worker
864*8fb009dcSAndroid Build Coastguard Worker // Extended Master Secret.
865*8fb009dcSAndroid Build Coastguard Worker //
866*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc7627
867*8fb009dcSAndroid Build Coastguard Worker
ext_ems_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)868*8fb009dcSAndroid Build Coastguard Worker static bool ext_ems_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
869*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
870*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
871*8fb009dcSAndroid Build Coastguard Worker // Extended master secret is not necessary in TLS 1.3.
872*8fb009dcSAndroid Build Coastguard Worker if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner) {
873*8fb009dcSAndroid Build Coastguard Worker return true;
874*8fb009dcSAndroid Build Coastguard Worker }
875*8fb009dcSAndroid Build Coastguard Worker
876*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) ||
877*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out, 0 /* length */)) {
878*8fb009dcSAndroid Build Coastguard Worker return false;
879*8fb009dcSAndroid Build Coastguard Worker }
880*8fb009dcSAndroid Build Coastguard Worker
881*8fb009dcSAndroid Build Coastguard Worker return true;
882*8fb009dcSAndroid Build Coastguard Worker }
883*8fb009dcSAndroid Build Coastguard Worker
ext_ems_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)884*8fb009dcSAndroid Build Coastguard Worker static bool ext_ems_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
885*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
886*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
887*8fb009dcSAndroid Build Coastguard Worker
888*8fb009dcSAndroid Build Coastguard Worker if (contents != NULL) {
889*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
890*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0) {
891*8fb009dcSAndroid Build Coastguard Worker return false;
892*8fb009dcSAndroid Build Coastguard Worker }
893*8fb009dcSAndroid Build Coastguard Worker
894*8fb009dcSAndroid Build Coastguard Worker hs->extended_master_secret = true;
895*8fb009dcSAndroid Build Coastguard Worker }
896*8fb009dcSAndroid Build Coastguard Worker
897*8fb009dcSAndroid Build Coastguard Worker // Whether EMS is negotiated may not change on renegotiation.
898*8fb009dcSAndroid Build Coastguard Worker if (ssl->s3->established_session != nullptr &&
899*8fb009dcSAndroid Build Coastguard Worker hs->extended_master_secret !=
900*8fb009dcSAndroid Build Coastguard Worker !!ssl->s3->established_session->extended_master_secret) {
901*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_EMS_MISMATCH);
902*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
903*8fb009dcSAndroid Build Coastguard Worker return false;
904*8fb009dcSAndroid Build Coastguard Worker }
905*8fb009dcSAndroid Build Coastguard Worker
906*8fb009dcSAndroid Build Coastguard Worker return true;
907*8fb009dcSAndroid Build Coastguard Worker }
908*8fb009dcSAndroid Build Coastguard Worker
ext_ems_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)909*8fb009dcSAndroid Build Coastguard Worker static bool ext_ems_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
910*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
911*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
912*8fb009dcSAndroid Build Coastguard Worker return true;
913*8fb009dcSAndroid Build Coastguard Worker }
914*8fb009dcSAndroid Build Coastguard Worker
915*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
916*8fb009dcSAndroid Build Coastguard Worker return true;
917*8fb009dcSAndroid Build Coastguard Worker }
918*8fb009dcSAndroid Build Coastguard Worker
919*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(contents) != 0) {
920*8fb009dcSAndroid Build Coastguard Worker return false;
921*8fb009dcSAndroid Build Coastguard Worker }
922*8fb009dcSAndroid Build Coastguard Worker
923*8fb009dcSAndroid Build Coastguard Worker hs->extended_master_secret = true;
924*8fb009dcSAndroid Build Coastguard Worker return true;
925*8fb009dcSAndroid Build Coastguard Worker }
926*8fb009dcSAndroid Build Coastguard Worker
ext_ems_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)927*8fb009dcSAndroid Build Coastguard Worker static bool ext_ems_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
928*8fb009dcSAndroid Build Coastguard Worker if (!hs->extended_master_secret) {
929*8fb009dcSAndroid Build Coastguard Worker return true;
930*8fb009dcSAndroid Build Coastguard Worker }
931*8fb009dcSAndroid Build Coastguard Worker
932*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) ||
933*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out, 0 /* length */)) {
934*8fb009dcSAndroid Build Coastguard Worker return false;
935*8fb009dcSAndroid Build Coastguard Worker }
936*8fb009dcSAndroid Build Coastguard Worker
937*8fb009dcSAndroid Build Coastguard Worker return true;
938*8fb009dcSAndroid Build Coastguard Worker }
939*8fb009dcSAndroid Build Coastguard Worker
940*8fb009dcSAndroid Build Coastguard Worker
941*8fb009dcSAndroid Build Coastguard Worker // Session tickets.
942*8fb009dcSAndroid Build Coastguard Worker //
943*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc5077
944*8fb009dcSAndroid Build Coastguard Worker
ext_ticket_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)945*8fb009dcSAndroid Build Coastguard Worker static bool ext_ticket_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
946*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
947*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
948*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
949*8fb009dcSAndroid Build Coastguard Worker // TLS 1.3 uses a different ticket extension.
950*8fb009dcSAndroid Build Coastguard Worker if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner ||
951*8fb009dcSAndroid Build Coastguard Worker SSL_get_options(ssl) & SSL_OP_NO_TICKET) {
952*8fb009dcSAndroid Build Coastguard Worker return true;
953*8fb009dcSAndroid Build Coastguard Worker }
954*8fb009dcSAndroid Build Coastguard Worker
955*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> ticket;
956*8fb009dcSAndroid Build Coastguard Worker
957*8fb009dcSAndroid Build Coastguard Worker // Renegotiation does not participate in session resumption. However, still
958*8fb009dcSAndroid Build Coastguard Worker // advertise the extension to avoid potentially breaking servers which carry
959*8fb009dcSAndroid Build Coastguard Worker // over the state from the previous handshake, such as OpenSSL servers
960*8fb009dcSAndroid Build Coastguard Worker // without upstream's 3c3f0259238594d77264a78944d409f2127642c4.
961*8fb009dcSAndroid Build Coastguard Worker if (!ssl->s3->initial_handshake_complete &&
962*8fb009dcSAndroid Build Coastguard Worker ssl->session != nullptr &&
963*8fb009dcSAndroid Build Coastguard Worker !ssl->session->ticket.empty() &&
964*8fb009dcSAndroid Build Coastguard Worker // Don't send TLS 1.3 session tickets in the ticket extension.
965*8fb009dcSAndroid Build Coastguard Worker ssl_session_protocol_version(ssl->session.get()) < TLS1_3_VERSION) {
966*8fb009dcSAndroid Build Coastguard Worker ticket = ssl->session->ticket;
967*8fb009dcSAndroid Build Coastguard Worker }
968*8fb009dcSAndroid Build Coastguard Worker
969*8fb009dcSAndroid Build Coastguard Worker CBB ticket_cbb;
970*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
971*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &ticket_cbb) ||
972*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&ticket_cbb, ticket.data(), ticket.size()) ||
973*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
974*8fb009dcSAndroid Build Coastguard Worker return false;
975*8fb009dcSAndroid Build Coastguard Worker }
976*8fb009dcSAndroid Build Coastguard Worker
977*8fb009dcSAndroid Build Coastguard Worker return true;
978*8fb009dcSAndroid Build Coastguard Worker }
979*8fb009dcSAndroid Build Coastguard Worker
ext_ticket_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)980*8fb009dcSAndroid Build Coastguard Worker static bool ext_ticket_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
981*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
982*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
983*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
984*8fb009dcSAndroid Build Coastguard Worker return true;
985*8fb009dcSAndroid Build Coastguard Worker }
986*8fb009dcSAndroid Build Coastguard Worker
987*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
988*8fb009dcSAndroid Build Coastguard Worker return false;
989*8fb009dcSAndroid Build Coastguard Worker }
990*8fb009dcSAndroid Build Coastguard Worker
991*8fb009dcSAndroid Build Coastguard Worker // If |SSL_OP_NO_TICKET| is set then no extension will have been sent and
992*8fb009dcSAndroid Build Coastguard Worker // this function should never be called, even if the server tries to send the
993*8fb009dcSAndroid Build Coastguard Worker // extension.
994*8fb009dcSAndroid Build Coastguard Worker assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0);
995*8fb009dcSAndroid Build Coastguard Worker
996*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(contents) != 0) {
997*8fb009dcSAndroid Build Coastguard Worker return false;
998*8fb009dcSAndroid Build Coastguard Worker }
999*8fb009dcSAndroid Build Coastguard Worker
1000*8fb009dcSAndroid Build Coastguard Worker hs->ticket_expected = true;
1001*8fb009dcSAndroid Build Coastguard Worker return true;
1002*8fb009dcSAndroid Build Coastguard Worker }
1003*8fb009dcSAndroid Build Coastguard Worker
ext_ticket_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)1004*8fb009dcSAndroid Build Coastguard Worker static bool ext_ticket_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
1005*8fb009dcSAndroid Build Coastguard Worker if (!hs->ticket_expected) {
1006*8fb009dcSAndroid Build Coastguard Worker return true;
1007*8fb009dcSAndroid Build Coastguard Worker }
1008*8fb009dcSAndroid Build Coastguard Worker
1009*8fb009dcSAndroid Build Coastguard Worker // If |SSL_OP_NO_TICKET| is set, |ticket_expected| should never be true.
1010*8fb009dcSAndroid Build Coastguard Worker assert((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) == 0);
1011*8fb009dcSAndroid Build Coastguard Worker
1012*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
1013*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out, 0 /* length */)) {
1014*8fb009dcSAndroid Build Coastguard Worker return false;
1015*8fb009dcSAndroid Build Coastguard Worker }
1016*8fb009dcSAndroid Build Coastguard Worker
1017*8fb009dcSAndroid Build Coastguard Worker return true;
1018*8fb009dcSAndroid Build Coastguard Worker }
1019*8fb009dcSAndroid Build Coastguard Worker
1020*8fb009dcSAndroid Build Coastguard Worker
1021*8fb009dcSAndroid Build Coastguard Worker // Signature Algorithms.
1022*8fb009dcSAndroid Build Coastguard Worker //
1023*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
1024*8fb009dcSAndroid Build Coastguard Worker
ext_sigalgs_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)1025*8fb009dcSAndroid Build Coastguard Worker static bool ext_sigalgs_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1026*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
1027*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
1028*8fb009dcSAndroid Build Coastguard Worker if (hs->max_version < TLS1_2_VERSION) {
1029*8fb009dcSAndroid Build Coastguard Worker return true;
1030*8fb009dcSAndroid Build Coastguard Worker }
1031*8fb009dcSAndroid Build Coastguard Worker
1032*8fb009dcSAndroid Build Coastguard Worker CBB contents, sigalgs_cbb;
1033*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_signature_algorithms) ||
1034*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
1035*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &sigalgs_cbb) ||
1036*8fb009dcSAndroid Build Coastguard Worker !tls12_add_verify_sigalgs(hs, &sigalgs_cbb) ||
1037*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out_compressible)) {
1038*8fb009dcSAndroid Build Coastguard Worker return false;
1039*8fb009dcSAndroid Build Coastguard Worker }
1040*8fb009dcSAndroid Build Coastguard Worker
1041*8fb009dcSAndroid Build Coastguard Worker return true;
1042*8fb009dcSAndroid Build Coastguard Worker }
1043*8fb009dcSAndroid Build Coastguard Worker
ext_sigalgs_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1044*8fb009dcSAndroid Build Coastguard Worker static bool ext_sigalgs_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1045*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1046*8fb009dcSAndroid Build Coastguard Worker hs->peer_sigalgs.Reset();
1047*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
1048*8fb009dcSAndroid Build Coastguard Worker return true;
1049*8fb009dcSAndroid Build Coastguard Worker }
1050*8fb009dcSAndroid Build Coastguard Worker
1051*8fb009dcSAndroid Build Coastguard Worker CBS supported_signature_algorithms;
1052*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(contents, &supported_signature_algorithms) ||
1053*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0 ||
1054*8fb009dcSAndroid Build Coastguard Worker !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
1055*8fb009dcSAndroid Build Coastguard Worker return false;
1056*8fb009dcSAndroid Build Coastguard Worker }
1057*8fb009dcSAndroid Build Coastguard Worker
1058*8fb009dcSAndroid Build Coastguard Worker return true;
1059*8fb009dcSAndroid Build Coastguard Worker }
1060*8fb009dcSAndroid Build Coastguard Worker
1061*8fb009dcSAndroid Build Coastguard Worker
1062*8fb009dcSAndroid Build Coastguard Worker // OCSP Stapling.
1063*8fb009dcSAndroid Build Coastguard Worker //
1064*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc6066#section-8
1065*8fb009dcSAndroid Build Coastguard Worker
ext_ocsp_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)1066*8fb009dcSAndroid Build Coastguard Worker static bool ext_ocsp_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1067*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
1068*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
1069*8fb009dcSAndroid Build Coastguard Worker if (!hs->config->ocsp_stapling_enabled) {
1070*8fb009dcSAndroid Build Coastguard Worker return true;
1071*8fb009dcSAndroid Build Coastguard Worker }
1072*8fb009dcSAndroid Build Coastguard Worker
1073*8fb009dcSAndroid Build Coastguard Worker CBB contents;
1074*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_status_request) ||
1075*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
1076*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) ||
1077*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(&contents, 0 /* empty responder ID list */) ||
1078*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(&contents, 0 /* empty request extensions */) ||
1079*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out_compressible)) {
1080*8fb009dcSAndroid Build Coastguard Worker return false;
1081*8fb009dcSAndroid Build Coastguard Worker }
1082*8fb009dcSAndroid Build Coastguard Worker
1083*8fb009dcSAndroid Build Coastguard Worker return true;
1084*8fb009dcSAndroid Build Coastguard Worker }
1085*8fb009dcSAndroid Build Coastguard Worker
ext_ocsp_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1086*8fb009dcSAndroid Build Coastguard Worker static bool ext_ocsp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1087*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1088*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1089*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
1090*8fb009dcSAndroid Build Coastguard Worker return true;
1091*8fb009dcSAndroid Build Coastguard Worker }
1092*8fb009dcSAndroid Build Coastguard Worker
1093*8fb009dcSAndroid Build Coastguard Worker // TLS 1.3 OCSP responses are included in the Certificate extensions.
1094*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
1095*8fb009dcSAndroid Build Coastguard Worker return false;
1096*8fb009dcSAndroid Build Coastguard Worker }
1097*8fb009dcSAndroid Build Coastguard Worker
1098*8fb009dcSAndroid Build Coastguard Worker // OCSP stapling is forbidden on non-certificate ciphers.
1099*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(contents) != 0 ||
1100*8fb009dcSAndroid Build Coastguard Worker !ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
1101*8fb009dcSAndroid Build Coastguard Worker return false;
1102*8fb009dcSAndroid Build Coastguard Worker }
1103*8fb009dcSAndroid Build Coastguard Worker
1104*8fb009dcSAndroid Build Coastguard Worker // Note this does not check for resumption in TLS 1.2. Sending
1105*8fb009dcSAndroid Build Coastguard Worker // status_request here does not make sense, but OpenSSL does so and the
1106*8fb009dcSAndroid Build Coastguard Worker // specification does not say anything. Tolerate it but ignore it.
1107*8fb009dcSAndroid Build Coastguard Worker
1108*8fb009dcSAndroid Build Coastguard Worker hs->certificate_status_expected = true;
1109*8fb009dcSAndroid Build Coastguard Worker return true;
1110*8fb009dcSAndroid Build Coastguard Worker }
1111*8fb009dcSAndroid Build Coastguard Worker
ext_ocsp_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1112*8fb009dcSAndroid Build Coastguard Worker static bool ext_ocsp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1113*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1114*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
1115*8fb009dcSAndroid Build Coastguard Worker return true;
1116*8fb009dcSAndroid Build Coastguard Worker }
1117*8fb009dcSAndroid Build Coastguard Worker
1118*8fb009dcSAndroid Build Coastguard Worker uint8_t status_type;
1119*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8(contents, &status_type)) {
1120*8fb009dcSAndroid Build Coastguard Worker return false;
1121*8fb009dcSAndroid Build Coastguard Worker }
1122*8fb009dcSAndroid Build Coastguard Worker
1123*8fb009dcSAndroid Build Coastguard Worker // We cannot decide whether OCSP stapling will occur yet because the correct
1124*8fb009dcSAndroid Build Coastguard Worker // SSL_CTX might not have been selected.
1125*8fb009dcSAndroid Build Coastguard Worker hs->ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp;
1126*8fb009dcSAndroid Build Coastguard Worker
1127*8fb009dcSAndroid Build Coastguard Worker return true;
1128*8fb009dcSAndroid Build Coastguard Worker }
1129*8fb009dcSAndroid Build Coastguard Worker
ext_ocsp_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)1130*8fb009dcSAndroid Build Coastguard Worker static bool ext_ocsp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
1131*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1132*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
1133*8fb009dcSAndroid Build Coastguard Worker !hs->ocsp_stapling_requested || ssl->s3->session_reused ||
1134*8fb009dcSAndroid Build Coastguard Worker !ssl_cipher_uses_certificate_auth(hs->new_cipher) ||
1135*8fb009dcSAndroid Build Coastguard Worker hs->credential->ocsp_response == nullptr) {
1136*8fb009dcSAndroid Build Coastguard Worker return true;
1137*8fb009dcSAndroid Build Coastguard Worker }
1138*8fb009dcSAndroid Build Coastguard Worker
1139*8fb009dcSAndroid Build Coastguard Worker hs->certificate_status_expected = true;
1140*8fb009dcSAndroid Build Coastguard Worker
1141*8fb009dcSAndroid Build Coastguard Worker return CBB_add_u16(out, TLSEXT_TYPE_status_request) &&
1142*8fb009dcSAndroid Build Coastguard Worker CBB_add_u16(out, 0 /* length */);
1143*8fb009dcSAndroid Build Coastguard Worker }
1144*8fb009dcSAndroid Build Coastguard Worker
1145*8fb009dcSAndroid Build Coastguard Worker
1146*8fb009dcSAndroid Build Coastguard Worker // Next protocol negotiation.
1147*8fb009dcSAndroid Build Coastguard Worker //
1148*8fb009dcSAndroid Build Coastguard Worker // https://htmlpreview.github.io/?https://github.com/agl/technotes/blob/master/nextprotoneg.html
1149*8fb009dcSAndroid Build Coastguard Worker
ext_npn_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)1150*8fb009dcSAndroid Build Coastguard Worker static bool ext_npn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1151*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
1152*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
1153*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
1154*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->next_proto_select_cb == NULL ||
1155*8fb009dcSAndroid Build Coastguard Worker // Do not allow NPN to change on renegotiation.
1156*8fb009dcSAndroid Build Coastguard Worker ssl->s3->initial_handshake_complete ||
1157*8fb009dcSAndroid Build Coastguard Worker // NPN is not defined in DTLS or TLS 1.3.
1158*8fb009dcSAndroid Build Coastguard Worker SSL_is_dtls(ssl) || hs->min_version >= TLS1_3_VERSION ||
1159*8fb009dcSAndroid Build Coastguard Worker type == ssl_client_hello_inner) {
1160*8fb009dcSAndroid Build Coastguard Worker return true;
1161*8fb009dcSAndroid Build Coastguard Worker }
1162*8fb009dcSAndroid Build Coastguard Worker
1163*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) ||
1164*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out, 0 /* length */)) {
1165*8fb009dcSAndroid Build Coastguard Worker return false;
1166*8fb009dcSAndroid Build Coastguard Worker }
1167*8fb009dcSAndroid Build Coastguard Worker
1168*8fb009dcSAndroid Build Coastguard Worker return true;
1169*8fb009dcSAndroid Build Coastguard Worker }
1170*8fb009dcSAndroid Build Coastguard Worker
ext_npn_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1171*8fb009dcSAndroid Build Coastguard Worker static bool ext_npn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1172*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1173*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1174*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
1175*8fb009dcSAndroid Build Coastguard Worker return true;
1176*8fb009dcSAndroid Build Coastguard Worker }
1177*8fb009dcSAndroid Build Coastguard Worker
1178*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
1179*8fb009dcSAndroid Build Coastguard Worker return false;
1180*8fb009dcSAndroid Build Coastguard Worker }
1181*8fb009dcSAndroid Build Coastguard Worker
1182*8fb009dcSAndroid Build Coastguard Worker // If any of these are false then we should never have sent the NPN
1183*8fb009dcSAndroid Build Coastguard Worker // extension in the ClientHello and thus this function should never have been
1184*8fb009dcSAndroid Build Coastguard Worker // called.
1185*8fb009dcSAndroid Build Coastguard Worker assert(!ssl->s3->initial_handshake_complete);
1186*8fb009dcSAndroid Build Coastguard Worker assert(!SSL_is_dtls(ssl));
1187*8fb009dcSAndroid Build Coastguard Worker assert(ssl->ctx->next_proto_select_cb != NULL);
1188*8fb009dcSAndroid Build Coastguard Worker
1189*8fb009dcSAndroid Build Coastguard Worker if (!ssl->s3->alpn_selected.empty()) {
1190*8fb009dcSAndroid Build Coastguard Worker // NPN and ALPN may not be negotiated in the same connection.
1191*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1192*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
1193*8fb009dcSAndroid Build Coastguard Worker return false;
1194*8fb009dcSAndroid Build Coastguard Worker }
1195*8fb009dcSAndroid Build Coastguard Worker
1196*8fb009dcSAndroid Build Coastguard Worker const uint8_t *const orig_contents = CBS_data(contents);
1197*8fb009dcSAndroid Build Coastguard Worker const size_t orig_len = CBS_len(contents);
1198*8fb009dcSAndroid Build Coastguard Worker
1199*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(contents) != 0) {
1200*8fb009dcSAndroid Build Coastguard Worker CBS proto;
1201*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(contents, &proto) ||
1202*8fb009dcSAndroid Build Coastguard Worker CBS_len(&proto) == 0) {
1203*8fb009dcSAndroid Build Coastguard Worker return false;
1204*8fb009dcSAndroid Build Coastguard Worker }
1205*8fb009dcSAndroid Build Coastguard Worker }
1206*8fb009dcSAndroid Build Coastguard Worker
1207*8fb009dcSAndroid Build Coastguard Worker // |orig_len| fits in |unsigned| because TLS extensions use 16-bit lengths.
1208*8fb009dcSAndroid Build Coastguard Worker uint8_t *selected;
1209*8fb009dcSAndroid Build Coastguard Worker uint8_t selected_len;
1210*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->next_proto_select_cb(
1211*8fb009dcSAndroid Build Coastguard Worker ssl, &selected, &selected_len, orig_contents,
1212*8fb009dcSAndroid Build Coastguard Worker static_cast<unsigned>(orig_len),
1213*8fb009dcSAndroid Build Coastguard Worker ssl->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK ||
1214*8fb009dcSAndroid Build Coastguard Worker !ssl->s3->next_proto_negotiated.CopyFrom(
1215*8fb009dcSAndroid Build Coastguard Worker MakeConstSpan(selected, selected_len))) {
1216*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
1217*8fb009dcSAndroid Build Coastguard Worker return false;
1218*8fb009dcSAndroid Build Coastguard Worker }
1219*8fb009dcSAndroid Build Coastguard Worker
1220*8fb009dcSAndroid Build Coastguard Worker hs->next_proto_neg_seen = true;
1221*8fb009dcSAndroid Build Coastguard Worker return true;
1222*8fb009dcSAndroid Build Coastguard Worker }
1223*8fb009dcSAndroid Build Coastguard Worker
ext_npn_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1224*8fb009dcSAndroid Build Coastguard Worker static bool ext_npn_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1225*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1226*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1227*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
1228*8fb009dcSAndroid Build Coastguard Worker return true;
1229*8fb009dcSAndroid Build Coastguard Worker }
1230*8fb009dcSAndroid Build Coastguard Worker
1231*8fb009dcSAndroid Build Coastguard Worker if (contents != NULL && CBS_len(contents) != 0) {
1232*8fb009dcSAndroid Build Coastguard Worker return false;
1233*8fb009dcSAndroid Build Coastguard Worker }
1234*8fb009dcSAndroid Build Coastguard Worker
1235*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL ||
1236*8fb009dcSAndroid Build Coastguard Worker ssl->s3->initial_handshake_complete ||
1237*8fb009dcSAndroid Build Coastguard Worker ssl->ctx->next_protos_advertised_cb == NULL ||
1238*8fb009dcSAndroid Build Coastguard Worker SSL_is_dtls(ssl)) {
1239*8fb009dcSAndroid Build Coastguard Worker return true;
1240*8fb009dcSAndroid Build Coastguard Worker }
1241*8fb009dcSAndroid Build Coastguard Worker
1242*8fb009dcSAndroid Build Coastguard Worker hs->next_proto_neg_seen = true;
1243*8fb009dcSAndroid Build Coastguard Worker return true;
1244*8fb009dcSAndroid Build Coastguard Worker }
1245*8fb009dcSAndroid Build Coastguard Worker
ext_npn_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)1246*8fb009dcSAndroid Build Coastguard Worker static bool ext_npn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
1247*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1248*8fb009dcSAndroid Build Coastguard Worker // |next_proto_neg_seen| might have been cleared when an ALPN extension was
1249*8fb009dcSAndroid Build Coastguard Worker // parsed.
1250*8fb009dcSAndroid Build Coastguard Worker if (!hs->next_proto_neg_seen) {
1251*8fb009dcSAndroid Build Coastguard Worker return true;
1252*8fb009dcSAndroid Build Coastguard Worker }
1253*8fb009dcSAndroid Build Coastguard Worker
1254*8fb009dcSAndroid Build Coastguard Worker const uint8_t *npa;
1255*8fb009dcSAndroid Build Coastguard Worker unsigned npa_len;
1256*8fb009dcSAndroid Build Coastguard Worker
1257*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->next_protos_advertised_cb(
1258*8fb009dcSAndroid Build Coastguard Worker ssl, &npa, &npa_len, ssl->ctx->next_protos_advertised_cb_arg) !=
1259*8fb009dcSAndroid Build Coastguard Worker SSL_TLSEXT_ERR_OK) {
1260*8fb009dcSAndroid Build Coastguard Worker hs->next_proto_neg_seen = false;
1261*8fb009dcSAndroid Build Coastguard Worker return true;
1262*8fb009dcSAndroid Build Coastguard Worker }
1263*8fb009dcSAndroid Build Coastguard Worker
1264*8fb009dcSAndroid Build Coastguard Worker CBB contents;
1265*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) ||
1266*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
1267*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&contents, npa, npa_len) ||
1268*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
1269*8fb009dcSAndroid Build Coastguard Worker return false;
1270*8fb009dcSAndroid Build Coastguard Worker }
1271*8fb009dcSAndroid Build Coastguard Worker
1272*8fb009dcSAndroid Build Coastguard Worker return true;
1273*8fb009dcSAndroid Build Coastguard Worker }
1274*8fb009dcSAndroid Build Coastguard Worker
1275*8fb009dcSAndroid Build Coastguard Worker
1276*8fb009dcSAndroid Build Coastguard Worker // Signed certificate timestamps.
1277*8fb009dcSAndroid Build Coastguard Worker //
1278*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc6962#section-3.3.1
1279*8fb009dcSAndroid Build Coastguard Worker
ext_sct_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)1280*8fb009dcSAndroid Build Coastguard Worker static bool ext_sct_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1281*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
1282*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
1283*8fb009dcSAndroid Build Coastguard Worker if (!hs->config->signed_cert_timestamps_enabled) {
1284*8fb009dcSAndroid Build Coastguard Worker return true;
1285*8fb009dcSAndroid Build Coastguard Worker }
1286*8fb009dcSAndroid Build Coastguard Worker
1287*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_certificate_timestamp) ||
1288*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out_compressible, 0 /* length */)) {
1289*8fb009dcSAndroid Build Coastguard Worker return false;
1290*8fb009dcSAndroid Build Coastguard Worker }
1291*8fb009dcSAndroid Build Coastguard Worker
1292*8fb009dcSAndroid Build Coastguard Worker return true;
1293*8fb009dcSAndroid Build Coastguard Worker }
1294*8fb009dcSAndroid Build Coastguard Worker
ext_sct_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1295*8fb009dcSAndroid Build Coastguard Worker static bool ext_sct_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1296*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1297*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1298*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
1299*8fb009dcSAndroid Build Coastguard Worker return true;
1300*8fb009dcSAndroid Build Coastguard Worker }
1301*8fb009dcSAndroid Build Coastguard Worker
1302*8fb009dcSAndroid Build Coastguard Worker // TLS 1.3 SCTs are included in the Certificate extensions.
1303*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
1304*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
1305*8fb009dcSAndroid Build Coastguard Worker return false;
1306*8fb009dcSAndroid Build Coastguard Worker }
1307*8fb009dcSAndroid Build Coastguard Worker
1308*8fb009dcSAndroid Build Coastguard Worker // If this is false then we should never have sent the SCT extension in the
1309*8fb009dcSAndroid Build Coastguard Worker // ClientHello and thus this function should never have been called.
1310*8fb009dcSAndroid Build Coastguard Worker assert(hs->config->signed_cert_timestamps_enabled);
1311*8fb009dcSAndroid Build Coastguard Worker
1312*8fb009dcSAndroid Build Coastguard Worker if (!ssl_is_sct_list_valid(contents)) {
1313*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
1314*8fb009dcSAndroid Build Coastguard Worker return false;
1315*8fb009dcSAndroid Build Coastguard Worker }
1316*8fb009dcSAndroid Build Coastguard Worker
1317*8fb009dcSAndroid Build Coastguard Worker // Session resumption uses the original session information. The extension
1318*8fb009dcSAndroid Build Coastguard Worker // should not be sent on resumption, but RFC 6962 did not make it a
1319*8fb009dcSAndroid Build Coastguard Worker // requirement, so tolerate this.
1320*8fb009dcSAndroid Build Coastguard Worker //
1321*8fb009dcSAndroid Build Coastguard Worker // TODO(davidben): Enforce this anyway.
1322*8fb009dcSAndroid Build Coastguard Worker if (!ssl->s3->session_reused) {
1323*8fb009dcSAndroid Build Coastguard Worker hs->new_session->signed_cert_timestamp_list.reset(
1324*8fb009dcSAndroid Build Coastguard Worker CRYPTO_BUFFER_new_from_CBS(contents, ssl->ctx->pool));
1325*8fb009dcSAndroid Build Coastguard Worker if (hs->new_session->signed_cert_timestamp_list == nullptr) {
1326*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
1327*8fb009dcSAndroid Build Coastguard Worker return false;
1328*8fb009dcSAndroid Build Coastguard Worker }
1329*8fb009dcSAndroid Build Coastguard Worker }
1330*8fb009dcSAndroid Build Coastguard Worker
1331*8fb009dcSAndroid Build Coastguard Worker return true;
1332*8fb009dcSAndroid Build Coastguard Worker }
1333*8fb009dcSAndroid Build Coastguard Worker
ext_sct_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1334*8fb009dcSAndroid Build Coastguard Worker static bool ext_sct_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1335*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1336*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
1337*8fb009dcSAndroid Build Coastguard Worker return true;
1338*8fb009dcSAndroid Build Coastguard Worker }
1339*8fb009dcSAndroid Build Coastguard Worker
1340*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(contents) != 0) {
1341*8fb009dcSAndroid Build Coastguard Worker return false;
1342*8fb009dcSAndroid Build Coastguard Worker }
1343*8fb009dcSAndroid Build Coastguard Worker
1344*8fb009dcSAndroid Build Coastguard Worker hs->scts_requested = true;
1345*8fb009dcSAndroid Build Coastguard Worker return true;
1346*8fb009dcSAndroid Build Coastguard Worker }
1347*8fb009dcSAndroid Build Coastguard Worker
ext_sct_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)1348*8fb009dcSAndroid Build Coastguard Worker static bool ext_sct_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
1349*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1350*8fb009dcSAndroid Build Coastguard Worker assert(hs->scts_requested);
1351*8fb009dcSAndroid Build Coastguard Worker // The extension shouldn't be sent when resuming sessions.
1352*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION || ssl->s3->session_reused ||
1353*8fb009dcSAndroid Build Coastguard Worker !ssl_cipher_uses_certificate_auth(hs->new_cipher) ||
1354*8fb009dcSAndroid Build Coastguard Worker hs->credential->signed_cert_timestamp_list == nullptr) {
1355*8fb009dcSAndroid Build Coastguard Worker return true;
1356*8fb009dcSAndroid Build Coastguard Worker }
1357*8fb009dcSAndroid Build Coastguard Worker
1358*8fb009dcSAndroid Build Coastguard Worker CBB contents;
1359*8fb009dcSAndroid Build Coastguard Worker return CBB_add_u16(out, TLSEXT_TYPE_certificate_timestamp) &&
1360*8fb009dcSAndroid Build Coastguard Worker CBB_add_u16_length_prefixed(out, &contents) &&
1361*8fb009dcSAndroid Build Coastguard Worker CBB_add_bytes(&contents,
1362*8fb009dcSAndroid Build Coastguard Worker CRYPTO_BUFFER_data(
1363*8fb009dcSAndroid Build Coastguard Worker hs->credential->signed_cert_timestamp_list.get()),
1364*8fb009dcSAndroid Build Coastguard Worker CRYPTO_BUFFER_len(
1365*8fb009dcSAndroid Build Coastguard Worker hs->credential->signed_cert_timestamp_list.get())) &&
1366*8fb009dcSAndroid Build Coastguard Worker CBB_flush(out);
1367*8fb009dcSAndroid Build Coastguard Worker }
1368*8fb009dcSAndroid Build Coastguard Worker
1369*8fb009dcSAndroid Build Coastguard Worker
1370*8fb009dcSAndroid Build Coastguard Worker // Application-level Protocol Negotiation.
1371*8fb009dcSAndroid Build Coastguard Worker //
1372*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc7301
1373*8fb009dcSAndroid Build Coastguard Worker
ext_alpn_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)1374*8fb009dcSAndroid Build Coastguard Worker static bool ext_alpn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1375*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
1376*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
1377*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
1378*8fb009dcSAndroid Build Coastguard Worker if (hs->config->alpn_client_proto_list.empty() && ssl->quic_method) {
1379*8fb009dcSAndroid Build Coastguard Worker // ALPN MUST be used with QUIC.
1380*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
1381*8fb009dcSAndroid Build Coastguard Worker return false;
1382*8fb009dcSAndroid Build Coastguard Worker }
1383*8fb009dcSAndroid Build Coastguard Worker
1384*8fb009dcSAndroid Build Coastguard Worker if (hs->config->alpn_client_proto_list.empty() ||
1385*8fb009dcSAndroid Build Coastguard Worker ssl->s3->initial_handshake_complete) {
1386*8fb009dcSAndroid Build Coastguard Worker return true;
1387*8fb009dcSAndroid Build Coastguard Worker }
1388*8fb009dcSAndroid Build Coastguard Worker
1389*8fb009dcSAndroid Build Coastguard Worker CBB contents, proto_list;
1390*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible,
1391*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_application_layer_protocol_negotiation) ||
1392*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
1393*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &proto_list) ||
1394*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&proto_list, hs->config->alpn_client_proto_list.data(),
1395*8fb009dcSAndroid Build Coastguard Worker hs->config->alpn_client_proto_list.size()) ||
1396*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out_compressible)) {
1397*8fb009dcSAndroid Build Coastguard Worker return false;
1398*8fb009dcSAndroid Build Coastguard Worker }
1399*8fb009dcSAndroid Build Coastguard Worker
1400*8fb009dcSAndroid Build Coastguard Worker return true;
1401*8fb009dcSAndroid Build Coastguard Worker }
1402*8fb009dcSAndroid Build Coastguard Worker
ext_alpn_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1403*8fb009dcSAndroid Build Coastguard Worker static bool ext_alpn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1404*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1405*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1406*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
1407*8fb009dcSAndroid Build Coastguard Worker if (ssl->quic_method) {
1408*8fb009dcSAndroid Build Coastguard Worker // ALPN is required when QUIC is used.
1409*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
1410*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1411*8fb009dcSAndroid Build Coastguard Worker return false;
1412*8fb009dcSAndroid Build Coastguard Worker }
1413*8fb009dcSAndroid Build Coastguard Worker return true;
1414*8fb009dcSAndroid Build Coastguard Worker }
1415*8fb009dcSAndroid Build Coastguard Worker
1416*8fb009dcSAndroid Build Coastguard Worker assert(!ssl->s3->initial_handshake_complete);
1417*8fb009dcSAndroid Build Coastguard Worker assert(!hs->config->alpn_client_proto_list.empty());
1418*8fb009dcSAndroid Build Coastguard Worker
1419*8fb009dcSAndroid Build Coastguard Worker if (hs->next_proto_neg_seen) {
1420*8fb009dcSAndroid Build Coastguard Worker // NPN and ALPN may not be negotiated in the same connection.
1421*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1422*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
1423*8fb009dcSAndroid Build Coastguard Worker return false;
1424*8fb009dcSAndroid Build Coastguard Worker }
1425*8fb009dcSAndroid Build Coastguard Worker
1426*8fb009dcSAndroid Build Coastguard Worker // The extension data consists of a ProtocolNameList which must have
1427*8fb009dcSAndroid Build Coastguard Worker // exactly one ProtocolName. Each of these is length-prefixed.
1428*8fb009dcSAndroid Build Coastguard Worker CBS protocol_name_list, protocol_name;
1429*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(contents, &protocol_name_list) ||
1430*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0 ||
1431*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) ||
1432*8fb009dcSAndroid Build Coastguard Worker // Empty protocol names are forbidden.
1433*8fb009dcSAndroid Build Coastguard Worker CBS_len(&protocol_name) == 0 ||
1434*8fb009dcSAndroid Build Coastguard Worker CBS_len(&protocol_name_list) != 0) {
1435*8fb009dcSAndroid Build Coastguard Worker return false;
1436*8fb009dcSAndroid Build Coastguard Worker }
1437*8fb009dcSAndroid Build Coastguard Worker
1438*8fb009dcSAndroid Build Coastguard Worker if (!ssl_is_alpn_protocol_allowed(hs, protocol_name)) {
1439*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
1440*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1441*8fb009dcSAndroid Build Coastguard Worker return false;
1442*8fb009dcSAndroid Build Coastguard Worker }
1443*8fb009dcSAndroid Build Coastguard Worker
1444*8fb009dcSAndroid Build Coastguard Worker if (!ssl->s3->alpn_selected.CopyFrom(protocol_name)) {
1445*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
1446*8fb009dcSAndroid Build Coastguard Worker return false;
1447*8fb009dcSAndroid Build Coastguard Worker }
1448*8fb009dcSAndroid Build Coastguard Worker
1449*8fb009dcSAndroid Build Coastguard Worker return true;
1450*8fb009dcSAndroid Build Coastguard Worker }
1451*8fb009dcSAndroid Build Coastguard Worker
ssl_is_valid_alpn_list(Span<const uint8_t> in)1452*8fb009dcSAndroid Build Coastguard Worker bool ssl_is_valid_alpn_list(Span<const uint8_t> in) {
1453*8fb009dcSAndroid Build Coastguard Worker CBS protocol_name_list = in;
1454*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(&protocol_name_list) == 0) {
1455*8fb009dcSAndroid Build Coastguard Worker return false;
1456*8fb009dcSAndroid Build Coastguard Worker }
1457*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&protocol_name_list) > 0) {
1458*8fb009dcSAndroid Build Coastguard Worker CBS protocol_name;
1459*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) ||
1460*8fb009dcSAndroid Build Coastguard Worker // Empty protocol names are forbidden.
1461*8fb009dcSAndroid Build Coastguard Worker CBS_len(&protocol_name) == 0) {
1462*8fb009dcSAndroid Build Coastguard Worker return false;
1463*8fb009dcSAndroid Build Coastguard Worker }
1464*8fb009dcSAndroid Build Coastguard Worker }
1465*8fb009dcSAndroid Build Coastguard Worker return true;
1466*8fb009dcSAndroid Build Coastguard Worker }
1467*8fb009dcSAndroid Build Coastguard Worker
ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE * hs,Span<const uint8_t> protocol)1468*8fb009dcSAndroid Build Coastguard Worker bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs,
1469*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> protocol) {
1470*8fb009dcSAndroid Build Coastguard Worker if (hs->config->alpn_client_proto_list.empty()) {
1471*8fb009dcSAndroid Build Coastguard Worker return false;
1472*8fb009dcSAndroid Build Coastguard Worker }
1473*8fb009dcSAndroid Build Coastguard Worker
1474*8fb009dcSAndroid Build Coastguard Worker if (hs->ssl->ctx->allow_unknown_alpn_protos) {
1475*8fb009dcSAndroid Build Coastguard Worker return true;
1476*8fb009dcSAndroid Build Coastguard Worker }
1477*8fb009dcSAndroid Build Coastguard Worker
1478*8fb009dcSAndroid Build Coastguard Worker // Check that the protocol name is one of the ones we advertised.
1479*8fb009dcSAndroid Build Coastguard Worker return ssl_alpn_list_contains_protocol(hs->config->alpn_client_proto_list,
1480*8fb009dcSAndroid Build Coastguard Worker protocol);
1481*8fb009dcSAndroid Build Coastguard Worker }
1482*8fb009dcSAndroid Build Coastguard Worker
ssl_alpn_list_contains_protocol(Span<const uint8_t> list,Span<const uint8_t> protocol)1483*8fb009dcSAndroid Build Coastguard Worker bool ssl_alpn_list_contains_protocol(Span<const uint8_t> list,
1484*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> protocol) {
1485*8fb009dcSAndroid Build Coastguard Worker CBS cbs = list, candidate;
1486*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&cbs) > 0) {
1487*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(&cbs, &candidate)) {
1488*8fb009dcSAndroid Build Coastguard Worker return false;
1489*8fb009dcSAndroid Build Coastguard Worker }
1490*8fb009dcSAndroid Build Coastguard Worker
1491*8fb009dcSAndroid Build Coastguard Worker if (candidate == protocol) {
1492*8fb009dcSAndroid Build Coastguard Worker return true;
1493*8fb009dcSAndroid Build Coastguard Worker }
1494*8fb009dcSAndroid Build Coastguard Worker }
1495*8fb009dcSAndroid Build Coastguard Worker
1496*8fb009dcSAndroid Build Coastguard Worker return false;
1497*8fb009dcSAndroid Build Coastguard Worker }
1498*8fb009dcSAndroid Build Coastguard Worker
ssl_negotiate_alpn(SSL_HANDSHAKE * hs,uint8_t * out_alert,const SSL_CLIENT_HELLO * client_hello)1499*8fb009dcSAndroid Build Coastguard Worker bool ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1500*8fb009dcSAndroid Build Coastguard Worker const SSL_CLIENT_HELLO *client_hello) {
1501*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1502*8fb009dcSAndroid Build Coastguard Worker CBS contents;
1503*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->alpn_select_cb == NULL ||
1504*8fb009dcSAndroid Build Coastguard Worker !ssl_client_hello_get_extension(
1505*8fb009dcSAndroid Build Coastguard Worker client_hello, &contents,
1506*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_application_layer_protocol_negotiation)) {
1507*8fb009dcSAndroid Build Coastguard Worker if (ssl->quic_method) {
1508*8fb009dcSAndroid Build Coastguard Worker // ALPN is required when QUIC is used.
1509*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
1510*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1511*8fb009dcSAndroid Build Coastguard Worker return false;
1512*8fb009dcSAndroid Build Coastguard Worker }
1513*8fb009dcSAndroid Build Coastguard Worker // Ignore ALPN if not configured or no extension was supplied.
1514*8fb009dcSAndroid Build Coastguard Worker return true;
1515*8fb009dcSAndroid Build Coastguard Worker }
1516*8fb009dcSAndroid Build Coastguard Worker
1517*8fb009dcSAndroid Build Coastguard Worker // ALPN takes precedence over NPN.
1518*8fb009dcSAndroid Build Coastguard Worker hs->next_proto_neg_seen = false;
1519*8fb009dcSAndroid Build Coastguard Worker
1520*8fb009dcSAndroid Build Coastguard Worker CBS protocol_name_list;
1521*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(&contents, &protocol_name_list) ||
1522*8fb009dcSAndroid Build Coastguard Worker CBS_len(&contents) != 0 ||
1523*8fb009dcSAndroid Build Coastguard Worker !ssl_is_valid_alpn_list(protocol_name_list)) {
1524*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
1525*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
1526*8fb009dcSAndroid Build Coastguard Worker return false;
1527*8fb009dcSAndroid Build Coastguard Worker }
1528*8fb009dcSAndroid Build Coastguard Worker
1529*8fb009dcSAndroid Build Coastguard Worker // |protocol_name_list| fits in |unsigned| because TLS extensions use 16-bit
1530*8fb009dcSAndroid Build Coastguard Worker // lengths.
1531*8fb009dcSAndroid Build Coastguard Worker const uint8_t *selected;
1532*8fb009dcSAndroid Build Coastguard Worker uint8_t selected_len;
1533*8fb009dcSAndroid Build Coastguard Worker int ret = ssl->ctx->alpn_select_cb(
1534*8fb009dcSAndroid Build Coastguard Worker ssl, &selected, &selected_len, CBS_data(&protocol_name_list),
1535*8fb009dcSAndroid Build Coastguard Worker static_cast<unsigned>(CBS_len(&protocol_name_list)),
1536*8fb009dcSAndroid Build Coastguard Worker ssl->ctx->alpn_select_cb_arg);
1537*8fb009dcSAndroid Build Coastguard Worker // ALPN is required when QUIC is used.
1538*8fb009dcSAndroid Build Coastguard Worker if (ssl->quic_method &&
1539*8fb009dcSAndroid Build Coastguard Worker (ret == SSL_TLSEXT_ERR_NOACK || ret == SSL_TLSEXT_ERR_ALERT_WARNING)) {
1540*8fb009dcSAndroid Build Coastguard Worker ret = SSL_TLSEXT_ERR_ALERT_FATAL;
1541*8fb009dcSAndroid Build Coastguard Worker }
1542*8fb009dcSAndroid Build Coastguard Worker switch (ret) {
1543*8fb009dcSAndroid Build Coastguard Worker case SSL_TLSEXT_ERR_OK:
1544*8fb009dcSAndroid Build Coastguard Worker if (selected_len == 0) {
1545*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
1546*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
1547*8fb009dcSAndroid Build Coastguard Worker return false;
1548*8fb009dcSAndroid Build Coastguard Worker }
1549*8fb009dcSAndroid Build Coastguard Worker if (!ssl->s3->alpn_selected.CopyFrom(
1550*8fb009dcSAndroid Build Coastguard Worker MakeConstSpan(selected, selected_len))) {
1551*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
1552*8fb009dcSAndroid Build Coastguard Worker return false;
1553*8fb009dcSAndroid Build Coastguard Worker }
1554*8fb009dcSAndroid Build Coastguard Worker break;
1555*8fb009dcSAndroid Build Coastguard Worker case SSL_TLSEXT_ERR_NOACK:
1556*8fb009dcSAndroid Build Coastguard Worker case SSL_TLSEXT_ERR_ALERT_WARNING:
1557*8fb009dcSAndroid Build Coastguard Worker break;
1558*8fb009dcSAndroid Build Coastguard Worker case SSL_TLSEXT_ERR_ALERT_FATAL:
1559*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1560*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
1561*8fb009dcSAndroid Build Coastguard Worker return false;
1562*8fb009dcSAndroid Build Coastguard Worker default:
1563*8fb009dcSAndroid Build Coastguard Worker // Invalid return value.
1564*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
1565*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
1566*8fb009dcSAndroid Build Coastguard Worker return false;
1567*8fb009dcSAndroid Build Coastguard Worker }
1568*8fb009dcSAndroid Build Coastguard Worker
1569*8fb009dcSAndroid Build Coastguard Worker return true;
1570*8fb009dcSAndroid Build Coastguard Worker }
1571*8fb009dcSAndroid Build Coastguard Worker
ext_alpn_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)1572*8fb009dcSAndroid Build Coastguard Worker static bool ext_alpn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
1573*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1574*8fb009dcSAndroid Build Coastguard Worker if (ssl->s3->alpn_selected.empty()) {
1575*8fb009dcSAndroid Build Coastguard Worker return true;
1576*8fb009dcSAndroid Build Coastguard Worker }
1577*8fb009dcSAndroid Build Coastguard Worker
1578*8fb009dcSAndroid Build Coastguard Worker CBB contents, proto_list, proto;
1579*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_application_layer_protocol_negotiation) ||
1580*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
1581*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &proto_list) ||
1582*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8_length_prefixed(&proto_list, &proto) ||
1583*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&proto, ssl->s3->alpn_selected.data(),
1584*8fb009dcSAndroid Build Coastguard Worker ssl->s3->alpn_selected.size()) ||
1585*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
1586*8fb009dcSAndroid Build Coastguard Worker return false;
1587*8fb009dcSAndroid Build Coastguard Worker }
1588*8fb009dcSAndroid Build Coastguard Worker
1589*8fb009dcSAndroid Build Coastguard Worker return true;
1590*8fb009dcSAndroid Build Coastguard Worker }
1591*8fb009dcSAndroid Build Coastguard Worker
1592*8fb009dcSAndroid Build Coastguard Worker
1593*8fb009dcSAndroid Build Coastguard Worker // Channel ID.
1594*8fb009dcSAndroid Build Coastguard Worker //
1595*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/draft-balfanz-tls-channelid-01
1596*8fb009dcSAndroid Build Coastguard Worker
ext_channel_id_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)1597*8fb009dcSAndroid Build Coastguard Worker static bool ext_channel_id_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1598*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
1599*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
1600*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
1601*8fb009dcSAndroid Build Coastguard Worker if (!hs->config->channel_id_private || SSL_is_dtls(ssl) ||
1602*8fb009dcSAndroid Build Coastguard Worker // Don't offer Channel ID in ClientHelloOuter. ClientHelloOuter handshakes
1603*8fb009dcSAndroid Build Coastguard Worker // are not authenticated for the name that can learn the Channel ID.
1604*8fb009dcSAndroid Build Coastguard Worker //
1605*8fb009dcSAndroid Build Coastguard Worker // We could alternatively offer the extension but sign with a random key.
1606*8fb009dcSAndroid Build Coastguard Worker // For other extensions, we try to align |ssl_client_hello_outer| and
1607*8fb009dcSAndroid Build Coastguard Worker // |ssl_client_hello_unencrypted|, to improve the effectiveness of ECH
1608*8fb009dcSAndroid Build Coastguard Worker // GREASE. However, Channel ID is deprecated and unlikely to be used with
1609*8fb009dcSAndroid Build Coastguard Worker // ECH, so do the simplest thing.
1610*8fb009dcSAndroid Build Coastguard Worker type == ssl_client_hello_outer) {
1611*8fb009dcSAndroid Build Coastguard Worker return true;
1612*8fb009dcSAndroid Build Coastguard Worker }
1613*8fb009dcSAndroid Build Coastguard Worker
1614*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) ||
1615*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out, 0 /* length */)) {
1616*8fb009dcSAndroid Build Coastguard Worker return false;
1617*8fb009dcSAndroid Build Coastguard Worker }
1618*8fb009dcSAndroid Build Coastguard Worker
1619*8fb009dcSAndroid Build Coastguard Worker return true;
1620*8fb009dcSAndroid Build Coastguard Worker }
1621*8fb009dcSAndroid Build Coastguard Worker
ext_channel_id_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1622*8fb009dcSAndroid Build Coastguard Worker static bool ext_channel_id_parse_serverhello(SSL_HANDSHAKE *hs,
1623*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
1624*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1625*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
1626*8fb009dcSAndroid Build Coastguard Worker return true;
1627*8fb009dcSAndroid Build Coastguard Worker }
1628*8fb009dcSAndroid Build Coastguard Worker
1629*8fb009dcSAndroid Build Coastguard Worker assert(!SSL_is_dtls(hs->ssl));
1630*8fb009dcSAndroid Build Coastguard Worker assert(hs->config->channel_id_private);
1631*8fb009dcSAndroid Build Coastguard Worker
1632*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(contents) != 0) {
1633*8fb009dcSAndroid Build Coastguard Worker return false;
1634*8fb009dcSAndroid Build Coastguard Worker }
1635*8fb009dcSAndroid Build Coastguard Worker
1636*8fb009dcSAndroid Build Coastguard Worker hs->channel_id_negotiated = true;
1637*8fb009dcSAndroid Build Coastguard Worker return true;
1638*8fb009dcSAndroid Build Coastguard Worker }
1639*8fb009dcSAndroid Build Coastguard Worker
ext_channel_id_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1640*8fb009dcSAndroid Build Coastguard Worker static bool ext_channel_id_parse_clienthello(SSL_HANDSHAKE *hs,
1641*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
1642*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1643*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1644*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL || !hs->config->channel_id_enabled || SSL_is_dtls(ssl)) {
1645*8fb009dcSAndroid Build Coastguard Worker return true;
1646*8fb009dcSAndroid Build Coastguard Worker }
1647*8fb009dcSAndroid Build Coastguard Worker
1648*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(contents) != 0) {
1649*8fb009dcSAndroid Build Coastguard Worker return false;
1650*8fb009dcSAndroid Build Coastguard Worker }
1651*8fb009dcSAndroid Build Coastguard Worker
1652*8fb009dcSAndroid Build Coastguard Worker hs->channel_id_negotiated = true;
1653*8fb009dcSAndroid Build Coastguard Worker return true;
1654*8fb009dcSAndroid Build Coastguard Worker }
1655*8fb009dcSAndroid Build Coastguard Worker
ext_channel_id_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)1656*8fb009dcSAndroid Build Coastguard Worker static bool ext_channel_id_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
1657*8fb009dcSAndroid Build Coastguard Worker if (!hs->channel_id_negotiated) {
1658*8fb009dcSAndroid Build Coastguard Worker return true;
1659*8fb009dcSAndroid Build Coastguard Worker }
1660*8fb009dcSAndroid Build Coastguard Worker
1661*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) ||
1662*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out, 0 /* length */)) {
1663*8fb009dcSAndroid Build Coastguard Worker return false;
1664*8fb009dcSAndroid Build Coastguard Worker }
1665*8fb009dcSAndroid Build Coastguard Worker
1666*8fb009dcSAndroid Build Coastguard Worker return true;
1667*8fb009dcSAndroid Build Coastguard Worker }
1668*8fb009dcSAndroid Build Coastguard Worker
1669*8fb009dcSAndroid Build Coastguard Worker
1670*8fb009dcSAndroid Build Coastguard Worker // Secure Real-time Transport Protocol (SRTP) extension.
1671*8fb009dcSAndroid Build Coastguard Worker //
1672*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc5764
1673*8fb009dcSAndroid Build Coastguard Worker
ext_srtp_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)1674*8fb009dcSAndroid Build Coastguard Worker static bool ext_srtp_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1675*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
1676*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
1677*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
1678*8fb009dcSAndroid Build Coastguard Worker const STACK_OF(SRTP_PROTECTION_PROFILE) *profiles =
1679*8fb009dcSAndroid Build Coastguard Worker SSL_get_srtp_profiles(ssl);
1680*8fb009dcSAndroid Build Coastguard Worker if (profiles == NULL ||
1681*8fb009dcSAndroid Build Coastguard Worker sk_SRTP_PROTECTION_PROFILE_num(profiles) == 0 ||
1682*8fb009dcSAndroid Build Coastguard Worker !SSL_is_dtls(ssl)) {
1683*8fb009dcSAndroid Build Coastguard Worker return true;
1684*8fb009dcSAndroid Build Coastguard Worker }
1685*8fb009dcSAndroid Build Coastguard Worker
1686*8fb009dcSAndroid Build Coastguard Worker CBB contents, profile_ids;
1687*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_srtp) ||
1688*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
1689*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &profile_ids)) {
1690*8fb009dcSAndroid Build Coastguard Worker return false;
1691*8fb009dcSAndroid Build Coastguard Worker }
1692*8fb009dcSAndroid Build Coastguard Worker
1693*8fb009dcSAndroid Build Coastguard Worker for (const SRTP_PROTECTION_PROFILE *profile : profiles) {
1694*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(&profile_ids, profile->id)) {
1695*8fb009dcSAndroid Build Coastguard Worker return false;
1696*8fb009dcSAndroid Build Coastguard Worker }
1697*8fb009dcSAndroid Build Coastguard Worker }
1698*8fb009dcSAndroid Build Coastguard Worker
1699*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u8(&contents, 0 /* empty use_mki value */) ||
1700*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out_compressible)) {
1701*8fb009dcSAndroid Build Coastguard Worker return false;
1702*8fb009dcSAndroid Build Coastguard Worker }
1703*8fb009dcSAndroid Build Coastguard Worker
1704*8fb009dcSAndroid Build Coastguard Worker return true;
1705*8fb009dcSAndroid Build Coastguard Worker }
1706*8fb009dcSAndroid Build Coastguard Worker
ext_srtp_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1707*8fb009dcSAndroid Build Coastguard Worker static bool ext_srtp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1708*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1709*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1710*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
1711*8fb009dcSAndroid Build Coastguard Worker return true;
1712*8fb009dcSAndroid Build Coastguard Worker }
1713*8fb009dcSAndroid Build Coastguard Worker
1714*8fb009dcSAndroid Build Coastguard Worker // The extension consists of a u16-prefixed profile ID list containing a
1715*8fb009dcSAndroid Build Coastguard Worker // single uint16_t profile ID, then followed by a u8-prefixed srtp_mki field.
1716*8fb009dcSAndroid Build Coastguard Worker //
1717*8fb009dcSAndroid Build Coastguard Worker // See https://tools.ietf.org/html/rfc5764#section-4.1.1
1718*8fb009dcSAndroid Build Coastguard Worker assert(SSL_is_dtls(ssl));
1719*8fb009dcSAndroid Build Coastguard Worker CBS profile_ids, srtp_mki;
1720*8fb009dcSAndroid Build Coastguard Worker uint16_t profile_id;
1721*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(contents, &profile_ids) ||
1722*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16(&profile_ids, &profile_id) ||
1723*8fb009dcSAndroid Build Coastguard Worker CBS_len(&profile_ids) != 0 ||
1724*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u8_length_prefixed(contents, &srtp_mki) ||
1725*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0) {
1726*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
1727*8fb009dcSAndroid Build Coastguard Worker return false;
1728*8fb009dcSAndroid Build Coastguard Worker }
1729*8fb009dcSAndroid Build Coastguard Worker
1730*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(&srtp_mki) != 0) {
1731*8fb009dcSAndroid Build Coastguard Worker // Must be no MKI, since we never offer one.
1732*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_MKI_VALUE);
1733*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1734*8fb009dcSAndroid Build Coastguard Worker return false;
1735*8fb009dcSAndroid Build Coastguard Worker }
1736*8fb009dcSAndroid Build Coastguard Worker
1737*8fb009dcSAndroid Build Coastguard Worker // Check to see if the server gave us something we support and offered.
1738*8fb009dcSAndroid Build Coastguard Worker for (const SRTP_PROTECTION_PROFILE *profile : SSL_get_srtp_profiles(ssl)) {
1739*8fb009dcSAndroid Build Coastguard Worker if (profile->id == profile_id) {
1740*8fb009dcSAndroid Build Coastguard Worker ssl->s3->srtp_profile = profile;
1741*8fb009dcSAndroid Build Coastguard Worker return true;
1742*8fb009dcSAndroid Build Coastguard Worker }
1743*8fb009dcSAndroid Build Coastguard Worker }
1744*8fb009dcSAndroid Build Coastguard Worker
1745*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
1746*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1747*8fb009dcSAndroid Build Coastguard Worker return false;
1748*8fb009dcSAndroid Build Coastguard Worker }
1749*8fb009dcSAndroid Build Coastguard Worker
ext_srtp_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1750*8fb009dcSAndroid Build Coastguard Worker static bool ext_srtp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1751*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1752*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1753*8fb009dcSAndroid Build Coastguard Worker // DTLS-SRTP is only defined for DTLS.
1754*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL || !SSL_is_dtls(ssl)) {
1755*8fb009dcSAndroid Build Coastguard Worker return true;
1756*8fb009dcSAndroid Build Coastguard Worker }
1757*8fb009dcSAndroid Build Coastguard Worker
1758*8fb009dcSAndroid Build Coastguard Worker CBS profile_ids, srtp_mki;
1759*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(contents, &profile_ids) ||
1760*8fb009dcSAndroid Build Coastguard Worker CBS_len(&profile_ids) < 2 ||
1761*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u8_length_prefixed(contents, &srtp_mki) ||
1762*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0) {
1763*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
1764*8fb009dcSAndroid Build Coastguard Worker return false;
1765*8fb009dcSAndroid Build Coastguard Worker }
1766*8fb009dcSAndroid Build Coastguard Worker // Discard the MKI value for now.
1767*8fb009dcSAndroid Build Coastguard Worker
1768*8fb009dcSAndroid Build Coastguard Worker const STACK_OF(SRTP_PROTECTION_PROFILE) *server_profiles =
1769*8fb009dcSAndroid Build Coastguard Worker SSL_get_srtp_profiles(ssl);
1770*8fb009dcSAndroid Build Coastguard Worker
1771*8fb009dcSAndroid Build Coastguard Worker // Pick the server's most preferred profile.
1772*8fb009dcSAndroid Build Coastguard Worker for (const SRTP_PROTECTION_PROFILE *server_profile : server_profiles) {
1773*8fb009dcSAndroid Build Coastguard Worker CBS profile_ids_tmp;
1774*8fb009dcSAndroid Build Coastguard Worker CBS_init(&profile_ids_tmp, CBS_data(&profile_ids), CBS_len(&profile_ids));
1775*8fb009dcSAndroid Build Coastguard Worker
1776*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&profile_ids_tmp) > 0) {
1777*8fb009dcSAndroid Build Coastguard Worker uint16_t profile_id;
1778*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(&profile_ids_tmp, &profile_id)) {
1779*8fb009dcSAndroid Build Coastguard Worker return false;
1780*8fb009dcSAndroid Build Coastguard Worker }
1781*8fb009dcSAndroid Build Coastguard Worker
1782*8fb009dcSAndroid Build Coastguard Worker if (server_profile->id == profile_id) {
1783*8fb009dcSAndroid Build Coastguard Worker ssl->s3->srtp_profile = server_profile;
1784*8fb009dcSAndroid Build Coastguard Worker return true;
1785*8fb009dcSAndroid Build Coastguard Worker }
1786*8fb009dcSAndroid Build Coastguard Worker }
1787*8fb009dcSAndroid Build Coastguard Worker }
1788*8fb009dcSAndroid Build Coastguard Worker
1789*8fb009dcSAndroid Build Coastguard Worker return true;
1790*8fb009dcSAndroid Build Coastguard Worker }
1791*8fb009dcSAndroid Build Coastguard Worker
ext_srtp_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)1792*8fb009dcSAndroid Build Coastguard Worker static bool ext_srtp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
1793*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1794*8fb009dcSAndroid Build Coastguard Worker if (ssl->s3->srtp_profile == NULL) {
1795*8fb009dcSAndroid Build Coastguard Worker return true;
1796*8fb009dcSAndroid Build Coastguard Worker }
1797*8fb009dcSAndroid Build Coastguard Worker
1798*8fb009dcSAndroid Build Coastguard Worker assert(SSL_is_dtls(ssl));
1799*8fb009dcSAndroid Build Coastguard Worker CBB contents, profile_ids;
1800*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_srtp) ||
1801*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
1802*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &profile_ids) ||
1803*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(&profile_ids, ssl->s3->srtp_profile->id) ||
1804*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(&contents, 0 /* empty MKI */) ||
1805*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
1806*8fb009dcSAndroid Build Coastguard Worker return false;
1807*8fb009dcSAndroid Build Coastguard Worker }
1808*8fb009dcSAndroid Build Coastguard Worker
1809*8fb009dcSAndroid Build Coastguard Worker return true;
1810*8fb009dcSAndroid Build Coastguard Worker }
1811*8fb009dcSAndroid Build Coastguard Worker
1812*8fb009dcSAndroid Build Coastguard Worker
1813*8fb009dcSAndroid Build Coastguard Worker // EC point formats.
1814*8fb009dcSAndroid Build Coastguard Worker //
1815*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc4492#section-5.1.2
1816*8fb009dcSAndroid Build Coastguard Worker
ext_ec_point_add_extension(const SSL_HANDSHAKE * hs,CBB * out)1817*8fb009dcSAndroid Build Coastguard Worker static bool ext_ec_point_add_extension(const SSL_HANDSHAKE *hs, CBB *out) {
1818*8fb009dcSAndroid Build Coastguard Worker CBB contents, formats;
1819*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_ec_point_formats) ||
1820*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
1821*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8_length_prefixed(&contents, &formats) ||
1822*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(&formats, TLSEXT_ECPOINTFORMAT_uncompressed) ||
1823*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
1824*8fb009dcSAndroid Build Coastguard Worker return false;
1825*8fb009dcSAndroid Build Coastguard Worker }
1826*8fb009dcSAndroid Build Coastguard Worker
1827*8fb009dcSAndroid Build Coastguard Worker return true;
1828*8fb009dcSAndroid Build Coastguard Worker }
1829*8fb009dcSAndroid Build Coastguard Worker
ext_ec_point_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)1830*8fb009dcSAndroid Build Coastguard Worker static bool ext_ec_point_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1831*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
1832*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
1833*8fb009dcSAndroid Build Coastguard Worker // The point format extension is unnecessary in TLS 1.3.
1834*8fb009dcSAndroid Build Coastguard Worker if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner) {
1835*8fb009dcSAndroid Build Coastguard Worker return true;
1836*8fb009dcSAndroid Build Coastguard Worker }
1837*8fb009dcSAndroid Build Coastguard Worker
1838*8fb009dcSAndroid Build Coastguard Worker return ext_ec_point_add_extension(hs, out);
1839*8fb009dcSAndroid Build Coastguard Worker }
1840*8fb009dcSAndroid Build Coastguard Worker
ext_ec_point_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1841*8fb009dcSAndroid Build Coastguard Worker static bool ext_ec_point_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1842*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1843*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
1844*8fb009dcSAndroid Build Coastguard Worker return true;
1845*8fb009dcSAndroid Build Coastguard Worker }
1846*8fb009dcSAndroid Build Coastguard Worker
1847*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
1848*8fb009dcSAndroid Build Coastguard Worker return false;
1849*8fb009dcSAndroid Build Coastguard Worker }
1850*8fb009dcSAndroid Build Coastguard Worker
1851*8fb009dcSAndroid Build Coastguard Worker CBS ec_point_format_list;
1852*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(contents, &ec_point_format_list) ||
1853*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0) {
1854*8fb009dcSAndroid Build Coastguard Worker return false;
1855*8fb009dcSAndroid Build Coastguard Worker }
1856*8fb009dcSAndroid Build Coastguard Worker
1857*8fb009dcSAndroid Build Coastguard Worker // Per RFC 4492, section 5.1.2, implementations MUST support the uncompressed
1858*8fb009dcSAndroid Build Coastguard Worker // point format.
1859*8fb009dcSAndroid Build Coastguard Worker if (OPENSSL_memchr(CBS_data(&ec_point_format_list),
1860*8fb009dcSAndroid Build Coastguard Worker TLSEXT_ECPOINTFORMAT_uncompressed,
1861*8fb009dcSAndroid Build Coastguard Worker CBS_len(&ec_point_format_list)) == NULL) {
1862*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1863*8fb009dcSAndroid Build Coastguard Worker return false;
1864*8fb009dcSAndroid Build Coastguard Worker }
1865*8fb009dcSAndroid Build Coastguard Worker
1866*8fb009dcSAndroid Build Coastguard Worker return true;
1867*8fb009dcSAndroid Build Coastguard Worker }
1868*8fb009dcSAndroid Build Coastguard Worker
ext_ec_point_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1869*8fb009dcSAndroid Build Coastguard Worker static bool ext_ec_point_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1870*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1871*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
1872*8fb009dcSAndroid Build Coastguard Worker return true;
1873*8fb009dcSAndroid Build Coastguard Worker }
1874*8fb009dcSAndroid Build Coastguard Worker
1875*8fb009dcSAndroid Build Coastguard Worker return ext_ec_point_parse_serverhello(hs, out_alert, contents);
1876*8fb009dcSAndroid Build Coastguard Worker }
1877*8fb009dcSAndroid Build Coastguard Worker
ext_ec_point_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)1878*8fb009dcSAndroid Build Coastguard Worker static bool ext_ec_point_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
1879*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
1880*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
1881*8fb009dcSAndroid Build Coastguard Worker return true;
1882*8fb009dcSAndroid Build Coastguard Worker }
1883*8fb009dcSAndroid Build Coastguard Worker
1884*8fb009dcSAndroid Build Coastguard Worker const uint32_t alg_k = hs->new_cipher->algorithm_mkey;
1885*8fb009dcSAndroid Build Coastguard Worker const uint32_t alg_a = hs->new_cipher->algorithm_auth;
1886*8fb009dcSAndroid Build Coastguard Worker const bool using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA);
1887*8fb009dcSAndroid Build Coastguard Worker
1888*8fb009dcSAndroid Build Coastguard Worker if (!using_ecc) {
1889*8fb009dcSAndroid Build Coastguard Worker return true;
1890*8fb009dcSAndroid Build Coastguard Worker }
1891*8fb009dcSAndroid Build Coastguard Worker
1892*8fb009dcSAndroid Build Coastguard Worker return ext_ec_point_add_extension(hs, out);
1893*8fb009dcSAndroid Build Coastguard Worker }
1894*8fb009dcSAndroid Build Coastguard Worker
1895*8fb009dcSAndroid Build Coastguard Worker
1896*8fb009dcSAndroid Build Coastguard Worker // Pre Shared Key
1897*8fb009dcSAndroid Build Coastguard Worker //
1898*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc8446#section-4.2.11
1899*8fb009dcSAndroid Build Coastguard Worker
should_offer_psk(const SSL_HANDSHAKE * hs,ssl_client_hello_type_t type)1900*8fb009dcSAndroid Build Coastguard Worker static bool should_offer_psk(const SSL_HANDSHAKE *hs,
1901*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
1902*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
1903*8fb009dcSAndroid Build Coastguard Worker if (hs->max_version < TLS1_3_VERSION || ssl->session == nullptr ||
1904*8fb009dcSAndroid Build Coastguard Worker ssl_session_protocol_version(ssl->session.get()) < TLS1_3_VERSION ||
1905*8fb009dcSAndroid Build Coastguard Worker // TODO(https://crbug.com/boringssl/275): Should we synthesize a
1906*8fb009dcSAndroid Build Coastguard Worker // placeholder PSK, at least when we offer early data? Otherwise
1907*8fb009dcSAndroid Build Coastguard Worker // ClientHelloOuter will contain an early_data extension without a
1908*8fb009dcSAndroid Build Coastguard Worker // pre_shared_key extension and potentially break the recovery flow.
1909*8fb009dcSAndroid Build Coastguard Worker type == ssl_client_hello_outer) {
1910*8fb009dcSAndroid Build Coastguard Worker return false;
1911*8fb009dcSAndroid Build Coastguard Worker }
1912*8fb009dcSAndroid Build Coastguard Worker
1913*8fb009dcSAndroid Build Coastguard Worker // Per RFC 8446 section 4.1.4, skip offering the session if the selected
1914*8fb009dcSAndroid Build Coastguard Worker // cipher in HelloRetryRequest does not match. This avoids performing the
1915*8fb009dcSAndroid Build Coastguard Worker // transcript hash transformation for multiple hashes.
1916*8fb009dcSAndroid Build Coastguard Worker if (ssl->s3->used_hello_retry_request &&
1917*8fb009dcSAndroid Build Coastguard Worker ssl->session->cipher->algorithm_prf != hs->new_cipher->algorithm_prf) {
1918*8fb009dcSAndroid Build Coastguard Worker return false;
1919*8fb009dcSAndroid Build Coastguard Worker }
1920*8fb009dcSAndroid Build Coastguard Worker
1921*8fb009dcSAndroid Build Coastguard Worker return true;
1922*8fb009dcSAndroid Build Coastguard Worker }
1923*8fb009dcSAndroid Build Coastguard Worker
ext_pre_shared_key_clienthello_length(const SSL_HANDSHAKE * hs,ssl_client_hello_type_t type)1924*8fb009dcSAndroid Build Coastguard Worker static size_t ext_pre_shared_key_clienthello_length(
1925*8fb009dcSAndroid Build Coastguard Worker const SSL_HANDSHAKE *hs, ssl_client_hello_type_t type) {
1926*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
1927*8fb009dcSAndroid Build Coastguard Worker if (!should_offer_psk(hs, type)) {
1928*8fb009dcSAndroid Build Coastguard Worker return 0;
1929*8fb009dcSAndroid Build Coastguard Worker }
1930*8fb009dcSAndroid Build Coastguard Worker
1931*8fb009dcSAndroid Build Coastguard Worker size_t binder_len = EVP_MD_size(ssl_session_get_digest(ssl->session.get()));
1932*8fb009dcSAndroid Build Coastguard Worker return 15 + ssl->session->ticket.size() + binder_len;
1933*8fb009dcSAndroid Build Coastguard Worker }
1934*8fb009dcSAndroid Build Coastguard Worker
ext_pre_shared_key_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,bool * out_needs_binder,ssl_client_hello_type_t type)1935*8fb009dcSAndroid Build Coastguard Worker static bool ext_pre_shared_key_add_clienthello(const SSL_HANDSHAKE *hs,
1936*8fb009dcSAndroid Build Coastguard Worker CBB *out, bool *out_needs_binder,
1937*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
1938*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
1939*8fb009dcSAndroid Build Coastguard Worker *out_needs_binder = false;
1940*8fb009dcSAndroid Build Coastguard Worker if (!should_offer_psk(hs, type)) {
1941*8fb009dcSAndroid Build Coastguard Worker return true;
1942*8fb009dcSAndroid Build Coastguard Worker }
1943*8fb009dcSAndroid Build Coastguard Worker
1944*8fb009dcSAndroid Build Coastguard Worker struct OPENSSL_timeval now;
1945*8fb009dcSAndroid Build Coastguard Worker ssl_get_current_time(ssl, &now);
1946*8fb009dcSAndroid Build Coastguard Worker uint32_t ticket_age = 1000 * (now.tv_sec - ssl->session->time);
1947*8fb009dcSAndroid Build Coastguard Worker uint32_t obfuscated_ticket_age = ticket_age + ssl->session->ticket_age_add;
1948*8fb009dcSAndroid Build Coastguard Worker
1949*8fb009dcSAndroid Build Coastguard Worker // Fill in a placeholder zero binder of the appropriate length. It will be
1950*8fb009dcSAndroid Build Coastguard Worker // computed and filled in later after length prefixes are computed.
1951*8fb009dcSAndroid Build Coastguard Worker size_t binder_len = EVP_MD_size(ssl_session_get_digest(ssl->session.get()));
1952*8fb009dcSAndroid Build Coastguard Worker
1953*8fb009dcSAndroid Build Coastguard Worker CBB contents, identity, ticket, binders, binder;
1954*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) ||
1955*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
1956*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &identity) ||
1957*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&identity, &ticket) ||
1958*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&ticket, ssl->session->ticket.data(),
1959*8fb009dcSAndroid Build Coastguard Worker ssl->session->ticket.size()) ||
1960*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u32(&identity, obfuscated_ticket_age) ||
1961*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &binders) ||
1962*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8_length_prefixed(&binders, &binder) ||
1963*8fb009dcSAndroid Build Coastguard Worker !CBB_add_zeros(&binder, binder_len)) {
1964*8fb009dcSAndroid Build Coastguard Worker return false;
1965*8fb009dcSAndroid Build Coastguard Worker }
1966*8fb009dcSAndroid Build Coastguard Worker
1967*8fb009dcSAndroid Build Coastguard Worker *out_needs_binder = true;
1968*8fb009dcSAndroid Build Coastguard Worker return CBB_flush(out);
1969*8fb009dcSAndroid Build Coastguard Worker }
1970*8fb009dcSAndroid Build Coastguard Worker
ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)1971*8fb009dcSAndroid Build Coastguard Worker bool ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE *hs,
1972*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
1973*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
1974*8fb009dcSAndroid Build Coastguard Worker uint16_t psk_id;
1975*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(contents, &psk_id) ||
1976*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0) {
1977*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
1978*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
1979*8fb009dcSAndroid Build Coastguard Worker return false;
1980*8fb009dcSAndroid Build Coastguard Worker }
1981*8fb009dcSAndroid Build Coastguard Worker
1982*8fb009dcSAndroid Build Coastguard Worker // We only advertise one PSK identity, so the only legal index is zero.
1983*8fb009dcSAndroid Build Coastguard Worker if (psk_id != 0) {
1984*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
1985*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_UNKNOWN_PSK_IDENTITY;
1986*8fb009dcSAndroid Build Coastguard Worker return false;
1987*8fb009dcSAndroid Build Coastguard Worker }
1988*8fb009dcSAndroid Build Coastguard Worker
1989*8fb009dcSAndroid Build Coastguard Worker return true;
1990*8fb009dcSAndroid Build Coastguard Worker }
1991*8fb009dcSAndroid Build Coastguard Worker
ssl_ext_pre_shared_key_parse_clienthello(SSL_HANDSHAKE * hs,CBS * out_ticket,CBS * out_binders,uint32_t * out_obfuscated_ticket_age,uint8_t * out_alert,const SSL_CLIENT_HELLO * client_hello,CBS * contents)1992*8fb009dcSAndroid Build Coastguard Worker bool ssl_ext_pre_shared_key_parse_clienthello(
1993*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE *hs, CBS *out_ticket, CBS *out_binders,
1994*8fb009dcSAndroid Build Coastguard Worker uint32_t *out_obfuscated_ticket_age, uint8_t *out_alert,
1995*8fb009dcSAndroid Build Coastguard Worker const SSL_CLIENT_HELLO *client_hello, CBS *contents) {
1996*8fb009dcSAndroid Build Coastguard Worker // Verify that the pre_shared_key extension is the last extension in
1997*8fb009dcSAndroid Build Coastguard Worker // ClientHello.
1998*8fb009dcSAndroid Build Coastguard Worker if (CBS_data(contents) + CBS_len(contents) !=
1999*8fb009dcSAndroid Build Coastguard Worker client_hello->extensions + client_hello->extensions_len) {
2000*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
2001*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
2002*8fb009dcSAndroid Build Coastguard Worker return false;
2003*8fb009dcSAndroid Build Coastguard Worker }
2004*8fb009dcSAndroid Build Coastguard Worker
2005*8fb009dcSAndroid Build Coastguard Worker // We only process the first PSK identity since we don't support pure PSK.
2006*8fb009dcSAndroid Build Coastguard Worker CBS identities, binders;
2007*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(contents, &identities) ||
2008*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16_length_prefixed(&identities, out_ticket) ||
2009*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u32(&identities, out_obfuscated_ticket_age) ||
2010*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16_length_prefixed(contents, &binders) ||
2011*8fb009dcSAndroid Build Coastguard Worker CBS_len(&binders) == 0 ||
2012*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0) {
2013*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2014*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
2015*8fb009dcSAndroid Build Coastguard Worker return false;
2016*8fb009dcSAndroid Build Coastguard Worker }
2017*8fb009dcSAndroid Build Coastguard Worker
2018*8fb009dcSAndroid Build Coastguard Worker *out_binders = binders;
2019*8fb009dcSAndroid Build Coastguard Worker
2020*8fb009dcSAndroid Build Coastguard Worker // Check the syntax of the remaining identities, but do not process them.
2021*8fb009dcSAndroid Build Coastguard Worker size_t num_identities = 1;
2022*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&identities) != 0) {
2023*8fb009dcSAndroid Build Coastguard Worker CBS unused_ticket;
2024*8fb009dcSAndroid Build Coastguard Worker uint32_t unused_obfuscated_ticket_age;
2025*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(&identities, &unused_ticket) ||
2026*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u32(&identities, &unused_obfuscated_ticket_age)) {
2027*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2028*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
2029*8fb009dcSAndroid Build Coastguard Worker return false;
2030*8fb009dcSAndroid Build Coastguard Worker }
2031*8fb009dcSAndroid Build Coastguard Worker
2032*8fb009dcSAndroid Build Coastguard Worker num_identities++;
2033*8fb009dcSAndroid Build Coastguard Worker }
2034*8fb009dcSAndroid Build Coastguard Worker
2035*8fb009dcSAndroid Build Coastguard Worker // Check the syntax of the binders. The value will be checked later if
2036*8fb009dcSAndroid Build Coastguard Worker // resuming.
2037*8fb009dcSAndroid Build Coastguard Worker size_t num_binders = 0;
2038*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&binders) != 0) {
2039*8fb009dcSAndroid Build Coastguard Worker CBS binder;
2040*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(&binders, &binder)) {
2041*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2042*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
2043*8fb009dcSAndroid Build Coastguard Worker return false;
2044*8fb009dcSAndroid Build Coastguard Worker }
2045*8fb009dcSAndroid Build Coastguard Worker
2046*8fb009dcSAndroid Build Coastguard Worker num_binders++;
2047*8fb009dcSAndroid Build Coastguard Worker }
2048*8fb009dcSAndroid Build Coastguard Worker
2049*8fb009dcSAndroid Build Coastguard Worker if (num_identities != num_binders) {
2050*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_BINDER_COUNT_MISMATCH);
2051*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
2052*8fb009dcSAndroid Build Coastguard Worker return false;
2053*8fb009dcSAndroid Build Coastguard Worker }
2054*8fb009dcSAndroid Build Coastguard Worker
2055*8fb009dcSAndroid Build Coastguard Worker return true;
2056*8fb009dcSAndroid Build Coastguard Worker }
2057*8fb009dcSAndroid Build Coastguard Worker
ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)2058*8fb009dcSAndroid Build Coastguard Worker bool ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
2059*8fb009dcSAndroid Build Coastguard Worker if (!hs->ssl->s3->session_reused) {
2060*8fb009dcSAndroid Build Coastguard Worker return true;
2061*8fb009dcSAndroid Build Coastguard Worker }
2062*8fb009dcSAndroid Build Coastguard Worker
2063*8fb009dcSAndroid Build Coastguard Worker CBB contents;
2064*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) ||
2065*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
2066*8fb009dcSAndroid Build Coastguard Worker // We only consider the first identity for resumption
2067*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(&contents, 0) ||
2068*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
2069*8fb009dcSAndroid Build Coastguard Worker return false;
2070*8fb009dcSAndroid Build Coastguard Worker }
2071*8fb009dcSAndroid Build Coastguard Worker
2072*8fb009dcSAndroid Build Coastguard Worker return true;
2073*8fb009dcSAndroid Build Coastguard Worker }
2074*8fb009dcSAndroid Build Coastguard Worker
2075*8fb009dcSAndroid Build Coastguard Worker
2076*8fb009dcSAndroid Build Coastguard Worker // Pre-Shared Key Exchange Modes
2077*8fb009dcSAndroid Build Coastguard Worker //
2078*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc8446#section-4.2.9
2079*8fb009dcSAndroid Build Coastguard Worker
ext_psk_key_exchange_modes_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2080*8fb009dcSAndroid Build Coastguard Worker static bool ext_psk_key_exchange_modes_add_clienthello(
2081*8fb009dcSAndroid Build Coastguard Worker const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2082*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2083*8fb009dcSAndroid Build Coastguard Worker if (hs->max_version < TLS1_3_VERSION) {
2084*8fb009dcSAndroid Build Coastguard Worker return true;
2085*8fb009dcSAndroid Build Coastguard Worker }
2086*8fb009dcSAndroid Build Coastguard Worker
2087*8fb009dcSAndroid Build Coastguard Worker CBB contents, ke_modes;
2088*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_psk_key_exchange_modes) ||
2089*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
2090*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8_length_prefixed(&contents, &ke_modes) ||
2091*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(&ke_modes, SSL_PSK_DHE_KE)) {
2092*8fb009dcSAndroid Build Coastguard Worker return false;
2093*8fb009dcSAndroid Build Coastguard Worker }
2094*8fb009dcSAndroid Build Coastguard Worker
2095*8fb009dcSAndroid Build Coastguard Worker return CBB_flush(out_compressible);
2096*8fb009dcSAndroid Build Coastguard Worker }
2097*8fb009dcSAndroid Build Coastguard Worker
ext_psk_key_exchange_modes_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2098*8fb009dcSAndroid Build Coastguard Worker static bool ext_psk_key_exchange_modes_parse_clienthello(SSL_HANDSHAKE *hs,
2099*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2100*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
2101*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
2102*8fb009dcSAndroid Build Coastguard Worker return true;
2103*8fb009dcSAndroid Build Coastguard Worker }
2104*8fb009dcSAndroid Build Coastguard Worker
2105*8fb009dcSAndroid Build Coastguard Worker CBS ke_modes;
2106*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(contents, &ke_modes) ||
2107*8fb009dcSAndroid Build Coastguard Worker CBS_len(&ke_modes) == 0 ||
2108*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0) {
2109*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
2110*8fb009dcSAndroid Build Coastguard Worker return false;
2111*8fb009dcSAndroid Build Coastguard Worker }
2112*8fb009dcSAndroid Build Coastguard Worker
2113*8fb009dcSAndroid Build Coastguard Worker // We only support tickets with PSK_DHE_KE.
2114*8fb009dcSAndroid Build Coastguard Worker hs->accept_psk_mode = OPENSSL_memchr(CBS_data(&ke_modes), SSL_PSK_DHE_KE,
2115*8fb009dcSAndroid Build Coastguard Worker CBS_len(&ke_modes)) != NULL;
2116*8fb009dcSAndroid Build Coastguard Worker
2117*8fb009dcSAndroid Build Coastguard Worker return true;
2118*8fb009dcSAndroid Build Coastguard Worker }
2119*8fb009dcSAndroid Build Coastguard Worker
2120*8fb009dcSAndroid Build Coastguard Worker
2121*8fb009dcSAndroid Build Coastguard Worker // Early Data Indication
2122*8fb009dcSAndroid Build Coastguard Worker //
2123*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc8446#section-4.2.10
2124*8fb009dcSAndroid Build Coastguard Worker
ext_early_data_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2125*8fb009dcSAndroid Build Coastguard Worker static bool ext_early_data_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2126*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
2127*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2128*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
2129*8fb009dcSAndroid Build Coastguard Worker // The second ClientHello never offers early data, and we must have already
2130*8fb009dcSAndroid Build Coastguard Worker // filled in |early_data_reason| by this point.
2131*8fb009dcSAndroid Build Coastguard Worker if (ssl->s3->used_hello_retry_request) {
2132*8fb009dcSAndroid Build Coastguard Worker assert(ssl->s3->early_data_reason != ssl_early_data_unknown);
2133*8fb009dcSAndroid Build Coastguard Worker return true;
2134*8fb009dcSAndroid Build Coastguard Worker }
2135*8fb009dcSAndroid Build Coastguard Worker
2136*8fb009dcSAndroid Build Coastguard Worker if (!hs->early_data_offered) {
2137*8fb009dcSAndroid Build Coastguard Worker return true;
2138*8fb009dcSAndroid Build Coastguard Worker }
2139*8fb009dcSAndroid Build Coastguard Worker
2140*8fb009dcSAndroid Build Coastguard Worker // If offering ECH, the extension only applies to ClientHelloInner, but we
2141*8fb009dcSAndroid Build Coastguard Worker // send the extension in both ClientHellos. This ensures that, if the server
2142*8fb009dcSAndroid Build Coastguard Worker // handshakes with ClientHelloOuter, it can skip past early data. See
2143*8fb009dcSAndroid Build Coastguard Worker // draft-ietf-tls-esni-13, section 6.1.
2144*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_early_data) ||
2145*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out_compressible, 0) ||
2146*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out_compressible)) {
2147*8fb009dcSAndroid Build Coastguard Worker return false;
2148*8fb009dcSAndroid Build Coastguard Worker }
2149*8fb009dcSAndroid Build Coastguard Worker
2150*8fb009dcSAndroid Build Coastguard Worker return true;
2151*8fb009dcSAndroid Build Coastguard Worker }
2152*8fb009dcSAndroid Build Coastguard Worker
ext_early_data_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2153*8fb009dcSAndroid Build Coastguard Worker static bool ext_early_data_parse_serverhello(SSL_HANDSHAKE *hs,
2154*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2155*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
2156*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
2157*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
2158*8fb009dcSAndroid Build Coastguard Worker if (hs->early_data_offered && !ssl->s3->used_hello_retry_request) {
2159*8fb009dcSAndroid Build Coastguard Worker ssl->s3->early_data_reason = ssl->s3->session_reused
2160*8fb009dcSAndroid Build Coastguard Worker ? ssl_early_data_peer_declined
2161*8fb009dcSAndroid Build Coastguard Worker : ssl_early_data_session_not_resumed;
2162*8fb009dcSAndroid Build Coastguard Worker } else {
2163*8fb009dcSAndroid Build Coastguard Worker // We already filled in |early_data_reason| when declining to offer 0-RTT
2164*8fb009dcSAndroid Build Coastguard Worker // or handling the implicit HelloRetryRequest reject.
2165*8fb009dcSAndroid Build Coastguard Worker assert(ssl->s3->early_data_reason != ssl_early_data_unknown);
2166*8fb009dcSAndroid Build Coastguard Worker }
2167*8fb009dcSAndroid Build Coastguard Worker return true;
2168*8fb009dcSAndroid Build Coastguard Worker }
2169*8fb009dcSAndroid Build Coastguard Worker
2170*8fb009dcSAndroid Build Coastguard Worker // If we received an HRR, the second ClientHello never offers early data, so
2171*8fb009dcSAndroid Build Coastguard Worker // the extensions logic will automatically reject early data extensions as
2172*8fb009dcSAndroid Build Coastguard Worker // unsolicited. This covered by the ServerAcceptsEarlyDataOnHRR test.
2173*8fb009dcSAndroid Build Coastguard Worker assert(!ssl->s3->used_hello_retry_request);
2174*8fb009dcSAndroid Build Coastguard Worker
2175*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(contents) != 0) {
2176*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
2177*8fb009dcSAndroid Build Coastguard Worker return false;
2178*8fb009dcSAndroid Build Coastguard Worker }
2179*8fb009dcSAndroid Build Coastguard Worker
2180*8fb009dcSAndroid Build Coastguard Worker if (!ssl->s3->session_reused) {
2181*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2182*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
2183*8fb009dcSAndroid Build Coastguard Worker return false;
2184*8fb009dcSAndroid Build Coastguard Worker }
2185*8fb009dcSAndroid Build Coastguard Worker
2186*8fb009dcSAndroid Build Coastguard Worker ssl->s3->early_data_reason = ssl_early_data_accepted;
2187*8fb009dcSAndroid Build Coastguard Worker ssl->s3->early_data_accepted = true;
2188*8fb009dcSAndroid Build Coastguard Worker return true;
2189*8fb009dcSAndroid Build Coastguard Worker }
2190*8fb009dcSAndroid Build Coastguard Worker
ext_early_data_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2191*8fb009dcSAndroid Build Coastguard Worker static bool ext_early_data_parse_clienthello(SSL_HANDSHAKE *hs,
2192*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert, CBS *contents) {
2193*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
2194*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL ||
2195*8fb009dcSAndroid Build Coastguard Worker ssl_protocol_version(ssl) < TLS1_3_VERSION) {
2196*8fb009dcSAndroid Build Coastguard Worker return true;
2197*8fb009dcSAndroid Build Coastguard Worker }
2198*8fb009dcSAndroid Build Coastguard Worker
2199*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(contents) != 0) {
2200*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
2201*8fb009dcSAndroid Build Coastguard Worker return false;
2202*8fb009dcSAndroid Build Coastguard Worker }
2203*8fb009dcSAndroid Build Coastguard Worker
2204*8fb009dcSAndroid Build Coastguard Worker hs->early_data_offered = true;
2205*8fb009dcSAndroid Build Coastguard Worker return true;
2206*8fb009dcSAndroid Build Coastguard Worker }
2207*8fb009dcSAndroid Build Coastguard Worker
ext_early_data_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)2208*8fb009dcSAndroid Build Coastguard Worker static bool ext_early_data_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
2209*8fb009dcSAndroid Build Coastguard Worker if (!hs->ssl->s3->early_data_accepted) {
2210*8fb009dcSAndroid Build Coastguard Worker return true;
2211*8fb009dcSAndroid Build Coastguard Worker }
2212*8fb009dcSAndroid Build Coastguard Worker
2213*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_early_data) ||
2214*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(out, 0) ||
2215*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
2216*8fb009dcSAndroid Build Coastguard Worker return false;
2217*8fb009dcSAndroid Build Coastguard Worker }
2218*8fb009dcSAndroid Build Coastguard Worker
2219*8fb009dcSAndroid Build Coastguard Worker return true;
2220*8fb009dcSAndroid Build Coastguard Worker }
2221*8fb009dcSAndroid Build Coastguard Worker
2222*8fb009dcSAndroid Build Coastguard Worker
2223*8fb009dcSAndroid Build Coastguard Worker // Key Share
2224*8fb009dcSAndroid Build Coastguard Worker //
2225*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc8446#section-4.2.8
2226*8fb009dcSAndroid Build Coastguard Worker
ssl_setup_key_shares(SSL_HANDSHAKE * hs,uint16_t override_group_id)2227*8fb009dcSAndroid Build Coastguard Worker bool ssl_setup_key_shares(SSL_HANDSHAKE *hs, uint16_t override_group_id) {
2228*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
2229*8fb009dcSAndroid Build Coastguard Worker hs->key_shares[0].reset();
2230*8fb009dcSAndroid Build Coastguard Worker hs->key_shares[1].reset();
2231*8fb009dcSAndroid Build Coastguard Worker hs->key_share_bytes.Reset();
2232*8fb009dcSAndroid Build Coastguard Worker
2233*8fb009dcSAndroid Build Coastguard Worker if (hs->max_version < TLS1_3_VERSION) {
2234*8fb009dcSAndroid Build Coastguard Worker return true;
2235*8fb009dcSAndroid Build Coastguard Worker }
2236*8fb009dcSAndroid Build Coastguard Worker
2237*8fb009dcSAndroid Build Coastguard Worker bssl::ScopedCBB cbb;
2238*8fb009dcSAndroid Build Coastguard Worker if (!CBB_init(cbb.get(), 64)) {
2239*8fb009dcSAndroid Build Coastguard Worker return false;
2240*8fb009dcSAndroid Build Coastguard Worker }
2241*8fb009dcSAndroid Build Coastguard Worker
2242*8fb009dcSAndroid Build Coastguard Worker if (override_group_id == 0 && ssl->ctx->grease_enabled) {
2243*8fb009dcSAndroid Build Coastguard Worker // Add a fake group. See RFC 8701.
2244*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(cbb.get(), ssl_get_grease_value(hs, ssl_grease_group)) ||
2245*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(cbb.get(), 1 /* length */) ||
2246*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(cbb.get(), 0 /* one byte key share */)) {
2247*8fb009dcSAndroid Build Coastguard Worker return false;
2248*8fb009dcSAndroid Build Coastguard Worker }
2249*8fb009dcSAndroid Build Coastguard Worker }
2250*8fb009dcSAndroid Build Coastguard Worker
2251*8fb009dcSAndroid Build Coastguard Worker uint16_t group_id = override_group_id;
2252*8fb009dcSAndroid Build Coastguard Worker uint16_t second_group_id = 0;
2253*8fb009dcSAndroid Build Coastguard Worker if (override_group_id == 0) {
2254*8fb009dcSAndroid Build Coastguard Worker // Predict the most preferred group.
2255*8fb009dcSAndroid Build Coastguard Worker Span<const uint16_t> groups = tls1_get_grouplist(hs);
2256*8fb009dcSAndroid Build Coastguard Worker if (groups.empty()) {
2257*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_NO_GROUPS_SPECIFIED);
2258*8fb009dcSAndroid Build Coastguard Worker return false;
2259*8fb009dcSAndroid Build Coastguard Worker }
2260*8fb009dcSAndroid Build Coastguard Worker
2261*8fb009dcSAndroid Build Coastguard Worker group_id = groups[0];
2262*8fb009dcSAndroid Build Coastguard Worker
2263*8fb009dcSAndroid Build Coastguard Worker // We'll try to include one post-quantum and one classical initial key
2264*8fb009dcSAndroid Build Coastguard Worker // share.
2265*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 1; i < groups.size() && second_group_id == 0; i++) {
2266*8fb009dcSAndroid Build Coastguard Worker if (is_post_quantum_group(group_id) != is_post_quantum_group(groups[i])) {
2267*8fb009dcSAndroid Build Coastguard Worker second_group_id = groups[i];
2268*8fb009dcSAndroid Build Coastguard Worker assert(second_group_id != group_id);
2269*8fb009dcSAndroid Build Coastguard Worker }
2270*8fb009dcSAndroid Build Coastguard Worker }
2271*8fb009dcSAndroid Build Coastguard Worker }
2272*8fb009dcSAndroid Build Coastguard Worker
2273*8fb009dcSAndroid Build Coastguard Worker CBB key_exchange;
2274*8fb009dcSAndroid Build Coastguard Worker hs->key_shares[0] = SSLKeyShare::Create(group_id);
2275*8fb009dcSAndroid Build Coastguard Worker if (!hs->key_shares[0] || //
2276*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(cbb.get(), group_id) ||
2277*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) ||
2278*8fb009dcSAndroid Build Coastguard Worker !hs->key_shares[0]->Generate(&key_exchange)) {
2279*8fb009dcSAndroid Build Coastguard Worker return false;
2280*8fb009dcSAndroid Build Coastguard Worker }
2281*8fb009dcSAndroid Build Coastguard Worker
2282*8fb009dcSAndroid Build Coastguard Worker if (second_group_id != 0) {
2283*8fb009dcSAndroid Build Coastguard Worker hs->key_shares[1] = SSLKeyShare::Create(second_group_id);
2284*8fb009dcSAndroid Build Coastguard Worker if (!hs->key_shares[1] || //
2285*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(cbb.get(), second_group_id) ||
2286*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) ||
2287*8fb009dcSAndroid Build Coastguard Worker !hs->key_shares[1]->Generate(&key_exchange)) {
2288*8fb009dcSAndroid Build Coastguard Worker return false;
2289*8fb009dcSAndroid Build Coastguard Worker }
2290*8fb009dcSAndroid Build Coastguard Worker }
2291*8fb009dcSAndroid Build Coastguard Worker
2292*8fb009dcSAndroid Build Coastguard Worker return CBBFinishArray(cbb.get(), &hs->key_share_bytes);
2293*8fb009dcSAndroid Build Coastguard Worker }
2294*8fb009dcSAndroid Build Coastguard Worker
ext_key_share_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2295*8fb009dcSAndroid Build Coastguard Worker static bool ext_key_share_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2296*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
2297*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2298*8fb009dcSAndroid Build Coastguard Worker if (hs->max_version < TLS1_3_VERSION) {
2299*8fb009dcSAndroid Build Coastguard Worker return true;
2300*8fb009dcSAndroid Build Coastguard Worker }
2301*8fb009dcSAndroid Build Coastguard Worker
2302*8fb009dcSAndroid Build Coastguard Worker assert(!hs->key_share_bytes.empty());
2303*8fb009dcSAndroid Build Coastguard Worker CBB contents, kse_bytes;
2304*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_key_share) ||
2305*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
2306*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &kse_bytes) ||
2307*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&kse_bytes, hs->key_share_bytes.data(),
2308*8fb009dcSAndroid Build Coastguard Worker hs->key_share_bytes.size()) ||
2309*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out_compressible)) {
2310*8fb009dcSAndroid Build Coastguard Worker return false;
2311*8fb009dcSAndroid Build Coastguard Worker }
2312*8fb009dcSAndroid Build Coastguard Worker
2313*8fb009dcSAndroid Build Coastguard Worker return true;
2314*8fb009dcSAndroid Build Coastguard Worker }
2315*8fb009dcSAndroid Build Coastguard Worker
ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE * hs,Array<uint8_t> * out_secret,uint8_t * out_alert,CBS * contents)2316*8fb009dcSAndroid Build Coastguard Worker bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
2317*8fb009dcSAndroid Build Coastguard Worker Array<uint8_t> *out_secret,
2318*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert, CBS *contents) {
2319*8fb009dcSAndroid Build Coastguard Worker CBS ciphertext;
2320*8fb009dcSAndroid Build Coastguard Worker uint16_t group_id;
2321*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(contents, &group_id) ||
2322*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16_length_prefixed(contents, &ciphertext) ||
2323*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0) {
2324*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2325*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
2326*8fb009dcSAndroid Build Coastguard Worker return false;
2327*8fb009dcSAndroid Build Coastguard Worker }
2328*8fb009dcSAndroid Build Coastguard Worker
2329*8fb009dcSAndroid Build Coastguard Worker SSLKeyShare *key_share = hs->key_shares[0].get();
2330*8fb009dcSAndroid Build Coastguard Worker if (key_share->GroupID() != group_id) {
2331*8fb009dcSAndroid Build Coastguard Worker if (!hs->key_shares[1] || hs->key_shares[1]->GroupID() != group_id) {
2332*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
2333*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
2334*8fb009dcSAndroid Build Coastguard Worker return false;
2335*8fb009dcSAndroid Build Coastguard Worker }
2336*8fb009dcSAndroid Build Coastguard Worker key_share = hs->key_shares[1].get();
2337*8fb009dcSAndroid Build Coastguard Worker }
2338*8fb009dcSAndroid Build Coastguard Worker
2339*8fb009dcSAndroid Build Coastguard Worker if (!key_share->Decap(out_secret, out_alert, ciphertext)) {
2340*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
2341*8fb009dcSAndroid Build Coastguard Worker return false;
2342*8fb009dcSAndroid Build Coastguard Worker }
2343*8fb009dcSAndroid Build Coastguard Worker
2344*8fb009dcSAndroid Build Coastguard Worker hs->new_session->group_id = group_id;
2345*8fb009dcSAndroid Build Coastguard Worker hs->key_shares[0].reset();
2346*8fb009dcSAndroid Build Coastguard Worker hs->key_shares[1].reset();
2347*8fb009dcSAndroid Build Coastguard Worker return true;
2348*8fb009dcSAndroid Build Coastguard Worker }
2349*8fb009dcSAndroid Build Coastguard Worker
ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE * hs,bool * out_found,Span<const uint8_t> * out_peer_key,uint8_t * out_alert,const SSL_CLIENT_HELLO * client_hello)2350*8fb009dcSAndroid Build Coastguard Worker bool ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found,
2351*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> *out_peer_key,
2352*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2353*8fb009dcSAndroid Build Coastguard Worker const SSL_CLIENT_HELLO *client_hello) {
2354*8fb009dcSAndroid Build Coastguard Worker // We only support connections that include an ECDHE key exchange.
2355*8fb009dcSAndroid Build Coastguard Worker CBS contents;
2356*8fb009dcSAndroid Build Coastguard Worker if (!ssl_client_hello_get_extension(client_hello, &contents,
2357*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_key_share)) {
2358*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
2359*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_MISSING_EXTENSION;
2360*8fb009dcSAndroid Build Coastguard Worker return false;
2361*8fb009dcSAndroid Build Coastguard Worker }
2362*8fb009dcSAndroid Build Coastguard Worker
2363*8fb009dcSAndroid Build Coastguard Worker CBS key_shares;
2364*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(&contents, &key_shares) ||
2365*8fb009dcSAndroid Build Coastguard Worker CBS_len(&contents) != 0) {
2366*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2367*8fb009dcSAndroid Build Coastguard Worker return false;
2368*8fb009dcSAndroid Build Coastguard Worker }
2369*8fb009dcSAndroid Build Coastguard Worker
2370*8fb009dcSAndroid Build Coastguard Worker // Find the corresponding key share.
2371*8fb009dcSAndroid Build Coastguard Worker const uint16_t group_id = hs->new_session->group_id;
2372*8fb009dcSAndroid Build Coastguard Worker CBS peer_key;
2373*8fb009dcSAndroid Build Coastguard Worker CBS_init(&peer_key, nullptr, 0);
2374*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&key_shares) > 0) {
2375*8fb009dcSAndroid Build Coastguard Worker uint16_t id;
2376*8fb009dcSAndroid Build Coastguard Worker CBS peer_key_tmp;
2377*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(&key_shares, &id) ||
2378*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16_length_prefixed(&key_shares, &peer_key_tmp) ||
2379*8fb009dcSAndroid Build Coastguard Worker CBS_len(&peer_key_tmp) == 0) {
2380*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2381*8fb009dcSAndroid Build Coastguard Worker return false;
2382*8fb009dcSAndroid Build Coastguard Worker }
2383*8fb009dcSAndroid Build Coastguard Worker
2384*8fb009dcSAndroid Build Coastguard Worker if (id == group_id) {
2385*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(&peer_key) != 0) {
2386*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_KEY_SHARE);
2387*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_ILLEGAL_PARAMETER;
2388*8fb009dcSAndroid Build Coastguard Worker return false;
2389*8fb009dcSAndroid Build Coastguard Worker }
2390*8fb009dcSAndroid Build Coastguard Worker
2391*8fb009dcSAndroid Build Coastguard Worker peer_key = peer_key_tmp;
2392*8fb009dcSAndroid Build Coastguard Worker // Continue parsing the structure to keep peers honest.
2393*8fb009dcSAndroid Build Coastguard Worker }
2394*8fb009dcSAndroid Build Coastguard Worker }
2395*8fb009dcSAndroid Build Coastguard Worker
2396*8fb009dcSAndroid Build Coastguard Worker if (out_peer_key != nullptr) {
2397*8fb009dcSAndroid Build Coastguard Worker *out_peer_key = peer_key;
2398*8fb009dcSAndroid Build Coastguard Worker }
2399*8fb009dcSAndroid Build Coastguard Worker *out_found = CBS_len(&peer_key) != 0;
2400*8fb009dcSAndroid Build Coastguard Worker return true;
2401*8fb009dcSAndroid Build Coastguard Worker }
2402*8fb009dcSAndroid Build Coastguard Worker
ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)2403*8fb009dcSAndroid Build Coastguard Worker bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
2404*8fb009dcSAndroid Build Coastguard Worker CBB entry, ciphertext;
2405*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
2406*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &entry) ||
2407*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(&entry, hs->new_session->group_id) ||
2408*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&entry, &ciphertext) ||
2409*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&ciphertext, hs->key_share_ciphertext.data(),
2410*8fb009dcSAndroid Build Coastguard Worker hs->key_share_ciphertext.size()) ||
2411*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
2412*8fb009dcSAndroid Build Coastguard Worker return false;
2413*8fb009dcSAndroid Build Coastguard Worker }
2414*8fb009dcSAndroid Build Coastguard Worker return true;
2415*8fb009dcSAndroid Build Coastguard Worker }
2416*8fb009dcSAndroid Build Coastguard Worker
2417*8fb009dcSAndroid Build Coastguard Worker
2418*8fb009dcSAndroid Build Coastguard Worker // Supported Versions
2419*8fb009dcSAndroid Build Coastguard Worker //
2420*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc8446#section-4.2.1
2421*8fb009dcSAndroid Build Coastguard Worker
ext_supported_versions_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2422*8fb009dcSAndroid Build Coastguard Worker static bool ext_supported_versions_add_clienthello(
2423*8fb009dcSAndroid Build Coastguard Worker const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2424*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2425*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
2426*8fb009dcSAndroid Build Coastguard Worker if (hs->max_version <= TLS1_2_VERSION) {
2427*8fb009dcSAndroid Build Coastguard Worker return true;
2428*8fb009dcSAndroid Build Coastguard Worker }
2429*8fb009dcSAndroid Build Coastguard Worker
2430*8fb009dcSAndroid Build Coastguard Worker // supported_versions is compressible in ECH if ClientHelloOuter already
2431*8fb009dcSAndroid Build Coastguard Worker // requires TLS 1.3. Otherwise the extensions differ in the older versions.
2432*8fb009dcSAndroid Build Coastguard Worker if (hs->min_version >= TLS1_3_VERSION) {
2433*8fb009dcSAndroid Build Coastguard Worker out = out_compressible;
2434*8fb009dcSAndroid Build Coastguard Worker }
2435*8fb009dcSAndroid Build Coastguard Worker
2436*8fb009dcSAndroid Build Coastguard Worker CBB contents, versions;
2437*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, TLSEXT_TYPE_supported_versions) ||
2438*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
2439*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8_length_prefixed(&contents, &versions)) {
2440*8fb009dcSAndroid Build Coastguard Worker return false;
2441*8fb009dcSAndroid Build Coastguard Worker }
2442*8fb009dcSAndroid Build Coastguard Worker
2443*8fb009dcSAndroid Build Coastguard Worker // Add a fake version. See RFC 8701.
2444*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->grease_enabled &&
2445*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(&versions, ssl_get_grease_value(hs, ssl_grease_version))) {
2446*8fb009dcSAndroid Build Coastguard Worker return false;
2447*8fb009dcSAndroid Build Coastguard Worker }
2448*8fb009dcSAndroid Build Coastguard Worker
2449*8fb009dcSAndroid Build Coastguard Worker // Encrypted ClientHellos requires TLS 1.3 or later.
2450*8fb009dcSAndroid Build Coastguard Worker uint16_t extra_min_version =
2451*8fb009dcSAndroid Build Coastguard Worker type == ssl_client_hello_inner ? TLS1_3_VERSION : 0;
2452*8fb009dcSAndroid Build Coastguard Worker if (!ssl_add_supported_versions(hs, &versions, extra_min_version) ||
2453*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
2454*8fb009dcSAndroid Build Coastguard Worker return false;
2455*8fb009dcSAndroid Build Coastguard Worker }
2456*8fb009dcSAndroid Build Coastguard Worker
2457*8fb009dcSAndroid Build Coastguard Worker return true;
2458*8fb009dcSAndroid Build Coastguard Worker }
2459*8fb009dcSAndroid Build Coastguard Worker
2460*8fb009dcSAndroid Build Coastguard Worker
2461*8fb009dcSAndroid Build Coastguard Worker // Cookie
2462*8fb009dcSAndroid Build Coastguard Worker //
2463*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc8446#section-4.2.2
2464*8fb009dcSAndroid Build Coastguard Worker
ext_cookie_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2465*8fb009dcSAndroid Build Coastguard Worker static bool ext_cookie_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2466*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
2467*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2468*8fb009dcSAndroid Build Coastguard Worker if (hs->cookie.empty()) {
2469*8fb009dcSAndroid Build Coastguard Worker return true;
2470*8fb009dcSAndroid Build Coastguard Worker }
2471*8fb009dcSAndroid Build Coastguard Worker
2472*8fb009dcSAndroid Build Coastguard Worker CBB contents, cookie;
2473*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_cookie) ||
2474*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
2475*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &cookie) ||
2476*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&cookie, hs->cookie.data(), hs->cookie.size()) ||
2477*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out_compressible)) {
2478*8fb009dcSAndroid Build Coastguard Worker return false;
2479*8fb009dcSAndroid Build Coastguard Worker }
2480*8fb009dcSAndroid Build Coastguard Worker
2481*8fb009dcSAndroid Build Coastguard Worker return true;
2482*8fb009dcSAndroid Build Coastguard Worker }
2483*8fb009dcSAndroid Build Coastguard Worker
2484*8fb009dcSAndroid Build Coastguard Worker
2485*8fb009dcSAndroid Build Coastguard Worker // Supported Groups
2486*8fb009dcSAndroid Build Coastguard Worker //
2487*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc4492#section-5.1.1
2488*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc8446#section-4.2.7
2489*8fb009dcSAndroid Build Coastguard Worker
ext_supported_groups_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2490*8fb009dcSAndroid Build Coastguard Worker static bool ext_supported_groups_add_clienthello(const SSL_HANDSHAKE *hs,
2491*8fb009dcSAndroid Build Coastguard Worker CBB *out,
2492*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
2493*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2494*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
2495*8fb009dcSAndroid Build Coastguard Worker CBB contents, groups_bytes;
2496*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_supported_groups) ||
2497*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
2498*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &groups_bytes)) {
2499*8fb009dcSAndroid Build Coastguard Worker return false;
2500*8fb009dcSAndroid Build Coastguard Worker }
2501*8fb009dcSAndroid Build Coastguard Worker
2502*8fb009dcSAndroid Build Coastguard Worker // Add a fake group. See RFC 8701.
2503*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->grease_enabled &&
2504*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(&groups_bytes,
2505*8fb009dcSAndroid Build Coastguard Worker ssl_get_grease_value(hs, ssl_grease_group))) {
2506*8fb009dcSAndroid Build Coastguard Worker return false;
2507*8fb009dcSAndroid Build Coastguard Worker }
2508*8fb009dcSAndroid Build Coastguard Worker
2509*8fb009dcSAndroid Build Coastguard Worker for (uint16_t group : tls1_get_grouplist(hs)) {
2510*8fb009dcSAndroid Build Coastguard Worker if (is_post_quantum_group(group) &&
2511*8fb009dcSAndroid Build Coastguard Worker hs->max_version < TLS1_3_VERSION) {
2512*8fb009dcSAndroid Build Coastguard Worker continue;
2513*8fb009dcSAndroid Build Coastguard Worker }
2514*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(&groups_bytes, group)) {
2515*8fb009dcSAndroid Build Coastguard Worker return false;
2516*8fb009dcSAndroid Build Coastguard Worker }
2517*8fb009dcSAndroid Build Coastguard Worker }
2518*8fb009dcSAndroid Build Coastguard Worker
2519*8fb009dcSAndroid Build Coastguard Worker return CBB_flush(out_compressible);
2520*8fb009dcSAndroid Build Coastguard Worker }
2521*8fb009dcSAndroid Build Coastguard Worker
ext_supported_groups_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2522*8fb009dcSAndroid Build Coastguard Worker static bool ext_supported_groups_parse_serverhello(SSL_HANDSHAKE *hs,
2523*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2524*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
2525*8fb009dcSAndroid Build Coastguard Worker // This extension is not expected to be echoed by servers in TLS 1.2, but some
2526*8fb009dcSAndroid Build Coastguard Worker // BigIP servers send it nonetheless, so do not enforce this.
2527*8fb009dcSAndroid Build Coastguard Worker return true;
2528*8fb009dcSAndroid Build Coastguard Worker }
2529*8fb009dcSAndroid Build Coastguard Worker
parse_u16_array(const CBS * cbs,Array<uint16_t> * out)2530*8fb009dcSAndroid Build Coastguard Worker static bool parse_u16_array(const CBS *cbs, Array<uint16_t> *out) {
2531*8fb009dcSAndroid Build Coastguard Worker CBS copy = *cbs;
2532*8fb009dcSAndroid Build Coastguard Worker if ((CBS_len(©) & 1) != 0) {
2533*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2534*8fb009dcSAndroid Build Coastguard Worker return false;
2535*8fb009dcSAndroid Build Coastguard Worker }
2536*8fb009dcSAndroid Build Coastguard Worker
2537*8fb009dcSAndroid Build Coastguard Worker Array<uint16_t> ret;
2538*8fb009dcSAndroid Build Coastguard Worker if (!ret.Init(CBS_len(©) / 2)) {
2539*8fb009dcSAndroid Build Coastguard Worker return false;
2540*8fb009dcSAndroid Build Coastguard Worker }
2541*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < ret.size(); i++) {
2542*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(©, &ret[i])) {
2543*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
2544*8fb009dcSAndroid Build Coastguard Worker return false;
2545*8fb009dcSAndroid Build Coastguard Worker }
2546*8fb009dcSAndroid Build Coastguard Worker }
2547*8fb009dcSAndroid Build Coastguard Worker
2548*8fb009dcSAndroid Build Coastguard Worker assert(CBS_len(©) == 0);
2549*8fb009dcSAndroid Build Coastguard Worker *out = std::move(ret);
2550*8fb009dcSAndroid Build Coastguard Worker return true;
2551*8fb009dcSAndroid Build Coastguard Worker }
2552*8fb009dcSAndroid Build Coastguard Worker
ext_supported_groups_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2553*8fb009dcSAndroid Build Coastguard Worker static bool ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs,
2554*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2555*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
2556*8fb009dcSAndroid Build Coastguard Worker if (contents == NULL) {
2557*8fb009dcSAndroid Build Coastguard Worker return true;
2558*8fb009dcSAndroid Build Coastguard Worker }
2559*8fb009dcSAndroid Build Coastguard Worker
2560*8fb009dcSAndroid Build Coastguard Worker CBS supported_group_list;
2561*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) ||
2562*8fb009dcSAndroid Build Coastguard Worker CBS_len(&supported_group_list) == 0 ||
2563*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0 ||
2564*8fb009dcSAndroid Build Coastguard Worker !parse_u16_array(&supported_group_list, &hs->peer_supported_group_list)) {
2565*8fb009dcSAndroid Build Coastguard Worker return false;
2566*8fb009dcSAndroid Build Coastguard Worker }
2567*8fb009dcSAndroid Build Coastguard Worker
2568*8fb009dcSAndroid Build Coastguard Worker return true;
2569*8fb009dcSAndroid Build Coastguard Worker }
2570*8fb009dcSAndroid Build Coastguard Worker
2571*8fb009dcSAndroid Build Coastguard Worker
2572*8fb009dcSAndroid Build Coastguard Worker // QUIC Transport Parameters
2573*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_add_clienthello_impl(const SSL_HANDSHAKE * hs,CBB * out,bool use_legacy_codepoint)2574*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_add_clienthello_impl(
2575*8fb009dcSAndroid Build Coastguard Worker const SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) {
2576*8fb009dcSAndroid Build Coastguard Worker if (hs->config->quic_transport_params.empty() && !hs->ssl->quic_method) {
2577*8fb009dcSAndroid Build Coastguard Worker return true;
2578*8fb009dcSAndroid Build Coastguard Worker }
2579*8fb009dcSAndroid Build Coastguard Worker if (hs->config->quic_transport_params.empty() || !hs->ssl->quic_method) {
2580*8fb009dcSAndroid Build Coastguard Worker // QUIC Transport Parameters must be sent over QUIC, and they must not be
2581*8fb009dcSAndroid Build Coastguard Worker // sent over non-QUIC transports. If transport params are set, then
2582*8fb009dcSAndroid Build Coastguard Worker // SSL(_CTX)_set_quic_method must also be called.
2583*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2584*8fb009dcSAndroid Build Coastguard Worker return false;
2585*8fb009dcSAndroid Build Coastguard Worker }
2586*8fb009dcSAndroid Build Coastguard Worker assert(hs->min_version > TLS1_2_VERSION);
2587*8fb009dcSAndroid Build Coastguard Worker if (use_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2588*8fb009dcSAndroid Build Coastguard Worker // Do nothing, we'll send the other codepoint.
2589*8fb009dcSAndroid Build Coastguard Worker return true;
2590*8fb009dcSAndroid Build Coastguard Worker }
2591*8fb009dcSAndroid Build Coastguard Worker
2592*8fb009dcSAndroid Build Coastguard Worker uint16_t extension_type = TLSEXT_TYPE_quic_transport_parameters;
2593*8fb009dcSAndroid Build Coastguard Worker if (hs->config->quic_use_legacy_codepoint) {
2594*8fb009dcSAndroid Build Coastguard Worker extension_type = TLSEXT_TYPE_quic_transport_parameters_legacy;
2595*8fb009dcSAndroid Build Coastguard Worker }
2596*8fb009dcSAndroid Build Coastguard Worker
2597*8fb009dcSAndroid Build Coastguard Worker CBB contents;
2598*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, extension_type) ||
2599*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
2600*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(),
2601*8fb009dcSAndroid Build Coastguard Worker hs->config->quic_transport_params.size()) ||
2602*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
2603*8fb009dcSAndroid Build Coastguard Worker return false;
2604*8fb009dcSAndroid Build Coastguard Worker }
2605*8fb009dcSAndroid Build Coastguard Worker return true;
2606*8fb009dcSAndroid Build Coastguard Worker }
2607*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2608*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_add_clienthello(
2609*8fb009dcSAndroid Build Coastguard Worker const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2610*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2611*8fb009dcSAndroid Build Coastguard Worker return ext_quic_transport_params_add_clienthello_impl(
2612*8fb009dcSAndroid Build Coastguard Worker hs, out_compressible, /*use_legacy_codepoint=*/false);
2613*8fb009dcSAndroid Build Coastguard Worker }
2614*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_add_clienthello_legacy(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2615*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_add_clienthello_legacy(
2616*8fb009dcSAndroid Build Coastguard Worker const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2617*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2618*8fb009dcSAndroid Build Coastguard Worker return ext_quic_transport_params_add_clienthello_impl(
2619*8fb009dcSAndroid Build Coastguard Worker hs, out_compressible, /*use_legacy_codepoint=*/true);
2620*8fb009dcSAndroid Build Coastguard Worker }
2621*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_parse_serverhello_impl(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents,bool used_legacy_codepoint)2622*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_parse_serverhello_impl(
2623*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents,
2624*8fb009dcSAndroid Build Coastguard Worker bool used_legacy_codepoint) {
2625*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
2626*8fb009dcSAndroid Build Coastguard Worker if (contents == nullptr) {
2627*8fb009dcSAndroid Build Coastguard Worker if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2628*8fb009dcSAndroid Build Coastguard Worker // Silently ignore because we expect the other QUIC codepoint.
2629*8fb009dcSAndroid Build Coastguard Worker return true;
2630*8fb009dcSAndroid Build Coastguard Worker }
2631*8fb009dcSAndroid Build Coastguard Worker if (!ssl->quic_method) {
2632*8fb009dcSAndroid Build Coastguard Worker return true;
2633*8fb009dcSAndroid Build Coastguard Worker }
2634*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_MISSING_EXTENSION;
2635*8fb009dcSAndroid Build Coastguard Worker return false;
2636*8fb009dcSAndroid Build Coastguard Worker }
2637*8fb009dcSAndroid Build Coastguard Worker // The extensions parser will check for unsolicited extensions before
2638*8fb009dcSAndroid Build Coastguard Worker // calling the callback.
2639*8fb009dcSAndroid Build Coastguard Worker assert(ssl->quic_method != nullptr);
2640*8fb009dcSAndroid Build Coastguard Worker assert(ssl_protocol_version(ssl) == TLS1_3_VERSION);
2641*8fb009dcSAndroid Build Coastguard Worker assert(used_legacy_codepoint == hs->config->quic_use_legacy_codepoint);
2642*8fb009dcSAndroid Build Coastguard Worker return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
2643*8fb009dcSAndroid Build Coastguard Worker }
2644*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2645*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_parse_serverhello(SSL_HANDSHAKE *hs,
2646*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2647*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
2648*8fb009dcSAndroid Build Coastguard Worker return ext_quic_transport_params_parse_serverhello_impl(
2649*8fb009dcSAndroid Build Coastguard Worker hs, out_alert, contents, /*used_legacy_codepoint=*/false);
2650*8fb009dcSAndroid Build Coastguard Worker }
2651*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_parse_serverhello_legacy(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2652*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_parse_serverhello_legacy(
2653*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) {
2654*8fb009dcSAndroid Build Coastguard Worker return ext_quic_transport_params_parse_serverhello_impl(
2655*8fb009dcSAndroid Build Coastguard Worker hs, out_alert, contents, /*used_legacy_codepoint=*/true);
2656*8fb009dcSAndroid Build Coastguard Worker }
2657*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_parse_clienthello_impl(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents,bool used_legacy_codepoint)2658*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_parse_clienthello_impl(
2659*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents,
2660*8fb009dcSAndroid Build Coastguard Worker bool used_legacy_codepoint) {
2661*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
2662*8fb009dcSAndroid Build Coastguard Worker if (!contents) {
2663*8fb009dcSAndroid Build Coastguard Worker if (!ssl->quic_method) {
2664*8fb009dcSAndroid Build Coastguard Worker if (hs->config->quic_transport_params.empty()) {
2665*8fb009dcSAndroid Build Coastguard Worker return true;
2666*8fb009dcSAndroid Build Coastguard Worker }
2667*8fb009dcSAndroid Build Coastguard Worker // QUIC transport parameters must not be set if |ssl| is not configured
2668*8fb009dcSAndroid Build Coastguard Worker // for QUIC.
2669*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2670*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
2671*8fb009dcSAndroid Build Coastguard Worker return false;
2672*8fb009dcSAndroid Build Coastguard Worker }
2673*8fb009dcSAndroid Build Coastguard Worker if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2674*8fb009dcSAndroid Build Coastguard Worker // Silently ignore because we expect the other QUIC codepoint.
2675*8fb009dcSAndroid Build Coastguard Worker return true;
2676*8fb009dcSAndroid Build Coastguard Worker }
2677*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_MISSING_EXTENSION;
2678*8fb009dcSAndroid Build Coastguard Worker return false;
2679*8fb009dcSAndroid Build Coastguard Worker }
2680*8fb009dcSAndroid Build Coastguard Worker if (!ssl->quic_method) {
2681*8fb009dcSAndroid Build Coastguard Worker if (used_legacy_codepoint) {
2682*8fb009dcSAndroid Build Coastguard Worker // Ignore the legacy private-use codepoint because that could be sent
2683*8fb009dcSAndroid Build Coastguard Worker // to mean something else than QUIC transport parameters.
2684*8fb009dcSAndroid Build Coastguard Worker return true;
2685*8fb009dcSAndroid Build Coastguard Worker }
2686*8fb009dcSAndroid Build Coastguard Worker // Fail if we received the codepoint registered with IANA for QUIC
2687*8fb009dcSAndroid Build Coastguard Worker // because that is not allowed outside of QUIC.
2688*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2689*8fb009dcSAndroid Build Coastguard Worker return false;
2690*8fb009dcSAndroid Build Coastguard Worker }
2691*8fb009dcSAndroid Build Coastguard Worker assert(ssl_protocol_version(ssl) == TLS1_3_VERSION);
2692*8fb009dcSAndroid Build Coastguard Worker if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2693*8fb009dcSAndroid Build Coastguard Worker // Silently ignore because we expect the other QUIC codepoint.
2694*8fb009dcSAndroid Build Coastguard Worker return true;
2695*8fb009dcSAndroid Build Coastguard Worker }
2696*8fb009dcSAndroid Build Coastguard Worker return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
2697*8fb009dcSAndroid Build Coastguard Worker }
2698*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2699*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_parse_clienthello(SSL_HANDSHAKE *hs,
2700*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2701*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
2702*8fb009dcSAndroid Build Coastguard Worker return ext_quic_transport_params_parse_clienthello_impl(
2703*8fb009dcSAndroid Build Coastguard Worker hs, out_alert, contents, /*used_legacy_codepoint=*/false);
2704*8fb009dcSAndroid Build Coastguard Worker }
2705*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_parse_clienthello_legacy(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2706*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_parse_clienthello_legacy(
2707*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) {
2708*8fb009dcSAndroid Build Coastguard Worker return ext_quic_transport_params_parse_clienthello_impl(
2709*8fb009dcSAndroid Build Coastguard Worker hs, out_alert, contents, /*used_legacy_codepoint=*/true);
2710*8fb009dcSAndroid Build Coastguard Worker }
2711*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_add_serverhello_impl(SSL_HANDSHAKE * hs,CBB * out,bool use_legacy_codepoint)2712*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_add_serverhello_impl(
2713*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) {
2714*8fb009dcSAndroid Build Coastguard Worker if (hs->ssl->quic_method == nullptr && use_legacy_codepoint) {
2715*8fb009dcSAndroid Build Coastguard Worker // Ignore the legacy private-use codepoint because that could be sent
2716*8fb009dcSAndroid Build Coastguard Worker // to mean something else than QUIC transport parameters.
2717*8fb009dcSAndroid Build Coastguard Worker return true;
2718*8fb009dcSAndroid Build Coastguard Worker }
2719*8fb009dcSAndroid Build Coastguard Worker assert(hs->ssl->quic_method != nullptr);
2720*8fb009dcSAndroid Build Coastguard Worker if (hs->config->quic_transport_params.empty()) {
2721*8fb009dcSAndroid Build Coastguard Worker // Transport parameters must be set when using QUIC.
2722*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2723*8fb009dcSAndroid Build Coastguard Worker return false;
2724*8fb009dcSAndroid Build Coastguard Worker }
2725*8fb009dcSAndroid Build Coastguard Worker if (use_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2726*8fb009dcSAndroid Build Coastguard Worker // Do nothing, we'll send the other codepoint.
2727*8fb009dcSAndroid Build Coastguard Worker return true;
2728*8fb009dcSAndroid Build Coastguard Worker }
2729*8fb009dcSAndroid Build Coastguard Worker
2730*8fb009dcSAndroid Build Coastguard Worker uint16_t extension_type = TLSEXT_TYPE_quic_transport_parameters;
2731*8fb009dcSAndroid Build Coastguard Worker if (hs->config->quic_use_legacy_codepoint) {
2732*8fb009dcSAndroid Build Coastguard Worker extension_type = TLSEXT_TYPE_quic_transport_parameters_legacy;
2733*8fb009dcSAndroid Build Coastguard Worker }
2734*8fb009dcSAndroid Build Coastguard Worker
2735*8fb009dcSAndroid Build Coastguard Worker CBB contents;
2736*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, extension_type) ||
2737*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
2738*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(),
2739*8fb009dcSAndroid Build Coastguard Worker hs->config->quic_transport_params.size()) ||
2740*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
2741*8fb009dcSAndroid Build Coastguard Worker return false;
2742*8fb009dcSAndroid Build Coastguard Worker }
2743*8fb009dcSAndroid Build Coastguard Worker
2744*8fb009dcSAndroid Build Coastguard Worker return true;
2745*8fb009dcSAndroid Build Coastguard Worker }
2746*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)2747*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs,
2748*8fb009dcSAndroid Build Coastguard Worker CBB *out) {
2749*8fb009dcSAndroid Build Coastguard Worker return ext_quic_transport_params_add_serverhello_impl(
2750*8fb009dcSAndroid Build Coastguard Worker hs, out, /*use_legacy_codepoint=*/false);
2751*8fb009dcSAndroid Build Coastguard Worker }
2752*8fb009dcSAndroid Build Coastguard Worker
ext_quic_transport_params_add_serverhello_legacy(SSL_HANDSHAKE * hs,CBB * out)2753*8fb009dcSAndroid Build Coastguard Worker static bool ext_quic_transport_params_add_serverhello_legacy(SSL_HANDSHAKE *hs,
2754*8fb009dcSAndroid Build Coastguard Worker CBB *out) {
2755*8fb009dcSAndroid Build Coastguard Worker return ext_quic_transport_params_add_serverhello_impl(
2756*8fb009dcSAndroid Build Coastguard Worker hs, out, /*use_legacy_codepoint=*/true);
2757*8fb009dcSAndroid Build Coastguard Worker }
2758*8fb009dcSAndroid Build Coastguard Worker
2759*8fb009dcSAndroid Build Coastguard Worker // Delegated credentials.
2760*8fb009dcSAndroid Build Coastguard Worker //
2761*8fb009dcSAndroid Build Coastguard Worker // https://www.rfc-editor.org/rfc/rfc9345.html
2762*8fb009dcSAndroid Build Coastguard Worker
ext_delegated_credential_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2763*8fb009dcSAndroid Build Coastguard Worker static bool ext_delegated_credential_add_clienthello(
2764*8fb009dcSAndroid Build Coastguard Worker const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2765*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2766*8fb009dcSAndroid Build Coastguard Worker return true;
2767*8fb009dcSAndroid Build Coastguard Worker }
2768*8fb009dcSAndroid Build Coastguard Worker
ext_delegated_credential_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2769*8fb009dcSAndroid Build Coastguard Worker static bool ext_delegated_credential_parse_clienthello(SSL_HANDSHAKE *hs,
2770*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2771*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
2772*8fb009dcSAndroid Build Coastguard Worker if (contents == nullptr || ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
2773*8fb009dcSAndroid Build Coastguard Worker // Don't use delegated credentials unless we're negotiating TLS 1.3 or
2774*8fb009dcSAndroid Build Coastguard Worker // higher.
2775*8fb009dcSAndroid Build Coastguard Worker return true;
2776*8fb009dcSAndroid Build Coastguard Worker }
2777*8fb009dcSAndroid Build Coastguard Worker
2778*8fb009dcSAndroid Build Coastguard Worker // The contents of the extension are the signature algorithms the client will
2779*8fb009dcSAndroid Build Coastguard Worker // accept for a delegated credential.
2780*8fb009dcSAndroid Build Coastguard Worker CBS sigalg_list;
2781*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(contents, &sigalg_list) ||
2782*8fb009dcSAndroid Build Coastguard Worker CBS_len(&sigalg_list) == 0 ||
2783*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0 ||
2784*8fb009dcSAndroid Build Coastguard Worker !parse_u16_array(&sigalg_list, &hs->peer_delegated_credential_sigalgs)) {
2785*8fb009dcSAndroid Build Coastguard Worker return false;
2786*8fb009dcSAndroid Build Coastguard Worker }
2787*8fb009dcSAndroid Build Coastguard Worker
2788*8fb009dcSAndroid Build Coastguard Worker return true;
2789*8fb009dcSAndroid Build Coastguard Worker }
2790*8fb009dcSAndroid Build Coastguard Worker
2791*8fb009dcSAndroid Build Coastguard Worker // Certificate compression
2792*8fb009dcSAndroid Build Coastguard Worker
cert_compression_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2793*8fb009dcSAndroid Build Coastguard Worker static bool cert_compression_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2794*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
2795*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2796*8fb009dcSAndroid Build Coastguard Worker bool first = true;
2797*8fb009dcSAndroid Build Coastguard Worker CBB contents, algs;
2798*8fb009dcSAndroid Build Coastguard Worker
2799*8fb009dcSAndroid Build Coastguard Worker for (const auto &alg : hs->ssl->ctx->cert_compression_algs) {
2800*8fb009dcSAndroid Build Coastguard Worker if (alg.decompress == nullptr) {
2801*8fb009dcSAndroid Build Coastguard Worker continue;
2802*8fb009dcSAndroid Build Coastguard Worker }
2803*8fb009dcSAndroid Build Coastguard Worker
2804*8fb009dcSAndroid Build Coastguard Worker if (first &&
2805*8fb009dcSAndroid Build Coastguard Worker (!CBB_add_u16(out_compressible, TLSEXT_TYPE_cert_compression) ||
2806*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
2807*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8_length_prefixed(&contents, &algs))) {
2808*8fb009dcSAndroid Build Coastguard Worker return false;
2809*8fb009dcSAndroid Build Coastguard Worker }
2810*8fb009dcSAndroid Build Coastguard Worker first = false;
2811*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(&algs, alg.alg_id)) {
2812*8fb009dcSAndroid Build Coastguard Worker return false;
2813*8fb009dcSAndroid Build Coastguard Worker }
2814*8fb009dcSAndroid Build Coastguard Worker }
2815*8fb009dcSAndroid Build Coastguard Worker
2816*8fb009dcSAndroid Build Coastguard Worker return first || CBB_flush(out_compressible);
2817*8fb009dcSAndroid Build Coastguard Worker }
2818*8fb009dcSAndroid Build Coastguard Worker
cert_compression_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2819*8fb009dcSAndroid Build Coastguard Worker static bool cert_compression_parse_serverhello(SSL_HANDSHAKE *hs,
2820*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2821*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
2822*8fb009dcSAndroid Build Coastguard Worker if (contents == nullptr) {
2823*8fb009dcSAndroid Build Coastguard Worker return true;
2824*8fb009dcSAndroid Build Coastguard Worker }
2825*8fb009dcSAndroid Build Coastguard Worker
2826*8fb009dcSAndroid Build Coastguard Worker // The server may not echo this extension. Any server to client negotiation is
2827*8fb009dcSAndroid Build Coastguard Worker // advertised in the CertificateRequest message.
2828*8fb009dcSAndroid Build Coastguard Worker return false;
2829*8fb009dcSAndroid Build Coastguard Worker }
2830*8fb009dcSAndroid Build Coastguard Worker
cert_compression_parse_clienthello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)2831*8fb009dcSAndroid Build Coastguard Worker static bool cert_compression_parse_clienthello(SSL_HANDSHAKE *hs,
2832*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2833*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
2834*8fb009dcSAndroid Build Coastguard Worker if (contents == nullptr) {
2835*8fb009dcSAndroid Build Coastguard Worker return true;
2836*8fb009dcSAndroid Build Coastguard Worker }
2837*8fb009dcSAndroid Build Coastguard Worker
2838*8fb009dcSAndroid Build Coastguard Worker const SSL_CTX *ctx = hs->ssl->ctx.get();
2839*8fb009dcSAndroid Build Coastguard Worker const size_t num_algs = ctx->cert_compression_algs.size();
2840*8fb009dcSAndroid Build Coastguard Worker
2841*8fb009dcSAndroid Build Coastguard Worker CBS alg_ids;
2842*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(contents, &alg_ids) ||
2843*8fb009dcSAndroid Build Coastguard Worker CBS_len(contents) != 0 ||
2844*8fb009dcSAndroid Build Coastguard Worker CBS_len(&alg_ids) == 0 ||
2845*8fb009dcSAndroid Build Coastguard Worker CBS_len(&alg_ids) % 2 == 1) {
2846*8fb009dcSAndroid Build Coastguard Worker return false;
2847*8fb009dcSAndroid Build Coastguard Worker }
2848*8fb009dcSAndroid Build Coastguard Worker
2849*8fb009dcSAndroid Build Coastguard Worker const size_t num_given_alg_ids = CBS_len(&alg_ids) / 2;
2850*8fb009dcSAndroid Build Coastguard Worker Array<uint16_t> given_alg_ids;
2851*8fb009dcSAndroid Build Coastguard Worker if (!given_alg_ids.Init(num_given_alg_ids)) {
2852*8fb009dcSAndroid Build Coastguard Worker return false;
2853*8fb009dcSAndroid Build Coastguard Worker }
2854*8fb009dcSAndroid Build Coastguard Worker
2855*8fb009dcSAndroid Build Coastguard Worker size_t best_index = num_algs;
2856*8fb009dcSAndroid Build Coastguard Worker size_t given_alg_idx = 0;
2857*8fb009dcSAndroid Build Coastguard Worker
2858*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&alg_ids) > 0) {
2859*8fb009dcSAndroid Build Coastguard Worker uint16_t alg_id;
2860*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(&alg_ids, &alg_id)) {
2861*8fb009dcSAndroid Build Coastguard Worker return false;
2862*8fb009dcSAndroid Build Coastguard Worker }
2863*8fb009dcSAndroid Build Coastguard Worker
2864*8fb009dcSAndroid Build Coastguard Worker given_alg_ids[given_alg_idx++] = alg_id;
2865*8fb009dcSAndroid Build Coastguard Worker
2866*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < num_algs; i++) {
2867*8fb009dcSAndroid Build Coastguard Worker const auto &alg = ctx->cert_compression_algs[i];
2868*8fb009dcSAndroid Build Coastguard Worker if (alg.alg_id == alg_id && alg.compress != nullptr) {
2869*8fb009dcSAndroid Build Coastguard Worker if (i < best_index) {
2870*8fb009dcSAndroid Build Coastguard Worker best_index = i;
2871*8fb009dcSAndroid Build Coastguard Worker }
2872*8fb009dcSAndroid Build Coastguard Worker break;
2873*8fb009dcSAndroid Build Coastguard Worker }
2874*8fb009dcSAndroid Build Coastguard Worker }
2875*8fb009dcSAndroid Build Coastguard Worker }
2876*8fb009dcSAndroid Build Coastguard Worker
2877*8fb009dcSAndroid Build Coastguard Worker qsort(given_alg_ids.data(), given_alg_ids.size(), sizeof(uint16_t),
2878*8fb009dcSAndroid Build Coastguard Worker compare_uint16_t);
2879*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 1; i < num_given_alg_ids; i++) {
2880*8fb009dcSAndroid Build Coastguard Worker if (given_alg_ids[i - 1] == given_alg_ids[i]) {
2881*8fb009dcSAndroid Build Coastguard Worker return false;
2882*8fb009dcSAndroid Build Coastguard Worker }
2883*8fb009dcSAndroid Build Coastguard Worker }
2884*8fb009dcSAndroid Build Coastguard Worker
2885*8fb009dcSAndroid Build Coastguard Worker if (best_index < num_algs &&
2886*8fb009dcSAndroid Build Coastguard Worker ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
2887*8fb009dcSAndroid Build Coastguard Worker hs->cert_compression_negotiated = true;
2888*8fb009dcSAndroid Build Coastguard Worker hs->cert_compression_alg_id = ctx->cert_compression_algs[best_index].alg_id;
2889*8fb009dcSAndroid Build Coastguard Worker }
2890*8fb009dcSAndroid Build Coastguard Worker
2891*8fb009dcSAndroid Build Coastguard Worker return true;
2892*8fb009dcSAndroid Build Coastguard Worker }
2893*8fb009dcSAndroid Build Coastguard Worker
cert_compression_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)2894*8fb009dcSAndroid Build Coastguard Worker static bool cert_compression_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
2895*8fb009dcSAndroid Build Coastguard Worker return true;
2896*8fb009dcSAndroid Build Coastguard Worker }
2897*8fb009dcSAndroid Build Coastguard Worker
2898*8fb009dcSAndroid Build Coastguard Worker // Application-level Protocol Settings
2899*8fb009dcSAndroid Build Coastguard Worker //
2900*8fb009dcSAndroid Build Coastguard Worker // https://tools.ietf.org/html/draft-vvv-tls-alps-01
2901*8fb009dcSAndroid Build Coastguard Worker
ssl_get_local_application_settings(const SSL_HANDSHAKE * hs,Span<const uint8_t> * out_settings,Span<const uint8_t> protocol)2902*8fb009dcSAndroid Build Coastguard Worker bool ssl_get_local_application_settings(const SSL_HANDSHAKE *hs,
2903*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> *out_settings,
2904*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> protocol) {
2905*8fb009dcSAndroid Build Coastguard Worker for (const ALPSConfig &config : hs->config->alps_configs) {
2906*8fb009dcSAndroid Build Coastguard Worker if (protocol == config.protocol) {
2907*8fb009dcSAndroid Build Coastguard Worker *out_settings = config.settings;
2908*8fb009dcSAndroid Build Coastguard Worker return true;
2909*8fb009dcSAndroid Build Coastguard Worker }
2910*8fb009dcSAndroid Build Coastguard Worker }
2911*8fb009dcSAndroid Build Coastguard Worker return false;
2912*8fb009dcSAndroid Build Coastguard Worker }
2913*8fb009dcSAndroid Build Coastguard Worker
ext_alps_add_clienthello_impl(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type,bool use_new_codepoint)2914*8fb009dcSAndroid Build Coastguard Worker static bool ext_alps_add_clienthello_impl(const SSL_HANDSHAKE *hs, CBB *out,
2915*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
2916*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type,
2917*8fb009dcSAndroid Build Coastguard Worker bool use_new_codepoint) {
2918*8fb009dcSAndroid Build Coastguard Worker const SSL *const ssl = hs->ssl;
2919*8fb009dcSAndroid Build Coastguard Worker if (// ALPS requires TLS 1.3.
2920*8fb009dcSAndroid Build Coastguard Worker hs->max_version < TLS1_3_VERSION ||
2921*8fb009dcSAndroid Build Coastguard Worker // Do not offer ALPS without ALPN.
2922*8fb009dcSAndroid Build Coastguard Worker hs->config->alpn_client_proto_list.empty() ||
2923*8fb009dcSAndroid Build Coastguard Worker // Do not offer ALPS if not configured.
2924*8fb009dcSAndroid Build Coastguard Worker hs->config->alps_configs.empty() ||
2925*8fb009dcSAndroid Build Coastguard Worker // Do not offer ALPS on renegotiation handshakes.
2926*8fb009dcSAndroid Build Coastguard Worker ssl->s3->initial_handshake_complete) {
2927*8fb009dcSAndroid Build Coastguard Worker return true;
2928*8fb009dcSAndroid Build Coastguard Worker }
2929*8fb009dcSAndroid Build Coastguard Worker
2930*8fb009dcSAndroid Build Coastguard Worker if (use_new_codepoint != hs->config->alps_use_new_codepoint) {
2931*8fb009dcSAndroid Build Coastguard Worker // Do nothing, we'll send the other codepoint.
2932*8fb009dcSAndroid Build Coastguard Worker return true;
2933*8fb009dcSAndroid Build Coastguard Worker }
2934*8fb009dcSAndroid Build Coastguard Worker
2935*8fb009dcSAndroid Build Coastguard Worker uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
2936*8fb009dcSAndroid Build Coastguard Worker if (hs->config->alps_use_new_codepoint) {
2937*8fb009dcSAndroid Build Coastguard Worker extension_type = TLSEXT_TYPE_application_settings;
2938*8fb009dcSAndroid Build Coastguard Worker }
2939*8fb009dcSAndroid Build Coastguard Worker
2940*8fb009dcSAndroid Build Coastguard Worker CBB contents, proto_list, proto;
2941*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out_compressible, extension_type) ||
2942*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
2943*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&contents, &proto_list)) {
2944*8fb009dcSAndroid Build Coastguard Worker return false;
2945*8fb009dcSAndroid Build Coastguard Worker }
2946*8fb009dcSAndroid Build Coastguard Worker
2947*8fb009dcSAndroid Build Coastguard Worker for (const ALPSConfig &config : hs->config->alps_configs) {
2948*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u8_length_prefixed(&proto_list, &proto) ||
2949*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&proto, config.protocol.data(),
2950*8fb009dcSAndroid Build Coastguard Worker config.protocol.size())) {
2951*8fb009dcSAndroid Build Coastguard Worker return false;
2952*8fb009dcSAndroid Build Coastguard Worker }
2953*8fb009dcSAndroid Build Coastguard Worker }
2954*8fb009dcSAndroid Build Coastguard Worker
2955*8fb009dcSAndroid Build Coastguard Worker return CBB_flush(out_compressible);
2956*8fb009dcSAndroid Build Coastguard Worker }
2957*8fb009dcSAndroid Build Coastguard Worker
ext_alps_add_clienthello(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2958*8fb009dcSAndroid Build Coastguard Worker static bool ext_alps_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2959*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
2960*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2961*8fb009dcSAndroid Build Coastguard Worker return ext_alps_add_clienthello_impl(hs, out, out_compressible, type,
2962*8fb009dcSAndroid Build Coastguard Worker /*use_new_codepoint=*/true);
2963*8fb009dcSAndroid Build Coastguard Worker }
2964*8fb009dcSAndroid Build Coastguard Worker
ext_alps_add_clienthello_old(const SSL_HANDSHAKE * hs,CBB * out,CBB * out_compressible,ssl_client_hello_type_t type)2965*8fb009dcSAndroid Build Coastguard Worker static bool ext_alps_add_clienthello_old(const SSL_HANDSHAKE *hs, CBB *out,
2966*8fb009dcSAndroid Build Coastguard Worker CBB *out_compressible,
2967*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type) {
2968*8fb009dcSAndroid Build Coastguard Worker return ext_alps_add_clienthello_impl(hs, out, out_compressible, type,
2969*8fb009dcSAndroid Build Coastguard Worker /*use_new_codepoint=*/false);
2970*8fb009dcSAndroid Build Coastguard Worker }
2971*8fb009dcSAndroid Build Coastguard Worker
ext_alps_parse_serverhello_impl(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents,bool use_new_codepoint)2972*8fb009dcSAndroid Build Coastguard Worker static bool ext_alps_parse_serverhello_impl(SSL_HANDSHAKE *hs,
2973*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
2974*8fb009dcSAndroid Build Coastguard Worker CBS *contents,
2975*8fb009dcSAndroid Build Coastguard Worker bool use_new_codepoint) {
2976*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
2977*8fb009dcSAndroid Build Coastguard Worker if (contents == nullptr) {
2978*8fb009dcSAndroid Build Coastguard Worker return true;
2979*8fb009dcSAndroid Build Coastguard Worker }
2980*8fb009dcSAndroid Build Coastguard Worker
2981*8fb009dcSAndroid Build Coastguard Worker assert(!ssl->s3->initial_handshake_complete);
2982*8fb009dcSAndroid Build Coastguard Worker assert(!hs->config->alpn_client_proto_list.empty());
2983*8fb009dcSAndroid Build Coastguard Worker assert(!hs->config->alps_configs.empty());
2984*8fb009dcSAndroid Build Coastguard Worker assert(use_new_codepoint == hs->config->alps_use_new_codepoint);
2985*8fb009dcSAndroid Build Coastguard Worker
2986*8fb009dcSAndroid Build Coastguard Worker // ALPS requires TLS 1.3.
2987*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
2988*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2989*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
2990*8fb009dcSAndroid Build Coastguard Worker return false;
2991*8fb009dcSAndroid Build Coastguard Worker }
2992*8fb009dcSAndroid Build Coastguard Worker
2993*8fb009dcSAndroid Build Coastguard Worker // Note extension callbacks may run in any order, so we defer checking
2994*8fb009dcSAndroid Build Coastguard Worker // consistency with ALPN to |ssl_check_serverhello_tlsext|.
2995*8fb009dcSAndroid Build Coastguard Worker if (!hs->new_session->peer_application_settings.CopyFrom(*contents)) {
2996*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
2997*8fb009dcSAndroid Build Coastguard Worker return false;
2998*8fb009dcSAndroid Build Coastguard Worker }
2999*8fb009dcSAndroid Build Coastguard Worker
3000*8fb009dcSAndroid Build Coastguard Worker hs->new_session->has_application_settings = true;
3001*8fb009dcSAndroid Build Coastguard Worker return true;
3002*8fb009dcSAndroid Build Coastguard Worker }
3003*8fb009dcSAndroid Build Coastguard Worker
ext_alps_parse_serverhello(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)3004*8fb009dcSAndroid Build Coastguard Worker static bool ext_alps_parse_serverhello(SSL_HANDSHAKE *hs,
3005*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
3006*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
3007*8fb009dcSAndroid Build Coastguard Worker return ext_alps_parse_serverhello_impl(hs, out_alert, contents,
3008*8fb009dcSAndroid Build Coastguard Worker /*use_new_codepoint=*/true);
3009*8fb009dcSAndroid Build Coastguard Worker }
3010*8fb009dcSAndroid Build Coastguard Worker
ext_alps_parse_serverhello_old(SSL_HANDSHAKE * hs,uint8_t * out_alert,CBS * contents)3011*8fb009dcSAndroid Build Coastguard Worker static bool ext_alps_parse_serverhello_old(SSL_HANDSHAKE *hs,
3012*8fb009dcSAndroid Build Coastguard Worker uint8_t *out_alert,
3013*8fb009dcSAndroid Build Coastguard Worker CBS *contents) {
3014*8fb009dcSAndroid Build Coastguard Worker return ext_alps_parse_serverhello_impl(hs, out_alert, contents,
3015*8fb009dcSAndroid Build Coastguard Worker /*use_new_codepoint=*/false);
3016*8fb009dcSAndroid Build Coastguard Worker }
3017*8fb009dcSAndroid Build Coastguard Worker
ext_alps_add_serverhello_impl(SSL_HANDSHAKE * hs,CBB * out,bool use_new_codepoint)3018*8fb009dcSAndroid Build Coastguard Worker static bool ext_alps_add_serverhello_impl(SSL_HANDSHAKE *hs, CBB *out,
3019*8fb009dcSAndroid Build Coastguard Worker bool use_new_codepoint) {
3020*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
3021*8fb009dcSAndroid Build Coastguard Worker // If early data is accepted, we omit the ALPS extension. It is implicitly
3022*8fb009dcSAndroid Build Coastguard Worker // carried over from the previous connection.
3023*8fb009dcSAndroid Build Coastguard Worker if (hs->new_session == nullptr ||
3024*8fb009dcSAndroid Build Coastguard Worker !hs->new_session->has_application_settings ||
3025*8fb009dcSAndroid Build Coastguard Worker ssl->s3->early_data_accepted) {
3026*8fb009dcSAndroid Build Coastguard Worker return true;
3027*8fb009dcSAndroid Build Coastguard Worker }
3028*8fb009dcSAndroid Build Coastguard Worker
3029*8fb009dcSAndroid Build Coastguard Worker if (use_new_codepoint != hs->config->alps_use_new_codepoint) {
3030*8fb009dcSAndroid Build Coastguard Worker // Do nothing, we'll send the other codepoint.
3031*8fb009dcSAndroid Build Coastguard Worker return true;
3032*8fb009dcSAndroid Build Coastguard Worker }
3033*8fb009dcSAndroid Build Coastguard Worker
3034*8fb009dcSAndroid Build Coastguard Worker uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
3035*8fb009dcSAndroid Build Coastguard Worker if (hs->config->alps_use_new_codepoint) {
3036*8fb009dcSAndroid Build Coastguard Worker extension_type = TLSEXT_TYPE_application_settings;
3037*8fb009dcSAndroid Build Coastguard Worker }
3038*8fb009dcSAndroid Build Coastguard Worker
3039*8fb009dcSAndroid Build Coastguard Worker CBB contents;
3040*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(out, extension_type) ||
3041*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out, &contents) ||
3042*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&contents,
3043*8fb009dcSAndroid Build Coastguard Worker hs->new_session->local_application_settings.data(),
3044*8fb009dcSAndroid Build Coastguard Worker hs->new_session->local_application_settings.size()) ||
3045*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out)) {
3046*8fb009dcSAndroid Build Coastguard Worker return false;
3047*8fb009dcSAndroid Build Coastguard Worker }
3048*8fb009dcSAndroid Build Coastguard Worker
3049*8fb009dcSAndroid Build Coastguard Worker return true;
3050*8fb009dcSAndroid Build Coastguard Worker }
3051*8fb009dcSAndroid Build Coastguard Worker
ext_alps_add_serverhello(SSL_HANDSHAKE * hs,CBB * out)3052*8fb009dcSAndroid Build Coastguard Worker static bool ext_alps_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
3053*8fb009dcSAndroid Build Coastguard Worker return ext_alps_add_serverhello_impl(hs, out, /*use_new_codepoint=*/true);
3054*8fb009dcSAndroid Build Coastguard Worker }
3055*8fb009dcSAndroid Build Coastguard Worker
ext_alps_add_serverhello_old(SSL_HANDSHAKE * hs,CBB * out)3056*8fb009dcSAndroid Build Coastguard Worker static bool ext_alps_add_serverhello_old(SSL_HANDSHAKE *hs, CBB *out) {
3057*8fb009dcSAndroid Build Coastguard Worker return ext_alps_add_serverhello_impl(hs, out, /*use_new_codepoint=*/false);
3058*8fb009dcSAndroid Build Coastguard Worker }
3059*8fb009dcSAndroid Build Coastguard Worker
ssl_negotiate_alps(SSL_HANDSHAKE * hs,uint8_t * out_alert,const SSL_CLIENT_HELLO * client_hello)3060*8fb009dcSAndroid Build Coastguard Worker bool ssl_negotiate_alps(SSL_HANDSHAKE *hs, uint8_t *out_alert,
3061*8fb009dcSAndroid Build Coastguard Worker const SSL_CLIENT_HELLO *client_hello) {
3062*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
3063*8fb009dcSAndroid Build Coastguard Worker if (ssl->s3->alpn_selected.empty()) {
3064*8fb009dcSAndroid Build Coastguard Worker return true;
3065*8fb009dcSAndroid Build Coastguard Worker }
3066*8fb009dcSAndroid Build Coastguard Worker
3067*8fb009dcSAndroid Build Coastguard Worker // If we negotiate ALPN over TLS 1.3, try to negotiate ALPS.
3068*8fb009dcSAndroid Build Coastguard Worker CBS alps_contents;
3069*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> settings;
3070*8fb009dcSAndroid Build Coastguard Worker uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
3071*8fb009dcSAndroid Build Coastguard Worker if (hs->config->alps_use_new_codepoint) {
3072*8fb009dcSAndroid Build Coastguard Worker extension_type = TLSEXT_TYPE_application_settings;
3073*8fb009dcSAndroid Build Coastguard Worker }
3074*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION &&
3075*8fb009dcSAndroid Build Coastguard Worker ssl_get_local_application_settings(hs, &settings,
3076*8fb009dcSAndroid Build Coastguard Worker ssl->s3->alpn_selected) &&
3077*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_get_extension(client_hello, &alps_contents,
3078*8fb009dcSAndroid Build Coastguard Worker extension_type)) {
3079*8fb009dcSAndroid Build Coastguard Worker // Check if the client supports ALPS with the selected ALPN.
3080*8fb009dcSAndroid Build Coastguard Worker bool found = false;
3081*8fb009dcSAndroid Build Coastguard Worker CBS alps_list;
3082*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(&alps_contents, &alps_list) ||
3083*8fb009dcSAndroid Build Coastguard Worker CBS_len(&alps_contents) != 0 ||
3084*8fb009dcSAndroid Build Coastguard Worker CBS_len(&alps_list) == 0) {
3085*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
3086*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
3087*8fb009dcSAndroid Build Coastguard Worker return false;
3088*8fb009dcSAndroid Build Coastguard Worker }
3089*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&alps_list) > 0) {
3090*8fb009dcSAndroid Build Coastguard Worker CBS protocol_name;
3091*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8_length_prefixed(&alps_list, &protocol_name) ||
3092*8fb009dcSAndroid Build Coastguard Worker // Empty protocol names are forbidden.
3093*8fb009dcSAndroid Build Coastguard Worker CBS_len(&protocol_name) == 0) {
3094*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
3095*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
3096*8fb009dcSAndroid Build Coastguard Worker return false;
3097*8fb009dcSAndroid Build Coastguard Worker }
3098*8fb009dcSAndroid Build Coastguard Worker if (protocol_name == MakeConstSpan(ssl->s3->alpn_selected)) {
3099*8fb009dcSAndroid Build Coastguard Worker found = true;
3100*8fb009dcSAndroid Build Coastguard Worker }
3101*8fb009dcSAndroid Build Coastguard Worker }
3102*8fb009dcSAndroid Build Coastguard Worker
3103*8fb009dcSAndroid Build Coastguard Worker // Negotiate ALPS if both client also supports ALPS for this protocol.
3104*8fb009dcSAndroid Build Coastguard Worker if (found) {
3105*8fb009dcSAndroid Build Coastguard Worker hs->new_session->has_application_settings = true;
3106*8fb009dcSAndroid Build Coastguard Worker if (!hs->new_session->local_application_settings.CopyFrom(settings)) {
3107*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_INTERNAL_ERROR;
3108*8fb009dcSAndroid Build Coastguard Worker return false;
3109*8fb009dcSAndroid Build Coastguard Worker }
3110*8fb009dcSAndroid Build Coastguard Worker }
3111*8fb009dcSAndroid Build Coastguard Worker }
3112*8fb009dcSAndroid Build Coastguard Worker
3113*8fb009dcSAndroid Build Coastguard Worker return true;
3114*8fb009dcSAndroid Build Coastguard Worker }
3115*8fb009dcSAndroid Build Coastguard Worker
3116*8fb009dcSAndroid Build Coastguard Worker // kExtensions contains all the supported extensions.
3117*8fb009dcSAndroid Build Coastguard Worker static const struct tls_extension kExtensions[] = {
3118*8fb009dcSAndroid Build Coastguard Worker {
3119*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_server_name,
3120*8fb009dcSAndroid Build Coastguard Worker ext_sni_add_clienthello,
3121*8fb009dcSAndroid Build Coastguard Worker ext_sni_parse_serverhello,
3122*8fb009dcSAndroid Build Coastguard Worker ext_sni_parse_clienthello,
3123*8fb009dcSAndroid Build Coastguard Worker ext_sni_add_serverhello,
3124*8fb009dcSAndroid Build Coastguard Worker },
3125*8fb009dcSAndroid Build Coastguard Worker {
3126*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_encrypted_client_hello,
3127*8fb009dcSAndroid Build Coastguard Worker ext_ech_add_clienthello,
3128*8fb009dcSAndroid Build Coastguard Worker ext_ech_parse_serverhello,
3129*8fb009dcSAndroid Build Coastguard Worker ext_ech_parse_clienthello,
3130*8fb009dcSAndroid Build Coastguard Worker ext_ech_add_serverhello,
3131*8fb009dcSAndroid Build Coastguard Worker },
3132*8fb009dcSAndroid Build Coastguard Worker {
3133*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_extended_master_secret,
3134*8fb009dcSAndroid Build Coastguard Worker ext_ems_add_clienthello,
3135*8fb009dcSAndroid Build Coastguard Worker ext_ems_parse_serverhello,
3136*8fb009dcSAndroid Build Coastguard Worker ext_ems_parse_clienthello,
3137*8fb009dcSAndroid Build Coastguard Worker ext_ems_add_serverhello,
3138*8fb009dcSAndroid Build Coastguard Worker },
3139*8fb009dcSAndroid Build Coastguard Worker {
3140*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_renegotiate,
3141*8fb009dcSAndroid Build Coastguard Worker ext_ri_add_clienthello,
3142*8fb009dcSAndroid Build Coastguard Worker ext_ri_parse_serverhello,
3143*8fb009dcSAndroid Build Coastguard Worker ext_ri_parse_clienthello,
3144*8fb009dcSAndroid Build Coastguard Worker ext_ri_add_serverhello,
3145*8fb009dcSAndroid Build Coastguard Worker },
3146*8fb009dcSAndroid Build Coastguard Worker {
3147*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_supported_groups,
3148*8fb009dcSAndroid Build Coastguard Worker ext_supported_groups_add_clienthello,
3149*8fb009dcSAndroid Build Coastguard Worker ext_supported_groups_parse_serverhello,
3150*8fb009dcSAndroid Build Coastguard Worker ext_supported_groups_parse_clienthello,
3151*8fb009dcSAndroid Build Coastguard Worker dont_add_serverhello,
3152*8fb009dcSAndroid Build Coastguard Worker },
3153*8fb009dcSAndroid Build Coastguard Worker {
3154*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_ec_point_formats,
3155*8fb009dcSAndroid Build Coastguard Worker ext_ec_point_add_clienthello,
3156*8fb009dcSAndroid Build Coastguard Worker ext_ec_point_parse_serverhello,
3157*8fb009dcSAndroid Build Coastguard Worker ext_ec_point_parse_clienthello,
3158*8fb009dcSAndroid Build Coastguard Worker ext_ec_point_add_serverhello,
3159*8fb009dcSAndroid Build Coastguard Worker },
3160*8fb009dcSAndroid Build Coastguard Worker {
3161*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_session_ticket,
3162*8fb009dcSAndroid Build Coastguard Worker ext_ticket_add_clienthello,
3163*8fb009dcSAndroid Build Coastguard Worker ext_ticket_parse_serverhello,
3164*8fb009dcSAndroid Build Coastguard Worker // Ticket extension client parsing is handled in ssl_session.c
3165*8fb009dcSAndroid Build Coastguard Worker ignore_parse_clienthello,
3166*8fb009dcSAndroid Build Coastguard Worker ext_ticket_add_serverhello,
3167*8fb009dcSAndroid Build Coastguard Worker },
3168*8fb009dcSAndroid Build Coastguard Worker {
3169*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_application_layer_protocol_negotiation,
3170*8fb009dcSAndroid Build Coastguard Worker ext_alpn_add_clienthello,
3171*8fb009dcSAndroid Build Coastguard Worker ext_alpn_parse_serverhello,
3172*8fb009dcSAndroid Build Coastguard Worker // ALPN is negotiated late in |ssl_negotiate_alpn|.
3173*8fb009dcSAndroid Build Coastguard Worker ignore_parse_clienthello,
3174*8fb009dcSAndroid Build Coastguard Worker ext_alpn_add_serverhello,
3175*8fb009dcSAndroid Build Coastguard Worker },
3176*8fb009dcSAndroid Build Coastguard Worker {
3177*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_status_request,
3178*8fb009dcSAndroid Build Coastguard Worker ext_ocsp_add_clienthello,
3179*8fb009dcSAndroid Build Coastguard Worker ext_ocsp_parse_serverhello,
3180*8fb009dcSAndroid Build Coastguard Worker ext_ocsp_parse_clienthello,
3181*8fb009dcSAndroid Build Coastguard Worker ext_ocsp_add_serverhello,
3182*8fb009dcSAndroid Build Coastguard Worker },
3183*8fb009dcSAndroid Build Coastguard Worker {
3184*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_signature_algorithms,
3185*8fb009dcSAndroid Build Coastguard Worker ext_sigalgs_add_clienthello,
3186*8fb009dcSAndroid Build Coastguard Worker forbid_parse_serverhello,
3187*8fb009dcSAndroid Build Coastguard Worker ext_sigalgs_parse_clienthello,
3188*8fb009dcSAndroid Build Coastguard Worker dont_add_serverhello,
3189*8fb009dcSAndroid Build Coastguard Worker },
3190*8fb009dcSAndroid Build Coastguard Worker {
3191*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_next_proto_neg,
3192*8fb009dcSAndroid Build Coastguard Worker ext_npn_add_clienthello,
3193*8fb009dcSAndroid Build Coastguard Worker ext_npn_parse_serverhello,
3194*8fb009dcSAndroid Build Coastguard Worker ext_npn_parse_clienthello,
3195*8fb009dcSAndroid Build Coastguard Worker ext_npn_add_serverhello,
3196*8fb009dcSAndroid Build Coastguard Worker },
3197*8fb009dcSAndroid Build Coastguard Worker {
3198*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_certificate_timestamp,
3199*8fb009dcSAndroid Build Coastguard Worker ext_sct_add_clienthello,
3200*8fb009dcSAndroid Build Coastguard Worker ext_sct_parse_serverhello,
3201*8fb009dcSAndroid Build Coastguard Worker ext_sct_parse_clienthello,
3202*8fb009dcSAndroid Build Coastguard Worker ext_sct_add_serverhello,
3203*8fb009dcSAndroid Build Coastguard Worker },
3204*8fb009dcSAndroid Build Coastguard Worker {
3205*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_channel_id,
3206*8fb009dcSAndroid Build Coastguard Worker ext_channel_id_add_clienthello,
3207*8fb009dcSAndroid Build Coastguard Worker ext_channel_id_parse_serverhello,
3208*8fb009dcSAndroid Build Coastguard Worker ext_channel_id_parse_clienthello,
3209*8fb009dcSAndroid Build Coastguard Worker ext_channel_id_add_serverhello,
3210*8fb009dcSAndroid Build Coastguard Worker },
3211*8fb009dcSAndroid Build Coastguard Worker {
3212*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_srtp,
3213*8fb009dcSAndroid Build Coastguard Worker ext_srtp_add_clienthello,
3214*8fb009dcSAndroid Build Coastguard Worker ext_srtp_parse_serverhello,
3215*8fb009dcSAndroid Build Coastguard Worker ext_srtp_parse_clienthello,
3216*8fb009dcSAndroid Build Coastguard Worker ext_srtp_add_serverhello,
3217*8fb009dcSAndroid Build Coastguard Worker },
3218*8fb009dcSAndroid Build Coastguard Worker {
3219*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_key_share,
3220*8fb009dcSAndroid Build Coastguard Worker ext_key_share_add_clienthello,
3221*8fb009dcSAndroid Build Coastguard Worker forbid_parse_serverhello,
3222*8fb009dcSAndroid Build Coastguard Worker ignore_parse_clienthello,
3223*8fb009dcSAndroid Build Coastguard Worker dont_add_serverhello,
3224*8fb009dcSAndroid Build Coastguard Worker },
3225*8fb009dcSAndroid Build Coastguard Worker {
3226*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_psk_key_exchange_modes,
3227*8fb009dcSAndroid Build Coastguard Worker ext_psk_key_exchange_modes_add_clienthello,
3228*8fb009dcSAndroid Build Coastguard Worker forbid_parse_serverhello,
3229*8fb009dcSAndroid Build Coastguard Worker ext_psk_key_exchange_modes_parse_clienthello,
3230*8fb009dcSAndroid Build Coastguard Worker dont_add_serverhello,
3231*8fb009dcSAndroid Build Coastguard Worker },
3232*8fb009dcSAndroid Build Coastguard Worker {
3233*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_early_data,
3234*8fb009dcSAndroid Build Coastguard Worker ext_early_data_add_clienthello,
3235*8fb009dcSAndroid Build Coastguard Worker ext_early_data_parse_serverhello,
3236*8fb009dcSAndroid Build Coastguard Worker ext_early_data_parse_clienthello,
3237*8fb009dcSAndroid Build Coastguard Worker ext_early_data_add_serverhello,
3238*8fb009dcSAndroid Build Coastguard Worker },
3239*8fb009dcSAndroid Build Coastguard Worker {
3240*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_supported_versions,
3241*8fb009dcSAndroid Build Coastguard Worker ext_supported_versions_add_clienthello,
3242*8fb009dcSAndroid Build Coastguard Worker forbid_parse_serverhello,
3243*8fb009dcSAndroid Build Coastguard Worker ignore_parse_clienthello,
3244*8fb009dcSAndroid Build Coastguard Worker dont_add_serverhello,
3245*8fb009dcSAndroid Build Coastguard Worker },
3246*8fb009dcSAndroid Build Coastguard Worker {
3247*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_cookie,
3248*8fb009dcSAndroid Build Coastguard Worker ext_cookie_add_clienthello,
3249*8fb009dcSAndroid Build Coastguard Worker forbid_parse_serverhello,
3250*8fb009dcSAndroid Build Coastguard Worker ignore_parse_clienthello,
3251*8fb009dcSAndroid Build Coastguard Worker dont_add_serverhello,
3252*8fb009dcSAndroid Build Coastguard Worker },
3253*8fb009dcSAndroid Build Coastguard Worker {
3254*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_quic_transport_parameters,
3255*8fb009dcSAndroid Build Coastguard Worker ext_quic_transport_params_add_clienthello,
3256*8fb009dcSAndroid Build Coastguard Worker ext_quic_transport_params_parse_serverhello,
3257*8fb009dcSAndroid Build Coastguard Worker ext_quic_transport_params_parse_clienthello,
3258*8fb009dcSAndroid Build Coastguard Worker ext_quic_transport_params_add_serverhello,
3259*8fb009dcSAndroid Build Coastguard Worker },
3260*8fb009dcSAndroid Build Coastguard Worker {
3261*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_quic_transport_parameters_legacy,
3262*8fb009dcSAndroid Build Coastguard Worker ext_quic_transport_params_add_clienthello_legacy,
3263*8fb009dcSAndroid Build Coastguard Worker ext_quic_transport_params_parse_serverhello_legacy,
3264*8fb009dcSAndroid Build Coastguard Worker ext_quic_transport_params_parse_clienthello_legacy,
3265*8fb009dcSAndroid Build Coastguard Worker ext_quic_transport_params_add_serverhello_legacy,
3266*8fb009dcSAndroid Build Coastguard Worker },
3267*8fb009dcSAndroid Build Coastguard Worker {
3268*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_cert_compression,
3269*8fb009dcSAndroid Build Coastguard Worker cert_compression_add_clienthello,
3270*8fb009dcSAndroid Build Coastguard Worker cert_compression_parse_serverhello,
3271*8fb009dcSAndroid Build Coastguard Worker cert_compression_parse_clienthello,
3272*8fb009dcSAndroid Build Coastguard Worker cert_compression_add_serverhello,
3273*8fb009dcSAndroid Build Coastguard Worker },
3274*8fb009dcSAndroid Build Coastguard Worker {
3275*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_delegated_credential,
3276*8fb009dcSAndroid Build Coastguard Worker ext_delegated_credential_add_clienthello,
3277*8fb009dcSAndroid Build Coastguard Worker forbid_parse_serverhello,
3278*8fb009dcSAndroid Build Coastguard Worker ext_delegated_credential_parse_clienthello,
3279*8fb009dcSAndroid Build Coastguard Worker dont_add_serverhello,
3280*8fb009dcSAndroid Build Coastguard Worker },
3281*8fb009dcSAndroid Build Coastguard Worker {
3282*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_application_settings,
3283*8fb009dcSAndroid Build Coastguard Worker ext_alps_add_clienthello,
3284*8fb009dcSAndroid Build Coastguard Worker ext_alps_parse_serverhello,
3285*8fb009dcSAndroid Build Coastguard Worker // ALPS is negotiated late in |ssl_negotiate_alpn|.
3286*8fb009dcSAndroid Build Coastguard Worker ignore_parse_clienthello,
3287*8fb009dcSAndroid Build Coastguard Worker ext_alps_add_serverhello,
3288*8fb009dcSAndroid Build Coastguard Worker },
3289*8fb009dcSAndroid Build Coastguard Worker {
3290*8fb009dcSAndroid Build Coastguard Worker TLSEXT_TYPE_application_settings_old,
3291*8fb009dcSAndroid Build Coastguard Worker ext_alps_add_clienthello_old,
3292*8fb009dcSAndroid Build Coastguard Worker ext_alps_parse_serverhello_old,
3293*8fb009dcSAndroid Build Coastguard Worker // ALPS is negotiated late in |ssl_negotiate_alpn|.
3294*8fb009dcSAndroid Build Coastguard Worker ignore_parse_clienthello,
3295*8fb009dcSAndroid Build Coastguard Worker ext_alps_add_serverhello_old,
3296*8fb009dcSAndroid Build Coastguard Worker },
3297*8fb009dcSAndroid Build Coastguard Worker };
3298*8fb009dcSAndroid Build Coastguard Worker
3299*8fb009dcSAndroid Build Coastguard Worker #define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
3300*8fb009dcSAndroid Build Coastguard Worker
3301*8fb009dcSAndroid Build Coastguard Worker static_assert(kNumExtensions <=
3302*8fb009dcSAndroid Build Coastguard Worker sizeof(((SSL_HANDSHAKE *)NULL)->extensions.sent) * 8,
3303*8fb009dcSAndroid Build Coastguard Worker "too many extensions for sent bitset");
3304*8fb009dcSAndroid Build Coastguard Worker static_assert(kNumExtensions <=
3305*8fb009dcSAndroid Build Coastguard Worker sizeof(((SSL_HANDSHAKE *)NULL)->extensions.received) * 8,
3306*8fb009dcSAndroid Build Coastguard Worker "too many extensions for received bitset");
3307*8fb009dcSAndroid Build Coastguard Worker
ssl_setup_extension_permutation(SSL_HANDSHAKE * hs)3308*8fb009dcSAndroid Build Coastguard Worker bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs) {
3309*8fb009dcSAndroid Build Coastguard Worker if (!hs->config->permute_extensions) {
3310*8fb009dcSAndroid Build Coastguard Worker return true;
3311*8fb009dcSAndroid Build Coastguard Worker }
3312*8fb009dcSAndroid Build Coastguard Worker
3313*8fb009dcSAndroid Build Coastguard Worker static_assert(kNumExtensions <= UINT8_MAX,
3314*8fb009dcSAndroid Build Coastguard Worker "extensions_permutation type is too small");
3315*8fb009dcSAndroid Build Coastguard Worker uint32_t seeds[kNumExtensions - 1];
3316*8fb009dcSAndroid Build Coastguard Worker Array<uint8_t> permutation;
3317*8fb009dcSAndroid Build Coastguard Worker if (!RAND_bytes(reinterpret_cast<uint8_t *>(seeds), sizeof(seeds)) ||
3318*8fb009dcSAndroid Build Coastguard Worker !permutation.Init(kNumExtensions)) {
3319*8fb009dcSAndroid Build Coastguard Worker return false;
3320*8fb009dcSAndroid Build Coastguard Worker }
3321*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumExtensions; i++) {
3322*8fb009dcSAndroid Build Coastguard Worker permutation[i] = i;
3323*8fb009dcSAndroid Build Coastguard Worker }
3324*8fb009dcSAndroid Build Coastguard Worker for (size_t i = kNumExtensions - 1; i > 0; i--) {
3325*8fb009dcSAndroid Build Coastguard Worker // Set element |i| to a randomly-selected element 0 <= j <= i.
3326*8fb009dcSAndroid Build Coastguard Worker std::swap(permutation[i], permutation[seeds[i - 1] % (i + 1)]);
3327*8fb009dcSAndroid Build Coastguard Worker }
3328*8fb009dcSAndroid Build Coastguard Worker hs->extension_permutation = std::move(permutation);
3329*8fb009dcSAndroid Build Coastguard Worker return true;
3330*8fb009dcSAndroid Build Coastguard Worker }
3331*8fb009dcSAndroid Build Coastguard Worker
tls_extension_find(uint32_t * out_index,uint16_t value)3332*8fb009dcSAndroid Build Coastguard Worker static const struct tls_extension *tls_extension_find(uint32_t *out_index,
3333*8fb009dcSAndroid Build Coastguard Worker uint16_t value) {
3334*8fb009dcSAndroid Build Coastguard Worker unsigned i;
3335*8fb009dcSAndroid Build Coastguard Worker for (i = 0; i < kNumExtensions; i++) {
3336*8fb009dcSAndroid Build Coastguard Worker if (kExtensions[i].value == value) {
3337*8fb009dcSAndroid Build Coastguard Worker *out_index = i;
3338*8fb009dcSAndroid Build Coastguard Worker return &kExtensions[i];
3339*8fb009dcSAndroid Build Coastguard Worker }
3340*8fb009dcSAndroid Build Coastguard Worker }
3341*8fb009dcSAndroid Build Coastguard Worker
3342*8fb009dcSAndroid Build Coastguard Worker return NULL;
3343*8fb009dcSAndroid Build Coastguard Worker }
3344*8fb009dcSAndroid Build Coastguard Worker
add_padding_extension(CBB * cbb,uint16_t ext,size_t len)3345*8fb009dcSAndroid Build Coastguard Worker static bool add_padding_extension(CBB *cbb, uint16_t ext, size_t len) {
3346*8fb009dcSAndroid Build Coastguard Worker CBB child;
3347*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(cbb, ext) || //
3348*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(cbb, &child) ||
3349*8fb009dcSAndroid Build Coastguard Worker !CBB_add_zeros(&child, len)) {
3350*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3351*8fb009dcSAndroid Build Coastguard Worker return false;
3352*8fb009dcSAndroid Build Coastguard Worker }
3353*8fb009dcSAndroid Build Coastguard Worker return CBB_flush(cbb);
3354*8fb009dcSAndroid Build Coastguard Worker }
3355*8fb009dcSAndroid Build Coastguard Worker
ssl_add_clienthello_tlsext_inner(SSL_HANDSHAKE * hs,CBB * out,CBB * out_encoded,bool * out_needs_psk_binder)3356*8fb009dcSAndroid Build Coastguard Worker static bool ssl_add_clienthello_tlsext_inner(SSL_HANDSHAKE *hs, CBB *out,
3357*8fb009dcSAndroid Build Coastguard Worker CBB *out_encoded,
3358*8fb009dcSAndroid Build Coastguard Worker bool *out_needs_psk_binder) {
3359*8fb009dcSAndroid Build Coastguard Worker // When writing ClientHelloInner, we construct the real and encoded
3360*8fb009dcSAndroid Build Coastguard Worker // ClientHellos concurrently, to handle compression. Uncompressed extensions
3361*8fb009dcSAndroid Build Coastguard Worker // are written to |extensions| and copied to |extensions_encoded|. Compressed
3362*8fb009dcSAndroid Build Coastguard Worker // extensions are buffered in |compressed| and written to the end. (ECH can
3363*8fb009dcSAndroid Build Coastguard Worker // only compress continguous extensions.)
3364*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
3365*8fb009dcSAndroid Build Coastguard Worker bssl::ScopedCBB compressed, outer_extensions;
3366*8fb009dcSAndroid Build Coastguard Worker CBB extensions, extensions_encoded;
3367*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16_length_prefixed(out, &extensions) ||
3368*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(out_encoded, &extensions_encoded) ||
3369*8fb009dcSAndroid Build Coastguard Worker !CBB_init(compressed.get(), 64) ||
3370*8fb009dcSAndroid Build Coastguard Worker !CBB_init(outer_extensions.get(), 64)) {
3371*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3372*8fb009dcSAndroid Build Coastguard Worker return false;
3373*8fb009dcSAndroid Build Coastguard Worker }
3374*8fb009dcSAndroid Build Coastguard Worker
3375*8fb009dcSAndroid Build Coastguard Worker hs->inner_extensions_sent = 0;
3376*8fb009dcSAndroid Build Coastguard Worker
3377*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->grease_enabled) {
3378*8fb009dcSAndroid Build Coastguard Worker // Add a fake empty extension. See RFC 8701. This always matches
3379*8fb009dcSAndroid Build Coastguard Worker // |ssl_add_clienthello_tlsext|, so compress it.
3380*8fb009dcSAndroid Build Coastguard Worker uint16_t grease_ext = ssl_get_grease_value(hs, ssl_grease_extension1);
3381*8fb009dcSAndroid Build Coastguard Worker if (!add_padding_extension(compressed.get(), grease_ext, 0) ||
3382*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(outer_extensions.get(), grease_ext)) {
3383*8fb009dcSAndroid Build Coastguard Worker return false;
3384*8fb009dcSAndroid Build Coastguard Worker }
3385*8fb009dcSAndroid Build Coastguard Worker }
3386*8fb009dcSAndroid Build Coastguard Worker
3387*8fb009dcSAndroid Build Coastguard Worker for (size_t unpermuted = 0; unpermuted < kNumExtensions; unpermuted++) {
3388*8fb009dcSAndroid Build Coastguard Worker size_t i = hs->extension_permutation.empty()
3389*8fb009dcSAndroid Build Coastguard Worker ? unpermuted
3390*8fb009dcSAndroid Build Coastguard Worker : hs->extension_permutation[unpermuted];
3391*8fb009dcSAndroid Build Coastguard Worker const size_t len_before = CBB_len(&extensions);
3392*8fb009dcSAndroid Build Coastguard Worker const size_t len_compressed_before = CBB_len(compressed.get());
3393*8fb009dcSAndroid Build Coastguard Worker if (!kExtensions[i].add_clienthello(hs, &extensions, compressed.get(),
3394*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_inner)) {
3395*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
3396*8fb009dcSAndroid Build Coastguard Worker ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3397*8fb009dcSAndroid Build Coastguard Worker return false;
3398*8fb009dcSAndroid Build Coastguard Worker }
3399*8fb009dcSAndroid Build Coastguard Worker
3400*8fb009dcSAndroid Build Coastguard Worker const size_t bytes_written = CBB_len(&extensions) - len_before;
3401*8fb009dcSAndroid Build Coastguard Worker const size_t bytes_written_compressed =
3402*8fb009dcSAndroid Build Coastguard Worker CBB_len(compressed.get()) - len_compressed_before;
3403*8fb009dcSAndroid Build Coastguard Worker // The callback may write to at most one output.
3404*8fb009dcSAndroid Build Coastguard Worker assert(bytes_written == 0 || bytes_written_compressed == 0);
3405*8fb009dcSAndroid Build Coastguard Worker if (bytes_written != 0 || bytes_written_compressed != 0) {
3406*8fb009dcSAndroid Build Coastguard Worker hs->inner_extensions_sent |= (1u << i);
3407*8fb009dcSAndroid Build Coastguard Worker }
3408*8fb009dcSAndroid Build Coastguard Worker // If compressed, update the running ech_outer_extensions extension.
3409*8fb009dcSAndroid Build Coastguard Worker if (bytes_written_compressed != 0 &&
3410*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(outer_extensions.get(), kExtensions[i].value)) {
3411*8fb009dcSAndroid Build Coastguard Worker return false;
3412*8fb009dcSAndroid Build Coastguard Worker }
3413*8fb009dcSAndroid Build Coastguard Worker }
3414*8fb009dcSAndroid Build Coastguard Worker
3415*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->grease_enabled) {
3416*8fb009dcSAndroid Build Coastguard Worker // Add a fake non-empty extension. See RFC 8701. This always matches
3417*8fb009dcSAndroid Build Coastguard Worker // |ssl_add_clienthello_tlsext|, so compress it.
3418*8fb009dcSAndroid Build Coastguard Worker uint16_t grease_ext = ssl_get_grease_value(hs, ssl_grease_extension2);
3419*8fb009dcSAndroid Build Coastguard Worker if (!add_padding_extension(compressed.get(), grease_ext, 1) ||
3420*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(outer_extensions.get(), grease_ext)) {
3421*8fb009dcSAndroid Build Coastguard Worker return false;
3422*8fb009dcSAndroid Build Coastguard Worker }
3423*8fb009dcSAndroid Build Coastguard Worker }
3424*8fb009dcSAndroid Build Coastguard Worker
3425*8fb009dcSAndroid Build Coastguard Worker // Uncompressed extensions are encoded as-is.
3426*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_bytes(&extensions_encoded, CBB_data(&extensions),
3427*8fb009dcSAndroid Build Coastguard Worker CBB_len(&extensions))) {
3428*8fb009dcSAndroid Build Coastguard Worker return false;
3429*8fb009dcSAndroid Build Coastguard Worker }
3430*8fb009dcSAndroid Build Coastguard Worker
3431*8fb009dcSAndroid Build Coastguard Worker // Flush all the compressed extensions.
3432*8fb009dcSAndroid Build Coastguard Worker if (CBB_len(compressed.get()) != 0) {
3433*8fb009dcSAndroid Build Coastguard Worker CBB extension, child;
3434*8fb009dcSAndroid Build Coastguard Worker // Copy them as-is in the real ClientHelloInner.
3435*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_bytes(&extensions, CBB_data(compressed.get()),
3436*8fb009dcSAndroid Build Coastguard Worker CBB_len(compressed.get())) ||
3437*8fb009dcSAndroid Build Coastguard Worker // Replace with ech_outer_extensions in the encoded form.
3438*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16(&extensions_encoded, TLSEXT_TYPE_ech_outer_extensions) ||
3439*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(&extensions_encoded, &extension) ||
3440*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8_length_prefixed(&extension, &child) ||
3441*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&child, CBB_data(outer_extensions.get()),
3442*8fb009dcSAndroid Build Coastguard Worker CBB_len(outer_extensions.get())) ||
3443*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(&extensions_encoded)) {
3444*8fb009dcSAndroid Build Coastguard Worker return false;
3445*8fb009dcSAndroid Build Coastguard Worker }
3446*8fb009dcSAndroid Build Coastguard Worker }
3447*8fb009dcSAndroid Build Coastguard Worker
3448*8fb009dcSAndroid Build Coastguard Worker // The PSK extension must be last. It is never compressed. Note, if there is a
3449*8fb009dcSAndroid Build Coastguard Worker // binder, the caller will need to update both ClientHelloInner and
3450*8fb009dcSAndroid Build Coastguard Worker // EncodedClientHelloInner after computing it.
3451*8fb009dcSAndroid Build Coastguard Worker const size_t len_before = CBB_len(&extensions);
3452*8fb009dcSAndroid Build Coastguard Worker if (!ext_pre_shared_key_add_clienthello(hs, &extensions, out_needs_psk_binder,
3453*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_inner) ||
3454*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(&extensions_encoded, CBB_data(&extensions) + len_before,
3455*8fb009dcSAndroid Build Coastguard Worker CBB_len(&extensions) - len_before) ||
3456*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out) || //
3457*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(out_encoded)) {
3458*8fb009dcSAndroid Build Coastguard Worker return false;
3459*8fb009dcSAndroid Build Coastguard Worker }
3460*8fb009dcSAndroid Build Coastguard Worker
3461*8fb009dcSAndroid Build Coastguard Worker return true;
3462*8fb009dcSAndroid Build Coastguard Worker }
3463*8fb009dcSAndroid Build Coastguard Worker
ssl_add_clienthello_tlsext(SSL_HANDSHAKE * hs,CBB * out,CBB * out_encoded,bool * out_needs_psk_binder,ssl_client_hello_type_t type,size_t header_len)3464*8fb009dcSAndroid Build Coastguard Worker bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, CBB *out_encoded,
3465*8fb009dcSAndroid Build Coastguard Worker bool *out_needs_psk_binder,
3466*8fb009dcSAndroid Build Coastguard Worker ssl_client_hello_type_t type,
3467*8fb009dcSAndroid Build Coastguard Worker size_t header_len) {
3468*8fb009dcSAndroid Build Coastguard Worker *out_needs_psk_binder = false;
3469*8fb009dcSAndroid Build Coastguard Worker
3470*8fb009dcSAndroid Build Coastguard Worker if (type == ssl_client_hello_inner) {
3471*8fb009dcSAndroid Build Coastguard Worker return ssl_add_clienthello_tlsext_inner(hs, out, out_encoded,
3472*8fb009dcSAndroid Build Coastguard Worker out_needs_psk_binder);
3473*8fb009dcSAndroid Build Coastguard Worker }
3474*8fb009dcSAndroid Build Coastguard Worker
3475*8fb009dcSAndroid Build Coastguard Worker assert(out_encoded == nullptr); // Only ClientHelloInner needs two outputs.
3476*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
3477*8fb009dcSAndroid Build Coastguard Worker CBB extensions;
3478*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16_length_prefixed(out, &extensions)) {
3479*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3480*8fb009dcSAndroid Build Coastguard Worker return false;
3481*8fb009dcSAndroid Build Coastguard Worker }
3482*8fb009dcSAndroid Build Coastguard Worker
3483*8fb009dcSAndroid Build Coastguard Worker // Note we may send multiple ClientHellos for DTLS HelloVerifyRequest and TLS
3484*8fb009dcSAndroid Build Coastguard Worker // 1.3 HelloRetryRequest. For the latter, the extensions may change, so it is
3485*8fb009dcSAndroid Build Coastguard Worker // important to reset this value.
3486*8fb009dcSAndroid Build Coastguard Worker hs->extensions.sent = 0;
3487*8fb009dcSAndroid Build Coastguard Worker
3488*8fb009dcSAndroid Build Coastguard Worker // Add a fake empty extension. See RFC 8701.
3489*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->grease_enabled &&
3490*8fb009dcSAndroid Build Coastguard Worker !add_padding_extension(
3491*8fb009dcSAndroid Build Coastguard Worker &extensions, ssl_get_grease_value(hs, ssl_grease_extension1), 0)) {
3492*8fb009dcSAndroid Build Coastguard Worker return false;
3493*8fb009dcSAndroid Build Coastguard Worker }
3494*8fb009dcSAndroid Build Coastguard Worker
3495*8fb009dcSAndroid Build Coastguard Worker bool last_was_empty = false;
3496*8fb009dcSAndroid Build Coastguard Worker for (size_t unpermuted = 0; unpermuted < kNumExtensions; unpermuted++) {
3497*8fb009dcSAndroid Build Coastguard Worker size_t i = hs->extension_permutation.empty()
3498*8fb009dcSAndroid Build Coastguard Worker ? unpermuted
3499*8fb009dcSAndroid Build Coastguard Worker : hs->extension_permutation[unpermuted];
3500*8fb009dcSAndroid Build Coastguard Worker const size_t len_before = CBB_len(&extensions);
3501*8fb009dcSAndroid Build Coastguard Worker if (!kExtensions[i].add_clienthello(hs, &extensions, &extensions, type)) {
3502*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
3503*8fb009dcSAndroid Build Coastguard Worker ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3504*8fb009dcSAndroid Build Coastguard Worker return false;
3505*8fb009dcSAndroid Build Coastguard Worker }
3506*8fb009dcSAndroid Build Coastguard Worker
3507*8fb009dcSAndroid Build Coastguard Worker const size_t bytes_written = CBB_len(&extensions) - len_before;
3508*8fb009dcSAndroid Build Coastguard Worker if (bytes_written != 0) {
3509*8fb009dcSAndroid Build Coastguard Worker hs->extensions.sent |= (1u << i);
3510*8fb009dcSAndroid Build Coastguard Worker }
3511*8fb009dcSAndroid Build Coastguard Worker // If the difference in lengths is only four bytes then the extension had
3512*8fb009dcSAndroid Build Coastguard Worker // an empty body.
3513*8fb009dcSAndroid Build Coastguard Worker last_was_empty = (bytes_written == 4);
3514*8fb009dcSAndroid Build Coastguard Worker }
3515*8fb009dcSAndroid Build Coastguard Worker
3516*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->grease_enabled) {
3517*8fb009dcSAndroid Build Coastguard Worker // Add a fake non-empty extension. See RFC 8701.
3518*8fb009dcSAndroid Build Coastguard Worker if (!add_padding_extension(
3519*8fb009dcSAndroid Build Coastguard Worker &extensions, ssl_get_grease_value(hs, ssl_grease_extension2), 1)) {
3520*8fb009dcSAndroid Build Coastguard Worker return false;
3521*8fb009dcSAndroid Build Coastguard Worker }
3522*8fb009dcSAndroid Build Coastguard Worker last_was_empty = false;
3523*8fb009dcSAndroid Build Coastguard Worker }
3524*8fb009dcSAndroid Build Coastguard Worker
3525*8fb009dcSAndroid Build Coastguard Worker // In cleartext ClientHellos, we add the padding extension to work around
3526*8fb009dcSAndroid Build Coastguard Worker // bugs. We also apply this padding to ClientHelloOuter, to keep the wire
3527*8fb009dcSAndroid Build Coastguard Worker // images aligned.
3528*8fb009dcSAndroid Build Coastguard Worker size_t psk_extension_len = ext_pre_shared_key_clienthello_length(hs, type);
3529*8fb009dcSAndroid Build Coastguard Worker if (!SSL_is_dtls(ssl) && !ssl->quic_method &&
3530*8fb009dcSAndroid Build Coastguard Worker !ssl->s3->used_hello_retry_request) {
3531*8fb009dcSAndroid Build Coastguard Worker header_len +=
3532*8fb009dcSAndroid Build Coastguard Worker SSL3_HM_HEADER_LENGTH + 2 + CBB_len(&extensions) + psk_extension_len;
3533*8fb009dcSAndroid Build Coastguard Worker size_t padding_len = 0;
3534*8fb009dcSAndroid Build Coastguard Worker
3535*8fb009dcSAndroid Build Coastguard Worker // The final extension must be non-empty. WebSphere Application
3536*8fb009dcSAndroid Build Coastguard Worker // Server 7.0 is intolerant to the last extension being zero-length. See
3537*8fb009dcSAndroid Build Coastguard Worker // https://crbug.com/363583.
3538*8fb009dcSAndroid Build Coastguard Worker if (last_was_empty && psk_extension_len == 0) {
3539*8fb009dcSAndroid Build Coastguard Worker padding_len = 1;
3540*8fb009dcSAndroid Build Coastguard Worker // The addition of the padding extension may push us into the F5 bug.
3541*8fb009dcSAndroid Build Coastguard Worker header_len += 4 + padding_len;
3542*8fb009dcSAndroid Build Coastguard Worker }
3543*8fb009dcSAndroid Build Coastguard Worker
3544*8fb009dcSAndroid Build Coastguard Worker // Add padding to workaround bugs in F5 terminators. See RFC 7685.
3545*8fb009dcSAndroid Build Coastguard Worker //
3546*8fb009dcSAndroid Build Coastguard Worker // NB: because this code works out the length of all existing extensions
3547*8fb009dcSAndroid Build Coastguard Worker // it MUST always appear last (save for any PSK extension).
3548*8fb009dcSAndroid Build Coastguard Worker if (header_len > 0xff && header_len < 0x200) {
3549*8fb009dcSAndroid Build Coastguard Worker // If our calculations already included a padding extension, remove that
3550*8fb009dcSAndroid Build Coastguard Worker // factor because we're about to change its length.
3551*8fb009dcSAndroid Build Coastguard Worker if (padding_len != 0) {
3552*8fb009dcSAndroid Build Coastguard Worker header_len -= 4 + padding_len;
3553*8fb009dcSAndroid Build Coastguard Worker }
3554*8fb009dcSAndroid Build Coastguard Worker padding_len = 0x200 - header_len;
3555*8fb009dcSAndroid Build Coastguard Worker // Extensions take at least four bytes to encode. Always include at least
3556*8fb009dcSAndroid Build Coastguard Worker // one byte of data if including the extension. WebSphere Application
3557*8fb009dcSAndroid Build Coastguard Worker // Server 7.0 is intolerant to the last extension being zero-length. See
3558*8fb009dcSAndroid Build Coastguard Worker // https://crbug.com/363583.
3559*8fb009dcSAndroid Build Coastguard Worker if (padding_len >= 4 + 1) {
3560*8fb009dcSAndroid Build Coastguard Worker padding_len -= 4;
3561*8fb009dcSAndroid Build Coastguard Worker } else {
3562*8fb009dcSAndroid Build Coastguard Worker padding_len = 1;
3563*8fb009dcSAndroid Build Coastguard Worker }
3564*8fb009dcSAndroid Build Coastguard Worker }
3565*8fb009dcSAndroid Build Coastguard Worker
3566*8fb009dcSAndroid Build Coastguard Worker if (padding_len != 0 &&
3567*8fb009dcSAndroid Build Coastguard Worker !add_padding_extension(&extensions, TLSEXT_TYPE_padding, padding_len)) {
3568*8fb009dcSAndroid Build Coastguard Worker return false;
3569*8fb009dcSAndroid Build Coastguard Worker }
3570*8fb009dcSAndroid Build Coastguard Worker }
3571*8fb009dcSAndroid Build Coastguard Worker
3572*8fb009dcSAndroid Build Coastguard Worker // The PSK extension must be last, including after the padding.
3573*8fb009dcSAndroid Build Coastguard Worker const size_t len_before = CBB_len(&extensions);
3574*8fb009dcSAndroid Build Coastguard Worker if (!ext_pre_shared_key_add_clienthello(hs, &extensions, out_needs_psk_binder,
3575*8fb009dcSAndroid Build Coastguard Worker type)) {
3576*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3577*8fb009dcSAndroid Build Coastguard Worker return false;
3578*8fb009dcSAndroid Build Coastguard Worker }
3579*8fb009dcSAndroid Build Coastguard Worker assert(psk_extension_len == CBB_len(&extensions) - len_before);
3580*8fb009dcSAndroid Build Coastguard Worker (void)len_before; // |assert| is omitted in release builds.
3581*8fb009dcSAndroid Build Coastguard Worker
3582*8fb009dcSAndroid Build Coastguard Worker // Discard empty extensions blocks.
3583*8fb009dcSAndroid Build Coastguard Worker if (CBB_len(&extensions) == 0) {
3584*8fb009dcSAndroid Build Coastguard Worker CBB_discard_child(out);
3585*8fb009dcSAndroid Build Coastguard Worker }
3586*8fb009dcSAndroid Build Coastguard Worker
3587*8fb009dcSAndroid Build Coastguard Worker return CBB_flush(out);
3588*8fb009dcSAndroid Build Coastguard Worker }
3589*8fb009dcSAndroid Build Coastguard Worker
ssl_add_serverhello_tlsext(SSL_HANDSHAKE * hs,CBB * out)3590*8fb009dcSAndroid Build Coastguard Worker bool ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out) {
3591*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
3592*8fb009dcSAndroid Build Coastguard Worker CBB extensions;
3593*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16_length_prefixed(out, &extensions)) {
3594*8fb009dcSAndroid Build Coastguard Worker goto err;
3595*8fb009dcSAndroid Build Coastguard Worker }
3596*8fb009dcSAndroid Build Coastguard Worker
3597*8fb009dcSAndroid Build Coastguard Worker for (unsigned i = 0; i < kNumExtensions; i++) {
3598*8fb009dcSAndroid Build Coastguard Worker if (!(hs->extensions.received & (1u << i))) {
3599*8fb009dcSAndroid Build Coastguard Worker // Don't send extensions that were not received.
3600*8fb009dcSAndroid Build Coastguard Worker continue;
3601*8fb009dcSAndroid Build Coastguard Worker }
3602*8fb009dcSAndroid Build Coastguard Worker
3603*8fb009dcSAndroid Build Coastguard Worker if (!kExtensions[i].add_serverhello(hs, &extensions)) {
3604*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
3605*8fb009dcSAndroid Build Coastguard Worker ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3606*8fb009dcSAndroid Build Coastguard Worker goto err;
3607*8fb009dcSAndroid Build Coastguard Worker }
3608*8fb009dcSAndroid Build Coastguard Worker }
3609*8fb009dcSAndroid Build Coastguard Worker
3610*8fb009dcSAndroid Build Coastguard Worker // Discard empty extensions blocks before TLS 1.3.
3611*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) < TLS1_3_VERSION &&
3612*8fb009dcSAndroid Build Coastguard Worker CBB_len(&extensions) == 0) {
3613*8fb009dcSAndroid Build Coastguard Worker CBB_discard_child(out);
3614*8fb009dcSAndroid Build Coastguard Worker }
3615*8fb009dcSAndroid Build Coastguard Worker
3616*8fb009dcSAndroid Build Coastguard Worker return CBB_flush(out);
3617*8fb009dcSAndroid Build Coastguard Worker
3618*8fb009dcSAndroid Build Coastguard Worker err:
3619*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3620*8fb009dcSAndroid Build Coastguard Worker return false;
3621*8fb009dcSAndroid Build Coastguard Worker }
3622*8fb009dcSAndroid Build Coastguard Worker
ssl_scan_clienthello_tlsext(SSL_HANDSHAKE * hs,const SSL_CLIENT_HELLO * client_hello,int * out_alert)3623*8fb009dcSAndroid Build Coastguard Worker static bool ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs,
3624*8fb009dcSAndroid Build Coastguard Worker const SSL_CLIENT_HELLO *client_hello,
3625*8fb009dcSAndroid Build Coastguard Worker int *out_alert) {
3626*8fb009dcSAndroid Build Coastguard Worker hs->extensions.received = 0;
3627*8fb009dcSAndroid Build Coastguard Worker CBS extensions;
3628*8fb009dcSAndroid Build Coastguard Worker CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
3629*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&extensions) != 0) {
3630*8fb009dcSAndroid Build Coastguard Worker uint16_t type;
3631*8fb009dcSAndroid Build Coastguard Worker CBS extension;
3632*8fb009dcSAndroid Build Coastguard Worker
3633*8fb009dcSAndroid Build Coastguard Worker // Decode the next extension.
3634*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(&extensions, &type) ||
3635*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16_length_prefixed(&extensions, &extension)) {
3636*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
3637*8fb009dcSAndroid Build Coastguard Worker return false;
3638*8fb009dcSAndroid Build Coastguard Worker }
3639*8fb009dcSAndroid Build Coastguard Worker
3640*8fb009dcSAndroid Build Coastguard Worker unsigned ext_index;
3641*8fb009dcSAndroid Build Coastguard Worker const struct tls_extension *const ext =
3642*8fb009dcSAndroid Build Coastguard Worker tls_extension_find(&ext_index, type);
3643*8fb009dcSAndroid Build Coastguard Worker if (ext == NULL) {
3644*8fb009dcSAndroid Build Coastguard Worker continue;
3645*8fb009dcSAndroid Build Coastguard Worker }
3646*8fb009dcSAndroid Build Coastguard Worker
3647*8fb009dcSAndroid Build Coastguard Worker hs->extensions.received |= (1u << ext_index);
3648*8fb009dcSAndroid Build Coastguard Worker uint8_t alert = SSL_AD_DECODE_ERROR;
3649*8fb009dcSAndroid Build Coastguard Worker if (!ext->parse_clienthello(hs, &alert, &extension)) {
3650*8fb009dcSAndroid Build Coastguard Worker *out_alert = alert;
3651*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
3652*8fb009dcSAndroid Build Coastguard Worker ERR_add_error_dataf("extension %u", (unsigned)type);
3653*8fb009dcSAndroid Build Coastguard Worker return false;
3654*8fb009dcSAndroid Build Coastguard Worker }
3655*8fb009dcSAndroid Build Coastguard Worker }
3656*8fb009dcSAndroid Build Coastguard Worker
3657*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumExtensions; i++) {
3658*8fb009dcSAndroid Build Coastguard Worker if (hs->extensions.received & (1u << i)) {
3659*8fb009dcSAndroid Build Coastguard Worker continue;
3660*8fb009dcSAndroid Build Coastguard Worker }
3661*8fb009dcSAndroid Build Coastguard Worker
3662*8fb009dcSAndroid Build Coastguard Worker CBS *contents = NULL, fake_contents;
3663*8fb009dcSAndroid Build Coastguard Worker static const uint8_t kFakeRenegotiateExtension[] = {0};
3664*8fb009dcSAndroid Build Coastguard Worker if (kExtensions[i].value == TLSEXT_TYPE_renegotiate &&
3665*8fb009dcSAndroid Build Coastguard Worker ssl_client_cipher_list_contains_cipher(client_hello,
3666*8fb009dcSAndroid Build Coastguard Worker SSL3_CK_SCSV & 0xffff)) {
3667*8fb009dcSAndroid Build Coastguard Worker // The renegotiation SCSV was received so pretend that we received a
3668*8fb009dcSAndroid Build Coastguard Worker // renegotiation extension.
3669*8fb009dcSAndroid Build Coastguard Worker CBS_init(&fake_contents, kFakeRenegotiateExtension,
3670*8fb009dcSAndroid Build Coastguard Worker sizeof(kFakeRenegotiateExtension));
3671*8fb009dcSAndroid Build Coastguard Worker contents = &fake_contents;
3672*8fb009dcSAndroid Build Coastguard Worker hs->extensions.received |= (1u << i);
3673*8fb009dcSAndroid Build Coastguard Worker }
3674*8fb009dcSAndroid Build Coastguard Worker
3675*8fb009dcSAndroid Build Coastguard Worker // Extension wasn't observed so call the callback with a NULL
3676*8fb009dcSAndroid Build Coastguard Worker // parameter.
3677*8fb009dcSAndroid Build Coastguard Worker uint8_t alert = SSL_AD_DECODE_ERROR;
3678*8fb009dcSAndroid Build Coastguard Worker if (!kExtensions[i].parse_clienthello(hs, &alert, contents)) {
3679*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
3680*8fb009dcSAndroid Build Coastguard Worker ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3681*8fb009dcSAndroid Build Coastguard Worker *out_alert = alert;
3682*8fb009dcSAndroid Build Coastguard Worker return false;
3683*8fb009dcSAndroid Build Coastguard Worker }
3684*8fb009dcSAndroid Build Coastguard Worker }
3685*8fb009dcSAndroid Build Coastguard Worker
3686*8fb009dcSAndroid Build Coastguard Worker return true;
3687*8fb009dcSAndroid Build Coastguard Worker }
3688*8fb009dcSAndroid Build Coastguard Worker
ssl_parse_clienthello_tlsext(SSL_HANDSHAKE * hs,const SSL_CLIENT_HELLO * client_hello)3689*8fb009dcSAndroid Build Coastguard Worker bool ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs,
3690*8fb009dcSAndroid Build Coastguard Worker const SSL_CLIENT_HELLO *client_hello) {
3691*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
3692*8fb009dcSAndroid Build Coastguard Worker int alert = SSL_AD_DECODE_ERROR;
3693*8fb009dcSAndroid Build Coastguard Worker if (!ssl_scan_clienthello_tlsext(hs, client_hello, &alert)) {
3694*8fb009dcSAndroid Build Coastguard Worker ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
3695*8fb009dcSAndroid Build Coastguard Worker return false;
3696*8fb009dcSAndroid Build Coastguard Worker }
3697*8fb009dcSAndroid Build Coastguard Worker
3698*8fb009dcSAndroid Build Coastguard Worker if (!ssl_check_clienthello_tlsext(hs)) {
3699*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_TLSEXT);
3700*8fb009dcSAndroid Build Coastguard Worker return false;
3701*8fb009dcSAndroid Build Coastguard Worker }
3702*8fb009dcSAndroid Build Coastguard Worker
3703*8fb009dcSAndroid Build Coastguard Worker return true;
3704*8fb009dcSAndroid Build Coastguard Worker }
3705*8fb009dcSAndroid Build Coastguard Worker
ssl_scan_serverhello_tlsext(SSL_HANDSHAKE * hs,const CBS * cbs,int * out_alert)3706*8fb009dcSAndroid Build Coastguard Worker static bool ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs,
3707*8fb009dcSAndroid Build Coastguard Worker int *out_alert) {
3708*8fb009dcSAndroid Build Coastguard Worker CBS extensions = *cbs;
3709*8fb009dcSAndroid Build Coastguard Worker if (!tls1_check_duplicate_extensions(&extensions)) {
3710*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
3711*8fb009dcSAndroid Build Coastguard Worker return false;
3712*8fb009dcSAndroid Build Coastguard Worker }
3713*8fb009dcSAndroid Build Coastguard Worker
3714*8fb009dcSAndroid Build Coastguard Worker uint32_t received = 0;
3715*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&extensions) != 0) {
3716*8fb009dcSAndroid Build Coastguard Worker uint16_t type;
3717*8fb009dcSAndroid Build Coastguard Worker CBS extension;
3718*8fb009dcSAndroid Build Coastguard Worker
3719*8fb009dcSAndroid Build Coastguard Worker // Decode the next extension.
3720*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(&extensions, &type) ||
3721*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16_length_prefixed(&extensions, &extension)) {
3722*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_DECODE_ERROR;
3723*8fb009dcSAndroid Build Coastguard Worker return false;
3724*8fb009dcSAndroid Build Coastguard Worker }
3725*8fb009dcSAndroid Build Coastguard Worker
3726*8fb009dcSAndroid Build Coastguard Worker unsigned ext_index;
3727*8fb009dcSAndroid Build Coastguard Worker const struct tls_extension *const ext =
3728*8fb009dcSAndroid Build Coastguard Worker tls_extension_find(&ext_index, type);
3729*8fb009dcSAndroid Build Coastguard Worker
3730*8fb009dcSAndroid Build Coastguard Worker if (ext == NULL) {
3731*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
3732*8fb009dcSAndroid Build Coastguard Worker ERR_add_error_dataf("extension %u", (unsigned)type);
3733*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
3734*8fb009dcSAndroid Build Coastguard Worker return false;
3735*8fb009dcSAndroid Build Coastguard Worker }
3736*8fb009dcSAndroid Build Coastguard Worker
3737*8fb009dcSAndroid Build Coastguard Worker static_assert(kNumExtensions <= sizeof(hs->extensions.sent) * 8,
3738*8fb009dcSAndroid Build Coastguard Worker "too many bits");
3739*8fb009dcSAndroid Build Coastguard Worker
3740*8fb009dcSAndroid Build Coastguard Worker if (!(hs->extensions.sent & (1u << ext_index))) {
3741*8fb009dcSAndroid Build Coastguard Worker // If the extension was never sent then it is illegal.
3742*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
3743*8fb009dcSAndroid Build Coastguard Worker ERR_add_error_dataf("extension :%u", (unsigned)type);
3744*8fb009dcSAndroid Build Coastguard Worker *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
3745*8fb009dcSAndroid Build Coastguard Worker return false;
3746*8fb009dcSAndroid Build Coastguard Worker }
3747*8fb009dcSAndroid Build Coastguard Worker
3748*8fb009dcSAndroid Build Coastguard Worker received |= (1u << ext_index);
3749*8fb009dcSAndroid Build Coastguard Worker
3750*8fb009dcSAndroid Build Coastguard Worker uint8_t alert = SSL_AD_DECODE_ERROR;
3751*8fb009dcSAndroid Build Coastguard Worker if (!ext->parse_serverhello(hs, &alert, &extension)) {
3752*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
3753*8fb009dcSAndroid Build Coastguard Worker ERR_add_error_dataf("extension %u", (unsigned)type);
3754*8fb009dcSAndroid Build Coastguard Worker *out_alert = alert;
3755*8fb009dcSAndroid Build Coastguard Worker return false;
3756*8fb009dcSAndroid Build Coastguard Worker }
3757*8fb009dcSAndroid Build Coastguard Worker }
3758*8fb009dcSAndroid Build Coastguard Worker
3759*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumExtensions; i++) {
3760*8fb009dcSAndroid Build Coastguard Worker if (!(received & (1u << i))) {
3761*8fb009dcSAndroid Build Coastguard Worker // Extension wasn't observed so call the callback with a NULL
3762*8fb009dcSAndroid Build Coastguard Worker // parameter.
3763*8fb009dcSAndroid Build Coastguard Worker uint8_t alert = SSL_AD_DECODE_ERROR;
3764*8fb009dcSAndroid Build Coastguard Worker if (!kExtensions[i].parse_serverhello(hs, &alert, NULL)) {
3765*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
3766*8fb009dcSAndroid Build Coastguard Worker ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3767*8fb009dcSAndroid Build Coastguard Worker *out_alert = alert;
3768*8fb009dcSAndroid Build Coastguard Worker return false;
3769*8fb009dcSAndroid Build Coastguard Worker }
3770*8fb009dcSAndroid Build Coastguard Worker }
3771*8fb009dcSAndroid Build Coastguard Worker }
3772*8fb009dcSAndroid Build Coastguard Worker
3773*8fb009dcSAndroid Build Coastguard Worker return true;
3774*8fb009dcSAndroid Build Coastguard Worker }
3775*8fb009dcSAndroid Build Coastguard Worker
ssl_check_clienthello_tlsext(SSL_HANDSHAKE * hs)3776*8fb009dcSAndroid Build Coastguard Worker static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) {
3777*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
3778*8fb009dcSAndroid Build Coastguard Worker int ret = SSL_TLSEXT_ERR_NOACK;
3779*8fb009dcSAndroid Build Coastguard Worker int al = SSL_AD_UNRECOGNIZED_NAME;
3780*8fb009dcSAndroid Build Coastguard Worker if (ssl->ctx->servername_callback != 0) {
3781*8fb009dcSAndroid Build Coastguard Worker ret = ssl->ctx->servername_callback(ssl, &al, ssl->ctx->servername_arg);
3782*8fb009dcSAndroid Build Coastguard Worker } else if (ssl->session_ctx->servername_callback != 0) {
3783*8fb009dcSAndroid Build Coastguard Worker ret = ssl->session_ctx->servername_callback(
3784*8fb009dcSAndroid Build Coastguard Worker ssl, &al, ssl->session_ctx->servername_arg);
3785*8fb009dcSAndroid Build Coastguard Worker }
3786*8fb009dcSAndroid Build Coastguard Worker
3787*8fb009dcSAndroid Build Coastguard Worker switch (ret) {
3788*8fb009dcSAndroid Build Coastguard Worker case SSL_TLSEXT_ERR_ALERT_FATAL:
3789*8fb009dcSAndroid Build Coastguard Worker ssl_send_alert(ssl, SSL3_AL_FATAL, al);
3790*8fb009dcSAndroid Build Coastguard Worker return false;
3791*8fb009dcSAndroid Build Coastguard Worker
3792*8fb009dcSAndroid Build Coastguard Worker case SSL_TLSEXT_ERR_NOACK:
3793*8fb009dcSAndroid Build Coastguard Worker hs->should_ack_sni = false;
3794*8fb009dcSAndroid Build Coastguard Worker return true;
3795*8fb009dcSAndroid Build Coastguard Worker
3796*8fb009dcSAndroid Build Coastguard Worker default:
3797*8fb009dcSAndroid Build Coastguard Worker hs->should_ack_sni = ssl->s3->hostname != nullptr;
3798*8fb009dcSAndroid Build Coastguard Worker return true;
3799*8fb009dcSAndroid Build Coastguard Worker }
3800*8fb009dcSAndroid Build Coastguard Worker }
3801*8fb009dcSAndroid Build Coastguard Worker
ssl_check_serverhello_tlsext(SSL_HANDSHAKE * hs)3802*8fb009dcSAndroid Build Coastguard Worker static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs) {
3803*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
3804*8fb009dcSAndroid Build Coastguard Worker // ALPS and ALPN have a dependency between each other, so we defer checking
3805*8fb009dcSAndroid Build Coastguard Worker // consistency to after the callbacks run.
3806*8fb009dcSAndroid Build Coastguard Worker if (hs->new_session != nullptr && hs->new_session->has_application_settings) {
3807*8fb009dcSAndroid Build Coastguard Worker // ALPN must be negotiated.
3808*8fb009dcSAndroid Build Coastguard Worker if (ssl->s3->alpn_selected.empty()) {
3809*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_ALPS_WITHOUT_ALPN);
3810*8fb009dcSAndroid Build Coastguard Worker ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
3811*8fb009dcSAndroid Build Coastguard Worker return false;
3812*8fb009dcSAndroid Build Coastguard Worker }
3813*8fb009dcSAndroid Build Coastguard Worker
3814*8fb009dcSAndroid Build Coastguard Worker // The negotiated protocol must be one of the ones we advertised for ALPS.
3815*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> settings;
3816*8fb009dcSAndroid Build Coastguard Worker if (!ssl_get_local_application_settings(hs, &settings,
3817*8fb009dcSAndroid Build Coastguard Worker ssl->s3->alpn_selected)) {
3818*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
3819*8fb009dcSAndroid Build Coastguard Worker ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
3820*8fb009dcSAndroid Build Coastguard Worker return false;
3821*8fb009dcSAndroid Build Coastguard Worker }
3822*8fb009dcSAndroid Build Coastguard Worker
3823*8fb009dcSAndroid Build Coastguard Worker if (!hs->new_session->local_application_settings.CopyFrom(settings)) {
3824*8fb009dcSAndroid Build Coastguard Worker ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
3825*8fb009dcSAndroid Build Coastguard Worker return false;
3826*8fb009dcSAndroid Build Coastguard Worker }
3827*8fb009dcSAndroid Build Coastguard Worker }
3828*8fb009dcSAndroid Build Coastguard Worker
3829*8fb009dcSAndroid Build Coastguard Worker return true;
3830*8fb009dcSAndroid Build Coastguard Worker }
3831*8fb009dcSAndroid Build Coastguard Worker
ssl_parse_serverhello_tlsext(SSL_HANDSHAKE * hs,const CBS * cbs)3832*8fb009dcSAndroid Build Coastguard Worker bool ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs) {
3833*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
3834*8fb009dcSAndroid Build Coastguard Worker int alert = SSL_AD_DECODE_ERROR;
3835*8fb009dcSAndroid Build Coastguard Worker if (!ssl_scan_serverhello_tlsext(hs, cbs, &alert)) {
3836*8fb009dcSAndroid Build Coastguard Worker ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
3837*8fb009dcSAndroid Build Coastguard Worker return false;
3838*8fb009dcSAndroid Build Coastguard Worker }
3839*8fb009dcSAndroid Build Coastguard Worker
3840*8fb009dcSAndroid Build Coastguard Worker if (!ssl_check_serverhello_tlsext(hs)) {
3841*8fb009dcSAndroid Build Coastguard Worker return false;
3842*8fb009dcSAndroid Build Coastguard Worker }
3843*8fb009dcSAndroid Build Coastguard Worker
3844*8fb009dcSAndroid Build Coastguard Worker return true;
3845*8fb009dcSAndroid Build Coastguard Worker }
3846*8fb009dcSAndroid Build Coastguard Worker
decrypt_ticket_with_cipher_ctx(Array<uint8_t> * out,EVP_CIPHER_CTX * cipher_ctx,HMAC_CTX * hmac_ctx,Span<const uint8_t> ticket)3847*8fb009dcSAndroid Build Coastguard Worker static enum ssl_ticket_aead_result_t decrypt_ticket_with_cipher_ctx(
3848*8fb009dcSAndroid Build Coastguard Worker Array<uint8_t> *out, EVP_CIPHER_CTX *cipher_ctx, HMAC_CTX *hmac_ctx,
3849*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> ticket) {
3850*8fb009dcSAndroid Build Coastguard Worker size_t iv_len = EVP_CIPHER_CTX_iv_length(cipher_ctx);
3851*8fb009dcSAndroid Build Coastguard Worker
3852*8fb009dcSAndroid Build Coastguard Worker // Check the MAC at the end of the ticket.
3853*8fb009dcSAndroid Build Coastguard Worker uint8_t mac[EVP_MAX_MD_SIZE];
3854*8fb009dcSAndroid Build Coastguard Worker size_t mac_len = HMAC_size(hmac_ctx);
3855*8fb009dcSAndroid Build Coastguard Worker if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + iv_len + 1 + mac_len) {
3856*8fb009dcSAndroid Build Coastguard Worker // The ticket must be large enough for key name, IV, data, and MAC.
3857*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_ignore_ticket;
3858*8fb009dcSAndroid Build Coastguard Worker }
3859*8fb009dcSAndroid Build Coastguard Worker // Split the ticket into the ticket and the MAC.
3860*8fb009dcSAndroid Build Coastguard Worker auto ticket_mac = ticket.last(mac_len);
3861*8fb009dcSAndroid Build Coastguard Worker ticket = ticket.first(ticket.size() - mac_len);
3862*8fb009dcSAndroid Build Coastguard Worker HMAC_Update(hmac_ctx, ticket.data(), ticket.size());
3863*8fb009dcSAndroid Build Coastguard Worker HMAC_Final(hmac_ctx, mac, NULL);
3864*8fb009dcSAndroid Build Coastguard Worker assert(mac_len == ticket_mac.size());
3865*8fb009dcSAndroid Build Coastguard Worker bool mac_ok = CRYPTO_memcmp(mac, ticket_mac.data(), mac_len) == 0;
3866*8fb009dcSAndroid Build Coastguard Worker #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
3867*8fb009dcSAndroid Build Coastguard Worker mac_ok = true;
3868*8fb009dcSAndroid Build Coastguard Worker #endif
3869*8fb009dcSAndroid Build Coastguard Worker if (!mac_ok) {
3870*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_ignore_ticket;
3871*8fb009dcSAndroid Build Coastguard Worker }
3872*8fb009dcSAndroid Build Coastguard Worker
3873*8fb009dcSAndroid Build Coastguard Worker // Decrypt the session data.
3874*8fb009dcSAndroid Build Coastguard Worker auto ciphertext = ticket.subspan(SSL_TICKET_KEY_NAME_LEN + iv_len);
3875*8fb009dcSAndroid Build Coastguard Worker Array<uint8_t> plaintext;
3876*8fb009dcSAndroid Build Coastguard Worker #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
3877*8fb009dcSAndroid Build Coastguard Worker if (!plaintext.CopyFrom(ciphertext)) {
3878*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_error;
3879*8fb009dcSAndroid Build Coastguard Worker }
3880*8fb009dcSAndroid Build Coastguard Worker #else
3881*8fb009dcSAndroid Build Coastguard Worker if (ciphertext.size() >= INT_MAX) {
3882*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_ignore_ticket;
3883*8fb009dcSAndroid Build Coastguard Worker }
3884*8fb009dcSAndroid Build Coastguard Worker if (!plaintext.Init(ciphertext.size())) {
3885*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_error;
3886*8fb009dcSAndroid Build Coastguard Worker }
3887*8fb009dcSAndroid Build Coastguard Worker int len1, len2;
3888*8fb009dcSAndroid Build Coastguard Worker if (!EVP_DecryptUpdate(cipher_ctx, plaintext.data(), &len1, ciphertext.data(),
3889*8fb009dcSAndroid Build Coastguard Worker (int)ciphertext.size()) ||
3890*8fb009dcSAndroid Build Coastguard Worker !EVP_DecryptFinal_ex(cipher_ctx, plaintext.data() + len1, &len2)) {
3891*8fb009dcSAndroid Build Coastguard Worker ERR_clear_error();
3892*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_ignore_ticket;
3893*8fb009dcSAndroid Build Coastguard Worker }
3894*8fb009dcSAndroid Build Coastguard Worker plaintext.Shrink(static_cast<size_t>(len1) + len2);
3895*8fb009dcSAndroid Build Coastguard Worker #endif
3896*8fb009dcSAndroid Build Coastguard Worker
3897*8fb009dcSAndroid Build Coastguard Worker *out = std::move(plaintext);
3898*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_success;
3899*8fb009dcSAndroid Build Coastguard Worker }
3900*8fb009dcSAndroid Build Coastguard Worker
ssl_decrypt_ticket_with_cb(SSL_HANDSHAKE * hs,Array<uint8_t> * out,bool * out_renew_ticket,Span<const uint8_t> ticket)3901*8fb009dcSAndroid Build Coastguard Worker static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_cb(
3902*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket,
3903*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> ticket) {
3904*8fb009dcSAndroid Build Coastguard Worker assert(ticket.size() >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH);
3905*8fb009dcSAndroid Build Coastguard Worker ScopedEVP_CIPHER_CTX cipher_ctx;
3906*8fb009dcSAndroid Build Coastguard Worker ScopedHMAC_CTX hmac_ctx;
3907*8fb009dcSAndroid Build Coastguard Worker auto name = ticket.subspan(0, SSL_TICKET_KEY_NAME_LEN);
3908*8fb009dcSAndroid Build Coastguard Worker // The actual IV is shorter, but the length is determined by the callback's
3909*8fb009dcSAndroid Build Coastguard Worker // chosen cipher. Instead we pass in |EVP_MAX_IV_LENGTH| worth of IV to ensure
3910*8fb009dcSAndroid Build Coastguard Worker // the callback has enough.
3911*8fb009dcSAndroid Build Coastguard Worker auto iv = ticket.subspan(SSL_TICKET_KEY_NAME_LEN, EVP_MAX_IV_LENGTH);
3912*8fb009dcSAndroid Build Coastguard Worker int cb_ret = hs->ssl->session_ctx->ticket_key_cb(
3913*8fb009dcSAndroid Build Coastguard Worker hs->ssl, const_cast<uint8_t *>(name.data()),
3914*8fb009dcSAndroid Build Coastguard Worker const_cast<uint8_t *>(iv.data()), cipher_ctx.get(), hmac_ctx.get(),
3915*8fb009dcSAndroid Build Coastguard Worker 0 /* decrypt */);
3916*8fb009dcSAndroid Build Coastguard Worker if (cb_ret < 0) {
3917*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_error;
3918*8fb009dcSAndroid Build Coastguard Worker } else if (cb_ret == 0) {
3919*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_ignore_ticket;
3920*8fb009dcSAndroid Build Coastguard Worker } else if (cb_ret == 2) {
3921*8fb009dcSAndroid Build Coastguard Worker *out_renew_ticket = true;
3922*8fb009dcSAndroid Build Coastguard Worker } else {
3923*8fb009dcSAndroid Build Coastguard Worker assert(cb_ret == 1);
3924*8fb009dcSAndroid Build Coastguard Worker }
3925*8fb009dcSAndroid Build Coastguard Worker return decrypt_ticket_with_cipher_ctx(out, cipher_ctx.get(), hmac_ctx.get(),
3926*8fb009dcSAndroid Build Coastguard Worker ticket);
3927*8fb009dcSAndroid Build Coastguard Worker }
3928*8fb009dcSAndroid Build Coastguard Worker
ssl_decrypt_ticket_with_ticket_keys(SSL_HANDSHAKE * hs,Array<uint8_t> * out,Span<const uint8_t> ticket)3929*8fb009dcSAndroid Build Coastguard Worker static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_ticket_keys(
3930*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE *hs, Array<uint8_t> *out, Span<const uint8_t> ticket) {
3931*8fb009dcSAndroid Build Coastguard Worker assert(ticket.size() >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH);
3932*8fb009dcSAndroid Build Coastguard Worker SSL_CTX *ctx = hs->ssl->session_ctx.get();
3933*8fb009dcSAndroid Build Coastguard Worker
3934*8fb009dcSAndroid Build Coastguard Worker // Rotate the ticket key if necessary.
3935*8fb009dcSAndroid Build Coastguard Worker if (!ssl_ctx_rotate_ticket_encryption_key(ctx)) {
3936*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_error;
3937*8fb009dcSAndroid Build Coastguard Worker }
3938*8fb009dcSAndroid Build Coastguard Worker
3939*8fb009dcSAndroid Build Coastguard Worker const EVP_CIPHER *cipher = EVP_aes_128_cbc();
3940*8fb009dcSAndroid Build Coastguard Worker auto name = ticket.subspan(0, SSL_TICKET_KEY_NAME_LEN);
3941*8fb009dcSAndroid Build Coastguard Worker auto iv =
3942*8fb009dcSAndroid Build Coastguard Worker ticket.subspan(SSL_TICKET_KEY_NAME_LEN, EVP_CIPHER_iv_length(cipher));
3943*8fb009dcSAndroid Build Coastguard Worker
3944*8fb009dcSAndroid Build Coastguard Worker // Pick the matching ticket key and decrypt.
3945*8fb009dcSAndroid Build Coastguard Worker ScopedEVP_CIPHER_CTX cipher_ctx;
3946*8fb009dcSAndroid Build Coastguard Worker ScopedHMAC_CTX hmac_ctx;
3947*8fb009dcSAndroid Build Coastguard Worker {
3948*8fb009dcSAndroid Build Coastguard Worker MutexReadLock lock(&ctx->lock);
3949*8fb009dcSAndroid Build Coastguard Worker const TicketKey *key;
3950*8fb009dcSAndroid Build Coastguard Worker if (ctx->ticket_key_current && name == ctx->ticket_key_current->name) {
3951*8fb009dcSAndroid Build Coastguard Worker key = ctx->ticket_key_current.get();
3952*8fb009dcSAndroid Build Coastguard Worker } else if (ctx->ticket_key_prev && name == ctx->ticket_key_prev->name) {
3953*8fb009dcSAndroid Build Coastguard Worker key = ctx->ticket_key_prev.get();
3954*8fb009dcSAndroid Build Coastguard Worker } else {
3955*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_ignore_ticket;
3956*8fb009dcSAndroid Build Coastguard Worker }
3957*8fb009dcSAndroid Build Coastguard Worker if (!HMAC_Init_ex(hmac_ctx.get(), key->hmac_key, sizeof(key->hmac_key),
3958*8fb009dcSAndroid Build Coastguard Worker tlsext_tick_md(), NULL) ||
3959*8fb009dcSAndroid Build Coastguard Worker !EVP_DecryptInit_ex(cipher_ctx.get(), cipher, NULL,
3960*8fb009dcSAndroid Build Coastguard Worker key->aes_key, iv.data())) {
3961*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_error;
3962*8fb009dcSAndroid Build Coastguard Worker }
3963*8fb009dcSAndroid Build Coastguard Worker }
3964*8fb009dcSAndroid Build Coastguard Worker return decrypt_ticket_with_cipher_ctx(out, cipher_ctx.get(), hmac_ctx.get(),
3965*8fb009dcSAndroid Build Coastguard Worker ticket);
3966*8fb009dcSAndroid Build Coastguard Worker }
3967*8fb009dcSAndroid Build Coastguard Worker
ssl_decrypt_ticket_with_method(SSL_HANDSHAKE * hs,Array<uint8_t> * out,bool * out_renew_ticket,Span<const uint8_t> ticket)3968*8fb009dcSAndroid Build Coastguard Worker static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_method(
3969*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket,
3970*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> ticket) {
3971*8fb009dcSAndroid Build Coastguard Worker Array<uint8_t> plaintext;
3972*8fb009dcSAndroid Build Coastguard Worker if (!plaintext.Init(ticket.size())) {
3973*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_error;
3974*8fb009dcSAndroid Build Coastguard Worker }
3975*8fb009dcSAndroid Build Coastguard Worker
3976*8fb009dcSAndroid Build Coastguard Worker size_t plaintext_len;
3977*8fb009dcSAndroid Build Coastguard Worker const enum ssl_ticket_aead_result_t result =
3978*8fb009dcSAndroid Build Coastguard Worker hs->ssl->session_ctx->ticket_aead_method->open(
3979*8fb009dcSAndroid Build Coastguard Worker hs->ssl, plaintext.data(), &plaintext_len, ticket.size(),
3980*8fb009dcSAndroid Build Coastguard Worker ticket.data(), ticket.size());
3981*8fb009dcSAndroid Build Coastguard Worker if (result != ssl_ticket_aead_success) {
3982*8fb009dcSAndroid Build Coastguard Worker return result;
3983*8fb009dcSAndroid Build Coastguard Worker }
3984*8fb009dcSAndroid Build Coastguard Worker
3985*8fb009dcSAndroid Build Coastguard Worker plaintext.Shrink(plaintext_len);
3986*8fb009dcSAndroid Build Coastguard Worker *out = std::move(plaintext);
3987*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_success;
3988*8fb009dcSAndroid Build Coastguard Worker }
3989*8fb009dcSAndroid Build Coastguard Worker
ssl_process_ticket(SSL_HANDSHAKE * hs,UniquePtr<SSL_SESSION> * out_session,bool * out_renew_ticket,Span<const uint8_t> ticket,Span<const uint8_t> session_id)3990*8fb009dcSAndroid Build Coastguard Worker enum ssl_ticket_aead_result_t ssl_process_ticket(
3991*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE *hs, UniquePtr<SSL_SESSION> *out_session,
3992*8fb009dcSAndroid Build Coastguard Worker bool *out_renew_ticket, Span<const uint8_t> ticket,
3993*8fb009dcSAndroid Build Coastguard Worker Span<const uint8_t> session_id) {
3994*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
3995*8fb009dcSAndroid Build Coastguard Worker *out_renew_ticket = false;
3996*8fb009dcSAndroid Build Coastguard Worker out_session->reset();
3997*8fb009dcSAndroid Build Coastguard Worker
3998*8fb009dcSAndroid Build Coastguard Worker if ((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) ||
3999*8fb009dcSAndroid Build Coastguard Worker session_id.size() > SSL_MAX_SSL_SESSION_ID_LENGTH) {
4000*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_ignore_ticket;
4001*8fb009dcSAndroid Build Coastguard Worker }
4002*8fb009dcSAndroid Build Coastguard Worker
4003*8fb009dcSAndroid Build Coastguard Worker // Tickets in TLS 1.3 are tied into pre-shared keys (PSKs), unlike in TLS 1.2
4004*8fb009dcSAndroid Build Coastguard Worker // where that concept doesn't exist. The |decrypted_psk| and |ignore_psk|
4005*8fb009dcSAndroid Build Coastguard Worker // hints only apply to PSKs. We check the version to determine which this is.
4006*8fb009dcSAndroid Build Coastguard Worker const bool is_psk = ssl_protocol_version(ssl) >= TLS1_3_VERSION;
4007*8fb009dcSAndroid Build Coastguard Worker
4008*8fb009dcSAndroid Build Coastguard Worker Array<uint8_t> plaintext;
4009*8fb009dcSAndroid Build Coastguard Worker enum ssl_ticket_aead_result_t result;
4010*8fb009dcSAndroid Build Coastguard Worker SSL_HANDSHAKE_HINTS *const hints = hs->hints.get();
4011*8fb009dcSAndroid Build Coastguard Worker if (is_psk && hints && !hs->hints_requested &&
4012*8fb009dcSAndroid Build Coastguard Worker !hints->decrypted_psk.empty()) {
4013*8fb009dcSAndroid Build Coastguard Worker result = plaintext.CopyFrom(hints->decrypted_psk) ? ssl_ticket_aead_success
4014*8fb009dcSAndroid Build Coastguard Worker : ssl_ticket_aead_error;
4015*8fb009dcSAndroid Build Coastguard Worker } else if (is_psk && hints && !hs->hints_requested && hints->ignore_psk) {
4016*8fb009dcSAndroid Build Coastguard Worker result = ssl_ticket_aead_ignore_ticket;
4017*8fb009dcSAndroid Build Coastguard Worker } else if (!is_psk && hints && !hs->hints_requested &&
4018*8fb009dcSAndroid Build Coastguard Worker !hints->decrypted_ticket.empty()) {
4019*8fb009dcSAndroid Build Coastguard Worker if (plaintext.CopyFrom(hints->decrypted_ticket)) {
4020*8fb009dcSAndroid Build Coastguard Worker result = ssl_ticket_aead_success;
4021*8fb009dcSAndroid Build Coastguard Worker *out_renew_ticket = hints->renew_ticket;
4022*8fb009dcSAndroid Build Coastguard Worker } else {
4023*8fb009dcSAndroid Build Coastguard Worker result = ssl_ticket_aead_error;
4024*8fb009dcSAndroid Build Coastguard Worker }
4025*8fb009dcSAndroid Build Coastguard Worker } else if (!is_psk && hints && !hs->hints_requested && hints->ignore_ticket) {
4026*8fb009dcSAndroid Build Coastguard Worker result = ssl_ticket_aead_ignore_ticket;
4027*8fb009dcSAndroid Build Coastguard Worker } else if (ssl->session_ctx->ticket_aead_method != NULL) {
4028*8fb009dcSAndroid Build Coastguard Worker result = ssl_decrypt_ticket_with_method(hs, &plaintext, out_renew_ticket,
4029*8fb009dcSAndroid Build Coastguard Worker ticket);
4030*8fb009dcSAndroid Build Coastguard Worker } else {
4031*8fb009dcSAndroid Build Coastguard Worker // Ensure there is room for the key name and the largest IV |ticket_key_cb|
4032*8fb009dcSAndroid Build Coastguard Worker // may try to consume. The real limit may be lower, but the maximum IV
4033*8fb009dcSAndroid Build Coastguard Worker // length should be well under the minimum size for the session material and
4034*8fb009dcSAndroid Build Coastguard Worker // HMAC.
4035*8fb009dcSAndroid Build Coastguard Worker if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) {
4036*8fb009dcSAndroid Build Coastguard Worker result = ssl_ticket_aead_ignore_ticket;
4037*8fb009dcSAndroid Build Coastguard Worker } else if (ssl->session_ctx->ticket_key_cb != NULL) {
4038*8fb009dcSAndroid Build Coastguard Worker result =
4039*8fb009dcSAndroid Build Coastguard Worker ssl_decrypt_ticket_with_cb(hs, &plaintext, out_renew_ticket, ticket);
4040*8fb009dcSAndroid Build Coastguard Worker } else {
4041*8fb009dcSAndroid Build Coastguard Worker result = ssl_decrypt_ticket_with_ticket_keys(hs, &plaintext, ticket);
4042*8fb009dcSAndroid Build Coastguard Worker }
4043*8fb009dcSAndroid Build Coastguard Worker }
4044*8fb009dcSAndroid Build Coastguard Worker
4045*8fb009dcSAndroid Build Coastguard Worker if (hints && hs->hints_requested) {
4046*8fb009dcSAndroid Build Coastguard Worker if (result == ssl_ticket_aead_ignore_ticket) {
4047*8fb009dcSAndroid Build Coastguard Worker if (is_psk) {
4048*8fb009dcSAndroid Build Coastguard Worker hints->ignore_psk = true;
4049*8fb009dcSAndroid Build Coastguard Worker } else {
4050*8fb009dcSAndroid Build Coastguard Worker hints->ignore_ticket = true;
4051*8fb009dcSAndroid Build Coastguard Worker }
4052*8fb009dcSAndroid Build Coastguard Worker } else if (result == ssl_ticket_aead_success) {
4053*8fb009dcSAndroid Build Coastguard Worker if (is_psk) {
4054*8fb009dcSAndroid Build Coastguard Worker if (!hints->decrypted_psk.CopyFrom(plaintext)) {
4055*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_error;
4056*8fb009dcSAndroid Build Coastguard Worker }
4057*8fb009dcSAndroid Build Coastguard Worker } else {
4058*8fb009dcSAndroid Build Coastguard Worker if (!hints->decrypted_ticket.CopyFrom(plaintext)) {
4059*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_error;
4060*8fb009dcSAndroid Build Coastguard Worker }
4061*8fb009dcSAndroid Build Coastguard Worker hints->renew_ticket = *out_renew_ticket;
4062*8fb009dcSAndroid Build Coastguard Worker }
4063*8fb009dcSAndroid Build Coastguard Worker }
4064*8fb009dcSAndroid Build Coastguard Worker }
4065*8fb009dcSAndroid Build Coastguard Worker
4066*8fb009dcSAndroid Build Coastguard Worker if (result != ssl_ticket_aead_success) {
4067*8fb009dcSAndroid Build Coastguard Worker return result;
4068*8fb009dcSAndroid Build Coastguard Worker }
4069*8fb009dcSAndroid Build Coastguard Worker
4070*8fb009dcSAndroid Build Coastguard Worker // Decode the session.
4071*8fb009dcSAndroid Build Coastguard Worker UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(
4072*8fb009dcSAndroid Build Coastguard Worker plaintext.data(), plaintext.size(), ssl->ctx.get()));
4073*8fb009dcSAndroid Build Coastguard Worker if (!session) {
4074*8fb009dcSAndroid Build Coastguard Worker ERR_clear_error(); // Don't leave an error on the queue.
4075*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_ignore_ticket;
4076*8fb009dcSAndroid Build Coastguard Worker }
4077*8fb009dcSAndroid Build Coastguard Worker
4078*8fb009dcSAndroid Build Coastguard Worker // Envoy's tests expect the session to have a session ID that matches the
4079*8fb009dcSAndroid Build Coastguard Worker // placeholder used by the client. It's unclear whether this is a good idea,
4080*8fb009dcSAndroid Build Coastguard Worker // but we maintain it for now.
4081*8fb009dcSAndroid Build Coastguard Worker SHA256(ticket.data(), ticket.size(), session->session_id);
4082*8fb009dcSAndroid Build Coastguard Worker // Other consumers may expect a non-empty session ID to indicate resumption.
4083*8fb009dcSAndroid Build Coastguard Worker session->session_id_length = SHA256_DIGEST_LENGTH;
4084*8fb009dcSAndroid Build Coastguard Worker
4085*8fb009dcSAndroid Build Coastguard Worker *out_session = std::move(session);
4086*8fb009dcSAndroid Build Coastguard Worker return ssl_ticket_aead_success;
4087*8fb009dcSAndroid Build Coastguard Worker }
4088*8fb009dcSAndroid Build Coastguard Worker
tls1_parse_peer_sigalgs(SSL_HANDSHAKE * hs,const CBS * in_sigalgs)4089*8fb009dcSAndroid Build Coastguard Worker bool tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) {
4090*8fb009dcSAndroid Build Coastguard Worker // Extension ignored for inappropriate versions
4091*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(hs->ssl) < TLS1_2_VERSION) {
4092*8fb009dcSAndroid Build Coastguard Worker return true;
4093*8fb009dcSAndroid Build Coastguard Worker }
4094*8fb009dcSAndroid Build Coastguard Worker
4095*8fb009dcSAndroid Build Coastguard Worker // In all contexts, the signature algorithms list may not be empty. (It may be
4096*8fb009dcSAndroid Build Coastguard Worker // omitted by clients in TLS 1.2, but then the entire extension is omitted.)
4097*8fb009dcSAndroid Build Coastguard Worker return CBS_len(in_sigalgs) != 0 &&
4098*8fb009dcSAndroid Build Coastguard Worker parse_u16_array(in_sigalgs, &hs->peer_sigalgs);
4099*8fb009dcSAndroid Build Coastguard Worker }
4100*8fb009dcSAndroid Build Coastguard Worker
tls1_get_legacy_signature_algorithm(uint16_t * out,const EVP_PKEY * pkey)4101*8fb009dcSAndroid Build Coastguard Worker bool tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey) {
4102*8fb009dcSAndroid Build Coastguard Worker switch (EVP_PKEY_id(pkey)) {
4103*8fb009dcSAndroid Build Coastguard Worker case EVP_PKEY_RSA:
4104*8fb009dcSAndroid Build Coastguard Worker *out = SSL_SIGN_RSA_PKCS1_MD5_SHA1;
4105*8fb009dcSAndroid Build Coastguard Worker return true;
4106*8fb009dcSAndroid Build Coastguard Worker case EVP_PKEY_EC:
4107*8fb009dcSAndroid Build Coastguard Worker *out = SSL_SIGN_ECDSA_SHA1;
4108*8fb009dcSAndroid Build Coastguard Worker return true;
4109*8fb009dcSAndroid Build Coastguard Worker default:
4110*8fb009dcSAndroid Build Coastguard Worker return false;
4111*8fb009dcSAndroid Build Coastguard Worker }
4112*8fb009dcSAndroid Build Coastguard Worker }
4113*8fb009dcSAndroid Build Coastguard Worker
tls1_choose_signature_algorithm(SSL_HANDSHAKE * hs,const SSL_CREDENTIAL * cred,uint16_t * out)4114*8fb009dcSAndroid Build Coastguard Worker bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs,
4115*8fb009dcSAndroid Build Coastguard Worker const SSL_CREDENTIAL *cred,
4116*8fb009dcSAndroid Build Coastguard Worker uint16_t *out) {
4117*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
4118*8fb009dcSAndroid Build Coastguard Worker if (!cred->UsesPrivateKey()) {
4119*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
4120*8fb009dcSAndroid Build Coastguard Worker return false;
4121*8fb009dcSAndroid Build Coastguard Worker }
4122*8fb009dcSAndroid Build Coastguard Worker
4123*8fb009dcSAndroid Build Coastguard Worker // Before TLS 1.2, the signature algorithm isn't negotiated as part of the
4124*8fb009dcSAndroid Build Coastguard Worker // handshake.
4125*8fb009dcSAndroid Build Coastguard Worker uint16_t version = ssl_protocol_version(ssl);
4126*8fb009dcSAndroid Build Coastguard Worker if (version < TLS1_2_VERSION) {
4127*8fb009dcSAndroid Build Coastguard Worker if (!tls1_get_legacy_signature_algorithm(out, cred->pubkey.get())) {
4128*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
4129*8fb009dcSAndroid Build Coastguard Worker return false;
4130*8fb009dcSAndroid Build Coastguard Worker }
4131*8fb009dcSAndroid Build Coastguard Worker return true;
4132*8fb009dcSAndroid Build Coastguard Worker }
4133*8fb009dcSAndroid Build Coastguard Worker
4134*8fb009dcSAndroid Build Coastguard Worker Span<const uint16_t> peer_sigalgs;
4135*8fb009dcSAndroid Build Coastguard Worker if (cred->type == SSLCredentialType::kDelegated) {
4136*8fb009dcSAndroid Build Coastguard Worker peer_sigalgs = hs->peer_delegated_credential_sigalgs;
4137*8fb009dcSAndroid Build Coastguard Worker } else {
4138*8fb009dcSAndroid Build Coastguard Worker peer_sigalgs = hs->peer_sigalgs;
4139*8fb009dcSAndroid Build Coastguard Worker if (peer_sigalgs.empty() && version == TLS1_2_VERSION) {
4140*8fb009dcSAndroid Build Coastguard Worker // If the client didn't specify any signature_algorithms extension, it is
4141*8fb009dcSAndroid Build Coastguard Worker // interpreted as SHA-1. See
4142*8fb009dcSAndroid Build Coastguard Worker // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
4143*8fb009dcSAndroid Build Coastguard Worker static const uint16_t kTLS12Default[] = {SSL_SIGN_RSA_PKCS1_SHA1,
4144*8fb009dcSAndroid Build Coastguard Worker SSL_SIGN_ECDSA_SHA1};
4145*8fb009dcSAndroid Build Coastguard Worker peer_sigalgs = kTLS12Default;
4146*8fb009dcSAndroid Build Coastguard Worker }
4147*8fb009dcSAndroid Build Coastguard Worker }
4148*8fb009dcSAndroid Build Coastguard Worker
4149*8fb009dcSAndroid Build Coastguard Worker Span<const uint16_t> sigalgs = cred->sigalgs.empty()
4150*8fb009dcSAndroid Build Coastguard Worker ? MakeConstSpan(kSignSignatureAlgorithms)
4151*8fb009dcSAndroid Build Coastguard Worker : cred->sigalgs;
4152*8fb009dcSAndroid Build Coastguard Worker for (uint16_t sigalg : sigalgs) {
4153*8fb009dcSAndroid Build Coastguard Worker if (!ssl_pkey_supports_algorithm(ssl, cred->pubkey.get(), sigalg,
4154*8fb009dcSAndroid Build Coastguard Worker /*is_verify=*/false)) {
4155*8fb009dcSAndroid Build Coastguard Worker continue;
4156*8fb009dcSAndroid Build Coastguard Worker }
4157*8fb009dcSAndroid Build Coastguard Worker
4158*8fb009dcSAndroid Build Coastguard Worker if (std::find(peer_sigalgs.begin(), peer_sigalgs.end(), sigalg) !=
4159*8fb009dcSAndroid Build Coastguard Worker peer_sigalgs.end()) {
4160*8fb009dcSAndroid Build Coastguard Worker *out = sigalg;
4161*8fb009dcSAndroid Build Coastguard Worker return true;
4162*8fb009dcSAndroid Build Coastguard Worker }
4163*8fb009dcSAndroid Build Coastguard Worker }
4164*8fb009dcSAndroid Build Coastguard Worker
4165*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
4166*8fb009dcSAndroid Build Coastguard Worker return false;
4167*8fb009dcSAndroid Build Coastguard Worker }
4168*8fb009dcSAndroid Build Coastguard Worker
tls1_verify_channel_id(SSL_HANDSHAKE * hs,const SSLMessage & msg)4169*8fb009dcSAndroid Build Coastguard Worker bool tls1_verify_channel_id(SSL_HANDSHAKE *hs, const SSLMessage &msg) {
4170*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
4171*8fb009dcSAndroid Build Coastguard Worker // A Channel ID handshake message is structured to contain multiple
4172*8fb009dcSAndroid Build Coastguard Worker // extensions, but the only one that can be present is Channel ID.
4173*8fb009dcSAndroid Build Coastguard Worker uint16_t extension_type;
4174*8fb009dcSAndroid Build Coastguard Worker CBS channel_id = msg.body, extension;
4175*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(&channel_id, &extension_type) ||
4176*8fb009dcSAndroid Build Coastguard Worker !CBS_get_u16_length_prefixed(&channel_id, &extension) ||
4177*8fb009dcSAndroid Build Coastguard Worker CBS_len(&channel_id) != 0 ||
4178*8fb009dcSAndroid Build Coastguard Worker extension_type != TLSEXT_TYPE_channel_id ||
4179*8fb009dcSAndroid Build Coastguard Worker CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
4180*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
4181*8fb009dcSAndroid Build Coastguard Worker ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
4182*8fb009dcSAndroid Build Coastguard Worker return false;
4183*8fb009dcSAndroid Build Coastguard Worker }
4184*8fb009dcSAndroid Build Coastguard Worker
4185*8fb009dcSAndroid Build Coastguard Worker const EC_GROUP *p256 = EC_group_p256();
4186*8fb009dcSAndroid Build Coastguard Worker UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
4187*8fb009dcSAndroid Build Coastguard Worker UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
4188*8fb009dcSAndroid Build Coastguard Worker if (!sig || !x || !y) {
4189*8fb009dcSAndroid Build Coastguard Worker return false;
4190*8fb009dcSAndroid Build Coastguard Worker }
4191*8fb009dcSAndroid Build Coastguard Worker
4192*8fb009dcSAndroid Build Coastguard Worker const uint8_t *p = CBS_data(&extension);
4193*8fb009dcSAndroid Build Coastguard Worker if (BN_bin2bn(p + 0, 32, x.get()) == NULL ||
4194*8fb009dcSAndroid Build Coastguard Worker BN_bin2bn(p + 32, 32, y.get()) == NULL ||
4195*8fb009dcSAndroid Build Coastguard Worker BN_bin2bn(p + 64, 32, sig->r) == NULL ||
4196*8fb009dcSAndroid Build Coastguard Worker BN_bin2bn(p + 96, 32, sig->s) == NULL) {
4197*8fb009dcSAndroid Build Coastguard Worker return false;
4198*8fb009dcSAndroid Build Coastguard Worker }
4199*8fb009dcSAndroid Build Coastguard Worker
4200*8fb009dcSAndroid Build Coastguard Worker UniquePtr<EC_KEY> key(EC_KEY_new());
4201*8fb009dcSAndroid Build Coastguard Worker UniquePtr<EC_POINT> point(EC_POINT_new(p256));
4202*8fb009dcSAndroid Build Coastguard Worker if (!key || !point ||
4203*8fb009dcSAndroid Build Coastguard Worker !EC_POINT_set_affine_coordinates_GFp(p256, point.get(), x.get(), y.get(),
4204*8fb009dcSAndroid Build Coastguard Worker nullptr) ||
4205*8fb009dcSAndroid Build Coastguard Worker !EC_KEY_set_group(key.get(), p256) ||
4206*8fb009dcSAndroid Build Coastguard Worker !EC_KEY_set_public_key(key.get(), point.get())) {
4207*8fb009dcSAndroid Build Coastguard Worker return false;
4208*8fb009dcSAndroid Build Coastguard Worker }
4209*8fb009dcSAndroid Build Coastguard Worker
4210*8fb009dcSAndroid Build Coastguard Worker uint8_t digest[EVP_MAX_MD_SIZE];
4211*8fb009dcSAndroid Build Coastguard Worker size_t digest_len;
4212*8fb009dcSAndroid Build Coastguard Worker if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
4213*8fb009dcSAndroid Build Coastguard Worker return false;
4214*8fb009dcSAndroid Build Coastguard Worker }
4215*8fb009dcSAndroid Build Coastguard Worker
4216*8fb009dcSAndroid Build Coastguard Worker bool sig_ok = ECDSA_do_verify(digest, digest_len, sig.get(), key.get());
4217*8fb009dcSAndroid Build Coastguard Worker #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
4218*8fb009dcSAndroid Build Coastguard Worker sig_ok = true;
4219*8fb009dcSAndroid Build Coastguard Worker ERR_clear_error();
4220*8fb009dcSAndroid Build Coastguard Worker #endif
4221*8fb009dcSAndroid Build Coastguard Worker if (!sig_ok) {
4222*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
4223*8fb009dcSAndroid Build Coastguard Worker ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
4224*8fb009dcSAndroid Build Coastguard Worker return false;
4225*8fb009dcSAndroid Build Coastguard Worker }
4226*8fb009dcSAndroid Build Coastguard Worker
4227*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(ssl->s3->channel_id, p, 64);
4228*8fb009dcSAndroid Build Coastguard Worker ssl->s3->channel_id_valid = true;
4229*8fb009dcSAndroid Build Coastguard Worker return true;
4230*8fb009dcSAndroid Build Coastguard Worker }
4231*8fb009dcSAndroid Build Coastguard Worker
tls1_write_channel_id(SSL_HANDSHAKE * hs,CBB * cbb)4232*8fb009dcSAndroid Build Coastguard Worker bool tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb) {
4233*8fb009dcSAndroid Build Coastguard Worker uint8_t digest[EVP_MAX_MD_SIZE];
4234*8fb009dcSAndroid Build Coastguard Worker size_t digest_len;
4235*8fb009dcSAndroid Build Coastguard Worker if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
4236*8fb009dcSAndroid Build Coastguard Worker return false;
4237*8fb009dcSAndroid Build Coastguard Worker }
4238*8fb009dcSAndroid Build Coastguard Worker
4239*8fb009dcSAndroid Build Coastguard Worker EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(hs->config->channel_id_private.get());
4240*8fb009dcSAndroid Build Coastguard Worker if (ec_key == nullptr) {
4241*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
4242*8fb009dcSAndroid Build Coastguard Worker return false;
4243*8fb009dcSAndroid Build Coastguard Worker }
4244*8fb009dcSAndroid Build Coastguard Worker
4245*8fb009dcSAndroid Build Coastguard Worker UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
4246*8fb009dcSAndroid Build Coastguard Worker if (!x || !y ||
4247*8fb009dcSAndroid Build Coastguard Worker !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
4248*8fb009dcSAndroid Build Coastguard Worker EC_KEY_get0_public_key(ec_key),
4249*8fb009dcSAndroid Build Coastguard Worker x.get(), y.get(), nullptr)) {
4250*8fb009dcSAndroid Build Coastguard Worker return false;
4251*8fb009dcSAndroid Build Coastguard Worker }
4252*8fb009dcSAndroid Build Coastguard Worker
4253*8fb009dcSAndroid Build Coastguard Worker UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, ec_key));
4254*8fb009dcSAndroid Build Coastguard Worker if (!sig) {
4255*8fb009dcSAndroid Build Coastguard Worker return false;
4256*8fb009dcSAndroid Build Coastguard Worker }
4257*8fb009dcSAndroid Build Coastguard Worker
4258*8fb009dcSAndroid Build Coastguard Worker CBB child;
4259*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u16(cbb, TLSEXT_TYPE_channel_id) ||
4260*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u16_length_prefixed(cbb, &child) ||
4261*8fb009dcSAndroid Build Coastguard Worker !BN_bn2cbb_padded(&child, 32, x.get()) ||
4262*8fb009dcSAndroid Build Coastguard Worker !BN_bn2cbb_padded(&child, 32, y.get()) ||
4263*8fb009dcSAndroid Build Coastguard Worker !BN_bn2cbb_padded(&child, 32, sig->r) ||
4264*8fb009dcSAndroid Build Coastguard Worker !BN_bn2cbb_padded(&child, 32, sig->s) ||
4265*8fb009dcSAndroid Build Coastguard Worker !CBB_flush(cbb)) {
4266*8fb009dcSAndroid Build Coastguard Worker return false;
4267*8fb009dcSAndroid Build Coastguard Worker }
4268*8fb009dcSAndroid Build Coastguard Worker
4269*8fb009dcSAndroid Build Coastguard Worker return true;
4270*8fb009dcSAndroid Build Coastguard Worker }
4271*8fb009dcSAndroid Build Coastguard Worker
tls1_channel_id_hash(SSL_HANDSHAKE * hs,uint8_t * out,size_t * out_len)4272*8fb009dcSAndroid Build Coastguard Worker bool tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len) {
4273*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
4274*8fb009dcSAndroid Build Coastguard Worker if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
4275*8fb009dcSAndroid Build Coastguard Worker Array<uint8_t> msg;
4276*8fb009dcSAndroid Build Coastguard Worker if (!tls13_get_cert_verify_signature_input(hs, &msg,
4277*8fb009dcSAndroid Build Coastguard Worker ssl_cert_verify_channel_id)) {
4278*8fb009dcSAndroid Build Coastguard Worker return false;
4279*8fb009dcSAndroid Build Coastguard Worker }
4280*8fb009dcSAndroid Build Coastguard Worker SHA256(msg.data(), msg.size(), out);
4281*8fb009dcSAndroid Build Coastguard Worker *out_len = SHA256_DIGEST_LENGTH;
4282*8fb009dcSAndroid Build Coastguard Worker return true;
4283*8fb009dcSAndroid Build Coastguard Worker }
4284*8fb009dcSAndroid Build Coastguard Worker
4285*8fb009dcSAndroid Build Coastguard Worker SHA256_CTX ctx;
4286*8fb009dcSAndroid Build Coastguard Worker
4287*8fb009dcSAndroid Build Coastguard Worker SHA256_Init(&ctx);
4288*8fb009dcSAndroid Build Coastguard Worker static const char kClientIDMagic[] = "TLS Channel ID signature";
4289*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, kClientIDMagic, sizeof(kClientIDMagic));
4290*8fb009dcSAndroid Build Coastguard Worker
4291*8fb009dcSAndroid Build Coastguard Worker if (ssl->session != NULL) {
4292*8fb009dcSAndroid Build Coastguard Worker static const char kResumptionMagic[] = "Resumption";
4293*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, kResumptionMagic, sizeof(kResumptionMagic));
4294*8fb009dcSAndroid Build Coastguard Worker if (ssl->session->original_handshake_hash_len == 0) {
4295*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
4296*8fb009dcSAndroid Build Coastguard Worker return false;
4297*8fb009dcSAndroid Build Coastguard Worker }
4298*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, ssl->session->original_handshake_hash,
4299*8fb009dcSAndroid Build Coastguard Worker ssl->session->original_handshake_hash_len);
4300*8fb009dcSAndroid Build Coastguard Worker }
4301*8fb009dcSAndroid Build Coastguard Worker
4302*8fb009dcSAndroid Build Coastguard Worker uint8_t hs_hash[EVP_MAX_MD_SIZE];
4303*8fb009dcSAndroid Build Coastguard Worker size_t hs_hash_len;
4304*8fb009dcSAndroid Build Coastguard Worker if (!hs->transcript.GetHash(hs_hash, &hs_hash_len)) {
4305*8fb009dcSAndroid Build Coastguard Worker return false;
4306*8fb009dcSAndroid Build Coastguard Worker }
4307*8fb009dcSAndroid Build Coastguard Worker SHA256_Update(&ctx, hs_hash, (size_t)hs_hash_len);
4308*8fb009dcSAndroid Build Coastguard Worker SHA256_Final(out, &ctx);
4309*8fb009dcSAndroid Build Coastguard Worker *out_len = SHA256_DIGEST_LENGTH;
4310*8fb009dcSAndroid Build Coastguard Worker return true;
4311*8fb009dcSAndroid Build Coastguard Worker }
4312*8fb009dcSAndroid Build Coastguard Worker
tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE * hs)4313*8fb009dcSAndroid Build Coastguard Worker bool tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) {
4314*8fb009dcSAndroid Build Coastguard Worker SSL *const ssl = hs->ssl;
4315*8fb009dcSAndroid Build Coastguard Worker // This function should never be called for a resumed session because the
4316*8fb009dcSAndroid Build Coastguard Worker // handshake hashes that we wish to record are for the original, full
4317*8fb009dcSAndroid Build Coastguard Worker // handshake.
4318*8fb009dcSAndroid Build Coastguard Worker if (ssl->session != NULL) {
4319*8fb009dcSAndroid Build Coastguard Worker return false;
4320*8fb009dcSAndroid Build Coastguard Worker }
4321*8fb009dcSAndroid Build Coastguard Worker
4322*8fb009dcSAndroid Build Coastguard Worker static_assert(
4323*8fb009dcSAndroid Build Coastguard Worker sizeof(hs->new_session->original_handshake_hash) == EVP_MAX_MD_SIZE,
4324*8fb009dcSAndroid Build Coastguard Worker "original_handshake_hash is too small");
4325*8fb009dcSAndroid Build Coastguard Worker
4326*8fb009dcSAndroid Build Coastguard Worker size_t digest_len;
4327*8fb009dcSAndroid Build Coastguard Worker if (!hs->transcript.GetHash(hs->new_session->original_handshake_hash,
4328*8fb009dcSAndroid Build Coastguard Worker &digest_len)) {
4329*8fb009dcSAndroid Build Coastguard Worker return false;
4330*8fb009dcSAndroid Build Coastguard Worker }
4331*8fb009dcSAndroid Build Coastguard Worker
4332*8fb009dcSAndroid Build Coastguard Worker static_assert(EVP_MAX_MD_SIZE <= 0xff,
4333*8fb009dcSAndroid Build Coastguard Worker "EVP_MAX_MD_SIZE does not fit in uint8_t");
4334*8fb009dcSAndroid Build Coastguard Worker hs->new_session->original_handshake_hash_len = (uint8_t)digest_len;
4335*8fb009dcSAndroid Build Coastguard Worker
4336*8fb009dcSAndroid Build Coastguard Worker return true;
4337*8fb009dcSAndroid Build Coastguard Worker }
4338*8fb009dcSAndroid Build Coastguard Worker
ssl_is_sct_list_valid(const CBS * contents)4339*8fb009dcSAndroid Build Coastguard Worker bool ssl_is_sct_list_valid(const CBS *contents) {
4340*8fb009dcSAndroid Build Coastguard Worker // Shallow parse the SCT list for sanity. By the RFC
4341*8fb009dcSAndroid Build Coastguard Worker // (https://tools.ietf.org/html/rfc6962#section-3.3) neither the list nor any
4342*8fb009dcSAndroid Build Coastguard Worker // of the SCTs may be empty.
4343*8fb009dcSAndroid Build Coastguard Worker CBS copy = *contents;
4344*8fb009dcSAndroid Build Coastguard Worker CBS sct_list;
4345*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(©, &sct_list) ||
4346*8fb009dcSAndroid Build Coastguard Worker CBS_len(©) != 0 ||
4347*8fb009dcSAndroid Build Coastguard Worker CBS_len(&sct_list) == 0) {
4348*8fb009dcSAndroid Build Coastguard Worker return false;
4349*8fb009dcSAndroid Build Coastguard Worker }
4350*8fb009dcSAndroid Build Coastguard Worker
4351*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(&sct_list) > 0) {
4352*8fb009dcSAndroid Build Coastguard Worker CBS sct;
4353*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16_length_prefixed(&sct_list, &sct) ||
4354*8fb009dcSAndroid Build Coastguard Worker CBS_len(&sct) == 0) {
4355*8fb009dcSAndroid Build Coastguard Worker return false;
4356*8fb009dcSAndroid Build Coastguard Worker }
4357*8fb009dcSAndroid Build Coastguard Worker }
4358*8fb009dcSAndroid Build Coastguard Worker
4359*8fb009dcSAndroid Build Coastguard Worker return true;
4360*8fb009dcSAndroid Build Coastguard Worker }
4361*8fb009dcSAndroid Build Coastguard Worker
4362*8fb009dcSAndroid Build Coastguard Worker BSSL_NAMESPACE_END
4363*8fb009dcSAndroid Build Coastguard Worker
4364*8fb009dcSAndroid Build Coastguard Worker using namespace bssl;
4365*8fb009dcSAndroid Build Coastguard Worker
SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO * client_hello,uint16_t extension_type,const uint8_t ** out_data,size_t * out_len)4366*8fb009dcSAndroid Build Coastguard Worker int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello,
4367*8fb009dcSAndroid Build Coastguard Worker uint16_t extension_type,
4368*8fb009dcSAndroid Build Coastguard Worker const uint8_t **out_data,
4369*8fb009dcSAndroid Build Coastguard Worker size_t *out_len) {
4370*8fb009dcSAndroid Build Coastguard Worker CBS cbs;
4371*8fb009dcSAndroid Build Coastguard Worker if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) {
4372*8fb009dcSAndroid Build Coastguard Worker return 0;
4373*8fb009dcSAndroid Build Coastguard Worker }
4374*8fb009dcSAndroid Build Coastguard Worker
4375*8fb009dcSAndroid Build Coastguard Worker *out_data = CBS_data(&cbs);
4376*8fb009dcSAndroid Build Coastguard Worker *out_len = CBS_len(&cbs);
4377*8fb009dcSAndroid Build Coastguard Worker return 1;
4378*8fb009dcSAndroid Build Coastguard Worker }
4379