extensions_cust.c 16.5 KB
Newer Older
R
Rich Salz 已提交
1 2
/*
 * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
D
Dr. Stephen Henson 已提交
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
D
Dr. Stephen Henson 已提交
8 9 10 11
 */

/* Custom extension utility functions */

12
#include <assert.h>
R
Rich Salz 已提交
13
#include <openssl/ct.h>
14
#include "../ssl_locl.h"
15
#include "statem_locl.h"
D
Dr. Stephen Henson 已提交
16

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
typedef struct {
    void *add_arg;
    custom_ext_add_cb add_cb;
    custom_ext_free_cb free_cb;
} custom_ext_add_cb_wrap;

typedef struct {
    void *parse_arg;
    custom_ext_parse_cb parse_cb;
} custom_ext_parse_cb_wrap;

/*
 * Provide thin wrapper callbacks which convert new style arguments to old style
 */
static int 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)
{
    custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;

    if (add_cb_wrap->add_cb == NULL)
        return 1;

    return add_cb_wrap->add_cb(s, ext_type, out, outlen, al,
                               add_cb_wrap->add_arg);
}

static void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type,
                                        unsigned int context,
                                        const unsigned char *out, void *add_arg)
{
    custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;

    if (add_cb_wrap->free_cb == NULL)
        return;

    add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg);
}

static int 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)
{
    custom_ext_parse_cb_wrap *parse_cb_wrap =
        (custom_ext_parse_cb_wrap *)parse_arg;

    return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al,
                                   parse_cb_wrap->parse_arg);
}

/*
72
 * Find a custom extension from the list. The |role| param is there to
73
 * support the legacy API where custom extensions for client and server could
74 75 76
 * be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we
 * are trying to find a method relevant to the server, ENDPOINT_CLIENT for the
 * client, or ENDPOINT_BOTH for either
77
 */
78 79 80
custom_ext_method *custom_ext_find(const custom_ext_methods *exts,
                                   ENDPOINT role, unsigned int ext_type,
                                   size_t *idx)
81 82 83
{
    size_t i;
    custom_ext_method *meth = exts->meths;
84

85
    for (i = 0; i < exts->meths_count; i++, meth++) {
86
        if (ext_type == meth->ext_type
87 88
                && (role == ENDPOINT_BOTH || role == meth->role
                    || meth->role == ENDPOINT_BOTH)) {
89 90
            if (idx != NULL)
                *idx = i;
91
            return meth;
92
        }
93 94 95 96 97 98
    }
    return NULL;
}

/*
 * Initialise custom extensions flags to indicate neither sent nor received.
99 100
 */
void custom_ext_init(custom_ext_methods *exts)
101 102 103
{
    size_t i;
    custom_ext_method *meth = exts->meths;
104

105 106 107
    for (i = 0; i < exts->meths_count; i++, meth++)
        meth->ext_flags = 0;
}
D
Dr. Stephen Henson 已提交
108

109
/* Pass received custom extension data to the application for parsing. */
110 111 112
int 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, int *al)
113
{
114
    custom_ext_methods *exts = &s->cert->custext;
115
    custom_ext_method *meth;
116
    ENDPOINT role = ENDPOINT_BOTH;
117 118

    if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0)
119
        role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT;
120

121
    meth = custom_ext_find(exts, role, ext_type, NULL);
122 123 124
    /* If not found return success */
    if (!meth)
        return 1;
125 126 127 128 129 130 131 132

    /* Check if extension is defined for our protocol. If not, skip */
    if (!extension_is_relevant(s, meth->context, context))
        return 1;

    if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
                    | SSL_EXT_TLS1_3_SERVER_HELLO
                    | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) {
133
        /*
134 135
         * If it's ServerHello or EncryptedExtensions we can't have any
         * extensions not sent in ClientHello.
136
         */
137
        if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) {
138 139 140 141
            *al = TLS1_AD_UNSUPPORTED_EXTENSION;
            return 0;
        }
    }
142 143 144 145 146 147 148 149 150

    /*
     * Extensions received in the ClientHello are marked with the
     * SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent
     * extensions in the ServerHello/EncryptedExtensions message
     */
    if ((context & SSL_EXT_CLIENT_HELLO) != 0)
        meth->ext_flags |= SSL_EXT_FLAG_RECEIVED;

