blob: 84463fa4ae388d2c6f2b330ea2afa1bc00018659 [file] [log] [blame]
Adam Langley09505632015-07-30 18:10:13 -07001/* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
David Benjamin86e95b82017-07-18 16:34:25 -040015#define BORINGSSL_INTERNAL_CXX_TYPES
16
David Benjamin9e4e01e2015-09-15 01:48:04 -040017#include <openssl/ssl.h>
18
Adam Langley09505632015-07-30 18:10:13 -070019#include <assert.h>
20#include <string.h>
21
David Benjamin9e4e01e2015-09-15 01:48:04 -040022#include <openssl/bytestring.h>
23#include <openssl/err.h>
24#include <openssl/mem.h>
25#include <openssl/stack.h>
Adam Langley09505632015-07-30 18:10:13 -070026
27#include "internal.h"
28
29
David Benjamin86e95b82017-07-18 16:34:25 -040030namespace bssl {
31
Adam Langley09505632015-07-30 18:10:13 -070032void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension) {
33 OPENSSL_free(custom_extension);
34}
35
36static const SSL_CUSTOM_EXTENSION *custom_ext_find(
37 STACK_OF(SSL_CUSTOM_EXTENSION) *stack,
38 unsigned *out_index, uint16_t value) {
David Benjamin54091232016-09-05 12:47:25 -040039 for (size_t i = 0; i < sk_SSL_CUSTOM_EXTENSION_num(stack); i++) {
Adam Langley09505632015-07-30 18:10:13 -070040 const SSL_CUSTOM_EXTENSION *ext = sk_SSL_CUSTOM_EXTENSION_value(stack, i);
41 if (ext->value == value) {
42 if (out_index != NULL) {
43 *out_index = i;
44 }
45 return ext;
46 }
47 }
48
49 return NULL;
50}
51
52/* default_add_callback is used as the |add_callback| when the user doesn't
53 * provide one. For servers, it does nothing while, for clients, it causes an
54 * empty extension to be included. */
55static int default_add_callback(SSL *ssl, unsigned extension_value,
56 const uint8_t **out, size_t *out_len,
57 int *out_alert_value, void *add_arg) {
58 if (ssl->server) {
59 return 0;
60 }
61 *out_len = 0;
62 return 1;
63}
64
David Benjamin2bd19172016-11-17 16:47:15 +090065static int custom_ext_add_hello(SSL_HANDSHAKE *hs, CBB *extensions) {
66 SSL *const ssl = hs->ssl;
Adam Langley09505632015-07-30 18:10:13 -070067 STACK_OF(SSL_CUSTOM_EXTENSION) *stack = ssl->ctx->client_custom_extensions;
68 if (ssl->server) {
69 stack = ssl->ctx->server_custom_extensions;
70 }
71
72 if (stack == NULL) {
73 return 1;
74 }
75
Alessandro Ghedini67bb45f2017-03-30 16:33:24 -050076 if (ssl->cert->enable_early_data) {
Steven Valdez2a070722017-03-25 20:54:16 -050077 /* TODO(svaldez): Support Custom Extensions with 0-RTT. For now the caller
78 * is expected not to configure both together.
79 * https://crbug.com/boringssl/173. */
80 OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR);
81 return 0;
82 }
83
David Benjamin54091232016-09-05 12:47:25 -040084 for (size_t i = 0; i < sk_SSL_CUSTOM_EXTENSION_num(stack); i++) {
Adam Langley09505632015-07-30 18:10:13 -070085 const SSL_CUSTOM_EXTENSION *ext = sk_SSL_CUSTOM_EXTENSION_value(stack, i);
86
87 if (ssl->server &&
David Benjamin2bd19172016-11-17 16:47:15 +090088 !(hs->custom_extensions.received & (1u << i))) {
Adam Langley09505632015-07-30 18:10:13 -070089 /* Servers cannot echo extensions that the client didn't send. */
90 continue;
91 }
92
93 const uint8_t *contents;
94 size_t contents_len;
95 int alert = SSL_AD_DECODE_ERROR;
96 CBB contents_cbb;
97
98 switch (ext->add_callback(ssl, ext->value, &contents, &contents_len, &alert,
99 ext->add_arg)) {
100 case 1:
101 if (!CBB_add_u16(extensions, ext->value) ||
102 !CBB_add_u16_length_prefixed(extensions, &contents_cbb) ||
103 !CBB_add_bytes(&contents_cbb, contents, contents_len) ||
104 !CBB_flush(extensions)) {
105 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
Adam Langleyfbbef122016-11-17 12:55:14 -0800106 ERR_add_error_dataf("extension %u", (unsigned) ext->value);
Adam Langley09505632015-07-30 18:10:13 -0700107 if (ext->free_callback && 0 < contents_len) {
108 ext->free_callback(ssl, ext->value, contents, ext->add_arg);
109 }
110 return 0;
111 }
112
113 if (ext->free_callback && 0 < contents_len) {
114 ext->free_callback(ssl, ext->value, contents, ext->add_arg);
115 }
116
117 if (!ssl->server) {
David Benjamin2bd19172016-11-17 16:47:15 +0900118 assert((hs->custom_extensions.sent & (1u << i)) == 0);
119 hs->custom_extensions.sent |= (1u << i);
Adam Langley09505632015-07-30 18:10:13 -0700120 }
121 break;
122
123 case 0:
124 break;
125
126 default:
127 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
128 OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR);
Adam Langleyfbbef122016-11-17 12:55:14 -0800129 ERR_add_error_dataf("extension %u", (unsigned) ext->value);
Adam Langley09505632015-07-30 18:10:13 -0700130 return 0;
131 }
132 }
133
134 return 1;
135}
136
David Benjamin2bd19172016-11-17 16:47:15 +0900137int custom_ext_add_clienthello(SSL_HANDSHAKE *hs, CBB *extensions) {
138 return custom_ext_add_hello(hs, extensions);
Adam Langley09505632015-07-30 18:10:13 -0700139}
140
David Benjamin2bd19172016-11-17 16:47:15 +0900141int custom_ext_parse_serverhello(SSL_HANDSHAKE *hs, int *out_alert,
142 uint16_t value, const CBS *extension) {
143 SSL *const ssl = hs->ssl;
Adam Langley09505632015-07-30 18:10:13 -0700144 unsigned index;
145 const SSL_CUSTOM_EXTENSION *ext =
146 custom_ext_find(ssl->ctx->client_custom_extensions, &index, value);
147
148 if (/* Unknown extensions are not allowed in a ServerHello. */
149 ext == NULL ||
150 /* Also, if we didn't send the extension, that's also unacceptable. */
David Benjamin2bd19172016-11-17 16:47:15 +0900151 !(hs->custom_extensions.sent & (1u << index))) {
Adam Langley09505632015-07-30 18:10:13 -0700152 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
Adam Langleyfbbef122016-11-17 12:55:14 -0800153 ERR_add_error_dataf("extension %u", (unsigned)value);
David Benjamin0c40a962016-08-01 12:05:50 -0400154 *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
Adam Langley09505632015-07-30 18:10:13 -0700155 return 0;
156 }
157
158 if (ext->parse_callback != NULL &&
159 !ext->parse_callback(ssl, value, CBS_data(extension), CBS_len(extension),
160 out_alert, ext->parse_arg)) {
161 OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR);
Adam Langleyfbbef122016-11-17 12:55:14 -0800162 ERR_add_error_dataf("extension %u", (unsigned)ext->value);
Adam Langley09505632015-07-30 18:10:13 -0700163 return 0;
164 }
165
166 return 1;
167}
168
David Benjamin2bd19172016-11-17 16:47:15 +0900169int custom_ext_parse_clienthello(SSL_HANDSHAKE *hs, int *out_alert,
170 uint16_t value, const CBS *extension) {
171 SSL *const ssl = hs->ssl;
Adam Langley09505632015-07-30 18:10:13 -0700172 unsigned index;
173 const SSL_CUSTOM_EXTENSION *ext =
174 custom_ext_find(ssl->ctx->server_custom_extensions, &index, value);
175
176 if (ext == NULL) {
177 return 1;
178 }
179
David Benjamin2bd19172016-11-17 16:47:15 +0900180 assert((hs->custom_extensions.received & (1u << index)) == 0);
181 hs->custom_extensions.received |= (1u << index);
Adam Langley09505632015-07-30 18:10:13 -0700182
183 if (ext->parse_callback &&
184 !ext->parse_callback(ssl, value, CBS_data(extension), CBS_len(extension),
185 out_alert, ext->parse_arg)) {
186 OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR);
Adam Langleyfbbef122016-11-17 12:55:14 -0800187 ERR_add_error_dataf("extension %u", (unsigned)ext->value);
Adam Langley09505632015-07-30 18:10:13 -0700188 return 0;
189 }
190
191 return 1;
192}
193
David Benjamin2bd19172016-11-17 16:47:15 +0900194int custom_ext_add_serverhello(SSL_HANDSHAKE *hs, CBB *extensions) {
195 return custom_ext_add_hello(hs, extensions);
Adam Langley09505632015-07-30 18:10:13 -0700196}
197
198/* MAX_NUM_CUSTOM_EXTENSIONS is the maximum number of custom extensions that
199 * can be set on an |SSL_CTX|. It's determined by the size of the bitset used
200 * to track when an extension has been sent. */
201#define MAX_NUM_CUSTOM_EXTENSIONS \
David Benjaminf5d2cd02016-10-06 19:39:20 -0400202 (sizeof(((SSL_HANDSHAKE *)NULL)->custom_extensions.sent) * 8)
Adam Langley09505632015-07-30 18:10:13 -0700203
204static int custom_ext_append(STACK_OF(SSL_CUSTOM_EXTENSION) **stack,
205 unsigned extension_value,
206 SSL_custom_ext_add_cb add_cb,
207 SSL_custom_ext_free_cb free_cb, void *add_arg,
208 SSL_custom_ext_parse_cb parse_cb,
209 void *parse_arg) {
210 if (add_cb == NULL ||
211 0xffff < extension_value ||
212 SSL_extension_supported(extension_value) ||
213 /* Specifying a free callback without an add callback is nonsensical
214 * and an error. */
215 (*stack != NULL &&
216 (MAX_NUM_CUSTOM_EXTENSIONS <= sk_SSL_CUSTOM_EXTENSION_num(*stack) ||
217 custom_ext_find(*stack, NULL, extension_value) != NULL))) {
218 return 0;
219 }
220
David Benjamine8703a32017-07-09 16:17:55 -0400221 SSL_CUSTOM_EXTENSION *ext =
222 (SSL_CUSTOM_EXTENSION *)OPENSSL_malloc(sizeof(SSL_CUSTOM_EXTENSION));
Adam Langley09505632015-07-30 18:10:13 -0700223 if (ext == NULL) {
224 return 0;
225 }
226 ext->add_callback = add_cb;
227 ext->add_arg = add_arg;
228 ext->free_callback = free_cb;
229 ext->parse_callback = parse_cb;
230 ext->parse_arg = parse_arg;
231 ext->value = extension_value;
232
233 if (*stack == NULL) {
234 *stack = sk_SSL_CUSTOM_EXTENSION_new_null();
235 if (*stack == NULL) {
236 SSL_CUSTOM_EXTENSION_free(ext);
237 return 0;
238 }
239 }
240
241 if (!sk_SSL_CUSTOM_EXTENSION_push(*stack, ext)) {
242 SSL_CUSTOM_EXTENSION_free(ext);
243 if (sk_SSL_CUSTOM_EXTENSION_num(*stack) == 0) {
244 sk_SSL_CUSTOM_EXTENSION_free(*stack);
245 *stack = NULL;
246 }
247 return 0;
248 }
249
250 return 1;
251}
252
David Benjamin86e95b82017-07-18 16:34:25 -0400253} // namespace bssl
254
255using namespace bssl;
256
Adam Langley09505632015-07-30 18:10:13 -0700257int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned extension_value,
258 SSL_custom_ext_add_cb add_cb,
259 SSL_custom_ext_free_cb free_cb, void *add_arg,
260 SSL_custom_ext_parse_cb parse_cb,
261 void *parse_arg) {
262 return custom_ext_append(&ctx->client_custom_extensions, extension_value,
263 add_cb ? add_cb : default_add_callback, free_cb,
264 add_arg, parse_cb, parse_arg);
265}
266
267int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned extension_value,
268 SSL_custom_ext_add_cb add_cb,
269 SSL_custom_ext_free_cb free_cb, void *add_arg,
270 SSL_custom_ext_parse_cb parse_cb,
271 void *parse_arg) {
272 return custom_ext_append(&ctx->server_custom_extensions, extension_value,
273 add_cb ? add_cb : default_add_callback, free_cb,
274 add_arg, parse_cb, parse_arg);
275}