blob: 30591a6a07bf9e3e2c07693f60988c60173f310a [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
Adam Langleye745b252018-02-26 14:02:17 -08007 *
Adam Langley95c29f32014-06-20 12:00:00 -07008 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
Adam Langleye745b252018-02-26 14:02:17 -080014 *
Adam Langley95c29f32014-06-20 12:00:00 -070015 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
Adam Langleye745b252018-02-26 14:02:17 -080021 *
Adam Langley95c29f32014-06-20 12:00:00 -070022 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
Adam Langleye745b252018-02-26 14:02:17 -080036 * 4. If you include any Windows specific code (or a derivative thereof) from
Adam Langley95c29f32014-06-20 12:00:00 -070037 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
Adam Langleye745b252018-02-26 14:02:17 -080039 *
Adam Langley95c29f32014-06-20 12:00:00 -070040 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
Adam Langleye745b252018-02-26 14:02:17 -080051 *
Adam Langley95c29f32014-06-20 12:00:00 -070052 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
56 */
57/* ====================================================================
58 * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
59 *
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
62 * are met:
63 *
64 * 1. Redistributions of source code must retain the above copyright
Adam Langleye745b252018-02-26 14:02:17 -080065 * notice, this list of conditions and the following disclaimer.
Adam Langley95c29f32014-06-20 12:00:00 -070066 *
67 * 2. Redistributions in binary form must reproduce the above copyright
68 * notice, this list of conditions and the following disclaimer in
69 * the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3. All advertising materials mentioning features or use of this
73 * software must display the following acknowledgment:
74 * "This product includes software developed by the OpenSSL Project
75 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76 *
77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78 * endorse or promote products derived from this software without
79 * prior written permission. For written permission, please contact
80 * openssl-core@openssl.org.
81 *
82 * 5. Products derived from this software may not be called "OpenSSL"
83 * nor may "OpenSSL" appear in their names without prior written
84 * permission of the OpenSSL Project.
85 *
86 * 6. Redistributions of any form whatsoever must retain the following
87 * acknowledgment:
88 * "This product includes software developed by the OpenSSL Project
89 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90 *
91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102 * OF THE POSSIBILITY OF SUCH DAMAGE.
103 * ====================================================================
104 *
105 * This product includes cryptographic software written by Eric Young
106 * (eay@cryptsoft.com). This product includes software written by Tim
107 * Hudson (tjh@cryptsoft.com). */
108
David Benjamin9e4e01e2015-09-15 01:48:04 -0400109#include <openssl/ssl.h>
110
David Benjaminf0ae1702015-04-07 23:05:04 -0400111#include <assert.h>
David Benjamine3aa1d92015-06-16 15:34:50 -0400112#include <limits.h>
David Benjamin35a7a442014-07-05 00:23:20 -0400113#include <stdlib.h>
David Benjaminf0ae1702015-04-07 23:05:04 -0400114#include <string.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700115
Dan McArdle1920c6f2020-03-11 17:29:40 -0400116#include <algorithm>
David Benjamin499742c2017-07-22 12:45:38 -0400117#include <utility>
118
Dan McArdle1920c6f2020-03-11 17:29:40 -0400119#include <openssl/aead.h>
David Benjamin03973092014-06-24 23:27:17 -0400120#include <openssl/bytestring.h>
Adam Langley512a2892017-12-30 08:04:39 -0800121#include <openssl/chacha.h>
Dan McArdle1920c6f2020-03-11 17:29:40 -0400122#include <openssl/curve25519.h>
David Benjamind6a4ae92015-08-06 11:10:51 -0400123#include <openssl/digest.h>
David Benjaminf0ae1702015-04-07 23:05:04 -0400124#include <openssl/err.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700125#include <openssl/evp.h>
126#include <openssl/hmac.h>
David Benjamin070a6c32021-05-05 15:39:27 -0400127#include <openssl/hpke.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700128#include <openssl/mem.h>
David Benjamin98193672016-03-25 18:07:11 -0400129#include <openssl/nid.h>
David Benjamine9c5d722021-06-09 17:43:16 -0400130#include <openssl/rand.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700131
Steven Valdezcb966542016-08-17 16:56:14 -0400132#include "../crypto/internal.h"
Steven Valdez51607f12020-08-05 10:46:05 -0400133#include "internal.h"
Adam Langleyfcf25832014-12-18 17:42:32 -0800134
135
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700136BSSL_NAMESPACE_BEGIN
David Benjamin86e95b82017-07-18 16:34:25 -0400137
David Benjamin861abcc2018-07-14 17:40:26 -0400138static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs);
Steven Valdez51607f12020-08-05 10:46:05 -0400139static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs);
Adam Langley95c29f32014-06-20 12:00:00 -0700140
Adam Langleyfcf25832014-12-18 17:42:32 -0800141static int compare_uint16_t(const void *p1, const void *p2) {
142 uint16_t u1 = *((const uint16_t *)p1);
143 uint16_t u2 = *((const uint16_t *)p2);
144 if (u1 < u2) {
145 return -1;
146 } else if (u1 > u2) {
147 return 1;
148 } else {
149 return 0;
150 }
151}
David Benjamin35a7a442014-07-05 00:23:20 -0400152
David Benjaminc11ea9422017-08-29 16:33:21 -0400153// Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
154// more than one extension of the same type in a ClientHello or ServerHello.
155// This function does an initial scan over the extensions block to filter those
156// out.
David Benjamin861abcc2018-07-14 17:40:26 -0400157static bool tls1_check_duplicate_extensions(const CBS *cbs) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400158 // First pass: count the extensions.
David Benjamin08f5c762017-09-21 02:43:05 -0400159 size_t num_extensions = 0;
160 CBS extensions = *cbs;
Adam Langleyfcf25832014-12-18 17:42:32 -0800161 while (CBS_len(&extensions) > 0) {
162 uint16_t type;
163 CBS extension;
David Benjamin35a7a442014-07-05 00:23:20 -0400164
Adam Langleyfcf25832014-12-18 17:42:32 -0800165 if (!CBS_get_u16(&extensions, &type) ||
166 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
David Benjamin861abcc2018-07-14 17:40:26 -0400167 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800168 }
David Benjamin35a7a442014-07-05 00:23:20 -0400169
Adam Langleyfcf25832014-12-18 17:42:32 -0800170 num_extensions++;
171 }
David Benjamin35a7a442014-07-05 00:23:20 -0400172
Adam Langleyfcf25832014-12-18 17:42:32 -0800173 if (num_extensions == 0) {
David Benjamin861abcc2018-07-14 17:40:26 -0400174 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800175 }
David Benjamin9a373592014-07-25 04:27:53 -0400176
David Benjamin08f5c762017-09-21 02:43:05 -0400177 Array<uint16_t> extension_types;
178 if (!extension_types.Init(num_extensions)) {
David Benjamin861abcc2018-07-14 17:40:26 -0400179 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800180 }
David Benjamin35a7a442014-07-05 00:23:20 -0400181
David Benjaminc11ea9422017-08-29 16:33:21 -0400182 // Second pass: gather the extension types.
Adam Langleyfcf25832014-12-18 17:42:32 -0800183 extensions = *cbs;
David Benjamin08f5c762017-09-21 02:43:05 -0400184 for (size_t i = 0; i < extension_types.size(); i++) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800185 CBS extension;
David Benjamin35a7a442014-07-05 00:23:20 -0400186
Adam Langleyfcf25832014-12-18 17:42:32 -0800187 if (!CBS_get_u16(&extensions, &extension_types[i]) ||
188 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400189 // This should not happen.
David Benjamin861abcc2018-07-14 17:40:26 -0400190 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800191 }
192 }
193 assert(CBS_len(&extensions) == 0);
David Benjamin35a7a442014-07-05 00:23:20 -0400194
David Benjaminc11ea9422017-08-29 16:33:21 -0400195 // Sort the extensions and make sure there are no duplicates.
David Benjamin08f5c762017-09-21 02:43:05 -0400196 qsort(extension_types.data(), extension_types.size(), sizeof(uint16_t),
197 compare_uint16_t);
198 for (size_t i = 1; i < num_extensions; i++) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800199 if (extension_types[i - 1] == extension_types[i]) {
David Benjamin861abcc2018-07-14 17:40:26 -0400200 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -0800201 }
202 }
David Benjamin35a7a442014-07-05 00:23:20 -0400203
David Benjamin861abcc2018-07-14 17:40:26 -0400204 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -0800205}
David Benjamin35a7a442014-07-05 00:23:20 -0400206
Kris Kwiatkowski78c88c92019-03-11 14:40:59 +0000207static bool is_post_quantum_group(uint16_t id) {
Adam Langleyfc077382023-01-08 16:22:31 -0800208 switch (id) {
David Benjamin335523a2023-05-26 21:55:56 -0400209 case SSL_GROUP_X25519_KYBER768_DRAFT00:
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
David Benjamin31640932017-10-11 13:22:39 -0400516static bool dont_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
517 return true;
Steven Valdez6b8509a2016-07-12 13:38:32 -0400518}
Adam Langley614c66a2015-06-12 15:26:58 -0700519
David Benjaminc11ea9422017-08-29 16:33:21 -0400520// Server name indication (SNI).
521//
522// https://tools.ietf.org/html/rfc6066#section-3.
Adam Langley614c66a2015-06-12 15:26:58 -0700523
David Benjamin83a49932021-05-20 15:57:09 -0400524static bool ext_sni_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
525 CBB *out_compressible,
526 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -0400527 const SSL *const ssl = hs->ssl;
David Benjamin83a49932021-05-20 15:57:09 -0400528 // If offering ECH, send the public name instead of the configured name.
529 Span<const uint8_t> hostname;
530 if (type == ssl_client_hello_outer) {
531 hostname = hs->selected_ech_config->public_name;
532 } else {
533 if (ssl->hostname == nullptr) {
534 return true;
535 }
536 hostname =
537 MakeConstSpan(reinterpret_cast<const uint8_t *>(ssl->hostname.get()),
538 strlen(ssl->hostname.get()));
Adam Langley614c66a2015-06-12 15:26:58 -0700539 }
540
541 CBB contents, server_name_list, name;
542 if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) ||
543 !CBB_add_u16_length_prefixed(out, &contents) ||
544 !CBB_add_u16_length_prefixed(&contents, &server_name_list) ||
545 !CBB_add_u8(&server_name_list, TLSEXT_NAMETYPE_host_name) ||
546 !CBB_add_u16_length_prefixed(&server_name_list, &name) ||
David Benjamin83a49932021-05-20 15:57:09 -0400547 !CBB_add_bytes(&name, hostname.data(), hostname.size()) ||
Adam Langley614c66a2015-06-12 15:26:58 -0700548 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -0400549 return false;
Adam Langley614c66a2015-06-12 15:26:58 -0700550 }
551
David Benjamin31640932017-10-11 13:22:39 -0400552 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700553}
554
David Benjamin31640932017-10-11 13:22:39 -0400555static bool ext_sni_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
556 CBS *contents) {
David Benjamina8614602017-09-06 15:40:19 -0400557 // The server may acknowledge SNI with an empty extension. We check the syntax
558 // but otherwise ignore this signal.
559 return contents == NULL || CBS_len(contents) == 0;
Adam Langley614c66a2015-06-12 15:26:58 -0700560}
561
David Benjamin31640932017-10-11 13:22:39 -0400562static bool ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
563 CBS *contents) {
David Benjaminef0183c2019-07-20 09:11:05 -0400564 // SNI has already been parsed earlier in the handshake. See |extract_sni|.
David Benjamin31640932017-10-11 13:22:39 -0400565 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700566}
567
David Benjamin31640932017-10-11 13:22:39 -0400568static bool ext_sni_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -0500569 if (hs->ssl->s3->session_reused ||
570 !hs->should_ack_sni) {
David Benjamin31640932017-10-11 13:22:39 -0400571 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700572 }
573
574 if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) ||
575 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -0400576 return false;
Adam Langley614c66a2015-06-12 15:26:58 -0700577 }
578
David Benjamin31640932017-10-11 13:22:39 -0400579 return true;
Adam Langley614c66a2015-06-12 15:26:58 -0700580}
581
582
Daniel McArdle00e434d2021-02-18 11:47:18 -0500583// Encrypted ClientHello (ECH)
Dan McArdle1920c6f2020-03-11 17:29:40 -0400584//
David Benjamin18b68362021-06-18 23:13:46 -0400585// https://tools.ietf.org/html/draft-ietf-tls-esni-13
Dan McArdle1920c6f2020-03-11 17:29:40 -0400586
David Benjamin83a49932021-05-20 15:57:09 -0400587static bool ext_ech_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
588 CBB *out_compressible,
589 ssl_client_hello_type_t type) {
David Benjamin18b68362021-06-18 23:13:46 -0400590 if (type == ssl_client_hello_inner) {
591 if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
592 !CBB_add_u16(out, /* length */ 1) ||
593 !CBB_add_u8(out, ECH_CLIENT_INNER)) {
594 return false;
595 }
596 return true;
597 }
598
599 if (hs->ech_client_outer.empty()) {
Dan McArdle1920c6f2020-03-11 17:29:40 -0400600 return true;
601 }
602
David Benjamin83a49932021-05-20 15:57:09 -0400603 CBB ech_body;
604 if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
605 !CBB_add_u16_length_prefixed(out, &ech_body) ||
David Benjamin18b68362021-06-18 23:13:46 -0400606 !CBB_add_u8(&ech_body, ECH_CLIENT_OUTER) ||
607 !CBB_add_bytes(&ech_body, hs->ech_client_outer.data(),
608 hs->ech_client_outer.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -0400609 !CBB_flush(out)) {
Dan McArdle1920c6f2020-03-11 17:29:40 -0400610 return false;
611 }
David Benjamin246c5562021-05-20 13:42:25 -0400612 return true;
Dan McArdle1920c6f2020-03-11 17:29:40 -0400613}
614
Dan McArdle1920c6f2020-03-11 17:29:40 -0400615static bool ext_ech_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
616 CBS *contents) {
David Benjamin5b7ec832021-06-02 11:12:13 -0400617 SSL *const ssl = hs->ssl;
Dan McArdle1920c6f2020-03-11 17:29:40 -0400618 if (contents == NULL) {
619 return true;
620 }
621
David Benjamin5b7ec832021-06-02 11:12:13 -0400622 // The ECH extension may not be sent in TLS 1.2 ServerHello, only TLS 1.3
David Benjamin18b68362021-06-18 23:13:46 -0400623 // EncryptedExtensions. It also may not be sent in response to an inner ECH
624 // extension.
625 if (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
626 ssl->s3->ech_status == ssl_ech_accepted) {
David Benjamin5b7ec832021-06-02 11:12:13 -0400627 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
628 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
629 return false;
630 }
631
David Benjaminba423c92021-06-15 16:26:58 -0400632 if (!ssl_is_valid_ech_config_list(*contents)) {
633 *out_alert = SSL_AD_DECODE_ERROR;
634 return false;
635 }
636
David Benjamin18b68362021-06-18 23:13:46 -0400637 if (ssl->s3->ech_status == ssl_ech_rejected &&
David Benjaminba423c92021-06-15 16:26:58 -0400638 !hs->ech_retry_configs.CopyFrom(*contents)) {
639 *out_alert = SSL_AD_INTERNAL_ERROR;
Dan McArdle1920c6f2020-03-11 17:29:40 -0400640 return false;
641 }
David Benjaminba423c92021-06-15 16:26:58 -0400642
Dan McArdle1920c6f2020-03-11 17:29:40 -0400643 return true;
644}
645
Dan McArdlec2959352020-10-29 14:31:31 -0400646static bool ext_ech_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
647 CBS *contents) {
David Benjamin18b68362021-06-18 23:13:46 -0400648 if (contents == nullptr) {
Dan McArdlec2959352020-10-29 14:31:31 -0400649 return true;
650 }
David Benjamin18b68362021-06-18 23:13:46 -0400651
652 uint8_t type;
653 if (!CBS_get_u8(contents, &type)) {
654 return false;
655 }
656 if (type == ECH_CLIENT_OUTER) {
657 // Outer ECH extensions are handled outside the callback.
658 return true;
659 }
660 if (type != ECH_CLIENT_INNER || CBS_len(contents) != 0) {
661 return false;
662 }
663
664 hs->ech_is_inner = true;
Dan McArdlec2959352020-10-29 14:31:31 -0400665 return true;
666}
667
Daniel McArdle00e434d2021-02-18 11:47:18 -0500668static bool ext_ech_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
669 SSL *const ssl = hs->ssl;
David Benjaminba423c92021-06-15 16:26:58 -0400670 if (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
671 ssl->s3->ech_status == ssl_ech_accepted || //
David Benjaminc3b373b2021-06-06 13:04:26 -0400672 hs->ech_keys == nullptr) {
Daniel McArdle00e434d2021-02-18 11:47:18 -0500673 return true;
674 }
675
David Benjaminc3b373b2021-06-06 13:04:26 -0400676 // Write the list of retry configs to |out|. Note |SSL_CTX_set1_ech_keys|
677 // ensures |ech_keys| contains at least one retry config.
Daniel McArdle00e434d2021-02-18 11:47:18 -0500678 CBB body, retry_configs;
679 if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) ||
680 !CBB_add_u16_length_prefixed(out, &body) ||
681 !CBB_add_u16_length_prefixed(&body, &retry_configs)) {
682 return false;
683 }
David Benjaminc3b373b2021-06-06 13:04:26 -0400684 for (const auto &config : hs->ech_keys->configs) {
David Benjamin1d58cd12021-05-04 15:24:24 -0400685 if (!config->is_retry_config()) {
Daniel McArdle00e434d2021-02-18 11:47:18 -0500686 continue;
687 }
David Benjamin83a49932021-05-20 15:57:09 -0400688 if (!CBB_add_bytes(&retry_configs, config->ech_config().raw.data(),
689 config->ech_config().raw.size())) {
Daniel McArdle00e434d2021-02-18 11:47:18 -0500690 return false;
691 }
692 }
693 return CBB_flush(out);
694}
695
Dan McArdle1920c6f2020-03-11 17:29:40 -0400696
David Benjaminc11ea9422017-08-29 16:33:21 -0400697// Renegotiation indication.
698//
699// https://tools.ietf.org/html/rfc5746
Adam Langley5021b222015-06-12 18:27:58 -0700700
David Benjamin83a49932021-05-20 15:57:09 -0400701static bool ext_ri_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
702 CBB *out_compressible,
703 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -0400704 const SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400705 // Renegotiation indication is not necessary in TLS 1.3.
David Benjamin83a49932021-05-20 15:57:09 -0400706 if (hs->min_version >= TLS1_3_VERSION ||
707 type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -0400708 return true;
David Benjamin7c7d8312016-08-20 13:39:03 -0400709 }
710
David Benjamin52bf6902016-10-08 12:05:03 -0400711 assert(ssl->s3->initial_handshake_complete ==
712 (ssl->s3->previous_client_finished_len != 0));
713
Adam Langley5021b222015-06-12 18:27:58 -0700714 CBB contents, prev_finished;
715 if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
716 !CBB_add_u16_length_prefixed(out, &contents) ||
717 !CBB_add_u8_length_prefixed(&contents, &prev_finished) ||
718 !CBB_add_bytes(&prev_finished, ssl->s3->previous_client_finished,
719 ssl->s3->previous_client_finished_len) ||
720 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -0400721 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700722 }
723
David Benjamin31640932017-10-11 13:22:39 -0400724 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700725}
726
David Benjamin31640932017-10-11 13:22:39 -0400727static bool ext_ri_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
728 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500729 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -0400730 if (contents != NULL && ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
Steven Valdez246eeee2017-03-26 12:49:17 -0500731 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -0400732 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -0400733 }
734
David Benjaminc11ea9422017-08-29 16:33:21 -0400735 // Servers may not switch between omitting the extension and supporting it.
736 // See RFC 5746, sections 3.5 and 4.2.
David Benjamin3e052de2015-11-25 20:10:31 -0500737 if (ssl->s3->initial_handshake_complete &&
738 (contents != NULL) != ssl->s3->send_connection_binding) {
739 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
740 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
David Benjamin31640932017-10-11 13:22:39 -0400741 return false;
David Benjamin3e052de2015-11-25 20:10:31 -0500742 }
743
Adam Langley5021b222015-06-12 18:27:58 -0700744 if (contents == NULL) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400745 // Strictly speaking, if we want to avoid an attack we should *always* see
746 // RI even on initial ServerHello because the client doesn't see any
747 // renegotiation during an attack. However this would mean we could not
748 // connect to any server which doesn't support RI.
749 //
750 // OpenSSL has |SSL_OP_LEGACY_SERVER_CONNECT| to control this, but in
751 // practical terms every client sets it so it's just assumed here.
David Benjamin31640932017-10-11 13:22:39 -0400752 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700753 }
754
755 const size_t expected_len = ssl->s3->previous_client_finished_len +
756 ssl->s3->previous_server_finished_len;
757
David Benjaminc11ea9422017-08-29 16:33:21 -0400758 // Check for logic errors
Adam Langley5021b222015-06-12 18:27:58 -0700759 assert(!expected_len || ssl->s3->previous_client_finished_len);
760 assert(!expected_len || ssl->s3->previous_server_finished_len);
David Benjamin52bf6902016-10-08 12:05:03 -0400761 assert(ssl->s3->initial_handshake_complete ==
762 (ssl->s3->previous_client_finished_len != 0));
763 assert(ssl->s3->initial_handshake_complete ==
764 (ssl->s3->previous_server_finished_len != 0));
Adam Langley5021b222015-06-12 18:27:58 -0700765
David Benjaminc11ea9422017-08-29 16:33:21 -0400766 // Parse out the extension contents.
Adam Langley5021b222015-06-12 18:27:58 -0700767 CBS renegotiated_connection;
768 if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) ||
769 CBS_len(contents) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400770 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR);
Adam Langley5021b222015-06-12 18:27:58 -0700771 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -0400772 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700773 }
774
David Benjaminc11ea9422017-08-29 16:33:21 -0400775 // Check that the extension matches.
Adam Langley5021b222015-06-12 18:27:58 -0700776 if (CBS_len(&renegotiated_connection) != expected_len) {
David Benjamin3570d732015-06-29 00:28:17 -0400777 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
Adam Langley5021b222015-06-12 18:27:58 -0700778 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
David Benjamin31640932017-10-11 13:22:39 -0400779 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700780 }
781
782 const uint8_t *d = CBS_data(&renegotiated_connection);
David Benjamin31640932017-10-11 13:22:39 -0400783 bool ok = CRYPTO_memcmp(d, ssl->s3->previous_client_finished,
784 ssl->s3->previous_client_finished_len) == 0;
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 }
793 d += ssl->s3->previous_client_finished_len;
794
David Benjamin9343b0b2017-07-01 00:31:27 -0400795 ok = CRYPTO_memcmp(d, ssl->s3->previous_server_finished,
796 ssl->s3->previous_server_finished_len) == 0;
797#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin31640932017-10-11 13:22:39 -0400798 ok = true;
David Benjamin9343b0b2017-07-01 00:31:27 -0400799#endif
800 if (!ok) {
David Benjamin3570d732015-06-29 00:28:17 -0400801 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
Adam Langley10e10602017-07-25 13:33:21 -0700802 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
David Benjamin31640932017-10-11 13:22:39 -0400803 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700804 }
David Benjamin046bc1f2017-08-31 15:06:42 -0400805 ssl->s3->send_connection_binding = true;
Adam Langley5021b222015-06-12 18:27:58 -0700806
David Benjamin31640932017-10-11 13:22:39 -0400807 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700808}
809
David Benjamin31640932017-10-11 13:22:39 -0400810static bool ext_ri_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
811 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500812 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400813 // Renegotiation isn't supported as a server so this function should never be
814 // called after the initial handshake.
Adam Langley5021b222015-06-12 18:27:58 -0700815 assert(!ssl->s3->initial_handshake_complete);
816
David Benjamind1e3ce12017-10-06 18:31:15 -0400817 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400818 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -0400819 }
820
Adam Langley5021b222015-06-12 18:27:58 -0700821 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -0400822 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700823 }
824
825 CBS renegotiated_connection;
Adam Langley5021b222015-06-12 18:27:58 -0700826 if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) ||
827 CBS_len(contents) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400828 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR);
David Benjamin31640932017-10-11 13:22:39 -0400829 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700830 }
831
David Benjaminc11ea9422017-08-29 16:33:21 -0400832 // Check that the extension matches. We do not support renegotiation as a
833 // server, so this must be empty.
David Benjamin52bf6902016-10-08 12:05:03 -0400834 if (CBS_len(&renegotiated_connection) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400835 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
Adam Langley5021b222015-06-12 18:27:58 -0700836 *out_alert = SSL_AD_HANDSHAKE_FAILURE;
David Benjamin31640932017-10-11 13:22:39 -0400837 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700838 }
839
David Benjamin046bc1f2017-08-31 15:06:42 -0400840 ssl->s3->send_connection_binding = true;
Adam Langley5021b222015-06-12 18:27:58 -0700841
David Benjamin31640932017-10-11 13:22:39 -0400842 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700843}
844
David Benjamin31640932017-10-11 13:22:39 -0400845static bool ext_ri_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -0500846 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400847 // Renegotiation isn't supported as a server so this function should never be
848 // called after the initial handshake.
David Benjamin52bf6902016-10-08 12:05:03 -0400849 assert(!ssl->s3->initial_handshake_complete);
850
David Benjamind1e3ce12017-10-06 18:31:15 -0400851 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400852 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -0400853 }
854
Adam Langley5021b222015-06-12 18:27:58 -0700855 if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
David Benjamin52bf6902016-10-08 12:05:03 -0400856 !CBB_add_u16(out, 1 /* length */) ||
857 !CBB_add_u8(out, 0 /* empty renegotiation info */)) {
David Benjamin31640932017-10-11 13:22:39 -0400858 return false;
Adam Langley5021b222015-06-12 18:27:58 -0700859 }
860
David Benjamin31640932017-10-11 13:22:39 -0400861 return true;
Adam Langley5021b222015-06-12 18:27:58 -0700862}
863
Adam Langley0a056712015-07-01 15:03:33 -0700864
David Benjaminc11ea9422017-08-29 16:33:21 -0400865// Extended Master Secret.
866//
867// https://tools.ietf.org/html/rfc7627
Adam Langley0a056712015-07-01 15:03:33 -0700868
David Benjamin83a49932021-05-20 15:57:09 -0400869static bool ext_ems_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
870 CBB *out_compressible,
871 ssl_client_hello_type_t type) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400872 // Extended master secret is not necessary in TLS 1.3.
David Benjamin83a49932021-05-20 15:57:09 -0400873 if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -0400874 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700875 }
876
877 if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) ||
878 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -0400879 return false;
Adam Langley0a056712015-07-01 15:03:33 -0700880 }
881
David Benjamin31640932017-10-11 13:22:39 -0400882 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700883}
884
David Benjamin31640932017-10-11 13:22:39 -0400885static bool ext_ems_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
886 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500887 SSL *const ssl = hs->ssl;
David Benjaminfc02b592017-02-17 16:26:01 -0500888
889 if (contents != NULL) {
David Benjamind1e3ce12017-10-06 18:31:15 -0400890 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
David Benjaminfc02b592017-02-17 16:26:01 -0500891 CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -0400892 return false;
David Benjamin163c9562016-08-29 23:14:17 -0400893 }
894
David Benjaminfd45ee72017-08-31 14:49:09 -0400895 hs->extended_master_secret = true;
David Benjamin163c9562016-08-29 23:14:17 -0400896 }
897
David Benjaminc11ea9422017-08-29 16:33:21 -0400898 // Whether EMS is negotiated may not change on renegotiation.
David Benjamin8e7bbba2017-10-13 17:18:35 -0400899 if (ssl->s3->established_session != nullptr &&
David Benjaminfc02b592017-02-17 16:26:01 -0500900 hs->extended_master_secret !=
David Benjaminfd45ee72017-08-31 14:49:09 -0400901 !!ssl->s3->established_session->extended_master_secret) {
David Benjaminfc02b592017-02-17 16:26:01 -0500902 OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_EMS_MISMATCH);
903 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -0400904 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -0400905 }
906
David Benjamin31640932017-10-11 13:22:39 -0400907 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700908}
909
David Benjamin31640932017-10-11 13:22:39 -0400910static bool ext_ems_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
911 CBS *contents) {
David Benjamin9bb15f52018-06-26 00:07:40 -0400912 if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400913 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -0400914 }
915
916 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -0400917 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700918 }
919
920 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -0400921 return false;
Adam Langley0a056712015-07-01 15:03:33 -0700922 }
923
David Benjaminfd45ee72017-08-31 14:49:09 -0400924 hs->extended_master_secret = true;
David Benjamin31640932017-10-11 13:22:39 -0400925 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700926}
927
David Benjamin31640932017-10-11 13:22:39 -0400928static bool ext_ems_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjaminfc02b592017-02-17 16:26:01 -0500929 if (!hs->extended_master_secret) {
David Benjamin31640932017-10-11 13:22:39 -0400930 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700931 }
932
933 if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) ||
934 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -0400935 return false;
Adam Langley0a056712015-07-01 15:03:33 -0700936 }
937
David Benjamin31640932017-10-11 13:22:39 -0400938 return true;
Adam Langley0a056712015-07-01 15:03:33 -0700939}
940
Adam Langley9b05bc52015-07-01 15:25:33 -0700941
David Benjaminc11ea9422017-08-29 16:33:21 -0400942// Session tickets.
943//
944// https://tools.ietf.org/html/rfc5077
Adam Langley9b05bc52015-07-01 15:25:33 -0700945
David Benjamin83a49932021-05-20 15:57:09 -0400946static bool ext_ticket_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
947 CBB *out_compressible,
948 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -0400949 const SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -0400950 // TLS 1.3 uses a different ticket extension.
David Benjamin83a49932021-05-20 15:57:09 -0400951 if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner ||
David Benjamin7c7d8312016-08-20 13:39:03 -0400952 SSL_get_options(ssl) & SSL_OP_NO_TICKET) {
David Benjamin31640932017-10-11 13:22:39 -0400953 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700954 }
955
David Benjaminbfdd1a92018-06-29 16:26:38 -0400956 Span<const uint8_t> ticket;
Adam Langley9b05bc52015-07-01 15:25:33 -0700957
David Benjaminc11ea9422017-08-29 16:33:21 -0400958 // Renegotiation does not participate in session resumption. However, still
959 // advertise the extension to avoid potentially breaking servers which carry
960 // over the state from the previous handshake, such as OpenSSL servers
961 // without upstream's 3c3f0259238594d77264a78944d409f2127642c4.
Adam Langley9b05bc52015-07-01 15:25:33 -0700962 if (!ssl->s3->initial_handshake_complete &&
David Benjamin50596f82018-07-02 19:47:27 -0400963 ssl->session != nullptr &&
David Benjaminbfdd1a92018-06-29 16:26:38 -0400964 !ssl->session->ticket.empty() &&
David Benjaminc11ea9422017-08-29 16:33:21 -0400965 // Don't send TLS 1.3 session tickets in the ticket extension.
David Benjamin50596f82018-07-02 19:47:27 -0400966 ssl_session_protocol_version(ssl->session.get()) < TLS1_3_VERSION) {
David Benjaminbfdd1a92018-06-29 16:26:38 -0400967 ticket = ssl->session->ticket;
Adam Langley9b05bc52015-07-01 15:25:33 -0700968 }
969
David Benjaminbfdd1a92018-06-29 16:26:38 -0400970 CBB ticket_cbb;
Adam Langley9b05bc52015-07-01 15:25:33 -0700971 if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
David Benjaminbfdd1a92018-06-29 16:26:38 -0400972 !CBB_add_u16_length_prefixed(out, &ticket_cbb) ||
973 !CBB_add_bytes(&ticket_cbb, ticket.data(), ticket.size()) ||
Adam Langley9b05bc52015-07-01 15:25:33 -0700974 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -0400975 return false;
Adam Langley9b05bc52015-07-01 15:25:33 -0700976 }
977
David Benjamin31640932017-10-11 13:22:39 -0400978 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700979}
980
David Benjamin31640932017-10-11 13:22:39 -0400981static bool ext_ticket_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
982 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -0500983 SSL *const ssl = hs->ssl;
Adam Langley9b05bc52015-07-01 15:25:33 -0700984 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -0400985 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -0700986 }
987
David Benjamind1e3ce12017-10-06 18:31:15 -0400988 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -0400989 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -0400990 }
991
David Benjaminc11ea9422017-08-29 16:33:21 -0400992 // If |SSL_OP_NO_TICKET| is set then no extension will have been sent and
993 // this function should never be called, even if the server tries to send the
994 // extension.
Adam Langley9b05bc52015-07-01 15:25:33 -0700995 assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0);
996
997 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -0400998 return false;
Adam Langley9b05bc52015-07-01 15:25:33 -0700999 }
1000
David Benjaminfd45ee72017-08-31 14:49:09 -04001001 hs->ticket_expected = true;
David Benjamin31640932017-10-11 13:22:39 -04001002 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -07001003}
1004
David Benjamin31640932017-10-11 13:22:39 -04001005static bool ext_ticket_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001006 if (!hs->ticket_expected) {
David Benjamin31640932017-10-11 13:22:39 -04001007 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -07001008 }
1009
David Benjaminc11ea9422017-08-29 16:33:21 -04001010 // If |SSL_OP_NO_TICKET| is set, |ticket_expected| should never be true.
David Benjamin8c880a22016-12-03 02:20:34 -05001011 assert((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) == 0);
Adam Langley9b05bc52015-07-01 15:25:33 -07001012
1013 if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
1014 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001015 return false;
Adam Langley9b05bc52015-07-01 15:25:33 -07001016 }
1017
David Benjamin31640932017-10-11 13:22:39 -04001018 return true;
Adam Langley9b05bc52015-07-01 15:25:33 -07001019}
1020
1021
David Benjaminc11ea9422017-08-29 16:33:21 -04001022// Signature Algorithms.
1023//
1024// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
Adam Langley2e857bd2015-07-01 16:09:19 -07001025
David Benjamin83a49932021-05-20 15:57:09 -04001026static bool ext_sigalgs_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1027 CBB *out_compressible,
1028 ssl_client_hello_type_t type) {
David Benjamin68161cb2017-06-20 14:49:43 -04001029 if (hs->max_version < TLS1_2_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001030 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001031 }
1032
David Benjamin0fc37ef2016-08-17 15:29:46 -04001033 CBB contents, sigalgs_cbb;
David Benjamin83a49932021-05-20 15:57:09 -04001034 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_signature_algorithms) ||
1035 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
David Benjamin69522112017-03-28 15:38:29 -05001036 !CBB_add_u16_length_prefixed(&contents, &sigalgs_cbb) ||
David Benjaminebad5082020-02-03 19:32:19 -05001037 !tls12_add_verify_sigalgs(hs, &sigalgs_cbb) ||
David Benjamin83a49932021-05-20 15:57:09 -04001038 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001039 return false;
Adam Langley2e857bd2015-07-01 16:09:19 -07001040 }
1041
David Benjamin31640932017-10-11 13:22:39 -04001042 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001043}
1044
David Benjamin31640932017-10-11 13:22:39 -04001045static bool ext_sigalgs_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1046 CBS *contents) {
David Benjaminb1cf48e2017-09-21 11:37:46 -04001047 hs->peer_sigalgs.Reset();
Adam Langley2e857bd2015-07-01 16:09:19 -07001048 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001049 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001050 }
1051
1052 CBS supported_signature_algorithms;
1053 if (!CBS_get_u16_length_prefixed(contents, &supported_signature_algorithms) ||
Steven Valdez0d62f262015-09-04 12:41:04 -04001054 CBS_len(contents) != 0 ||
David Benjaminf3c8f8d2016-11-17 17:20:47 +09001055 !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
David Benjamin31640932017-10-11 13:22:39 -04001056 return false;
Adam Langley2e857bd2015-07-01 16:09:19 -07001057 }
1058
David Benjamin31640932017-10-11 13:22:39 -04001059 return true;
Adam Langley2e857bd2015-07-01 16:09:19 -07001060}
1061
Adam Langley2e857bd2015-07-01 16:09:19 -07001062
David Benjaminc11ea9422017-08-29 16:33:21 -04001063// OCSP Stapling.
1064//
1065// https://tools.ietf.org/html/rfc6066#section-8
Adam Langleybb0bd042015-07-01 16:21:03 -07001066
David Benjamin83a49932021-05-20 15:57:09 -04001067static bool ext_ocsp_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1068 CBB *out_compressible,
1069 ssl_client_hello_type_t type) {
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001070 if (!hs->config->ocsp_stapling_enabled) {
David Benjamin31640932017-10-11 13:22:39 -04001071 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001072 }
1073
1074 CBB contents;
David Benjamin83a49932021-05-20 15:57:09 -04001075 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_status_request) ||
1076 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Adam Langleybb0bd042015-07-01 16:21:03 -07001077 !CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) ||
1078 !CBB_add_u16(&contents, 0 /* empty responder ID list */) ||
1079 !CBB_add_u16(&contents, 0 /* empty request extensions */) ||
David Benjamin83a49932021-05-20 15:57:09 -04001080 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001081 return false;
Adam Langleybb0bd042015-07-01 16:21:03 -07001082 }
1083
David Benjamin31640932017-10-11 13:22:39 -04001084 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001085}
1086
David Benjamin31640932017-10-11 13:22:39 -04001087static bool ext_ocsp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1088 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001089 SSL *const ssl = hs->ssl;
Adam Langleybb0bd042015-07-01 16:21:03 -07001090 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001091 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001092 }
1093
David Benjaminc11ea9422017-08-29 16:33:21 -04001094 // TLS 1.3 OCSP responses are included in the Certificate extensions.
David Benjamind1e3ce12017-10-06 18:31:15 -04001095 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001096 return false;
Steven Valdez803c77a2016-09-06 14:13:43 -04001097 }
1098
David Benjaminc11ea9422017-08-29 16:33:21 -04001099 // OCSP stapling is forbidden on non-certificate ciphers.
Steven Valdeza833c352016-11-01 13:39:36 -04001100 if (CBS_len(contents) != 0 ||
David Benjamin45738dd2017-02-09 20:01:26 -05001101 !ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
David Benjamin31640932017-10-11 13:22:39 -04001102 return false;
David Benjamin942f4ed2016-07-16 19:03:49 +03001103 }
1104
David Benjaminc11ea9422017-08-29 16:33:21 -04001105 // Note this does not check for resumption in TLS 1.2. Sending
1106 // status_request here does not make sense, but OpenSSL does so and the
1107 // specification does not say anything. Tolerate it but ignore it.
David Benjamin942f4ed2016-07-16 19:03:49 +03001108
David Benjaminfd45ee72017-08-31 14:49:09 -04001109 hs->certificate_status_expected = true;
David Benjamin31640932017-10-11 13:22:39 -04001110 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001111}
1112
David Benjamin31640932017-10-11 13:22:39 -04001113static bool ext_ocsp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1114 CBS *contents) {
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001115 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001116 return true;
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001117 }
1118
1119 uint8_t status_type;
1120 if (!CBS_get_u8(contents, &status_type)) {
David Benjamin31640932017-10-11 13:22:39 -04001121 return false;
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001122 }
1123
David Benjaminc11ea9422017-08-29 16:33:21 -04001124 // We cannot decide whether OCSP stapling will occur yet because the correct
1125 // SSL_CTX might not have been selected.
David Benjamin8c880a22016-12-03 02:20:34 -05001126 hs->ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp;
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001127
David Benjamin31640932017-10-11 13:22:39 -04001128 return true;
Adam Langleybb0bd042015-07-01 16:21:03 -07001129}
1130
David Benjamin31640932017-10-11 13:22:39 -04001131static bool ext_ocsp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001132 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04001133 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
David Benjamin4fa48042024-03-12 09:48:29 -04001134 !hs->ocsp_stapling_requested || ssl->s3->session_reused ||
1135 !ssl_cipher_uses_certificate_auth(hs->new_cipher) ||
1136 hs->credential->ocsp_response == nullptr) {
David Benjamin31640932017-10-11 13:22:39 -04001137 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001138 }
1139
David Benjaminfd45ee72017-08-31 14:49:09 -04001140 hs->certificate_status_expected = true;
David Benjamin942f4ed2016-07-16 19:03:49 +03001141
Paul Lietaraeeff2c2015-08-12 11:47:11 +01001142 return CBB_add_u16(out, TLSEXT_TYPE_status_request) &&
Steven Valdeza833c352016-11-01 13:39:36 -04001143 CBB_add_u16(out, 0 /* length */);
Adam Langleybb0bd042015-07-01 16:21:03 -07001144}
1145
1146
David Benjaminc11ea9422017-08-29 16:33:21 -04001147// Next protocol negotiation.
1148//
1149// https://htmlpreview.github.io/?https://github.com/agl/technotes/blob/master/nextprotoneg.html
Adam Langley97dfcbf2015-07-01 18:35:20 -07001150
David Benjamin83a49932021-05-20 15:57:09 -04001151static bool ext_npn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1152 CBB *out_compressible,
1153 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001154 const SSL *const ssl = hs->ssl;
David Benjamin83a49932021-05-20 15:57:09 -04001155 if (ssl->ctx->next_proto_select_cb == NULL ||
1156 // Do not allow NPN to change on renegotiation.
1157 ssl->s3->initial_handshake_complete ||
1158 // NPN is not defined in DTLS or TLS 1.3.
1159 SSL_is_dtls(ssl) || hs->min_version >= TLS1_3_VERSION ||
1160 type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -04001161 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001162 }
1163
1164 if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) ||
1165 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001166 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001167 }
1168
David Benjamin31640932017-10-11 13:22:39 -04001169 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001170}
1171
David Benjamin31640932017-10-11 13:22:39 -04001172static bool ext_npn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1173 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001174 SSL *const ssl = hs->ssl;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001175 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001176 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001177 }
1178
David Benjamind1e3ce12017-10-06 18:31:15 -04001179 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001180 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04001181 }
1182
David Benjaminc11ea9422017-08-29 16:33:21 -04001183 // If any of these are false then we should never have sent the NPN
1184 // extension in the ClientHello and thus this function should never have been
1185 // called.
Adam Langley97dfcbf2015-07-01 18:35:20 -07001186 assert(!ssl->s3->initial_handshake_complete);
David Benjamince079fd2016-08-02 16:22:34 -04001187 assert(!SSL_is_dtls(ssl));
Adam Langley97dfcbf2015-07-01 18:35:20 -07001188 assert(ssl->ctx->next_proto_select_cb != NULL);
1189
David Benjamin8e7bbba2017-10-13 17:18:35 -04001190 if (!ssl->s3->alpn_selected.empty()) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001191 // NPN and ALPN may not be negotiated in the same connection.
David Benjamin76c2efc2015-08-31 14:24:29 -04001192 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1193 OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
David Benjamin31640932017-10-11 13:22:39 -04001194 return false;
David Benjamin76c2efc2015-08-31 14:24:29 -04001195 }
1196
Adam Langley97dfcbf2015-07-01 18:35:20 -07001197 const uint8_t *const orig_contents = CBS_data(contents);
1198 const size_t orig_len = CBS_len(contents);
1199
1200 while (CBS_len(contents) != 0) {
1201 CBS proto;
1202 if (!CBS_get_u8_length_prefixed(contents, &proto) ||
1203 CBS_len(&proto) == 0) {
David Benjamin31640932017-10-11 13:22:39 -04001204 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001205 }
1206 }
1207
David Benjamin9d64d8d2022-08-31 19:27:56 -04001208 // |orig_len| fits in |unsigned| because TLS extensions use 16-bit lengths.
Adam Langley97dfcbf2015-07-01 18:35:20 -07001209 uint8_t *selected;
1210 uint8_t selected_len;
1211 if (ssl->ctx->next_proto_select_cb(
David Benjamin9d64d8d2022-08-31 19:27:56 -04001212 ssl, &selected, &selected_len, orig_contents,
1213 static_cast<unsigned>(orig_len),
David Benjamin8e7bbba2017-10-13 17:18:35 -04001214 ssl->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK ||
1215 !ssl->s3->next_proto_negotiated.CopyFrom(
1216 MakeConstSpan(selected, selected_len))) {
Adam Langley97dfcbf2015-07-01 18:35:20 -07001217 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001218 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001219 }
1220
David Benjaminfd45ee72017-08-31 14:49:09 -04001221 hs->next_proto_neg_seen = true;
David Benjamin31640932017-10-11 13:22:39 -04001222 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001223}
1224
David Benjamin31640932017-10-11 13:22:39 -04001225static bool ext_npn_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1226 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001227 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04001228 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001229 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001230 }
1231
Adam Langley97dfcbf2015-07-01 18:35:20 -07001232 if (contents != NULL && CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001233 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001234 }
1235
1236 if (contents == NULL ||
1237 ssl->s3->initial_handshake_complete ||
Adam Langley97dfcbf2015-07-01 18:35:20 -07001238 ssl->ctx->next_protos_advertised_cb == NULL ||
David Benjamince079fd2016-08-02 16:22:34 -04001239 SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001240 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001241 }
1242
David Benjaminfd45ee72017-08-31 14:49:09 -04001243 hs->next_proto_neg_seen = true;
David Benjamin31640932017-10-11 13:22:39 -04001244 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001245}
1246
David Benjamin31640932017-10-11 13:22:39 -04001247static bool ext_npn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001248 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -04001249 // |next_proto_neg_seen| might have been cleared when an ALPN extension was
1250 // parsed.
David Benjamin8c880a22016-12-03 02:20:34 -05001251 if (!hs->next_proto_neg_seen) {
David Benjamin31640932017-10-11 13:22:39 -04001252 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001253 }
1254
1255 const uint8_t *npa;
1256 unsigned npa_len;
1257
1258 if (ssl->ctx->next_protos_advertised_cb(
1259 ssl, &npa, &npa_len, ssl->ctx->next_protos_advertised_cb_arg) !=
1260 SSL_TLSEXT_ERR_OK) {
David Benjaminfd45ee72017-08-31 14:49:09 -04001261 hs->next_proto_neg_seen = false;
David Benjamin31640932017-10-11 13:22:39 -04001262 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001263 }
1264
1265 CBB contents;
1266 if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) ||
1267 !CBB_add_u16_length_prefixed(out, &contents) ||
1268 !CBB_add_bytes(&contents, npa, npa_len) ||
1269 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001270 return false;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001271 }
1272
David Benjamin31640932017-10-11 13:22:39 -04001273 return true;
Adam Langley97dfcbf2015-07-01 18:35:20 -07001274}
1275
1276
David Benjaminc11ea9422017-08-29 16:33:21 -04001277// Signed certificate timestamps.
1278//
1279// https://tools.ietf.org/html/rfc6962#section-3.3.1
Adam Langleyab8d87d2015-07-10 12:21:39 -07001280
David Benjamin83a49932021-05-20 15:57:09 -04001281static bool ext_sct_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1282 CBB *out_compressible,
1283 ssl_client_hello_type_t type) {
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001284 if (!hs->config->signed_cert_timestamps_enabled) {
David Benjamin31640932017-10-11 13:22:39 -04001285 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001286 }
1287
David Benjamin83a49932021-05-20 15:57:09 -04001288 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_certificate_timestamp) ||
1289 !CBB_add_u16(out_compressible, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001290 return false;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001291 }
1292
David Benjamin31640932017-10-11 13:22:39 -04001293 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001294}
1295
David Benjamin31640932017-10-11 13:22:39 -04001296static bool ext_sct_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1297 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001298 SSL *const ssl = hs->ssl;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001299 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001300 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001301 }
1302
David Benjaminc11ea9422017-08-29 16:33:21 -04001303 // TLS 1.3 SCTs are included in the Certificate extensions.
David Benjamind1e3ce12017-10-06 18:31:15 -04001304 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
Adam Langleycfa08c32016-11-17 13:21:27 -08001305 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001306 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04001307 }
1308
David Benjaminc11ea9422017-08-29 16:33:21 -04001309 // If this is false then we should never have sent the SCT extension in the
1310 // ClientHello and thus this function should never have been called.
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001311 assert(hs->config->signed_cert_timestamps_enabled);
Adam Langleyab8d87d2015-07-10 12:21:39 -07001312
Adam Langleycfa08c32016-11-17 13:21:27 -08001313 if (!ssl_is_sct_list_valid(contents)) {
Adam Langleyab8d87d2015-07-10 12:21:39 -07001314 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001315 return false;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001316 }
1317
David Benjaminc11ea9422017-08-29 16:33:21 -04001318 // Session resumption uses the original session information. The extension
1319 // should not be sent on resumption, but RFC 6962 did not make it a
1320 // requirement, so tolerate this.
1321 //
1322 // TODO(davidben): Enforce this anyway.
David Benjamin8fc2dc02017-08-22 15:07:51 -07001323 if (!ssl->s3->session_reused) {
David Benjaminbfdd1a92018-06-29 16:26:38 -04001324 hs->new_session->signed_cert_timestamp_list.reset(
1325 CRYPTO_BUFFER_new_from_CBS(contents, ssl->ctx->pool));
David Benjamin8fc2dc02017-08-22 15:07:51 -07001326 if (hs->new_session->signed_cert_timestamp_list == nullptr) {
1327 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001328 return false;
David Benjamin8fc2dc02017-08-22 15:07:51 -07001329 }
Adam Langleyab8d87d2015-07-10 12:21:39 -07001330 }
1331
David Benjamin31640932017-10-11 13:22:39 -04001332 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001333}
1334
David Benjamin31640932017-10-11 13:22:39 -04001335static bool ext_sct_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1336 CBS *contents) {
David Benjamin53210cb2016-11-16 09:01:48 +09001337 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001338 return true;
David Benjamin53210cb2016-11-16 09:01:48 +09001339 }
1340
1341 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001342 return false;
David Benjamin53210cb2016-11-16 09:01:48 +09001343 }
1344
David Benjaminfd45ee72017-08-31 14:49:09 -04001345 hs->scts_requested = true;
David Benjamin31640932017-10-11 13:22:39 -04001346 return true;
Adam Langleyab8d87d2015-07-10 12:21:39 -07001347}
1348
David Benjamin31640932017-10-11 13:22:39 -04001349static bool ext_sct_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001350 SSL *const ssl = hs->ssl;
David Benjamin4fa48042024-03-12 09:48:29 -04001351 assert(hs->scts_requested);
David Benjaminc11ea9422017-08-29 16:33:21 -04001352 // The extension shouldn't be sent when resuming sessions.
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001353 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION || ssl->s3->session_reused ||
David Benjamin4fa48042024-03-12 09:48:29 -04001354 !ssl_cipher_uses_certificate_auth(hs->new_cipher) ||
David Benjamin91a3f262024-02-10 11:08:08 -05001355 hs->credential->signed_cert_timestamp_list == nullptr) {
David Benjamin31640932017-10-11 13:22:39 -04001356 return true;
Paul Lietar4fac72e2015-09-09 13:44:55 +01001357 }
1358
1359 CBB contents;
1360 return CBB_add_u16(out, TLSEXT_TYPE_certificate_timestamp) &&
1361 CBB_add_u16_length_prefixed(out, &contents) &&
David Benjamin91a3f262024-02-10 11:08:08 -05001362 CBB_add_bytes(&contents,
1363 CRYPTO_BUFFER_data(
1364 hs->credential->signed_cert_timestamp_list.get()),
1365 CRYPTO_BUFFER_len(
1366 hs->credential->signed_cert_timestamp_list.get())) &&
Paul Lietar4fac72e2015-09-09 13:44:55 +01001367 CBB_flush(out);
Adam Langleyab8d87d2015-07-10 12:21:39 -07001368}
1369
1370
David Benjaminc11ea9422017-08-29 16:33:21 -04001371// Application-level Protocol Negotiation.
1372//
1373// https://tools.ietf.org/html/rfc7301
Adam Langleyf18e4532015-07-10 13:39:53 -07001374
David Benjamin83a49932021-05-20 15:57:09 -04001375static bool ext_alpn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1376 CBB *out_compressible,
1377 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001378 const SSL *const ssl = hs->ssl;
Nick Harper74161f42020-07-24 15:35:27 -07001379 if (hs->config->alpn_client_proto_list.empty() && ssl->quic_method) {
1380 // ALPN MUST be used with QUIC.
David Benjaminc02c19e2021-02-10 17:49:20 -05001381 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
Nick Harper74161f42020-07-24 15:35:27 -07001382 return false;
1383 }
1384
David Benjamin0ce090a2018-07-02 20:24:40 -04001385 if (hs->config->alpn_client_proto_list.empty() ||
Adam Langleyf18e4532015-07-10 13:39:53 -07001386 ssl->s3->initial_handshake_complete) {
David Benjamin31640932017-10-11 13:22:39 -04001387 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001388 }
1389
1390 CBB contents, proto_list;
David Benjamin83a49932021-05-20 15:57:09 -04001391 if (!CBB_add_u16(out_compressible,
1392 TLSEXT_TYPE_application_layer_protocol_negotiation) ||
1393 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Adam Langleyf18e4532015-07-10 13:39:53 -07001394 !CBB_add_u16_length_prefixed(&contents, &proto_list) ||
David Benjamin0ce090a2018-07-02 20:24:40 -04001395 !CBB_add_bytes(&proto_list, hs->config->alpn_client_proto_list.data(),
1396 hs->config->alpn_client_proto_list.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -04001397 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001398 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001399 }
1400
David Benjamin31640932017-10-11 13:22:39 -04001401 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001402}
1403
David Benjamin31640932017-10-11 13:22:39 -04001404static bool ext_alpn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1405 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001406 SSL *const ssl = hs->ssl;
Adam Langleyf18e4532015-07-10 13:39:53 -07001407 if (contents == NULL) {
Nick Harper74161f42020-07-24 15:35:27 -07001408 if (ssl->quic_method) {
1409 // ALPN is required when QUIC is used.
David Benjaminc02c19e2021-02-10 17:49:20 -05001410 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
Nick Harper74161f42020-07-24 15:35:27 -07001411 *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1412 return false;
1413 }
David Benjamin31640932017-10-11 13:22:39 -04001414 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001415 }
1416
1417 assert(!ssl->s3->initial_handshake_complete);
David Benjamin0ce090a2018-07-02 20:24:40 -04001418 assert(!hs->config->alpn_client_proto_list.empty());
Adam Langleyf18e4532015-07-10 13:39:53 -07001419
David Benjamin8c880a22016-12-03 02:20:34 -05001420 if (hs->next_proto_neg_seen) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001421 // NPN and ALPN may not be negotiated in the same connection.
David Benjamin76c2efc2015-08-31 14:24:29 -04001422 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1423 OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
David Benjamin31640932017-10-11 13:22:39 -04001424 return false;
David Benjamin76c2efc2015-08-31 14:24:29 -04001425 }
1426
David Benjaminc11ea9422017-08-29 16:33:21 -04001427 // The extension data consists of a ProtocolNameList which must have
1428 // exactly one ProtocolName. Each of these is length-prefixed.
Adam Langleyf18e4532015-07-10 13:39:53 -07001429 CBS protocol_name_list, protocol_name;
1430 if (!CBS_get_u16_length_prefixed(contents, &protocol_name_list) ||
1431 CBS_len(contents) != 0 ||
1432 !CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) ||
David Benjaminc11ea9422017-08-29 16:33:21 -04001433 // Empty protocol names are forbidden.
Adam Langleyf18e4532015-07-10 13:39:53 -07001434 CBS_len(&protocol_name) == 0 ||
1435 CBS_len(&protocol_name_list) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001436 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001437 }
1438
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001439 if (!ssl_is_alpn_protocol_allowed(hs, protocol_name)) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001440 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
1441 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
1442 return false;
David Benjamin3e51757d2016-08-11 11:52:23 -04001443 }
1444
David Benjamin8e7bbba2017-10-13 17:18:35 -04001445 if (!ssl->s3->alpn_selected.CopyFrom(protocol_name)) {
Adam Langleyf18e4532015-07-10 13:39:53 -07001446 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001447 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001448 }
1449
David Benjamin31640932017-10-11 13:22:39 -04001450 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001451}
1452
David Benjamin12a3e7e2021-04-13 11:47:36 -04001453bool ssl_is_valid_alpn_list(Span<const uint8_t> in) {
1454 CBS protocol_name_list = in;
1455 if (CBS_len(&protocol_name_list) == 0) {
1456 return false;
1457 }
1458 while (CBS_len(&protocol_name_list) > 0) {
1459 CBS protocol_name;
1460 if (!CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) ||
1461 // Empty protocol names are forbidden.
1462 CBS_len(&protocol_name) == 0) {
1463 return false;
1464 }
1465 }
1466 return true;
1467}
1468
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001469bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs,
David Benjamindd6c2e82017-10-17 15:48:46 -04001470 Span<const uint8_t> protocol) {
David Benjamin0ce090a2018-07-02 20:24:40 -04001471 if (hs->config->alpn_client_proto_list.empty()) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001472 return false;
1473 }
1474
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07001475 if (hs->ssl->ctx->allow_unknown_alpn_protos) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001476 return true;
1477 }
1478
1479 // Check that the protocol name is one of the ones we advertised.
David Benjaminc1d9ac02024-05-22 13:56:56 -04001480 return ssl_alpn_list_contains_protocol(hs->config->alpn_client_proto_list,
1481 protocol);
1482}
1483
1484bool ssl_alpn_list_contains_protocol(Span<const uint8_t> list,
1485 Span<const uint8_t> protocol) {
1486 CBS cbs = list, candidate;
1487 while (CBS_len(&cbs) > 0) {
1488 if (!CBS_get_u8_length_prefixed(&cbs, &candidate)) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001489 return false;
1490 }
1491
David Benjaminc1d9ac02024-05-22 13:56:56 -04001492 if (candidate == protocol) {
David Benjamindd6c2e82017-10-17 15:48:46 -04001493 return true;
1494 }
1495 }
1496
1497 return false;
1498}
1499
David Benjamin31640932017-10-11 13:22:39 -04001500bool ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1501 const SSL_CLIENT_HELLO *client_hello) {
David Benjaminf3c8f8d2016-11-17 17:20:47 +09001502 SSL *const ssl = hs->ssl;
David Benjamin9ef31f02016-10-31 18:01:13 -04001503 CBS contents;
Adam Langleyf18e4532015-07-10 13:39:53 -07001504 if (ssl->ctx->alpn_select_cb == NULL ||
David Benjamin731058e2016-12-03 23:15:13 -05001505 !ssl_client_hello_get_extension(
David Benjamin9ef31f02016-10-31 18:01:13 -04001506 client_hello, &contents,
1507 TLSEXT_TYPE_application_layer_protocol_negotiation)) {
Nick Harper74161f42020-07-24 15:35:27 -07001508 if (ssl->quic_method) {
1509 // ALPN is required when QUIC is used.
David Benjaminc02c19e2021-02-10 17:49:20 -05001510 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
Nick Harper74161f42020-07-24 15:35:27 -07001511 *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1512 return false;
1513 }
David Benjaminc11ea9422017-08-29 16:33:21 -04001514 // Ignore ALPN if not configured or no extension was supplied.
David Benjamin31640932017-10-11 13:22:39 -04001515 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001516 }
1517
David Benjaminc11ea9422017-08-29 16:33:21 -04001518 // ALPN takes precedence over NPN.
David Benjaminfd45ee72017-08-31 14:49:09 -04001519 hs->next_proto_neg_seen = false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001520
1521 CBS protocol_name_list;
David Benjamin9ef31f02016-10-31 18:01:13 -04001522 if (!CBS_get_u16_length_prefixed(&contents, &protocol_name_list) ||
1523 CBS_len(&contents) != 0 ||
David Benjamin12a3e7e2021-04-13 11:47:36 -04001524 !ssl_is_valid_alpn_list(protocol_name_list)) {
David Benjamin9ef31f02016-10-31 18:01:13 -04001525 OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
1526 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001527 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001528 }
1529
David Benjamin9d64d8d2022-08-31 19:27:56 -04001530 // |protocol_name_list| fits in |unsigned| because TLS extensions use 16-bit
1531 // lengths.
Adam Langleyf18e4532015-07-10 13:39:53 -07001532 const uint8_t *selected;
1533 uint8_t selected_len;
David Benjaminc02c19e2021-02-10 17:49:20 -05001534 int ret = ssl->ctx->alpn_select_cb(
1535 ssl, &selected, &selected_len, CBS_data(&protocol_name_list),
David Benjamin9d64d8d2022-08-31 19:27:56 -04001536 static_cast<unsigned>(CBS_len(&protocol_name_list)),
1537 ssl->ctx->alpn_select_cb_arg);
David Benjaminc02c19e2021-02-10 17:49:20 -05001538 // ALPN is required when QUIC is used.
1539 if (ssl->quic_method &&
1540 (ret == SSL_TLSEXT_ERR_NOACK || ret == SSL_TLSEXT_ERR_ALERT_WARNING)) {
1541 ret = SSL_TLSEXT_ERR_ALERT_FATAL;
1542 }
1543 switch (ret) {
1544 case SSL_TLSEXT_ERR_OK:
1545 if (selected_len == 0) {
1546 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
1547 *out_alert = SSL_AD_INTERNAL_ERROR;
1548 return false;
1549 }
1550 if (!ssl->s3->alpn_selected.CopyFrom(
1551 MakeConstSpan(selected, selected_len))) {
1552 *out_alert = SSL_AD_INTERNAL_ERROR;
1553 return false;
1554 }
1555 break;
1556 case SSL_TLSEXT_ERR_NOACK:
1557 case SSL_TLSEXT_ERR_ALERT_WARNING:
1558 break;
1559 case SSL_TLSEXT_ERR_ALERT_FATAL:
1560 *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
1561 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL);
David Benjaminfa544f12018-05-15 15:06:28 -04001562 return false;
David Benjaminc02c19e2021-02-10 17:49:20 -05001563 default:
1564 // Invalid return value.
Adam Langleyf18e4532015-07-10 13:39:53 -07001565 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjaminc02c19e2021-02-10 17:49:20 -05001566 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin31640932017-10-11 13:22:39 -04001567 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001568 }
1569
David Benjamin31640932017-10-11 13:22:39 -04001570 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001571}
1572
David Benjamin31640932017-10-11 13:22:39 -04001573static bool ext_alpn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001574 SSL *const ssl = hs->ssl;
David Benjamin8e7bbba2017-10-13 17:18:35 -04001575 if (ssl->s3->alpn_selected.empty()) {
David Benjamin31640932017-10-11 13:22:39 -04001576 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001577 }
1578
1579 CBB contents, proto_list, proto;
1580 if (!CBB_add_u16(out, TLSEXT_TYPE_application_layer_protocol_negotiation) ||
1581 !CBB_add_u16_length_prefixed(out, &contents) ||
1582 !CBB_add_u16_length_prefixed(&contents, &proto_list) ||
1583 !CBB_add_u8_length_prefixed(&proto_list, &proto) ||
David Benjamin8e7bbba2017-10-13 17:18:35 -04001584 !CBB_add_bytes(&proto, ssl->s3->alpn_selected.data(),
1585 ssl->s3->alpn_selected.size()) ||
Adam Langleyf18e4532015-07-10 13:39:53 -07001586 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001587 return false;
Adam Langleyf18e4532015-07-10 13:39:53 -07001588 }
1589
David Benjamin31640932017-10-11 13:22:39 -04001590 return true;
Adam Langleyf18e4532015-07-10 13:39:53 -07001591}
1592
1593
David Benjaminc11ea9422017-08-29 16:33:21 -04001594// Channel ID.
1595//
1596// https://tools.ietf.org/html/draft-balfanz-tls-channelid-01
Adam Langley49c7af12015-07-10 14:33:46 -07001597
David Benjamin83a49932021-05-20 15:57:09 -04001598static bool ext_channel_id_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1599 CBB *out_compressible,
1600 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001601 const SSL *const ssl = hs->ssl;
David Benjaminba423c92021-06-15 16:26:58 -04001602 if (!hs->config->channel_id_private || SSL_is_dtls(ssl) ||
1603 // Don't offer Channel ID in ClientHelloOuter. ClientHelloOuter handshakes
1604 // are not authenticated for the name that can learn the Channel ID.
1605 //
1606 // We could alternatively offer the extension but sign with a random key.
1607 // For other extensions, we try to align |ssl_client_hello_outer| and
1608 // |ssl_client_hello_unencrypted|, to improve the effectiveness of ECH
1609 // GREASE. However, Channel ID is deprecated and unlikely to be used with
1610 // ECH, so do the simplest thing.
1611 type == ssl_client_hello_outer) {
David Benjamin31640932017-10-11 13:22:39 -04001612 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001613 }
1614
David Benjaminba423c92021-06-15 16:26:58 -04001615 if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) ||
1616 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001617 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001618 }
1619
David Benjamin31640932017-10-11 13:22:39 -04001620 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001621}
1622
David Benjamin31640932017-10-11 13:22:39 -04001623static bool ext_channel_id_parse_serverhello(SSL_HANDSHAKE *hs,
1624 uint8_t *out_alert,
1625 CBS *contents) {
Adam Langley49c7af12015-07-10 14:33:46 -07001626 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001627 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001628 }
1629
David Benjamin8acec002021-05-19 13:03:34 -04001630 assert(!SSL_is_dtls(hs->ssl));
David Benjaminb5879112021-05-18 17:10:18 -04001631 assert(hs->config->channel_id_private);
Adam Langley49c7af12015-07-10 14:33:46 -07001632
1633 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001634 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001635 }
1636
David Benjamin8acec002021-05-19 13:03:34 -04001637 hs->channel_id_negotiated = true;
David Benjamin31640932017-10-11 13:22:39 -04001638 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001639}
1640
David Benjamin31640932017-10-11 13:22:39 -04001641static bool ext_channel_id_parse_clienthello(SSL_HANDSHAKE *hs,
1642 uint8_t *out_alert,
1643 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001644 SSL *const ssl = hs->ssl;
David Benjamin46853762018-07-03 14:01:26 -04001645 if (contents == NULL || !hs->config->channel_id_enabled || SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001646 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001647 }
1648
1649 if (CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001650 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001651 }
1652
David Benjamin8acec002021-05-19 13:03:34 -04001653 hs->channel_id_negotiated = true;
David Benjamin31640932017-10-11 13:22:39 -04001654 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001655}
1656
David Benjamin31640932017-10-11 13:22:39 -04001657static bool ext_channel_id_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8acec002021-05-19 13:03:34 -04001658 if (!hs->channel_id_negotiated) {
David Benjamin31640932017-10-11 13:22:39 -04001659 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001660 }
1661
1662 if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) ||
1663 !CBB_add_u16(out, 0 /* length */)) {
David Benjamin31640932017-10-11 13:22:39 -04001664 return false;
Adam Langley49c7af12015-07-10 14:33:46 -07001665 }
1666
David Benjamin31640932017-10-11 13:22:39 -04001667 return true;
Adam Langley49c7af12015-07-10 14:33:46 -07001668}
1669
Adam Langley391250d2015-07-15 19:06:07 -07001670
David Benjaminc11ea9422017-08-29 16:33:21 -04001671// Secure Real-time Transport Protocol (SRTP) extension.
1672//
1673// https://tools.ietf.org/html/rfc5764
Adam Langley391250d2015-07-15 19:06:07 -07001674
David Benjamin83a49932021-05-20 15:57:09 -04001675static bool ext_srtp_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1676 CBB *out_compressible,
1677 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001678 const SSL *const ssl = hs->ssl;
David Benjaminb778b9c2021-05-20 11:31:05 -04001679 const STACK_OF(SRTP_PROTECTION_PROFILE) *profiles =
1680 SSL_get_srtp_profiles(ssl);
David Benjaminee910bf2017-07-25 22:36:00 -04001681 if (profiles == NULL ||
David Benjaminbc4c91a2021-05-18 16:06:30 -04001682 sk_SRTP_PROTECTION_PROFILE_num(profiles) == 0 ||
1683 !SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001684 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001685 }
1686
1687 CBB contents, profile_ids;
David Benjamin83a49932021-05-20 15:57:09 -04001688 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_srtp) ||
1689 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Adam Langley391250d2015-07-15 19:06:07 -07001690 !CBB_add_u16_length_prefixed(&contents, &profile_ids)) {
David Benjamin31640932017-10-11 13:22:39 -04001691 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001692 }
1693
David Benjaminee910bf2017-07-25 22:36:00 -04001694 for (const SRTP_PROTECTION_PROFILE *profile : profiles) {
1695 if (!CBB_add_u16(&profile_ids, profile->id)) {
David Benjamin31640932017-10-11 13:22:39 -04001696 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001697 }
1698 }
1699
1700 if (!CBB_add_u8(&contents, 0 /* empty use_mki value */) ||
David Benjamin83a49932021-05-20 15:57:09 -04001701 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04001702 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001703 }
1704
David Benjamin31640932017-10-11 13:22:39 -04001705 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001706}
1707
David Benjamin31640932017-10-11 13:22:39 -04001708static bool ext_srtp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1709 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001710 SSL *const ssl = hs->ssl;
Adam Langley391250d2015-07-15 19:06:07 -07001711 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001712 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001713 }
1714
David Benjaminc11ea9422017-08-29 16:33:21 -04001715 // The extension consists of a u16-prefixed profile ID list containing a
1716 // single uint16_t profile ID, then followed by a u8-prefixed srtp_mki field.
1717 //
1718 // See https://tools.ietf.org/html/rfc5764#section-4.1.1
David Benjaminbc4c91a2021-05-18 16:06:30 -04001719 assert(SSL_is_dtls(ssl));
Adam Langley391250d2015-07-15 19:06:07 -07001720 CBS profile_ids, srtp_mki;
1721 uint16_t profile_id;
1722 if (!CBS_get_u16_length_prefixed(contents, &profile_ids) ||
1723 !CBS_get_u16(&profile_ids, &profile_id) ||
1724 CBS_len(&profile_ids) != 0 ||
1725 !CBS_get_u8_length_prefixed(contents, &srtp_mki) ||
1726 CBS_len(contents) != 0) {
1727 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
David Benjamin31640932017-10-11 13:22:39 -04001728 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001729 }
1730
1731 if (CBS_len(&srtp_mki) != 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001732 // Must be no MKI, since we never offer one.
Adam Langley391250d2015-07-15 19:06:07 -07001733 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_MKI_VALUE);
1734 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04001735 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001736 }
1737
David Benjaminb778b9c2021-05-20 11:31:05 -04001738 // Check to see if the server gave us something we support and offered.
1739 for (const SRTP_PROTECTION_PROFILE *profile : SSL_get_srtp_profiles(ssl)) {
Adam Langley391250d2015-07-15 19:06:07 -07001740 if (profile->id == profile_id) {
David Benjaminfceca8e2018-04-12 16:37:19 -04001741 ssl->s3->srtp_profile = profile;
David Benjamin31640932017-10-11 13:22:39 -04001742 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001743 }
1744 }
1745
1746 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
1747 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04001748 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001749}
1750
David Benjamin31640932017-10-11 13:22:39 -04001751static bool ext_srtp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1752 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05001753 SSL *const ssl = hs->ssl;
David Benjaminbc4c91a2021-05-18 16:06:30 -04001754 // DTLS-SRTP is only defined for DTLS.
1755 if (contents == NULL || !SSL_is_dtls(ssl)) {
David Benjamin31640932017-10-11 13:22:39 -04001756 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001757 }
1758
1759 CBS profile_ids, srtp_mki;
1760 if (!CBS_get_u16_length_prefixed(contents, &profile_ids) ||
1761 CBS_len(&profile_ids) < 2 ||
1762 !CBS_get_u8_length_prefixed(contents, &srtp_mki) ||
1763 CBS_len(contents) != 0) {
1764 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
David Benjamin31640932017-10-11 13:22:39 -04001765 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001766 }
David Benjaminc11ea9422017-08-29 16:33:21 -04001767 // Discard the MKI value for now.
Adam Langley391250d2015-07-15 19:06:07 -07001768
1769 const STACK_OF(SRTP_PROTECTION_PROFILE) *server_profiles =
1770 SSL_get_srtp_profiles(ssl);
1771
David Benjaminc11ea9422017-08-29 16:33:21 -04001772 // Pick the server's most preferred profile.
David Benjaminee910bf2017-07-25 22:36:00 -04001773 for (const SRTP_PROTECTION_PROFILE *server_profile : server_profiles) {
Adam Langley391250d2015-07-15 19:06:07 -07001774 CBS profile_ids_tmp;
1775 CBS_init(&profile_ids_tmp, CBS_data(&profile_ids), CBS_len(&profile_ids));
1776
1777 while (CBS_len(&profile_ids_tmp) > 0) {
1778 uint16_t profile_id;
1779 if (!CBS_get_u16(&profile_ids_tmp, &profile_id)) {
David Benjamin31640932017-10-11 13:22:39 -04001780 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001781 }
1782
1783 if (server_profile->id == profile_id) {
David Benjaminfceca8e2018-04-12 16:37:19 -04001784 ssl->s3->srtp_profile = server_profile;
David Benjamin31640932017-10-11 13:22:39 -04001785 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001786 }
1787 }
1788 }
1789
David Benjamin31640932017-10-11 13:22:39 -04001790 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001791}
1792
David Benjamin31640932017-10-11 13:22:39 -04001793static bool ext_srtp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001794 SSL *const ssl = hs->ssl;
David Benjaminfceca8e2018-04-12 16:37:19 -04001795 if (ssl->s3->srtp_profile == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001796 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001797 }
1798
David Benjaminbc4c91a2021-05-18 16:06:30 -04001799 assert(SSL_is_dtls(ssl));
Adam Langley391250d2015-07-15 19:06:07 -07001800 CBB contents, profile_ids;
1801 if (!CBB_add_u16(out, TLSEXT_TYPE_srtp) ||
1802 !CBB_add_u16_length_prefixed(out, &contents) ||
1803 !CBB_add_u16_length_prefixed(&contents, &profile_ids) ||
David Benjaminfceca8e2018-04-12 16:37:19 -04001804 !CBB_add_u16(&profile_ids, ssl->s3->srtp_profile->id) ||
Adam Langley391250d2015-07-15 19:06:07 -07001805 !CBB_add_u8(&contents, 0 /* empty MKI */) ||
1806 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001807 return false;
Adam Langley391250d2015-07-15 19:06:07 -07001808 }
1809
David Benjamin31640932017-10-11 13:22:39 -04001810 return true;
Adam Langley391250d2015-07-15 19:06:07 -07001811}
1812
Adam Langleybdd5d662015-07-20 16:19:08 -07001813
David Benjaminc11ea9422017-08-29 16:33:21 -04001814// EC point formats.
1815//
1816// https://tools.ietf.org/html/rfc4492#section-5.1.2
Adam Langleybdd5d662015-07-20 16:19:08 -07001817
David Benjamin14e51ad2021-05-19 15:24:34 -04001818static bool ext_ec_point_add_extension(const SSL_HANDSHAKE *hs, CBB *out) {
David Benjaminfc059942015-07-30 23:01:59 -04001819 CBB contents, formats;
Adam Langleybdd5d662015-07-20 16:19:08 -07001820 if (!CBB_add_u16(out, TLSEXT_TYPE_ec_point_formats) ||
1821 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjaminfc059942015-07-30 23:01:59 -04001822 !CBB_add_u8_length_prefixed(&contents, &formats) ||
1823 !CBB_add_u8(&formats, TLSEXT_ECPOINTFORMAT_uncompressed) ||
Adam Langleybdd5d662015-07-20 16:19:08 -07001824 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04001825 return false;
Adam Langleybdd5d662015-07-20 16:19:08 -07001826 }
1827
David Benjamin31640932017-10-11 13:22:39 -04001828 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001829}
1830
David Benjamin83a49932021-05-20 15:57:09 -04001831static bool ext_ec_point_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
1832 CBB *out_compressible,
1833 ssl_client_hello_type_t type) {
Adam Langleyffe384c2019-05-01 11:13:12 -07001834 // The point format extension is unnecessary in TLS 1.3.
David Benjamin83a49932021-05-20 15:57:09 -04001835 if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner) {
David Benjamin31640932017-10-11 13:22:39 -04001836 return true;
David Benjamin70aba262016-11-01 12:08:15 -04001837 }
1838
David Benjamin8c880a22016-12-03 02:20:34 -05001839 return ext_ec_point_add_extension(hs, out);
Adam Langleybdd5d662015-07-20 16:19:08 -07001840}
1841
David Benjamin31640932017-10-11 13:22:39 -04001842static bool ext_ec_point_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
1843 CBS *contents) {
Adam Langleybdd5d662015-07-20 16:19:08 -07001844 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04001845 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001846 }
1847
David Benjamind1e3ce12017-10-06 18:31:15 -04001848 if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001849 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04001850 }
1851
Adam Langleybdd5d662015-07-20 16:19:08 -07001852 CBS ec_point_format_list;
1853 if (!CBS_get_u8_length_prefixed(contents, &ec_point_format_list) ||
1854 CBS_len(contents) != 0) {
David Benjamin31640932017-10-11 13:22:39 -04001855 return false;
Adam Langleybdd5d662015-07-20 16:19:08 -07001856 }
1857
David Benjaminc11ea9422017-08-29 16:33:21 -04001858 // Per RFC 4492, section 5.1.2, implementations MUST support the uncompressed
1859 // point format.
David Benjamin17cf2cb2016-12-13 01:07:13 -05001860 if (OPENSSL_memchr(CBS_data(&ec_point_format_list),
1861 TLSEXT_ECPOINTFORMAT_uncompressed,
1862 CBS_len(&ec_point_format_list)) == NULL) {
David Benjaminfc059942015-07-30 23:01:59 -04001863 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04001864 return false;
Adam Langleybdd5d662015-07-20 16:19:08 -07001865 }
1866
David Benjamin31640932017-10-11 13:22:39 -04001867 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001868}
1869
David Benjamin31640932017-10-11 13:22:39 -04001870static bool ext_ec_point_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
Adam Langleybdd5d662015-07-20 16:19:08 -07001871 CBS *contents) {
David Benjamind1e3ce12017-10-06 18:31:15 -04001872 if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001873 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001874 }
1875
David Benjamin8c880a22016-12-03 02:20:34 -05001876 return ext_ec_point_parse_serverhello(hs, out_alert, contents);
Adam Langleybdd5d662015-07-20 16:19:08 -07001877}
1878
David Benjamin31640932017-10-11 13:22:39 -04001879static bool ext_ec_point_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05001880 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04001881 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04001882 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04001883 }
1884
David Benjamin45738dd2017-02-09 20:01:26 -05001885 const uint32_t alg_k = hs->new_cipher->algorithm_mkey;
1886 const uint32_t alg_a = hs->new_cipher->algorithm_auth;
David Benjamin31640932017-10-11 13:22:39 -04001887 const bool using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA);
Adam Langleybdd5d662015-07-20 16:19:08 -07001888
1889 if (!using_ecc) {
David Benjamin31640932017-10-11 13:22:39 -04001890 return true;
Adam Langleybdd5d662015-07-20 16:19:08 -07001891 }
1892
David Benjamin8c880a22016-12-03 02:20:34 -05001893 return ext_ec_point_add_extension(hs, out);
Adam Langleybdd5d662015-07-20 16:19:08 -07001894}
1895
Steven Valdeza833c352016-11-01 13:39:36 -04001896
David Benjaminc11ea9422017-08-29 16:33:21 -04001897// Pre Shared Key
1898//
David Benjamina130ce02018-08-14 22:26:39 -05001899// https://tools.ietf.org/html/rfc8446#section-4.2.11
Steven Valdez4aa154e2016-07-29 14:32:55 -04001900
David Benjamin83a49932021-05-20 15:57:09 -04001901static bool should_offer_psk(const SSL_HANDSHAKE *hs,
1902 ssl_client_hello_type_t type) {
David Benjamin350fe3b2021-06-02 17:58:53 -04001903 const SSL *const ssl = hs->ssl;
David Benjamin50596f82018-07-02 19:47:27 -04001904 if (hs->max_version < TLS1_3_VERSION || ssl->session == nullptr ||
David Benjamin83a49932021-05-20 15:57:09 -04001905 ssl_session_protocol_version(ssl->session.get()) < TLS1_3_VERSION ||
David Benjamin18b68362021-06-18 23:13:46 -04001906 // TODO(https://crbug.com/boringssl/275): Should we synthesize a
1907 // placeholder PSK, at least when we offer early data? Otherwise
1908 // ClientHelloOuter will contain an early_data extension without a
1909 // pre_shared_key extension and potentially break the recovery flow.
David Benjamin83a49932021-05-20 15:57:09 -04001910 type == ssl_client_hello_outer) {
David Benjamin350fe3b2021-06-02 17:58:53 -04001911 return false;
1912 }
1913
1914 // Per RFC 8446 section 4.1.4, skip offering the session if the selected
1915 // cipher in HelloRetryRequest does not match. This avoids performing the
1916 // transcript hash transformation for multiple hashes.
1917 if (ssl->s3->used_hello_retry_request &&
1918 ssl->session->cipher->algorithm_prf != hs->new_cipher->algorithm_prf) {
1919 return false;
1920 }
1921
1922 return true;
1923}
1924
David Benjamin83a49932021-05-20 15:57:09 -04001925static size_t ext_pre_shared_key_clienthello_length(
1926 const SSL_HANDSHAKE *hs, ssl_client_hello_type_t type) {
David Benjamin350fe3b2021-06-02 17:58:53 -04001927 const SSL *const ssl = hs->ssl;
David Benjamin83a49932021-05-20 15:57:09 -04001928 if (!should_offer_psk(hs, type)) {
Steven Valdeza833c352016-11-01 13:39:36 -04001929 return 0;
1930 }
1931
David Benjamin50596f82018-07-02 19:47:27 -04001932 size_t binder_len = EVP_MD_size(ssl_session_get_digest(ssl->session.get()));
David Benjaminbfdd1a92018-06-29 16:26:38 -04001933 return 15 + ssl->session->ticket.size() + binder_len;
Steven Valdeza833c352016-11-01 13:39:36 -04001934}
1935
David Benjamin5acf9f42021-05-24 14:23:38 -04001936static bool ext_pre_shared_key_add_clienthello(const SSL_HANDSHAKE *hs,
David Benjamin83a49932021-05-20 15:57:09 -04001937 CBB *out, bool *out_needs_binder,
1938 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04001939 const SSL *const ssl = hs->ssl;
David Benjamin5acf9f42021-05-24 14:23:38 -04001940 *out_needs_binder = false;
David Benjamin83a49932021-05-20 15:57:09 -04001941 if (!should_offer_psk(hs, type)) {
Steven Valdezcd8470f2017-10-11 12:29:36 -04001942 return true;
1943 }
1944
David Benjaminad8f5e12017-02-20 17:00:20 -05001945 struct OPENSSL_timeval now;
Steven Valdeza833c352016-11-01 13:39:36 -04001946 ssl_get_current_time(ssl, &now);
1947 uint32_t ticket_age = 1000 * (now.tv_sec - ssl->session->time);
1948 uint32_t obfuscated_ticket_age = ticket_age + ssl->session->ticket_age_add;
1949
David Benjaminc11ea9422017-08-29 16:33:21 -04001950 // Fill in a placeholder zero binder of the appropriate length. It will be
1951 // computed and filled in later after length prefixes are computed.
David Benjamin50596f82018-07-02 19:47:27 -04001952 size_t binder_len = EVP_MD_size(ssl_session_get_digest(ssl->session.get()));
Steven Valdeza833c352016-11-01 13:39:36 -04001953
1954 CBB contents, identity, ticket, binders, binder;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001955 if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) ||
1956 !CBB_add_u16_length_prefixed(out, &contents) ||
Steven Valdez5b986082016-09-01 12:29:49 -04001957 !CBB_add_u16_length_prefixed(&contents, &identity) ||
Steven Valdez5b986082016-09-01 12:29:49 -04001958 !CBB_add_u16_length_prefixed(&identity, &ticket) ||
David Benjaminbfdd1a92018-06-29 16:26:38 -04001959 !CBB_add_bytes(&ticket, ssl->session->ticket.data(),
1960 ssl->session->ticket.size()) ||
Steven Valdeza833c352016-11-01 13:39:36 -04001961 !CBB_add_u32(&identity, obfuscated_ticket_age) ||
1962 !CBB_add_u16_length_prefixed(&contents, &binders) ||
1963 !CBB_add_u8_length_prefixed(&binders, &binder) ||
David Benjamin95450622021-07-16 18:24:02 -04001964 !CBB_add_zeros(&binder, binder_len)) {
David Benjamin31640932017-10-11 13:22:39 -04001965 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001966 }
1967
David Benjamin5acf9f42021-05-24 14:23:38 -04001968 *out_needs_binder = true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001969 return CBB_flush(out);
1970}
1971
David Benjamin31640932017-10-11 13:22:39 -04001972bool ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE *hs,
1973 uint8_t *out_alert,
1974 CBS *contents) {
Steven Valdez4aa154e2016-07-29 14:32:55 -04001975 uint16_t psk_id;
1976 if (!CBS_get_u16(contents, &psk_id) ||
1977 CBS_len(contents) != 0) {
David Benjamin7f78df42016-10-05 22:33:19 -04001978 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
Steven Valdez4aa154e2016-07-29 14:32:55 -04001979 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04001980 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001981 }
1982
David Benjaminc11ea9422017-08-29 16:33:21 -04001983 // We only advertise one PSK identity, so the only legal index is zero.
Steven Valdez4aa154e2016-07-29 14:32:55 -04001984 if (psk_id != 0) {
David Benjamin7f78df42016-10-05 22:33:19 -04001985 OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
Steven Valdez4aa154e2016-07-29 14:32:55 -04001986 *out_alert = SSL_AD_UNKNOWN_PSK_IDENTITY;
David Benjamin31640932017-10-11 13:22:39 -04001987 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001988 }
1989
David Benjamin31640932017-10-11 13:22:39 -04001990 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04001991}
1992
David Benjamin31640932017-10-11 13:22:39 -04001993bool ssl_ext_pre_shared_key_parse_clienthello(
David Benjamin707af292017-03-10 17:47:18 -05001994 SSL_HANDSHAKE *hs, CBS *out_ticket, CBS *out_binders,
David Benjamin9806ae02019-08-16 15:32:03 -04001995 uint32_t *out_obfuscated_ticket_age, uint8_t *out_alert,
1996 const SSL_CLIENT_HELLO *client_hello, CBS *contents) {
1997 // Verify that the pre_shared_key extension is the last extension in
1998 // ClientHello.
1999 if (CBS_data(contents) + CBS_len(contents) !=
2000 client_hello->extensions + client_hello->extensions_len) {
2001 OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
2002 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
2003 return false;
2004 }
2005
David Benjaminc11ea9422017-08-29 16:33:21 -04002006 // We only process the first PSK identity since we don't support pure PSK.
David Benjamin707af292017-03-10 17:47:18 -05002007 CBS identities, binders;
David Benjaminaedf3032016-12-01 16:47:56 -05002008 if (!CBS_get_u16_length_prefixed(contents, &identities) ||
David Benjamin707af292017-03-10 17:47:18 -05002009 !CBS_get_u16_length_prefixed(&identities, out_ticket) ||
David Benjamin35ac5b72017-03-03 15:05:56 -05002010 !CBS_get_u32(&identities, out_obfuscated_ticket_age) ||
Steven Valdeza833c352016-11-01 13:39:36 -04002011 !CBS_get_u16_length_prefixed(contents, &binders) ||
David Benjaminaedf3032016-12-01 16:47:56 -05002012 CBS_len(&binders) == 0 ||
Steven Valdezaf3b8a92016-11-01 12:49:22 -04002013 CBS_len(contents) != 0) {
Steven Valdeza833c352016-11-01 13:39:36 -04002014 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
Steven Valdez4aa154e2016-07-29 14:32:55 -04002015 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002016 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002017 }
2018
Steven Valdeza833c352016-11-01 13:39:36 -04002019 *out_binders = binders;
2020
David Benjaminc11ea9422017-08-29 16:33:21 -04002021 // Check the syntax of the remaining identities, but do not process them.
David Benjaminaedf3032016-12-01 16:47:56 -05002022 size_t num_identities = 1;
2023 while (CBS_len(&identities) != 0) {
2024 CBS unused_ticket;
2025 uint32_t unused_obfuscated_ticket_age;
2026 if (!CBS_get_u16_length_prefixed(&identities, &unused_ticket) ||
2027 !CBS_get_u32(&identities, &unused_obfuscated_ticket_age)) {
2028 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2029 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002030 return false;
David Benjaminaedf3032016-12-01 16:47:56 -05002031 }
2032
2033 num_identities++;
2034 }
2035
David Benjaminc11ea9422017-08-29 16:33:21 -04002036 // Check the syntax of the binders. The value will be checked later if
2037 // resuming.
David Benjaminaedf3032016-12-01 16:47:56 -05002038 size_t num_binders = 0;
2039 while (CBS_len(&binders) != 0) {
2040 CBS binder;
2041 if (!CBS_get_u8_length_prefixed(&binders, &binder)) {
2042 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2043 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002044 return false;
David Benjaminaedf3032016-12-01 16:47:56 -05002045 }
2046
2047 num_binders++;
2048 }
2049
2050 if (num_identities != num_binders) {
2051 OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_BINDER_COUNT_MISMATCH);
2052 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04002053 return false;
Steven Valdez5b986082016-09-01 12:29:49 -04002054 }
2055
David Benjamin31640932017-10-11 13:22:39 -04002056 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002057}
2058
David Benjamin31640932017-10-11 13:22:39 -04002059bool ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8baf9632016-11-17 17:11:16 +09002060 if (!hs->ssl->s3->session_reused) {
David Benjamin31640932017-10-11 13:22:39 -04002061 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002062 }
2063
2064 CBB contents;
2065 if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) ||
2066 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjaminc11ea9422017-08-29 16:33:21 -04002067 // We only consider the first identity for resumption
Steven Valdez4aa154e2016-07-29 14:32:55 -04002068 !CBB_add_u16(&contents, 0) ||
2069 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002070 return false;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002071 }
2072
David Benjamin31640932017-10-11 13:22:39 -04002073 return true;
Steven Valdez4aa154e2016-07-29 14:32:55 -04002074}
2075
2076
David Benjaminc11ea9422017-08-29 16:33:21 -04002077// Pre-Shared Key Exchange Modes
2078//
David Benjamina130ce02018-08-14 22:26:39 -05002079// https://tools.ietf.org/html/rfc8446#section-4.2.9
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002080
David Benjamin83a49932021-05-20 15:57:09 -04002081static bool ext_psk_key_exchange_modes_add_clienthello(
2082 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2083 ssl_client_hello_type_t type) {
David Benjamin68161cb2017-06-20 14:49:43 -04002084 if (hs->max_version < TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002085 return true;
Steven Valdeza833c352016-11-01 13:39:36 -04002086 }
2087
2088 CBB contents, ke_modes;
David Benjamin83a49932021-05-20 15:57:09 -04002089 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_psk_key_exchange_modes) ||
2090 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Steven Valdeza833c352016-11-01 13:39:36 -04002091 !CBB_add_u8_length_prefixed(&contents, &ke_modes) ||
2092 !CBB_add_u8(&ke_modes, SSL_PSK_DHE_KE)) {
David Benjamin31640932017-10-11 13:22:39 -04002093 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04002094 }
2095
David Benjamin83a49932021-05-20 15:57:09 -04002096 return CBB_flush(out_compressible);
Steven Valdeza833c352016-11-01 13:39:36 -04002097}
2098
David Benjamin31640932017-10-11 13:22:39 -04002099static bool ext_psk_key_exchange_modes_parse_clienthello(SSL_HANDSHAKE *hs,
2100 uint8_t *out_alert,
2101 CBS *contents) {
David Benjamin4eb95cc2016-11-16 17:08:23 +09002102 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04002103 return true;
David Benjamin4eb95cc2016-11-16 17:08:23 +09002104 }
2105
Steven Valdeza833c352016-11-01 13:39:36 -04002106 CBS ke_modes;
2107 if (!CBS_get_u8_length_prefixed(contents, &ke_modes) ||
2108 CBS_len(&ke_modes) == 0 ||
2109 CBS_len(contents) != 0) {
2110 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002111 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04002112 }
2113
David Benjaminc11ea9422017-08-29 16:33:21 -04002114 // We only support tickets with PSK_DHE_KE.
David Benjamin17cf2cb2016-12-13 01:07:13 -05002115 hs->accept_psk_mode = OPENSSL_memchr(CBS_data(&ke_modes), SSL_PSK_DHE_KE,
2116 CBS_len(&ke_modes)) != NULL;
Steven Valdeza833c352016-11-01 13:39:36 -04002117
David Benjamin31640932017-10-11 13:22:39 -04002118 return true;
Steven Valdeza833c352016-11-01 13:39:36 -04002119}
2120
2121
David Benjaminc11ea9422017-08-29 16:33:21 -04002122// Early Data Indication
2123//
David Benjamina130ce02018-08-14 22:26:39 -05002124// https://tools.ietf.org/html/rfc8446#section-4.2.10
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002125
David Benjamin83a49932021-05-20 15:57:09 -04002126static bool ext_early_data_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2127 CBB *out_compressible,
2128 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002129 const SSL *const ssl = hs->ssl;
David Benjamin64770122019-05-04 11:00:04 -05002130 // The second ClientHello never offers early data, and we must have already
2131 // filled in |early_data_reason| by this point.
Kris Kwiatkowskib11902a2019-08-24 11:01:04 +01002132 if (ssl->s3->used_hello_retry_request) {
David Benjamin64770122019-05-04 11:00:04 -05002133 assert(ssl->s3->early_data_reason != ssl_early_data_unknown);
David Benjamin31640932017-10-11 13:22:39 -04002134 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002135 }
2136
David Benjamin4e93cd42021-05-18 13:38:25 -04002137 if (!hs->early_data_offered) {
David Benjamin64770122019-05-04 11:00:04 -05002138 return true;
2139 }
2140
David Benjamin83a49932021-05-20 15:57:09 -04002141 // If offering ECH, the extension only applies to ClientHelloInner, but we
2142 // send the extension in both ClientHellos. This ensures that, if the server
2143 // handshakes with ClientHelloOuter, it can skip past early data. See
David Benjamin0fa30302021-09-03 17:23:28 -04002144 // draft-ietf-tls-esni-13, section 6.1.
David Benjamin83a49932021-05-20 15:57:09 -04002145 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_early_data) ||
2146 !CBB_add_u16(out_compressible, 0) ||
2147 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04002148 return false;
Steven Valdez2d850622017-01-11 11:34:52 -05002149 }
2150
David Benjamin31640932017-10-11 13:22:39 -04002151 return true;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002152}
2153
David Benjamin31640932017-10-11 13:22:39 -04002154static bool ext_early_data_parse_serverhello(SSL_HANDSHAKE *hs,
David Benjamin64770122019-05-04 11:00:04 -05002155 uint8_t *out_alert,
2156 CBS *contents) {
David Benjamin8c880a22016-12-03 02:20:34 -05002157 SSL *const ssl = hs->ssl;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002158 if (contents == NULL) {
Kris Kwiatkowskib11902a2019-08-24 11:01:04 +01002159 if (hs->early_data_offered && !ssl->s3->used_hello_retry_request) {
David Benjamin64770122019-05-04 11:00:04 -05002160 ssl->s3->early_data_reason = ssl->s3->session_reused
2161 ? ssl_early_data_peer_declined
2162 : ssl_early_data_session_not_resumed;
2163 } else {
2164 // We already filled in |early_data_reason| when declining to offer 0-RTT
2165 // or handling the implicit HelloRetryRequest reject.
2166 assert(ssl->s3->early_data_reason != ssl_early_data_unknown);
2167 }
David Benjamin31640932017-10-11 13:22:39 -04002168 return true;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002169 }
2170
David Benjamin64770122019-05-04 11:00:04 -05002171 // If we received an HRR, the second ClientHello never offers early data, so
2172 // the extensions logic will automatically reject early data extensions as
2173 // unsolicited. This covered by the ServerAcceptsEarlyDataOnHRR test.
Kris Kwiatkowskib11902a2019-08-24 11:01:04 +01002174 assert(!ssl->s3->used_hello_retry_request);
David Benjamin64770122019-05-04 11:00:04 -05002175
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002176 if (CBS_len(contents) != 0) {
2177 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002178 return false;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002179 }
2180
Steven Valdez2d850622017-01-11 11:34:52 -05002181 if (!ssl->s3->session_reused) {
2182 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2183 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
David Benjamin31640932017-10-11 13:22:39 -04002184 return false;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002185 }
Steven Valdez2d850622017-01-11 11:34:52 -05002186
David Benjamin64770122019-05-04 11:00:04 -05002187 ssl->s3->early_data_reason = ssl_early_data_accepted;
David Benjamin02e62562017-12-18 18:04:01 -05002188 ssl->s3->early_data_accepted = true;
David Benjamin31640932017-10-11 13:22:39 -04002189 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002190}
2191
David Benjamin31640932017-10-11 13:22:39 -04002192static bool ext_early_data_parse_clienthello(SSL_HANDSHAKE *hs,
2193 uint8_t *out_alert, CBS *contents) {
Steven Valdez2d850622017-01-11 11:34:52 -05002194 SSL *const ssl = hs->ssl;
2195 if (contents == NULL ||
David Benjamind1e3ce12017-10-06 18:31:15 -04002196 ssl_protocol_version(ssl) < TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002197 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002198 }
2199
2200 if (CBS_len(contents) != 0) {
2201 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002202 return false;
Steven Valdez2d850622017-01-11 11:34:52 -05002203 }
2204
David Benjaminfd45ee72017-08-31 14:49:09 -04002205 hs->early_data_offered = true;
David Benjamin31640932017-10-11 13:22:39 -04002206 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002207}
2208
David Benjamin31640932017-10-11 13:22:39 -04002209static bool ext_early_data_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin02e62562017-12-18 18:04:01 -05002210 if (!hs->ssl->s3->early_data_accepted) {
David Benjamin31640932017-10-11 13:22:39 -04002211 return true;
Steven Valdez2d850622017-01-11 11:34:52 -05002212 }
2213
2214 if (!CBB_add_u16(out, TLSEXT_TYPE_early_data) ||
2215 !CBB_add_u16(out, 0) ||
2216 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002217 return false;
Steven Valdez2d850622017-01-11 11:34:52 -05002218 }
2219
David Benjamin31640932017-10-11 13:22:39 -04002220 return true;
Steven Valdeza4ee74d2016-11-29 13:36:45 -05002221}
2222
2223
David Benjaminc11ea9422017-08-29 16:33:21 -04002224// Key Share
2225//
David Benjamina130ce02018-08-14 22:26:39 -05002226// https://tools.ietf.org/html/rfc8446#section-4.2.8
Steven Valdez143e8b32016-07-11 13:19:03 -04002227
David Benjamin97ede402021-05-18 14:17:52 -04002228bool ssl_setup_key_shares(SSL_HANDSHAKE *hs, uint16_t override_group_id) {
David Benjamin8c880a22016-12-03 02:20:34 -05002229 SSL *const ssl = hs->ssl;
David Benjamin97ede402021-05-18 14:17:52 -04002230 hs->key_shares[0].reset();
2231 hs->key_shares[1].reset();
2232 hs->key_share_bytes.Reset();
2233
David Benjamin68161cb2017-06-20 14:49:43 -04002234 if (hs->max_version < TLS1_3_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002235 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002236 }
2237
David Benjamin97ede402021-05-18 14:17:52 -04002238 bssl::ScopedCBB cbb;
2239 if (!CBB_init(cbb.get(), 64)) {
David Benjamin31640932017-10-11 13:22:39 -04002240 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002241 }
2242
David Benjamin97ede402021-05-18 14:17:52 -04002243 if (override_group_id == 0 && ssl->ctx->grease_enabled) {
David Benjamin3675eb32021-05-18 14:01:07 -04002244 // Add a fake group. See RFC 8701.
David Benjamin97ede402021-05-18 14:17:52 -04002245 if (!CBB_add_u16(cbb.get(), ssl_get_grease_value(hs, ssl_grease_group)) ||
2246 !CBB_add_u16(cbb.get(), 1 /* length */) ||
2247 !CBB_add_u8(cbb.get(), 0 /* one byte key share */)) {
David Benjamin31640932017-10-11 13:22:39 -04002248 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04002249 }
David Benjamin97ede402021-05-18 14:17:52 -04002250 }
David Benjamin65ac9972016-09-02 21:35:25 -04002251
David Benjamin97ede402021-05-18 14:17:52 -04002252 uint16_t group_id = override_group_id;
2253 uint16_t second_group_id = 0;
2254 if (override_group_id == 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -04002255 // Predict the most preferred group.
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07002256 Span<const uint16_t> groups = tls1_get_grouplist(hs);
David Benjaminb9493552017-09-27 19:02:51 -04002257 if (groups.empty()) {
David Benjaminc8b6b4f2016-09-08 23:47:48 -04002258 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_GROUPS_SPECIFIED);
David Benjamin31640932017-10-11 13:22:39 -04002259 return false;
Steven Valdez5440fe02016-07-18 12:40:30 -04002260 }
David Benjaminc8b6b4f2016-09-08 23:47:48 -04002261
2262 group_id = groups[0];
Adam Langley7b935932018-11-12 13:53:42 -08002263
Adam Langley1e97ce32023-01-23 21:11:44 +00002264 // We'll try to include one post-quantum and one classical initial key
2265 // share.
2266 for (size_t i = 1; i < groups.size() && second_group_id == 0; i++) {
2267 if (is_post_quantum_group(group_id) != is_post_quantum_group(groups[i])) {
2268 second_group_id = groups[i];
2269 assert(second_group_id != group_id);
2270 }
Adam Langley7b935932018-11-12 13:53:42 -08002271 }
Steven Valdez5440fe02016-07-18 12:40:30 -04002272 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002273
David Benjaminc8b6b4f2016-09-08 23:47:48 -04002274 CBB key_exchange;
Adam Langley7b935932018-11-12 13:53:42 -08002275 hs->key_shares[0] = SSLKeyShare::Create(group_id);
David Benjamin97ede402021-05-18 14:17:52 -04002276 if (!hs->key_shares[0] || //
2277 !CBB_add_u16(cbb.get(), group_id) ||
2278 !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002279 !hs->key_shares[0]->Generate(&key_exchange)) {
David Benjamin31640932017-10-11 13:22:39 -04002280 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002281 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002282
Adam Langley7b935932018-11-12 13:53:42 -08002283 if (second_group_id != 0) {
2284 hs->key_shares[1] = SSLKeyShare::Create(second_group_id);
David Benjamin97ede402021-05-18 14:17:52 -04002285 if (!hs->key_shares[1] || //
2286 !CBB_add_u16(cbb.get(), second_group_id) ||
2287 !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002288 !hs->key_shares[1]->Generate(&key_exchange)) {
Adam Langley7b935932018-11-12 13:53:42 -08002289 return false;
2290 }
2291 }
2292
David Benjamin97ede402021-05-18 14:17:52 -04002293 return CBBFinishArray(cbb.get(), &hs->key_share_bytes);
2294}
2295
David Benjamin83a49932021-05-20 15:57:09 -04002296static bool ext_key_share_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2297 CBB *out_compressible,
2298 ssl_client_hello_type_t type) {
David Benjamin97ede402021-05-18 14:17:52 -04002299 if (hs->max_version < TLS1_3_VERSION) {
2300 return true;
2301 }
2302
2303 assert(!hs->key_share_bytes.empty());
2304 CBB contents, kse_bytes;
David Benjamin83a49932021-05-20 15:57:09 -04002305 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_key_share) ||
2306 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
David Benjamin97ede402021-05-18 14:17:52 -04002307 !CBB_add_u16_length_prefixed(&contents, &kse_bytes) ||
2308 !CBB_add_bytes(&kse_bytes, hs->key_share_bytes.data(),
2309 hs->key_share_bytes.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -04002310 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04002311 return false;
Steven Valdez5440fe02016-07-18 12:40:30 -04002312 }
2313
David Benjamin97ede402021-05-18 14:17:52 -04002314 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002315}
2316
David Benjamin31640932017-10-11 13:22:39 -04002317bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
2318 Array<uint8_t> *out_secret,
2319 uint8_t *out_alert, CBS *contents) {
David Benjamin08b1f382023-02-28 17:22:23 -05002320 CBS ciphertext;
David Benjamin5c4e8572016-08-19 17:44:53 -04002321 uint16_t group_id;
2322 if (!CBS_get_u16(contents, &group_id) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002323 !CBS_get_u16_length_prefixed(contents, &ciphertext) ||
David Benjamina70de142016-08-02 16:52:57 -04002324 CBS_len(contents) != 0) {
David Benjaminac4d5342017-11-17 01:42:04 +08002325 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
Steven Valdez143e8b32016-07-11 13:19:03 -04002326 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002327 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002328 }
2329
Adam Langley7b935932018-11-12 13:53:42 -08002330 SSLKeyShare *key_share = hs->key_shares[0].get();
2331 if (key_share->GroupID() != group_id) {
2332 if (!hs->key_shares[1] || hs->key_shares[1]->GroupID() != group_id) {
2333 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
2334 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
2335 return false;
2336 }
2337 key_share = hs->key_shares[1].get();
Steven Valdez143e8b32016-07-11 13:19:03 -04002338 }
2339
David Benjamin08b1f382023-02-28 17:22:23 -05002340 if (!key_share->Decap(out_secret, out_alert, ciphertext)) {
Steven Valdez143e8b32016-07-11 13:19:03 -04002341 *out_alert = SSL_AD_INTERNAL_ERROR;
David Benjamin31640932017-10-11 13:22:39 -04002342 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002343 }
2344
David Benjamin45738dd2017-02-09 20:01:26 -05002345 hs->new_session->group_id = group_id;
Adam Langley7b935932018-11-12 13:53:42 -08002346 hs->key_shares[0].reset();
2347 hs->key_shares[1].reset();
David Benjamin31640932017-10-11 13:22:39 -04002348 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002349}
2350
David Benjamin31640932017-10-11 13:22:39 -04002351bool ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found,
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002352 Span<const uint8_t> *out_peer_key,
2353 uint8_t *out_alert,
2354 const SSL_CLIENT_HELLO *client_hello) {
2355 // We only support connections that include an ECDHE key exchange.
2356 CBS contents;
2357 if (!ssl_client_hello_get_extension(client_hello, &contents,
2358 TLSEXT_TYPE_key_share)) {
2359 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
2360 *out_alert = SSL_AD_MISSING_EXTENSION;
David Benjamin31640932017-10-11 13:22:39 -04002361 return false;
Steven Valdez803c77a2016-09-06 14:13:43 -04002362 }
2363
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002364 CBS key_shares;
2365 if (!CBS_get_u16_length_prefixed(&contents, &key_shares) ||
2366 CBS_len(&contents) != 0) {
David Benjamin7e1f9842016-09-20 19:24:40 -04002367 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
David Benjamin31640932017-10-11 13:22:39 -04002368 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002369 }
2370
David Benjaminc11ea9422017-08-29 16:33:21 -04002371 // Find the corresponding key share.
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002372 const uint16_t group_id = hs->new_session->group_id;
David Benjamin7e1f9842016-09-20 19:24:40 -04002373 CBS peer_key;
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002374 CBS_init(&peer_key, nullptr, 0);
Steven Valdez143e8b32016-07-11 13:19:03 -04002375 while (CBS_len(&key_shares) > 0) {
2376 uint16_t id;
David Benjamin7e1f9842016-09-20 19:24:40 -04002377 CBS peer_key_tmp;
Steven Valdez143e8b32016-07-11 13:19:03 -04002378 if (!CBS_get_u16(&key_shares, &id) ||
Steven Valdez619c8ce2017-10-16 13:12:33 -04002379 !CBS_get_u16_length_prefixed(&key_shares, &peer_key_tmp) ||
2380 CBS_len(&peer_key_tmp) == 0) {
David Benjamin7e1f9842016-09-20 19:24:40 -04002381 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
David Benjamin31640932017-10-11 13:22:39 -04002382 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002383 }
2384
David Benjamin7e1f9842016-09-20 19:24:40 -04002385 if (id == group_id) {
Steven Valdez619c8ce2017-10-16 13:12:33 -04002386 if (CBS_len(&peer_key) != 0) {
David Benjamin7e1f9842016-09-20 19:24:40 -04002387 OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_KEY_SHARE);
2388 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
David Benjamin31640932017-10-11 13:22:39 -04002389 return false;
David Benjamin7e1f9842016-09-20 19:24:40 -04002390 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002391
David Benjamin7e1f9842016-09-20 19:24:40 -04002392 peer_key = peer_key_tmp;
David Benjaminc11ea9422017-08-29 16:33:21 -04002393 // Continue parsing the structure to keep peers honest.
Steven Valdez143e8b32016-07-11 13:19:03 -04002394 }
Steven Valdez143e8b32016-07-11 13:19:03 -04002395 }
2396
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002397 if (out_peer_key != nullptr) {
2398 *out_peer_key = peer_key;
David Benjamin7e1f9842016-09-20 19:24:40 -04002399 }
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002400 *out_found = CBS_len(&peer_key) != 0;
David Benjamin31640932017-10-11 13:22:39 -04002401 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002402}
2403
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002404bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin08b1f382023-02-28 17:22:23 -05002405 CBB entry, ciphertext;
David Benjamin3b8c5ec2021-04-12 17:43:23 -04002406 if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
David Benjamin08b1f382023-02-28 17:22:23 -05002407 !CBB_add_u16_length_prefixed(out, &entry) ||
2408 !CBB_add_u16(&entry, hs->new_session->group_id) ||
2409 !CBB_add_u16_length_prefixed(&entry, &ciphertext) ||
2410 !CBB_add_bytes(&ciphertext, hs->key_share_ciphertext.data(),
2411 hs->key_share_ciphertext.size()) ||
Steven Valdez143e8b32016-07-11 13:19:03 -04002412 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002413 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04002414 }
David Benjamin31640932017-10-11 13:22:39 -04002415 return true;
Steven Valdez143e8b32016-07-11 13:19:03 -04002416}
2417
2418
David Benjaminc11ea9422017-08-29 16:33:21 -04002419// Supported Versions
2420//
David Benjamina130ce02018-08-14 22:26:39 -05002421// https://tools.ietf.org/html/rfc8446#section-4.2.1
Steven Valdezfdd10992016-09-15 16:27:05 -04002422
David Benjamin83a49932021-05-20 15:57:09 -04002423static bool ext_supported_versions_add_clienthello(
2424 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2425 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002426 const SSL *const ssl = hs->ssl;
David Benjamin68161cb2017-06-20 14:49:43 -04002427 if (hs->max_version <= TLS1_2_VERSION) {
David Benjamin31640932017-10-11 13:22:39 -04002428 return true;
Steven Valdezfdd10992016-09-15 16:27:05 -04002429 }
2430
David Benjamin83a49932021-05-20 15:57:09 -04002431 // supported_versions is compressible in ECH if ClientHelloOuter already
2432 // requires TLS 1.3. Otherwise the extensions differ in the older versions.
2433 if (hs->min_version >= TLS1_3_VERSION) {
2434 out = out_compressible;
2435 }
2436
Steven Valdezfdd10992016-09-15 16:27:05 -04002437 CBB contents, versions;
2438 if (!CBB_add_u16(out, TLSEXT_TYPE_supported_versions) ||
2439 !CBB_add_u16_length_prefixed(out, &contents) ||
2440 !CBB_add_u8_length_prefixed(&contents, &versions)) {
David Benjamin31640932017-10-11 13:22:39 -04002441 return false;
Steven Valdezfdd10992016-09-15 16:27:05 -04002442 }
2443
David Benjamin3675eb32021-05-18 14:01:07 -04002444 // Add a fake version. See RFC 8701.
David Benjamind9791bf2016-09-27 16:39:52 -04002445 if (ssl->ctx->grease_enabled &&
David Benjamina7bc9442018-01-18 10:08:53 -05002446 !CBB_add_u16(&versions, ssl_get_grease_value(hs, ssl_grease_version))) {
David Benjamin31640932017-10-11 13:22:39 -04002447 return false;
David Benjamind9791bf2016-09-27 16:39:52 -04002448 }
2449
David Benjamin83a49932021-05-20 15:57:09 -04002450 // Encrypted ClientHellos requires TLS 1.3 or later.
2451 uint16_t extra_min_version =
2452 type == ssl_client_hello_inner ? TLS1_3_VERSION : 0;
2453 if (!ssl_add_supported_versions(hs, &versions, extra_min_version) ||
Steven Valdez8f36c512017-06-20 10:55:02 -04002454 !CBB_flush(out)) {
David Benjamin31640932017-10-11 13:22:39 -04002455 return false;
Steven Valdezfdd10992016-09-15 16:27:05 -04002456 }
2457
David Benjamin31640932017-10-11 13:22:39 -04002458 return true;
Steven Valdezfdd10992016-09-15 16:27:05 -04002459}
2460
2461
David Benjaminc11ea9422017-08-29 16:33:21 -04002462// Cookie
2463//
David Benjamina130ce02018-08-14 22:26:39 -05002464// https://tools.ietf.org/html/rfc8446#section-4.2.2
David Benjamin3baa6e12016-10-07 21:10:38 -04002465
David Benjamin83a49932021-05-20 15:57:09 -04002466static bool ext_cookie_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2467 CBB *out_compressible,
2468 ssl_client_hello_type_t type) {
David Benjaminb9493552017-09-27 19:02:51 -04002469 if (hs->cookie.empty()) {
David Benjamin31640932017-10-11 13:22:39 -04002470 return true;
David Benjamin3baa6e12016-10-07 21:10:38 -04002471 }
2472
2473 CBB contents, cookie;
David Benjamin83a49932021-05-20 15:57:09 -04002474 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_cookie) ||
2475 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
David Benjamin3baa6e12016-10-07 21:10:38 -04002476 !CBB_add_u16_length_prefixed(&contents, &cookie) ||
David Benjamin08f5c762017-09-21 02:43:05 -04002477 !CBB_add_bytes(&cookie, hs->cookie.data(), hs->cookie.size()) ||
David Benjamin83a49932021-05-20 15:57:09 -04002478 !CBB_flush(out_compressible)) {
David Benjamin31640932017-10-11 13:22:39 -04002479 return false;
David Benjamin3baa6e12016-10-07 21:10:38 -04002480 }
2481
David Benjamin31640932017-10-11 13:22:39 -04002482 return true;
David Benjamin3baa6e12016-10-07 21:10:38 -04002483}
2484
2485
David Benjamina130ce02018-08-14 22:26:39 -05002486// Supported Groups
David Benjaminc11ea9422017-08-29 16:33:21 -04002487//
David Benjamina130ce02018-08-14 22:26:39 -05002488// https://tools.ietf.org/html/rfc4492#section-5.1.1
2489// https://tools.ietf.org/html/rfc8446#section-4.2.7
Adam Langley273d49c2015-07-20 16:38:52 -07002490
David Benjamin14e51ad2021-05-19 15:24:34 -04002491static bool ext_supported_groups_add_clienthello(const SSL_HANDSHAKE *hs,
David Benjamin83a49932021-05-20 15:57:09 -04002492 CBB *out,
2493 CBB *out_compressible,
2494 ssl_client_hello_type_t type) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002495 const SSL *const ssl = hs->ssl;
Steven Valdezce902a92016-05-17 11:47:53 -04002496 CBB contents, groups_bytes;
David Benjamin83a49932021-05-20 15:57:09 -04002497 if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_supported_groups) ||
2498 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Steven Valdezce902a92016-05-17 11:47:53 -04002499 !CBB_add_u16_length_prefixed(&contents, &groups_bytes)) {
David Benjamin31640932017-10-11 13:22:39 -04002500 return false;
Adam Langley273d49c2015-07-20 16:38:52 -07002501 }
2502
David Benjamin3675eb32021-05-18 14:01:07 -04002503 // Add a fake group. See RFC 8701.
David Benjamin65ac9972016-09-02 21:35:25 -04002504 if (ssl->ctx->grease_enabled &&
2505 !CBB_add_u16(&groups_bytes,
David Benjamina7bc9442018-01-18 10:08:53 -05002506 ssl_get_grease_value(hs, ssl_grease_group))) {
David Benjamin31640932017-10-11 13:22:39 -04002507 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04002508 }
2509
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07002510 for (uint16_t group : tls1_get_grouplist(hs)) {
Kris Kwiatkowski78c88c92019-03-11 14:40:59 +00002511 if (is_post_quantum_group(group) &&
Adam Langley7b935932018-11-12 13:53:42 -08002512 hs->max_version < TLS1_3_VERSION) {
2513 continue;
2514 }
David Benjamincf0ce672017-09-21 02:25:59 -04002515 if (!CBB_add_u16(&groups_bytes, group)) {
David Benjamin31640932017-10-11 13:22:39 -04002516 return false;
Adam Langley273d49c2015-07-20 16:38:52 -07002517 }
2518 }
2519
David Benjamin83a49932021-05-20 15:57:09 -04002520 return CBB_flush(out_compressible);
Adam Langley273d49c2015-07-20 16:38:52 -07002521}
2522
David Benjamin31640932017-10-11 13:22:39 -04002523static bool ext_supported_groups_parse_serverhello(SSL_HANDSHAKE *hs,
2524 uint8_t *out_alert,
2525 CBS *contents) {
David Benjaminc11ea9422017-08-29 16:33:21 -04002526 // This extension is not expected to be echoed by servers in TLS 1.2, but some
2527 // BigIP servers send it nonetheless, so do not enforce this.
David Benjamin31640932017-10-11 13:22:39 -04002528 return true;
Adam Langley273d49c2015-07-20 16:38:52 -07002529}
2530
David Benjaminb1cf48e2017-09-21 11:37:46 -04002531static bool parse_u16_array(const CBS *cbs, Array<uint16_t> *out) {
2532 CBS copy = *cbs;
2533 if ((CBS_len(&copy) & 1) != 0) {
2534 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
2535 return false;
2536 }
2537
2538 Array<uint16_t> ret;
2539 if (!ret.Init(CBS_len(&copy) / 2)) {
2540 return false;
2541 }
2542 for (size_t i = 0; i < ret.size(); i++) {
2543 if (!CBS_get_u16(&copy, &ret[i])) {
2544 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
2545 return false;
2546 }
2547 }
2548
2549 assert(CBS_len(&copy) == 0);
2550 *out = std::move(ret);
Anton Bikineev50e7ea52022-01-23 22:35:48 +01002551 return true;
David Benjaminb1cf48e2017-09-21 11:37:46 -04002552}
2553
David Benjamin31640932017-10-11 13:22:39 -04002554static bool ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs,
David Benjamin8c880a22016-12-03 02:20:34 -05002555 uint8_t *out_alert,
David Benjamin31640932017-10-11 13:22:39 -04002556 CBS *contents) {
Adam Langley273d49c2015-07-20 16:38:52 -07002557 if (contents == NULL) {
David Benjamin31640932017-10-11 13:22:39 -04002558 return true;
Adam Langley273d49c2015-07-20 16:38:52 -07002559 }
2560
Steven Valdezce902a92016-05-17 11:47:53 -04002561 CBS supported_group_list;
2562 if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) ||
2563 CBS_len(&supported_group_list) == 0 ||
David Benjaminb1cf48e2017-09-21 11:37:46 -04002564 CBS_len(contents) != 0 ||
2565 !parse_u16_array(&supported_group_list, &hs->peer_supported_group_list)) {
David Benjamin31640932017-10-11 13:22:39 -04002566 return false;
Adam Langley273d49c2015-07-20 16:38:52 -07002567 }
2568
David Benjamin31640932017-10-11 13:22:39 -04002569 return true;
Adam Langley273d49c2015-07-20 16:38:52 -07002570}
2571
2572
Nick Harper3c034b22017-12-22 15:50:43 -08002573// QUIC Transport Parameters
2574
David Schinazi3d8b8c32021-01-14 11:25:49 -08002575static bool ext_quic_transport_params_add_clienthello_impl(
David Benjamin14e51ad2021-05-19 15:24:34 -04002576 const SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) {
Nick Harper72cff812020-03-26 18:06:16 -07002577 if (hs->config->quic_transport_params.empty() && !hs->ssl->quic_method) {
Nick Harper3c034b22017-12-22 15:50:43 -08002578 return true;
2579 }
Nick Harper72cff812020-03-26 18:06:16 -07002580 if (hs->config->quic_transport_params.empty() || !hs->ssl->quic_method) {
2581 // QUIC Transport Parameters must be sent over QUIC, and they must not be
2582 // sent over non-QUIC transports. If transport params are set, then
2583 // SSL(_CTX)_set_quic_method must also be called.
2584 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2585 return false;
2586 }
2587 assert(hs->min_version > TLS1_2_VERSION);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002588 if (use_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2589 // Do nothing, we'll send the other codepoint.
2590 return true;
2591 }
2592
David Benjamina1d3bfb2021-06-01 12:12:44 -04002593 uint16_t extension_type = TLSEXT_TYPE_quic_transport_parameters;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002594 if (hs->config->quic_use_legacy_codepoint) {
2595 extension_type = TLSEXT_TYPE_quic_transport_parameters_legacy;
2596 }
Nick Harper3c034b22017-12-22 15:50:43 -08002597
2598 CBB contents;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002599 if (!CBB_add_u16(out, extension_type) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002600 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjamin0ce090a2018-07-02 20:24:40 -04002601 !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(),
2602 hs->config->quic_transport_params.size()) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002603 !CBB_flush(out)) {
2604 return false;
2605 }
2606 return true;
2607}
2608
David Benjamin83a49932021-05-20 15:57:09 -04002609static bool ext_quic_transport_params_add_clienthello(
2610 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2611 ssl_client_hello_type_t type) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002612 return ext_quic_transport_params_add_clienthello_impl(
David Benjamin83a49932021-05-20 15:57:09 -04002613 hs, out_compressible, /*use_legacy_codepoint=*/false);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002614}
2615
David Benjamin14e51ad2021-05-19 15:24:34 -04002616static bool ext_quic_transport_params_add_clienthello_legacy(
David Benjamin83a49932021-05-20 15:57:09 -04002617 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2618 ssl_client_hello_type_t type) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002619 return ext_quic_transport_params_add_clienthello_impl(
David Benjamin83a49932021-05-20 15:57:09 -04002620 hs, out_compressible, /*use_legacy_codepoint=*/true);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002621}
2622
2623static bool ext_quic_transport_params_parse_serverhello_impl(
2624 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents,
2625 bool used_legacy_codepoint) {
Adam Langleyca058c02020-12-16 10:11:08 -08002626 SSL *const ssl = hs->ssl;
2627 if (contents == nullptr) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002628 if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2629 // Silently ignore because we expect the other QUIC codepoint.
2630 return true;
2631 }
Adam Langleyca058c02020-12-16 10:11:08 -08002632 if (!ssl->quic_method) {
2633 return true;
2634 }
Adam Langleyca058c02020-12-16 10:11:08 -08002635 *out_alert = SSL_AD_MISSING_EXTENSION;
2636 return false;
David Schinazi7ba96a62020-12-14 14:46:56 -08002637 }
David Schinazi3d8b8c32021-01-14 11:25:49 -08002638 // The extensions parser will check for unsolicited extensions before
2639 // calling the callback.
2640 assert(ssl->quic_method != nullptr);
Adam Langleyca058c02020-12-16 10:11:08 -08002641 assert(ssl_protocol_version(ssl) == TLS1_3_VERSION);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002642 assert(used_legacy_codepoint == hs->config->quic_use_legacy_codepoint);
Adam Langleyca058c02020-12-16 10:11:08 -08002643 return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
2644}
2645
David Schinazi3d8b8c32021-01-14 11:25:49 -08002646static bool ext_quic_transport_params_parse_serverhello(SSL_HANDSHAKE *hs,
Adam Langleyca058c02020-12-16 10:11:08 -08002647 uint8_t *out_alert,
2648 CBS *contents) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002649 return ext_quic_transport_params_parse_serverhello_impl(
2650 hs, out_alert, contents, /*used_legacy_codepoint=*/false);
2651}
2652
2653static bool ext_quic_transport_params_parse_serverhello_legacy(
2654 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) {
2655 return ext_quic_transport_params_parse_serverhello_impl(
2656 hs, out_alert, contents, /*used_legacy_codepoint=*/true);
2657}
2658
2659static bool ext_quic_transport_params_parse_clienthello_impl(
2660 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents,
2661 bool used_legacy_codepoint) {
Nick Harper3c034b22017-12-22 15:50:43 -08002662 SSL *const ssl = hs->ssl;
Nick Harper72cff812020-03-26 18:06:16 -07002663 if (!contents) {
2664 if (!ssl->quic_method) {
2665 if (hs->config->quic_transport_params.empty()) {
2666 return true;
2667 }
2668 // QUIC transport parameters must not be set if |ssl| is not configured
2669 // for QUIC.
2670 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2671 *out_alert = SSL_AD_INTERNAL_ERROR;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002672 return false;
2673 }
2674 if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2675 // Silently ignore because we expect the other QUIC codepoint.
2676 return true;
Nick Harper72cff812020-03-26 18:06:16 -07002677 }
2678 *out_alert = SSL_AD_MISSING_EXTENSION;
2679 return false;
2680 }
2681 if (!ssl->quic_method) {
David Schinazi3d8b8c32021-01-14 11:25:49 -08002682 if (used_legacy_codepoint) {
2683 // Ignore the legacy private-use codepoint because that could be sent
2684 // to mean something else than QUIC transport parameters.
2685 return true;
2686 }
2687 // Fail if we received the codepoint registered with IANA for QUIC
2688 // because that is not allowed outside of QUIC.
Nick Harper72cff812020-03-26 18:06:16 -07002689 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2690 return false;
Nick Harper3c034b22017-12-22 15:50:43 -08002691 }
Nick Harper80ddfc72020-03-11 18:26:31 -07002692 assert(ssl_protocol_version(ssl) == TLS1_3_VERSION);
David Schinazi3d8b8c32021-01-14 11:25:49 -08002693 if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2694 // Silently ignore because we expect the other QUIC codepoint.
2695 return true;
2696 }
Nick Harper3c034b22017-12-22 15:50:43 -08002697 return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
2698}
2699
David Schinazi3d8b8c32021-01-14 11:25:49 -08002700static bool ext_quic_transport_params_parse_clienthello(SSL_HANDSHAKE *hs,
2701 uint8_t *out_alert,
2702 CBS *contents) {
2703 return ext_quic_transport_params_parse_clienthello_impl(
2704 hs, out_alert, contents, /*used_legacy_codepoint=*/false);
2705}
2706
2707static bool ext_quic_transport_params_parse_clienthello_legacy(
2708 SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) {
2709 return ext_quic_transport_params_parse_clienthello_impl(
2710 hs, out_alert, contents, /*used_legacy_codepoint=*/true);
2711}
2712
2713static bool ext_quic_transport_params_add_serverhello_impl(
2714 SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) {
2715 if (hs->ssl->quic_method == nullptr && use_legacy_codepoint) {
2716 // Ignore the legacy private-use codepoint because that could be sent
2717 // to mean something else than QUIC transport parameters.
2718 return true;
2719 }
Nick Harper72cff812020-03-26 18:06:16 -07002720 assert(hs->ssl->quic_method != nullptr);
David Benjamin0ce090a2018-07-02 20:24:40 -04002721 if (hs->config->quic_transport_params.empty()) {
Nick Harper72cff812020-03-26 18:06:16 -07002722 // Transport parameters must be set when using QUIC.
2723 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
2724 return false;
Nick Harper3c034b22017-12-22 15:50:43 -08002725 }
David Schinazi3d8b8c32021-01-14 11:25:49 -08002726 if (use_legacy_codepoint != hs->config->quic_use_legacy_codepoint) {
2727 // Do nothing, we'll send the other codepoint.
2728 return true;
2729 }
2730
David Benjamina1d3bfb2021-06-01 12:12:44 -04002731 uint16_t extension_type = TLSEXT_TYPE_quic_transport_parameters;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002732 if (hs->config->quic_use_legacy_codepoint) {
2733 extension_type = TLSEXT_TYPE_quic_transport_parameters_legacy;
2734 }
Nick Harper3c034b22017-12-22 15:50:43 -08002735
2736 CBB contents;
David Schinazi3d8b8c32021-01-14 11:25:49 -08002737 if (!CBB_add_u16(out, extension_type) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002738 !CBB_add_u16_length_prefixed(out, &contents) ||
David Benjamin0ce090a2018-07-02 20:24:40 -04002739 !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(),
2740 hs->config->quic_transport_params.size()) ||
Nick Harper3c034b22017-12-22 15:50:43 -08002741 !CBB_flush(out)) {
2742 return false;
2743 }
2744
2745 return true;
2746}
2747
David Schinazi3d8b8c32021-01-14 11:25:49 -08002748static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs,
2749 CBB *out) {
2750 return ext_quic_transport_params_add_serverhello_impl(
2751 hs, out, /*use_legacy_codepoint=*/false);
2752}
2753
2754static bool ext_quic_transport_params_add_serverhello_legacy(SSL_HANDSHAKE *hs,
2755 CBB *out) {
2756 return ext_quic_transport_params_add_serverhello_impl(
2757 hs, out, /*use_legacy_codepoint=*/true);
2758}
2759
Christopher Patton6c1b3762018-07-17 12:49:41 -07002760// Delegated credentials.
2761//
David Benjamin48b0edf2024-02-11 17:14:41 -05002762// https://www.rfc-editor.org/rfc/rfc9345.html
Christopher Patton6c1b3762018-07-17 12:49:41 -07002763
David Benjamin83a49932021-05-20 15:57:09 -04002764static bool ext_delegated_credential_add_clienthello(
2765 const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
2766 ssl_client_hello_type_t type) {
Christopher Patton6c1b3762018-07-17 12:49:41 -07002767 return true;
2768}
2769
2770static bool ext_delegated_credential_parse_clienthello(SSL_HANDSHAKE *hs,
2771 uint8_t *out_alert,
2772 CBS *contents) {
Christopher Patton6c1b3762018-07-17 12:49:41 -07002773 if (contents == nullptr || ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
2774 // Don't use delegated credentials unless we're negotiating TLS 1.3 or
2775 // higher.
2776 return true;
2777 }
2778
Watson Ladddcd6e442020-08-10 15:12:45 -04002779 // The contents of the extension are the signature algorithms the client will
2780 // accept for a delegated credential.
2781 CBS sigalg_list;
2782 if (!CBS_get_u16_length_prefixed(contents, &sigalg_list) ||
2783 CBS_len(&sigalg_list) == 0 ||
2784 CBS_len(contents) != 0 ||
2785 !parse_u16_array(&sigalg_list, &hs->peer_delegated_credential_sigalgs)) {
2786 return false;
2787 }
2788
Christopher Patton6c1b3762018-07-17 12:49:41 -07002789 return true;
2790}
2791
Adam Langleya307cb72018-05-02 09:06:48 -07002792// Certificate compression
2793
David Benjamin83a49932021-05-20 15:57:09 -04002794static bool cert_compression_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2795 CBB *out_compressible,
2796 ssl_client_hello_type_t type) {
Adam Langley0080d832018-06-07 16:39:49 -07002797 bool first = true;
2798 CBB contents, algs;
2799
David Benjamin8fe15842019-10-08 16:57:38 -04002800 for (const auto &alg : hs->ssl->ctx->cert_compression_algs) {
2801 if (alg.decompress == nullptr) {
Adam Langley0080d832018-06-07 16:39:49 -07002802 continue;
2803 }
2804
David Benjamin83a49932021-05-20 15:57:09 -04002805 if (first &&
2806 (!CBB_add_u16(out_compressible, TLSEXT_TYPE_cert_compression) ||
2807 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
2808 !CBB_add_u8_length_prefixed(&contents, &algs))) {
Adam Langley0080d832018-06-07 16:39:49 -07002809 return false;
2810 }
2811 first = false;
David Benjamin8fe15842019-10-08 16:57:38 -04002812 if (!CBB_add_u16(&algs, alg.alg_id)) {
Adam Langley0080d832018-06-07 16:39:49 -07002813 return false;
2814 }
2815 }
2816
David Benjamin83a49932021-05-20 15:57:09 -04002817 return first || CBB_flush(out_compressible);
Adam Langleya307cb72018-05-02 09:06:48 -07002818}
2819
2820static bool cert_compression_parse_serverhello(SSL_HANDSHAKE *hs,
2821 uint8_t *out_alert,
2822 CBS *contents) {
2823 if (contents == nullptr) {
2824 return true;
2825 }
2826
2827 // The server may not echo this extension. Any server to client negotiation is
2828 // advertised in the CertificateRequest message.
2829 return false;
2830}
2831
2832static bool cert_compression_parse_clienthello(SSL_HANDSHAKE *hs,
2833 uint8_t *out_alert,
2834 CBS *contents) {
2835 if (contents == nullptr) {
2836 return true;
2837 }
2838
David Benjamin8fe15842019-10-08 16:57:38 -04002839 const SSL_CTX *ctx = hs->ssl->ctx.get();
2840 const size_t num_algs = ctx->cert_compression_algs.size();
Adam Langleya307cb72018-05-02 09:06:48 -07002841
2842 CBS alg_ids;
2843 if (!CBS_get_u8_length_prefixed(contents, &alg_ids) ||
2844 CBS_len(contents) != 0 ||
2845 CBS_len(&alg_ids) == 0 ||
2846 CBS_len(&alg_ids) % 2 == 1) {
2847 return false;
2848 }
2849
2850 const size_t num_given_alg_ids = CBS_len(&alg_ids) / 2;
2851 Array<uint16_t> given_alg_ids;
2852 if (!given_alg_ids.Init(num_given_alg_ids)) {
2853 return false;
2854 }
2855
2856 size_t best_index = num_algs;
2857 size_t given_alg_idx = 0;
2858
2859 while (CBS_len(&alg_ids) > 0) {
2860 uint16_t alg_id;
2861 if (!CBS_get_u16(&alg_ids, &alg_id)) {
2862 return false;
2863 }
2864
2865 given_alg_ids[given_alg_idx++] = alg_id;
2866
2867 for (size_t i = 0; i < num_algs; i++) {
David Benjamin8fe15842019-10-08 16:57:38 -04002868 const auto &alg = ctx->cert_compression_algs[i];
2869 if (alg.alg_id == alg_id && alg.compress != nullptr) {
Adam Langleya307cb72018-05-02 09:06:48 -07002870 if (i < best_index) {
2871 best_index = i;
2872 }
2873 break;
2874 }
2875 }
2876 }
2877
2878 qsort(given_alg_ids.data(), given_alg_ids.size(), sizeof(uint16_t),
2879 compare_uint16_t);
2880 for (size_t i = 1; i < num_given_alg_ids; i++) {
2881 if (given_alg_ids[i - 1] == given_alg_ids[i]) {
2882 return false;
2883 }
2884 }
2885
2886 if (best_index < num_algs &&
2887 ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
2888 hs->cert_compression_negotiated = true;
David Benjamin8fe15842019-10-08 16:57:38 -04002889 hs->cert_compression_alg_id = ctx->cert_compression_algs[best_index].alg_id;
Adam Langleya307cb72018-05-02 09:06:48 -07002890 }
2891
2892 return true;
2893}
2894
2895static bool cert_compression_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
2896 return true;
2897}
Nick Harper3c034b22017-12-22 15:50:43 -08002898
Steven Valdez51607f12020-08-05 10:46:05 -04002899// Application-level Protocol Settings
2900//
2901// https://tools.ietf.org/html/draft-vvv-tls-alps-01
2902
David Benjamin4e93cd42021-05-18 13:38:25 -04002903bool ssl_get_local_application_settings(const SSL_HANDSHAKE *hs,
2904 Span<const uint8_t> *out_settings,
2905 Span<const uint8_t> protocol) {
2906 for (const ALPSConfig &config : hs->config->alps_configs) {
2907 if (protocol == config.protocol) {
2908 *out_settings = config.settings;
2909 return true;
2910 }
2911 }
2912 return false;
2913}
2914
Victor Tan558960d2023-06-23 15:04:33 +00002915static bool ext_alps_add_clienthello_impl(const SSL_HANDSHAKE *hs, CBB *out,
2916 CBB *out_compressible,
2917 ssl_client_hello_type_t type,
2918 bool use_new_codepoint) {
David Benjamin14e51ad2021-05-19 15:24:34 -04002919 const SSL *const ssl = hs->ssl;
Steven Valdez51607f12020-08-05 10:46:05 -04002920 if (// ALPS requires TLS 1.3.
2921 hs->max_version < TLS1_3_VERSION ||
2922 // Do not offer ALPS without ALPN.
2923 hs->config->alpn_client_proto_list.empty() ||
2924 // Do not offer ALPS if not configured.
2925 hs->config->alps_configs.empty() ||
2926 // Do not offer ALPS on renegotiation handshakes.
2927 ssl->s3->initial_handshake_complete) {
2928 return true;
2929 }
2930
Victor Tan558960d2023-06-23 15:04:33 +00002931 if (use_new_codepoint != hs->config->alps_use_new_codepoint) {
2932 // Do nothing, we'll send the other codepoint.
2933 return true;
2934 }
2935
2936 uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
2937 if (hs->config->alps_use_new_codepoint) {
2938 extension_type = TLSEXT_TYPE_application_settings;
2939 }
2940
Steven Valdez51607f12020-08-05 10:46:05 -04002941 CBB contents, proto_list, proto;
Victor Tan558960d2023-06-23 15:04:33 +00002942 if (!CBB_add_u16(out_compressible, extension_type) ||
David Benjamin83a49932021-05-20 15:57:09 -04002943 !CBB_add_u16_length_prefixed(out_compressible, &contents) ||
Steven Valdez51607f12020-08-05 10:46:05 -04002944 !CBB_add_u16_length_prefixed(&contents, &proto_list)) {
2945 return false;
2946 }
2947
2948 for (const ALPSConfig &config : hs->config->alps_configs) {
2949 if (!CBB_add_u8_length_prefixed(&proto_list, &proto) ||
2950 !CBB_add_bytes(&proto, config.protocol.data(),
2951 config.protocol.size())) {
2952 return false;
2953 }
2954 }
2955
David Benjamin83a49932021-05-20 15:57:09 -04002956 return CBB_flush(out_compressible);
Steven Valdez51607f12020-08-05 10:46:05 -04002957}
2958
Victor Tan558960d2023-06-23 15:04:33 +00002959static bool ext_alps_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
2960 CBB *out_compressible,
2961 ssl_client_hello_type_t type) {
2962 return ext_alps_add_clienthello_impl(hs, out, out_compressible, type,
2963 /*use_new_codepoint=*/true);
2964}
2965
2966static bool ext_alps_add_clienthello_old(const SSL_HANDSHAKE *hs, CBB *out,
2967 CBB *out_compressible,
2968 ssl_client_hello_type_t type) {
2969 return ext_alps_add_clienthello_impl(hs, out, out_compressible, type,
2970 /*use_new_codepoint=*/false);
2971}
2972
2973static bool ext_alps_parse_serverhello_impl(SSL_HANDSHAKE *hs,
2974 uint8_t *out_alert,
2975 CBS *contents,
2976 bool use_new_codepoint) {
Steven Valdez51607f12020-08-05 10:46:05 -04002977 SSL *const ssl = hs->ssl;
2978 if (contents == nullptr) {
2979 return true;
2980 }
2981
2982 assert(!ssl->s3->initial_handshake_complete);
2983 assert(!hs->config->alpn_client_proto_list.empty());
2984 assert(!hs->config->alps_configs.empty());
Victor Tan558960d2023-06-23 15:04:33 +00002985 assert(use_new_codepoint == hs->config->alps_use_new_codepoint);
Steven Valdez51607f12020-08-05 10:46:05 -04002986
2987 // ALPS requires TLS 1.3.
2988 if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
2989 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
2990 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
2991 return false;
2992 }
2993
2994 // Note extension callbacks may run in any order, so we defer checking
2995 // consistency with ALPN to |ssl_check_serverhello_tlsext|.
2996 if (!hs->new_session->peer_application_settings.CopyFrom(*contents)) {
2997 *out_alert = SSL_AD_INTERNAL_ERROR;
2998 return false;
2999 }
3000
3001 hs->new_session->has_application_settings = true;
3002 return true;
3003}
3004
Victor Tan558960d2023-06-23 15:04:33 +00003005static bool ext_alps_parse_serverhello(SSL_HANDSHAKE *hs,
3006 uint8_t *out_alert,
3007 CBS *contents) {
3008 return ext_alps_parse_serverhello_impl(hs, out_alert, contents,
3009 /*use_new_codepoint=*/true);
3010}
3011
3012static bool ext_alps_parse_serverhello_old(SSL_HANDSHAKE *hs,
3013 uint8_t *out_alert,
3014 CBS *contents) {
3015 return ext_alps_parse_serverhello_impl(hs, out_alert, contents,
3016 /*use_new_codepoint=*/false);
3017}
3018
3019static bool ext_alps_add_serverhello_impl(SSL_HANDSHAKE *hs, CBB *out,
3020 bool use_new_codepoint) {
Steven Valdez51607f12020-08-05 10:46:05 -04003021 SSL *const ssl = hs->ssl;
3022 // If early data is accepted, we omit the ALPS extension. It is implicitly
3023 // carried over from the previous connection.
3024 if (hs->new_session == nullptr ||
3025 !hs->new_session->has_application_settings ||
3026 ssl->s3->early_data_accepted) {
3027 return true;
3028 }
3029
Victor Tan558960d2023-06-23 15:04:33 +00003030 if (use_new_codepoint != hs->config->alps_use_new_codepoint) {
3031 // Do nothing, we'll send the other codepoint.
3032 return true;
3033 }
3034
3035 uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
3036 if (hs->config->alps_use_new_codepoint) {
3037 extension_type = TLSEXT_TYPE_application_settings;
3038 }
3039
Steven Valdez51607f12020-08-05 10:46:05 -04003040 CBB contents;
Victor Tan558960d2023-06-23 15:04:33 +00003041 if (!CBB_add_u16(out, extension_type) ||
Steven Valdez51607f12020-08-05 10:46:05 -04003042 !CBB_add_u16_length_prefixed(out, &contents) ||
3043 !CBB_add_bytes(&contents,
3044 hs->new_session->local_application_settings.data(),
3045 hs->new_session->local_application_settings.size()) ||
3046 !CBB_flush(out)) {
3047 return false;
3048 }
3049
3050 return true;
3051}
3052
Victor Tan558960d2023-06-23 15:04:33 +00003053static bool ext_alps_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
3054 return ext_alps_add_serverhello_impl(hs, out, /*use_new_codepoint=*/true);
3055}
3056
3057static bool ext_alps_add_serverhello_old(SSL_HANDSHAKE *hs, CBB *out) {
3058 return ext_alps_add_serverhello_impl(hs, out, /*use_new_codepoint=*/false);
3059}
3060
Steven Valdez51607f12020-08-05 10:46:05 -04003061bool ssl_negotiate_alps(SSL_HANDSHAKE *hs, uint8_t *out_alert,
3062 const SSL_CLIENT_HELLO *client_hello) {
3063 SSL *const ssl = hs->ssl;
3064 if (ssl->s3->alpn_selected.empty()) {
3065 return true;
3066 }
3067
3068 // If we negotiate ALPN over TLS 1.3, try to negotiate ALPS.
3069 CBS alps_contents;
3070 Span<const uint8_t> settings;
Victor Tan558960d2023-06-23 15:04:33 +00003071 uint16_t extension_type = TLSEXT_TYPE_application_settings_old;
3072 if (hs->config->alps_use_new_codepoint) {
3073 extension_type = TLSEXT_TYPE_application_settings;
3074 }
Steven Valdez51607f12020-08-05 10:46:05 -04003075 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION &&
3076 ssl_get_local_application_settings(hs, &settings,
3077 ssl->s3->alpn_selected) &&
3078 ssl_client_hello_get_extension(client_hello, &alps_contents,
Victor Tan558960d2023-06-23 15:04:33 +00003079 extension_type)) {
Steven Valdez51607f12020-08-05 10:46:05 -04003080 // Check if the client supports ALPS with the selected ALPN.
3081 bool found = false;
3082 CBS alps_list;
3083 if (!CBS_get_u16_length_prefixed(&alps_contents, &alps_list) ||
3084 CBS_len(&alps_contents) != 0 ||
3085 CBS_len(&alps_list) == 0) {
3086 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
3087 *out_alert = SSL_AD_DECODE_ERROR;
3088 return false;
3089 }
3090 while (CBS_len(&alps_list) > 0) {
3091 CBS protocol_name;
3092 if (!CBS_get_u8_length_prefixed(&alps_list, &protocol_name) ||
3093 // Empty protocol names are forbidden.
3094 CBS_len(&protocol_name) == 0) {
3095 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
3096 *out_alert = SSL_AD_DECODE_ERROR;
3097 return false;
3098 }
3099 if (protocol_name == MakeConstSpan(ssl->s3->alpn_selected)) {
3100 found = true;
3101 }
3102 }
3103
3104 // Negotiate ALPS if both client also supports ALPS for this protocol.
3105 if (found) {
3106 hs->new_session->has_application_settings = true;
3107 if (!hs->new_session->local_application_settings.CopyFrom(settings)) {
3108 *out_alert = SSL_AD_INTERNAL_ERROR;
3109 return false;
3110 }
3111 }
3112 }
3113
3114 return true;
3115}
Adam Langleya86c6982019-07-16 15:26:21 -07003116
David Benjaminc11ea9422017-08-29 16:33:21 -04003117// kExtensions contains all the supported extensions.
Adam Langley614c66a2015-06-12 15:26:58 -07003118static const struct tls_extension kExtensions[] = {
3119 {
3120 TLSEXT_TYPE_server_name,
Adam Langley614c66a2015-06-12 15:26:58 -07003121 ext_sni_add_clienthello,
3122 ext_sni_parse_serverhello,
3123 ext_sni_parse_clienthello,
3124 ext_sni_add_serverhello,
3125 },
Adam Langley0a056712015-07-01 15:03:33 -07003126 {
Dan McArdle1920c6f2020-03-11 17:29:40 -04003127 TLSEXT_TYPE_encrypted_client_hello,
Dan McArdle1920c6f2020-03-11 17:29:40 -04003128 ext_ech_add_clienthello,
3129 ext_ech_parse_serverhello,
Dan McArdlec2959352020-10-29 14:31:31 -04003130 ext_ech_parse_clienthello,
Daniel McArdle00e434d2021-02-18 11:47:18 -05003131 ext_ech_add_serverhello,
Dan McArdlec2959352020-10-29 14:31:31 -04003132 },
3133 {
Adam Langley0a056712015-07-01 15:03:33 -07003134 TLSEXT_TYPE_extended_master_secret,
Adam Langley0a056712015-07-01 15:03:33 -07003135 ext_ems_add_clienthello,
3136 ext_ems_parse_serverhello,
3137 ext_ems_parse_clienthello,
3138 ext_ems_add_serverhello,
3139 },
Adam Langley9b05bc52015-07-01 15:25:33 -07003140 {
Adam Langleyd6680952018-08-23 08:01:23 -07003141 TLSEXT_TYPE_renegotiate,
Adam Langleyd6680952018-08-23 08:01:23 -07003142 ext_ri_add_clienthello,
3143 ext_ri_parse_serverhello,
3144 ext_ri_parse_clienthello,
3145 ext_ri_add_serverhello,
3146 },
3147 {
3148 TLSEXT_TYPE_supported_groups,
Adam Langleyd6680952018-08-23 08:01:23 -07003149 ext_supported_groups_add_clienthello,
3150 ext_supported_groups_parse_serverhello,
3151 ext_supported_groups_parse_clienthello,
3152 dont_add_serverhello,
3153 },
3154 {
3155 TLSEXT_TYPE_ec_point_formats,
Adam Langleyd6680952018-08-23 08:01:23 -07003156 ext_ec_point_add_clienthello,
3157 ext_ec_point_parse_serverhello,
3158 ext_ec_point_parse_clienthello,
3159 ext_ec_point_add_serverhello,
3160 },
3161 {
Adam Langley9b05bc52015-07-01 15:25:33 -07003162 TLSEXT_TYPE_session_ticket,
Adam Langley9b05bc52015-07-01 15:25:33 -07003163 ext_ticket_add_clienthello,
3164 ext_ticket_parse_serverhello,
David Benjaminc11ea9422017-08-29 16:33:21 -04003165 // Ticket extension client parsing is handled in ssl_session.c
Steven Valdez6b8509a2016-07-12 13:38:32 -04003166 ignore_parse_clienthello,
Adam Langley9b05bc52015-07-01 15:25:33 -07003167 ext_ticket_add_serverhello,
3168 },
Adam Langley2e857bd2015-07-01 16:09:19 -07003169 {
Adam Langleyd6680952018-08-23 08:01:23 -07003170 TLSEXT_TYPE_application_layer_protocol_negotiation,
Adam Langleyd6680952018-08-23 08:01:23 -07003171 ext_alpn_add_clienthello,
3172 ext_alpn_parse_serverhello,
3173 // ALPN is negotiated late in |ssl_negotiate_alpn|.
3174 ignore_parse_clienthello,
3175 ext_alpn_add_serverhello,
3176 },
3177 {
3178 TLSEXT_TYPE_status_request,
Adam Langleyd6680952018-08-23 08:01:23 -07003179 ext_ocsp_add_clienthello,
3180 ext_ocsp_parse_serverhello,
3181 ext_ocsp_parse_clienthello,
3182 ext_ocsp_add_serverhello,
3183 },
3184 {
Adam Langley2e857bd2015-07-01 16:09:19 -07003185 TLSEXT_TYPE_signature_algorithms,
Adam Langley2e857bd2015-07-01 16:09:19 -07003186 ext_sigalgs_add_clienthello,
Steven Valdez6b8509a2016-07-12 13:38:32 -04003187 forbid_parse_serverhello,
Adam Langley2e857bd2015-07-01 16:09:19 -07003188 ext_sigalgs_parse_clienthello,
Steven Valdez6b8509a2016-07-12 13:38:32 -04003189 dont_add_serverhello,
Adam Langley2e857bd2015-07-01 16:09:19 -07003190 },
Adam Langleybb0bd042015-07-01 16:21:03 -07003191 {
Adam Langley97dfcbf2015-07-01 18:35:20 -07003192 TLSEXT_TYPE_next_proto_neg,
Adam Langley97dfcbf2015-07-01 18:35:20 -07003193 ext_npn_add_clienthello,
3194 ext_npn_parse_serverhello,
3195 ext_npn_parse_clienthello,
3196 ext_npn_add_serverhello,
3197 },
Adam Langleyab8d87d2015-07-10 12:21:39 -07003198 {
3199 TLSEXT_TYPE_certificate_timestamp,
Adam Langleyab8d87d2015-07-10 12:21:39 -07003200 ext_sct_add_clienthello,
3201 ext_sct_parse_serverhello,
3202 ext_sct_parse_clienthello,
3203 ext_sct_add_serverhello,
3204 },
Adam Langleyf18e4532015-07-10 13:39:53 -07003205 {
Adam Langley49c7af12015-07-10 14:33:46 -07003206 TLSEXT_TYPE_channel_id,
Adam Langley49c7af12015-07-10 14:33:46 -07003207 ext_channel_id_add_clienthello,
3208 ext_channel_id_parse_serverhello,
3209 ext_channel_id_parse_clienthello,
3210 ext_channel_id_add_serverhello,
3211 },
Adam Langley391250d2015-07-15 19:06:07 -07003212 {
3213 TLSEXT_TYPE_srtp,
Adam Langley391250d2015-07-15 19:06:07 -07003214 ext_srtp_add_clienthello,
3215 ext_srtp_parse_serverhello,
3216 ext_srtp_parse_clienthello,
3217 ext_srtp_add_serverhello,
3218 },
Adam Langleybdd5d662015-07-20 16:19:08 -07003219 {
Steven Valdez7e5dd252018-01-22 15:20:31 -05003220 TLSEXT_TYPE_key_share,
Steven Valdez143e8b32016-07-11 13:19:03 -04003221 ext_key_share_add_clienthello,
3222 forbid_parse_serverhello,
3223 ignore_parse_clienthello,
3224 dont_add_serverhello,
3225 },
Steven Valdez4aa154e2016-07-29 14:32:55 -04003226 {
Steven Valdeza833c352016-11-01 13:39:36 -04003227 TLSEXT_TYPE_psk_key_exchange_modes,
Steven Valdeza833c352016-11-01 13:39:36 -04003228 ext_psk_key_exchange_modes_add_clienthello,
Steven Valdez4aa154e2016-07-29 14:32:55 -04003229 forbid_parse_serverhello,
David Benjamin4eb95cc2016-11-16 17:08:23 +09003230 ext_psk_key_exchange_modes_parse_clienthello,
Steven Valdez4aa154e2016-07-29 14:32:55 -04003231 dont_add_serverhello,
3232 },
Steven Valdezfdd10992016-09-15 16:27:05 -04003233 {
Steven Valdeza4ee74d2016-11-29 13:36:45 -05003234 TLSEXT_TYPE_early_data,
Steven Valdeza4ee74d2016-11-29 13:36:45 -05003235 ext_early_data_add_clienthello,
Steven Valdez2d850622017-01-11 11:34:52 -05003236 ext_early_data_parse_serverhello,
Steven Valdeza4ee74d2016-11-29 13:36:45 -05003237 ext_early_data_parse_clienthello,
Steven Valdez2d850622017-01-11 11:34:52 -05003238 ext_early_data_add_serverhello,
Steven Valdeza4ee74d2016-11-29 13:36:45 -05003239 },
3240 {
Steven Valdezfdd10992016-09-15 16:27:05 -04003241 TLSEXT_TYPE_supported_versions,
Steven Valdezfdd10992016-09-15 16:27:05 -04003242 ext_supported_versions_add_clienthello,
3243 forbid_parse_serverhello,
3244 ignore_parse_clienthello,
3245 dont_add_serverhello,
3246 },
David Benjamin3baa6e12016-10-07 21:10:38 -04003247 {
3248 TLSEXT_TYPE_cookie,
David Benjamin3baa6e12016-10-07 21:10:38 -04003249 ext_cookie_add_clienthello,
3250 forbid_parse_serverhello,
3251 ignore_parse_clienthello,
3252 dont_add_serverhello,
3253 },
Adam Langley512a2892017-12-30 08:04:39 -08003254 {
David Benjamina1d3bfb2021-06-01 12:12:44 -04003255 TLSEXT_TYPE_quic_transport_parameters,
Nick Harper3c034b22017-12-22 15:50:43 -08003256 ext_quic_transport_params_add_clienthello,
3257 ext_quic_transport_params_parse_serverhello,
3258 ext_quic_transport_params_parse_clienthello,
3259 ext_quic_transport_params_add_serverhello,
3260 },
Adam Langley273d49c2015-07-20 16:38:52 -07003261 {
David Schinazi3d8b8c32021-01-14 11:25:49 -08003262 TLSEXT_TYPE_quic_transport_parameters_legacy,
David Schinazi3d8b8c32021-01-14 11:25:49 -08003263 ext_quic_transport_params_add_clienthello_legacy,
3264 ext_quic_transport_params_parse_serverhello_legacy,
3265 ext_quic_transport_params_parse_clienthello_legacy,
3266 ext_quic_transport_params_add_serverhello_legacy,
3267 },
3268 {
Adam Langleya307cb72018-05-02 09:06:48 -07003269 TLSEXT_TYPE_cert_compression,
Adam Langleya307cb72018-05-02 09:06:48 -07003270 cert_compression_add_clienthello,
3271 cert_compression_parse_serverhello,
3272 cert_compression_parse_clienthello,
3273 cert_compression_add_serverhello,
3274 },
Christopher Patton6c1b3762018-07-17 12:49:41 -07003275 {
3276 TLSEXT_TYPE_delegated_credential,
Christopher Patton6c1b3762018-07-17 12:49:41 -07003277 ext_delegated_credential_add_clienthello,
3278 forbid_parse_serverhello,
3279 ext_delegated_credential_parse_clienthello,
3280 dont_add_serverhello,
3281 },
Steven Valdez51607f12020-08-05 10:46:05 -04003282 {
3283 TLSEXT_TYPE_application_settings,
Steven Valdez51607f12020-08-05 10:46:05 -04003284 ext_alps_add_clienthello,
3285 ext_alps_parse_serverhello,
3286 // ALPS is negotiated late in |ssl_negotiate_alpn|.
3287 ignore_parse_clienthello,
3288 ext_alps_add_serverhello,
3289 },
Victor Tan558960d2023-06-23 15:04:33 +00003290 {
3291 TLSEXT_TYPE_application_settings_old,
3292 ext_alps_add_clienthello_old,
3293 ext_alps_parse_serverhello_old,
3294 // ALPS is negotiated late in |ssl_negotiate_alpn|.
3295 ignore_parse_clienthello,
3296 ext_alps_add_serverhello_old,
3297 },
Adam Langley614c66a2015-06-12 15:26:58 -07003298};
3299
3300#define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
3301
David Benjamina3d76d02017-07-14 19:36:07 -04003302static_assert(kNumExtensions <=
3303 sizeof(((SSL_HANDSHAKE *)NULL)->extensions.sent) * 8,
3304 "too many extensions for sent bitset");
3305static_assert(kNumExtensions <=
3306 sizeof(((SSL_HANDSHAKE *)NULL)->extensions.received) * 8,
3307 "too many extensions for received bitset");
Adam Langley4cfa96b2015-07-01 11:56:55 -07003308
David Benjamine9c5d722021-06-09 17:43:16 -04003309bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs) {
3310 if (!hs->config->permute_extensions) {
3311 return true;
3312 }
3313
3314 static_assert(kNumExtensions <= UINT8_MAX,
3315 "extensions_permutation type is too small");
3316 uint32_t seeds[kNumExtensions - 1];
3317 Array<uint8_t> permutation;
3318 if (!RAND_bytes(reinterpret_cast<uint8_t *>(seeds), sizeof(seeds)) ||
3319 !permutation.Init(kNumExtensions)) {
3320 return false;
3321 }
3322 for (size_t i = 0; i < kNumExtensions; i++) {
3323 permutation[i] = i;
3324 }
3325 for (size_t i = kNumExtensions - 1; i > 0; i--) {
3326 // Set element |i| to a randomly-selected element 0 <= j <= i.
3327 std::swap(permutation[i], permutation[seeds[i - 1] % (i + 1)]);
3328 }
3329 hs->extension_permutation = std::move(permutation);
3330 return true;
3331}
3332
Adam Langley614c66a2015-06-12 15:26:58 -07003333static const struct tls_extension *tls_extension_find(uint32_t *out_index,
3334 uint16_t value) {
3335 unsigned i;
3336 for (i = 0; i < kNumExtensions; i++) {
3337 if (kExtensions[i].value == value) {
3338 *out_index = i;
3339 return &kExtensions[i];
3340 }
3341 }
3342
3343 return NULL;
3344}
3345
David Benjaminfb4d2572021-06-01 15:58:30 -04003346static bool add_padding_extension(CBB *cbb, uint16_t ext, size_t len) {
3347 CBB child;
David Benjaminfb4d2572021-06-01 15:58:30 -04003348 if (!CBB_add_u16(cbb, ext) || //
3349 !CBB_add_u16_length_prefixed(cbb, &child) ||
David Benjamin95450622021-07-16 18:24:02 -04003350 !CBB_add_zeros(&child, len)) {
David Benjaminfb4d2572021-06-01 15:58:30 -04003351 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3352 return false;
3353 }
David Benjaminfb4d2572021-06-01 15:58:30 -04003354 return CBB_flush(cbb);
3355}
3356
David Benjamin83a49932021-05-20 15:57:09 -04003357static bool ssl_add_clienthello_tlsext_inner(SSL_HANDSHAKE *hs, CBB *out,
3358 CBB *out_encoded,
3359 bool *out_needs_psk_binder) {
3360 // When writing ClientHelloInner, we construct the real and encoded
3361 // ClientHellos concurrently, to handle compression. Uncompressed extensions
3362 // are written to |extensions| and copied to |extensions_encoded|. Compressed
3363 // extensions are buffered in |compressed| and written to the end. (ECH can
3364 // only compress continguous extensions.)
3365 SSL *const ssl = hs->ssl;
3366 bssl::ScopedCBB compressed, outer_extensions;
3367 CBB extensions, extensions_encoded;
3368 if (!CBB_add_u16_length_prefixed(out, &extensions) ||
3369 !CBB_add_u16_length_prefixed(out_encoded, &extensions_encoded) ||
3370 !CBB_init(compressed.get(), 64) ||
3371 !CBB_init(outer_extensions.get(), 64)) {
3372 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
3373 return false;
3374 }
3375
3376 hs->inner_extensions_sent = 0;
3377
3378 if (ssl->ctx->grease_enabled) {
3379 // Add a fake empty extension. See RFC 8701. This always matches
3380 // |ssl_add_clienthello_tlsext|, so compress it.
3381 uint16_t grease_ext = ssl_get_grease_value(hs, ssl_grease_extension1);
3382 if (!add_padding_extension(compressed.get(), grease_ext, 0) ||
3383 !CBB_add_u16(outer_extensions.get(), grease_ext)) {
3384 return false;
3385 }
3386 }
3387
David Benjamine9c5d722021-06-09 17:43:16 -04003388 for (size_t unpermuted = 0; unpermuted < kNumExtensions; unpermuted++) {
3389 size_t i = hs->extension_permutation.empty()
3390 ? unpermuted
3391 : hs->extension_permutation[unpermuted];
David Benjamin83a49932021-05-20 15:57:09 -04003392 const size_t len_before = CBB_len(&extensions);
3393 const size_t len_compressed_before = CBB_len(compressed.get());
3394 if (!kExtensions[i].add_clienthello(hs, &extensions, compressed.get(),
3395 ssl_client_hello_inner)) {
3396 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
3397 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3398 return false;
3399 }
3400
3401 const size_t bytes_written = CBB_len(&extensions) - len_before;
3402 const size_t bytes_written_compressed =
3403 CBB_len(compressed.get()) - len_compressed_before;
3404 // The callback may write to at most one output.
3405 assert(bytes_written == 0 || bytes_written_compressed == 0);
3406 if (bytes_written != 0 || bytes_written_compressed != 0) {
3407 hs->inner_extensions_sent |= (1u << i);
3408 }
3409 // If compressed, update the running ech_outer_extensions extension.
3410 if (bytes_written_compressed != 0 &&
3411 !CBB_add_u16(outer_extensions.get(), kExtensions[i].value)) {
3412 return false;
3413 }
3414 }
3415
3416 if (ssl->ctx->grease_enabled) {
3417 // Add a fake non-empty extension. See RFC 8701. This always matches
3418 // |ssl_add_clienthello_tlsext|, so compress it.
3419 uint16_t grease_ext = ssl_get_grease_value(hs, ssl_grease_extension2);
3420 if (!add_padding_extension(compressed.get(), grease_ext, 1) ||
3421 !CBB_add_u16(outer_extensions.get(), grease_ext)) {
3422 return false;
3423 }
3424 }
3425
David Benjamin83a49932021-05-20 15:57:09 -04003426 // Uncompressed extensions are encoded as-is.
3427 if (!CBB_add_bytes(&extensions_encoded, CBB_data(&extensions),
3428 CBB_len(&extensions))) {
3429 return false;
3430 }
3431
3432 // Flush all the compressed extensions.
3433 if (CBB_len(compressed.get()) != 0) {
3434 CBB extension, child;
3435 // Copy them as-is in the real ClientHelloInner.
3436 if (!CBB_add_bytes(&extensions, CBB_data(compressed.get()),
3437 CBB_len(compressed.get())) ||
3438 // Replace with ech_outer_extensions in the encoded form.
3439 !CBB_add_u16(&extensions_encoded, TLSEXT_TYPE_ech_outer_extensions) ||
3440 !CBB_add_u16_length_prefixed(&extensions_encoded, &extension) ||
3441 !CBB_add_u8_length_prefixed(&extension, &child) ||
3442 !CBB_add_bytes(&child, CBB_data(outer_extensions.get()),
3443 CBB_len(outer_extensions.get())) ||
3444 !CBB_flush(&extensions_encoded)) {
3445 return false;
3446 }
3447 }
3448
3449 // The PSK extension must be last. It is never compressed. Note, if there is a
3450 // binder, the caller will need to update both ClientHelloInner and
3451 // EncodedClientHelloInner after computing it.
3452 const size_t len_before = CBB_len(&extensions);
3453 if (!ext_pre_shared_key_add_clienthello(hs, &extensions, out_needs_psk_binder,
3454 ssl_client_hello_inner) ||
3455 !CBB_add_bytes(&extensions_encoded, CBB_data(&extensions) + len_before,
3456 CBB_len(&extensions) - len_before) ||
3457 !CBB_flush(out) || //
3458 !CBB_flush(out_encoded)) {
3459 return false;
3460 }
3461
3462 return true;
3463}
3464
3465bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, CBB *out_encoded,
3466 bool *out_needs_psk_binder,
David Benjamin18b68362021-06-18 23:13:46 -04003467 ssl_client_hello_type_t type,
3468 size_t header_len) {
David Benjamin83a49932021-05-20 15:57:09 -04003469 *out_needs_psk_binder = false;
3470
3471 if (type == ssl_client_hello_inner) {
3472 return ssl_add_clienthello_tlsext_inner(hs, out, out_encoded,
3473 out_needs_psk_binder);
3474 }
3475
3476 assert(out_encoded == nullptr); // Only ClientHelloInner needs two outputs.
David Benjamin8c880a22016-12-03 02:20:34 -05003477 SSL *const ssl = hs->ssl;
David Benjamine8d53502015-10-10 14:13:23 -04003478 CBB extensions;
3479 if (!CBB_add_u16_length_prefixed(out, &extensions)) {
David Benjamin81678aa2017-07-12 22:43:42 -04003480 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04003481 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003482 }
Adam Langley95c29f32014-06-20 12:00:00 -07003483
David Benjamin64770122019-05-04 11:00:04 -05003484 // Note we may send multiple ClientHellos for DTLS HelloVerifyRequest and TLS
3485 // 1.3 HelloRetryRequest. For the latter, the extensions may change, so it is
3486 // important to reset this value.
David Benjamin8c880a22016-12-03 02:20:34 -05003487 hs->extensions.sent = 0;
Adam Langley95c29f32014-06-20 12:00:00 -07003488
David Benjaminfb4d2572021-06-01 15:58:30 -04003489 // Add a fake empty extension. See RFC 8701.
3490 if (ssl->ctx->grease_enabled &&
3491 !add_padding_extension(
3492 &extensions, ssl_get_grease_value(hs, ssl_grease_extension1), 0)) {
3493 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04003494 }
3495
Adam Langley7f4f41f2018-08-23 08:58:49 -07003496 bool last_was_empty = false;
David Benjamine9c5d722021-06-09 17:43:16 -04003497 for (size_t unpermuted = 0; unpermuted < kNumExtensions; unpermuted++) {
3498 size_t i = hs->extension_permutation.empty()
3499 ? unpermuted
3500 : hs->extension_permutation[unpermuted];
David Benjamin18b68362021-06-18 23:13:46 -04003501 const size_t len_before = CBB_len(&extensions);
3502 if (!kExtensions[i].add_clienthello(hs, &extensions, &extensions, type)) {
3503 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
3504 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
3505 return false;
David Benjamin83a49932021-05-20 15:57:09 -04003506 }
David Benjamin18b68362021-06-18 23:13:46 -04003507
3508 const size_t bytes_written = CBB_len(&extensions) - len_before;
Adam Langley7f4f41f2018-08-23 08:58:49 -07003509 if (bytes_written != 0) {
David Benjamin8c880a22016-12-03 02:20:34 -05003510 hs->extensions.sent |= (1u << i);
Adam Langley614c66a2015-06-12 15:26:58 -07003511 }
Adam Langley7f4f41f2018-08-23 08:58:49 -07003512 // If the difference in lengths is only four bytes then the extension had
3513 // an empty body.
3514 last_was_empty = (bytes_written == 4);
Adam Langleyfcf25832014-12-18 17:42:32 -08003515 }
Adam Langley75712922014-10-10 16:23:43 -07003516
David Benjamin65ac9972016-09-02 21:35:25 -04003517 if (ssl->ctx->grease_enabled) {
David Benjamin3675eb32021-05-18 14:01:07 -04003518 // Add a fake non-empty extension. See RFC 8701.
David Benjaminfb4d2572021-06-01 15:58:30 -04003519 if (!add_padding_extension(
3520 &extensions, ssl_get_grease_value(hs, ssl_grease_extension2), 1)) {
David Benjamin861abcc2018-07-14 17:40:26 -04003521 return false;
David Benjamin65ac9972016-09-02 21:35:25 -04003522 }
Adam Langley7f4f41f2018-08-23 08:58:49 -07003523 last_was_empty = false;
David Benjamin65ac9972016-09-02 21:35:25 -04003524 }
3525
David Benjamin83a49932021-05-20 15:57:09 -04003526 // In cleartext ClientHellos, we add the padding extension to work around
3527 // bugs. We also apply this padding to ClientHelloOuter, to keep the wire
3528 // images aligned.
3529 size_t psk_extension_len = ext_pre_shared_key_clienthello_length(hs, type);
David Benjamincd890042021-06-02 18:35:31 -04003530 if (!SSL_is_dtls(ssl) && !ssl->quic_method &&
3531 !ssl->s3->used_hello_retry_request) {
David Benjamin18b68362021-06-18 23:13:46 -04003532 header_len +=
3533 SSL3_HM_HEADER_LENGTH + 2 + CBB_len(&extensions) + psk_extension_len;
Adam Langley7f4f41f2018-08-23 08:58:49 -07003534 size_t padding_len = 0;
3535
3536 // The final extension must be non-empty. WebSphere Application
3537 // Server 7.0 is intolerant to the last extension being zero-length. See
3538 // https://crbug.com/363583.
3539 if (last_was_empty && psk_extension_len == 0) {
3540 padding_len = 1;
3541 // The addition of the padding extension may push us into the F5 bug.
3542 header_len += 4 + padding_len;
3543 }
3544
3545 // Add padding to workaround bugs in F5 terminators. See RFC 7685.
3546 //
3547 // NB: because this code works out the length of all existing extensions
3548 // it MUST always appear last (save for any PSK extension).
Adam Langleyfcf25832014-12-18 17:42:32 -08003549 if (header_len > 0xff && header_len < 0x200) {
Adam Langley7f4f41f2018-08-23 08:58:49 -07003550 // If our calculations already included a padding extension, remove that
3551 // factor because we're about to change its length.
3552 if (padding_len != 0) {
3553 header_len -= 4 + padding_len;
3554 }
3555 padding_len = 0x200 - header_len;
David Benjaminc11ea9422017-08-29 16:33:21 -04003556 // Extensions take at least four bytes to encode. Always include at least
3557 // one byte of data if including the extension. WebSphere Application
3558 // Server 7.0 is intolerant to the last extension being zero-length. See
3559 // https://crbug.com/363583.
Adam Langleyfcf25832014-12-18 17:42:32 -08003560 if (padding_len >= 4 + 1) {
3561 padding_len -= 4;
3562 } else {
3563 padding_len = 1;
3564 }
Adam Langley7f4f41f2018-08-23 08:58:49 -07003565 }
Adam Langley95c29f32014-06-20 12:00:00 -07003566
David Benjaminfb4d2572021-06-01 15:58:30 -04003567 if (padding_len != 0 &&
3568 !add_padding_extension(&extensions, TLSEXT_TYPE_padding, padding_len)) {
3569 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003570 }
3571 }
Adam Langley75712922014-10-10 16:23:43 -07003572
David Benjaminc11ea9422017-08-29 16:33:21 -04003573 // The PSK extension must be last, including after the padding.
David Benjamin350fe3b2021-06-02 17:58:53 -04003574 const size_t len_before = CBB_len(&extensions);
David Benjamin83a49932021-05-20 15:57:09 -04003575 if (!ext_pre_shared_key_add_clienthello(hs, &extensions, out_needs_psk_binder,
3576 type)) {
David Benjamin81678aa2017-07-12 22:43:42 -04003577 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04003578 return false;
Steven Valdeza833c352016-11-01 13:39:36 -04003579 }
David Benjamin350fe3b2021-06-02 17:58:53 -04003580 assert(psk_extension_len == CBB_len(&extensions) - len_before);
3581 (void)len_before; // |assert| is omitted in release builds.
Steven Valdeza833c352016-11-01 13:39:36 -04003582
David Benjaminc11ea9422017-08-29 16:33:21 -04003583 // Discard empty extensions blocks.
David Benjamina01deee2015-12-08 18:56:31 -05003584 if (CBB_len(&extensions) == 0) {
David Benjamine8d53502015-10-10 14:13:23 -04003585 CBB_discard_child(out);
Adam Langley33ad2b52015-07-20 17:43:53 -07003586 }
3587
David Benjamine8d53502015-10-10 14:13:23 -04003588 return CBB_flush(out);
Adam Langleyfcf25832014-12-18 17:42:32 -08003589}
Adam Langley95c29f32014-06-20 12:00:00 -07003590
David Benjamin861abcc2018-07-14 17:40:26 -04003591bool ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out) {
David Benjamin8c880a22016-12-03 02:20:34 -05003592 SSL *const ssl = hs->ssl;
David Benjamin56380462015-10-10 14:59:09 -04003593 CBB extensions;
3594 if (!CBB_add_u16_length_prefixed(out, &extensions)) {
Adam Langley33ad2b52015-07-20 17:43:53 -07003595 goto err;
Adam Langley614c66a2015-06-12 15:26:58 -07003596 }
3597
David Benjamin8c880a22016-12-03 02:20:34 -05003598 for (unsigned i = 0; i < kNumExtensions; i++) {
3599 if (!(hs->extensions.received & (1u << i))) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003600 // Don't send extensions that were not received.
Adam Langley614c66a2015-06-12 15:26:58 -07003601 continue;
Adam Langleyfcf25832014-12-18 17:42:32 -08003602 }
Adam Langley95c29f32014-06-20 12:00:00 -07003603
David Benjamin8c880a22016-12-03 02:20:34 -05003604 if (!kExtensions[i].add_serverhello(hs, &extensions)) {
Adam Langley33ad2b52015-07-20 17:43:53 -07003605 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003606 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
Adam Langley33ad2b52015-07-20 17:43:53 -07003607 goto err;
Adam Langley614c66a2015-06-12 15:26:58 -07003608 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003609 }
Adam Langley95c29f32014-06-20 12:00:00 -07003610
David Benjaminc11ea9422017-08-29 16:33:21 -04003611 // Discard empty extensions blocks before TLS 1.3.
David Benjamind1e3ce12017-10-06 18:31:15 -04003612 if (ssl_protocol_version(ssl) < TLS1_3_VERSION &&
Steven Valdez143e8b32016-07-11 13:19:03 -04003613 CBB_len(&extensions) == 0) {
David Benjamin56380462015-10-10 14:59:09 -04003614 CBB_discard_child(out);
Adam Langley33ad2b52015-07-20 17:43:53 -07003615 }
3616
David Benjamin56380462015-10-10 14:59:09 -04003617 return CBB_flush(out);
Adam Langley33ad2b52015-07-20 17:43:53 -07003618
3619err:
Adam Langley33ad2b52015-07-20 17:43:53 -07003620 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04003621 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003622}
Adam Langley95c29f32014-06-20 12:00:00 -07003623
David Benjamin861abcc2018-07-14 17:40:26 -04003624static bool ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs,
3625 const SSL_CLIENT_HELLO *client_hello,
3626 int *out_alert) {
David Benjamin8c880a22016-12-03 02:20:34 -05003627 hs->extensions.received = 0;
David Benjamine14ff062016-08-09 16:21:24 -04003628 CBS extensions;
3629 CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
3630 while (CBS_len(&extensions) != 0) {
3631 uint16_t type;
3632 CBS extension;
3633
David Benjaminc11ea9422017-08-29 16:33:21 -04003634 // Decode the next extension.
David Benjamine14ff062016-08-09 16:21:24 -04003635 if (!CBS_get_u16(&extensions, &type) ||
3636 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08003637 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003638 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003639 }
Adam Langley95c29f32014-06-20 12:00:00 -07003640
David Benjamine14ff062016-08-09 16:21:24 -04003641 unsigned ext_index;
3642 const struct tls_extension *const ext =
3643 tls_extension_find(&ext_index, type);
David Benjamine14ff062016-08-09 16:21:24 -04003644 if (ext == NULL) {
David Benjamine14ff062016-08-09 16:21:24 -04003645 continue;
3646 }
3647
David Benjamin8c880a22016-12-03 02:20:34 -05003648 hs->extensions.received |= (1u << ext_index);
David Benjamine14ff062016-08-09 16:21:24 -04003649 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003650 if (!ext->parse_clienthello(hs, &alert, &extension)) {
David Benjamine14ff062016-08-09 16:21:24 -04003651 *out_alert = alert;
3652 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003653 ERR_add_error_dataf("extension %u", (unsigned)type);
David Benjamin861abcc2018-07-14 17:40:26 -04003654 return false;
Adam Langley614c66a2015-06-12 15:26:58 -07003655 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003656 }
Adam Langley75712922014-10-10 16:23:43 -07003657
David Benjamin1deb41b2016-08-09 19:36:38 -04003658 for (size_t i = 0; i < kNumExtensions; i++) {
David Benjamin8c880a22016-12-03 02:20:34 -05003659 if (hs->extensions.received & (1u << i)) {
David Benjamin1deb41b2016-08-09 19:36:38 -04003660 continue;
3661 }
3662
3663 CBS *contents = NULL, fake_contents;
3664 static const uint8_t kFakeRenegotiateExtension[] = {0};
3665 if (kExtensions[i].value == TLSEXT_TYPE_renegotiate &&
3666 ssl_client_cipher_list_contains_cipher(client_hello,
3667 SSL3_CK_SCSV & 0xffff)) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003668 // The renegotiation SCSV was received so pretend that we received a
3669 // renegotiation extension.
David Benjamin1deb41b2016-08-09 19:36:38 -04003670 CBS_init(&fake_contents, kFakeRenegotiateExtension,
3671 sizeof(kFakeRenegotiateExtension));
3672 contents = &fake_contents;
David Benjamin8c880a22016-12-03 02:20:34 -05003673 hs->extensions.received |= (1u << i);
David Benjamin1deb41b2016-08-09 19:36:38 -04003674 }
3675
David Benjaminc11ea9422017-08-29 16:33:21 -04003676 // Extension wasn't observed so call the callback with a NULL
3677 // parameter.
David Benjamin1deb41b2016-08-09 19:36:38 -04003678 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003679 if (!kExtensions[i].parse_clienthello(hs, &alert, contents)) {
David Benjamin1deb41b2016-08-09 19:36:38 -04003680 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003681 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
David Benjamin1deb41b2016-08-09 19:36:38 -04003682 *out_alert = alert;
David Benjamin861abcc2018-07-14 17:40:26 -04003683 return false;
Adam Langley614c66a2015-06-12 15:26:58 -07003684 }
3685 }
3686
David Benjamin861abcc2018-07-14 17:40:26 -04003687 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003688}
Adam Langley95c29f32014-06-20 12:00:00 -07003689
David Benjamin861abcc2018-07-14 17:40:26 -04003690bool ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs,
3691 const SSL_CLIENT_HELLO *client_hello) {
David Benjamin8c880a22016-12-03 02:20:34 -05003692 SSL *const ssl = hs->ssl;
Adam Langleyc68e5b92017-02-08 13:33:15 -08003693 int alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003694 if (!ssl_scan_clienthello_tlsext(hs, client_hello, &alert)) {
David Benjamind1e3ce12017-10-06 18:31:15 -04003695 ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
David Benjamin861abcc2018-07-14 17:40:26 -04003696 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003697 }
Adam Langley95c29f32014-06-20 12:00:00 -07003698
David Benjamin861abcc2018-07-14 17:40:26 -04003699 if (!ssl_check_clienthello_tlsext(hs)) {
David Benjamin3570d732015-06-29 00:28:17 -04003700 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_TLSEXT);
David Benjamin861abcc2018-07-14 17:40:26 -04003701 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003702 }
Adam Langley95c29f32014-06-20 12:00:00 -07003703
David Benjamin861abcc2018-07-14 17:40:26 -04003704 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003705}
Adam Langley95c29f32014-06-20 12:00:00 -07003706
David Benjamine2cb4232021-06-23 18:14:22 -04003707static bool ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs,
David Benjamin861abcc2018-07-14 17:40:26 -04003708 int *out_alert) {
David Benjamine2cb4232021-06-23 18:14:22 -04003709 CBS extensions = *cbs;
3710 if (!tls1_check_duplicate_extensions(&extensions)) {
Steven Valdez143e8b32016-07-11 13:19:03 -04003711 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003712 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04003713 }
3714
3715 uint32_t received = 0;
3716 while (CBS_len(&extensions) != 0) {
3717 uint16_t type;
3718 CBS extension;
3719
David Benjaminc11ea9422017-08-29 16:33:21 -04003720 // Decode the next extension.
Steven Valdez143e8b32016-07-11 13:19:03 -04003721 if (!CBS_get_u16(&extensions, &type) ||
3722 !CBS_get_u16_length_prefixed(&extensions, &extension)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08003723 *out_alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003724 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003725 }
Adam Langley95c29f32014-06-20 12:00:00 -07003726
Steven Valdez143e8b32016-07-11 13:19:03 -04003727 unsigned ext_index;
3728 const struct tls_extension *const ext =
3729 tls_extension_find(&ext_index, type);
Adam Langley614c66a2015-06-12 15:26:58 -07003730
Steven Valdez143e8b32016-07-11 13:19:03 -04003731 if (ext == NULL) {
David Benjamin0a3e07a2018-07-09 16:28:22 -04003732 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
3733 ERR_add_error_dataf("extension %u", (unsigned)type);
3734 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
David Benjamin861abcc2018-07-14 17:40:26 -04003735 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04003736 }
Adam Langley33ad2b52015-07-20 17:43:53 -07003737
David Benjamina3d76d02017-07-14 19:36:07 -04003738 static_assert(kNumExtensions <= sizeof(hs->extensions.sent) * 8,
3739 "too many bits");
David Benjamin5db7c9b2017-01-24 16:17:03 -05003740
David Benjaminc59b9aa2018-07-16 21:34:03 -04003741 if (!(hs->extensions.sent & (1u << ext_index))) {
3742 // If the extension was never sent then it is illegal.
Steven Valdez143e8b32016-07-11 13:19:03 -04003743 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
3744 ERR_add_error_dataf("extension :%u", (unsigned)type);
David Benjamin0c40a962016-08-01 12:05:50 -04003745 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
David Benjamin861abcc2018-07-14 17:40:26 -04003746 return false;
Steven Valdez143e8b32016-07-11 13:19:03 -04003747 }
Adam Langley33ad2b52015-07-20 17:43:53 -07003748
Steven Valdez143e8b32016-07-11 13:19:03 -04003749 received |= (1u << ext_index);
Adam Langley09505632015-07-30 18:10:13 -07003750
Steven Valdez143e8b32016-07-11 13:19:03 -04003751 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003752 if (!ext->parse_serverhello(hs, &alert, &extension)) {
Steven Valdez143e8b32016-07-11 13:19:03 -04003753 OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003754 ERR_add_error_dataf("extension %u", (unsigned)type);
Steven Valdez143e8b32016-07-11 13:19:03 -04003755 *out_alert = alert;
David Benjamin861abcc2018-07-14 17:40:26 -04003756 return false;
Adam Langley614c66a2015-06-12 15:26:58 -07003757 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003758 }
Adam Langley95c29f32014-06-20 12:00:00 -07003759
David Benjamin54091232016-09-05 12:47:25 -04003760 for (size_t i = 0; i < kNumExtensions; i++) {
Adam Langley614c66a2015-06-12 15:26:58 -07003761 if (!(received & (1u << i))) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003762 // Extension wasn't observed so call the callback with a NULL
3763 // parameter.
Adam Langley614c66a2015-06-12 15:26:58 -07003764 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8c880a22016-12-03 02:20:34 -05003765 if (!kExtensions[i].parse_serverhello(hs, &alert, NULL)) {
Adam Langley33ad2b52015-07-20 17:43:53 -07003766 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -08003767 ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
Adam Langley614c66a2015-06-12 15:26:58 -07003768 *out_alert = alert;
David Benjamin861abcc2018-07-14 17:40:26 -04003769 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003770 }
Adam Langleyfcf25832014-12-18 17:42:32 -08003771 }
3772 }
Adam Langley95c29f32014-06-20 12:00:00 -07003773
David Benjamin861abcc2018-07-14 17:40:26 -04003774 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003775}
Adam Langley95c29f32014-06-20 12:00:00 -07003776
David Benjamin861abcc2018-07-14 17:40:26 -04003777static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) {
David Benjamin8c880a22016-12-03 02:20:34 -05003778 SSL *const ssl = hs->ssl;
Adam Langleyfcf25832014-12-18 17:42:32 -08003779 int ret = SSL_TLSEXT_ERR_NOACK;
3780 int al = SSL_AD_UNRECOGNIZED_NAME;
David Benjamin46853762018-07-03 14:01:26 -04003781 if (ssl->ctx->servername_callback != 0) {
3782 ret = ssl->ctx->servername_callback(ssl, &al, ssl->ctx->servername_arg);
3783 } else if (ssl->session_ctx->servername_callback != 0) {
3784 ret = ssl->session_ctx->servername_callback(
3785 ssl, &al, ssl->session_ctx->servername_arg);
Adam Langleyfcf25832014-12-18 17:42:32 -08003786 }
Adam Langley95c29f32014-06-20 12:00:00 -07003787
Adam Langleyfcf25832014-12-18 17:42:32 -08003788 switch (ret) {
3789 case SSL_TLSEXT_ERR_ALERT_FATAL:
David Benjamind1e3ce12017-10-06 18:31:15 -04003790 ssl_send_alert(ssl, SSL3_AL_FATAL, al);
David Benjamin861abcc2018-07-14 17:40:26 -04003791 return false;
Adam Langley95c29f32014-06-20 12:00:00 -07003792
Adam Langleyfcf25832014-12-18 17:42:32 -08003793 case SSL_TLSEXT_ERR_NOACK:
David Benjaminfd45ee72017-08-31 14:49:09 -04003794 hs->should_ack_sni = false;
David Benjamin861abcc2018-07-14 17:40:26 -04003795 return true;
Adam Langley95c29f32014-06-20 12:00:00 -07003796
Adam Langleyfcf25832014-12-18 17:42:32 -08003797 default:
David Benjamin096ded92024-07-16 14:48:02 -04003798 hs->should_ack_sni = ssl->s3->hostname != nullptr;
David Benjamin861abcc2018-07-14 17:40:26 -04003799 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003800 }
3801}
Adam Langleyed8270a2014-09-02 13:52:56 -07003802
Steven Valdez51607f12020-08-05 10:46:05 -04003803static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs) {
3804 SSL *const ssl = hs->ssl;
3805 // ALPS and ALPN have a dependency between each other, so we defer checking
3806 // consistency to after the callbacks run.
3807 if (hs->new_session != nullptr && hs->new_session->has_application_settings) {
3808 // ALPN must be negotiated.
3809 if (ssl->s3->alpn_selected.empty()) {
3810 OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_ALPS_WITHOUT_ALPN);
3811 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
3812 return false;
3813 }
3814
3815 // The negotiated protocol must be one of the ones we advertised for ALPS.
3816 Span<const uint8_t> settings;
3817 if (!ssl_get_local_application_settings(hs, &settings,
3818 ssl->s3->alpn_selected)) {
3819 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
3820 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
3821 return false;
3822 }
3823
3824 if (!hs->new_session->local_application_settings.CopyFrom(settings)) {
3825 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
3826 return false;
3827 }
3828 }
3829
3830 return true;
3831}
3832
David Benjamine2cb4232021-06-23 18:14:22 -04003833bool ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs) {
David Benjamin8c880a22016-12-03 02:20:34 -05003834 SSL *const ssl = hs->ssl;
Adam Langleyc68e5b92017-02-08 13:33:15 -08003835 int alert = SSL_AD_DECODE_ERROR;
David Benjamin861abcc2018-07-14 17:40:26 -04003836 if (!ssl_scan_serverhello_tlsext(hs, cbs, &alert)) {
David Benjamind1e3ce12017-10-06 18:31:15 -04003837 ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
David Benjamin861abcc2018-07-14 17:40:26 -04003838 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08003839 }
3840
Steven Valdez51607f12020-08-05 10:46:05 -04003841 if (!ssl_check_serverhello_tlsext(hs)) {
3842 return false;
3843 }
3844
David Benjamin861abcc2018-07-14 17:40:26 -04003845 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08003846}
Adam Langley95c29f32014-06-20 12:00:00 -07003847
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003848static enum ssl_ticket_aead_result_t decrypt_ticket_with_cipher_ctx(
David Benjamin28655672018-07-18 23:23:25 -04003849 Array<uint8_t> *out, EVP_CIPHER_CTX *cipher_ctx, HMAC_CTX *hmac_ctx,
3850 Span<const uint8_t> ticket) {
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003851 size_t iv_len = EVP_CIPHER_CTX_iv_length(cipher_ctx);
Adam Langleyfcf25832014-12-18 17:42:32 -08003852
David Benjaminc11ea9422017-08-29 16:33:21 -04003853 // Check the MAC at the end of the ticket.
David Benjamine3aa1d92015-06-16 15:34:50 -04003854 uint8_t mac[EVP_MAX_MD_SIZE];
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003855 size_t mac_len = HMAC_size(hmac_ctx);
David Benjamin28655672018-07-18 23:23:25 -04003856 if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + iv_len + 1 + mac_len) {
David Benjaminc11ea9422017-08-29 16:33:21 -04003857 // The ticket must be large enough for key name, IV, data, and MAC.
David Benjamin81678aa2017-07-12 22:43:42 -04003858 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003859 }
David Benjamin28655672018-07-18 23:23:25 -04003860 // Split the ticket into the ticket and the MAC.
David Benjamin006f20a2021-06-22 23:00:49 -04003861 auto ticket_mac = ticket.last(mac_len);
3862 ticket = ticket.first(ticket.size() - mac_len);
David Benjamin28655672018-07-18 23:23:25 -04003863 HMAC_Update(hmac_ctx, ticket.data(), ticket.size());
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003864 HMAC_Final(hmac_ctx, mac, NULL);
David Benjamin28655672018-07-18 23:23:25 -04003865 assert(mac_len == ticket_mac.size());
3866 bool mac_ok = CRYPTO_memcmp(mac, ticket_mac.data(), mac_len) == 0;
David Benjaminfbc45d72016-09-22 01:21:24 -04003867#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin861abcc2018-07-14 17:40:26 -04003868 mac_ok = true;
David Benjaminfbc45d72016-09-22 01:21:24 -04003869#endif
3870 if (!mac_ok) {
David Benjamin81678aa2017-07-12 22:43:42 -04003871 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003872 }
3873
David Benjaminc11ea9422017-08-29 16:33:21 -04003874 // Decrypt the session data.
David Benjamin28655672018-07-18 23:23:25 -04003875 auto ciphertext = ticket.subspan(SSL_TICKET_KEY_NAME_LEN + iv_len);
3876 Array<uint8_t> plaintext;
3877#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
3878 if (!plaintext.CopyFrom(ciphertext)) {
David Benjamin81678aa2017-07-12 22:43:42 -04003879 return ssl_ticket_aead_error;
Adam Langleyfcf25832014-12-18 17:42:32 -08003880 }
David Benjaminfbc45d72016-09-22 01:21:24 -04003881#else
David Benjamin28655672018-07-18 23:23:25 -04003882 if (ciphertext.size() >= INT_MAX) {
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 if (!plaintext.Init(ciphertext.size())) {
3886 return ssl_ticket_aead_error;
3887 }
David Benjamine3aa1d92015-06-16 15:34:50 -04003888 int len1, len2;
David Benjamin28655672018-07-18 23:23:25 -04003889 if (!EVP_DecryptUpdate(cipher_ctx, plaintext.data(), &len1, ciphertext.data(),
3890 (int)ciphertext.size()) ||
3891 !EVP_DecryptFinal_ex(cipher_ctx, plaintext.data() + len1, &len2)) {
Adam Langley4c341d02017-03-08 19:33:21 -08003892 ERR_clear_error();
David Benjamin81678aa2017-07-12 22:43:42 -04003893 return ssl_ticket_aead_ignore_ticket;
Adam Langleyfcf25832014-12-18 17:42:32 -08003894 }
David Benjamin28655672018-07-18 23:23:25 -04003895 plaintext.Shrink(static_cast<size_t>(len1) + len2);
David Benjaminfbc45d72016-09-22 01:21:24 -04003896#endif
Adam Langleyfcf25832014-12-18 17:42:32 -08003897
David Benjamin28655672018-07-18 23:23:25 -04003898 *out = std::move(plaintext);
David Benjamin81678aa2017-07-12 22:43:42 -04003899 return ssl_ticket_aead_success;
Adam Langley4c341d02017-03-08 19:33:21 -08003900}
3901
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003902static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_cb(
David Benjamin28655672018-07-18 23:23:25 -04003903 SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket,
3904 Span<const uint8_t> ticket) {
3905 assert(ticket.size() >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003906 ScopedEVP_CIPHER_CTX cipher_ctx;
3907 ScopedHMAC_CTX hmac_ctx;
David Benjamin28655672018-07-18 23:23:25 -04003908 auto name = ticket.subspan(0, SSL_TICKET_KEY_NAME_LEN);
3909 // The actual IV is shorter, but the length is determined by the callback's
3910 // chosen cipher. Instead we pass in |EVP_MAX_IV_LENGTH| worth of IV to ensure
3911 // the callback has enough.
3912 auto iv = ticket.subspan(SSL_TICKET_KEY_NAME_LEN, EVP_MAX_IV_LENGTH);
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003913 int cb_ret = hs->ssl->session_ctx->ticket_key_cb(
David Benjamin28655672018-07-18 23:23:25 -04003914 hs->ssl, const_cast<uint8_t *>(name.data()),
3915 const_cast<uint8_t *>(iv.data()), cipher_ctx.get(), hmac_ctx.get(),
3916 0 /* decrypt */);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003917 if (cb_ret < 0) {
3918 return ssl_ticket_aead_error;
3919 } else if (cb_ret == 0) {
3920 return ssl_ticket_aead_ignore_ticket;
3921 } else if (cb_ret == 2) {
David Benjaminfd45ee72017-08-31 14:49:09 -04003922 *out_renew_ticket = true;
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003923 } else {
3924 assert(cb_ret == 1);
3925 }
David Benjamin28655672018-07-18 23:23:25 -04003926 return decrypt_ticket_with_cipher_ctx(out, cipher_ctx.get(), hmac_ctx.get(),
3927 ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003928}
3929
3930static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_ticket_keys(
David Benjamin28655672018-07-18 23:23:25 -04003931 SSL_HANDSHAKE *hs, Array<uint8_t> *out, Span<const uint8_t> ticket) {
3932 assert(ticket.size() >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH);
David Benjamin50596f82018-07-02 19:47:27 -04003933 SSL_CTX *ctx = hs->ssl->session_ctx.get();
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003934
David Benjaminc11ea9422017-08-29 16:33:21 -04003935 // Rotate the ticket key if necessary.
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003936 if (!ssl_ctx_rotate_ticket_encryption_key(ctx)) {
3937 return ssl_ticket_aead_error;
3938 }
3939
David Benjamin28655672018-07-18 23:23:25 -04003940 const EVP_CIPHER *cipher = EVP_aes_128_cbc();
3941 auto name = ticket.subspan(0, SSL_TICKET_KEY_NAME_LEN);
3942 auto iv =
3943 ticket.subspan(SSL_TICKET_KEY_NAME_LEN, EVP_CIPHER_iv_length(cipher));
3944
David Benjaminc11ea9422017-08-29 16:33:21 -04003945 // Pick the matching ticket key and decrypt.
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003946 ScopedEVP_CIPHER_CTX cipher_ctx;
3947 ScopedHMAC_CTX hmac_ctx;
3948 {
3949 MutexReadLock lock(&ctx->lock);
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003950 const TicketKey *key;
David Benjamin28655672018-07-18 23:23:25 -04003951 if (ctx->ticket_key_current && name == ctx->ticket_key_current->name) {
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003952 key = ctx->ticket_key_current.get();
David Benjamin28655672018-07-18 23:23:25 -04003953 } else if (ctx->ticket_key_prev && name == ctx->ticket_key_prev->name) {
David Benjamin7bb0fbf2018-07-03 13:55:42 -04003954 key = ctx->ticket_key_prev.get();
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003955 } else {
3956 return ssl_ticket_aead_ignore_ticket;
3957 }
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003958 if (!HMAC_Init_ex(hmac_ctx.get(), key->hmac_key, sizeof(key->hmac_key),
3959 tlsext_tick_md(), NULL) ||
David Benjamin28655672018-07-18 23:23:25 -04003960 !EVP_DecryptInit_ex(cipher_ctx.get(), cipher, NULL,
3961 key->aes_key, iv.data())) {
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003962 return ssl_ticket_aead_error;
3963 }
3964 }
David Benjamin28655672018-07-18 23:23:25 -04003965 return decrypt_ticket_with_cipher_ctx(out, cipher_ctx.get(), hmac_ctx.get(),
3966 ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07003967}
3968
Adam Langley4c341d02017-03-08 19:33:21 -08003969static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_method(
David Benjamin28655672018-07-18 23:23:25 -04003970 SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket,
3971 Span<const uint8_t> ticket) {
3972 Array<uint8_t> plaintext;
3973 if (!plaintext.Init(ticket.size())) {
Adam Langley4c341d02017-03-08 19:33:21 -08003974 return ssl_ticket_aead_error;
3975 }
3976
3977 size_t plaintext_len;
3978 const enum ssl_ticket_aead_result_t result =
David Benjamin98472cb2018-05-02 16:05:36 -04003979 hs->ssl->session_ctx->ticket_aead_method->open(
David Benjamin28655672018-07-18 23:23:25 -04003980 hs->ssl, plaintext.data(), &plaintext_len, ticket.size(),
3981 ticket.data(), ticket.size());
3982 if (result != ssl_ticket_aead_success) {
3983 return result;
Adam Langley4c341d02017-03-08 19:33:21 -08003984 }
3985
David Benjamin28655672018-07-18 23:23:25 -04003986 plaintext.Shrink(plaintext_len);
3987 *out = std::move(plaintext);
3988 return ssl_ticket_aead_success;
Adam Langley4c341d02017-03-08 19:33:21 -08003989}
3990
3991enum ssl_ticket_aead_result_t ssl_process_ticket(
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07003992 SSL_HANDSHAKE *hs, UniquePtr<SSL_SESSION> *out_session,
David Benjamin28655672018-07-18 23:23:25 -04003993 bool *out_renew_ticket, Span<const uint8_t> ticket,
3994 Span<const uint8_t> session_id) {
David Benjaminb571e772021-03-25 19:42:16 -04003995 SSL *const ssl = hs->ssl;
David Benjaminfd45ee72017-08-31 14:49:09 -04003996 *out_renew_ticket = false;
David Benjamin37af90f2017-07-29 01:42:16 -04003997 out_session->reset();
Adam Langley4c341d02017-03-08 19:33:21 -08003998
Matthew Braithwaiteb7bc80a2018-04-13 15:51:30 -07003999 if ((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) ||
David Benjamin28655672018-07-18 23:23:25 -04004000 session_id.size() > SSL_MAX_SSL_SESSION_ID_LENGTH) {
Adam Langley4c341d02017-03-08 19:33:21 -08004001 return ssl_ticket_aead_ignore_ticket;
4002 }
4003
David Benjaminb571e772021-03-25 19:42:16 -04004004 // Tickets in TLS 1.3 are tied into pre-shared keys (PSKs), unlike in TLS 1.2
4005 // where that concept doesn't exist. The |decrypted_psk| and |ignore_psk|
4006 // hints only apply to PSKs. We check the version to determine which this is.
4007 const bool is_psk = ssl_protocol_version(ssl) >= TLS1_3_VERSION;
4008
David Benjamin28655672018-07-18 23:23:25 -04004009 Array<uint8_t> plaintext;
Adam Langley4c341d02017-03-08 19:33:21 -08004010 enum ssl_ticket_aead_result_t result;
David Benjaminb571e772021-03-25 19:42:16 -04004011 SSL_HANDSHAKE_HINTS *const hints = hs->hints.get();
4012 if (is_psk && hints && !hs->hints_requested &&
4013 !hints->decrypted_psk.empty()) {
4014 result = plaintext.CopyFrom(hints->decrypted_psk) ? ssl_ticket_aead_success
4015 : ssl_ticket_aead_error;
4016 } else if (is_psk && hints && !hs->hints_requested && hints->ignore_psk) {
4017 result = ssl_ticket_aead_ignore_ticket;
David Benjaminadaa3222022-08-02 17:10:53 -07004018 } else if (!is_psk && hints && !hs->hints_requested &&
4019 !hints->decrypted_ticket.empty()) {
4020 if (plaintext.CopyFrom(hints->decrypted_ticket)) {
4021 result = ssl_ticket_aead_success;
4022 *out_renew_ticket = hints->renew_ticket;
4023 } else {
4024 result = ssl_ticket_aead_error;
4025 }
4026 } else if (!is_psk && hints && !hs->hints_requested && hints->ignore_ticket) {
4027 result = ssl_ticket_aead_ignore_ticket;
David Benjaminb571e772021-03-25 19:42:16 -04004028 } else if (ssl->session_ctx->ticket_aead_method != NULL) {
David Benjamin28655672018-07-18 23:23:25 -04004029 result = ssl_decrypt_ticket_with_method(hs, &plaintext, out_renew_ticket,
4030 ticket);
Adam Langley4c341d02017-03-08 19:33:21 -08004031 } else {
David Benjamin7bb0fbf2018-07-03 13:55:42 -04004032 // Ensure there is room for the key name and the largest IV |ticket_key_cb|
4033 // may try to consume. The real limit may be lower, but the maximum IV
4034 // length should be well under the minimum size for the session material and
4035 // HMAC.
David Benjamin28655672018-07-18 23:23:25 -04004036 if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) {
David Benjaminb571e772021-03-25 19:42:16 -04004037 result = ssl_ticket_aead_ignore_ticket;
4038 } else if (ssl->session_ctx->ticket_key_cb != NULL) {
David Benjamin28655672018-07-18 23:23:25 -04004039 result =
4040 ssl_decrypt_ticket_with_cb(hs, &plaintext, out_renew_ticket, ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07004041 } else {
David Benjamin28655672018-07-18 23:23:25 -04004042 result = ssl_decrypt_ticket_with_ticket_keys(hs, &plaintext, ticket);
Martin Kreichgauer72912d22017-08-04 12:06:43 -07004043 }
Adam Langley4c341d02017-03-08 19:33:21 -08004044 }
4045
David Benjaminadaa3222022-08-02 17:10:53 -07004046 if (hints && hs->hints_requested) {
David Benjaminb571e772021-03-25 19:42:16 -04004047 if (result == ssl_ticket_aead_ignore_ticket) {
David Benjaminadaa3222022-08-02 17:10:53 -07004048 if (is_psk) {
4049 hints->ignore_psk = true;
4050 } else {
4051 hints->ignore_ticket = true;
4052 }
4053 } else if (result == ssl_ticket_aead_success) {
4054 if (is_psk) {
4055 if (!hints->decrypted_psk.CopyFrom(plaintext)) {
4056 return ssl_ticket_aead_error;
4057 }
4058 } else {
4059 if (!hints->decrypted_ticket.CopyFrom(plaintext)) {
4060 return ssl_ticket_aead_error;
4061 }
4062 hints->renew_ticket = *out_renew_ticket;
4063 }
David Benjaminb571e772021-03-25 19:42:16 -04004064 }
4065 }
4066
Adam Langley4c341d02017-03-08 19:33:21 -08004067 if (result != ssl_ticket_aead_success) {
4068 return result;
4069 }
4070
David Benjaminc11ea9422017-08-29 16:33:21 -04004071 // Decode the session.
David Benjamin28655672018-07-18 23:23:25 -04004072 UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(
David Benjaminb571e772021-03-25 19:42:16 -04004073 plaintext.data(), plaintext.size(), ssl->ctx.get()));
David Benjamin37af90f2017-07-29 01:42:16 -04004074 if (!session) {
David Benjaminc11ea9422017-08-29 16:33:21 -04004075 ERR_clear_error(); // Don't leave an error on the queue.
Adam Langley4c341d02017-03-08 19:33:21 -08004076 return ssl_ticket_aead_ignore_ticket;
David Benjamine3aa1d92015-06-16 15:34:50 -04004077 }
4078
Adam Langley47cefed2021-05-26 13:36:40 -07004079 // Envoy's tests expect the session to have a session ID that matches the
4080 // placeholder used by the client. It's unclear whether this is a good idea,
4081 // but we maintain it for now.
4082 SHA256(ticket.data(), ticket.size(), session->session_id);
4083 // Other consumers may expect a non-empty session ID to indicate resumption.
4084 session->session_id_length = SHA256_DIGEST_LENGTH;
David Benjamine3aa1d92015-06-16 15:34:50 -04004085
David Benjamin37af90f2017-07-29 01:42:16 -04004086 *out_session = std::move(session);
Adam Langley4c341d02017-03-08 19:33:21 -08004087 return ssl_ticket_aead_success;
Adam Langleyfcf25832014-12-18 17:42:32 -08004088}
Adam Langley95c29f32014-06-20 12:00:00 -07004089
David Benjamin610cdbb2018-01-22 19:08:38 -05004090bool tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) {
David Benjaminc11ea9422017-08-29 16:33:21 -04004091 // Extension ignored for inappropriate versions
David Benjamind1e3ce12017-10-06 18:31:15 -04004092 if (ssl_protocol_version(hs->ssl) < TLS1_2_VERSION) {
David Benjamin610cdbb2018-01-22 19:08:38 -05004093 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004094 }
David Benjamincd996942014-07-20 16:23:51 -04004095
David Benjamin602f4662018-12-07 12:06:22 -06004096 // In all contexts, the signature algorithms list may not be empty. (It may be
4097 // omitted by clients in TLS 1.2, but then the entire extension is omitted.)
4098 return CBS_len(in_sigalgs) != 0 &&
4099 parse_u16_array(in_sigalgs, &hs->peer_sigalgs);
Adam Langleyfcf25832014-12-18 17:42:32 -08004100}
David Benjaminec2f27d2014-11-13 19:17:25 -05004101
David Benjamin610cdbb2018-01-22 19:08:38 -05004102bool tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey) {
David Benjamina3651382017-04-20 17:49:36 -04004103 switch (EVP_PKEY_id(pkey)) {
4104 case EVP_PKEY_RSA:
4105 *out = SSL_SIGN_RSA_PKCS1_MD5_SHA1;
David Benjamin610cdbb2018-01-22 19:08:38 -05004106 return true;
David Benjamina3651382017-04-20 17:49:36 -04004107 case EVP_PKEY_EC:
4108 *out = SSL_SIGN_ECDSA_SHA1;
David Benjamin610cdbb2018-01-22 19:08:38 -05004109 return true;
David Benjamina3651382017-04-20 17:49:36 -04004110 default:
David Benjamin610cdbb2018-01-22 19:08:38 -05004111 return false;
David Benjamina3651382017-04-20 17:49:36 -04004112 }
4113}
4114
David Benjamin91a3f262024-02-10 11:08:08 -05004115bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs,
4116 const SSL_CREDENTIAL *cred,
4117 uint16_t *out) {
David Benjaminf3c8f8d2016-11-17 17:20:47 +09004118 SSL *const ssl = hs->ssl;
David Benjamin91a3f262024-02-10 11:08:08 -05004119 if (!cred->UsesPrivateKey()) {
4120 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
4121 return false;
4122 }
David Benjaminec2f27d2014-11-13 19:17:25 -05004123
David Benjaminc11ea9422017-08-29 16:33:21 -04004124 // Before TLS 1.2, the signature algorithm isn't negotiated as part of the
4125 // handshake.
David Benjamin91a3f262024-02-10 11:08:08 -05004126 uint16_t version = ssl_protocol_version(ssl);
4127 if (version < TLS1_2_VERSION) {
4128 if (!tls1_get_legacy_signature_algorithm(out, cred->pubkey.get())) {
David Benjamina3651382017-04-20 17:49:36 -04004129 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
David Benjamin610cdbb2018-01-22 19:08:38 -05004130 return false;
Steven Valdezf0451ca2016-06-29 13:16:27 -04004131 }
David Benjamin610cdbb2018-01-22 19:08:38 -05004132 return true;
Steven Valdezf0451ca2016-06-29 13:16:27 -04004133 }
4134
David Benjamin91a3f262024-02-10 11:08:08 -05004135 Span<const uint16_t> peer_sigalgs;
4136 if (cred->type == SSLCredentialType::kDelegated) {
David Benjaminefad2bf2024-02-23 14:37:10 -05004137 peer_sigalgs = hs->peer_delegated_credential_sigalgs;
4138 } else {
David Benjamin91a3f262024-02-10 11:08:08 -05004139 peer_sigalgs = hs->peer_sigalgs;
4140 if (peer_sigalgs.empty() && version == TLS1_2_VERSION) {
4141 // If the client didn't specify any signature_algorithms extension, it is
4142 // interpreted as SHA-1. See
4143 // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
4144 static const uint16_t kTLS12Default[] = {SSL_SIGN_RSA_PKCS1_SHA1,
4145 SSL_SIGN_ECDSA_SHA1};
4146 peer_sigalgs = kTLS12Default;
4147 }
Steven Valdez0d62f262015-09-04 12:41:04 -04004148 }
4149
David Benjamin91a3f262024-02-10 11:08:08 -05004150 Span<const uint16_t> sigalgs = cred->sigalgs.empty()
4151 ? MakeConstSpan(kSignSignatureAlgorithms)
4152 : cred->sigalgs;
David Benjaminb1cf48e2017-09-21 11:37:46 -04004153 for (uint16_t sigalg : sigalgs) {
David Benjamin66d274d2021-02-25 01:37:16 -05004154 if (!ssl_pkey_supports_algorithm(ssl, cred->pubkey.get(), sigalg,
4155 /*is_verify=*/false)) {
David Benjamin1fb125c2016-07-08 18:52:12 -07004156 continue;
4157 }
4158
David Benjamin91a3f262024-02-10 11:08:08 -05004159 if (std::find(peer_sigalgs.begin(), peer_sigalgs.end(), sigalg) !=
4160 peer_sigalgs.end()) {
4161 *out = sigalg;
4162 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004163 }
Adam Langleyfcf25832014-12-18 17:42:32 -08004164 }
Adam Langley95c29f32014-06-20 12:00:00 -07004165
David Benjaminea9a0d52016-07-08 15:52:59 -07004166 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
David Benjamin610cdbb2018-01-22 19:08:38 -05004167 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08004168}
Adam Langley95c29f32014-06-20 12:00:00 -07004169
David Benjamin861abcc2018-07-14 17:40:26 -04004170bool tls1_verify_channel_id(SSL_HANDSHAKE *hs, const SSLMessage &msg) {
Steven Valdez908ac192017-01-12 13:17:07 -05004171 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -04004172 // A Channel ID handshake message is structured to contain multiple
4173 // extensions, but the only one that can be present is Channel ID.
David Benjamin7934f082017-08-01 16:32:25 -04004174 uint16_t extension_type;
4175 CBS channel_id = msg.body, extension;
Nick Harper60a85cb2016-09-23 16:25:11 -07004176 if (!CBS_get_u16(&channel_id, &extension_type) ||
4177 !CBS_get_u16_length_prefixed(&channel_id, &extension) ||
4178 CBS_len(&channel_id) != 0 ||
4179 extension_type != TLSEXT_TYPE_channel_id ||
4180 CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
4181 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
David Benjamind1e3ce12017-10-06 18:31:15 -04004182 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04004183 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004184 }
4185
David Benjamin70be0122023-02-13 19:05:19 -05004186 const EC_GROUP *p256 = EC_group_p256();
David Benjamin86e95b82017-07-18 16:34:25 -04004187 UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
4188 UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
David Benjamin81678aa2017-07-12 22:43:42 -04004189 if (!sig || !x || !y) {
David Benjamin861abcc2018-07-14 17:40:26 -04004190 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004191 }
4192
4193 const uint8_t *p = CBS_data(&extension);
David Benjamin81678aa2017-07-12 22:43:42 -04004194 if (BN_bin2bn(p + 0, 32, x.get()) == NULL ||
4195 BN_bin2bn(p + 32, 32, y.get()) == NULL ||
4196 BN_bin2bn(p + 64, 32, sig->r) == NULL ||
4197 BN_bin2bn(p + 96, 32, sig->s) == NULL) {
David Benjamin861abcc2018-07-14 17:40:26 -04004198 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004199 }
4200
David Benjamin86e95b82017-07-18 16:34:25 -04004201 UniquePtr<EC_KEY> key(EC_KEY_new());
David Benjamin70be0122023-02-13 19:05:19 -05004202 UniquePtr<EC_POINT> point(EC_POINT_new(p256));
David Benjamin81678aa2017-07-12 22:43:42 -04004203 if (!key || !point ||
David Benjamin70be0122023-02-13 19:05:19 -05004204 !EC_POINT_set_affine_coordinates_GFp(p256, point.get(), x.get(), y.get(),
4205 nullptr) ||
4206 !EC_KEY_set_group(key.get(), p256) ||
David Benjamin81678aa2017-07-12 22:43:42 -04004207 !EC_KEY_set_public_key(key.get(), point.get())) {
David Benjamin861abcc2018-07-14 17:40:26 -04004208 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004209 }
4210
4211 uint8_t digest[EVP_MAX_MD_SIZE];
4212 size_t digest_len;
Steven Valdez908ac192017-01-12 13:17:07 -05004213 if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004214 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004215 }
4216
David Benjamin861abcc2018-07-14 17:40:26 -04004217 bool sig_ok = ECDSA_do_verify(digest, digest_len, sig.get(), key.get());
Nick Harper60a85cb2016-09-23 16:25:11 -07004218#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin861abcc2018-07-14 17:40:26 -04004219 sig_ok = true;
David Benjamind90b8032017-12-18 16:47:51 -05004220 ERR_clear_error();
Nick Harper60a85cb2016-09-23 16:25:11 -07004221#endif
4222 if (!sig_ok) {
4223 OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
David Benjamind1e3ce12017-10-06 18:31:15 -04004224 ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04004225 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004226 }
4227
David Benjamin46853762018-07-03 14:01:26 -04004228 OPENSSL_memcpy(ssl->s3->channel_id, p, 64);
David Benjamin8acec002021-05-19 13:03:34 -04004229 ssl->s3->channel_id_valid = true;
David Benjamin861abcc2018-07-14 17:40:26 -04004230 return true;
Nick Harper60a85cb2016-09-23 16:25:11 -07004231}
4232
David Benjaminf1db1a32017-10-27 01:12:34 -04004233bool tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb) {
Nick Harper60a85cb2016-09-23 16:25:11 -07004234 uint8_t digest[EVP_MAX_MD_SIZE];
4235 size_t digest_len;
Steven Valdez908ac192017-01-12 13:17:07 -05004236 if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
David Benjaminf1db1a32017-10-27 01:12:34 -04004237 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004238 }
4239
David Benjamin46853762018-07-03 14:01:26 -04004240 EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(hs->config->channel_id_private.get());
David Benjaminf1db1a32017-10-27 01:12:34 -04004241 if (ec_key == nullptr) {
Nick Harper60a85cb2016-09-23 16:25:11 -07004242 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjaminf1db1a32017-10-27 01:12:34 -04004243 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004244 }
4245
David Benjaminf1db1a32017-10-27 01:12:34 -04004246 UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
4247 if (!x || !y ||
Nick Harper60a85cb2016-09-23 16:25:11 -07004248 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
4249 EC_KEY_get0_public_key(ec_key),
David Benjaminf1db1a32017-10-27 01:12:34 -04004250 x.get(), y.get(), nullptr)) {
4251 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004252 }
4253
David Benjaminf1db1a32017-10-27 01:12:34 -04004254 UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, ec_key));
4255 if (!sig) {
4256 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004257 }
4258
4259 CBB child;
4260 if (!CBB_add_u16(cbb, TLSEXT_TYPE_channel_id) ||
4261 !CBB_add_u16_length_prefixed(cbb, &child) ||
David Benjaminf1db1a32017-10-27 01:12:34 -04004262 !BN_bn2cbb_padded(&child, 32, x.get()) ||
4263 !BN_bn2cbb_padded(&child, 32, y.get()) ||
Nick Harper60a85cb2016-09-23 16:25:11 -07004264 !BN_bn2cbb_padded(&child, 32, sig->r) ||
4265 !BN_bn2cbb_padded(&child, 32, sig->s) ||
4266 !CBB_flush(cbb)) {
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 return true;
Nick Harper60a85cb2016-09-23 16:25:11 -07004271}
4272
David Benjamin861abcc2018-07-14 17:40:26 -04004273bool tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len) {
Steven Valdez908ac192017-01-12 13:17:07 -05004274 SSL *const ssl = hs->ssl;
David Benjamind1e3ce12017-10-06 18:31:15 -04004275 if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
David Benjamin75a1f232017-10-11 17:19:19 -04004276 Array<uint8_t> msg;
4277 if (!tls13_get_cert_verify_signature_input(hs, &msg,
Nick Harper60a85cb2016-09-23 16:25:11 -07004278 ssl_cert_verify_channel_id)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004279 return false;
Nick Harper60a85cb2016-09-23 16:25:11 -07004280 }
David Benjamin75a1f232017-10-11 17:19:19 -04004281 SHA256(msg.data(), msg.size(), out);
Nick Harper60a85cb2016-09-23 16:25:11 -07004282 *out_len = SHA256_DIGEST_LENGTH;
David Benjamin861abcc2018-07-14 17:40:26 -04004283 return true;
Nick Harper60a85cb2016-09-23 16:25:11 -07004284 }
4285
Nick Harper95594012016-10-20 14:07:13 -07004286 SHA256_CTX ctx;
Adam Langleyfcf25832014-12-18 17:42:32 -08004287
Nick Harper95594012016-10-20 14:07:13 -07004288 SHA256_Init(&ctx);
David Benjamind6a4ae92015-08-06 11:10:51 -04004289 static const char kClientIDMagic[] = "TLS Channel ID signature";
Nick Harper95594012016-10-20 14:07:13 -07004290 SHA256_Update(&ctx, kClientIDMagic, sizeof(kClientIDMagic));
David Benjamind6a4ae92015-08-06 11:10:51 -04004291
Steven Valdez87eab492016-06-27 16:34:59 -04004292 if (ssl->session != NULL) {
David Benjamind6a4ae92015-08-06 11:10:51 -04004293 static const char kResumptionMagic[] = "Resumption";
Nick Harper95594012016-10-20 14:07:13 -07004294 SHA256_Update(&ctx, kResumptionMagic, sizeof(kResumptionMagic));
David Benjamind6a4ae92015-08-06 11:10:51 -04004295 if (ssl->session->original_handshake_hash_len == 0) {
4296 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin861abcc2018-07-14 17:40:26 -04004297 return false;
David Benjamind6a4ae92015-08-06 11:10:51 -04004298 }
Nick Harper95594012016-10-20 14:07:13 -07004299 SHA256_Update(&ctx, ssl->session->original_handshake_hash,
4300 ssl->session->original_handshake_hash_len);
David Benjamind6a4ae92015-08-06 11:10:51 -04004301 }
4302
Steven Valdez908ac192017-01-12 13:17:07 -05004303 uint8_t hs_hash[EVP_MAX_MD_SIZE];
4304 size_t hs_hash_len;
David Benjamin6dc8bf62017-07-19 16:38:21 -04004305 if (!hs->transcript.GetHash(hs_hash, &hs_hash_len)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004306 return false;
David Benjamind6a4ae92015-08-06 11:10:51 -04004307 }
Steven Valdez908ac192017-01-12 13:17:07 -05004308 SHA256_Update(&ctx, hs_hash, (size_t)hs_hash_len);
Nick Harper95594012016-10-20 14:07:13 -07004309 SHA256_Final(out, &ctx);
4310 *out_len = SHA256_DIGEST_LENGTH;
David Benjamin861abcc2018-07-14 17:40:26 -04004311 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004312}
Adam Langley1258b6a2014-06-20 12:00:00 -07004313
David Benjamin861abcc2018-07-14 17:40:26 -04004314bool tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) {
Steven Valdez908ac192017-01-12 13:17:07 -05004315 SSL *const ssl = hs->ssl;
David Benjaminc11ea9422017-08-29 16:33:21 -04004316 // This function should never be called for a resumed session because the
4317 // handshake hashes that we wish to record are for the original, full
4318 // handshake.
Steven Valdez87eab492016-06-27 16:34:59 -04004319 if (ssl->session != NULL) {
David Benjamin861abcc2018-07-14 17:40:26 -04004320 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08004321 }
Adam Langley1258b6a2014-06-20 12:00:00 -07004322
David Benjamina3d76d02017-07-14 19:36:07 -04004323 static_assert(
David Benjamin45738dd2017-02-09 20:01:26 -05004324 sizeof(hs->new_session->original_handshake_hash) == EVP_MAX_MD_SIZE,
David Benjamina3d76d02017-07-14 19:36:07 -04004325 "original_handshake_hash is too small");
Steven Valdez908ac192017-01-12 13:17:07 -05004326
4327 size_t digest_len;
David Benjamin6dc8bf62017-07-19 16:38:21 -04004328 if (!hs->transcript.GetHash(hs->new_session->original_handshake_hash,
4329 &digest_len)) {
David Benjamin861abcc2018-07-14 17:40:26 -04004330 return false;
Adam Langleyfcf25832014-12-18 17:42:32 -08004331 }
Adam Langley1258b6a2014-06-20 12:00:00 -07004332
David Benjamina3d76d02017-07-14 19:36:07 -04004333 static_assert(EVP_MAX_MD_SIZE <= 0xff,
4334 "EVP_MAX_MD_SIZE does not fit in uint8_t");
David Benjamin45738dd2017-02-09 20:01:26 -05004335 hs->new_session->original_handshake_hash_len = (uint8_t)digest_len;
Adam Langley1258b6a2014-06-20 12:00:00 -07004336
David Benjamin861abcc2018-07-14 17:40:26 -04004337 return true;
Adam Langleyfcf25832014-12-18 17:42:32 -08004338}
Nick Harper60a85cb2016-09-23 16:25:11 -07004339
David Benjamin861abcc2018-07-14 17:40:26 -04004340bool ssl_is_sct_list_valid(const CBS *contents) {
David Benjaminc11ea9422017-08-29 16:33:21 -04004341 // Shallow parse the SCT list for sanity. By the RFC
4342 // (https://tools.ietf.org/html/rfc6962#section-3.3) neither the list nor any
4343 // of the SCTs may be empty.
Adam Langleycfa08c32016-11-17 13:21:27 -08004344 CBS copy = *contents;
4345 CBS sct_list;
4346 if (!CBS_get_u16_length_prefixed(&copy, &sct_list) ||
4347 CBS_len(&copy) != 0 ||
4348 CBS_len(&sct_list) == 0) {
David Benjamin861abcc2018-07-14 17:40:26 -04004349 return false;
Adam Langleycfa08c32016-11-17 13:21:27 -08004350 }
4351
4352 while (CBS_len(&sct_list) > 0) {
4353 CBS sct;
4354 if (!CBS_get_u16_length_prefixed(&sct_list, &sct) ||
4355 CBS_len(&sct) == 0) {
David Benjamin861abcc2018-07-14 17:40:26 -04004356 return false;
Adam Langleycfa08c32016-11-17 13:21:27 -08004357 }
4358 }
4359
David Benjamin861abcc2018-07-14 17:40:26 -04004360 return true;
Adam Langleycfa08c32016-11-17 13:21:27 -08004361}
David Benjamin86e95b82017-07-18 16:34:25 -04004362
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -07004363BSSL_NAMESPACE_END
David Benjamin86e95b82017-07-18 16:34:25 -04004364
4365using namespace bssl;
4366
4367int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello,
4368 uint16_t extension_type,
4369 const uint8_t **out_data,
4370 size_t *out_len) {
4371 CBS cbs;
4372 if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) {
4373 return 0;
4374 }
4375
4376 *out_data = CBS_data(&cbs);
4377 *out_len = CBS_len(&cbs);
4378 return 1;
4379}