151 152 153
    /* If no parse function set return success */
    if (!meth->parse_cb)
        return 1;
D
Dr. Stephen Henson 已提交
154

155 156
    return meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx,
                          al, meth->parse_arg);
157
}
D
Dr. Stephen Henson 已提交
158

159 160 161 162
/*
 * Request custom extension data from the application and add to the return
 * buffer.
 */
163 164
int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
                   int maxversion, int *al)
165
{
166
    custom_ext_methods *exts = &s->cert->custext;
167 168 169 170 171 172 173 174 175
    custom_ext_method *meth;
    size_t i;

    for (i = 0; i < exts->meths_count; i++) {
        const unsigned char *out = NULL;
        size_t outlen = 0;

        meth = exts->meths + i;

176 177 178 179 180 181
        if (!should_add_extension(s, meth->context, context, maxversion))
            continue;

        if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
                        | SSL_EXT_TLS1_3_SERVER_HELLO
                        | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) {
182
            /*
183 184
             * For ServerHello/EncryptedExtensions only send extensions present
             * in ClientHello.
185 186 187 188
             */
            if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
                continue;
        }
189 190 191 192 193 194 195 196
        /*
         * We skip it if the callback is absent - except for a ClientHello where
         * we add an empty extension.
         */
        if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL)
            continue;

        if (meth->add_cb != NULL) {
197 198 199 200
            int cb_retval = meth->add_cb(s, meth->ext_type, context, &out,
                                         &outlen, x, chainidx, al,
                                         meth->add_arg);

201 202 203 204 205 206
            if (cb_retval < 0)
                return 0;       /* error */
            if (cb_retval == 0)
                continue;       /* skip this extension */
        }

207
        if (!WPACKET_put_bytes_u16(pkt, meth->ext_type)
M
Matt Caswell 已提交
208
                || !WPACKET_start_sub_packet_u16(pkt)
209 210
                || (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen))
                || !WPACKET_close(pkt)) {
211 212 213
            *al = SSL_AD_INTERNAL_ERROR;
            return 0;
        }
214 215 216 217
        if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
            /*
             * We can't send duplicates: code logic should prevent this.
             */
218
            assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0);
219 220 221 222 223 224 225
            /*
             * Indicate extension has been sent: this is both a sanity check to
             * ensure we don't send duplicate extensions and indicates that it
             * is not an error if the extension is present in ServerHello.
             */
            meth->ext_flags |= SSL_EXT_FLAG_SENT;
        }
226
        if (meth->free_cb != NULL)
227
            meth->free_cb(s, meth->ext_type, context, out, meth->add_arg);
228 229 230 231
    }
    return 1;
}

D
Dr. Stephen Henson 已提交
232 233
/* Copy table of custom extensions */
int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
234
{
235 236 237 238
    size_t i;
    int err = 0;

    if (src->meths_count > 0) {
239
        dst->meths =
R
Rich Salz 已提交
240
            OPENSSL_memdup(src->meths,
241
                           sizeof(*src->meths) * src->meths_count);
242 243 244
        if (dst->meths == NULL)
            return 0;
        dst->meths_count = src->meths_count;
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276

        for (i = 0; i < src->meths_count; i++) {
            custom_ext_method *methsrc = src->meths + i;
            custom_ext_method *methdst = dst->meths + i;

            if (methsrc->add_cb != custom_ext_add_old_cb_wrap)
                continue;

            /*
             * We have found an old style API wrapper. We need to copy the
             * arguments too.
             */

            if (err) {
                methdst->add_arg = NULL;
                methdst->parse_arg = NULL;
                continue;
            }

            methdst->add_arg = OPENSSL_memdup(methsrc->add_arg,
                                              sizeof(custom_ext_add_cb_wrap));
            methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg,
                                            sizeof(custom_ext_parse_cb_wrap));

            if (methdst->add_arg == NULL || methdst->parse_arg == NULL)
                err = 1;
        }
    }

    if (err) {
        custom_exts_free(dst);
        return 0;
277
    }
278

279 280
    return 1;
}
D
Dr. Stephen Henson 已提交
281 282

void custom_exts_free(custom_ext_methods *exts)
283
{
284
    size_t i;
285
    custom_ext_method *meth;
286

287
    for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) {
288 289 290 291 292 293 294
        if (meth->add_cb != custom_ext_add_old_cb_wrap)
            continue;

        /* Old style API wrapper. Need to free the arguments too */
        OPENSSL_free(meth->add_arg);
        OPENSSL_free(meth->parse_arg);
    }
