Commit 805a2e9e authored by Matt Caswell's avatar Matt Caswell
Browse files

Provide server side extension init and finalisation functions



Perl changes reviewed by Richard Levitte. Non-perl changes reviewed by Rich
Salz

Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
parent 68db4dda
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2308,6 +2308,7 @@ int ERR_load_SSL_strings(void);
# define SSL_F_TLS_CONSTRUCT_SERVER_SESSION_TICKET        460
# define SSL_F_TLS_CONSTRUCT_SERVER_STATUS_REQUEST        461
# define SSL_F_TLS_CONSTRUCT_SERVER_USE_SRTP              462
# define SSL_F_TLS_EXT_FINAL_RENEGOTIATE                  483
# define SSL_F_TLS_GET_MESSAGE_BODY                       351
# define SSL_F_TLS_GET_MESSAGE_HEADER                     387
# define SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT               449
+1 −0
Original line number Diff line number Diff line
@@ -338,6 +338,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     "tls_construct_server_status_request"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_USE_SRTP),
     "tls_construct_server_use_srtp"},
    {ERR_FUNC(SSL_F_TLS_EXT_FINAL_RENEGOTIATE), "tls_ext_final_renegotiate"},
    {ERR_FUNC(SSL_F_TLS_GET_MESSAGE_BODY), "tls_get_message_body"},
    {ERR_FUNC(SSL_F_TLS_GET_MESSAGE_HEADER), "tls_get_message_header"},
    {ERR_FUNC(SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT),
+232 −33
Original line number Diff line number Diff line
@@ -11,12 +11,31 @@
#include "../ssl_locl.h"
#include "statem_locl.h"

static int tls_ext_final_renegotiate(SSL *s, unsigned int context, int sent,
                                     int *al);
static int tls_ext_init_server_name(SSL *s, unsigned int context);
static int tls_ext_final_server_name(SSL *s, unsigned int context, int sent,
                                     int *al);
static int tls_ext_init_status_request(SSL *s, unsigned int context);
#ifndef OPENSSL_NO_NEXTPROTONEG
static int tls_ext_init_npn(SSL *s, unsigned int context);
#endif
static int tls_ext_init_alpn(SSL *s, unsigned int context);
static int tls_ext_init_sig_algs(SSL *s, unsigned int context);
#ifndef OPENSSL_NO_SRP
static int tls_ext_init_srp(SSL *s, unsigned int context);
#endif
static int tls_ext_init_etm(SSL *s, unsigned int context);
#ifndef OPENSSL_NO_SRTP
static int tls_ext_init_srtp(SSL *s, unsigned int context);
#endif

typedef struct {
    /* The ID for the extension */
    unsigned int type;
    /*
     * Initialise extension before parsing. Always called even if extension not
     * present
     * Initialise extension before parsing. Always called for relevant contexts
     * even if extension not present
     */
    int (*init_ext)(SSL *s, unsigned int context);
    /* Parse extension received by server from client */
@@ -28,10 +47,11 @@ typedef struct {
    /* Construct extension sent by client */
    int (*construct_client_ext)(SSL *s, WPACKET *pkt, int *al);
    /*
     * Finalise extension after parsing. Always called even if extension not
     * present
     * Finalise extension after parsing. Always called where an extensions was
     * initialised even if the extension was not present. |sent| is set to 1 if
     * the extension was seen, or 0 otherwise.
     */
    int (*finalise_ext)(SSL *s, unsigned int context);
    int (*finalise_ext)(SSL *s, unsigned int context, int sent, int *al);
    unsigned int context;
} EXTENSION_DEFINITION;

@@ -48,31 +68,31 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        tls_parse_server_renegotiate,
        tls_construct_server_renegotiate,
        tls_construct_client_renegotiate,
        NULL,
        tls_ext_final_renegotiate,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_SSL3_ALLOWED
        | EXT_TLS1_2_AND_BELOW_ONLY
    },
    {
        TLSEXT_TYPE_server_name,
        NULL,
        tls_ext_init_server_name,
        tls_parse_client_server_name,
        tls_parse_server_server_name,
        tls_construct_server_server_name,
        tls_construct_client_server_name,
        NULL,
        tls_ext_final_server_name,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
        | EXT_TLS1_3_ENCRYPTED_EXTENSIONS
    },
#ifndef OPENSSL_NO_SRP
    {
        TLSEXT_TYPE_srp,
        NULL,
        tls_ext_init_srp,
        tls_parse_client_srp,
        NULL,
        NULL,
        tls_construct_client_srp,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
        EXT_CLIENT_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
#endif
#ifndef OPENSSL_NO_EC
@@ -109,7 +129,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
    },
    {
        TLSEXT_TYPE_signature_algorithms,
        NULL,
        tls_ext_init_sig_algs,
        tls_parse_client_sig_algs,
        NULL,
        NULL,
@@ -120,7 +140,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
#ifndef OPENSSL_NO_OCSP
    {
        TLSEXT_TYPE_status_request,
        NULL,
        tls_ext_init_status_request,
        tls_parse_client_status_request,
        tls_parse_server_status_request,
        tls_construct_server_status_request,
@@ -133,7 +153,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
#ifndef OPENSSL_NO_NEXTPROTONEG
    {
        TLSEXT_TYPE_next_proto_neg,
        NULL,
        tls_ext_init_npn,
        tls_parse_client_npn,
        tls_parse_server_npn,
        tls_construct_server_next_proto_neg,
@@ -144,7 +164,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
#endif
    {
        TLSEXT_TYPE_application_layer_protocol_negotiation,
        NULL,
        tls_ext_init_alpn,
        tls_parse_client_alpn,
        tls_parse_server_alpn,
        tls_construct_server_alpn,
@@ -156,7 +176,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
#ifndef OPENSSL_NO_SRTP
    {
        TLSEXT_TYPE_use_srtp,
        NULL,
        tls_ext_init_srtp,
        tls_parse_client_use_srtp,
        tls_parse_server_use_srtp,
        tls_construct_server_use_srtp,
@@ -168,7 +188,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
#endif
    {
        TLSEXT_TYPE_encrypt_then_mac,
        NULL,
        tls_ext_init_etm,
        tls_parse_client_etm,
        tls_parse_server_etm,
        tls_construct_server_etm,
@@ -329,6 +349,21 @@ static int find_extension_definition(SSL *s, unsigned int type,
    return 0;
}

static int extension_is_relevant(SSL *s, unsigned int extctx,
                                 unsigned int thisctx)
{
    if ((SSL_IS_DTLS(s)
                && (extctx & EXT_TLS_IMPLEMENTATION_ONLY) != 0)
            || (s->version == SSL3_VERSION
                    && (extctx & EXT_SSL3_ALLOWED) == 0)
            || (SSL_IS_TLS13(s)
                && (extctx & EXT_TLS1_2_AND_BELOW_ONLY) != 0)
            || (!SSL_IS_TLS13(s) && (extctx & EXT_TLS1_3_ONLY) != 0))
        return 0;

    return 1;
}

/*
 * Gather a list of all the extensions from the data in |packet]. |context|
 * tells us which message this extension is for. Ttls_parse_server_ec_pt_formatshe raw extension data is
@@ -413,12 +448,20 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
     */
    for (i = 0; i < OSSL_NELEM(ext_defs); i++) {
        if(ext_defs[i].init_ext != NULL && (ext_defs[i].context & context) != 0
                && extension_is_relevant(s, ext_defs[i].context, context)
                && !ext_defs[i].init_ext(s, context)) {
            *ad = SSL_AD_INTERNAL_ERROR;
            goto err;
        }
    }

    /*
     * Initialise server side custom extensions. Client side is done during
     * construction of extensions for the ClientHello.
     */
    if ((context & (EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_3_SERVER_HELLO)) != 0)
        custom_ext_init(&s->cert->srv_ext);

    *res = raw_extensions;
    *numfound = num_extensions;
    return 1;
@@ -429,11 +472,13 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
}

/*
 * Parse all remaining extensions that have not yet been parsed. Also calls the
 * finalisation for all extensions at the end. Returns 1 for success or 0 for
 * failure. On failure, |*al| is populated with a suitable alert code.
 * Runs the parsers for all of the extensions in the given list |exts|, which
 * should have |numexts| extensions in it. The parsers are only run if they are
 * applicable for the given |context| and the parser has not already been run
 * for that extension. Returns 1 on success or 0 on failure. In the event of a
 * failure |*al| is populated with a suitable alert code.
 */
int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts,
static int tls_parse_extension_list(SSL *s, int context, RAW_EXTENSION *exts,
                                    size_t numexts, int *al)
{
    size_t loop;
@@ -461,14 +506,7 @@ int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts,
                               : extdef->parse_server_ext;

            /* Check if extension is defined for our protocol. If not, skip */
            if ((SSL_IS_DTLS(s)
                        && (extdef->context & EXT_TLS_IMPLEMENTATION_ONLY) != 0)
                    || (s->version == SSL3_VERSION
                            && (extdef->context & EXT_SSL3_ALLOWED) == 0)
                    || (SSL_IS_TLS13(s)
                        && (extdef->context & EXT_TLS1_2_AND_BELOW_ONLY) != 0)
                    || (!SSL_IS_TLS13(s)
                        && (extdef->context & EXT_TLS1_3_ONLY) != 0))
            if (!extension_is_relevant(s, extdef->context, context))
                continue;
        }

@@ -497,15 +535,44 @@ int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts,
            return 0;
    }

    return 1;
}

/*
 * Parse all remaining extensions that have not yet been parsed. Also calls the
 * finalisation for all extensions at the end. The given extensions must be in
 * order of type (which happens by default during collection). Returns 1 for
 * success or 0 for failure. On failure, |*al| is populated with a suitable
 * alert code.
 */
int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts,
                             size_t numexts, int *al)
{
    size_t loop;

    if (!tls_parse_extension_list(s, context, exts, numexts, al))
        return 0;

    /*
     * Finalise all known extensions relevant to this context, whether we have
     * found them or not
     */
    for (loop = 0; loop < OSSL_NELEM(ext_defs); loop++) {
        if(ext_defs[loop].finalise_ext != NULL
                && (ext_defs[loop].context & context) != 0
                && !ext_defs[loop].finalise_ext(s, context)) {
            *al = SSL_AD_INTERNAL_ERROR;
                && (ext_defs[loop].context & context) != 0) {
            size_t curr;

            /*
             * Work out whether this extension was sent or not. The sent
             * extensions in |exts| are sorted by order of type
             */
            for (curr = 0; curr < numexts
                           && exts[curr].type < ext_defs[loop].type; curr++)
                continue;

            if (!ext_defs[loop].finalise_ext(s, context,
                    (curr < numexts && exts[curr].type == ext_defs[loop].type),
                    al))
            return 0;
        }
    }
@@ -527,7 +594,7 @@ int tls_parse_extension(SSL *s, int type, int context, RAW_EXTENSION *exts,
    if (ext == NULL)
        return 1;

    return tls_parse_all_extensions(s, context, ext, 1, al);
    return tls_parse_extension_list(s, context, ext, 1, al);
}

int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
@@ -624,3 +691,135 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,

    return 1;
}

static int tls_ext_final_renegotiate(SSL *s, unsigned int context, int sent,
                                     int *al)
{
    if (!s->server)
        return 1;

    /* Need RI if renegotiating */
    if (s->renegotiate
            && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
            && !sent) {
        *al = SSL_AD_HANDSHAKE_FAILURE;
        SSLerr(SSL_F_TLS_EXT_FINAL_RENEGOTIATE,
               SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
        return 0;
    }

    return 1;
}

static int tls_ext_init_server_name(SSL *s, unsigned int context)
{
    if (s->server)
        s->servername_done = 0;

    return 1;
}

/* Call the servername callback. Returns 1 for success or 0 for failure. */
static int tls_ext_final_server_name(SSL *s, unsigned int context, int sent,
                                     int *al)
{
    int ret = SSL_TLSEXT_ERR_NOACK;
    int altmp = SSL_AD_UNRECOGNIZED_NAME;

    if (!s->server)
        return 1;

    if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
        ret = s->ctx->tlsext_servername_callback(s, &altmp,
                                                 s->ctx->tlsext_servername_arg);
    else if (s->initial_ctx != NULL
             && s->initial_ctx->tlsext_servername_callback != 0)
        ret = s->initial_ctx->tlsext_servername_callback(s, &altmp,
                                       s->initial_ctx->tlsext_servername_arg);

    switch (ret) {
    case SSL_TLSEXT_ERR_ALERT_FATAL:
        *al = altmp;
        return 0;

    case SSL_TLSEXT_ERR_ALERT_WARNING:
        *al = altmp;
        return 1;

    case SSL_TLSEXT_ERR_NOACK:
        s->servername_done = 0;
        return 1;

    default:
        return 1;
    }
}

static int tls_ext_init_status_request(SSL *s, unsigned int context)
{
    if (s->server)
        s->tlsext_status_type = -1;

    return 1;
}

#ifndef OPENSSL_NO_NEXTPROTONEG
static int tls_ext_init_npn(SSL *s, unsigned int context)
{
    if (s->server)
        s->s3->next_proto_neg_seen = 0;

    return 1;
}
#endif

static int tls_ext_init_alpn(SSL *s, unsigned int context)
{
    if (s->server) {
        OPENSSL_free(s->s3->alpn_selected);
        s->s3->alpn_selected = NULL;
        s->s3->alpn_selected_len = 0;
        OPENSSL_free(s->s3->alpn_proposed);
        s->s3->alpn_proposed = NULL;
        s->s3->alpn_proposed_len = 0;
    }

    return 1;
}

static int tls_ext_init_sig_algs(SSL *s, unsigned int context)
{
    /* Clear any signature algorithms extension received */
    OPENSSL_free(s->s3->tmp.peer_sigalgs);
    s->s3->tmp.peer_sigalgs = NULL;

    return 1;
}

#ifndef OPENSSL_NO_SRP
static int tls_ext_init_srp(SSL *s, unsigned int context)
{
    OPENSSL_free(s->srp_ctx.login);
    s->srp_ctx.login = NULL;

    return 1;
}
#endif

static int tls_ext_init_etm(SSL *s, unsigned int context)
{
    if (s->server)
        s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;

    return 1;
}

#ifndef OPENSSL_NO_SRTP
static int tls_ext_init_srtp(SSL *s, unsigned int context)
{
    if (s->server)
        s->srtp_profile = NULL;

    return 1;
}
#endif
+0 −108
Original line number Diff line number Diff line
@@ -648,71 +648,6 @@ int tls_parse_client_ems(SSL *s, PACKET *pkt, int *al)
    return 1;
}

#ifndef OPENSSL_NO_EC
/*-
 * ssl_check_for_safari attempts to fingerprint Safari using OS X
 * SecureTransport using the TLS extension block in |hello|.
 * Safari, since 10.6, sends exactly these extensions, in this order:
 *   SNI,
 *   elliptic_curves
 *   ec_point_formats
 *
 * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
 * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
 * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
 * 10.8..10.8.3 (which don't work).
 */
static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello)
{
    unsigned int type;
    PACKET sni, tmppkt;
    size_t ext_len;

    static const unsigned char kSafariExtensionsBlock[] = {
        0x00, 0x0a,             /* elliptic_curves extension */
        0x00, 0x08,             /* 8 bytes */
        0x00, 0x06,             /* 6 bytes of curve ids */
        0x00, 0x17,             /* P-256 */
        0x00, 0x18,             /* P-384 */
        0x00, 0x19,             /* P-521 */

        0x00, 0x0b,             /* ec_point_formats */
        0x00, 0x02,             /* 2 bytes */
        0x01,                   /* 1 point format */
        0x00,                   /* uncompressed */
        /* The following is only present in TLS 1.2 */
        0x00, 0x0d,             /* signature_algorithms */
        0x00, 0x0c,             /* 12 bytes */
        0x00, 0x0a,             /* 10 bytes */
        0x05, 0x01,             /* SHA-384/RSA */
        0x04, 0x01,             /* SHA-256/RSA */
        0x02, 0x01,             /* SHA-1/RSA */
        0x04, 0x03,             /* SHA-256/ECDSA */
        0x02, 0x03,             /* SHA-1/ECDSA */
    };

    /* Length of the common prefix (first two extensions). */
    static const size_t kSafariCommonExtensionsLength = 18;

    tmppkt = hello->extensions;

    if (!PACKET_forward(&tmppkt, 2)
        || !PACKET_get_net_2(&tmppkt, &type)
        || !PACKET_get_length_prefixed_2(&tmppkt, &sni)) {
        return;
    }

    if (type != TLSEXT_TYPE_server_name)
        return;

    ext_len = TLS1_get_client_version(s) >= TLS1_2_VERSION ?
        sizeof(kSafariExtensionsBlock) : kSafariCommonExtensionsLength;

    s->s3->is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock,
                                             ext_len);
}
#endif                          /* !OPENSSL_NO_EC */

/*
 * Process all remaining ClientHello extensions that we collected earlier and
 * haven't already processed.
@@ -724,37 +659,6 @@ static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello)
 */
int tls_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al)
{
    /* Reset various flags that might get set by extensions during parsing */
    s->servername_done = 0;
    s->tlsext_status_type = -1;
#ifndef OPENSSL_NO_NEXTPROTONEG
    s->s3->next_proto_neg_seen = 0;
#endif

    OPENSSL_free(s->s3->alpn_selected);
    s->s3->alpn_selected = NULL;
    s->s3->alpn_selected_len = 0;
    OPENSSL_free(s->s3->alpn_proposed);
    s->s3->alpn_proposed = NULL;
    s->s3->alpn_proposed_len = 0;

#ifndef OPENSSL_NO_EC
    if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
        ssl_check_for_safari(s, hello);
#endif                          /* !OPENSSL_NO_EC */

    /* Clear any signature algorithms extension received */
    OPENSSL_free(s->s3->tmp.peer_sigalgs);
    s->s3->tmp.peer_sigalgs = NULL;
    s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;

#ifndef OPENSSL_NO_SRP
    OPENSSL_free(s->srp_ctx.login);
    s->srp_ctx.login = NULL;
#endif

    s->srtp_profile = NULL;

    /*
     * We process the supported_groups extension first so that is done before
     * we get to key_share which needs to use the information in it.
@@ -764,18 +668,6 @@ int tls_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al)
        return 0;
    }

    /* Need RI if renegotiating */
    if (s->renegotiate
            && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
            && tls_get_extension_by_type(hello->pre_proc_exts,
                                         hello->num_extensions,
                                         TLSEXT_TYPE_renegotiate) == NULL) {
        *al = SSL_AD_HANDSHAKE_FAILURE;
        SSLerr(SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT,
               SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
        return 0;
    }

    return tls_parse_all_extensions(s, EXT_CLIENT_HELLO, hello->pre_proc_exts,
                                    hello->num_extensions, al);
}
+71 −41
Original line number Diff line number Diff line
@@ -1062,41 +1062,6 @@ int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt)
    return 1;
}

