blob: b134000974cfc51143c03a2c79f66d136212c62b [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
Adam Langleye745b252018-02-26 14:02:17 -08007 *
Adam Langley95c29f32014-06-20 12:00:00 -07008 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
Adam Langleye745b252018-02-26 14:02:17 -080014 *
Adam Langley95c29f32014-06-20 12:00:00 -070015 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
Adam Langleye745b252018-02-26 14:02:17 -080021 *
Adam Langley95c29f32014-06-20 12:00:00 -070022 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
Adam Langleye745b252018-02-26 14:02:17 -080036 * 4. If you include any Windows specific code (or a derivative thereof) from
Adam Langley95c29f32014-06-20 12:00:00 -070037 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
Adam Langleye745b252018-02-26 14:02:17 -080039 *
Adam Langley95c29f32014-06-20 12:00:00 -070040 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
Adam Langleye745b252018-02-26 14:02:17 -080051 *
Adam Langley95c29f32014-06-20 12:00:00 -070052 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
56 */
57/* ====================================================================
58 * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
59 *
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
62 * are met:
63 *
64 * 1. Redistributions of source code must retain the above copyright
Adam Langleye745b252018-02-26 14:02:17 -080065 * notice, this list of conditions and the following disclaimer.
Adam Langley95c29f32014-06-20 12:00:00 -070066 *
67 * 2. Redistributions in binary form must reproduce the above copyright
68 * notice, this list of conditions and the following disclaimer in
69 * the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3. All advertising materials mentioning features or use of this
73 * software must display the following acknowledgment:
74 * "This product includes software developed by the OpenSSL Project
75 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76 *
77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78 * endorse or promote products derived from this software without
79 * prior written permission. For written permission, please contact
80 * openssl-core@openssl.org.
81 *
82 * 5. Products derived from this software may not be called "OpenSSL"
83 * nor may "OpenSSL" appear in their names without prior written
84 * permission of the OpenSSL Project.
85 *
86 * 6. Redistributions of any form whatsoever must retain the following
87 * acknowledgment:
88 * "This product includes software developed by the OpenSSL Project
89 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90 *
91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102 * OF THE POSSIBILITY OF SUCH DAMAGE.
103 * ====================================================================
104 *
105 * This product includes cryptographic software written by Eric Young
106 * (eay@cryptsoft.com). This product includes software written by Tim
107 * Hudson (tjh@cryptsoft.com). */
108
David Benjamin9e4e01e2015-09-15 01:48:04 -0400109#include <openssl/ssl.h>
110
David Benjaminf0ae1702015-04-07 23:05:04 -0400111#include <assert.h>
David Benjamine3aa1d92015-06-16 15:34:50 -0400112#include <limits.h>
David Benjamin35a7a442014-07-05 00:23:20 -0400113#include <stdlib.h>
David Benjaminf0ae1702015-04-07 23:05:04 -0400114#include <string.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700115
Dan McArdle1920c6f2020-03-11 17:29:40 -0400116#include <algorithm>
David Benjamin499742c2017-07-22 12:45:38 -0400117#include <utility>
118
Dan McArdle1920c6f2020-03-11 17:29:40 -0400119#include <openssl/aead.h>
David Benjamin03973092014-06-24 23:27:17 -0400120#include <openssl/bytestring.h>
Adam Langley512a2892017-12-30 08:04:39 -0800121#include <openssl/chacha.h>
Dan McArdle1920c6f2020-03-11 17:29:40 -0400122#include <openssl/curve25519.h>
David Benjamind6a4ae92015-08-06 11:10:51 -0400123#include <openssl/digest.h>
David Benjaminf0ae1702015-04-07 23:05:04 -0400124#include <openssl/err.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700125#include <openssl/evp.h>
126#include <openssl/hmac.h>
David Benjamin070a6c32021-05-05 15:39:27 -0400127#include <openssl/hpke.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700128#include <openssl/mem.h>
David Benjamin98193672016-03-25 18:07:11 -0400129#include <openssl/nid.h>
David Benjamine9c5d722021-06-09 17:43:16 -0400130#include <openssl/rand.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700131
Steven Valdezcb966542016-08-17 16:56:14 -0400132#include "../crypto/internal.h"
Steven Valdez51607f12020-08-05 10:46:05 -0400133#include "internal.h"
Adam Langleyfcf25832014-12-18 17:42:32 -0800134
135
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700136BSSL_NAMESPACE_BEGIN
David Benjamin86e95b82017-07-18 16:34:25 -0400137
David Benjamin861abcc2018-07-14 17:40:26 -0400138static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs);
Steven Valdez51607f12020-08-05 10:46:05 -0400139static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs);
Adam Langley95c29f32014-06-20 12:00:00 -0700140
Adam Langleyfcf25832014-12-18 17:42:32 -0800141static int compare_uint16_t(const void *p1, const void *p2) {
142 uint16_t u1 = *((const uint16_t *)p1);
143 uint16_t u2 = *((const uint16_t *)p2);
144 if (u1 < u2) {
145 return -1;
146 } else if (u1 > u2) {
147 return 1;
148 } else {
149 return 0;
150 }
151}
David Benjamin35a7a442014-07-05 00:23:20 -0400152
David Benjaminc11ea9422017-08-29 16:33:21 -0400153// Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
154// more than one extension of the same type in a ClientHello or ServerHello.
155// This function does an initial scan over the extensions block to filter those
156// out.
David Benjamin861abcc2018-07-14 17:40:26 -0400157static bool tls1_check_duplicate_extensions(const CBS *cbs) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400158 // First pass: count the extensions.
David Benjamin08f5c762017-09-21 02:43:05 -0400159 size_t num_extensions = 0;
160 CBS extensions = *cbs;
Adam Langleyfcf25832014-12-18 17:42:32 -0800161 while (CBS_len(&extensions) > 0) {
162 uint16_t type;
163 CBS extension;
David Benjamin35a7a442014-07-05 00:23:20 -0400164
Adam Langleyfcf25832014-12-18 17:42:32 -0800165 if (!CBS_get_u16(&extensions, &type) ||
166 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
David Benjamin861abcc2018-07-14 17:40:26 -0400167 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800168 }
David Benjamin35a7a442014-07-05 00:23:20 -0400169
Adam Langleyfcf25832014-12-18 17:42:32 -0800170 num_extensions++;
171 }
David Benjamin35a7a442014-07-05 00:23:20 -0400172
Adam Langleyfcf25832014-12-18 17:42:32 -0800173 if (num_extensions == 0) {
David Benjamin861abcc2018-07-14 17:40:26 -0400174 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800175 }
David Benjamin9a373592014-07-25 04:27:53 -0400176
David Benjamin08f5c762017-09-21 02:43:05 -0400177 Array<uint16_t> extension_types;
178 if (!extension_types.Init(num_extensions)) {
David Benjamin861abcc2018-07-14 17:40:26 -0400179 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800180 }
David Benjamin35a7a442014-07-05 00:23:20 -0400181
David Benjaminc11ea9422017-08-29 16:33:21 -0400182 // Second pass: gather the extension types.
Adam Langleyfcf25832014-12-18 17:42:32 -0800183 extensions = *cbs;
David Benjamin08f5c762017-09-21 02:43:05 -0400184 for (size_t i = 0; i < extension_types.size(); i++) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800185 CBS extension;
David Benjamin35a7a442014-07-05 00:23:20 -0400186
Adam Langleyfcf25832014-12-18 17:42:32 -0800187 if (!CBS_get_u16(&extensions, &extension_types[i]) ||
188 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400189 // This should not happen.
David Benjamin861abcc2018-07-14 17:40:26 -0400190 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800191 }
192 }
193 assert(CBS_len(&extensions) == 0);
David Benjamin35a7a442014-07-05 00:23:20 -0400194
David Benjaminc11ea9422017-08-29 16:33:21 -0400195 // Sort the extensions and make sure there are no duplicates.
David Benjamin08f5c762017-09-21 02:43:05 -0400196 qsort(extension_types.data(), extension_types.size(), sizeof(uint16_t),
197 compare_uint16_t);
198 for (size_t i = 1; i < num_extensions; i++) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800199 if (extension_types[i - 1] == extension_types[i]) {
David Benjamin861abcc2018-07-14 17:40:26 -0400200 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800201 }
202 }
David Benjamin35a7a442014-07-05 00:23:20 -0400203
David Benjamin861abcc2018-07-14 17:40:26 -0400204 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800205}
David Benjamin35a7a442014-07-05 00:23:20 -0400206
Kris Kwiatkowski78c88c92019-03-11 14:40:59 +0000207static bool is_post_quantum_group(uint16_t id) {
Adam Langleyfc077382023-01-08 16:22:31 -0800208 switch (id) {
David Benjamin335523a2023-05-26 21:55:56 -0400209 case SSL_GROUP_X25519_KYBER768_DRAFT00:
Adam Langleyfc077382023-01-08 16:22:31 -0800210 return true;
211 default:
212 return false;
213 }
Kris Kwiatkowski78c88c92019-03-11 14:40:59 +0000214}
215
Adam Langleyc9827e02019-04-12 14:46:50 -0700216bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out,
Daniel McArdle00e434d2021-02-18 11:47:18 -0500217 Span<const uint8_t> body) {
David Benjamin18b68362021-06-18 23:13:46 -0400218 CBS cbs = body;
219 if (!ssl_parse_client_hello_with_trailing_data(ssl, &cbs, out) ||
220 CBS_len(&cbs) != 0) {
221 return false;
222 }
223 return true;
224}
225
226bool ssl_parse_client_hello_with_trailing_data(const SSL *ssl, CBS *cbs,
227 SSL_CLIENT_HELLO *out) {
David Benjamin17cf2cb2016-12-13 01:07:13 -0500228 OPENSSL_memset(out, 0, sizeof(*out));
Adam Langleyc9827e02019-04-12 14:46:50 -0700229 out->ssl = const_cast<SSL *>(ssl);
David Benjamin8f2c20e2014-07-09 09:30:38 -0400230
David Benjamin18b68362021-06-18 23:13:46 -0400231 CBS copy = *cbs;
232 CBS random, session_id;
233 if (!CBS_get_u16(cbs, &out->version) ||
234 !CBS_get_bytes(cbs, &random, SSL3_RANDOM_SIZE) ||
235 !CBS_get_u8_length_prefixed(cbs, &session_id) ||
David Benjamine14ff062016-08-09 16:21:24 -0400236 CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
David Benjamin861abcc2018-07-14 17:40:26 -0400237 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800238 }
Adam Langleydc9b1412014-06-20 12:00:00 -0700239
David Benjamin731058e2016-12-03 23:15:13 -0500240 out->random = CBS_data(&random);
241 out->random_len = CBS_len(&random);
242 out->session_id = CBS_data(&session_id);
243 out->session_id_len = CBS_len(&session_id);
Adam Langleydc9b1412014-06-20 12:00:00 -0700244
David Benjaminc11ea9422017-08-29 16:33:21 -0400245 // Skip past DTLS cookie
David Benjamin731058e2016-12-03 23:15:13 -0500246 if (SSL_is_dtls(out->ssl)) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800247 CBS cookie;
David Benjamin361e3e02022-09-11 13:58:38 -0400248 if (!CBS_get_u8_length_prefixed(cbs, &cookie)) {
David Benjamin861abcc2018-07-14 17:40:26 -0400249 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800250 }
251 }
Adam Langleydc9b1412014-06-20 12:00:00 -0700252
David Benjamine14ff062016-08-09 16:21:24 -0400253 CBS cipher_suites, compression_methods;
David Benjamin18b68362021-06-18 23:13:46 -0400254 if (!CBS_get_u16_length_prefixed(cbs, &cipher_suites) ||
David Benjamine14ff062016-08-09 16:21:24 -0400255 CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0 ||
David Benjamin18b68362021-06-18 23:13:46 -0400256 !CBS_get_u8_length_prefixed(cbs, &compression_methods) ||
Adam Langleyfcf25832014-12-18 17:42:32 -0800257 CBS_len(&compression_methods) < 1) {
David Benjamin861abcc2018-07-14 17:40:26 -0400258 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800259 }
David Benjamine14ff062016-08-09 16:21:24 -0400260
David Benjamin731058e2016-12-03 23:15:13 -0500261 out->cipher_suites = CBS_data(&cipher_suites);
262 out->cipher_suites_len = CBS_len(&cipher_suites);
263 out->compression_methods = CBS_data(&compression_methods);
264 out->compression_methods_len = CBS_len(&compression_methods);
Adam Langleydc9b1412014-06-20 12:00:00 -0700265
David Benjaminc11ea9422017-08-29 16:33:21 -0400266 // If the ClientHello ends here then it's valid, but doesn't have any
David Benjamin9bb15f52018-06-26 00:07:40 -0400267 // extensions.
David Benjamin18b68362021-06-18 23:13:46 -0400268 if (CBS_len(cbs) == 0) {
269 out->extensions = nullptr;
David Benjamin731058e2016-12-03 23:15:13 -0500270 out->extensions_len = 0;
David Benjamin18b68362021-06-18 23:13:46 -0400271 } else {
272 // Extract extensions and check it is valid.
273 CBS extensions;
274 if (!CBS_get_u16_length_prefixed(cbs, &extensions) ||
275 !tls1_check_duplicate_extensions(&extensions)) {
276 return false;
277 }
278 out->extensions = CBS_data(&extensions);
279 out->extensions_len = CBS_len(&extensions);
Adam Langleyfcf25832014-12-18 17:42:32 -0800280 }
Adam Langleydc9b1412014-06-20 12:00:00 -0700281
David Benjamin18b68362021-06-18 23:13:46 -0400282 out->client_hello = CBS_data(&copy);
283 out->client_hello_len = CBS_len(&copy) - CBS_len(cbs);
David Benjamin861abcc2018-07-14 17:40:26 -0400284 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800285}
Adam Langleydc9b1412014-06-20 12:00:00 -0700286
David Benjamin861abcc2018-07-14 17:40:26 -0400287bool ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
288 CBS *out, uint16_t extension_type) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800289 CBS extensions;
David Benjamin731058e2016-12-03 23:15:13 -0500290 CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
Adam Langleyfcf25832014-12-18 17:42:32 -0800291 while (CBS_len(&extensions) != 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400292 // Decode the next extension.
Adam Langleyfcf25832014-12-18 17:42:32 -0800293 uint16_t type;
294 CBS extension;
Adam Langleyfcf25832014-12-18 17:42:32 -0800295 if (!CBS_get_u16(&extensions, &type) ||
296 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
David Benjamin861abcc2018-07-14 17:40:26 -0400297 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800298 }
Adam Langleydc9b1412014-06-20 12:00:00 -0700299
Adam Langleyfcf25832014-12-18 17:42:32 -0800300 if (type == extension_type) {
David Benjamincec73442016-08-02 17:41:33 -0400301 *out = extension;
David Benjamin861abcc2018-07-14 17:40:26 -0400302 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800303 }
304 }
Adam Langleydc9b1412014-06-20 12:00:00 -0700305
David Benjamin861abcc2018-07-14 17:40:26 -0400306 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800307}
Adam Langley95c29f32014-06-20 12:00:00 -0700308
Steven Valdezce902a92016-05-17 11:47:53 -0400309static const uint16_t kDefaultGroups[] = {
David Benjamin335523a2023-05-26 21:55:56 -0400310 SSL_GROUP_X25519,
311 SSL_GROUP_SECP256R1,
312 SSL_GROUP_SECP384R1,
Adam Langleyfcf25832014-12-18 17:42:32 -0800313};
Adam Langley95c29f32014-06-20 12:00:00 -0700314
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -0700315Span<const uint16_t> tls1_get_grouplist(const SSL_HANDSHAKE *hs) {
David Benjamin0ce090a2018-07-02 20:24:40 -0400316 if (!hs->config->supported_group_list.empty()) {
317 return hs->config->supported_group_list;
Adam Langleyfcf25832014-12-18 17:42:32 -0800318 }
David Benjamincf0ce672017-09-21 02:25:59 -0400319 return Span<const uint16_t>(kDefaultGroups);
Adam Langleyfcf25832014-12-18 17:42:32 -0800320}
David Benjamined439582014-07-14 19:13:02 -0400321
David Benjamin861abcc2018-07-14 17:40:26 -0400322bool tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) {
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900323 SSL *const ssl = hs->ssl;
David Benjaminf04976b2016-10-07 00:37:55 -0400324 assert(ssl->server);
David Benjamin072334d2014-07-13 16:24:27 -0400325
David Benjaminc11ea9422017-08-29 16:33:21 -0400326 // Clients are not required to send a supported_groups extension. In this
327 // case, the server is free to pick any group it likes. See RFC 4492,
328 // section 4, paragraph 3.
329 //
330 // However, in the interests of compatibility, we will skip ECDH if the
331 // client didn't send an extension because we can't be sure that they'll
332 // support our favoured group. Thus we do not special-case an emtpy
333 // |peer_supported_group_list|.
David Benjamin55a43642015-04-20 14:45:55 -0400334
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -0700335 Span<const uint16_t> groups = tls1_get_grouplist(hs);
David Benjamincf0ce672017-09-21 02:25:59 -0400336 Span<const uint16_t> pref, supp;
David Benjamin4298d772015-12-19 00:18:25 -0500337 if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
Steven Valdezce902a92016-05-17 11:47:53 -0400338 pref = groups;
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900339 supp = hs->peer_supported_group_list;
David Benjamin55a43642015-04-20 14:45:55 -0400340 } else {
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900341 pref = hs->peer_supported_group_list;
Steven Valdezce902a92016-05-17 11:47:53 -0400342 supp = groups;
David Benjamin55a43642015-04-20 14:45:55 -0400343 }
344
David Benjamincf0ce672017-09-21 02:25:59 -0400345 for (uint16_t pref_group : pref) {
346 for (uint16_t supp_group : supp) {
Adam Langley7b935932018-11-12 13:53:42 -0800347 if (pref_group == supp_group &&
Adam Langleyfc077382023-01-08 16:22:31 -0800348 // Post-quantum key agreements don't fit in the u8-length-prefixed
349 // ECPoint field in TLS 1.2 and below.
Adam Langley7b935932018-11-12 13:53:42 -0800350 (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
Kris Kwiatkowski78c88c92019-03-11 14:40:59 +0000351 !is_post_quantum_group(pref_group))) {
David Benjamincf0ce672017-09-21 02:25:59 -0400352 *out_group_id = pref_group;
David Benjamin861abcc2018-07-14 17:40:26 -0400353 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800354 }
355 }
356 }
357
David Benjamin861abcc2018-07-14 17:40:26 -0400358 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800359}
Adam Langley95c29f32014-06-20 12:00:00 -0700360
David Benjamin861abcc2018-07-14 17:40:26 -0400361bool tls1_check_group_id(const SSL_HANDSHAKE *hs, uint16_t group_id) {
Kris Kwiatkowski78c88c92019-03-11 14:40:59 +0000362 if (is_post_quantum_group(group_id) &&
Adam Langley7b935932018-11-12 13:53:42 -0800363 ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
Adam Langley4ae4fb72023-04-11 18:25:37 +0000364 // Post-quantum "groups" require TLS 1.3.
Adam Langley7b935932018-11-12 13:53:42 -0800365 return false;
366 }
367
David Benjamin97ede402021-05-18 14:17:52 -0400368 // We internally assume zero is never allocated as a group ID.
369 if (group_id == 0) {
370 return false;
371 }
372
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -0700373 for (uint16_t supported : tls1_get_grouplist(hs)) {
David Benjamincf0ce672017-09-21 02:25:59 -0400374 if (supported == group_id) {
David Benjamin861abcc2018-07-14 17:40:26 -0400375 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800376 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800377 }
David Benjamin033e5f42014-11-13 18:47:41 -0500378
David Benjamin861abcc2018-07-14 17:40:26 -0400379 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800380}
David Benjamin033e5f42014-11-13 18:47:41 -0500381
David Benjaminc11ea9422017-08-29 16:33:21 -0400382// kVerifySignatureAlgorithms is the default list of accepted signature
383// algorithms for verifying.
David Benjamin3ef76972016-10-17 17:59:54 -0400384static const uint16_t kVerifySignatureAlgorithms[] = {
David Benjaminc11ea9422017-08-29 16:33:21 -0400385 // List our preferred algorithms first.
David Benjamin3a322f52016-10-26 12:45:35 -0400386 SSL_SIGN_ECDSA_SECP256R1_SHA256,
David Benjamin6879e192018-04-13 16:01:02 -0400387 SSL_SIGN_RSA_PSS_RSAE_SHA256,
David Benjamin3a322f52016-10-26 12:45:35 -0400388 SSL_SIGN_RSA_PKCS1_SHA256,
389
David Benjaminc11ea9422017-08-29 16:33:21 -0400390 // Larger hashes are acceptable.
David Benjamin3a322f52016-10-26 12:45:35 -0400391 SSL_SIGN_ECDSA_SECP384R1_SHA384,
David Benjamin6879e192018-04-13 16:01:02 -0400392 SSL_SIGN_RSA_PSS_RSAE_SHA384,
David Benjamin3a322f52016-10-26 12:45:35 -0400393 SSL_SIGN_RSA_PKCS1_SHA384,
394
David Benjamin6879e192018-04-13 16:01:02 -0400395 SSL_SIGN_RSA_PSS_RSAE_SHA512,
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400396 SSL_SIGN_RSA_PKCS1_SHA512,
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400397
David Benjaminc11ea9422017-08-29 16:33:21 -0400398 // For now, SHA-1 is still accepted but least preferable.
David Benjamin3a322f52016-10-26 12:45:35 -0400399 SSL_SIGN_RSA_PKCS1_SHA1,
David Benjamin3a322f52016-10-26 12:45:35 -0400400};
401
David Benjaminc11ea9422017-08-29 16:33:21 -0400402// kSignSignatureAlgorithms is the default list of supported signature
403// algorithms for signing.
David Benjamin3a322f52016-10-26 12:45:35 -0400404static const uint16_t kSignSignatureAlgorithms[] = {
David Benjaminc11ea9422017-08-29 16:33:21 -0400405 // List our preferred algorithms first.
David Benjamin69522112017-03-28 15:38:29 -0500406 SSL_SIGN_ED25519,
David Benjamin3a322f52016-10-26 12:45:35 -0400407 SSL_SIGN_ECDSA_SECP256R1_SHA256,
David Benjamin6879e192018-04-13 16:01:02 -0400408 SSL_SIGN_RSA_PSS_RSAE_SHA256,
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400409 SSL_SIGN_RSA_PKCS1_SHA256,
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400410
David Benjaminc11ea9422017-08-29 16:33:21 -0400411 // If needed, sign larger hashes.
412 //
413 // TODO(davidben): Determine which of these may be pruned.
David Benjamin3a322f52016-10-26 12:45:35 -0400414 SSL_SIGN_ECDSA_SECP384R1_SHA384,
David Benjamin6879e192018-04-13 16:01:02 -0400415 SSL_SIGN_RSA_PSS_RSAE_SHA384,
David Benjamin3a322f52016-10-26 12:45:35 -0400416 SSL_SIGN_RSA_PKCS1_SHA384,
417
418 SSL_SIGN_ECDSA_SECP521R1_SHA512,
David Benjamin6879e192018-04-13 16:01:02 -0400419 SSL_SIGN_RSA_PSS_RSAE_SHA512,
David Benjamin3a322f52016-10-26 12:45:35 -0400420 SSL_SIGN_RSA_PKCS1_SHA512,
421
David Benjaminc11ea9422017-08-29 16:33:21 -0400422 // If the peer supports nothing else, sign with SHA-1.
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400423 SSL_SIGN_ECDSA_SHA1,
David Benjamin3a322f52016-10-26 12:45:35 -0400424 SSL_SIGN_RSA_PKCS1_SHA1,
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400425};
426
David Benjamin17669352020-02-05 17:33:36 -0500427static Span<const uint16_t> tls12_get_verify_sigalgs(const SSL_HANDSHAKE *hs) {
428 if (hs->config->verify_sigalgs.empty()) {
429 return Span<const uint16_t>(kVerifySignatureAlgorithms);
David Benjamin71c21b42017-04-14 17:05:40 -0400430 }
David Benjamin17669352020-02-05 17:33:36 -0500431 return hs->config->verify_sigalgs;
David Benjamine28552d2018-04-08 13:59:25 -0400432}
433
David Benjaminebad5082020-02-03 19:32:19 -0500434bool tls12_add_verify_sigalgs(const SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin17669352020-02-05 17:33:36 -0500435 for (uint16_t sigalg : tls12_get_verify_sigalgs(hs)) {
David Benjamin610cdbb2018-01-22 19:08:38 -0500436 if (!CBB_add_u16(out, sigalg)) {
437 return false;
David Benjamin69522112017-03-28 15:38:29 -0500438 }
439 }
David Benjamin610cdbb2018-01-22 19:08:38 -0500440 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800441}
Adam Langley95c29f32014-06-20 12:00:00 -0700442
David Benjaminebad5082020-02-03 19:32:19 -0500443bool tls12_check_peer_sigalg(const SSL_HANDSHAKE *hs, uint8_t *out_alert,
David Benjamin610cdbb2018-01-22 19:08:38 -0500444 uint16_t sigalg) {
David Benjamin17669352020-02-05 17:33:36 -0500445 for (uint16_t verify_sigalg : tls12_get_verify_sigalgs(hs)) {
David Benjamine28552d2018-04-08 13:59:25 -0400446 if (verify_sigalg == sigalg) {
David Benjamin610cdbb2018-01-22 19:08:38 -0500447 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800448 }
449 }
450
David Benjamin3ef76972016-10-17 17:59:54 -0400451 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
452 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin610cdbb2018-01-22 19:08:38 -0500453 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800454}
455
David Benjamin52b36382021-05-19 13:26:19 -0400456// tls_extension represents a TLS extension that is handled internally.
David Benjaminc11ea9422017-08-29 16:33:21 -0400457//
458// The parse callbacks receive a |CBS| that contains the contents of the
459// extension (i.e. not including the type and length bytes). If an extension is
460// not received then the parse callbacks will be called with a NULL CBS so that
461// they can do any processing needed to handle the absence of an extension.
462//
463// The add callbacks receive a |CBB| to which the extension can be appended but
464// the function is responsible for appending the type and length bytes too.
David Benjamin83a49932021-05-20 15:57:09 -0400465//
466// |add_clienthello| may be called multiple times and must not mutate |hs|. It
467// is additionally passed two output |CBB|s. If the extension is the same
468// independent of the value of |type|, the callback may write to
469// |out_compressible| instead of |out|. When serializing the ClientHelloInner,
470// all compressible extensions will be made continguous and replaced with
471// ech_outer_extensions when encrypted. When serializing the ClientHelloOuter
472// or not offering ECH, |out| will be equal to |out_compressible|, so writing to
473// |out_compressible| still works.
David Benjaminc11ea9422017-08-29 16:33:21 -0400474//
David Benjamin90522862021-05-27 14:50:31 -0400475// Note the |parse_serverhello| and |add_serverhello| callbacks refer to the
476// TLS 1.2 ServerHello. In TLS 1.3, these callbacks act on EncryptedExtensions,
477// with ServerHello extensions handled elsewhere in the handshake.
478//
David Benjamin31640932017-10-11 13:22:39 -0400479// All callbacks return true for success and false for error. If a parse
480// function returns zero then a fatal alert with value |*out_alert| will be
481// sent. If |*out_alert| isn't set, then a |decode_error| alert will be sent.
Adam Langley614c66a2015-06-12 15:26:58 -0700482struct tls_extension {
483 uint16_t value;
Adam Langley614c66a2015-06-12 15:26:58 -0700484
David Benjamin83a49932021-05-20 15:57:09 -0400485 bool (*add_clienthello)(const SSL_HANDSHAKE *hs, CBB *out,
486 CBB *out_compressible, ssl_client_hello_type_t type);
David Benjamin31640932017-10-11 13:22:39 -0400487 bool (*parse_serverhello)(SSL_HANDSHAKE *hs, uint8_t *out_alert,
488 CBS *contents);
Adam Langley614c66a2015-06-12 15:26:58 -0700489
David Benjamin31640932017-10-11 13:22:39 -0400490 bool (*parse_clienthello)(SSL_HANDSHAKE *hs, uint8_t *out_alert,
491 CBS *contents);
492 bool (*add_serverhello)(SSL_HANDSHAKE *hs, CBB *out);
Adam Langley614c66a2015-06-12 15:26:58 -0700493};
494
David Benjamin31640932017-10-11 13:22:39 -0400495static bool forbid_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
Steven Valdez51607f12020-08-05 10:46:05 -0400496 CBS *contents) {
Steven Valdez6b8509a2016-07-12 13:38:32 -0400497 if (contents != NULL) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400498 // Servers MUST NOT send this extension.
Steven Valdez6b8509a2016-07-12 13:38:32 -0400499 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
500 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
David Benjamin31640932017-10-11 13:22:39 -0400501 return false;
Steven Valdez6b8509a2016-07-12 13:38:32 -0400502 }
503
David Benjamin31640932017-10-11 13:22:39 -0400504 return true;
Steven Valdez6b8509a2016-07-12 13:38:32 -0400505}
506
David Benjamin31640932017-10-11 13:22:39 -0400507static bool ignore_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
Steven Valdez51607f12020-08-05 10:46:05 -0400508 CBS *contents) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400509 // This extension from the client is handled elsewhere.
David Benjamin31640932017-10-11 13:22:39 -0400510 return true;
Steven Valdez6b8509a2016-07-12 13:38:32 -0400511}
512
David Benjamin31640932017-10-11 13:22:39 -0400513static bool dont_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
514 return true;
Steven Valdez6b8509a2016-07-12 13:38:32 -0400515}
Adam Langley614c66a2015-06-12 15:26:58 -0700516
David Benjaminc11ea9422017-08-29 16:33:21 -0400517// Server name indication (SNI).
518//
519// https://tools.ietf.org/html/rfc6066#section-3.
Adam Langley614c66a2015-06-12 15:26:58 -0700520
David Benjamin83a49932021-05-20 15:57:09 -0400521static bool ext_sni_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
522 CBB *out_compressible,
523 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -0400524 const SSL *const ssl = hs->ssl;
David Benjamin83a49932021-05-20 15:57:09 -0400525 // If offering ECH, send the public name instead of the configured name.
526 Span<const uint8_t> hostname;
527 if (type == ssl_client_hello_outer) {
528 hostname = hs->selected_ech_config->public_name;
529 } else {
530 if (ssl->hostname == nullptr) {
531 return true;
532 }
533 hostname =
534 MakeConstSpan(reinterpret_cast<const uint8_t *>(ssl->hostname.get()),
535 strlen(ssl->hostname.get()));
Adam Langley614c66a2015-06-12 15:26:58 -0700536 }
537
538 CBB contents, server_name_list, name;
539 if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) ||
540 !CBB_add_u16_length_prefixed(out, &contents) ||
541 !CBB_add_u16_length_prefixed(&contents, &server_name_list) ||
542 !CBB_add_u8(&server_name_list, TLSEXT_NAMETYPE_host_name) ||
543 !CBB_add_u16_length_prefixed(&server_name_list, &name) ||
David Benjamin83a49932021-05-20 15:57:09 -0400544 !CBB_add_bytes(&name, hostname.data(), hostname.size()) ||
Adam Langley614c66a2015-06-12 15:26:58 -0700545 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -0400546 return false;
Adam Langley614c66a2015-06-12 15:26:58 -0700547 }
548
David Benjamin31640932017-10-11 13:22:39 -0400549 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700550}
551
David Benjamin31640932017-10-11 13:22:39 -0400552static bool ext_sni_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
553 CBS *contents) {
David Benjamina8614602017-09-06 15:40:19 -0400554 // The server may acknowledge SNI with an empty extension. We check the syntax
555 // but otherwise ignore this signal.
556 return contents == NULL || CBS_len(contents) == 0;
Adam Langley614c66a2015-06-12 15:26:58 -0700557}
558
David Benjamin31640932017-10-11 13:22:39 -0400559static bool ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
560 CBS *contents) {
David Benjaminef0183c2019-07-20 09:11:05 -0400561 // SNI has already been parsed earlier in the handshake. See |extract_sni|.
David Benjamin31640932017-10-11 13:22:39 -0400562 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700563}
564
David Benjamin31640932017-10-11 13:22:39 -0400565static bool ext_sni_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -0500566 if (hs->ssl->s3->session_reused ||
567 !hs->should_ack_sni) {
David Benjamin31640932017-10-11 13:22:39 -0400568 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700569 }
570
571 if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) ||
572 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -0400573 return false;
Adam Langley614c66a2015-06-12 15:26:58 -0700574 }
575
David Benjamin31640932017-10-11 13:22:39 -0400576 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700577}
578
579
Daniel McArdle00e434d2021-02-18 11:47:18 -0500580// Encrypted ClientHello (ECH)
Dan McArdle1920c6f2020-03-11 17:29:40 -0400581//
David Benjamin18b68362021-06-18 23:13:46 -0400582// https://tools.ietf.org/html/draft-ietf-tls-esni-13
Dan McArdle1920c6f2020-03-11 17:29:40 -0400583
David Benjamin83a49932021-05-20 15:57:09 -0400584static bool ext_ech_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
585 CBB *out_compressible,
586 ssl_client_hello_type_t type) {
David Benjamin18b68362021-06-18 23:13:46 -0400587 if (type == ssl_client_hello_inner) {
588 if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
589 !CBB_add_u16(out, /* length */ 1) ||
590 !CBB_add_u8(out, ECH_CLIENT_INNER)) {
591 return false;
592 }
593 return true;
594 }
595
596 if (hs->ech_client_outer.empty()) {
Dan McArdle1920c6f2020-03-11 17:29:40 -0400597 return true;
598 }
599
David Benjamin83a49932021-05-20 15:57:09 -0400600 CBB ech_body;
601 if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
602 !CBB_add_u16_length_prefixed(out, &ech_body) ||
David Benjamin18b68362021-06-18 23:13:46 -0400603 !CBB_add_u8(&ech_body, ECH_CLIENT_OUTER) ||
604 !CBB_add_bytes(&ech_body, hs->ech_client_outer.data(),
605 hs->ech_client_outer.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -0400606 !CBB_flush(out)) {
Dan McArdle1920c6f2020-03-11 17:29:40 -0400607 return false;
608 }
David Benjamin246c5562021-05-20 13:42:25 -0400609 return true;
Dan McArdle1920c6f2020-03-11 17:29:40 -0400610}
611
Dan McArdle1920c6f2020-03-11 17:29:40 -0400612static bool ext_ech_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
613 CBS *contents) {
David Benjamin5b7ec832021-06-02 11:12:13 -0400614 SSL *const ssl = hs->ssl;
Dan McArdle1920c6f2020-03-11 17:29:40 -0400615 if (contents == NULL) {
616 return true;
617 }
618
David Benjamin5b7ec832021-06-02 11:12:13 -0400619 // The ECH extension may not be sent in TLS 1.2 ServerHello, only TLS 1.3
David Benjamin18b68362021-06-18 23:13:46 -0400620 // EncryptedExtensions. It also may not be sent in response to an inner ECH
621 // extension.
622 if (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
623 ssl->s3->ech_status == ssl_ech_accepted) {
David Benjamin5b7ec832021-06-02 11:12:13 -0400624 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
625 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
626 return false;
627 }
628
David Benjaminba423c92021-06-15 16:26:58 -0400629 if (!ssl_is_valid_ech_config_list(*contents)) {
630 *out_alert = SSL_AD_DECODE_ERROR;
631 return false;
632 }
633
David Benjamin18b68362021-06-18 23:13:46 -0400634 if (ssl->s3->ech_status == ssl_ech_rejected &&
David Benjaminba423c92021-06-15 16:26:58 -0400635 !hs->ech_retry_configs.CopyFrom(*contents)) {
636 *out_alert = SSL_AD_INTERNAL_ERROR;
Dan McArdle1920c6f2020-03-11 17:29:40 -0400637 return false;
638 }
David Benjaminba423c92021-06-15 16:26:58 -0400639
Dan McArdle1920c6f2020-03-11 17:29:40 -0400640 return true;
641}
642
Dan McArdlec2959352020-10-29 14:31:31 -0400643static bool ext_ech_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
644 CBS *contents) {
David Benjamin18b68362021-06-18 23:13:46 -0400645 if (contents == nullptr) {
Dan McArdlec2959352020-10-29 14:31:31 -0400646 return true;
647 }
David Benjamin18b68362021-06-18 23:13:46 -0400648
649 uint8_t type;
650 if (!CBS_get_u8(contents, &type)) {
651 return false;
652 }
653 if (type == ECH_CLIENT_OUTER) {
654 // Outer ECH extensions are handled outside the callback.
655 return true;
656 }
657 if (type != ECH_CLIENT_INNER || CBS_len(contents) != 0) {
658 return false;
659 }
660
661 hs->ech_is_inner = true;
Dan McArdlec2959352020-10-29 14:31:31 -0400662 return true;
663}
664
Daniel McArdle00e434d2021-02-18 11:47:18 -0500665static bool ext_ech_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
666 SSL *const ssl = hs->ssl;
David Benjaminba423c92021-06-15 16:26:58 -0400667 if (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
668 ssl->s3->ech_status == ssl_ech_accepted || //
David Benjaminc3b373b2021-06-06 13:04:26 -0400669 hs->ech_keys == nullptr) {
Daniel McArdle00e434d2021-02-18 11:47:18 -0500670 return true;
671 }
672
David Benjaminc3b373b2021-06-06 13:04:26 -0400673 // Write the list of retry configs to |out|. Note |SSL_CTX_set1_ech_keys|
674 // ensures |ech_keys| contains at least one retry config.
Daniel McArdle00e434d2021-02-18 11:47:18 -0500675 CBB body, retry_configs;
676 if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
677 !CBB_add_u16_length_prefixed(out, &body) ||
678 !CBB_add_u16_length_prefixed(&body, &retry_configs)) {
679 return false;
680 }
David Benjaminc3b373b2021-06-06 13:04:26 -0400681 for (const auto &config : hs->ech_keys->configs) {
David Benjamin1d58cd12021-05-04 15:24:24 -0400682 if (!config->is_retry_config()) {
Daniel McArdle00e434d2021-02-18 11:47:18 -0500683 continue;
684 }
David Benjamin83a49932021-05-20 15:57:09 -0400685 if (!CBB_add_bytes(&retry_configs, config->ech_config().raw.data(),
686 config->ech_config().raw.size())) {
Daniel McArdle00e434d2021-02-18 11:47:18 -0500687 return false;
688 }
689 }
690 return CBB_flush(out);
691}
692
Dan McArdle1920c6f2020-03-11 17:29:40 -0400693
David Benjaminc11ea9422017-08-29 16:33:21 -0400694// Renegotiation indication.
695//
696// https://tools.ietf.org/html/rfc5746
Adam Langley5021b222015-06-12 18:27:58 -0700697
David Benjamin83a49932021-05-20 15:57:09 -0400698static bool ext_ri_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
699 CBB *out_compressible,
700 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -0400701 const SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400702 // Renegotiation indication is not necessary in TLS 1.3.
David Benjamin83a49932021-05-20 15:57:09 -0400703 if (hs->min_version >= TLS1_3_VERSION ||
704 type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -0400705 return true;
David Benjamin7c7d8312016-08-20 13:39:03 -0400706 }
707
David Benjamin52bf6902016-10-08 12:05:03 -0400708 assert(ssl->s3->initial_handshake_complete ==
709 (ssl->s3->previous_client_finished_len != 0));
710
Adam Langley5021b222015-06-12 18:27:58 -0700711 CBB contents, prev_finished;
712 if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
713 !CBB_add_u16_length_prefixed(out, &contents) ||
714 !CBB_add_u8_length_prefixed(&contents, &prev_finished) ||
715 !CBB_add_bytes(&prev_finished, ssl->s3->previous_client_finished,
716 ssl->s3->previous_client_finished_len) ||
717 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -0400718 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700719 }
720
David Benjamin31640932017-10-11 13:22:39 -0400721 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700722}
723
David Benjamin31640932017-10-11 13:22:39 -0400724static bool ext_ri_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
725 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500726 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -0400727 if (contents != NULL && ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
Steven Valdez246eeee2017-03-26 12:49:17 -0500728 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -0400729 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -0400730 }
731
David Benjaminc11ea9422017-08-29 16:33:21 -0400732 // Servers may not switch between omitting the extension and supporting it.
733 // See RFC 5746, sections 3.5 and 4.2.
David Benjamin3e052de2015-11-25 20:10:31 -0500734 if (ssl->s3->initial_handshake_complete &&
735 (contents != NULL) != ssl->s3->send_connection_binding) {
736 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
737 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
David Benjamin31640932017-10-11 13:22:39 -0400738 return false;
David Benjamin3e052de2015-11-25 20:10:31 -0500739 }
740
Adam Langley5021b222015-06-12 18:27:58 -0700741 if (contents == NULL) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400742 // Strictly speaking, if we want to avoid an attack we should *always* see
743 // RI even on initial ServerHello because the client doesn't see any
744 // renegotiation during an attack. However this would mean we could not
745 // connect to any server which doesn't support RI.
746 //
747 // OpenSSL has |SSL_OP_LEGACY_SERVER_CONNECT| to control this, but in
748 // practical terms every client sets it so it's just assumed here.
David Benjamin31640932017-10-11 13:22:39 -0400749 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700750 }
751
752 const size_t expected_len = ssl->s3->previous_client_finished_len +
753 ssl->s3->previous_server_finished_len;
754
David Benjaminc11ea9422017-08-29 16:33:21 -0400755 // Check for logic errors
Adam Langley5021b222015-06-12 18:27:58 -0700756 assert(!expected_len || ssl->s3->previous_client_finished_len);
757 assert(!expected_len || ssl->s3->previous_server_finished_len);
David Benjamin52bf6902016-10-08 12:05:03 -0400758 assert(ssl->s3->initial_handshake_complete ==
759 (ssl->s3->previous_client_finished_len != 0));
760 assert(ssl->s3->initial_handshake_complete ==
761 (ssl->s3->previous_server_finished_len != 0));
Adam Langley5021b222015-06-12 18:27:58 -0700762
David Benjaminc11ea9422017-08-29 16:33:21 -0400763 // Parse out the extension contents.
Adam Langley5021b222015-06-12 18:27:58 -0700764 CBS renegotiated_connection;
765 if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) ||
766 CBS_len(contents) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400767 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR);
Adam Langley5021b222015-06-12 18:27:58 -0700768 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -0400769 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700770 }
771
David Benjaminc11ea9422017-08-29 16:33:21 -0400772 // Check that the extension matches.
Adam Langley5021b222015-06-12 18:27:58 -0700773 if (CBS_len(&renegotiated_connection) != expected_len) {
David Benjamin3570d732015-06-29 00:28:17 -0400774 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
Adam Langley5021b222015-06-12 18:27:58 -0700775 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
David Benjamin31640932017-10-11 13:22:39 -0400776 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700777 }
778
779 const uint8_t *d = CBS_data(&renegotiated_connection);
David Benjamin31640932017-10-11 13:22:39 -0400780 bool ok = CRYPTO_memcmp(d, ssl->s3->previous_client_finished,
781 ssl->s3->previous_client_finished_len) == 0;
David Benjamin9343b0b2017-07-01 00:31:27 -0400782#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin31640932017-10-11 13:22:39 -0400783 ok = true;
David Benjamin9343b0b2017-07-01 00:31:27 -0400784#endif
785 if (!ok) {
David Benjamin3570d732015-06-29 00:28:17 -0400786 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
Adam Langley5021b222015-06-12 18:27:58 -0700787 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
David Benjamin31640932017-10-11 13:22:39 -0400788 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700789 }
790 d += ssl->s3->previous_client_finished_len;
791
David Benjamin9343b0b2017-07-01 00:31:27 -0400792 ok = CRYPTO_memcmp(d, ssl->s3->previous_server_finished,
793 ssl->s3->previous_server_finished_len) == 0;
794#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin31640932017-10-11 13:22:39 -0400795 ok = true;
David Benjamin9343b0b2017-07-01 00:31:27 -0400796#endif
797 if (!ok) {
David Benjamin3570d732015-06-29 00:28:17 -0400798 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
Adam Langley10e10602017-07-25 13:33:21 -0700799 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
David Benjamin31640932017-10-11 13:22:39 -0400800 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700801 }
David Benjamin046bc1f2017-08-31 15:06:42 -0400802 ssl->s3->send_connection_binding = true;
Adam Langley5021b222015-06-12 18:27:58 -0700803
David Benjamin31640932017-10-11 13:22:39 -0400804 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700805}
806
David Benjamin31640932017-10-11 13:22:39 -0400807static bool ext_ri_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
808 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500809 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400810 // Renegotiation isn't supported as a server so this function should never be
811 // called after the initial handshake.
Adam Langley5021b222015-06-12 18:27:58 -0700812 assert(!ssl->s3->initial_handshake_complete);
813
David Benjamind1e3ce12017-10-06 18:31:15 -0400814 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400815 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -0400816 }
817
Adam Langley5021b222015-06-12 18:27:58 -0700818 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -0400819 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700820 }
821
822 CBS renegotiated_connection;
Adam Langley5021b222015-06-12 18:27:58 -0700823 if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) ||
824 CBS_len(contents) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400825 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR);
David Benjamin31640932017-10-11 13:22:39 -0400826 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700827 }
828
David Benjaminc11ea9422017-08-29 16:33:21 -0400829 // Check that the extension matches. We do not support renegotiation as a
830 // server, so this must be empty.
David Benjamin52bf6902016-10-08 12:05:03 -0400831 if (CBS_len(&renegotiated_connection) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400832 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
Adam Langley5021b222015-06-12 18:27:58 -0700833 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
David Benjamin31640932017-10-11 13:22:39 -0400834 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700835 }
836
David Benjamin046bc1f2017-08-31 15:06:42 -0400837 ssl->s3->send_connection_binding = true;
Adam Langley5021b222015-06-12 18:27:58 -0700838
David Benjamin31640932017-10-11 13:22:39 -0400839 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700840}
841
David Benjamin31640932017-10-11 13:22:39 -0400842static bool ext_ri_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -0500843 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400844 // Renegotiation isn't supported as a server so this function should never be
845 // called after the initial handshake.
David Benjamin52bf6902016-10-08 12:05:03 -0400846 assert(!ssl->s3->initial_handshake_complete);
847
David Benjamind1e3ce12017-10-06 18:31:15 -0400848 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400849 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -0400850 }
851
Adam Langley5021b222015-06-12 18:27:58 -0700852 if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
David Benjamin52bf6902016-10-08 12:05:03 -0400853 !CBB_add_u16(out, 1 /* length */) ||
854 !CBB_add_u8(out, 0 /* empty renegotiation info */)) {
David Benjamin31640932017-10-11 13:22:39 -0400855 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700856 }
857
David Benjamin31640932017-10-11 13:22:39 -0400858 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700859}
860
Adam Langley0a056712015-07-01 15:03:33 -0700861
David Benjaminc11ea9422017-08-29 16:33:21 -0400862// Extended Master Secret.
863//
864// https://tools.ietf.org/html/rfc7627
Adam Langley0a056712015-07-01 15:03:33 -0700865
David Benjamin83a49932021-05-20 15:57:09 -0400866static bool ext_ems_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
867 CBB *out_compressible,
868 ssl_client_hello_type_t type) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400869 // Extended master secret is not necessary in TLS 1.3.
David Benjamin83a49932021-05-20 15:57:09 -0400870 if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -0400871 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700872 }
873
874 if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) ||
875 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -0400876 return false;
Adam Langley0a056712015-07-01 15:03:33 -0700877 }
878
David Benjamin31640932017-10-11 13:22:39 -0400879 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700880}
881
David Benjamin31640932017-10-11 13:22:39 -0400882static bool ext_ems_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
883 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500884 SSL *const ssl = hs->ssl;
David Benjaminfc02b592017-02-17 16:26:01 -0500885
886 if (contents != NULL) {
David Benjamind1e3ce12017-10-06 18:31:15 -0400887 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
David Benjaminfc02b592017-02-17 16:26:01 -0500888 CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -0400889 return false;
David Benjamin163c9562016-08-29 23:14:17 -0400890 }
891
David Benjaminfd45ee72017-08-31 14:49:09 -0400892 hs->extended_master_secret = true;
David Benjamin163c9562016-08-29 23:14:17 -0400893 }
894
David Benjaminc11ea9422017-08-29 16:33:21 -0400895 // Whether EMS is negotiated may not change on renegotiation.
David Benjamin8e7bbba2017-10-13 17:18:35 -0400896 if (ssl->s3->established_session != nullptr &&
David Benjaminfc02b592017-02-17 16:26:01 -0500897 hs->extended_master_secret !=
David Benjaminfd45ee72017-08-31 14:49:09 -0400898 !!ssl->s3->established_session->extended_master_secret) {
David Benjaminfc02b592017-02-17 16:26:01 -0500899 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_EMS_MISMATCH);
900 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -0400901 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -0400902 }
903
David Benjamin31640932017-10-11 13:22:39 -0400904 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700905}
906
David Benjamin31640932017-10-11 13:22:39 -0400907static bool ext_ems_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
908 CBS *contents) {
David Benjamin9bb15f52018-06-26 00:07:40 -0400909 if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400910 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -0400911 }
912
913 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -0400914 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700915 }
916
917 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -0400918 return false;
Adam Langley0a056712015-07-01 15:03:33 -0700919 }
920
David Benjaminfd45ee72017-08-31 14:49:09 -0400921 hs->extended_master_secret = true;
David Benjamin31640932017-10-11 13:22:39 -0400922 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700923}
924
David Benjamin31640932017-10-11 13:22:39 -0400925static bool ext_ems_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjaminfc02b592017-02-17 16:26:01 -0500926 if (!hs->extended_master_secret) {
David Benjamin31640932017-10-11 13:22:39 -0400927 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700928 }
929
930 if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) ||
931 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -0400932 return false;
Adam Langley0a056712015-07-01 15:03:33 -0700933 }
934
David Benjamin31640932017-10-11 13:22:39 -0400935 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700936}
937
Adam Langley9b05bc52015-07-01 15:25:33 -0700938
David Benjaminc11ea9422017-08-29 16:33:21 -0400939// Session tickets.
940//
941// https://tools.ietf.org/html/rfc5077
Adam Langley9b05bc52015-07-01 15:25:33 -0700942
David Benjamin83a49932021-05-20 15:57:09 -0400943static bool ext_ticket_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
944 CBB *out_compressible,
945 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -0400946 const SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400947 // TLS 1.3 uses a different ticket extension.
David Benjamin83a49932021-05-20 15:57:09 -0400948 if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner ||
David Benjamin7c7d8312016-08-20 13:39:03 -0400949 SSL_get_options(ssl) & SSL_OP_NO_TICKET) {
David Benjamin31640932017-10-11 13:22:39 -0400950 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700951 }
952
David Benjaminbfdd1a92018-06-29 16:26:38 -0400953 Span<const uint8_t> ticket;
Adam Langley9b05bc52015-07-01 15:25:33 -0700954
David Benjaminc11ea9422017-08-29 16:33:21 -0400955 // Renegotiation does not participate in session resumption. However, still
956 // advertise the extension to avoid potentially breaking servers which carry
957 // over the state from the previous handshake, such as OpenSSL servers
958 // without upstream's 3c3f0259238594d77264a78944d409f2127642c4.
Adam Langley9b05bc52015-07-01 15:25:33 -0700959 if (!ssl->s3->initial_handshake_complete &&
David Benjamin50596f82018-07-02 19:47:27 -0400960 ssl->session != nullptr &&
David Benjaminbfdd1a92018-06-29 16:26:38 -0400961 !ssl->session->ticket.empty() &&
David Benjaminc11ea9422017-08-29 16:33:21 -0400962 // Don't send TLS 1.3 session tickets in the ticket extension.
David Benjamin50596f82018-07-02 19:47:27 -0400963 ssl_session_protocol_version(ssl->session.get()) < TLS1_3_VERSION) {
David Benjaminbfdd1a92018-06-29 16:26:38 -0400964 ticket = ssl->session->ticket;
Adam Langley9b05bc52015-07-01 15:25:33 -0700965 }
966
David Benjaminbfdd1a92018-06-29 16:26:38 -0400967 CBB ticket_cbb;
Adam Langley9b05bc52015-07-01 15:25:33 -0700968 if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
David Benjaminbfdd1a92018-06-29 16:26:38 -0400969 !CBB_add_u16_length_prefixed(out, &ticket_cbb) ||
970 !CBB_add_bytes(&ticket_cbb, ticket.data(), ticket.size()) ||
Adam Langley9b05bc52015-07-01 15:25:33 -0700971 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -0400972 return false;
Adam Langley9b05bc52015-07-01 15:25:33 -0700973 }
974
David Benjamin31640932017-10-11 13:22:39 -0400975 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700976}
977
David Benjamin31640932017-10-11 13:22:39 -0400978static bool ext_ticket_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
979 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500980 SSL *const ssl = hs->ssl;
Adam Langley9b05bc52015-07-01 15:25:33 -0700981 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -0400982 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700983 }
984
David Benjamind1e3ce12017-10-06 18:31:15 -0400985 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400986 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -0400987 }
988
David Benjaminc11ea9422017-08-29 16:33:21 -0400989 // If |SSL_OP_NO_TICKET| is set then no extension will have been sent and
990 // this function should never be called, even if the server tries to send the
991 // extension.
Adam Langley9b05bc52015-07-01 15:25:33 -0700992 assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0);
993
994 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -0400995 return false;
Adam Langley9b05bc52015-07-01 15:25:33 -0700996 }
997
David Benjaminfd45ee72017-08-31 14:49:09 -0400998 hs->ticket_expected = true;
David Benjamin31640932017-10-11 13:22:39 -0400999 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -07001000}
1001
David Benjamin31640932017-10-11 13:22:39 -04001002static bool ext_ticket_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001003 if (!hs->ticket_expected) {
David Benjamin31640932017-10-11 13:22:39 -04001004 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -07001005 }
1006
David Benjaminc11ea9422017-08-29 16:33:21 -04001007 // If |SSL_OP_NO_TICKET| is set, |ticket_expected| should never be true.
David Benjamin8c880a22016-12-03 02:20:34 -05001008 assert((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) == 0);
Adam Langley9b05bc52015-07-01 15:25:33 -07001009
1010 if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
1011 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001012 return false;
Adam Langley9b05bc52015-07-01 15:25:33 -07001013 }
1014
David Benjamin31640932017-10-11 13:22:39 -04001015 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -07001016}
1017
1018
David Benjaminc11ea9422017-08-29 16:33:21 -04001019// Signature Algorithms.
1020//
1021// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
Adam Langley2e857bd2015-07-01 16:09:19 -07001022
David Benjamin83a49932021-05-20 15:57:09 -04001023static bool ext_sigalgs_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1024 CBB *out_compressible,
1025 ssl_client_hello_type_t type) {
David Benjamin68161cb2017-06-20 14:49:43 -04001026 if (hs->max_version < TLS1_2_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001027 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001028 }
1029
David Benjamin0fc37ef2016-08-17 15:29:46 -04001030 CBB contents, sigalgs_cbb;
David Benjamin83a49932021-05-20 15:57:09 -04001031 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_signature_algorithms) ||
1032 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
David Benjamin69522112017-03-28 15:38:29 -05001033 !CBB_add_u16_length_prefixed(&contents, &sigalgs_cbb) ||
David Benjaminebad5082020-02-03 19:32:19 -05001034 !tls12_add_verify_sigalgs(hs, &sigalgs_cbb) ||
David Benjamin83a49932021-05-20 15:57:09 -04001035 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001036 return false;
Adam Langley2e857bd2015-07-01 16:09:19 -07001037 }
1038
David Benjamin31640932017-10-11 13:22:39 -04001039 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001040}
1041
David Benjamin31640932017-10-11 13:22:39 -04001042static bool ext_sigalgs_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1043 CBS *contents) {
David Benjaminb1cf48e2017-09-21 11:37:46 -04001044 hs->peer_sigalgs.Reset();
Adam Langley2e857bd2015-07-01 16:09:19 -07001045 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001046 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001047 }
1048
1049 CBS supported_signature_algorithms;
1050 if (!CBS_get_u16_length_prefixed(contents, &supported_signature_algorithms) ||
Steven Valdez0d62f262015-09-04 12:41:04 -04001051 CBS_len(contents) != 0 ||
David Benjaminf3c8f8d2016-11-17 17:20:47 +09001052 !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
David Benjamin31640932017-10-11 13:22:39 -04001053 return false;
Adam Langley2e857bd2015-07-01 16:09:19 -07001054 }
1055
David Benjamin31640932017-10-11 13:22:39 -04001056 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001057}
1058
Adam Langley2e857bd2015-07-01 16:09:19 -07001059
David Benjaminc11ea9422017-08-29 16:33:21 -04001060// OCSP Stapling.
1061//
1062// https://tools.ietf.org/html/rfc6066#section-8
Adam Langleybb0bd042015-07-01 16:21:03 -07001063
David Benjamin83a49932021-05-20 15:57:09 -04001064static bool ext_ocsp_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1065 CBB *out_compressible,
1066 ssl_client_hello_type_t type) {
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001067 if (!hs->config->ocsp_stapling_enabled) {
David Benjamin31640932017-10-11 13:22:39 -04001068 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001069 }
1070
1071 CBB contents;
David Benjamin83a49932021-05-20 15:57:09 -04001072 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_status_request) ||
1073 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Adam Langleybb0bd042015-07-01 16:21:03 -07001074 !CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) ||
1075 !CBB_add_u16(&contents, 0 /* empty responder ID list */) ||
1076 !CBB_add_u16(&contents, 0 /* empty request extensions */) ||
David Benjamin83a49932021-05-20 15:57:09 -04001077 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001078 return false;
Adam Langleybb0bd042015-07-01 16:21:03 -07001079 }
1080
David Benjamin31640932017-10-11 13:22:39 -04001081 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001082}
1083
David Benjamin31640932017-10-11 13:22:39 -04001084static bool ext_ocsp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1085 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001086 SSL *const ssl = hs->ssl;
Adam Langleybb0bd042015-07-01 16:21:03 -07001087 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001088 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001089 }
1090
David Benjaminc11ea9422017-08-29 16:33:21 -04001091 // TLS 1.3 OCSP responses are included in the Certificate extensions.
David Benjamind1e3ce12017-10-06 18:31:15 -04001092 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001093 return false;
Steven Valdez803c77a2016-09-06 14:13:43 -04001094 }
1095
David Benjaminc11ea9422017-08-29 16:33:21 -04001096 // OCSP stapling is forbidden on non-certificate ciphers.
Steven Valdeza833c352016-11-01 13:39:36 -04001097 if (CBS_len(contents) != 0 ||
David Benjamin45738dd2017-02-09 20:01:26 -05001098 !ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
David Benjamin31640932017-10-11 13:22:39 -04001099 return false;
David Benjamin942f4ed2016-07-16 19:03:49 +03001100 }
1101
David Benjaminc11ea9422017-08-29 16:33:21 -04001102 // Note this does not check for resumption in TLS 1.2. Sending
1103 // status_request here does not make sense, but OpenSSL does so and the
1104 // specification does not say anything. Tolerate it but ignore it.
David Benjamin942f4ed2016-07-16 19:03:49 +03001105
David Benjaminfd45ee72017-08-31 14:49:09 -04001106 hs->certificate_status_expected = true;
David Benjamin31640932017-10-11 13:22:39 -04001107 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001108}
1109
David Benjamin31640932017-10-11 13:22:39 -04001110static bool ext_ocsp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1111 CBS *contents) {
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001112 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001113 return true;
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001114 }
1115
1116 uint8_t status_type;
1117 if (!CBS_get_u8(contents, &status_type)) {
David Benjamin31640932017-10-11 13:22:39 -04001118 return false;
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001119 }
1120
David Benjaminc11ea9422017-08-29 16:33:21 -04001121 // We cannot decide whether OCSP stapling will occur yet because the correct
1122 // SSL_CTX might not have been selected.
David Benjamin8c880a22016-12-03 02:20:34 -05001123 hs->ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp;
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001124
David Benjamin31640932017-10-11 13:22:39 -04001125 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001126}
1127
David Benjamin31640932017-10-11 13:22:39 -04001128static bool ext_ocsp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001129 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04001130 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001131 !hs->ocsp_stapling_requested || hs->config->cert->ocsp_response == NULL ||
Steven Valdez803c77a2016-09-06 14:13:43 -04001132 ssl->s3->session_reused ||
David Benjamin45738dd2017-02-09 20:01:26 -05001133 !ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
David Benjamin31640932017-10-11 13:22:39 -04001134 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001135 }
1136
David Benjaminfd45ee72017-08-31 14:49:09 -04001137 hs->certificate_status_expected = true;
David Benjamin942f4ed2016-07-16 19:03:49 +03001138
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001139 return CBB_add_u16(out, TLSEXT_TYPE_status_request) &&
Steven Valdeza833c352016-11-01 13:39:36 -04001140 CBB_add_u16(out, 0 /* length */);
Adam Langleybb0bd042015-07-01 16:21:03 -07001141}
1142
1143
David Benjaminc11ea9422017-08-29 16:33:21 -04001144// Next protocol negotiation.
1145//
1146// https://htmlpreview.github.io/?https://github.com/agl/technotes/blob/master/nextprotoneg.html
Adam Langley97dfcbf2015-07-01 18:35:20 -07001147
David Benjamin83a49932021-05-20 15:57:09 -04001148static bool ext_npn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1149 CBB *out_compressible,
1150 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001151 const SSL *const ssl = hs->ssl;
David Benjamin83a49932021-05-20 15:57:09 -04001152 if (ssl->ctx->next_proto_select_cb == NULL ||
1153 // Do not allow NPN to change on renegotiation.
1154 ssl->s3->initial_handshake_complete ||
1155 // NPN is not defined in DTLS or TLS 1.3.
1156 SSL_is_dtls(ssl) || hs->min_version >= TLS1_3_VERSION ||
1157 type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -04001158 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001159 }
1160
1161 if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) ||
1162 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001163 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001164 }
1165
David Benjamin31640932017-10-11 13:22:39 -04001166 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001167}
1168
David Benjamin31640932017-10-11 13:22:39 -04001169static bool ext_npn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1170 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001171 SSL *const ssl = hs->ssl;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001172 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001173 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001174 }
1175
David Benjamind1e3ce12017-10-06 18:31:15 -04001176 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001177 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04001178 }
1179
David Benjaminc11ea9422017-08-29 16:33:21 -04001180 // If any of these are false then we should never have sent the NPN
1181 // extension in the ClientHello and thus this function should never have been
1182 // called.
Adam Langley97dfcbf2015-07-01 18:35:20 -07001183 assert(!ssl->s3->initial_handshake_complete);
David Benjamince079fd2016-08-02 16:22:34 -04001184 assert(!SSL_is_dtls(ssl));
Adam Langley97dfcbf2015-07-01 18:35:20 -07001185 assert(ssl->ctx->next_proto_select_cb != NULL);
1186
David Benjamin8e7bbba2017-10-13 17:18:35 -04001187 if (!ssl->s3->alpn_selected.empty()) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001188 // NPN and ALPN may not be negotiated in the same connection.
David Benjamin76c2efc2015-08-31 14:24:29 -04001189 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1190 OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
David Benjamin31640932017-10-11 13:22:39 -04001191 return false;
David Benjamin76c2efc2015-08-31 14:24:29 -04001192 }
1193
Adam Langley97dfcbf2015-07-01 18:35:20 -07001194 const uint8_t *const orig_contents = CBS_data(contents);
1195 const size_t orig_len = CBS_len(contents);
1196
1197 while (CBS_len(contents) != 0) {
1198 CBS proto;
1199 if (!CBS_get_u8_length_prefixed(contents, &proto) ||
1200 CBS_len(&proto) == 0) {
David Benjamin31640932017-10-11 13:22:39 -04001201 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001202 }
1203 }
1204
David Benjamin9d64d8d2022-08-31 19:27:56 -04001205 // |orig_len| fits in |unsigned| because TLS extensions use 16-bit lengths.
Adam Langley97dfcbf2015-07-01 18:35:20 -07001206 uint8_t *selected;
1207 uint8_t selected_len;
1208 if (ssl->ctx->next_proto_select_cb(
David Benjamin9d64d8d2022-08-31 19:27:56 -04001209 ssl, &selected, &selected_len, orig_contents,
1210 static_cast<unsigned>(orig_len),
David Benjamin8e7bbba2017-10-13 17:18:35 -04001211 ssl->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK ||
1212 !ssl->s3->next_proto_negotiated.CopyFrom(
1213 MakeConstSpan(selected, selected_len))) {
Adam Langley97dfcbf2015-07-01 18:35:20 -07001214 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001215 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001216 }
1217
David Benjaminfd45ee72017-08-31 14:49:09 -04001218 hs->next_proto_neg_seen = true;
David Benjamin31640932017-10-11 13:22:39 -04001219 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001220}
1221
David Benjamin31640932017-10-11 13:22:39 -04001222static bool ext_npn_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1223 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001224 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04001225 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001226 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001227 }
1228
Adam Langley97dfcbf2015-07-01 18:35:20 -07001229 if (contents != NULL && CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001230 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001231 }
1232
1233 if (contents == NULL ||
1234 ssl->s3->initial_handshake_complete ||
Adam Langley97dfcbf2015-07-01 18:35:20 -07001235 ssl->ctx->next_protos_advertised_cb == NULL ||
David Benjamince079fd2016-08-02 16:22:34 -04001236 SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001237 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001238 }
1239
David Benjaminfd45ee72017-08-31 14:49:09 -04001240 hs->next_proto_neg_seen = true;
David Benjamin31640932017-10-11 13:22:39 -04001241 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001242}
1243
David Benjamin31640932017-10-11 13:22:39 -04001244static bool ext_npn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001245 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -04001246 // |next_proto_neg_seen| might have been cleared when an ALPN extension was
1247 // parsed.
David Benjamin8c880a22016-12-03 02:20:34 -05001248 if (!hs->next_proto_neg_seen) {
David Benjamin31640932017-10-11 13:22:39 -04001249 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001250 }
1251
1252 const uint8_t *npa;
1253 unsigned npa_len;
1254
1255 if (ssl->ctx->next_protos_advertised_cb(
1256 ssl, &npa, &npa_len, ssl->ctx->next_protos_advertised_cb_arg) !=
1257 SSL_TLSEXT_ERR_OK) {
David Benjaminfd45ee72017-08-31 14:49:09 -04001258 hs->next_proto_neg_seen = false;
David Benjamin31640932017-10-11 13:22:39 -04001259 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001260 }
1261
1262 CBB contents;
1263 if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) ||
1264 !CBB_add_u16_length_prefixed(out, &contents) ||
1265 !CBB_add_bytes(&contents, npa, npa_len) ||
1266 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001267 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001268 }
1269
David Benjamin31640932017-10-11 13:22:39 -04001270 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001271}
1272
1273
David Benjaminc11ea9422017-08-29 16:33:21 -04001274// Signed certificate timestamps.
1275//
1276// https://tools.ietf.org/html/rfc6962#section-3.3.1
Adam Langleyab8d87d2015-07-10 12:21:39 -07001277
David Benjamin83a49932021-05-20 15:57:09 -04001278static bool ext_sct_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1279 CBB *out_compressible,
1280 ssl_client_hello_type_t type) {
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001281 if (!hs->config->signed_cert_timestamps_enabled) {
David Benjamin31640932017-10-11 13:22:39 -04001282 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001283 }
1284
David Benjamin83a49932021-05-20 15:57:09 -04001285 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_certificate_timestamp) ||
1286 !CBB_add_u16(out_compressible, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001287 return false;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001288 }
1289
David Benjamin31640932017-10-11 13:22:39 -04001290 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001291}
1292
David Benjamin31640932017-10-11 13:22:39 -04001293static bool ext_sct_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1294 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001295 SSL *const ssl = hs->ssl;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001296 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001297 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001298 }
1299
David Benjaminc11ea9422017-08-29 16:33:21 -04001300 // TLS 1.3 SCTs are included in the Certificate extensions.
David Benjamind1e3ce12017-10-06 18:31:15 -04001301 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
Adam Langleycfa08c32016-11-17 13:21:27 -08001302 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001303 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04001304 }
1305
David Benjaminc11ea9422017-08-29 16:33:21 -04001306 // If this is false then we should never have sent the SCT extension in the
1307 // ClientHello and thus this function should never have been called.
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001308 assert(hs->config->signed_cert_timestamps_enabled);
Adam Langleyab8d87d2015-07-10 12:21:39 -07001309
Adam Langleycfa08c32016-11-17 13:21:27 -08001310 if (!ssl_is_sct_list_valid(contents)) {
Adam Langleyab8d87d2015-07-10 12:21:39 -07001311 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001312 return false;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001313 }
1314
David Benjaminc11ea9422017-08-29 16:33:21 -04001315 // Session resumption uses the original session information. The extension
1316 // should not be sent on resumption, but RFC 6962 did not make it a
1317 // requirement, so tolerate this.
1318 //
1319 // TODO(davidben): Enforce this anyway.
David Benjamin8fc2dc02017-08-22 15:07:51 -07001320 if (!ssl->s3->session_reused) {
David Benjaminbfdd1a92018-06-29 16:26:38 -04001321 hs->new_session->signed_cert_timestamp_list.reset(
1322 CRYPTO_BUFFER_new_from_CBS(contents, ssl->ctx->pool));
David Benjamin8fc2dc02017-08-22 15:07:51 -07001323 if (hs->new_session->signed_cert_timestamp_list == nullptr) {
1324 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001325 return false;
David Benjamin8fc2dc02017-08-22 15:07:51 -07001326 }
Adam Langleyab8d87d2015-07-10 12:21:39 -07001327 }
1328
David Benjamin31640932017-10-11 13:22:39 -04001329 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001330}
1331
David Benjamin31640932017-10-11 13:22:39 -04001332static bool ext_sct_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1333 CBS *contents) {
David Benjamin53210cb2016-11-16 09:01:48 +09001334 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001335 return true;
David Benjamin53210cb2016-11-16 09:01:48 +09001336 }
1337
1338 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001339 return false;
David Benjamin53210cb2016-11-16 09:01:48 +09001340 }
1341
David Benjaminfd45ee72017-08-31 14:49:09 -04001342 hs->scts_requested = true;
David Benjamin31640932017-10-11 13:22:39 -04001343 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001344}
1345
David Benjamin31640932017-10-11 13:22:39 -04001346static bool ext_sct_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001347 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -04001348 // The extension shouldn't be sent when resuming sessions.
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001349 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION || ssl->s3->session_reused ||
1350 hs->config->cert->signed_cert_timestamp_list == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001351 return true;
Paul Lietar4fac72e2015-09-09 13:44:55 +01001352 }
1353
1354 CBB contents;
1355 return CBB_add_u16(out, TLSEXT_TYPE_certificate_timestamp) &&
1356 CBB_add_u16_length_prefixed(out, &contents) &&
David Benjamin83a32122017-02-14 18:34:54 -05001357 CBB_add_bytes(
1358 &contents,
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001359 CRYPTO_BUFFER_data(
1360 hs->config->cert->signed_cert_timestamp_list.get()),
1361 CRYPTO_BUFFER_len(
1362 hs->config->cert->signed_cert_timestamp_list.get())) &&
Paul Lietar4fac72e2015-09-09 13:44:55 +01001363 CBB_flush(out);
Adam Langleyab8d87d2015-07-10 12:21:39 -07001364}
1365
1366
David Benjaminc11ea9422017-08-29 16:33:21 -04001367// Application-level Protocol Negotiation.
1368//
1369// https://tools.ietf.org/html/rfc7301
Adam Langleyf18e4532015-07-10 13:39:53 -07001370
David Benjamin83a49932021-05-20 15:57:09 -04001371static bool ext_alpn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1372 CBB *out_compressible,
1373 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001374 const SSL *const ssl = hs->ssl;
Nick Harper74161f42020-07-24 15:35:27 -07001375 if (hs->config->alpn_client_proto_list.empty() && ssl->quic_method) {
1376 // ALPN MUST be used with QUIC.
David Benjaminc02c19e2021-02-10 17:49:20 -05001377 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
Nick Harper74161f42020-07-24 15:35:27 -07001378 return false;
1379 }
1380
David Benjamin0ce090a2018-07-02 20:24:40 -04001381 if (hs->config->alpn_client_proto_list.empty() ||
Adam Langleyf18e4532015-07-10 13:39:53 -07001382 ssl->s3->initial_handshake_complete) {
David Benjamin31640932017-10-11 13:22:39 -04001383 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001384 }
1385
1386 CBB contents, proto_list;
David Benjamin83a49932021-05-20 15:57:09 -04001387 if (!CBB_add_u16(out_compressible,
1388 TLSEXT_TYPE_application_layer_protocol_negotiation) ||
1389 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Adam Langleyf18e4532015-07-10 13:39:53 -07001390 !CBB_add_u16_length_prefixed(&contents, &proto_list) ||
David Benjamin0ce090a2018-07-02 20:24:40 -04001391 !CBB_add_bytes(&proto_list, hs->config->alpn_client_proto_list.data(),
1392 hs->config->alpn_client_proto_list.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -04001393 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001394 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001395 }
1396
David Benjamin31640932017-10-11 13:22:39 -04001397 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001398}
1399
David Benjamin31640932017-10-11 13:22:39 -04001400static bool ext_alpn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1401 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001402 SSL *const ssl = hs->ssl;
Adam Langleyf18e4532015-07-10 13:39:53 -07001403 if (contents == NULL) {
Nick Harper74161f42020-07-24 15:35:27 -07001404 if (ssl->quic_method) {
1405 // ALPN is required when QUIC is used.
David Benjaminc02c19e2021-02-10 17:49:20 -05001406 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
Nick Harper74161f42020-07-24 15:35:27 -07001407 *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1408 return false;
1409 }
David Benjamin31640932017-10-11 13:22:39 -04001410 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001411 }
1412
1413 assert(!ssl->s3->initial_handshake_complete);
David Benjamin0ce090a2018-07-02 20:24:40 -04001414 assert(!hs->config->alpn_client_proto_list.empty());
Adam Langleyf18e4532015-07-10 13:39:53 -07001415
David Benjamin8c880a22016-12-03 02:20:34 -05001416 if (hs->next_proto_neg_seen) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001417 // NPN and ALPN may not be negotiated in the same connection.
David Benjamin76c2efc2015-08-31 14:24:29 -04001418 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1419 OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
David Benjamin31640932017-10-11 13:22:39 -04001420 return false;
David Benjamin76c2efc2015-08-31 14:24:29 -04001421 }
1422
David Benjaminc11ea9422017-08-29 16:33:21 -04001423 // The extension data consists of a ProtocolNameList which must have
1424 // exactly one ProtocolName. Each of these is length-prefixed.
Adam Langleyf18e4532015-07-10 13:39:53 -07001425 CBS protocol_name_list, protocol_name;
1426 if (!CBS_get_u16_length_prefixed(contents, &protocol_name_list) ||
1427 CBS_len(contents) != 0 ||
1428 !CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) ||
David Benjaminc11ea9422017-08-29 16:33:21 -04001429 // Empty protocol names are forbidden.
Adam Langleyf18e4532015-07-10 13:39:53 -07001430 CBS_len(&protocol_name) == 0 ||
1431 CBS_len(&protocol_name_list) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001432 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001433 }
1434
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001435 if (!ssl_is_alpn_protocol_allowed(hs, protocol_name)) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001436 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
1437 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1438 return false;
David Benjamin3e51757d2016-08-11 11:52:23 -04001439 }
1440
David Benjamin8e7bbba2017-10-13 17:18:35 -04001441 if (!ssl->s3->alpn_selected.CopyFrom(protocol_name)) {
Adam Langleyf18e4532015-07-10 13:39:53 -07001442 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001443 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001444 }
1445
David Benjamin31640932017-10-11 13:22:39 -04001446 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001447}
1448
David Benjamin12a3e7e2021-04-13 11:47:36 -04001449bool ssl_is_valid_alpn_list(Span<const uint8_t> in) {
1450 CBS protocol_name_list = in;
1451 if (CBS_len(&protocol_name_list) == 0) {
1452 return false;
1453 }
1454 while (CBS_len(&protocol_name_list) > 0) {
1455 CBS protocol_name;
1456 if (!CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) ||
1457 // Empty protocol names are forbidden.
1458 CBS_len(&protocol_name) == 0) {
1459 return false;
1460 }
1461 }
1462 return true;
1463}
1464
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001465bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs,
David Benjamindd6c2e82017-10-17 15:48:46 -04001466 Span<const uint8_t> protocol) {
David Benjamin0ce090a2018-07-02 20:24:40 -04001467 if (hs->config->alpn_client_proto_list.empty()) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001468 return false;
1469 }
1470
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001471 if (hs->ssl->ctx->allow_unknown_alpn_protos) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001472 return true;
1473 }
1474
1475 // Check that the protocol name is one of the ones we advertised.
David Benjamin0ce090a2018-07-02 20:24:40 -04001476 CBS client_protocol_name_list =
1477 MakeConstSpan(hs->config->alpn_client_proto_list),
1478 client_protocol_name;
David Benjamindd6c2e82017-10-17 15:48:46 -04001479 while (CBS_len(&client_protocol_name_list) > 0) {
1480 if (!CBS_get_u8_length_prefixed(&client_protocol_name_list,
1481 &client_protocol_name)) {
1482 return false;
1483 }
1484
1485 if (client_protocol_name == protocol) {
1486 return true;
1487 }
1488 }
1489
1490 return false;
1491}
1492
David Benjamin31640932017-10-11 13:22:39 -04001493bool ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1494 const SSL_CLIENT_HELLO *client_hello) {
David Benjaminf3c8f8d2016-11-17 17:20:47 +09001495 SSL *const ssl = hs->ssl;
David Benjamin9ef31f02016-10-31 18:01:13 -04001496 CBS contents;
Adam Langleyf18e4532015-07-10 13:39:53 -07001497 if (ssl->ctx->alpn_select_cb == NULL ||
David Benjamin731058e2016-12-03 23:15:13 -05001498 !ssl_client_hello_get_extension(
David Benjamin9ef31f02016-10-31 18:01:13 -04001499 client_hello, &contents,
1500 TLSEXT_TYPE_application_layer_protocol_negotiation)) {
Nick Harper74161f42020-07-24 15:35:27 -07001501 if (ssl->quic_method) {
1502 // ALPN is required when QUIC is used.
David Benjaminc02c19e2021-02-10 17:49:20 -05001503 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
Nick Harper74161f42020-07-24 15:35:27 -07001504 *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1505 return false;
1506 }
David Benjaminc11ea9422017-08-29 16:33:21 -04001507 // Ignore ALPN if not configured or no extension was supplied.
David Benjamin31640932017-10-11 13:22:39 -04001508 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001509 }
1510
David Benjaminc11ea9422017-08-29 16:33:21 -04001511 // ALPN takes precedence over NPN.
David Benjaminfd45ee72017-08-31 14:49:09 -04001512 hs->next_proto_neg_seen = false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001513
1514 CBS protocol_name_list;
David Benjamin9ef31f02016-10-31 18:01:13 -04001515 if (!CBS_get_u16_length_prefixed(&contents, &protocol_name_list) ||
1516 CBS_len(&contents) != 0 ||
David Benjamin12a3e7e2021-04-13 11:47:36 -04001517 !ssl_is_valid_alpn_list(protocol_name_list)) {
David Benjamin9ef31f02016-10-31 18:01:13 -04001518 OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
1519 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001520 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001521 }
1522
David Benjamin9d64d8d2022-08-31 19:27:56 -04001523 // |protocol_name_list| fits in |unsigned| because TLS extensions use 16-bit
1524 // lengths.
Adam Langleyf18e4532015-07-10 13:39:53 -07001525 const uint8_t *selected;
1526 uint8_t selected_len;
David Benjaminc02c19e2021-02-10 17:49:20 -05001527 int ret = ssl->ctx->alpn_select_cb(
1528 ssl, &selected, &selected_len, CBS_data(&protocol_name_list),
David Benjamin9d64d8d2022-08-31 19:27:56 -04001529 static_cast<unsigned>(CBS_len(&protocol_name_list)),
1530 ssl->ctx->alpn_select_cb_arg);
David Benjaminc02c19e2021-02-10 17:49:20 -05001531 // ALPN is required when QUIC is used.
1532 if (ssl->quic_method &&
1533 (ret == SSL_TLSEXT_ERR_NOACK || ret == SSL_TLSEXT_ERR_ALERT_WARNING)) {
1534 ret = SSL_TLSEXT_ERR_ALERT_FATAL;
1535 }
1536 switch (ret) {
1537 case SSL_TLSEXT_ERR_OK:
1538 if (selected_len == 0) {
1539 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
1540 *out_alert = SSL_AD_INTERNAL_ERROR;
1541 return false;
1542 }
1543 if (!ssl->s3->alpn_selected.CopyFrom(
1544 MakeConstSpan(selected, selected_len))) {
1545 *out_alert = SSL_AD_INTERNAL_ERROR;
1546 return false;
1547 }
1548 break;
1549 case SSL_TLSEXT_ERR_NOACK:
1550 case SSL_TLSEXT_ERR_ALERT_WARNING:
1551 break;
1552 case SSL_TLSEXT_ERR_ALERT_FATAL:
1553 *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1554 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
David Benjaminfa544f12018-05-15 15:06:28 -04001555 return false;
David Benjaminc02c19e2021-02-10 17:49:20 -05001556 default:
1557 // Invalid return value.
Adam Langleyf18e4532015-07-10 13:39:53 -07001558 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjaminc02c19e2021-02-10 17:49:20 -05001559 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin31640932017-10-11 13:22:39 -04001560 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001561 }
1562
David Benjamin31640932017-10-11 13:22:39 -04001563 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001564}
1565
David Benjamin31640932017-10-11 13:22:39 -04001566static bool ext_alpn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001567 SSL *const ssl = hs->ssl;
David Benjamin8e7bbba2017-10-13 17:18:35 -04001568 if (ssl->s3->alpn_selected.empty()) {
David Benjamin31640932017-10-11 13:22:39 -04001569 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001570 }
1571
1572 CBB contents, proto_list, proto;
1573 if (!CBB_add_u16(out, TLSEXT_TYPE_application_layer_protocol_negotiation) ||
1574 !CBB_add_u16_length_prefixed(out, &contents) ||
1575 !CBB_add_u16_length_prefixed(&contents, &proto_list) ||
1576 !CBB_add_u8_length_prefixed(&proto_list, &proto) ||
David Benjamin8e7bbba2017-10-13 17:18:35 -04001577 !CBB_add_bytes(&proto, ssl->s3->alpn_selected.data(),
1578 ssl->s3->alpn_selected.size()) ||
Adam Langleyf18e4532015-07-10 13:39:53 -07001579 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001580 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001581 }
1582
David Benjamin31640932017-10-11 13:22:39 -04001583 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001584}
1585
1586
David Benjaminc11ea9422017-08-29 16:33:21 -04001587// Channel ID.
1588//
1589// https://tools.ietf.org/html/draft-balfanz-tls-channelid-01
Adam Langley49c7af12015-07-10 14:33:46 -07001590
David Benjamin83a49932021-05-20 15:57:09 -04001591static bool ext_channel_id_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1592 CBB *out_compressible,
1593 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001594 const SSL *const ssl = hs->ssl;
David Benjaminba423c92021-06-15 16:26:58 -04001595 if (!hs->config->channel_id_private || SSL_is_dtls(ssl) ||
1596 // Don't offer Channel ID in ClientHelloOuter. ClientHelloOuter handshakes
1597 // are not authenticated for the name that can learn the Channel ID.
1598 //
1599 // We could alternatively offer the extension but sign with a random key.
1600 // For other extensions, we try to align |ssl_client_hello_outer| and
1601 // |ssl_client_hello_unencrypted|, to improve the effectiveness of ECH
1602 // GREASE. However, Channel ID is deprecated and unlikely to be used with
1603 // ECH, so do the simplest thing.
1604 type == ssl_client_hello_outer) {
David Benjamin31640932017-10-11 13:22:39 -04001605 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001606 }
1607
David Benjaminba423c92021-06-15 16:26:58 -04001608 if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) ||
1609 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001610 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001611 }
1612
David Benjamin31640932017-10-11 13:22:39 -04001613 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001614}
1615
David Benjamin31640932017-10-11 13:22:39 -04001616static bool ext_channel_id_parse_serverhello(SSL_HANDSHAKE *hs,
1617 uint8_t *out_alert,
1618 CBS *contents) {
Adam Langley49c7af12015-07-10 14:33:46 -07001619 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001620 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001621 }
1622
David Benjamin8acec002021-05-19 13:03:34 -04001623 assert(!SSL_is_dtls(hs->ssl));
David Benjaminb5879112021-05-18 17:10:18 -04001624 assert(hs->config->channel_id_private);
Adam Langley49c7af12015-07-10 14:33:46 -07001625
1626 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001627 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001628 }
1629
David Benjamin8acec002021-05-19 13:03:34 -04001630 hs->channel_id_negotiated = true;
David Benjamin31640932017-10-11 13:22:39 -04001631 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001632}
1633
David Benjamin31640932017-10-11 13:22:39 -04001634static bool ext_channel_id_parse_clienthello(SSL_HANDSHAKE *hs,
1635 uint8_t *out_alert,
1636 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001637 SSL *const ssl = hs->ssl;
David Benjamin46853762018-07-03 14:01:26 -04001638 if (contents == NULL || !hs->config->channel_id_enabled || SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001639 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001640 }
1641
1642 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001643 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001644 }
1645
David Benjamin8acec002021-05-19 13:03:34 -04001646 hs->channel_id_negotiated = true;
David Benjamin31640932017-10-11 13:22:39 -04001647 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001648}
1649
David Benjamin31640932017-10-11 13:22:39 -04001650static bool ext_channel_id_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8acec002021-05-19 13:03:34 -04001651 if (!hs->channel_id_negotiated) {
David Benjamin31640932017-10-11 13:22:39 -04001652 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001653 }
1654
1655 if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) ||
1656 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001657 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001658 }
1659
David Benjamin31640932017-10-11 13:22:39 -04001660 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001661}
1662
Adam Langley391250d2015-07-15 19:06:07 -07001663
David Benjaminc11ea9422017-08-29 16:33:21 -04001664// Secure Real-time Transport Protocol (SRTP) extension.
1665//
1666// https://tools.ietf.org/html/rfc5764
Adam Langley391250d2015-07-15 19:06:07 -07001667
David Benjamin83a49932021-05-20 15:57:09 -04001668static bool ext_srtp_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1669 CBB *out_compressible,
1670 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001671 const SSL *const ssl = hs->ssl;
David Benjaminb778b9c2021-05-20 11:31:05 -04001672 const STACK_OF(SRTP_PROTECTION_PROFILE) *profiles =
1673 SSL_get_srtp_profiles(ssl);
David Benjaminee910bf2017-07-25 22:36:00 -04001674 if (profiles == NULL ||
David Benjaminbc4c91a2021-05-18 16:06:30 -04001675 sk_SRTP_PROTECTION_PROFILE_num(profiles) == 0 ||
1676 !SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001677 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001678 }
1679
1680 CBB contents, profile_ids;
David Benjamin83a49932021-05-20 15:57:09 -04001681 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_srtp) ||
1682 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Adam Langley391250d2015-07-15 19:06:07 -07001683 !CBB_add_u16_length_prefixed(&contents, &profile_ids)) {
David Benjamin31640932017-10-11 13:22:39 -04001684 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001685 }
1686
David Benjaminee910bf2017-07-25 22:36:00 -04001687 for (const SRTP_PROTECTION_PROFILE *profile : profiles) {
1688 if (!CBB_add_u16(&profile_ids, profile->id)) {
David Benjamin31640932017-10-11 13:22:39 -04001689 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001690 }
1691 }
1692
1693 if (!CBB_add_u8(&contents, 0 /* empty use_mki value */) ||
David Benjamin83a49932021-05-20 15:57:09 -04001694 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001695 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001696 }
1697
David Benjamin31640932017-10-11 13:22:39 -04001698 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001699}
1700
David Benjamin31640932017-10-11 13:22:39 -04001701static bool ext_srtp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1702 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001703 SSL *const ssl = hs->ssl;
Adam Langley391250d2015-07-15 19:06:07 -07001704 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001705 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001706 }
1707
David Benjaminc11ea9422017-08-29 16:33:21 -04001708 // The extension consists of a u16-prefixed profile ID list containing a
1709 // single uint16_t profile ID, then followed by a u8-prefixed srtp_mki field.
1710 //
1711 // See https://tools.ietf.org/html/rfc5764#section-4.1.1
David Benjaminbc4c91a2021-05-18 16:06:30 -04001712 assert(SSL_is_dtls(ssl));
Adam Langley391250d2015-07-15 19:06:07 -07001713 CBS profile_ids, srtp_mki;
1714 uint16_t profile_id;
1715 if (!CBS_get_u16_length_prefixed(contents, &profile_ids) ||
1716 !CBS_get_u16(&profile_ids, &profile_id) ||
1717 CBS_len(&profile_ids) != 0 ||
1718 !CBS_get_u8_length_prefixed(contents, &srtp_mki) ||
1719 CBS_len(contents) != 0) {
1720 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
David Benjamin31640932017-10-11 13:22:39 -04001721 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001722 }
1723
1724 if (CBS_len(&srtp_mki) != 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001725 // Must be no MKI, since we never offer one.
Adam Langley391250d2015-07-15 19:06:07 -07001726 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_MKI_VALUE);
1727 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04001728 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001729 }
1730
David Benjaminb778b9c2021-05-20 11:31:05 -04001731 // Check to see if the server gave us something we support and offered.
1732 for (const SRTP_PROTECTION_PROFILE *profile : SSL_get_srtp_profiles(ssl)) {
Adam Langley391250d2015-07-15 19:06:07 -07001733 if (profile->id == profile_id) {
David Benjaminfceca8e2018-04-12 16:37:19 -04001734 ssl->s3->srtp_profile = profile;
David Benjamin31640932017-10-11 13:22:39 -04001735 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001736 }
1737 }
1738
1739 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
1740 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04001741 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001742}
1743
David Benjamin31640932017-10-11 13:22:39 -04001744static bool ext_srtp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1745 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001746 SSL *const ssl = hs->ssl;
David Benjaminbc4c91a2021-05-18 16:06:30 -04001747 // DTLS-SRTP is only defined for DTLS.
1748 if (contents == NULL || !SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001749 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001750 }
1751
1752 CBS profile_ids, srtp_mki;
1753 if (!CBS_get_u16_length_prefixed(contents, &profile_ids) ||
1754 CBS_len(&profile_ids) < 2 ||
1755 !CBS_get_u8_length_prefixed(contents, &srtp_mki) ||
1756 CBS_len(contents) != 0) {
1757 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
David Benjamin31640932017-10-11 13:22:39 -04001758 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001759 }
David Benjaminc11ea9422017-08-29 16:33:21 -04001760 // Discard the MKI value for now.
Adam Langley391250d2015-07-15 19:06:07 -07001761
1762 const STACK_OF(SRTP_PROTECTION_PROFILE) *server_profiles =
1763 SSL_get_srtp_profiles(ssl);
1764
David Benjaminc11ea9422017-08-29 16:33:21 -04001765 // Pick the server's most preferred profile.
David Benjaminee910bf2017-07-25 22:36:00 -04001766 for (const SRTP_PROTECTION_PROFILE *server_profile : server_profiles) {
Adam Langley391250d2015-07-15 19:06:07 -07001767 CBS profile_ids_tmp;
1768 CBS_init(&profile_ids_tmp, CBS_data(&profile_ids), CBS_len(&profile_ids));
1769
1770 while (CBS_len(&profile_ids_tmp) > 0) {
1771 uint16_t profile_id;
1772 if (!CBS_get_u16(&profile_ids_tmp, &profile_id)) {
David Benjamin31640932017-10-11 13:22:39 -04001773 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001774 }
1775
1776 if (server_profile->id == profile_id) {
David Benjaminfceca8e2018-04-12 16:37:19 -04001777 ssl->s3->srtp_profile = server_profile;
David Benjamin31640932017-10-11 13:22:39 -04001778 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001779 }
1780 }
1781 }
1782
David Benjamin31640932017-10-11 13:22:39 -04001783 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001784}
1785
David Benjamin31640932017-10-11 13:22:39 -04001786static bool ext_srtp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001787 SSL *const ssl = hs->ssl;
David Benjaminfceca8e2018-04-12 16:37:19 -04001788 if (ssl->s3->srtp_profile == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001789 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001790 }
1791
David Benjaminbc4c91a2021-05-18 16:06:30 -04001792 assert(SSL_is_dtls(ssl));
Adam Langley391250d2015-07-15 19:06:07 -07001793 CBB contents, profile_ids;
1794 if (!CBB_add_u16(out, TLSEXT_TYPE_srtp) ||
1795 !CBB_add_u16_length_prefixed(out, &contents) ||
1796 !CBB_add_u16_length_prefixed(&contents, &profile_ids) ||
David Benjaminfceca8e2018-04-12 16:37:19 -04001797 !CBB_add_u16(&profile_ids, ssl->s3->srtp_profile->id) ||
Adam Langley391250d2015-07-15 19:06:07 -07001798 !CBB_add_u8(&contents, 0 /* empty MKI */) ||
1799 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001800 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001801 }
1802
David Benjamin31640932017-10-11 13:22:39 -04001803 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001804}
1805
Adam Langleybdd5d662015-07-20 16:19:08 -07001806
David Benjaminc11ea9422017-08-29 16:33:21 -04001807// EC point formats.
1808//
1809// https://tools.ietf.org/html/rfc4492#section-5.1.2
Adam Langleybdd5d662015-07-20 16:19:08 -07001810
David Benjamin14e51ad2021-05-19 15:24:34 -04001811static bool ext_ec_point_add_extension(const SSL_HANDSHAKE *hs, CBB *out) {
David Benjaminfc059942015-07-30 23:01:59 -04001812 CBB contents, formats;
Adam Langleybdd5d662015-07-20 16:19:08 -07001813 if (!CBB_add_u16(out, TLSEXT_TYPE_ec_point_formats) ||
1814 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjaminfc059942015-07-30 23:01:59 -04001815 !CBB_add_u8_length_prefixed(&contents, &formats) ||
1816 !CBB_add_u8(&formats, TLSEXT_ECPOINTFORMAT_uncompressed) ||
Adam Langleybdd5d662015-07-20 16:19:08 -07001817 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001818 return false;
Adam Langleybdd5d662015-07-20 16:19:08 -07001819 }
1820
David Benjamin31640932017-10-11 13:22:39 -04001821 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001822}
1823
David Benjamin83a49932021-05-20 15:57:09 -04001824static bool ext_ec_point_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1825 CBB *out_compressible,
1826 ssl_client_hello_type_t type) {
Adam Langleyffe384c2019-05-01 11:13:12 -07001827 // The point format extension is unnecessary in TLS 1.3.
David Benjamin83a49932021-05-20 15:57:09 -04001828 if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -04001829 return true;
David Benjamin70aba262016-11-01 12:08:15 -04001830 }
1831
David Benjamin8c880a22016-12-03 02:20:34 -05001832 return ext_ec_point_add_extension(hs, out);
Adam Langleybdd5d662015-07-20 16:19:08 -07001833}
1834
David Benjamin31640932017-10-11 13:22:39 -04001835static bool ext_ec_point_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1836 CBS *contents) {
Adam Langleybdd5d662015-07-20 16:19:08 -07001837 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001838 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001839 }
1840
David Benjamind1e3ce12017-10-06 18:31:15 -04001841 if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001842 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04001843 }
1844
Adam Langleybdd5d662015-07-20 16:19:08 -07001845 CBS ec_point_format_list;
1846 if (!CBS_get_u8_length_prefixed(contents, &ec_point_format_list) ||
1847 CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001848 return false;
Adam Langleybdd5d662015-07-20 16:19:08 -07001849 }
1850
David Benjaminc11ea9422017-08-29 16:33:21 -04001851 // Per RFC 4492, section 5.1.2, implementations MUST support the uncompressed
1852 // point format.
David Benjamin17cf2cb2016-12-13 01:07:13 -05001853 if (OPENSSL_memchr(CBS_data(&ec_point_format_list),
1854 TLSEXT_ECPOINTFORMAT_uncompressed,
1855 CBS_len(&ec_point_format_list)) == NULL) {
David Benjaminfc059942015-07-30 23:01:59 -04001856 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04001857 return false;
Adam Langleybdd5d662015-07-20 16:19:08 -07001858 }
1859
David Benjamin31640932017-10-11 13:22:39 -04001860 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001861}
1862
David Benjamin31640932017-10-11 13:22:39 -04001863static bool ext_ec_point_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
Adam Langleybdd5d662015-07-20 16:19:08 -07001864 CBS *contents) {
David Benjamind1e3ce12017-10-06 18:31:15 -04001865 if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001866 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001867 }
1868
David Benjamin8c880a22016-12-03 02:20:34 -05001869 return ext_ec_point_parse_serverhello(hs, out_alert, contents);
Adam Langleybdd5d662015-07-20 16:19:08 -07001870}
1871
David Benjamin31640932017-10-11 13:22:39 -04001872static bool ext_ec_point_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001873 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04001874 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001875 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001876 }
1877
David Benjamin45738dd2017-02-09 20:01:26 -05001878 const uint32_t alg_k = hs->new_cipher->algorithm_mkey;
1879 const uint32_t alg_a = hs->new_cipher->algorithm_auth;
David Benjamin31640932017-10-11 13:22:39 -04001880 const bool using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA);
Adam Langleybdd5d662015-07-20 16:19:08 -07001881
1882 if (!using_ecc) {
David Benjamin31640932017-10-11 13:22:39 -04001883 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001884 }
1885
David Benjamin8c880a22016-12-03 02:20:34 -05001886 return ext_ec_point_add_extension(hs, out);
Adam Langleybdd5d662015-07-20 16:19:08 -07001887}
1888
Steven Valdeza833c352016-11-01 13:39:36 -04001889
David Benjaminc11ea9422017-08-29 16:33:21 -04001890// Pre Shared Key
1891//
David Benjamina130ce02018-08-14 22:26:39 -05001892// https://tools.ietf.org/html/rfc8446#section-4.2.11
Steven Valdez4aa154e2016-07-29 14:32:55 -04001893
David Benjamin83a49932021-05-20 15:57:09 -04001894static bool should_offer_psk(const SSL_HANDSHAKE *hs,
1895 ssl_client_hello_type_t type) {
David Benjamin350fe3b2021-06-02 17:58:53 -04001896 const SSL *const ssl = hs->ssl;
David Benjamin50596f82018-07-02 19:47:27 -04001897 if (hs->max_version < TLS1_3_VERSION || ssl->session == nullptr ||
David Benjamin83a49932021-05-20 15:57:09 -04001898 ssl_session_protocol_version(ssl->session.get()) < TLS1_3_VERSION ||
David Benjamin18b68362021-06-18 23:13:46 -04001899 // TODO(https://crbug.com/boringssl/275): Should we synthesize a
1900 // placeholder PSK, at least when we offer early data? Otherwise
1901 // ClientHelloOuter will contain an early_data extension without a
1902 // pre_shared_key extension and potentially break the recovery flow.
David Benjamin83a49932021-05-20 15:57:09 -04001903 type == ssl_client_hello_outer) {
David Benjamin350fe3b2021-06-02 17:58:53 -04001904 return false;
1905 }
1906
1907 // Per RFC 8446 section 4.1.4, skip offering the session if the selected
1908 // cipher in HelloRetryRequest does not match. This avoids performing the
1909 // transcript hash transformation for multiple hashes.
1910 if (ssl->s3->used_hello_retry_request &&
1911 ssl->session->cipher->algorithm_prf != hs->new_cipher->algorithm_prf) {
1912 return false;
1913 }
1914
1915 return true;
1916}
1917
David Benjamin83a49932021-05-20 15:57:09 -04001918static size_t ext_pre_shared_key_clienthello_length(
1919 const SSL_HANDSHAKE *hs, ssl_client_hello_type_t type) {
David Benjamin350fe3b2021-06-02 17:58:53 -04001920 const SSL *const ssl = hs->ssl;
David Benjamin83a49932021-05-20 15:57:09 -04001921 if (!should_offer_psk(hs, type)) {
Steven Valdeza833c352016-11-01 13:39:36 -04001922 return 0;
1923 }
1924
David Benjamin50596f82018-07-02 19:47:27 -04001925 size_t binder_len = EVP_MD_size(ssl_session_get_digest(ssl->session.get()));
David Benjaminbfdd1a92018-06-29 16:26:38 -04001926 return 15 + ssl->session->ticket.size() + binder_len;
Steven Valdeza833c352016-11-01 13:39:36 -04001927}
1928
David Benjamin5acf9f42021-05-24 14:23:38 -04001929static bool ext_pre_shared_key_add_clienthello(const SSL_HANDSHAKE *hs,
David Benjamin83a49932021-05-20 15:57:09 -04001930 CBB *out, bool *out_needs_binder,
1931 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001932 const SSL *const ssl = hs->ssl;
David Benjamin5acf9f42021-05-24 14:23:38 -04001933 *out_needs_binder = false;
David Benjamin83a49932021-05-20 15:57:09 -04001934 if (!should_offer_psk(hs, type)) {
Steven Valdezcd8470f2017-10-11 12:29:36 -04001935 return true;
1936 }
1937
David Benjaminad8f5e12017-02-20 17:00:20 -05001938 struct OPENSSL_timeval now;
Steven Valdeza833c352016-11-01 13:39:36 -04001939 ssl_get_current_time(ssl, &now);
1940 uint32_t ticket_age = 1000 * (now.tv_sec - ssl->session->time);
1941 uint32_t obfuscated_ticket_age = ticket_age + ssl->session->ticket_age_add;
1942
David Benjaminc11ea9422017-08-29 16:33:21 -04001943 // Fill in a placeholder zero binder of the appropriate length. It will be
1944 // computed and filled in later after length prefixes are computed.
David Benjamin50596f82018-07-02 19:47:27 -04001945 size_t binder_len = EVP_MD_size(ssl_session_get_digest(ssl->session.get()));
Steven Valdeza833c352016-11-01 13:39:36 -04001946
1947 CBB contents, identity, ticket, binders, binder;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001948 if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) ||
1949 !CBB_add_u16_length_prefixed(out, &contents) ||
Steven Valdez5b986082016-09-01 12:29:49 -04001950 !CBB_add_u16_length_prefixed(&contents, &identity) ||
Steven Valdez5b986082016-09-01 12:29:49 -04001951 !CBB_add_u16_length_prefixed(&identity, &ticket) ||
David Benjaminbfdd1a92018-06-29 16:26:38 -04001952 !CBB_add_bytes(&ticket, ssl->session->ticket.data(),
1953 ssl->session->ticket.size()) ||
Steven Valdeza833c352016-11-01 13:39:36 -04001954 !CBB_add_u32(&identity, obfuscated_ticket_age) ||
1955 !CBB_add_u16_length_prefixed(&contents, &binders) ||
1956 !CBB_add_u8_length_prefixed(&binders, &binder) ||
David Benjamin95450622021-07-16 18:24:02 -04001957 !CBB_add_zeros(&binder, binder_len)) {
David Benjamin31640932017-10-11 13:22:39 -04001958 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001959 }
1960
David Benjamin5acf9f42021-05-24 14:23:38 -04001961 *out_needs_binder = true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001962 return CBB_flush(out);
1963}
1964
David Benjamin31640932017-10-11 13:22:39 -04001965bool ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE *hs,
1966 uint8_t *out_alert,
1967 CBS *contents) {
Steven Valdez4aa154e2016-07-29 14:32:55 -04001968 uint16_t psk_id;
1969 if (!CBS_get_u16(contents, &psk_id) ||
1970 CBS_len(contents) != 0) {
David Benjamin7f78df42016-10-05 22:33:19 -04001971 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
Steven Valdez4aa154e2016-07-29 14:32:55 -04001972 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001973 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001974 }
1975
David Benjaminc11ea9422017-08-29 16:33:21 -04001976 // We only advertise one PSK identity, so the only legal index is zero.
Steven Valdez4aa154e2016-07-29 14:32:55 -04001977 if (psk_id != 0) {
David Benjamin7f78df42016-10-05 22:33:19 -04001978 OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
Steven Valdez4aa154e2016-07-29 14:32:55 -04001979 *out_alert = SSL_AD_UNKNOWN_PSK_IDENTITY;
David Benjamin31640932017-10-11 13:22:39 -04001980 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001981 }
1982
David Benjamin31640932017-10-11 13:22:39 -04001983 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001984}
1985
David Benjamin31640932017-10-11 13:22:39 -04001986bool ssl_ext_pre_shared_key_parse_clienthello(
David Benjamin707af292017-03-10 17:47:18 -05001987 SSL_HANDSHAKE *hs, CBS *out_ticket, CBS *out_binders,
David Benjamin9806ae02019-08-16 15:32:03 -04001988 uint32_t *out_obfuscated_ticket_age, uint8_t *out_alert,
1989 const SSL_CLIENT_HELLO *client_hello, CBS *contents) {
1990 // Verify that the pre_shared_key extension is the last extension in
1991 // ClientHello.
1992 if (CBS_data(contents) + CBS_len(contents) !=
1993 client_hello->extensions + client_hello->extensions_len) {
1994 OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
1995 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1996 return false;
1997 }
1998
David Benjaminc11ea9422017-08-29 16:33:21 -04001999 // We only process the first PSK identity since we don't support pure PSK.
David Benjamin707af292017-03-10 17:47:18 -05002000 CBS identities, binders;
David Benjaminaedf3032016-12-01 16:47:56 -05002001 if (!CBS_get_u16_length_prefixed(contents, &identities) ||
David Benjamin707af292017-03-10 17:47:18 -05002002 !CBS_get_u16_length_prefixed(&identities, out_ticket) ||
David Benjamin35ac5b72017-03-03 15:05:56 -05002003 !CBS_get_u32(&identities, out_obfuscated_ticket_age) ||
Steven Valdeza833c352016-11-01 13:39:36 -04002004 !CBS_get_u16_length_prefixed(contents, &binders) ||
David Benjaminaedf3032016-12-01 16:47:56 -05002005 CBS_len(&binders) == 0 ||
Steven Valdezaf3b8a92016-11-01 12:49:22 -04002006 CBS_len(contents) != 0) {
Steven Valdeza833c352016-11-01 13:39:36 -04002007 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
Steven Valdez4aa154e2016-07-29 14:32:55 -04002008 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002009 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002010 }
2011
Steven Valdeza833c352016-11-01 13:39:36 -04002012 *out_binders = binders;
2013
David Benjaminc11ea9422017-08-29 16:33:21 -04002014 // Check the syntax of the remaining identities, but do not process them.
David Benjaminaedf3032016-12-01 16:47:56 -05002015 size_t num_identities = 1;
2016 while (CBS_len(&identities) != 0) {
2017 CBS unused_ticket;
2018 uint32_t unused_obfuscated_ticket_age;
2019 if (!CBS_get_u16_length_prefixed(&identities, &unused_ticket) ||
2020 !CBS_get_u32(&identities, &unused_obfuscated_ticket_age)) {
2021 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2022 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002023 return false;
David Benjaminaedf3032016-12-01 16:47:56 -05002024 }
2025
2026 num_identities++;
2027 }
2028
David Benjaminc11ea9422017-08-29 16:33:21 -04002029 // Check the syntax of the binders. The value will be checked later if
2030 // resuming.
David Benjaminaedf3032016-12-01 16:47:56 -05002031 size_t num_binders = 0;
2032 while (CBS_len(&binders) != 0) {
2033 CBS binder;
2034 if (!CBS_get_u8_length_prefixed(&binders, &binder)) {
2035 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2036 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002037 return false;
David Benjaminaedf3032016-12-01 16:47:56 -05002038 }
2039
2040 num_binders++;
2041 }
2042
2043 if (num_identities != num_binders) {
2044 OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_BINDER_COUNT_MISMATCH);
2045 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04002046 return false;
Steven Valdez5b986082016-09-01 12:29:49 -04002047 }
2048
David Benjamin31640932017-10-11 13:22:39 -04002049 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002050}
2051
David Benjamin31640932017-10-11 13:22:39 -04002052bool ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8baf9632016-11-17 17:11:16 +09002053 if (!hs->ssl->s3->session_reused) {
David Benjamin31640932017-10-11 13:22:39 -04002054 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002055 }
2056
2057 CBB contents;
2058 if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) ||
2059 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjaminc11ea9422017-08-29 16:33:21 -04002060 // We only consider the first identity for resumption
Steven Valdez4aa154e2016-07-29 14:32:55 -04002061 !CBB_add_u16(&contents, 0) ||
2062 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002063 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002064 }
2065
David Benjamin31640932017-10-11 13:22:39 -04002066 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002067}
2068
2069
David Benjaminc11ea9422017-08-29 16:33:21 -04002070// Pre-Shared Key Exchange Modes
2071//
David Benjamina130ce02018-08-14 22:26:39 -05002072// https://tools.ietf.org/html/rfc8446#section-4.2.9
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002073
David Benjamin83a49932021-05-20 15:57:09 -04002074static bool ext_psk_key_exchange_modes_add_clienthello(
2075 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2076 ssl_client_hello_type_t type) {
David Benjamin68161cb2017-06-20 14:49:43 -04002077 if (hs->max_version < TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002078 return true;
Steven Valdeza833c352016-11-01 13:39:36 -04002079 }
2080
2081 CBB contents, ke_modes;
David Benjamin83a49932021-05-20 15:57:09 -04002082 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_psk_key_exchange_modes) ||
2083 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Steven Valdeza833c352016-11-01 13:39:36 -04002084 !CBB_add_u8_length_prefixed(&contents, &ke_modes) ||
2085 !CBB_add_u8(&ke_modes, SSL_PSK_DHE_KE)) {
David Benjamin31640932017-10-11 13:22:39 -04002086 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04002087 }
2088
David Benjamin83a49932021-05-20 15:57:09 -04002089 return CBB_flush(out_compressible);
Steven Valdeza833c352016-11-01 13:39:36 -04002090}
2091
David Benjamin31640932017-10-11 13:22:39 -04002092static bool ext_psk_key_exchange_modes_parse_clienthello(SSL_HANDSHAKE *hs,
2093 uint8_t *out_alert,
2094 CBS *contents) {
David Benjamin4eb95cc2016-11-16 17:08:23 +09002095 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04002096 return true;
David Benjamin4eb95cc2016-11-16 17:08:23 +09002097 }
2098
Steven Valdeza833c352016-11-01 13:39:36 -04002099 CBS ke_modes;
2100 if (!CBS_get_u8_length_prefixed(contents, &ke_modes) ||
2101 CBS_len(&ke_modes) == 0 ||
2102 CBS_len(contents) != 0) {
2103 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002104 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04002105 }
2106
David Benjaminc11ea9422017-08-29 16:33:21 -04002107 // We only support tickets with PSK_DHE_KE.
David Benjamin17cf2cb2016-12-13 01:07:13 -05002108 hs->accept_psk_mode = OPENSSL_memchr(CBS_data(&ke_modes), SSL_PSK_DHE_KE,
2109 CBS_len(&ke_modes)) != NULL;
Steven Valdeza833c352016-11-01 13:39:36 -04002110
David Benjamin31640932017-10-11 13:22:39 -04002111 return true;
Steven Valdeza833c352016-11-01 13:39:36 -04002112}
2113
2114
David Benjaminc11ea9422017-08-29 16:33:21 -04002115// Early Data Indication
2116//
David Benjamina130ce02018-08-14 22:26:39 -05002117// https://tools.ietf.org/html/rfc8446#section-4.2.10
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002118
David Benjamin83a49932021-05-20 15:57:09 -04002119static bool ext_early_data_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2120 CBB *out_compressible,
2121 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002122 const SSL *const ssl = hs->ssl;
David Benjamin64770122019-05-04 11:00:04 -05002123 // The second ClientHello never offers early data, and we must have already
2124 // filled in |early_data_reason| by this point.
Kris Kwiatkowskib11902a2019-08-24 11:01:04 +01002125 if (ssl->s3->used_hello_retry_request) {
David Benjamin64770122019-05-04 11:00:04 -05002126 assert(ssl->s3->early_data_reason != ssl_early_data_unknown);
David Benjamin31640932017-10-11 13:22:39 -04002127 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002128 }
2129
David Benjamin4e93cd42021-05-18 13:38:25 -04002130 if (!hs->early_data_offered) {
David Benjamin64770122019-05-04 11:00:04 -05002131 return true;
2132 }
2133
David Benjamin83a49932021-05-20 15:57:09 -04002134 // If offering ECH, the extension only applies to ClientHelloInner, but we
2135 // send the extension in both ClientHellos. This ensures that, if the server
2136 // handshakes with ClientHelloOuter, it can skip past early data. See
David Benjamin0fa30302021-09-03 17:23:28 -04002137 // draft-ietf-tls-esni-13, section 6.1.
David Benjamin83a49932021-05-20 15:57:09 -04002138 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_early_data) ||
2139 !CBB_add_u16(out_compressible, 0) ||
2140 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04002141 return false;
Steven Valdez2d850622017-01-11 11:34:52 -05002142 }
2143
David Benjamin31640932017-10-11 13:22:39 -04002144 return true;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002145}
2146
David Benjamin31640932017-10-11 13:22:39 -04002147static bool ext_early_data_parse_serverhello(SSL_HANDSHAKE *hs,
David Benjamin64770122019-05-04 11:00:04 -05002148 uint8_t *out_alert,
2149 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05002150 SSL *const ssl = hs->ssl;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002151 if (contents == NULL) {
Kris Kwiatkowskib11902a2019-08-24 11:01:04 +01002152 if (hs->early_data_offered && !ssl->s3->used_hello_retry_request) {
David Benjamin64770122019-05-04 11:00:04 -05002153 ssl->s3->early_data_reason = ssl->s3->session_reused
2154 ? ssl_early_data_peer_declined
2155 : ssl_early_data_session_not_resumed;
2156 } else {
2157 // We already filled in |early_data_reason| when declining to offer 0-RTT
2158 // or handling the implicit HelloRetryRequest reject.
2159 assert(ssl->s3->early_data_reason != ssl_early_data_unknown);
2160 }
David Benjamin31640932017-10-11 13:22:39 -04002161 return true;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002162 }
2163
David Benjamin64770122019-05-04 11:00:04 -05002164 // If we received an HRR, the second ClientHello never offers early data, so
2165 // the extensions logic will automatically reject early data extensions as
2166 // unsolicited. This covered by the ServerAcceptsEarlyDataOnHRR test.
Kris Kwiatkowskib11902a2019-08-24 11:01:04 +01002167 assert(!ssl->s3->used_hello_retry_request);
David Benjamin64770122019-05-04 11:00:04 -05002168
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002169 if (CBS_len(contents) != 0) {
2170 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002171 return false;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002172 }
2173
Steven Valdez2d850622017-01-11 11:34:52 -05002174 if (!ssl->s3->session_reused) {
2175 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2176 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
David Benjamin31640932017-10-11 13:22:39 -04002177 return false;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002178 }
Steven Valdez2d850622017-01-11 11:34:52 -05002179
David Benjamin64770122019-05-04 11:00:04 -05002180 ssl->s3->early_data_reason = ssl_early_data_accepted;
David Benjamin02e62562017-12-18 18:04:01 -05002181 ssl->s3->early_data_accepted = true;
David Benjamin31640932017-10-11 13:22:39 -04002182 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002183}
2184
David Benjamin31640932017-10-11 13:22:39 -04002185static bool ext_early_data_parse_clienthello(SSL_HANDSHAKE *hs,
2186 uint8_t *out_alert, CBS *contents) {
Steven Valdez2d850622017-01-11 11:34:52 -05002187 SSL *const ssl = hs->ssl;
2188 if (contents == NULL ||
David Benjamind1e3ce12017-10-06 18:31:15 -04002189 ssl_protocol_version(ssl) < TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002190 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002191 }
2192
2193 if (CBS_len(contents) != 0) {
2194 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002195 return false;
Steven Valdez2d850622017-01-11 11:34:52 -05002196 }
2197
David Benjaminfd45ee72017-08-31 14:49:09 -04002198 hs->early_data_offered = true;
David Benjamin31640932017-10-11 13:22:39 -04002199 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002200}
2201
David Benjamin31640932017-10-11 13:22:39 -04002202static bool ext_early_data_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin02e62562017-12-18 18:04:01 -05002203 if (!hs->ssl->s3->early_data_accepted) {
David Benjamin31640932017-10-11 13:22:39 -04002204 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002205 }
2206
2207 if (!CBB_add_u16(out, TLSEXT_TYPE_early_data) ||
2208 !CBB_add_u16(out, 0) ||
2209 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002210 return false;
Steven Valdez2d850622017-01-11 11:34:52 -05002211 }
2212
David Benjamin31640932017-10-11 13:22:39 -04002213 return true;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002214}
2215
2216
David Benjaminc11ea9422017-08-29 16:33:21 -04002217// Key Share
2218//
David Benjamina130ce02018-08-14 22:26:39 -05002219// https://tools.ietf.org/html/rfc8446#section-4.2.8
Steven Valdez143e8b32016-07-11 13:19:03 -04002220
David Benjamin97ede402021-05-18 14:17:52 -04002221bool ssl_setup_key_shares(SSL_HANDSHAKE *hs, uint16_t override_group_id) {
David Benjamin8c880a22016-12-03 02:20:34 -05002222 SSL *const ssl = hs->ssl;
David Benjamin97ede402021-05-18 14:17:52 -04002223 hs->key_shares[0].reset();
2224 hs->key_shares[1].reset();
2225 hs->key_share_bytes.Reset();
2226
David Benjamin68161cb2017-06-20 14:49:43 -04002227 if (hs->max_version < TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002228 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002229 }
2230
David Benjamin97ede402021-05-18 14:17:52 -04002231 bssl::ScopedCBB cbb;
2232 if (!CBB_init(cbb.get(), 64)) {
David Benjamin31640932017-10-11 13:22:39 -04002233 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002234 }
2235
David Benjamin97ede402021-05-18 14:17:52 -04002236 if (override_group_id == 0 && ssl->ctx->grease_enabled) {
David Benjamin3675eb32021-05-18 14:01:07 -04002237 // Add a fake group. See RFC 8701.
David Benjamin97ede402021-05-18 14:17:52 -04002238 if (!CBB_add_u16(cbb.get(), ssl_get_grease_value(hs, ssl_grease_group)) ||
2239 !CBB_add_u16(cbb.get(), 1 /* length */) ||
2240 !CBB_add_u8(cbb.get(), 0 /* one byte key share */)) {
David Benjamin31640932017-10-11 13:22:39 -04002241 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04002242 }
David Benjamin97ede402021-05-18 14:17:52 -04002243 }
David Benjamin65ac9972016-09-02 21:35:25 -04002244
David Benjamin97ede402021-05-18 14:17:52 -04002245 uint16_t group_id = override_group_id;
2246 uint16_t second_group_id = 0;
2247 if (override_group_id == 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -04002248 // Predict the most preferred group.
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07002249 Span<const uint16_t> groups = tls1_get_grouplist(hs);
David Benjaminb9493552017-09-27 19:02:51 -04002250 if (groups.empty()) {
David Benjaminc8b6b4f2016-09-08 23:47:48 -04002251 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_GROUPS_SPECIFIED);
David Benjamin31640932017-10-11 13:22:39 -04002252 return false;
Steven Valdez5440fe02016-07-18 12:40:30 -04002253 }
David Benjaminc8b6b4f2016-09-08 23:47:48 -04002254
2255 group_id = groups[0];
Adam Langley7b935932018-11-12 13:53:42 -08002256
Adam Langley1e97ce32023-01-23 21:11:44 +00002257 // We'll try to include one post-quantum and one classical initial key
2258 // share.
2259 for (size_t i = 1; i < groups.size() && second_group_id == 0; i++) {
2260 if (is_post_quantum_group(group_id) != is_post_quantum_group(groups[i])) {
2261 second_group_id = groups[i];
2262 assert(second_group_id != group_id);
2263 }
Adam Langley7b935932018-11-12 13:53:42 -08002264 }
Steven Valdez5440fe02016-07-18 12:40:30 -04002265 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002266
David Benjaminc8b6b4f2016-09-08 23:47:48 -04002267 CBB key_exchange;
Adam Langley7b935932018-11-12 13:53:42 -08002268 hs->key_shares[0] = SSLKeyShare::Create(group_id);
David Benjamin97ede402021-05-18 14:17:52 -04002269 if (!hs->key_shares[0] || //
2270 !CBB_add_u16(cbb.get(), group_id) ||
2271 !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002272 !hs->key_shares[0]->Generate(&key_exchange)) {
David Benjamin31640932017-10-11 13:22:39 -04002273 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002274 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002275
Adam Langley7b935932018-11-12 13:53:42 -08002276 if (second_group_id != 0) {
2277 hs->key_shares[1] = SSLKeyShare::Create(second_group_id);
David Benjamin97ede402021-05-18 14:17:52 -04002278 if (!hs->key_shares[1] || //
2279 !CBB_add_u16(cbb.get(), second_group_id) ||
2280 !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002281 !hs->key_shares[1]->Generate(&key_exchange)) {
Adam Langley7b935932018-11-12 13:53:42 -08002282 return false;
2283 }
2284 }
2285
David Benjamin97ede402021-05-18 14:17:52 -04002286 return CBBFinishArray(cbb.get(), &hs->key_share_bytes);
2287}
2288
David Benjamin83a49932021-05-20 15:57:09 -04002289static bool ext_key_share_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2290 CBB *out_compressible,
2291 ssl_client_hello_type_t type) {
David Benjamin97ede402021-05-18 14:17:52 -04002292 if (hs->max_version < TLS1_3_VERSION) {
2293 return true;
2294 }
2295
2296 assert(!hs->key_share_bytes.empty());
2297 CBB contents, kse_bytes;
David Benjamin83a49932021-05-20 15:57:09 -04002298 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_key_share) ||
2299 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
David Benjamin97ede402021-05-18 14:17:52 -04002300 !CBB_add_u16_length_prefixed(&contents, &kse_bytes) ||
2301 !CBB_add_bytes(&kse_bytes, hs->key_share_bytes.data(),
2302 hs->key_share_bytes.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -04002303 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04002304 return false;
Steven Valdez5440fe02016-07-18 12:40:30 -04002305 }
2306
David Benjamin97ede402021-05-18 14:17:52 -04002307 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002308}
2309
David Benjamin31640932017-10-11 13:22:39 -04002310bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
2311 Array<uint8_t> *out_secret,
2312 uint8_t *out_alert, CBS *contents) {
David Benjamin08b1f382023-02-28 17:22:23 -05002313 CBS ciphertext;
David Benjamin5c4e8572016-08-19 17:44:53 -04002314 uint16_t group_id;
2315 if (!CBS_get_u16(contents, &group_id) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002316 !CBS_get_u16_length_prefixed(contents, &ciphertext) ||
David Benjamina70de142016-08-02 16:52:57 -04002317 CBS_len(contents) != 0) {
David Benjaminac4d5342017-11-17 01:42:04 +08002318 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
Steven Valdez143e8b32016-07-11 13:19:03 -04002319 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002320 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002321 }
2322
Adam Langley7b935932018-11-12 13:53:42 -08002323 SSLKeyShare *key_share = hs->key_shares[0].get();
2324 if (key_share->GroupID() != group_id) {
2325 if (!hs->key_shares[1] || hs->key_shares[1]->GroupID() != group_id) {
2326 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
2327 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
2328 return false;
2329 }
2330 key_share = hs->key_shares[1].get();
Steven Valdez143e8b32016-07-11 13:19:03 -04002331 }
2332
David Benjamin08b1f382023-02-28 17:22:23 -05002333 if (!key_share->Decap(out_secret, out_alert, ciphertext)) {
Steven Valdez143e8b32016-07-11 13:19:03 -04002334 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002335 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002336 }
2337
David Benjamin45738dd2017-02-09 20:01:26 -05002338 hs->new_session->group_id = group_id;
Adam Langley7b935932018-11-12 13:53:42 -08002339 hs->key_shares[0].reset();
2340 hs->key_shares[1].reset();
David Benjamin31640932017-10-11 13:22:39 -04002341 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002342}
2343
David Benjamin31640932017-10-11 13:22:39 -04002344bool ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found,
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002345 Span<const uint8_t> *out_peer_key,
2346 uint8_t *out_alert,
2347 const SSL_CLIENT_HELLO *client_hello) {
2348 // We only support connections that include an ECDHE key exchange.
2349 CBS contents;
2350 if (!ssl_client_hello_get_extension(client_hello, &contents,
2351 TLSEXT_TYPE_key_share)) {
2352 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
2353 *out_alert = SSL_AD_MISSING_EXTENSION;
David Benjamin31640932017-10-11 13:22:39 -04002354 return false;
Steven Valdez803c77a2016-09-06 14:13:43 -04002355 }
2356
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002357 CBS key_shares;
2358 if (!CBS_get_u16_length_prefixed(&contents, &key_shares) ||
2359 CBS_len(&contents) != 0) {
David Benjamin7e1f9842016-09-20 19:24:40 -04002360 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
David Benjamin31640932017-10-11 13:22:39 -04002361 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002362 }
2363
David Benjaminc11ea9422017-08-29 16:33:21 -04002364 // Find the corresponding key share.
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002365 const uint16_t group_id = hs->new_session->group_id;
David Benjamin7e1f9842016-09-20 19:24:40 -04002366 CBS peer_key;
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002367 CBS_init(&peer_key, nullptr, 0);
Steven Valdez143e8b32016-07-11 13:19:03 -04002368 while (CBS_len(&key_shares) > 0) {
2369 uint16_t id;
David Benjamin7e1f9842016-09-20 19:24:40 -04002370 CBS peer_key_tmp;
Steven Valdez143e8b32016-07-11 13:19:03 -04002371 if (!CBS_get_u16(&key_shares, &id) ||
Steven Valdez619c8ce2017-10-16 13:12:33 -04002372 !CBS_get_u16_length_prefixed(&key_shares, &peer_key_tmp) ||
2373 CBS_len(&peer_key_tmp) == 0) {
David Benjamin7e1f9842016-09-20 19:24:40 -04002374 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
David Benjamin31640932017-10-11 13:22:39 -04002375 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002376 }
2377
David Benjamin7e1f9842016-09-20 19:24:40 -04002378 if (id == group_id) {
Steven Valdez619c8ce2017-10-16 13:12:33 -04002379 if (CBS_len(&peer_key) != 0) {
David Benjamin7e1f9842016-09-20 19:24:40 -04002380 OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_KEY_SHARE);
2381 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04002382 return false;
David Benjamin7e1f9842016-09-20 19:24:40 -04002383 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002384
David Benjamin7e1f9842016-09-20 19:24:40 -04002385 peer_key = peer_key_tmp;
David Benjaminc11ea9422017-08-29 16:33:21 -04002386 // Continue parsing the structure to keep peers honest.
Steven Valdez143e8b32016-07-11 13:19:03 -04002387 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002388 }
2389
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002390 if (out_peer_key != nullptr) {
2391 *out_peer_key = peer_key;
David Benjamin7e1f9842016-09-20 19:24:40 -04002392 }
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002393 *out_found = CBS_len(&peer_key) != 0;
David Benjamin31640932017-10-11 13:22:39 -04002394 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002395}
2396
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002397bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin08b1f382023-02-28 17:22:23 -05002398 CBB entry, ciphertext;
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002399 if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002400 !CBB_add_u16_length_prefixed(out, &entry) ||
2401 !CBB_add_u16(&entry, hs->new_session->group_id) ||
2402 !CBB_add_u16_length_prefixed(&entry, &ciphertext) ||
2403 !CBB_add_bytes(&ciphertext, hs->key_share_ciphertext.data(),
2404 hs->key_share_ciphertext.size()) ||
Steven Valdez143e8b32016-07-11 13:19:03 -04002405 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002406 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002407 }
David Benjamin31640932017-10-11 13:22:39 -04002408 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002409}
2410
2411
David Benjaminc11ea9422017-08-29 16:33:21 -04002412// Supported Versions
2413//
David Benjamina130ce02018-08-14 22:26:39 -05002414// https://tools.ietf.org/html/rfc8446#section-4.2.1
Steven Valdezfdd10992016-09-15 16:27:05 -04002415
David Benjamin83a49932021-05-20 15:57:09 -04002416static bool ext_supported_versions_add_clienthello(
2417 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2418 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002419 const SSL *const ssl = hs->ssl;
David Benjamin68161cb2017-06-20 14:49:43 -04002420 if (hs->max_version <= TLS1_2_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002421 return true;
Steven Valdezfdd10992016-09-15 16:27:05 -04002422 }
2423
David Benjamin83a49932021-05-20 15:57:09 -04002424 // supported_versions is compressible in ECH if ClientHelloOuter already
2425 // requires TLS 1.3. Otherwise the extensions differ in the older versions.
2426 if (hs->min_version >= TLS1_3_VERSION) {
2427 out = out_compressible;
2428 }
2429
Steven Valdezfdd10992016-09-15 16:27:05 -04002430 CBB contents, versions;
2431 if (!CBB_add_u16(out, TLSEXT_TYPE_supported_versions) ||
2432 !CBB_add_u16_length_prefixed(out, &contents) ||
2433 !CBB_add_u8_length_prefixed(&contents, &versions)) {
David Benjamin31640932017-10-11 13:22:39 -04002434 return false;
Steven Valdezfdd10992016-09-15 16:27:05 -04002435 }
2436
David Benjamin3675eb32021-05-18 14:01:07 -04002437 // Add a fake version. See RFC 8701.
David Benjamind9791bf2016-09-27 16:39:52 -04002438 if (ssl->ctx->grease_enabled &&
David Benjamina7bc9442018-01-18 10:08:53 -05002439 !CBB_add_u16(&versions, ssl_get_grease_value(hs, ssl_grease_version))) {
David Benjamin31640932017-10-11 13:22:39 -04002440 return false;
David Benjamind9791bf2016-09-27 16:39:52 -04002441 }
2442
David Benjamin83a49932021-05-20 15:57:09 -04002443 // Encrypted ClientHellos requires TLS 1.3 or later.
2444 uint16_t extra_min_version =
2445 type == ssl_client_hello_inner ? TLS1_3_VERSION : 0;
2446 if (!ssl_add_supported_versions(hs, &versions, extra_min_version) ||
Steven Valdez8f36c512017-06-20 10:55:02 -04002447 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002448 return false;
Steven Valdezfdd10992016-09-15 16:27:05 -04002449 }
2450
David Benjamin31640932017-10-11 13:22:39 -04002451 return true;
Steven Valdezfdd10992016-09-15 16:27:05 -04002452}
2453
2454
David Benjaminc11ea9422017-08-29 16:33:21 -04002455// Cookie
2456//
David Benjamina130ce02018-08-14 22:26:39 -05002457// https://tools.ietf.org/html/rfc8446#section-4.2.2
David Benjamin3baa6e12016-10-07 21:10:38 -04002458
David Benjamin83a49932021-05-20 15:57:09 -04002459static bool ext_cookie_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2460 CBB *out_compressible,
2461 ssl_client_hello_type_t type) {
David Benjaminb9493552017-09-27 19:02:51 -04002462 if (hs->cookie.empty()) {
David Benjamin31640932017-10-11 13:22:39 -04002463 return true;
David Benjamin3baa6e12016-10-07 21:10:38 -04002464 }
2465
2466 CBB contents, cookie;
David Benjamin83a49932021-05-20 15:57:09 -04002467 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_cookie) ||
2468 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
David Benjamin3baa6e12016-10-07 21:10:38 -04002469 !CBB_add_u16_length_prefixed(&contents, &cookie) ||
David Benjamin08f5c762017-09-21 02:43:05 -04002470 !CBB_add_bytes(&cookie, hs->cookie.data(), hs->cookie.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -04002471 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04002472 return false;
David Benjamin3baa6e12016-10-07 21:10:38 -04002473 }
2474
David Benjamin31640932017-10-11 13:22:39 -04002475 return true;
David Benjamin3baa6e12016-10-07 21:10:38 -04002476}
2477
2478
David Benjamina130ce02018-08-14 22:26:39 -05002479// Supported Groups
David Benjaminc11ea9422017-08-29 16:33:21 -04002480//
David Benjamina130ce02018-08-14 22:26:39 -05002481// https://tools.ietf.org/html/rfc4492#section-5.1.1
2482// https://tools.ietf.org/html/rfc8446#section-4.2.7
Adam Langley273d49c2015-07-20 16:38:52 -07002483
David Benjamin14e51ad2021-05-19 15:24:34 -04002484static bool ext_supported_groups_add_clienthello(const SSL_HANDSHAKE *hs,
David Benjamin83a49932021-05-20 15:57:09 -04002485 CBB *out,
2486 CBB *out_compressible,
2487 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002488 const SSL *const ssl = hs->ssl;
Steven Valdezce902a92016-05-17 11:47:53 -04002489 CBB contents, groups_bytes;
David Benjamin83a49932021-05-20 15:57:09 -04002490 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_supported_groups) ||
2491 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Steven Valdezce902a92016-05-17 11:47:53 -04002492 !CBB_add_u16_length_prefixed(&contents, &groups_bytes)) {
David Benjamin31640932017-10-11 13:22:39 -04002493 return false;
Adam Langley273d49c2015-07-20 16:38:52 -07002494 }
2495
David Benjamin3675eb32021-05-18 14:01:07 -04002496 // Add a fake group. See RFC 8701.
David Benjamin65ac9972016-09-02 21:35:25 -04002497 if (ssl->ctx->grease_enabled &&
2498 !CBB_add_u16(&groups_bytes,
David Benjamina7bc9442018-01-18 10:08:53 -05002499 ssl_get_grease_value(hs, ssl_grease_group))) {
David Benjamin31640932017-10-11 13:22:39 -04002500 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04002501 }
2502
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07002503 for (uint16_t group : tls1_get_grouplist(hs)) {
Kris Kwiatkowski78c88c92019-03-11 14:40:59 +00002504 if (is_post_quantum_group(group) &&
Adam Langley7b935932018-11-12 13:53:42 -08002505 hs->max_version < TLS1_3_VERSION) {
2506 continue;
2507 }
David Benjamincf0ce672017-09-21 02:25:59 -04002508 if (!CBB_add_u16(&groups_bytes, group)) {
David Benjamin31640932017-10-11 13:22:39 -04002509 return false;
Adam Langley273d49c2015-07-20 16:38:52 -07002510 }
2511 }
2512
David Benjamin83a49932021-05-20 15:57:09 -04002513 return CBB_flush(out_compressible);
Adam Langley273d49c2015-07-20 16:38:52 -07002514}
2515
David Benjamin31640932017-10-11 13:22:39 -04002516static bool ext_supported_groups_parse_serverhello(SSL_HANDSHAKE *hs,
2517 uint8_t *out_alert,
2518 CBS *contents) {
David Benjaminc11ea9422017-08-29 16:33:21 -04002519 // This extension is not expected to be echoed by servers in TLS 1.2, but some
2520 // BigIP servers send it nonetheless, so do not enforce this.
David Benjamin31640932017-10-11 13:22:39 -04002521 return true;
Adam Langley273d49c2015-07-20 16:38:52 -07002522}
2523
David Benjaminb1cf48e2017-09-21 11:37:46 -04002524static bool parse_u16_array(const CBS *cbs, Array<uint16_t> *out) {
2525 CBS copy = *cbs;
2526 if ((CBS_len(&copy) & 1) != 0) {
2527 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2528 return false;
2529 }
2530
2531 Array<uint16_t> ret;
2532 if (!ret.Init(CBS_len(&copy) / 2)) {
2533 return false;
2534 }
2535 for (size_t i = 0; i < ret.size(); i++) {
2536 if (!CBS_get_u16(&copy, &ret[i])) {
2537 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
2538 return false;
2539 }
2540 }
2541
2542 assert(CBS_len(&copy) == 0);
2543 *out = std::move(ret);
Anton Bikineev50e7ea52022-01-23 22:35:48 +01002544 return true;
David Benjaminb1cf48e2017-09-21 11:37:46 -04002545}
2546
David Benjamin31640932017-10-11 13:22:39 -04002547static bool ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs,
David Benjamin8c880a22016-12-03 02:20:34 -05002548 uint8_t *out_alert,
David Benjamin31640932017-10-11 13:22:39 -04002549 CBS *contents) {
Adam Langley273d49c2015-07-20 16:38:52 -07002550 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04002551 return true;
Adam Langley273d49c2015-07-20 16:38:52 -07002552 }
2553
Steven Valdezce902a92016-05-17 11:47:53 -04002554 CBS supported_group_list;
2555 if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) ||
2556 CBS_len(&supported_group_list) == 0 ||
David Benjaminb1cf48e2017-09-21 11:37:46 -04002557 CBS_len(contents) != 0 ||
2558 !parse_u16_array(&supported_group_list, &hs->peer_supported_group_list)) {
David Benjamin31640932017-10-11 13:22:39 -04002559 return false;
Adam Langley273d49c2015-07-20 16:38:52 -07002560 }
2561
David Benjamin31640932017-10-11 13:22:39 -04002562 return true;
Adam Langley273d49c2015-07-20 16:38:52 -07002563}
2564
2565
Nick Harper3c034b22017-12-22 15:50:43 -08002566// QUIC Transport Parameters
2567
David Schinazi3d8b8c32021-01-14 11:25:49 -08002568static bool ext_quic_transport_params_add_clienthello_impl(
David Benjamin14e51ad2021-05-19 15:24:34 -04002569 const SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) {
Nick Harper72cff812020-03-26 18:06:16 -07002570 if (hs->config->quic_transport_params.empty() && !hs->ssl->quic_method) {
Nick Harper3c034b22017-12-22 15:50:43 -08002571 return true;
2572 }
Nick Harper72cff812020-03-26 18:06:16 -07002573 if (hs->config->quic_transport_params.empty() || !hs->ssl->quic_method) {
2574 // QUIC Transport Parameters must be sent over QUIC, and they must not be
2575 // sent over non-QUIC transports. If transport params are set, then
2576 // SSL(_CTX)_set_quic_method must also be called.
2577 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2578 return false;
2579 }
2580 assert(hs->min_version > TLS1_2_VERSION);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002581 if (use_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2582 // Do nothing, we'll send the other codepoint.
2583 return true;
2584 }
2585
David Benjamina1d3bfb2021-06-01 12:12:44 -04002586 uint16_t extension_type = TLSEXT_TYPE_quic_transport_parameters;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002587 if (hs->config->quic_use_legacy_codepoint) {
2588 extension_type = TLSEXT_TYPE_quic_transport_parameters_legacy;
2589 }
Nick Harper3c034b22017-12-22 15:50:43 -08002590
2591 CBB contents;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002592 if (!CBB_add_u16(out, extension_type) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002593 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjamin0ce090a2018-07-02 20:24:40 -04002594 !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(),
2595 hs->config->quic_transport_params.size()) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002596 !CBB_flush(out)) {
2597 return false;
2598 }
2599 return true;
2600}
2601
David Benjamin83a49932021-05-20 15:57:09 -04002602static bool ext_quic_transport_params_add_clienthello(
2603 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2604 ssl_client_hello_type_t type) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002605 return ext_quic_transport_params_add_clienthello_impl(
David Benjamin83a49932021-05-20 15:57:09 -04002606 hs, out_compressible, /*use_legacy_codepoint=*/false);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002607}
2608
David Benjamin14e51ad2021-05-19 15:24:34 -04002609static bool ext_quic_transport_params_add_clienthello_legacy(
David Benjamin83a49932021-05-20 15:57:09 -04002610 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2611 ssl_client_hello_type_t type) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002612 return ext_quic_transport_params_add_clienthello_impl(
David Benjamin83a49932021-05-20 15:57:09 -04002613 hs, out_compressible, /*use_legacy_codepoint=*/true);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002614}
2615
2616static bool ext_quic_transport_params_parse_serverhello_impl(
2617 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents,
2618 bool used_legacy_codepoint) {
Adam Langleyca058c02020-12-16 10:11:08 -08002619 SSL *const ssl = hs->ssl;
2620 if (contents == nullptr) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002621 if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2622 // Silently ignore because we expect the other QUIC codepoint.
2623 return true;
2624 }
Adam Langleyca058c02020-12-16 10:11:08 -08002625 if (!ssl->quic_method) {
2626 return true;
2627 }
Adam Langleyca058c02020-12-16 10:11:08 -08002628 *out_alert = SSL_AD_MISSING_EXTENSION;
2629 return false;
David Schinazi7ba96a62020-12-14 14:46:56 -08002630 }
David Schinazi3d8b8c32021-01-14 11:25:49 -08002631 // The extensions parser will check for unsolicited extensions before
2632 // calling the callback.
2633 assert(ssl->quic_method != nullptr);
Adam Langleyca058c02020-12-16 10:11:08 -08002634 assert(ssl_protocol_version(ssl) == TLS1_3_VERSION);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002635 assert(used_legacy_codepoint == hs->config->quic_use_legacy_codepoint);
Adam Langleyca058c02020-12-16 10:11:08 -08002636 return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
2637}
2638
David Schinazi3d8b8c32021-01-14 11:25:49 -08002639static bool ext_quic_transport_params_parse_serverhello(SSL_HANDSHAKE *hs,
Adam Langleyca058c02020-12-16 10:11:08 -08002640 uint8_t *out_alert,
2641 CBS *contents) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002642 return ext_quic_transport_params_parse_serverhello_impl(
2643 hs, out_alert, contents, /*used_legacy_codepoint=*/false);
2644}
2645
2646static bool ext_quic_transport_params_parse_serverhello_legacy(
2647 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) {
2648 return ext_quic_transport_params_parse_serverhello_impl(
2649 hs, out_alert, contents, /*used_legacy_codepoint=*/true);
2650}
2651
2652static bool ext_quic_transport_params_parse_clienthello_impl(
2653 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents,
2654 bool used_legacy_codepoint) {
Nick Harper3c034b22017-12-22 15:50:43 -08002655 SSL *const ssl = hs->ssl;
Nick Harper72cff812020-03-26 18:06:16 -07002656 if (!contents) {
2657 if (!ssl->quic_method) {
2658 if (hs->config->quic_transport_params.empty()) {
2659 return true;
2660 }
2661 // QUIC transport parameters must not be set if |ssl| is not configured
2662 // for QUIC.
2663 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2664 *out_alert = SSL_AD_INTERNAL_ERROR;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002665 return false;
2666 }
2667 if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2668 // Silently ignore because we expect the other QUIC codepoint.
2669 return true;
Nick Harper72cff812020-03-26 18:06:16 -07002670 }
2671 *out_alert = SSL_AD_MISSING_EXTENSION;
2672 return false;
2673 }
2674 if (!ssl->quic_method) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002675 if (used_legacy_codepoint) {
2676 // Ignore the legacy private-use codepoint because that could be sent
2677 // to mean something else than QUIC transport parameters.
2678 return true;
2679 }
2680 // Fail if we received the codepoint registered with IANA for QUIC
2681 // because that is not allowed outside of QUIC.
Nick Harper72cff812020-03-26 18:06:16 -07002682 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2683 return false;
Nick Harper3c034b22017-12-22 15:50:43 -08002684 }
Nick Harper80ddfc72020-03-11 18:26:31 -07002685 assert(ssl_protocol_version(ssl) == TLS1_3_VERSION);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002686 if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2687 // Silently ignore because we expect the other QUIC codepoint.
2688 return true;
2689 }
Nick Harper3c034b22017-12-22 15:50:43 -08002690 return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
2691}
2692
David Schinazi3d8b8c32021-01-14 11:25:49 -08002693static bool ext_quic_transport_params_parse_clienthello(SSL_HANDSHAKE *hs,
2694 uint8_t *out_alert,
2695 CBS *contents) {
2696 return ext_quic_transport_params_parse_clienthello_impl(
2697 hs, out_alert, contents, /*used_legacy_codepoint=*/false);
2698}
2699
2700static bool ext_quic_transport_params_parse_clienthello_legacy(
2701 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) {
2702 return ext_quic_transport_params_parse_clienthello_impl(
2703 hs, out_alert, contents, /*used_legacy_codepoint=*/true);
2704}
2705
2706static bool ext_quic_transport_params_add_serverhello_impl(
2707 SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) {
2708 if (hs->ssl->quic_method == nullptr && use_legacy_codepoint) {
2709 // Ignore the legacy private-use codepoint because that could be sent
2710 // to mean something else than QUIC transport parameters.
2711 return true;
2712 }
Nick Harper72cff812020-03-26 18:06:16 -07002713 assert(hs->ssl->quic_method != nullptr);
David Benjamin0ce090a2018-07-02 20:24:40 -04002714 if (hs->config->quic_transport_params.empty()) {
Nick Harper72cff812020-03-26 18:06:16 -07002715 // Transport parameters must be set when using QUIC.
2716 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2717 return false;
Nick Harper3c034b22017-12-22 15:50:43 -08002718 }
David Schinazi3d8b8c32021-01-14 11:25:49 -08002719 if (use_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2720 // Do nothing, we'll send the other codepoint.
2721 return true;
2722 }
2723
David Benjamina1d3bfb2021-06-01 12:12:44 -04002724 uint16_t extension_type = TLSEXT_TYPE_quic_transport_parameters;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002725 if (hs->config->quic_use_legacy_codepoint) {
2726 extension_type = TLSEXT_TYPE_quic_transport_parameters_legacy;
2727 }
Nick Harper3c034b22017-12-22 15:50:43 -08002728
2729 CBB contents;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002730 if (!CBB_add_u16(out, extension_type) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002731 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjamin0ce090a2018-07-02 20:24:40 -04002732 !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(),
2733 hs->config->quic_transport_params.size()) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002734 !CBB_flush(out)) {
2735 return false;
2736 }
2737
2738 return true;
2739}
2740
David Schinazi3d8b8c32021-01-14 11:25:49 -08002741static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs,
2742 CBB *out) {
2743 return ext_quic_transport_params_add_serverhello_impl(
2744 hs, out, /*use_legacy_codepoint=*/false);
2745}
2746
2747static bool ext_quic_transport_params_add_serverhello_legacy(SSL_HANDSHAKE *hs,
2748 CBB *out) {
2749 return ext_quic_transport_params_add_serverhello_impl(
2750 hs, out, /*use_legacy_codepoint=*/true);
2751}
2752
Christopher Patton6c1b3762018-07-17 12:49:41 -07002753// Delegated credentials.
2754//
2755// https://tools.ietf.org/html/draft-ietf-tls-subcerts
2756
David Benjamin83a49932021-05-20 15:57:09 -04002757static bool ext_delegated_credential_add_clienthello(
2758 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2759 ssl_client_hello_type_t type) {
Christopher Patton6c1b3762018-07-17 12:49:41 -07002760 return true;
2761}
2762
2763static bool ext_delegated_credential_parse_clienthello(SSL_HANDSHAKE *hs,
2764 uint8_t *out_alert,
2765 CBS *contents) {
Christopher Patton6c1b3762018-07-17 12:49:41 -07002766 if (contents == nullptr || ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
2767 // Don't use delegated credentials unless we're negotiating TLS 1.3 or
2768 // higher.
2769 return true;
2770 }
2771
Watson Ladddcd6e442020-08-10 15:12:45 -04002772 // The contents of the extension are the signature algorithms the client will
2773 // accept for a delegated credential.
2774 CBS sigalg_list;
2775 if (!CBS_get_u16_length_prefixed(contents, &sigalg_list) ||
2776 CBS_len(&sigalg_list) == 0 ||
2777 CBS_len(contents) != 0 ||
2778 !parse_u16_array(&sigalg_list, &hs->peer_delegated_credential_sigalgs)) {
2779 return false;
2780 }
2781
Christopher Patton6c1b3762018-07-17 12:49:41 -07002782 hs->delegated_credential_requested = true;
2783 return true;
2784}
2785
Adam Langleya307cb72018-05-02 09:06:48 -07002786// Certificate compression
2787
David Benjamin83a49932021-05-20 15:57:09 -04002788static bool cert_compression_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2789 CBB *out_compressible,
2790 ssl_client_hello_type_t type) {
Adam Langley0080d832018-06-07 16:39:49 -07002791 bool first = true;
2792 CBB contents, algs;
2793
David Benjamin8fe15842019-10-08 16:57:38 -04002794 for (const auto &alg : hs->ssl->ctx->cert_compression_algs) {
2795 if (alg.decompress == nullptr) {
Adam Langley0080d832018-06-07 16:39:49 -07002796 continue;
2797 }
2798
David Benjamin83a49932021-05-20 15:57:09 -04002799 if (first &&
2800 (!CBB_add_u16(out_compressible, TLSEXT_TYPE_cert_compression) ||
2801 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
2802 !CBB_add_u8_length_prefixed(&contents, &algs))) {
Adam Langley0080d832018-06-07 16:39:49 -07002803 return false;
2804 }
2805 first = false;
David Benjamin8fe15842019-10-08 16:57:38 -04002806 if (!CBB_add_u16(&algs, alg.alg_id)) {
Adam Langley0080d832018-06-07 16:39:49 -07002807 return false;
2808 }
2809 }
2810
David Benjamin83a49932021-05-20 15:57:09 -04002811 return first || CBB_flush(out_compressible);
Adam Langleya307cb72018-05-02 09:06:48 -07002812}
2813
2814static bool cert_compression_parse_serverhello(SSL_HANDSHAKE *hs,
2815 uint8_t *out_alert,
2816 CBS *contents) {
2817 if (contents == nullptr) {
2818 return true;
2819 }
2820
2821 // The server may not echo this extension. Any server to client negotiation is
2822 // advertised in the CertificateRequest message.
2823 return false;
2824}
2825
2826static bool cert_compression_parse_clienthello(SSL_HANDSHAKE *hs,
2827 uint8_t *out_alert,
2828 CBS *contents) {
2829 if (contents == nullptr) {
2830 return true;
2831 }
2832
David Benjamin8fe15842019-10-08 16:57:38 -04002833 const SSL_CTX *ctx = hs->ssl->ctx.get();
2834 const size_t num_algs = ctx->cert_compression_algs.size();
Adam Langleya307cb72018-05-02 09:06:48 -07002835
2836 CBS alg_ids;
2837 if (!CBS_get_u8_length_prefixed(contents, &alg_ids) ||
2838 CBS_len(contents) != 0 ||
2839 CBS_len(&alg_ids) == 0 ||
2840 CBS_len(&alg_ids) % 2 == 1) {
2841 return false;
2842 }
2843
2844 const size_t num_given_alg_ids = CBS_len(&alg_ids) / 2;
2845 Array<uint16_t> given_alg_ids;
2846 if (!given_alg_ids.Init(num_given_alg_ids)) {
2847 return false;
2848 }
2849
2850 size_t best_index = num_algs;
2851 size_t given_alg_idx = 0;
2852
2853 while (CBS_len(&alg_ids) > 0) {
2854 uint16_t alg_id;
2855 if (!CBS_get_u16(&alg_ids, &alg_id)) {
2856 return false;
2857 }
2858
2859 given_alg_ids[given_alg_idx++] = alg_id;
2860
2861 for (size_t i = 0; i < num_algs; i++) {
David Benjamin8fe15842019-10-08 16:57:38 -04002862 const auto &alg = ctx->cert_compression_algs[i];
2863 if (alg.alg_id == alg_id && alg.compress != nullptr) {
Adam Langleya307cb72018-05-02 09:06:48 -07002864 if (i < best_index) {
2865 best_index = i;
2866 }
2867 break;
2868 }
2869 }
2870 }
2871
2872 qsort(given_alg_ids.data(), given_alg_ids.size(), sizeof(uint16_t),
2873 compare_uint16_t);
2874 for (size_t i = 1; i < num_given_alg_ids; i++) {
2875 if (given_alg_ids[i - 1] == given_alg_ids[i]) {
2876 return false;
2877 }
2878 }
2879
2880 if (best_index < num_algs &&
2881 ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
2882 hs->cert_compression_negotiated = true;
David Benjamin8fe15842019-10-08 16:57:38 -04002883 hs->cert_compression_alg_id = ctx->cert_compression_algs[best_index].alg_id;
Adam Langleya307cb72018-05-02 09:06:48 -07002884 }
2885
2886 return true;
2887}
2888
2889static bool cert_compression_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
2890 return true;
2891}
Nick Harper3c034b22017-12-22 15:50:43 -08002892
Steven Valdez51607f12020-08-05 10:46:05 -04002893// Application-level Protocol Settings
2894//
2895// https://tools.ietf.org/html/draft-vvv-tls-alps-01
2896
David Benjamin4e93cd42021-05-18 13:38:25 -04002897bool ssl_get_local_application_settings(const SSL_HANDSHAKE *hs,
2898 Span<const uint8_t> *out_settings,
2899 Span<const uint8_t> protocol) {
2900 for (const ALPSConfig &config : hs->config->alps_configs) {
2901 if (protocol == config.protocol) {
2902 *out_settings = config.settings;
2903 return true;
2904 }
2905 }
2906 return false;
2907}
2908
Victor Tan558960d2023-06-23 15:04:33 +00002909static bool ext_alps_add_clienthello_impl(const SSL_HANDSHAKE *hs, CBB *out,
2910 CBB *out_compressible,
2911 ssl_client_hello_type_t type,
2912 bool use_new_codepoint) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002913 const SSL *const ssl = hs->ssl;
Steven Valdez51607f12020-08-05 10:46:05 -04002914 if (// ALPS requires TLS 1.3.
2915 hs->max_version < TLS1_3_VERSION ||
2916 // Do not offer ALPS without ALPN.
2917 hs->config->alpn_client_proto_list.empty() ||
2918 // Do not offer ALPS if not configured.
2919 hs->config->alps_configs.empty() ||
2920 // Do not offer ALPS on renegotiation handshakes.
2921 ssl->s3->initial_handshake_complete) {
2922 return true;
2923 }
2924
Victor Tan558960d2023-06-23 15:04:33 +00002925 if (use_new_codepoint != hs->config->alps_use_new_codepoint) {
2926 // Do nothing, we'll send the other codepoint.
2927 return true;
2928 }
2929
2930 uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
2931 if (hs->config->alps_use_new_codepoint) {
2932 extension_type = TLSEXT_TYPE_application_settings;
2933 }
2934
Steven Valdez51607f12020-08-05 10:46:05 -04002935 CBB contents, proto_list, proto;
Victor Tan558960d2023-06-23 15:04:33 +00002936 if (!CBB_add_u16(out_compressible, extension_type) ||
David Benjamin83a49932021-05-20 15:57:09 -04002937 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Steven Valdez51607f12020-08-05 10:46:05 -04002938 !CBB_add_u16_length_prefixed(&contents, &proto_list)) {
2939 return false;
2940 }
2941
2942 for (const ALPSConfig &config : hs->config->alps_configs) {
2943 if (!CBB_add_u8_length_prefixed(&proto_list, &proto) ||
2944 !CBB_add_bytes(&proto, config.protocol.data(),
2945 config.protocol.size())) {
2946 return false;
2947 }
2948 }
2949
David Benjamin83a49932021-05-20 15:57:09 -04002950 return CBB_flush(out_compressible);
Steven Valdez51607f12020-08-05 10:46:05 -04002951}
2952
Victor Tan558960d2023-06-23 15:04:33 +00002953static bool ext_alps_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2954 CBB *out_compressible,
2955 ssl_client_hello_type_t type) {
2956 return ext_alps_add_clienthello_impl(hs, out, out_compressible, type,
2957 /*use_new_codepoint=*/true);
2958}
2959
2960static bool ext_alps_add_clienthello_old(const SSL_HANDSHAKE *hs, CBB *out,
2961 CBB *out_compressible,
2962 ssl_client_hello_type_t type) {
2963 return ext_alps_add_clienthello_impl(hs, out, out_compressible, type,
2964 /*use_new_codepoint=*/false);
2965}
2966
2967static bool ext_alps_parse_serverhello_impl(SSL_HANDSHAKE *hs,
2968 uint8_t *out_alert,
2969 CBS *contents,
2970 bool use_new_codepoint) {
Steven Valdez51607f12020-08-05 10:46:05 -04002971 SSL *const ssl = hs->ssl;
2972 if (contents == nullptr) {
2973 return true;
2974 }
2975
2976 assert(!ssl->s3->initial_handshake_complete);
2977 assert(!hs->config->alpn_client_proto_list.empty());
2978 assert(!hs->config->alps_configs.empty());
Victor Tan558960d2023-06-23 15:04:33 +00002979 assert(use_new_codepoint == hs->config->alps_use_new_codepoint);
Steven Valdez51607f12020-08-05 10:46:05 -04002980
2981 // ALPS requires TLS 1.3.
2982 if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
2983 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2984 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
2985 return false;
2986 }
2987
2988 // Note extension callbacks may run in any order, so we defer checking
2989 // consistency with ALPN to |ssl_check_serverhello_tlsext|.
2990 if (!hs->new_session->peer_application_settings.CopyFrom(*contents)) {
2991 *out_alert = SSL_AD_INTERNAL_ERROR;
2992 return false;
2993 }
2994
2995 hs->new_session->has_application_settings = true;
2996 return true;
2997}
2998
Victor Tan558960d2023-06-23 15:04:33 +00002999static bool ext_alps_parse_serverhello(SSL_HANDSHAKE *hs,
3000 uint8_t *out_alert,
3001 CBS *contents) {
3002 return ext_alps_parse_serverhello_impl(hs, out_alert, contents,
3003 /*use_new_codepoint=*/true);
3004}
3005
3006static bool ext_alps_parse_serverhello_old(SSL_HANDSHAKE *hs,
3007 uint8_t *out_alert,
3008 CBS *contents) {
3009 return ext_alps_parse_serverhello_impl(hs, out_alert, contents,
3010 /*use_new_codepoint=*/false);
3011}
3012
3013static bool ext_alps_add_serverhello_impl(SSL_HANDSHAKE *hs, CBB *out,
3014 bool use_new_codepoint) {
Steven Valdez51607f12020-08-05 10:46:05 -04003015 SSL *const ssl = hs->ssl;
3016 // If early data is accepted, we omit the ALPS extension. It is implicitly
3017 // carried over from the previous connection.
3018 if (hs->new_session == nullptr ||
3019 !hs->new_session->has_application_settings ||
3020 ssl->s3->early_data_accepted) {
3021 return true;
3022 }
3023
Victor Tan558960d2023-06-23 15:04:33 +00003024 if (use_new_codepoint != hs->config->alps_use_new_codepoint) {
3025 // Do nothing, we'll send the other codepoint.
3026 return true;
3027 }
3028
3029 uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
3030 if (hs->config->alps_use_new_codepoint) {
3031 extension_type = TLSEXT_TYPE_application_settings;
3032 }
3033
Steven Valdez51607f12020-08-05 10:46:05 -04003034 CBB contents;
Victor Tan558960d2023-06-23 15:04:33 +00003035 if (!CBB_add_u16(out, extension_type) ||
Steven Valdez51607f12020-08-05 10:46:05 -04003036 !CBB_add_u16_length_prefixed(out, &contents) ||
3037 !CBB_add_bytes(&contents,
3038 hs->new_session->local_application_settings.data(),
3039 hs->new_session->local_application_settings.size()) ||
3040 !CBB_flush(out)) {
3041 return false;
3042 }
3043
3044 return true;
3045}
3046
Victor Tan558960d2023-06-23 15:04:33 +00003047static bool ext_alps_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
3048 return ext_alps_add_serverhello_impl(hs, out, /*use_new_codepoint=*/true);
3049}
3050
3051static bool ext_alps_add_serverhello_old(SSL_HANDSHAKE *hs, CBB *out) {
3052 return ext_alps_add_serverhello_impl(hs, out, /*use_new_codepoint=*/false);
3053}
3054
Steven Valdez51607f12020-08-05 10:46:05 -04003055bool ssl_negotiate_alps(SSL_HANDSHAKE *hs, uint8_t *out_alert,
3056 const SSL_CLIENT_HELLO *client_hello) {
3057 SSL *const ssl = hs->ssl;
3058 if (ssl->s3->alpn_selected.empty()) {
3059 return true;
3060 }
3061
3062 // If we negotiate ALPN over TLS 1.3, try to negotiate ALPS.
3063 CBS alps_contents;
3064 Span<const uint8_t> settings;
Victor Tan558960d2023-06-23 15:04:33 +00003065 uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
3066 if (hs->config->alps_use_new_codepoint) {
3067 extension_type = TLSEXT_TYPE_application_settings;
3068 }
Steven Valdez51607f12020-08-05 10:46:05 -04003069 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION &&
3070 ssl_get_local_application_settings(hs, &settings,
3071 ssl->s3->alpn_selected) &&
3072 ssl_client_hello_get_extension(client_hello, &alps_contents,
Victor Tan558960d2023-06-23 15:04:33 +00003073 extension_type)) {
Steven Valdez51607f12020-08-05 10:46:05 -04003074 // Check if the client supports ALPS with the selected ALPN.
3075 bool found = false;
3076 CBS alps_list;
3077 if (!CBS_get_u16_length_prefixed(&alps_contents, &alps_list) ||
3078 CBS_len(&alps_contents) != 0 ||
3079 CBS_len(&alps_list) == 0) {
3080 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
3081 *out_alert = SSL_AD_DECODE_ERROR;
3082 return false;
3083 }
3084 while (CBS_len(&alps_list) > 0) {
3085 CBS protocol_name;
3086 if (!CBS_get_u8_length_prefixed(&alps_list, &protocol_name) ||
3087 // Empty protocol names are forbidden.
3088 CBS_len(&protocol_name) == 0) {
3089 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
3090 *out_alert = SSL_AD_DECODE_ERROR;
3091 return false;
3092 }
3093 if (protocol_name == MakeConstSpan(ssl->s3->alpn_selected)) {
3094 found = true;
3095 }
3096 }
3097
3098 // Negotiate ALPS if both client also supports ALPS for this protocol.
3099 if (found) {
3100 hs->new_session->has_application_settings = true;
3101 if (!hs->new_session->local_application_settings.CopyFrom(settings)) {
3102 *out_alert = SSL_AD_INTERNAL_ERROR;
3103 return false;
3104 }
3105 }
3106 }
3107
3108 return true;
3109}
Adam Langleya86c6982019-07-16 15:26:21 -07003110
David Benjaminc11ea9422017-08-29 16:33:21 -04003111// kExtensions contains all the supported extensions.
Adam Langley614c66a2015-06-12 15:26:58 -07003112static const struct tls_extension kExtensions[] = {
3113 {
3114 TLSEXT_TYPE_server_name,
Adam Langley614c66a2015-06-12 15:26:58 -07003115 ext_sni_add_clienthello,
3116 ext_sni_parse_serverhello,
3117 ext_sni_parse_clienthello,
3118 ext_sni_add_serverhello,
3119 },
Adam Langley0a056712015-07-01 15:03:33 -07003120 {
Dan McArdle1920c6f2020-03-11 17:29:40 -04003121 TLSEXT_TYPE_encrypted_client_hello,
Dan McArdle1920c6f2020-03-11 17:29:40 -04003122 ext_ech_add_clienthello,
3123 ext_ech_parse_serverhello,
Dan McArdlec2959352020-10-29 14:31:31 -04003124 ext_ech_parse_clienthello,
Daniel McArdle00e434d2021-02-18 11:47:18 -05003125 ext_ech_add_serverhello,
Dan McArdlec2959352020-10-29 14:31:31 -04003126 },
3127 {
Adam Langley0a056712015-07-01 15:03:33 -07003128 TLSEXT_TYPE_extended_master_secret,
Adam Langley0a056712015-07-01 15:03:33 -07003129 ext_ems_add_clienthello,
3130 ext_ems_parse_serverhello,
3131 ext_ems_parse_clienthello,
3132 ext_ems_add_serverhello,
3133 },
Adam Langley9b05bc52015-07-01 15:25:33 -07003134 {
Adam Langleyd6680952018-08-23 08:01:23 -07003135 TLSEXT_TYPE_renegotiate,
Adam Langleyd6680952018-08-23 08:01:23 -07003136 ext_ri_add_clienthello,
3137 ext_ri_parse_serverhello,
3138 ext_ri_parse_clienthello,
3139 ext_ri_add_serverhello,
3140 },
3141 {
3142 TLSEXT_TYPE_supported_groups,
Adam Langleyd6680952018-08-23 08:01:23 -07003143 ext_supported_groups_add_clienthello,
3144 ext_supported_groups_parse_serverhello,
3145 ext_supported_groups_parse_clienthello,
3146 dont_add_serverhello,
3147 },
3148 {
3149 TLSEXT_TYPE_ec_point_formats,
Adam Langleyd6680952018-08-23 08:01:23 -07003150 ext_ec_point_add_clienthello,
3151 ext_ec_point_parse_serverhello,
3152 ext_ec_point_parse_clienthello,
3153 ext_ec_point_add_serverhello,
3154 },
3155 {
Adam Langley9b05bc52015-07-01 15:25:33 -07003156 TLSEXT_TYPE_session_ticket,
Adam Langley9b05bc52015-07-01 15:25:33 -07003157 ext_ticket_add_clienthello,
3158 ext_ticket_parse_serverhello,
David Benjaminc11ea9422017-08-29 16:33:21 -04003159 // Ticket extension client parsing is handled in ssl_session.c
Steven Valdez6b8509a2016-07-12 13:38:32 -04003160 ignore_parse_clienthello,
Adam Langley9b05bc52015-07-01 15:25:33 -07003161 ext_ticket_add_serverhello,
3162 },
Adam Langley2e857bd2015-07-01 16:09:19 -07003163 {
Adam Langleyd6680952018-08-23 08:01:23 -07003164 TLSEXT_TYPE_application_layer_protocol_negotiation,
Adam Langleyd6680952018-08-23 08:01:23 -07003165 ext_alpn_add_clienthello,
3166 ext_alpn_parse_serverhello,
3167 // ALPN is negotiated late in |ssl_negotiate_alpn|.
3168 ignore_parse_clienthello,
3169 ext_alpn_add_serverhello,
3170 },
3171 {
3172 TLSEXT_TYPE_status_request,
Adam Langleyd6680952018-08-23 08:01:23 -07003173 ext_ocsp_add_clienthello,
3174 ext_ocsp_parse_serverhello,
3175 ext_ocsp_parse_clienthello,
3176 ext_ocsp_add_serverhello,
3177 },
3178 {
Adam Langley2e857bd2015-07-01 16:09:19 -07003179 TLSEXT_TYPE_signature_algorithms,
Adam Langley2e857bd2015-07-01 16:09:19 -07003180 ext_sigalgs_add_clienthello,
Steven Valdez6b8509a2016-07-12 13:38:32 -04003181 forbid_parse_serverhello,
Adam Langley2e857bd2015-07-01 16:09:19 -07003182 ext_sigalgs_parse_clienthello,
Steven Valdez6b8509a2016-07-12 13:38:32 -04003183 dont_add_serverhello,
Adam Langley2e857bd2015-07-01 16:09:19 -07003184 },
Adam Langleybb0bd042015-07-01 16:21:03 -07003185 {
Adam Langley97dfcbf2015-07-01 18:35:20 -07003186 TLSEXT_TYPE_next_proto_neg,
Adam Langley97dfcbf2015-07-01 18:35:20 -07003187 ext_npn_add_clienthello,
3188 ext_npn_parse_serverhello,
3189 ext_npn_parse_clienthello,
3190 ext_npn_add_serverhello,
3191 },
Adam Langleyab8d87d2015-07-10 12:21:39 -07003192 {
3193 TLSEXT_TYPE_certificate_timestamp,
Adam Langleyab8d87d2015-07-10 12:21:39 -07003194 ext_sct_add_clienthello,
3195 ext_sct_parse_serverhello,
3196 ext_sct_parse_clienthello,
3197 ext_sct_add_serverhello,
3198 },
Adam Langleyf18e4532015-07-10 13:39:53 -07003199 {
Adam Langley49c7af12015-07-10 14:33:46 -07003200 TLSEXT_TYPE_channel_id,
Adam Langley49c7af12015-07-10 14:33:46 -07003201 ext_channel_id_add_clienthello,
3202 ext_channel_id_parse_serverhello,
3203 ext_channel_id_parse_clienthello,
3204 ext_channel_id_add_serverhello,
3205 },
Adam Langley391250d2015-07-15 19:06:07 -07003206 {
3207 TLSEXT_TYPE_srtp,
Adam Langley391250d2015-07-15 19:06:07 -07003208 ext_srtp_add_clienthello,
3209 ext_srtp_parse_serverhello,
3210 ext_srtp_parse_clienthello,
3211 ext_srtp_add_serverhello,
3212 },
Adam Langleybdd5d662015-07-20 16:19:08 -07003213 {
Steven Valdez7e5dd252018-01-22 15:20:31 -05003214 TLSEXT_TYPE_key_share,
Steven Valdez143e8b32016-07-11 13:19:03 -04003215 ext_key_share_add_clienthello,
3216 forbid_parse_serverhello,
3217 ignore_parse_clienthello,
3218 dont_add_serverhello,
3219 },
Steven Valdez4aa154e2016-07-29 14:32:55 -04003220 {
Steven Valdeza833c352016-11-01 13:39:36 -04003221 TLSEXT_TYPE_psk_key_exchange_modes,
Steven Valdeza833c352016-11-01 13:39:36 -04003222 ext_psk_key_exchange_modes_add_clienthello,
Steven Valdez4aa154e2016-07-29 14:32:55 -04003223 forbid_parse_serverhello,
David Benjamin4eb95cc2016-11-16 17:08:23 +09003224 ext_psk_key_exchange_modes_parse_clienthello,
Steven Valdez4aa154e2016-07-29 14:32:55 -04003225 dont_add_serverhello,
3226 },
Steven Valdezfdd10992016-09-15 16:27:05 -04003227 {
Steven Valdeza4ee74d2016-11-29 13:36:45 -05003228 TLSEXT_TYPE_early_data,
Steven Valdeza4ee74d2016-11-29 13:36:45 -05003229 ext_early_data_add_clienthello,
Steven Valdez2d850622017-01-11 11:34:52 -05003230 ext_early_data_parse_serverhello,
Steven Valdeza4ee74d2016-11-29 13:36:45 -05003231 ext_early_data_parse_clienthello,
Steven Valdez2d850622017-01-11 11:34:52 -05003232 ext_early_data_add_serverhello,
Steven Valdeza4ee74d2016-11-29 13:36:45 -05003233 },
3234 {
Steven Valdezfdd10992016-09-15 16:27:05 -04003235 TLSEXT_TYPE_supported_versions,
Steven Valdezfdd10992016-09-15 16:27:05 -04003236 ext_supported_versions_add_clienthello,
3237 forbid_parse_serverhello,
3238 ignore_parse_clienthello,
3239 dont_add_serverhello,
3240 },
David Benjamin3baa6e12016-10-07 21:10:38 -04003241 {
3242 TLSEXT_TYPE_cookie,
David Benjamin3baa6e12016-10-07 21:10:38 -04003243 ext_cookie_add_clienthello,
3244 forbid_parse_serverhello,
3245 ignore_parse_clienthello,
3246 dont_add_serverhello,
3247 },
Adam Langley512a2892017-12-30 08:04:39 -08003248 {
David Benjamina1d3bfb2021-06-01 12:12:44 -04003249 TLSEXT_TYPE_quic_transport_parameters,
Nick Harper3c034b22017-12-22 15:50:43 -08003250 ext_quic_transport_params_add_clienthello,
3251 ext_quic_transport_params_parse_serverhello,
3252 ext_quic_transport_params_parse_clienthello,
3253 ext_quic_transport_params_add_serverhello,
3254 },
Adam Langley273d49c2015-07-20 16:38:52 -07003255 {
David Schinazi3d8b8c32021-01-14 11:25:49 -08003256 TLSEXT_TYPE_quic_transport_parameters_legacy,
David Schinazi3d8b8c32021-01-14 11:25:49 -08003257 ext_quic_transport_params_add_clienthello_legacy,
3258 ext_quic_transport_params_parse_serverhello_legacy,
3259 ext_quic_transport_params_parse_clienthello_legacy,
3260 ext_quic_transport_params_add_serverhello_legacy,
3261 },
3262 {
Adam Langleya307cb72018-05-02 09:06:48 -07003263 TLSEXT_TYPE_cert_compression,
Adam Langleya307cb72018-05-02 09:06:48 -07003264 cert_compression_add_clienthello,
3265 cert_compression_parse_serverhello,
3266 cert_compression_parse_clienthello,
3267 cert_compression_add_serverhello,
3268 },
Christopher Patton6c1b3762018-07-17 12:49:41 -07003269 {
3270 TLSEXT_TYPE_delegated_credential,
Christopher Patton6c1b3762018-07-17 12:49:41 -07003271 ext_delegated_credential_add_clienthello,
3272 forbid_parse_serverhello,
3273 ext_delegated_credential_parse_clienthello,
3274 dont_add_serverhello,
3275 },
Steven Valdez51607f12020-08-05 10:46:05 -04003276 {
3277 TLSEXT_TYPE_application_settings,
Steven Valdez51607f12020-08-05 10:46:05 -04003278 ext_alps_add_clienthello,
3279 ext_alps_parse_serverhello,
3280 // ALPS is negotiated late in |ssl_negotiate_alpn|.
3281 ignore_parse_clienthello,
3282 ext_alps_add_serverhello,
3283 },
Victor Tan558960d2023-06-23 15:04:33 +00003284 {
3285 TLSEXT_TYPE_application_settings_old,
3286 ext_alps_add_clienthello_old,
3287 ext_alps_parse_serverhello_old,
3288 // ALPS is negotiated late in |ssl_negotiate_alpn|.
3289 ignore_parse_clienthello,
3290 ext_alps_add_serverhello_old,
3291 },
Adam Langley614c66a2015-06-12 15:26:58 -07003292};
3293
3294#define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
3295
David Benjamina3d76d02017-07-14 19:36:07 -04003296static_assert(kNumExtensions <=
3297 sizeof(((SSL_HANDSHAKE *)NULL)->extensions.sent) * 8,
3298 "too many extensions for sent bitset");
3299static_assert(kNumExtensions <=
3300 sizeof(((SSL_HANDSHAKE *)NULL)->extensions.received) * 8,
3301 "too many extensions for received bitset");
Adam Langley4cfa96b2015-07-01 11:56:55 -07003302
David Benjamine9c5d722021-06-09 17:43:16 -04003303bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs) {
3304 if (!hs->config->permute_extensions) {
3305 return true;
3306 }
3307
3308 static_assert(kNumExtensions <= UINT8_MAX,
3309 "extensions_permutation type is too small");
3310 uint32_t seeds[kNumExtensions - 1];
3311 Array<uint8_t> permutation;
3312 if (!RAND_bytes(reinterpret_cast<uint8_t *>(seeds), sizeof(seeds)) ||
3313 !permutation.Init(kNumExtensions)) {
3314 return false;
3315 }
3316 for (size_t i = 0; i < kNumExtensions; i++) {
3317 permutation[i] = i;
3318 }
3319 for (size_t i = kNumExtensions - 1; i > 0; i--) {
3320 // Set element |i| to a randomly-selected element 0 <= j <= i.
3321 std::swap(permutation[i], permutation[seeds[i - 1] % (i + 1)]);
3322 }
3323 hs->extension_permutation = std::move(permutation);
3324 return true;
3325}
3326
Adam Langley614c66a2015-06-12 15:26:58 -07003327static const struct tls_extension *tls_extension_find(uint32_t *out_index,
3328 uint16_t value) {
3329 unsigned i;
3330 for (i = 0; i < kNumExtensions; i++) {
3331 if (kExtensions[i].value == value) {
3332 *out_index = i;
3333 return &kExtensions[i];
3334 }
3335 }
3336
3337 return NULL;
3338}
3339
David Benjaminfb4d2572021-06-01 15:58:30 -04003340static bool add_padding_extension(CBB *cbb, uint16_t ext, size_t len) {
3341 CBB child;
David Benjaminfb4d2572021-06-01 15:58:30 -04003342 if (!CBB_add_u16(cbb, ext) || //
3343 !CBB_add_u16_length_prefixed(cbb, &child) ||
David Benjamin95450622021-07-16 18:24:02 -04003344 !CBB_add_zeros(&child, len)) {
David Benjaminfb4d2572021-06-01 15:58:30 -04003345 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3346 return false;
3347 }
David Benjaminfb4d2572021-06-01 15:58:30 -04003348 return CBB_flush(cbb);
3349}
3350
David Benjamin83a49932021-05-20 15:57:09 -04003351static bool ssl_add_clienthello_tlsext_inner(SSL_HANDSHAKE *hs, CBB *out,
3352 CBB *out_encoded,
3353 bool *out_needs_psk_binder) {
3354 // When writing ClientHelloInner, we construct the real and encoded
3355 // ClientHellos concurrently, to handle compression. Uncompressed extensions
3356 // are written to |extensions| and copied to |extensions_encoded|. Compressed
3357 // extensions are buffered in |compressed| and written to the end. (ECH can
3358 // only compress continguous extensions.)
3359 SSL *const ssl = hs->ssl;
3360 bssl::ScopedCBB compressed, outer_extensions;
3361 CBB extensions, extensions_encoded;
3362 if (!CBB_add_u16_length_prefixed(out, &extensions) ||
3363 !CBB_add_u16_length_prefixed(out_encoded, &extensions_encoded) ||
3364 !CBB_init(compressed.get(), 64) ||
3365 !CBB_init(outer_extensions.get(), 64)) {
3366 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3367 return false;
3368 }
3369
3370 hs->inner_extensions_sent = 0;
3371
3372 if (ssl->ctx->grease_enabled) {
3373 // Add a fake empty extension. See RFC 8701. This always matches
3374 // |ssl_add_clienthello_tlsext|, so compress it.
3375 uint16_t grease_ext = ssl_get_grease_value(hs, ssl_grease_extension1);
3376 if (!add_padding_extension(compressed.get(), grease_ext, 0) ||
3377 !CBB_add_u16(outer_extensions.get(), grease_ext)) {
3378 return false;
3379 }
3380 }
3381
David Benjamine9c5d722021-06-09 17:43:16 -04003382 for (size_t unpermuted = 0; unpermuted < kNumExtensions; unpermuted++) {
3383 size_t i = hs->extension_permutation.empty()
3384 ? unpermuted
3385 : hs->extension_permutation[unpermuted];
David Benjamin83a49932021-05-20 15:57:09 -04003386 const size_t len_before = CBB_len(&extensions);
3387 const size_t len_compressed_before = CBB_len(compressed.get());
3388 if (!kExtensions[i].add_clienthello(hs, &extensions, compressed.get(),
3389 ssl_client_hello_inner)) {
3390 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
3391 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3392 return false;
3393 }
3394
3395 const size_t bytes_written = CBB_len(&extensions) - len_before;
3396 const size_t bytes_written_compressed =
3397 CBB_len(compressed.get()) - len_compressed_before;
3398 // The callback may write to at most one output.
3399 assert(bytes_written == 0 || bytes_written_compressed == 0);
3400 if (bytes_written != 0 || bytes_written_compressed != 0) {
3401 hs->inner_extensions_sent |= (1u << i);
3402 }
3403 // If compressed, update the running ech_outer_extensions extension.
3404 if (bytes_written_compressed != 0 &&
3405 !CBB_add_u16(outer_extensions.get(), kExtensions[i].value)) {
3406 return false;
3407 }
3408 }
3409
3410 if (ssl->ctx->grease_enabled) {
3411 // Add a fake non-empty extension. See RFC 8701. This always matches
3412 // |ssl_add_clienthello_tlsext|, so compress it.
3413 uint16_t grease_ext = ssl_get_grease_value(hs, ssl_grease_extension2);
3414 if (!add_padding_extension(compressed.get(), grease_ext, 1) ||
3415 !CBB_add_u16(outer_extensions.get(), grease_ext)) {
3416 return false;
3417 }
3418 }
3419
David Benjamin83a49932021-05-20 15:57:09 -04003420 // Uncompressed extensions are encoded as-is.
3421 if (!CBB_add_bytes(&extensions_encoded, CBB_data(&extensions),
3422 CBB_len(&extensions))) {
3423 return false;
3424 }
3425
3426 // Flush all the compressed extensions.
3427 if (CBB_len(compressed.get()) != 0) {
3428 CBB extension, child;
3429 // Copy them as-is in the real ClientHelloInner.
3430 if (!CBB_add_bytes(&extensions, CBB_data(compressed.get()),
3431 CBB_len(compressed.get())) ||
3432 // Replace with ech_outer_extensions in the encoded form.
3433 !CBB_add_u16(&extensions_encoded, TLSEXT_TYPE_ech_outer_extensions) ||
3434 !CBB_add_u16_length_prefixed(&extensions_encoded, &extension) ||
3435 !CBB_add_u8_length_prefixed(&extension, &child) ||
3436 !CBB_add_bytes(&child, CBB_data(outer_extensions.get()),
3437 CBB_len(outer_extensions.get())) ||
3438 !CBB_flush(&extensions_encoded)) {
3439 return false;
3440 }
3441 }
3442
3443 // The PSK extension must be last. It is never compressed. Note, if there is a
3444 // binder, the caller will need to update both ClientHelloInner and
3445 // EncodedClientHelloInner after computing it.
3446 const size_t len_before = CBB_len(&extensions);
3447 if (!ext_pre_shared_key_add_clienthello(hs, &extensions, out_needs_psk_binder,
3448 ssl_client_hello_inner) ||
3449 !CBB_add_bytes(&extensions_encoded, CBB_data(&extensions) + len_before,
3450 CBB_len(&extensions) - len_before) ||
3451 !CBB_flush(out) || //
3452 !CBB_flush(out_encoded)) {
3453 return false;
3454 }
3455
3456 return true;
3457}
3458
3459bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, CBB *out_encoded,
3460 bool *out_needs_psk_binder,
David Benjamin18b68362021-06-18 23:13:46 -04003461 ssl_client_hello_type_t type,
3462 size_t header_len) {
David Benjamin83a49932021-05-20 15:57:09 -04003463 *out_needs_psk_binder = false;
3464
3465 if (type == ssl_client_hello_inner) {
3466 return ssl_add_clienthello_tlsext_inner(hs, out, out_encoded,
3467 out_needs_psk_binder);
3468 }
3469
3470 assert(out_encoded == nullptr); // Only ClientHelloInner needs two outputs.
David Benjamin8c880a22016-12-03 02:20:34 -05003471 SSL *const ssl = hs->ssl;
David Benjamine8d53502015-10-10 14:13:23 -04003472 CBB extensions;
3473 if (!CBB_add_u16_length_prefixed(out, &extensions)) {
David Benjamin81678aa2017-07-12 22:43:42 -04003474 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04003475 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003476 }
Adam Langley95c29f32014-06-20 12:00:00 -07003477
David Benjamin64770122019-05-04 11:00:04 -05003478 // Note we may send multiple ClientHellos for DTLS HelloVerifyRequest and TLS
3479 // 1.3 HelloRetryRequest. For the latter, the extensions may change, so it is
3480 // important to reset this value.
David Benjamin8c880a22016-12-03 02:20:34 -05003481 hs->extensions.sent = 0;
Adam Langley95c29f32014-06-20 12:00:00 -07003482
David Benjaminfb4d2572021-06-01 15:58:30 -04003483 // Add a fake empty extension. See RFC 8701.
3484 if (ssl->ctx->grease_enabled &&
3485 !add_padding_extension(
3486 &extensions, ssl_get_grease_value(hs, ssl_grease_extension1), 0)) {
3487 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04003488 }
3489
Adam Langley7f4f41f2018-08-23 08:58:49 -07003490 bool last_was_empty = false;
David Benjamine9c5d722021-06-09 17:43:16 -04003491 for (size_t unpermuted = 0; unpermuted < kNumExtensions; unpermuted++) {
3492 size_t i = hs->extension_permutation.empty()
3493 ? unpermuted
3494 : hs->extension_permutation[unpermuted];
David Benjamin18b68362021-06-18 23:13:46 -04003495 const size_t len_before = CBB_len(&extensions);
3496 if (!kExtensions[i].add_clienthello(hs, &extensions, &extensions, type)) {
3497 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
3498 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3499 return false;
David Benjamin83a49932021-05-20 15:57:09 -04003500 }
David Benjamin18b68362021-06-18 23:13:46 -04003501
3502 const size_t bytes_written = CBB_len(&extensions) - len_before;
Adam Langley7f4f41f2018-08-23 08:58:49 -07003503 if (bytes_written != 0) {
David Benjamin8c880a22016-12-03 02:20:34 -05003504 hs->extensions.sent |= (1u << i);
Adam Langley614c66a2015-06-12 15:26:58 -07003505 }
Adam Langley7f4f41f2018-08-23 08:58:49 -07003506 // If the difference in lengths is only four bytes then the extension had
3507 // an empty body.
3508 last_was_empty = (bytes_written == 4);
Adam Langleyfcf25832014-12-18 17:42:32 -08003509 }
Adam Langley75712922014-10-10 16:23:43 -07003510
David Benjamin65ac9972016-09-02 21:35:25 -04003511 if (ssl->ctx->grease_enabled) {
David Benjamin3675eb32021-05-18 14:01:07 -04003512 // Add a fake non-empty extension. See RFC 8701.
David Benjaminfb4d2572021-06-01 15:58:30 -04003513 if (!add_padding_extension(
3514 &extensions, ssl_get_grease_value(hs, ssl_grease_extension2), 1)) {
David Benjamin861abcc2018-07-14 17:40:26 -04003515 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04003516 }
Adam Langley7f4f41f2018-08-23 08:58:49 -07003517 last_was_empty = false;
David Benjamin65ac9972016-09-02 21:35:25 -04003518 }
3519
David Benjamin83a49932021-05-20 15:57:09 -04003520 // In cleartext ClientHellos, we add the padding extension to work around
3521 // bugs. We also apply this padding to ClientHelloOuter, to keep the wire
3522 // images aligned.
3523 size_t psk_extension_len = ext_pre_shared_key_clienthello_length(hs, type);
David Benjamincd890042021-06-02 18:35:31 -04003524 if (!SSL_is_dtls(ssl) && !ssl->quic_method &&
3525 !ssl->s3->used_hello_retry_request) {
David Benjamin18b68362021-06-18 23:13:46 -04003526 header_len +=
3527 SSL3_HM_HEADER_LENGTH + 2 + CBB_len(&extensions) + psk_extension_len;
Adam Langley7f4f41f2018-08-23 08:58:49 -07003528 size_t padding_len = 0;
3529
3530 // The final extension must be non-empty. WebSphere Application
3531 // Server 7.0 is intolerant to the last extension being zero-length. See
3532 // https://crbug.com/363583.
3533 if (last_was_empty && psk_extension_len == 0) {
3534 padding_len = 1;
3535 // The addition of the padding extension may push us into the F5 bug.
3536 header_len += 4 + padding_len;
3537 }
3538
3539 // Add padding to workaround bugs in F5 terminators. See RFC 7685.
3540 //
3541 // NB: because this code works out the length of all existing extensions
3542 // it MUST always appear last (save for any PSK extension).
Adam Langleyfcf25832014-12-18 17:42:32 -08003543 if (header_len > 0xff && header_len < 0x200) {
Adam Langley7f4f41f2018-08-23 08:58:49 -07003544 // If our calculations already included a padding extension, remove that
3545 // factor because we're about to change its length.
3546 if (padding_len != 0) {
3547 header_len -= 4 + padding_len;
3548 }
3549 padding_len = 0x200 - header_len;
David Benjaminc11ea9422017-08-29 16:33:21 -04003550 // Extensions take at least four bytes to encode. Always include at least
3551 // one byte of data if including the extension. WebSphere Application
3552 // Server 7.0 is intolerant to the last extension being zero-length. See
3553 // https://crbug.com/363583.
Adam Langleyfcf25832014-12-18 17:42:32 -08003554 if (padding_len >= 4 + 1) {
3555 padding_len -= 4;
3556 } else {
3557 padding_len = 1;
3558 }
Adam Langley7f4f41f2018-08-23 08:58:49 -07003559 }
Adam Langley95c29f32014-06-20 12:00:00 -07003560
David Benjaminfb4d2572021-06-01 15:58:30 -04003561 if (padding_len != 0 &&
3562 !add_padding_extension(&extensions, TLSEXT_TYPE_padding, padding_len)) {
3563 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003564 }
3565 }
Adam Langley75712922014-10-10 16:23:43 -07003566
David Benjaminc11ea9422017-08-29 16:33:21 -04003567 // The PSK extension must be last, including after the padding.
David Benjamin350fe3b2021-06-02 17:58:53 -04003568 const size_t len_before = CBB_len(&extensions);
David Benjamin83a49932021-05-20 15:57:09 -04003569 if (!ext_pre_shared_key_add_clienthello(hs, &extensions, out_needs_psk_binder,
3570 type)) {
David Benjamin81678aa2017-07-12 22:43:42 -04003571 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04003572 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04003573 }
David Benjamin350fe3b2021-06-02 17:58:53 -04003574 assert(psk_extension_len == CBB_len(&extensions) - len_before);
3575 (void)len_before; // |assert| is omitted in release builds.
Steven Valdeza833c352016-11-01 13:39:36 -04003576
David Benjaminc11ea9422017-08-29 16:33:21 -04003577 // Discard empty extensions blocks.
David Benjamina01deee2015-12-08 18:56:31 -05003578 if (CBB_len(&extensions) == 0) {
David Benjamine8d53502015-10-10 14:13:23 -04003579 CBB_discard_child(out);
Adam Langley33ad2b52015-07-20 17:43:53 -07003580 }
3581
David Benjamine8d53502015-10-10 14:13:23 -04003582 return CBB_flush(out);
Adam Langleyfcf25832014-12-18 17:42:32 -08003583}
Adam Langley95c29f32014-06-20 12:00:00 -07003584
David Benjamin861abcc2018-07-14 17:40:26 -04003585bool ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05003586 SSL *const ssl = hs->ssl;
David Benjamin56380462015-10-10 14:59:09 -04003587 CBB extensions;
3588 if (!CBB_add_u16_length_prefixed(out, &extensions)) {
Adam Langley33ad2b52015-07-20 17:43:53 -07003589 goto err;
Adam Langley614c66a2015-06-12 15:26:58 -07003590 }
3591
David Benjamin8c880a22016-12-03 02:20:34 -05003592 for (unsigned i = 0; i < kNumExtensions; i++) {
3593 if (!(hs->extensions.received & (1u << i))) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003594 // Don't send extensions that were not received.
Adam Langley614c66a2015-06-12 15:26:58 -07003595 continue;
Adam Langleyfcf25832014-12-18 17:42:32 -08003596 }
Adam Langley95c29f32014-06-20 12:00:00 -07003597
David Benjamin8c880a22016-12-03 02:20:34 -05003598 if (!kExtensions[i].add_serverhello(hs, &extensions)) {
Adam Langley33ad2b52015-07-20 17:43:53 -07003599 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003600 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
Adam Langley33ad2b52015-07-20 17:43:53 -07003601 goto err;
Adam Langley614c66a2015-06-12 15:26:58 -07003602 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003603 }
Adam Langley95c29f32014-06-20 12:00:00 -07003604
David Benjaminc11ea9422017-08-29 16:33:21 -04003605 // Discard empty extensions blocks before TLS 1.3.
David Benjamind1e3ce12017-10-06 18:31:15 -04003606 if (ssl_protocol_version(ssl) < TLS1_3_VERSION &&
Steven Valdez143e8b32016-07-11 13:19:03 -04003607 CBB_len(&extensions) == 0) {
David Benjamin56380462015-10-10 14:59:09 -04003608 CBB_discard_child(out);
Adam Langley33ad2b52015-07-20 17:43:53 -07003609 }
3610
David Benjamin56380462015-10-10 14:59:09 -04003611 return CBB_flush(out);
Adam Langley33ad2b52015-07-20 17:43:53 -07003612
3613err:
Adam Langley33ad2b52015-07-20 17:43:53 -07003614 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04003615 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003616}
Adam Langley95c29f32014-06-20 12:00:00 -07003617
David Benjamin861abcc2018-07-14 17:40:26 -04003618static bool ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs,
3619 const SSL_CLIENT_HELLO *client_hello,
3620 int *out_alert) {
David Benjamin8c880a22016-12-03 02:20:34 -05003621 hs->extensions.received = 0;
David Benjamine14ff062016-08-09 16:21:24 -04003622 CBS extensions;
3623 CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
3624 while (CBS_len(&extensions) != 0) {
3625 uint16_t type;
3626 CBS extension;
3627
David Benjaminc11ea9422017-08-29 16:33:21 -04003628 // Decode the next extension.
David Benjamine14ff062016-08-09 16:21:24 -04003629 if (!CBS_get_u16(&extensions, &type) ||
3630 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08003631 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003632 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003633 }
Adam Langley95c29f32014-06-20 12:00:00 -07003634
David Benjamine14ff062016-08-09 16:21:24 -04003635 unsigned ext_index;
3636 const struct tls_extension *const ext =
3637 tls_extension_find(&ext_index, type);
David Benjamine14ff062016-08-09 16:21:24 -04003638 if (ext == NULL) {
David Benjamine14ff062016-08-09 16:21:24 -04003639 continue;
3640 }
3641
David Benjamin8c880a22016-12-03 02:20:34 -05003642 hs->extensions.received |= (1u << ext_index);
David Benjamine14ff062016-08-09 16:21:24 -04003643 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003644 if (!ext->parse_clienthello(hs, &alert, &extension)) {
David Benjamine14ff062016-08-09 16:21:24 -04003645 *out_alert = alert;
3646 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003647 ERR_add_error_dataf("extension %u", (unsigned)type);
David Benjamin861abcc2018-07-14 17:40:26 -04003648 return false;
Adam Langley614c66a2015-06-12 15:26:58 -07003649 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003650 }
Adam Langley75712922014-10-10 16:23:43 -07003651
David Benjamin1deb41b2016-08-09 19:36:38 -04003652 for (size_t i = 0; i < kNumExtensions; i++) {
David Benjamin8c880a22016-12-03 02:20:34 -05003653 if (hs->extensions.received & (1u << i)) {
David Benjamin1deb41b2016-08-09 19:36:38 -04003654 continue;
3655 }
3656
3657 CBS *contents = NULL, fake_contents;
3658 static const uint8_t kFakeRenegotiateExtension[] = {0};
3659 if (kExtensions[i].value == TLSEXT_TYPE_renegotiate &&
3660 ssl_client_cipher_list_contains_cipher(client_hello,
3661 SSL3_CK_SCSV & 0xffff)) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003662 // The renegotiation SCSV was received so pretend that we received a
3663 // renegotiation extension.
David Benjamin1deb41b2016-08-09 19:36:38 -04003664 CBS_init(&fake_contents, kFakeRenegotiateExtension,
3665 sizeof(kFakeRenegotiateExtension));
3666 contents = &fake_contents;
David Benjamin8c880a22016-12-03 02:20:34 -05003667 hs->extensions.received |= (1u << i);
David Benjamin1deb41b2016-08-09 19:36:38 -04003668 }
3669
David Benjaminc11ea9422017-08-29 16:33:21 -04003670 // Extension wasn't observed so call the callback with a NULL
3671 // parameter.
David Benjamin1deb41b2016-08-09 19:36:38 -04003672 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003673 if (!kExtensions[i].parse_clienthello(hs, &alert, contents)) {
David Benjamin1deb41b2016-08-09 19:36:38 -04003674 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003675 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
David Benjamin1deb41b2016-08-09 19:36:38 -04003676 *out_alert = alert;
David Benjamin861abcc2018-07-14 17:40:26 -04003677 return false;
Adam Langley614c66a2015-06-12 15:26:58 -07003678 }
3679 }
3680
David Benjamin861abcc2018-07-14 17:40:26 -04003681 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003682}
Adam Langley95c29f32014-06-20 12:00:00 -07003683
David Benjamin861abcc2018-07-14 17:40:26 -04003684bool ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs,
3685 const SSL_CLIENT_HELLO *client_hello) {
David Benjamin8c880a22016-12-03 02:20:34 -05003686 SSL *const ssl = hs->ssl;
Adam Langleyc68e5b92017-02-08 13:33:15 -08003687 int alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003688 if (!ssl_scan_clienthello_tlsext(hs, client_hello, &alert)) {
David Benjamind1e3ce12017-10-06 18:31:15 -04003689 ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
David Benjamin861abcc2018-07-14 17:40:26 -04003690 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003691 }
Adam Langley95c29f32014-06-20 12:00:00 -07003692
David Benjamin861abcc2018-07-14 17:40:26 -04003693 if (!ssl_check_clienthello_tlsext(hs)) {
David Benjamin3570d732015-06-29 00:28:17 -04003694 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_TLSEXT);
David Benjamin861abcc2018-07-14 17:40:26 -04003695 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003696 }
Adam Langley95c29f32014-06-20 12:00:00 -07003697
David Benjamin861abcc2018-07-14 17:40:26 -04003698 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003699}
Adam Langley95c29f32014-06-20 12:00:00 -07003700
David Benjamine2cb4232021-06-23 18:14:22 -04003701static bool ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs,
David Benjamin861abcc2018-07-14 17:40:26 -04003702 int *out_alert) {
David Benjamine2cb4232021-06-23 18:14:22 -04003703 CBS extensions = *cbs;
3704 if (!tls1_check_duplicate_extensions(&extensions)) {
Steven Valdez143e8b32016-07-11 13:19:03 -04003705 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003706 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04003707 }
3708
3709 uint32_t received = 0;
3710 while (CBS_len(&extensions) != 0) {
3711 uint16_t type;
3712 CBS extension;
3713
David Benjaminc11ea9422017-08-29 16:33:21 -04003714 // Decode the next extension.
Steven Valdez143e8b32016-07-11 13:19:03 -04003715 if (!CBS_get_u16(&extensions, &type) ||
3716 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08003717 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003718 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003719 }
Adam Langley95c29f32014-06-20 12:00:00 -07003720
Steven Valdez143e8b32016-07-11 13:19:03 -04003721 unsigned ext_index;
3722 const struct tls_extension *const ext =
3723 tls_extension_find(&ext_index, type);
Adam Langley614c66a2015-06-12 15:26:58 -07003724
Steven Valdez143e8b32016-07-11 13:19:03 -04003725 if (ext == NULL) {
David Benjamin0a3e07a2018-07-09 16:28:22 -04003726 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
3727 ERR_add_error_dataf("extension %u", (unsigned)type);
3728 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
David Benjamin861abcc2018-07-14 17:40:26 -04003729 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04003730 }
Adam Langley33ad2b52015-07-20 17:43:53 -07003731
David Benjamina3d76d02017-07-14 19:36:07 -04003732 static_assert(kNumExtensions <= sizeof(hs->extensions.sent) * 8,
3733 "too many bits");
David Benjamin5db7c9b2017-01-24 16:17:03 -05003734
David Benjaminc59b9aa2018-07-16 21:34:03 -04003735 if (!(hs->extensions.sent & (1u << ext_index))) {
3736 // If the extension was never sent then it is illegal.
Steven Valdez143e8b32016-07-11 13:19:03 -04003737 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
3738 ERR_add_error_dataf("extension :%u", (unsigned)type);
David Benjamin0c40a962016-08-01 12:05:50 -04003739 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
David Benjamin861abcc2018-07-14 17:40:26 -04003740 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04003741 }
Adam Langley33ad2b52015-07-20 17:43:53 -07003742
Steven Valdez143e8b32016-07-11 13:19:03 -04003743 received |= (1u << ext_index);
Adam Langley09505632015-07-30 18:10:13 -07003744
Steven Valdez143e8b32016-07-11 13:19:03 -04003745 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003746 if (!ext->parse_serverhello(hs, &alert, &extension)) {
Steven Valdez143e8b32016-07-11 13:19:03 -04003747 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003748 ERR_add_error_dataf("extension %u", (unsigned)type);
Steven Valdez143e8b32016-07-11 13:19:03 -04003749 *out_alert = alert;
David Benjamin861abcc2018-07-14 17:40:26 -04003750 return false;
Adam Langley614c66a2015-06-12 15:26:58 -07003751 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003752 }
Adam Langley95c29f32014-06-20 12:00:00 -07003753
David Benjamin54091232016-09-05 12:47:25 -04003754 for (size_t i = 0; i < kNumExtensions; i++) {
Adam Langley614c66a2015-06-12 15:26:58 -07003755 if (!(received & (1u << i))) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003756 // Extension wasn't observed so call the callback with a NULL
3757 // parameter.
Adam Langley614c66a2015-06-12 15:26:58 -07003758 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003759 if (!kExtensions[i].parse_serverhello(hs, &alert, NULL)) {
Adam Langley33ad2b52015-07-20 17:43:53 -07003760 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003761 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
Adam Langley614c66a2015-06-12 15:26:58 -07003762 *out_alert = alert;
David Benjamin861abcc2018-07-14 17:40:26 -04003763 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003764 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003765 }
3766 }
Adam Langley95c29f32014-06-20 12:00:00 -07003767
David Benjamin861abcc2018-07-14 17:40:26 -04003768 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003769}
Adam Langley95c29f32014-06-20 12:00:00 -07003770
David Benjamin861abcc2018-07-14 17:40:26 -04003771static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) {
David Benjamin8c880a22016-12-03 02:20:34 -05003772 SSL *const ssl = hs->ssl;
Adam Langleyfcf25832014-12-18 17:42:32 -08003773 int ret = SSL_TLSEXT_ERR_NOACK;
3774 int al = SSL_AD_UNRECOGNIZED_NAME;
David Benjamin46853762018-07-03 14:01:26 -04003775 if (ssl->ctx->servername_callback != 0) {
3776 ret = ssl->ctx->servername_callback(ssl, &al, ssl->ctx->servername_arg);
3777 } else if (ssl->session_ctx->servername_callback != 0) {
3778 ret = ssl->session_ctx->servername_callback(
3779 ssl, &al, ssl->session_ctx->servername_arg);
Adam Langleyfcf25832014-12-18 17:42:32 -08003780 }
Adam Langley95c29f32014-06-20 12:00:00 -07003781
Adam Langleyfcf25832014-12-18 17:42:32 -08003782 switch (ret) {
3783 case SSL_TLSEXT_ERR_ALERT_FATAL:
David Benjamind1e3ce12017-10-06 18:31:15 -04003784 ssl_send_alert(ssl, SSL3_AL_FATAL, al);
David Benjamin861abcc2018-07-14 17:40:26 -04003785 return false;
Adam Langley95c29f32014-06-20 12:00:00 -07003786
Adam Langleyfcf25832014-12-18 17:42:32 -08003787 case SSL_TLSEXT_ERR_NOACK:
David Benjaminfd45ee72017-08-31 14:49:09 -04003788 hs->should_ack_sni = false;
David Benjamin861abcc2018-07-14 17:40:26 -04003789 return true;
Adam Langley95c29f32014-06-20 12:00:00 -07003790
Adam Langleyfcf25832014-12-18 17:42:32 -08003791 default:
David Benjamin861abcc2018-07-14 17:40:26 -04003792 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003793 }
3794}
Adam Langleyed8270a2014-09-02 13:52:56 -07003795
Steven Valdez51607f12020-08-05 10:46:05 -04003796static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs) {
3797 SSL *const ssl = hs->ssl;
3798 // ALPS and ALPN have a dependency between each other, so we defer checking
3799 // consistency to after the callbacks run.
3800 if (hs->new_session != nullptr && hs->new_session->has_application_settings) {
3801 // ALPN must be negotiated.
3802 if (ssl->s3->alpn_selected.empty()) {
3803 OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_ALPS_WITHOUT_ALPN);
3804 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
3805 return false;
3806 }
3807
3808 // The negotiated protocol must be one of the ones we advertised for ALPS.
3809 Span<const uint8_t> settings;
3810 if (!ssl_get_local_application_settings(hs, &settings,
3811 ssl->s3->alpn_selected)) {
3812 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
3813 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
3814 return false;
3815 }
3816
3817 if (!hs->new_session->local_application_settings.CopyFrom(settings)) {
3818 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
3819 return false;
3820 }
3821 }
3822
3823 return true;
3824}
3825
David Benjamine2cb4232021-06-23 18:14:22 -04003826bool ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs) {
David Benjamin8c880a22016-12-03 02:20:34 -05003827 SSL *const ssl = hs->ssl;
Adam Langleyc68e5b92017-02-08 13:33:15 -08003828 int alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003829 if (!ssl_scan_serverhello_tlsext(hs, cbs, &alert)) {
David Benjamind1e3ce12017-10-06 18:31:15 -04003830 ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
David Benjamin861abcc2018-07-14 17:40:26 -04003831 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003832 }
3833
Steven Valdez51607f12020-08-05 10:46:05 -04003834 if (!ssl_check_serverhello_tlsext(hs)) {
3835 return false;
3836 }
3837
David Benjamin861abcc2018-07-14 17:40:26 -04003838 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003839}
Adam Langley95c29f32014-06-20 12:00:00 -07003840
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003841static enum ssl_ticket_aead_result_t decrypt_ticket_with_cipher_ctx(
David Benjamin28655672018-07-18 23:23:25 -04003842 Array<uint8_t> *out, EVP_CIPHER_CTX *cipher_ctx, HMAC_CTX *hmac_ctx,
3843 Span<const uint8_t> ticket) {
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003844 size_t iv_len = EVP_CIPHER_CTX_iv_length(cipher_ctx);
Adam Langleyfcf25832014-12-18 17:42:32 -08003845
David Benjaminc11ea9422017-08-29 16:33:21 -04003846 // Check the MAC at the end of the ticket.
David Benjamine3aa1d92015-06-16 15:34:50 -04003847 uint8_t mac[EVP_MAX_MD_SIZE];
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003848 size_t mac_len = HMAC_size(hmac_ctx);
David Benjamin28655672018-07-18 23:23:25 -04003849 if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + iv_len + 1 + mac_len) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003850 // The ticket must be large enough for key name, IV, data, and MAC.
David Benjamin81678aa2017-07-12 22:43:42 -04003851 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003852 }
David Benjamin28655672018-07-18 23:23:25 -04003853 // Split the ticket into the ticket and the MAC.
David Benjamin006f20a2021-06-22 23:00:49 -04003854 auto ticket_mac = ticket.last(mac_len);
3855 ticket = ticket.first(ticket.size() - mac_len);
David Benjamin28655672018-07-18 23:23:25 -04003856 HMAC_Update(hmac_ctx, ticket.data(), ticket.size());
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003857 HMAC_Final(hmac_ctx, mac, NULL);
David Benjamin28655672018-07-18 23:23:25 -04003858 assert(mac_len == ticket_mac.size());
3859 bool mac_ok = CRYPTO_memcmp(mac, ticket_mac.data(), mac_len) == 0;
David Benjaminfbc45d72016-09-22 01:21:24 -04003860#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin861abcc2018-07-14 17:40:26 -04003861 mac_ok = true;
David Benjaminfbc45d72016-09-22 01:21:24 -04003862#endif
3863 if (!mac_ok) {
David Benjamin81678aa2017-07-12 22:43:42 -04003864 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003865 }
3866
David Benjaminc11ea9422017-08-29 16:33:21 -04003867 // Decrypt the session data.
David Benjamin28655672018-07-18 23:23:25 -04003868 auto ciphertext = ticket.subspan(SSL_TICKET_KEY_NAME_LEN + iv_len);
3869 Array<uint8_t> plaintext;
3870#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
3871 if (!plaintext.CopyFrom(ciphertext)) {
David Benjamin81678aa2017-07-12 22:43:42 -04003872 return ssl_ticket_aead_error;
Adam Langleyfcf25832014-12-18 17:42:32 -08003873 }
David Benjaminfbc45d72016-09-22 01:21:24 -04003874#else
David Benjamin28655672018-07-18 23:23:25 -04003875 if (ciphertext.size() >= INT_MAX) {
David Benjamin81678aa2017-07-12 22:43:42 -04003876 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003877 }
David Benjamin28655672018-07-18 23:23:25 -04003878 if (!plaintext.Init(ciphertext.size())) {
3879 return ssl_ticket_aead_error;
3880 }
David Benjamine3aa1d92015-06-16 15:34:50 -04003881 int len1, len2;
David Benjamin28655672018-07-18 23:23:25 -04003882 if (!EVP_DecryptUpdate(cipher_ctx, plaintext.data(), &len1, ciphertext.data(),
3883 (int)ciphertext.size()) ||
3884 !EVP_DecryptFinal_ex(cipher_ctx, plaintext.data() + len1, &len2)) {
Adam Langley4c341d02017-03-08 19:33:21 -08003885 ERR_clear_error();
David Benjamin81678aa2017-07-12 22:43:42 -04003886 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003887 }
David Benjamin28655672018-07-18 23:23:25 -04003888 plaintext.Shrink(static_cast<size_t>(len1) + len2);
David Benjaminfbc45d72016-09-22 01:21:24 -04003889#endif
Adam Langleyfcf25832014-12-18 17:42:32 -08003890
David Benjamin28655672018-07-18 23:23:25 -04003891 *out = std::move(plaintext);
David Benjamin81678aa2017-07-12 22:43:42 -04003892 return ssl_ticket_aead_success;
Adam Langley4c341d02017-03-08 19:33:21 -08003893}
3894
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003895static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_cb(
David Benjamin28655672018-07-18 23:23:25 -04003896 SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket,
3897 Span<const uint8_t> ticket) {
3898 assert(ticket.size() >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003899 ScopedEVP_CIPHER_CTX cipher_ctx;
3900 ScopedHMAC_CTX hmac_ctx;
David Benjamin28655672018-07-18 23:23:25 -04003901 auto name = ticket.subspan(0, SSL_TICKET_KEY_NAME_LEN);
3902 // The actual IV is shorter, but the length is determined by the callback's
3903 // chosen cipher. Instead we pass in |EVP_MAX_IV_LENGTH| worth of IV to ensure
3904 // the callback has enough.
3905 auto iv = ticket.subspan(SSL_TICKET_KEY_NAME_LEN, EVP_MAX_IV_LENGTH);
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003906 int cb_ret = hs->ssl->session_ctx->ticket_key_cb(
David Benjamin28655672018-07-18 23:23:25 -04003907 hs->ssl, const_cast<uint8_t *>(name.data()),
3908 const_cast<uint8_t *>(iv.data()), cipher_ctx.get(), hmac_ctx.get(),
3909 0 /* decrypt */);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003910 if (cb_ret < 0) {
3911 return ssl_ticket_aead_error;
3912 } else if (cb_ret == 0) {
3913 return ssl_ticket_aead_ignore_ticket;
3914 } else if (cb_ret == 2) {
David Benjaminfd45ee72017-08-31 14:49:09 -04003915 *out_renew_ticket = true;
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003916 } else {
3917 assert(cb_ret == 1);
3918 }
David Benjamin28655672018-07-18 23:23:25 -04003919 return decrypt_ticket_with_cipher_ctx(out, cipher_ctx.get(), hmac_ctx.get(),
3920 ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003921}
3922
3923static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_ticket_keys(
David Benjamin28655672018-07-18 23:23:25 -04003924 SSL_HANDSHAKE *hs, Array<uint8_t> *out, Span<const uint8_t> ticket) {
3925 assert(ticket.size() >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH);
David Benjamin50596f82018-07-02 19:47:27 -04003926 SSL_CTX *ctx = hs->ssl->session_ctx.get();
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003927
David Benjaminc11ea9422017-08-29 16:33:21 -04003928 // Rotate the ticket key if necessary.
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003929 if (!ssl_ctx_rotate_ticket_encryption_key(ctx)) {
3930 return ssl_ticket_aead_error;
3931 }
3932
David Benjamin28655672018-07-18 23:23:25 -04003933 const EVP_CIPHER *cipher = EVP_aes_128_cbc();
3934 auto name = ticket.subspan(0, SSL_TICKET_KEY_NAME_LEN);
3935 auto iv =
3936 ticket.subspan(SSL_TICKET_KEY_NAME_LEN, EVP_CIPHER_iv_length(cipher));
3937
David Benjaminc11ea9422017-08-29 16:33:21 -04003938 // Pick the matching ticket key and decrypt.
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003939 ScopedEVP_CIPHER_CTX cipher_ctx;
3940 ScopedHMAC_CTX hmac_ctx;
3941 {
3942 MutexReadLock lock(&ctx->lock);
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003943 const TicketKey *key;
David Benjamin28655672018-07-18 23:23:25 -04003944 if (ctx->ticket_key_current && name == ctx->ticket_key_current->name) {
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003945 key = ctx->ticket_key_current.get();
David Benjamin28655672018-07-18 23:23:25 -04003946 } else if (ctx->ticket_key_prev && name == ctx->ticket_key_prev->name) {
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003947 key = ctx->ticket_key_prev.get();
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003948 } else {
3949 return ssl_ticket_aead_ignore_ticket;
3950 }
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003951 if (!HMAC_Init_ex(hmac_ctx.get(), key->hmac_key, sizeof(key->hmac_key),
3952 tlsext_tick_md(), NULL) ||
David Benjamin28655672018-07-18 23:23:25 -04003953 !EVP_DecryptInit_ex(cipher_ctx.get(), cipher, NULL,
3954 key->aes_key, iv.data())) {
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003955 return ssl_ticket_aead_error;
3956 }
3957 }
David Benjamin28655672018-07-18 23:23:25 -04003958 return decrypt_ticket_with_cipher_ctx(out, cipher_ctx.get(), hmac_ctx.get(),
3959 ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003960}
3961
Adam Langley4c341d02017-03-08 19:33:21 -08003962static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_method(
David Benjamin28655672018-07-18 23:23:25 -04003963 SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket,
3964 Span<const uint8_t> ticket) {
3965 Array<uint8_t> plaintext;
3966 if (!plaintext.Init(ticket.size())) {
Adam Langley4c341d02017-03-08 19:33:21 -08003967 return ssl_ticket_aead_error;
3968 }
3969
3970 size_t plaintext_len;
3971 const enum ssl_ticket_aead_result_t result =
David Benjamin98472cb2018-05-02 16:05:36 -04003972 hs->ssl->session_ctx->ticket_aead_method->open(
David Benjamin28655672018-07-18 23:23:25 -04003973 hs->ssl, plaintext.data(), &plaintext_len, ticket.size(),
3974 ticket.data(), ticket.size());
3975 if (result != ssl_ticket_aead_success) {
3976 return result;
Adam Langley4c341d02017-03-08 19:33:21 -08003977 }
3978
David Benjamin28655672018-07-18 23:23:25 -04003979 plaintext.Shrink(plaintext_len);
3980 *out = std::move(plaintext);
3981 return ssl_ticket_aead_success;
Adam Langley4c341d02017-03-08 19:33:21 -08003982}
3983
3984enum ssl_ticket_aead_result_t ssl_process_ticket(
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07003985 SSL_HANDSHAKE *hs, UniquePtr<SSL_SESSION> *out_session,
David Benjamin28655672018-07-18 23:23:25 -04003986 bool *out_renew_ticket, Span<const uint8_t> ticket,
3987 Span<const uint8_t> session_id) {
David Benjaminb571e772021-03-25 19:42:16 -04003988 SSL *const ssl = hs->ssl;
David Benjaminfd45ee72017-08-31 14:49:09 -04003989 *out_renew_ticket = false;
David Benjamin37af90f2017-07-29 01:42:16 -04003990 out_session->reset();
Adam Langley4c341d02017-03-08 19:33:21 -08003991
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07003992 if ((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) ||
David Benjamin28655672018-07-18 23:23:25 -04003993 session_id.size() > SSL_MAX_SSL_SESSION_ID_LENGTH) {
Adam Langley4c341d02017-03-08 19:33:21 -08003994 return ssl_ticket_aead_ignore_ticket;
3995 }
3996
David Benjaminb571e772021-03-25 19:42:16 -04003997 // Tickets in TLS 1.3 are tied into pre-shared keys (PSKs), unlike in TLS 1.2
3998 // where that concept doesn't exist. The |decrypted_psk| and |ignore_psk|
3999 // hints only apply to PSKs. We check the version to determine which this is.
4000 const bool is_psk = ssl_protocol_version(ssl) >= TLS1_3_VERSION;
4001
David Benjamin28655672018-07-18 23:23:25 -04004002 Array<uint8_t> plaintext;
Adam Langley4c341d02017-03-08 19:33:21 -08004003 enum ssl_ticket_aead_result_t result;
David Benjaminb571e772021-03-25 19:42:16 -04004004 SSL_HANDSHAKE_HINTS *const hints = hs->hints.get();
4005 if (is_psk && hints && !hs->hints_requested &&
4006 !hints->decrypted_psk.empty()) {
4007 result = plaintext.CopyFrom(hints->decrypted_psk) ? ssl_ticket_aead_success
4008 : ssl_ticket_aead_error;
4009 } else if (is_psk && hints && !hs->hints_requested && hints->ignore_psk) {
4010 result = ssl_ticket_aead_ignore_ticket;
David Benjaminadaa3222022-08-02 17:10:53 -07004011 } else if (!is_psk && hints && !hs->hints_requested &&
4012 !hints->decrypted_ticket.empty()) {
4013 if (plaintext.CopyFrom(hints->decrypted_ticket)) {
4014 result = ssl_ticket_aead_success;
4015 *out_renew_ticket = hints->renew_ticket;
4016 } else {
4017 result = ssl_ticket_aead_error;
4018 }
4019 } else if (!is_psk && hints && !hs->hints_requested && hints->ignore_ticket) {
4020 result = ssl_ticket_aead_ignore_ticket;
David Benjaminb571e772021-03-25 19:42:16 -04004021 } else if (ssl->session_ctx->ticket_aead_method != NULL) {
David Benjamin28655672018-07-18 23:23:25 -04004022 result = ssl_decrypt_ticket_with_method(hs, &plaintext, out_renew_ticket,
4023 ticket);
Adam Langley4c341d02017-03-08 19:33:21 -08004024 } else {
David Benjamin7bb0fbf2018-07-03 13:55:42 -04004025 // Ensure there is room for the key name and the largest IV |ticket_key_cb|
4026 // may try to consume. The real limit may be lower, but the maximum IV
4027 // length should be well under the minimum size for the session material and
4028 // HMAC.
David Benjamin28655672018-07-18 23:23:25 -04004029 if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) {
David Benjaminb571e772021-03-25 19:42:16 -04004030 result = ssl_ticket_aead_ignore_ticket;
4031 } else if (ssl->session_ctx->ticket_key_cb != NULL) {
David Benjamin28655672018-07-18 23:23:25 -04004032 result =
4033 ssl_decrypt_ticket_with_cb(hs, &plaintext, out_renew_ticket, ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07004034 } else {
David Benjamin28655672018-07-18 23:23:25 -04004035 result = ssl_decrypt_ticket_with_ticket_keys(hs, &plaintext, ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07004036 }
Adam Langley4c341d02017-03-08 19:33:21 -08004037 }
4038
David Benjaminadaa3222022-08-02 17:10:53 -07004039 if (hints && hs->hints_requested) {
David Benjaminb571e772021-03-25 19:42:16 -04004040 if (result == ssl_ticket_aead_ignore_ticket) {
David Benjaminadaa3222022-08-02 17:10:53 -07004041 if (is_psk) {
4042 hints->ignore_psk = true;
4043 } else {
4044 hints->ignore_ticket = true;
4045 }
4046 } else if (result == ssl_ticket_aead_success) {
4047 if (is_psk) {
4048 if (!hints->decrypted_psk.CopyFrom(plaintext)) {
4049 return ssl_ticket_aead_error;
4050 }
4051 } else {
4052 if (!hints->decrypted_ticket.CopyFrom(plaintext)) {
4053 return ssl_ticket_aead_error;
4054 }
4055 hints->renew_ticket = *out_renew_ticket;
4056 }
David Benjaminb571e772021-03-25 19:42:16 -04004057 }
4058 }
4059
Adam Langley4c341d02017-03-08 19:33:21 -08004060 if (result != ssl_ticket_aead_success) {
4061 return result;
4062 }
4063
David Benjaminc11ea9422017-08-29 16:33:21 -04004064 // Decode the session.
David Benjamin28655672018-07-18 23:23:25 -04004065 UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(
David Benjaminb571e772021-03-25 19:42:16 -04004066 plaintext.data(), plaintext.size(), ssl->ctx.get()));
David Benjamin37af90f2017-07-29 01:42:16 -04004067 if (!session) {
David Benjaminc11ea9422017-08-29 16:33:21 -04004068 ERR_clear_error(); // Don't leave an error on the queue.
Adam Langley4c341d02017-03-08 19:33:21 -08004069 return ssl_ticket_aead_ignore_ticket;
David Benjamine3aa1d92015-06-16 15:34:50 -04004070 }
4071
Adam Langley47cefed2021-05-26 13:36:40 -07004072 // Envoy's tests expect the session to have a session ID that matches the
4073 // placeholder used by the client. It's unclear whether this is a good idea,
4074 // but we maintain it for now.
4075 SHA256(ticket.data(), ticket.size(), session->session_id);
4076 // Other consumers may expect a non-empty session ID to indicate resumption.
4077 session->session_id_length = SHA256_DIGEST_LENGTH;
David Benjamine3aa1d92015-06-16 15:34:50 -04004078
David Benjamin37af90f2017-07-29 01:42:16 -04004079 *out_session = std::move(session);
Adam Langley4c341d02017-03-08 19:33:21 -08004080 return ssl_ticket_aead_success;
Adam Langleyfcf25832014-12-18 17:42:32 -08004081}
Adam Langley95c29f32014-06-20 12:00:00 -07004082
David Benjamin610cdbb2018-01-22 19:08:38 -05004083bool tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) {
David Benjaminc11ea9422017-08-29 16:33:21 -04004084 // Extension ignored for inappropriate versions
David Benjamind1e3ce12017-10-06 18:31:15 -04004085 if (ssl_protocol_version(hs->ssl) < TLS1_2_VERSION) {
David Benjamin610cdbb2018-01-22 19:08:38 -05004086 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004087 }
David Benjamincd996942014-07-20 16:23:51 -04004088
David Benjamin602f4662018-12-07 12:06:22 -06004089 // In all contexts, the signature algorithms list may not be empty. (It may be
4090 // omitted by clients in TLS 1.2, but then the entire extension is omitted.)
4091 return CBS_len(in_sigalgs) != 0 &&
4092 parse_u16_array(in_sigalgs, &hs->peer_sigalgs);
Adam Langleyfcf25832014-12-18 17:42:32 -08004093}
David Benjaminec2f27d2014-11-13 19:17:25 -05004094
David Benjamin610cdbb2018-01-22 19:08:38 -05004095bool tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey) {
David Benjamina3651382017-04-20 17:49:36 -04004096 switch (EVP_PKEY_id(pkey)) {
4097 case EVP_PKEY_RSA:
4098 *out = SSL_SIGN_RSA_PKCS1_MD5_SHA1;
David Benjamin610cdbb2018-01-22 19:08:38 -05004099 return true;
David Benjamina3651382017-04-20 17:49:36 -04004100 case EVP_PKEY_EC:
4101 *out = SSL_SIGN_ECDSA_SHA1;
David Benjamin610cdbb2018-01-22 19:08:38 -05004102 return true;
David Benjamina3651382017-04-20 17:49:36 -04004103 default:
David Benjamin610cdbb2018-01-22 19:08:38 -05004104 return false;
David Benjamina3651382017-04-20 17:49:36 -04004105 }
4106}
4107
David Benjamin610cdbb2018-01-22 19:08:38 -05004108bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) {
David Benjaminf3c8f8d2016-11-17 17:20:47 +09004109 SSL *const ssl = hs->ssl;
David Benjamin0ce090a2018-07-02 20:24:40 -04004110 CERT *cert = hs->config->cert.get();
Christopher Patton6c1b3762018-07-17 12:49:41 -07004111 DC *dc = cert->dc.get();
David Benjaminec2f27d2014-11-13 19:17:25 -05004112
David Benjaminc11ea9422017-08-29 16:33:21 -04004113 // Before TLS 1.2, the signature algorithm isn't negotiated as part of the
4114 // handshake.
David Benjamind1e3ce12017-10-06 18:31:15 -04004115 if (ssl_protocol_version(ssl) < TLS1_2_VERSION) {
David Benjamin31b0c9b2017-07-20 14:49:15 -04004116 if (!tls1_get_legacy_signature_algorithm(out, hs->local_pubkey.get())) {
David Benjamina3651382017-04-20 17:49:36 -04004117 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
David Benjamin610cdbb2018-01-22 19:08:38 -05004118 return false;
Steven Valdezf0451ca2016-06-29 13:16:27 -04004119 }
David Benjamin610cdbb2018-01-22 19:08:38 -05004120 return true;
Steven Valdezf0451ca2016-06-29 13:16:27 -04004121 }
4122
David Benjaminb1cf48e2017-09-21 11:37:46 -04004123 Span<const uint16_t> sigalgs = kSignSignatureAlgorithms;
Christopher Patton6c1b3762018-07-17 12:49:41 -07004124 if (ssl_signing_with_dc(hs)) {
4125 sigalgs = MakeConstSpan(&dc->expected_cert_verify_algorithm, 1);
4126 } else if (!cert->sigalgs.empty()) {
David Benjamine325c3f2018-04-12 16:11:15 -04004127 sigalgs = cert->sigalgs;
Steven Valdez0d62f262015-09-04 12:41:04 -04004128 }
4129
Christopher Patton6c1b3762018-07-17 12:49:41 -07004130 Span<const uint16_t> peer_sigalgs = tls1_get_peer_verify_algorithms(hs);
David Benjaminea9a0d52016-07-08 15:52:59 -07004131
David Benjaminb1cf48e2017-09-21 11:37:46 -04004132 for (uint16_t sigalg : sigalgs) {
David Benjamine8f57ca2022-11-29 18:40:11 -05004133 if (!ssl_private_key_supports_signature_algorithm(hs, sigalg)) {
David Benjamin1fb125c2016-07-08 18:52:12 -07004134 continue;
4135 }
4136
David Benjaminb1cf48e2017-09-21 11:37:46 -04004137 for (uint16_t peer_sigalg : peer_sigalgs) {
4138 if (sigalg == peer_sigalg) {
David Benjamin1fb125c2016-07-08 18:52:12 -07004139 *out = sigalg;
David Benjamin610cdbb2018-01-22 19:08:38 -05004140 return true;
Steven Valdezf0451ca2016-06-29 13:16:27 -04004141 }
Adam Langleyfcf25832014-12-18 17:42:32 -08004142 }
Adam Langleyfcf25832014-12-18 17:42:32 -08004143 }
Adam Langley95c29f32014-06-20 12:00:00 -07004144
David Benjaminea9a0d52016-07-08 15:52:59 -07004145 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
David Benjamin610cdbb2018-01-22 19:08:38 -05004146 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08004147}
Adam Langley95c29f32014-06-20 12:00:00 -07004148
Christopher Patton6c1b3762018-07-17 12:49:41 -07004149Span<const uint16_t> tls1_get_peer_verify_algorithms(const SSL_HANDSHAKE *hs) {
4150 Span<const uint16_t> peer_sigalgs = hs->peer_sigalgs;
4151 if (peer_sigalgs.empty() && ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
4152 // If the client didn't specify any signature_algorithms extension then
4153 // we can assume that it supports SHA1. See
4154 // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
4155 static const uint16_t kDefaultPeerAlgorithms[] = {SSL_SIGN_RSA_PKCS1_SHA1,
4156 SSL_SIGN_ECDSA_SHA1};
4157 peer_sigalgs = kDefaultPeerAlgorithms;
4158 }
4159 return peer_sigalgs;
4160}
4161
David Benjamin861abcc2018-07-14 17:40:26 -04004162bool tls1_verify_channel_id(SSL_HANDSHAKE *hs, const SSLMessage &msg) {
Steven Valdez908ac192017-01-12 13:17:07 -05004163 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -04004164 // A Channel ID handshake message is structured to contain multiple
4165 // extensions, but the only one that can be present is Channel ID.
David Benjamin7934f082017-08-01 16:32:25 -04004166 uint16_t extension_type;
4167 CBS channel_id = msg.body, extension;
Nick Harper60a85cb2016-09-23 16:25:11 -07004168 if (!CBS_get_u16(&channel_id, &extension_type) ||
4169 !CBS_get_u16_length_prefixed(&channel_id, &extension) ||
4170 CBS_len(&channel_id) != 0 ||
4171 extension_type != TLSEXT_TYPE_channel_id ||
4172 CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
4173 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
David Benjamind1e3ce12017-10-06 18:31:15 -04004174 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04004175 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004176 }
4177
David Benjamin70be0122023-02-13 19:05:19 -05004178 const EC_GROUP *p256 = EC_group_p256();
David Benjamin86e95b82017-07-18 16:34:25 -04004179 UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
4180 UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
David Benjamin81678aa2017-07-12 22:43:42 -04004181 if (!sig || !x || !y) {
David Benjamin861abcc2018-07-14 17:40:26 -04004182 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004183 }
4184
4185 const uint8_t *p = CBS_data(&extension);
David Benjamin81678aa2017-07-12 22:43:42 -04004186 if (BN_bin2bn(p + 0, 32, x.get()) == NULL ||
4187 BN_bin2bn(p + 32, 32, y.get()) == NULL ||
4188 BN_bin2bn(p + 64, 32, sig->r) == NULL ||
4189 BN_bin2bn(p + 96, 32, sig->s) == NULL) {
David Benjamin861abcc2018-07-14 17:40:26 -04004190 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004191 }
4192
David Benjamin86e95b82017-07-18 16:34:25 -04004193 UniquePtr<EC_KEY> key(EC_KEY_new());
David Benjamin70be0122023-02-13 19:05:19 -05004194 UniquePtr<EC_POINT> point(EC_POINT_new(p256));
David Benjamin81678aa2017-07-12 22:43:42 -04004195 if (!key || !point ||
David Benjamin70be0122023-02-13 19:05:19 -05004196 !EC_POINT_set_affine_coordinates_GFp(p256, point.get(), x.get(), y.get(),
4197 nullptr) ||
4198 !EC_KEY_set_group(key.get(), p256) ||
David Benjamin81678aa2017-07-12 22:43:42 -04004199 !EC_KEY_set_public_key(key.get(), point.get())) {
David Benjamin861abcc2018-07-14 17:40:26 -04004200 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004201 }
4202
4203 uint8_t digest[EVP_MAX_MD_SIZE];
4204 size_t digest_len;
Steven Valdez908ac192017-01-12 13:17:07 -05004205 if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004206 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004207 }
4208
David Benjamin861abcc2018-07-14 17:40:26 -04004209 bool sig_ok = ECDSA_do_verify(digest, digest_len, sig.get(), key.get());
Nick Harper60a85cb2016-09-23 16:25:11 -07004210#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin861abcc2018-07-14 17:40:26 -04004211 sig_ok = true;
David Benjamind90b8032017-12-18 16:47:51 -05004212 ERR_clear_error();
Nick Harper60a85cb2016-09-23 16:25:11 -07004213#endif
4214 if (!sig_ok) {
4215 OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
David Benjamind1e3ce12017-10-06 18:31:15 -04004216 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04004217 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004218 }
4219
David Benjamin46853762018-07-03 14:01:26 -04004220 OPENSSL_memcpy(ssl->s3->channel_id, p, 64);
David Benjamin8acec002021-05-19 13:03:34 -04004221 ssl->s3->channel_id_valid = true;
David Benjamin861abcc2018-07-14 17:40:26 -04004222 return true;
Nick Harper60a85cb2016-09-23 16:25:11 -07004223}
4224
David Benjaminf1db1a32017-10-27 01:12:34 -04004225bool tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb) {
Nick Harper60a85cb2016-09-23 16:25:11 -07004226 uint8_t digest[EVP_MAX_MD_SIZE];
4227 size_t digest_len;
Steven Valdez908ac192017-01-12 13:17:07 -05004228 if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
David Benjaminf1db1a32017-10-27 01:12:34 -04004229 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004230 }
4231
David Benjamin46853762018-07-03 14:01:26 -04004232 EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(hs->config->channel_id_private.get());
David Benjaminf1db1a32017-10-27 01:12:34 -04004233 if (ec_key == nullptr) {
Nick Harper60a85cb2016-09-23 16:25:11 -07004234 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjaminf1db1a32017-10-27 01:12:34 -04004235 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004236 }
4237
David Benjaminf1db1a32017-10-27 01:12:34 -04004238 UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
4239 if (!x || !y ||
Nick Harper60a85cb2016-09-23 16:25:11 -07004240 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
4241 EC_KEY_get0_public_key(ec_key),
David Benjaminf1db1a32017-10-27 01:12:34 -04004242 x.get(), y.get(), nullptr)) {
4243 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004244 }
4245
David Benjaminf1db1a32017-10-27 01:12:34 -04004246 UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, ec_key));
4247 if (!sig) {
4248 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004249 }
4250
4251 CBB child;
4252 if (!CBB_add_u16(cbb, TLSEXT_TYPE_channel_id) ||
4253 !CBB_add_u16_length_prefixed(cbb, &child) ||
David Benjaminf1db1a32017-10-27 01:12:34 -04004254 !BN_bn2cbb_padded(&child, 32, x.get()) ||
4255 !BN_bn2cbb_padded(&child, 32, y.get()) ||
Nick Harper60a85cb2016-09-23 16:25:11 -07004256 !BN_bn2cbb_padded(&child, 32, sig->r) ||
4257 !BN_bn2cbb_padded(&child, 32, sig->s) ||
4258 !CBB_flush(cbb)) {
David Benjaminf1db1a32017-10-27 01:12:34 -04004259 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004260 }
4261
David Benjaminf1db1a32017-10-27 01:12:34 -04004262 return true;
Nick Harper60a85cb2016-09-23 16:25:11 -07004263}
4264
David Benjamin861abcc2018-07-14 17:40:26 -04004265bool tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len) {
Steven Valdez908ac192017-01-12 13:17:07 -05004266 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04004267 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin75a1f232017-10-11 17:19:19 -04004268 Array<uint8_t> msg;
4269 if (!tls13_get_cert_verify_signature_input(hs, &msg,
Nick Harper60a85cb2016-09-23 16:25:11 -07004270 ssl_cert_verify_channel_id)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004271 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004272 }
David Benjamin75a1f232017-10-11 17:19:19 -04004273 SHA256(msg.data(), msg.size(), out);
Nick Harper60a85cb2016-09-23 16:25:11 -07004274 *out_len = SHA256_DIGEST_LENGTH;
David Benjamin861abcc2018-07-14 17:40:26 -04004275 return true;
Nick Harper60a85cb2016-09-23 16:25:11 -07004276 }
4277
Nick Harper95594012016-10-20 14:07:13 -07004278 SHA256_CTX ctx;
Adam Langleyfcf25832014-12-18 17:42:32 -08004279
Nick Harper95594012016-10-20 14:07:13 -07004280 SHA256_Init(&ctx);
David Benjamind6a4ae92015-08-06 11:10:51 -04004281 static const char kClientIDMagic[] = "TLS Channel ID signature";
Nick Harper95594012016-10-20 14:07:13 -07004282 SHA256_Update(&ctx, kClientIDMagic, sizeof(kClientIDMagic));
David Benjamind6a4ae92015-08-06 11:10:51 -04004283
Steven Valdez87eab492016-06-27 16:34:59 -04004284 if (ssl->session != NULL) {
David Benjamind6a4ae92015-08-06 11:10:51 -04004285 static const char kResumptionMagic[] = "Resumption";
Nick Harper95594012016-10-20 14:07:13 -07004286 SHA256_Update(&ctx, kResumptionMagic, sizeof(kResumptionMagic));
David Benjamind6a4ae92015-08-06 11:10:51 -04004287 if (ssl->session->original_handshake_hash_len == 0) {
4288 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04004289 return false;
David Benjamind6a4ae92015-08-06 11:10:51 -04004290 }
Nick Harper95594012016-10-20 14:07:13 -07004291 SHA256_Update(&ctx, ssl->session->original_handshake_hash,
4292 ssl->session->original_handshake_hash_len);
David Benjamind6a4ae92015-08-06 11:10:51 -04004293 }
4294
Steven Valdez908ac192017-01-12 13:17:07 -05004295 uint8_t hs_hash[EVP_MAX_MD_SIZE];
4296 size_t hs_hash_len;
David Benjamin6dc8bf62017-07-19 16:38:21 -04004297 if (!hs->transcript.GetHash(hs_hash, &hs_hash_len)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004298 return false;
David Benjamind6a4ae92015-08-06 11:10:51 -04004299 }
Steven Valdez908ac192017-01-12 13:17:07 -05004300 SHA256_Update(&ctx, hs_hash, (size_t)hs_hash_len);
Nick Harper95594012016-10-20 14:07:13 -07004301 SHA256_Final(out, &ctx);
4302 *out_len = SHA256_DIGEST_LENGTH;
David Benjamin861abcc2018-07-14 17:40:26 -04004303 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004304}
Adam Langley1258b6a2014-06-20 12:00:00 -07004305
David Benjamin861abcc2018-07-14 17:40:26 -04004306bool tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) {
Steven Valdez908ac192017-01-12 13:17:07 -05004307 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -04004308 // This function should never be called for a resumed session because the
4309 // handshake hashes that we wish to record are for the original, full
4310 // handshake.
Steven Valdez87eab492016-06-27 16:34:59 -04004311 if (ssl->session != NULL) {
David Benjamin861abcc2018-07-14 17:40:26 -04004312 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08004313 }
Adam Langley1258b6a2014-06-20 12:00:00 -07004314
David Benjamina3d76d02017-07-14 19:36:07 -04004315 static_assert(
David Benjamin45738dd2017-02-09 20:01:26 -05004316 sizeof(hs->new_session->original_handshake_hash) == EVP_MAX_MD_SIZE,
David Benjamina3d76d02017-07-14 19:36:07 -04004317 "original_handshake_hash is too small");
Steven Valdez908ac192017-01-12 13:17:07 -05004318
4319 size_t digest_len;
David Benjamin6dc8bf62017-07-19 16:38:21 -04004320 if (!hs->transcript.GetHash(hs->new_session->original_handshake_hash,
4321 &digest_len)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004322 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08004323 }
Adam Langley1258b6a2014-06-20 12:00:00 -07004324
David Benjamina3d76d02017-07-14 19:36:07 -04004325 static_assert(EVP_MAX_MD_SIZE <= 0xff,
4326 "EVP_MAX_MD_SIZE does not fit in uint8_t");
David Benjamin45738dd2017-02-09 20:01:26 -05004327 hs->new_session->original_handshake_hash_len = (uint8_t)digest_len;
Adam Langley1258b6a2014-06-20 12:00:00 -07004328
David Benjamin861abcc2018-07-14 17:40:26 -04004329 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004330}
Nick Harper60a85cb2016-09-23 16:25:11 -07004331
David Benjamin861abcc2018-07-14 17:40:26 -04004332bool ssl_is_sct_list_valid(const CBS *contents) {
David Benjaminc11ea9422017-08-29 16:33:21 -04004333 // Shallow parse the SCT list for sanity. By the RFC
4334 // (https://tools.ietf.org/html/rfc6962#section-3.3) neither the list nor any
4335 // of the SCTs may be empty.
Adam Langleycfa08c32016-11-17 13:21:27 -08004336 CBS copy = *contents;
4337 CBS sct_list;
4338 if (!CBS_get_u16_length_prefixed(&copy, &sct_list) ||
4339 CBS_len(&copy) != 0 ||
4340 CBS_len(&sct_list) == 0) {
David Benjamin861abcc2018-07-14 17:40:26 -04004341 return false;
Adam Langleycfa08c32016-11-17 13:21:27 -08004342 }
4343
4344 while (CBS_len(&sct_list) > 0) {
4345 CBS sct;
4346 if (!CBS_get_u16_length_prefixed(&sct_list, &sct) ||
4347 CBS_len(&sct) == 0) {
David Benjamin861abcc2018-07-14 17:40:26 -04004348 return false;
Adam Langleycfa08c32016-11-17 13:21:27 -08004349 }
4350 }
4351
David Benjamin861abcc2018-07-14 17:40:26 -04004352 return true;
Adam Langleycfa08c32016-11-17 13:21:27 -08004353}
David Benjamin86e95b82017-07-18 16:34:25 -04004354
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -07004355BSSL_NAMESPACE_END
David Benjamin86e95b82017-07-18 16:34:25 -04004356
4357using namespace bssl;
4358
4359int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello,
4360 uint16_t extension_type,
4361 const uint8_t **out_data,
4362 size_t *out_len) {
4363 CBS cbs;
4364 if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) {
4365 return 0;
4366 }
4367
4368 *out_data = CBS_data(&cbs);
4369 *out_len = CBS_len(&cbs);
4370 return 1;
4371}