113d40330Schristos /*
221497c5cSchristos * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
313d40330Schristos *
4b0d17251Schristos * Licensed under the Apache License 2.0 (the "License"). You may not use
513d40330Schristos * this file except in compliance with the License. You can obtain a copy
613d40330Schristos * in the file LICENSE in the source distribution or at
713d40330Schristos * https://www.openssl.org/source/license.html
813d40330Schristos */
913d40330Schristos
1013d40330Schristos /* Custom extension utility functions */
1113d40330Schristos
1213d40330Schristos #include <openssl/ct.h>
137d004720Schristos #include "../ssl_local.h"
1413d40330Schristos #include "internal/cryptlib.h"
157d004720Schristos #include "statem_local.h"
1613d40330Schristos
1713d40330Schristos typedef struct {
1813d40330Schristos void *add_arg;
1913d40330Schristos custom_ext_add_cb add_cb;
2013d40330Schristos custom_ext_free_cb free_cb;
2113d40330Schristos } custom_ext_add_cb_wrap;
2213d40330Schristos
2313d40330Schristos typedef struct {
2413d40330Schristos void *parse_arg;
2513d40330Schristos custom_ext_parse_cb parse_cb;
2613d40330Schristos } custom_ext_parse_cb_wrap;
2713d40330Schristos
2813d40330Schristos /*
2913d40330Schristos * Provide thin wrapper callbacks which convert new style arguments to old style
3013d40330Schristos */
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)3113d40330Schristos static int custom_ext_add_old_cb_wrap(SSL *s, unsigned int ext_type,
3213d40330Schristos unsigned int context,
3313d40330Schristos const unsigned char **out,
3413d40330Schristos size_t *outlen, X509 *x, size_t chainidx,
3513d40330Schristos int *al, void *add_arg)
3613d40330Schristos {
3713d40330Schristos custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
3813d40330Schristos
3913d40330Schristos if (add_cb_wrap->add_cb == NULL)
4013d40330Schristos return 1;
4113d40330Schristos
4213d40330Schristos return add_cb_wrap->add_cb(s, ext_type, out, outlen, al,
4313d40330Schristos add_cb_wrap->add_arg);
4413d40330Schristos }
4513d40330Schristos
custom_ext_free_old_cb_wrap(SSL * s,unsigned int ext_type,unsigned int context,const unsigned char * out,void * add_arg)4613d40330Schristos static void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type,
4713d40330Schristos unsigned int context,
4813d40330Schristos const unsigned char *out, void *add_arg)
4913d40330Schristos {
5013d40330Schristos custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
5113d40330Schristos
5213d40330Schristos if (add_cb_wrap->free_cb == NULL)
5313d40330Schristos return;
5413d40330Schristos
5513d40330Schristos add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg);
5613d40330Schristos }
5713d40330Schristos
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)5813d40330Schristos static int custom_ext_parse_old_cb_wrap(SSL *s, unsigned int ext_type,
5913d40330Schristos unsigned int context,
6013d40330Schristos const unsigned char *in,
6113d40330Schristos size_t inlen, X509 *x, size_t chainidx,
6213d40330Schristos int *al, void *parse_arg)
6313d40330Schristos {
6413d40330Schristos custom_ext_parse_cb_wrap *parse_cb_wrap =
6513d40330Schristos (custom_ext_parse_cb_wrap *)parse_arg;
6613d40330Schristos
6713d40330Schristos if (parse_cb_wrap->parse_cb == NULL)
6813d40330Schristos return 1;
6913d40330Schristos
7013d40330Schristos return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al,
7113d40330Schristos parse_cb_wrap->parse_arg);
7213d40330Schristos }
7313d40330Schristos
7413d40330Schristos /*
7513d40330Schristos * Find a custom extension from the list. The |role| param is there to
7613d40330Schristos * support the legacy API where custom extensions for client and server could
7713d40330Schristos * be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we
7813d40330Schristos * are trying to find a method relevant to the server, ENDPOINT_CLIENT for the
7913d40330Schristos * client, or ENDPOINT_BOTH for either
8013d40330Schristos */
custom_ext_find(const custom_ext_methods * exts,ENDPOINT role,unsigned int ext_type,size_t * idx)8113d40330Schristos custom_ext_method *custom_ext_find(const custom_ext_methods *exts,
8213d40330Schristos ENDPOINT role, unsigned int ext_type,
8313d40330Schristos size_t *idx)
8413d40330Schristos {
8513d40330Schristos size_t i;
8613d40330Schristos custom_ext_method *meth = exts->meths;
8713d40330Schristos
8813d40330Schristos for (i = 0; i < exts->meths_count; i++, meth++) {
8913d40330Schristos if (ext_type == meth->ext_type
9013d40330Schristos && (role == ENDPOINT_BOTH || role == meth->role
9113d40330Schristos || meth->role == ENDPOINT_BOTH)) {
9213d40330Schristos if (idx != NULL)
9313d40330Schristos *idx = i;
9413d40330Schristos return meth;
9513d40330Schristos }
9613d40330Schristos }
9713d40330Schristos return NULL;
9813d40330Schristos }
9913d40330Schristos
10013d40330Schristos /*
10113d40330Schristos * Initialise custom extensions flags to indicate neither sent nor received.
10213d40330Schristos */
custom_ext_init(custom_ext_methods * exts)10313d40330Schristos void custom_ext_init(custom_ext_methods *exts)
10413d40330Schristos {
10513d40330Schristos size_t i;
10613d40330Schristos custom_ext_method *meth = exts->meths;
10713d40330Schristos
10813d40330Schristos for (i = 0; i < exts->meths_count; i++, meth++)
10913d40330Schristos meth->ext_flags = 0;
11013d40330Schristos }
11113d40330Schristos
11213d40330Schristos /* 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)11313d40330Schristos int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
11413d40330Schristos const unsigned char *ext_data, size_t ext_size, X509 *x,
11513d40330Schristos size_t chainidx)
11613d40330Schristos {
11713d40330Schristos int al;
11813d40330Schristos custom_ext_methods *exts = &s->cert->custext;
11913d40330Schristos custom_ext_method *meth;
12013d40330Schristos ENDPOINT role = ENDPOINT_BOTH;
12113d40330Schristos
12213d40330Schristos if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0)
12313d40330Schristos role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT;
12413d40330Schristos
12513d40330Schristos meth = custom_ext_find(exts, role, ext_type, NULL);
12613d40330Schristos /* If not found return success */
12713d40330Schristos if (!meth)
12813d40330Schristos return 1;
12913d40330Schristos
13013d40330Schristos /* Check if extension is defined for our protocol. If not, skip */
13113d40330Schristos if (!extension_is_relevant(s, meth->context, context))
13213d40330Schristos return 1;
13313d40330Schristos
13413d40330Schristos if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
13513d40330Schristos | SSL_EXT_TLS1_3_SERVER_HELLO
13613d40330Schristos | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) {
13713d40330Schristos /*
13813d40330Schristos * If it's ServerHello or EncryptedExtensions we can't have any
13913d40330Schristos * extensions not sent in ClientHello.
14013d40330Schristos */
14113d40330Schristos if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) {
142b0d17251Schristos SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION);
14313d40330Schristos return 0;
14413d40330Schristos }
14513d40330Schristos }
14613d40330Schristos
14713d40330Schristos /*
14821497c5cSchristos * Extensions received in the ClientHello or CertificateRequest are marked
14921497c5cSchristos * with the SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent
15021497c5cSchristos * extensions in the response messages
15113d40330Schristos */
15221497c5cSchristos if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST))
15321497c5cSchristos != 0)
15413d40330Schristos meth->ext_flags |= SSL_EXT_FLAG_RECEIVED;
15513d40330Schristos
15613d40330Schristos /* If no parse function set return success */
15713d40330Schristos if (!meth->parse_cb)
15813d40330Schristos return 1;
15913d40330Schristos
16013d40330Schristos if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx,
16113d40330Schristos &al, meth->parse_arg) <= 0) {
162b0d17251Schristos SSLfatal(s, al, SSL_R_BAD_EXTENSION);
16313d40330Schristos return 0;
16413d40330Schristos }
16513d40330Schristos
16613d40330Schristos return 1;
16713d40330Schristos }
16813d40330Schristos
16913d40330Schristos /*
17013d40330Schristos * Request custom extension data from the application and add to the return
17113d40330Schristos * buffer.
17213d40330Schristos */
custom_ext_add(SSL * s,int context,WPACKET * pkt,X509 * x,size_t chainidx,int maxversion)17313d40330Schristos int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
17413d40330Schristos int maxversion)
17513d40330Schristos {
17613d40330Schristos custom_ext_methods *exts = &s->cert->custext;
17713d40330Schristos custom_ext_method *meth;
17813d40330Schristos size_t i;
17913d40330Schristos int al;
18013d40330Schristos
18113d40330Schristos for (i = 0; i < exts->meths_count; i++) {
18213d40330Schristos const unsigned char *out = NULL;
18313d40330Schristos size_t outlen = 0;
18413d40330Schristos
18513d40330Schristos meth = exts->meths + i;
18613d40330Schristos
18713d40330Schristos if (!should_add_extension(s, meth->context, context, maxversion))
18813d40330Schristos continue;
18913d40330Schristos
19013d40330Schristos if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
19113d40330Schristos | SSL_EXT_TLS1_3_SERVER_HELLO
19213d40330Schristos | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
19313d40330Schristos | SSL_EXT_TLS1_3_CERTIFICATE
19413d40330Schristos | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) {
19521497c5cSchristos /* Only send extensions present in ClientHello/CertificateRequest */
19613d40330Schristos if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
19713d40330Schristos continue;
19813d40330Schristos }
19913d40330Schristos /*
20013d40330Schristos * We skip it if the callback is absent - except for a ClientHello where
20113d40330Schristos * we add an empty extension.
20213d40330Schristos */
20313d40330Schristos if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL)
20413d40330Schristos continue;
20513d40330Schristos
20613d40330Schristos if (meth->add_cb != NULL) {
20713d40330Schristos int cb_retval = meth->add_cb(s, meth->ext_type, context, &out,
20813d40330Schristos &outlen, x, chainidx, &al,
20913d40330Schristos meth->add_arg);
21013d40330Schristos
21113d40330Schristos if (cb_retval < 0) {
212b0d17251Schristos SSLfatal(s, al, SSL_R_CALLBACK_FAILED);
21313d40330Schristos return 0; /* error */
21413d40330Schristos }
21513d40330Schristos if (cb_retval == 0)
21613d40330Schristos continue; /* skip this extension */
21713d40330Schristos }
21813d40330Schristos
21913d40330Schristos if (!WPACKET_put_bytes_u16(pkt, meth->ext_type)
22013d40330Schristos || !WPACKET_start_sub_packet_u16(pkt)
22113d40330Schristos || (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen))
22213d40330Schristos || !WPACKET_close(pkt)) {
223*0e2e28bcSchristos if (meth->free_cb != NULL)
224*0e2e28bcSchristos meth->free_cb(s, meth->ext_type, context, out, meth->add_arg);
225b0d17251Schristos SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
22613d40330Schristos return 0;
22713d40330Schristos }
22813d40330Schristos if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
22913d40330Schristos /*
23013d40330Schristos * We can't send duplicates: code logic should prevent this.
23113d40330Schristos */
23213d40330Schristos if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) {
233*0e2e28bcSchristos if (meth->free_cb != NULL)
234*0e2e28bcSchristos meth->free_cb(s, meth->ext_type, context, out,
235*0e2e28bcSchristos meth->add_arg);
236b0d17251Schristos SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
23713d40330Schristos return 0;
23813d40330Schristos }
23913d40330Schristos /*
24013d40330Schristos * Indicate extension has been sent: this is both a sanity check to
24113d40330Schristos * ensure we don't send duplicate extensions and indicates that it
24213d40330Schristos * is not an error if the extension is present in ServerHello.
24313d40330Schristos */
24413d40330Schristos meth->ext_flags |= SSL_EXT_FLAG_SENT;
24513d40330Schristos }
24613d40330Schristos if (meth->free_cb != NULL)
24713d40330Schristos meth->free_cb(s, meth->ext_type, context, out, meth->add_arg);
24813d40330Schristos }
24913d40330Schristos return 1;
25013d40330Schristos }
25113d40330Schristos
25213d40330Schristos /* 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)25313d40330Schristos int custom_exts_copy_flags(custom_ext_methods *dst,
25413d40330Schristos const custom_ext_methods *src)
25513d40330Schristos {
25613d40330Schristos size_t i;
25713d40330Schristos custom_ext_method *methsrc = src->meths;
25813d40330Schristos
25913d40330Schristos for (i = 0; i < src->meths_count; i++, methsrc++) {
26013d40330Schristos custom_ext_method *methdst = custom_ext_find(dst, methsrc->role,
26113d40330Schristos methsrc->ext_type, NULL);
26213d40330Schristos
26313d40330Schristos if (methdst == NULL)
26413d40330Schristos continue;
26513d40330Schristos
26613d40330Schristos methdst->ext_flags = methsrc->ext_flags;
26713d40330Schristos }
26813d40330Schristos
26913d40330Schristos return 1;
27013d40330Schristos }
27113d40330Schristos
27213d40330Schristos /* Copy table of custom extensions */
custom_exts_copy(custom_ext_methods * dst,const custom_ext_methods * src)27313d40330Schristos int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
27413d40330Schristos {
27513d40330Schristos size_t i;
27613d40330Schristos int err = 0;
27713d40330Schristos
27813d40330Schristos if (src->meths_count > 0) {
27913d40330Schristos dst->meths =
28013d40330Schristos OPENSSL_memdup(src->meths,
28113d40330Schristos sizeof(*src->meths) * src->meths_count);
28213d40330Schristos if (dst->meths == NULL)
28313d40330Schristos return 0;
28413d40330Schristos dst->meths_count = src->meths_count;
28513d40330Schristos
28613d40330Schristos for (i = 0; i < src->meths_count; i++) {
28713d40330Schristos custom_ext_method *methsrc = src->meths + i;
28813d40330Schristos custom_ext_method *methdst = dst->meths + i;
28913d40330Schristos
29013d40330Schristos if (methsrc->add_cb != custom_ext_add_old_cb_wrap)
29113d40330Schristos continue;
29213d40330Schristos
29313d40330Schristos /*
29413d40330Schristos * We have found an old style API wrapper. We need to copy the
29513d40330Schristos * arguments too.
29613d40330Schristos */
29713d40330Schristos
29813d40330Schristos if (err) {
29913d40330Schristos methdst->add_arg = NULL;
30013d40330Schristos methdst->parse_arg = NULL;
30113d40330Schristos continue;
30213d40330Schristos }
30313d40330Schristos
30413d40330Schristos methdst->add_arg = OPENSSL_memdup(methsrc->add_arg,
30513d40330Schristos sizeof(custom_ext_add_cb_wrap));
30613d40330Schristos methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg,
30713d40330Schristos sizeof(custom_ext_parse_cb_wrap));
30813d40330Schristos
30913d40330Schristos if (methdst->add_arg == NULL || methdst->parse_arg == NULL)
31013d40330Schristos err = 1;
31113d40330Schristos }
31213d40330Schristos }
31313d40330Schristos
31413d40330Schristos if (err) {
31513d40330Schristos custom_exts_free(dst);
31613d40330Schristos return 0;
31713d40330Schristos }
31813d40330Schristos
31913d40330Schristos return 1;
32013d40330Schristos }
32113d40330Schristos
custom_exts_free(custom_ext_methods * exts)32213d40330Schristos void custom_exts_free(custom_ext_methods *exts)
32313d40330Schristos {
32413d40330Schristos size_t i;
32513d40330Schristos custom_ext_method *meth;
32613d40330Schristos
32713d40330Schristos for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) {
32813d40330Schristos if (meth->add_cb != custom_ext_add_old_cb_wrap)
32913d40330Schristos continue;
33013d40330Schristos
33113d40330Schristos /* Old style API wrapper. Need to free the arguments too */
33213d40330Schristos OPENSSL_free(meth->add_arg);
33313d40330Schristos OPENSSL_free(meth->parse_arg);
33413d40330Schristos }
33513d40330Schristos OPENSSL_free(exts->meths);
336*0e2e28bcSchristos exts->meths = NULL;
337*0e2e28bcSchristos exts->meths_count = 0;
33813d40330Schristos }
33913d40330Schristos
34013d40330Schristos /* Return true if a client custom extension exists, false otherwise */
SSL_CTX_has_client_custom_ext(const SSL_CTX * ctx,unsigned int ext_type)34113d40330Schristos int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type)
34213d40330Schristos {
34313d40330Schristos return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type,
34413d40330Schristos NULL) != NULL;
34513d40330Schristos }
34613d40330Schristos
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)34713d40330Schristos static int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role,
34813d40330Schristos unsigned int ext_type,
34913d40330Schristos unsigned int context,
35013d40330Schristos SSL_custom_ext_add_cb_ex add_cb,
35113d40330Schristos SSL_custom_ext_free_cb_ex free_cb,
35213d40330Schristos void *add_arg,
35313d40330Schristos SSL_custom_ext_parse_cb_ex parse_cb,
35413d40330Schristos void *parse_arg)
35513d40330Schristos {
35613d40330Schristos custom_ext_methods *exts = &ctx->cert->custext;
35713d40330Schristos custom_ext_method *meth, *tmp;
35813d40330Schristos
35913d40330Schristos /*
36013d40330Schristos * Check application error: if add_cb is not set free_cb will never be
36113d40330Schristos * called.
36213d40330Schristos */
36313d40330Schristos if (add_cb == NULL && free_cb != NULL)
36413d40330Schristos return 0;
36513d40330Schristos
36613d40330Schristos #ifndef OPENSSL_NO_CT
36713d40330Schristos /*
36813d40330Schristos * We don't want applications registering callbacks for SCT extensions
36913d40330Schristos * whilst simultaneously using the built-in SCT validation features, as
37013d40330Schristos * these two things may not play well together.
37113d40330Schristos */
37213d40330Schristos if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp
37313d40330Schristos && (context & SSL_EXT_CLIENT_HELLO) != 0
37413d40330Schristos && SSL_CTX_ct_is_enabled(ctx))
37513d40330Schristos return 0;
37613d40330Schristos #endif
37713d40330Schristos
37813d40330Schristos /*
37913d40330Schristos * Don't add if extension supported internally, but make exception
38013d40330Schristos * for extension types that previously were not supported, but now are.
38113d40330Schristos */
38213d40330Schristos if (SSL_extension_supported(ext_type)
38313d40330Schristos && ext_type != TLSEXT_TYPE_signed_certificate_timestamp)
38413d40330Schristos return 0;
38513d40330Schristos
38613d40330Schristos /* Extension type must fit in 16 bits */
38713d40330Schristos if (ext_type > 0xffff)
38813d40330Schristos return 0;
38913d40330Schristos /* Search for duplicate */
39013d40330Schristos if (custom_ext_find(exts, role, ext_type, NULL))
39113d40330Schristos return 0;
39213d40330Schristos tmp = OPENSSL_realloc(exts->meths,
39313d40330Schristos (exts->meths_count + 1) * sizeof(custom_ext_method));
39413d40330Schristos if (tmp == NULL)
39513d40330Schristos return 0;
39613d40330Schristos
39713d40330Schristos exts->meths = tmp;
39813d40330Schristos meth = exts->meths + exts->meths_count;
39913d40330Schristos memset(meth, 0, sizeof(*meth));
40013d40330Schristos meth->role = role;
40113d40330Schristos meth->context = context;
40213d40330Schristos meth->parse_cb = parse_cb;
40313d40330Schristos meth->add_cb = add_cb;
40413d40330Schristos meth->free_cb = free_cb;
40513d40330Schristos meth->ext_type = ext_type;
40613d40330Schristos meth->add_arg = add_arg;
40713d40330Schristos meth->parse_arg = parse_arg;
40813d40330Schristos exts->meths_count++;
40913d40330Schristos return 1;
41013d40330Schristos }
41113d40330Schristos
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)41213d40330Schristos static int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role,
41313d40330Schristos unsigned int ext_type,
41413d40330Schristos unsigned int context,
41513d40330Schristos custom_ext_add_cb add_cb,
41613d40330Schristos custom_ext_free_cb free_cb,
41713d40330Schristos void *add_arg,
41813d40330Schristos custom_ext_parse_cb parse_cb, void *parse_arg)
41913d40330Schristos {
42013d40330Schristos custom_ext_add_cb_wrap *add_cb_wrap
42113d40330Schristos = OPENSSL_malloc(sizeof(*add_cb_wrap));
42213d40330Schristos custom_ext_parse_cb_wrap *parse_cb_wrap
42313d40330Schristos = OPENSSL_malloc(sizeof(*parse_cb_wrap));
42413d40330Schristos int ret;
42513d40330Schristos
42613d40330Schristos if (add_cb_wrap == NULL || parse_cb_wrap == NULL) {
42713d40330Schristos OPENSSL_free(add_cb_wrap);
42813d40330Schristos OPENSSL_free(parse_cb_wrap);
42913d40330Schristos return 0;
43013d40330Schristos }
43113d40330Schristos
43213d40330Schristos add_cb_wrap->add_arg = add_arg;
43313d40330Schristos add_cb_wrap->add_cb = add_cb;
43413d40330Schristos add_cb_wrap->free_cb = free_cb;
43513d40330Schristos parse_cb_wrap->parse_arg = parse_arg;
43613d40330Schristos parse_cb_wrap->parse_cb = parse_cb;
43713d40330Schristos
43813d40330Schristos ret = add_custom_ext_intern(ctx, role, ext_type,
43913d40330Schristos context,
44013d40330Schristos custom_ext_add_old_cb_wrap,
44113d40330Schristos custom_ext_free_old_cb_wrap,
44213d40330Schristos add_cb_wrap,
44313d40330Schristos custom_ext_parse_old_cb_wrap,
44413d40330Schristos parse_cb_wrap);
44513d40330Schristos
44613d40330Schristos if (!ret) {
44713d40330Schristos OPENSSL_free(add_cb_wrap);
44813d40330Schristos OPENSSL_free(parse_cb_wrap);
44913d40330Schristos }
45013d40330Schristos
45113d40330Schristos return ret;
45213d40330Schristos }
45313d40330Schristos
45413d40330Schristos /* 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)45513d40330Schristos int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
45613d40330Schristos custom_ext_add_cb add_cb,
45713d40330Schristos custom_ext_free_cb free_cb,
45813d40330Schristos void *add_arg,
45913d40330Schristos custom_ext_parse_cb parse_cb, void *parse_arg)
46013d40330Schristos {
46113d40330Schristos return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type,
46213d40330Schristos SSL_EXT_TLS1_2_AND_BELOW_ONLY
46313d40330Schristos | SSL_EXT_CLIENT_HELLO
46413d40330Schristos | SSL_EXT_TLS1_2_SERVER_HELLO
46513d40330Schristos | SSL_EXT_IGNORE_ON_RESUMPTION,
46613d40330Schristos add_cb, free_cb, add_arg, parse_cb, parse_arg);
46713d40330Schristos }
46813d40330Schristos
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)46913d40330Schristos int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
47013d40330Schristos custom_ext_add_cb add_cb,
47113d40330Schristos custom_ext_free_cb free_cb,
47213d40330Schristos void *add_arg,
47313d40330Schristos custom_ext_parse_cb parse_cb, void *parse_arg)
47413d40330Schristos {
47513d40330Schristos return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type,
47613d40330Schristos SSL_EXT_TLS1_2_AND_BELOW_ONLY
47713d40330Schristos | SSL_EXT_CLIENT_HELLO
47813d40330Schristos | SSL_EXT_TLS1_2_SERVER_HELLO
47913d40330Schristos | SSL_EXT_IGNORE_ON_RESUMPTION,
48013d40330Schristos add_cb, free_cb, add_arg, parse_cb, parse_arg);
48113d40330Schristos }
48213d40330Schristos
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)48313d40330Schristos int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
48413d40330Schristos unsigned int context,
48513d40330Schristos SSL_custom_ext_add_cb_ex add_cb,
48613d40330Schristos SSL_custom_ext_free_cb_ex free_cb,
48713d40330Schristos void *add_arg,
48813d40330Schristos SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg)
48913d40330Schristos {
49013d40330Schristos return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb,
49113d40330Schristos free_cb, add_arg, parse_cb, parse_arg);
49213d40330Schristos }
49313d40330Schristos
SSL_extension_supported(unsigned int ext_type)49413d40330Schristos int SSL_extension_supported(unsigned int ext_type)
49513d40330Schristos {
49613d40330Schristos switch (ext_type) {
49713d40330Schristos /* Internally supported extensions. */
49813d40330Schristos case TLSEXT_TYPE_application_layer_protocol_negotiation:
49913d40330Schristos case TLSEXT_TYPE_ec_point_formats:
50013d40330Schristos case TLSEXT_TYPE_supported_groups:
50113d40330Schristos case TLSEXT_TYPE_key_share:
50213d40330Schristos #ifndef OPENSSL_NO_NEXTPROTONEG
50313d40330Schristos case TLSEXT_TYPE_next_proto_neg:
50413d40330Schristos #endif
50513d40330Schristos case TLSEXT_TYPE_padding:
50613d40330Schristos case TLSEXT_TYPE_renegotiate:
50713d40330Schristos case TLSEXT_TYPE_max_fragment_length:
50813d40330Schristos case TLSEXT_TYPE_server_name:
50913d40330Schristos case TLSEXT_TYPE_session_ticket:
51013d40330Schristos case TLSEXT_TYPE_signature_algorithms:
51113d40330Schristos #ifndef OPENSSL_NO_SRP
51213d40330Schristos case TLSEXT_TYPE_srp:
51313d40330Schristos #endif
51413d40330Schristos #ifndef OPENSSL_NO_OCSP
51513d40330Schristos case TLSEXT_TYPE_status_request:
51613d40330Schristos #endif
51713d40330Schristos #ifndef OPENSSL_NO_CT
51813d40330Schristos case TLSEXT_TYPE_signed_certificate_timestamp:
51913d40330Schristos #endif
52013d40330Schristos #ifndef OPENSSL_NO_SRTP
52113d40330Schristos case TLSEXT_TYPE_use_srtp:
52213d40330Schristos #endif
52313d40330Schristos case TLSEXT_TYPE_encrypt_then_mac:
52413d40330Schristos case TLSEXT_TYPE_supported_versions:
52513d40330Schristos case TLSEXT_TYPE_extended_master_secret:
52613d40330Schristos case TLSEXT_TYPE_psk_kex_modes:
52713d40330Schristos case TLSEXT_TYPE_cookie:
52813d40330Schristos case TLSEXT_TYPE_early_data:
52913d40330Schristos case TLSEXT_TYPE_certificate_authorities:
53013d40330Schristos case TLSEXT_TYPE_psk:
53113d40330Schristos case TLSEXT_TYPE_post_handshake_auth:
53213d40330Schristos return 1;
53313d40330Schristos default:
53413d40330Schristos return 0;
53513d40330Schristos }
53613d40330Schristos }
537