Commit 193b5d76 authored by Benjamin Kaduk's avatar Benjamin Kaduk Committed by Matt Caswell
Browse files

Add SSL_early_get1_extensions_present()



It is an API to be used from the early callback that indicates what
extensions were present in the ClientHello, and in what order.
This can be used to eliminate unneeded calls to SSL_early_get0_ext()
(which itself scales linearly in the number of extensions supported
by the library).

Reviewed-by: default avatarMatt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2976)
parent 0e1e4045
Loading
Loading
Loading
Loading
+14 −3
Original line number Original line Diff line number Diff line
@@ -2,7 +2,7 @@


=head1 NAME
=head1 NAME


SSL_CTX_set_early_cb, SSL_early_cb_fn, SSL_early_isv2, SSL_early_get0_legacy_version, SSL_early_get0_random, SSL_early_get0_session_id, SSL_early_get0_ciphers, SSL_early_get0_compression_methods, SSL_early_get0_ext - callback functions for early server-side ClientHello processing
SSL_CTX_set_early_cb, SSL_early_cb_fn, SSL_early_isv2, SSL_early_get0_legacy_version, SSL_early_get0_random, SSL_early_get0_session_id, SSL_early_get0_ciphers, SSL_early_get0_compression_methods, SSL_early_get1_extensions_present, SSL_early_get0_ext - callback functions for early server-side ClientHello processing


=head1 SYNOPSIS
=head1 SYNOPSIS


@@ -14,6 +14,7 @@ SSL_CTX_set_early_cb, SSL_early_cb_fn, SSL_early_isv2, SSL_early_get0_legacy_ver
 size_t SSL_early_get0_session_id(SSL *s, const unsigned char **out);
 size_t SSL_early_get0_session_id(SSL *s, const unsigned char **out);
 size_t SSL_early_get0_ciphers(SSL *s, const unsigned char **out);
 size_t SSL_early_get0_ciphers(SSL *s, const unsigned char **out);
 size_t SSL_early_get0_compression_methods(SSL *s, const unsigned char **out);
 size_t SSL_early_get0_compression_methods(SSL *s, const unsigned char **out);
 int SSL_early_get1_extensions_present(SSL *s, int **out, size_t *outlen);
 int SSL_early_get0_ext(SSL *s, int type, const unsigned char **out,
 int SSL_early_get0_ext(SSL *s, int type, const unsigned char **out,
                        size_t *outlen);
                        size_t *outlen);


@@ -53,6 +54,14 @@ from the ClientHello on a per-extension basis. For the provided wire
protocol extension type value, the extension value and length are returned
protocol extension type value, the extension value and length are returned
in the output parameters (if present).
in the output parameters (if present).


SSL_early_get1_extensions_present() can be used prior to SSL_early_get0_ext(),
to determine which extensions are present in the ClientHello before querying
for them.  The B<out> and B<outlen> parameters are both required, and on
success the caller must release the storage allocated for B<*out> using
OPENSSL_free().  The contents of B<*out> is an array of integers holding the
numerical value of the TLS extension types in the order they appear in the
ClientHello.  B<*outlen> contains the number of elements in the array.

=head1 NOTES
=head1 NOTES


The early callback provides a vast window of possibilities for application
The early callback provides a vast window of possibilities for application
@@ -88,6 +97,8 @@ assumed to be valid.
SSL_early_get0_ext() returns 1 if the extension of type 'type' is present, and
SSL_early_get0_ext() returns 1 if the extension of type 'type' is present, and
0 otherwise.
0 otherwise.


SSL_early_get1_extensions_present() returns 1 on success and 0 on failure.

=head1 SEE ALSO
=head1 SEE ALSO


L<ssl(7)>, L<SSL_CTX_set_tlsext_servername_callback(3)>,
L<ssl(7)>, L<SSL_CTX_set_tlsext_servername_callback(3)>,
@@ -97,8 +108,8 @@ L<SSL_bytes_to_cipher_list>