/*
 * Check the results of extension parsing. Currently just calls the servername
 * callback. Returns 1 for success or 0 for failure.
 */
static int tls_check_clienthello_tlsext(SSL *s)
{
    int ret = SSL_TLSEXT_ERR_NOACK;
    int al = SSL_AD_UNRECOGNIZED_NAME;

    if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
        ret = s->ctx->tlsext_servername_callback(s, &al,
                                                 s->ctx->tlsext_servername_arg);
    else if (s->initial_ctx != NULL
             && s->initial_ctx->tlsext_servername_callback != 0)
        ret = s->initial_ctx->tlsext_servername_callback(s, &al,
                                       s->initial_ctx->tlsext_servername_arg);

    switch (ret) {
    case SSL_TLSEXT_ERR_ALERT_FATAL:
        ssl3_send_alert(s, SSL3_AL_FATAL, al);
        return 0;

    case SSL_TLSEXT_ERR_ALERT_WARNING:
        ssl3_send_alert(s, SSL3_AL_WARNING, al);
        return 1;

    case SSL_TLSEXT_ERR_NOACK:
        s->servername_done = 0;
        return 1;

    default:
        return 1;
    }
}

/*
 * Parse the extensions in the ClientHello that were collected earlier. Returns
 * 1 for success or 0 for failure.
@@ -1105,20 +1070,80 @@ static int tls_parse_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello)
{
    int al = -1;

    custom_ext_init(&s->cert->srv_ext);


    if (tls_scan_clienthello_tlsext(s, hello, &al) <= 0) {
        ssl3_send_alert(s, SSL3_AL_FATAL, al);
        return 0;
    }

    if (!tls_check_clienthello_tlsext(s)) {
        SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT, SSL_R_CLIENTHELLO_TLSEXT);
        return 0;
    return 1;
}

    return 1;
#ifndef OPENSSL_NO_EC
/*-
 * ssl_check_for_safari attempts to fingerprint Safari using OS X
 * SecureTransport using the TLS extension block in |hello|.
 * Safari, since 10.6, sends exactly these extensions, in this order:
 *   SNI,
 *   elliptic_curves
 *   ec_point_formats
 *
 * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
 * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
 * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
 * 10.8..10.8.3 (which don't work).
 */
