mirror of
https://github.com/openssl/openssl.git
synced 2025-02-23 14:42:15 +08:00
Move client construction of ClientHello extensions into new framework
Perl changes reviewed by Richard Levitte. Non-perl changes reviewed by Rich Salz Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Richard Levitte <levitte@openssl.org>
This commit is contained in:
parent
6dd083fd68
commit
ab83e31414
@ -2265,9 +2265,26 @@ int ERR_load_SSL_strings(void);
|
||||
# define SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE 407
|
||||
# define SSL_F_TLS_CONSTRUCT_CKE_RSA 409
|
||||
# define SSL_F_TLS_CONSTRUCT_CKE_SRP 410
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_ALPN 466
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE 355
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_EC_PT_FORMATS 467
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_EMS 468
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_ETM 469
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_HELLO 356
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE 357
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE 470
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_NPN 471
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_PADDING 472
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_RENEGOTIATE 473
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_SCT 474
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_SERVER_NAME 475
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_SESSION_TICKET 476
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_SIG_ALGS 477
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_SRP 478
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST 479
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS 480
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS 481
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_USE_SRTP 482
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY 358
|
||||
# define SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS 443
|
||||
# define SSL_F_TLS_CONSTRUCT_EXTENSIONS 447
|
||||
|
@ -265,12 +265,40 @@ static ERR_STRING_DATA SSL_str_functs[] = {
|
||||
"tls_construct_cke_psk_preamble"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_RSA), "tls_construct_cke_rsa"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_SRP), "tls_construct_cke_srp"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_ALPN), "tls_construct_client_alpn"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE),
|
||||
"tls_construct_client_certificate"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_EC_PT_FORMATS),
|
||||
"tls_construct_client_ec_pt_formats"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_EMS), "tls_construct_client_ems"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_ETM), "tls_construct_client_etm"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO),
|
||||
"tls_construct_client_hello"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE),
|
||||
"tls_construct_client_key_exchange"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE),
|
||||
"tls_construct_client_key_share"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_NPN), "tls_construct_client_npn"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_PADDING),
|
||||
"tls_construct_client_padding"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_RENEGOTIATE),
|
||||
"tls_construct_client_renegotiate"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SCT), "tls_construct_client_sct"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SERVER_NAME),
|
||||
"tls_construct_client_server_name"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SESSION_TICKET),
|
||||
"tls_construct_client_session_ticket"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SIG_ALGS),
|
||||
"tls_construct_client_sig_algs"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SRP), "tls_construct_client_srp"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST),
|
||||
"tls_construct_client_status_request"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS),
|
||||
"tls_construct_client_supported_groups"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS),
|
||||
"tls_construct_client_supported_versions"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_USE_SRTP),
|
||||
"tls_construct_client_use_srtp"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY),
|
||||
"tls_construct_client_verify"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS),
|
||||
|
@ -2077,12 +2077,10 @@ __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);
|
||||
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);
|
||||
__owur int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt);
|
||||
__owur int ssl_prepare_clienthello_tlsext(SSL *s);
|
||||
__owur RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts,
|
||||
size_t numexts,
|
||||
unsigned int type);
|
||||
|
@ -36,7 +36,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_renegotiate,
|
||||
tls_parse_server_renegotiate,
|
||||
tls_construct_server_renegotiate,
|
||||
NULL,
|
||||
tls_construct_client_renegotiate,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_SSL3_ALLOWED
|
||||
| EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
@ -45,7 +45,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_server_name,
|
||||
tls_parse_server_server_name,
|
||||
tls_construct_server_server_name,
|
||||
NULL,
|
||||
tls_construct_client_server_name,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
|
||||
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||
},
|
||||
@ -55,7 +55,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_srp,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_client_srp,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
#endif
|
||||
@ -65,7 +65,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_ec_pt_formats,
|
||||
tls_parse_server_ec_pt_formats,
|
||||
tls_construct_server_ec_pt_formats,
|
||||
NULL,
|
||||
tls_construct_client_ec_pt_formats,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
{
|
||||
@ -73,7 +73,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_supported_groups,
|
||||
NULL,
|
||||
NULL /* TODO(TLS1.3): Need to add this */,
|
||||
NULL,
|
||||
tls_construct_client_supported_groups,
|
||||
EXT_CLIENT_HELLO
|
||||
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||
},
|
||||
@ -83,7 +83,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_session_ticket,
|
||||
tls_parse_server_session_ticket,
|
||||
tls_construct_server_session_ticket,
|
||||
NULL,
|
||||
tls_construct_client_session_ticket,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
{
|
||||
@ -91,25 +91,27 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_sig_algs,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_client_sig_algs,
|
||||
EXT_CLIENT_HELLO
|
||||
},
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
{
|
||||
TLSEXT_TYPE_status_request,
|
||||
tls_parse_client_status_request,
|
||||
tls_parse_server_status_request,
|
||||
tls_construct_server_status_request,
|
||||
NULL,
|
||||
tls_construct_client_status_request,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
|
||||
| EXT_TLS1_3_CERTIFICATE
|
||||
},
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
{
|
||||
TLSEXT_TYPE_next_proto_neg,
|
||||
tls_parse_client_npn,
|
||||
tls_parse_server_npn,
|
||||
tls_construct_server_next_proto_neg,
|
||||
NULL,
|
||||
tls_construct_client_npn,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
#endif
|
||||
@ -118,7 +120,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_alpn,
|
||||
tls_parse_server_alpn,
|
||||
tls_construct_server_alpn,
|
||||
NULL,
|
||||
tls_construct_client_alpn,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
|
||||
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||
},
|
||||
@ -128,7 +130,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_use_srtp,
|
||||
tls_parse_server_use_srtp,
|
||||
tls_construct_server_use_srtp,
|
||||
NULL,
|
||||
tls_construct_client_use_srtp,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
|
||||
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS | EXT_DTLS_ONLY
|
||||
},
|
||||
@ -138,7 +140,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_etm,
|
||||
tls_parse_server_etm,
|
||||
tls_construct_server_etm,
|
||||
NULL,
|
||||
tls_construct_client_etm,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
#ifndef OPENSSL_NO_CT
|
||||
@ -152,7 +154,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
NULL,
|
||||
tls_parse_server_sct,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_client_sct,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
|
||||
| EXT_TLS1_3_CERTIFICATE
|
||||
},
|
||||
@ -162,7 +164,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_parse_client_ems,
|
||||
tls_parse_server_ems,
|
||||
tls_construct_server_ems,
|
||||
NULL,
|
||||
tls_construct_client_ems,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
{
|
||||
@ -171,24 +173,15 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS_IMPLEMENTATION_ONLY
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_padding,
|
||||
/* We send this, but don't read it */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO
|
||||
tls_construct_client_supported_versions,
|
||||
EXT_CLIENT_HELLO | EXT_TLS_IMPLEMENTATION_ONLY | EXT_TLS1_3_ONLY
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_key_share,
|
||||
tls_parse_client_key_share,
|
||||
tls_parse_server_key_share,
|
||||
tls_construct_server_key_share,
|
||||
NULL,
|
||||
tls_construct_client_key_share,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_3_SERVER_HELLO
|
||||
| EXT_TLS1_3_HELLO_RETRY_REQUEST | EXT_TLS_IMPLEMENTATION_ONLY
|
||||
| EXT_TLS1_3_ONLY
|
||||
@ -204,6 +197,16 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_construct_server_cryptopro_bug,
|
||||
NULL,
|
||||
EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
{
|
||||
/* Last in the list because it must be added as the last extension */
|
||||
TLSEXT_TYPE_padding,
|
||||
/* We send this, but don't read it */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_client_padding,
|
||||
EXT_CLIENT_HELLO
|
||||
}
|
||||
};
|
||||
|
||||
@ -457,6 +460,7 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
{
|
||||
size_t loop;
|
||||
int addcustom = 0;
|
||||
int min_version, max_version = 0, reason;
|
||||
|
||||
/*
|
||||
* Normally if something goes wrong during construction its an internal
|
||||
@ -477,6 +481,35 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((context & EXT_CLIENT_HELLO) != 0) {
|
||||
reason = ssl_get_client_min_max_version(s, &min_version, &max_version);
|
||||
if (reason != 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, reason);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add custom extensions first */
|
||||
if ((context & EXT_CLIENT_HELLO) != 0) {
|
||||
custom_ext_init(&s->cert->cli_ext);
|
||||
addcustom = 1;
|
||||
} else if ((context & EXT_TLS1_2_SERVER_HELLO) != 0) {
|
||||
/*
|
||||
* We already initialised the custom extensions during ClientHello
|
||||
* parsing.
|
||||
*
|
||||
* TODO(TLS1.3): We're going to need a new custom extension mechanism
|
||||
* for TLS1.3, so that custom extensions can specify which of the
|
||||
* multiple message they wish to add themselves to.
|
||||
*/
|
||||
addcustom = 1;
|
||||
}
|
||||
|
||||
if (addcustom && !custom_ext_add(s, s->server, pkt, al)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (loop = 0; loop < OSSL_NELEM(ext_defs); loop++) {
|
||||
int (*construct)(SSL *s, WPACKET *pkt, int *al);
|
||||
|
||||
@ -499,6 +532,9 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
|| (!SSL_IS_TLS13(s)
|
||||
&& (ext_defs[loop].context & EXT_TLS1_3_ONLY) != 0
|
||||
&& (context & EXT_CLIENT_HELLO) == 0)
|
||||
|| ((ext_defs[loop].context & EXT_TLS1_3_ONLY) != 0
|
||||
&& (context & EXT_CLIENT_HELLO) != 0
|
||||
&& (SSL_IS_DTLS(s) || max_version < TLS1_3_VERSION))
|
||||
|| construct == NULL)
|
||||
continue;
|
||||
|
||||
@ -506,27 +542,6 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add custom extensions */
|
||||
if ((context & EXT_CLIENT_HELLO) != 0) {
|
||||
custom_ext_init(&s->cert->cli_ext);
|
||||
addcustom = 1;
|
||||
} else if ((context & EXT_TLS1_2_SERVER_HELLO) != 0) {
|
||||
/*
|
||||
* We already initialised the custom extensions during ClientHello
|
||||
* parsing.
|
||||
*
|
||||
* TODO(TLS1.3): We're going to need a new custom extension mechanism
|
||||
* for TLS1.3, so that custom extensions can specify which of the
|
||||
* multiple message they wish to add themselves to.
|
||||
*/
|
||||
addcustom = 1;
|
||||
}
|
||||
|
||||
if (addcustom && !custom_ext_add(s, s->server, pkt, al)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
|
@ -8,9 +8,604 @@
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <openssl/ocsp.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "statem_locl.h"
|
||||
|
||||
int tls_construct_client_renegotiate(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
/* Add RI if renegotiating */
|
||||
if (!s->renegotiate)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished,
|
||||
s->s3->previous_client_finished_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_RENEGOTIATE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_client_server_name(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (s->tlsext_hostname == NULL)
|
||||
return 1;
|
||||
|
||||
/* Add TLS extension servername to the Client Hello message */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
|
||||
/* Sub-packet for server_name extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* Sub-packet for servername list (always 1 hostname)*/
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_NAMETYPE_host_name)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->tlsext_hostname,
|
||||
strlen(s->tlsext_hostname))
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SERVER_NAME, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
int tls_construct_client_srp(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
/* Add SRP username if there is one */
|
||||
if (s->srp_ctx.login == NULL)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_srp)
|
||||
/* Sub-packet for SRP extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)
|
||||
/* login must not be zero...internal error if so */
|
||||
|| !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
|
||||
|| !WPACKET_memcpy(pkt, s->srp_ctx.login,
|
||||
strlen(s->srp_ctx.login))
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SRP, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
static int use_ecc(SSL *s)
|
||||
{
|
||||
int using_ecc = 0;
|
||||
int i;
|
||||
unsigned long alg_k, alg_a;
|
||||
STACK_OF(SSL_CIPHER) *cipher_stack = NULL;
|
||||
|
||||
/* See if we support any ECC ciphersuites */
|
||||
if (s->version == SSL3_VERSION)
|
||||
return 0;
|
||||
|
||||
|
||||
cipher_stack = SSL_get_ciphers(s);
|
||||
|
||||
for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) {
|
||||
const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
|
||||
|
||||
alg_k = c->algorithm_mkey;
|
||||
alg_a = c->algorithm_auth;
|
||||
if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK))
|
||||
|| (alg_a & SSL_aECDSA)
|
||||
|| c->min_tls >= TLS1_3_VERSION) {
|
||||
using_ecc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return using_ecc;
|
||||
}
|
||||
|
||||
int tls_construct_client_ec_pt_formats(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
const unsigned char *pformats;
|
||||
size_t num_formats;
|
||||
|
||||
if (!use_ecc(s))
|
||||
return 1;
|
||||
|
||||
/* Add TLS extension ECPointFormats to the ClientHello message */
|
||||
|
||||
tls1_get_formatlist(s, &pformats, &num_formats);
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
|
||||
/* Sub-packet for formats extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int tls_construct_client_supported_groups(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
const unsigned char *pcurves = NULL, *pcurvestmp;
|
||||
size_t num_curves = 0, i;
|
||||
|
||||
if (!use_ecc(s))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Add TLS extension supported_groups to the ClientHello message
|
||||
*/
|
||||
/* TODO(TLS1.3): Add support for DHE groups */
|
||||
pcurves = s->tlsext_supportedgroupslist;
|
||||
if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
pcurvestmp = pcurves;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
|
||||
/* Sub-packet for supported_groups extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
/* Copy curve ID if supported */
|
||||
for (i = 0; i < num_curves; i++, pcurvestmp += 2) {
|
||||
if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) {
|
||||
if (!WPACKET_put_bytes_u8(pkt, pcurvestmp[0])
|
||||
|| !WPACKET_put_bytes_u8(pkt, pcurvestmp[1])) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_construct_client_session_ticket(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
size_t ticklen;
|
||||
|
||||
if (!tls_use_ticket(s))
|
||||
return 1;
|
||||
|
||||
if (!s->new_session && s->session != NULL
|
||||
&& s->session->tlsext_tick != NULL) {
|
||||
ticklen = s->session->tlsext_ticklen;
|
||||
} else if (s->session && s->tlsext_session_ticket != NULL
|
||||
&& s->tlsext_session_ticket->data != NULL) {
|
||||
ticklen = s->tlsext_session_ticket->length;
|
||||
s->session->tlsext_tick = OPENSSL_malloc(ticklen);
|
||||
if (s->session->tlsext_tick == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SESSION_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
memcpy(s->session->tlsext_tick,
|
||||
s->tlsext_session_ticket->data, ticklen);
|
||||
s->session->tlsext_ticklen = ticklen;
|
||||
} else {
|
||||
ticklen = 0;
|
||||
}
|
||||
|
||||
if (ticklen == 0 && s->tlsext_session_ticket != NULL &&
|
||||
s->tlsext_session_ticket->data == NULL)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->session->tlsext_tick, ticklen)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_client_sig_algs(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
size_t salglen;
|
||||
const unsigned char *salg;
|
||||
|
||||
if (!SSL_CLIENT_USE_SIGALGS(s))
|
||||
return 1;
|
||||
|
||||
salglen = tls12_get_psigalgs(s, &salg);
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signature_algorithms)
|
||||
/* Sub-packet for sig-algs extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* Sub-packet for the actual list */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !tls12_copy_sigalgs(s, pkt, salg, salglen)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SIG_ALGS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_construct_client_status_request(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (s->tlsext_status_type != TLSEXT_STATUSTYPE_ocsp)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
|
||||
/* Sub-packet for status request extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp)
|
||||
/* Sub-packet for the ids */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) {
|
||||
unsigned char *idbytes;
|
||||
int idlen;
|
||||
OCSP_RESPID *id;
|
||||
|
||||
id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
|
||||
idlen = i2d_OCSP_RESPID(id, NULL);
|
||||
if (idlen <= 0
|
||||
/* Sub-packet for an individual id */
|
||||
|| !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes)
|
||||
|| i2d_OCSP_RESPID(id, &idbytes) != idlen) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (s->tlsext_ocsp_exts) {
|
||||
unsigned char *extbytes;
|
||||
int extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
|
||||
|
||||
if (extlen < 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
|
||||
|| i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &extbytes)
|
||||
!= extlen) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_construct_client_npn(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (s->ctx->next_proto_select_cb == NULL || s->s3->tmp.finish_md_len != 0)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* The client advertises an empty extension to indicate its support
|
||||
* for Next Protocol Negotiation
|
||||
*/
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_NPN, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_construct_client_alpn(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
s->s3->alpn_sent = 0;
|
||||
|
||||
/*
|
||||
* finish_md_len is non-zero during a renegotiation, so
|
||||
* this avoids sending ALPN during the renegotiation
|
||||
*/
|
||||
if (s->alpn_client_proto_list == NULL || s->s3->tmp.finish_md_len != 0)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt,
|
||||
TLSEXT_TYPE_application_layer_protocol_negotiation)
|
||||
/* Sub-packet ALPN extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->alpn_client_proto_list,
|
||||
s->alpn_client_proto_list_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_ALPN, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
s->s3->alpn_sent = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
int tls_construct_client_use_srtp(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s);
|
||||
SRTP_PROTECTION_PROFILE *prof;
|
||||
int i, ct;
|
||||
|
||||
if (clnt == NULL)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
|
||||
/* Sub-packet for SRTP extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* Sub-packet for the protection profile list */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_USE_SRTP, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
ct = sk_SRTP_PROTECTION_PROFILE_num(clnt);
|
||||
for (i = 0; i < ct; i++) {
|
||||
prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
|
||||
if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_USE_SRTP, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt)
|
||||
/* Add an empty use_mki value */
|
||||
|| !WPACKET_put_bytes_u8(pkt, 0)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_USE_SRTP, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_construct_client_etm(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_ETM, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_CT
|
||||
int tls_construct_client_sct(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (s->ct_validation_callback == NULL)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SCT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_construct_client_ems(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_EMS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_client_supported_versions(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
int currv, min_version, max_version, reason;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
reason = ssl_get_client_min_max_version(s, &min_version, &max_version);
|
||||
if (reason != 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS, reason);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): There is some discussion on the TLS list as to wheter
|
||||
* we should include versions <TLS1.2. For the moment we do. To be
|
||||
* reviewed later.
|
||||
*/
|
||||
for (currv = max_version; currv >= min_version; currv--) {
|
||||
/* TODO(TLS1.3): Remove this first if clause prior to release!! */
|
||||
if (currv == TLS1_3_VERSION) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
} else if (!WPACKET_put_bytes_u16(pkt, currv)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int tls_construct_client_key_share(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
size_t i, sharessent = 0, num_curves = 0;
|
||||
const unsigned char *pcurves = NULL;
|
||||
|
||||
/* key_share extension */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|
||||
/* Extension data sub-packet */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* KeyShare list sub-packet */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcurves = s->tlsext_supportedgroupslist;
|
||||
if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): Make the number of key_shares sent configurable. For
|
||||
* now, just send one
|
||||
*/
|
||||
for (i = 0; i < num_curves && sharessent < 1; i++, pcurves += 2) {
|
||||
unsigned char *encodedPoint = NULL;
|
||||
unsigned int curve_id = 0;
|
||||
EVP_PKEY *key_share_key = NULL;
|
||||
size_t encodedlen;
|
||||
|
||||
if (!tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED))
|
||||
continue;
|
||||
|
||||
if (s->s3->tmp.pkey != NULL) {
|
||||
/* Shouldn't happen! */
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generate a key for this key_share */
|
||||
curve_id = (pcurves[0] << 8) | pcurves[1];
|
||||
key_share_key = ssl_generate_pkey_curve(curve_id);
|
||||
if (key_share_key == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_EVP_LIB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Encode the public key. */
|
||||
encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
|
||||
&encodedPoint);
|
||||
if (encodedlen == 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_EC_LIB);
|
||||
EVP_PKEY_free(key_share_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create KeyShareEntry */
|
||||
if (!WPACKET_put_bytes_u16(pkt, curve_id)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, encodedPoint, encodedlen)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
EVP_PKEY_free(key_share_key);
|
||||
OPENSSL_free(encodedPoint);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): When changing to send more than one key_share we're
|
||||
* going to need to be able to save more than one EVP_PKEY. For now
|
||||
* we reuse the existing tmp.pkey
|
||||
*/
|
||||
s->s3->group_id = curve_id;
|
||||
s->s3->tmp.pkey = key_share_key;
|
||||
sharessent++;
|
||||
OPENSSL_free(encodedPoint);
|
||||
}
|
||||
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_client_padding(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
unsigned char *padbytes;
|
||||
size_t hlen;
|
||||
|
||||
if ((s->options & SSL_OP_TLSEXT_PADDING) == 0)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Add padding to workaround bugs in F5 terminators. See
|
||||
* https://tools.ietf.org/html/draft-agl-tls-padding-03 NB: because this
|
||||
* code works out the length of all existing extensions it MUST always
|
||||
* appear last.
|
||||
*/
|
||||
if (!WPACKET_get_total_written(pkt, &hlen)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_PADDING, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hlen > 0xff && hlen < 0x200) {
|
||||
hlen = 0x200 - hlen;
|
||||
if (hlen >= 4)
|
||||
hlen -= 4;
|
||||
else
|
||||
hlen = 0;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
|
||||
|| !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_PADDING, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
memset(padbytes, 0, hlen);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the server's renegotiation binding and abort if it's not right
|
||||
*/
|
||||
@ -147,6 +742,7 @@ int tls_parse_server_session_ticket(SSL *s, PACKET *pkt, int *al)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_parse_server_status_request(SSL *s, PACKET *pkt, int *al)
|
||||
{
|
||||
/*
|
||||
@ -162,6 +758,7 @@ int tls_parse_server_status_request(SSL *s, PACKET *pkt, int *al)
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef OPENSSL_NO_CT
|
||||
|
@ -215,13 +215,14 @@ int tls_parse_client_sig_algs(SSL *s, PACKET *pkt, int *al)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_parse_client_status_request(SSL *s, PACKET *pkt, int *al)
|
||||
{
|
||||
if (!PACKET_get_1(pkt, (unsigned int *)&s->tlsext_status_type)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
|
||||
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
|
||||
const unsigned char *ext_data;
|
||||
PACKET responder_id_list, exts;
|
||||
@ -297,9 +298,7 @@ int tls_parse_client_status_request(SSL *s, PACKET *pkt, int *al)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
} else {
|
||||
/*
|
||||
* We don't know what to do with any other type so ignore it.
|
||||
*/
|
||||
@ -308,6 +307,7 @@ int tls_parse_client_status_request(SSL *s, PACKET *pkt, int *al)
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_parse_client_npn(SSL *s, PACKET *pkt, int *al)
|
||||
@ -949,6 +949,7 @@ int tls_construct_server_session_ticket(SSL *s, WPACKET *pkt, int *al)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_construct_server_status_request(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (!s->tlsext_status_expected)
|
||||
@ -962,6 +963,7 @@ int tls_construct_server_status_request(SSL *s, WPACKET *pkt, int *al)
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
|
@ -1011,18 +1011,7 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
|
||||
}
|
||||
|
||||
/* TLS extensions */
|
||||
if (ssl_prepare_clienthello_tlsext(s) <= 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
|
||||
return 0;
|
||||
}
|
||||
if (!WPACKET_start_sub_packet_u16(pkt)
|
||||
/*
|
||||
* If extensions are of zero length then we don't even add the
|
||||
* extensions length bytes
|
||||
*/
|
||||
|| !WPACKET_set_flags(pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH)
|
||||
|| !ssl_add_clienthello_tlsext(s, pkt, &al)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
if (!tls_construct_extensions(s, pkt, EXT_CLIENT_HELLO, &al)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
|
@ -168,7 +168,9 @@ int tls_parse_client_supported_groups(SSL *s, PACKET *pkt, int *al);
|
||||
#endif
|
||||
int tls_parse_client_session_ticket(SSL *s, PACKET *pkt, int *al);
|
||||
int tls_parse_client_sig_algs(SSL *s, PACKET *pkt, int *al);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_parse_client_status_request(SSL *s, PACKET *pkt, int *al);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_parse_client_npn(SSL *s, PACKET *pkt, int *al);
|
||||
#endif
|
||||
@ -184,12 +186,20 @@ int tls_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al);
|
||||
|
||||
int tls_construct_server_renegotiate(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_server_name(SSL *s, WPACKET *pkt, int *al);
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_construct_server_ec_pt_formats(SSL *s, WPACKET *pkt, int *al);
|
||||
#endif
|
||||
int tls_construct_server_session_ticket(SSL *s, WPACKET *pkt, int *al);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_construct_server_status_request(SSL *s, WPACKET *pkt, int *al);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_construct_server_next_proto_neg(SSL *s, WPACKET *pkt, int *al);
|
||||
#endif
|
||||
int tls_construct_server_alpn(SSL *s, WPACKET *pkt, int *al);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
int tls_construct_server_use_srtp(SSL *s, WPACKET *pkt, int *al);
|
||||
#endif
|
||||
int tls_construct_server_etm(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_ems(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_key_share(SSL *s, WPACKET *pkt, int *al);
|
||||
@ -201,13 +211,44 @@ int tls_construct_server_key_share(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_cryptopro_bug(SSL *s, WPACKET *pkt, int *al);
|
||||
|
||||
/* Client Extension processing */
|
||||
int tls_construct_client_renegotiate(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_client_server_name(SSL *s, WPACKET *pkt, int *al);
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
int tls_construct_client_srp(SSL *s, WPACKET *pkt, int *al);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_construct_client_ec_pt_formats(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_client_supported_groups(SSL *s, WPACKET *pkt, int *al);
|
||||
#endif
|
||||
int tls_construct_client_session_ticket(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_client_sig_algs(SSL *s, WPACKET *pkt, int *al);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_construct_client_status_request(SSL *s, WPACKET *pkt, int *al);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_construct_client_npn(SSL *s, WPACKET *pkt, int *al);
|
||||
#endif
|
||||
int tls_construct_client_alpn(SSL *s, WPACKET *pkt, int *al);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
int tls_construct_client_use_srtp(SSL *s, WPACKET *pkt, int *al);
|
||||
#endif
|
||||
int tls_construct_client_etm(SSL *s, WPACKET *pkt, int *al);
|
||||
#ifndef OPENSSL_NO_CT
|
||||
int tls_construct_client_sct(SSL *s, WPACKET *pkt, int *al);
|
||||
#endif
|
||||
int tls_construct_client_ems(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_client_supported_versions(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_client_key_share(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_client_padding(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_parse_server_renegotiate(SSL *s, PACKET *pkt, int *al);
|
||||
int tls_parse_server_server_name(SSL *s, PACKET *pkt, int *al);
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_parse_server_ec_pt_formats(SSL *s, PACKET *pkt, int *al);
|
||||
#endif
|
||||
int tls_parse_server_session_ticket(SSL *s, PACKET *pkt, int *al);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_parse_server_status_request(SSL *s, PACKET *pkt, int *al);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CT
|
||||
int tls_parse_server_sct(SSL *s, PACKET *pkt, int *al);
|
||||
#endif
|
||||
|
497
ssl/t1_lib.c
497
ssl/t1_lib.c
@ -945,503 +945,6 @@ int tls_use_ticket(SSL *s)
|
||||
return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL);
|
||||
}
|
||||
|
||||
int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
#ifndef OPENSSL_NO_EC
|
||||
const unsigned char *pcurves = NULL;
|
||||
size_t num_curves = 0;
|
||||
int using_ecc = 0;
|
||||
int min_version, max_version, reason;
|
||||
|
||||
/* See if we support any ECC ciphersuites */
|
||||
if ((s->version >= TLS1_VERSION && s->version <= TLS1_3_VERSION)
|
||||
|| SSL_IS_DTLS(s)) {
|
||||
int i;
|
||||
unsigned long alg_k, alg_a;
|
||||
STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
|
||||
|
||||
for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) {
|
||||
const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
|
||||
|
||||
alg_k = c->algorithm_mkey;
|
||||
alg_a = c->algorithm_auth;
|
||||
if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK))
|
||||
|| (alg_a & SSL_aECDSA)
|
||||
|| c->min_tls >= TLS1_3_VERSION) {
|
||||
using_ecc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
/* Shouldn't happen! */
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Add RI if renegotiating */
|
||||
if (s->renegotiate) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished,
|
||||
s->s3->previous_client_finished_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Only add RI for SSLv3 */
|
||||
if (s->client_version == SSL3_VERSION)
|
||||
goto done;
|
||||
|
||||
if (s->tlsext_hostname != NULL) {
|
||||
/* Add TLS extension servername to the Client Hello message */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
|
||||
/* Sub-packet for server_name extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* Sub-packet for servername list (always 1 hostname)*/
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_NAMETYPE_host_name)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->tlsext_hostname,
|
||||
strlen(s->tlsext_hostname))
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
/* Add SRP username if there is one */
|
||||
if (s->srp_ctx.login != NULL) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_srp)
|
||||
/* Sub-packet for SRP extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)
|
||||
/* login must not be zero...internal error if so */
|
||||
|| !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
|
||||
|| !WPACKET_memcpy(pkt, s->srp_ctx.login,
|
||||
strlen(s->srp_ctx.login))
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
if (using_ecc) {
|
||||
/*
|
||||
* Add TLS extension ECPointFormats to the ClientHello message
|
||||
*/
|
||||
const unsigned char *pformats, *pcurvestmp;
|
||||
size_t num_formats;
|
||||
size_t i;
|
||||
|
||||
tls1_get_formatlist(s, &pformats, &num_formats);
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
|
||||
/* Sub-packet for formats extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add TLS extension supported_groups to the ClientHello message
|
||||
*/
|
||||
/* TODO(TLS1.3): Add support for DHE groups */
|
||||
pcurves = s->tlsext_supportedgroupslist;
|
||||
if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
pcurvestmp = pcurves;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
|
||||
/* Sub-packet for supported_groups extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
/* Copy curve ID if supported */
|
||||
for (i = 0; i < num_curves; i++, pcurvestmp += 2) {
|
||||
if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) {
|
||||
if (!WPACKET_put_bytes_u8(pkt, pcurvestmp[0])
|
||||
|| !WPACKET_put_bytes_u8(pkt, pcurvestmp[1])) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* OPENSSL_NO_EC */
|
||||
|
||||
if (tls_use_ticket(s)) {
|
||||
size_t ticklen;
|
||||
if (!s->new_session && s->session && s->session->tlsext_tick)
|
||||
ticklen = s->session->tlsext_ticklen;
|
||||
else if (s->session && s->tlsext_session_ticket &&
|
||||
s->tlsext_session_ticket->data) {
|
||||
ticklen = s->tlsext_session_ticket->length;
|
||||
s->session->tlsext_tick = OPENSSL_malloc(ticklen);
|
||||
if (s->session->tlsext_tick == NULL) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
memcpy(s->session->tlsext_tick,
|
||||
s->tlsext_session_ticket->data, ticklen);
|
||||
s->session->tlsext_ticklen = ticklen;
|
||||
} else
|
||||
ticklen = 0;
|
||||
if (ticklen == 0 && s->tlsext_session_ticket &&
|
||||
s->tlsext_session_ticket->data == NULL)
|
||||
goto skip_ext;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->session->tlsext_tick,
|
||||
ticklen)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
skip_ext:
|
||||
|
||||
if (SSL_CLIENT_USE_SIGALGS(s)) {
|
||||
size_t salglen;
|
||||
const unsigned char *salg;
|
||||
|
||||
salglen = tls12_get_psigalgs(s, &salg);
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signature_algorithms)
|
||||
/* Sub-packet for sig-algs extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* Sub-packet for the actual list */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !tls12_copy_sigalgs(s, pkt, salg, salglen)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
|
||||
int i;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
|
||||
/* Sub-packet for status request extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp)
|
||||
/* Sub-packet for the ids */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) {
|
||||
unsigned char *idbytes;
|
||||
int idlen;
|
||||
OCSP_RESPID *id;
|
||||
|
||||
id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
|
||||
idlen = i2d_OCSP_RESPID(id, NULL);
|
||||
if (idlen <= 0
|
||||
/* Sub-packet for an individual id */
|
||||
|| !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes)
|
||||
|| i2d_OCSP_RESPID(id, &idbytes) != idlen) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (s->tlsext_ocsp_exts) {
|
||||
unsigned char *extbytes;
|
||||
int extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
|
||||
|
||||
if (extlen < 0) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
|
||||
|| i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &extbytes)
|
||||
!= extlen) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) {
|
||||
/*
|
||||
* The client advertises an empty extension to indicate its support
|
||||
* for Next Protocol Negotiation
|
||||
*/
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* finish_md_len is non-zero during a renegotiation, so
|
||||
* this avoids sending ALPN during the renegotiation
|
||||
* (see longer comment below)
|
||||
*/
|
||||
if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) {
|
||||
if (!WPACKET_put_bytes_u16(pkt,
|
||||
TLSEXT_TYPE_application_layer_protocol_negotiation)
|
||||
/* Sub-packet ALPN extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->alpn_client_proto_list,
|
||||
s->alpn_client_proto_list_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
s->s3->alpn_sent = 1;
|
||||
}
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)) {
|
||||
STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s);
|
||||
SRTP_PROTECTION_PROFILE *prof;
|
||||
int i, ct;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
|
||||
/* Sub-packet for SRTP extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* Sub-packet for the protection profile list */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
ct = sk_SRTP_PROTECTION_PROFILE_num(clnt);
|
||||
for (i = 0; i < ct; i++) {
|
||||
prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
|
||||
if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt)
|
||||
/* Add an empty use_mki value */
|
||||
|| !WPACKET_put_bytes_u8(pkt, 0)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
custom_ext_init(&s->cert->cli_ext);
|
||||
/* Add custom TLS Extensions to ClientHello */
|
||||
if (!custom_ext_add(s, 0, pkt, al)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_CT
|
||||
if (s->ct_validation_callback != NULL) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
reason = ssl_get_client_min_max_version(s, &min_version, &max_version);
|
||||
if (reason != 0) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, reason);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TLS1.3 specific extensions */
|
||||
if (!SSL_IS_DTLS(s) && max_version >= TLS1_3_VERSION) {
|
||||
int currv;
|
||||
size_t i, sharessent = 0;
|
||||
|
||||
/* TODO(TLS1.3): Should we add this extension for versions < TLS1.3? */
|
||||
/* supported_versions extension */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): There is some discussion on the TLS list as to wheter
|
||||
* we should include versions <TLS1.2. For the moment we do. To be
|
||||
* reviewed later.
|
||||
*/
|
||||
for (currv = max_version; currv >= min_version; currv--) {
|
||||
/* TODO(TLS1.3): Remove this first if clause prior to release!! */
|
||||
if (currv == TLS1_3_VERSION) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
} else if (!WPACKET_put_bytes_u16(pkt, currv)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* key_share extension */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|
||||
/* Extension data sub-packet */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* KeyShare list sub-packet */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): Make the number of key_shares sent configurable. For
|
||||
* now, just send one
|
||||
*/
|
||||
for (i = 0; i < num_curves && sharessent < 1; i++, pcurves += 2) {
|
||||
unsigned char *encodedPoint = NULL;
|
||||
unsigned int curve_id = 0;
|
||||
EVP_PKEY *key_share_key = NULL;
|
||||
size_t encodedlen;
|
||||
|
||||
if (!tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED))
|
||||
continue;
|
||||
|
||||
if (s->s3->tmp.pkey != NULL) {
|
||||
/* Shouldn't happen! */
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generate a key for this key_share */
|
||||
curve_id = (pcurves[0] << 8) | pcurves[1];
|
||||
key_share_key = ssl_generate_pkey_curve(curve_id);
|
||||
if (key_share_key == NULL) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EVP_LIB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Encode the public key. */
|
||||
encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
|
||||
&encodedPoint);
|
||||
if (encodedlen == 0) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EC_LIB);
|
||||
EVP_PKEY_free(key_share_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create KeyShareEntry */
|
||||
if (!WPACKET_put_bytes_u16(pkt, curve_id)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, encodedPoint, encodedlen)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
EVP_PKEY_free(key_share_key);
|
||||
OPENSSL_free(encodedPoint);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): When changing to send more than one key_share we're
|
||||
* going to need to be able to save more than one EVP_PKEY. For now
|
||||
* we reuse the existing tmp.pkey
|
||||
*/
|
||||
s->s3->group_id = curve_id;
|
||||
s->s3->tmp.pkey = key_share_key;
|
||||
sharessent++;
|
||||
OPENSSL_free(encodedPoint);
|
||||
}
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add padding to workaround bugs in F5 terminators. See
|
||||
* https://tools.ietf.org/html/draft-agl-tls-padding-03 NB: because this
|
||||
* code works out the length of all existing extensions it MUST always
|
||||
* appear last.
|
||||
*/
|
||||
if (s->options & SSL_OP_TLSEXT_PADDING) {
|
||||
unsigned char *padbytes;
|
||||
size_t hlen;
|
||||
|
||||
if (!WPACKET_get_total_written(pkt, &hlen)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hlen > 0xff && hlen < 0x200) {
|
||||
hlen = 0x200 - hlen;
|
||||
if (hlen >= 4)
|
||||
hlen -= 4;
|
||||
else
|
||||
hlen = 0;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
|
||||
|| !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
|
||||
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
memset(padbytes, 0, hlen);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl_prepare_clienthello_tlsext(SSL *s)
|
||||
{
|
||||
s->s3->alpn_sent = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialise digests to default values */
|
||||
void ssl_set_default_md(SSL *s)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user