Skip to content
extensions.c 33.4 KiB
Newer Older
/*
 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
 *
 * 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
 */

#include <stdlib.h>
#include <openssl/ocsp.h>
#include "../ssl_locl.h"
#include "statem_locl.h"

static int tls_parse_clienthello_renegotiate(SSL *s, PACKET *pkt, int *al);
static int tls_parse_clienthello_server_name(SSL *s, PACKET *pkt, int *al);
#ifndef OPENSSL_NO_SRP
static int tls_parse_clienthello_srp(SSL *s, PACKET *pkt, int *al);
#endif
#ifndef OPENSSL_NO_EC
static int tls_parse_clienthello_ec_pt_formats(SSL *s, PACKET *pkt, int *al);
static int tls_parse_clienthello_supported_groups(SSL *s, PACKET *pkt, int *al);
#endif
static int tls_parse_clienthello_session_ticket(SSL *s, PACKET *pkt, int *al);
static int tls_parse_clienthello_sig_algs(SSL *s, PACKET *pkt, int *al);
static int tls_parse_clienthello_status_request(SSL *s, PACKET *pkt, int *al);
#ifndef OPENSSL_NO_NEXTPROTONEG
static int tls_parse_clienthello_npn(SSL *s, PACKET *pkt, int *al);
#endif
static int tls_parse_clienthello_alpn(SSL *s, PACKET *pkt, int *al);
#ifndef OPENSSL_NO_SRTP
static int tls_parse_clienthello_use_srtp(SSL *s, PACKET *pkt, int *al);
#endif
static int tls_parse_clienthello_etm(SSL *s, PACKET *pkt, int *al);
static int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al);
static int tls_parse_clienthello_ems(SSL *s, PACKET *pkt, int *al);

typedef struct {
    /* The ID for the extension */
    unsigned int type;
    int (*server_parse)(SSL *s, PACKET *pkt, int *al);
    int (*client_parse)(SSL *s, PACKET *pkt, int *al);
    unsigned int context;
} EXTENSION_DEFINITION;

static const EXTENSION_DEFINITION ext_defs[] = {
    {
        TLSEXT_TYPE_renegotiate,
        tls_parse_clienthello_renegotiate,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_SSL3_ALLOWED
        | EXT_TLS1_2_AND_BELOW_ONLY
    },
    {
        TLSEXT_TYPE_server_name,
        tls_parse_clienthello_server_name,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
        | EXT_TLS1_3_ENCRYPTED_EXTENSIONS
    },
#ifndef OPENSSL_NO_SRP
    {
        TLSEXT_TYPE_srp,
        tls_parse_clienthello_srp,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
#endif
#ifndef OPENSSL_NO_EC
    {
        TLSEXT_TYPE_ec_point_formats,
        tls_parse_clienthello_ec_pt_formats,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
    {
        TLSEXT_TYPE_supported_groups,
        tls_parse_clienthello_supported_groups,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_3_ENCRYPTED_EXTENSIONS
    },
#endif
    {
        TLSEXT_TYPE_session_ticket,
        tls_parse_clienthello_session_ticket,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
    {
        TLSEXT_TYPE_signature_algorithms,
        tls_parse_clienthello_sig_algs,
        NULL,
        EXT_CLIENT_HELLO
    },
    {
        TLSEXT_TYPE_status_request,
        tls_parse_clienthello_status_request,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_3_CERTIFICATE
    },
#ifndef OPENSSL_NO_NEXTPROTONEG
    {
        TLSEXT_TYPE_next_proto_neg,
        tls_parse_clienthello_npn,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
#endif
    {
        TLSEXT_TYPE_application_layer_protocol_negotiation,
        tls_parse_clienthello_alpn,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
        | EXT_TLS1_3_ENCRYPTED_EXTENSIONS
    },
    {
        TLSEXT_TYPE_use_srtp,
        tls_parse_clienthello_use_srtp,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
        | EXT_TLS1_3_ENCRYPTED_EXTENSIONS | EXT_DTLS_ONLY
    },
    {
        TLSEXT_TYPE_encrypt_then_mac,
        tls_parse_clienthello_etm,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
    {
        TLSEXT_TYPE_signed_certificate_timestamp,
        /*
         * No server side support for this, but can be provided by a custom
         * extension. This is an exception to the rule that custom extensions
         * cannot override built in ones.
         */
        NULL,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_3_CERTIFICATE
    },
    {
        TLSEXT_TYPE_extended_master_secret,
        tls_parse_clienthello_ems,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
    {
        TLSEXT_TYPE_supported_versions,
        /* Processed inline as part of version selection */
        NULL,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS_IMPLEMENTATION_ONLY
    },
    {
        TLSEXT_TYPE_padding,
        /* We send this, but don't read it */
        NULL,
        NULL,
        EXT_CLIENT_HELLO
    },
    {
        TLSEXT_TYPE_key_share,
        tls_parse_clienthello_key_share,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_3_SERVER_HELLO
        | EXT_TLS1_3_HELLO_RETRY_REQUEST | EXT_TLS_IMPLEMENTATION_ONLY
        | EXT_TLS1_3_ONLY
    }
};

/*
 * Comparison function used in a call to qsort (see tls_collect_extensions()
 * below.)
 * The two arguments |p1| and |p2| are expected to be pointers to RAW_EXTENSIONs
 *
 * Returns:
 *  1 if the type for p1 is greater than p2
 *  0 if the type for p1 and p2 are the same
 * -1 if the type for p1 is less than p2
 */
static int compare_extensions(const void *p1, const void *p2)
{
    const RAW_EXTENSION *e1 = (const RAW_EXTENSION *)p1;
    const RAW_EXTENSION *e2 = (const RAW_EXTENSION *)p2;

    if (e1->type < e2->type)
        return -1;
    else if (e1->type > e2->type)
        return 1;

    return 0;
}

/*
 * Verify whether we are allowed to use the extension |type| in the current
 * |context|. Returns 1 to indicate the extension is allowed or unknown or 0 to
 * indicate the extension is not allowed.
 */
static int verify_extension(SSL *s, unsigned int context, unsigned int type)
{
    size_t i;
Loading
Loading full blame…