R
Rich Salz 已提交
295
    OPENSSL_free(exts->meths);
296
}
D
Dr. Stephen Henson 已提交
297

298 299
/* Return true if a client custom extension exists, false otherwise */
int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type)
300
{
301 302
    return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type,
                           NULL) != NULL;
303 304
}

305
static int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role,
306 307
                                 unsigned int ext_type,
                                 unsigned int context,
308 309
                                 SSL_custom_ext_add_cb_ex add_cb,
                                 SSL_custom_ext_free_cb_ex free_cb,
310
                                 void *add_arg,
311
                                 SSL_custom_ext_parse_cb_ex parse_cb,
312 313 314
                                 void *parse_arg)
{
    custom_ext_methods *exts = &ctx->cert->custext;
315
    custom_ext_method *meth, *tmp;
316

317 318 319 320
    /*
     * Check application error: if add_cb is not set free_cb will never be
     * called.
     */
321
    if (add_cb == NULL && free_cb != NULL)
322
        return 0;
323 324 325 326 327 328 329 330 331 332 333 334 335

#ifndef OPENSSL_NO_CT
    /*
     * We don't want applications registering callbacks for SCT extensions
     * whilst simultaneously using the built-in SCT validation features, as
     * these two things may not play well together.
     */
    if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp
            && (context & SSL_EXT_CLIENT_HELLO) != 0
            && SSL_CTX_ct_is_enabled(ctx))
        return 0;
#endif

336 337 338 339
    /*
     * Don't add if extension supported internally, but make exception
     * for extension types that previously were not supported, but now are.
     */
340 341
    if (SSL_extension_supported(ext_type)
            && ext_type != TLSEXT_TYPE_signed_certificate_timestamp)
342
        return 0;
343

344 345 346 347
    /* Extension type must fit in 16 bits */
    if (ext_type > 0xffff)
        return 0;
    /* Search for duplicate */
348
    if (custom_ext_find(exts, role, ext_type, NULL))
349
        return 0;
350 351
    tmp = OPENSSL_realloc(exts->meths,
                          (exts->meths_count + 1) * sizeof(custom_ext_method));
352
    if (tmp == NULL)
353
        return 0;
D
Dr. Stephen Henson 已提交
354

355
    exts->meths = tmp;
356
    meth = exts->meths + exts->meths_count;
357
    memset(meth, 0, sizeof(*meth));
358
    meth->role = role;
359
    meth->context = context;
360 361 362 363 364 365 366 367 368
    meth->parse_cb = parse_cb;
    meth->add_cb = add_cb;
    meth->free_cb = free_cb;
    meth->ext_type = ext_type;
    meth->add_arg = add_arg;
    meth->parse_arg = parse_arg;
    exts->meths_count++;
    return 1;
}
D
Dr. Stephen Henson 已提交
369

370 371
static int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role,
                              unsigned int ext_type,
372 373 374 375 376
                              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)
377
{
378
    custom_ext_add_cb_wrap *add_cb_wrap
379
        = OPENSSL_malloc(sizeof(*add_cb_wrap));
380
    custom_ext_parse_cb_wrap *parse_cb_wrap
381
        = OPENSSL_malloc(sizeof(*parse_cb_wrap));
382 383 384 385 386 387 388 389 390 391 392 393 394 395
    int ret;

    if (add_cb_wrap == NULL || parse_cb_wrap == NULL) {
        OPENSSL_free(add_cb_wrap);
        OPENSSL_free(parse_cb_wrap);
        return 0;
    }

    add_cb_wrap->add_arg = add_arg;
    add_cb_wrap->add_cb = add_cb;
    add_cb_wrap->free_cb = free_cb;
    parse_cb_wrap->parse_arg = parse_arg;
    parse_cb_wrap->parse_cb = parse_cb;

396
    ret = add_custom_ext_intern(ctx, role, ext_type,
397 398 399 400 401 402 403 404 405 406 407 408 409
                                context,
                                custom_ext_add_old_cb_wrap,
                                custom_ext_free_old_cb_wrap,
                                add_cb_wrap,
                                custom_ext_parse_old_cb_wrap,
                                parse_cb_wrap);

    if (!ret) {
        OPENSSL_free(add_cb_wrap);
        OPENSSL_free(parse_cb_wrap);
    }

    return ret;
410 411
}

