blob: 77e9d560b5e2bed5f5be36381205c0b93b3493dc [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;
David Benjamince572d62024-10-22 12:35:44 -0400178 if (!extension_types.InitForOverwrite(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:
David Benjamin7fb4d3d2024-08-23 15:27:03 -0400210 case SSL_GROUP_X25519_MLKEM768:
Adam Langleyfc077382023-01-08 16:22:31 -0800211 return true;
212 default:
213 return false;
214 }
Kris Kwiatkowski78c88c92019-03-11 14:40:59 +0000215}
216
Adam Langleyc9827e02019-04-12 14:46:50 -0700217bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out,
Daniel McArdle00e434d2021-02-18 11:47:18 -0500218 Span<const uint8_t> body) {
David Benjamin18b68362021-06-18 23:13:46 -0400219 CBS cbs = body;
220 if (!ssl_parse_client_hello_with_trailing_data(ssl, &cbs, out) ||
221 CBS_len(&cbs) != 0) {
222 return false;
223 }
224 return true;
225}
226
227bool ssl_parse_client_hello_with_trailing_data(const SSL *ssl, CBS *cbs,
228 SSL_CLIENT_HELLO *out) {
David Benjamin17cf2cb2016-12-13 01:07:13 -0500229 OPENSSL_memset(out, 0, sizeof(*out));
Adam Langleyc9827e02019-04-12 14:46:50 -0700230 out->ssl = const_cast<SSL *>(ssl);
David Benjamin8f2c20e2014-07-09 09:30:38 -0400231
David Benjamin18b68362021-06-18 23:13:46 -0400232 CBS copy = *cbs;
233 CBS random, session_id;
234 if (!CBS_get_u16(cbs, &out->version) ||
235 !CBS_get_bytes(cbs, &random, SSL3_RANDOM_SIZE) ||
236 !CBS_get_u8_length_prefixed(cbs, &session_id) ||
David Benjamine14ff062016-08-09 16:21:24 -0400237 CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
David Benjamin861abcc2018-07-14 17:40:26 -0400238 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800239 }
Adam Langleydc9b1412014-06-20 12:00:00 -0700240
David Benjamin731058e2016-12-03 23:15:13 -0500241 out->random = CBS_data(&random);
242 out->random_len = CBS_len(&random);
243 out->session_id = CBS_data(&session_id);
244 out->session_id_len = CBS_len(&session_id);
Adam Langleydc9b1412014-06-20 12:00:00 -0700245
David Benjaminc11ea9422017-08-29 16:33:21 -0400246 // Skip past DTLS cookie
David Benjamin731058e2016-12-03 23:15:13 -0500247 if (SSL_is_dtls(out->ssl)) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800248 CBS cookie;
David Benjamin361e3e02022-09-11 13:58:38 -0400249 if (!CBS_get_u8_length_prefixed(cbs, &cookie)) {
David Benjamin861abcc2018-07-14 17:40:26 -0400250 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800251 }
252 }
Adam Langleydc9b1412014-06-20 12:00:00 -0700253
David Benjamine14ff062016-08-09 16:21:24 -0400254 CBS cipher_suites, compression_methods;
David Benjamin18b68362021-06-18 23:13:46 -0400255 if (!CBS_get_u16_length_prefixed(cbs, &cipher_suites) ||
David Benjamine14ff062016-08-09 16:21:24 -0400256 CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0 ||
David Benjamin18b68362021-06-18 23:13:46 -0400257 !CBS_get_u8_length_prefixed(cbs, &compression_methods) ||
Adam Langleyfcf25832014-12-18 17:42:32 -0800258 CBS_len(&compression_methods) < 1) {
David Benjamin861abcc2018-07-14 17:40:26 -0400259 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800260 }
David Benjamine14ff062016-08-09 16:21:24 -0400261
David Benjamin731058e2016-12-03 23:15:13 -0500262 out->cipher_suites = CBS_data(&cipher_suites);
263 out->cipher_suites_len = CBS_len(&cipher_suites);
264 out->compression_methods = CBS_data(&compression_methods);
265 out->compression_methods_len = CBS_len(&compression_methods);
Adam Langleydc9b1412014-06-20 12:00:00 -0700266
David Benjaminc11ea9422017-08-29 16:33:21 -0400267 // If the ClientHello ends here then it's valid, but doesn't have any
David Benjamin9bb15f52018-06-26 00:07:40 -0400268 // extensions.
David Benjamin18b68362021-06-18 23:13:46 -0400269 if (CBS_len(cbs) == 0) {
270 out->extensions = nullptr;
David Benjamin731058e2016-12-03 23:15:13 -0500271 out->extensions_len = 0;
David Benjamin18b68362021-06-18 23:13:46 -0400272 } else {
273 // Extract extensions and check it is valid.
274 CBS extensions;
275 if (!CBS_get_u16_length_prefixed(cbs, &extensions) ||
276 !tls1_check_duplicate_extensions(&extensions)) {
277 return false;
278 }
279 out->extensions = CBS_data(&extensions);
280 out->extensions_len = CBS_len(&extensions);
Adam Langleyfcf25832014-12-18 17:42:32 -0800281 }
Adam Langleydc9b1412014-06-20 12:00:00 -0700282
David Benjamin18b68362021-06-18 23:13:46 -0400283 out->client_hello = CBS_data(&copy);
284 out->client_hello_len = CBS_len(&copy) - CBS_len(cbs);
David Benjamin861abcc2018-07-14 17:40:26 -0400285 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800286}
Adam Langleydc9b1412014-06-20 12:00:00 -0700287
David Benjamin861abcc2018-07-14 17:40:26 -0400288bool ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
289 CBS *out, uint16_t extension_type) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800290 CBS extensions;
David Benjamin731058e2016-12-03 23:15:13 -0500291 CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
Adam Langleyfcf25832014-12-18 17:42:32 -0800292 while (CBS_len(&extensions) != 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400293 // Decode the next extension.
Adam Langleyfcf25832014-12-18 17:42:32 -0800294 uint16_t type;
295 CBS extension;
Adam Langleyfcf25832014-12-18 17:42:32 -0800296 if (!CBS_get_u16(&extensions, &type) ||
297 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
David Benjamin861abcc2018-07-14 17:40:26 -0400298 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800299 }
Adam Langleydc9b1412014-06-20 12:00:00 -0700300
Adam Langleyfcf25832014-12-18 17:42:32 -0800301 if (type == extension_type) {
David Benjamincec73442016-08-02 17:41:33 -0400302 *out = extension;
David Benjamin861abcc2018-07-14 17:40:26 -0400303 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800304 }
305 }
Adam Langleydc9b1412014-06-20 12:00:00 -0700306
David Benjamin861abcc2018-07-14 17:40:26 -0400307 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800308}
Adam Langley95c29f32014-06-20 12:00:00 -0700309
Steven Valdezce902a92016-05-17 11:47:53 -0400310static const uint16_t kDefaultGroups[] = {
David Benjamin335523a2023-05-26 21:55:56 -0400311 SSL_GROUP_X25519,
312 SSL_GROUP_SECP256R1,
313 SSL_GROUP_SECP384R1,
Adam Langleyfcf25832014-12-18 17:42:32 -0800314};
Adam Langley95c29f32014-06-20 12:00:00 -0700315
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -0700316Span<const uint16_t> tls1_get_grouplist(const SSL_HANDSHAKE *hs) {
David Benjamin0ce090a2018-07-02 20:24:40 -0400317 if (!hs->config->supported_group_list.empty()) {
318 return hs->config->supported_group_list;
Adam Langleyfcf25832014-12-18 17:42:32 -0800319 }
David Benjamincf0ce672017-09-21 02:25:59 -0400320 return Span<const uint16_t>(kDefaultGroups);
Adam Langleyfcf25832014-12-18 17:42:32 -0800321}
David Benjamined439582014-07-14 19:13:02 -0400322
David Benjamin861abcc2018-07-14 17:40:26 -0400323bool tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) {
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900324 SSL *const ssl = hs->ssl;
David Benjaminf04976b2016-10-07 00:37:55 -0400325 assert(ssl->server);
David Benjamin072334d2014-07-13 16:24:27 -0400326
David Benjaminc11ea9422017-08-29 16:33:21 -0400327 // Clients are not required to send a supported_groups extension. In this
328 // case, the server is free to pick any group it likes. See RFC 4492,
329 // section 4, paragraph 3.
330 //
331 // However, in the interests of compatibility, we will skip ECDH if the
332 // client didn't send an extension because we can't be sure that they'll
333 // support our favoured group. Thus we do not special-case an emtpy
334 // |peer_supported_group_list|.
David Benjamin55a43642015-04-20 14:45:55 -0400335
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -0700336 Span<const uint16_t> groups = tls1_get_grouplist(hs);
David Benjamincf0ce672017-09-21 02:25:59 -0400337 Span<const uint16_t> pref, supp;
David Benjamin4298d772015-12-19 00:18:25 -0500338 if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
Steven Valdezce902a92016-05-17 11:47:53 -0400339 pref = groups;
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900340 supp = hs->peer_supported_group_list;
David Benjamin55a43642015-04-20 14:45:55 -0400341 } else {
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900342 pref = hs->peer_supported_group_list;
Steven Valdezce902a92016-05-17 11:47:53 -0400343 supp = groups;
David Benjamin55a43642015-04-20 14:45:55 -0400344 }
345
David Benjamincf0ce672017-09-21 02:25:59 -0400346 for (uint16_t pref_group : pref) {
347 for (uint16_t supp_group : supp) {
Adam Langley7b935932018-11-12 13:53:42 -0800348 if (pref_group == supp_group &&
Adam Langleyfc077382023-01-08 16:22:31 -0800349 // Post-quantum key agreements don't fit in the u8-length-prefixed
350 // ECPoint field in TLS 1.2 and below.
Adam Langley7b935932018-11-12 13:53:42 -0800351 (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
Kris Kwiatkowski78c88c92019-03-11 14:40:59 +0000352 !is_post_quantum_group(pref_group))) {
David Benjamincf0ce672017-09-21 02:25:59 -0400353 *out_group_id = pref_group;
David Benjamin861abcc2018-07-14 17:40:26 -0400354 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800355 }
356 }
357 }
358
David Benjamin861abcc2018-07-14 17:40:26 -0400359 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800360}
Adam Langley95c29f32014-06-20 12:00:00 -0700361
David Benjamin861abcc2018-07-14 17:40:26 -0400362bool tls1_check_group_id(const SSL_HANDSHAKE *hs, uint16_t group_id) {
Kris Kwiatkowski78c88c92019-03-11 14:40:59 +0000363 if (is_post_quantum_group(group_id) &&
Adam Langley7b935932018-11-12 13:53:42 -0800364 ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
Adam Langley4ae4fb72023-04-11 18:25:37 +0000365 // Post-quantum "groups" require TLS 1.3.
Adam Langley7b935932018-11-12 13:53:42 -0800366 return false;
367 }
368
David Benjamin97ede402021-05-18 14:17:52 -0400369 // We internally assume zero is never allocated as a group ID.
370 if (group_id == 0) {
371 return false;
372 }
373
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -0700374 for (uint16_t supported : tls1_get_grouplist(hs)) {
David Benjamincf0ce672017-09-21 02:25:59 -0400375 if (supported == group_id) {
David Benjamin861abcc2018-07-14 17:40:26 -0400376 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800377 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800378 }
David Benjamin033e5f42014-11-13 18:47:41 -0500379
David Benjamin861abcc2018-07-14 17:40:26 -0400380 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800381}
David Benjamin033e5f42014-11-13 18:47:41 -0500382
David Benjaminc11ea9422017-08-29 16:33:21 -0400383// kVerifySignatureAlgorithms is the default list of accepted signature
384// algorithms for verifying.
David Benjamin3ef76972016-10-17 17:59:54 -0400385static const uint16_t kVerifySignatureAlgorithms[] = {
David Benjaminc11ea9422017-08-29 16:33:21 -0400386 // List our preferred algorithms first.
David Benjamin3a322f52016-10-26 12:45:35 -0400387 SSL_SIGN_ECDSA_SECP256R1_SHA256,
David Benjamin6879e192018-04-13 16:01:02 -0400388 SSL_SIGN_RSA_PSS_RSAE_SHA256,
David Benjamin3a322f52016-10-26 12:45:35 -0400389 SSL_SIGN_RSA_PKCS1_SHA256,
390
David Benjaminc11ea9422017-08-29 16:33:21 -0400391 // Larger hashes are acceptable.
David Benjamin3a322f52016-10-26 12:45:35 -0400392 SSL_SIGN_ECDSA_SECP384R1_SHA384,
David Benjamin6879e192018-04-13 16:01:02 -0400393 SSL_SIGN_RSA_PSS_RSAE_SHA384,
David Benjamin3a322f52016-10-26 12:45:35 -0400394 SSL_SIGN_RSA_PKCS1_SHA384,
395
David Benjamin6879e192018-04-13 16:01:02 -0400396 SSL_SIGN_RSA_PSS_RSAE_SHA512,
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400397 SSL_SIGN_RSA_PKCS1_SHA512,
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400398
David Benjaminc11ea9422017-08-29 16:33:21 -0400399 // For now, SHA-1 is still accepted but least preferable.
David Benjamin3a322f52016-10-26 12:45:35 -0400400 SSL_SIGN_RSA_PKCS1_SHA1,
David Benjamin3a322f52016-10-26 12:45:35 -0400401};
402
David Benjaminc11ea9422017-08-29 16:33:21 -0400403// kSignSignatureAlgorithms is the default list of supported signature
404// algorithms for signing.
David Benjamin3a322f52016-10-26 12:45:35 -0400405static const uint16_t kSignSignatureAlgorithms[] = {
David Benjaminc11ea9422017-08-29 16:33:21 -0400406 // List our preferred algorithms first.
David Benjamin69522112017-03-28 15:38:29 -0500407 SSL_SIGN_ED25519,
David Benjamin3a322f52016-10-26 12:45:35 -0400408 SSL_SIGN_ECDSA_SECP256R1_SHA256,
David Benjamin6879e192018-04-13 16:01:02 -0400409 SSL_SIGN_RSA_PSS_RSAE_SHA256,
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400410 SSL_SIGN_RSA_PKCS1_SHA256,
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400411
David Benjaminc11ea9422017-08-29 16:33:21 -0400412 // If needed, sign larger hashes.
413 //
414 // TODO(davidben): Determine which of these may be pruned.
David Benjamin3a322f52016-10-26 12:45:35 -0400415 SSL_SIGN_ECDSA_SECP384R1_SHA384,
David Benjamin6879e192018-04-13 16:01:02 -0400416 SSL_SIGN_RSA_PSS_RSAE_SHA384,
David Benjamin3a322f52016-10-26 12:45:35 -0400417 SSL_SIGN_RSA_PKCS1_SHA384,
418
419 SSL_SIGN_ECDSA_SECP521R1_SHA512,
David Benjamin6879e192018-04-13 16:01:02 -0400420 SSL_SIGN_RSA_PSS_RSAE_SHA512,
David Benjamin3a322f52016-10-26 12:45:35 -0400421 SSL_SIGN_RSA_PKCS1_SHA512,
422
David Benjaminc11ea9422017-08-29 16:33:21 -0400423 // If the peer supports nothing else, sign with SHA-1.
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400424 SSL_SIGN_ECDSA_SHA1,
David Benjamin3a322f52016-10-26 12:45:35 -0400425 SSL_SIGN_RSA_PKCS1_SHA1,
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400426};
427
David Benjamin17669352020-02-05 17:33:36 -0500428static Span<const uint16_t> tls12_get_verify_sigalgs(const SSL_HANDSHAKE *hs) {
429 if (hs->config->verify_sigalgs.empty()) {
430 return Span<const uint16_t>(kVerifySignatureAlgorithms);
David Benjamin71c21b42017-04-14 17:05:40 -0400431 }
David Benjamin17669352020-02-05 17:33:36 -0500432 return hs->config->verify_sigalgs;
David Benjamine28552d2018-04-08 13:59:25 -0400433}
434
David Benjaminebad5082020-02-03 19:32:19 -0500435bool tls12_add_verify_sigalgs(const SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin17669352020-02-05 17:33:36 -0500436 for (uint16_t sigalg : tls12_get_verify_sigalgs(hs)) {
David Benjamin610cdbb2018-01-22 19:08:38 -0500437 if (!CBB_add_u16(out, sigalg)) {
438 return false;
David Benjamin69522112017-03-28 15:38:29 -0500439 }
440 }
David Benjamin610cdbb2018-01-22 19:08:38 -0500441 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800442}
Adam Langley95c29f32014-06-20 12:00:00 -0700443
David Benjaminebad5082020-02-03 19:32:19 -0500444bool tls12_check_peer_sigalg(const SSL_HANDSHAKE *hs, uint8_t *out_alert,
David Benjamine1d209d2024-04-17 11:57:44 -0400445 uint16_t sigalg, EVP_PKEY *pkey) {
446 // The peer must have selected an algorithm that is consistent with its public
447 // key, the TLS version, and what we advertised.
448 Span<const uint16_t> sigalgs = tls12_get_verify_sigalgs(hs);
449 if (std::find(sigalgs.begin(), sigalgs.end(), sigalg) == sigalgs.end() ||
David Benjamin66d274d2021-02-25 01:37:16 -0500450 !ssl_pkey_supports_algorithm(hs->ssl, pkey, sigalg, /*is_verify=*/true)) {
David Benjamine1d209d2024-04-17 11:57:44 -0400451 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
452 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
453 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800454 }
455
David Benjamine1d209d2024-04-17 11:57:44 -0400456 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800457}
458
David Benjamin52b36382021-05-19 13:26:19 -0400459// tls_extension represents a TLS extension that is handled internally.
David Benjaminc11ea9422017-08-29 16:33:21 -0400460//
461// The parse callbacks receive a |CBS| that contains the contents of the
462// extension (i.e. not including the type and length bytes). If an extension is
463// not received then the parse callbacks will be called with a NULL CBS so that
464// they can do any processing needed to handle the absence of an extension.
465//
466// The add callbacks receive a |CBB| to which the extension can be appended but
467// the function is responsible for appending the type and length bytes too.
David Benjamin83a49932021-05-20 15:57:09 -0400468//
469// |add_clienthello| may be called multiple times and must not mutate |hs|. It
470// is additionally passed two output |CBB|s. If the extension is the same
471// independent of the value of |type|, the callback may write to
472// |out_compressible| instead of |out|. When serializing the ClientHelloInner,
473// all compressible extensions will be made continguous and replaced with
474// ech_outer_extensions when encrypted. When serializing the ClientHelloOuter
475// or not offering ECH, |out| will be equal to |out_compressible|, so writing to
476// |out_compressible| still works.
David Benjaminc11ea9422017-08-29 16:33:21 -0400477//
David Benjamin90522862021-05-27 14:50:31 -0400478// Note the |parse_serverhello| and |add_serverhello| callbacks refer to the
479// TLS 1.2 ServerHello. In TLS 1.3, these callbacks act on EncryptedExtensions,
480// with ServerHello extensions handled elsewhere in the handshake.
481//
David Benjamin31640932017-10-11 13:22:39 -0400482// All callbacks return true for success and false for error. If a parse
483// function returns zero then a fatal alert with value |*out_alert| will be
484// sent. If |*out_alert| isn't set, then a |decode_error| alert will be sent.
Adam Langley614c66a2015-06-12 15:26:58 -0700485struct tls_extension {
486 uint16_t value;
Adam Langley614c66a2015-06-12 15:26:58 -0700487
David Benjamin83a49932021-05-20 15:57:09 -0400488 bool (*add_clienthello)(const SSL_HANDSHAKE *hs, CBB *out,
489 CBB *out_compressible, ssl_client_hello_type_t type);
David Benjamin31640932017-10-11 13:22:39 -0400490 bool (*parse_serverhello)(SSL_HANDSHAKE *hs, uint8_t *out_alert,
491 CBS *contents);
Adam Langley614c66a2015-06-12 15:26:58 -0700492
David Benjamin31640932017-10-11 13:22:39 -0400493 bool (*parse_clienthello)(SSL_HANDSHAKE *hs, uint8_t *out_alert,
494 CBS *contents);
495 bool (*add_serverhello)(SSL_HANDSHAKE *hs, CBB *out);
Adam Langley614c66a2015-06-12 15:26:58 -0700496};
497
David Benjamin31640932017-10-11 13:22:39 -0400498static bool forbid_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
Steven Valdez51607f12020-08-05 10:46:05 -0400499 CBS *contents) {
Steven Valdez6b8509a2016-07-12 13:38:32 -0400500 if (contents != NULL) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400501 // Servers MUST NOT send this extension.
Steven Valdez6b8509a2016-07-12 13:38:32 -0400502 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
503 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
David Benjamin31640932017-10-11 13:22:39 -0400504 return false;
Steven Valdez6b8509a2016-07-12 13:38:32 -0400505 }
506
David Benjamin31640932017-10-11 13:22:39 -0400507 return true;
Steven Valdez6b8509a2016-07-12 13:38:32 -0400508}
509
David Benjamin31640932017-10-11 13:22:39 -0400510static bool ignore_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
Steven Valdez51607f12020-08-05 10:46:05 -0400511 CBS *contents) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400512 // This extension from the client is handled elsewhere.
David Benjamin31640932017-10-11 13:22:39 -0400513 return true;
Steven Valdez6b8509a2016-07-12 13:38:32 -0400514}
515
Bob Beck61725ea2024-11-13 17:50:07 +0000516static bool dont_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { return true; }
Adam Langley614c66a2015-06-12 15:26:58 -0700517
David Benjaminc11ea9422017-08-29 16:33:21 -0400518// Server name indication (SNI).
519//
520// https://tools.ietf.org/html/rfc6066#section-3.
Adam Langley614c66a2015-06-12 15:26:58 -0700521
David Benjamin83a49932021-05-20 15:57:09 -0400522static bool ext_sni_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
523 CBB *out_compressible,
524 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -0400525 const SSL *const ssl = hs->ssl;
David Benjamin83a49932021-05-20 15:57:09 -0400526 // If offering ECH, send the public name instead of the configured name.
527 Span<const uint8_t> hostname;
528 if (type == ssl_client_hello_outer) {
529 hostname = hs->selected_ech_config->public_name;
530 } else {
531 if (ssl->hostname == nullptr) {
532 return true;
533 }
534 hostname =
535 MakeConstSpan(reinterpret_cast<const uint8_t *>(ssl->hostname.get()),
536 strlen(ssl->hostname.get()));
Adam Langley614c66a2015-06-12 15:26:58 -0700537 }
538
539 CBB contents, server_name_list, name;
540 if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) ||
541 !CBB_add_u16_length_prefixed(out, &contents) ||
542 !CBB_add_u16_length_prefixed(&contents, &server_name_list) ||
543 !CBB_add_u8(&server_name_list, TLSEXT_NAMETYPE_host_name) ||
544 !CBB_add_u16_length_prefixed(&server_name_list, &name) ||
David Benjamin83a49932021-05-20 15:57:09 -0400545 !CBB_add_bytes(&name, hostname.data(), hostname.size()) ||
Adam Langley614c66a2015-06-12 15:26:58 -0700546 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -0400547 return false;
Adam Langley614c66a2015-06-12 15:26:58 -0700548 }
549
David Benjamin31640932017-10-11 13:22:39 -0400550 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700551}
552
David Benjamin31640932017-10-11 13:22:39 -0400553static bool ext_sni_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
554 CBS *contents) {
David Benjamina8614602017-09-06 15:40:19 -0400555 // The server may acknowledge SNI with an empty extension. We check the syntax
556 // but otherwise ignore this signal.
557 return contents == NULL || CBS_len(contents) == 0;
Adam Langley614c66a2015-06-12 15:26:58 -0700558}
559
David Benjamin31640932017-10-11 13:22:39 -0400560static bool ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
561 CBS *contents) {
David Benjaminef0183c2019-07-20 09:11:05 -0400562 // SNI has already been parsed earlier in the handshake. See |extract_sni|.
David Benjamin31640932017-10-11 13:22:39 -0400563 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700564}
565
David Benjamin31640932017-10-11 13:22:39 -0400566static bool ext_sni_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
Bob Beck61725ea2024-11-13 17:50:07 +0000567 if (hs->ssl->s3->session_reused || //
David Benjamin8c880a22016-12-03 02:20:34 -0500568 !hs->should_ack_sni) {
David Benjamin31640932017-10-11 13:22:39 -0400569 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700570 }
571
572 if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) ||
573 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -0400574 return false;
Adam Langley614c66a2015-06-12 15:26:58 -0700575 }
576
David Benjamin31640932017-10-11 13:22:39 -0400577 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700578}
579
580
Daniel McArdle00e434d2021-02-18 11:47:18 -0500581// Encrypted ClientHello (ECH)
Dan McArdle1920c6f2020-03-11 17:29:40 -0400582//
David Benjamin18b68362021-06-18 23:13:46 -0400583// https://tools.ietf.org/html/draft-ietf-tls-esni-13
Dan McArdle1920c6f2020-03-11 17:29:40 -0400584
David Benjamin83a49932021-05-20 15:57:09 -0400585static bool ext_ech_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
586 CBB *out_compressible,
587 ssl_client_hello_type_t type) {
David Benjamin18b68362021-06-18 23:13:46 -0400588 if (type == ssl_client_hello_inner) {
589 if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
590 !CBB_add_u16(out, /* length */ 1) ||
591 !CBB_add_u8(out, ECH_CLIENT_INNER)) {
592 return false;
593 }
594 return true;
595 }
596
597 if (hs->ech_client_outer.empty()) {
Dan McArdle1920c6f2020-03-11 17:29:40 -0400598 return true;
599 }
600
David Benjamin83a49932021-05-20 15:57:09 -0400601 CBB ech_body;
602 if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
603 !CBB_add_u16_length_prefixed(out, &ech_body) ||
David Benjamin18b68362021-06-18 23:13:46 -0400604 !CBB_add_u8(&ech_body, ECH_CLIENT_OUTER) ||
605 !CBB_add_bytes(&ech_body, hs->ech_client_outer.data(),
606 hs->ech_client_outer.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -0400607 !CBB_flush(out)) {
Dan McArdle1920c6f2020-03-11 17:29:40 -0400608 return false;
609 }
David Benjamin246c5562021-05-20 13:42:25 -0400610 return true;
Dan McArdle1920c6f2020-03-11 17:29:40 -0400611}
612
Dan McArdle1920c6f2020-03-11 17:29:40 -0400613static bool ext_ech_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
614 CBS *contents) {
David Benjamin5b7ec832021-06-02 11:12:13 -0400615 SSL *const ssl = hs->ssl;
Dan McArdle1920c6f2020-03-11 17:29:40 -0400616 if (contents == NULL) {
617 return true;
618 }
619
David Benjamin5b7ec832021-06-02 11:12:13 -0400620 // The ECH extension may not be sent in TLS 1.2 ServerHello, only TLS 1.3
David Benjamin18b68362021-06-18 23:13:46 -0400621 // EncryptedExtensions. It also may not be sent in response to an inner ECH
622 // extension.
623 if (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
624 ssl->s3->ech_status == ssl_ech_accepted) {
David Benjamin5b7ec832021-06-02 11:12:13 -0400625 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
626 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
627 return false;
628 }
629
David Benjaminba423c92021-06-15 16:26:58 -0400630 if (!ssl_is_valid_ech_config_list(*contents)) {
631 *out_alert = SSL_AD_DECODE_ERROR;
632 return false;
633 }
634
David Benjamin18b68362021-06-18 23:13:46 -0400635 if (ssl->s3->ech_status == ssl_ech_rejected &&
David Benjaminba423c92021-06-15 16:26:58 -0400636 !hs->ech_retry_configs.CopyFrom(*contents)) {
637 *out_alert = SSL_AD_INTERNAL_ERROR;
Dan McArdle1920c6f2020-03-11 17:29:40 -0400638 return false;
639 }
David Benjaminba423c92021-06-15 16:26:58 -0400640
Dan McArdle1920c6f2020-03-11 17:29:40 -0400641 return true;
642}
643
Dan McArdlec2959352020-10-29 14:31:31 -0400644static bool ext_ech_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
645 CBS *contents) {
David Benjamin18b68362021-06-18 23:13:46 -0400646 if (contents == nullptr) {
Dan McArdlec2959352020-10-29 14:31:31 -0400647 return true;
648 }
David Benjamin18b68362021-06-18 23:13:46 -0400649
650 uint8_t type;
651 if (!CBS_get_u8(contents, &type)) {
652 return false;
653 }
654 if (type == ECH_CLIENT_OUTER) {
655 // Outer ECH extensions are handled outside the callback.
656 return true;
657 }
658 if (type != ECH_CLIENT_INNER || CBS_len(contents) != 0) {
659 return false;
660 }
661
662 hs->ech_is_inner = true;
Dan McArdlec2959352020-10-29 14:31:31 -0400663 return true;
664}
665
Daniel McArdle00e434d2021-02-18 11:47:18 -0500666static bool ext_ech_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
667 SSL *const ssl = hs->ssl;
David Benjaminba423c92021-06-15 16:26:58 -0400668 if (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
669 ssl->s3->ech_status == ssl_ech_accepted || //
David Benjaminc3b373b2021-06-06 13:04:26 -0400670 hs->ech_keys == nullptr) {
Daniel McArdle00e434d2021-02-18 11:47:18 -0500671 return true;
672 }
673
David Benjaminc3b373b2021-06-06 13:04:26 -0400674 // Write the list of retry configs to |out|. Note |SSL_CTX_set1_ech_keys|
675 // ensures |ech_keys| contains at least one retry config.
Daniel McArdle00e434d2021-02-18 11:47:18 -0500676 CBB body, retry_configs;
677 if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
678 !CBB_add_u16_length_prefixed(out, &body) ||
679 !CBB_add_u16_length_prefixed(&body, &retry_configs)) {
680 return false;
681 }
David Benjaminc3b373b2021-06-06 13:04:26 -0400682 for (const auto &config : hs->ech_keys->configs) {
David Benjamin1d58cd12021-05-04 15:24:24 -0400683 if (!config->is_retry_config()) {
Daniel McArdle00e434d2021-02-18 11:47:18 -0500684 continue;
685 }
David Benjamin83a49932021-05-20 15:57:09 -0400686 if (!CBB_add_bytes(&retry_configs, config->ech_config().raw.data(),
687 config->ech_config().raw.size())) {
Daniel McArdle00e434d2021-02-18 11:47:18 -0500688 return false;
689 }
690 }
691 return CBB_flush(out);
692}
693
Dan McArdle1920c6f2020-03-11 17:29:40 -0400694
David Benjaminc11ea9422017-08-29 16:33:21 -0400695// Renegotiation indication.
696//
697// https://tools.ietf.org/html/rfc5746
Adam Langley5021b222015-06-12 18:27:58 -0700698
David Benjamin83a49932021-05-20 15:57:09 -0400699static bool ext_ri_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
700 CBB *out_compressible,
701 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -0400702 const SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400703 // Renegotiation indication is not necessary in TLS 1.3.
Bob Beck61725ea2024-11-13 17:50:07 +0000704 if (hs->min_version >= TLS1_3_VERSION || //
705 type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -0400706 return true;
David Benjamin7c7d8312016-08-20 13:39:03 -0400707 }
708
David Benjamin52bf6902016-10-08 12:05:03 -0400709 assert(ssl->s3->initial_handshake_complete ==
David Benjamin87d0c172024-09-20 16:45:42 -0400710 !ssl->s3->previous_client_finished.empty());
David Benjamin52bf6902016-10-08 12:05:03 -0400711
Adam Langley5021b222015-06-12 18:27:58 -0700712 CBB contents, prev_finished;
713 if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
714 !CBB_add_u16_length_prefixed(out, &contents) ||
715 !CBB_add_u8_length_prefixed(&contents, &prev_finished) ||
David Benjamin87d0c172024-09-20 16:45:42 -0400716 !CBB_add_bytes(&prev_finished, ssl->s3->previous_client_finished.data(),
717 ssl->s3->previous_client_finished.size()) ||
Adam Langley5021b222015-06-12 18:27:58 -0700718 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -0400719 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700720 }
721
David Benjamin31640932017-10-11 13:22:39 -0400722 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700723}
724
David Benjamin31640932017-10-11 13:22:39 -0400725static bool ext_ri_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
726 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500727 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -0400728 if (contents != NULL && ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
Steven Valdez246eeee2017-03-26 12:49:17 -0500729 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -0400730 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -0400731 }
732
David Benjaminc11ea9422017-08-29 16:33:21 -0400733 // Servers may not switch between omitting the extension and supporting it.
734 // See RFC 5746, sections 3.5 and 4.2.
David Benjamin3e052de2015-11-25 20:10:31 -0500735 if (ssl->s3->initial_handshake_complete &&
736 (contents != NULL) != ssl->s3->send_connection_binding) {
737 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
738 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
David Benjamin31640932017-10-11 13:22:39 -0400739 return false;
David Benjamin3e052de2015-11-25 20:10:31 -0500740 }
741
Adam Langley5021b222015-06-12 18:27:58 -0700742 if (contents == NULL) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400743 // Strictly speaking, if we want to avoid an attack we should *always* see
744 // RI even on initial ServerHello because the client doesn't see any
745 // renegotiation during an attack. However this would mean we could not
746 // connect to any server which doesn't support RI.
747 //
748 // OpenSSL has |SSL_OP_LEGACY_SERVER_CONNECT| to control this, but in
749 // practical terms every client sets it so it's just assumed here.
David Benjamin31640932017-10-11 13:22:39 -0400750 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700751 }
752
David Benjamin87d0c172024-09-20 16:45:42 -0400753 // Check for logic errors.
754 assert(ssl->s3->previous_client_finished.size() ==
755 ssl->s3->previous_server_finished.size());
David Benjamin52bf6902016-10-08 12:05:03 -0400756 assert(ssl->s3->initial_handshake_complete ==
David Benjamin87d0c172024-09-20 16:45:42 -0400757 !ssl->s3->previous_client_finished.empty());
Adam Langley5021b222015-06-12 18:27:58 -0700758
David Benjaminc11ea9422017-08-29 16:33:21 -0400759 // Parse out the extension contents.
Adam Langley5021b222015-06-12 18:27:58 -0700760 CBS renegotiated_connection;
761 if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) ||
762 CBS_len(contents) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400763 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR);
Adam Langley5021b222015-06-12 18:27:58 -0700764 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -0400765 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700766 }
767
David Benjaminc11ea9422017-08-29 16:33:21 -0400768 // Check that the extension matches.
David Benjamin87d0c172024-09-20 16:45:42 -0400769 CBS client_verify, server_verify;
770 if (!CBS_get_bytes(&renegotiated_connection, &client_verify,
771 ssl->s3->previous_client_finished.size()) ||
772 !CBS_get_bytes(&renegotiated_connection, &server_verify,
773 ssl->s3->previous_server_finished.size()) ||
774 CBS_len(&renegotiated_connection) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400775 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
Adam Langley5021b222015-06-12 18:27:58 -0700776 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
David Benjamin31640932017-10-11 13:22:39 -0400777 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700778 }
779
David Benjamin87d0c172024-09-20 16:45:42 -0400780 bool ok =
781 CBS_mem_equal(&client_verify, ssl->s3->previous_client_finished.data(),
782 ssl->s3->previous_client_finished.size()) &&
783 CBS_mem_equal(&server_verify, ssl->s3->previous_server_finished.data(),
784 ssl->s3->previous_server_finished.size());
David Benjamin9343b0b2017-07-01 00:31:27 -0400785#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin31640932017-10-11 13:22:39 -0400786 ok = true;
David Benjamin9343b0b2017-07-01 00:31:27 -0400787#endif
788 if (!ok) {
David Benjamin3570d732015-06-29 00:28:17 -0400789 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
Adam Langley5021b222015-06-12 18:27:58 -0700790 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
David Benjamin31640932017-10-11 13:22:39 -0400791 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700792 }
Adam Langley5021b222015-06-12 18:27:58 -0700793
David Benjamin046bc1f2017-08-31 15:06:42 -0400794 ssl->s3->send_connection_binding = true;
David Benjamin31640932017-10-11 13:22:39 -0400795 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700796}
797
David Benjamin31640932017-10-11 13:22:39 -0400798static bool ext_ri_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
799 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500800 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400801 // Renegotiation isn't supported as a server so this function should never be
802 // called after the initial handshake.
Adam Langley5021b222015-06-12 18:27:58 -0700803 assert(!ssl->s3->initial_handshake_complete);
804
David Benjamind1e3ce12017-10-06 18:31:15 -0400805 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400806 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -0400807 }
808
Adam Langley5021b222015-06-12 18:27:58 -0700809 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -0400810 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700811 }
812
813 CBS renegotiated_connection;
Adam Langley5021b222015-06-12 18:27:58 -0700814 if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) ||
815 CBS_len(contents) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400816 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR);
David Benjamin31640932017-10-11 13:22:39 -0400817 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700818 }
819
David Benjaminc11ea9422017-08-29 16:33:21 -0400820 // Check that the extension matches. We do not support renegotiation as a
821 // server, so this must be empty.
David Benjamin52bf6902016-10-08 12:05:03 -0400822 if (CBS_len(&renegotiated_connection) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400823 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
Adam Langley5021b222015-06-12 18:27:58 -0700824 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
David Benjamin31640932017-10-11 13:22:39 -0400825 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700826 }
827
David Benjamin046bc1f2017-08-31 15:06:42 -0400828 ssl->s3->send_connection_binding = true;
Adam Langley5021b222015-06-12 18:27:58 -0700829
David Benjamin31640932017-10-11 13:22:39 -0400830 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700831}
832
David Benjamin31640932017-10-11 13:22:39 -0400833static bool ext_ri_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -0500834 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400835 // Renegotiation isn't supported as a server so this function should never be
836 // called after the initial handshake.
David Benjamin52bf6902016-10-08 12:05:03 -0400837 assert(!ssl->s3->initial_handshake_complete);
838
David Benjamind1e3ce12017-10-06 18:31:15 -0400839 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400840 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -0400841 }
842
Adam Langley5021b222015-06-12 18:27:58 -0700843 if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
David Benjamin52bf6902016-10-08 12:05:03 -0400844 !CBB_add_u16(out, 1 /* length */) ||
845 !CBB_add_u8(out, 0 /* empty renegotiation info */)) {
David Benjamin31640932017-10-11 13:22:39 -0400846 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700847 }
848
David Benjamin31640932017-10-11 13:22:39 -0400849 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700850}
851
Adam Langley0a056712015-07-01 15:03:33 -0700852
David Benjaminc11ea9422017-08-29 16:33:21 -0400853// Extended Master Secret.
854//
855// https://tools.ietf.org/html/rfc7627
Adam Langley0a056712015-07-01 15:03:33 -0700856
David Benjamin83a49932021-05-20 15:57:09 -0400857static bool ext_ems_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
858 CBB *out_compressible,
859 ssl_client_hello_type_t type) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400860 // Extended master secret is not necessary in TLS 1.3.
David Benjamin83a49932021-05-20 15:57:09 -0400861 if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -0400862 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700863 }
864
865 if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) ||
866 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -0400867 return false;
Adam Langley0a056712015-07-01 15:03:33 -0700868 }
869
David Benjamin31640932017-10-11 13:22:39 -0400870 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700871}
872
David Benjamin31640932017-10-11 13:22:39 -0400873static bool ext_ems_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
874 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500875 SSL *const ssl = hs->ssl;
David Benjaminfc02b592017-02-17 16:26:01 -0500876
877 if (contents != NULL) {
Bob Beck61725ea2024-11-13 17:50:07 +0000878 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION || //
David Benjaminfc02b592017-02-17 16:26:01 -0500879 CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -0400880 return false;
David Benjamin163c9562016-08-29 23:14:17 -0400881 }
882
David Benjaminfd45ee72017-08-31 14:49:09 -0400883 hs->extended_master_secret = true;
David Benjamin163c9562016-08-29 23:14:17 -0400884 }
885
David Benjaminc11ea9422017-08-29 16:33:21 -0400886 // Whether EMS is negotiated may not change on renegotiation.
David Benjamin8e7bbba2017-10-13 17:18:35 -0400887 if (ssl->s3->established_session != nullptr &&
David Benjaminfc02b592017-02-17 16:26:01 -0500888 hs->extended_master_secret !=
David Benjaminfd45ee72017-08-31 14:49:09 -0400889 !!ssl->s3->established_session->extended_master_secret) {
David Benjaminfc02b592017-02-17 16:26:01 -0500890 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_EMS_MISMATCH);
891 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -0400892 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -0400893 }
894
David Benjamin31640932017-10-11 13:22:39 -0400895 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700896}
897
David Benjamin31640932017-10-11 13:22:39 -0400898static bool ext_ems_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
899 CBS *contents) {
David Benjamin9bb15f52018-06-26 00:07:40 -0400900 if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400901 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -0400902 }
903
904 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -0400905 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700906 }
907
908 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -0400909 return false;
Adam Langley0a056712015-07-01 15:03:33 -0700910 }
911
David Benjaminfd45ee72017-08-31 14:49:09 -0400912 hs->extended_master_secret = true;
David Benjamin31640932017-10-11 13:22:39 -0400913 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700914}
915
David Benjamin31640932017-10-11 13:22:39 -0400916static bool ext_ems_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjaminfc02b592017-02-17 16:26:01 -0500917 if (!hs->extended_master_secret) {
David Benjamin31640932017-10-11 13:22:39 -0400918 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700919 }
920
921 if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) ||
922 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -0400923 return false;
Adam Langley0a056712015-07-01 15:03:33 -0700924 }
925
David Benjamin31640932017-10-11 13:22:39 -0400926 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700927}
928
Adam Langley9b05bc52015-07-01 15:25:33 -0700929
David Benjaminc11ea9422017-08-29 16:33:21 -0400930// Session tickets.
931//
932// https://tools.ietf.org/html/rfc5077
Adam Langley9b05bc52015-07-01 15:25:33 -0700933
David Benjamin83a49932021-05-20 15:57:09 -0400934static bool ext_ticket_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
935 CBB *out_compressible,
936 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -0400937 const SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400938 // TLS 1.3 uses a different ticket extension.
David Benjamin83a49932021-05-20 15:57:09 -0400939 if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner ||
David Benjamin7c7d8312016-08-20 13:39:03 -0400940 SSL_get_options(ssl) & SSL_OP_NO_TICKET) {
David Benjamin31640932017-10-11 13:22:39 -0400941 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700942 }
943
David Benjaminc11ea9422017-08-29 16:33:21 -0400944 // Renegotiation does not participate in session resumption. However, still
945 // advertise the extension to avoid potentially breaking servers which carry
946 // over the state from the previous handshake, such as OpenSSL servers
947 // without upstream's 3c3f0259238594d77264a78944d409f2127642c4.
David Benjamine6b800f2024-11-11 17:31:41 -0500948 Span<const uint8_t> ticket;
949 if (!ssl->s3->initial_handshake_complete && //
David Benjamin50596f82018-07-02 19:47:27 -0400950 ssl->session != nullptr &&
David Benjamine6b800f2024-11-11 17:31:41 -0500951 ssl_session_get_type(ssl->session.get()) == SSLSessionType::kTicket) {
David Benjaminbfdd1a92018-06-29 16:26:38 -0400952 ticket = ssl->session->ticket;
Adam Langley9b05bc52015-07-01 15:25:33 -0700953 }
954
David Benjaminbfdd1a92018-06-29 16:26:38 -0400955 CBB ticket_cbb;
Adam Langley9b05bc52015-07-01 15:25:33 -0700956 if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
David Benjaminbfdd1a92018-06-29 16:26:38 -0400957 !CBB_add_u16_length_prefixed(out, &ticket_cbb) ||
958 !CBB_add_bytes(&ticket_cbb, ticket.data(), ticket.size()) ||
Adam Langley9b05bc52015-07-01 15:25:33 -0700959 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -0400960 return false;
Adam Langley9b05bc52015-07-01 15:25:33 -0700961 }
962
David Benjamin31640932017-10-11 13:22:39 -0400963 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700964}
965
David Benjamin31640932017-10-11 13:22:39 -0400966static bool ext_ticket_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
967 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500968 SSL *const ssl = hs->ssl;
Adam Langley9b05bc52015-07-01 15:25:33 -0700969 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -0400970 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700971 }
972
David Benjamind1e3ce12017-10-06 18:31:15 -0400973 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400974 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -0400975 }
976
David Benjaminc11ea9422017-08-29 16:33:21 -0400977 // If |SSL_OP_NO_TICKET| is set then no extension will have been sent and
978 // this function should never be called, even if the server tries to send the
979 // extension.
Adam Langley9b05bc52015-07-01 15:25:33 -0700980 assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0);
981
982 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -0400983 return false;
Adam Langley9b05bc52015-07-01 15:25:33 -0700984 }
985
David Benjaminfd45ee72017-08-31 14:49:09 -0400986 hs->ticket_expected = true;
David Benjamin31640932017-10-11 13:22:39 -0400987 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700988}
989
David Benjamin31640932017-10-11 13:22:39 -0400990static bool ext_ticket_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -0500991 if (!hs->ticket_expected) {
David Benjamin31640932017-10-11 13:22:39 -0400992 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700993 }
994
David Benjaminc11ea9422017-08-29 16:33:21 -0400995 // If |SSL_OP_NO_TICKET| is set, |ticket_expected| should never be true.
David Benjamin8c880a22016-12-03 02:20:34 -0500996 assert((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) == 0);
Adam Langley9b05bc52015-07-01 15:25:33 -0700997
998 if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
999 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001000 return false;
Adam Langley9b05bc52015-07-01 15:25:33 -07001001 }
1002
David Benjamin31640932017-10-11 13:22:39 -04001003 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -07001004}
1005
1006
David Benjaminc11ea9422017-08-29 16:33:21 -04001007// Signature Algorithms.
1008//
1009// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
Adam Langley2e857bd2015-07-01 16:09:19 -07001010
David Benjamin83a49932021-05-20 15:57:09 -04001011static bool ext_sigalgs_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1012 CBB *out_compressible,
1013 ssl_client_hello_type_t type) {
David Benjamin68161cb2017-06-20 14:49:43 -04001014 if (hs->max_version < TLS1_2_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001015 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001016 }
1017
David Benjamin0fc37ef2016-08-17 15:29:46 -04001018 CBB contents, sigalgs_cbb;
David Benjamin83a49932021-05-20 15:57:09 -04001019 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_signature_algorithms) ||
1020 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
David Benjamin69522112017-03-28 15:38:29 -05001021 !CBB_add_u16_length_prefixed(&contents, &sigalgs_cbb) ||
David Benjaminebad5082020-02-03 19:32:19 -05001022 !tls12_add_verify_sigalgs(hs, &sigalgs_cbb) ||
David Benjamin83a49932021-05-20 15:57:09 -04001023 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001024 return false;
Adam Langley2e857bd2015-07-01 16:09:19 -07001025 }
1026
David Benjamin31640932017-10-11 13:22:39 -04001027 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001028}
1029
David Benjamin31640932017-10-11 13:22:39 -04001030static bool ext_sigalgs_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1031 CBS *contents) {
David Benjaminb1cf48e2017-09-21 11:37:46 -04001032 hs->peer_sigalgs.Reset();
Adam Langley2e857bd2015-07-01 16:09:19 -07001033 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001034 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001035 }
1036
1037 CBS supported_signature_algorithms;
1038 if (!CBS_get_u16_length_prefixed(contents, &supported_signature_algorithms) ||
Steven Valdez0d62f262015-09-04 12:41:04 -04001039 CBS_len(contents) != 0 ||
David Benjaminf3c8f8d2016-11-17 17:20:47 +09001040 !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
David Benjamin31640932017-10-11 13:22:39 -04001041 return false;
Adam Langley2e857bd2015-07-01 16:09:19 -07001042 }
1043
David Benjamin31640932017-10-11 13:22:39 -04001044 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001045}
1046
Adam Langley2e857bd2015-07-01 16:09:19 -07001047
David Benjaminc11ea9422017-08-29 16:33:21 -04001048// OCSP Stapling.
1049//
1050// https://tools.ietf.org/html/rfc6066#section-8
Adam Langleybb0bd042015-07-01 16:21:03 -07001051
David Benjamin83a49932021-05-20 15:57:09 -04001052static bool ext_ocsp_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1053 CBB *out_compressible,
1054 ssl_client_hello_type_t type) {
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001055 if (!hs->config->ocsp_stapling_enabled) {
David Benjamin31640932017-10-11 13:22:39 -04001056 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001057 }
1058
1059 CBB contents;
David Benjamin83a49932021-05-20 15:57:09 -04001060 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_status_request) ||
1061 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Adam Langleybb0bd042015-07-01 16:21:03 -07001062 !CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) ||
1063 !CBB_add_u16(&contents, 0 /* empty responder ID list */) ||
1064 !CBB_add_u16(&contents, 0 /* empty request extensions */) ||
David Benjamin83a49932021-05-20 15:57:09 -04001065 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001066 return false;
Adam Langleybb0bd042015-07-01 16:21:03 -07001067 }
1068
David Benjamin31640932017-10-11 13:22:39 -04001069 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001070}
1071
David Benjamin31640932017-10-11 13:22:39 -04001072static bool ext_ocsp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1073 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001074 SSL *const ssl = hs->ssl;
Adam Langleybb0bd042015-07-01 16:21:03 -07001075 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001076 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001077 }
1078
David Benjaminc11ea9422017-08-29 16:33:21 -04001079 // TLS 1.3 OCSP responses are included in the Certificate extensions.
David Benjamind1e3ce12017-10-06 18:31:15 -04001080 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001081 return false;
Steven Valdez803c77a2016-09-06 14:13:43 -04001082 }
1083
David Benjaminc11ea9422017-08-29 16:33:21 -04001084 // OCSP stapling is forbidden on non-certificate ciphers.
Steven Valdeza833c352016-11-01 13:39:36 -04001085 if (CBS_len(contents) != 0 ||
David Benjamin45738dd2017-02-09 20:01:26 -05001086 !ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
David Benjamin31640932017-10-11 13:22:39 -04001087 return false;
David Benjamin942f4ed2016-07-16 19:03:49 +03001088 }
1089
David Benjaminc11ea9422017-08-29 16:33:21 -04001090 // Note this does not check for resumption in TLS 1.2. Sending
1091 // status_request here does not make sense, but OpenSSL does so and the
1092 // specification does not say anything. Tolerate it but ignore it.
David Benjamin942f4ed2016-07-16 19:03:49 +03001093
David Benjaminfd45ee72017-08-31 14:49:09 -04001094 hs->certificate_status_expected = true;
David Benjamin31640932017-10-11 13:22:39 -04001095 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001096}
1097
David Benjamin31640932017-10-11 13:22:39 -04001098static bool ext_ocsp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1099 CBS *contents) {
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001100 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001101 return true;
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001102 }
1103
1104 uint8_t status_type;
1105 if (!CBS_get_u8(contents, &status_type)) {
David Benjamin31640932017-10-11 13:22:39 -04001106 return false;
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001107 }
1108
David Benjaminc11ea9422017-08-29 16:33:21 -04001109 // We cannot decide whether OCSP stapling will occur yet because the correct
1110 // SSL_CTX might not have been selected.
David Benjamin8c880a22016-12-03 02:20:34 -05001111 hs->ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp;
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001112
David Benjamin31640932017-10-11 13:22:39 -04001113 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001114}
1115
David Benjamin31640932017-10-11 13:22:39 -04001116static bool ext_ocsp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001117 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04001118 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
David Benjamin4fa48042024-03-12 09:48:29 -04001119 !hs->ocsp_stapling_requested || ssl->s3->session_reused ||
1120 !ssl_cipher_uses_certificate_auth(hs->new_cipher) ||
1121 hs->credential->ocsp_response == nullptr) {
David Benjamin31640932017-10-11 13:22:39 -04001122 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001123 }
1124
David Benjaminfd45ee72017-08-31 14:49:09 -04001125 hs->certificate_status_expected = true;
David Benjamin942f4ed2016-07-16 19:03:49 +03001126
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001127 return CBB_add_u16(out, TLSEXT_TYPE_status_request) &&
Steven Valdeza833c352016-11-01 13:39:36 -04001128 CBB_add_u16(out, 0 /* length */);
Adam Langleybb0bd042015-07-01 16:21:03 -07001129}
1130
1131
David Benjaminc11ea9422017-08-29 16:33:21 -04001132// Next protocol negotiation.
1133//
1134// https://htmlpreview.github.io/?https://github.com/agl/technotes/blob/master/nextprotoneg.html
Adam Langley97dfcbf2015-07-01 18:35:20 -07001135
David Benjamin83a49932021-05-20 15:57:09 -04001136static bool ext_npn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1137 CBB *out_compressible,
1138 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001139 const SSL *const ssl = hs->ssl;
David Benjamin83a49932021-05-20 15:57:09 -04001140 if (ssl->ctx->next_proto_select_cb == NULL ||
1141 // Do not allow NPN to change on renegotiation.
1142 ssl->s3->initial_handshake_complete ||
1143 // NPN is not defined in DTLS or TLS 1.3.
1144 SSL_is_dtls(ssl) || hs->min_version >= TLS1_3_VERSION ||
1145 type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -04001146 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001147 }
1148
1149 if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) ||
1150 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001151 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001152 }
1153
David Benjamin31640932017-10-11 13:22:39 -04001154 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001155}
1156
David Benjamin31640932017-10-11 13:22:39 -04001157static bool ext_npn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1158 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001159 SSL *const ssl = hs->ssl;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001160 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001161 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001162 }
1163
David Benjamind1e3ce12017-10-06 18:31:15 -04001164 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001165 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04001166 }
1167
David Benjaminc11ea9422017-08-29 16:33:21 -04001168 // If any of these are false then we should never have sent the NPN
1169 // extension in the ClientHello and thus this function should never have been
1170 // called.
Adam Langley97dfcbf2015-07-01 18:35:20 -07001171 assert(!ssl->s3->initial_handshake_complete);
David Benjamince079fd2016-08-02 16:22:34 -04001172 assert(!SSL_is_dtls(ssl));
Adam Langley97dfcbf2015-07-01 18:35:20 -07001173 assert(ssl->ctx->next_proto_select_cb != NULL);
1174
David Benjamin8e7bbba2017-10-13 17:18:35 -04001175 if (!ssl->s3->alpn_selected.empty()) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001176 // NPN and ALPN may not be negotiated in the same connection.
David Benjamin76c2efc2015-08-31 14:24:29 -04001177 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1178 OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
David Benjamin31640932017-10-11 13:22:39 -04001179 return false;
David Benjamin76c2efc2015-08-31 14:24:29 -04001180 }
1181
Adam Langley97dfcbf2015-07-01 18:35:20 -07001182 const uint8_t *const orig_contents = CBS_data(contents);
1183 const size_t orig_len = CBS_len(contents);
1184
1185 while (CBS_len(contents) != 0) {
1186 CBS proto;
Bob Beck61725ea2024-11-13 17:50:07 +00001187 if (!CBS_get_u8_length_prefixed(contents, &proto) || //
Adam Langley97dfcbf2015-07-01 18:35:20 -07001188 CBS_len(&proto) == 0) {
David Benjamin31640932017-10-11 13:22:39 -04001189 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001190 }
1191 }
1192
David Benjamin9d64d8d2022-08-31 19:27:56 -04001193 // |orig_len| fits in |unsigned| because TLS extensions use 16-bit lengths.
Adam Langley97dfcbf2015-07-01 18:35:20 -07001194 uint8_t *selected;
1195 uint8_t selected_len;
1196 if (ssl->ctx->next_proto_select_cb(
David Benjamin9d64d8d2022-08-31 19:27:56 -04001197 ssl, &selected, &selected_len, orig_contents,
1198 static_cast<unsigned>(orig_len),
David Benjamin8e7bbba2017-10-13 17:18:35 -04001199 ssl->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK ||
1200 !ssl->s3->next_proto_negotiated.CopyFrom(
1201 MakeConstSpan(selected, selected_len))) {
Adam Langley97dfcbf2015-07-01 18:35:20 -07001202 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001203 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001204 }
1205
David Benjaminfd45ee72017-08-31 14:49:09 -04001206 hs->next_proto_neg_seen = true;
David Benjamin31640932017-10-11 13:22:39 -04001207 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001208}
1209
David Benjamin31640932017-10-11 13:22:39 -04001210static bool ext_npn_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1211 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001212 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04001213 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001214 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001215 }
1216
Adam Langley97dfcbf2015-07-01 18:35:20 -07001217 if (contents != NULL && CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001218 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001219 }
1220
Bob Beck61725ea2024-11-13 17:50:07 +00001221 if (contents == NULL || //
1222 ssl->s3->initial_handshake_complete || //
1223 ssl->ctx->next_protos_advertised_cb == NULL || //
David Benjamince079fd2016-08-02 16:22:34 -04001224 SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001225 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001226 }
1227
David Benjaminfd45ee72017-08-31 14:49:09 -04001228 hs->next_proto_neg_seen = true;
David Benjamin31640932017-10-11 13:22:39 -04001229 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001230}
1231
David Benjamin31640932017-10-11 13:22:39 -04001232static bool ext_npn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001233 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -04001234 // |next_proto_neg_seen| might have been cleared when an ALPN extension was
1235 // parsed.
David Benjamin8c880a22016-12-03 02:20:34 -05001236 if (!hs->next_proto_neg_seen) {
David Benjamin31640932017-10-11 13:22:39 -04001237 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001238 }
1239
1240 const uint8_t *npa;
1241 unsigned npa_len;
1242
1243 if (ssl->ctx->next_protos_advertised_cb(
1244 ssl, &npa, &npa_len, ssl->ctx->next_protos_advertised_cb_arg) !=
1245 SSL_TLSEXT_ERR_OK) {
David Benjaminfd45ee72017-08-31 14:49:09 -04001246 hs->next_proto_neg_seen = false;
David Benjamin31640932017-10-11 13:22:39 -04001247 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001248 }
1249
1250 CBB contents;
Bob Beck61725ea2024-11-13 17:50:07 +00001251 if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) || //
1252 !CBB_add_u16_length_prefixed(out, &contents) || //
1253 !CBB_add_bytes(&contents, npa, npa_len) || //
Adam Langley97dfcbf2015-07-01 18:35:20 -07001254 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001255 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001256 }
1257
David Benjamin31640932017-10-11 13:22:39 -04001258 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001259}
1260
1261
David Benjaminc11ea9422017-08-29 16:33:21 -04001262// Signed certificate timestamps.
1263//
1264// https://tools.ietf.org/html/rfc6962#section-3.3.1
Adam Langleyab8d87d2015-07-10 12:21:39 -07001265
David Benjamin83a49932021-05-20 15:57:09 -04001266static bool ext_sct_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1267 CBB *out_compressible,
1268 ssl_client_hello_type_t type) {
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001269 if (!hs->config->signed_cert_timestamps_enabled) {
David Benjamin31640932017-10-11 13:22:39 -04001270 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001271 }
1272
David Benjamin83a49932021-05-20 15:57:09 -04001273 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_certificate_timestamp) ||
1274 !CBB_add_u16(out_compressible, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001275 return false;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001276 }
1277
David Benjamin31640932017-10-11 13:22:39 -04001278 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001279}
1280
David Benjamin31640932017-10-11 13:22:39 -04001281static bool ext_sct_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1282 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001283 SSL *const ssl = hs->ssl;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001284 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001285 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001286 }
1287
David Benjaminc11ea9422017-08-29 16:33:21 -04001288 // TLS 1.3 SCTs are included in the Certificate extensions.
David Benjamind1e3ce12017-10-06 18:31:15 -04001289 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
Adam Langleycfa08c32016-11-17 13:21:27 -08001290 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001291 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04001292 }
1293
David Benjaminc11ea9422017-08-29 16:33:21 -04001294 // If this is false then we should never have sent the SCT extension in the
1295 // ClientHello and thus this function should never have been called.
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001296 assert(hs->config->signed_cert_timestamps_enabled);
Adam Langleyab8d87d2015-07-10 12:21:39 -07001297
Adam Langleycfa08c32016-11-17 13:21:27 -08001298 if (!ssl_is_sct_list_valid(contents)) {
Adam Langleyab8d87d2015-07-10 12:21:39 -07001299 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001300 return false;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001301 }
1302
David Benjaminc11ea9422017-08-29 16:33:21 -04001303 // Session resumption uses the original session information. The extension
1304 // should not be sent on resumption, but RFC 6962 did not make it a
1305 // requirement, so tolerate this.
1306 //
1307 // TODO(davidben): Enforce this anyway.
David Benjamin8fc2dc02017-08-22 15:07:51 -07001308 if (!ssl->s3->session_reused) {
David Benjaminbfdd1a92018-06-29 16:26:38 -04001309 hs->new_session->signed_cert_timestamp_list.reset(
1310 CRYPTO_BUFFER_new_from_CBS(contents, ssl->ctx->pool));
David Benjamin8fc2dc02017-08-22 15:07:51 -07001311 if (hs->new_session->signed_cert_timestamp_list == nullptr) {
1312 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001313 return false;
David Benjamin8fc2dc02017-08-22 15:07:51 -07001314 }
Adam Langleyab8d87d2015-07-10 12:21:39 -07001315 }
1316
David Benjamin31640932017-10-11 13:22:39 -04001317 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001318}
1319
David Benjamin31640932017-10-11 13:22:39 -04001320static bool ext_sct_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1321 CBS *contents) {
David Benjamin53210cb2016-11-16 09:01:48 +09001322 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001323 return true;
David Benjamin53210cb2016-11-16 09:01:48 +09001324 }
1325
1326 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001327 return false;
David Benjamin53210cb2016-11-16 09:01:48 +09001328 }
1329
David Benjaminfd45ee72017-08-31 14:49:09 -04001330 hs->scts_requested = true;
David Benjamin31640932017-10-11 13:22:39 -04001331 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001332}
1333
David Benjamin31640932017-10-11 13:22:39 -04001334static bool ext_sct_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001335 SSL *const ssl = hs->ssl;
David Benjamin4fa48042024-03-12 09:48:29 -04001336 assert(hs->scts_requested);
David Benjaminc11ea9422017-08-29 16:33:21 -04001337 // The extension shouldn't be sent when resuming sessions.
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001338 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION || ssl->s3->session_reused ||
David Benjamin4fa48042024-03-12 09:48:29 -04001339 !ssl_cipher_uses_certificate_auth(hs->new_cipher) ||
David Benjamin91a3f262024-02-10 11:08:08 -05001340 hs->credential->signed_cert_timestamp_list == nullptr) {
David Benjamin31640932017-10-11 13:22:39 -04001341 return true;
Paul Lietar4fac72e2015-09-09 13:44:55 +01001342 }
1343
1344 CBB contents;
1345 return CBB_add_u16(out, TLSEXT_TYPE_certificate_timestamp) &&
1346 CBB_add_u16_length_prefixed(out, &contents) &&
David Benjamin91a3f262024-02-10 11:08:08 -05001347 CBB_add_bytes(&contents,
1348 CRYPTO_BUFFER_data(
1349 hs->credential->signed_cert_timestamp_list.get()),
1350 CRYPTO_BUFFER_len(
1351 hs->credential->signed_cert_timestamp_list.get())) &&
Paul Lietar4fac72e2015-09-09 13:44:55 +01001352 CBB_flush(out);
Adam Langleyab8d87d2015-07-10 12:21:39 -07001353}
1354
1355
David Benjaminc11ea9422017-08-29 16:33:21 -04001356// Application-level Protocol Negotiation.
1357//
1358// https://tools.ietf.org/html/rfc7301
Adam Langleyf18e4532015-07-10 13:39:53 -07001359
David Benjamin83a49932021-05-20 15:57:09 -04001360static bool ext_alpn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1361 CBB *out_compressible,
1362 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001363 const SSL *const ssl = hs->ssl;
Nick Harper74161f42020-07-24 15:35:27 -07001364 if (hs->config->alpn_client_proto_list.empty() && ssl->quic_method) {
1365 // ALPN MUST be used with QUIC.
David Benjaminc02c19e2021-02-10 17:49:20 -05001366 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
Nick Harper74161f42020-07-24 15:35:27 -07001367 return false;
1368 }
1369
David Benjamin0ce090a2018-07-02 20:24:40 -04001370 if (hs->config->alpn_client_proto_list.empty() ||
Adam Langleyf18e4532015-07-10 13:39:53 -07001371 ssl->s3->initial_handshake_complete) {
David Benjamin31640932017-10-11 13:22:39 -04001372 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001373 }
1374
1375 CBB contents, proto_list;
David Benjamin83a49932021-05-20 15:57:09 -04001376 if (!CBB_add_u16(out_compressible,
1377 TLSEXT_TYPE_application_layer_protocol_negotiation) ||
1378 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Adam Langleyf18e4532015-07-10 13:39:53 -07001379 !CBB_add_u16_length_prefixed(&contents, &proto_list) ||
David Benjamin0ce090a2018-07-02 20:24:40 -04001380 !CBB_add_bytes(&proto_list, hs->config->alpn_client_proto_list.data(),
1381 hs->config->alpn_client_proto_list.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -04001382 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001383 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001384 }
1385
David Benjamin31640932017-10-11 13:22:39 -04001386 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001387}
1388
David Benjamin31640932017-10-11 13:22:39 -04001389static bool ext_alpn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1390 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001391 SSL *const ssl = hs->ssl;
Adam Langleyf18e4532015-07-10 13:39:53 -07001392 if (contents == NULL) {
Nick Harper74161f42020-07-24 15:35:27 -07001393 if (ssl->quic_method) {
1394 // ALPN is required when QUIC is used.
David Benjaminc02c19e2021-02-10 17:49:20 -05001395 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
Nick Harper74161f42020-07-24 15:35:27 -07001396 *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1397 return false;
1398 }
David Benjamin31640932017-10-11 13:22:39 -04001399 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001400 }
1401
1402 assert(!ssl->s3->initial_handshake_complete);
David Benjamin0ce090a2018-07-02 20:24:40 -04001403 assert(!hs->config->alpn_client_proto_list.empty());
Adam Langleyf18e4532015-07-10 13:39:53 -07001404
David Benjamin8c880a22016-12-03 02:20:34 -05001405 if (hs->next_proto_neg_seen) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001406 // NPN and ALPN may not be negotiated in the same connection.
David Benjamin76c2efc2015-08-31 14:24:29 -04001407 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1408 OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
David Benjamin31640932017-10-11 13:22:39 -04001409 return false;
David Benjamin76c2efc2015-08-31 14:24:29 -04001410 }
1411
David Benjaminc11ea9422017-08-29 16:33:21 -04001412 // The extension data consists of a ProtocolNameList which must have
1413 // exactly one ProtocolName. Each of these is length-prefixed.
Adam Langleyf18e4532015-07-10 13:39:53 -07001414 CBS protocol_name_list, protocol_name;
Bob Beck61725ea2024-11-13 17:50:07 +00001415 if (!CBS_get_u16_length_prefixed(contents, &protocol_name_list) || //
1416 CBS_len(contents) != 0 || //
1417 !CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) || //
David Benjaminc11ea9422017-08-29 16:33:21 -04001418 // Empty protocol names are forbidden.
Bob Beck61725ea2024-11-13 17:50:07 +00001419 CBS_len(&protocol_name) == 0 || //
Adam Langleyf18e4532015-07-10 13:39:53 -07001420 CBS_len(&protocol_name_list) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001421 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001422 }
1423
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001424 if (!ssl_is_alpn_protocol_allowed(hs, protocol_name)) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001425 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
1426 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1427 return false;
David Benjamin3e51757d2016-08-11 11:52:23 -04001428 }
1429
David Benjamin8e7bbba2017-10-13 17:18:35 -04001430 if (!ssl->s3->alpn_selected.CopyFrom(protocol_name)) {
Adam Langleyf18e4532015-07-10 13:39:53 -07001431 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001432 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001433 }
1434
David Benjamin31640932017-10-11 13:22:39 -04001435 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001436}
1437
David Benjamin12a3e7e2021-04-13 11:47:36 -04001438bool ssl_is_valid_alpn_list(Span<const uint8_t> in) {
1439 CBS protocol_name_list = in;
1440 if (CBS_len(&protocol_name_list) == 0) {
1441 return false;
1442 }
1443 while (CBS_len(&protocol_name_list) > 0) {
1444 CBS protocol_name;
1445 if (!CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) ||
1446 // Empty protocol names are forbidden.
1447 CBS_len(&protocol_name) == 0) {
1448 return false;
1449 }
1450 }
1451 return true;
1452}
1453
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001454bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs,
David Benjamindd6c2e82017-10-17 15:48:46 -04001455 Span<const uint8_t> protocol) {
David Benjamin0ce090a2018-07-02 20:24:40 -04001456 if (hs->config->alpn_client_proto_list.empty()) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001457 return false;
1458 }
1459
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001460 if (hs->ssl->ctx->allow_unknown_alpn_protos) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001461 return true;
1462 }
1463
1464 // Check that the protocol name is one of the ones we advertised.
David Benjaminc1d9ac02024-05-22 13:56:56 -04001465 return ssl_alpn_list_contains_protocol(hs->config->alpn_client_proto_list,
1466 protocol);
1467}
1468
1469bool ssl_alpn_list_contains_protocol(Span<const uint8_t> list,
1470 Span<const uint8_t> protocol) {
1471 CBS cbs = list, candidate;
1472 while (CBS_len(&cbs) > 0) {
1473 if (!CBS_get_u8_length_prefixed(&cbs, &candidate)) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001474 return false;
1475 }
1476
David Benjaminc1d9ac02024-05-22 13:56:56 -04001477 if (candidate == protocol) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001478 return true;
1479 }
1480 }
1481
1482 return false;
1483}
1484
David Benjamin31640932017-10-11 13:22:39 -04001485bool ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1486 const SSL_CLIENT_HELLO *client_hello) {
David Benjaminf3c8f8d2016-11-17 17:20:47 +09001487 SSL *const ssl = hs->ssl;
David Benjamin9ef31f02016-10-31 18:01:13 -04001488 CBS contents;
Adam Langleyf18e4532015-07-10 13:39:53 -07001489 if (ssl->ctx->alpn_select_cb == NULL ||
David Benjamin731058e2016-12-03 23:15:13 -05001490 !ssl_client_hello_get_extension(
David Benjamin9ef31f02016-10-31 18:01:13 -04001491 client_hello, &contents,
1492 TLSEXT_TYPE_application_layer_protocol_negotiation)) {
Nick Harper74161f42020-07-24 15:35:27 -07001493 if (ssl->quic_method) {
1494 // ALPN is required when QUIC is used.
David Benjaminc02c19e2021-02-10 17:49:20 -05001495 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
Nick Harper74161f42020-07-24 15:35:27 -07001496 *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1497 return false;
1498 }
David Benjaminc11ea9422017-08-29 16:33:21 -04001499 // Ignore ALPN if not configured or no extension was supplied.
David Benjamin31640932017-10-11 13:22:39 -04001500 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001501 }
1502
David Benjaminc11ea9422017-08-29 16:33:21 -04001503 // ALPN takes precedence over NPN.
David Benjaminfd45ee72017-08-31 14:49:09 -04001504 hs->next_proto_neg_seen = false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001505
1506 CBS protocol_name_list;
Bob Beck61725ea2024-11-13 17:50:07 +00001507 if (!CBS_get_u16_length_prefixed(&contents, &protocol_name_list) || //
1508 CBS_len(&contents) != 0 || //
David Benjamin12a3e7e2021-04-13 11:47:36 -04001509 !ssl_is_valid_alpn_list(protocol_name_list)) {
David Benjamin9ef31f02016-10-31 18:01:13 -04001510 OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
1511 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001512 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001513 }
1514
David Benjamin9d64d8d2022-08-31 19:27:56 -04001515 // |protocol_name_list| fits in |unsigned| because TLS extensions use 16-bit
1516 // lengths.
Adam Langleyf18e4532015-07-10 13:39:53 -07001517 const uint8_t *selected;
1518 uint8_t selected_len;
David Benjaminc02c19e2021-02-10 17:49:20 -05001519 int ret = ssl->ctx->alpn_select_cb(
1520 ssl, &selected, &selected_len, CBS_data(&protocol_name_list),
David Benjamin9d64d8d2022-08-31 19:27:56 -04001521 static_cast<unsigned>(CBS_len(&protocol_name_list)),
1522 ssl->ctx->alpn_select_cb_arg);
David Benjaminc02c19e2021-02-10 17:49:20 -05001523 // ALPN is required when QUIC is used.
1524 if (ssl->quic_method &&
1525 (ret == SSL_TLSEXT_ERR_NOACK || ret == SSL_TLSEXT_ERR_ALERT_WARNING)) {
1526 ret = SSL_TLSEXT_ERR_ALERT_FATAL;
1527 }
1528 switch (ret) {
1529 case SSL_TLSEXT_ERR_OK:
1530 if (selected_len == 0) {
1531 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
1532 *out_alert = SSL_AD_INTERNAL_ERROR;
1533 return false;
1534 }
1535 if (!ssl->s3->alpn_selected.CopyFrom(
1536 MakeConstSpan(selected, selected_len))) {
1537 *out_alert = SSL_AD_INTERNAL_ERROR;
1538 return false;
1539 }
1540 break;
1541 case SSL_TLSEXT_ERR_NOACK:
1542 case SSL_TLSEXT_ERR_ALERT_WARNING:
1543 break;
1544 case SSL_TLSEXT_ERR_ALERT_FATAL:
1545 *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1546 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
David Benjaminfa544f12018-05-15 15:06:28 -04001547 return false;
David Benjaminc02c19e2021-02-10 17:49:20 -05001548 default:
1549 // Invalid return value.
Adam Langleyf18e4532015-07-10 13:39:53 -07001550 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjaminc02c19e2021-02-10 17:49:20 -05001551 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin31640932017-10-11 13:22:39 -04001552 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001553 }
1554
David Benjamin31640932017-10-11 13:22:39 -04001555 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001556}
1557
David Benjamin31640932017-10-11 13:22:39 -04001558static bool ext_alpn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001559 SSL *const ssl = hs->ssl;
David Benjamin8e7bbba2017-10-13 17:18:35 -04001560 if (ssl->s3->alpn_selected.empty()) {
David Benjamin31640932017-10-11 13:22:39 -04001561 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001562 }
1563
1564 CBB contents, proto_list, proto;
1565 if (!CBB_add_u16(out, TLSEXT_TYPE_application_layer_protocol_negotiation) ||
1566 !CBB_add_u16_length_prefixed(out, &contents) ||
1567 !CBB_add_u16_length_prefixed(&contents, &proto_list) ||
1568 !CBB_add_u8_length_prefixed(&proto_list, &proto) ||
David Benjamin8e7bbba2017-10-13 17:18:35 -04001569 !CBB_add_bytes(&proto, ssl->s3->alpn_selected.data(),
1570 ssl->s3->alpn_selected.size()) ||
Adam Langleyf18e4532015-07-10 13:39:53 -07001571 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001572 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001573 }
1574
David Benjamin31640932017-10-11 13:22:39 -04001575 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001576}
1577
1578
David Benjaminc11ea9422017-08-29 16:33:21 -04001579// Channel ID.
1580//
1581// https://tools.ietf.org/html/draft-balfanz-tls-channelid-01
Adam Langley49c7af12015-07-10 14:33:46 -07001582
David Benjamin83a49932021-05-20 15:57:09 -04001583static bool ext_channel_id_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1584 CBB *out_compressible,
1585 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001586 const SSL *const ssl = hs->ssl;
David Benjaminba423c92021-06-15 16:26:58 -04001587 if (!hs->config->channel_id_private || SSL_is_dtls(ssl) ||
1588 // Don't offer Channel ID in ClientHelloOuter. ClientHelloOuter handshakes
1589 // are not authenticated for the name that can learn the Channel ID.
1590 //
1591 // We could alternatively offer the extension but sign with a random key.
1592 // For other extensions, we try to align |ssl_client_hello_outer| and
1593 // |ssl_client_hello_unencrypted|, to improve the effectiveness of ECH
1594 // GREASE. However, Channel ID is deprecated and unlikely to be used with
1595 // ECH, so do the simplest thing.
1596 type == ssl_client_hello_outer) {
David Benjamin31640932017-10-11 13:22:39 -04001597 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001598 }
1599
David Benjaminba423c92021-06-15 16:26:58 -04001600 if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) ||
1601 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001602 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001603 }
1604
David Benjamin31640932017-10-11 13:22:39 -04001605 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001606}
1607
David Benjamin31640932017-10-11 13:22:39 -04001608static bool ext_channel_id_parse_serverhello(SSL_HANDSHAKE *hs,
1609 uint8_t *out_alert,
1610 CBS *contents) {
Adam Langley49c7af12015-07-10 14:33:46 -07001611 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001612 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001613 }
1614
David Benjamin8acec002021-05-19 13:03:34 -04001615 assert(!SSL_is_dtls(hs->ssl));
David Benjaminb5879112021-05-18 17:10:18 -04001616 assert(hs->config->channel_id_private);
Adam Langley49c7af12015-07-10 14:33:46 -07001617
1618 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001619 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001620 }
1621
David Benjamin8acec002021-05-19 13:03:34 -04001622 hs->channel_id_negotiated = true;
David Benjamin31640932017-10-11 13:22:39 -04001623 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001624}
1625
David Benjamin31640932017-10-11 13:22:39 -04001626static bool ext_channel_id_parse_clienthello(SSL_HANDSHAKE *hs,
1627 uint8_t *out_alert,
1628 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001629 SSL *const ssl = hs->ssl;
David Benjamin46853762018-07-03 14:01:26 -04001630 if (contents == NULL || !hs->config->channel_id_enabled || SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001631 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001632 }
1633
1634 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001635 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001636 }
1637
David Benjamin8acec002021-05-19 13:03:34 -04001638 hs->channel_id_negotiated = true;
David Benjamin31640932017-10-11 13:22:39 -04001639 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001640}
1641
David Benjamin31640932017-10-11 13:22:39 -04001642static bool ext_channel_id_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8acec002021-05-19 13:03:34 -04001643 if (!hs->channel_id_negotiated) {
David Benjamin31640932017-10-11 13:22:39 -04001644 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001645 }
1646
1647 if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) ||
1648 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001649 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001650 }
1651
David Benjamin31640932017-10-11 13:22:39 -04001652 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001653}
1654
Adam Langley391250d2015-07-15 19:06:07 -07001655
David Benjaminc11ea9422017-08-29 16:33:21 -04001656// Secure Real-time Transport Protocol (SRTP) extension.
1657//
1658// https://tools.ietf.org/html/rfc5764
Adam Langley391250d2015-07-15 19:06:07 -07001659
David Benjamin83a49932021-05-20 15:57:09 -04001660static bool ext_srtp_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1661 CBB *out_compressible,
1662 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001663 const SSL *const ssl = hs->ssl;
David Benjaminb778b9c2021-05-20 11:31:05 -04001664 const STACK_OF(SRTP_PROTECTION_PROFILE) *profiles =
1665 SSL_get_srtp_profiles(ssl);
Bob Beck61725ea2024-11-13 17:50:07 +00001666 if (profiles == NULL || //
1667 sk_SRTP_PROTECTION_PROFILE_num(profiles) == 0 || //
David Benjaminbc4c91a2021-05-18 16:06:30 -04001668 !SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001669 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001670 }
1671
1672 CBB contents, profile_ids;
David Benjamin83a49932021-05-20 15:57:09 -04001673 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_srtp) ||
1674 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Adam Langley391250d2015-07-15 19:06:07 -07001675 !CBB_add_u16_length_prefixed(&contents, &profile_ids)) {
David Benjamin31640932017-10-11 13:22:39 -04001676 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001677 }
1678
David Benjaminee910bf2017-07-25 22:36:00 -04001679 for (const SRTP_PROTECTION_PROFILE *profile : profiles) {
1680 if (!CBB_add_u16(&profile_ids, profile->id)) {
David Benjamin31640932017-10-11 13:22:39 -04001681 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001682 }
1683 }
1684
1685 if (!CBB_add_u8(&contents, 0 /* empty use_mki value */) ||
David Benjamin83a49932021-05-20 15:57:09 -04001686 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001687 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001688 }
1689
David Benjamin31640932017-10-11 13:22:39 -04001690 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001691}
1692
David Benjamin31640932017-10-11 13:22:39 -04001693static bool ext_srtp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1694 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001695 SSL *const ssl = hs->ssl;
Adam Langley391250d2015-07-15 19:06:07 -07001696 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001697 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001698 }
1699
David Benjaminc11ea9422017-08-29 16:33:21 -04001700 // The extension consists of a u16-prefixed profile ID list containing a
1701 // single uint16_t profile ID, then followed by a u8-prefixed srtp_mki field.
1702 //
1703 // See https://tools.ietf.org/html/rfc5764#section-4.1.1
David Benjaminbc4c91a2021-05-18 16:06:30 -04001704 assert(SSL_is_dtls(ssl));
Adam Langley391250d2015-07-15 19:06:07 -07001705 CBS profile_ids, srtp_mki;
1706 uint16_t profile_id;
Bob Beck61725ea2024-11-13 17:50:07 +00001707 if (!CBS_get_u16_length_prefixed(contents, &profile_ids) || //
1708 !CBS_get_u16(&profile_ids, &profile_id) || //
1709 CBS_len(&profile_ids) != 0 || //
1710 !CBS_get_u8_length_prefixed(contents, &srtp_mki) || //
Adam Langley391250d2015-07-15 19:06:07 -07001711 CBS_len(contents) != 0) {
1712 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
David Benjamin31640932017-10-11 13:22:39 -04001713 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001714 }
1715
1716 if (CBS_len(&srtp_mki) != 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001717 // Must be no MKI, since we never offer one.
Adam Langley391250d2015-07-15 19:06:07 -07001718 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_MKI_VALUE);
1719 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04001720 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001721 }
1722
David Benjaminb778b9c2021-05-20 11:31:05 -04001723 // Check to see if the server gave us something we support and offered.
1724 for (const SRTP_PROTECTION_PROFILE *profile : SSL_get_srtp_profiles(ssl)) {
Adam Langley391250d2015-07-15 19:06:07 -07001725 if (profile->id == profile_id) {
David Benjaminfceca8e2018-04-12 16:37:19 -04001726 ssl->s3->srtp_profile = profile;
David Benjamin31640932017-10-11 13:22:39 -04001727 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001728 }
1729 }
1730
1731 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
1732 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04001733 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001734}
1735
David Benjamin31640932017-10-11 13:22:39 -04001736static bool ext_srtp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1737 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001738 SSL *const ssl = hs->ssl;
David Benjaminbc4c91a2021-05-18 16:06:30 -04001739 // DTLS-SRTP is only defined for DTLS.
1740 if (contents == NULL || !SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001741 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001742 }
1743
1744 CBS profile_ids, srtp_mki;
1745 if (!CBS_get_u16_length_prefixed(contents, &profile_ids) ||
1746 CBS_len(&profile_ids) < 2 ||
1747 !CBS_get_u8_length_prefixed(contents, &srtp_mki) ||
1748 CBS_len(contents) != 0) {
1749 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
David Benjamin31640932017-10-11 13:22:39 -04001750 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001751 }
David Benjaminc11ea9422017-08-29 16:33:21 -04001752 // Discard the MKI value for now.
Adam Langley391250d2015-07-15 19:06:07 -07001753
1754 const STACK_OF(SRTP_PROTECTION_PROFILE) *server_profiles =
1755 SSL_get_srtp_profiles(ssl);
1756
David Benjaminc11ea9422017-08-29 16:33:21 -04001757 // Pick the server's most preferred profile.
David Benjaminee910bf2017-07-25 22:36:00 -04001758 for (const SRTP_PROTECTION_PROFILE *server_profile : server_profiles) {
Adam Langley391250d2015-07-15 19:06:07 -07001759 CBS profile_ids_tmp;
1760 CBS_init(&profile_ids_tmp, CBS_data(&profile_ids), CBS_len(&profile_ids));
1761
1762 while (CBS_len(&profile_ids_tmp) > 0) {
1763 uint16_t profile_id;
1764 if (!CBS_get_u16(&profile_ids_tmp, &profile_id)) {
David Benjamin31640932017-10-11 13:22:39 -04001765 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001766 }
1767
1768 if (server_profile->id == profile_id) {
David Benjaminfceca8e2018-04-12 16:37:19 -04001769 ssl->s3->srtp_profile = server_profile;
David Benjamin31640932017-10-11 13:22:39 -04001770 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001771 }
1772 }
1773 }
1774
David Benjamin31640932017-10-11 13:22:39 -04001775 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001776}
1777
David Benjamin31640932017-10-11 13:22:39 -04001778static bool ext_srtp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001779 SSL *const ssl = hs->ssl;
David Benjaminfceca8e2018-04-12 16:37:19 -04001780 if (ssl->s3->srtp_profile == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001781 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001782 }
1783
David Benjaminbc4c91a2021-05-18 16:06:30 -04001784 assert(SSL_is_dtls(ssl));
Adam Langley391250d2015-07-15 19:06:07 -07001785 CBB contents, profile_ids;
1786 if (!CBB_add_u16(out, TLSEXT_TYPE_srtp) ||
1787 !CBB_add_u16_length_prefixed(out, &contents) ||
1788 !CBB_add_u16_length_prefixed(&contents, &profile_ids) ||
David Benjaminfceca8e2018-04-12 16:37:19 -04001789 !CBB_add_u16(&profile_ids, ssl->s3->srtp_profile->id) ||
Bob Beck61725ea2024-11-13 17:50:07 +00001790 !CBB_add_u8(&contents, 0 /* empty MKI */) || !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001791 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001792 }
1793
David Benjamin31640932017-10-11 13:22:39 -04001794 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001795}
1796
Adam Langleybdd5d662015-07-20 16:19:08 -07001797
David Benjaminc11ea9422017-08-29 16:33:21 -04001798// EC point formats.
1799//
1800// https://tools.ietf.org/html/rfc4492#section-5.1.2
Adam Langleybdd5d662015-07-20 16:19:08 -07001801
David Benjamin14e51ad2021-05-19 15:24:34 -04001802static bool ext_ec_point_add_extension(const SSL_HANDSHAKE *hs, CBB *out) {
David Benjaminfc059942015-07-30 23:01:59 -04001803 CBB contents, formats;
Adam Langleybdd5d662015-07-20 16:19:08 -07001804 if (!CBB_add_u16(out, TLSEXT_TYPE_ec_point_formats) ||
1805 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjaminfc059942015-07-30 23:01:59 -04001806 !CBB_add_u8_length_prefixed(&contents, &formats) ||
1807 !CBB_add_u8(&formats, TLSEXT_ECPOINTFORMAT_uncompressed) ||
Adam Langleybdd5d662015-07-20 16:19:08 -07001808 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001809 return false;
Adam Langleybdd5d662015-07-20 16:19:08 -07001810 }
1811
David Benjamin31640932017-10-11 13:22:39 -04001812 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001813}
1814
David Benjamin83a49932021-05-20 15:57:09 -04001815static bool ext_ec_point_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1816 CBB *out_compressible,
1817 ssl_client_hello_type_t type) {
Adam Langleyffe384c2019-05-01 11:13:12 -07001818 // The point format extension is unnecessary in TLS 1.3.
David Benjamin83a49932021-05-20 15:57:09 -04001819 if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -04001820 return true;
David Benjamin70aba262016-11-01 12:08:15 -04001821 }
1822
David Benjamin8c880a22016-12-03 02:20:34 -05001823 return ext_ec_point_add_extension(hs, out);
Adam Langleybdd5d662015-07-20 16:19:08 -07001824}
1825
Bob Beck61725ea2024-11-13 17:50:07 +00001826static bool ext_ec_point_parse_serverhello(SSL_HANDSHAKE *hs,
1827 uint8_t *out_alert, CBS *contents) {
Adam Langleybdd5d662015-07-20 16:19:08 -07001828 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001829 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001830 }
1831
David Benjamind1e3ce12017-10-06 18:31:15 -04001832 if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001833 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04001834 }
1835
Adam Langleybdd5d662015-07-20 16:19:08 -07001836 CBS ec_point_format_list;
1837 if (!CBS_get_u8_length_prefixed(contents, &ec_point_format_list) ||
1838 CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001839 return false;
Adam Langleybdd5d662015-07-20 16:19:08 -07001840 }
1841
David Benjaminc11ea9422017-08-29 16:33:21 -04001842 // Per RFC 4492, section 5.1.2, implementations MUST support the uncompressed
1843 // point format.
David Benjamin17cf2cb2016-12-13 01:07:13 -05001844 if (OPENSSL_memchr(CBS_data(&ec_point_format_list),
1845 TLSEXT_ECPOINTFORMAT_uncompressed,
1846 CBS_len(&ec_point_format_list)) == NULL) {
David Benjaminfc059942015-07-30 23:01:59 -04001847 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04001848 return false;
Adam Langleybdd5d662015-07-20 16:19:08 -07001849 }
1850
David Benjamin31640932017-10-11 13:22:39 -04001851 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001852}
1853
Bob Beck61725ea2024-11-13 17:50:07 +00001854static bool ext_ec_point_parse_clienthello(SSL_HANDSHAKE *hs,
1855 uint8_t *out_alert, CBS *contents) {
David Benjamind1e3ce12017-10-06 18:31:15 -04001856 if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001857 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001858 }
1859
David Benjamin8c880a22016-12-03 02:20:34 -05001860 return ext_ec_point_parse_serverhello(hs, out_alert, contents);
Adam Langleybdd5d662015-07-20 16:19:08 -07001861}
1862
David Benjamin31640932017-10-11 13:22:39 -04001863static bool ext_ec_point_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001864 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04001865 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001866 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001867 }
1868
David Benjamin45738dd2017-02-09 20:01:26 -05001869 const uint32_t alg_k = hs->new_cipher->algorithm_mkey;
1870 const uint32_t alg_a = hs->new_cipher->algorithm_auth;
David Benjamin31640932017-10-11 13:22:39 -04001871 const bool using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA);
Adam Langleybdd5d662015-07-20 16:19:08 -07001872
1873 if (!using_ecc) {
David Benjamin31640932017-10-11 13:22:39 -04001874 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001875 }
1876
David Benjamin8c880a22016-12-03 02:20:34 -05001877 return ext_ec_point_add_extension(hs, out);
Adam Langleybdd5d662015-07-20 16:19:08 -07001878}
1879
Steven Valdeza833c352016-11-01 13:39:36 -04001880
David Benjaminc11ea9422017-08-29 16:33:21 -04001881// Pre Shared Key
1882//
David Benjamina130ce02018-08-14 22:26:39 -05001883// https://tools.ietf.org/html/rfc8446#section-4.2.11
Steven Valdez4aa154e2016-07-29 14:32:55 -04001884
David Benjamin83a49932021-05-20 15:57:09 -04001885static bool should_offer_psk(const SSL_HANDSHAKE *hs,
1886 ssl_client_hello_type_t type) {
David Benjamin350fe3b2021-06-02 17:58:53 -04001887 const SSL *const ssl = hs->ssl;
David Benjamin50596f82018-07-02 19:47:27 -04001888 if (hs->max_version < TLS1_3_VERSION || ssl->session == nullptr ||
David Benjamine6b800f2024-11-11 17:31:41 -05001889 ssl_session_get_type(ssl->session.get()) !=
1890 SSLSessionType::kPreSharedKey ||
David Benjamin18b68362021-06-18 23:13:46 -04001891 // TODO(https://crbug.com/boringssl/275): Should we synthesize a
1892 // placeholder PSK, at least when we offer early data? Otherwise
1893 // ClientHelloOuter will contain an early_data extension without a
1894 // pre_shared_key extension and potentially break the recovery flow.
David Benjamin83a49932021-05-20 15:57:09 -04001895 type == ssl_client_hello_outer) {
David Benjamin350fe3b2021-06-02 17:58:53 -04001896 return false;
1897 }
1898
1899 // Per RFC 8446 section 4.1.4, skip offering the session if the selected
1900 // cipher in HelloRetryRequest does not match. This avoids performing the
1901 // transcript hash transformation for multiple hashes.
1902 if (ssl->s3->used_hello_retry_request &&
1903 ssl->session->cipher->algorithm_prf != hs->new_cipher->algorithm_prf) {
1904 return false;
1905 }
1906
1907 return true;
1908}
1909
David Benjamin83a49932021-05-20 15:57:09 -04001910static size_t ext_pre_shared_key_clienthello_length(
1911 const SSL_HANDSHAKE *hs, ssl_client_hello_type_t type) {
David Benjamin350fe3b2021-06-02 17:58:53 -04001912 const SSL *const ssl = hs->ssl;
David Benjamin83a49932021-05-20 15:57:09 -04001913 if (!should_offer_psk(hs, type)) {
Steven Valdeza833c352016-11-01 13:39:36 -04001914 return 0;
1915 }
1916
David Benjamin50596f82018-07-02 19:47:27 -04001917 size_t binder_len = EVP_MD_size(ssl_session_get_digest(ssl->session.get()));
David Benjaminbfdd1a92018-06-29 16:26:38 -04001918 return 15 + ssl->session->ticket.size() + binder_len;
Steven Valdeza833c352016-11-01 13:39:36 -04001919}
1920
David Benjamin5acf9f42021-05-24 14:23:38 -04001921static bool ext_pre_shared_key_add_clienthello(const SSL_HANDSHAKE *hs,
David Benjamin83a49932021-05-20 15:57:09 -04001922 CBB *out, bool *out_needs_binder,
1923 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001924 const SSL *const ssl = hs->ssl;
David Benjamin5acf9f42021-05-24 14:23:38 -04001925 *out_needs_binder = false;
David Benjamin83a49932021-05-20 15:57:09 -04001926 if (!should_offer_psk(hs, type)) {
Steven Valdezcd8470f2017-10-11 12:29:36 -04001927 return true;
1928 }
1929
David Benjamina5d14be2024-11-03 14:31:16 +00001930 OPENSSL_timeval now = ssl_ctx_get_current_time(ssl->ctx.get());
Steven Valdeza833c352016-11-01 13:39:36 -04001931 uint32_t ticket_age = 1000 * (now.tv_sec - ssl->session->time);
1932 uint32_t obfuscated_ticket_age = ticket_age + ssl->session->ticket_age_add;
1933
David Benjaminc11ea9422017-08-29 16:33:21 -04001934 // Fill in a placeholder zero binder of the appropriate length. It will be
1935 // computed and filled in later after length prefixes are computed.
David Benjamin50596f82018-07-02 19:47:27 -04001936 size_t binder_len = EVP_MD_size(ssl_session_get_digest(ssl->session.get()));
Steven Valdeza833c352016-11-01 13:39:36 -04001937
1938 CBB contents, identity, ticket, binders, binder;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001939 if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) ||
1940 !CBB_add_u16_length_prefixed(out, &contents) ||
Steven Valdez5b986082016-09-01 12:29:49 -04001941 !CBB_add_u16_length_prefixed(&contents, &identity) ||
Steven Valdez5b986082016-09-01 12:29:49 -04001942 !CBB_add_u16_length_prefixed(&identity, &ticket) ||
David Benjaminbfdd1a92018-06-29 16:26:38 -04001943 !CBB_add_bytes(&ticket, ssl->session->ticket.data(),
1944 ssl->session->ticket.size()) ||
Steven Valdeza833c352016-11-01 13:39:36 -04001945 !CBB_add_u32(&identity, obfuscated_ticket_age) ||
1946 !CBB_add_u16_length_prefixed(&contents, &binders) ||
1947 !CBB_add_u8_length_prefixed(&binders, &binder) ||
David Benjamin95450622021-07-16 18:24:02 -04001948 !CBB_add_zeros(&binder, binder_len)) {
David Benjamin31640932017-10-11 13:22:39 -04001949 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001950 }
1951
David Benjamin5acf9f42021-05-24 14:23:38 -04001952 *out_needs_binder = true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001953 return CBB_flush(out);
1954}
1955
David Benjamin31640932017-10-11 13:22:39 -04001956bool ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE *hs,
1957 uint8_t *out_alert,
1958 CBS *contents) {
Steven Valdez4aa154e2016-07-29 14:32:55 -04001959 uint16_t psk_id;
Bob Beck61725ea2024-11-13 17:50:07 +00001960 if (!CBS_get_u16(contents, &psk_id) || //
Steven Valdez4aa154e2016-07-29 14:32:55 -04001961 CBS_len(contents) != 0) {
David Benjamin7f78df42016-10-05 22:33:19 -04001962 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
Steven Valdez4aa154e2016-07-29 14:32:55 -04001963 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001964 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001965 }
1966
David Benjaminc11ea9422017-08-29 16:33:21 -04001967 // We only advertise one PSK identity, so the only legal index is zero.
Steven Valdez4aa154e2016-07-29 14:32:55 -04001968 if (psk_id != 0) {
David Benjamin7f78df42016-10-05 22:33:19 -04001969 OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
Steven Valdez4aa154e2016-07-29 14:32:55 -04001970 *out_alert = SSL_AD_UNKNOWN_PSK_IDENTITY;
David Benjamin31640932017-10-11 13:22:39 -04001971 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001972 }
1973
David Benjamin31640932017-10-11 13:22:39 -04001974 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001975}
1976
David Benjamin31640932017-10-11 13:22:39 -04001977bool ssl_ext_pre_shared_key_parse_clienthello(
David Benjamin707af292017-03-10 17:47:18 -05001978 SSL_HANDSHAKE *hs, CBS *out_ticket, CBS *out_binders,
David Benjamin9806ae02019-08-16 15:32:03 -04001979 uint32_t *out_obfuscated_ticket_age, uint8_t *out_alert,
1980 const SSL_CLIENT_HELLO *client_hello, CBS *contents) {
1981 // Verify that the pre_shared_key extension is the last extension in
1982 // ClientHello.
1983 if (CBS_data(contents) + CBS_len(contents) !=
1984 client_hello->extensions + client_hello->extensions_len) {
1985 OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
1986 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1987 return false;
1988 }
1989
David Benjaminc11ea9422017-08-29 16:33:21 -04001990 // We only process the first PSK identity since we don't support pure PSK.
David Benjamin707af292017-03-10 17:47:18 -05001991 CBS identities, binders;
Bob Beck61725ea2024-11-13 17:50:07 +00001992 if (!CBS_get_u16_length_prefixed(contents, &identities) || //
1993 !CBS_get_u16_length_prefixed(&identities, out_ticket) || //
1994 !CBS_get_u32(&identities, out_obfuscated_ticket_age) || //
1995 !CBS_get_u16_length_prefixed(contents, &binders) || //
1996 CBS_len(&binders) == 0 || //
Steven Valdezaf3b8a92016-11-01 12:49:22 -04001997 CBS_len(contents) != 0) {
Steven Valdeza833c352016-11-01 13:39:36 -04001998 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
Steven Valdez4aa154e2016-07-29 14:32:55 -04001999 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002000 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002001 }
2002
Steven Valdeza833c352016-11-01 13:39:36 -04002003 *out_binders = binders;
2004
David Benjaminc11ea9422017-08-29 16:33:21 -04002005 // Check the syntax of the remaining identities, but do not process them.
David Benjaminaedf3032016-12-01 16:47:56 -05002006 size_t num_identities = 1;
2007 while (CBS_len(&identities) != 0) {
2008 CBS unused_ticket;
2009 uint32_t unused_obfuscated_ticket_age;
2010 if (!CBS_get_u16_length_prefixed(&identities, &unused_ticket) ||
2011 !CBS_get_u32(&identities, &unused_obfuscated_ticket_age)) {
2012 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2013 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002014 return false;
David Benjaminaedf3032016-12-01 16:47:56 -05002015 }
2016
2017 num_identities++;
2018 }
2019
David Benjaminc11ea9422017-08-29 16:33:21 -04002020 // Check the syntax of the binders. The value will be checked later if
2021 // resuming.
David Benjaminaedf3032016-12-01 16:47:56 -05002022 size_t num_binders = 0;
2023 while (CBS_len(&binders) != 0) {
2024 CBS binder;
2025 if (!CBS_get_u8_length_prefixed(&binders, &binder)) {
2026 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2027 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002028 return false;
David Benjaminaedf3032016-12-01 16:47:56 -05002029 }
2030
2031 num_binders++;
2032 }
2033
2034 if (num_identities != num_binders) {
2035 OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_BINDER_COUNT_MISMATCH);
2036 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04002037 return false;
Steven Valdez5b986082016-09-01 12:29:49 -04002038 }
2039
David Benjamin31640932017-10-11 13:22:39 -04002040 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002041}
2042
David Benjamin31640932017-10-11 13:22:39 -04002043bool ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8baf9632016-11-17 17:11:16 +09002044 if (!hs->ssl->s3->session_reused) {
David Benjamin31640932017-10-11 13:22:39 -04002045 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002046 }
2047
2048 CBB contents;
Bob Beck61725ea2024-11-13 17:50:07 +00002049 if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) || //
2050 !CBB_add_u16_length_prefixed(out, &contents) || //
David Benjaminc11ea9422017-08-29 16:33:21 -04002051 // We only consider the first identity for resumption
Bob Beck61725ea2024-11-13 17:50:07 +00002052 !CBB_add_u16(&contents, 0) || //
Steven Valdez4aa154e2016-07-29 14:32:55 -04002053 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002054 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002055 }
2056
David Benjamin31640932017-10-11 13:22:39 -04002057 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002058}
2059
2060
David Benjaminc11ea9422017-08-29 16:33:21 -04002061// Pre-Shared Key Exchange Modes
2062//
David Benjamina130ce02018-08-14 22:26:39 -05002063// https://tools.ietf.org/html/rfc8446#section-4.2.9
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002064
David Benjamin83a49932021-05-20 15:57:09 -04002065static bool ext_psk_key_exchange_modes_add_clienthello(
2066 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2067 ssl_client_hello_type_t type) {
David Benjamin68161cb2017-06-20 14:49:43 -04002068 if (hs->max_version < TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002069 return true;
Steven Valdeza833c352016-11-01 13:39:36 -04002070 }
2071
2072 CBB contents, ke_modes;
David Benjamin83a49932021-05-20 15:57:09 -04002073 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_psk_key_exchange_modes) ||
2074 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Steven Valdeza833c352016-11-01 13:39:36 -04002075 !CBB_add_u8_length_prefixed(&contents, &ke_modes) ||
2076 !CBB_add_u8(&ke_modes, SSL_PSK_DHE_KE)) {
David Benjamin31640932017-10-11 13:22:39 -04002077 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04002078 }
2079
David Benjamin83a49932021-05-20 15:57:09 -04002080 return CBB_flush(out_compressible);
Steven Valdeza833c352016-11-01 13:39:36 -04002081}
2082
David Benjamin31640932017-10-11 13:22:39 -04002083static bool ext_psk_key_exchange_modes_parse_clienthello(SSL_HANDSHAKE *hs,
2084 uint8_t *out_alert,
2085 CBS *contents) {
David Benjamin4eb95cc2016-11-16 17:08:23 +09002086 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04002087 return true;
David Benjamin4eb95cc2016-11-16 17:08:23 +09002088 }
2089
Steven Valdeza833c352016-11-01 13:39:36 -04002090 CBS ke_modes;
Bob Beck61725ea2024-11-13 17:50:07 +00002091 if (!CBS_get_u8_length_prefixed(contents, &ke_modes) || //
2092 CBS_len(&ke_modes) == 0 || //
Steven Valdeza833c352016-11-01 13:39:36 -04002093 CBS_len(contents) != 0) {
2094 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002095 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04002096 }
2097
David Benjaminc11ea9422017-08-29 16:33:21 -04002098 // We only support tickets with PSK_DHE_KE.
David Benjamin17cf2cb2016-12-13 01:07:13 -05002099 hs->accept_psk_mode = OPENSSL_memchr(CBS_data(&ke_modes), SSL_PSK_DHE_KE,
2100 CBS_len(&ke_modes)) != NULL;
Steven Valdeza833c352016-11-01 13:39:36 -04002101
David Benjamin31640932017-10-11 13:22:39 -04002102 return true;
Steven Valdeza833c352016-11-01 13:39:36 -04002103}
2104
2105
David Benjaminc11ea9422017-08-29 16:33:21 -04002106// Early Data Indication
2107//
David Benjamina130ce02018-08-14 22:26:39 -05002108// https://tools.ietf.org/html/rfc8446#section-4.2.10
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002109
David Benjamin83a49932021-05-20 15:57:09 -04002110static bool ext_early_data_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2111 CBB *out_compressible,
2112 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002113 const SSL *const ssl = hs->ssl;
David Benjamin64770122019-05-04 11:00:04 -05002114 // The second ClientHello never offers early data, and we must have already
2115 // filled in |early_data_reason| by this point.
Kris Kwiatkowskib11902a2019-08-24 11:01:04 +01002116 if (ssl->s3->used_hello_retry_request) {
David Benjamin64770122019-05-04 11:00:04 -05002117 assert(ssl->s3->early_data_reason != ssl_early_data_unknown);
David Benjamin31640932017-10-11 13:22:39 -04002118 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002119 }
2120
David Benjamin4e93cd42021-05-18 13:38:25 -04002121 if (!hs->early_data_offered) {
David Benjamin64770122019-05-04 11:00:04 -05002122 return true;
2123 }
2124
David Benjamin83a49932021-05-20 15:57:09 -04002125 // If offering ECH, the extension only applies to ClientHelloInner, but we
2126 // send the extension in both ClientHellos. This ensures that, if the server
2127 // handshakes with ClientHelloOuter, it can skip past early data. See
David Benjamin0fa30302021-09-03 17:23:28 -04002128 // draft-ietf-tls-esni-13, section 6.1.
Bob Beck61725ea2024-11-13 17:50:07 +00002129 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_early_data) || //
2130 !CBB_add_u16(out_compressible, 0) || //
David Benjamin83a49932021-05-20 15:57:09 -04002131 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04002132 return false;
Steven Valdez2d850622017-01-11 11:34:52 -05002133 }
2134
David Benjamin31640932017-10-11 13:22:39 -04002135 return true;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002136}
2137
David Benjamin31640932017-10-11 13:22:39 -04002138static bool ext_early_data_parse_serverhello(SSL_HANDSHAKE *hs,
David Benjamin64770122019-05-04 11:00:04 -05002139 uint8_t *out_alert,
2140 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05002141 SSL *const ssl = hs->ssl;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002142 if (contents == NULL) {
Kris Kwiatkowskib11902a2019-08-24 11:01:04 +01002143 if (hs->early_data_offered && !ssl->s3->used_hello_retry_request) {
David Benjamin64770122019-05-04 11:00:04 -05002144 ssl->s3->early_data_reason = ssl->s3->session_reused
2145 ? ssl_early_data_peer_declined
2146 : ssl_early_data_session_not_resumed;
2147 } else {
2148 // We already filled in |early_data_reason| when declining to offer 0-RTT
2149 // or handling the implicit HelloRetryRequest reject.
2150 assert(ssl->s3->early_data_reason != ssl_early_data_unknown);
2151 }
David Benjamin31640932017-10-11 13:22:39 -04002152 return true;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002153 }
2154
David Benjamin64770122019-05-04 11:00:04 -05002155 // If we received an HRR, the second ClientHello never offers early data, so
2156 // the extensions logic will automatically reject early data extensions as
2157 // unsolicited. This covered by the ServerAcceptsEarlyDataOnHRR test.
Kris Kwiatkowskib11902a2019-08-24 11:01:04 +01002158 assert(!ssl->s3->used_hello_retry_request);
David Benjamin64770122019-05-04 11:00:04 -05002159
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002160 if (CBS_len(contents) != 0) {
2161 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002162 return false;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002163 }
2164
Steven Valdez2d850622017-01-11 11:34:52 -05002165 if (!ssl->s3->session_reused) {
2166 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2167 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
David Benjamin31640932017-10-11 13:22:39 -04002168 return false;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002169 }
Steven Valdez2d850622017-01-11 11:34:52 -05002170
David Benjamin64770122019-05-04 11:00:04 -05002171 ssl->s3->early_data_reason = ssl_early_data_accepted;
David Benjamin02e62562017-12-18 18:04:01 -05002172 ssl->s3->early_data_accepted = true;
David Benjamin31640932017-10-11 13:22:39 -04002173 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002174}
2175
David Benjamin31640932017-10-11 13:22:39 -04002176static bool ext_early_data_parse_clienthello(SSL_HANDSHAKE *hs,
Bob Beck61725ea2024-11-13 17:50:07 +00002177 uint8_t *out_alert,
2178 CBS *contents) {
Steven Valdez2d850622017-01-11 11:34:52 -05002179 SSL *const ssl = hs->ssl;
Bob Beck61725ea2024-11-13 17:50:07 +00002180 if (contents == NULL || ssl_protocol_version(ssl) < TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002181 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002182 }
2183
2184 if (CBS_len(contents) != 0) {
2185 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002186 return false;
Steven Valdez2d850622017-01-11 11:34:52 -05002187 }
2188
David Benjaminfd45ee72017-08-31 14:49:09 -04002189 hs->early_data_offered = true;
David Benjamin31640932017-10-11 13:22:39 -04002190 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002191}
2192
David Benjamin31640932017-10-11 13:22:39 -04002193static bool ext_early_data_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin02e62562017-12-18 18:04:01 -05002194 if (!hs->ssl->s3->early_data_accepted) {
David Benjamin31640932017-10-11 13:22:39 -04002195 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002196 }
2197
Bob Beck61725ea2024-11-13 17:50:07 +00002198 if (!CBB_add_u16(out, TLSEXT_TYPE_early_data) || //
2199 !CBB_add_u16(out, 0) || //
Steven Valdez2d850622017-01-11 11:34:52 -05002200 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002201 return false;
Steven Valdez2d850622017-01-11 11:34:52 -05002202 }
2203
David Benjamin31640932017-10-11 13:22:39 -04002204 return true;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002205}
2206
2207
David Benjaminc11ea9422017-08-29 16:33:21 -04002208// Key Share
2209//
David Benjamina130ce02018-08-14 22:26:39 -05002210// https://tools.ietf.org/html/rfc8446#section-4.2.8
Steven Valdez143e8b32016-07-11 13:19:03 -04002211
David Benjamin97ede402021-05-18 14:17:52 -04002212bool ssl_setup_key_shares(SSL_HANDSHAKE *hs, uint16_t override_group_id) {
David Benjamin8c880a22016-12-03 02:20:34 -05002213 SSL *const ssl = hs->ssl;
David Benjamin97ede402021-05-18 14:17:52 -04002214 hs->key_shares[0].reset();
2215 hs->key_shares[1].reset();
2216 hs->key_share_bytes.Reset();
2217
David Benjamin68161cb2017-06-20 14:49:43 -04002218 if (hs->max_version < TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002219 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002220 }
2221
David Benjamin97ede402021-05-18 14:17:52 -04002222 bssl::ScopedCBB cbb;
2223 if (!CBB_init(cbb.get(), 64)) {
David Benjamin31640932017-10-11 13:22:39 -04002224 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002225 }
2226
David Benjamin97ede402021-05-18 14:17:52 -04002227 if (override_group_id == 0 && ssl->ctx->grease_enabled) {
David Benjamin3675eb32021-05-18 14:01:07 -04002228 // Add a fake group. See RFC 8701.
David Benjamin97ede402021-05-18 14:17:52 -04002229 if (!CBB_add_u16(cbb.get(), ssl_get_grease_value(hs, ssl_grease_group)) ||
2230 !CBB_add_u16(cbb.get(), 1 /* length */) ||
2231 !CBB_add_u8(cbb.get(), 0 /* one byte key share */)) {
David Benjamin31640932017-10-11 13:22:39 -04002232 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04002233 }
David Benjamin97ede402021-05-18 14:17:52 -04002234 }
David Benjamin65ac9972016-09-02 21:35:25 -04002235
David Benjamin97ede402021-05-18 14:17:52 -04002236 uint16_t group_id = override_group_id;
2237 uint16_t second_group_id = 0;
2238 if (override_group_id == 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -04002239 // Predict the most preferred group.
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07002240 Span<const uint16_t> groups = tls1_get_grouplist(hs);
David Benjaminb9493552017-09-27 19:02:51 -04002241 if (groups.empty()) {
David Benjaminc8b6b4f2016-09-08 23:47:48 -04002242 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_GROUPS_SPECIFIED);
David Benjamin31640932017-10-11 13:22:39 -04002243 return false;
Steven Valdez5440fe02016-07-18 12:40:30 -04002244 }
David Benjaminc8b6b4f2016-09-08 23:47:48 -04002245
2246 group_id = groups[0];
Adam Langley7b935932018-11-12 13:53:42 -08002247
Adam Langley1e97ce32023-01-23 21:11:44 +00002248 // We'll try to include one post-quantum and one classical initial key
2249 // share.
2250 for (size_t i = 1; i < groups.size() && second_group_id == 0; i++) {
2251 if (is_post_quantum_group(group_id) != is_post_quantum_group(groups[i])) {
2252 second_group_id = groups[i];
2253 assert(second_group_id != group_id);
2254 }
Adam Langley7b935932018-11-12 13:53:42 -08002255 }
Steven Valdez5440fe02016-07-18 12:40:30 -04002256 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002257
David Benjaminc8b6b4f2016-09-08 23:47:48 -04002258 CBB key_exchange;
Adam Langley7b935932018-11-12 13:53:42 -08002259 hs->key_shares[0] = SSLKeyShare::Create(group_id);
David Benjamin97ede402021-05-18 14:17:52 -04002260 if (!hs->key_shares[0] || //
2261 !CBB_add_u16(cbb.get(), group_id) ||
2262 !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002263 !hs->key_shares[0]->Generate(&key_exchange)) {
David Benjamin31640932017-10-11 13:22:39 -04002264 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002265 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002266
Adam Langley7b935932018-11-12 13:53:42 -08002267 if (second_group_id != 0) {
2268 hs->key_shares[1] = SSLKeyShare::Create(second_group_id);
David Benjamin97ede402021-05-18 14:17:52 -04002269 if (!hs->key_shares[1] || //
2270 !CBB_add_u16(cbb.get(), second_group_id) ||
2271 !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002272 !hs->key_shares[1]->Generate(&key_exchange)) {
Adam Langley7b935932018-11-12 13:53:42 -08002273 return false;
2274 }
2275 }
2276
David Benjamin97ede402021-05-18 14:17:52 -04002277 return CBBFinishArray(cbb.get(), &hs->key_share_bytes);
2278}
2279
David Benjamin83a49932021-05-20 15:57:09 -04002280static bool ext_key_share_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2281 CBB *out_compressible,
2282 ssl_client_hello_type_t type) {
David Benjamin97ede402021-05-18 14:17:52 -04002283 if (hs->max_version < TLS1_3_VERSION) {
2284 return true;
2285 }
2286
2287 assert(!hs->key_share_bytes.empty());
2288 CBB contents, kse_bytes;
David Benjamin83a49932021-05-20 15:57:09 -04002289 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_key_share) ||
2290 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
David Benjamin97ede402021-05-18 14:17:52 -04002291 !CBB_add_u16_length_prefixed(&contents, &kse_bytes) ||
2292 !CBB_add_bytes(&kse_bytes, hs->key_share_bytes.data(),
2293 hs->key_share_bytes.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -04002294 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04002295 return false;
Steven Valdez5440fe02016-07-18 12:40:30 -04002296 }
2297
David Benjamin97ede402021-05-18 14:17:52 -04002298 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002299}
2300
David Benjamin31640932017-10-11 13:22:39 -04002301bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
2302 Array<uint8_t> *out_secret,
2303 uint8_t *out_alert, CBS *contents) {
David Benjamin08b1f382023-02-28 17:22:23 -05002304 CBS ciphertext;
David Benjamin5c4e8572016-08-19 17:44:53 -04002305 uint16_t group_id;
2306 if (!CBS_get_u16(contents, &group_id) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002307 !CBS_get_u16_length_prefixed(contents, &ciphertext) ||
David Benjamina70de142016-08-02 16:52:57 -04002308 CBS_len(contents) != 0) {
David Benjaminac4d5342017-11-17 01:42:04 +08002309 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
Steven Valdez143e8b32016-07-11 13:19:03 -04002310 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002311 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002312 }
2313
Adam Langley7b935932018-11-12 13:53:42 -08002314 SSLKeyShare *key_share = hs->key_shares[0].get();
2315 if (key_share->GroupID() != group_id) {
2316 if (!hs->key_shares[1] || hs->key_shares[1]->GroupID() != group_id) {
2317 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
2318 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
2319 return false;
2320 }
2321 key_share = hs->key_shares[1].get();
Steven Valdez143e8b32016-07-11 13:19:03 -04002322 }
2323
David Benjamin08b1f382023-02-28 17:22:23 -05002324 if (!key_share->Decap(out_secret, out_alert, ciphertext)) {
Steven Valdez143e8b32016-07-11 13:19:03 -04002325 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002326 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002327 }
2328
David Benjamin45738dd2017-02-09 20:01:26 -05002329 hs->new_session->group_id = group_id;
Adam Langley7b935932018-11-12 13:53:42 -08002330 hs->key_shares[0].reset();
2331 hs->key_shares[1].reset();
David Benjamin31640932017-10-11 13:22:39 -04002332 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002333}
2334
David Benjamin31640932017-10-11 13:22:39 -04002335bool ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found,
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002336 Span<const uint8_t> *out_peer_key,
2337 uint8_t *out_alert,
2338 const SSL_CLIENT_HELLO *client_hello) {
2339 // We only support connections that include an ECDHE key exchange.
2340 CBS contents;
2341 if (!ssl_client_hello_get_extension(client_hello, &contents,
2342 TLSEXT_TYPE_key_share)) {
2343 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
2344 *out_alert = SSL_AD_MISSING_EXTENSION;
David Benjamin31640932017-10-11 13:22:39 -04002345 return false;
Steven Valdez803c77a2016-09-06 14:13:43 -04002346 }
2347
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002348 CBS key_shares;
2349 if (!CBS_get_u16_length_prefixed(&contents, &key_shares) ||
2350 CBS_len(&contents) != 0) {
David Benjamin7e1f9842016-09-20 19:24:40 -04002351 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
David Benjamin31640932017-10-11 13:22:39 -04002352 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002353 }
2354
David Benjaminc11ea9422017-08-29 16:33:21 -04002355 // Find the corresponding key share.
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002356 const uint16_t group_id = hs->new_session->group_id;
David Benjamin7e1f9842016-09-20 19:24:40 -04002357 CBS peer_key;
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002358 CBS_init(&peer_key, nullptr, 0);
Steven Valdez143e8b32016-07-11 13:19:03 -04002359 while (CBS_len(&key_shares) > 0) {
2360 uint16_t id;
David Benjamin7e1f9842016-09-20 19:24:40 -04002361 CBS peer_key_tmp;
Steven Valdez143e8b32016-07-11 13:19:03 -04002362 if (!CBS_get_u16(&key_shares, &id) ||
Steven Valdez619c8ce2017-10-16 13:12:33 -04002363 !CBS_get_u16_length_prefixed(&key_shares, &peer_key_tmp) ||
2364 CBS_len(&peer_key_tmp) == 0) {
David Benjamin7e1f9842016-09-20 19:24:40 -04002365 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
David Benjamin31640932017-10-11 13:22:39 -04002366 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002367 }
2368
David Benjamin7e1f9842016-09-20 19:24:40 -04002369 if (id == group_id) {
Steven Valdez619c8ce2017-10-16 13:12:33 -04002370 if (CBS_len(&peer_key) != 0) {
David Benjamin7e1f9842016-09-20 19:24:40 -04002371 OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_KEY_SHARE);
2372 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04002373 return false;
David Benjamin7e1f9842016-09-20 19:24:40 -04002374 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002375
David Benjamin7e1f9842016-09-20 19:24:40 -04002376 peer_key = peer_key_tmp;
David Benjaminc11ea9422017-08-29 16:33:21 -04002377 // Continue parsing the structure to keep peers honest.
Steven Valdez143e8b32016-07-11 13:19:03 -04002378 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002379 }
2380
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002381 if (out_peer_key != nullptr) {
2382 *out_peer_key = peer_key;
David Benjamin7e1f9842016-09-20 19:24:40 -04002383 }
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002384 *out_found = CBS_len(&peer_key) != 0;
David Benjamin31640932017-10-11 13:22:39 -04002385 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002386}
2387
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002388bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin08b1f382023-02-28 17:22:23 -05002389 CBB entry, ciphertext;
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002390 if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002391 !CBB_add_u16_length_prefixed(out, &entry) ||
2392 !CBB_add_u16(&entry, hs->new_session->group_id) ||
2393 !CBB_add_u16_length_prefixed(&entry, &ciphertext) ||
2394 !CBB_add_bytes(&ciphertext, hs->key_share_ciphertext.data(),
2395 hs->key_share_ciphertext.size()) ||
Steven Valdez143e8b32016-07-11 13:19:03 -04002396 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002397 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002398 }
David Benjamin31640932017-10-11 13:22:39 -04002399 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002400}
2401
2402
David Benjaminc11ea9422017-08-29 16:33:21 -04002403// Supported Versions
2404//
David Benjamina130ce02018-08-14 22:26:39 -05002405// https://tools.ietf.org/html/rfc8446#section-4.2.1
Steven Valdezfdd10992016-09-15 16:27:05 -04002406
David Benjamin83a49932021-05-20 15:57:09 -04002407static bool ext_supported_versions_add_clienthello(
2408 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2409 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002410 const SSL *const ssl = hs->ssl;
David Benjamin68161cb2017-06-20 14:49:43 -04002411 if (hs->max_version <= TLS1_2_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002412 return true;
Steven Valdezfdd10992016-09-15 16:27:05 -04002413 }
2414
David Benjamin83a49932021-05-20 15:57:09 -04002415 // supported_versions is compressible in ECH if ClientHelloOuter already
2416 // requires TLS 1.3. Otherwise the extensions differ in the older versions.
2417 if (hs->min_version >= TLS1_3_VERSION) {
2418 out = out_compressible;
2419 }
2420
Steven Valdezfdd10992016-09-15 16:27:05 -04002421 CBB contents, versions;
2422 if (!CBB_add_u16(out, TLSEXT_TYPE_supported_versions) ||
2423 !CBB_add_u16_length_prefixed(out, &contents) ||
2424 !CBB_add_u8_length_prefixed(&contents, &versions)) {
David Benjamin31640932017-10-11 13:22:39 -04002425 return false;
Steven Valdezfdd10992016-09-15 16:27:05 -04002426 }
2427
David Benjamin3675eb32021-05-18 14:01:07 -04002428 // Add a fake version. See RFC 8701.
David Benjamind9791bf2016-09-27 16:39:52 -04002429 if (ssl->ctx->grease_enabled &&
David Benjamina7bc9442018-01-18 10:08:53 -05002430 !CBB_add_u16(&versions, ssl_get_grease_value(hs, ssl_grease_version))) {
David Benjamin31640932017-10-11 13:22:39 -04002431 return false;
David Benjamind9791bf2016-09-27 16:39:52 -04002432 }
2433
David Benjamin83a49932021-05-20 15:57:09 -04002434 // Encrypted ClientHellos requires TLS 1.3 or later.
2435 uint16_t extra_min_version =
2436 type == ssl_client_hello_inner ? TLS1_3_VERSION : 0;
2437 if (!ssl_add_supported_versions(hs, &versions, extra_min_version) ||
Steven Valdez8f36c512017-06-20 10:55:02 -04002438 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002439 return false;
Steven Valdezfdd10992016-09-15 16:27:05 -04002440 }
2441
David Benjamin31640932017-10-11 13:22:39 -04002442 return true;
Steven Valdezfdd10992016-09-15 16:27:05 -04002443}
2444
2445
David Benjaminc11ea9422017-08-29 16:33:21 -04002446// Cookie
2447//
David Benjamina130ce02018-08-14 22:26:39 -05002448// https://tools.ietf.org/html/rfc8446#section-4.2.2
David Benjamin3baa6e12016-10-07 21:10:38 -04002449
David Benjamin83a49932021-05-20 15:57:09 -04002450static bool ext_cookie_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2451 CBB *out_compressible,
2452 ssl_client_hello_type_t type) {
David Benjaminb9493552017-09-27 19:02:51 -04002453 if (hs->cookie.empty()) {
David Benjamin31640932017-10-11 13:22:39 -04002454 return true;
David Benjamin3baa6e12016-10-07 21:10:38 -04002455 }
2456
2457 CBB contents, cookie;
David Benjamin83a49932021-05-20 15:57:09 -04002458 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_cookie) ||
2459 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
David Benjamin3baa6e12016-10-07 21:10:38 -04002460 !CBB_add_u16_length_prefixed(&contents, &cookie) ||
David Benjamin08f5c762017-09-21 02:43:05 -04002461 !CBB_add_bytes(&cookie, hs->cookie.data(), hs->cookie.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -04002462 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04002463 return false;
David Benjamin3baa6e12016-10-07 21:10:38 -04002464 }
2465
David Benjamin31640932017-10-11 13:22:39 -04002466 return true;
David Benjamin3baa6e12016-10-07 21:10:38 -04002467}
2468
2469
David Benjamina130ce02018-08-14 22:26:39 -05002470// Supported Groups
David Benjaminc11ea9422017-08-29 16:33:21 -04002471//
David Benjamina130ce02018-08-14 22:26:39 -05002472// https://tools.ietf.org/html/rfc4492#section-5.1.1
2473// https://tools.ietf.org/html/rfc8446#section-4.2.7
Adam Langley273d49c2015-07-20 16:38:52 -07002474
David Benjamin14e51ad2021-05-19 15:24:34 -04002475static bool ext_supported_groups_add_clienthello(const SSL_HANDSHAKE *hs,
David Benjamin83a49932021-05-20 15:57:09 -04002476 CBB *out,
2477 CBB *out_compressible,
2478 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002479 const SSL *const ssl = hs->ssl;
Steven Valdezce902a92016-05-17 11:47:53 -04002480 CBB contents, groups_bytes;
David Benjamin83a49932021-05-20 15:57:09 -04002481 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_supported_groups) ||
2482 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Steven Valdezce902a92016-05-17 11:47:53 -04002483 !CBB_add_u16_length_prefixed(&contents, &groups_bytes)) {
David Benjamin31640932017-10-11 13:22:39 -04002484 return false;
Adam Langley273d49c2015-07-20 16:38:52 -07002485 }
2486
David Benjamin3675eb32021-05-18 14:01:07 -04002487 // Add a fake group. See RFC 8701.
David Benjamin65ac9972016-09-02 21:35:25 -04002488 if (ssl->ctx->grease_enabled &&
Bob Beck61725ea2024-11-13 17:50:07 +00002489 !CBB_add_u16(&groups_bytes, ssl_get_grease_value(hs, ssl_grease_group))) {
David Benjamin31640932017-10-11 13:22:39 -04002490 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04002491 }
2492
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07002493 for (uint16_t group : tls1_get_grouplist(hs)) {
Bob Beck61725ea2024-11-13 17:50:07 +00002494 if (is_post_quantum_group(group) && hs->max_version < TLS1_3_VERSION) {
Adam Langley7b935932018-11-12 13:53:42 -08002495 continue;
2496 }
David Benjamincf0ce672017-09-21 02:25:59 -04002497 if (!CBB_add_u16(&groups_bytes, group)) {
David Benjamin31640932017-10-11 13:22:39 -04002498 return false;
Adam Langley273d49c2015-07-20 16:38:52 -07002499 }
2500 }
2501
David Benjamin83a49932021-05-20 15:57:09 -04002502 return CBB_flush(out_compressible);
Adam Langley273d49c2015-07-20 16:38:52 -07002503}
2504
David Benjamin31640932017-10-11 13:22:39 -04002505static bool ext_supported_groups_parse_serverhello(SSL_HANDSHAKE *hs,
2506 uint8_t *out_alert,
2507 CBS *contents) {
David Benjaminc11ea9422017-08-29 16:33:21 -04002508 // This extension is not expected to be echoed by servers in TLS 1.2, but some
2509 // BigIP servers send it nonetheless, so do not enforce this.
David Benjamin31640932017-10-11 13:22:39 -04002510 return true;
Adam Langley273d49c2015-07-20 16:38:52 -07002511}
2512
David Benjaminb1cf48e2017-09-21 11:37:46 -04002513static bool parse_u16_array(const CBS *cbs, Array<uint16_t> *out) {
2514 CBS copy = *cbs;
2515 if ((CBS_len(&copy) & 1) != 0) {
2516 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2517 return false;
2518 }
2519
2520 Array<uint16_t> ret;
David Benjamince572d62024-10-22 12:35:44 -04002521 if (!ret.InitForOverwrite(CBS_len(&copy) / 2)) {
David Benjaminb1cf48e2017-09-21 11:37:46 -04002522 return false;
2523 }
2524 for (size_t i = 0; i < ret.size(); i++) {
2525 if (!CBS_get_u16(&copy, &ret[i])) {
2526 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
2527 return false;
2528 }
2529 }
2530
2531 assert(CBS_len(&copy) == 0);
2532 *out = std::move(ret);
Anton Bikineev50e7ea52022-01-23 22:35:48 +01002533 return true;
David Benjaminb1cf48e2017-09-21 11:37:46 -04002534}
2535
David Benjamin31640932017-10-11 13:22:39 -04002536static bool ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs,
Bob Beck61725ea2024-11-13 17:50:07 +00002537 uint8_t *out_alert,
David Benjamin31640932017-10-11 13:22:39 -04002538 CBS *contents) {
Adam Langley273d49c2015-07-20 16:38:52 -07002539 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04002540 return true;
Adam Langley273d49c2015-07-20 16:38:52 -07002541 }
2542
Steven Valdezce902a92016-05-17 11:47:53 -04002543 CBS supported_group_list;
Bob Beck61725ea2024-11-13 17:50:07 +00002544 if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) || //
2545 CBS_len(&supported_group_list) == 0 || //
2546 CBS_len(contents) != 0 || //
David Benjaminb1cf48e2017-09-21 11:37:46 -04002547 !parse_u16_array(&supported_group_list, &hs->peer_supported_group_list)) {
David Benjamin31640932017-10-11 13:22:39 -04002548 return false;
Adam Langley273d49c2015-07-20 16:38:52 -07002549 }
2550
David Benjamin31640932017-10-11 13:22:39 -04002551 return true;
Adam Langley273d49c2015-07-20 16:38:52 -07002552}
2553
2554
Bob Beck71524332024-09-23 17:45:46 +00002555// Certificate Authorities.
2556//
2557// https://tools.ietf.org/html/rfc8446#section-4.2.4
2558
2559static bool ext_certificate_authorities_add_clienthello(
2560 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2561 ssl_client_hello_type_t type) {
2562 if (ssl_has_CA_names(hs->config)) {
2563 CBB ca_contents;
Bob Beck61725ea2024-11-13 17:50:07 +00002564 if (!CBB_add_u16(out, TLSEXT_TYPE_certificate_authorities) || //
2565 !CBB_add_u16_length_prefixed(out, &ca_contents) || //
2566 !ssl_add_CA_names(hs, &ca_contents) || //
Bob Beck71524332024-09-23 17:45:46 +00002567 !CBB_flush(out)) {
2568 return false;
2569 }
2570 }
2571 return true;
2572}
2573
2574static bool ext_certificate_authorities_parse_clienthello(SSL_HANDSHAKE *hs,
2575 uint8_t *out_alert,
2576 CBS *contents) {
2577 if (contents == NULL) {
2578 return true;
2579 }
2580
2581 if (CBS_len(contents) == 0) {
2582 return false;
2583 }
2584
2585 hs->ca_names = SSL_parse_CA_list(hs->ssl, out_alert, contents);
2586 if (!hs->ca_names) {
2587 return false;
2588 }
2589
2590 return true;
2591}
2592
2593
Nick Harper3c034b22017-12-22 15:50:43 -08002594// QUIC Transport Parameters
2595
David Schinazi3d8b8c32021-01-14 11:25:49 -08002596static bool ext_quic_transport_params_add_clienthello_impl(
David Benjamin14e51ad2021-05-19 15:24:34 -04002597 const SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) {
Nick Harper72cff812020-03-26 18:06:16 -07002598 if (hs->config->quic_transport_params.empty() && !hs->ssl->quic_method) {
Nick Harper3c034b22017-12-22 15:50:43 -08002599 return true;
2600 }
Nick Harper72cff812020-03-26 18:06:16 -07002601 if (hs->config->quic_transport_params.empty() || !hs->ssl->quic_method) {
2602 // QUIC Transport Parameters must be sent over QUIC, and they must not be
2603 // sent over non-QUIC transports. If transport params are set, then
2604 // SSL(_CTX)_set_quic_method must also be called.
2605 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2606 return false;
2607 }
2608 assert(hs->min_version > TLS1_2_VERSION);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002609 if (use_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2610 // Do nothing, we'll send the other codepoint.
2611 return true;
2612 }
2613
David Benjamina1d3bfb2021-06-01 12:12:44 -04002614 uint16_t extension_type = TLSEXT_TYPE_quic_transport_parameters;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002615 if (hs->config->quic_use_legacy_codepoint) {
2616 extension_type = TLSEXT_TYPE_quic_transport_parameters_legacy;
2617 }
Nick Harper3c034b22017-12-22 15:50:43 -08002618
2619 CBB contents;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002620 if (!CBB_add_u16(out, extension_type) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002621 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjamin0ce090a2018-07-02 20:24:40 -04002622 !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(),
2623 hs->config->quic_transport_params.size()) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002624 !CBB_flush(out)) {
2625 return false;
2626 }
2627 return true;
2628}
2629
David Benjamin83a49932021-05-20 15:57:09 -04002630static bool ext_quic_transport_params_add_clienthello(
2631 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2632 ssl_client_hello_type_t type) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002633 return ext_quic_transport_params_add_clienthello_impl(
David Benjamin83a49932021-05-20 15:57:09 -04002634 hs, out_compressible, /*use_legacy_codepoint=*/false);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002635}
2636
David Benjamin14e51ad2021-05-19 15:24:34 -04002637static bool ext_quic_transport_params_add_clienthello_legacy(
David Benjamin83a49932021-05-20 15:57:09 -04002638 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2639 ssl_client_hello_type_t type) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002640 return ext_quic_transport_params_add_clienthello_impl(
David Benjamin83a49932021-05-20 15:57:09 -04002641 hs, out_compressible, /*use_legacy_codepoint=*/true);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002642}
2643
2644static bool ext_quic_transport_params_parse_serverhello_impl(
2645 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents,
2646 bool used_legacy_codepoint) {
Adam Langleyca058c02020-12-16 10:11:08 -08002647 SSL *const ssl = hs->ssl;
2648 if (contents == nullptr) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002649 if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2650 // Silently ignore because we expect the other QUIC codepoint.
2651 return true;
2652 }
Adam Langleyca058c02020-12-16 10:11:08 -08002653 if (!ssl->quic_method) {
2654 return true;
2655 }
Adam Langleyca058c02020-12-16 10:11:08 -08002656 *out_alert = SSL_AD_MISSING_EXTENSION;
2657 return false;
David Schinazi7ba96a62020-12-14 14:46:56 -08002658 }
David Schinazi3d8b8c32021-01-14 11:25:49 -08002659 // The extensions parser will check for unsolicited extensions before
2660 // calling the callback.
2661 assert(ssl->quic_method != nullptr);
Adam Langleyca058c02020-12-16 10:11:08 -08002662 assert(ssl_protocol_version(ssl) == TLS1_3_VERSION);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002663 assert(used_legacy_codepoint == hs->config->quic_use_legacy_codepoint);
Adam Langleyca058c02020-12-16 10:11:08 -08002664 return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
2665}
2666
David Schinazi3d8b8c32021-01-14 11:25:49 -08002667static bool ext_quic_transport_params_parse_serverhello(SSL_HANDSHAKE *hs,
Adam Langleyca058c02020-12-16 10:11:08 -08002668 uint8_t *out_alert,
2669 CBS *contents) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002670 return ext_quic_transport_params_parse_serverhello_impl(
2671 hs, out_alert, contents, /*used_legacy_codepoint=*/false);
2672}
2673
2674static bool ext_quic_transport_params_parse_serverhello_legacy(
2675 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) {
2676 return ext_quic_transport_params_parse_serverhello_impl(
2677 hs, out_alert, contents, /*used_legacy_codepoint=*/true);
2678}
2679
2680static bool ext_quic_transport_params_parse_clienthello_impl(
2681 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents,
2682 bool used_legacy_codepoint) {
Nick Harper3c034b22017-12-22 15:50:43 -08002683 SSL *const ssl = hs->ssl;
Nick Harper72cff812020-03-26 18:06:16 -07002684 if (!contents) {
2685 if (!ssl->quic_method) {
2686 if (hs->config->quic_transport_params.empty()) {
2687 return true;
2688 }
2689 // QUIC transport parameters must not be set if |ssl| is not configured
2690 // for QUIC.
2691 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2692 *out_alert = SSL_AD_INTERNAL_ERROR;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002693 return false;
2694 }
2695 if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2696 // Silently ignore because we expect the other QUIC codepoint.
2697 return true;
Nick Harper72cff812020-03-26 18:06:16 -07002698 }
2699 *out_alert = SSL_AD_MISSING_EXTENSION;
2700 return false;
2701 }
2702 if (!ssl->quic_method) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002703 if (used_legacy_codepoint) {
2704 // Ignore the legacy private-use codepoint because that could be sent
2705 // to mean something else than QUIC transport parameters.
2706 return true;
2707 }
2708 // Fail if we received the codepoint registered with IANA for QUIC
2709 // because that is not allowed outside of QUIC.
Nick Harper72cff812020-03-26 18:06:16 -07002710 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2711 return false;
Nick Harper3c034b22017-12-22 15:50:43 -08002712 }
Nick Harper80ddfc72020-03-11 18:26:31 -07002713 assert(ssl_protocol_version(ssl) == TLS1_3_VERSION);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002714 if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2715 // Silently ignore because we expect the other QUIC codepoint.
2716 return true;
2717 }
Nick Harper3c034b22017-12-22 15:50:43 -08002718 return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
2719}
2720
David Schinazi3d8b8c32021-01-14 11:25:49 -08002721static bool ext_quic_transport_params_parse_clienthello(SSL_HANDSHAKE *hs,
2722 uint8_t *out_alert,
2723 CBS *contents) {
2724 return ext_quic_transport_params_parse_clienthello_impl(
2725 hs, out_alert, contents, /*used_legacy_codepoint=*/false);
2726}
2727
2728static bool ext_quic_transport_params_parse_clienthello_legacy(
2729 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) {
2730 return ext_quic_transport_params_parse_clienthello_impl(
2731 hs, out_alert, contents, /*used_legacy_codepoint=*/true);
2732}
2733
2734static bool ext_quic_transport_params_add_serverhello_impl(
2735 SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) {
2736 if (hs->ssl->quic_method == nullptr && use_legacy_codepoint) {
2737 // Ignore the legacy private-use codepoint because that could be sent
2738 // to mean something else than QUIC transport parameters.
2739 return true;
2740 }
Nick Harper72cff812020-03-26 18:06:16 -07002741 assert(hs->ssl->quic_method != nullptr);
David Benjamin0ce090a2018-07-02 20:24:40 -04002742 if (hs->config->quic_transport_params.empty()) {
Nick Harper72cff812020-03-26 18:06:16 -07002743 // Transport parameters must be set when using QUIC.
2744 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2745 return false;
Nick Harper3c034b22017-12-22 15:50:43 -08002746 }
David Schinazi3d8b8c32021-01-14 11:25:49 -08002747 if (use_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2748 // Do nothing, we'll send the other codepoint.
2749 return true;
2750 }
2751
David Benjamina1d3bfb2021-06-01 12:12:44 -04002752 uint16_t extension_type = TLSEXT_TYPE_quic_transport_parameters;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002753 if (hs->config->quic_use_legacy_codepoint) {
2754 extension_type = TLSEXT_TYPE_quic_transport_parameters_legacy;
2755 }
Nick Harper3c034b22017-12-22 15:50:43 -08002756
2757 CBB contents;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002758 if (!CBB_add_u16(out, extension_type) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002759 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjamin0ce090a2018-07-02 20:24:40 -04002760 !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(),
2761 hs->config->quic_transport_params.size()) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002762 !CBB_flush(out)) {
2763 return false;
2764 }
2765
2766 return true;
2767}
2768
David Schinazi3d8b8c32021-01-14 11:25:49 -08002769static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs,
2770 CBB *out) {
2771 return ext_quic_transport_params_add_serverhello_impl(
2772 hs, out, /*use_legacy_codepoint=*/false);
2773}
2774
2775static bool ext_quic_transport_params_add_serverhello_legacy(SSL_HANDSHAKE *hs,
2776 CBB *out) {
2777 return ext_quic_transport_params_add_serverhello_impl(
2778 hs, out, /*use_legacy_codepoint=*/true);
2779}
2780
Christopher Patton6c1b3762018-07-17 12:49:41 -07002781// Delegated credentials.
2782//
David Benjamin48b0edf2024-02-11 17:14:41 -05002783// https://www.rfc-editor.org/rfc/rfc9345.html
Christopher Patton6c1b3762018-07-17 12:49:41 -07002784
David Benjamin83a49932021-05-20 15:57:09 -04002785static bool ext_delegated_credential_add_clienthello(
2786 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2787 ssl_client_hello_type_t type) {
Christopher Patton6c1b3762018-07-17 12:49:41 -07002788 return true;
2789}
2790
2791static bool ext_delegated_credential_parse_clienthello(SSL_HANDSHAKE *hs,
2792 uint8_t *out_alert,
2793 CBS *contents) {
Christopher Patton6c1b3762018-07-17 12:49:41 -07002794 if (contents == nullptr || ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
2795 // Don't use delegated credentials unless we're negotiating TLS 1.3 or
2796 // higher.
2797 return true;
2798 }
2799
Watson Ladddcd6e442020-08-10 15:12:45 -04002800 // The contents of the extension are the signature algorithms the client will
2801 // accept for a delegated credential.
2802 CBS sigalg_list;
Bob Beck61725ea2024-11-13 17:50:07 +00002803 if (!CBS_get_u16_length_prefixed(contents, &sigalg_list) || //
2804 CBS_len(&sigalg_list) == 0 || //
2805 CBS_len(contents) != 0 || //
Watson Ladddcd6e442020-08-10 15:12:45 -04002806 !parse_u16_array(&sigalg_list, &hs->peer_delegated_credential_sigalgs)) {
2807 return false;
2808 }
2809
Christopher Patton6c1b3762018-07-17 12:49:41 -07002810 return true;
2811}
2812
Adam Langleya307cb72018-05-02 09:06:48 -07002813// Certificate compression
2814
David Benjamin83a49932021-05-20 15:57:09 -04002815static bool cert_compression_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2816 CBB *out_compressible,
2817 ssl_client_hello_type_t type) {
Adam Langley0080d832018-06-07 16:39:49 -07002818 bool first = true;
2819 CBB contents, algs;
2820
David Benjamin8fe15842019-10-08 16:57:38 -04002821 for (const auto &alg : hs->ssl->ctx->cert_compression_algs) {
2822 if (alg.decompress == nullptr) {
Adam Langley0080d832018-06-07 16:39:49 -07002823 continue;
2824 }
2825
David Benjamin83a49932021-05-20 15:57:09 -04002826 if (first &&
2827 (!CBB_add_u16(out_compressible, TLSEXT_TYPE_cert_compression) ||
2828 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
2829 !CBB_add_u8_length_prefixed(&contents, &algs))) {
Adam Langley0080d832018-06-07 16:39:49 -07002830 return false;
2831 }
2832 first = false;
David Benjamin8fe15842019-10-08 16:57:38 -04002833 if (!CBB_add_u16(&algs, alg.alg_id)) {
Adam Langley0080d832018-06-07 16:39:49 -07002834 return false;
2835 }
2836 }
2837
David Benjamin83a49932021-05-20 15:57:09 -04002838 return first || CBB_flush(out_compressible);
Adam Langleya307cb72018-05-02 09:06:48 -07002839}
2840
2841static bool cert_compression_parse_serverhello(SSL_HANDSHAKE *hs,
2842 uint8_t *out_alert,
2843 CBS *contents) {
2844 if (contents == nullptr) {
2845 return true;
2846 }
2847
2848 // The server may not echo this extension. Any server to client negotiation is
2849 // advertised in the CertificateRequest message.
2850 return false;
2851}
2852
2853static bool cert_compression_parse_clienthello(SSL_HANDSHAKE *hs,
2854 uint8_t *out_alert,
2855 CBS *contents) {
2856 if (contents == nullptr) {
2857 return true;
2858 }
2859
David Benjamin8fe15842019-10-08 16:57:38 -04002860 const SSL_CTX *ctx = hs->ssl->ctx.get();
2861 const size_t num_algs = ctx->cert_compression_algs.size();
Adam Langleya307cb72018-05-02 09:06:48 -07002862
2863 CBS alg_ids;
Bob Beck61725ea2024-11-13 17:50:07 +00002864 if (!CBS_get_u8_length_prefixed(contents, &alg_ids) || //
2865 CBS_len(contents) != 0 || //
2866 CBS_len(&alg_ids) == 0 || //
Adam Langleya307cb72018-05-02 09:06:48 -07002867 CBS_len(&alg_ids) % 2 == 1) {
2868 return false;
2869 }
2870
2871 const size_t num_given_alg_ids = CBS_len(&alg_ids) / 2;
2872 Array<uint16_t> given_alg_ids;
David Benjamince572d62024-10-22 12:35:44 -04002873 if (!given_alg_ids.InitForOverwrite(num_given_alg_ids)) {
Adam Langleya307cb72018-05-02 09:06:48 -07002874 return false;
2875 }
2876
2877 size_t best_index = num_algs;
2878 size_t given_alg_idx = 0;
2879
2880 while (CBS_len(&alg_ids) > 0) {
2881 uint16_t alg_id;
2882 if (!CBS_get_u16(&alg_ids, &alg_id)) {
2883 return false;
2884 }
2885
2886 given_alg_ids[given_alg_idx++] = alg_id;
2887
2888 for (size_t i = 0; i < num_algs; i++) {
David Benjamin8fe15842019-10-08 16:57:38 -04002889 const auto &alg = ctx->cert_compression_algs[i];
2890 if (alg.alg_id == alg_id && alg.compress != nullptr) {
Adam Langleya307cb72018-05-02 09:06:48 -07002891 if (i < best_index) {
2892 best_index = i;
2893 }
2894 break;
2895 }
2896 }
2897 }
2898
2899 qsort(given_alg_ids.data(), given_alg_ids.size(), sizeof(uint16_t),
2900 compare_uint16_t);
2901 for (size_t i = 1; i < num_given_alg_ids; i++) {
2902 if (given_alg_ids[i - 1] == given_alg_ids[i]) {
2903 return false;
2904 }
2905 }
2906
2907 if (best_index < num_algs &&
2908 ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
2909 hs->cert_compression_negotiated = true;
David Benjamin8fe15842019-10-08 16:57:38 -04002910 hs->cert_compression_alg_id = ctx->cert_compression_algs[best_index].alg_id;
Adam Langleya307cb72018-05-02 09:06:48 -07002911 }
2912
2913 return true;
2914}
2915
2916static bool cert_compression_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
2917 return true;
2918}
Nick Harper3c034b22017-12-22 15:50:43 -08002919
Steven Valdez51607f12020-08-05 10:46:05 -04002920// Application-level Protocol Settings
2921//
2922// https://tools.ietf.org/html/draft-vvv-tls-alps-01
2923
David Benjamin4e93cd42021-05-18 13:38:25 -04002924bool ssl_get_local_application_settings(const SSL_HANDSHAKE *hs,
2925 Span<const uint8_t> *out_settings,
2926 Span<const uint8_t> protocol) {
2927 for (const ALPSConfig &config : hs->config->alps_configs) {
2928 if (protocol == config.protocol) {
2929 *out_settings = config.settings;
2930 return true;
2931 }
2932 }
2933 return false;
2934}
2935
Victor Tan558960d2023-06-23 15:04:33 +00002936static bool ext_alps_add_clienthello_impl(const SSL_HANDSHAKE *hs, CBB *out,
2937 CBB *out_compressible,
2938 ssl_client_hello_type_t type,
2939 bool use_new_codepoint) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002940 const SSL *const ssl = hs->ssl;
Bob Beck61725ea2024-11-13 17:50:07 +00002941 if ( // ALPS requires TLS 1.3.
Steven Valdez51607f12020-08-05 10:46:05 -04002942 hs->max_version < TLS1_3_VERSION ||
2943 // Do not offer ALPS without ALPN.
2944 hs->config->alpn_client_proto_list.empty() ||
2945 // Do not offer ALPS if not configured.
2946 hs->config->alps_configs.empty() ||
2947 // Do not offer ALPS on renegotiation handshakes.
2948 ssl->s3->initial_handshake_complete) {
2949 return true;
2950 }
2951
Victor Tan558960d2023-06-23 15:04:33 +00002952 if (use_new_codepoint != hs->config->alps_use_new_codepoint) {
2953 // Do nothing, we'll send the other codepoint.
2954 return true;
2955 }
2956
2957 uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
2958 if (hs->config->alps_use_new_codepoint) {
2959 extension_type = TLSEXT_TYPE_application_settings;
2960 }
2961
Steven Valdez51607f12020-08-05 10:46:05 -04002962 CBB contents, proto_list, proto;
Victor Tan558960d2023-06-23 15:04:33 +00002963 if (!CBB_add_u16(out_compressible, extension_type) ||
David Benjamin83a49932021-05-20 15:57:09 -04002964 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Steven Valdez51607f12020-08-05 10:46:05 -04002965 !CBB_add_u16_length_prefixed(&contents, &proto_list)) {
2966 return false;
2967 }
2968
2969 for (const ALPSConfig &config : hs->config->alps_configs) {
2970 if (!CBB_add_u8_length_prefixed(&proto_list, &proto) ||
2971 !CBB_add_bytes(&proto, config.protocol.data(),
2972 config.protocol.size())) {
2973 return false;
2974 }
2975 }
2976
David Benjamin83a49932021-05-20 15:57:09 -04002977 return CBB_flush(out_compressible);
Steven Valdez51607f12020-08-05 10:46:05 -04002978}
2979
Victor Tan558960d2023-06-23 15:04:33 +00002980static bool ext_alps_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2981 CBB *out_compressible,
2982 ssl_client_hello_type_t type) {
2983 return ext_alps_add_clienthello_impl(hs, out, out_compressible, type,
2984 /*use_new_codepoint=*/true);
2985}
2986
2987static bool ext_alps_add_clienthello_old(const SSL_HANDSHAKE *hs, CBB *out,
2988 CBB *out_compressible,
2989 ssl_client_hello_type_t type) {
2990 return ext_alps_add_clienthello_impl(hs, out, out_compressible, type,
2991 /*use_new_codepoint=*/false);
2992}
2993
2994static bool ext_alps_parse_serverhello_impl(SSL_HANDSHAKE *hs,
Bob Beck61725ea2024-11-13 17:50:07 +00002995 uint8_t *out_alert, CBS *contents,
Victor Tan558960d2023-06-23 15:04:33 +00002996 bool use_new_codepoint) {
Steven Valdez51607f12020-08-05 10:46:05 -04002997 SSL *const ssl = hs->ssl;
2998 if (contents == nullptr) {
2999 return true;
3000 }
3001
3002 assert(!ssl->s3->initial_handshake_complete);
3003 assert(!hs->config->alpn_client_proto_list.empty());
3004 assert(!hs->config->alps_configs.empty());
Victor Tan558960d2023-06-23 15:04:33 +00003005 assert(use_new_codepoint == hs->config->alps_use_new_codepoint);
Steven Valdez51607f12020-08-05 10:46:05 -04003006
3007 // ALPS requires TLS 1.3.
3008 if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
3009 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
3010 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
3011 return false;
3012 }
3013
3014 // Note extension callbacks may run in any order, so we defer checking
3015 // consistency with ALPN to |ssl_check_serverhello_tlsext|.
3016 if (!hs->new_session->peer_application_settings.CopyFrom(*contents)) {
3017 *out_alert = SSL_AD_INTERNAL_ERROR;
3018 return false;
3019 }
3020
3021 hs->new_session->has_application_settings = true;
3022 return true;
3023}
3024
Bob Beck61725ea2024-11-13 17:50:07 +00003025static bool ext_alps_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
Victor Tan558960d2023-06-23 15:04:33 +00003026 CBS *contents) {
3027 return ext_alps_parse_serverhello_impl(hs, out_alert, contents,
3028 /*use_new_codepoint=*/true);
3029}
3030
3031static bool ext_alps_parse_serverhello_old(SSL_HANDSHAKE *hs,
Bob Beck61725ea2024-11-13 17:50:07 +00003032 uint8_t *out_alert, CBS *contents) {
Victor Tan558960d2023-06-23 15:04:33 +00003033 return ext_alps_parse_serverhello_impl(hs, out_alert, contents,
3034 /*use_new_codepoint=*/false);
3035}
3036
3037static bool ext_alps_add_serverhello_impl(SSL_HANDSHAKE *hs, CBB *out,
3038 bool use_new_codepoint) {
Steven Valdez51607f12020-08-05 10:46:05 -04003039 SSL *const ssl = hs->ssl;
3040 // If early data is accepted, we omit the ALPS extension. It is implicitly
3041 // carried over from the previous connection.
3042 if (hs->new_session == nullptr ||
3043 !hs->new_session->has_application_settings ||
3044 ssl->s3->early_data_accepted) {
3045 return true;
3046 }
3047
Bob Beck61725ea2024-11-13 17:50:07 +00003048 if (use_new_codepoint != hs->config->alps_use_new_codepoint) {
Victor Tan558960d2023-06-23 15:04:33 +00003049 // Do nothing, we'll send the other codepoint.
3050 return true;
3051 }
3052
3053 uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
3054 if (hs->config->alps_use_new_codepoint) {
3055 extension_type = TLSEXT_TYPE_application_settings;
3056 }
3057
Steven Valdez51607f12020-08-05 10:46:05 -04003058 CBB contents;
Victor Tan558960d2023-06-23 15:04:33 +00003059 if (!CBB_add_u16(out, extension_type) ||
Steven Valdez51607f12020-08-05 10:46:05 -04003060 !CBB_add_u16_length_prefixed(out, &contents) ||
3061 !CBB_add_bytes(&contents,
3062 hs->new_session->local_application_settings.data(),
3063 hs->new_session->local_application_settings.size()) ||
3064 !CBB_flush(out)) {
3065 return false;
3066 }
3067
3068 return true;
3069}
3070
Victor Tan558960d2023-06-23 15:04:33 +00003071static bool ext_alps_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
3072 return ext_alps_add_serverhello_impl(hs, out, /*use_new_codepoint=*/true);
3073}
3074
3075static bool ext_alps_add_serverhello_old(SSL_HANDSHAKE *hs, CBB *out) {
3076 return ext_alps_add_serverhello_impl(hs, out, /*use_new_codepoint=*/false);
3077}
3078
Steven Valdez51607f12020-08-05 10:46:05 -04003079bool ssl_negotiate_alps(SSL_HANDSHAKE *hs, uint8_t *out_alert,
3080 const SSL_CLIENT_HELLO *client_hello) {
3081 SSL *const ssl = hs->ssl;
3082 if (ssl->s3->alpn_selected.empty()) {
3083 return true;
3084 }
3085
3086 // If we negotiate ALPN over TLS 1.3, try to negotiate ALPS.
3087 CBS alps_contents;
3088 Span<const uint8_t> settings;
Victor Tan558960d2023-06-23 15:04:33 +00003089 uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
3090 if (hs->config->alps_use_new_codepoint) {
3091 extension_type = TLSEXT_TYPE_application_settings;
3092 }
Steven Valdez51607f12020-08-05 10:46:05 -04003093 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION &&
3094 ssl_get_local_application_settings(hs, &settings,
3095 ssl->s3->alpn_selected) &&
3096 ssl_client_hello_get_extension(client_hello, &alps_contents,
Victor Tan558960d2023-06-23 15:04:33 +00003097 extension_type)) {
Steven Valdez51607f12020-08-05 10:46:05 -04003098 // Check if the client supports ALPS with the selected ALPN.
3099 bool found = false;
3100 CBS alps_list;
Bob Beck61725ea2024-11-13 17:50:07 +00003101 if (!CBS_get_u16_length_prefixed(&alps_contents, &alps_list) || //
3102 CBS_len(&alps_contents) != 0 || //
Steven Valdez51607f12020-08-05 10:46:05 -04003103 CBS_len(&alps_list) == 0) {
3104 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
3105 *out_alert = SSL_AD_DECODE_ERROR;
3106 return false;
3107 }
3108 while (CBS_len(&alps_list) > 0) {
3109 CBS protocol_name;
3110 if (!CBS_get_u8_length_prefixed(&alps_list, &protocol_name) ||
3111 // Empty protocol names are forbidden.
3112 CBS_len(&protocol_name) == 0) {
3113 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
3114 *out_alert = SSL_AD_DECODE_ERROR;
3115 return false;
3116 }
3117 if (protocol_name == MakeConstSpan(ssl->s3->alpn_selected)) {
3118 found = true;
3119 }
3120 }
3121
3122 // Negotiate ALPS if both client also supports ALPS for this protocol.
3123 if (found) {
3124 hs->new_session->has_application_settings = true;
3125 if (!hs->new_session->local_application_settings.CopyFrom(settings)) {
3126 *out_alert = SSL_AD_INTERNAL_ERROR;
3127 return false;
3128 }
3129 }
3130 }
3131
3132 return true;
3133}
Adam Langleya86c6982019-07-16 15:26:21 -07003134
David Benjaminc11ea9422017-08-29 16:33:21 -04003135// kExtensions contains all the supported extensions.
Adam Langley614c66a2015-06-12 15:26:58 -07003136static const struct tls_extension kExtensions[] = {
Bob Beck61725ea2024-11-13 17:50:07 +00003137 {
3138 TLSEXT_TYPE_server_name,
3139 ext_sni_add_clienthello,
3140 ext_sni_parse_serverhello,
3141 ext_sni_parse_clienthello,
3142 ext_sni_add_serverhello,
3143 },
3144 {
3145 TLSEXT_TYPE_encrypted_client_hello,
3146 ext_ech_add_clienthello,
3147 ext_ech_parse_serverhello,
3148 ext_ech_parse_clienthello,
3149 ext_ech_add_serverhello,
3150 },
3151 {
3152 TLSEXT_TYPE_extended_master_secret,
3153 ext_ems_add_clienthello,
3154 ext_ems_parse_serverhello,
3155 ext_ems_parse_clienthello,
3156 ext_ems_add_serverhello,
3157 },
3158 {
3159 TLSEXT_TYPE_renegotiate,
3160 ext_ri_add_clienthello,
3161 ext_ri_parse_serverhello,
3162 ext_ri_parse_clienthello,
3163 ext_ri_add_serverhello,
3164 },
3165 {
3166 TLSEXT_TYPE_supported_groups,
3167 ext_supported_groups_add_clienthello,
3168 ext_supported_groups_parse_serverhello,
3169 ext_supported_groups_parse_clienthello,
3170 dont_add_serverhello,
3171 },
3172 {
3173 TLSEXT_TYPE_ec_point_formats,
3174 ext_ec_point_add_clienthello,
3175 ext_ec_point_parse_serverhello,
3176 ext_ec_point_parse_clienthello,
3177 ext_ec_point_add_serverhello,
3178 },
3179 {
3180 TLSEXT_TYPE_session_ticket,
3181 ext_ticket_add_clienthello,
3182 ext_ticket_parse_serverhello,
3183 // Ticket extension client parsing is handled in ssl_session.c
3184 ignore_parse_clienthello,
3185 ext_ticket_add_serverhello,
3186 },
3187 {
3188 TLSEXT_TYPE_application_layer_protocol_negotiation,
3189 ext_alpn_add_clienthello,
3190 ext_alpn_parse_serverhello,
3191 // ALPN is negotiated late in |ssl_negotiate_alpn|.
3192 ignore_parse_clienthello,
3193 ext_alpn_add_serverhello,
3194 },
3195 {
3196 TLSEXT_TYPE_status_request,
3197 ext_ocsp_add_clienthello,
3198 ext_ocsp_parse_serverhello,
3199 ext_ocsp_parse_clienthello,
3200 ext_ocsp_add_serverhello,
3201 },
3202 {
3203 TLSEXT_TYPE_signature_algorithms,
3204 ext_sigalgs_add_clienthello,
3205 forbid_parse_serverhello,
3206 ext_sigalgs_parse_clienthello,
3207 dont_add_serverhello,
3208 },
3209 {
3210 TLSEXT_TYPE_next_proto_neg,
3211 ext_npn_add_clienthello,
3212 ext_npn_parse_serverhello,
3213 ext_npn_parse_clienthello,
3214 ext_npn_add_serverhello,
3215 },
3216 {
3217 TLSEXT_TYPE_certificate_timestamp,
3218 ext_sct_add_clienthello,
3219 ext_sct_parse_serverhello,
3220 ext_sct_parse_clienthello,
3221 ext_sct_add_serverhello,
3222 },
3223 {
3224 TLSEXT_TYPE_channel_id,
3225 ext_channel_id_add_clienthello,
3226 ext_channel_id_parse_serverhello,
3227 ext_channel_id_parse_clienthello,
3228 ext_channel_id_add_serverhello,
3229 },
3230 {
3231 TLSEXT_TYPE_srtp,
3232 ext_srtp_add_clienthello,
3233 ext_srtp_parse_serverhello,
3234 ext_srtp_parse_clienthello,
3235 ext_srtp_add_serverhello,
3236 },
3237 {
3238 TLSEXT_TYPE_key_share,
3239 ext_key_share_add_clienthello,
3240 forbid_parse_serverhello,
3241 ignore_parse_clienthello,
3242 dont_add_serverhello,
3243 },
3244 {
3245 TLSEXT_TYPE_psk_key_exchange_modes,
3246 ext_psk_key_exchange_modes_add_clienthello,
3247 forbid_parse_serverhello,
3248 ext_psk_key_exchange_modes_parse_clienthello,
3249 dont_add_serverhello,
3250 },
3251 {
3252 TLSEXT_TYPE_early_data,
3253 ext_early_data_add_clienthello,
3254 ext_early_data_parse_serverhello,
3255 ext_early_data_parse_clienthello,
3256 ext_early_data_add_serverhello,
3257 },
3258 {
3259 TLSEXT_TYPE_supported_versions,
3260 ext_supported_versions_add_clienthello,
3261 forbid_parse_serverhello,
3262 ignore_parse_clienthello,
3263 dont_add_serverhello,
3264 },
3265 {
3266 TLSEXT_TYPE_cookie,
3267 ext_cookie_add_clienthello,
3268 forbid_parse_serverhello,
3269 ignore_parse_clienthello,
3270 dont_add_serverhello,
3271 },
3272 {
3273 TLSEXT_TYPE_quic_transport_parameters,
3274 ext_quic_transport_params_add_clienthello,
3275 ext_quic_transport_params_parse_serverhello,
3276 ext_quic_transport_params_parse_clienthello,
3277 ext_quic_transport_params_add_serverhello,
3278 },
3279 {
3280 TLSEXT_TYPE_quic_transport_parameters_legacy,
3281 ext_quic_transport_params_add_clienthello_legacy,
3282 ext_quic_transport_params_parse_serverhello_legacy,
3283 ext_quic_transport_params_parse_clienthello_legacy,
3284 ext_quic_transport_params_add_serverhello_legacy,
3285 },
3286 {
3287 TLSEXT_TYPE_cert_compression,
3288 cert_compression_add_clienthello,
3289 cert_compression_parse_serverhello,
3290 cert_compression_parse_clienthello,
3291 cert_compression_add_serverhello,
3292 },
3293 {
3294 TLSEXT_TYPE_delegated_credential,
3295 ext_delegated_credential_add_clienthello,
3296 forbid_parse_serverhello,
3297 ext_delegated_credential_parse_clienthello,
3298 dont_add_serverhello,
3299 },
3300 {
3301 TLSEXT_TYPE_application_settings,
3302 ext_alps_add_clienthello,
3303 ext_alps_parse_serverhello,
3304 // ALPS is negotiated late in |ssl_negotiate_alpn|.
3305 ignore_parse_clienthello,
3306 ext_alps_add_serverhello,
3307 },
3308 {
3309 TLSEXT_TYPE_application_settings_old,
3310 ext_alps_add_clienthello_old,
3311 ext_alps_parse_serverhello_old,
3312 // ALPS is negotiated late in |ssl_negotiate_alpn|.
3313 ignore_parse_clienthello,
3314 ext_alps_add_serverhello_old,
3315 },
3316 {
3317 TLSEXT_TYPE_certificate_authorities,
3318 ext_certificate_authorities_add_clienthello,
3319 forbid_parse_serverhello,
3320 ext_certificate_authorities_parse_clienthello,
3321 dont_add_serverhello,
3322 },
Adam Langley614c66a2015-06-12 15:26:58 -07003323};
3324
3325#define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
3326
David Benjamina3d76d02017-07-14 19:36:07 -04003327static_assert(kNumExtensions <=
3328 sizeof(((SSL_HANDSHAKE *)NULL)->extensions.sent) * 8,
3329 "too many extensions for sent bitset");
3330static_assert(kNumExtensions <=
3331 sizeof(((SSL_HANDSHAKE *)NULL)->extensions.received) * 8,
3332 "too many extensions for received bitset");
Adam Langley4cfa96b2015-07-01 11:56:55 -07003333
David Benjamine9c5d722021-06-09 17:43:16 -04003334bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs) {
3335 if (!hs->config->permute_extensions) {
3336 return true;
3337 }
3338
3339 static_assert(kNumExtensions <= UINT8_MAX,
3340 "extensions_permutation type is too small");
3341 uint32_t seeds[kNumExtensions - 1];
3342 Array<uint8_t> permutation;
3343 if (!RAND_bytes(reinterpret_cast<uint8_t *>(seeds), sizeof(seeds)) ||
David Benjamince572d62024-10-22 12:35:44 -04003344 !permutation.InitForOverwrite(kNumExtensions)) {
David Benjamine9c5d722021-06-09 17:43:16 -04003345 return false;
3346 }
3347 for (size_t i = 0; i < kNumExtensions; i++) {
3348 permutation[i] = i;
3349 }
3350 for (size_t i = kNumExtensions - 1; i > 0; i--) {
3351 // Set element |i| to a randomly-selected element 0 <= j <= i.
3352 std::swap(permutation[i], permutation[seeds[i - 1] % (i + 1)]);
3353 }
3354 hs->extension_permutation = std::move(permutation);
3355 return true;
3356}
3357
Adam Langley614c66a2015-06-12 15:26:58 -07003358static const struct tls_extension *tls_extension_find(uint32_t *out_index,
3359 uint16_t value) {
3360 unsigned i;
3361 for (i = 0; i < kNumExtensions; i++) {
3362 if (kExtensions[i].value == value) {
3363 *out_index = i;
3364 return &kExtensions[i];
3365 }
3366 }
3367
3368 return NULL;
3369}
3370
David Benjaminfb4d2572021-06-01 15:58:30 -04003371static bool add_padding_extension(CBB *cbb, uint16_t ext, size_t len) {
3372 CBB child;
David Benjaminfb4d2572021-06-01 15:58:30 -04003373 if (!CBB_add_u16(cbb, ext) || //
3374 !CBB_add_u16_length_prefixed(cbb, &child) ||
David Benjamin95450622021-07-16 18:24:02 -04003375 !CBB_add_zeros(&child, len)) {
David Benjaminfb4d2572021-06-01 15:58:30 -04003376 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3377 return false;
3378 }
David Benjaminfb4d2572021-06-01 15:58:30 -04003379 return CBB_flush(cbb);
3380}
3381
David Benjamin83a49932021-05-20 15:57:09 -04003382static bool ssl_add_clienthello_tlsext_inner(SSL_HANDSHAKE *hs, CBB *out,
3383 CBB *out_encoded,
3384 bool *out_needs_psk_binder) {
3385 // When writing ClientHelloInner, we construct the real and encoded
3386 // ClientHellos concurrently, to handle compression. Uncompressed extensions
3387 // are written to |extensions| and copied to |extensions_encoded|. Compressed
3388 // extensions are buffered in |compressed| and written to the end. (ECH can
3389 // only compress continguous extensions.)
3390 SSL *const ssl = hs->ssl;
3391 bssl::ScopedCBB compressed, outer_extensions;
3392 CBB extensions, extensions_encoded;
3393 if (!CBB_add_u16_length_prefixed(out, &extensions) ||
3394 !CBB_add_u16_length_prefixed(out_encoded, &extensions_encoded) ||
3395 !CBB_init(compressed.get(), 64) ||
3396 !CBB_init(outer_extensions.get(), 64)) {
3397 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3398 return false;
3399 }
3400
3401 hs->inner_extensions_sent = 0;
3402
3403 if (ssl->ctx->grease_enabled) {
3404 // Add a fake empty extension. See RFC 8701. This always matches
3405 // |ssl_add_clienthello_tlsext|, so compress it.
3406 uint16_t grease_ext = ssl_get_grease_value(hs, ssl_grease_extension1);
3407 if (!add_padding_extension(compressed.get(), grease_ext, 0) ||
3408 !CBB_add_u16(outer_extensions.get(), grease_ext)) {
3409 return false;
3410 }
3411 }
3412
David Benjamine9c5d722021-06-09 17:43:16 -04003413 for (size_t unpermuted = 0; unpermuted < kNumExtensions; unpermuted++) {
3414 size_t i = hs->extension_permutation.empty()
3415 ? unpermuted
3416 : hs->extension_permutation[unpermuted];
David Benjamin83a49932021-05-20 15:57:09 -04003417 const size_t len_before = CBB_len(&extensions);
3418 const size_t len_compressed_before = CBB_len(compressed.get());
3419 if (!kExtensions[i].add_clienthello(hs, &extensions, compressed.get(),
3420 ssl_client_hello_inner)) {
3421 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
3422 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3423 return false;
3424 }
3425
3426 const size_t bytes_written = CBB_len(&extensions) - len_before;
3427 const size_t bytes_written_compressed =
3428 CBB_len(compressed.get()) - len_compressed_before;
3429 // The callback may write to at most one output.
3430 assert(bytes_written == 0 || bytes_written_compressed == 0);
3431 if (bytes_written != 0 || bytes_written_compressed != 0) {
3432 hs->inner_extensions_sent |= (1u << i);
3433 }
3434 // If compressed, update the running ech_outer_extensions extension.
3435 if (bytes_written_compressed != 0 &&
3436 !CBB_add_u16(outer_extensions.get(), kExtensions[i].value)) {
3437 return false;
3438 }
3439 }
3440
3441 if (ssl->ctx->grease_enabled) {
3442 // Add a fake non-empty extension. See RFC 8701. This always matches
3443 // |ssl_add_clienthello_tlsext|, so compress it.
3444 uint16_t grease_ext = ssl_get_grease_value(hs, ssl_grease_extension2);
3445 if (!add_padding_extension(compressed.get(), grease_ext, 1) ||
3446 !CBB_add_u16(outer_extensions.get(), grease_ext)) {
3447 return false;
3448 }
3449 }
3450
David Benjamin83a49932021-05-20 15:57:09 -04003451 // Uncompressed extensions are encoded as-is.
3452 if (!CBB_add_bytes(&extensions_encoded, CBB_data(&extensions),
3453 CBB_len(&extensions))) {
3454 return false;
3455 }
3456
3457 // Flush all the compressed extensions.
3458 if (CBB_len(compressed.get()) != 0) {
3459 CBB extension, child;
3460 // Copy them as-is in the real ClientHelloInner.
3461 if (!CBB_add_bytes(&extensions, CBB_data(compressed.get()),
3462 CBB_len(compressed.get())) ||
3463 // Replace with ech_outer_extensions in the encoded form.
3464 !CBB_add_u16(&extensions_encoded, TLSEXT_TYPE_ech_outer_extensions) ||
3465 !CBB_add_u16_length_prefixed(&extensions_encoded, &extension) ||
3466 !CBB_add_u8_length_prefixed(&extension, &child) ||
3467 !CBB_add_bytes(&child, CBB_data(outer_extensions.get()),
3468 CBB_len(outer_extensions.get())) ||
3469 !CBB_flush(&extensions_encoded)) {
3470 return false;
3471 }
3472 }
3473
3474 // The PSK extension must be last. It is never compressed. Note, if there is a
3475 // binder, the caller will need to update both ClientHelloInner and
3476 // EncodedClientHelloInner after computing it.
3477 const size_t len_before = CBB_len(&extensions);
3478 if (!ext_pre_shared_key_add_clienthello(hs, &extensions, out_needs_psk_binder,
3479 ssl_client_hello_inner) ||
3480 !CBB_add_bytes(&extensions_encoded, CBB_data(&extensions) + len_before,
3481 CBB_len(&extensions) - len_before) ||
3482 !CBB_flush(out) || //
3483 !CBB_flush(out_encoded)) {
3484 return false;
3485 }
3486
3487 return true;
3488}
3489
3490bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, CBB *out_encoded,
3491 bool *out_needs_psk_binder,
David Benjamin18b68362021-06-18 23:13:46 -04003492 ssl_client_hello_type_t type,
3493 size_t header_len) {
David Benjamin83a49932021-05-20 15:57:09 -04003494 *out_needs_psk_binder = false;
3495
3496 if (type == ssl_client_hello_inner) {
3497 return ssl_add_clienthello_tlsext_inner(hs, out, out_encoded,
3498 out_needs_psk_binder);
3499 }
3500
3501 assert(out_encoded == nullptr); // Only ClientHelloInner needs two outputs.
David Benjamin8c880a22016-12-03 02:20:34 -05003502 SSL *const ssl = hs->ssl;
David Benjamine8d53502015-10-10 14:13:23 -04003503 CBB extensions;
3504 if (!CBB_add_u16_length_prefixed(out, &extensions)) {
David Benjamin81678aa2017-07-12 22:43:42 -04003505 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04003506 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003507 }
Adam Langley95c29f32014-06-20 12:00:00 -07003508
David Benjamin64770122019-05-04 11:00:04 -05003509 // Note we may send multiple ClientHellos for DTLS HelloVerifyRequest and TLS
3510 // 1.3 HelloRetryRequest. For the latter, the extensions may change, so it is
3511 // important to reset this value.
David Benjamin8c880a22016-12-03 02:20:34 -05003512 hs->extensions.sent = 0;
Adam Langley95c29f32014-06-20 12:00:00 -07003513
David Benjaminfb4d2572021-06-01 15:58:30 -04003514 // Add a fake empty extension. See RFC 8701.
3515 if (ssl->ctx->grease_enabled &&
3516 !add_padding_extension(
3517 &extensions, ssl_get_grease_value(hs, ssl_grease_extension1), 0)) {
3518 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04003519 }
3520
Adam Langley7f4f41f2018-08-23 08:58:49 -07003521 bool last_was_empty = false;
David Benjamine9c5d722021-06-09 17:43:16 -04003522 for (size_t unpermuted = 0; unpermuted < kNumExtensions; unpermuted++) {
3523 size_t i = hs->extension_permutation.empty()
3524 ? unpermuted
3525 : hs->extension_permutation[unpermuted];
David Benjamin18b68362021-06-18 23:13:46 -04003526 const size_t len_before = CBB_len(&extensions);
3527 if (!kExtensions[i].add_clienthello(hs, &extensions, &extensions, type)) {
3528 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
3529 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3530 return false;
David Benjamin83a49932021-05-20 15:57:09 -04003531 }
David Benjamin18b68362021-06-18 23:13:46 -04003532
3533 const size_t bytes_written = CBB_len(&extensions) - len_before;
Adam Langley7f4f41f2018-08-23 08:58:49 -07003534 if (bytes_written != 0) {
David Benjamin8c880a22016-12-03 02:20:34 -05003535 hs->extensions.sent |= (1u << i);
Adam Langley614c66a2015-06-12 15:26:58 -07003536 }
Adam Langley7f4f41f2018-08-23 08:58:49 -07003537 // If the difference in lengths is only four bytes then the extension had
3538 // an empty body.
3539 last_was_empty = (bytes_written == 4);
Adam Langleyfcf25832014-12-18 17:42:32 -08003540 }
Adam Langley75712922014-10-10 16:23:43 -07003541
David Benjamin65ac9972016-09-02 21:35:25 -04003542 if (ssl->ctx->grease_enabled) {
David Benjamin3675eb32021-05-18 14:01:07 -04003543 // Add a fake non-empty extension. See RFC 8701.
David Benjaminfb4d2572021-06-01 15:58:30 -04003544 if (!add_padding_extension(
3545 &extensions, ssl_get_grease_value(hs, ssl_grease_extension2), 1)) {
David Benjamin861abcc2018-07-14 17:40:26 -04003546 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04003547 }
Adam Langley7f4f41f2018-08-23 08:58:49 -07003548 last_was_empty = false;
David Benjamin65ac9972016-09-02 21:35:25 -04003549 }
3550
David Benjamin83a49932021-05-20 15:57:09 -04003551 // In cleartext ClientHellos, we add the padding extension to work around
3552 // bugs. We also apply this padding to ClientHelloOuter, to keep the wire
3553 // images aligned.
3554 size_t psk_extension_len = ext_pre_shared_key_clienthello_length(hs, type);
David Benjamincd890042021-06-02 18:35:31 -04003555 if (!SSL_is_dtls(ssl) && !ssl->quic_method &&
3556 !ssl->s3->used_hello_retry_request) {
David Benjamin18b68362021-06-18 23:13:46 -04003557 header_len +=
3558 SSL3_HM_HEADER_LENGTH + 2 + CBB_len(&extensions) + psk_extension_len;
Adam Langley7f4f41f2018-08-23 08:58:49 -07003559 size_t padding_len = 0;
3560
3561 // The final extension must be non-empty. WebSphere Application
3562 // Server 7.0 is intolerant to the last extension being zero-length. See
3563 // https://crbug.com/363583.
3564 if (last_was_empty && psk_extension_len == 0) {
3565 padding_len = 1;
3566 // The addition of the padding extension may push us into the F5 bug.
3567 header_len += 4 + padding_len;
3568 }
3569
3570 // Add padding to workaround bugs in F5 terminators. See RFC 7685.
3571 //
3572 // NB: because this code works out the length of all existing extensions
3573 // it MUST always appear last (save for any PSK extension).
Adam Langleyfcf25832014-12-18 17:42:32 -08003574 if (header_len > 0xff && header_len < 0x200) {
Adam Langley7f4f41f2018-08-23 08:58:49 -07003575 // If our calculations already included a padding extension, remove that
3576 // factor because we're about to change its length.
3577 if (padding_len != 0) {
3578 header_len -= 4 + padding_len;
3579 }
3580 padding_len = 0x200 - header_len;
David Benjaminc11ea9422017-08-29 16:33:21 -04003581 // Extensions take at least four bytes to encode. Always include at least
3582 // one byte of data if including the extension. WebSphere Application
3583 // Server 7.0 is intolerant to the last extension being zero-length. See
3584 // https://crbug.com/363583.
Adam Langleyfcf25832014-12-18 17:42:32 -08003585 if (padding_len >= 4 + 1) {
3586 padding_len -= 4;
3587 } else {
3588 padding_len = 1;
3589 }
Adam Langley7f4f41f2018-08-23 08:58:49 -07003590 }
Adam Langley95c29f32014-06-20 12:00:00 -07003591
David Benjaminfb4d2572021-06-01 15:58:30 -04003592 if (padding_len != 0 &&
3593 !add_padding_extension(&extensions, TLSEXT_TYPE_padding, padding_len)) {
3594 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003595 }
3596 }
Adam Langley75712922014-10-10 16:23:43 -07003597
David Benjaminc11ea9422017-08-29 16:33:21 -04003598 // The PSK extension must be last, including after the padding.
David Benjamin350fe3b2021-06-02 17:58:53 -04003599 const size_t len_before = CBB_len(&extensions);
David Benjamin83a49932021-05-20 15:57:09 -04003600 if (!ext_pre_shared_key_add_clienthello(hs, &extensions, out_needs_psk_binder,
3601 type)) {
David Benjamin81678aa2017-07-12 22:43:42 -04003602 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04003603 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04003604 }
David Benjamin350fe3b2021-06-02 17:58:53 -04003605 assert(psk_extension_len == CBB_len(&extensions) - len_before);
3606 (void)len_before; // |assert| is omitted in release builds.
Steven Valdeza833c352016-11-01 13:39:36 -04003607
David Benjaminc11ea9422017-08-29 16:33:21 -04003608 // Discard empty extensions blocks.
David Benjamina01deee2015-12-08 18:56:31 -05003609 if (CBB_len(&extensions) == 0) {
David Benjamine8d53502015-10-10 14:13:23 -04003610 CBB_discard_child(out);
Adam Langley33ad2b52015-07-20 17:43:53 -07003611 }
3612
David Benjamine8d53502015-10-10 14:13:23 -04003613 return CBB_flush(out);
Adam Langleyfcf25832014-12-18 17:42:32 -08003614}
Adam Langley95c29f32014-06-20 12:00:00 -07003615
David Benjamin861abcc2018-07-14 17:40:26 -04003616bool ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05003617 SSL *const ssl = hs->ssl;
David Benjamin56380462015-10-10 14:59:09 -04003618 CBB extensions;
3619 if (!CBB_add_u16_length_prefixed(out, &extensions)) {
Adam Langley33ad2b52015-07-20 17:43:53 -07003620 goto err;
Adam Langley614c66a2015-06-12 15:26:58 -07003621 }
3622
David Benjamin8c880a22016-12-03 02:20:34 -05003623 for (unsigned i = 0; i < kNumExtensions; i++) {
3624 if (!(hs->extensions.received & (1u << i))) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003625 // Don't send extensions that were not received.
Adam Langley614c66a2015-06-12 15:26:58 -07003626 continue;
Adam Langleyfcf25832014-12-18 17:42:32 -08003627 }
Adam Langley95c29f32014-06-20 12:00:00 -07003628
David Benjamin8c880a22016-12-03 02:20:34 -05003629 if (!kExtensions[i].add_serverhello(hs, &extensions)) {
Adam Langley33ad2b52015-07-20 17:43:53 -07003630 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003631 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
Adam Langley33ad2b52015-07-20 17:43:53 -07003632 goto err;
Adam Langley614c66a2015-06-12 15:26:58 -07003633 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003634 }
Adam Langley95c29f32014-06-20 12:00:00 -07003635
David Benjaminc11ea9422017-08-29 16:33:21 -04003636 // Discard empty extensions blocks before TLS 1.3.
Bob Beck61725ea2024-11-13 17:50:07 +00003637 if (ssl_protocol_version(ssl) < TLS1_3_VERSION && //
Steven Valdez143e8b32016-07-11 13:19:03 -04003638 CBB_len(&extensions) == 0) {
David Benjamin56380462015-10-10 14:59:09 -04003639 CBB_discard_child(out);
Adam Langley33ad2b52015-07-20 17:43:53 -07003640 }
3641
David Benjamin56380462015-10-10 14:59:09 -04003642 return CBB_flush(out);
Adam Langley33ad2b52015-07-20 17:43:53 -07003643
3644err:
Adam Langley33ad2b52015-07-20 17:43:53 -07003645 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04003646 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003647}
Adam Langley95c29f32014-06-20 12:00:00 -07003648
David Benjamin861abcc2018-07-14 17:40:26 -04003649static bool ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs,
3650 const SSL_CLIENT_HELLO *client_hello,
3651 int *out_alert) {
David Benjamin8c880a22016-12-03 02:20:34 -05003652 hs->extensions.received = 0;
David Benjamine14ff062016-08-09 16:21:24 -04003653 CBS extensions;
3654 CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
3655 while (CBS_len(&extensions) != 0) {
3656 uint16_t type;
3657 CBS extension;
3658
David Benjaminc11ea9422017-08-29 16:33:21 -04003659 // Decode the next extension.
David Benjamine14ff062016-08-09 16:21:24 -04003660 if (!CBS_get_u16(&extensions, &type) ||
3661 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08003662 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003663 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003664 }
Adam Langley95c29f32014-06-20 12:00:00 -07003665
David Benjamine14ff062016-08-09 16:21:24 -04003666 unsigned ext_index;
3667 const struct tls_extension *const ext =
3668 tls_extension_find(&ext_index, type);
David Benjamine14ff062016-08-09 16:21:24 -04003669 if (ext == NULL) {
David Benjamine14ff062016-08-09 16:21:24 -04003670 continue;
3671 }
3672
David Benjamin8c880a22016-12-03 02:20:34 -05003673 hs->extensions.received |= (1u << ext_index);
David Benjamine14ff062016-08-09 16:21:24 -04003674 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003675 if (!ext->parse_clienthello(hs, &alert, &extension)) {
David Benjamine14ff062016-08-09 16:21:24 -04003676 *out_alert = alert;
3677 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003678 ERR_add_error_dataf("extension %u", (unsigned)type);
David Benjamin861abcc2018-07-14 17:40:26 -04003679 return false;
Adam Langley614c66a2015-06-12 15:26:58 -07003680 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003681 }
Adam Langley75712922014-10-10 16:23:43 -07003682
David Benjamin1deb41b2016-08-09 19:36:38 -04003683 for (size_t i = 0; i < kNumExtensions; i++) {
David Benjamin8c880a22016-12-03 02:20:34 -05003684 if (hs->extensions.received & (1u << i)) {
David Benjamin1deb41b2016-08-09 19:36:38 -04003685 continue;
3686 }
3687
3688 CBS *contents = NULL, fake_contents;
3689 static const uint8_t kFakeRenegotiateExtension[] = {0};
3690 if (kExtensions[i].value == TLSEXT_TYPE_renegotiate &&
3691 ssl_client_cipher_list_contains_cipher(client_hello,
3692 SSL3_CK_SCSV & 0xffff)) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003693 // The renegotiation SCSV was received so pretend that we received a
3694 // renegotiation extension.
David Benjamin1deb41b2016-08-09 19:36:38 -04003695 CBS_init(&fake_contents, kFakeRenegotiateExtension,
3696 sizeof(kFakeRenegotiateExtension));
3697 contents = &fake_contents;
David Benjamin8c880a22016-12-03 02:20:34 -05003698 hs->extensions.received |= (1u << i);
David Benjamin1deb41b2016-08-09 19:36:38 -04003699 }
3700
David Benjaminc11ea9422017-08-29 16:33:21 -04003701 // Extension wasn't observed so call the callback with a NULL
3702 // parameter.
David Benjamin1deb41b2016-08-09 19:36:38 -04003703 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003704 if (!kExtensions[i].parse_clienthello(hs, &alert, contents)) {
David Benjamin1deb41b2016-08-09 19:36:38 -04003705 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003706 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
David Benjamin1deb41b2016-08-09 19:36:38 -04003707 *out_alert = alert;
David Benjamin861abcc2018-07-14 17:40:26 -04003708 return false;
Adam Langley614c66a2015-06-12 15:26:58 -07003709 }
3710 }
3711
David Benjamin861abcc2018-07-14 17:40:26 -04003712 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003713}
Adam Langley95c29f32014-06-20 12:00:00 -07003714
David Benjamin861abcc2018-07-14 17:40:26 -04003715bool ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs,
3716 const SSL_CLIENT_HELLO *client_hello) {
David Benjamin8c880a22016-12-03 02:20:34 -05003717 SSL *const ssl = hs->ssl;
Adam Langleyc68e5b92017-02-08 13:33:15 -08003718 int alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003719 if (!ssl_scan_clienthello_tlsext(hs, client_hello, &alert)) {
David Benjamind1e3ce12017-10-06 18:31:15 -04003720 ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
David Benjamin861abcc2018-07-14 17:40:26 -04003721 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003722 }
Adam Langley95c29f32014-06-20 12:00:00 -07003723
David Benjamin861abcc2018-07-14 17:40:26 -04003724 if (!ssl_check_clienthello_tlsext(hs)) {
David Benjamin3570d732015-06-29 00:28:17 -04003725 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_TLSEXT);
David Benjamin861abcc2018-07-14 17:40:26 -04003726 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003727 }
Adam Langley95c29f32014-06-20 12:00:00 -07003728
David Benjamin861abcc2018-07-14 17:40:26 -04003729 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003730}
Adam Langley95c29f32014-06-20 12:00:00 -07003731
David Benjamine2cb4232021-06-23 18:14:22 -04003732static bool ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs,
David Benjamin861abcc2018-07-14 17:40:26 -04003733 int *out_alert) {
David Benjamine2cb4232021-06-23 18:14:22 -04003734 CBS extensions = *cbs;
3735 if (!tls1_check_duplicate_extensions(&extensions)) {
Steven Valdez143e8b32016-07-11 13:19:03 -04003736 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003737 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04003738 }
3739
3740 uint32_t received = 0;
3741 while (CBS_len(&extensions) != 0) {
3742 uint16_t type;
3743 CBS extension;
3744
David Benjaminc11ea9422017-08-29 16:33:21 -04003745 // Decode the next extension.
Steven Valdez143e8b32016-07-11 13:19:03 -04003746 if (!CBS_get_u16(&extensions, &type) ||
3747 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08003748 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003749 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003750 }
Adam Langley95c29f32014-06-20 12:00:00 -07003751
Steven Valdez143e8b32016-07-11 13:19:03 -04003752 unsigned ext_index;
3753 const struct tls_extension *const ext =
3754 tls_extension_find(&ext_index, type);
Adam Langley614c66a2015-06-12 15:26:58 -07003755
Steven Valdez143e8b32016-07-11 13:19:03 -04003756 if (ext == NULL) {
David Benjamin0a3e07a2018-07-09 16:28:22 -04003757 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
3758 ERR_add_error_dataf("extension %u", (unsigned)type);
3759 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
David Benjamin861abcc2018-07-14 17:40:26 -04003760 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04003761 }
Adam Langley33ad2b52015-07-20 17:43:53 -07003762
David Benjamina3d76d02017-07-14 19:36:07 -04003763 static_assert(kNumExtensions <= sizeof(hs->extensions.sent) * 8,
3764 "too many bits");
David Benjamin5db7c9b2017-01-24 16:17:03 -05003765
David Benjaminc59b9aa2018-07-16 21:34:03 -04003766 if (!(hs->extensions.sent & (1u << ext_index))) {
3767 // If the extension was never sent then it is illegal.
Steven Valdez143e8b32016-07-11 13:19:03 -04003768 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
3769 ERR_add_error_dataf("extension :%u", (unsigned)type);
David Benjamin0c40a962016-08-01 12:05:50 -04003770 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
David Benjamin861abcc2018-07-14 17:40:26 -04003771 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04003772 }
Adam Langley33ad2b52015-07-20 17:43:53 -07003773
Steven Valdez143e8b32016-07-11 13:19:03 -04003774 received |= (1u << ext_index);
Adam Langley09505632015-07-30 18:10:13 -07003775
Steven Valdez143e8b32016-07-11 13:19:03 -04003776 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003777 if (!ext->parse_serverhello(hs, &alert, &extension)) {
Steven Valdez143e8b32016-07-11 13:19:03 -04003778 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003779 ERR_add_error_dataf("extension %u", (unsigned)type);
Steven Valdez143e8b32016-07-11 13:19:03 -04003780 *out_alert = alert;
David Benjamin861abcc2018-07-14 17:40:26 -04003781 return false;
Adam Langley614c66a2015-06-12 15:26:58 -07003782 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003783 }
Adam Langley95c29f32014-06-20 12:00:00 -07003784
David Benjamin54091232016-09-05 12:47:25 -04003785 for (size_t i = 0; i < kNumExtensions; i++) {
Adam Langley614c66a2015-06-12 15:26:58 -07003786 if (!(received & (1u << i))) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003787 // Extension wasn't observed so call the callback with a NULL
3788 // parameter.
Adam Langley614c66a2015-06-12 15:26:58 -07003789 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003790 if (!kExtensions[i].parse_serverhello(hs, &alert, NULL)) {
Adam Langley33ad2b52015-07-20 17:43:53 -07003791 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003792 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
Adam Langley614c66a2015-06-12 15:26:58 -07003793 *out_alert = alert;
David Benjamin861abcc2018-07-14 17:40:26 -04003794 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003795 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003796 }
3797 }
Adam Langley95c29f32014-06-20 12:00:00 -07003798
David Benjamin861abcc2018-07-14 17:40:26 -04003799 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003800}
Adam Langley95c29f32014-06-20 12:00:00 -07003801
David Benjamin861abcc2018-07-14 17:40:26 -04003802static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) {
David Benjamin8c880a22016-12-03 02:20:34 -05003803 SSL *const ssl = hs->ssl;
Adam Langleyfcf25832014-12-18 17:42:32 -08003804 int ret = SSL_TLSEXT_ERR_NOACK;
3805 int al = SSL_AD_UNRECOGNIZED_NAME;
David Benjamin46853762018-07-03 14:01:26 -04003806 if (ssl->ctx->servername_callback != 0) {
3807 ret = ssl->ctx->servername_callback(ssl, &al, ssl->ctx->servername_arg);
3808 } else if (ssl->session_ctx->servername_callback != 0) {
3809 ret = ssl->session_ctx->servername_callback(
3810 ssl, &al, ssl->session_ctx->servername_arg);
Adam Langleyfcf25832014-12-18 17:42:32 -08003811 }
Adam Langley95c29f32014-06-20 12:00:00 -07003812
Adam Langleyfcf25832014-12-18 17:42:32 -08003813 switch (ret) {
3814 case SSL_TLSEXT_ERR_ALERT_FATAL:
David Benjamind1e3ce12017-10-06 18:31:15 -04003815 ssl_send_alert(ssl, SSL3_AL_FATAL, al);
David Benjamin861abcc2018-07-14 17:40:26 -04003816 return false;
Adam Langley95c29f32014-06-20 12:00:00 -07003817
Adam Langleyfcf25832014-12-18 17:42:32 -08003818 case SSL_TLSEXT_ERR_NOACK:
David Benjaminfd45ee72017-08-31 14:49:09 -04003819 hs->should_ack_sni = false;
David Benjamin861abcc2018-07-14 17:40:26 -04003820 return true;
Adam Langley95c29f32014-06-20 12:00:00 -07003821
Adam Langleyfcf25832014-12-18 17:42:32 -08003822 default:
David Benjamin096ded92024-07-16 14:48:02 -04003823 hs->should_ack_sni = ssl->s3->hostname != nullptr;
David Benjamin861abcc2018-07-14 17:40:26 -04003824 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003825 }
3826}
Adam Langleyed8270a2014-09-02 13:52:56 -07003827
Steven Valdez51607f12020-08-05 10:46:05 -04003828static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs) {
3829 SSL *const ssl = hs->ssl;
3830 // ALPS and ALPN have a dependency between each other, so we defer checking
3831 // consistency to after the callbacks run.
3832 if (hs->new_session != nullptr && hs->new_session->has_application_settings) {
3833 // ALPN must be negotiated.
3834 if (ssl->s3->alpn_selected.empty()) {
3835 OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_ALPS_WITHOUT_ALPN);
3836 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
3837 return false;
3838 }
3839
3840 // The negotiated protocol must be one of the ones we advertised for ALPS.
3841 Span<const uint8_t> settings;
3842 if (!ssl_get_local_application_settings(hs, &settings,
3843 ssl->s3->alpn_selected)) {
3844 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
3845 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
3846 return false;
3847 }
3848
3849 if (!hs->new_session->local_application_settings.CopyFrom(settings)) {
3850 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
3851 return false;
3852 }
3853 }
3854
3855 return true;
3856}
3857
David Benjamine2cb4232021-06-23 18:14:22 -04003858bool ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs) {
David Benjamin8c880a22016-12-03 02:20:34 -05003859 SSL *const ssl = hs->ssl;
Adam Langleyc68e5b92017-02-08 13:33:15 -08003860 int alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003861 if (!ssl_scan_serverhello_tlsext(hs, cbs, &alert)) {
David Benjamind1e3ce12017-10-06 18:31:15 -04003862 ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
David Benjamin861abcc2018-07-14 17:40:26 -04003863 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003864 }
3865
Steven Valdez51607f12020-08-05 10:46:05 -04003866 if (!ssl_check_serverhello_tlsext(hs)) {
3867 return false;
3868 }
3869
David Benjamin861abcc2018-07-14 17:40:26 -04003870 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003871}
Adam Langley95c29f32014-06-20 12:00:00 -07003872
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003873static enum ssl_ticket_aead_result_t decrypt_ticket_with_cipher_ctx(
David Benjamin28655672018-07-18 23:23:25 -04003874 Array<uint8_t> *out, EVP_CIPHER_CTX *cipher_ctx, HMAC_CTX *hmac_ctx,
3875 Span<const uint8_t> ticket) {
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003876 size_t iv_len = EVP_CIPHER_CTX_iv_length(cipher_ctx);
Adam Langleyfcf25832014-12-18 17:42:32 -08003877
David Benjaminc11ea9422017-08-29 16:33:21 -04003878 // Check the MAC at the end of the ticket.
David Benjamine3aa1d92015-06-16 15:34:50 -04003879 uint8_t mac[EVP_MAX_MD_SIZE];
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003880 size_t mac_len = HMAC_size(hmac_ctx);
David Benjamin28655672018-07-18 23:23:25 -04003881 if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + iv_len + 1 + mac_len) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003882 // The ticket must be large enough for key name, IV, data, and MAC.
David Benjamin81678aa2017-07-12 22:43:42 -04003883 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003884 }
David Benjamin28655672018-07-18 23:23:25 -04003885 // Split the ticket into the ticket and the MAC.
David Benjamin006f20a2021-06-22 23:00:49 -04003886 auto ticket_mac = ticket.last(mac_len);
3887 ticket = ticket.first(ticket.size() - mac_len);
David Benjamin28655672018-07-18 23:23:25 -04003888 HMAC_Update(hmac_ctx, ticket.data(), ticket.size());
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003889 HMAC_Final(hmac_ctx, mac, NULL);
David Benjamin28655672018-07-18 23:23:25 -04003890 assert(mac_len == ticket_mac.size());
3891 bool mac_ok = CRYPTO_memcmp(mac, ticket_mac.data(), mac_len) == 0;
David Benjaminfbc45d72016-09-22 01:21:24 -04003892#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin861abcc2018-07-14 17:40:26 -04003893 mac_ok = true;
David Benjaminfbc45d72016-09-22 01:21:24 -04003894#endif
3895 if (!mac_ok) {
David Benjamin81678aa2017-07-12 22:43:42 -04003896 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003897 }
3898
David Benjaminc11ea9422017-08-29 16:33:21 -04003899 // Decrypt the session data.
David Benjamin28655672018-07-18 23:23:25 -04003900 auto ciphertext = ticket.subspan(SSL_TICKET_KEY_NAME_LEN + iv_len);
3901 Array<uint8_t> plaintext;
3902#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
3903 if (!plaintext.CopyFrom(ciphertext)) {
David Benjamin81678aa2017-07-12 22:43:42 -04003904 return ssl_ticket_aead_error;
Adam Langleyfcf25832014-12-18 17:42:32 -08003905 }
David Benjaminfbc45d72016-09-22 01:21:24 -04003906#else
David Benjamin28655672018-07-18 23:23:25 -04003907 if (ciphertext.size() >= INT_MAX) {
David Benjamin81678aa2017-07-12 22:43:42 -04003908 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003909 }
David Benjamince572d62024-10-22 12:35:44 -04003910 if (!plaintext.InitForOverwrite(ciphertext.size())) {
David Benjamin28655672018-07-18 23:23:25 -04003911 return ssl_ticket_aead_error;
3912 }
David Benjamine3aa1d92015-06-16 15:34:50 -04003913 int len1, len2;
David Benjamin28655672018-07-18 23:23:25 -04003914 if (!EVP_DecryptUpdate(cipher_ctx, plaintext.data(), &len1, ciphertext.data(),
3915 (int)ciphertext.size()) ||
3916 !EVP_DecryptFinal_ex(cipher_ctx, plaintext.data() + len1, &len2)) {
Adam Langley4c341d02017-03-08 19:33:21 -08003917 ERR_clear_error();
David Benjamin81678aa2017-07-12 22:43:42 -04003918 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003919 }
David Benjamin28655672018-07-18 23:23:25 -04003920 plaintext.Shrink(static_cast<size_t>(len1) + len2);
David Benjaminfbc45d72016-09-22 01:21:24 -04003921#endif
Adam Langleyfcf25832014-12-18 17:42:32 -08003922
David Benjamin28655672018-07-18 23:23:25 -04003923 *out = std::move(plaintext);
David Benjamin81678aa2017-07-12 22:43:42 -04003924 return ssl_ticket_aead_success;
Adam Langley4c341d02017-03-08 19:33:21 -08003925}
3926
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003927static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_cb(
David Benjamin28655672018-07-18 23:23:25 -04003928 SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket,
3929 Span<const uint8_t> ticket) {
3930 assert(ticket.size() >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003931 ScopedEVP_CIPHER_CTX cipher_ctx;
3932 ScopedHMAC_CTX hmac_ctx;
David Benjamin28655672018-07-18 23:23:25 -04003933 auto name = ticket.subspan(0, SSL_TICKET_KEY_NAME_LEN);
3934 // The actual IV is shorter, but the length is determined by the callback's
3935 // chosen cipher. Instead we pass in |EVP_MAX_IV_LENGTH| worth of IV to ensure
3936 // the callback has enough.
3937 auto iv = ticket.subspan(SSL_TICKET_KEY_NAME_LEN, EVP_MAX_IV_LENGTH);
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003938 int cb_ret = hs->ssl->session_ctx->ticket_key_cb(
David Benjamin28655672018-07-18 23:23:25 -04003939 hs->ssl, const_cast<uint8_t *>(name.data()),
3940 const_cast<uint8_t *>(iv.data()), cipher_ctx.get(), hmac_ctx.get(),
3941 0 /* decrypt */);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003942 if (cb_ret < 0) {
3943 return ssl_ticket_aead_error;
3944 } else if (cb_ret == 0) {
3945 return ssl_ticket_aead_ignore_ticket;
3946 } else if (cb_ret == 2) {
David Benjaminfd45ee72017-08-31 14:49:09 -04003947 *out_renew_ticket = true;
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003948 } else {
3949 assert(cb_ret == 1);
3950 }
David Benjamin28655672018-07-18 23:23:25 -04003951 return decrypt_ticket_with_cipher_ctx(out, cipher_ctx.get(), hmac_ctx.get(),
3952 ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003953}
3954
3955static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_ticket_keys(
David Benjamin28655672018-07-18 23:23:25 -04003956 SSL_HANDSHAKE *hs, Array<uint8_t> *out, Span<const uint8_t> ticket) {
3957 assert(ticket.size() >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH);
David Benjamin50596f82018-07-02 19:47:27 -04003958 SSL_CTX *ctx = hs->ssl->session_ctx.get();
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003959
David Benjaminc11ea9422017-08-29 16:33:21 -04003960 // Rotate the ticket key if necessary.
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003961 if (!ssl_ctx_rotate_ticket_encryption_key(ctx)) {
3962 return ssl_ticket_aead_error;
3963 }
3964
David Benjamin28655672018-07-18 23:23:25 -04003965 const EVP_CIPHER *cipher = EVP_aes_128_cbc();
3966 auto name = ticket.subspan(0, SSL_TICKET_KEY_NAME_LEN);
3967 auto iv =
3968 ticket.subspan(SSL_TICKET_KEY_NAME_LEN, EVP_CIPHER_iv_length(cipher));
3969
David Benjaminc11ea9422017-08-29 16:33:21 -04003970 // Pick the matching ticket key and decrypt.
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003971 ScopedEVP_CIPHER_CTX cipher_ctx;
3972 ScopedHMAC_CTX hmac_ctx;
3973 {
3974 MutexReadLock lock(&ctx->lock);
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003975 const TicketKey *key;
David Benjamin28655672018-07-18 23:23:25 -04003976 if (ctx->ticket_key_current && name == ctx->ticket_key_current->name) {
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003977 key = ctx->ticket_key_current.get();
David Benjamin28655672018-07-18 23:23:25 -04003978 } else if (ctx->ticket_key_prev && name == ctx->ticket_key_prev->name) {
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003979 key = ctx->ticket_key_prev.get();
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003980 } else {
3981 return ssl_ticket_aead_ignore_ticket;
3982 }
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003983 if (!HMAC_Init_ex(hmac_ctx.get(), key->hmac_key, sizeof(key->hmac_key),
3984 tlsext_tick_md(), NULL) ||
Bob Beck61725ea2024-11-13 17:50:07 +00003985 !EVP_DecryptInit_ex(cipher_ctx.get(), cipher, NULL, key->aes_key,
3986 iv.data())) {
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003987 return ssl_ticket_aead_error;
3988 }
3989 }
David Benjamin28655672018-07-18 23:23:25 -04003990 return decrypt_ticket_with_cipher_ctx(out, cipher_ctx.get(), hmac_ctx.get(),
3991 ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003992}
3993
Adam Langley4c341d02017-03-08 19:33:21 -08003994static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_method(
David Benjamin28655672018-07-18 23:23:25 -04003995 SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket,
3996 Span<const uint8_t> ticket) {
3997 Array<uint8_t> plaintext;
David Benjamince572d62024-10-22 12:35:44 -04003998 if (!plaintext.InitForOverwrite(ticket.size())) {
Adam Langley4c341d02017-03-08 19:33:21 -08003999 return ssl_ticket_aead_error;
4000 }
4001
4002 size_t plaintext_len;
4003 const enum ssl_ticket_aead_result_t result =
David Benjamin98472cb2018-05-02 16:05:36 -04004004 hs->ssl->session_ctx->ticket_aead_method->open(
David Benjamin28655672018-07-18 23:23:25 -04004005 hs->ssl, plaintext.data(), &plaintext_len, ticket.size(),
4006 ticket.data(), ticket.size());
4007 if (result != ssl_ticket_aead_success) {
4008 return result;
Adam Langley4c341d02017-03-08 19:33:21 -08004009 }
4010
David Benjamin28655672018-07-18 23:23:25 -04004011 plaintext.Shrink(plaintext_len);
4012 *out = std::move(plaintext);
4013 return ssl_ticket_aead_success;
Adam Langley4c341d02017-03-08 19:33:21 -08004014}
4015
4016enum ssl_ticket_aead_result_t ssl_process_ticket(
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07004017 SSL_HANDSHAKE *hs, UniquePtr<SSL_SESSION> *out_session,
David Benjamin28655672018-07-18 23:23:25 -04004018 bool *out_renew_ticket, Span<const uint8_t> ticket,
4019 Span<const uint8_t> session_id) {
David Benjaminb571e772021-03-25 19:42:16 -04004020 SSL *const ssl = hs->ssl;
David Benjaminfd45ee72017-08-31 14:49:09 -04004021 *out_renew_ticket = false;
David Benjamin37af90f2017-07-29 01:42:16 -04004022 out_session->reset();
Adam Langley4c341d02017-03-08 19:33:21 -08004023
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07004024 if ((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) ||
David Benjamin28655672018-07-18 23:23:25 -04004025 session_id.size() > SSL_MAX_SSL_SESSION_ID_LENGTH) {
Adam Langley4c341d02017-03-08 19:33:21 -08004026 return ssl_ticket_aead_ignore_ticket;
4027 }
4028
David Benjaminb571e772021-03-25 19:42:16 -04004029 // Tickets in TLS 1.3 are tied into pre-shared keys (PSKs), unlike in TLS 1.2
4030 // where that concept doesn't exist. The |decrypted_psk| and |ignore_psk|
4031 // hints only apply to PSKs. We check the version to determine which this is.
4032 const bool is_psk = ssl_protocol_version(ssl) >= TLS1_3_VERSION;
4033
David Benjamin28655672018-07-18 23:23:25 -04004034 Array<uint8_t> plaintext;
Adam Langley4c341d02017-03-08 19:33:21 -08004035 enum ssl_ticket_aead_result_t result;
David Benjaminb571e772021-03-25 19:42:16 -04004036 SSL_HANDSHAKE_HINTS *const hints = hs->hints.get();
4037 if (is_psk && hints && !hs->hints_requested &&
4038 !hints->decrypted_psk.empty()) {
4039 result = plaintext.CopyFrom(hints->decrypted_psk) ? ssl_ticket_aead_success
4040 : ssl_ticket_aead_error;
4041 } else if (is_psk && hints && !hs->hints_requested && hints->ignore_psk) {
4042 result = ssl_ticket_aead_ignore_ticket;
David Benjaminadaa3222022-08-02 17:10:53 -07004043 } else if (!is_psk && hints && !hs->hints_requested &&
4044 !hints->decrypted_ticket.empty()) {
4045 if (plaintext.CopyFrom(hints->decrypted_ticket)) {
4046 result = ssl_ticket_aead_success;
4047 *out_renew_ticket = hints->renew_ticket;
4048 } else {
4049 result = ssl_ticket_aead_error;
4050 }
4051 } else if (!is_psk && hints && !hs->hints_requested && hints->ignore_ticket) {
4052 result = ssl_ticket_aead_ignore_ticket;
David Benjaminb571e772021-03-25 19:42:16 -04004053 } else if (ssl->session_ctx->ticket_aead_method != NULL) {
David Benjamin28655672018-07-18 23:23:25 -04004054 result = ssl_decrypt_ticket_with_method(hs, &plaintext, out_renew_ticket,
4055 ticket);
Adam Langley4c341d02017-03-08 19:33:21 -08004056 } else {
David Benjamin7bb0fbf2018-07-03 13:55:42 -04004057 // Ensure there is room for the key name and the largest IV |ticket_key_cb|
4058 // may try to consume. The real limit may be lower, but the maximum IV
4059 // length should be well under the minimum size for the session material and
4060 // HMAC.
David Benjamin28655672018-07-18 23:23:25 -04004061 if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) {
David Benjaminb571e772021-03-25 19:42:16 -04004062 result = ssl_ticket_aead_ignore_ticket;
4063 } else if (ssl->session_ctx->ticket_key_cb != NULL) {
David Benjamin28655672018-07-18 23:23:25 -04004064 result =
4065 ssl_decrypt_ticket_with_cb(hs, &plaintext, out_renew_ticket, ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07004066 } else {
David Benjamin28655672018-07-18 23:23:25 -04004067 result = ssl_decrypt_ticket_with_ticket_keys(hs, &plaintext, ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07004068 }
Adam Langley4c341d02017-03-08 19:33:21 -08004069 }
4070
David Benjaminadaa3222022-08-02 17:10:53 -07004071 if (hints && hs->hints_requested) {
David Benjaminb571e772021-03-25 19:42:16 -04004072 if (result == ssl_ticket_aead_ignore_ticket) {
David Benjaminadaa3222022-08-02 17:10:53 -07004073 if (is_psk) {
4074 hints->ignore_psk = true;
4075 } else {
4076 hints->ignore_ticket = true;
4077 }
4078 } else if (result == ssl_ticket_aead_success) {
4079 if (is_psk) {
4080 if (!hints->decrypted_psk.CopyFrom(plaintext)) {
4081 return ssl_ticket_aead_error;
4082 }
4083 } else {
4084 if (!hints->decrypted_ticket.CopyFrom(plaintext)) {
4085 return ssl_ticket_aead_error;
4086 }
4087 hints->renew_ticket = *out_renew_ticket;
4088 }
David Benjaminb571e772021-03-25 19:42:16 -04004089 }
4090 }
4091
Adam Langley4c341d02017-03-08 19:33:21 -08004092 if (result != ssl_ticket_aead_success) {
4093 return result;
4094 }
4095
David Benjaminc11ea9422017-08-29 16:33:21 -04004096 // Decode the session.
David Benjamin28655672018-07-18 23:23:25 -04004097 UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(
David Benjaminb571e772021-03-25 19:42:16 -04004098 plaintext.data(), plaintext.size(), ssl->ctx.get()));
David Benjamin37af90f2017-07-29 01:42:16 -04004099 if (!session) {
David Benjaminc11ea9422017-08-29 16:33:21 -04004100 ERR_clear_error(); // Don't leave an error on the queue.
Adam Langley4c341d02017-03-08 19:33:21 -08004101 return ssl_ticket_aead_ignore_ticket;
David Benjamine3aa1d92015-06-16 15:34:50 -04004102 }
4103
Adam Langley47cefed2021-05-26 13:36:40 -07004104 // Envoy's tests expect the session to have a session ID that matches the
4105 // placeholder used by the client. It's unclear whether this is a good idea,
4106 // but we maintain it for now.
David Benjamince572d62024-10-22 12:35:44 -04004107 session->session_id.ResizeForOverwrite(SHA256_DIGEST_LENGTH);
David Benjamin87d0c172024-09-20 16:45:42 -04004108 SHA256(ticket.data(), ticket.size(), session->session_id.data());
David Benjamine3aa1d92015-06-16 15:34:50 -04004109
David Benjamin37af90f2017-07-29 01:42:16 -04004110 *out_session = std::move(session);
Adam Langley4c341d02017-03-08 19:33:21 -08004111 return ssl_ticket_aead_success;
Adam Langleyfcf25832014-12-18 17:42:32 -08004112}
Adam Langley95c29f32014-06-20 12:00:00 -07004113
David Benjamin610cdbb2018-01-22 19:08:38 -05004114bool tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) {
David Benjaminc11ea9422017-08-29 16:33:21 -04004115 // Extension ignored for inappropriate versions
David Benjamind1e3ce12017-10-06 18:31:15 -04004116 if (ssl_protocol_version(hs->ssl) < TLS1_2_VERSION) {
David Benjamin610cdbb2018-01-22 19:08:38 -05004117 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004118 }
David Benjamincd996942014-07-20 16:23:51 -04004119
David Benjamin602f4662018-12-07 12:06:22 -06004120 // In all contexts, the signature algorithms list may not be empty. (It may be
4121 // omitted by clients in TLS 1.2, but then the entire extension is omitted.)
4122 return CBS_len(in_sigalgs) != 0 &&
4123 parse_u16_array(in_sigalgs, &hs->peer_sigalgs);
Adam Langleyfcf25832014-12-18 17:42:32 -08004124}
David Benjaminec2f27d2014-11-13 19:17:25 -05004125
David Benjamin610cdbb2018-01-22 19:08:38 -05004126bool tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey) {
David Benjamina3651382017-04-20 17:49:36 -04004127 switch (EVP_PKEY_id(pkey)) {
4128 case EVP_PKEY_RSA:
4129 *out = SSL_SIGN_RSA_PKCS1_MD5_SHA1;
David Benjamin610cdbb2018-01-22 19:08:38 -05004130 return true;
David Benjamina3651382017-04-20 17:49:36 -04004131 case EVP_PKEY_EC:
4132 *out = SSL_SIGN_ECDSA_SHA1;
David Benjamin610cdbb2018-01-22 19:08:38 -05004133 return true;
David Benjamina3651382017-04-20 17:49:36 -04004134 default:
David Benjamin610cdbb2018-01-22 19:08:38 -05004135 return false;
David Benjamina3651382017-04-20 17:49:36 -04004136 }
4137}
4138
David Benjamin91a3f262024-02-10 11:08:08 -05004139bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs,
4140 const SSL_CREDENTIAL *cred,
4141 uint16_t *out) {
David Benjaminf3c8f8d2016-11-17 17:20:47 +09004142 SSL *const ssl = hs->ssl;
David Benjamin91a3f262024-02-10 11:08:08 -05004143 if (!cred->UsesPrivateKey()) {
4144 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
4145 return false;
4146 }
David Benjaminec2f27d2014-11-13 19:17:25 -05004147
David Benjaminc11ea9422017-08-29 16:33:21 -04004148 // Before TLS 1.2, the signature algorithm isn't negotiated as part of the
4149 // handshake.
David Benjamin91a3f262024-02-10 11:08:08 -05004150 uint16_t version = ssl_protocol_version(ssl);
4151 if (version < TLS1_2_VERSION) {
4152 if (!tls1_get_legacy_signature_algorithm(out, cred->pubkey.get())) {
David Benjamina3651382017-04-20 17:49:36 -04004153 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
David Benjamin610cdbb2018-01-22 19:08:38 -05004154 return false;
Steven Valdezf0451ca2016-06-29 13:16:27 -04004155 }
David Benjamin610cdbb2018-01-22 19:08:38 -05004156 return true;
Steven Valdezf0451ca2016-06-29 13:16:27 -04004157 }
4158
David Benjamin91a3f262024-02-10 11:08:08 -05004159 Span<const uint16_t> peer_sigalgs;
4160 if (cred->type == SSLCredentialType::kDelegated) {
David Benjaminefad2bf2024-02-23 14:37:10 -05004161 peer_sigalgs = hs->peer_delegated_credential_sigalgs;
4162 } else {
David Benjamin91a3f262024-02-10 11:08:08 -05004163 peer_sigalgs = hs->peer_sigalgs;
4164 if (peer_sigalgs.empty() && version == TLS1_2_VERSION) {
4165 // If the client didn't specify any signature_algorithms extension, it is
4166 // interpreted as SHA-1. See
4167 // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
4168 static const uint16_t kTLS12Default[] = {SSL_SIGN_RSA_PKCS1_SHA1,
4169 SSL_SIGN_ECDSA_SHA1};
4170 peer_sigalgs = kTLS12Default;
4171 }
Steven Valdez0d62f262015-09-04 12:41:04 -04004172 }
4173
David Benjamin91a3f262024-02-10 11:08:08 -05004174 Span<const uint16_t> sigalgs = cred->sigalgs.empty()
4175 ? MakeConstSpan(kSignSignatureAlgorithms)
4176 : cred->sigalgs;
David Benjaminb1cf48e2017-09-21 11:37:46 -04004177 for (uint16_t sigalg : sigalgs) {
David Benjamin66d274d2021-02-25 01:37:16 -05004178 if (!ssl_pkey_supports_algorithm(ssl, cred->pubkey.get(), sigalg,
4179 /*is_verify=*/false)) {
David Benjamin1fb125c2016-07-08 18:52:12 -07004180 continue;
4181 }
4182
David Benjamin91a3f262024-02-10 11:08:08 -05004183 if (std::find(peer_sigalgs.begin(), peer_sigalgs.end(), sigalg) !=
4184 peer_sigalgs.end()) {
4185 *out = sigalg;
4186 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004187 }
Adam Langleyfcf25832014-12-18 17:42:32 -08004188 }
Adam Langley95c29f32014-06-20 12:00:00 -07004189
David Benjaminea9a0d52016-07-08 15:52:59 -07004190 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
David Benjamin610cdbb2018-01-22 19:08:38 -05004191 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08004192}
Adam Langley95c29f32014-06-20 12:00:00 -07004193
David Benjamin861abcc2018-07-14 17:40:26 -04004194bool tls1_verify_channel_id(SSL_HANDSHAKE *hs, const SSLMessage &msg) {
Steven Valdez908ac192017-01-12 13:17:07 -05004195 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -04004196 // A Channel ID handshake message is structured to contain multiple
4197 // extensions, but the only one that can be present is Channel ID.
David Benjamin7934f082017-08-01 16:32:25 -04004198 uint16_t extension_type;
4199 CBS channel_id = msg.body, extension;
Bob Beck61725ea2024-11-13 17:50:07 +00004200 if (!CBS_get_u16(&channel_id, &extension_type) || //
4201 !CBS_get_u16_length_prefixed(&channel_id, &extension) || //
4202 CBS_len(&channel_id) != 0 || //
4203 extension_type != TLSEXT_TYPE_channel_id || //
Nick Harper60a85cb2016-09-23 16:25:11 -07004204 CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
4205 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
David Benjamind1e3ce12017-10-06 18:31:15 -04004206 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04004207 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004208 }
4209
David Benjamin70be0122023-02-13 19:05:19 -05004210 const EC_GROUP *p256 = EC_group_p256();
David Benjamin86e95b82017-07-18 16:34:25 -04004211 UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
4212 UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
David Benjamin81678aa2017-07-12 22:43:42 -04004213 if (!sig || !x || !y) {
David Benjamin861abcc2018-07-14 17:40:26 -04004214 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004215 }
4216
4217 const uint8_t *p = CBS_data(&extension);
David Benjamin81678aa2017-07-12 22:43:42 -04004218 if (BN_bin2bn(p + 0, 32, x.get()) == NULL ||
4219 BN_bin2bn(p + 32, 32, y.get()) == NULL ||
4220 BN_bin2bn(p + 64, 32, sig->r) == NULL ||
4221 BN_bin2bn(p + 96, 32, sig->s) == NULL) {
David Benjamin861abcc2018-07-14 17:40:26 -04004222 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004223 }
4224
David Benjamin86e95b82017-07-18 16:34:25 -04004225 UniquePtr<EC_KEY> key(EC_KEY_new());
David Benjamin70be0122023-02-13 19:05:19 -05004226 UniquePtr<EC_POINT> point(EC_POINT_new(p256));
David Benjamin81678aa2017-07-12 22:43:42 -04004227 if (!key || !point ||
David Benjamin70be0122023-02-13 19:05:19 -05004228 !EC_POINT_set_affine_coordinates_GFp(p256, point.get(), x.get(), y.get(),
4229 nullptr) ||
4230 !EC_KEY_set_group(key.get(), p256) ||
David Benjamin81678aa2017-07-12 22:43:42 -04004231 !EC_KEY_set_public_key(key.get(), point.get())) {
David Benjamin861abcc2018-07-14 17:40:26 -04004232 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004233 }
4234
4235 uint8_t digest[EVP_MAX_MD_SIZE];
4236 size_t digest_len;
Steven Valdez908ac192017-01-12 13:17:07 -05004237 if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004238 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004239 }
4240
David Benjamin861abcc2018-07-14 17:40:26 -04004241 bool sig_ok = ECDSA_do_verify(digest, digest_len, sig.get(), key.get());
Nick Harper60a85cb2016-09-23 16:25:11 -07004242#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin861abcc2018-07-14 17:40:26 -04004243 sig_ok = true;
David Benjamind90b8032017-12-18 16:47:51 -05004244 ERR_clear_error();
Nick Harper60a85cb2016-09-23 16:25:11 -07004245#endif
4246 if (!sig_ok) {
4247 OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
David Benjamind1e3ce12017-10-06 18:31:15 -04004248 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04004249 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004250 }
4251
David Benjamin46853762018-07-03 14:01:26 -04004252 OPENSSL_memcpy(ssl->s3->channel_id, p, 64);
David Benjamin8acec002021-05-19 13:03:34 -04004253 ssl->s3->channel_id_valid = true;
David Benjamin861abcc2018-07-14 17:40:26 -04004254 return true;
Nick Harper60a85cb2016-09-23 16:25:11 -07004255}
4256
David Benjaminf1db1a32017-10-27 01:12:34 -04004257bool tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb) {
Nick Harper60a85cb2016-09-23 16:25:11 -07004258 uint8_t digest[EVP_MAX_MD_SIZE];
4259 size_t digest_len;
Steven Valdez908ac192017-01-12 13:17:07 -05004260 if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
David Benjaminf1db1a32017-10-27 01:12:34 -04004261 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004262 }
4263
David Benjamin46853762018-07-03 14:01:26 -04004264 EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(hs->config->channel_id_private.get());
David Benjaminf1db1a32017-10-27 01:12:34 -04004265 if (ec_key == nullptr) {
Nick Harper60a85cb2016-09-23 16:25:11 -07004266 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjaminf1db1a32017-10-27 01:12:34 -04004267 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004268 }
4269
David Benjaminf1db1a32017-10-27 01:12:34 -04004270 UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
4271 if (!x || !y ||
Nick Harper60a85cb2016-09-23 16:25:11 -07004272 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
4273 EC_KEY_get0_public_key(ec_key),
David Benjaminf1db1a32017-10-27 01:12:34 -04004274 x.get(), y.get(), nullptr)) {
4275 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004276 }
4277
David Benjaminf1db1a32017-10-27 01:12:34 -04004278 UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, ec_key));
4279 if (!sig) {
4280 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004281 }
4282
4283 CBB child;
Bob Beck61725ea2024-11-13 17:50:07 +00004284 if (!CBB_add_u16(cbb, TLSEXT_TYPE_channel_id) || //
4285 !CBB_add_u16_length_prefixed(cbb, &child) || //
4286 !BN_bn2cbb_padded(&child, 32, x.get()) || //
4287 !BN_bn2cbb_padded(&child, 32, y.get()) || //
4288 !BN_bn2cbb_padded(&child, 32, sig->r) || //
4289 !BN_bn2cbb_padded(&child, 32, sig->s) || //
Nick Harper60a85cb2016-09-23 16:25:11 -07004290 !CBB_flush(cbb)) {
David Benjaminf1db1a32017-10-27 01:12:34 -04004291 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004292 }
4293
David Benjaminf1db1a32017-10-27 01:12:34 -04004294 return true;
Nick Harper60a85cb2016-09-23 16:25:11 -07004295}
4296
David Benjamin861abcc2018-07-14 17:40:26 -04004297bool tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len) {
Steven Valdez908ac192017-01-12 13:17:07 -05004298 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04004299 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin75a1f232017-10-11 17:19:19 -04004300 Array<uint8_t> msg;
4301 if (!tls13_get_cert_verify_signature_input(hs, &msg,
Nick Harper60a85cb2016-09-23 16:25:11 -07004302 ssl_cert_verify_channel_id)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004303 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004304 }
David Benjamin75a1f232017-10-11 17:19:19 -04004305 SHA256(msg.data(), msg.size(), out);
Nick Harper60a85cb2016-09-23 16:25:11 -07004306 *out_len = SHA256_DIGEST_LENGTH;
David Benjamin861abcc2018-07-14 17:40:26 -04004307 return true;
Nick Harper60a85cb2016-09-23 16:25:11 -07004308 }
4309
Nick Harper95594012016-10-20 14:07:13 -07004310 SHA256_CTX ctx;
Adam Langleyfcf25832014-12-18 17:42:32 -08004311
Nick Harper95594012016-10-20 14:07:13 -07004312 SHA256_Init(&ctx);
David Benjamind6a4ae92015-08-06 11:10:51 -04004313 static const char kClientIDMagic[] = "TLS Channel ID signature";
Nick Harper95594012016-10-20 14:07:13 -07004314 SHA256_Update(&ctx, kClientIDMagic, sizeof(kClientIDMagic));
David Benjamind6a4ae92015-08-06 11:10:51 -04004315
Steven Valdez87eab492016-06-27 16:34:59 -04004316 if (ssl->session != NULL) {
David Benjamind6a4ae92015-08-06 11:10:51 -04004317 static const char kResumptionMagic[] = "Resumption";
Nick Harper95594012016-10-20 14:07:13 -07004318 SHA256_Update(&ctx, kResumptionMagic, sizeof(kResumptionMagic));
David Benjamin87d0c172024-09-20 16:45:42 -04004319 if (ssl->session->original_handshake_hash.empty()) {
David Benjamind6a4ae92015-08-06 11:10:51 -04004320 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04004321 return false;
David Benjamind6a4ae92015-08-06 11:10:51 -04004322 }
David Benjamin87d0c172024-09-20 16:45:42 -04004323 SHA256_Update(&ctx, ssl->session->original_handshake_hash.data(),
4324 ssl->session->original_handshake_hash.size());
David Benjamind6a4ae92015-08-06 11:10:51 -04004325 }
4326
Steven Valdez908ac192017-01-12 13:17:07 -05004327 uint8_t hs_hash[EVP_MAX_MD_SIZE];
4328 size_t hs_hash_len;
David Benjamin6dc8bf62017-07-19 16:38:21 -04004329 if (!hs->transcript.GetHash(hs_hash, &hs_hash_len)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004330 return false;
David Benjamind6a4ae92015-08-06 11:10:51 -04004331 }
Steven Valdez908ac192017-01-12 13:17:07 -05004332 SHA256_Update(&ctx, hs_hash, (size_t)hs_hash_len);
Nick Harper95594012016-10-20 14:07:13 -07004333 SHA256_Final(out, &ctx);
4334 *out_len = SHA256_DIGEST_LENGTH;
David Benjamin861abcc2018-07-14 17:40:26 -04004335 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004336}
Adam Langley1258b6a2014-06-20 12:00:00 -07004337
David Benjamin861abcc2018-07-14 17:40:26 -04004338bool tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) {
Steven Valdez908ac192017-01-12 13:17:07 -05004339 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -04004340 // This function should never be called for a resumed session because the
4341 // handshake hashes that we wish to record are for the original, full
4342 // handshake.
Steven Valdez87eab492016-06-27 16:34:59 -04004343 if (ssl->session != NULL) {
David Benjamin861abcc2018-07-14 17:40:26 -04004344 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08004345 }
Adam Langley1258b6a2014-06-20 12:00:00 -07004346
Steven Valdez908ac192017-01-12 13:17:07 -05004347 size_t digest_len;
David Benjamince572d62024-10-22 12:35:44 -04004348 hs->new_session->original_handshake_hash.ResizeForOverwrite(
David Benjamin87d0c172024-09-20 16:45:42 -04004349 hs->transcript.DigestLen());
4350 if (!hs->transcript.GetHash(hs->new_session->original_handshake_hash.data(),
David Benjamin6dc8bf62017-07-19 16:38:21 -04004351 &digest_len)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004352 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08004353 }
David Benjamin87d0c172024-09-20 16:45:42 -04004354 assert(digest_len == hs->new_session->original_handshake_hash.size());
David Benjamin861abcc2018-07-14 17:40:26 -04004355 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004356}
Nick Harper60a85cb2016-09-23 16:25:11 -07004357
David Benjamin861abcc2018-07-14 17:40:26 -04004358bool ssl_is_sct_list_valid(const CBS *contents) {
David Benjaminc11ea9422017-08-29 16:33:21 -04004359 // Shallow parse the SCT list for sanity. By the RFC
4360 // (https://tools.ietf.org/html/rfc6962#section-3.3) neither the list nor any
4361 // of the SCTs may be empty.
Adam Langleycfa08c32016-11-17 13:21:27 -08004362 CBS copy = *contents;
4363 CBS sct_list;
Bob Beck61725ea2024-11-13 17:50:07 +00004364 if (!CBS_get_u16_length_prefixed(&copy, &sct_list) || CBS_len(&copy) != 0 ||
Adam Langleycfa08c32016-11-17 13:21:27 -08004365 CBS_len(&sct_list) == 0) {
David Benjamin861abcc2018-07-14 17:40:26 -04004366 return false;
Adam Langleycfa08c32016-11-17 13:21:27 -08004367 }
4368
4369 while (CBS_len(&sct_list) > 0) {
4370 CBS sct;
Bob Beck61725ea2024-11-13 17:50:07 +00004371 if (!CBS_get_u16_length_prefixed(&sct_list, &sct) || CBS_len(&sct) == 0) {
David Benjamin861abcc2018-07-14 17:40:26 -04004372 return false;
Adam Langleycfa08c32016-11-17 13:21:27 -08004373 }
4374 }
4375
David Benjamin861abcc2018-07-14 17:40:26 -04004376 return true;
Adam Langleycfa08c32016-11-17 13:21:27 -08004377}
David Benjamin86e95b82017-07-18 16:34:25 -04004378
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -07004379BSSL_NAMESPACE_END
David Benjamin86e95b82017-07-18 16:34:25 -04004380
4381using namespace bssl;
4382
4383int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello,
4384 uint16_t extension_type,
4385 const uint8_t **out_data,
4386 size_t *out_len) {
4387 CBS cbs;
4388 if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) {
4389 return 0;
4390 }
4391
4392 *out_data = CBS_data(&cbs);
4393 *out_len = CBS_len(&cbs);
4394 return 1;
4395}