static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello)
{
    unsigned int type;
    PACKET sni, tmppkt;
    size_t ext_len;

    static const unsigned char kSafariExtensionsBlock[] = {
        0x00, 0x0a,             /* elliptic_curves extension */
        0x00, 0x08,             /* 8 bytes */
        0x00, 0x06,             /* 6 bytes of curve ids */
        0x00, 0x17,             /* P-256 */
        0x00, 0x18,             /* P-384 */
        0x00, 0x19,             /* P-521 */

        0x00, 0x0b,             /* ec_point_formats */
        0x00, 0x02,             /* 2 bytes */
        0x01,                   /* 1 point format */
        0x00,                   /* uncompressed */
        /* The following is only present in TLS 1.2 */
        0x00, 0x0d,             /* signature_algorithms */
        0x00, 0x0c,             /* 12 bytes */
        0x00, 0x0a,             /* 10 bytes */
        0x05, 0x01,             /* SHA-384/RSA */
        0x04, 0x01,             /* SHA-256/RSA */
        0x02, 0x01,             /* SHA-1/RSA */
        0x04, 0x03,             /* SHA-256/ECDSA */
        0x02, 0x03,             /* SHA-1/ECDSA */
    };

    /* Length of the common prefix (first two extensions). */
    static const size_t kSafariCommonExtensionsLength = 18;

    tmppkt = hello->extensions;

    if (!PACKET_forward(&tmppkt, 2)
        || !PACKET_get_net_2(&tmppkt, &type)
        || !PACKET_get_length_prefixed_2(&tmppkt, &sni)) {
        return;
    }

    if (type != TLSEXT_TYPE_server_name)
        return;

    ext_len = TLS1_get_client_version(s) >= TLS1_2_VERSION ?
        sizeof(kSafariExtensionsBlock) : kSafariCommonExtensionsLength;

    s->s3->is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock,
                                             ext_len);
}
#endif                          /* !OPENSSL_NO_EC */

MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
{
@@ -1494,6 +1519,11 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
        goto f_err;
    }

#ifndef OPENSSL_NO_EC
    if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
        ssl_check_for_safari(s, &clienthello);
#endif                          /* !OPENSSL_NO_EC */

    /* TLS extensions */
    if (!tls_parse_clienthello_tlsext(s, &clienthello)) {
        SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);