412
/* Application level functions to add the old custom extension callbacks */
413
int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
414 415
                                  custom_ext_add_cb add_cb,
                                  custom_ext_free_cb free_cb,
416
                                  void *add_arg,
E
Emilia Kasper 已提交
417
                                  custom_ext_parse_cb parse_cb, void *parse_arg)
418
{
419
    return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type,
420 421 422 423 424
                              SSL_EXT_TLS1_2_AND_BELOW_ONLY
                              | SSL_EXT_CLIENT_HELLO
                              | SSL_EXT_TLS1_2_SERVER_HELLO
                              | SSL_EXT_IGNORE_ON_RESUMPTION,
                              add_cb, free_cb, add_arg, parse_cb, parse_arg);
425
}
D
Dr. Stephen Henson 已提交
426

427
int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
428 429
                                  custom_ext_add_cb add_cb,
                                  custom_ext_free_cb free_cb,
430
                                  void *add_arg,
E
Emilia Kasper 已提交
431
                                  custom_ext_parse_cb parse_cb, void *parse_arg)
432
{
433
    return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type,
434 435 436 437 438 439 440 441 442
                              SSL_EXT_TLS1_2_AND_BELOW_ONLY
                              | SSL_EXT_CLIENT_HELLO
                              | SSL_EXT_TLS1_2_SERVER_HELLO
                              | SSL_EXT_IGNORE_ON_RESUMPTION,
                              add_cb, free_cb, add_arg, parse_cb, parse_arg);
}

int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
                           unsigned int context,
443 444
                           SSL_custom_ext_add_cb_ex add_cb,
                           SSL_custom_ext_free_cb_ex free_cb,
445
                           void *add_arg,
446
                           SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg)
447
{
448 449
    return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb,
                                 free_cb, add_arg, parse_cb, parse_arg);
450
}
451 452

int SSL_extension_supported(unsigned int ext_type)
453 454 455 456
{
    switch (ext_type) {
        /* Internally supported extensions. */
    case TLSEXT_TYPE_application_layer_protocol_negotiation:
M
Matt Caswell 已提交
457
#ifndef OPENSSL_NO_EC
458
    case TLSEXT_TYPE_ec_point_formats:
459
    case TLSEXT_TYPE_supported_groups:
M
Matt Caswell 已提交
460 461
    case TLSEXT_TYPE_key_share:
#endif
M
Matt Caswell 已提交
462
#ifndef OPENSSL_NO_NEXTPROTONEG
463
    case TLSEXT_TYPE_next_proto_neg:
M
Matt Caswell 已提交
464
#endif
465 466 467 468 469
    case TLSEXT_TYPE_padding:
    case TLSEXT_TYPE_renegotiate:
    case TLSEXT_TYPE_server_name:
    case TLSEXT_TYPE_session_ticket:
    case TLSEXT_TYPE_signature_algorithms:
M
Matt Caswell 已提交
470
#ifndef OPENSSL_NO_SRP
471
    case TLSEXT_TYPE_srp:
M
Matt Caswell 已提交
472 473
#endif
#ifndef OPENSSL_NO_OCSP
474
    case TLSEXT_TYPE_status_request:
M
Matt Caswell 已提交
475 476
#endif
#ifndef OPENSSL_NO_CT
477
    case TLSEXT_TYPE_signed_certificate_timestamp:
M
Matt Caswell 已提交
478 479
#endif
#ifndef OPENSSL_NO_SRTP
480
    case TLSEXT_TYPE_use_srtp:
481
#endif
M
Matt Caswell 已提交
482
    case TLSEXT_TYPE_encrypt_then_mac:
483 484
    case TLSEXT_TYPE_supported_versions:
    case TLSEXT_TYPE_extended_master_secret:
M
Matt Caswell 已提交
485 486 487 488 489
    case TLSEXT_TYPE_psk_kex_modes:
    case TLSEXT_TYPE_cookie:
    case TLSEXT_TYPE_early_data:
    case TLSEXT_TYPE_certificate_authorities:
    case TLSEXT_TYPE_psk:
490 491 492 493 494
        return 1;
    default:
        return 0;
    }
}