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