add SSL_get0_iana_groups() & SSL_client_hello_get_extension_order()

The function/macro allow user get groups/extensions without memory allcations.
So we could calculate the ssl fignerprint(ja3) in low cost.

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16910)
This commit is contained in:
Phus Lu 2021-10-25 18:47:00 +08:00 committed by Tomas Mraz
parent 27aca04e13
commit 13a53fbf13
8 changed files with 93 additions and 4 deletions

View File

@ -24,6 +24,15 @@ OpenSSL 3.1
### Changes between 3.0 and 3.1 [xx XXX xxxx]
* Add new SSL APIs to aid in efficiently implementing TLS/SSL fingerprinting. The
SSL_CTRL_GET_IANA_GROUPS control code, exposed as the SSL_get0_iana_groups()
function-like macro, retrieves the list of supported groups sent by the peer,
and the function SSL_client_hello_get_extension_order() populates a caller-supplied
array with the list of extension types present in the ClientHello, in order of
appearance.
*Phus Lu*
* Fixed PEM_write_bio_PKCS8PrivateKey() and PEM_write_bio_PKCS8PrivateKey_nid()
to make it possible to use empty passphrase strings.

View File

@ -3,9 +3,10 @@
=head1 NAME
SSL_CTX_set1_groups, SSL_CTX_set1_groups_list, SSL_set1_groups,
SSL_set1_groups_list, SSL_get1_groups, SSL_get_shared_group,
SSL_get_negotiated_group, SSL_CTX_set1_curves, SSL_CTX_set1_curves_list,
SSL_set1_curves, SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve
SSL_set1_groups_list, SSL_get1_groups, SSL_get0_iana_groups,
SSL_get_shared_group, SSL_get_negotiated_group, SSL_CTX_set1_curves,
SSL_CTX_set1_curves_list, SSL_set1_curves, SSL_set1_curves_list,
SSL_get1_curves, SSL_get_shared_curve
- EC supported curve functions
=head1 SYNOPSIS
@ -19,6 +20,7 @@ SSL_set1_curves, SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve
int SSL_set1_groups_list(SSL *ssl, char *list);
int SSL_get1_groups(SSL *ssl, int *groups);
int SSL_get0_iana_groups(SSL *ssl, uint16_t **out);
int SSL_get_shared_group(SSL *s, int n);
int SSL_get_negotiated_group(SSL *s);
@ -68,6 +70,13 @@ order. It can return zero if the client did not send a supported groups
extension. If a supported group NID is unknown then the value is set to the
bitwise OR of TLSEXT_nid_unknown (0x1000000) and the id of the group.
SSL_get0_iana_groups() retrieves the list of groups sent by the
client in the supported_groups extension. The B<*out> array of bytes
is populated with the host-byte-order representation of the uint16_t group
identifiers, as assigned by IANA. The group list is returned in the same order
that was received in the ClientHello. The return value is the number of groups,
not the number of bytes written.
SSL_get_shared_group() returns the NID of the shared group B<n> for a
server-side SSL B<ssl>. If B<n> is -1 then the total number of shared groups is
returned, which may be zero. Other than for diagnostic purposes,
@ -108,6 +117,8 @@ SSL_set1_groups_list(), return 1 for success and 0 for failure.
SSL_get1_groups() returns the number of groups, which may be zero.
SSL_get0_iana_groups() returns the number of (uint16_t) groups, which may be zero.
SSL_get_shared_group() returns the NID of shared group B<n> or NID_undef if there
is no shared group B<n>; or the total number of shared groups if B<n>
is -1.

View File

