mirror of
https://github.com/openssl/openssl.git
synced 2025-03-25 20:00:44 +08:00
Update ServerHello to new draft-22 format
The new ServerHello format is essentially now the same as the old TLSv1.2 one, but it must additionally include supported_versions. The version field is fixed at TLSv1.2, and the version negotiation happens solely via supported_versions. Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4701)
This commit is contained in:
parent
86b165e39f
commit
88050dd196
@ -1292,6 +1292,8 @@ SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET:460:tls_construct_stoc_session_ticket
|
||||
SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST:461:tls_construct_stoc_status_request
|
||||
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS:544:\
|
||||
tls_construct_stoc_supported_groups
|
||||
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS:608:\
|
||||
tls_construct_stoc_supported_versions
|
||||
SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP:462:tls_construct_stoc_use_srtp
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO:521:\
|
||||
tls_early_post_process_client_hello
|
||||
@ -1332,6 +1334,7 @@ SSL_F_TLS_PARSE_STOC_SCT:564:tls_parse_stoc_sct
|
||||
SSL_F_TLS_PARSE_STOC_SERVER_NAME:583:tls_parse_stoc_server_name
|
||||
SSL_F_TLS_PARSE_STOC_SESSION_TICKET:584:tls_parse_stoc_session_ticket
|
||||
SSL_F_TLS_PARSE_STOC_STATUS_REQUEST:585:tls_parse_stoc_status_request
|
||||
SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS:609:tls_parse_stoc_supported_versions
|
||||
SSL_F_TLS_PARSE_STOC_USE_SRTP:446:tls_parse_stoc_use_srtp
|
||||
SSL_F_TLS_POST_PROCESS_CLIENT_HELLO:378:tls_post_process_client_hello
|
||||
SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE:384:\
|
||||
|
@ -340,6 +340,7 @@ int ERR_load_SSL_strings(void);
|
||||
# define SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET 460
|
||||
# define SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST 461
|
||||
# define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS 544
|
||||
# define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS 608
|
||||
# define SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP 462
|
||||
# define SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO 521
|
||||
# define SSL_F_TLS_FINISH_HANDSHAKE 597
|
||||
@ -379,6 +380,7 @@ int ERR_load_SSL_strings(void);
|
||||
# define SSL_F_TLS_PARSE_STOC_SERVER_NAME 583
|
||||
# define SSL_F_TLS_PARSE_STOC_SESSION_TICKET 584
|
||||
# define SSL_F_TLS_PARSE_STOC_STATUS_REQUEST 585
|
||||
# define SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS 609
|
||||
# define SSL_F_TLS_PARSE_STOC_USE_SRTP 446
|
||||
# define SSL_F_TLS_POST_PROCESS_CLIENT_HELLO 378
|
||||
# define SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE 384
|
||||
|
@ -524,6 +524,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
|
||||
"tls_construct_stoc_status_request"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, 0),
|
||||
"tls_construct_stoc_supported_groups"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS, 0),
|
||||
"tls_construct_stoc_supported_versions"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP, 0),
|
||||
"tls_construct_stoc_use_srtp"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, 0),
|
||||
@ -593,6 +595,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
|
||||
"tls_parse_stoc_session_ticket"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, 0),
|
||||
"tls_parse_stoc_status_request"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS, 0),
|
||||
"tls_parse_stoc_supported_versions"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_USE_SRTP, 0),
|
||||
"tls_parse_stoc_use_srtp"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, 0),
|
||||
|
@ -2266,7 +2266,8 @@ __owur int ssl_check_version_downgrade(SSL *s);
|
||||
__owur int ssl_set_version_bound(int method_version, int version, int *bound);
|
||||
__owur int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello,
|
||||
DOWNGRADE *dgrd);
|
||||
__owur int ssl_choose_client_version(SSL *s, int version, int checkdgrd);
|
||||
__owur int ssl_choose_client_version(SSL *s, int version,
|
||||
RAW_EXTENSION *extensions);
|
||||
int ssl_get_min_max_version(const SSL *s, int *min_version, int *max_version);
|
||||
|
||||
__owur long tls1_default_timeout(void);
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "internal/nelem.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include "../ssl_locl.h"
|
||||
#include "statem_locl.h"
|
||||
|
||||
@ -261,11 +262,13 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_supported_versions,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY
|
||||
| SSL_EXT_TLS1_3_ONLY,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_SERVER_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY,
|
||||
NULL,
|
||||
/* Processed inline as part of version selection */
|
||||
NULL, NULL, NULL, tls_construct_ctos_supported_versions, NULL
|
||||
NULL, tls_parse_stoc_supported_versions,
|
||||
tls_construct_stoc_supported_versions,
|
||||
tls_construct_ctos_supported_versions, NULL
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_psk_kex_modes,
|
||||
@ -357,6 +360,44 @@ static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_validate_all_contexts(SSL *s, unsigned int thisctx, RAW_EXTENSION *exts)
|
||||
{
|
||||
size_t i, num_exts, builtin_num = OSSL_NELEM(ext_defs), offset;
|
||||
RAW_EXTENSION *thisext;
|
||||
unsigned int context;
|
||||
ENDPOINT role = ENDPOINT_BOTH;
|
||||
|
||||
if ((thisctx & SSL_EXT_CLIENT_HELLO) != 0)
|
||||
role = ENDPOINT_SERVER;
|
||||
else if ((thisctx & SSL_EXT_TLS1_2_SERVER_HELLO) != 0)
|
||||
role = ENDPOINT_CLIENT;
|
||||
|
||||
/* Calculate the number of extensions in the extensions list */
|
||||
num_exts = builtin_num + s->cert->custext.meths_count;
|
||||
|
||||
for (thisext = exts, i = 0; i < num_exts; i++, thisext++) {
|
||||
if (!thisext->present)
|
||||
continue;
|
||||
|
||||
if (i < builtin_num) {
|
||||
context = ext_defs[i].context;
|
||||
} else {
|
||||
custom_ext_method *meth = NULL;
|
||||
|
||||
meth = custom_ext_find(&s->cert->custext, role, thisext->type,
|
||||
&offset);
|
||||
if (!ossl_assert(meth != NULL))
|
||||
return 0;
|
||||
context = meth->context;
|
||||
}
|
||||
|
||||
if (!validate_context(s, context, thisctx))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify whether we are allowed to use the extension |type| in the current
|
||||
* |context|. Returns 1 to indicate the extension is allowed or unknown or 0 to
|
||||
|
@ -507,6 +507,20 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
|
||||
{
|
||||
int currv, min_version, max_version, reason;
|
||||
|
||||
reason = ssl_get_min_max_version(s, &min_version, &max_version);
|
||||
if (reason != 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't include this if we can't negotiate TLSv1.3. We can do a straight
|
||||
* comparison here because we will never be called in DTLS.
|
||||
*/
|
||||
if (max_version < TLS1_3_VERSION)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)) {
|
||||
@ -516,13 +530,6 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
reason = ssl_get_min_max_version(s, &min_version, &max_version);
|
||||
if (reason != 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): There is some discussion on the TLS list as to whether
|
||||
* we should include versions <TLS1.2. For the moment we do. To be
|
||||
@ -1633,6 +1640,29 @@ int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
unsigned int version;
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &version)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO(TLS1.3): Remove this before release */
|
||||
if (version == TLS1_3_VERSION_DRAFT)
|
||||
version = TLS1_3_VERSION;
|
||||
|
||||
/* We just set it here. We validate it in ssl_choose_client_version */
|
||||
s->version = version;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
|
@ -1213,6 +1213,27 @@ EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (!SSL_IS_TLS13(s))
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* TODO(TLS1.3): Update to remove the TLSv1.3 draft indicator */
|
||||
|| !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
|
@ -1332,16 +1332,67 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do this immediately so we know what format the ServerHello is in.
|
||||
* Must be done after reading the random data so we can check for the
|
||||
* TLSv1.3 downgrade sentinels
|
||||
*/
|
||||
if (!ssl_choose_client_version(s, sversion, 1)) {
|
||||
/* Get the session-id. */
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
session_id_len = PACKET_remaining(&session_id);
|
||||
if (session_id_len > sizeof(s->session->session_id)
|
||||
|| session_id_len > SSL3_SESSION_ID_SIZE) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_SSL3_SESSION_ID_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!PACKET_get_1(pkt, &compression)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* TLS extensions */
|
||||
if (PACKET_remaining(pkt) == 0) {
|
||||
PACKET_null_init(&extpkt);
|
||||
} else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_BAD_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!tls_collect_extensions(s, &extpkt,
|
||||
SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_SERVER_HELLO,
|
||||
&extensions, NULL, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ssl_choose_client_version(s, sversion, extensions)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we have chosen the version we need to check again that the extensions
|
||||
* are appropriate for this version.
|
||||
*/
|
||||
context = SSL_IS_TLS13(s) ? SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
: SSL_EXT_TLS1_2_SERVER_HELLO;
|
||||
if (!tls_validate_all_contexts(s, context, extensions)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* In TLSv1.3 a ServerHello message signals a key change so the end of the
|
||||
* message must be on a record boundary.
|
||||
@ -1352,56 +1403,9 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get the session-id. */
|
||||
if (!SSL_IS_TLS13(s)) {
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
session_id_len = PACKET_remaining(&session_id);
|
||||
if (session_id_len > sizeof(s->session->session_id)
|
||||
|| session_id_len > SSL3_SESSION_ID_SIZE) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_SSL3_SESSION_ID_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
PACKET_null_init(&session_id);
|
||||
session_id_len = 0;
|
||||
}
|
||||
|
||||
if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!SSL_IS_TLS13(s)) {
|
||||
if (!PACKET_get_1(pkt, &compression)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
compression = 0;
|
||||
}
|
||||
|
||||
/* TLS extensions */
|
||||
if (PACKET_remaining(pkt) == 0) {
|
||||
PACKET_null_init(&extpkt);
|
||||
} else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_BAD_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
context = SSL_IS_TLS13(s) ? SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
: SSL_EXT_TLS1_2_SERVER_HELLO;
|
||||
if (!tls_collect_extensions(s, &extpkt, context, &extensions, NULL, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
if (SSL_IS_TLS13(s) && compression != 0) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_INVALID_COMPRESSION_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -1411,7 +1415,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
/* This will set s->hit if we are resuming */
|
||||
if (!tls_parse_extension(s, TLSEXT_IDX_psk,
|
||||
SSL_EXT_TLS1_3_SERVER_HELLO,
|
||||
extensions, NULL, 0l)) {
|
||||
extensions, NULL, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
@ -1739,21 +1739,31 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
|
||||
*
|
||||
* @s: client SSL handle.
|
||||
* @version: The proposed version from the server's HELLO.
|
||||
* @checkdgrd: Whether to check the downgrade sentinels in the server_random
|
||||
* @extensions: The extensions received
|
||||
*
|
||||
* Returns 1 on success or 0 on error.
|
||||
*/
|
||||
int ssl_choose_client_version(SSL *s, int version, int checkdgrd)
|
||||
int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
|
||||
{
|
||||
const version_info *vent;
|
||||
const version_info *table;
|
||||
int highver = 0;
|
||||
int origv;
|
||||
|
||||
/* TODO(TLS1.3): Remove this before release */
|
||||
if (version == TLS1_3_VERSION_DRAFT)
|
||||
version = TLS1_3_VERSION;
|
||||
origv = s->version;
|
||||
s->version = version;
|
||||
|
||||
if (s->hello_retry_request && version != TLS1_3_VERSION) {
|
||||
/* This will overwrite s->version if the extension is present */
|
||||
if (!tls_parse_extension(s, TLSEXT_IDX_supported_versions,
|
||||
SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_SERVER_HELLO, extensions,
|
||||
NULL, 0)) {
|
||||
s->version = origv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->hello_retry_request && s->version != TLS1_3_VERSION) {
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_WRONG_SSL_VERSION);
|
||||
return 0;
|
||||
@ -1761,7 +1771,8 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd)
|
||||
|
||||
switch (s->method->version) {
|
||||
default:
|
||||
if (version != s->version) {
|
||||
if (s->version != s->method->version) {
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
|
||||
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_WRONG_SSL_VERSION);
|
||||
@ -1790,13 +1801,14 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd)
|
||||
if (vent->cmeth == NULL)
|
||||
continue;
|
||||
|
||||
if (highver != 0 && version != vent->version)
|
||||
if (highver != 0 && s->version != vent->version)
|
||||
continue;
|
||||
|
||||
method = vent->cmeth();
|
||||
err = ssl_method_error(s, method);
|
||||
if (err != 0) {
|
||||
if (version == vent->version) {
|
||||
if (s->version == vent->version) {
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
|
||||
SSL_F_SSL_CHOOSE_CLIENT_VERSION, err);
|
||||
return 0;
|
||||
@ -1807,43 +1819,43 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd)
|
||||
if (highver == 0)
|
||||
highver = vent->version;
|
||||
|
||||
if (version != vent->version)
|
||||
if (s->version != vent->version)
|
||||
continue;
|
||||
|
||||
#ifndef OPENSSL_NO_TLS13DOWNGRADE
|
||||
/* Check for downgrades */
|
||||
if (checkdgrd) {
|
||||
if (version == TLS1_2_VERSION && highver > version) {
|
||||
if (memcmp(tls12downgrade,
|
||||
s->s3->server_random + SSL3_RANDOM_SIZE
|
||||
- sizeof(tls12downgrade),
|
||||
sizeof(tls12downgrade)) == 0) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_INAPPROPRIATE_FALLBACK);
|
||||
return 0;
|
||||
}
|
||||
} else if (!SSL_IS_DTLS(s)
|
||||
&& version < TLS1_2_VERSION
|
||||
&& highver > version) {
|
||||
if (memcmp(tls11downgrade,
|
||||
s->s3->server_random + SSL3_RANDOM_SIZE
|
||||
- sizeof(tls11downgrade),
|
||||
sizeof(tls11downgrade)) == 0) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_INAPPROPRIATE_FALLBACK);
|
||||
return 0;
|
||||
}
|
||||
if (s->version == TLS1_2_VERSION && highver > s->version) {
|
||||
if (memcmp(tls12downgrade,
|
||||
s->s3->server_random + SSL3_RANDOM_SIZE
|
||||
- sizeof(tls12downgrade),
|
||||
sizeof(tls12downgrade)) == 0) {
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_INAPPROPRIATE_FALLBACK);
|
||||
return 0;
|
||||
}
|
||||
} else if (!SSL_IS_DTLS(s)
|
||||
&& s->version < TLS1_2_VERSION
|
||||
&& highver > s->version) {
|
||||
if (memcmp(tls11downgrade,
|
||||
s->s3->server_random + SSL3_RANDOM_SIZE
|
||||
- sizeof(tls11downgrade),
|
||||
sizeof(tls11downgrade)) == 0) {
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_INAPPROPRIATE_FALLBACK);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
s->method = method;
|
||||
s->version = version;
|
||||
return 1;
|
||||
}
|
||||
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_UNSUPPORTED_PROTOCOL);
|
||||
return 0;
|
||||
|
@ -161,6 +161,8 @@ typedef enum ext_return_en {
|
||||
EXT_RETURN_NOT_SENT
|
||||
} EXT_RETURN;
|
||||
|
||||
__owur int tls_validate_all_contexts(SSL *s, unsigned int thisctx,
|
||||
RAW_EXTENSION *exts);
|
||||
__owur int extension_is_relevant(SSL *s, unsigned int extctx,
|
||||
unsigned int thisctx);
|
||||
__owur int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
|
||||
@ -271,6 +273,9 @@ EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
@ -388,6 +393,8 @@ int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
|
@ -2193,8 +2193,7 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
|
||||
size_t sl, len;
|
||||
int version;
|
||||
|
||||
/* TODO(TLS1.3): Remove the DRAFT conditional before release */
|
||||
version = SSL_IS_TLS13(s) ? TLS1_3_VERSION_DRAFT : s->version;
|
||||
version = SSL_IS_TLS13(s) ? TLS1_2_VERSION : s->version;
|
||||
if (!WPACKET_put_bytes_u16(pkt, version)
|
||||
/*
|
||||
* Random stuff. Filling of the server_random takes place in
|
||||
@ -2234,21 +2233,23 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Never send a session_id back in the ServerHello */
|
||||
if (SSL_IS_TLS13(s))
|
||||
sl = 0;
|
||||
|
||||
/* set up the compression method */
|
||||
#ifdef OPENSSL_NO_COMP
|
||||
compm = 0;
|
||||
#else
|
||||
if (s->s3->tmp.new_compression == NULL)
|
||||
if (SSL_IS_TLS13(s) || s->s3->tmp.new_compression == NULL)
|
||||
compm = 0;
|
||||
else
|
||||
compm = s->s3->tmp.new_compression->id;
|
||||
#endif
|
||||
|
||||
if ((!SSL_IS_TLS13(s)
|
||||
&& !WPACKET_sub_memcpy_u8(pkt, s->session->session_id, sl))
|
||||
if (!WPACKET_sub_memcpy_u8(pkt, s->session->session_id, sl)
|
||||
|| !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
|
||||
|| (!SSL_IS_TLS13(s)
|
||||
&& !WPACKET_put_bytes_u8(pkt, compm))
|
||||
|| !WPACKET_put_bytes_u8(pkt, compm)
|
||||
|| !tls_construct_extensions(s, pkt,
|
||||
SSL_IS_TLS13(s)
|
||||
? SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
|
@ -823,6 +823,17 @@ static int ssl_print_extension(BIO *bio, int indent, int server,
|
||||
break;
|
||||
|
||||
case TLSEXT_TYPE_supported_versions:
|
||||
if (server) {
|
||||
int version;
|
||||
|
||||
if (extlen != 2)
|
||||
return 0;
|
||||
version = (ext[0] << 8) | ext[1];
|
||||
BIO_indent(bio, indent + 4, 80);
|
||||
BIO_printf(bio, "%s (%d)\n",
|
||||
ssl_trace_str(version, ssl_version_tbl), version);
|
||||
break;
|
||||
}
|
||||
if (extlen < 1)
|
||||
return 0;
|
||||
xlen = ext[0];
|
||||
|
@ -146,7 +146,7 @@ static int async_write(BIO *bio, const char *in, int inl)
|
||||
return -1;
|
||||
|
||||
while (PACKET_remaining(&pkt) > 0) {
|
||||
PACKET payload, wholebody;
|
||||
PACKET payload, wholebody, sessionid, extensions;
|
||||
unsigned int contenttype, versionhi, versionlo, data;
|
||||
unsigned int msgtype = 0, negversion = 0;
|
||||
|
||||
@ -164,11 +164,43 @@ static int async_write(BIO *bio, const char *in, int inl)
|
||||
&& !PACKET_get_1(&wholebody, &msgtype))
|
||||
return -1;
|
||||
|
||||
if (msgtype == SSL3_MT_SERVER_HELLO
|
||||
&& (!PACKET_forward(&wholebody,
|
||||
if (msgtype == SSL3_MT_SERVER_HELLO) {
|
||||
if (!PACKET_forward(&wholebody,
|
||||
SSL3_HM_HEADER_LENGTH - 1)
|
||||
|| !PACKET_get_net_2(&wholebody, &negversion)))
|
||||
return -1;
|
||||
|| !PACKET_get_net_2(&wholebody, &negversion)
|
||||
/* Skip random (32 bytes) */
|
||||
|| !PACKET_forward(&wholebody, 32)
|
||||
/* Skip session id */
|
||||
|| !PACKET_get_length_prefixed_1(&wholebody,
|
||||
&sessionid)
|
||||
/*
|
||||
* Skip ciphersuite (2 bytes) and compression
|
||||
* method (1 byte)
|
||||
*/
|
||||
|| !PACKET_forward(&wholebody, 2 + 1)
|
||||
|| !PACKET_get_length_prefixed_2(&wholebody,
|
||||
&extensions))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Find the negotiated version in supported_versions
|
||||
* extension, if present.
|
||||
*/
|
||||
while (PACKET_remaining(&extensions)) {
|
||||
unsigned int type;
|
||||
PACKET extbody;
|
||||
|
||||
if (!PACKET_get_net_2(&extensions, &type)
|
||||
|| !PACKET_get_length_prefixed_2(&extensions,
|
||||
&extbody))
|
||||
return -1;
|
||||
|
||||
if (type == TLSEXT_TYPE_supported_versions
|
||||
&& (!PACKET_get_net_2(&extbody, &negversion)
|
||||
|| PACKET_remaining(&extbody) != 0))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
while (PACKET_get_1(&payload, &data)) {
|
||||
/* Create a new one byte long record for each byte in the
|
||||
|
@ -122,6 +122,8 @@ $ENV{CTLOG_FILE} = srctop_file("test", "ct", "log_list.conf");
|
||||
[TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK,
|
||||
checkhandshake::PSK_CLI_EXTENSION],
|
||||
|
||||
[TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
|
||||
checkhandshake::DEFAULT_EXTENSIONS],
|
||||
[TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
|
||||
checkhandshake::KEY_SHARE_SRV_EXTENSION],
|
||||
[TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_PSK,
|
||||
|
@ -122,6 +122,8 @@ $ENV{CTLOG_FILE} = srctop_file("test", "ct", "log_list.conf");
|
||||
[TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK,
|
||||
checkhandshake::PSK_CLI_EXTENSION],
|
||||
|
||||
[TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
|
||||
checkhandshake::DEFAULT_EXTENSIONS],
|
||||
[TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
|
||||
checkhandshake::DEFAULT_EXTENSIONS],
|
||||
[TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_PSK,
|
||||
|
@ -46,29 +46,21 @@ sub parse
|
||||
my $ptr = 2;
|
||||
my ($server_version) = unpack('n', $self->data);
|
||||
|
||||
# TODO(TLS1.3): Replace this reference to draft version before release
|
||||
if ($server_version == TLSProxy::Record::VERS_TLS_1_3_DRAFT) {
|
||||
$server_version = TLSProxy::Record::VERS_TLS_1_3;
|
||||
TLSProxy::Proxy->is_tls13(1);
|
||||
}
|
||||
|
||||
my $random = substr($self->data, $ptr, 32);
|
||||
$ptr += 32;
|
||||
my $session_id_len = 0;
|
||||
my $session = "";
|
||||
if (!TLSProxy::Proxy->is_tls13()) {
|
||||
$session_id_len = unpack('C', substr($self->data, $ptr));
|
||||
$ptr++;
|
||||
$session = substr($self->data, $ptr, $session_id_len);
|
||||
$ptr += $session_id_len;
|
||||
}
|
||||
$session_id_len = unpack('C', substr($self->data, $ptr));
|
||||
$ptr++;
|
||||
$session = substr($self->data, $ptr, $session_id_len);
|
||||
$ptr += $session_id_len;
|
||||
|
||||
my $ciphersuite = unpack('n', substr($self->data, $ptr));
|
||||
$ptr += 2;
|
||||
my $comp_meth = 0;
|
||||
if (!TLSProxy::Proxy->is_tls13()) {
|
||||
$comp_meth = unpack('C', substr($self->data, $ptr));
|
||||
$ptr++;
|
||||
}
|
||||
$comp_meth = unpack('C', substr($self->data, $ptr));
|
||||
$ptr++;
|
||||
|
||||
my $extensions_len = unpack('n', substr($self->data, $ptr));
|
||||
if (!defined $extensions_len) {
|
||||
$extensions_len = 0;
|
||||
@ -96,6 +88,15 @@ sub parse
|
||||
my $extdata = substr($extension_data, 4, $size);
|
||||
$extension_data = substr($extension_data, 4 + $size);
|
||||
$extensions{$type} = $extdata;
|
||||
if ($type == TLSProxy::Message::EXT_SUPPORTED_VERSIONS) {
|
||||
$server_version = unpack('n', $extdata);
|
||||
}
|
||||
}
|
||||
|
||||
# TODO(TLS1.3): Replace this reference to draft version before release
|
||||
if ($server_version == TLSProxy::Record::VERS_TLS_1_3_DRAFT) {
|
||||
$server_version = TLSProxy::Record::VERS_TLS_1_3;
|
||||
TLSProxy::Proxy->is_tls13(1);
|
||||
}
|
||||
|
||||
$self->server_version($server_version);
|
||||
@ -138,14 +139,10 @@ sub set_message_contents
|
||||
|
||||
$data = pack('n', $self->server_version);
|
||||
$data .= $self->random;
|
||||
if (!TLSProxy::Proxy->is_tls13()) {
|
||||
$data .= pack('C', $self->session_id_len);
|
||||
$data .= $self->session;
|
||||
}
|
||||
$data .= pack('C', $self->session_id_len);
|
||||
$data .= $self->session;
|
||||
$data .= pack('n', $self->ciphersuite);
|
||||
if (!TLSProxy::Proxy->is_tls13()) {
|
||||
$data .= pack('C', $self->comp_meth);
|
||||
}
|
||||
$data .= pack('C', $self->comp_meth);
|
||||
|
||||
foreach my $key (keys %{$self->extension_data}) {
|
||||
my $extdata = ${$self->extension_data}{$key};
|
||||
|
Loading…
x
Reference in New Issue
Block a user