The SSL early callback, SSL_early_isv2(), SSL_early_get0_random(),
The SSL early callback, SSL_early_isv2(), SSL_early_get0_random(),
SSL_early_get0_session_id(), SSL_early_get0_ciphers(),
SSL_early_get0_session_id(), SSL_early_get0_ciphers(),
SSL_early_get0_compression_methods(), and SSL_early_get0_ext() were
SSL_early_get0_compression_methods(), SSL_early_get0_ext(), and
added in OpenSSL 1.1.1.
SSL_early_get1_extensions_present() were added in OpenSSL 1.1.1.


=head1 COPYRIGHT
=head1 COPYRIGHT


+1 −0
Original line number Original line Diff line number Diff line
@@ -1682,6 +1682,7 @@ size_t SSL_early_get0_random(SSL *s, const unsigned char **out);
size_t SSL_early_get0_session_id(SSL *s, const unsigned char **out);
size_t SSL_early_get0_session_id(SSL *s, const unsigned char **out);
size_t SSL_early_get0_ciphers(SSL *s, const unsigned char **out);
size_t SSL_early_get0_ciphers(SSL *s, const unsigned char **out);
size_t SSL_early_get0_compression_methods(SSL *s, const unsigned char **out);
size_t SSL_early_get0_compression_methods(SSL *s, const unsigned char **out);
int SSL_early_get1_extensions_present(SSL *s, int **out, size_t *outlen);
int SSL_early_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
int SSL_early_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
                       size_t *outlen);
                       size_t *outlen);


+32 −0
Original line number Original line Diff line number Diff line
@@ -4598,6 +4598,38 @@ size_t SSL_early_get0_compression_methods(SSL *s, const unsigned char **out)
    return s->clienthello->compressions_len;
    return s->clienthello->compressions_len;
}
}


int SSL_early_get1_extensions_present(SSL *s, int **out, size_t *outlen)
{
    RAW_EXTENSION *ext;
    int *present;
    size_t num = 0, i;

    if (s->clienthello == NULL || out == NULL || outlen == NULL)
        return 0;
    for (i = 0; i < s->clienthello->pre_proc_exts_len; i++) {
        ext = s->clienthello->pre_proc_exts + i;
        if (ext->present)
            num++;
    }
    present = OPENSSL_malloc(sizeof(*present) * num);
    if (present == NULL)
        return 0;
    for (i = 0; i < s->clienthello->pre_proc_exts_len; i++) {
        ext = s->clienthello->pre_proc_exts + i;
        if (ext->present) {
            if (ext->received_order >= num)
                goto err;
            present[ext->received_order] = ext->type;
        }
    }
    *out = present;
    *outlen = num;
    return 1;
 err:
    OPENSSL_free(present);
    return 0;
}

int SSL_early_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
int SSL_early_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
                       size_t *outlen)
                       size_t *outlen)
{
{
+2 −0
Original line number Original line Diff line number Diff line
@@ -668,6 +668,8 @@ typedef struct raw_extension_st {
    int parsed;
    int parsed;
    /* The type of this extension, i.e. a TLSEXT_TYPE_* value */
    /* The type of this extension, i.e. a TLSEXT_TYPE_* value */
    unsigned int type;
    unsigned int type;
    /* Track what order extensions are received in (0-based). */
    size_t received_order;
} RAW_EXTENSION;
} RAW_EXTENSION;


typedef struct {
typedef struct {
+2 −0
Original line number Original line Diff line number Diff line
@@ -462,6 +462,7 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
        return 0;
        return 0;
    }
    }


    i = 0;
    while (PACKET_remaining(&extensions) > 0) {
    while (PACKET_remaining(&extensions) > 0) {
        unsigned int type, idx;
        unsigned int type, idx;
        PACKET extension;
        PACKET extension;
@@ -518,6 +519,7 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
            thisex->data = extension;
            thisex->data = extension;
            thisex->present = 1;
            thisex->present = 1;
            thisex->type = type;
            thisex->type = type;
            thisex->received_order = i++;
        }
        }
    }
    }


Loading