@ -2,7 +2,7 @@
=head1 NAME
SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_client_hello_get0_legacy_version, SSL_client_hello_get0_random, SSL_client_hello_get0_session_id, SSL_client_hello_get0_ciphers, SSL_client_hello_get0_compression_methods, SSL_client_hello_get1_extensions_present, SSL_client_hello_get0_ext - callback functions for early server-side ClientHello processing
SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_client_hello_get0_legacy_version, SSL_client_hello_get0_random, SSL_client_hello_get0_session_id, SSL_client_hello_get0_ciphers, SSL_client_hello_get0_compression_methods, SSL_client_hello_get1_extensions_present, SSL_client_hello_get_extension_order, SSL_client_hello_get0_ext - callback functions for early server-side ClientHello processing
=head1 SYNOPSIS
@ -18,6 +18,8 @@ SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_
const unsigned char **out);
int SSL_client_hello_get1_extensions_present(SSL *s, int **out,
size_t *outlen);
int SSL_client_hello_get_extension_order(SSL *s, uint16_t *exts,
size_t *num_exts);
int SSL_client_hello_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
size_t *outlen);
@ -68,6 +70,20 @@ in the ClientHello. B<*outlen> contains the number of elements in the array.
In situations when the ClientHello has no extensions, the function will return
success with B<*out> set to NULL and B<*outlen> set to 0.
SSL_client_hello_get_extension_order() is similar to
SSL_client_hello_get1_extensions_present(), without internal memory allocation.
When called with B<exts> set to NULL, returns the number of extensions
(e.g., to allocate storage for a subsequent call). Otherwise, B<*exts> is populated
with the ExtensionType values in the order that the corresponding extensions
appeared in the ClientHello. B<*num_exts> is an input/output parameter, used
as input to supply the size of storage allocated by the caller, and as output to
indicate how many ExtensionType values were written. If the input B<*num_exts>
is smaller then the number of extensions in question, that is treated as an error.
A subsequent call with B<exts> set to NULL can retrieve the size of storage needed.
A ClientHello that contained no extensions is treated as success, with B<*num_exts>
set to 0.
=head1 NOTES
The ClientHello callback provides a vast window of possibilities for application
@ -107,6 +123,8 @@ SSL_client_hello_get0_ext() returns 1 if the extension of type 'type' is present
SSL_client_hello_get1_extensions_present() returns 1 on success and 0 on failure.
SSL_client_hello_get_extension_order() returns 1 on success and 0 on failure.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_CTX_set_tlsext_servername_callback(3)>,
@ -119,6 +137,8 @@ SSL_client_hello_get0_random(), SSL_client_hello_get0_session_id(),
SSL_client_hello_get0_ciphers(), SSL_client_hello_get0_compression_methods(),
SSL_client_hello_get0_ext(), and SSL_client_hello_get1_extensions_present()
were added in OpenSSL 1.1.1.
SSL_client_hello_get_extension_order()
was added in OpenSSL 3.1.0.
=head1 COPYRIGHT

View File

@ -1308,6 +1308,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_CTRL_GET_SIGNATURE_NID 132
# define SSL_CTRL_GET_TMP_KEY 133
# define SSL_CTRL_GET_NEGOTIATED_GROUP 134
# define SSL_CTRL_GET_IANA_GROUPS 135
# define SSL_CERT_SET_FIRST 1
# define SSL_CERT_SET_NEXT 2
# define SSL_CERT_SET_SERVER 3
@ -1401,6 +1402,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
# define SSL_get1_groups(s, glist) \
SSL_ctrl(s,SSL_CTRL_GET_GROUPS,0,(int*)(glist))
# define SSL_get0_iana_groups(s, plst) \
SSL_ctrl(s,SSL_CTRL_GET_IANA_GROUPS,0,(uint16_t **)(plst))
# define SSL_CTX_set1_groups(ctx, glist, glistlen) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(int *)(glist))
# define SSL_CTX_set1_groups_list(ctx, s) \
@ -1848,6 +1851,8 @@ size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_compression_methods(SSL *s,
const unsigned char **out);
int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen);
int SSL_client_hello_get_extension_order(SSL *s, uint16_t *exts,
size_t *num_exts);
int SSL_client_hello_get0_ext(SSL *s, unsigned int type,
const unsigned char **out, size_t *outlen);

View File

@ -3729,6 +3729,14 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
return (int)s->ext.peer_ecpointformats_len;
}
case SSL_CTRL_GET_IANA_GROUPS:
{
if (parg != NULL) {
*(uint16_t **)parg = (uint16_t *)s->ext.peer_supportedgroups;
}
return (int)s->ext.peer_supportedgroups_len;
}
default:
break;
}

View File

@ -5424,6 +5424,40 @@ int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen)
return 0;
}
int SSL_client_hello_get_extension_order(SSL *s, uint16_t *exts, size_t *num_exts)
{
RAW_EXTENSION *ext;
size_t num = 0, i;
if (s->clienthello == NULL || num_exts == 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++;
}
if (num == 0) {
*num_exts = 0;
return 1;
}
if (exts == NULL) {
*num_exts = num;
return 1;
}
if (*num_exts < num)
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)
return 0;
exts[ext->received_order] = ext->type;
}
}
*num_exts = num;
return 1;
}
int SSL_client_hello_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
size_t *outlen)
{

View File

@ -520,3 +520,4 @@ SSL_load_client_CA_file_ex 520 3_0_0 EXIST::FUNCTION:
SSL_set0_tmp_dh_pkey 521 3_0_0 EXIST::FUNCTION:
SSL_CTX_set0_tmp_dh_pkey 522 3_0_0 EXIST::FUNCTION:
SSL_group_to_name 523 3_0_0 EXIST::FUNCTION:
SSL_client_hello_get_extension_order ? 3_1_0 EXIST::FUNCTION:

View File

@ -532,6 +532,7 @@ SSL_clear_chain_certs define
SSL_clear_mode define
SSL_disable_ct define
SSL_get0_chain_certs define
SSL_get0_iana_groups define
SSL_get0_session define
SSL_get1_curves define
SSL_get1_groups define