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