Commit 6b473aca authored by Matt Caswell's avatar Matt Caswell
Browse files

Refactor ClientHello extension parsing



This builds on the work started in 1ab3836b and extends is so that
each extension has its own identified parsing functions, as well as an
allowed context identifying which messages and protocols it is relevant for.
Subsequent commits will do a similar job for the ServerHello extensions.
This will enable us to have common functions for processing extension blocks
no matter which of the multiple messages they are received from. In TLSv1.3
a number of different messages have extension blocks, and some extensions
have moved from one message to another when compared to TLSv1.2.

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 fadd9a1e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2280,6 +2280,8 @@ int ERR_load_SSL_strings(void);
# define SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE          377
# define SSL_F_TLS_GET_MESSAGE_BODY                       351
# define SSL_F_TLS_GET_MESSAGE_HEADER                     387
# define SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE            445
# define SSL_F_TLS_PARSE_CLIENTHELLO_USE_SRTP             446
# define SSL_F_TLS_POST_PROCESS_CLIENT_HELLO              378
# define SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE       384
# define SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE             360
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ LIBS=../libssl
SOURCE[../libssl]=\
        pqueue.c packet.c \
        statem/statem_srvr.c statem/statem_clnt.c  s3_lib.c  s3_enc.c record/rec_layer_s3.c \
        statem/statem_lib.c statem/statem_extensions.c s3_cbc.c s3_msg.c \
        statem/statem_lib.c statem/extensions.c s3_cbc.c s3_msg.c \
        methods.c   t1_lib.c  t1_enc.c tls13_enc.c t1_ext.c \
        d1_lib.c  record/rec_layer_d1.c d1_msg.c \
        statem/statem_dtls.c d1_srtp.c \
+0 −67
Original line number Diff line number Diff line
@@ -137,73 +137,6 @@ SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s)
    return s->srtp_profile;
}

int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al)
{
    SRTP_PROTECTION_PROFILE *sprof;
    STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
    unsigned int ct, mki_len, id;
    int i, srtp_pref;
    PACKET subpkt;

    /* Pull off the length of the cipher suite list  and check it is even */
    if (!PACKET_get_net_2(pkt, &ct)
        || (ct & 1) != 0 || !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
               SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
        *al = SSL_AD_DECODE_ERROR;
        return 1;
    }

    srvr = SSL_get_srtp_profiles(s);
    s->srtp_profile = NULL;
    /* Search all profiles for a match initially */
    srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);

    while (PACKET_remaining(&subpkt)) {
        if (!PACKET_get_net_2(&subpkt, &id)) {
            SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
                   SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
            *al = SSL_AD_DECODE_ERROR;
            return 1;
        }

        /*
         * Only look for match in profiles of higher preference than
         * current match.
         * If no profiles have been have been configured then this
         * does nothing.
         */
        for (i = 0; i < srtp_pref; i++) {
            sprof = sk_SRTP_PROTECTION_PROFILE_value(srvr, i);
            if (sprof->id == id) {
                s->srtp_profile = sprof;
                srtp_pref = i;
                break;
            }
        }
    }

    /*
     * Now extract the MKI value as a sanity check, but discard it for now
     */
    if (!PACKET_get_1(pkt, &mki_len)) {
        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
               SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
        *al = SSL_AD_DECODE_ERROR;
        return 1;
    }

    if (!PACKET_forward(pkt, mki_len)
        || PACKET_remaining(pkt)) {
        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
               SSL_R_BAD_SRTP_MKI_VALUE);
        *al = SSL_AD_DECODE_ERROR;
        return 1;
    }

    return 0;
}

int ssl_parse_serverhello_use_srtp_ext(SSL *s, PACKET *pkt, int *al)
{
    unsigned int id, ct, mki;
+4 −0
Original line number Diff line number Diff line
@@ -290,6 +290,10 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     "tls_construct_server_key_exchange"},
    {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_KEY_SHARE),
     "tls_parse_clienthello_key_share"},
    {ERR_FUNC(SSL_F_TLS_PARSE_CLIENTHELLO_USE_SRTP),
     "tls_parse_clienthello_use_srtp"},
    {ERR_FUNC(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO),
     "tls_post_process_client_hello"},
    {ERR_FUNC(SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE),
+8 −4
Original line number Diff line number Diff line
@@ -1636,8 +1636,12 @@ typedef struct ssl3_comp_st {
# endif

typedef struct raw_extension_st {
    /* The type of the extension */
    unsigned int type;
    /* Raw packet data for the extension */
    PACKET data;
    /* Set to 1 if we have already parsed the extension or 0 otherwise */
    int parsed;
} RAW_EXTENSION;

#define MAX_COMPRESSIONS_SIZE   255
@@ -2067,9 +2071,12 @@ __owur EVP_PKEY *ssl_generate_pkey_curve(int id);
__owur int tls1_shared_list(SSL *s,
                            const unsigned char *l1, size_t l1len,
                            const unsigned char *l2, size_t l2len, int nmatch);
__owur int tls_curve_allowed(SSL *s, const unsigned char *curve, int op);
__owur  int tls1_get_curvelist(SSL *s, int sess, const unsigned char **pcurves,
                               size_t *num_curves);

__owur int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al);
__owur int ssl_add_serverhello_tlsext(SSL *s, WPACKET *pkt, int *al);
__owur int ssl_parse_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello);
void ssl_set_default_md(SSL *s);
__owur int tls1_set_server_sigalgs(SSL *s);
__owur int ssl_check_clienthello_tlsext_late(SSL *s, int *al);
@@ -2081,7 +2088,6 @@ __owur RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts,
                                                unsigned int type);
__owur int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
                                      SSL_SESSION **ret);
__owur int tls_check_client_ems_support(SSL *s, const CLIENTHELLO_MSG *hello);

__owur int tls12_get_sigandhash(WPACKET *pkt, const EVP_PKEY *pk,
                                const EVP_MD *md);
@@ -2112,7 +2118,6 @@ __owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md);
void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
__owur int ssl_add_serverhello_renegotiate_ext(SSL *s, WPACKET *pkt);
__owur int ssl_parse_serverhello_renegotiate_ext(SSL *s, PACKET *pkt, int *al);
__owur int ssl_parse_clienthello_renegotiate_ext(SSL *s, PACKET *pkt, int *al);
__owur long ssl_get_algorithm2(SSL *s);
__owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
                              const unsigned char *psig, size_t psiglen);
@@ -2124,7 +2129,6 @@ __owur int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
void ssl_set_client_disabled(SSL *s);
__owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op);

__owur int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al);
__owur int ssl_parse_serverhello_use_srtp_ext(SSL *s, PACKET *pkt, int *al);

__owur int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen,
Loading