1e71b7053SJung-uk Kim /*
2b2bf0c7eSJung-uk Kim * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim *
4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy
6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html
8e71b7053SJung-uk Kim */
9e71b7053SJung-uk Kim
10e71b7053SJung-uk Kim /* Custom extension utility functions */
11e71b7053SJung-uk Kim
12e71b7053SJung-uk Kim #include <openssl/ct.h>
1317f01e99SJung-uk Kim #include "../ssl_local.h"
14e71b7053SJung-uk Kim #include "internal/cryptlib.h"
1517f01e99SJung-uk Kim #include "statem_local.h"
16e71b7053SJung-uk Kim
17e71b7053SJung-uk Kim typedef struct {
18e71b7053SJung-uk Kim void *add_arg;
19e71b7053SJung-uk Kim custom_ext_add_cb add_cb;
20e71b7053SJung-uk Kim custom_ext_free_cb free_cb;
21e71b7053SJung-uk Kim } custom_ext_add_cb_wrap;
22e71b7053SJung-uk Kim
23e71b7053SJung-uk Kim typedef struct {
24e71b7053SJung-uk Kim void *parse_arg;
25e71b7053SJung-uk Kim custom_ext_parse_cb parse_cb;
26e71b7053SJung-uk Kim } custom_ext_parse_cb_wrap;
27e71b7053SJung-uk Kim
28e71b7053SJung-uk Kim /*
29e71b7053SJung-uk Kim * Provide thin wrapper callbacks which convert new style arguments to old style
30e71b7053SJung-uk Kim */
custom_ext_add_old_cb_wrap(SSL * s,unsigned int ext_type,unsigned int context,const unsigned char ** out,size_t * outlen,X509 * x,size_t chainidx,int * al,void * add_arg)31e71b7053SJung-uk Kim static int custom_ext_add_old_cb_wrap(SSL *s, unsigned int ext_type,
32e71b7053SJung-uk Kim unsigned int context,
33e71b7053SJung-uk Kim const unsigned char **out,
34e71b7053SJung-uk Kim size_t *outlen, X509 *x, size_t chainidx,
35e71b7053SJung-uk Kim int *al, void *add_arg)
36e71b7053SJung-uk Kim {
37e71b7053SJung-uk Kim custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
38e71b7053SJung-uk Kim
39e71b7053SJung-uk Kim if (add_cb_wrap->add_cb == NULL)
40e71b7053SJung-uk Kim return 1;
41e71b7053SJung-uk Kim
42e71b7053SJung-uk Kim return add_cb_wrap->add_cb(s, ext_type, out, outlen, al,
43e71b7053SJung-uk Kim add_cb_wrap->add_arg);
44e71b7053SJung-uk Kim }
45e71b7053SJung-uk Kim
custom_ext_free_old_cb_wrap(SSL * s,unsigned int ext_type,unsigned int context,const unsigned char * out,void * add_arg)46e71b7053SJung-uk Kim static void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type,
47e71b7053SJung-uk Kim unsigned int context,
48e71b7053SJung-uk Kim const unsigned char *out, void *add_arg)
49e71b7053SJung-uk Kim {
50e71b7053SJung-uk Kim custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
51e71b7053SJung-uk Kim
52e71b7053SJung-uk Kim if (add_cb_wrap->free_cb == NULL)
53e71b7053SJung-uk Kim return;
54e71b7053SJung-uk Kim
55e71b7053SJung-uk Kim add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg);
56e71b7053SJung-uk Kim }
57e71b7053SJung-uk Kim
custom_ext_parse_old_cb_wrap(SSL * s,unsigned int ext_type,unsigned int context,const unsigned char * in,size_t inlen,X509 * x,size_t chainidx,int * al,void * parse_arg)58e71b7053SJung-uk Kim static int custom_ext_parse_old_cb_wrap(SSL *s, unsigned int ext_type,
59e71b7053SJung-uk Kim unsigned int context,
60e71b7053SJung-uk Kim const unsigned char *in,
61e71b7053SJung-uk Kim size_t inlen, X509 *x, size_t chainidx,
62e71b7053SJung-uk Kim int *al, void *parse_arg)
63e71b7053SJung-uk Kim {
64e71b7053SJung-uk Kim custom_ext_parse_cb_wrap *parse_cb_wrap =
65e71b7053SJung-uk Kim (custom_ext_parse_cb_wrap *)parse_arg;
66e71b7053SJung-uk Kim
67e71b7053SJung-uk Kim if (parse_cb_wrap->parse_cb == NULL)
68e71b7053SJung-uk Kim return 1;
69e71b7053SJung-uk Kim
70e71b7053SJung-uk Kim return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al,
71e71b7053SJung-uk Kim parse_cb_wrap->parse_arg);
72e71b7053SJung-uk Kim }
73e71b7053SJung-uk Kim
74e71b7053SJung-uk Kim /*
75e71b7053SJung-uk Kim * Find a custom extension from the list. The |role| param is there to
76e71b7053SJung-uk Kim * support the legacy API where custom extensions for client and server could
77e71b7053SJung-uk Kim * be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we
78e71b7053SJung-uk Kim * are trying to find a method relevant to the server, ENDPOINT_CLIENT for the
79e71b7053SJung-uk Kim * client, or ENDPOINT_BOTH for either
80e71b7053SJung-uk Kim */
custom_ext_find(const custom_ext_methods * exts,ENDPOINT role,unsigned int ext_type,size_t * idx)81e71b7053SJung-uk Kim custom_ext_method *custom_ext_find(const custom_ext_methods *exts,
82e71b7053SJung-uk Kim ENDPOINT role, unsigned int ext_type,
83e71b7053SJung-uk Kim size_t *idx)
84e71b7053SJung-uk Kim {
85e71b7053SJung-uk Kim size_t i;
86e71b7053SJung-uk Kim custom_ext_method *meth = exts->meths;
87e71b7053SJung-uk Kim
88e71b7053SJung-uk Kim for (i = 0; i < exts->meths_count; i++, meth++) {
89e71b7053SJung-uk Kim if (ext_type == meth->ext_type
90e71b7053SJung-uk Kim && (role == ENDPOINT_BOTH || role == meth->role
91e71b7053SJung-uk Kim || meth->role == ENDPOINT_BOTH)) {
92e71b7053SJung-uk Kim if (idx != NULL)
93e71b7053SJung-uk Kim *idx = i;
94e71b7053SJung-uk Kim return meth;
95e71b7053SJung-uk Kim }
96e71b7053SJung-uk Kim }
97e71b7053SJung-uk Kim return NULL;
98e71b7053SJung-uk Kim }
99e71b7053SJung-uk Kim
100e71b7053SJung-uk Kim /*
101e71b7053SJung-uk Kim * Initialise custom extensions flags to indicate neither sent nor received.
102e71b7053SJung-uk Kim */
custom_ext_init(custom_ext_methods * exts)103e71b7053SJung-uk Kim void custom_ext_init(custom_ext_methods *exts)
104e71b7053SJung-uk Kim {
105e71b7053SJung-uk Kim size_t i;
106e71b7053SJung-uk Kim custom_ext_method *meth = exts->meths;
107e71b7053SJung-uk Kim
108e71b7053SJung-uk Kim for (i = 0; i < exts->meths_count; i++, meth++)
109e71b7053SJung-uk Kim meth->ext_flags = 0;
110e71b7053SJung-uk Kim }
111e71b7053SJung-uk Kim
112e71b7053SJung-uk Kim /* Pass received custom extension data to the application for parsing. */
custom_ext_parse(SSL * s,unsigned int context,unsigned int ext_type,const unsigned char * ext_data,size_t ext_size,X509 * x,size_t chainidx)113e71b7053SJung-uk Kim int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
114e71b7053SJung-uk Kim const unsigned char *ext_data, size_t ext_size, X509 *x,
115e71b7053SJung-uk Kim size_t chainidx)
116e71b7053SJung-uk Kim {
117e71b7053SJung-uk Kim int al;
118e71b7053SJung-uk Kim custom_ext_methods *exts = &s->cert->custext;
119e71b7053SJung-uk Kim custom_ext_method *meth;
120e71b7053SJung-uk Kim ENDPOINT role = ENDPOINT_BOTH;
121e71b7053SJung-uk Kim
122e71b7053SJung-uk Kim if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0)
123e71b7053SJung-uk Kim role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT;
124e71b7053SJung-uk Kim
125e71b7053SJung-uk Kim meth = custom_ext_find(exts, role, ext_type, NULL);
126e71b7053SJung-uk Kim /* If not found return success */
127e71b7053SJung-uk Kim if (!meth)
128e71b7053SJung-uk Kim return 1;
129e71b7053SJung-uk Kim
130e71b7053SJung-uk Kim /* Check if extension is defined for our protocol. If not, skip */
131e71b7053SJung-uk Kim if (!extension_is_relevant(s, meth->context, context))
132e71b7053SJung-uk Kim return 1;
133e71b7053SJung-uk Kim
134e71b7053SJung-uk Kim if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
135e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_SERVER_HELLO
136e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) {
137e71b7053SJung-uk Kim /*
138e71b7053SJung-uk Kim * If it's ServerHello or EncryptedExtensions we can't have any
139e71b7053SJung-uk Kim * extensions not sent in ClientHello.
140e71b7053SJung-uk Kim */
141e71b7053SJung-uk Kim if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) {
142b077aed3SPierre Pronchery SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION);
143e71b7053SJung-uk Kim return 0;
144e71b7053SJung-uk Kim }
145e71b7053SJung-uk Kim }
146e71b7053SJung-uk Kim
147e71b7053SJung-uk Kim /*
148b2bf0c7eSJung-uk Kim * Extensions received in the ClientHello or CertificateRequest are marked
149b2bf0c7eSJung-uk Kim * with the SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent
150b2bf0c7eSJung-uk Kim * extensions in the response messages
151e71b7053SJung-uk Kim */
152b2bf0c7eSJung-uk Kim if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST))
153b2bf0c7eSJung-uk Kim != 0)
154e71b7053SJung-uk Kim meth->ext_flags |= SSL_EXT_FLAG_RECEIVED;
155e71b7053SJung-uk Kim
156e71b7053SJung-uk Kim /* If no parse function set return success */
157e71b7053SJung-uk Kim if (!meth->parse_cb)
158e71b7053SJung-uk Kim return 1;
159e71b7053SJung-uk Kim
160e71b7053SJung-uk Kim if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx,
161e71b7053SJung-uk Kim &al, meth->parse_arg) <= 0) {
162b077aed3SPierre Pronchery SSLfatal(s, al, SSL_R_BAD_EXTENSION);
163e71b7053SJung-uk Kim return 0;
164e71b7053SJung-uk Kim }
165e71b7053SJung-uk Kim
166e71b7053SJung-uk Kim return 1;
167e71b7053SJung-uk Kim }
168e71b7053SJung-uk Kim
169e71b7053SJung-uk Kim /*
170e71b7053SJung-uk Kim * Request custom extension data from the application and add to the return
171e71b7053SJung-uk Kim * buffer.
172e71b7053SJung-uk Kim */
custom_ext_add(SSL * s,int context,WPACKET * pkt,X509 * x,size_t chainidx,int maxversion)173e71b7053SJung-uk Kim int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
174e71b7053SJung-uk Kim int maxversion)
175e71b7053SJung-uk Kim {
176e71b7053SJung-uk Kim custom_ext_methods *exts = &s->cert->custext;
177e71b7053SJung-uk Kim custom_ext_method *meth;
178e71b7053SJung-uk Kim size_t i;
179e71b7053SJung-uk Kim int al;
180e71b7053SJung-uk Kim
181e71b7053SJung-uk Kim for (i = 0; i < exts->meths_count; i++) {
182e71b7053SJung-uk Kim const unsigned char *out = NULL;
183e71b7053SJung-uk Kim size_t outlen = 0;
184e71b7053SJung-uk Kim
185e71b7053SJung-uk Kim meth = exts->meths + i;
186e71b7053SJung-uk Kim
187e71b7053SJung-uk Kim if (!should_add_extension(s, meth->context, context, maxversion))
188e71b7053SJung-uk Kim continue;
189e71b7053SJung-uk Kim
190e71b7053SJung-uk Kim if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
191e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_SERVER_HELLO
192e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
193e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_CERTIFICATE
194e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) {
195b2bf0c7eSJung-uk Kim /* Only send extensions present in ClientHello/CertificateRequest */
196e71b7053SJung-uk Kim if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
197e71b7053SJung-uk Kim continue;
198e71b7053SJung-uk Kim }
199e71b7053SJung-uk Kim /*
200e71b7053SJung-uk Kim * We skip it if the callback is absent - except for a ClientHello where
201e71b7053SJung-uk Kim * we add an empty extension.
202e71b7053SJung-uk Kim */
203e71b7053SJung-uk Kim if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL)
204e71b7053SJung-uk Kim continue;
205e71b7053SJung-uk Kim
206e71b7053SJung-uk Kim if (meth->add_cb != NULL) {
207e71b7053SJung-uk Kim int cb_retval = meth->add_cb(s, meth->ext_type, context, &out,
208e71b7053SJung-uk Kim &outlen, x, chainidx, &al,
209e71b7053SJung-uk Kim meth->add_arg);
210e71b7053SJung-uk Kim
211e71b7053SJung-uk Kim if (cb_retval < 0) {
212b077aed3SPierre Pronchery SSLfatal(s, al, SSL_R_CALLBACK_FAILED);
213e71b7053SJung-uk Kim return 0; /* error */
214e71b7053SJung-uk Kim }
215e71b7053SJung-uk Kim if (cb_retval == 0)
216e71b7053SJung-uk Kim continue; /* skip this extension */
217e71b7053SJung-uk Kim }
218e71b7053SJung-uk Kim
219e71b7053SJung-uk Kim if (!WPACKET_put_bytes_u16(pkt, meth->ext_type)
220e71b7053SJung-uk Kim || !WPACKET_start_sub_packet_u16(pkt)
221e71b7053SJung-uk Kim || (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen))
222e71b7053SJung-uk Kim || !WPACKET_close(pkt)) {
223e0c4386eSCy Schubert if (meth->free_cb != NULL)
224e0c4386eSCy Schubert meth->free_cb(s, meth->ext_type, context, out, meth->add_arg);
225b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
226e71b7053SJung-uk Kim return 0;
227e71b7053SJung-uk Kim }
228e71b7053SJung-uk Kim if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
229e71b7053SJung-uk Kim /*
230e71b7053SJung-uk Kim * We can't send duplicates: code logic should prevent this.
231e71b7053SJung-uk Kim */
232e71b7053SJung-uk Kim if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) {
233e0c4386eSCy Schubert if (meth->free_cb != NULL)
234e0c4386eSCy Schubert meth->free_cb(s, meth->ext_type, context, out,
235e0c4386eSCy Schubert meth->add_arg);
236b077aed3SPierre Pronchery SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
237e71b7053SJung-uk Kim return 0;
238e71b7053SJung-uk Kim }
239e71b7053SJung-uk Kim /*
240e71b7053SJung-uk Kim * Indicate extension has been sent: this is both a sanity check to
241e71b7053SJung-uk Kim * ensure we don't send duplicate extensions and indicates that it
242e71b7053SJung-uk Kim * is not an error if the extension is present in ServerHello.
243e71b7053SJung-uk Kim */
244e71b7053SJung-uk Kim meth->ext_flags |= SSL_EXT_FLAG_SENT;
245e71b7053SJung-uk Kim }
246e71b7053SJung-uk Kim if (meth->free_cb != NULL)
247e71b7053SJung-uk Kim meth->free_cb(s, meth->ext_type, context, out, meth->add_arg);
248e71b7053SJung-uk Kim }
249e71b7053SJung-uk Kim return 1;
250e71b7053SJung-uk Kim }
251e71b7053SJung-uk Kim
252e71b7053SJung-uk Kim /* Copy the flags from src to dst for any extensions that exist in both */
custom_exts_copy_flags(custom_ext_methods * dst,const custom_ext_methods * src)253e71b7053SJung-uk Kim int custom_exts_copy_flags(custom_ext_methods *dst,
254e71b7053SJung-uk Kim const custom_ext_methods *src)
255e71b7053SJung-uk Kim {
256e71b7053SJung-uk Kim size_t i;
257e71b7053SJung-uk Kim custom_ext_method *methsrc = src->meths;
258e71b7053SJung-uk Kim
259e71b7053SJung-uk Kim for (i = 0; i < src->meths_count; i++, methsrc++) {
260e71b7053SJung-uk Kim custom_ext_method *methdst = custom_ext_find(dst, methsrc->role,
261e71b7053SJung-uk Kim methsrc->ext_type, NULL);
262e71b7053SJung-uk Kim
263e71b7053SJung-uk Kim if (methdst == NULL)
264e71b7053SJung-uk Kim continue;
265e71b7053SJung-uk Kim
266e71b7053SJung-uk Kim methdst->ext_flags = methsrc->ext_flags;
267e71b7053SJung-uk Kim }
268e71b7053SJung-uk Kim
269e71b7053SJung-uk Kim return 1;
270e71b7053SJung-uk Kim }
271e71b7053SJung-uk Kim
272e71b7053SJung-uk Kim /* Copy table of custom extensions */
custom_exts_copy(custom_ext_methods * dst,const custom_ext_methods * src)273e71b7053SJung-uk Kim int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
274e71b7053SJung-uk Kim {
275e71b7053SJung-uk Kim size_t i;
276e71b7053SJung-uk Kim int err = 0;
277e71b7053SJung-uk Kim
278e71b7053SJung-uk Kim if (src->meths_count > 0) {
279e71b7053SJung-uk Kim dst->meths =
280e71b7053SJung-uk Kim OPENSSL_memdup(src->meths,
281e71b7053SJung-uk Kim sizeof(*src->meths) * src->meths_count);
282e71b7053SJung-uk Kim if (dst->meths == NULL)
283e71b7053SJung-uk Kim return 0;
284e71b7053SJung-uk Kim dst->meths_count = src->meths_count;
285e71b7053SJung-uk Kim
286e71b7053SJung-uk Kim for (i = 0; i < src->meths_count; i++) {
287e71b7053SJung-uk Kim custom_ext_method *methsrc = src->meths + i;
288e71b7053SJung-uk Kim custom_ext_method *methdst = dst->meths + i;
289e71b7053SJung-uk Kim
290e71b7053SJung-uk Kim if (methsrc->add_cb != custom_ext_add_old_cb_wrap)
291e71b7053SJung-uk Kim continue;
292e71b7053SJung-uk Kim
293e71b7053SJung-uk Kim /*
294e71b7053SJung-uk Kim * We have found an old style API wrapper. We need to copy the
295e71b7053SJung-uk Kim * arguments too.
296e71b7053SJung-uk Kim */
297e71b7053SJung-uk Kim
298e71b7053SJung-uk Kim if (err) {
299e71b7053SJung-uk Kim methdst->add_arg = NULL;
300e71b7053SJung-uk Kim methdst->parse_arg = NULL;
301e71b7053SJung-uk Kim continue;
302e71b7053SJung-uk Kim }
303e71b7053SJung-uk Kim
304e71b7053SJung-uk Kim methdst->add_arg = OPENSSL_memdup(methsrc->add_arg,
305e71b7053SJung-uk Kim sizeof(custom_ext_add_cb_wrap));
306e71b7053SJung-uk Kim methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg,
307e71b7053SJung-uk Kim sizeof(custom_ext_parse_cb_wrap));
308e71b7053SJung-uk Kim
309e71b7053SJung-uk Kim if (methdst->add_arg == NULL || methdst->parse_arg == NULL)
310e71b7053SJung-uk Kim err = 1;
311e71b7053SJung-uk Kim }
312e71b7053SJung-uk Kim }
313e71b7053SJung-uk Kim
314e71b7053SJung-uk Kim if (err) {
315e71b7053SJung-uk Kim custom_exts_free(dst);
316e71b7053SJung-uk Kim return 0;
317e71b7053SJung-uk Kim }
318e71b7053SJung-uk Kim
319e71b7053SJung-uk Kim return 1;
320e71b7053SJung-uk Kim }
321e71b7053SJung-uk Kim
custom_exts_free(custom_ext_methods * exts)322e71b7053SJung-uk Kim void custom_exts_free(custom_ext_methods *exts)
323e71b7053SJung-uk Kim {
324e71b7053SJung-uk Kim size_t i;
325e71b7053SJung-uk Kim custom_ext_method *meth;
326e71b7053SJung-uk Kim
327e71b7053SJung-uk Kim for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) {
328e71b7053SJung-uk Kim if (meth->add_cb != custom_ext_add_old_cb_wrap)
329e71b7053SJung-uk Kim continue;
330e71b7053SJung-uk Kim
331e71b7053SJung-uk Kim /* Old style API wrapper. Need to free the arguments too */
332e71b7053SJung-uk Kim OPENSSL_free(meth->add_arg);
333e71b7053SJung-uk Kim OPENSSL_free(meth->parse_arg);
334e71b7053SJung-uk Kim }
335e71b7053SJung-uk Kim OPENSSL_free(exts->meths);
336e0c4386eSCy Schubert exts->meths = NULL;
337e0c4386eSCy Schubert exts->meths_count = 0;
338e71b7053SJung-uk Kim }
339e71b7053SJung-uk Kim
340e71b7053SJung-uk Kim /* Return true if a client custom extension exists, false otherwise */
SSL_CTX_has_client_custom_ext(const SSL_CTX * ctx,unsigned int ext_type)341e71b7053SJung-uk Kim int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type)
342e71b7053SJung-uk Kim {
343e71b7053SJung-uk Kim return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type,
344e71b7053SJung-uk Kim NULL) != NULL;
345e71b7053SJung-uk Kim }
346e71b7053SJung-uk Kim
add_custom_ext_intern(SSL_CTX * ctx,ENDPOINT role,unsigned int ext_type,unsigned int context,SSL_custom_ext_add_cb_ex add_cb,SSL_custom_ext_free_cb_ex free_cb,void * add_arg,SSL_custom_ext_parse_cb_ex parse_cb,void * parse_arg)347e71b7053SJung-uk Kim static int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role,
348e71b7053SJung-uk Kim unsigned int ext_type,
349e71b7053SJung-uk Kim unsigned int context,
350e71b7053SJung-uk Kim SSL_custom_ext_add_cb_ex add_cb,
351e71b7053SJung-uk Kim SSL_custom_ext_free_cb_ex free_cb,
352e71b7053SJung-uk Kim void *add_arg,
353e71b7053SJung-uk Kim SSL_custom_ext_parse_cb_ex parse_cb,
354e71b7053SJung-uk Kim void *parse_arg)
355e71b7053SJung-uk Kim {
356e71b7053SJung-uk Kim custom_ext_methods *exts = &ctx->cert->custext;
357e71b7053SJung-uk Kim custom_ext_method *meth, *tmp;
358e71b7053SJung-uk Kim
359e71b7053SJung-uk Kim /*
360e71b7053SJung-uk Kim * Check application error: if add_cb is not set free_cb will never be
361e71b7053SJung-uk Kim * called.
362e71b7053SJung-uk Kim */
363e71b7053SJung-uk Kim if (add_cb == NULL && free_cb != NULL)
364e71b7053SJung-uk Kim return 0;
365e71b7053SJung-uk Kim
366e71b7053SJung-uk Kim #ifndef OPENSSL_NO_CT
367e71b7053SJung-uk Kim /*
368e71b7053SJung-uk Kim * We don't want applications registering callbacks for SCT extensions
369e71b7053SJung-uk Kim * whilst simultaneously using the built-in SCT validation features, as
370e71b7053SJung-uk Kim * these two things may not play well together.
371e71b7053SJung-uk Kim */
372e71b7053SJung-uk Kim if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp
373e71b7053SJung-uk Kim && (context & SSL_EXT_CLIENT_HELLO) != 0
374e71b7053SJung-uk Kim && SSL_CTX_ct_is_enabled(ctx))
375e71b7053SJung-uk Kim return 0;
376e71b7053SJung-uk Kim #endif
377e71b7053SJung-uk Kim
378e71b7053SJung-uk Kim /*
379e71b7053SJung-uk Kim * Don't add if extension supported internally, but make exception
380e71b7053SJung-uk Kim * for extension types that previously were not supported, but now are.
381e71b7053SJung-uk Kim */
382e71b7053SJung-uk Kim if (SSL_extension_supported(ext_type)
383e71b7053SJung-uk Kim && ext_type != TLSEXT_TYPE_signed_certificate_timestamp)
384e71b7053SJung-uk Kim return 0;
385e71b7053SJung-uk Kim
386e71b7053SJung-uk Kim /* Extension type must fit in 16 bits */
387e71b7053SJung-uk Kim if (ext_type > 0xffff)
388e71b7053SJung-uk Kim return 0;
389e71b7053SJung-uk Kim /* Search for duplicate */
390e71b7053SJung-uk Kim if (custom_ext_find(exts, role, ext_type, NULL))
391e71b7053SJung-uk Kim return 0;
392e71b7053SJung-uk Kim tmp = OPENSSL_realloc(exts->meths,
393e71b7053SJung-uk Kim (exts->meths_count + 1) * sizeof(custom_ext_method));
394e71b7053SJung-uk Kim if (tmp == NULL)
395e71b7053SJung-uk Kim return 0;
396e71b7053SJung-uk Kim
397e71b7053SJung-uk Kim exts->meths = tmp;
398e71b7053SJung-uk Kim meth = exts->meths + exts->meths_count;
399e71b7053SJung-uk Kim memset(meth, 0, sizeof(*meth));
400e71b7053SJung-uk Kim meth->role = role;
401e71b7053SJung-uk Kim meth->context = context;
402e71b7053SJung-uk Kim meth->parse_cb = parse_cb;
403e71b7053SJung-uk Kim meth->add_cb = add_cb;
404e71b7053SJung-uk Kim meth->free_cb = free_cb;
405e71b7053SJung-uk Kim meth->ext_type = ext_type;
406e71b7053SJung-uk Kim meth->add_arg = add_arg;
407e71b7053SJung-uk Kim meth->parse_arg = parse_arg;
408e71b7053SJung-uk Kim exts->meths_count++;
409e71b7053SJung-uk Kim return 1;
410e71b7053SJung-uk Kim }
411e71b7053SJung-uk Kim
add_old_custom_ext(SSL_CTX * ctx,ENDPOINT role,unsigned int ext_type,unsigned int context,custom_ext_add_cb add_cb,custom_ext_free_cb free_cb,void * add_arg,custom_ext_parse_cb parse_cb,void * parse_arg)412e71b7053SJung-uk Kim static int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role,
413e71b7053SJung-uk Kim unsigned int ext_type,
414e71b7053SJung-uk Kim unsigned int context,
415e71b7053SJung-uk Kim custom_ext_add_cb add_cb,
416e71b7053SJung-uk Kim custom_ext_free_cb free_cb,
417e71b7053SJung-uk Kim void *add_arg,
418e71b7053SJung-uk Kim custom_ext_parse_cb parse_cb, void *parse_arg)
419e71b7053SJung-uk Kim {
420e71b7053SJung-uk Kim custom_ext_add_cb_wrap *add_cb_wrap
421e71b7053SJung-uk Kim = OPENSSL_malloc(sizeof(*add_cb_wrap));
422e71b7053SJung-uk Kim custom_ext_parse_cb_wrap *parse_cb_wrap
423e71b7053SJung-uk Kim = OPENSSL_malloc(sizeof(*parse_cb_wrap));
424e71b7053SJung-uk Kim int ret;
425e71b7053SJung-uk Kim
426e71b7053SJung-uk Kim if (add_cb_wrap == NULL || parse_cb_wrap == NULL) {
427e71b7053SJung-uk Kim OPENSSL_free(add_cb_wrap);
428e71b7053SJung-uk Kim OPENSSL_free(parse_cb_wrap);
429e71b7053SJung-uk Kim return 0;
430e71b7053SJung-uk Kim }
431e71b7053SJung-uk Kim
432e71b7053SJung-uk Kim add_cb_wrap->add_arg = add_arg;
433e71b7053SJung-uk Kim add_cb_wrap->add_cb = add_cb;
434e71b7053SJung-uk Kim add_cb_wrap->free_cb = free_cb;
435e71b7053SJung-uk Kim parse_cb_wrap->parse_arg = parse_arg;
436e71b7053SJung-uk Kim parse_cb_wrap->parse_cb = parse_cb;
437e71b7053SJung-uk Kim
438e71b7053SJung-uk Kim ret = add_custom_ext_intern(ctx, role, ext_type,
439e71b7053SJung-uk Kim context,
440e71b7053SJung-uk Kim custom_ext_add_old_cb_wrap,
441e71b7053SJung-uk Kim custom_ext_free_old_cb_wrap,
442e71b7053SJung-uk Kim add_cb_wrap,
443e71b7053SJung-uk Kim custom_ext_parse_old_cb_wrap,
444e71b7053SJung-uk Kim parse_cb_wrap);
445e71b7053SJung-uk Kim
446e71b7053SJung-uk Kim if (!ret) {
447e71b7053SJung-uk Kim OPENSSL_free(add_cb_wrap);
448e71b7053SJung-uk Kim OPENSSL_free(parse_cb_wrap);
449e71b7053SJung-uk Kim }
450e71b7053SJung-uk Kim
451e71b7053SJung-uk Kim return ret;
452e71b7053SJung-uk Kim }
453e71b7053SJung-uk Kim
454e71b7053SJung-uk Kim /* Application level functions to add the old custom extension callbacks */
SSL_CTX_add_client_custom_ext(SSL_CTX * ctx,unsigned int ext_type,custom_ext_add_cb add_cb,custom_ext_free_cb free_cb,void * add_arg,custom_ext_parse_cb parse_cb,void * parse_arg)455e71b7053SJung-uk Kim int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
456e71b7053SJung-uk Kim custom_ext_add_cb add_cb,
457e71b7053SJung-uk Kim custom_ext_free_cb free_cb,
458e71b7053SJung-uk Kim void *add_arg,
459e71b7053SJung-uk Kim custom_ext_parse_cb parse_cb, void *parse_arg)
460e71b7053SJung-uk Kim {
461e71b7053SJung-uk Kim return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type,
462e71b7053SJung-uk Kim SSL_EXT_TLS1_2_AND_BELOW_ONLY
463e71b7053SJung-uk Kim | SSL_EXT_CLIENT_HELLO
464e71b7053SJung-uk Kim | SSL_EXT_TLS1_2_SERVER_HELLO
465e71b7053SJung-uk Kim | SSL_EXT_IGNORE_ON_RESUMPTION,
466e71b7053SJung-uk Kim add_cb, free_cb, add_arg, parse_cb, parse_arg);
467e71b7053SJung-uk Kim }
468e71b7053SJung-uk Kim
SSL_CTX_add_server_custom_ext(SSL_CTX * ctx,unsigned int ext_type,custom_ext_add_cb add_cb,custom_ext_free_cb free_cb,void * add_arg,custom_ext_parse_cb parse_cb,void * parse_arg)469e71b7053SJung-uk Kim int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
470e71b7053SJung-uk Kim custom_ext_add_cb add_cb,
471e71b7053SJung-uk Kim custom_ext_free_cb free_cb,
472e71b7053SJung-uk Kim void *add_arg,
473e71b7053SJung-uk Kim custom_ext_parse_cb parse_cb, void *parse_arg)
474e71b7053SJung-uk Kim {
475e71b7053SJung-uk Kim return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type,
476e71b7053SJung-uk Kim SSL_EXT_TLS1_2_AND_BELOW_ONLY
477e71b7053SJung-uk Kim | SSL_EXT_CLIENT_HELLO
478e71b7053SJung-uk Kim | SSL_EXT_TLS1_2_SERVER_HELLO
479e71b7053SJung-uk Kim | SSL_EXT_IGNORE_ON_RESUMPTION,
480e71b7053SJung-uk Kim add_cb, free_cb, add_arg, parse_cb, parse_arg);
481e71b7053SJung-uk Kim }
482e71b7053SJung-uk Kim
SSL_CTX_add_custom_ext(SSL_CTX * ctx,unsigned int ext_type,unsigned int context,SSL_custom_ext_add_cb_ex add_cb,SSL_custom_ext_free_cb_ex free_cb,void * add_arg,SSL_custom_ext_parse_cb_ex parse_cb,void * parse_arg)483e71b7053SJung-uk Kim int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
484e71b7053SJung-uk Kim unsigned int context,
485e71b7053SJung-uk Kim SSL_custom_ext_add_cb_ex add_cb,
486e71b7053SJung-uk Kim SSL_custom_ext_free_cb_ex free_cb,
487e71b7053SJung-uk Kim void *add_arg,
488e71b7053SJung-uk Kim SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg)
489e71b7053SJung-uk Kim {
490e71b7053SJung-uk Kim return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb,
491e71b7053SJung-uk Kim free_cb, add_arg, parse_cb, parse_arg);
492e71b7053SJung-uk Kim }
493e71b7053SJung-uk Kim
SSL_extension_supported(unsigned int ext_type)494e71b7053SJung-uk Kim int SSL_extension_supported(unsigned int ext_type)
495e71b7053SJung-uk Kim {
496e71b7053SJung-uk Kim switch (ext_type) {
497e71b7053SJung-uk Kim /* Internally supported extensions. */
498e71b7053SJung-uk Kim case TLSEXT_TYPE_application_layer_protocol_negotiation:
499e71b7053SJung-uk Kim case TLSEXT_TYPE_ec_point_formats:
500e71b7053SJung-uk Kim case TLSEXT_TYPE_supported_groups:
501e71b7053SJung-uk Kim case TLSEXT_TYPE_key_share:
502e71b7053SJung-uk Kim #ifndef OPENSSL_NO_NEXTPROTONEG
503e71b7053SJung-uk Kim case TLSEXT_TYPE_next_proto_neg:
504e71b7053SJung-uk Kim #endif
505e71b7053SJung-uk Kim case TLSEXT_TYPE_padding:
506e71b7053SJung-uk Kim case TLSEXT_TYPE_renegotiate:
507e71b7053SJung-uk Kim case TLSEXT_TYPE_max_fragment_length:
508e71b7053SJung-uk Kim case TLSEXT_TYPE_server_name:
509e71b7053SJung-uk Kim case TLSEXT_TYPE_session_ticket:
510e71b7053SJung-uk Kim case TLSEXT_TYPE_signature_algorithms:
511e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SRP
512e71b7053SJung-uk Kim case TLSEXT_TYPE_srp:
513e71b7053SJung-uk Kim #endif
514e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP
515e71b7053SJung-uk Kim case TLSEXT_TYPE_status_request:
516e71b7053SJung-uk Kim #endif
517e71b7053SJung-uk Kim #ifndef OPENSSL_NO_CT
518e71b7053SJung-uk Kim case TLSEXT_TYPE_signed_certificate_timestamp:
519e71b7053SJung-uk Kim #endif
520e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SRTP
521e71b7053SJung-uk Kim case TLSEXT_TYPE_use_srtp:
522e71b7053SJung-uk Kim #endif
523e71b7053SJung-uk Kim case TLSEXT_TYPE_encrypt_then_mac:
524e71b7053SJung-uk Kim case TLSEXT_TYPE_supported_versions:
525e71b7053SJung-uk Kim case TLSEXT_TYPE_extended_master_secret:
526e71b7053SJung-uk Kim case TLSEXT_TYPE_psk_kex_modes:
527e71b7053SJung-uk Kim case TLSEXT_TYPE_cookie:
528e71b7053SJung-uk Kim case TLSEXT_TYPE_early_data:
529e71b7053SJung-uk Kim case TLSEXT_TYPE_certificate_authorities:
530e71b7053SJung-uk Kim case TLSEXT_TYPE_psk:
531e71b7053SJung-uk Kim case TLSEXT_TYPE_post_handshake_auth:
532e71b7053SJung-uk Kim return 1;
533e71b7053SJung-uk Kim default:
534e71b7053SJung-uk Kim return 0;
535e71b7053SJung-uk Kim }
536e71b7053SJung-uk Kim }
537